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 Unicode::Normalize;
15 use OpenILS::Utils::FlatXML;
17 use OpenSRF::Utils::SettingsClient;
18 use OpenSRF::Utils::Logger qw($logger);
20 my $apputils = "OpenILS::Application::AppUtils";
22 my $utils = "OpenILS::Application::Cat::Utils";
38 $stuff =~ s/([\x{0080}-\x{fffd}])/sprintf('&#x%X;',ord($1))/sgoe;
42 __PACKAGE__->register_method(
43 method => "retrieve_marc_template",
44 api_name => "open-ils.cat.biblio.marc_template.retrieve",
46 Returns a MARC 'record tree' based on a set of pre-defined templates.
47 Templates include : book
50 sub retrieve_marc_template {
51 my( $self, $client, $type ) = @_;
53 return $marctemplates{$type} if defined($marctemplates{$type});
54 $marctemplates{$type} = _load_marc_template($type);
55 return $marctemplates{$type};
58 sub _load_marc_template {
61 if(!$conf) { $conf = OpenSRF::Utils::SettingsClient->new; }
63 my $template = $conf->config_value(
64 "apps", "open-ils.cat","app_settings", "marctemplates", $type );
65 warn "Opening template file $template\n";
67 open( F, $template ) or
68 throw OpenSRF::EX::ERROR ("Unable to open MARC template file: $template : $@");
72 my $xml = join('', @xml);
74 return XML::LibXML->new->parse_string($xml)->documentElement->toString;
79 __PACKAGE__->register_method(
80 method => "create_record_xml",
81 api_name => "open-ils.cat.biblio.record.xml.create",
83 Inserts a new MARC 'record tree' into the system
86 sub create_record_xml {
87 my( $self, $client, $login, $tree, $source ) = @_;
90 my $user_obj = $apputils->check_user_session($login);
92 if($apputils->check_user_perms(
93 $user_obj->id, $user_obj->home_ou, "CREATE_MARC")) {
94 return OpenILS::Perm->new("CREATE_MARC");
97 warn "Creating a new record entry...";
98 my $meth = $self->method_lookup("open-ils.cat.biblio.record.xml.import");
99 my ($s) = $meth->run($login, $tree, 2);
106 __PACKAGE__->register_method(
107 method => "biblio_record_xml_import",
108 api_name => "open-ils.cat.biblio.record.xml.import",
109 notes => <<" NOTES");
110 Takes a marcxml record and imports the record into the database. In this
111 case, the marcxml record is assumed to be a complete record (i.e. valid
112 MARC). The title control number is taken from (whichever comes first)
113 tags 001, 039[ab], 020a, 022a, 010, 035a and whichever does not already exist
115 user_session must have IMPORT_MARC permissions
119 sub biblio_record_xml_import {
120 my( $self, $client, $user_session, $xml, $source) = @_;
121 my $user_obj = $apputils->check_user_session($user_session);
123 if($apputils->check_user_perms(
124 $user_obj->id, $user_obj->home_ou, "IMPORT_MARC")) {
125 return OpenILS::Perm->new("IMPORT_MARC");
128 # copy the doc so that we can mangle the namespace.
129 my $marcxml = XML::LibXML->new->parse_string( $xml );
131 $marcxml->documentElement->setNamespace( "http://www.loc.gov/MARC21/slim", "marc", 1 );
132 my ($tcn, $tcn_source);
134 #warn "Importing MARC Doc:\n".$marcxml->toString(1)."\n";
135 #warn "Namespace: " . $marcxml->documentElement->firstChild->namespaceURI . "\n";
138 warn "Starting db session in import\n";
139 my $session = $apputils->start_db_session();
141 my $xpath = '//controlfield[@tag="001"]';
142 $tcn = $marcxml->documentElement->findvalue($xpath);
144 $xpath = '//controlfield[@tag="003"]';
145 $tcn_source = $marcxml->documentElement->findvalue($xpath);
147 if(_tcn_exists($session, $tcn)) {$tcn = undef;}
151 $xpath = '//datafield[@tag="039"]/subfield[@code="a"]';
152 ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
154 $add_039++ if (!$tcn);
156 $xpath = '//datafield[@tag="039"]/subfield[@code="b"]';
157 $tcn_source = $marcxml->documentElement->findvalue($xpath) || "System Local";
158 if(_tcn_exists($session, $tcn, $tcn_source)) {$tcn = undef;}
162 $xpath = '//datafield[@tag="020"]/subfield[@code="a"]';
163 ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
164 $tcn_source = "ISBN";
165 if(_tcn_exists($session, $tcn, $tcn_source)) {$tcn = undef;}
169 $xpath = '//datafield[@tag="022"]/subfield[@code="a"]';
170 ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
171 $tcn_source = "ISSN";
172 if(_tcn_exists($session, $tcn, $tcn_source)) {$tcn = undef;}
176 $xpath = '//datafield[@tag="010"]';
177 ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
178 $tcn_source = "LCCN";
179 if(_tcn_exists($session, $tcn, $tcn_source)) {$tcn = undef;}
183 $xpath = '//datafield[@tag="035"]/subfield[@code="a"]';
184 ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
185 $tcn_source = "System Legacy";
186 if(_tcn_exists($session, $tcn, $tcn_source)) {$tcn = undef;}
189 $marcxml->documentElement->removeChild(
190 $marcxml->documentElement->findnodes( '//datafield[@tag="035"]' )
196 my $df = $marcxml->createElementNS( 'http://www.loc.gov/MARC21/slim', 'datafield');
197 $df->setAttribute( tag => '039' );
198 $df->setAttribute( ind1 => ' ' );
199 $df->setAttribute( ind2 => ' ' );
200 $marcxml->documentElement->appendChild( $df );
202 my $sfa = $marcxml->createElementNS( 'http://www.loc.gov/MARC21/slim', 'subfield');
203 $sfa->setAttribute( code => 'a' );
204 $sfa->appendChild( $marcxml->createTextNode( $tcn ) );
205 $df->appendChid( $sfa );
207 my $sfb = $marcxml->createElementNS( 'http://www.loc.gov/MARC21/slim', 'subfield');
208 $sfb->setAttribute( code => 'b' );
209 $sfb->appendChild( $marcxml->createTextNode( $tcn_source ) );
210 $df->appendChid( $sfb );
213 warn "Record import with tcn: $tcn and source $tcn_source\n";
215 my $record = Fieldmapper::biblio::record_entry->new;
217 $record->source($source) if ($source);
218 $record->tcn_source($tcn_source);
219 $record->tcn_value($tcn);
220 $record->creator($user_obj->id);
221 $record->editor($user_obj->id);
222 $record->marc( entityize( $marcxml->documentElement->toString ) );
225 my $req = $session->request(
226 "open-ils.storage.direct.biblio.record_entry.create", $record );
228 my $id = $req->gather(1);
231 if(!$id) { throw OpenSRF::EX::ERROR ("Unable to create new record_entry from import"); }
232 warn "received id: $id from record_entry create\n";
234 $apputils->commit_db_session($session);
236 $session = OpenSRF::AppSession->create("open-ils.storage");
238 my $wreq = $session->request("open-ils.worm.wormize.biblio", $id)->gather(1);
239 warn "Done worming record $id\n";
241 if(!$wreq) { throw OpenSRF::EX::ERROR ("Unable to wormize imported record"); }
252 if(!$tcn) {return 0;}
254 my $req = $session->request(
255 "open-ils.storage.id_list.biblio.record_entry.search_where.atomic",
256 { tcn_value => $tcn, tcn_source => $source, deleted => 'f' } );
258 my $recs = $req->gather(1);
260 if($recs and $recs->[0]) {
261 $logger->debug("_tcn_exists is true for tcn : $tcn ($source)");
265 $logger->debug("_tcn_exists is false for tcn : $tcn ($source)");
271 __PACKAGE__->register_method(
272 method => "biblio_record_tree_retrieve",
273 api_name => "open-ils.cat.biblio.record.tree.retrieve",
276 sub biblio_record_tree_retrieve {
278 my( $self, $client, $recordid ) = @_;
280 my $name = "open-ils.storage.direct.biblio.record_entry.retrieve";
281 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
282 my $request = $session->request( $name, $recordid );
283 my $marcxml = $request->gather(1);
286 throw OpenSRF::EX::ERROR
287 ("No record in database with id $recordid");
290 $session->disconnect();
293 warn "turning into nodeset\n";
294 my $nodes = OpenILS::Utils::FlatXML->new()->xml_to_nodeset( $marcxml->marc );
295 warn "turning nodeset into tree\n";
296 my $tree = $utils->nodeset2tree( $nodes->nodeset );
298 $tree->owner_doc( $marcxml->id() );
300 warn "returning tree\n";
305 __PACKAGE__->register_method(
306 method => "biblio_record_xml_update",
307 api_name => "open-ils.cat.biblio.record.xml.update",
308 argc => 3, #(session_id, biblio_tree )
309 notes => <<' NOTES');
310 Updates the XML of a biblio record entry
311 @param authtoken The session token for the staff updating the record
312 @param docID The record entry ID to update
313 @param xml The new MARCXML record
316 sub biblio_record_xml_update {
318 my( $self, $client, $user_session, $id, $xml ) = @_;
320 throw OpenSRF::EX::InvalidArg
321 ("Not enough args to to open-ils.cat.biblio.record.tree.commit")
322 unless ( $user_session and $tree );
324 my $user_obj = $apputils->check_user_session($user_session);
326 if($apputils->check_user_perms(
327 $user_obj->id, $user_obj->home_ou, "UPDATE_MARC")) {
328 return OpenILS::Perm->new("UPDATE_MARC");
332 warn "Starting db session\n";
333 my $session = OpenILS::Application::AppUtils->start_db_session();
335 warn "Retrieving biblio record from storage for update\n";
337 my $req1 = $session->request(
338 "open-ils.storage.direct.biblio.record_entry.batch.retrieve", $id );
339 my $biblio = $req1->gather(1);
341 warn "retrieved doc $id\n";
343 $biblio->marc( entityize( $xml ) );
344 $biblio->editor( $user_obj->id );
345 $biblio->edit_date( 'now' );
348 warn "Sending updated doc $id to db\n";
349 my $req = $session->request( "open-ils.storage.direct.biblio.record_entry.update", $biblio );
352 my $status = $req->recv();
353 if( !$status || $status->isa("Error") || ! $status->content) {
354 OpenILS::Application::AppUtils->rollback_db_session($session);
355 if($status->isa("Error")) { throw $status ($status); }
356 throw OpenSRF::EX::ERROR ("Error updating biblio record");
360 # Send the doc to the wormer for wormizing
361 warn "Starting worm session\n";
366 my $wreq = $session->request( "open-ils.worm.wormize.biblio", $docid );
370 $w = $wreq->gather(1);
374 warn "wormizing failed, rolling back\n";
375 OpenILS::Application::AppUtils->rollback_db_session($session);
377 if($e) { throw $e ($e); }
378 throw OpenSRF::EX::ERROR ("Wormizing Failed for $docid" );
381 warn "Committing db session...\n";
382 OpenILS::Application::AppUtils->commit_db_session( $session );
384 # $client->respond_complete($tree);
386 warn "Done wormizing\n";
389 #warn "Returning tree:\n";
398 __PACKAGE__->register_method(
399 method => "biblio_record_record_metadata",
400 api_name => "open-ils.cat.biblio.record.metadata.retrieve",
401 argc => 1, #(session_id, biblio_tree )
402 notes => "Walks the tree and commits any changed nodes " .
403 "adds any new nodes, and deletes any deleted nodes",
406 sub biblio_record_record_metadata {
407 my( $self, $client, @ids ) = @_;
409 if(!@ids){return undef;}
411 my $session = OpenSRF::AppSession->create("open-ils.storage");
412 my $request = $session->request(
413 "open-ils.storage.direct.biblio.record_entry.batch.retrieve", @ids );
417 while( my $response = $request->recv() ) {
420 throw OpenSRF::EX::ERROR ("No Response from Storage");
422 if($response->isa("Error")) {
423 throw $response ($response->stringify);
426 my $record_entry = $response->content;
428 my $creator = $record_entry->creator;
429 my $editor = $record_entry->editor;
431 ($creator, $editor) = _get_userid_by_id($creator, $editor);
433 $record_entry->creator($creator);
434 $record_entry->editor($editor);
436 push @$results, $record_entry;
441 $session->disconnect();
448 __PACKAGE__->register_method(
449 method => "biblio_record_marc_cn",
450 api_name => "open-ils.cat.biblio.record.marc_cn.retrieve",
451 argc => 1, #(bib id )
454 sub biblio_record_marc_cn {
455 my( $self, $client, $id ) = @_;
457 my $session = OpenSRF::AppSession->create("open-ils.storage");
459 ->request("open-ils.storage.direct.biblio.record_entry.retrieve", $id )
463 my $doc = XML::LibXML->new->parse_string($marc);
464 $doc->documentElement->setNamespace( "http://www.loc.gov/MARC21/slim", "marc", 1 );
467 for my $tag ( qw/050 055 060 070 080 082 086 088 090 092 096 098 099/ ) {
468 my @node = $doc->findnodes("//marc:datafield[\@tag='$tag']");
470 my $cn = $x->findvalue("marc:subfield[\@code='a' or \@code='b']");
471 push @res, {$tag => $cn} if ($cn);
479 sub _get_userid_by_id {
484 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
485 my $request = $session->request(
486 "open-ils.storage.direct.actor.user.batch.retrieve.atomic", @ids );
488 $request->wait_complete;
489 my $response = $request->recv();
490 if(!$request->complete) { return undef; }
492 if($response->isa("Error")){
493 throw $response ($response);
496 for my $u (@{$response->content}) {
498 push @users, $u->usrname;
502 $session->disconnect;
508 sub _get_id_by_userid {
513 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
514 my $request = $session->request(
515 "open-ils.storage.direct.actor.user.search.usrname.atomic", @users );
517 $request->wait_complete;
518 my $response = $request->recv();
519 if(!$request->complete) {
520 throw OpenSRF::EX::ERROR ("no response from storage on user retrieve");
523 if(UNIVERSAL::isa( $response, "Error")){
524 throw $response ($response);
527 for my $u (@{$response->content}) {
533 $session->disconnect;
540 # commits metadata objects to the db
541 sub _update_record_metadata {
543 my ($session, @docs ) = @_;
545 for my $doc (@docs) {
547 my $user_obj = $doc->{user};
548 my $docid = $doc->{docid};
550 warn "Updating metata for doc $docid\n";
552 my $request = $session->request(
553 "open-ils.storage.direct.biblio.record_entry.retrieve", $docid );
554 my $record = $request->gather(1);
556 warn "retrieved record\n";
557 my ($id) = _get_id_by_userid($user_obj->usrname);
559 warn "got $id from _get_id_by_userid\n";
560 $record->editor($id);
562 warn "Grabbed the record, updating and moving on\n";
564 $request = $session->request(
565 "open-ils.storage.direct.biblio.record_entry.update", $record );
569 warn "committing metarecord update\n";
576 __PACKAGE__->register_method(
577 method => "orgs_for_title",
578 api_name => "open-ils.cat.actor.org_unit.retrieve_by_title"
582 my( $self, $client, $record_id ) = @_;
584 my $vols = $apputils->simple_scalar_request(
586 "open-ils.storage.direct.asset.call_number.search_where.atomic",
587 { record => $record_id, deleted => 'f' });
588 #"open-ils.storage.direct.asset.call_number.search.record.atomic",
590 my $orgs = { map {$_->owning_lib => 1 } @$vols };
591 return [ keys %$orgs ];
595 __PACKAGE__->register_method(
596 method => "retrieve_copies",
597 api_name => "open-ils.cat.asset.copy_tree.retrieve");
599 __PACKAGE__->register_method(
600 method => "retrieve_copies",
601 api_name => "open-ils.cat.asset.copy_tree.global.retrieve");
603 # user_session may be null/undef
604 sub retrieve_copies {
606 my( $self, $client, $user_session, $docid, @org_ids ) = @_;
608 if(ref($org_ids[0])) { @org_ids = @{$org_ids[0]}; }
612 warn " $$ retrieving copy tree for orgs @org_ids and doc $docid at " . time() . "\n";
614 # grabbing copy trees should be available for everyone..
615 if(!@org_ids and $user_session) {
617 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
618 @org_ids = ($user_obj->home_ou);
621 if( $self->api_name =~ /global/ ) {
622 warn "performing global copy_tree search for $docid\n";
623 return _build_volume_list( { record => $docid } );
628 for my $orgid (@org_ids) {
629 my $vols = _build_volume_list(
630 { record => $docid, owning_lib => $orgid } );
631 warn "Volumes built for org $orgid\n";
632 push( @all_vols, @$vols );
635 warn " $$ Finished copy_tree at " . time() . "\n";
643 sub _build_volume_list {
644 my $search_hash = shift;
646 $search_hash->{deleted} = 'f';
648 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
651 my $request = $session->request(
652 "open-ils.storage.direct.asset.call_number.search.atomic", $search_hash );
653 #"open-ils.storage.direct.asset.call_number.search.atomic", $search_hash );
655 my $vols = $request->gather(1);
658 for my $volume (@$vols) {
660 warn "Grabbing copies for volume: " . $volume->id . "\n";
661 my $creq = $session->request(
662 "open-ils.storage.direct.asset.copy.search_where.atomic",
663 { call_number => $volume->id , deleted => 'f' });
664 #"open-ils.storage.direct.asset.copy.search.call_number.atomic", $volume->id );
666 my $copies = $creq->gather(1);
668 $copies = [ sort { $a->barcode cmp $b->barcode } @$copies ];
670 $volume->copies($copies);
672 push( @volumes, $volume );
676 $session->disconnect();
682 # -----------------------------------------------------------------
683 # Fleshed volume tree batch add/update. This does everything a
684 # volume tree could want, add, update, delete
685 # -----------------------------------------------------------------
686 __PACKAGE__->register_method(
687 method => "volume_tree_fleshed_update",
688 api_name => "open-ils.cat.asset.volume_tree.fleshed.batch.update",
690 sub volume_tree_fleshed_update {
692 my( $self, $client, $user_session, $volumes ) = @_;
693 return undef unless $volumes;
695 my $user_obj = $apputils->check_user_session($user_session);
698 my $session = $apputils->start_db_session();
699 warn "Looping on volumes in fleshed volume tree update\n";
701 # cycle through the volumes provided and update/create/delete where necessary
702 for my $volume (@$volumes) {
704 warn "updating volume " . $volume->id . "\n";
706 my $update_copy_list = $volume->copies;
709 if( $volume->isdeleted) {
710 my $status = _delete_volume($session, $volume, $user_obj);
712 #throw OpenSRF::EX::ERROR
713 #("Volume delete failed for volume " . $volume->id);
715 if(UNIVERSAL::isa($status, "Fieldmapper::perm_ex")) { return $status; }
717 } elsif( $volume->isnew ) {
720 $volume->editor($user_obj->id);
721 $volume->creator($user_obj->id);
722 $volume = _add_volume($session, $volume, $user_obj);
725 if($volume and UNIVERSAL::isa($volume, "Fieldmapper::perm_ex")) { return $volume; }
727 } elsif( $volume->ischanged ) {
729 $volume->editor($user_obj->id);
730 my $stat = _update_volume($session, $volume, $user_obj);
731 if($stat and UNIVERSAL::isa($stat, "Fieldmapper::perm_ex")) { return $stat; }
735 if( ! $volume->isdeleted ) {
736 for my $copy (@{$update_copy_list}) {
738 $copy->editor($user_obj->id);
739 warn "updating copy for volume " . $volume->id . "\n";
744 $copy->call_number($volume->id);
745 $copy->creator($user_obj->id);
746 $copy = _fleshed_copy_update($session,$copy,$user_obj);
748 } elsif( $copy->ischanged ) {
749 $copy->call_number($volume->id);
750 $copy = _fleshed_copy_update($session, $copy, $user_obj);
752 } elsif( $copy->isdeleted ) {
753 warn "Deleting copy " . $copy->id . " for volume " . $volume->id . "\n";
754 my $status = _fleshed_copy_update($session, $copy, $user_obj);
755 warn "Copy delete returned a status of $status\n";
761 $apputils->commit_db_session($session);
762 return scalar(@$volumes);
767 my( $session, $volume, $user_obj ) = @_;
769 if($apputils->check_user_perms(
770 $user_obj->id, $user_obj->home_ou, "DELETE_VOLUME")) {
771 return OpenILS::Perm->new("DELETE_VOLUME"); }
773 #$volume = _find_volume($session, $volume);
774 warn "Deleting volume " . $volume->id . "\n";
776 my $copies = $session->request(
777 "open-ils.storage.direct.asset.copy.search_where.atomic",
778 { call_number => $volume->id, deleted => 'f' } )->gather(1);
779 #"open-ils.storage.direct.asset.copy.search.call_number.atomic",
782 throw OpenSRF::EX::ERROR
783 ("Cannot remove volume with copies attached");
786 my $req = $session->request(
787 "open-ils.storage.direct.asset.call_number.delete",
789 return $req->gather(1);
794 my($session, $volume, $user_obj) = @_;
795 if($apputils->check_user_perms(
796 $user_obj->id, $user_obj->home_ou, "UPDATE_VOLUME")) {
797 return OpenILS::Perm->new("UPDATE_VOLUME"); }
799 my $req = $session->request(
800 "open-ils.storage.direct.asset.call_number.update",
802 my $status = $req->gather(1);
807 my($session, $volume, $user_obj) = @_;
809 if($apputils->check_user_perms(
810 $user_obj->id, $user_obj->home_ou, "CREATE_VOLUME")) {
811 warn "User does not have priveleges to create new volumes\n";
812 return OpenILS::Perm->new("CREATE_VOLUME");
815 my $request = $session->request(
816 "open-ils.storage.direct.asset.call_number.create", $volume );
818 my $id = $request->gather(1);
821 OpenILS::Application::AppUtils->rollback_db_session($session);
822 throw OpenSRF::EX::ERROR (" * -> Error creating new volume");
826 warn "received new volume id: $id\n";
834 __PACKAGE__->register_method(
835 method => "fleshed_copy_update",
836 api_name => "open-ils.cat.asset.copy.fleshed.batch.update",
839 sub fleshed_copy_update {
840 my($self, $client, $user_session, $copies) = @_;
842 my $user_obj = $apputils->check_user_session($user_session);
843 my $session = $apputils->start_db_session();
845 for my $copy (@$copies) {
846 _fleshed_copy_update($session, $copy, $user_obj);
849 $apputils->commit_db_session($session);
856 my($session, $copy, $user_obj) = @_;
858 if($apputils->check_user_perms(
859 $user_obj->id, $user_obj->home_ou, "DELETE_COPY")) {
860 return OpenILS::Perm->new("DELETE_COPY"); }
862 warn "Deleting copy " . $copy->id . "\n";
863 my $request = $session->request(
864 "open-ils.storage.direct.asset.copy.delete",
866 return $request->gather(1);
870 my($session, $copy, $user_obj) = @_;
872 if($apputils->check_user_perms(
873 $user_obj->id, $user_obj->home_ou, "CREATE_COPY")) {
874 return OpenILS::Perm->new("CREATE_COPY"); }
876 my $request = $session->request(
877 "open-ils.storage.direct.asset.copy.create",
879 my $id = $request->gather(1);
882 throw OpenSRF::EX::ERROR
883 ("Unable to create new copy " . Dumper($copy));
886 warn "Created copy " . $copy->id . "\n";
893 my($session, $copy, $user_obj) = @_;
895 my $evt = $apputils->check_perms($user_obj->id, $copy->circ_lib, 'UPDATE_COPY');
896 return $evt if $evt; #XXX NOT YET HANDLED BY CALLER
898 my $status = $apputils->simplereq(
900 "open-ils.storage.direct.asset.copy.update", $copy );
901 $logger->debug("Successfully updated copy " . $copy->id );
906 # -----------------------------------------------------------------
907 # Creates/Updates/Deletes a fleshed asset.copy.
908 # adds/deletes copy stat_cat maps where necessary
909 # -----------------------------------------------------------------
910 sub _fleshed_copy_update {
911 my($session, $copy, $editor) = @_;
913 my $stat_cat_entries = $copy->stat_cat_entries;
914 $copy->editor($editor->id);
916 # in case we're fleshed
917 if(ref($copy->status)) {$copy->status( $copy->status->id ); }
918 if(ref($copy->location)) {$copy->location( $copy->location->id ); }
919 if(ref($copy->circ_lib)) {$copy->circ_lib( $copy->circ_lib->id ); }
921 warn "Updating copy " . Dumper($copy) . "\n";
923 if( $copy->isdeleted ) {
924 return _delete_copy($session, $copy, $editor);
925 } elsif( $copy->isnew ) {
926 $copy = _create_copy($session, $copy, $editor);
927 } elsif( $copy->ischanged ) {
928 _update_copy($session, $copy, $editor);
932 return 1 unless ( $stat_cat_entries and @$stat_cat_entries );
934 my $stat_maps = $session->request(
935 "open-ils.storage.direct.asset.stat_cat_entry_copy_map.search.owning_copy.atomic",
936 $copy->id )->gather(1);
938 if(!$copy->isnew) { _delete_stale_maps($session, $stat_maps, $copy); }
940 # go through the stat cat update/create process
941 for my $stat_entry (@{$stat_cat_entries}){
942 _copy_update_stat_cats( $session, $copy, $stat_maps, $stat_entry, $editor );
949 # -----------------------------------------------------------------
950 # Deletes stat maps attached to this copy in the database that
951 # are no longer attached to the current copy
952 # -----------------------------------------------------------------
953 sub _delete_stale_maps {
954 my( $session, $stat_maps, $copy) = @_;
956 warn "Deleting stale stat maps for copy " . $copy->id . "\n";
957 for my $map (@$stat_maps) {
958 # if there is no stat cat entry on the copy who's id matches the
959 # current map's id, remove the map from the database
960 if(! grep { $_->id == $map->stat_cat_entry } @{$copy->stat_cat_entries} ) {
961 my $req = $session->request(
962 "open-ils.storage.direct.asset.stat_cat_entry_copy_map.delete", $map );
971 # -----------------------------------------------------------------
972 # Searches the stat maps to see if '$entry' already exists on
973 # the given copy. If it does not, a new stat map is created
974 # for the given entry and copy
975 # -----------------------------------------------------------------
976 sub _copy_update_stat_cats {
977 my ( $session, $copy, $stat_maps, $entry, $editor ) = @_;
979 warn "Updating stat maps for copy " . $copy->id . "\n";
981 # see if this map already exists
982 for my $map (@$stat_maps) {
983 if( $map->stat_cat_entry == $entry->id ) {return;}
986 warn "Creating new stat map for stat " .
987 $entry->stat_cat . " and copy " . $copy->id . "\n";
990 my $new_map = Fieldmapper::asset::stat_cat_entry_copy_map->new();
992 $new_map->stat_cat( $entry->stat_cat );
993 $new_map->stat_cat_entry( $entry->id );
994 $new_map->owning_copy( $copy->id );
996 warn "New map is " . Dumper($new_map) . "\n";
998 my $request = $session->request(
999 "open-ils.storage.direct.asset.stat_cat_entry_copy_map.create",
1001 my $status = $request->gather(1);
1002 warn "created new map with id $status\n";