]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Cat.pm
added org_type to the org tree
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Cat.pm
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);
9 use JSON;
10 use OpenILS::Utils::Fieldmapper;
11
12 my $utils = "OpenILS::Application::Cat::Utils";
13
14 sub _child_init {
15         try {
16                 OpenSRF::Application->method_lookup( "blah" );
17         } catch Error with { 
18                 warn "Child Init Failed: " . shift() . "\n";
19         };
20 }
21
22
23 __PACKAGE__->register_method(
24         method  => "biblio_record_tree_retrieve",
25         api_name        => "open-ils.cat.biblio.record.tree.retrieve",
26         argc            => 1, 
27         note            => "Returns the tree associated with the nodeset of the given doc id"
28 );
29
30 sub biblio_record_tree_retrieve {
31
32         my( $self, $client, $recordid ) = @_;
33
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";
40
41         if(!$response) { 
42                 throw OpenSRF::EX::ERROR ("No record in database with id $recordid");
43         }
44
45         if( $response->isa("OpenSRF::EX")) {
46                 throw $response ($response->stringify);
47         }
48
49         warn "grabbing content in retrieve\n";
50         my $marcxml = $response->content;
51
52         if(!$marcxml) {
53                 throw OpenSRF::EX::ERROR 
54                         ("No record in database with id $recordid");
55         }
56
57         $request->finish();
58         $session->disconnect();
59         $session->kill_me();
60
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 );
65
66         $tree->owner_doc( $marcxml->id() );
67
68         warn "returning tree\n";
69
70         return $tree;
71 }
72
73 __PACKAGE__->register_method(
74         method  => "biblio_record_tree_commit",
75         api_name        => "open-ils.cat.biblio.record.tree.commit",
76         argc            => 3, #(session_id, biblio_tree ) 
77         note            => "Walks the tree and commits any changed nodes " .
78                                         "adds any new nodes, and deletes any deleted nodes",
79 );
80
81 sub biblio_record_tree_commit {
82
83         my( $self, $client, $user_session,  $tree ) = @_;
84         new Fieldmapper::biblio::record_node ($tree);
85
86         use Data::Dumper;
87
88         throw OpenSRF::EX::InvalidArg 
89                 ("Not enough args to to open-ils.cat.biblio.record.tree.commit")
90                 unless ( $user_session and $client and $tree );
91
92         my $user_obj = 
93                 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
94
95         # capture the doc id
96         my $docid = $tree->owner_doc();
97
98         # turn the tree into a nodeset
99         my $nodeset = $utils->tree2nodeset($tree);
100         $nodeset = $utils->clean_nodeset( $nodeset );
101
102         if(!defined($docid)) { # be sure
103                 for my $node (@$nodeset) {
104                         $docid = $node->owner_doc();
105                         last if defined($docid);
106                 }
107         }
108
109         # turn the nodeset into a doc
110         my $marcxml = OpenILS::Utils::FlatXML->new()->nodeset_to_xml( $nodeset );
111
112         my $biblio =  Fieldmapper::biblio::record_marc->new();
113         $biblio->id( $docid );
114         $biblio->marc( $marcxml->toString() );
115
116         warn "Starting db session\n";
117         my $session = OpenILS::Application::AppUtils->start_db_session();
118
119         my $x = _update_record_metadata( $session, { user => $user_obj, docid => $docid } );
120         OpenILS::Application::AppUtils->rollback_db_session($session) unless $x;
121
122         warn "Sending updated doc $docid to db\n";
123         my $req = $session->request( "open-ils.storage.direct.biblio.record_marc.update", $biblio );
124
125         $req->wait_complete;
126         my $status = $req->recv();
127         if( !$status || $status->isa("Error") || ! $status->content) {
128                 OpenILS::Application::AppUtils->rollback_db_session($session);
129                 if($status->isa("Error")) { throw $status ($status); }
130                 throw OpenSRF::EX::ERROR ("Error updating biblio record");
131         }
132         $req->finish();
133
134         # Send the doc to the wormer for wormizing
135         warn "Starting worm session\n";
136
137         my $success = 0;
138         my $wresp;
139
140         my $wreq = $session->request( "open-ils.worm.wormize", $docid );
141         warn "Calling worm receive\n";
142
143         $wreq->wait_complete;
144         $wresp = $wreq->recv();
145
146         if( ref($wresp) && 
147                         UNIVERSAL::can($wresp,"content") and $wresp->content ) {
148                 $success = 1;
149         }
150
151         $wreq->finish();
152
153         if( !$success ) {
154
155                 warn "wormizing failed, rolling back\n";
156                 if($wresp and $wresp->isa("Error") ) {
157                         OpenILS::Application::AppUtils->rollback_db_session($session);
158                         throw $wresp ($wresp->stringify);
159                 }
160
161                 OpenILS::Application::AppUtils->rollback_db_session($session);
162                 throw OpenSRF::EX::ERROR ("Wormizing Failed for $docid" );
163         }
164
165         OpenILS::Application::AppUtils->commit_db_session( $session );
166
167         $nodeset = OpenILS::Utils::FlatXML->new()->xmldoc_to_nodeset($marcxml);
168         $tree = $utils->nodeset2tree($nodeset->nodeset);
169         $tree->owner_doc($docid);
170
171         $client->respond_complete($tree);
172
173         warn "Done wormizing\n";
174
175 }
176
177
178
179 __PACKAGE__->register_method(
180         method  => "biblio_record_record_metadata",
181         api_name        => "open-ils.cat.biblio.record.metadata.retrieve",
182         argc            => 1, #(session_id, biblio_tree ) 
183         note            => "Walks the tree and commits any changed nodes " .
184                                         "adds any new nodes, and deletes any deleted nodes",
185 );
186
187 sub biblio_record_record_metadata {
188         my( $self, $client, @ids ) = @_;
189
190         if(!@ids){return undef;}
191
192         my $session = OpenSRF::AppSession->create("open-ils.storage");
193         my $request = $session->request( 
194                         "open-ils.storage.direct.biblio.record_entry.batch.retrieve", @ids );
195
196         my $results = [];
197
198         while( my $response = $request->recv() ) {
199
200                 if(!$response) {
201                         throw OpenSRF::EX::ERROR ("No Response from Storage");
202                 }
203                 if($response->isa("Error")) {
204                         throw $response ($response->stringify);
205                 }
206
207                 my $record_entry = $response->content;
208
209                 my $creator = $record_entry->creator;
210                 my $editor      = $record_entry->editor;
211
212                 ($creator, $editor) = _get_userid_by_id($creator, $editor);
213
214                 $record_entry->creator( $creator );
215                 $record_entry->editor( $editor );
216
217                 push @$results, $record_entry;
218
219         }
220
221         $request->finish;
222         $session->disconnect();
223         $session->finish();
224
225         return $results;
226
227 }
228
229 # gets the username
230 sub _get_userid_by_id {
231
232         my @ids = @_;
233         my @users;
234
235         my $session = OpenSRF::AppSession->create( "open-ils.storage" );
236         my $request = $session->request( 
237                 "open-ils.storage.direct.actor.user.batch.retrieve.atomic", @ids );
238
239         $request->wait_complete;
240         my $response = $request->recv();
241         if(!$request->complete) { return undef; }
242
243         if($response->isa("Error")){
244                 throw $response ($response);
245         }
246
247         for my $u (@{$response->content}) {
248                 next unless ref($u);
249                 push @users, $u->usrname;
250         }
251
252         $request->finish;
253         $session->disconnect;
254         $session->kill_me();
255
256         return @users;
257 }
258
259 # open-ils.storage.direct.actor.user.search.usrid
260
261 sub _get_id_by_userid {
262
263         my @users = @_;
264         my @ids;
265
266         my $session = OpenSRF::AppSession->create( "open-ils.storage" );
267         my $request = $session->request( 
268                 "open-ils.storage.direct.actor.user.search.usrid", @users );
269
270         $request->wait_complete;
271         my $response = $request->recv();
272         if(!$request->complete) { 
273                 throw OpenSRF::EX::ERROR ("no response from storage on user retrieve");
274         }
275
276         if(UNIVERSAL::isa( $response, "Error")){
277                 throw $response ($response);
278         }
279
280         for my $u (@{$response->content}) {
281                 next unless ref($u);
282                 push @ids, $u->id();
283         }
284
285         $request->finish;
286         $session->disconnect;
287         $session->kill_me();
288
289         return @ids;
290 }
291
292
293 # commits metadata objects to the db
294 sub _update_record_metadata {
295
296         my ($session, @docs ) = @_;
297
298         for my $doc (@docs) {
299
300                 my $user_obj = $doc->{user};
301                 my $docid = $doc->{docid};
302
303                 warn "Updating metata for doc $docid\n";
304
305                 # ----------------------------------------
306                 # grab the meta information  and update it
307                 my $user_session = OpenSRF::AppSession->create("open-ils.storage");
308                 my $user_request = $user_session->request( 
309                         "open-ils.storage.direct.biblio.record_entry.retrieve", $docid );
310                 $user_request->wait_complete;
311                 my $meta = $user_request->recv();
312
313                 if(!$meta) {
314                         throw OpenSRF::EX::ERROR ("No meta info returned for biblio $docid");
315                 }
316                 if($meta->isa("Error")) {
317                         throw $meta ($meta->stringify);
318                 }
319
320                 $meta = $meta->content;
321                 my ($id) = _get_id_by_userid($user_obj->usrid);
322                 warn "got $id from _get_id_by_userid\n";
323                 $meta->editor($id);
324
325                 $user_request->finish;
326                 $user_session->disconnect;
327                 $user_session->kill_me;
328                 # -------------------------------------
329                 
330                 warn "Grabbed the record, updating and moving on\n";
331
332                 my $request = $session->request( 
333                         "open-ils.storage.direct.biblio.record_entry.update", $meta );
334
335                 my $response = $request->recv();
336                 if(!$response) { 
337                         throw OpenSRF::EX::ERROR 
338                                 ("Error commit record metadata for " . $meta->id);
339                 }
340
341                 if($response->isa("Error")){ 
342                         throw $response ($response->stringify); 
343                 }
344
345                 $request->finish;
346         }
347
348         warn "committing metarecord update\n";
349
350         return 1;
351 }
352
353
354
355
356 __PACKAGE__->register_method(
357         method  => "retrieve_copies",
358         api_name        => "open-ils.cat.asset.copy_tree.retrieve",
359         argc            => 2,  #(user_session, record_id)
360         note            => <<TEXT
361         Returns the copies for a given bib record and for the users home library
362 TEXT
363 );
364
365 sub retrieve_copies {
366
367         my( $self, $client, $user_session, $docid, $home_ou ) = @_;
368
369         $docid = "$docid";
370
371         #my $results = [];
372
373         if(!$home_ou) {
374                 my $user_obj = 
375                         OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
376                         $home_ou = $user_obj->home_ou;
377         }
378
379         my $session = OpenSRF::AppSession->create( "open-ils.storage" );
380         
381         # ------------------------------------------------------
382         # grab the short name of the library location
383         my $request = $session->request( 
384                         "open-ils.storage.direct.actor.org_unit.retrieve", $home_ou );
385
386         my $org_unit = $request->recv();
387         if(!$org_unit) {
388                 throw OpenSRF::EX::ERROR 
389                         ("No response from storage for org unit search");
390         }
391         if($org_unit->isa("Error")) { throw $org_unit ($org_unit->stringify);}
392         my $location = $org_unit->content->shortname;
393         $request->finish();
394         # ------------------------------------------------------
395
396
397         # ------------------------------------------------------
398         # grab all the volumes for the given record and location
399         my $search_hash = { record => $docid, owning_lib => $location };
400
401
402
403         $request = $session->request( 
404                         "open-ils.storage.direct.asset.call_number.search", $search_hash );
405
406         my $volume;
407         my @volume_ids;
408
409         while( $volume = $request->recv() ) {
410
411                 if($volume->isa("Error")) { 
412                         throw $volume ($volume->stringify);}
413
414                 $volume = $volume->content;
415                 
416                 warn "Grabbing copies for volume: " . $volume->id . "\n";
417                 my $copies = 
418                         OpenILS::Application::AppUtils->simple_scalar_request( "open-ils.storage", 
419                                 "open-ils.storage.direct.asset.copy.search.call_number", $volume->id );
420
421                 $volume->copies($copies);
422
423                 $client->respond( $volume );
424
425                 #push @$results, $volume;
426
427         }
428
429         $request->finish();
430         $session->finish();
431         $session->disconnect();
432         $session->kill_me();
433
434         return undef;
435         #return $results;
436         
437 }
438
439
440
441
442 __PACKAGE__->register_method(
443         method  => "retrieve_copies_global",
444         api_name        => "open-ils.cat.asset.copy_tree.global.retrieve",
445         argc            => 2,  #(user_session, record_id)
446         note            => <<TEXT
447         Returns all volumes and attached copies for a given bib record
448 TEXT
449 );
450
451 sub retrieve_copies_global {
452
453         my( $self, $client, $user_session, $docid ) = @_;
454
455         $docid = "$docid";
456
457         my $session = OpenSRF::AppSession->create( "open-ils.storage" );
458
459         # ------------------------------------------------------
460         # grab all the volumes for the given record and location
461         my $request = $session->request( 
462                         "open-ils.storage.direct.asset.call_number.search.record", $docid );
463
464         my $volumes = $request->recv();
465
466                 
467         if($volumes->isa("Error")) { 
468                 throw $volumes ($volumes->stringify);}
469
470         $volumes = $volumes->content;
471
472         $request->finish();
473
474         my $vol_hash = {};
475
476         my @volume_ids;
477         for my $volume (@$volumes) {
478                 $vol_hash->{$volume->id} = $volume;
479         }
480
481         my @ii = keys %$vol_hash;
482         warn "Searching volumes @ii\n";
483                 
484         $request = $session->request( 
485                         "open-ils.storage.direct.asset.copy.search.call_number", keys %$vol_hash );
486         
487         while( my $copylist = $request->recv ) {
488                 
489                 if(UNIVERSAL::isa( $copylist, "Error")) {
490                         throw $copylist ($copylist->stringify);
491                 }
492
493                 warn "received copy list " . time() . "\n";
494                 $copylist = $copylist->content;
495
496                 my $vol;
497                 for my $copy (@$copylist) {
498                         $vol = $vol_hash->{$copy->call_number} unless $vol;
499                         $vol->copies([]) unless $vol->copies();
500                         push @{$vol->copies}, $copy;
501                 }
502                 $client->respond( $vol );
503         }
504
505
506
507         $request->finish();
508         $session->finish();
509         $session->disconnect();
510         $session->kill_me();
511
512         return undef;
513         
514 }
515
516
517
518
519 __PACKAGE__->register_method(
520         method  => "generic_edit_copies_volumes",
521         api_name        => "open-ils.cat.asset.volume.batch.update",
522 );
523
524 __PACKAGE__->register_method(
525         method  => "generic_edit_copies_volumes",
526         api_name        => "open-ils.cat.asset.volume.batch.delete",
527 );
528
529 __PACKAGE__->register_method(
530         method  => "generic_edit_copies_volumes",
531         api_name        => "open-ils.cat.asset.copy.batch.update",
532 );
533
534 __PACKAGE__->register_method(
535         method  => "generic_edit_copies_volumes",
536         api_name        => "open-ils.cat.asset.copy.batch.delete",
537 );
538
539
540 sub generic_edit_copies_volumes {
541
542         my( $self, $client, $user_session, $items ) = @_;
543
544         my $method = $self->api_name;
545         warn "received api name $method\n";
546         $method =~ s/open-ils\.cat/open-ils\.storage/og;
547         warn "our method is $method\n";
548
549         use Data::Dumper;
550         warn Dumper $items;
551
552         my $user_obj = 
553                 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
554         
555         warn "updating editor info\n";
556
557         for my $item (@$items) {
558
559                 next unless $item;
560
561                 if( $method =~ /copy/ ) {
562                         new Fieldmapper::asset::copy($item);
563                 } else {
564                         new Fieldmapper::asset::call_number($item);
565                 }
566
567                 $item->editor( $user_obj->id );
568         }
569
570         my $session = OpenILS::Application::AppUtils->start_db_session;
571         my $request = $session->request( $method, @$items );
572
573         my $result = $request->recv();
574
575         if(!$request->complete) {
576                 OpenILS::Application::AppUtils->rollback_db_session($session);
577                 throw OpenSRF::EX::ERROR 
578                         ("No response from storage on $method");
579         }
580
581         if(UNIVERSAL::isa($result, "Error")) {
582                 OpenILS::Application::AppUtils->rollback_db_session($session);
583                 throw $result ($result->stringify);
584         }
585
586         OpenILS::Application::AppUtils->commit_db_session($session);
587
588         warn "looks like we succeeded\n";
589         return $result->content;
590 }
591
592
593 __PACKAGE__->register_method(
594         method  => "volume_tree_add",
595         api_name        => "open-ils.cat.asset.volume.tree.batch.add",
596 );
597
598 sub volume_tree_add {
599
600         my( $self, $client, $user_session, $volumes ) = @_;
601         return undef unless $volumes;
602
603         use Data::Dumper;
604         warn "Volumes:\n";
605         warn Dumper $volumes;
606
607         my $user_obj = 
608                 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
609
610         warn "volume_tree_add creating new db session\n";
611
612         my $session = OpenILS::Application::AppUtils->start_db_session;
613
614         for my $volume (@$volumes) {
615
616                 new Fieldmapper::asset::call_number($volume);
617
618                 warn "Looping on volumes\n";
619
620
621
622                 my $new_copy_list = $volume->copies;
623                 my $id;
624
625                 warn "Searching for volume with ".$volume->owning_lib . " " .
626                         $volume->label . " " . $volume->record . "\n";
627
628                 my $cn_req = $session->request( 
629                                 'open-ils.storage.direct.asset.call_number.search' =>
630                       {       owning_lib      => $volume->owning_lib,
631                               label           => $volume->label,
632                               record          => $volume->record,
633                                 }); 
634
635                 $cn_req->wait_complete;
636                 my $cn = $cn_req->recv();
637                 
638                 if(!$cn_req->complete) {
639                         throw OpenSRF::EX::ERROR ("Error searching volumes on storage");
640                 }
641
642                 $cn_req->finish();
643
644                 if($cn) {
645
646                         if(UNIVERSAL::isa($cn,"Error")) {
647                                 throw $cn ($cn->stringify);
648                         }
649
650                         $volume = $cn->content;
651                         $id = $volume->id;
652                         $volume->editor( $user_obj->id );
653
654                 } else {
655
656                         $volume->creator( $user_obj->id );
657                         $volume->editor( $user_obj->id );
658
659                         warn "Attempting to create a new volume:\n";
660
661                         warn Dumper $volume;
662
663                         my $request = $session->request( 
664                                 "open-ils.storage.direct.asset.call_number.create", $volume );
665
666                         warn "0\n";
667                         my $response = $request->recv();
668
669                         warn "1\n";
670                         if(!$request->complete) { 
671                                 OpenILS::Application::AppUtils->rollback_db_session($session);
672                                 throw OpenSRF::EX::ERROR 
673                                         ("No response from storage on call_number.create");
674                         }
675                 
676                         warn "2\n";
677                         if(UNIVERSAL::isa($response, "Error")) {
678                                 OpenILS::Application::AppUtils->rollback_db_session($session);
679                                 throw $response ($response->stringify);
680                         }
681
682                         $id = $response->content;
683
684                         warn "3\n";
685                         if( $id == 0 ) {
686                                 OpenILS::Application::AppUtils->rollback_db_session($session);
687                                 throw OpenSRF::EX::ERROR (" * -> Error creating new volume");
688                         }
689
690                         $request->finish();
691         
692                         warn "received new volume id: $id\n";
693
694                 }
695
696
697                 for my $copy (@{$new_copy_list}) {
698
699                         new Fieldmapper::asset::copy($copy);
700
701                         warn "adding a copy for volume $id\n";
702
703                         $copy->call_number($id);
704                         $copy->creator( $user_obj->id );
705                         $copy->editor( $user_obj->id );
706
707                         warn Dumper $copy;
708
709                         my $req = $session->request(
710                                         "open-ils.storage.direct.asset.copy.create", $copy );
711                         my $resp = $req->recv();
712
713                         if(!$resp || ! ref($resp) ) { 
714                                 OpenILS::Application::AppUtils->rollback_db_session($session);
715                                 throw OpenSRF::EX::ERROR 
716                                         ("No response from storage on call_number.create");
717                         }
718         
719                         if(UNIVERSAL::isa($resp, "Error")) {
720                                 OpenILS::Application::AppUtils->rollback_db_session($session);
721                                 throw $resp ($resp->stringify);
722                         }
723                         
724                         my $cid = $resp->content;
725
726                         if(!$cid) {
727                                 OpenILS::Application::AppUtils->rollback_db_session($session);
728                                 throw OpenSRF::EX::ERROR ("Error adding copy to volume $id" );
729                         }
730
731                         warn "got new copy id $cid\n";
732
733                         $req->finish();
734                 }
735
736                 warn "completed adding copies for $id\n";
737
738
739         }
740
741         warn "committing volume tree add db session\n";
742         OpenILS::Application::AppUtils->commit_db_session($session);
743
744         return scalar(@$volumes);
745
746 }
747
748
749
750 __PACKAGE__->register_method(
751         method  => "volume_tree_delete",
752         api_name        => "open-ils.cat.asset.volume.tree.batch.delete",
753 );
754
755 sub volume_tree_delete {
756
757
758         my( $self, $client, $user_session, $volumes ) = @_;
759         return undef unless $volumes;
760
761         my $user_obj = 
762                 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
763
764         my $session = OpenILS::Application::AppUtils->start_db_session;
765
766         for my $volume (@$volumes) {
767
768                 $volume->editor($user_obj->id);
769
770                 new Fieldmapper::asset::call_number($volume);
771
772                 for my $copy (@{$volume->copies}) {
773
774                         new Fieldmapper::asset::copy($copy);
775
776                         $copy->editor( $user_obj->id );
777
778                         warn "Deleting copy " . $copy->id . " from db\n";
779
780                         my $req = $session->request(
781                                         "open-ils.storage.direct.asset.copy.delete", $copy );
782
783                         my $resp = $req->recv();
784
785                         if( !$req->complete ) {
786                                 OpenILS::Application::AppUtils->rollback_db_session($session);
787                                 throw OpenSRF::EX::ERROR (
788                                                 "No response from storage on copy delete");
789                         }
790         
791                         if(UNIVERSAL::isa($resp, "Error")) {
792                                 OpenILS::Application::AppUtils->rollback_db_session($session);
793                                 throw $resp ($resp->stringify);
794                         }
795                         
796                         $req->finish();
797                 }
798
799                 warn "Deleting volume " . $volume->id . " from database\n";
800
801                 my $vol_req = $session->request(
802                                 "open-ils.storage.direct.asset.call_number.delete", $volume );
803                 my $vol_resp = $vol_req;
804
805                 if(!$vol_req->complete) {
806                         OpenILS::Application::AppUtils->rollback_db_session($session);
807                                 throw OpenSRF::EX::ERROR 
808                                         ("No response from storage on volume delete");
809                 }
810
811                 if( $vol_resp and UNIVERSAL::isa($vol_resp, "Error")) {
812                         OpenILS::Application::AppUtils->rollback_db_session($session);
813                         throw $vol_resp ($vol_resp->stringify);
814                 }
815
816                 $vol_req->finish();
817
818         }
819
820         warn "committing delete volume tree add db session\n";
821
822         OpenILS::Application::AppUtils->commit_db_session($session);
823
824         return scalar(@$volumes);
825
826 }
827
828
829
830
831
832 1;