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;
12 my $utils = "OpenILS::Application::Cat::Utils";
16 OpenSRF::Application->method_lookup( "blah" );
18 warn "Child Init Failed: " . shift() . "\n";
23 __PACKAGE__->register_method(
24 method => "biblio_record_tree_retrieve",
25 api_name => "open-ils.cat.biblio.record.tree.retrieve",
27 note => "Returns the tree associated with the nodeset of the given doc id"
30 sub biblio_record_tree_retrieve {
32 my( $self, $client, $recordid ) = @_;
34 my $name = "open-ils.storage.direct.biblio.record_entry.retrieve";
35 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
36 my $request = $session->request( $name, $recordid );
37 $request->wait_complete;
38 my $response = $request->recv();
39 warn "got response from storage in retrieve for $recordid\n";
42 throw OpenSRF::EX::ERROR ("No record in database with id $recordid");
45 if( $response->isa("OpenSRF::EX")) {
46 throw $response ($response->stringify);
49 warn "grabbing content in retrieve\n";
50 my $marcxml = $response->content;
53 throw OpenSRF::EX::ERROR
54 ("No record in database with id $recordid");
58 $session->disconnect();
61 warn "turning into nodeset\n";
62 my $nodes = OpenILS::Utils::FlatXML->new()->xml_to_nodeset( $marcxml->marc );
63 warn "turning nodeset into tree\n";
64 my $tree = $utils->nodeset2tree( $nodes->nodeset );
66 $tree->owner_doc( $marcxml->id() );
68 warn "returning tree\n";
75 __PACKAGE__->register_method(
76 method => "biblio_record_tree_commit",
77 api_name => "open-ils.cat.biblio.record.tree.commit",
78 argc => 3, #(session_id, biblio_tree )
79 note => "Walks the tree and commits any changed nodes " .
80 "adds any new nodes, and deletes any deleted nodes",
83 sub biblio_record_tree_commit {
85 my( $self, $client, $user_session, $tree ) = @_;
86 new Fieldmapper::biblio::record_node ($tree);
90 throw OpenSRF::EX::InvalidArg
91 ("Not enough args to to open-ils.cat.biblio.record.tree.commit")
92 unless ( $user_session and $client and $tree );
95 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
98 my $docid = $tree->owner_doc();
99 my $session = OpenILS::Application::AppUtils->start_db_session();
101 warn "Retrieving biblio record from storage for update\n";
103 my $req1 = $session->request('open-ils.storage',
104 "open-ils.storage.direct.biblio.record_entry.batch.retrieve", $docid );
105 if(UNIVERSAL::usa($req1,"Error")) { throw $req1 ($req1->stringify);}
106 my $biblio = $req1->content;
109 # turn the tree into a nodeset
110 my $nodeset = $utils->tree2nodeset($tree);
111 $nodeset = $utils->clean_nodeset( $nodeset );
113 if(!defined($docid)) { # be sure
114 for my $node (@$nodeset) {
115 $docid = $node->owner_doc();
116 last if defined($docid);
120 # turn the nodeset into a doc
121 my $marcxml = OpenILS::Utils::FlatXML->new()->nodeset_to_xml( $nodeset );
123 #my $biblio = Fieldmapper::biblio::record_marc->new();
124 #$biblio->id( $docid );
126 $biblio->marc( $marcxml->toString() );
128 warn "Starting db session\n";
130 my $x = _update_record_metadata( $session, { user => $user_obj, docid => $docid } );
131 OpenILS::Application::AppUtils->rollback_db_session($session) unless $x;
133 warn "Sending updated doc $docid to db\n";
134 my $req = $session->request( "open-ils.storage.direct.biblio.record_entry.update", $biblio );
137 my $status = $req->recv();
138 if( !$status || $status->isa("Error") || ! $status->content) {
139 OpenILS::Application::AppUtils->rollback_db_session($session);
140 if($status->isa("Error")) { throw $status ($status); }
141 throw OpenSRF::EX::ERROR ("Error updating biblio record");
145 # Send the doc to the wormer for wormizing
146 warn "Starting worm session\n";
151 my $wreq = $session->request( "open-ils.worm.wormize", $docid );
152 warn "Calling worm receive\n";
154 $wreq->wait_complete;
155 $wresp = $wreq->recv();
158 UNIVERSAL::can($wresp,"content") and $wresp->content ) {
166 warn "wormizing failed, rolling back\n";
167 if($wresp and $wresp->isa("Error") ) {
168 OpenILS::Application::AppUtils->rollback_db_session($session);
169 throw $wresp ($wresp->stringify);
172 OpenILS::Application::AppUtils->rollback_db_session($session);
173 throw OpenSRF::EX::ERROR ("Wormizing Failed for $docid" );
176 OpenILS::Application::AppUtils->commit_db_session( $session );
178 $nodeset = OpenILS::Utils::FlatXML->new()->xmldoc_to_nodeset($marcxml);
179 $tree = $utils->nodeset2tree($nodeset->nodeset);
180 $tree->owner_doc($docid);
182 $client->respond_complete($tree);
184 warn "Done wormizing\n";
190 __PACKAGE__->register_method(
191 method => "biblio_record_record_metadata",
192 api_name => "open-ils.cat.biblio.record.metadata.retrieve",
193 argc => 1, #(session_id, biblio_tree )
194 note => "Walks the tree and commits any changed nodes " .
195 "adds any new nodes, and deletes any deleted nodes",
198 sub biblio_record_record_metadata {
199 my( $self, $client, @ids ) = @_;
201 if(!@ids){return undef;}
203 my $session = OpenSRF::AppSession->create("open-ils.storage");
204 my $request = $session->request(
205 "open-ils.storage.direct.biblio.record_entry.batch.retrieve", @ids );
209 while( my $response = $request->recv() ) {
212 throw OpenSRF::EX::ERROR ("No Response from Storage");
214 if($response->isa("Error")) {
215 throw $response ($response->stringify);
218 my $record_entry = $response->content;
220 my $creator = $record_entry->creator;
221 my $editor = $record_entry->editor;
223 ($creator, $editor) = _get_userid_by_id($creator, $editor);
225 $record_entry->creator( $creator );
226 $record_entry->editor( $editor );
228 push @$results, $record_entry;
233 $session->disconnect();
241 sub _get_userid_by_id {
246 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
247 my $request = $session->request(
248 "open-ils.storage.direct.actor.user.batch.retrieve.atomic", @ids );
250 $request->wait_complete;
251 my $response = $request->recv();
252 if(!$request->complete) { return undef; }
254 if($response->isa("Error")){
255 throw $response ($response);
258 for my $u (@{$response->content}) {
260 push @users, $u->usrname;
264 $session->disconnect;
270 # open-ils.storage.direct.actor.user.search.usrid
272 sub _get_id_by_userid {
277 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
278 my $request = $session->request(
279 "open-ils.storage.direct.actor.user.search.usrid", @users );
281 $request->wait_complete;
282 my $response = $request->recv();
283 if(!$request->complete) {
284 throw OpenSRF::EX::ERROR ("no response from storage on user retrieve");
287 if(UNIVERSAL::isa( $response, "Error")){
288 throw $response ($response);
291 for my $u (@{$response->content}) {
297 $session->disconnect;
304 # commits metadata objects to the db
305 sub _update_record_metadata {
307 my ($session, @docs ) = @_;
309 for my $doc (@docs) {
311 my $user_obj = $doc->{user};
312 my $docid = $doc->{docid};
314 warn "Updating metata for doc $docid\n";
316 # ----------------------------------------
317 # grab the meta information and update it
318 my $user_session = OpenSRF::AppSession->create("open-ils.storage");
319 my $user_request = $user_session->request(
320 "open-ils.storage.direct.biblio.record_entry.retrieve", $docid );
321 $user_request->wait_complete;
322 my $meta = $user_request->recv();
325 throw OpenSRF::EX::ERROR ("No meta info returned for biblio $docid");
327 if($meta->isa("Error")) {
328 throw $meta ($meta->stringify);
331 $meta = $meta->content;
332 my ($id) = _get_id_by_userid($user_obj->usrid);
333 warn "got $id from _get_id_by_userid\n";
336 $user_request->finish;
337 $user_session->disconnect;
338 $user_session->kill_me;
339 # -------------------------------------
341 warn "Grabbed the record, updating and moving on\n";
343 my $request = $session->request(
344 "open-ils.storage.direct.biblio.record_entry.update", $meta );
346 my $response = $request->recv();
348 throw OpenSRF::EX::ERROR
349 ("Error commit record metadata for " . $meta->id);
352 if($response->isa("Error")){
353 throw $response ($response->stringify);
359 warn "committing metarecord update\n";
367 __PACKAGE__->register_method(
368 method => "retrieve_copies",
369 api_name => "open-ils.cat.asset.copy_tree.retrieve",
370 argc => 2, #(user_session, record_id)
372 Returns the copies for a given bib record and for the users home library
376 sub retrieve_copies {
378 my( $self, $client, $user_session, $docid, $home_ou ) = @_;
386 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
387 $home_ou = $user_obj->home_ou;
390 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
392 # ------------------------------------------------------
393 # grab the short name of the library location
394 my $request = $session->request(
395 "open-ils.storage.direct.actor.org_unit.retrieve", $home_ou );
397 my $org_unit = $request->recv();
399 throw OpenSRF::EX::ERROR
400 ("No response from storage for org unit search");
402 if($org_unit->isa("Error")) { throw $org_unit ($org_unit->stringify);}
403 my $location = $org_unit->content->shortname;
405 # ------------------------------------------------------
408 # ------------------------------------------------------
409 # grab all the volumes for the given record and location
410 my $search_hash = { record => $docid, owning_lib => $location };
414 $request = $session->request(
415 "open-ils.storage.direct.asset.call_number.search", $search_hash );
420 while( $volume = $request->recv() ) {
422 if($volume->isa("Error")) {
423 throw $volume ($volume->stringify);}
425 $volume = $volume->content;
427 warn "Grabbing copies for volume: " . $volume->id . "\n";
429 OpenILS::Application::AppUtils->simple_scalar_request( "open-ils.storage",
430 "open-ils.storage.direct.asset.copy.search.call_number", $volume->id );
432 $volume->copies($copies);
434 $client->respond( $volume );
436 #push @$results, $volume;
442 $session->disconnect();
453 __PACKAGE__->register_method(
454 method => "retrieve_copies_global",
455 api_name => "open-ils.cat.asset.copy_tree.global.retrieve",
456 argc => 2, #(user_session, record_id)
458 Returns all volumes and attached copies for a given bib record
462 sub retrieve_copies_global {
464 my( $self, $client, $user_session, $docid ) = @_;
468 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
470 # ------------------------------------------------------
471 # grab all the volumes for the given record and location
472 my $request = $session->request(
473 "open-ils.storage.direct.asset.call_number.search.record", $docid );
475 my $volumes = $request->recv();
478 if($volumes->isa("Error")) {
479 throw $volumes ($volumes->stringify);}
481 $volumes = $volumes->content;
488 for my $volume (@$volumes) {
489 $vol_hash->{$volume->id} = $volume;
492 my @ii = keys %$vol_hash;
493 warn "Searching volumes @ii\n";
495 $request = $session->request(
496 "open-ils.storage.direct.asset.copy.search.call_number", keys %$vol_hash );
498 while( my $copylist = $request->recv ) {
500 if(UNIVERSAL::isa( $copylist, "Error")) {
501 throw $copylist ($copylist->stringify);
504 warn "received copy list " . time() . "\n";
505 $copylist = $copylist->content;
508 for my $copy (@$copylist) {
509 $vol = $vol_hash->{$copy->call_number} unless $vol;
510 $vol->copies([]) unless $vol->copies();
511 push @{$vol->copies}, $copy;
513 $client->respond( $vol );
520 $session->disconnect();
530 __PACKAGE__->register_method(
531 method => "generic_edit_copies_volumes",
532 api_name => "open-ils.cat.asset.volume.batch.update",
535 __PACKAGE__->register_method(
536 method => "generic_edit_copies_volumes",
537 api_name => "open-ils.cat.asset.volume.batch.delete",
540 __PACKAGE__->register_method(
541 method => "generic_edit_copies_volumes",
542 api_name => "open-ils.cat.asset.copy.batch.update",
545 __PACKAGE__->register_method(
546 method => "generic_edit_copies_volumes",
547 api_name => "open-ils.cat.asset.copy.batch.delete",
551 sub generic_edit_copies_volumes {
553 my( $self, $client, $user_session, $items ) = @_;
555 my $method = $self->api_name;
556 warn "received api name $method\n";
557 $method =~ s/open-ils\.cat/open-ils\.storage/og;
558 warn "our method is $method\n";
564 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
566 warn "updating editor info\n";
568 for my $item (@$items) {
572 if( $method =~ /copy/ ) {
573 new Fieldmapper::asset::copy($item);
575 new Fieldmapper::asset::call_number($item);
578 $item->editor( $user_obj->id );
581 my $session = OpenILS::Application::AppUtils->start_db_session;
582 my $request = $session->request( $method, @$items );
584 my $result = $request->recv();
586 if(!$request->complete) {
587 OpenILS::Application::AppUtils->rollback_db_session($session);
588 throw OpenSRF::EX::ERROR
589 ("No response from storage on $method");
592 if(UNIVERSAL::isa($result, "Error")) {
593 OpenILS::Application::AppUtils->rollback_db_session($session);
594 throw $result ($result->stringify);
597 OpenILS::Application::AppUtils->commit_db_session($session);
599 warn "looks like we succeeded\n";
600 return $result->content;
604 __PACKAGE__->register_method(
605 method => "volume_tree_add",
606 api_name => "open-ils.cat.asset.volume.tree.batch.add",
609 sub volume_tree_add {
611 my( $self, $client, $user_session, $volumes ) = @_;
612 return undef unless $volumes;
616 warn Dumper $volumes;
619 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
621 warn "volume_tree_add creating new db session\n";
623 my $session = OpenILS::Application::AppUtils->start_db_session;
625 for my $volume (@$volumes) {
627 new Fieldmapper::asset::call_number($volume);
629 warn "Looping on volumes\n";
633 my $new_copy_list = $volume->copies;
636 warn "Searching for volume with ".$volume->owning_lib . " " .
637 $volume->label . " " . $volume->record . "\n";
639 my $cn_req = $session->request(
640 'open-ils.storage.direct.asset.call_number.search' =>
641 { owning_lib => $volume->owning_lib,
642 label => $volume->label,
643 record => $volume->record,
646 $cn_req->wait_complete;
647 my $cn = $cn_req->recv();
649 if(!$cn_req->complete) {
650 throw OpenSRF::EX::ERROR ("Error searching volumes on storage");
657 if(UNIVERSAL::isa($cn,"Error")) {
658 throw $cn ($cn->stringify);
661 $volume = $cn->content;
663 $volume->editor( $user_obj->id );
667 $volume->creator( $user_obj->id );
668 $volume->editor( $user_obj->id );
670 warn "Attempting to create a new volume:\n";
674 my $request = $session->request(
675 "open-ils.storage.direct.asset.call_number.create", $volume );
678 my $response = $request->recv();
681 if(!$request->complete) {
682 OpenILS::Application::AppUtils->rollback_db_session($session);
683 throw OpenSRF::EX::ERROR
684 ("No response from storage on call_number.create");
688 if(UNIVERSAL::isa($response, "Error")) {
689 OpenILS::Application::AppUtils->rollback_db_session($session);
690 throw $response ($response->stringify);
693 $id = $response->content;
697 OpenILS::Application::AppUtils->rollback_db_session($session);
698 throw OpenSRF::EX::ERROR (" * -> Error creating new volume");
703 warn "received new volume id: $id\n";
708 for my $copy (@{$new_copy_list}) {
710 new Fieldmapper::asset::copy($copy);
712 warn "adding a copy for volume $id\n";
714 $copy->call_number($id);
715 $copy->creator( $user_obj->id );
716 $copy->editor( $user_obj->id );
720 my $req = $session->request(
721 "open-ils.storage.direct.asset.copy.create", $copy );
722 my $resp = $req->recv();
724 if(!$resp || ! ref($resp) ) {
725 OpenILS::Application::AppUtils->rollback_db_session($session);
726 throw OpenSRF::EX::ERROR
727 ("No response from storage on call_number.create");
730 if(UNIVERSAL::isa($resp, "Error")) {
731 OpenILS::Application::AppUtils->rollback_db_session($session);
732 throw $resp ($resp->stringify);
735 my $cid = $resp->content;
738 OpenILS::Application::AppUtils->rollback_db_session($session);
739 throw OpenSRF::EX::ERROR ("Error adding copy to volume $id" );
742 warn "got new copy id $cid\n";
747 warn "completed adding copies for $id\n";
752 warn "committing volume tree add db session\n";
753 OpenILS::Application::AppUtils->commit_db_session($session);
755 return scalar(@$volumes);
761 __PACKAGE__->register_method(
762 method => "volume_tree_delete",
763 api_name => "open-ils.cat.asset.volume.tree.batch.delete",
766 sub volume_tree_delete {
769 my( $self, $client, $user_session, $volumes ) = @_;
770 return undef unless $volumes;
773 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
775 my $session = OpenILS::Application::AppUtils->start_db_session;
777 for my $volume (@$volumes) {
779 $volume->editor($user_obj->id);
781 new Fieldmapper::asset::call_number($volume);
783 for my $copy (@{$volume->copies}) {
785 new Fieldmapper::asset::copy($copy);
787 $copy->editor( $user_obj->id );
789 warn "Deleting copy " . $copy->id . " from db\n";
791 my $req = $session->request(
792 "open-ils.storage.direct.asset.copy.delete", $copy );
794 my $resp = $req->recv();
796 if( !$req->complete ) {
797 OpenILS::Application::AppUtils->rollback_db_session($session);
798 throw OpenSRF::EX::ERROR (
799 "No response from storage on copy delete");
802 if(UNIVERSAL::isa($resp, "Error")) {
803 OpenILS::Application::AppUtils->rollback_db_session($session);
804 throw $resp ($resp->stringify);
810 warn "Deleting volume " . $volume->id . " from database\n";
812 my $vol_req = $session->request(
813 "open-ils.storage.direct.asset.call_number.delete", $volume );
814 my $vol_resp = $vol_req;
816 if(!$vol_req->complete) {
817 OpenILS::Application::AppUtils->rollback_db_session($session);
818 throw OpenSRF::EX::ERROR
819 ("No response from storage on volume delete");
822 if( $vol_resp and UNIVERSAL::isa($vol_resp, "Error")) {
823 OpenILS::Application::AppUtils->rollback_db_session($session);
824 throw $vol_resp ($vol_resp->stringify);
831 warn "committing delete volume tree add db session\n";
833 OpenILS::Application::AppUtils->commit_db_session($session);
835 return scalar(@$volumes);