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