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