]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Actor.pm
some small changes
[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 Digest::MD5 qw(md5_hex);
7
8 use OpenSRF::EX qw(:try);
9 use OpenILS::EX;
10 use OpenILS::Perm;
11
12 use OpenILS::Application::AppUtils;
13 use OpenILS::Utils::Fieldmapper;
14 use OpenILS::Application::Search::Actor;
15 use OpenILS::Utils::ModsParser;
16
17 use OpenSRF::Utils::Cache;
18
19 my $apputils = "OpenILS::Application::AppUtils";
20
21 sub _d { warn "Patron:\n" . Dumper(shift()); }
22
23 my $cache_client;
24
25
26 __PACKAGE__->register_method(
27         method  => "update_patron",
28         api_name        => "open-ils.actor.patron.update",);
29
30 sub update_patron {
31         my( $self, $client, $user_session, $patron ) = @_;
32
33         my $session = $apputils->start_db_session();
34         my $err = undef;
35
36         warn $user_session . " " . $patron . "\n";
37         _d($patron);
38
39         my $user_obj = 
40                 OpenILS::Application::AppUtils->check_user_session( 
41                                 $user_session ); #throws EX on error
42
43         # XXX does this user have permission to add/create users.  Granularity?
44         # $new_patron is the patron in progress.  $patron is the original patron
45         # passed in with the method.  new_patron will change as the components
46         # of patron are added/updated.
47
48         my $new_patron;
49
50         if(ref($patron->card)) { $patron->card( $patron->card->id ); }
51         if(ref($patron->billing_address)) { $patron->billing_address( $patron->billing_address->id ); }
52         if(ref($patron->mailing_address)) { $patron->mailing_address( $patron->mailing_address->id ); }
53
54         # create/update the patron first so we can use his id
55         if($patron->isnew()) {
56
57                 $new_patron = _add_patron($session, _clone_patron($patron), $user_obj);
58
59                 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") || 
60                         UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
61                         $client->respond_complete($new_patron->ex);
62                         return undef;
63                 }
64
65         } else { $new_patron = $patron; }
66
67         $new_patron = _add_update_addresses($session, $patron, $new_patron, $user_obj);
68
69         if(UNIVERSAL::isa($new_patron, "OpenILS::EX") || 
70                 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
71                 $client->respond_complete($new_patron->ex);
72                 return undef;
73         }
74
75         $new_patron = _add_update_cards($session, $patron, $new_patron, $user_obj);
76
77         if(UNIVERSAL::isa($new_patron, "OpenILS::EX") || 
78                 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
79                 $client->respond_complete($new_patron->ex);
80                 return undef;
81         }
82
83         $new_patron = _add_survey_responses($session, $patron, $new_patron, $user_obj);
84         if(UNIVERSAL::isa($new_patron, "OpenILS::EX") || 
85                 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
86                 $client->respond_complete($new_patron->ex);
87                 return undef;
88         }
89
90
91         # re-update the patron if anything has happened to him during this process
92         if($new_patron->ischanged()) {
93                 $new_patron = _update_patron($session, $new_patron, $user_obj);
94
95                 if(UNIVERSAL::isa($new_patron, "OpenILS::EX") || 
96                         UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
97                         $client->respond_complete($new_patron->ex);
98                         return undef;
99                 }
100         }
101
102         $apputils->commit_db_session($session);
103
104         $session = OpenSRF::AppSession->create("open-ils.storage");
105         $new_patron     = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
106         if(UNIVERSAL::isa($new_patron, "OpenILS::EX") || 
107                 UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
108                 $client->respond_complete($new_patron->ex);
109                 return undef;
110         }
111
112
113         warn "Patron Update/Create complete\n";
114         return flesh_user($new_patron->id());
115 }
116
117
118
119
120 __PACKAGE__->register_method(
121         method  => "user_retrieve_fleshed_by_id",
122         api_name        => "open-ils.actor.user.fleshed.retrieve",);
123
124 sub user_retrieve_fleshed_by_id {
125         my( $self, $client, $user_session, $user_id ) = @_;
126         my $user_obj = $apputils->check_user_session( $user_session ); 
127
128         if(!defined($user_id)) { $user_id = $user_obj->id; }
129
130         if( $user_obj->id ne $user_id ) {
131                 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER")) {
132                         return OpenILS::Perm->new("VIEW_USER");
133                 }
134         }
135
136         return flesh_user($user_id);
137 }
138
139
140 sub flesh_user {
141         my $id = shift;
142         my $session = shift;
143
144         my $kill = 0;
145
146         if(!$session) {
147                 $session = OpenSRF::AppSession->create("open-ils.storage");
148                 $kill = 1;
149         }
150
151         # grab the user with the given id 
152         my $ureq = $session->request(
153                         "open-ils.storage.direct.actor.user.retrieve", $id);
154         my $user = $ureq->gather(1);
155
156         if(!$user) { return undef; }
157
158         # grab the cards
159         my $cards_req = $session->request(
160                         "open-ils.storage.direct.actor.card.search.usr.atomic",
161                         $user->id() );
162         $user->cards( $cards_req->gather(1) );
163
164         for my $c(@{$user->cards}) {
165                 if($c->id == $user->card || $c->id eq $user->card ) {
166                         warn "Setting my card to " . $c->id . "\n";
167                         $user->card($c);
168                 }
169         }
170
171         my $add_req = $session->request(
172                         "open-ils.storage.direct.actor.user_address.search.usr.atomic",
173                         $user->id() );
174         $user->addresses( $add_req->gather(1) );
175
176         for my $c(@{$user->addresses}) {
177                 if($c->id == $user->billing_address || $c->id eq $user->billing_address ) {
178                         warn "Setting my address to " . $c->id . "\n";
179                         $user->billing_address($c);
180                 }
181         }
182
183         for my $c(@{$user->addresses}) {
184                 if($c->id == $user->mailing_address || $c->id eq $user->mailing_address ) {
185                         warn "Setting my address to " . $c->id . "\n";
186                         $user->mailing_address($c);
187                 }
188         }
189
190         my $stat_req = $session->request(
191                 "open-ils.storage.direct.actor.stat_cat_entry_user_map.search.target_usr.atomic",
192                 $user->id() );
193         $user->stat_cat_entries($stat_req->gather(1));
194
195         if($kill) { $session->disconnect(); }
196         $user->clear_passwd();
197         warn Dumper $user;
198
199         return $user;
200
201 }
202
203
204 # clone and clear stuff that would break the database
205 sub _clone_patron {
206         my $patron = shift;
207
208         my $new_patron = Fieldmapper::actor::user->new();
209
210         my $fmap = $Fieldmapper::fieldmap;
211         no strict; # shallow clone, may be useful in the fieldmapper
212         for my $field 
213                 (keys %{$fmap->{"Fieldmapper::actor::user"}->{'fields'}}) {
214                         $new_patron->$field( $patron->$field() );
215         }
216         use strict;
217
218         # clear these
219         $new_patron->clear_billing_address();
220         $new_patron->clear_mailing_address();
221         $new_patron->clear_addresses();
222         $new_patron->clear_card();
223         $new_patron->clear_cards();
224         $new_patron->clear_id();
225         $new_patron->clear_isnew();
226         $new_patron->clear_ischanged();
227         $new_patron->clear_isdeleted();
228         $new_patron->clear_stat_cat_entries();
229
230         return $new_patron;
231 }
232
233
234 sub _add_patron {
235         my $session             = shift;
236         my $patron              = shift;
237         my $user_obj    = shift;
238
239
240         if($apputils->check_user_perms(
241                                 $user_obj->id, $user_obj->home_ou, "CREATE_USER")) {
242                 return OpenILS::Perm->new("CREATE_USER");
243         }
244
245         warn "Creating new patron\n";
246         _d($patron);
247
248         my $req = $session->request(
249                 "open-ils.storage.direct.actor.user.create",$patron);
250         my $id = $req->gather(1);
251         if(!$id) { 
252                 return OpenILS::EX->new("DUPLICATE_USER_USERNAME");
253         }
254
255         # retrieve the patron from the db to collect defaults
256         my $ureq = $session->request(
257                         "open-ils.storage.direct.actor.user.retrieve",
258                         $id);
259
260         warn "Created new patron with id $id\n";
261
262         return $ureq->gather(1);
263 }
264
265
266 sub _update_patron {
267         my( $session, $patron, $user_obj) = @_;
268
269
270         if($apputils->check_user_perms(
271                                 $user_obj->id, $user_obj->home_ou, "UPDATE_USER")) {
272                 return OpenILS::Perm->new("UPDATE_USER");
273         }
274
275         warn "updating patron " . Dumper($patron) . "\n";
276
277         my $req = $session->request(
278                 "open-ils.storage.direct.actor.user.update",$patron );
279         my $status = $req->gather(1);
280         if(!defined($status)) { 
281                 throw OpenSRF::EX::ERROR 
282                         ("Unknown error updating patron"); 
283         }
284         return $patron;
285 }
286
287
288 sub _add_update_addresses {
289         my $session = shift;
290         my $patron = shift;
291         my $new_patron = shift;
292
293         my $current_id; # id of the address before creation
294
295         for my $address (@{$patron->addresses()}) {
296
297                 $address->usr($new_patron->id());
298
299                 if(ref($address) and $address->isnew()) {
300                         warn "Adding new address at street " . $address->street1() . "\n";
301
302                         $current_id = $address->id();
303                         $address = _add_address($session,$address);
304
305                         if( $patron->billing_address() and 
306                                         $patron->billing_address() == $current_id ) {
307                                 $new_patron->billing_address($address->id());
308                                 $new_patron->ischanged(1);
309                         }
310
311                         if( $patron->mailing_address() and
312                                         $patron->mailing_address() == $current_id ) {
313                                 $new_patron->mailing_address($address->id());
314                                 $new_patron->ischanged(1);
315                         }
316
317                 } elsif( ref($address) and $address->ischanged() ) {
318                         warn "Updating address at street " . $address->street1();
319                         $address->usr($new_patron->id());
320                         _update_address($session,$address);
321
322                 } elsif( ref($address) and $address->isdeleted() ) {
323                         warn "Deleting address at street " . $address->street1();
324
325                         if( $address->id() == $new_patron->mailing_address() ) {
326                                 $new_patron->clear_mailing_address();
327                                 _update_patron($session, $new_patron);
328                         }
329
330                         if( $address->id() == $new_patron->billing_address() ) {
331                                 $new_patron->clear_billing_address();
332                                 _update_patron($session, $new_patron);
333                         }
334
335                         _delete_address($session,$address);
336                 }
337         }
338
339         return $new_patron;
340 }
341
342
343 # adds an address to the db and returns the address with new id
344 sub _add_address {
345         my($session, $address) = @_;
346         $address->clear_id();
347
348         # put the address into the database
349         my $req = $session->request(
350                 "open-ils.storage.direct.actor.user_address.create",
351                 $address );
352
353         #update the id
354         my $id = $req->gather(1);
355         if(!$id) { 
356                 throw OpenSRF::EX::ERROR 
357                         ("Unable to create new user address"); 
358         }
359
360         warn "Created address with id $id\n";
361
362         # update all the necessary id's
363         $address->id( $id );
364         return $address;
365 }
366
367
368 sub _update_address {
369         my( $session, $address ) = @_;
370         my $req = $session->request(
371                 "open-ils.storage.direct.actor.user_address.update",
372                 $address );
373         my $status = $req->gather(1);
374         if(!defined($status)) { 
375                 throw OpenSRF::EX::ERROR 
376                         ("Unknown error updating address"); 
377         }
378         return $address;
379 }
380
381
382
383 sub _add_update_cards {
384
385         my $session = shift;
386         my $patron = shift;
387         my $new_patron = shift;
388
389         my $virtual_id; #id of the card before creation
390         for my $card (@{$patron->cards()}) {
391
392                 $card->usr($new_patron->id());
393
394                 if(ref($card) and $card->isnew()) {
395
396                         $virtual_id = $card->id();
397                         $card = _add_card($session,$card);
398                         if(UNIVERSAL::isa($card,"OpenILS::EX")) {
399                                 return $card;
400                         }
401
402                         #if(ref($patron->card)) { $patron->card($patron->card->id); }
403                         if($patron->card() == $virtual_id) {
404                                 $new_patron->card($card->id());
405                                 $new_patron->ischanged(1);
406                         }
407
408                 } elsif( ref($card) and $card->ischanged() ) {
409                         $card->usr($new_patron->id());
410                         _update_card($session, $card);
411                 }
412         }
413         return $new_patron;
414 }
415
416
417 # adds an card to the db and returns the card with new id
418 sub _add_card {
419         my( $session, $card ) = @_;
420         $card->clear_id();
421
422         warn "Adding card with barcode " . $card->barcode() . "\n";
423         my $req = $session->request(
424                 "open-ils.storage.direct.actor.card.create",
425                 $card );
426
427         my $id = $req->gather(1);
428         if(!$id) { 
429                 return OpenILS::EX->new("DUPLICATE_INVALID_USER_BARCODE");
430         }
431
432         $card->id($id);
433         warn "Created patron card with id $id\n";
434         return $card;
435 }
436
437
438 sub _update_card {
439         my( $session, $card ) = @_;
440         warn Dumper $card;
441
442         my $req = $session->request(
443                 "open-ils.storage.direct.actor.card.update",
444                 $card );
445         my $status = $req->gather(1);
446         if(!defined($status)) { 
447                 throw OpenSRF::EX::ERROR 
448                         ("Unknown error updating card"); 
449         }
450         return $card;
451 }
452
453
454
455
456 sub _delete_address {
457         my( $session, $address ) = @_;
458
459         warn "Deleting address " . $address->street1() . "\n";
460
461         my $req = $session->request(
462                 "open-ils.storage.direct.actor.user_address.delete",
463                 $address );
464         my $status = $req->gather(1);
465         if(!defined($status)) { 
466                 throw OpenSRF::EX::ERROR 
467                         ("Unknown error updating address"); 
468         }
469         warn "Delete address status is $status\n";
470 }
471
472
473
474 sub _add_survey_responses {
475         my ($session, $patron, $new_patron) = @_;
476
477         warn "updating responses for user " . $new_patron->id . "\n";
478
479         my $responses = $patron->survey_responses;
480
481         if($responses) {
482
483                 for my $resp( @$responses ) {
484                         $resp->usr($new_patron->id);
485                 }
486
487                 my $status = $apputils->simple_scalar_request(
488                         "open-ils.circ", 
489                         "open-ils.circ.survey.submit.user_id",
490                         $responses );
491
492         }
493
494         return $new_patron;
495 }
496
497
498 sub _create_stat_maps {
499
500         my($session, $user_session, $patron, $new_patron) = @_;
501
502         my $maps = $patron->stat_cat_entries();
503
504         for my $map (@$maps) {
505
506                 next unless($map->isnew() || $map->ischanged());
507
508                 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
509                 if($map->isnew()) {
510                         $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
511                         $map->clear_id;
512                 }
513
514                 $map->target_usr($new_patron->id);
515
516                 warn "Updating stat entry with method $method and session $user_session and map $map\n";
517
518                 my $req = $session->request($method, $map);
519                 my $status = $req->gather(1);
520
521                 warn "Updated\n";
522
523                 if(!$status) {
524                         throw OpenSRF::EX::ERROR 
525                                 ("Error updating stat map with method $method");        
526                 }
527
528         }
529
530         return $new_patron;
531 }
532
533
534
535 __PACKAGE__->register_method(
536         method  => "search_username",
537         api_name        => "open-ils.actor.user.search.username",
538 );
539
540 sub search_username {
541         my($self, $client, $username) = @_;
542         my $users = OpenILS::Application::AppUtils->simple_scalar_request(
543                         "open-ils.storage", 
544                         "open-ils.storage.direct.actor.user.search.usrname.atomic",
545                         $username );
546         return $users;
547 }
548
549
550
551
552 __PACKAGE__->register_method(
553         method  => "user_retrieve_by_barcode",
554         api_name        => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
555
556 sub user_retrieve_by_barcode {
557         my($self, $client, $user_session, $barcode) = @_;
558         warn "Searching for user with barcode $barcode\n";
559         my $user_obj = $apputils->check_user_session( $user_session ); 
560
561         my $session = OpenSRF::AppSession->create("open-ils.storage");
562
563         # find the card with the given barcode
564         my $creq        = $session->request(
565                         "open-ils.storage.direct.actor.card.search.barcode.atomic",
566                         $barcode );
567         my $card = $creq->gather(1);
568
569         if(!$card || !$card->[0]) {
570                 $session->disconnect();
571                 return undef;
572         }
573
574         $card = $card->[0];
575         my $user = flesh_user($card->usr(), $session);
576         $session->disconnect();
577         return $user;
578
579 }
580
581
582
583 __PACKAGE__->register_method(
584         method  => "get_user_by_id",
585         api_name        => "open-ils.actor.user.retrieve",);
586
587 sub get_user_by_id {
588         my ($self, $client, $user_session, $id) = @_;
589
590         my $user_obj = $apputils->check_user_session( $user_session ); 
591
592         return $apputils->simple_scalar_request(
593                 "open-ils.storage",
594                 "open-ils.storage.direct.actor.user.retrieve",
595                 $id );
596 }
597
598
599
600 __PACKAGE__->register_method(
601         method  => "get_org_types",
602         api_name        => "open-ils.actor.org_types.retrieve",);
603
604 my $org_types;
605 sub get_org_types {
606         my($self, $client) = @_;
607
608         return $org_types if $org_types;
609          return $org_types = 
610                  $apputils->simple_scalar_request(
611                         "open-ils.storage",
612                         "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
613 }
614
615
616
617 __PACKAGE__->register_method(
618         method  => "get_user_profiles",
619         api_name        => "open-ils.actor.user.profiles.retrieve",
620 );
621
622 my $user_profiles;
623 sub get_user_profiles {
624         return $user_profiles if $user_profiles;
625
626         return $user_profiles = 
627                 $apputils->simple_scalar_request(
628                         "open-ils.storage",
629                         "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
630 }
631
632
633
634 __PACKAGE__->register_method(
635         method  => "get_user_ident_types",
636         api_name        => "open-ils.actor.user.ident_types.retrieve",
637 );
638 my $ident_types;
639 sub get_user_ident_types {
640         return $ident_types if $ident_types;
641         return $ident_types = 
642                 $apputils->simple_scalar_request(
643                 "open-ils.storage",
644                 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
645 }
646
647
648
649
650 __PACKAGE__->register_method(
651         method  => "get_org_unit",
652         api_name        => "open-ils.actor.org_unit.retrieve",
653 );
654
655 sub get_org_unit {
656
657         my( $self, $client, $user_session, $org_id ) = @_;
658
659         if(defined($user_session) && !defined($org_id)) {
660                 my $user_obj = 
661                         OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
662                 if(!defined($org_id)) {
663                         $org_id = $user_obj->home_ou;
664                 }
665         }
666
667
668         my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
669                 "open-ils.storage",
670                 "open-ils.storage.direct.actor.org_unit.retrieve", 
671                 $org_id );
672
673         return $home_ou;
674 }
675
676
677 # build the org tree
678
679 __PACKAGE__->register_method(
680         method  => "get_org_tree",
681         api_name        => "open-ils.actor.org_tree.retrieve",
682         argc            => 1, 
683         note            => "Returns the entire org tree structure",
684 );
685
686 sub get_org_tree {
687         my( $self, $client) = @_;
688
689         if(!$cache_client) {
690                 $cache_client = OpenSRF::Utils::Cache->new("global", 0);
691         }
692         # see if it's in the cache
693         warn "Getting ORG Tree\n";
694         my $tree = $cache_client->get_cache('orgtree');
695         if($tree) { 
696                 warn "Found orgtree in cache. returning...\n";
697                 return $tree; 
698         }
699
700         my $orglist = $apputils->simple_scalar_request( 
701                 "open-ils.storage", 
702                 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
703
704         if($orglist) {
705                 warn "found org list\n";
706         }
707
708         $tree = $self->build_org_tree($orglist);
709         $cache_client->put_cache('orgtree', $tree);
710
711         return $tree;
712
713 }
714
715 # turns an org list into an org tree
716 sub build_org_tree {
717
718         my( $self, $orglist) = @_;
719
720         return $orglist unless ( 
721                         ref($orglist) and @$orglist > 1 );
722
723         my @list = sort { 
724                 $a->ou_type <=> $b->ou_type ||
725                 $a->name cmp $b->name } @$orglist;
726
727         for my $org (@list) {
728
729                 next unless ($org and defined($org->parent_ou));
730                 my ($parent) = grep { $_->id == $org->parent_ou } @list;
731                 next unless $parent;
732
733                 $parent->children([]) unless defined($parent->children); 
734                 push( @{$parent->children}, $org );
735         }
736
737         return $list[0];
738
739 }
740
741
742 __PACKAGE__->register_method(
743         method  => "get_org_descendants",
744         api_name        => "open-ils.actor.org_tree.descendants.retrieve"
745 );
746
747 # depth is optional.  org_unit is the id
748 sub get_org_descendants {
749         my( $self, $client, $org_unit, $depth ) = @_;
750         my $orglist = $apputils->simple_scalar_request(
751                         "open-ils.storage", 
752                         "open-ils.storage.actor.org_unit.descendants.atomic",
753                         $org_unit, $depth );
754         return $self->build_org_tree($orglist);
755 }
756
757
758 __PACKAGE__->register_method(
759         method  => "get_org_ancestors",
760         api_name        => "open-ils.actor.org_tree.ancestors.retrieve"
761 );
762
763 # depth is optional.  org_unit is the id
764 sub get_org_ancestors {
765         my( $self, $client, $org_unit, $depth ) = @_;
766         my $orglist = $apputils->simple_scalar_request(
767                         "open-ils.storage", 
768                         "open-ils.storage.actor.org_unit.ancestors.atomic",
769                         $org_unit, $depth );
770         return $self->build_org_tree($orglist);
771 }
772
773
774 __PACKAGE__->register_method(
775         method  => "get_standings",
776         api_name        => "open-ils.actor.standings.retrieve"
777 );
778
779 my $user_standings;
780 sub get_standings {
781         return $user_standings if $user_standings;
782         return $user_standings = 
783                 $apputils->simple_scalar_request(
784                         "open-ils.storage",
785                         "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
786 }
787
788
789
790 __PACKAGE__->register_method(
791         method  => "get_my_org_path",
792         api_name        => "open-ils.actor.org_unit.full_path.retrieve"
793 );
794
795 sub get_my_org_path {
796         my( $self, $client, $user_session, $org_id ) = @_;
797         my $user_obj = $apputils->check_user_session($user_session); 
798         if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
799
800         return $apputils->simple_scalar_request(
801                 "open-ils.storage",
802                 "open-ils.storage.actor.org_unit.full_path.atomic",
803                 $org_id );
804 }
805
806
807 __PACKAGE__->register_method(
808         method  => "patron_adv_search",
809         api_name        => "open-ils.actor.patron.search.advanced" );
810
811 sub patron_adv_search {
812         my( $self, $client, $staff_login, $search_hash ) = @_;
813
814         use Data::Dumper;
815         warn "patron adv with $staff_login and search " . 
816                 Dumper($search_hash) . "\n";
817
818         my $session = OpenSRF::AppSession->create("open-ils.storage");
819         my $req = $session->request(
820                 "open-ils.storage.actor.user.crazy_search", $search_hash);
821
822         my $ans = $req->gather(1);
823
824         my %hash = map { ($_ =>1) } @$ans;
825         $ans = [ keys %hash ];
826
827         warn "Returning @$ans\n";
828
829         $session->disconnect();
830         return $ans;
831
832 }
833
834
835
836 sub _verify_password {
837         my($user_session, $password) = @_;
838         my $user_obj = $apputils->check_user_session($user_session); 
839
840         #grab the user with password
841         $user_obj = $apputils->simple_scalar_request(
842                 "open-ils.storage", 
843                 "open-ils.storage.direct.actor.user.retrieve",
844                 $user_obj->id );
845
846         if($user_obj->passwd eq $password) {
847                 return 1;
848         }
849
850         return 0;
851 }
852
853
854 __PACKAGE__->register_method(
855         method  => "update_password",
856         api_name        => "open-ils.actor.user.password.update");
857
858 __PACKAGE__->register_method(
859         method  => "update_password",
860         api_name        => "open-ils.actor.user.username.update");
861
862 __PACKAGE__->register_method(
863         method  => "update_password",
864         api_name        => "open-ils.actor.user.email.update");
865
866 sub update_password {
867         my( $self, $client, $user_session, $new_value, $current_password ) = @_;
868
869         warn "Updating user with method " .$self->api_name . "\n";
870         my $user_obj = $apputils->check_user_session($user_session); 
871
872         if($self->api_name =~ /password/) {
873
874                 #make sure they know the current password
875                 if(!_verify_password($user_session, md5_hex($current_password))) {
876                         return OpenILS::EX->new("USER_WRONG_PASSWORD")->ex;
877                 }
878
879                 $user_obj->passwd($new_value);
880         } 
881         elsif($self->api_name =~ /username/) {
882                 $user_obj->usrname($new_value);
883         }
884
885         elsif($self->api_name =~ /email/) {
886                 warn "Updating email to $new_value\n";
887                 $user_obj->email($new_value);
888         }
889
890         my $session = $apputils->start_db_session();
891         $user_obj = _update_patron($session, $user_obj);
892         $apputils->commit_db_session($session);
893
894         if($user_obj) { return 1; }
895         return undef;
896 }
897
898
899 __PACKAGE__->register_method(
900         method  => "check_user_perms",
901         api_name        => "open-ils.actor.user.perm.check",
902         notes           => <<"  NOTES");
903         Takes a login session, user id, an org id, and an array of perm type strings.  For each
904         perm type, if the user does *not* have the given permission it is added
905         to a list which is returned from the method.  If all permissions
906         are allowed, an empty list is returned
907         if the logged in user does not match 'user_id', then the logged in user must
908         have VIEW_PERMISSION priveleges.
909         NOTES
910
911 sub check_user_perms {
912         my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
913         my $user_obj = $apputils->check_user_session($login_session); 
914
915         if($user_obj->id ne $user_id) {
916                 if($apputils->check_user_perms($user_obj->id, $org_id, "VIEW_PERMISSION")) {
917                         return OpenILS::Perm->new("VIEW_PERMISSION");
918                 }
919         }
920
921         my @not_allowed;
922         for my $perm (@$perm_types) {
923                 if($apputils->check_user_perms($user_id, $org_id, $perm)) {
924                         push @not_allowed, $perm;
925                 }
926         }
927
928         return \@not_allowed
929 }
930
931
932
933 __PACKAGE__->register_method(
934         method  => "user_fines_summary",
935         api_name        => "open-ils.actor.user.fines.summary",
936         notes           => <<"  NOTES");
937         Returns a short summary of the users total open fines, excluding voided fines
938         Params are login_session, user_id
939         Returns a 'mus' object.
940         NOTES
941
942 sub user_fines_summary {
943         my( $self, $client, $login_session, $user_id ) = @_;
944
945         my $user_obj = $apputils->check_user_session($login_session); 
946         if($user_obj->id ne $user_id) {
947                 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_FINES_SUMMARY")) {
948                         return OpenILS::Perm->new("VIEW_USER_FINES_SUMMARY"); 
949                 }
950         }
951
952         return $apputils->simple_scalar_request( 
953                 "open-ils.storage",
954                 "open-ils.storage.direct.money.user_summary.search.usr",
955                 $user_id );
956
957 }
958
959
960
961
962 __PACKAGE__->register_method(
963         method  => "user_transactions",
964         api_name        => "open-ils.actor.user.transactions",
965         notes           => <<"  NOTES");
966         Returns a list of open user transactions (mbts objects);
967         Params are login_session, user_id
968         Optional third parameter is the transactions type.  defaults to all
969         NOTES
970
971 __PACKAGE__->register_method(
972         method  => "user_transactions",
973         api_name        => "open-ils.actor.user.transactions.have_charge",
974         notes           => <<"  NOTES");
975         Returns a list of all open user transactions (mbts objects) that have an initial charge
976         Params are login_session, user_id
977         Optional third parameter is the transactions type.  defaults to all
978         NOTES
979
980 __PACKAGE__->register_method(
981         method  => "user_transactions",
982         api_name        => "open-ils.actor.user.transactions.have_balance",
983         notes           => <<"  NOTES");
984         Returns a list of all open user transactions (mbts objects) that have a balance
985         Params are login_session, user_id
986         Optional third parameter is the transactions type.  defaults to all
987         NOTES
988
989 __PACKAGE__->register_method(
990         method  => "user_transactions",
991         api_name        => "open-ils.actor.user.transactions.fleshed",
992         notes           => <<"  NOTES");
993         Returns an object/hash of transaction, circ, title where transaction = an open 
994         user transactions (mbts objects), circ is the attached circluation, and title
995         is the title the circ points to
996         Params are login_session, user_id
997         Optional third parameter is the transactions type.  defaults to all
998         NOTES
999
1000 __PACKAGE__->register_method(
1001         method  => "user_transactions",
1002         api_name        => "open-ils.actor.user.transactions.have_charge.fleshed",
1003         notes           => <<"  NOTES");
1004         Returns an object/hash of transaction, circ, title where transaction = an open 
1005         user transactions that has an initial charge (mbts objects), circ is the 
1006         attached circluation, and title is the title the circ points to
1007         Params are login_session, user_id
1008         Optional third parameter is the transactions type.  defaults to all
1009         NOTES
1010
1011 __PACKAGE__->register_method(
1012         method  => "user_transactions",
1013         api_name        => "open-ils.actor.user.transactions.have_balance.fleshed",
1014         notes           => <<"  NOTES");
1015         Returns an object/hash of transaction, circ, title where transaction = an open 
1016         user transaction that has a balance (mbts objects), circ is the attached 
1017         circluation, and title is the title the circ points to
1018         Params are login_session, user_id
1019         Optional third parameter is the transaction type.  defaults to all
1020         NOTES
1021
1022
1023
1024 sub user_transactions {
1025         my( $self, $client, $login_session, $user_id, $type ) = @_;
1026
1027         my $user_obj = $apputils->check_user_session($login_session); 
1028         if($user_obj->id ne $user_id) {
1029                 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_TRANSACTIONS")) {
1030                         return OpenILS::Perm->new("VIEW_USER_TRANSACTIONS"); 
1031                 }
1032         }
1033
1034         my $api = $self->api_name();
1035         my $trans;
1036         my @xact;
1037         if(defined($type)) { @xact = (xact_type =>  $type); 
1038         } else { @xact = (); }
1039
1040         if($api =~ /have_charge/) {
1041
1042                 $trans = $apputils->simple_scalar_request( 
1043                         "open-ils.storage",
1044                         "open-ils.storage.direct.money.billable_transaction_summary.search_where.atomic",
1045                         { usr => $user_id, total_owed => { ">" => 0 }, @xact });
1046
1047         } elsif($api =~ /have_balance/) {
1048
1049                 $trans =  $apputils->simple_scalar_request( 
1050                         "open-ils.storage",
1051                         "open-ils.storage.direct.money.billable_transaction_summary.search_where.atomic",
1052                         { usr => $user_id, balance_owed => { ">" => 0 }, @xact });
1053
1054         } else {
1055
1056                 $trans =  $apputils->simple_scalar_request( 
1057                         "open-ils.storage",
1058                         "open-ils.storage.direct.money.billable_transaction_summary.search_where.atomic",
1059                         { usr => $user_id, @xact });
1060         }
1061
1062         if($api !~ /fleshed/) { return $trans; }
1063
1064         warn "API: $api\n";
1065
1066         my @resp;
1067         for my $t (@$trans) {
1068                         
1069                 warn $t->id . "\n";
1070
1071                 my $circ = $apputils->simple_scalar_request(
1072                                 "open-ils.storage",
1073                                 "open-ils.storage.direct.action.circulation.retrieve",
1074                                 $t->id );
1075
1076                 my $title = $apputils->simple_scalar_request(
1077                         "open-ils.storage", 
1078                         "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1079                         $circ->target_copy );
1080
1081                 my $u = OpenILS::Utils::ModsParser->new();
1082                 $u->start_mods_batch($title->marc());
1083                 my $mods = $u->finish_mods_batch();
1084
1085                 push @resp, {transaction => $t, circ => $circ, record => $mods };
1086
1087         }
1088
1089         return \@resp; 
1090
1091
1092
1093
1094
1095 __PACKAGE__->register_method(
1096         method  => "retrieve_groups",
1097         api_name        => "open-ils.actor.groups.retrieve",
1098         notes           => <<"  NOTES");
1099         Returns a list of user groups
1100         NOTES
1101 sub retrieve_groups {
1102         my( $self, $client ) = @_;
1103         return $apputils->simple_scalar_request(
1104                 "open-ils.storage",
1105                 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1106 }
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119 1;
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156 __END__
1157
1158
1159 some old methods that may be good to keep around for now
1160
1161 sub _delete_card {
1162         my( $session, $card ) = @_;
1163
1164         warn "Deleting card with barcode " . $card->barcode() . "\n";
1165         my $req = $session->request(
1166                 "open-ils.storage.direct.actor.card.delete",
1167                 $card );
1168         my $status = $req->gather(1);
1169         if(!defined($status)) { 
1170                 throw OpenSRF::EX::ERROR 
1171                         ("Unknown error updating card"); 
1172         }
1173 }
1174
1175
1176
1177 # deletes the patron and any attached addresses and cards
1178 __PACKAGE__->register_method(
1179         method  => "delete_patron",
1180         api_name        => "open-ils.actor.patron.delete",
1181 );
1182
1183 sub delete_patron {
1184
1185         my( $self, $client, $patron ) = @_;
1186         my $session = $apputils->start_db_session();
1187         my $err = undef;
1188
1189         try {
1190
1191                 $patron->clear_mailing_address();
1192                 $patron->clear_billing_address();
1193                 $patron->ischanged(1);
1194
1195                 _update_patron($session, $patron);
1196                 _delete_address($session,$_) for (@{$patron->addresses()});
1197                 _delete_card($session,$_) for (@{$patron->cards()});
1198                 _delete_patron($session,$patron);
1199                 $apputils->commit_db_session($session);
1200
1201         } catch Error with {
1202                 my $e = shift;
1203                 $err =  "-*- Failure deleting user: $e";
1204                 $apputils->rollback_db_session($session);
1205                 warn $err;
1206         };
1207
1208         if($err) { throw OpenSRF::EX::ERROR ($err); }
1209         warn "Patron Delete complete\n";
1210         return 1;
1211 }
1212
1213 sub _delete_patron {
1214         my( $session, $patron ) = @_;
1215
1216         warn "Deleting patron " . $patron->usrname() . "\n";
1217
1218         my $req = $session->request(
1219                 "open-ils.storage.direct.actor.user.delete",
1220                 $patron );
1221         my $status = $req->gather(1);
1222         if(!defined($status)) { 
1223                 throw OpenSRF::EX::ERROR 
1224                         ("Unknown error updating patron"); 
1225         }
1226 }
1227
1228