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