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