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 my $nodeset = $utils->tree2nodeset($tree);
115 # copy the doc so that we can mangle the namespace.
116 my $marcxml = OpenILS::Utils::FlatXML->new()->nodeset_to_xml($nodeset);
117 my $copy_marcxml = XML::LibXML->new->parse_string($marcxml->toString);
119 $marcxml->documentElement->setNamespace( "http://www.loc.gov/MARC21/slim", "marc", 1 );
122 #warn "Importing MARC Doc:\n".$marcxml->toString(1)."\n";
123 #warn "Namespace: " . $marcxml->documentElement->firstChild->namespaceURI . "\n";
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]) {
212 $logger->debug("_tcn_exists is true for tcn : $tcn");
216 $logger->debug("_tcn_exists is false for tcn : $tcn");
222 __PACKAGE__->register_method(
223 method => "biblio_record_tree_retrieve",
224 api_name => "open-ils.cat.biblio.record.tree.retrieve",
227 sub biblio_record_tree_retrieve {
229 my( $self, $client, $recordid ) = @_;
231 my $name = "open-ils.storage.direct.biblio.record_entry.retrieve";
232 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
233 my $request = $session->request( $name, $recordid );
234 my $marcxml = $request->gather(1);
237 throw OpenSRF::EX::ERROR
238 ("No record in database with id $recordid");
241 $session->disconnect();
244 warn "turning into nodeset\n";
245 my $nodes = OpenILS::Utils::FlatXML->new()->xml_to_nodeset( $marcxml->marc );
246 warn "turning nodeset into tree\n";
247 my $tree = $utils->nodeset2tree( $nodes->nodeset );
249 $tree->owner_doc( $marcxml->id() );
251 warn "returning tree\n";
256 __PACKAGE__->register_method(
257 method => "biblio_record_tree_commit",
258 api_name => "open-ils.cat.biblio.record.tree.commit",
259 argc => 3, #(session_id, biblio_tree )
260 notes => <<" NOTES");
261 Walks the tree and commits any changed nodes
262 adds any new nodes, and deletes any deleted nodes
263 The record to commit must already exist or this
267 sub biblio_record_tree_commit {
269 my( $self, $client, $user_session, $tree ) = @_;
271 throw OpenSRF::EX::InvalidArg
272 ("Not enough args to to open-ils.cat.biblio.record.tree.commit")
273 unless ( $user_session and $tree );
275 my $user_obj = $apputils->check_user_session($user_session);
277 if($apputils->check_user_perms(
278 $user_obj->id, $user_obj->home_ou, "UPDATE_MARC")) {
279 return OpenILS::Perm->new("UPDATE_MARC");
284 my $docid = $tree->owner_doc();
285 my $session = OpenILS::Application::AppUtils->start_db_session();
287 warn "Retrieving biblio record from storage for update\n";
289 my $req1 = $session->request(
290 "open-ils.storage.direct.biblio.record_entry.batch.retrieve", $docid );
291 my $biblio = $req1->gather(1);
293 warn "retrieved doc $docid\n";
296 # turn the tree into a nodeset
297 my $nodeset = $utils->tree2nodeset($tree);
298 $nodeset = $utils->clean_nodeset($nodeset);
300 if(!defined($docid)) { # be sure
301 for my $node (@$nodeset) {
302 $docid = $node->owner_doc();
303 last if defined($docid);
307 # turn the nodeset into a doc
308 my $marcxml = OpenILS::Utils::FlatXML->new()->nodeset_to_xml( $nodeset );
310 $biblio->marc( $marcxml->toString() );
312 warn "Starting db session\n";
314 my $x = _update_record_metadata( $session, { user => $user_obj, docid => $docid } );
315 OpenILS::Application::AppUtils->rollback_db_session($session) unless $x;
317 warn "Sending updated doc $docid to db\n";
318 my $req = $session->request( "open-ils.storage.direct.biblio.record_entry.update", $biblio );
321 my $status = $req->recv();
322 if( !$status || $status->isa("Error") || ! $status->content) {
323 OpenILS::Application::AppUtils->rollback_db_session($session);
324 if($status->isa("Error")) { throw $status ($status); }
325 throw OpenSRF::EX::ERROR ("Error updating biblio record");
329 # Send the doc to the wormer for wormizing
330 warn "Starting worm session\n";
335 my $wreq = $session->request( "open-ils.worm.wormize.biblio", $docid );
342 warn "wormizing failed, rolling back\n";
343 OpenILS::Application::AppUtils->rollback_db_session($session);
345 if($e) { throw $e ($e); }
346 throw OpenSRF::EX::ERROR ("Wormizing Failed for $docid" );
349 warn "Committing db session...\n";
350 OpenILS::Application::AppUtils->commit_db_session( $session );
352 $nodeset = OpenILS::Utils::FlatXML->new()->xmldoc_to_nodeset($marcxml);
353 $tree = $utils->nodeset2tree($nodeset->nodeset);
354 $tree->owner_doc($docid);
356 # $client->respond_complete($tree);
358 warn "Done wormizing\n";
361 #warn "Returning tree:\n";
370 __PACKAGE__->register_method(
371 method => "biblio_record_record_metadata",
372 api_name => "open-ils.cat.biblio.record.metadata.retrieve",
373 argc => 1, #(session_id, biblio_tree )
374 notes => "Walks the tree and commits any changed nodes " .
375 "adds any new nodes, and deletes any deleted nodes",
378 sub biblio_record_record_metadata {
379 my( $self, $client, @ids ) = @_;
381 if(!@ids){return undef;}
383 my $session = OpenSRF::AppSession->create("open-ils.storage");
384 my $request = $session->request(
385 "open-ils.storage.direct.biblio.record_entry.batch.retrieve", @ids );
389 while( my $response = $request->recv() ) {
392 throw OpenSRF::EX::ERROR ("No Response from Storage");
394 if($response->isa("Error")) {
395 throw $response ($response->stringify);
398 my $record_entry = $response->content;
400 my $creator = $record_entry->creator;
401 my $editor = $record_entry->editor;
403 ($creator, $editor) = _get_userid_by_id($creator, $editor);
405 $record_entry->creator($creator);
406 $record_entry->editor($editor);
408 push @$results, $record_entry;
413 $session->disconnect();
421 sub _get_userid_by_id {
426 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
427 my $request = $session->request(
428 "open-ils.storage.direct.actor.user.batch.retrieve.atomic", @ids );
430 $request->wait_complete;
431 my $response = $request->recv();
432 if(!$request->complete) { return undef; }
434 if($response->isa("Error")){
435 throw $response ($response);
438 for my $u (@{$response->content}) {
440 push @users, $u->usrname;
444 $session->disconnect;
450 sub _get_id_by_userid {
455 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
456 my $request = $session->request(
457 "open-ils.storage.direct.actor.user.search.usrname.atomic", @users );
459 $request->wait_complete;
460 my $response = $request->recv();
461 if(!$request->complete) {
462 throw OpenSRF::EX::ERROR ("no response from storage on user retrieve");
465 if(UNIVERSAL::isa( $response, "Error")){
466 throw $response ($response);
469 for my $u (@{$response->content}) {
475 $session->disconnect;
482 # commits metadata objects to the db
483 sub _update_record_metadata {
485 my ($session, @docs ) = @_;
487 for my $doc (@docs) {
489 my $user_obj = $doc->{user};
490 my $docid = $doc->{docid};
492 warn "Updating metata for doc $docid\n";
494 my $request = $session->request(
495 "open-ils.storage.direct.biblio.record_entry.retrieve", $docid );
496 my $record = $request->gather(1);
498 warn "retrieved record\n";
499 my ($id) = _get_id_by_userid($user_obj->usrname);
501 warn "got $id from _get_id_by_userid\n";
502 $record->editor($id);
504 warn "Grabbed the record, updating and moving on\n";
506 $request = $session->request(
507 "open-ils.storage.direct.biblio.record_entry.update", $record );
511 warn "committing metarecord update\n";
518 __PACKAGE__->register_method(
519 method => "orgs_for_title",
520 api_name => "open-ils.cat.actor.org_unit.retrieve_by_title"
524 my( $self, $client, $record_id ) = @_;
526 my $vols = $apputils->simple_scalar_request(
528 "open-ils.storage.direct.asset.call_number.search.record.atomic",
531 my $orgs = { map {$_->owning_lib => 1 } @$vols };
532 return [ keys %$orgs ];
537 __PACKAGE__->register_method(
538 method => "retrieve_copies",
539 api_name => "open-ils.cat.asset.copy_tree.retrieve");
541 __PACKAGE__->register_method(
542 method => "retrieve_copies",
543 api_name => "open-ils.cat.asset.copy_tree.global.retrieve");
545 # user_session may be null/undef
546 sub retrieve_copies {
548 my( $self, $client, $user_session, $docid, @org_ids ) = @_;
550 if(ref($org_ids[0])) { @org_ids = @{$org_ids[0]}; }
554 warn " $$ retrieving copy tree for orgs @org_ids and doc $docid at " . time() . "\n";
556 # grabbing copy trees should be available for everyone..
557 if(!@org_ids and $user_session) {
559 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
560 @org_ids = ($user_obj->home_ou);
563 if( $self->api_name =~ /global/ ) {
564 warn "performing global copy_tree search for $docid\n";
565 return _build_volume_list( { record => $docid } );
570 for my $orgid (@org_ids) {
571 my $vols = _build_volume_list(
572 { record => $docid, owning_lib => $orgid } );
573 warn "Volumes built for org $orgid\n";
574 push( @all_vols, @$vols );
577 warn " $$ Finished copy_tree at " . time() . "\n";
585 sub _build_volume_list {
586 my $search_hash = shift;
588 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
591 my $request = $session->request(
592 "open-ils.storage.direct.asset.call_number.search.atomic", $search_hash );
594 my $vols = $request->gather(1);
597 for my $volume (@$vols) {
599 warn "Grabbing copies for volume: " . $volume->id . "\n";
600 my $creq = $session->request(
601 "open-ils.storage.direct.asset.copy.search.call_number.atomic", $volume->id );
603 my $copies = $creq->gather(1);
605 $copies = [ sort { $a->barcode cmp $b->barcode } @$copies ];
607 $volume->copies($copies);
609 push( @volumes, $volume );
613 $session->disconnect();
619 # -----------------------------------------------------------------
620 # Fleshed volume tree batch add/update. This does everything a
621 # volume tree could want, add, update, delete
622 # -----------------------------------------------------------------
623 __PACKAGE__->register_method(
624 method => "volume_tree_fleshed_update",
625 api_name => "open-ils.cat.asset.volume_tree.fleshed.batch.update",
627 sub volume_tree_fleshed_update {
629 my( $self, $client, $user_session, $volumes ) = @_;
630 return undef unless $volumes;
632 my $user_obj = $apputils->check_user_session($user_session);
635 my $session = $apputils->start_db_session();
636 warn "Looping on volumes in fleshed volume tree update\n";
638 # cycle through the volumes provided and update/create/delete where necessary
639 for my $volume (@$volumes) {
641 warn "updating volume " . $volume->id . "\n";
643 my $update_copy_list = $volume->copies;
646 if( $volume->isdeleted) {
647 my $status = _delete_volume($session, $volume, $user_obj);
649 throw OpenSRF::EX::ERROR
650 ("Volume delete failed for volume " . $volume->id);
652 if(UNIVERSAL::isa($status, "Fieldmapper::perm_ex")) { return $status; }
654 } elsif( $volume->isnew ) {
657 $volume->editor($user_obj->id);
658 $volume->creator($user_obj->id);
659 $volume = _add_volume($session, $volume, $user_obj);
662 if($volume and UNIVERSAL::isa($volume, "Fieldmapper::perm_ex")) { return $volume; }
664 } elsif( $volume->ischanged ) {
666 $volume->editor($user_obj->id);
667 my $stat = _update_volume($session, $volume, $user_obj);
668 if($stat and UNIVERSAL::isa($stat, "Fieldmapper::perm_ex")) { return $stat; }
672 if( ! $volume->isdeleted ) {
673 for my $copy (@{$update_copy_list}) {
675 $copy->editor($user_obj->id);
676 warn "updating copy for volume " . $volume->id . "\n";
681 $copy->call_number($volume->id);
682 $copy->creator($user_obj->id);
683 $copy = _fleshed_copy_update($session,$copy,$user_obj);
685 } elsif( $copy->ischanged ) {
686 $copy->call_number($volume->id);
687 $copy = _fleshed_copy_update($session, $copy, $user_obj);
689 } elsif( $copy->isdeleted ) {
690 warn "Deleting copy " . $copy->id . " for volume " . $volume->id . "\n";
691 my $status = _fleshed_copy_update($session, $copy, $user_obj);
692 warn "Copy delete returned a status of $status\n";
698 $apputils->commit_db_session($session);
699 return scalar(@$volumes);
704 my( $session, $volume, $user_obj ) = @_;
706 if($apputils->check_user_perms(
707 $user_obj->id, $user_obj->home_ou, "DELETE_VOLUME")) {
708 return OpenILS::Perm->new("DELETE_VOLUME"); }
710 #$volume = _find_volume($session, $volume);
711 warn "Deleting volume " . $volume->id . "\n";
713 my $copies = $session->request(
714 "open-ils.storage.direct.asset.copy.search.call_number.atomic",
715 $volume->id )->gather(1);
717 throw OpenSRF::EX::ERROR
718 ("Cannot remove volume with copies attached");
721 my $req = $session->request(
722 "open-ils.storage.direct.asset.call_number.delete",
724 return $req->gather(1);
729 my($session, $volume, $user_obj) = @_;
730 if($apputils->check_user_perms(
731 $user_obj->id, $user_obj->home_ou, "UPDATE_VOLUME")) {
732 return OpenILS::Perm->new("UPDATE_VOLUME"); }
734 my $req = $session->request(
735 "open-ils.storage.direct.asset.call_number.update",
737 my $status = $req->gather(1);
742 my($session, $volume, $user_obj) = @_;
744 if($apputils->check_user_perms(
745 $user_obj->id, $user_obj->home_ou, "CREATE_VOLUME")) {
746 warn "User does not have priveleges to create new volumes\n";
747 return OpenILS::Perm->new("CREATE_VOLUME");
750 my $request = $session->request(
751 "open-ils.storage.direct.asset.call_number.create", $volume );
753 my $id = $request->gather(1);
756 OpenILS::Application::AppUtils->rollback_db_session($session);
757 throw OpenSRF::EX::ERROR (" * -> Error creating new volume");
761 warn "received new volume id: $id\n";
769 __PACKAGE__->register_method(
770 method => "fleshed_copy_update",
771 api_name => "open-ils.cat.asset.copy.fleshed.batch.update",
774 sub fleshed_copy_update {
775 my($self, $client, $user_session, $copies) = @_;
777 my $user_obj = $apputils->check_user_session($user_session);
778 my $session = $apputils->start_db_session();
780 for my $copy (@$copies) {
781 _fleshed_copy_update($session, $copy, $user_obj);
784 $apputils->commit_db_session($session);
791 my($session, $copy, $user_obj) = @_;
793 if($apputils->check_user_perms(
794 $user_obj->id, $user_obj->home_ou, "DELETE_COPY")) {
795 return OpenILS::Perm->new("DELETE_COPY"); }
797 warn "Deleting copy " . $copy->id . "\n";
798 my $request = $session->request(
799 "open-ils.storage.direct.asset.copy.delete",
801 return $request->gather(1);
805 my($session, $copy, $user_obj) = @_;
807 if($apputils->check_user_perms(
808 $user_obj->id, $user_obj->home_ou, "CREATE_COPY")) {
809 return OpenILS::Perm->new("CREATE_COPY"); }
811 my $request = $session->request(
812 "open-ils.storage.direct.asset.copy.create",
814 my $id = $request->gather(1);
817 throw OpenSRF::EX::ERROR
818 ("Unable to create new copy " . Dumper($copy));
821 warn "Created copy " . $copy->id . "\n";
828 my($session, $copy, $user_obj) = @_;
830 my $evt = $apputils->check_perms($user_obj->id, $copy->circ_lib, 'UPDATE_COPY');
831 return $evt if $evt; #XXX NOT YET HANDLED BY CALLER
833 my $status = $apputils->simplereq(
835 "open-ils.storage.direct.asset.copy.update", $copy );
836 $logger->debug("Successfully updated copy " . $copy->id );
841 # -----------------------------------------------------------------
842 # Creates/Updates/Deletes a fleshed asset.copy.
843 # adds/deletes copy stat_cat maps where necessary
844 # -----------------------------------------------------------------
845 sub _fleshed_copy_update {
846 my($session, $copy, $editor) = @_;
848 my $stat_cat_entries = $copy->stat_cat_entries;
849 $copy->editor($editor->id);
851 # in case we're fleshed
852 if(ref($copy->status)) {$copy->status( $copy->status->id ); }
853 if(ref($copy->location)) {$copy->location( $copy->location->id ); }
854 if(ref($copy->circ_lib)) {$copy->circ_lib( $copy->circ_lib->id ); }
856 warn "Updating copy " . Dumper($copy) . "\n";
858 if( $copy->isdeleted ) {
859 return _delete_copy($session, $copy, $editor);
860 } elsif( $copy->isnew ) {
861 $copy = _create_copy($session, $copy, $editor);
862 } elsif( $copy->ischanged ) {
863 _update_copy($session, $copy, $editor);
867 return 1 unless ( $stat_cat_entries and @$stat_cat_entries );
869 my $stat_maps = $session->request(
870 "open-ils.storage.direct.asset.stat_cat_entry_copy_map.search.owning_copy.atomic",
871 $copy->id )->gather(1);
873 if(!$copy->isnew) { _delete_stale_maps($session, $stat_maps, $copy); }
875 # go through the stat cat update/create process
876 for my $stat_entry (@{$stat_cat_entries}){
877 _copy_update_stat_cats( $session, $copy, $stat_maps, $stat_entry, $editor );
884 # -----------------------------------------------------------------
885 # Deletes stat maps attached to this copy in the database that
886 # are no longer attached to the current copy
887 # -----------------------------------------------------------------
888 sub _delete_stale_maps {
889 my( $session, $stat_maps, $copy) = @_;
891 warn "Deleting stale stat maps for copy " . $copy->id . "\n";
892 for my $map (@$stat_maps) {
893 # if there is no stat cat entry on the copy who's id matches the
894 # current map's id, remove the map from the database
895 if(! grep { $_->id == $map->stat_cat_entry } @{$copy->stat_cat_entries} ) {
896 my $req = $session->request(
897 "open-ils.storage.direct.asset.stat_cat_entry_copy_map.delete", $map );
906 # -----------------------------------------------------------------
907 # Searches the stat maps to see if '$entry' already exists on
908 # the given copy. If it does not, a new stat map is created
909 # for the given entry and copy
910 # -----------------------------------------------------------------
911 sub _copy_update_stat_cats {
912 my ( $session, $copy, $stat_maps, $entry, $editor ) = @_;
914 warn "Updating stat maps for copy " . $copy->id . "\n";
916 # see if this map already exists
917 for my $map (@$stat_maps) {
918 if( $map->stat_cat_entry == $entry->id ) {return;}
921 warn "Creating new stat map for stat " .
922 $entry->stat_cat . " and copy " . $copy->id . "\n";
925 my $new_map = Fieldmapper::asset::stat_cat_entry_copy_map->new();
927 $new_map->stat_cat( $entry->stat_cat );
928 $new_map->stat_cat_entry( $entry->id );
929 $new_map->owning_copy( $copy->id );
931 warn "New map is " . Dumper($new_map) . "\n";
933 my $request = $session->request(
934 "open-ils.storage.direct.asset.stat_cat_entry_copy_map.create",
936 my $status = $request->gather(1);
937 warn "created new map with id $status\n";