]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Actor.pm
more work on holds capturing, adding permissions, 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
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 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         NOTES
877         );
878
879 sub check_user_perms {
880         my( $self, $client, $user_id, $org_id, $perm_types ) = @_;
881
882         my @not_allowed;
883         for my $perm (@$perm_types) {
884                 if($apputils->check_user_perms($user_id, $org_id, $perm)) {
885                         push @not_allowed, $perm;
886                 }
887         }
888
889         return \@not_allowed
890 }
891
892
893
894 __PACKAGE__->register_method(
895         method  => "user_fines_summary",
896         api_name        => "open-ils.actor.user.fines.summary",
897         notes           => <<"  NOTES"
898         Returns a short summary of the users total open fines, excluding voided fines
899         Params are login_session, user_id
900         Returns a 'mus' object.
901         NOTES
902         );
903
904 sub user_fines_summary {
905         my( $self, $client, $login_session, $user_id ) = @_;
906
907         my $user_obj = $apputils->check_user_session($login_session); 
908         if($user_obj->id ne $user_id) {
909                 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_FINES_SUMMARY")) {
910                         return OpenILS::Perm->new("VIEW_USER_FINES_SUMMARY"); 
911                 }
912         }
913
914         return $apputils->simple_scalar_request( 
915                 "open-ils.storage",
916                 "open-ils.storage.direct.money.user_summary.search.usr",
917                 $user_id );
918
919 }
920
921
922
923
924 __PACKAGE__->register_method(
925         method  => "user_transactions",
926         api_name        => "open-ils.actor.user.transactions",
927         notes           => <<"  NOTES");
928         Returns a list of open user transactions (mbts objects);
929         Params are login_session, user_id
930         Optional third parameter is the transactions type.  defaults to all
931         NOTES
932
933 __PACKAGE__->register_method(
934         method  => "user_transactions",
935         api_name        => "open-ils.actor.user.transactions.have_charge",
936         notes           => <<"  NOTES");
937         Returns a list of all open user transactions (mbts objects) that have an initial charge
938         Params are login_session, user_id
939         Optional third parameter is the transactions type.  defaults to all
940         NOTES
941
942 __PACKAGE__->register_method(
943         method  => "user_transactions",
944         api_name        => "open-ils.actor.user.transactions.have_balance",
945         notes           => <<"  NOTES");
946         Returns a list of all open user transactions (mbts objects) that have a balance
947         Params are login_session, user_id
948         Optional third parameter is the transactions type.  defaults to all
949         NOTES
950
951 __PACKAGE__->register_method(
952         method  => "user_transactions",
953         api_name        => "open-ils.actor.user.transactions.fleshed",
954         notes           => <<"  NOTES");
955         Returns an object/hash of transaction, circ, title where transaction = an open 
956         user transactions (mbts objects), circ is the attached circluation, and title
957         is the title the circ points to
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.fleshed",
965         notes           => <<"  NOTES");
966         Returns an object/hash of transaction, circ, title where transaction = an open 
967         user transactions that has an initial charge (mbts objects), circ is the 
968         attached circluation, and title is the title the circ points to
969         Params are login_session, user_id
970         Optional third parameter is the transactions type.  defaults to all
971         NOTES
972
973 __PACKAGE__->register_method(
974         method  => "user_transactions",
975         api_name        => "open-ils.actor.user.transactions.have_balance.fleshed",
976         notes           => <<"  NOTES");
977         Returns an object/hash of transaction, circ, title where transaction = an open 
978         user transaction that has a balance (mbts objects), circ is the attached 
979         circluation, and title is the title the circ points to
980         Params are login_session, user_id
981         Optional third parameter is the transaction type.  defaults to all
982         NOTES
983
984
985
986 sub user_transactions {
987         my( $self, $client, $login_session, $user_id, $type ) = @_;
988
989         my $user_obj = $apputils->check_user_session($login_session); 
990         if($user_obj->id ne $user_id) {
991                 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_TRANSACTIONS")) {
992                         return OpenILS::Perm->new("VIEW_USER_TRANSACTIONS"); 
993                 }
994         }
995
996         my $api = $self->api_name();
997         my $trans;
998         my @xact;
999         if(defined($type)) { @xact = (xact_type =>  $type); 
1000         } else { @xact = (); }
1001
1002         if($api =~ /have_charge/) {
1003
1004                 $trans = $apputils->simple_scalar_request( 
1005                         "open-ils.storage",
1006                         "open-ils.storage.direct.money.billable_transaction_summary.search_where.atomic",
1007                         { usr => $user_id, total_owed => { ">" => 0 }, @xact });
1008
1009         } elsif($api =~ /have_balance/) {
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, balance_owed => { ">" => 0 }, @xact });
1015
1016         } else {
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, @xact });
1022         }
1023
1024         if($api !~ /fleshed/) { return $trans; }
1025
1026         warn "API: $api\n";
1027
1028         my @resp;
1029         for my $t (@$trans) {
1030                         
1031                 warn $t->id . "\n";
1032
1033                 my $circ = $apputils->simple_scalar_request(
1034                                 "open-ils.storage",
1035                                 "open-ils.storage.direct.action.circulation.retrieve",
1036                                 $t->id );
1037
1038                 my $title = $apputils->simple_scalar_request(
1039                         "open-ils.storage", 
1040                         "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1041                         $circ->target_copy );
1042
1043                 my $u = OpenILS::Utils::ModsParser->new();
1044                 $u->start_mods_batch($title->marc());
1045                 my $mods = $u->finish_mods_batch();
1046
1047                 push @resp, {transaction => $t, circ => $circ, record => $mods };
1048
1049         }
1050
1051         return \@resp; 
1052
1053
1054
1055
1056
1057 __PACKAGE__->register_method(
1058         method  => "retrieve_groups",
1059         api_name        => "open-ils.actor.groups.retrieve",
1060         notes           => <<"  NOTES");
1061         Returns a list of user groups
1062         NOTES
1063 sub retrieve_groups {
1064         my( $self, $client ) = @_;
1065         return $apputils->simple_scalar_request(
1066                 "open-ils.storage",
1067                 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1068 }
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081 1;
1082
1083
1084
1085
1086
1087
1088
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 __END__
1119
1120
1121 some old methods that may be good to keep around for now
1122
1123 sub _delete_card {
1124         my( $session, $card ) = @_;
1125
1126         warn "Deleting card with barcode " . $card->barcode() . "\n";
1127         my $req = $session->request(
1128                 "open-ils.storage.direct.actor.card.delete",
1129                 $card );
1130         my $status = $req->gather(1);
1131         if(!defined($status)) { 
1132                 throw OpenSRF::EX::ERROR 
1133                         ("Unknown error updating card"); 
1134         }
1135 }
1136
1137
1138
1139 # deletes the patron and any attached addresses and cards
1140 __PACKAGE__->register_method(
1141         method  => "delete_patron",
1142         api_name        => "open-ils.actor.patron.delete",
1143 );
1144
1145 sub delete_patron {
1146
1147         my( $self, $client, $patron ) = @_;
1148         my $session = $apputils->start_db_session();
1149         my $err = undef;
1150
1151         try {
1152
1153                 $patron->clear_mailing_address();
1154                 $patron->clear_billing_address();
1155                 $patron->ischanged(1);
1156
1157                 _update_patron($session, $patron);
1158                 _delete_address($session,$_) for (@{$patron->addresses()});
1159                 _delete_card($session,$_) for (@{$patron->cards()});
1160                 _delete_patron($session,$patron);
1161                 $apputils->commit_db_session($session);
1162
1163         } catch Error with {
1164                 my $e = shift;
1165                 $err =  "-*- Failure deleting user: $e";
1166                 $apputils->rollback_db_session($session);
1167                 warn $err;
1168         };
1169
1170         if($err) { throw OpenSRF::EX::ERROR ($err); }
1171         warn "Patron Delete complete\n";
1172         return 1;
1173 }
1174
1175 sub _delete_patron {
1176         my( $session, $patron ) = @_;
1177
1178         warn "Deleting patron " . $patron->usrname() . "\n";
1179
1180         my $req = $session->request(
1181                 "open-ils.storage.direct.actor.user.delete",
1182                 $patron );
1183         my $status = $req->gather(1);
1184         if(!defined($status)) { 
1185                 throw OpenSRF::EX::ERROR 
1186                         ("Unknown error updating patron"); 
1187         }
1188 }
1189
1190