1 package OpenILS::Application::Actor;
2 use base qw/OpenSRF::Application/;
3 use strict; use warnings;
6 use OpenSRF::EX qw(:try);
9 use OpenILS::Application::AppUtils;
10 use OpenILS::Utils::Fieldmapper;
11 use OpenILS::Application::Search::Actor;
13 my $apputils = "OpenILS::Application::AppUtils";
14 sub _d { warn "Patron:\n" . Dumper(shift()); }
15 my $cache_client = OpenSRF::Utils::Cache->new("global", 0);
18 __PACKAGE__->register_method(
19 method => "update_patron",
20 api_name => "open-ils.actor.patron.update",
25 my( $self, $client, $user_session, $patron ) = @_;
27 my $session = $apputils->start_db_session();
30 warn $user_session . " " . $patron . "\n";
34 OpenILS::Application::AppUtils->check_user_session(
35 $user_session ); #throws EX on error
37 # XXX does this user have permission to add/create users. Granularity?
39 # $new_patron is the patron in progress. $patron is the original patron
40 # passed in with the method. new_patron will change as the components
41 # of patron are added/updated.
46 # create/update the patron first so we can use his id
47 if($patron->isnew()) {
48 $new_patron = _add_patron(
49 $session, _clone_patron($patron));
50 if(UNIVERSAL::isa($new_patron, "OpenILS::EX")) {
51 $client->respond_complete($new_patron->ex);
56 $new_patron = $patron;
59 $new_patron = _add_update_addresses($session, $patron, $new_patron);
60 $new_patron = _add_update_cards($session, $patron, $new_patron);
62 if(UNIVERSAL::isa($new_patron,"OpenILS::EX")) {
63 $client->respond_complete($new_patron->ex);
67 $new_patron = _add_survey_responses($session, $patron, $new_patron);
68 $new_patron = _create_stat_maps($session, $user_session, $patron, $new_patron);
70 # re-update the patron if anything has happened to him during this process
71 if($new_patron->ischanged()) {
72 $new_patron = _update_patron($session, $new_patron);
74 $apputils->commit_db_session($session);
79 $err = "-*- Failure adding user: $e";
80 $apputils->rollback_db_session($session);
84 if($err) { throw OpenSRF::EX::ERROR ($err); }
87 warn "Patron Update/Create complete\n";
88 return flesh_user($new_patron->id());
92 __PACKAGE__->register_method(
93 method => "user_retrieve_fleshed_by_id",
94 api_name => "open-ils.actor.user.fleshed.retrieve",);
96 sub user_retrieve_fleshed_by_id {
97 my( $self, $client, $user_session, $user_id ) = @_;
98 my $user_obj = $apputils->check_user_session( $user_session );
99 return flesh_user($user_id);
110 $session = OpenSRF::AppSession->create("open-ils.storage");
114 # grab the user with the given card
115 my $ureq = $session->request(
116 "open-ils.storage.direct.actor.user.retrieve",
118 my $user = $ureq->gather(1);
121 my $cards_req = $session->request(
122 "open-ils.storage.direct.actor.card.search.usr",
124 $user->cards( $cards_req->gather(1) );
126 my $add_req = $session->request(
127 "open-ils.storage.direct.actor.user_address.search.usr",
129 $user->addresses( $add_req->gather(1) );
131 my $stat_req = $session->request(
132 "open-ils.storage.direct.actor.stat_cat_entry_user_map.search.target_usr",
134 $user->stat_cat_entries($stat_req->gather(1));
136 if($kill) { $session->disconnect(); }
137 $user->clear_passwd();
145 # clone and clear stuff that would break the database
149 my $new_patron = Fieldmapper::actor::user->new();
151 my $fmap = $Fieldmapper::fieldmap;
152 no strict; # shallow clone, may be useful in the fieldmapper
154 (keys %{$fmap->{"Fieldmapper::actor::user"}->{'fields'}}) {
155 $new_patron->$field( $patron->$field() );
160 $new_patron->clear_billing_address();
161 $new_patron->clear_mailing_address();
162 $new_patron->clear_addresses();
163 $new_patron->clear_card();
164 $new_patron->clear_cards();
165 $new_patron->clear_id();
166 $new_patron->clear_isnew();
167 $new_patron->clear_changed();
168 $new_patron->clear_deleted();
169 $new_patron->clear_stat_cat_entries();
179 warn "Creating new patron\n";
182 my $req = $session->request(
183 "open-ils.storage.direct.actor.user.create",$patron);
184 my $id = $req->gather(1);
186 return OpenILS::EX->new("DUPLICATE_USER_USERNAME");
189 # retrieve the patron from the db to collect defaults
190 my $ureq = $session->request(
191 "open-ils.storage.direct.actor.user.retrieve",
194 warn "Created new patron with id $id\n";
196 return $ureq->gather(1);
201 my( $session, $patron) = @_;
203 warn "updating patron " . Dumper($patron) . "\n";
205 my $req = $session->request(
206 "open-ils.storage.direct.actor.user.update",$patron );
207 my $status = $req->gather(1);
208 if(!defined($status)) {
209 throw OpenSRF::EX::ERROR
210 ("Unknown error updating patron");
216 sub _add_update_addresses {
219 my $new_patron = shift;
221 my $current_id; # id of the address before creation
223 for my $address (@{$patron->addresses()}) {
225 $address->usr($new_patron->id());
227 if(ref($address) and $address->isnew()) {
228 warn "Adding new address at street " . $address->street1() . "\n";
230 $current_id = $address->id();
231 $address = _add_address($session,$address);
233 if( $patron->billing_address() and
234 $patron->billing_address() == $current_id ) {
235 $new_patron->billing_address($address->id());
236 $new_patron->ischanged(1);
239 if( $patron->mailing_address() and
240 $patron->mailing_address() == $current_id ) {
241 $new_patron->mailing_address($address->id());
242 $new_patron->ischanged(1);
245 } elsif( ref($address) and $address->ischanged() ) {
246 warn "Updating address at street " . $address->street1();
247 $address->usr($new_patron->id());
248 _update_address($session,$address);
250 } elsif( ref($address) and $address->isdeleted() ) {
251 warn "Deleting address at street " . $address->street1();
253 if( $address->id() == $new_patron->mailing_address() ) {
254 $new_patron->clear_mailing_address();
255 _update_patron($session, $new_patron);
258 if( $address->id() == $new_patron->billing_address() ) {
259 $new_patron->clear_billing_address();
260 _update_patron($session, $new_patron);
263 _delete_address($session,$address);
271 # adds an address to the db and returns the address with new id
273 my($session, $address) = @_;
274 $address->clear_id();
276 # put the address into the database
277 my $req = $session->request(
278 "open-ils.storage.direct.actor.user_address.create",
282 my $id = $req->gather(1);
284 throw OpenSRF::EX::ERROR
285 ("Unable to create new user address");
288 warn "Created address with id $id\n";
290 # update all the necessary id's
296 sub _update_address {
297 my( $session, $address ) = @_;
298 my $req = $session->request(
299 "open-ils.storage.direct.actor.user_address.update",
301 my $status = $req->gather(1);
302 if(!defined($status)) {
303 throw OpenSRF::EX::ERROR
304 ("Unknown error updating address");
311 sub _add_update_cards {
315 my $new_patron = shift;
317 my $virtual_id; #id of the card before creation
318 for my $card (@{$patron->cards()}) {
320 $card->usr($new_patron->id());
322 if(ref($card) and $card->isnew()) {
324 $virtual_id = $card->id();
325 $card = _add_card($session,$card);
326 if(UNIVERSAL::isa($card,"OpenILS::EX")) {
330 if($patron->card() == $virtual_id) {
331 $new_patron->card($card->id());
332 $new_patron->ischanged(1);
335 } elsif( ref($card) and $card->ischanged() ) {
336 $card->usr($new_patron->id());
337 _update_card($session, $card);
344 # adds an card to the db and returns the card with new id
346 my( $session, $card ) = @_;
349 warn "Adding card with barcode " . $card->barcode() . "\n";
350 my $req = $session->request(
351 "open-ils.storage.direct.actor.card.create",
354 my $id = $req->gather(1);
356 return OpenILS::EX->new("DUPLICATE_INVALID_USER_BARCODE");
360 warn "Created patron card with id $id\n";
366 my( $session, $card ) = @_;
369 my $req = $session->request(
370 "open-ils.storage.direct.actor.card.update",
372 my $status = $req->gather(1);
373 if(!defined($status)) {
374 throw OpenSRF::EX::ERROR
375 ("Unknown error updating card");
383 sub _delete_address {
384 my( $session, $address ) = @_;
386 warn "Deleting address " . $address->street1() . "\n";
388 my $req = $session->request(
389 "open-ils.storage.direct.actor.user_address.delete",
391 my $status = $req->gather(1);
392 if(!defined($status)) {
393 throw OpenSRF::EX::ERROR
394 ("Unknown error updating address");
396 warn "Delete address status is $status\n";
401 sub _add_survey_responses {
402 my ($session, $patron, $new_patron) = @_;
404 warn "updating responses for user " . $new_patron->id . "\n";
406 my $responses = $patron->survey_responses;
407 for my $resp( @$responses ) {
408 $resp->usr($new_patron->id);
411 my $status = $apputils->simple_scalar_request(
413 "open-ils.circ.survey.submit.user_id",
420 sub _create_stat_maps {
422 my($session, $user_session, $patron, $new_patron) = @_;
424 my $maps = $patron->stat_cat_entries();
426 for my $map (@$maps) {
428 next unless($map->isnew() || $map->ischanged());
430 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
432 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
435 $map->target_usr($new_patron->id);
437 warn "Updating stat entry with method $method and session $user_session and map $map\n";
439 my $req = $session->request($method, $map);
440 my $status = $req->gather(1);
445 throw OpenSRF::EX::ERROR
446 ("Error updating stat map with method $method");
455 __PACKAGE__->register_method(
456 method => "search_username",
457 api_name => "open-ils.actor.user.search.username",
460 sub search_username {
461 my($self, $client, $username) = @_;
462 my $users = OpenILS::Application::AppUtils->simple_scalar_request(
464 "open-ils.storage.direct.actor.user.search.usrname",
472 __PACKAGE__->register_method(
473 method => "user_retrieve_by_barcode",
474 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
476 sub user_retrieve_by_barcode {
477 my($self, $client, $user_session, $barcode) = @_;
478 warn "Searching for user with barcode $barcode\n";
479 my $user_obj = $apputils->check_user_session( $user_session );
481 my $session = OpenSRF::AppSession->create("open-ils.storage");
483 # find the card with the given barcode
484 my $creq = $session->request(
485 "open-ils.storage.direct.actor.card.search.barcode",
487 my $card = $creq->gather(1);
489 if(!$card || !$card->[0]) {
490 $session->disconnect();
495 my $user = flesh_user($card->usr(), $session);
496 $session->disconnect();
503 __PACKAGE__->register_method(
504 method => "get_user_by_id",
505 api_name => "open-ils.actor.user.retrieve",);
508 my ($self, $client, $user_session, $id) = @_;
510 my $user_obj = $apputils->check_user_session( $user_session );
512 return $apputils->simple_scalar_request(
514 "open-ils.storage.direct.actor.user.retrieve",
520 __PACKAGE__->register_method(
521 method => "get_org_types",
522 api_name => "open-ils.actor.org_types.retrieve",);
526 my($self, $client) = @_;
528 return $org_types if $org_types;
530 $apputils->simple_scalar_request(
532 "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
537 __PACKAGE__->register_method(
538 method => "get_user_profiles",
539 api_name => "open-ils.actor.user.profiles.retrieve",
543 sub get_user_profiles {
544 return $user_profiles if $user_profiles;
546 return $user_profiles =
547 $apputils->simple_scalar_request(
549 "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
554 __PACKAGE__->register_method(
555 method => "get_user_ident_types",
556 api_name => "open-ils.actor.user.ident_types.retrieve",
559 sub get_user_ident_types {
560 return $ident_types if $ident_types;
561 return $ident_types =
562 $apputils->simple_scalar_request(
564 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
570 __PACKAGE__->register_method(
571 method => "get_org_unit",
572 api_name => "open-ils.actor.org_unit.retrieve",
577 my( $self, $client, $user_session ) = @_;
580 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
582 my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
584 "open-ils.storage.direct.actor.org_unit.retrieve",
585 $user_obj->home_ou );
593 __PACKAGE__->register_method(
594 method => "get_org_tree",
595 api_name => "open-ils.actor.org_tree.retrieve",
597 note => "Returns the entire org tree structure",
601 my( $self, $client) = @_;
603 # see if it's in the cache
604 warn "Getting ORG Tree\n";
605 my $tree = $cache_client->get_cache('orgtree');
607 warn "Found orgtree in cache. returning...\n";
611 my $orglist = $apputils->simple_scalar_request(
613 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
615 $tree = $self->build_org_tree($orglist);
616 $cache_client->put_cache('orgtree', $tree);
622 # turns an org list into an org tree
625 my( $self, $orglist) = @_;
627 return $orglist unless (
628 ref($orglist) and @$orglist > 1 );
631 $a->ou_type <=> $b->ou_type ||
632 $a->name cmp $b->name } @$orglist;
634 for my $org (@list) {
636 next unless ($org and defined($org->parent_ou));
637 my ($parent) = grep { $_->id == $org->parent_ou } @list;
640 $parent->children([]) unless defined($parent->children);
641 push( @{$parent->children}, $org );
649 __PACKAGE__->register_method(
650 method => "get_org_descendants",
651 api_name => "open-ils.actor.org_tree.descendants.retrieve"
654 # depth is optional. org_unit is the id
655 sub get_org_descendants {
656 my( $self, $client, $org_unit, $depth ) = @_;
657 my $orglist = $apputils->simple_scalar_request(
659 "open-ils.storage.actor.org_unit.descendants.atomic",
661 return $self->build_org_tree($orglist);
665 __PACKAGE__->register_method(
666 method => "get_org_ancestors",
667 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
670 # depth is optional. org_unit is the id
671 sub get_org_ancestors {
672 my( $self, $client, $org_unit, $depth ) = @_;
673 my $orglist = $apputils->simple_scalar_request(
675 "open-ils.storage.actor.org_unit.ancestors.atomic",
677 return $self->build_org_tree($orglist);
681 __PACKAGE__->register_method(
682 method => "get_standings",
683 api_name => "open-ils.actor.standings.retrieve"
688 return $user_standings if $user_standings;
689 return $user_standings =
690 $apputils->simple_scalar_request(
692 "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
697 __PACKAGE__->register_method(
698 method => "get_my_org_path",
699 api_name => "open-ils.actor.org_unit.full_path.retrieve"
702 sub get_my_org_path {
703 my( $self, $client, $user_session, $org_id ) = @_;
704 my $user_obj = $apputils->check_user_session($user_session);
705 if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
707 return $apputils->simple_scalar_request(
709 "open-ils.storage.actor.org_unit.full_path.atomic",
714 __PACKAGE__->register_method(
715 method => "patron_adv_search",
716 api_name => "open-ils.actor.patron.search.advanced" );
718 sub patron_adv_search {
719 my( $self, $client, $staff_login, $search_hash ) = @_;
722 warn "patron adv with $staff_login and search " .
723 Dumper($search_hash) . "\n";
725 my $session = OpenSRF::AppSession->create("open-ils.storage");
726 my $req = $session->request(
727 "open-ils.storage.actor.user.crazy_search", $search_hash);
729 my $ans = $req->gather(1);
731 my %hash = map { ($_ =>1) } @$ans;
732 $ans = [ keys %hash ];
734 warn "Returning @$ans\n";
736 $session->disconnect();
756 some old methods that may be good to keep around for now
759 my( $session, $card ) = @_;
761 warn "Deleting card with barcode " . $card->barcode() . "\n";
762 my $req = $session->request(
763 "open-ils.storage.direct.actor.card.delete",
765 my $status = $req->gather(1);
766 if(!defined($status)) {
767 throw OpenSRF::EX::ERROR
768 ("Unknown error updating card");
774 # deletes the patron and any attached addresses and cards
775 __PACKAGE__->register_method(
776 method => "delete_patron",
777 api_name => "open-ils.actor.patron.delete",
782 my( $self, $client, $patron ) = @_;
783 my $session = $apputils->start_db_session();
788 $patron->clear_mailing_address();
789 $patron->clear_billing_address();
790 $patron->ischanged(1);
792 _update_patron($session, $patron);
793 _delete_address($session,$_) for (@{$patron->addresses()});
794 _delete_card($session,$_) for (@{$patron->cards()});
795 _delete_patron($session,$patron);
796 $apputils->commit_db_session($session);
800 $err = "-*- Failure deleting user: $e";
801 $apputils->rollback_db_session($session);
805 if($err) { throw OpenSRF::EX::ERROR ($err); }
806 warn "Patron Delete complete\n";
811 my( $session, $patron ) = @_;
813 warn "Deleting patron " . $patron->usrname() . "\n";
815 my $req = $session->request(
816 "open-ils.storage.direct.actor.user.delete",
818 my $status = $req->gather(1);
819 if(!defined($status)) {
820 throw OpenSRF::EX::ERROR
821 ("Unknown error updating patron");