1 use strict; use warnings;
2 package OpenILS::Application::Cat;
3 use OpenILS::Application::AppUtils;
4 use OpenSRF::Application;
5 use OpenILS::Application::Cat::Utils;
6 use base qw/OpenSRF::Application/;
7 use Time::HiRes qw(time);
8 use OpenSRF::EX qw(:try);
10 use OpenILS::Utils::Fieldmapper;
13 use OpenILS::Utils::FlatXML;
15 use OpenSRF::Utils::SettingsClient;
16 use OpenSRF::Utils::Logger qw($logger);
18 my $apputils = "OpenILS::Application::AppUtils";
20 my $utils = "OpenILS::Application::Cat::Utils";
27 __PACKAGE__->register_method(
28 method => "retrieve_marc_template",
29 api_name => "open-ils.cat.biblio.marc_template.retrieve",
31 Returns a MARC 'record tree' based on a set of pre-defined templates.
32 Templates include : book
35 sub retrieve_marc_template {
36 my( $self, $client, $type ) = @_;
38 return $marctemplates{$type} if defined($marctemplates{$type});
40 my $xml = _load_marc_template($type);
42 my $nodes = OpenILS::Utils::FlatXML->new()->xml_to_nodeset( $xml );
43 $marctemplates{$type} = $utils->nodeset2tree( $nodes->nodeset );
44 return $marctemplates{$type};
47 sub _load_marc_template {
50 if(!$conf) { $conf = OpenSRF::Utils::SettingsClient->new; }
52 my $template = $conf->config_value(
53 "apps", "open-ils.cat","app_settings", "marctemplates", $type );
54 warn "Opening template file $template\n";
59 return join('', @xml);
65 __PACKAGE__->register_method(
66 method => "create_record_tree",
67 api_name => "open-ils.cat.biblio.record_tree.create",
69 Inserts a new MARC 'record tree' into the system
72 sub create_record_tree {
73 my( $self, $client, $login, $tree ) = @_;
75 my $user_obj = $apputils->check_user_session($login);
77 if($apputils->check_user_perms(
78 $user_obj->id, $user_obj->home_ou, "CREATE_MARC")) {
79 return OpenILS::Perm->new("CREATE_MARC");
82 warn "Creating a new record tree entry...";
83 my $meth = $self->method_lookup("open-ils.cat.biblio.record.tree.import");
84 my ($s) = $meth->run($login, $tree);
91 __PACKAGE__->register_method(
92 method => "biblio_record_tree_import",
93 api_name => "open-ils.cat.biblio.record.tree.import",
95 Takes a record tree and imports the record into the database. In this
96 case, the record tree is assumed to be a complete record (i.e. valid
97 MARC. The title control number is taken from (whichever comes first)
98 tags 001, 020, 022, 010, 035 and whichever does not already exist
100 user_session must have IMPORT_MARC permissions
104 sub biblio_record_tree_import {
105 my( $self, $client, $user_session, $tree) = @_;
106 my $user_obj = $apputils->check_user_session($user_session);
108 if($apputils->check_user_perms(
109 $user_obj->id, $user_obj->home_ou, "IMPORT_MARC")) {
110 return OpenILS::Perm->new("IMPORT_MARC");
113 warn "importing new record " . Dumper($tree) . "\n";
115 my $nodeset = $utils->tree2nodeset($tree);
116 warn "turned into nodeset " . Dumper($nodeset) . "\n";
118 # copy the doc so that we can mangle the namespace.
119 my $marcxml = OpenILS::Utils::FlatXML->new()->nodeset_to_xml($nodeset);
120 my $copy_marcxml = XML::LibXML->new->parse_string($marcxml->toString);
122 $marcxml->documentElement->setNamespace( "http://www.loc.gov/MARC21/slim", "marc", 1 );
126 warn "Starting db session in import\n";
127 my $session = $apputils->start_db_session();
128 my $source = 2; # system local source
130 my $xpath = '//controlfield[@tag="001"]';
131 $tcn = $marcxml->documentElement->findvalue($xpath);
132 if(_tcn_exists($session, $tcn)) {$tcn = undef;}
133 my $tcn_source = "External";
137 $xpath = '//datafield[@tag="020"]';
138 $tcn = $marcxml->documentElement->findvalue($xpath);
139 $tcn_source = "ISBN";
140 if(_tcn_exists($session, $tcn)) {$tcn = undef;}
144 $xpath = '//datafield[@tag="022"]';
145 $tcn = $marcxml->documentElement->findvalue($xpath);
146 $tcn_source = "ISSN";
147 if(_tcn_exists($session, $tcn)) {$tcn = undef;}
151 $xpath = '//datafield[@tag="010"]';
152 $tcn = $marcxml->documentElement->findvalue($xpath);
153 $tcn_source = "LCCN";
154 if(_tcn_exists($session, $tcn)) {$tcn = undef;}
158 $xpath = '//datafield[@tag="035"]';
159 $tcn = $marcxml->documentElement->findvalue($xpath);
160 $tcn_source = "System";
161 if(_tcn_exists($session, $tcn)) {$tcn = undef;}
167 warn "Record import with tcn: $tcn and source $tcn_source\n";
169 my $record = Fieldmapper::biblio::record_entry->new;
171 $record->source($source);
172 $record->tcn_source($tcn_source);
173 $record->tcn_value($tcn);
174 $record->creator($user_obj->id);
175 $record->editor($user_obj->id);
176 $record->marc($copy_marcxml->toString);
179 my $req = $session->request(
180 "open-ils.storage.direct.biblio.record_entry.create", $record );
182 my $id = $req->gather(1);
184 if(!$id) { throw OpenSRF::EX::ERROR ("Unable to create new record_entry from import"); }
185 warn "received id: $id from record_entry create\n";
187 $apputils->commit_db_session($session);
189 $session = OpenSRF::AppSession->create("open-ils.storage");
191 my $wreq = $session->request("open-ils.worm.wormize.biblio", $id)->gather(1);
192 warn "Done worming record $id\n";
194 if(!$wreq) { throw OpenSRF::EX::ERROR ("Unable to wormize imported record"); }
196 return $self->biblio_record_tree_retrieve($client, $id);
204 if(!$tcn) {return 0;}
206 my $req = $session->request(
207 "open-ils.storage.direct.biblio.record_entry.search.tcn_value.atomic",
209 my $recs = $req->gather(1);
211 if($recs and $recs->[0]) {
219 __PACKAGE__->register_method(
220 method => "biblio_record_tree_retrieve",
221 api_name => "open-ils.cat.biblio.record.tree.retrieve",
224 sub biblio_record_tree_retrieve {
226 my( $self, $client, $recordid ) = @_;
228 my $name = "open-ils.storage.direct.biblio.record_entry.retrieve";
229 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
230 my $request = $session->request( $name, $recordid );
231 my $marcxml = $request->gather(1);
234 throw OpenSRF::EX::ERROR
235 ("No record in database with id $recordid");
238 $session->disconnect();
241 warn "turning into nodeset\n";
242 my $nodes = OpenILS::Utils::FlatXML->new()->xml_to_nodeset( $marcxml->marc );
243 warn "turning nodeset into tree\n";
244 my $tree = $utils->nodeset2tree( $nodes->nodeset );
246 $tree->owner_doc( $marcxml->id() );
248 warn "returning tree\n";
253 __PACKAGE__->register_method(
254 method => "biblio_record_tree_commit",
255 api_name => "open-ils.cat.biblio.record.tree.commit",
256 argc => 3, #(session_id, biblio_tree )
257 notes => <<" NOTES");
258 Walks the tree and commits any changed nodes
259 adds any new nodes, and deletes any deleted nodes
260 The record to commit must already exist or this
264 sub biblio_record_tree_commit {
266 my( $self, $client, $user_session, $tree ) = @_;
268 throw OpenSRF::EX::InvalidArg
269 ("Not enough args to to open-ils.cat.biblio.record.tree.commit")
270 unless ( $user_session and $tree );
272 my $user_obj = $apputils->check_user_session($user_session);
274 if($apputils->check_user_perms(
275 $user_obj->id, $user_obj->home_ou, "UPDATE_MARC")) {
276 return OpenILS::Perm->new("UPDATE_MARC");
281 my $docid = $tree->owner_doc();
282 my $session = OpenILS::Application::AppUtils->start_db_session();
284 warn "Retrieving biblio record from storage for update\n";
286 my $req1 = $session->request(
287 "open-ils.storage.direct.biblio.record_entry.batch.retrieve", $docid );
288 my $biblio = $req1->gather(1);
290 warn "retrieved doc $docid\n";
293 # turn the tree into a nodeset
294 my $nodeset = $utils->tree2nodeset($tree);
295 $nodeset = $utils->clean_nodeset($nodeset);
297 if(!defined($docid)) { # be sure
298 for my $node (@$nodeset) {
299 $docid = $node->owner_doc();
300 last if defined($docid);
304 # turn the nodeset into a doc
305 my $marcxml = OpenILS::Utils::FlatXML->new()->nodeset_to_xml( $nodeset );
307 $biblio->marc( $marcxml->toString() );
309 warn "Starting db session\n";
311 my $x = _update_record_metadata( $session, { user => $user_obj, docid => $docid } );
312 OpenILS::Application::AppUtils->rollback_db_session($session) unless $x;
314 warn "Sending updated doc $docid to db\n";
315 my $req = $session->request( "open-ils.storage.direct.biblio.record_entry.update", $biblio );
318 my $status = $req->recv();
319 if( !$status || $status->isa("Error") || ! $status->content) {
320 OpenILS::Application::AppUtils->rollback_db_session($session);
321 if($status->isa("Error")) { throw $status ($status); }
322 throw OpenSRF::EX::ERROR ("Error updating biblio record");
326 # Send the doc to the wormer for wormizing
327 warn "Starting worm session\n";
332 my $wreq = $session->request( "open-ils.worm.wormize.biblio", $docid );
339 warn "wormizing failed, rolling back\n";
340 OpenILS::Application::AppUtils->rollback_db_session($session);
342 if($e) { throw $e ($e); }
343 throw OpenSRF::EX::ERROR ("Wormizing Failed for $docid" );
346 warn "Committing db session...\n";
347 OpenILS::Application::AppUtils->commit_db_session( $session );
349 $nodeset = OpenILS::Utils::FlatXML->new()->xmldoc_to_nodeset($marcxml);
350 $tree = $utils->nodeset2tree($nodeset->nodeset);
351 $tree->owner_doc($docid);
353 # $client->respond_complete($tree);
355 warn "Done wormizing\n";
358 #warn "Returning tree:\n";
367 __PACKAGE__->register_method(
368 method => "biblio_record_record_metadata",
369 api_name => "open-ils.cat.biblio.record.metadata.retrieve",
370 argc => 1, #(session_id, biblio_tree )
371 notes => "Walks the tree and commits any changed nodes " .
372 "adds any new nodes, and deletes any deleted nodes",
375 sub biblio_record_record_metadata {
376 my( $self, $client, @ids ) = @_;
378 if(!@ids){return undef;}
380 my $session = OpenSRF::AppSession->create("open-ils.storage");
381 my $request = $session->request(
382 "open-ils.storage.direct.biblio.record_entry.batch.retrieve", @ids );
386 while( my $response = $request->recv() ) {
389 throw OpenSRF::EX::ERROR ("No Response from Storage");
391 if($response->isa("Error")) {
392 throw $response ($response->stringify);
395 my $record_entry = $response->content;
397 my $creator = $record_entry->creator;
398 my $editor = $record_entry->editor;
400 ($creator, $editor) = _get_userid_by_id($creator, $editor);
402 $record_entry->creator($creator);
403 $record_entry->editor($editor);
405 push @$results, $record_entry;
410 $session->disconnect();
418 sub _get_userid_by_id {
423 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
424 my $request = $session->request(
425 "open-ils.storage.direct.actor.user.batch.retrieve.atomic", @ids );
427 $request->wait_complete;
428 my $response = $request->recv();
429 if(!$request->complete) { return undef; }
431 if($response->isa("Error")){
432 throw $response ($response);
435 for my $u (@{$response->content}) {
437 push @users, $u->usrname;
441 $session->disconnect;
447 sub _get_id_by_userid {
452 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
453 my $request = $session->request(
454 "open-ils.storage.direct.actor.user.search.usrname.atomic", @users );
456 $request->wait_complete;
457 my $response = $request->recv();
458 if(!$request->complete) {
459 throw OpenSRF::EX::ERROR ("no response from storage on user retrieve");
462 if(UNIVERSAL::isa( $response, "Error")){
463 throw $response ($response);
466 for my $u (@{$response->content}) {
472 $session->disconnect;
479 # commits metadata objects to the db
480 sub _update_record_metadata {
482 my ($session, @docs ) = @_;
484 for my $doc (@docs) {
486 my $user_obj = $doc->{user};
487 my $docid = $doc->{docid};
489 warn "Updating metata for doc $docid\n";
491 my $request = $session->request(
492 "open-ils.storage.direct.biblio.record_entry.retrieve", $docid );
493 my $record = $request->gather(1);
495 warn "retrieved record\n";
496 my ($id) = _get_id_by_userid($user_obj->usrname);
498 warn "got $id from _get_id_by_userid\n";
499 $record->editor($id);
501 warn "Grabbed the record, updating and moving on\n";
503 $request = $session->request(
504 "open-ils.storage.direct.biblio.record_entry.update", $record );
508 warn "committing metarecord update\n";
515 __PACKAGE__->register_method(
516 method => "orgs_for_title",
517 api_name => "open-ils.cat.actor.org_unit.retrieve_by_title"
521 my( $self, $client, $record_id ) = @_;
523 my $vols = $apputils->simple_scalar_request(
525 "open-ils.storage.direct.asset.call_number.search.record.atomic",
528 my $orgs = { map {$_->owning_lib => 1 } @$vols };
529 return [ keys %$orgs ];
534 __PACKAGE__->register_method(
535 method => "retrieve_copies",
536 api_name => "open-ils.cat.asset.copy_tree.retrieve");
538 __PACKAGE__->register_method(
539 method => "retrieve_copies",
540 api_name => "open-ils.cat.asset.copy_tree.global.retrieve");
542 # user_session may be null/undef
543 sub retrieve_copies {
545 my( $self, $client, $user_session, $docid, @org_ids ) = @_;
547 if(ref($org_ids[0])) { @org_ids = @{$org_ids[0]}; }
551 warn " $$ retrieving copy tree for orgs @org_ids and doc $docid at " . time() . "\n";
553 # grabbing copy trees should be available for everyone..
554 if(!@org_ids and $user_session) {
556 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
557 @org_ids = ($user_obj->home_ou);
560 if( $self->api_name =~ /global/ ) {
561 warn "performing global copy_tree search for $docid\n";
562 return _build_volume_list( { record => $docid } );
567 for my $orgid (@org_ids) {
568 my $vols = _build_volume_list(
569 { record => $docid, owning_lib => $orgid } );
570 warn "Volumes built for org $orgid\n";
571 push( @all_vols, @$vols );
574 warn " $$ Finished copy_tree at " . time() . "\n";
582 sub _build_volume_list {
583 my $search_hash = shift;
585 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
588 my $request = $session->request(
589 "open-ils.storage.direct.asset.call_number.search.atomic", $search_hash );
591 my $vols = $request->gather(1);
594 for my $volume (@$vols) {
596 warn "Grabbing copies for volume: " . $volume->id . "\n";
597 my $creq = $session->request(
598 "open-ils.storage.direct.asset.copy.search.call_number.atomic", $volume->id );
600 my $copies = $creq->gather(1);
602 $copies = [ sort { $a->barcode cmp $b->barcode } @$copies ];
604 $volume->copies($copies);
606 push( @volumes, $volume );
610 $session->disconnect();
616 # -----------------------------------------------------------------
617 # Fleshed volume tree batch add/update. This does everything a
618 # volume tree could want, add, update, delete
619 # -----------------------------------------------------------------
620 __PACKAGE__->register_method(
621 method => "volume_tree_fleshed_update",
622 api_name => "open-ils.cat.asset.volume_tree.fleshed.batch.update",
624 sub volume_tree_fleshed_update {
626 my( $self, $client, $user_session, $volumes ) = @_;
627 return undef unless $volumes;
629 my $user_obj = $apputils->check_user_session($user_session);
632 my $session = $apputils->start_db_session();
633 warn "Looping on volumes in fleshed volume tree update\n";
635 # cycle through the volumes provided and update/create/delete where necessary
636 for my $volume (@$volumes) {
638 warn "updating volume " . $volume->id . "\n";
640 my $update_copy_list = $volume->copies;
643 if( $volume->isdeleted) {
644 my $status = _delete_volume($session, $volume, $user_obj);
646 throw OpenSRF::EX::ERROR
647 ("Volume delete failed for volume " . $volume->id);
649 if(UNIVERSAL::isa($status, "Fieldmapper::perm_ex")) { return $status; }
651 } elsif( $volume->isnew ) {
654 $volume->editor($user_obj->id);
655 $volume->creator($user_obj->id);
656 $volume = _add_volume($session, $volume, $user_obj);
659 if($volume and UNIVERSAL::isa($volume, "Fieldmapper::perm_ex")) { return $volume; }
661 } elsif( $volume->ischanged ) {
663 $volume->editor($user_obj->id);
664 my $stat = _update_volume($session, $volume, $user_obj);
665 if($stat and UNIVERSAL::isa($stat, "Fieldmapper::perm_ex")) { return $stat; }
669 if( ! $volume->isdeleted ) {
670 for my $copy (@{$update_copy_list}) {
672 $copy->editor($user_obj->id);
673 warn "updating copy for volume " . $volume->id . "\n";
678 $copy->call_number($volume->id);
679 $copy->creator($user_obj->id);
680 $copy = _fleshed_copy_update($session,$copy,$user_obj);
682 } elsif( $copy->ischanged ) {
683 $copy->call_number($volume->id);
684 $copy = _fleshed_copy_update($session, $copy, $user_obj);
686 } elsif( $copy->isdeleted ) {
687 warn "Deleting copy " . $copy->id . " for volume " . $volume->id . "\n";
688 my $status = _fleshed_copy_update($session, $copy, $user_obj);
689 warn "Copy delete returned a status of $status\n";
695 $apputils->commit_db_session($session);
696 return scalar(@$volumes);
701 my( $session, $volume, $user_obj ) = @_;
703 if($apputils->check_user_perms(
704 $user_obj->id, $user_obj->home_ou, "DELETE_VOLUME")) {
705 return OpenILS::Perm->new("DELETE_VOLUME"); }
707 #$volume = _find_volume($session, $volume);
708 warn "Deleting volume " . $volume->id . "\n";
710 my $copies = $session->request(
711 "open-ils.storage.direct.asset.copy.search.call_number.atomic",
712 $volume->id )->gather(1);
714 throw OpenSRF::EX::ERROR
715 ("Cannot remove volume with copies attached");
718 my $req = $session->request(
719 "open-ils.storage.direct.asset.call_number.delete",
721 return $req->gather(1);
726 my($session, $volume, $user_obj) = @_;
727 if($apputils->check_user_perms(
728 $user_obj->id, $user_obj->home_ou, "UPDATE_VOLUME")) {
729 return OpenILS::Perm->new("UPDATE_VOLUME"); }
731 my $req = $session->request(
732 "open-ils.storage.direct.asset.call_number.update",
734 my $status = $req->gather(1);
739 my($session, $volume, $user_obj) = @_;
741 if($apputils->check_user_perms(
742 $user_obj->id, $user_obj->home_ou, "CREATE_VOLUME")) {
743 warn "User does not have priveleges to create new volumes\n";
744 return OpenILS::Perm->new("CREATE_VOLUME");
747 my $request = $session->request(
748 "open-ils.storage.direct.asset.call_number.create", $volume );
750 my $id = $request->gather(1);
753 OpenILS::Application::AppUtils->rollback_db_session($session);
754 throw OpenSRF::EX::ERROR (" * -> Error creating new volume");
758 warn "received new volume id: $id\n";
766 __PACKAGE__->register_method(
767 method => "fleshed_copy_update",
768 api_name => "open-ils.cat.asset.copy.fleshed.batch.update",
771 sub fleshed_copy_update {
772 my($self, $client, $user_session, $copies) = @_;
774 my $user_obj = $apputils->check_user_session($user_session);
775 my $session = $apputils->start_db_session();
777 for my $copy (@$copies) {
778 _fleshed_copy_update($session, $copy, $user_obj);
781 $apputils->commit_db_session($session);
788 my($session, $copy, $user_obj) = @_;
790 if($apputils->check_user_perms(
791 $user_obj->id, $user_obj->home_ou, "DELETE_COPY")) {
792 return OpenILS::Perm->new("DELETE_COPY"); }
794 warn "Deleting copy " . $copy->id . "\n";
795 my $request = $session->request(
796 "open-ils.storage.direct.asset.copy.delete",
798 return $request->gather(1);
802 my($session, $copy, $user_obj) = @_;
804 if($apputils->check_user_perms(
805 $user_obj->id, $user_obj->home_ou, "CREATE_COPY")) {
806 return OpenILS::Perm->new("CREATE_COPY"); }
808 my $request = $session->request(
809 "open-ils.storage.direct.asset.copy.create",
811 my $id = $request->gather(1);
814 throw OpenSRF::EX::ERROR
815 ("Unable to create new copy " . Dumper($copy));
818 warn "Created copy " . $copy->id . "\n";
825 my($session, $copy, $user_obj) = @_;
827 my $evt = $apputils->check_perms($user_obj->id, $copy->circ_lib, 'UPDATE_COPY');
828 return $evt if $evt; #XXX NOT YET HANDLED BY CALLER
830 my $status = $apputils->simplereq(
832 "open-ils.storage.direct.asset.copy.update", $copy );
833 $logger->debug("Successfully updated copy " . $copy->id );
838 # -----------------------------------------------------------------
839 # Creates/Updates/Deletes a fleshed asset.copy.
840 # adds/deletes copy stat_cat maps where necessary
841 # -----------------------------------------------------------------
842 sub _fleshed_copy_update {
843 my($session, $copy, $editor) = @_;
845 my $stat_cat_entries = $copy->stat_cat_entries;
846 $copy->editor($editor->id);
848 # in case we're fleshed
849 if(ref($copy->status)) {$copy->status( $copy->status->id ); }
850 if(ref($copy->location)) {$copy->location( $copy->location->id ); }
851 if(ref($copy->circ_lib)) {$copy->circ_lib( $copy->circ_lib->id ); }
853 warn "Updating copy " . Dumper($copy) . "\n";
855 if( $copy->isdeleted ) {
856 return _delete_copy($session, $copy, $editor);
857 } elsif( $copy->isnew ) {
858 $copy = _create_copy($session, $copy, $editor);
859 } elsif( $copy->ischanged ) {
860 _update_copy($session, $copy, $editor);
864 return 1 unless ( $stat_cat_entries and @$stat_cat_entries );
866 my $stat_maps = $session->request(
867 "open-ils.storage.direct.asset.stat_cat_entry_copy_map.search.owning_copy.atomic",
868 $copy->id )->gather(1);
870 if(!$copy->isnew) { _delete_stale_maps($session, $stat_maps, $copy); }
872 # go through the stat cat update/create process
873 for my $stat_entry (@{$stat_cat_entries}){
874 _copy_update_stat_cats( $session, $copy, $stat_maps, $stat_entry, $editor );
881 # -----------------------------------------------------------------
882 # Deletes stat maps attached to this copy in the database that
883 # are no longer attached to the current copy
884 # -----------------------------------------------------------------
885 sub _delete_stale_maps {
886 my( $session, $stat_maps, $copy) = @_;
888 warn "Deleting stale stat maps for copy " . $copy->id . "\n";
889 for my $map (@$stat_maps) {
890 # if there is no stat cat entry on the copy who's id matches the
891 # current map's id, remove the map from the database
892 if(! grep { $_->id == $map->stat_cat_entry } @{$copy->stat_cat_entries} ) {
893 my $req = $session->request(
894 "open-ils.storage.direct.asset.stat_cat_entry_copy_map.delete", $map );
903 # -----------------------------------------------------------------
904 # Searches the stat maps to see if '$entry' already exists on
905 # the given copy. If it does not, a new stat map is created
906 # for the given entry and copy
907 # -----------------------------------------------------------------
908 sub _copy_update_stat_cats {
909 my ( $session, $copy, $stat_maps, $entry, $editor ) = @_;
911 warn "Updating stat maps for copy " . $copy->id . "\n";
913 # see if this map already exists
914 for my $map (@$stat_maps) {
915 if( $map->stat_cat_entry == $entry->id ) {return;}
918 warn "Creating new stat map for stat " .
919 $entry->stat_cat . " and copy " . $copy->id . "\n";
922 my $new_map = Fieldmapper::asset::stat_cat_entry_copy_map->new();
924 $new_map->stat_cat( $entry->stat_cat );
925 $new_map->stat_cat_entry( $entry->id );
926 $new_map->owning_copy( $copy->id );
928 warn "New map is " . Dumper($new_map) . "\n";
930 my $request = $session->request(
931 "open-ils.storage.direct.asset.stat_cat_entry_copy_map.create",
933 my $status = $request->gather(1);
934 warn "created new map with id $status\n";