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