]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Actor.pm
caching some of the static db data
[working/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 OpenSRF::EX qw(:try);
6 use OpenILS::Application::AppUtils;
7 use OpenILS::Utils::Fieldmapper;
8 use OpenILS::Application::Search::Actor;
9
10 my $apputils = "OpenILS::Application::AppUtils";
11 sub _d { warn "Patron:\n" . Dumper(shift()); }
12 my $cache_client = OpenSRF::Utils::Cache->new( "global", 0 );
13
14
15 __PACKAGE__->register_method(
16         method  => "update_patron",
17         api_name        => "open-ils.actor.patron.update",
18 );
19
20
21 sub update_patron {
22         my( $self, $client, $user_session, $patron ) = @_;
23
24         my $session = $apputils->start_db_session();
25         my $err = undef;
26
27         warn $user_session . " " . $patron . "\n";
28         _d($patron);
29
30         my $user_obj = 
31                 OpenILS::Application::AppUtils->check_user_session( 
32                                 $user_session ); #throws EX on error
33
34         # XXX does this user have permission to add/create users.  Granularity?
35
36         # $new_patron is the patron in progress.  $patron is the original patron
37         # passed in with the method.  new_patron will change as the components
38         # of patron are added/updated.
39
40         my $new_patron;
41
42         try {
43                 # create/update the patron first so we can use his id
44                 if( $patron->isnew() ) {
45                         $new_patron = _add_patron(
46                                         $session, _clone_patron($patron));
47                 } else { 
48                         $new_patron = $patron; 
49                 }
50
51                 $new_patron = _add_update_addresses($session, $patron, $new_patron);
52                 $new_patron = _add_update_cards($session, $patron, $new_patron);
53
54                 # re-update the patron if anything has happened to him during this process
55                 if($new_patron->ischanged()) {
56                         $new_patron = _update_patron($session, $new_patron);
57                 }
58                 $apputils->commit_db_session($session);
59
60         } catch Error with { 
61                 my $e = shift;
62                 $err =  "-*- Failure adding user: $e";
63                 $apputils->rollback_db_session($session);
64                 warn $err;
65         };
66
67         if($err) { throw OpenSRF::EX::ERROR ($err); }
68         warn "Patron Update/Create complete\n";
69         return flesh_user($new_patron->id());
70 }
71
72
73 sub flesh_user {
74         my $id = shift;
75         my $session = shift;
76         my $kill = 0;
77
78         if(!$session) {
79                 $session = OpenSRF::AppSession->create("open-ils.storage");
80                 $kill = 1;
81         }
82
83         # grab the user with the given card
84         my $ureq = $session->request(
85                         "open-ils.storage.direct.actor.user.retrieve",
86                         $id);
87         my $user = $ureq->gather(1);
88
89         # grab the cards
90         my $cards_req = $session->request(
91                         "open-ils.storage.direct.actor.card.search.usr",
92                         $user->id() );
93         $user->cards( $cards_req->gather(1) );
94
95         my $add_req = $session->request(
96                         "open-ils.storage.direct.actor.user_address.search.usr",
97                         $user->id() );
98         $user->addresses( $add_req->gather(1) );
99
100         if($kill) { $session->disconnect(); }
101         $user->clear_passwd();
102         warn Dumper $user;
103
104         return $user;
105
106 }
107
108
109 # clone and clear stuff that would break the database
110 sub _clone_patron {
111         my $patron = shift;
112
113         my $new_patron = Fieldmapper::actor::user->new();
114
115         my $fmap = $Fieldmapper::fieldmap;
116         no strict; # shallow clone, may be useful in the fieldmapper
117         for my $field 
118                 (keys %{$fmap->{"Fieldmapper::actor::user"}->{'fields'}}) {
119                         $new_patron->$field( $patron->$field() );
120         }
121         use strict;
122
123         # clear these
124         $new_patron->clear_billing_address();
125         $new_patron->clear_mailing_address();
126         $new_patron->clear_addresses();
127         $new_patron->clear_card();
128         $new_patron->clear_cards();
129         $new_patron->clear_id();
130         $new_patron->clear_isnew();
131         $new_patron->clear_changed();
132         $new_patron->clear_deleted();
133
134         return $new_patron;
135 }
136
137
138 sub _add_patron {
139         my $session             = shift;
140         my $patron              = shift;
141
142         warn "Creating new patron\n";
143         _d($patron);
144
145         my $req = $session->request(
146                 "open-ils.storage.direct.actor.user.create",$patron);
147         my $id = $req->gather(1);
148         if(!$id) { throw OpenSRF::EX::ERROR ("Unable to create new user"); }
149         warn "Created new patron with id $id\n";
150         $patron->id($id);
151
152         return $patron;
153 }
154
155
156 sub _update_patron {
157         my( $session, $patron) = @_;
158
159         warn "updating patron " . $patron->usrname() . "\n";
160         my $req = $session->request(
161                 "open-ils.storage.direct.actor.user.update",$patron );
162         my $status = $req->gather(1);
163         if(!defined($status)) { 
164                 throw OpenSRF::EX::ERROR 
165                         ("Unknown error updating patron"); 
166         }
167         return $patron;
168 }
169
170
171 sub _add_update_addresses {
172         my $session = shift;
173         my $patron = shift;
174         my $new_patron = shift;
175
176         my $current_id; # id of the address before creation
177
178         for my $address (@{$patron->addresses()}) {
179
180                 $address->usr($new_patron->id());
181
182                 if(ref($address) and $address->isnew()) {
183                         warn "Adding new address at street " . $address->street1() . "\n";
184
185                         $current_id = $address->id();
186                         $address = _add_address($session,$address);
187
188                         if( $patron->billing_address() == $current_id ) {
189                                 $new_patron->billing_address($address->id());
190                                 $new_patron->ischanged(1);
191                         }
192
193                         if( $patron->mailing_address() == $current_id ) {
194                                 $new_patron->mailing_address($address->id());
195                                 $new_patron->ischanged(1);
196                         }
197
198                 } elsif( ref($address) and $address->ischanged() ) {
199                         warn "Updating address at street " . $address->street1();
200                         $address->usr($new_patron->id());
201                         _update_address($session,$address);
202
203                 } elsif( ref($address) and $address->isdeleted() ) {
204                         warn "Deleting address at street " . $address->street1();
205
206                         if( $address->id() == $new_patron->mailing_address() ) {
207                                 $new_patron->clear_mailing_address();
208                                 _update_patron($session, $new_patron);
209                         }
210
211                         if( $address->id() == $new_patron->billing_address() ) {
212                                 $new_patron->clear_billing_address();
213                                 _update_patron($session, $new_patron);
214                         }
215
216                         _delete_address($session,$address);
217                 }
218         }
219
220         return $new_patron;
221 }
222
223
224 # adds an address to the db and returns the address with new id
225 sub _add_address {
226         my($session, $address) = @_;
227         $address->clear_id();
228
229         # put the address into the database
230         my $req = $session->request(
231                 "open-ils.storage.direct.actor.user_address.create",
232                 $address );
233
234         #update the id
235         my $id = $req->gather(1);
236         if(!$id) { 
237                 throw OpenSRF::EX::ERROR 
238                         ("Unable to create new user address"); 
239         }
240
241         warn "Created address with id $id\n";
242
243         # update all the necessary id's
244         $address->id( $id );
245         return $address;
246 }
247
248
249 sub _update_address {
250         my( $session, $address ) = @_;
251         my $req = $session->request(
252                 "open-ils.storage.direct.actor.user_address.update",
253                 $address );
254         my $status = $req->gather(1);
255         if(!defined($status)) { 
256                 throw OpenSRF::EX::ERROR 
257                         ("Unknown error updating address"); 
258         }
259         return $address;
260 }
261
262
263
264 sub _add_update_cards {
265
266         my $session = shift;
267         my $patron = shift;
268         my $new_patron = shift;
269
270         my $virtual_id; #id of the card before creation
271         for my $card (@{$patron->cards()}) {
272
273                 $card->usr($new_patron->id());
274
275                 if(ref($card) and $card->isnew()) {
276
277                         $virtual_id = $card->id();
278                         $card = _add_card($session,$card);
279
280                         if($patron->card() == $virtual_id) {
281                                 $new_patron->card($card->id());
282                                 $new_patron->ischanged(1);
283                         }
284
285                 } elsif( ref($card) and $card->ischanged() ) {
286                         $card->usr($new_patron->id());
287                         _update_card($session, $card);
288                 }
289         }
290         return $new_patron;
291 }
292
293
294 # adds an card to the db and returns the card with new id
295 sub _add_card {
296         my( $session, $card ) = @_;
297         $card->clear_id();
298
299         warn "Adding card with barcode " . $card->barcode() . "\n";
300         my $req = $session->request(
301                 "open-ils.storage.direct.actor.card.create",
302                 $card );
303
304         my $id = $req->gather(1);
305         if(!$id) { 
306                 throw OpenSRF::EX::ERROR 
307                         ("Unknown error creating card"); 
308         }
309
310         $card->id($id);
311         warn "Created patron card with id $id\n";
312         return $card;
313 }
314
315
316 sub _update_card {
317         my( $session, $card ) = @_;
318         warn Dumper $card;
319
320         my $req = $session->request(
321                 "open-ils.storage.direct.actor.card.update",
322                 $card );
323         my $status = $req->gather(1);
324         if(!defined($status)) { 
325                 throw OpenSRF::EX::ERROR 
326                         ("Unknown error updating card"); 
327         }
328         return $card;
329 }
330
331
332
333
334 sub _delete_address {
335         my( $session, $address ) = @_;
336
337         warn "Deleting address " . $address->street1() . "\n";
338
339         my $req = $session->request(
340                 "open-ils.storage.direct.actor.user_address.delete",
341                 $address );
342         my $status = $req->gather(1);
343         if(!defined($status)) { 
344                 throw OpenSRF::EX::ERROR 
345                         ("Unknown error updating address"); 
346         }
347         warn "Delete address status is $status\n";
348 }
349
350
351
352
353 __PACKAGE__->register_method(
354         method  => "search_username",
355         api_name        => "open-ils.actor.user.search.username",
356 );
357
358 sub search_username {
359         my($self, $client, $username) = @_;
360         my $users = OpenILS::Application::AppUtils->simple_scalar_request(
361                         "open-ils.storage", 
362                         "open-ils.storage.direct.actor.user.search.usrname",
363                         $username );
364         return $users;
365 }
366
367
368 __PACKAGE__->register_method(
369         method  => "user_retrieve_by_barcode",
370         api_name        => "open-ils.actor.user.fleshed.retrieve_by_barcode",
371 );
372
373 sub user_retrieve_by_barcode {
374         my($self, $client, $barcode) = @_;
375         warn "Searching for user with barcode $barcode\n";
376
377         my $session = OpenSRF::AppSession->create("open-ils.storage");
378
379         # find the card with the given barcode
380         my $creq        = $session->request(
381                         "open-ils.storage.direct.actor.card.search.barcode",
382                         $barcode );
383         my $card = $creq->gather(1);
384         $card = $card->[0];
385         my $user = flesh_user($card->usr(), $session);
386         $session->disconnect();
387         return $user;
388
389 }
390
391
392
393
394 __PACKAGE__->register_method(
395         method  => "get_org_types",
396         api_name        => "open-ils.actor.org_types.retrieve",
397 );
398 sub get_org_types {
399         my($self, $client) = @_;
400
401          my $org_typelist = OpenILS::Application::AppUtils->simple_scalar_request(
402                 "open-ils.storage",
403                 "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
404
405          return $org_typelist;
406 }
407
408
409 __PACKAGE__->register_method(
410         method  => "get_user_profiles",
411         api_name        => "open-ils.actor.user.profiles.retrieve",
412 );
413
414 my $user_profiles;
415 sub get_user_profiles {
416         return $user_profiles if $user_profiles;
417
418         return $user_profiles = 
419                 $apputils->simple_scalar_request(
420                         "open-ils.storage",
421                         "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
422 }
423
424
425
426 __PACKAGE__->register_method(
427         method  => "get_user_ident_types",
428         api_name        => "open-ils.actor.user.ident_types.retrieve",
429 );
430 my $ident_types;
431 sub get_user_ident_types {
432         return $ident_types if $ident_types;
433         return $ident_types = 
434                 $apputils->simple_scalar_request(
435                 "open-ils.storage",
436                 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
437 }
438
439
440
441
442 __PACKAGE__->register_method(
443         method  => "get_org_unit",
444         api_name        => "open-ils.actor.org_unit.retrieve",
445 );
446
447 sub get_org_unit {
448
449         my( $self, $client, $user_session ) = @_;
450
451         my $user_obj = 
452                 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
453
454         my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
455                 "open-ils.storage",
456                 "open-ils.storage.direct.actor.org_unit.retrieve", 
457                 $user_obj->home_ou );
458
459         return $home_ou;
460 }
461
462
463 # build the org tree
464
465 __PACKAGE__->register_method(
466         method  => "get_org_tree",
467         api_name        => "open-ils.actor.org_tree.retrieve",
468         argc            => 1, 
469         note            => "Returns the entire org tree structure",
470 );
471
472 sub get_org_tree {
473         my( $self, $client) = @_;
474
475         # see if it's in the cache
476         warn "Getting ORG Tree\n";
477         my $tree = $cache_client->get_cache('orgtree');
478         if($tree) { 
479                 warn "Found orgtree in cache. returning...\n";
480                 return $tree; 
481         }
482
483         my $orglist = $apputils->simple_scalar_request( 
484                 "open-ils.storage", 
485                 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
486
487         $tree = $self->build_org_tree($orglist);
488         $cache_client->put_cache('orgtree', $tree);
489
490         return $tree;
491
492 }
493
494 # turns an org list into an org tree
495 sub build_org_tree {
496
497         my( $self, $orglist) = @_;
498
499         return $orglist unless ( 
500                         ref($orglist) and @$orglist > 1 );
501
502         my @list = sort { 
503                 $a->ou_type <=> $b->ou_type ||
504                 $a->name cmp $b->name } @$orglist;
505
506         for my $org (@list) {
507
508                 next unless ($org and defined($org->parent_ou));
509                 my ($parent) = grep { $_->id == $org->parent_ou } @list;
510                 next unless $parent;
511
512                 $parent->children([]) unless defined($parent->children); 
513                 push( @{$parent->children}, $org );
514         }
515
516         return $list[0];
517
518 }
519
520
521 __PACKAGE__->register_method(
522         method  => "get_org_descendants",
523         api_name        => "open-ils.actor.org_tree.descendants.retrieve"
524 );
525
526 # depth is optional.  org_unit is the id
527 sub get_org_descendants {
528         my( $self, $client, $org_unit, $depth ) = @_;
529         my $orglist = $apputils->simple_scalar_request(
530                         "open-ils.storage", 
531                         "open-ils.storage.actor.org_unit.descendants.atomic",
532                         $org_unit, $depth );
533         return $self->build_org_tree($orglist);
534 }
535
536
537 __PACKAGE__->register_method(
538         method  => "get_org_ancestors",
539         api_name        => "open-ils.actor.org_tree.ancestors.retrieve"
540 );
541
542 # depth is optional.  org_unit is the id
543 sub get_org_ancestors {
544         my( $self, $client, $org_unit, $depth ) = @_;
545         my $orglist = $apputils->simple_scalar_request(
546                         "open-ils.storage", 
547                         "open-ils.storage.actor.org_unit.ancestors.atomic",
548                         $org_unit, $depth );
549         return $self->build_org_tree($orglist);
550 }
551
552
553 __PACKAGE__->register_method(
554         method  => "get_standings",
555         api_name        => "open-ils.actor.standings.retrieve"
556 );
557
558 my $user_standings;
559 sub get_standings {
560         return $user_standings if $user_standings;
561         return $user_standings = 
562                 $apputils->simple_scalar_request(
563                         "open-ils.storage",
564                         "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
565 }
566
567
568
569 __PACKAGE__->register_method(
570         method  => "get_my_org_path",
571         api_name        => "open-ils.actor.org_unit.full_path.retrieve"
572 );
573
574 sub get_my_org_path {
575         my( $self, $client, $user_session, $org_id ) = @_;
576         my $user_obj = $apputils->check_user_session($user_session); 
577         if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
578
579         return $apputils->simple_scalar_request(
580                 "open-ils.storage",
581                 "open-ils.storage.actor.org_unit.full_path.atomic",
582                 $org_id );
583 }
584
585
586
587 1;
588
589
590
591
592 __END__
593
594
595 some old methods that may be good to keep around for now
596
597 sub _delete_card {
598         my( $session, $card ) = @_;
599
600         warn "Deleting card with barcode " . $card->barcode() . "\n";
601         my $req = $session->request(
602                 "open-ils.storage.direct.actor.card.delete",
603                 $card );
604         my $status = $req->gather(1);
605         if(!defined($status)) { 
606                 throw OpenSRF::EX::ERROR 
607                         ("Unknown error updating card"); 
608         }
609 }
610
611
612
613 # deletes the patron and any attached addresses and cards
614 __PACKAGE__->register_method(
615         method  => "delete_patron",
616         api_name        => "open-ils.actor.patron.delete",
617 );
618
619 sub delete_patron {
620
621         my( $self, $client, $patron ) = @_;
622         my $session = $apputils->start_db_session();
623         my $err = undef;
624
625         try {
626
627                 $patron->clear_mailing_address();
628                 $patron->clear_billing_address();
629                 $patron->ischanged(1);
630
631                 _update_patron($session, $patron);
632                 _delete_address($session,$_) for (@{$patron->addresses()});
633                 _delete_card($session,$_) for (@{$patron->cards()});
634                 _delete_patron($session,$patron);
635                 $apputils->commit_db_session($session);
636
637         } catch Error with {
638                 my $e = shift;
639                 $err =  "-*- Failure deleting user: $e";
640                 $apputils->rollback_db_session($session);
641                 warn $err;
642         };
643
644         if($err) { throw OpenSRF::EX::ERROR ($err); }
645         warn "Patron Delete complete\n";
646         return 1;
647 }
648
649 sub _delete_patron {
650         my( $session, $patron ) = @_;
651
652         warn "Deleting patron " . $patron->usrname() . "\n";
653
654         my $req = $session->request(
655                 "open-ils.storage.direct.actor.user.delete",
656                 $patron );
657         my $status = $req->gather(1);
658         if(!defined($status)) { 
659                 throw OpenSRF::EX::ERROR 
660                         ("Unknown error updating patron"); 
661         }
662 }
663