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