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_marc.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();
100 # turn the tree into a nodeset
101 my $nodeset = $utils->tree2nodeset($tree);
102 $nodeset = $utils->clean_nodeset( $nodeset );
104 if(!defined($docid)) { # be sure
105 for my $node (@$nodeset) {
106 $docid = $node->owner_doc();
107 last if defined($docid);
111 # turn the nodeset into a doc
112 my $marcxml = OpenILS::Utils::FlatXML->new()->nodeset_to_xml( $nodeset );
114 my $biblio = Fieldmapper::biblio::record_marc->new();
115 $biblio->id( $docid );
116 $biblio->marc( $marcxml->toString() );
118 warn "Starting db session\n";
119 my $session = OpenILS::Application::AppUtils->start_db_session();
121 my $x = _update_record_metadata( $session, { user => $user_obj, docid => $docid } );
122 OpenILS::Application::AppUtils->rollback_db_session($session) unless $x;
124 warn "Sending updated doc $docid to db\n";
125 my $req = $session->request( "open-ils.storage.direct.biblio.record_marc.update", $biblio );
128 my $status = $req->recv();
129 if( !$status || $status->isa("Error") || ! $status->content) {
130 OpenILS::Application::AppUtils->rollback_db_session($session);
131 if($status->isa("Error")) { throw $status ($status); }
132 throw OpenSRF::EX::ERROR ("Error updating biblio record");
136 # Send the doc to the wormer for wormizing
137 warn "Starting worm session\n";
142 my $wreq = $session->request( "open-ils.worm.wormize", $docid );
143 warn "Calling worm receive\n";
145 $wreq->wait_complete;
146 $wresp = $wreq->recv();
149 UNIVERSAL::can($wresp,"content") and $wresp->content ) {
157 warn "wormizing failed, rolling back\n";
158 if($wresp and $wresp->isa("Error") ) {
159 OpenILS::Application::AppUtils->rollback_db_session($session);
160 throw $wresp ($wresp->stringify);
163 OpenILS::Application::AppUtils->rollback_db_session($session);
164 throw OpenSRF::EX::ERROR ("Wormizing Failed for $docid" );
167 OpenILS::Application::AppUtils->commit_db_session( $session );
169 $nodeset = OpenILS::Utils::FlatXML->new()->xmldoc_to_nodeset($marcxml);
170 $tree = $utils->nodeset2tree($nodeset->nodeset);
171 $tree->owner_doc($docid);
173 $client->respond_complete($tree);
175 warn "Done wormizing\n";
181 __PACKAGE__->register_method(
182 method => "biblio_record_record_metadata",
183 api_name => "open-ils.cat.biblio.record.metadata.retrieve",
184 argc => 1, #(session_id, biblio_tree )
185 note => "Walks the tree and commits any changed nodes " .
186 "adds any new nodes, and deletes any deleted nodes",
189 sub biblio_record_record_metadata {
190 my( $self, $client, @ids ) = @_;
192 if(!@ids){return undef;}
194 my $session = OpenSRF::AppSession->create("open-ils.storage");
195 my $request = $session->request(
196 "open-ils.storage.direct.biblio.record_entry.batch.retrieve", @ids );
200 while( my $response = $request->recv() ) {
203 throw OpenSRF::EX::ERROR ("No Response from Storage");
205 if($response->isa("Error")) {
206 throw $response ($response->stringify);
209 my $record_entry = $response->content;
211 my $creator = $record_entry->creator;
212 my $editor = $record_entry->editor;
214 ($creator, $editor) = _get_userid_by_id($creator, $editor);
216 $record_entry->creator( $creator );
217 $record_entry->editor( $editor );
219 push @$results, $record_entry;
224 $session->disconnect();
232 sub _get_userid_by_id {
237 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
238 my $request = $session->request(
239 "open-ils.storage.direct.actor.user.batch.retrieve.atomic", @ids );
241 $request->wait_complete;
242 my $response = $request->recv();
243 if(!$request->complete) { return undef; }
245 if($response->isa("Error")){
246 throw $response ($response);
249 for my $u (@{$response->content}) {
251 push @users, $u->usrname;
255 $session->disconnect;
261 # open-ils.storage.direct.actor.user.search.usrid
263 sub _get_id_by_userid {
268 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
269 my $request = $session->request(
270 "open-ils.storage.direct.actor.user.search.usrid", @users );
272 $request->wait_complete;
273 my $response = $request->recv();
274 if(!$request->complete) {
275 throw OpenSRF::EX::ERROR ("no response from storage on user retrieve");
278 if(UNIVERSAL::isa( $response, "Error")){
279 throw $response ($response);
282 for my $u (@{$response->content}) {
288 $session->disconnect;
295 # commits metadata objects to the db
296 sub _update_record_metadata {
298 my ($session, @docs ) = @_;
300 for my $doc (@docs) {
302 my $user_obj = $doc->{user};
303 my $docid = $doc->{docid};
305 warn "Updating metata for doc $docid\n";
307 # ----------------------------------------
308 # grab the meta information and update it
309 my $user_session = OpenSRF::AppSession->create("open-ils.storage");
310 my $user_request = $user_session->request(
311 "open-ils.storage.direct.biblio.record_entry.retrieve", $docid );
312 $user_request->wait_complete;
313 my $meta = $user_request->recv();
316 throw OpenSRF::EX::ERROR ("No meta info returned for biblio $docid");
318 if($meta->isa("Error")) {
319 throw $meta ($meta->stringify);
322 $meta = $meta->content;
323 my ($id) = _get_id_by_userid($user_obj->usrid);
324 warn "got $id from _get_id_by_userid\n";
327 $user_request->finish;
328 $user_session->disconnect;
329 $user_session->kill_me;
330 # -------------------------------------
332 warn "Grabbed the record, updating and moving on\n";
334 my $request = $session->request(
335 "open-ils.storage.direct.biblio.record_entry.update", $meta );
337 my $response = $request->recv();
339 throw OpenSRF::EX::ERROR
340 ("Error commit record metadata for " . $meta->id);
343 if($response->isa("Error")){
344 throw $response ($response->stringify);
350 warn "committing metarecord update\n";
358 __PACKAGE__->register_method(
359 method => "retrieve_copies",
360 api_name => "open-ils.cat.asset.copy_tree.retrieve",
361 argc => 2, #(user_session, record_id)
363 Returns the copies for a given bib record and for the users home library
367 sub retrieve_copies {
369 my( $self, $client, $user_session, $docid, $home_ou ) = @_;
377 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
378 $home_ou = $user_obj->home_ou;
381 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
383 # ------------------------------------------------------
384 # grab the short name of the library location
385 my $request = $session->request(
386 "open-ils.storage.direct.actor.org_unit.retrieve", $home_ou );
388 my $org_unit = $request->recv();
390 throw OpenSRF::EX::ERROR
391 ("No response from storage for org unit search");
393 if($org_unit->isa("Error")) { throw $org_unit ($org_unit->stringify);}
394 my $location = $org_unit->content->shortname;
396 # ------------------------------------------------------
399 # ------------------------------------------------------
400 # grab all the volumes for the given record and location
401 my $search_hash = { record => $docid, owning_lib => $location };
405 $request = $session->request(
406 "open-ils.storage.direct.asset.call_number.search", $search_hash );
411 while( $volume = $request->recv() ) {
413 if($volume->isa("Error")) {
414 throw $volume ($volume->stringify);}
416 $volume = $volume->content;
418 warn "Grabbing copies for volume: " . $volume->id . "\n";
420 OpenILS::Application::AppUtils->simple_scalar_request( "open-ils.storage",
421 "open-ils.storage.direct.asset.copy.search.call_number", $volume->id );
423 $volume->copies($copies);
425 $client->respond( $volume );
427 #push @$results, $volume;
433 $session->disconnect();
444 __PACKAGE__->register_method(
445 method => "retrieve_copies_global",
446 api_name => "open-ils.cat.asset.copy_tree.global.retrieve",
447 argc => 2, #(user_session, record_id)
449 Returns all volumes and attached copies for a given bib record
453 sub retrieve_copies_global {
455 my( $self, $client, $user_session, $docid ) = @_;
459 my $session = OpenSRF::AppSession->create( "open-ils.storage" );
461 # ------------------------------------------------------
462 # grab all the volumes for the given record and location
463 my $request = $session->request(
464 "open-ils.storage.direct.asset.call_number.search.record", $docid );
466 my $volumes = $request->recv();
469 if($volumes->isa("Error")) {
470 throw $volumes ($volumes->stringify);}
472 $volumes = $volumes->content;
479 for my $volume (@$volumes) {
480 $vol_hash->{$volume->id} = $volume;
483 my @ii = keys %$vol_hash;
484 warn "Searching volumes @ii\n";
486 $request = $session->request(
487 "open-ils.storage.direct.asset.copy.search.call_number", keys %$vol_hash );
489 while( my $copylist = $request->recv ) {
491 if(UNIVERSAL::isa( $copylist, "Error")) {
492 throw $copylist ($copylist->stringify);
495 warn "received copy list " . time() . "\n";
496 $copylist = $copylist->content;
499 for my $copy (@$copylist) {
500 $vol = $vol_hash->{$copy->call_number} unless $vol;
501 $vol->copies([]) unless $vol->copies();
502 push @{$vol->copies}, $copy;
504 $client->respond( $vol );
511 $session->disconnect();
521 __PACKAGE__->register_method(
522 method => "generic_edit_copies_volumes",
523 api_name => "open-ils.cat.asset.volume.batch.update",
526 __PACKAGE__->register_method(
527 method => "generic_edit_copies_volumes",
528 api_name => "open-ils.cat.asset.volume.batch.delete",
531 __PACKAGE__->register_method(
532 method => "generic_edit_copies_volumes",
533 api_name => "open-ils.cat.asset.copy.batch.update",
536 __PACKAGE__->register_method(
537 method => "generic_edit_copies_volumes",
538 api_name => "open-ils.cat.asset.copy.batch.delete",
542 sub generic_edit_copies_volumes {
544 my( $self, $client, $user_session, $items ) = @_;
546 my $method = $self->api_name;
547 warn "received api name $method\n";
548 $method =~ s/open-ils\.cat/open-ils\.storage/og;
549 warn "our method is $method\n";
555 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
557 warn "updating editor info\n";
559 for my $item (@$items) {
563 if( $method =~ /copy/ ) {
564 new Fieldmapper::asset::copy($item);
566 new Fieldmapper::asset::call_number($item);
569 $item->editor( $user_obj->id );
572 my $session = OpenILS::Application::AppUtils->start_db_session;
573 my $request = $session->request( $method, @$items );
575 my $result = $request->recv();
577 if(!$request->complete) {
578 OpenILS::Application::AppUtils->rollback_db_session($session);
579 throw OpenSRF::EX::ERROR
580 ("No response from storage on $method");
583 if(UNIVERSAL::isa($result, "Error")) {
584 OpenILS::Application::AppUtils->rollback_db_session($session);
585 throw $result ($result->stringify);
588 OpenILS::Application::AppUtils->commit_db_session($session);
590 warn "looks like we succeeded\n";
591 return $result->content;
595 __PACKAGE__->register_method(
596 method => "volume_tree_add",
597 api_name => "open-ils.cat.asset.volume.tree.batch.add",
600 sub volume_tree_add {
602 my( $self, $client, $user_session, $volumes ) = @_;
603 return undef unless $volumes;
607 warn Dumper $volumes;
610 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
612 warn "volume_tree_add creating new db session\n";
614 my $session = OpenILS::Application::AppUtils->start_db_session;
616 for my $volume (@$volumes) {
618 new Fieldmapper::asset::call_number($volume);
620 warn "Looping on volumes\n";
624 my $new_copy_list = $volume->copies;
627 warn "Searching for volume with ".$volume->owning_lib . " " .
628 $volume->label . " " . $volume->record . "\n";
630 my $cn_req = $session->request(
631 'open-ils.storage.direct.asset.call_number.search' =>
632 { owning_lib => $volume->owning_lib,
633 label => $volume->label,
634 record => $volume->record,
637 $cn_req->wait_complete;
638 my $cn = $cn_req->recv();
640 if(!$cn_req->complete) {
641 throw OpenSRF::EX::ERROR ("Error searching volumes on storage");
648 if(UNIVERSAL::isa($cn,"Error")) {
649 throw $cn ($cn->stringify);
652 $volume = $cn->content;
654 $volume->editor( $user_obj->id );
658 $volume->creator( $user_obj->id );
659 $volume->editor( $user_obj->id );
661 warn "Attempting to create a new volume:\n";
665 my $request = $session->request(
666 "open-ils.storage.direct.asset.call_number.create", $volume );
669 my $response = $request->recv();
672 if(!$request->complete) {
673 OpenILS::Application::AppUtils->rollback_db_session($session);
674 throw OpenSRF::EX::ERROR
675 ("No response from storage on call_number.create");
679 if(UNIVERSAL::isa($response, "Error")) {
680 OpenILS::Application::AppUtils->rollback_db_session($session);
681 throw $response ($response->stringify);
684 $id = $response->content;
688 OpenILS::Application::AppUtils->rollback_db_session($session);
689 throw OpenSRF::EX::ERROR (" * -> Error creating new volume");
694 warn "received new volume id: $id\n";
699 for my $copy (@{$new_copy_list}) {
701 new Fieldmapper::asset::copy($copy);
703 warn "adding a copy for volume $id\n";
705 $copy->call_number($id);
706 $copy->creator( $user_obj->id );
707 $copy->editor( $user_obj->id );
711 my $req = $session->request(
712 "open-ils.storage.direct.asset.copy.create", $copy );
713 my $resp = $req->recv();
715 if(!$resp || ! ref($resp) ) {
716 OpenILS::Application::AppUtils->rollback_db_session($session);
717 throw OpenSRF::EX::ERROR
718 ("No response from storage on call_number.create");
721 if(UNIVERSAL::isa($resp, "Error")) {
722 OpenILS::Application::AppUtils->rollback_db_session($session);
723 throw $resp ($resp->stringify);
726 my $cid = $resp->content;
729 OpenILS::Application::AppUtils->rollback_db_session($session);
730 throw OpenSRF::EX::ERROR ("Error adding copy to volume $id" );
733 warn "got new copy id $cid\n";
738 warn "completed adding copies for $id\n";
743 warn "committing volume tree add db session\n";
744 OpenILS::Application::AppUtils->commit_db_session($session);
746 return scalar(@$volumes);
752 __PACKAGE__->register_method(
753 method => "volume_tree_delete",
754 api_name => "open-ils.cat.asset.volume.tree.batch.delete",
757 sub volume_tree_delete {
760 my( $self, $client, $user_session, $volumes ) = @_;
761 return undef unless $volumes;
764 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
766 my $session = OpenILS::Application::AppUtils->start_db_session;
768 for my $volume (@$volumes) {
770 $volume->editor($user_obj->id);
772 new Fieldmapper::asset::call_number($volume);
774 for my $copy (@{$volume->copies}) {
776 new Fieldmapper::asset::copy($copy);
778 $copy->editor( $user_obj->id );
780 warn "Deleting copy " . $copy->id . " from db\n";
782 my $req = $session->request(
783 "open-ils.storage.direct.asset.copy.delete", $copy );
785 my $resp = $req->recv();
787 if( !$req->complete ) {
788 OpenILS::Application::AppUtils->rollback_db_session($session);
789 throw OpenSRF::EX::ERROR (
790 "No response from storage on copy delete");
793 if(UNIVERSAL::isa($resp, "Error")) {
794 OpenILS::Application::AppUtils->rollback_db_session($session);
795 throw $resp ($resp->stringify);
801 warn "Deleting volume " . $volume->id . " from database\n";
803 my $vol_req = $session->request(
804 "open-ils.storage.direct.asset.call_number.delete", $volume );
805 my $vol_resp = $vol_req;
807 if(!$vol_req->complete) {
808 OpenILS::Application::AppUtils->rollback_db_session($session);
809 throw OpenSRF::EX::ERROR
810 ("No response from storage on volume delete");
813 if( $vol_resp and UNIVERSAL::isa($vol_resp, "Error")) {
814 OpenILS::Application::AppUtils->rollback_db_session($session);
815 throw $vol_resp ($vol_resp->stringify);
822 warn "committing delete volume tree add db session\n";
824 OpenILS::Application::AppUtils->commit_db_session($session);
826 return scalar(@$volumes);