]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Actor.pm
removing dups from actor search
[working/Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Actor.pm
1 package OpenILS::Application::Actor;
2 use base qw/OpenSRF::Application/;
3 use strict; use warnings;
4 use Data::Dumper;
5
6 use OpenSRF::EX qw(:try);
7 use OpenILS::EX;
8
9 use OpenILS::Application::AppUtils;
10 use OpenILS::Utils::Fieldmapper;
11 use OpenILS::Application::Search::Actor;
12
13 my $apputils = "OpenILS::Application::AppUtils";
14 sub _d { warn "Patron:\n" . Dumper(shift()); }
15 my $cache_client = OpenSRF::Utils::Cache->new("global", 0);
16
17
18 __PACKAGE__->register_method(
19         method  => "update_patron",
20         api_name        => "open-ils.actor.patron.update",
21 );
22
23
24 sub update_patron {
25         my( $self, $client, $user_session, $patron ) = @_;
26
27         my $session = $apputils->start_db_session();
28         my $err = undef;
29
30         warn $user_session . " " . $patron . "\n";
31         _d($patron);
32
33         my $user_obj = 
34                 OpenILS::Application::AppUtils->check_user_session( 
35                                 $user_session ); #throws EX on error
36
37         # XXX does this user have permission to add/create users.  Granularity?
38
39         # $new_patron is the patron in progress.  $patron is the original patron
40         # passed in with the method.  new_patron will change as the components
41         # of patron are added/updated.
42
43         my $new_patron;
44
45         #try {
46                 # create/update the patron first so we can use his id
47                 if($patron->isnew()) {
48                         $new_patron = _add_patron(
49                                         $session, _clone_patron($patron));
50                         if(UNIVERSAL::isa($new_patron, "OpenILS::EX")) {
51                                 $client->respond_complete($new_patron->ex);
52                                 return undef;
53                         }
54
55                 } else { 
56                         $new_patron = $patron; 
57                 }
58
59                 $new_patron = _add_update_addresses($session, $patron, $new_patron);
60                 $new_patron = _add_update_cards($session, $patron, $new_patron);
61
62                 if(UNIVERSAL::isa($new_patron,"OpenILS::EX")) {
63                         $client->respond_complete($new_patron->ex);
64                         return undef;
65                 }
66
67                 $new_patron = _add_survey_responses($session, $patron, $new_patron);
68                 $new_patron     = _create_stat_maps($session, $user_session, $patron, $new_patron);
69
70                 # re-update the patron if anything has happened to him during this process
71                 if($new_patron->ischanged()) {
72                         $new_patron = _update_patron($session, $new_patron);
73                 }
74                 $apputils->commit_db_session($session);
75
76 =head
77         } catch Error with { 
78                 my $e = shift;
79                 $err =  "-*- Failure adding user: $e";
80                 $apputils->rollback_db_session($session);
81                 warn $err;
82         };
83
84         if($err) { throw OpenSRF::EX::ERROR ($err); }
85 =cut
86
87         warn "Patron Update/Create complete\n";
88         return flesh_user($new_patron->id());
89 }
90
91
92 __PACKAGE__->register_method(
93         method  => "user_retrieve_fleshed_by_id",
94         api_name        => "open-ils.actor.user.fleshed.retrieve",);
95
96 sub user_retrieve_fleshed_by_id {
97         my( $self, $client, $user_session, $user_id ) = @_;
98         my $user_obj = $apputils->check_user_session( $user_session ); 
99         return flesh_user($user_id);
100 }
101
102
103 sub flesh_user {
104         my $id = shift;
105         my $session = shift;
106
107         my $kill = 0;
108
109         if(!$session) {
110                 $session = OpenSRF::AppSession->create("open-ils.storage");
111                 $kill = 1;
112         }
113
114         # grab the user with the given card
115         my $ureq = $session->request(
116                         "open-ils.storage.direct.actor.user.retrieve",
117                         $id);
118         my $user = $ureq->gather(1);
119
120         # grab the cards
121         my $cards_req = $session->request(
122                         "open-ils.storage.direct.actor.card.search.usr",
123                         $user->id() );
124         $user->cards( $cards_req->gather(1) );
125
126         my $add_req = $session->request(
127                         "open-ils.storage.direct.actor.user_address.search.usr",
128                         $user->id() );
129         $user->addresses( $add_req->gather(1) );
130
131         my $stat_req = $session->request(
132                 "open-ils.storage.direct.actor.stat_cat_entry_user_map.search.target_usr",
133                 $user->id() );
134         $user->stat_cat_entries($stat_req->gather(1));
135
136         if($kill) { $session->disconnect(); }
137         $user->clear_passwd();
138         warn Dumper $user;
139
140         return $user;
141
142 }
143
144
145 # clone and clear stuff that would break the database
146 sub _clone_patron {
147         my $patron = shift;
148
149         my $new_patron = Fieldmapper::actor::user->new();
150
151         my $fmap = $Fieldmapper::fieldmap;
152         no strict; # shallow clone, may be useful in the fieldmapper
153         for my $field 
154                 (keys %{$fmap->{"Fieldmapper::actor::user"}->{'fields'}}) {
155                         $new_patron->$field( $patron->$field() );
156         }
157         use strict;
158
159         # clear these
160         $new_patron->clear_billing_address();
161         $new_patron->clear_mailing_address();
162         $new_patron->clear_addresses();
163         $new_patron->clear_card();
164         $new_patron->clear_cards();
165         $new_patron->clear_id();
166         $new_patron->clear_isnew();
167         $new_patron->clear_changed();
168         $new_patron->clear_deleted();
169         $new_patron->clear_stat_cat_entries();
170
171         return $new_patron;
172 }
173
174
175 sub _add_patron {
176         my $session             = shift;
177         my $patron              = shift;
178
179         warn "Creating new patron\n";
180         _d($patron);
181
182         my $req = $session->request(
183                 "open-ils.storage.direct.actor.user.create",$patron);
184         my $id = $req->gather(1);
185         if(!$id) { 
186                 return OpenILS::EX->new("DUPLICATE_USER_USERNAME");
187         }
188
189         # retrieve the patron from the db to collect defaults
190         my $ureq = $session->request(
191                         "open-ils.storage.direct.actor.user.retrieve",
192                         $id);
193
194         warn "Created new patron with id $id\n";
195
196         return $ureq->gather(1);
197 }
198
199
200 sub _update_patron {
201         my( $session, $patron) = @_;
202
203         warn "updating patron " . Dumper($patron) . "\n";
204
205         my $req = $session->request(
206                 "open-ils.storage.direct.actor.user.update",$patron );
207         my $status = $req->gather(1);
208         if(!defined($status)) { 
209                 throw OpenSRF::EX::ERROR 
210                         ("Unknown error updating patron"); 
211         }
212         return $patron;
213 }
214
215
216 sub _add_update_addresses {
217         my $session = shift;
218         my $patron = shift;
219         my $new_patron = shift;
220
221         my $current_id; # id of the address before creation
222
223         for my $address (@{$patron->addresses()}) {
224
225                 $address->usr($new_patron->id());
226
227                 if(ref($address) and $address->isnew()) {
228                         warn "Adding new address at street " . $address->street1() . "\n";
229
230                         $current_id = $address->id();
231                         $address = _add_address($session,$address);
232
233                         if( $patron->billing_address() and 
234                                         $patron->billing_address() == $current_id ) {
235                                 $new_patron->billing_address($address->id());
236                                 $new_patron->ischanged(1);
237                         }
238
239                         if( $patron->mailing_address() and
240                                         $patron->mailing_address() == $current_id ) {
241                                 $new_patron->mailing_address($address->id());
242                                 $new_patron->ischanged(1);
243                         }
244
245                 } elsif( ref($address) and $address->ischanged() ) {
246                         warn "Updating address at street " . $address->street1();
247                         $address->usr($new_patron->id());
248                         _update_address($session,$address);
249
250                 } elsif( ref($address) and $address->isdeleted() ) {
251                         warn "Deleting address at street " . $address->street1();
252
253                         if( $address->id() == $new_patron->mailing_address() ) {
254                                 $new_patron->clear_mailing_address();
255                                 _update_patron($session, $new_patron);
256                         }
257
258                         if( $address->id() == $new_patron->billing_address() ) {
259                                 $new_patron->clear_billing_address();
260                                 _update_patron($session, $new_patron);
261                         }
262
263                         _delete_address($session,$address);
264                 }
265         }
266
267         return $new_patron;
268 }
269
270
271 # adds an address to the db and returns the address with new id
272 sub _add_address {
273         my($session, $address) = @_;
274         $address->clear_id();
275
276         # put the address into the database
277         my $req = $session->request(
278                 "open-ils.storage.direct.actor.user_address.create",
279                 $address );
280
281         #update the id
282         my $id = $req->gather(1);
283         if(!$id) { 
284                 throw OpenSRF::EX::ERROR 
285                         ("Unable to create new user address"); 
286         }
287
288         warn "Created address with id $id\n";
289
290         # update all the necessary id's
291         $address->id( $id );
292         return $address;
293 }
294
295
296 sub _update_address {
297         my( $session, $address ) = @_;
298         my $req = $session->request(
299                 "open-ils.storage.direct.actor.user_address.update",
300                 $address );
301         my $status = $req->gather(1);
302         if(!defined($status)) { 
303                 throw OpenSRF::EX::ERROR 
304                         ("Unknown error updating address"); 
305         }
306         return $address;
307 }
308
309
310
311 sub _add_update_cards {
312
313         my $session = shift;
314         my $patron = shift;
315         my $new_patron = shift;
316
317         my $virtual_id; #id of the card before creation
318         for my $card (@{$patron->cards()}) {
319
320                 $card->usr($new_patron->id());
321
322                 if(ref($card) and $card->isnew()) {
323
324                         $virtual_id = $card->id();
325                         $card = _add_card($session,$card);
326                         if(UNIVERSAL::isa($card,"OpenILS::EX")) {
327                                 return $card;
328                         }
329
330                         if($patron->card() == $virtual_id) {
331                                 $new_patron->card($card->id());
332                                 $new_patron->ischanged(1);
333                         }
334
335                 } elsif( ref($card) and $card->ischanged() ) {
336                         $card->usr($new_patron->id());
337                         _update_card($session, $card);
338                 }
339         }
340         return $new_patron;
341 }
342
343
344 # adds an card to the db and returns the card with new id
345 sub _add_card {
346         my( $session, $card ) = @_;
347         $card->clear_id();
348
349         warn "Adding card with barcode " . $card->barcode() . "\n";
350         my $req = $session->request(
351                 "open-ils.storage.direct.actor.card.create",
352                 $card );
353
354         my $id = $req->gather(1);
355         if(!$id) { 
356                 return OpenILS::EX->new("DUPLICATE_INVALID_USER_BARCODE");
357         }
358
359         $card->id($id);
360         warn "Created patron card with id $id\n";
361         return $card;
362 }
363
364
365 sub _update_card {
366         my( $session, $card ) = @_;
367         warn Dumper $card;
368
369         my $req = $session->request(
370                 "open-ils.storage.direct.actor.card.update",
371                 $card );
372         my $status = $req->gather(1);
373         if(!defined($status)) { 
374                 throw OpenSRF::EX::ERROR 
375                         ("Unknown error updating card"); 
376         }
377         return $card;
378 }
379
380
381
382
383 sub _delete_address {
384         my( $session, $address ) = @_;
385
386         warn "Deleting address " . $address->street1() . "\n";
387
388         my $req = $session->request(
389                 "open-ils.storage.direct.actor.user_address.delete",
390                 $address );
391         my $status = $req->gather(1);
392         if(!defined($status)) { 
393                 throw OpenSRF::EX::ERROR 
394                         ("Unknown error updating address"); 
395         }
396         warn "Delete address status is $status\n";
397 }
398
399
400
401 sub _add_survey_responses {
402         my ($session, $patron, $new_patron) = @_;
403
404         warn "updating responses for user " . $new_patron->id . "\n";
405
406         my $responses = $patron->survey_responses;
407         for my $resp( @$responses ) {
408                 $resp->usr($new_patron->id);
409         }
410
411         my $status = $apputils->simple_scalar_request(
412                 "open-ils.circ", 
413                 "open-ils.circ.survey.submit.user_id",
414                 $responses );
415
416         return $new_patron;
417 }
418
419
420 sub _create_stat_maps {
421
422         my($session, $user_session, $patron, $new_patron) = @_;
423
424         my $maps = $patron->stat_cat_entries();
425
426         for my $map (@$maps) {
427
428                 next unless($map->isnew() || $map->ischanged());
429
430                 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
431                 if($map->isnew()) {
432                         $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
433                 }
434
435                 $map->target_usr($new_patron->id);
436
437                 warn "Updating stat entry with method $method and session $user_session and map $map\n";
438
439                 my $req = $session->request($method, $map);
440                 my $status = $req->gather(1);
441
442                 warn "Updated\n";
443
444                 if(!$status) {
445                         throw OpenSRF::EX::ERROR 
446                                 ("Error updating stat map with method $method");        
447                 }
448         }
449
450         return $new_patron;
451 }
452
453
454
455 __PACKAGE__->register_method(
456         method  => "search_username",
457         api_name        => "open-ils.actor.user.search.username",
458 );
459
460 sub search_username {
461         my($self, $client, $username) = @_;
462         my $users = OpenILS::Application::AppUtils->simple_scalar_request(
463                         "open-ils.storage", 
464                         "open-ils.storage.direct.actor.user.search.usrname",
465                         $username );
466         return $users;
467 }
468
469
470
471
472 __PACKAGE__->register_method(
473         method  => "user_retrieve_by_barcode",
474         api_name        => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
475
476 sub user_retrieve_by_barcode {
477         my($self, $client, $user_session, $barcode) = @_;
478         warn "Searching for user with barcode $barcode\n";
479         my $user_obj = $apputils->check_user_session( $user_session ); 
480
481         my $session = OpenSRF::AppSession->create("open-ils.storage");
482
483         # find the card with the given barcode
484         my $creq        = $session->request(
485                         "open-ils.storage.direct.actor.card.search.barcode",
486                         $barcode );
487         my $card = $creq->gather(1);
488
489         if(!$card || !$card->[0]) {
490                 $session->disconnect();
491                 return undef;
492         }
493
494         $card = $card->[0];
495         my $user = flesh_user($card->usr(), $session);
496         $session->disconnect();
497         return $user;
498
499 }
500
501
502
503 __PACKAGE__->register_method(
504         method  => "get_user_by_id",
505         api_name        => "open-ils.actor.user.retrieve",);
506
507 sub get_user_by_id {
508         my ($self, $client, $user_session, $id) = @_;
509
510         my $user_obj = $apputils->check_user_session( $user_session ); 
511
512         return $apputils->simple_scalar_request(
513                 "open-ils.storage",
514                 "open-ils.storage.direct.actor.user.retrieve",
515                 $id );
516 }
517
518
519
520 __PACKAGE__->register_method(
521         method  => "get_org_types",
522         api_name        => "open-ils.actor.org_types.retrieve",);
523
524 my $org_types;
525 sub get_org_types {
526         my($self, $client) = @_;
527
528         return $org_types if $org_types;
529          return $org_types = 
530                  $apputils->simple_scalar_request(
531                         "open-ils.storage",
532                         "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
533 }
534
535
536
537 __PACKAGE__->register_method(
538         method  => "get_user_profiles",
539         api_name        => "open-ils.actor.user.profiles.retrieve",
540 );
541
542 my $user_profiles;
543 sub get_user_profiles {
544         return $user_profiles if $user_profiles;
545
546         return $user_profiles = 
547                 $apputils->simple_scalar_request(
548                         "open-ils.storage",
549                         "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
550 }
551
552
553
554 __PACKAGE__->register_method(
555         method  => "get_user_ident_types",
556         api_name        => "open-ils.actor.user.ident_types.retrieve",
557 );
558 my $ident_types;
559 sub get_user_ident_types {
560         return $ident_types if $ident_types;
561         return $ident_types = 
562                 $apputils->simple_scalar_request(
563                 "open-ils.storage",
564                 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
565 }
566
567
568
569
570 __PACKAGE__->register_method(
571         method  => "get_org_unit",
572         api_name        => "open-ils.actor.org_unit.retrieve",
573 );
574
575 sub get_org_unit {
576
577         my( $self, $client, $user_session ) = @_;
578
579         my $user_obj = 
580                 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
581
582         my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
583                 "open-ils.storage",
584                 "open-ils.storage.direct.actor.org_unit.retrieve", 
585                 $user_obj->home_ou );
586
587         return $home_ou;
588 }
589
590
591 # build the org tree
592
593 __PACKAGE__->register_method(
594         method  => "get_org_tree",
595         api_name        => "open-ils.actor.org_tree.retrieve",
596         argc            => 1, 
597         note            => "Returns the entire org tree structure",
598 );
599
600 sub get_org_tree {
601         my( $self, $client) = @_;
602
603         # see if it's in the cache
604         warn "Getting ORG Tree\n";
605         my $tree = $cache_client->get_cache('orgtree');
606         if($tree) { 
607                 warn "Found orgtree in cache. returning...\n";
608                 return $tree; 
609         }
610
611         my $orglist = $apputils->simple_scalar_request( 
612                 "open-ils.storage", 
613                 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
614
615         $tree = $self->build_org_tree($orglist);
616         $cache_client->put_cache('orgtree', $tree);
617
618         return $tree;
619
620 }
621
622 # turns an org list into an org tree
623 sub build_org_tree {
624
625         my( $self, $orglist) = @_;
626
627         return $orglist unless ( 
628                         ref($orglist) and @$orglist > 1 );
629
630         my @list = sort { 
631                 $a->ou_type <=> $b->ou_type ||
632                 $a->name cmp $b->name } @$orglist;
633
634         for my $org (@list) {
635
636                 next unless ($org and defined($org->parent_ou));
637                 my ($parent) = grep { $_->id == $org->parent_ou } @list;
638                 next unless $parent;
639
640                 $parent->children([]) unless defined($parent->children); 
641                 push( @{$parent->children}, $org );
642         }
643
644         return $list[0];
645
646 }
647
648
649 __PACKAGE__->register_method(
650         method  => "get_org_descendants",
651         api_name        => "open-ils.actor.org_tree.descendants.retrieve"
652 );
653
654 # depth is optional.  org_unit is the id
655 sub get_org_descendants {
656         my( $self, $client, $org_unit, $depth ) = @_;
657         my $orglist = $apputils->simple_scalar_request(
658                         "open-ils.storage", 
659                         "open-ils.storage.actor.org_unit.descendants.atomic",
660                         $org_unit, $depth );
661         return $self->build_org_tree($orglist);
662 }
663
664
665 __PACKAGE__->register_method(
666         method  => "get_org_ancestors",
667         api_name        => "open-ils.actor.org_tree.ancestors.retrieve"
668 );
669
670 # depth is optional.  org_unit is the id
671 sub get_org_ancestors {
672         my( $self, $client, $org_unit, $depth ) = @_;
673         my $orglist = $apputils->simple_scalar_request(
674                         "open-ils.storage", 
675                         "open-ils.storage.actor.org_unit.ancestors.atomic",
676                         $org_unit, $depth );
677         return $self->build_org_tree($orglist);
678 }
679
680
681 __PACKAGE__->register_method(
682         method  => "get_standings",
683         api_name        => "open-ils.actor.standings.retrieve"
684 );
685
686 my $user_standings;
687 sub get_standings {
688         return $user_standings if $user_standings;
689         return $user_standings = 
690                 $apputils->simple_scalar_request(
691                         "open-ils.storage",
692                         "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
693 }
694
695
696
697 __PACKAGE__->register_method(
698         method  => "get_my_org_path",
699         api_name        => "open-ils.actor.org_unit.full_path.retrieve"
700 );
701
702 sub get_my_org_path {
703         my( $self, $client, $user_session, $org_id ) = @_;
704         my $user_obj = $apputils->check_user_session($user_session); 
705         if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
706
707         return $apputils->simple_scalar_request(
708                 "open-ils.storage",
709                 "open-ils.storage.actor.org_unit.full_path.atomic",
710                 $org_id );
711 }
712
713
714 __PACKAGE__->register_method(
715         method  => "patron_adv_search",
716         api_name        => "open-ils.actor.patron.search.advanced" );
717
718 sub patron_adv_search {
719         my( $self, $client, $staff_login, $search_hash ) = @_;
720
721         use Data::Dumper;
722         warn "patron adv with $staff_login and search " . 
723                 Dumper($search_hash) . "\n";
724
725         my $session = OpenSRF::AppSession->create("open-ils.storage");
726         my $req = $session->request(
727                 "open-ils.storage.actor.user.crazy_search", $search_hash);
728
729         my $ans = $req->gather(1);
730
731         my %hash = map { ($_ =>1) } @$ans;
732         $ans = [ keys %hash ];
733
734         warn "Returning @$ans\n";
735
736         $session->disconnect();
737         return $ans;
738
739 }
740
741
742
743
744
745
746
747
748 1;
749
750
751
752
753 __END__
754
755
756 some old methods that may be good to keep around for now
757
758 sub _delete_card {
759         my( $session, $card ) = @_;
760
761         warn "Deleting card with barcode " . $card->barcode() . "\n";
762         my $req = $session->request(
763                 "open-ils.storage.direct.actor.card.delete",
764                 $card );
765         my $status = $req->gather(1);
766         if(!defined($status)) { 
767                 throw OpenSRF::EX::ERROR 
768                         ("Unknown error updating card"); 
769         }
770 }
771
772
773
774 # deletes the patron and any attached addresses and cards
775 __PACKAGE__->register_method(
776         method  => "delete_patron",
777         api_name        => "open-ils.actor.patron.delete",
778 );
779
780 sub delete_patron {
781
782         my( $self, $client, $patron ) = @_;
783         my $session = $apputils->start_db_session();
784         my $err = undef;
785
786         try {
787
788                 $patron->clear_mailing_address();
789                 $patron->clear_billing_address();
790                 $patron->ischanged(1);
791
792                 _update_patron($session, $patron);
793                 _delete_address($session,$_) for (@{$patron->addresses()});
794                 _delete_card($session,$_) for (@{$patron->cards()});
795                 _delete_patron($session,$patron);
796                 $apputils->commit_db_session($session);
797
798         } catch Error with {
799                 my $e = shift;
800                 $err =  "-*- Failure deleting user: $e";
801                 $apputils->rollback_db_session($session);
802                 warn $err;
803         };
804
805         if($err) { throw OpenSRF::EX::ERROR ($err); }
806         warn "Patron Delete complete\n";
807         return 1;
808 }
809
810 sub _delete_patron {
811         my( $session, $patron ) = @_;
812
813         warn "Deleting patron " . $patron->usrname() . "\n";
814
815         my $req = $session->request(
816                 "open-ils.storage.direct.actor.user.delete",
817                 $patron );
818         my $status = $req->gather(1);
819         if(!defined($status)) { 
820                 throw OpenSRF::EX::ERROR 
821                         ("Unknown error updating patron"); 
822         }
823 }
824