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