1 package OpenILS::Application::Actor;
2 use base qw/OpenSRF::Application/;
3 use strict; use warnings;
5 $Data::Dumper::Indent = 0;
8 use Digest::MD5 qw(md5_hex);
10 use OpenSRF::EX qw(:try);
14 use OpenILS::Application::AppUtils;
16 use OpenILS::Utils::Fieldmapper;
17 use OpenILS::Application::Search::Actor;
18 use OpenILS::Utils::ModsParser;
19 use OpenSRF::Utils::Logger qw/$logger/;
21 use OpenSRF::Utils::Cache;
24 use OpenILS::Application::Actor::Container;
26 OpenILS::Application::Actor::Container->initialize();
29 my $apputils = "OpenILS::Application::AppUtils";
32 sub _d { warn "Patron:\n" . Dumper(shift()); }
37 my $set_user_settings;
40 __PACKAGE__->register_method(
41 method => "set_user_settings",
42 api_name => "open-ils.actor.patron.settings.update",
44 sub set_user_settings {
45 my( $self, $client, $user_session, $uid, $settings ) = @_;
47 $logger->debug("Setting user settings: $user_session, $uid, " . Dumper($settings));
49 my( $staff, $user, $evt ) =
50 $apputils->checkses_requestor( $user_session, $uid, 'UPDATE_USER' );
55 [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
57 $logger->activity("User " . $staff->id . " updating user $uid settings with: " . Dumper($params));
59 return $apputils->simplereq(
61 'open-ils.storage.direct.actor.user_setting.batch.merge', $params );
67 __PACKAGE__->register_method(
68 method => "set_ou_settings",
69 api_name => "open-ils.actor.org_unit.settings.update",
72 my( $self, $client, $user_session, $ouid, $settings ) = @_;
74 my( $staff, $evt ) = $apputils->checkses( $user_session );
76 $evt = $apputils->check_perms( $staff->id, $ouid, 'UPDATE_ORG_UNIT' );
81 map { [{ org_unit => $ouid, name => $_}, {value => $$settings{$_}}] } keys %$settings;
83 $logger->activity("Updating org unit [$ouid] settings with: " . Dumper($params));
85 return $apputils->simplereq(
87 'open-ils.storage.direct.actor.org_unit_setting.merge', @$params );
91 my $fetch_user_settings;
92 my $fetch_ou_settings;
94 __PACKAGE__->register_method(
95 method => "user_settings",
96 api_name => "open-ils.actor.patron.settings.retrieve",
99 my( $self, $client, $user_session, $uid ) = @_;
101 my( $staff, $user, $evt ) =
102 $apputils->checkses_requestor( $user_session, $uid, 'VIEW_USER' );
105 $logger->debug("User " . $staff->id . " fetching user $uid\n");
106 my $s = $apputils->simplereq(
108 'open-ils.storage.direct.actor.user_setting.search.usr.atomic',$uid );
110 return { map { ($_->name,$_->value) } @$s };
115 __PACKAGE__->register_method(
116 method => "ou_settings",
117 api_name => "open-ils.actor.org_unit.settings.retrieve",
120 my( $self, $client, $ouid ) = @_;
122 my $s = $apputils->simplereq(
124 'open-ils.storage.direct.actor.org_unit_setting.search.org_unit.atomic', $ouid);
126 return { map { ($_->name,$_->value) } @$s };
131 __PACKAGE__->register_method(
132 method => "update_patron",
133 api_name => "open-ils.actor.patron.update",);
136 my( $self, $client, $user_session, $patron ) = @_;
138 my $session = $apputils->start_db_session();
141 $logger->info("Creating new patron...") if $patron->isnew;
142 $logger->info("Updating Patron: " . $patron->id) unless $patron->isnew;
144 my( $user_obj, $evt ) = $U->checkses($user_session);
147 # XXX does this user have permission to add/create users. Granularity?
148 # $new_patron is the patron in progress. $patron is the original patron
149 # passed in with the method. new_patron will change as the components
150 # of patron are added/updated.
154 # unflesh the real items on the patron
155 $patron->card( $patron->card->id ) if(ref($patron->card));
156 $patron->billing_address( $patron->billing_address->id )
157 if(ref($patron->billing_address));
158 $patron->mailing_address( $patron->mailing_address->id )
159 if(ref($patron->mailing_address));
161 # create/update the patron first so we can use his id
162 if($patron->isnew()) {
163 ( $new_patron, $evt ) = _add_patron($session, _clone_patron($patron), $user_obj);
165 } else { $new_patron = $patron; }
167 ( $new_patron, $evt ) = _add_update_addresses($session, $patron, $new_patron, $user_obj);
170 ( $new_patron, $evt ) = _add_update_cards($session, $patron, $new_patron, $user_obj);
173 ( $new_patron, $evt ) = _add_survey_responses($session, $patron, $new_patron, $user_obj);
176 # re-update the patron if anything has happened to him during this process
177 if($new_patron->ischanged()) {
178 ( $new_patron, $evt ) = _update_patron($session, $new_patron, $user_obj);
182 #$session = OpenSRF::AppSession->create("open-ils.storage"); # why did i put this here?
184 ($new_patron, $evt) = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
187 ($new_patron, $evt) = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
190 ($new_patron, $evt) = _create_standing_penalties($session, $user_session, $patron, $new_patron, $user_obj);
193 $apputils->commit_db_session($session);
195 #warn "Patron Update/Create complete\n";
196 return flesh_user($new_patron->id());
202 __PACKAGE__->register_method(
203 method => "user_retrieve_fleshed_by_id",
204 api_name => "open-ils.actor.user.fleshed.retrieve",);
206 sub user_retrieve_fleshed_by_id {
207 my( $self, $client, $user_session, $user_id ) = @_;
209 my( $requestor, $target, $evt ) = $apputils->
210 checkses_requestor( $user_session, $user_id, 'VIEW_USER' );
213 return flesh_user($user_id);
224 $session = OpenSRF::AppSession->create("open-ils.storage");
228 # grab the user with the given id
229 my $ureq = $session->request(
230 "open-ils.storage.direct.actor.user.retrieve", $id);
231 my $user = $ureq->gather(1);
233 if(!$user) { return undef; }
236 my $cards_req = $session->request(
237 "open-ils.storage.direct.actor.card.search.usr.atomic",
239 $user->cards( $cards_req->gather(1) );
241 for my $c(@{$user->cards}) {
242 if($c->id == $user->card || $c->id eq $user->card ) {
243 #warn "Setting my card to " . $c->id . "\n";
248 my $add_req = $session->request(
249 "open-ils.storage.direct.actor.user_address.search.usr.atomic",
251 $user->addresses( $add_req->gather(1) );
253 for my $c(@{$user->addresses}) {
254 if($c->id eq $user->billing_address ) { $user->billing_address($c); }
255 if($c->id eq $user->mailing_address ) { $user->mailing_address($c); }
258 my $stat_req = $session->request(
259 "open-ils.storage.direct.actor.stat_cat_entry_user_map.search.target_usr.atomic",
261 $user->stat_cat_entries($stat_req->gather(1));
263 my $standing_penalties_req = $session->request(
264 "open-ils.storage.direct.actor.user_standing_penalty.search.usr.atomic",
266 $user->standing_penalties($standing_penalties_req->gather(1));
268 if($kill) { $session->disconnect(); }
269 $user->clear_passwd();
275 # clone and clear stuff that would break the database
279 my $new_patron = $patron->clone;
281 # Using the Fieldmapper clone method
282 #my $new_patron = Fieldmapper::actor::user->new();
284 #my $fmap = $Fieldmapper::fieldmap;
285 #no strict; # shallow clone, may be useful in the fieldmapper
287 # (keys %{$fmap->{"Fieldmapper::actor::user"}->{'fields'}}) {
288 # $new_patron->$field( $patron->$field() );
293 $new_patron->clear_billing_address();
294 $new_patron->clear_mailing_address();
295 $new_patron->clear_addresses();
296 $new_patron->clear_card();
297 $new_patron->clear_cards();
298 $new_patron->clear_id();
299 $new_patron->clear_isnew();
300 $new_patron->clear_ischanged();
301 $new_patron->clear_isdeleted();
302 $new_patron->clear_stat_cat_entries();
303 $new_patron->clear_permissions();
304 $new_patron->clear_standing_penalties();
314 my $user_obj = shift;
316 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'CREATE_USER');
317 return (undef, $evt) if $evt;
319 $logger->info("Creating new user in the DB with username: ".$patron->usrname());
321 my $id = $session->request(
322 "open-ils.storage.direct.actor.user.create", $patron)->gather(1);
323 return (undef, $U->DB_UPDATE_FAILED($patron)) unless $id;
325 $logger->info("Successfully created new user [$id] in DB");
327 return ( $session->request(
328 "open-ils.storage.direct.actor.user.retrieve", $id)->gather(1), undef );
333 my( $session, $patron, $user_obj) = @_;
335 $logger->info("Updating patron ".$patron->id." in DB");
336 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'UPDATE_USER');
337 return (undef, $evt) if $evt;
339 my $stat = $session->request(
340 "open-ils.storage.direct.actor.user.update",$patron )->gather(1);
341 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($stat);
347 sub _add_update_addresses {
351 my $new_patron = shift;
355 my $current_id; # id of the address before creation
357 for my $address (@{$patron->addresses()}) {
359 $address->usr($new_patron->id());
361 if(ref($address) and $address->isnew()) {
363 $current_id = $address->id();
364 ($address, $evt) = _add_address($session,$address);
365 return (undef, $evt) if $evt;
367 if( $patron->billing_address() and
368 $patron->billing_address() == $current_id ) {
369 $new_patron->billing_address($address->id());
370 $new_patron->ischanged(1);
373 if( $patron->mailing_address() and
374 $patron->mailing_address() == $current_id ) {
375 $new_patron->mailing_address($address->id());
376 $new_patron->ischanged(1);
379 } elsif( ref($address) and $address->ischanged() ) {
381 $address->usr($new_patron->id());
382 ($address, $evt) = _update_address($session, $address);
383 return (undef, $evt) if $evt;
385 } elsif( ref($address) and $address->isdeleted() ) {
387 if( $address->id() == $new_patron->mailing_address() ) {
388 $new_patron->clear_mailing_address();
389 ($new_patron, $evt) = _update_patron($session, $new_patron);
390 return (undef, $evt) if $evt;
393 if( $address->id() == $new_patron->billing_address() ) {
394 $new_patron->clear_billing_address();
395 ($new_patron, $evt) = _update_patron($session, $new_patron);
396 return (undef, $evt) if $evt;
399 $evt = _delete_address($session, $address);
400 return (undef, $evt) if $evt;
404 return ( $new_patron, undef );
408 # adds an address to the db and returns the address with new id
410 my($session, $address) = @_;
411 $address->clear_id();
413 $logger->info("Creating new address at street ".$address->street1);
415 # put the address into the database
416 my $id = $session->request(
417 "open-ils.storage.direct.actor.user_address.create", $address )->gather(1);
418 return (undef, $U->DB_UPDATE_FAILED($address)) unless $id;
421 return ($address, undef);
425 sub _update_address {
426 my( $session, $address ) = @_;
427 $logger->info("Updating address ".$address->id." in the DB");
429 my $stat = $session->request(
430 "open-ils.storage.direct.actor.user_address.update", $address )->gather(1);
432 return (undef, $U->DB_UPDATE_FAILED($address)) unless defined($stat);
433 return ($address, undef);
438 sub _add_update_cards {
442 my $new_patron = shift;
446 my $virtual_id; #id of the card before creation
447 for my $card (@{$patron->cards()}) {
449 $card->usr($new_patron->id());
451 if(ref($card) and $card->isnew()) {
453 $virtual_id = $card->id();
454 ( $card, $evt ) = _add_card($session,$card);
455 return (undef, $evt) if $evt;
457 #if(ref($patron->card)) { $patron->card($patron->card->id); }
458 if($patron->card() == $virtual_id) {
459 $new_patron->card($card->id());
460 $new_patron->ischanged(1);
463 } elsif( ref($card) and $card->ischanged() ) {
464 $card->usr($new_patron->id());
465 $evt = _update_card($session, $card);
466 return (undef, $evt) if $evt;
470 return ( $new_patron, undef );
474 # adds an card to the db and returns the card with new id
476 my( $session, $card ) = @_;
478 $logger->info("Adding new patron card ".$card->barcode);
480 my $id = $session->request(
481 "open-ils.storage.direct.actor.card.create", $card )->gather(1);
482 return (undef, $U->DB_UPDATE_FAILED($card)) unless $id;
483 $logger->info("Successfully created patron card $id");
486 return ( $card, undef );
490 # returns event on error. returns undef otherwise
492 my( $session, $card ) = @_;
493 $logger->info("Updating patron card ".$card->id);
495 my $stat = $session->request(
496 "open-ils.storage.direct.actor.card.update", $card )->gather(1);
497 return $U->DB_UPDATE_FAILED($card) unless defined($stat);
504 # returns event on error. returns undef otherwise
505 sub _delete_address {
506 my( $session, $address ) = @_;
507 $logger->info("Deleting address ".$address->id." from DB");
509 my $stat = $session->request(
510 "open-ils.storage.direct.actor.user_address.delete", $address )->gather(1);
512 return $U->DB_UPDATE_FAILED($address) unless defined($stat);
518 sub _add_survey_responses {
519 my ($session, $patron, $new_patron) = @_;
521 $logger->info( "Updating survey responses for patron ".$new_patron->id );
523 my $responses = $patron->survey_responses;
527 $_->usr($new_patron->id) for (@$responses);
529 my $evt = $U->simplereq( "open-ils.circ",
530 "open-ils.circ.survey.submit.user_id", $responses );
532 return (undef, $evt) if defined($U->event_code($evt));
536 return ( $new_patron, undef );
540 sub _create_stat_maps {
542 my($session, $user_session, $patron, $new_patron) = @_;
544 my $maps = $patron->stat_cat_entries();
546 for my $map (@$maps) {
548 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
550 if ($map->isdeleted()) {
551 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.delete";
553 } elsif ($map->isnew()) {
554 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
559 $map->target_usr($new_patron->id);
562 $logger->info("Updating stat entry with method $method and map $map");
564 my $stat = $session->request($method, $map)->gather(1);
565 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
569 return ($new_patron, undef);
572 sub _create_perm_maps {
574 my($session, $user_session, $patron, $new_patron) = @_;
576 my $maps = $patron->permissions;
578 for my $map (@$maps) {
580 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
581 if ($map->isdeleted()) {
582 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
583 } elsif ($map->isnew()) {
584 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
589 $map->usr($new_patron->id);
591 #warn( "Updating permissions with method $method and session $user_session and map $map" );
592 $logger->info( "Updating permissions with method $method and map $map" );
594 my $stat = $session->request($method, $map)->gather(1);
595 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
599 return ($new_patron, undef);
603 sub _create_standing_penalties {
605 my($session, $user_session, $patron, $new_patron) = @_;
607 my $maps = $patron->standing_penalties;
610 for my $map (@$maps) {
612 if ($map->isdeleted()) {
613 $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
614 } elsif ($map->isnew()) {
615 $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
621 $map->usr($new_patron->id);
623 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
625 my $stat = $session->request($method, $map)->gather(1);
626 return (undef, $U->DB_UPDATE_FAILED($map)) unless $stat;
629 return ($new_patron, undef);
634 __PACKAGE__->register_method(
635 method => "search_username",
636 api_name => "open-ils.actor.user.search.username",
639 sub search_username {
640 my($self, $client, $username) = @_;
641 my $users = OpenILS::Application::AppUtils->simple_scalar_request(
643 "open-ils.storage.direct.actor.user.search.usrname.atomic",
651 __PACKAGE__->register_method(
652 method => "user_retrieve_by_barcode",
653 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
655 sub user_retrieve_by_barcode {
656 my($self, $client, $user_session, $barcode) = @_;
658 $logger->debug("Searching for user with barcode $barcode");
659 my ($user_obj, $evt) = $apputils->checkses($user_session);
662 my $session = OpenSRF::AppSession->create("open-ils.storage");
664 # find the card with the given barcode
665 my $creq = $session->request(
666 "open-ils.storage.direct.actor.card.search.barcode.atomic",
668 my $card = $creq->gather(1);
670 if(!$card || !$card->[0]) {
671 $session->disconnect();
672 return OpenILS::Event->new( 'USER_NOT_FOUND' );
676 my $user = flesh_user($card->usr(), $session);
677 $session->disconnect();
678 if(!$user) { return OpenILS::Event->new( 'USER_NOT_FOUND' ); }
685 __PACKAGE__->register_method(
686 method => "get_user_by_id",
687 api_name => "open-ils.actor.user.retrieve",);
690 my ($self, $client, $user_session, $id) = @_;
692 my $user_obj = $apputils->check_user_session( $user_session );
694 return $apputils->simple_scalar_request(
696 "open-ils.storage.direct.actor.user.retrieve",
702 __PACKAGE__->register_method(
703 method => "get_org_types",
704 api_name => "open-ils.actor.org_types.retrieve",);
708 my($self, $client) = @_;
710 return $org_types if $org_types;
712 $apputils->simple_scalar_request(
714 "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
719 __PACKAGE__->register_method(
720 method => "get_user_profiles",
721 api_name => "open-ils.actor.user.profiles.retrieve",
725 sub get_user_profiles {
726 return $user_profiles if $user_profiles;
728 return $user_profiles =
729 $apputils->simple_scalar_request(
731 "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
736 __PACKAGE__->register_method(
737 method => "get_user_ident_types",
738 api_name => "open-ils.actor.user.ident_types.retrieve",
741 sub get_user_ident_types {
742 return $ident_types if $ident_types;
743 return $ident_types =
744 $apputils->simple_scalar_request(
746 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
752 __PACKAGE__->register_method(
753 method => "get_org_unit",
754 api_name => "open-ils.actor.org_unit.retrieve",
759 my( $self, $client, $user_session, $org_id ) = @_;
761 if(defined($user_session) && !defined($org_id)) {
763 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
764 if(!defined($org_id)) {
765 $org_id = $user_obj->home_ou;
770 my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
772 "open-ils.storage.direct.actor.org_unit.retrieve",
781 __PACKAGE__->register_method(
782 method => "get_org_tree",
783 api_name => "open-ils.actor.org_tree.retrieve",
785 note => "Returns the entire org tree structure",
789 my( $self, $client) = @_;
792 $cache_client = OpenSRF::Utils::Cache->new("global", 0);
794 # see if it's in the cache
795 #warn "Getting ORG Tree\n";
796 my $tree = $cache_client->get_cache('orgtree');
798 #warn "Found orgtree in cache. returning...\n";
802 my $orglist = $apputils->simple_scalar_request(
804 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
807 #warn "found org list\n";
810 $tree = $self->build_org_tree($orglist);
811 $cache_client->put_cache('orgtree', $tree);
817 # turns an org list into an org tree
820 my( $self, $orglist) = @_;
822 return $orglist unless (
823 ref($orglist) and @$orglist > 1 );
826 $a->ou_type <=> $b->ou_type ||
827 $a->name cmp $b->name } @$orglist;
829 for my $org (@list) {
831 next unless ($org and defined($org->parent_ou));
832 my ($parent) = grep { $_->id == $org->parent_ou } @list;
835 $parent->children([]) unless defined($parent->children);
836 push( @{$parent->children}, $org );
844 __PACKAGE__->register_method(
845 method => "get_org_descendants",
846 api_name => "open-ils.actor.org_tree.descendants.retrieve"
849 # depth is optional. org_unit is the id
850 sub get_org_descendants {
851 my( $self, $client, $org_unit, $depth ) = @_;
852 my $orglist = $apputils->simple_scalar_request(
854 "open-ils.storage.actor.org_unit.descendants.atomic",
856 return $self->build_org_tree($orglist);
860 __PACKAGE__->register_method(
861 method => "get_org_ancestors",
862 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
865 # depth is optional. org_unit is the id
866 sub get_org_ancestors {
867 my( $self, $client, $org_unit, $depth ) = @_;
868 my $orglist = $apputils->simple_scalar_request(
870 "open-ils.storage.actor.org_unit.ancestors.atomic",
872 return $self->build_org_tree($orglist);
876 __PACKAGE__->register_method(
877 method => "get_standings",
878 api_name => "open-ils.actor.standings.retrieve"
883 return $user_standings if $user_standings;
884 return $user_standings =
885 $apputils->simple_scalar_request(
887 "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
892 __PACKAGE__->register_method(
893 method => "get_my_org_path",
894 api_name => "open-ils.actor.org_unit.full_path.retrieve"
897 sub get_my_org_path {
898 my( $self, $client, $user_session, $org_id ) = @_;
899 my $user_obj = $apputils->check_user_session($user_session);
900 if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
902 return $apputils->simple_scalar_request(
904 "open-ils.storage.actor.org_unit.full_path.atomic",
909 __PACKAGE__->register_method(
910 method => "patron_adv_search",
911 api_name => "open-ils.actor.patron.search.advanced" );
913 sub patron_adv_search {
914 my( $self, $client, $staff_login, $search_hash ) = @_;
916 #warn "patron adv with $staff_login and search " .
917 #Dumper($search_hash) . "\n";
919 my $session = OpenSRF::AppSession->create("open-ils.storage");
920 my $req = $session->request(
921 "open-ils.storage.actor.user.crazy_search", $search_hash);
923 my $ans = $req->gather(1);
925 my %hash = map { ($_ =>1) } @$ans;
926 $ans = [ keys %hash ];
928 #warn "Returning @$ans\n";
930 $session->disconnect();
937 sub _verify_password {
938 my($user_session, $password) = @_;
939 my $user_obj = $apputils->check_user_session($user_session);
941 #grab the user with password
942 $user_obj = $apputils->simple_scalar_request(
944 "open-ils.storage.direct.actor.user.retrieve",
947 if($user_obj->passwd eq $password) {
955 __PACKAGE__->register_method(
956 method => "update_password",
957 api_name => "open-ils.actor.user.password.update");
959 __PACKAGE__->register_method(
960 method => "update_password",
961 api_name => "open-ils.actor.user.username.update");
963 __PACKAGE__->register_method(
964 method => "update_password",
965 api_name => "open-ils.actor.user.email.update");
967 sub update_password {
968 my( $self, $client, $user_session, $new_value, $current_password ) = @_;
972 #warn "Updating user with method " .$self->api_name . "\n";
973 my $user_obj = $apputils->check_user_session($user_session);
975 if($self->api_name =~ /password/) {
977 #make sure they know the current password
978 if(!_verify_password($user_session, md5_hex($current_password))) {
979 return OpenILS::EX->new("USER_WRONG_PASSWORD")->ex;
982 $user_obj->passwd($new_value);
984 elsif($self->api_name =~ /username/) {
985 my $users = search_username(undef, undef, $new_value);
986 if( $users and $users->[0] ) {
987 return OpenILS::Event->new('USERNAME_EXISTS');
989 $user_obj->usrname($new_value);
992 elsif($self->api_name =~ /email/) {
993 #warn "Updating email to $new_value\n";
994 $user_obj->email($new_value);
997 my $session = $apputils->start_db_session();
999 ( $user_obj, $evt ) = _update_patron($session, $user_obj, $user_obj);
1000 return $evt if $evt;
1002 $apputils->commit_db_session($session);
1004 if($user_obj) { return 1; }
1009 __PACKAGE__->register_method(
1010 method => "check_user_perms",
1011 api_name => "open-ils.actor.user.perm.check",
1012 notes => <<" NOTES");
1013 Takes a login session, user id, an org id, and an array of perm type strings. For each
1014 perm type, if the user does *not* have the given permission it is added
1015 to a list which is returned from the method. If all permissions
1016 are allowed, an empty list is returned
1017 if the logged in user does not match 'user_id', then the logged in user must
1018 have VIEW_PERMISSION priveleges.
1021 sub check_user_perms {
1022 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1024 my( $staff, $evt ) = $apputils->checkses($login_session);
1025 return $evt if $evt;
1027 if($staff->id ne $user_id) {
1028 if( my $evt = $apputils->check_perms(
1029 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1035 for my $perm (@$perm_types) {
1036 if($apputils->check_perms($user_id, $org_id, $perm)) {
1037 push @not_allowed, $perm;
1041 return \@not_allowed
1044 __PACKAGE__->register_method(
1045 method => "check_user_perms2",
1046 api_name => "open-ils.actor.user.perm.check.multi_org",
1048 Checks the permissions on a list of perms and orgs for a user
1049 @param authtoken The login session key
1050 @param user_id The id of the user to check
1051 @param orgs The array of org ids
1052 @param perms The array of permission names
1053 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1054 if the logged in user does not match 'user_id', then the logged in user must
1055 have VIEW_PERMISSION priveleges.
1058 sub check_user_perms2 {
1059 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1061 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1062 $authtoken, $user_id, 'VIEW_PERMISSION' );
1063 return $evt if $evt;
1066 for my $org (@$orgs) {
1067 for my $perm (@$perms) {
1068 if($apputils->check_perms($user_id, $org, $perm)) {
1069 push @not_allowed, [ $org, $perm ];
1074 return \@not_allowed
1078 __PACKAGE__->register_method(
1079 method => 'check_user_perms3',
1080 api_name => 'open-ils.actor.user.perm.highest_org',
1082 Returns the highest org unit id at which a user has a given permission
1083 If the requestor does not match the target user, the requestor must have
1084 'VIEW_PERMISSION' rights at the home org unit of the target user
1085 @param authtoken The login session key
1086 @param userid The id of the user in question
1087 @param perm The permission to check
1088 @return The org unit highest in the org tree within which the user has
1089 the requested permission
1092 sub check_user_perms3 {
1093 my( $self, $client, $authtoken, $userid, $perm ) = @_;
1095 my( $staff, $target, $org, $evt );
1097 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1098 $authtoken, $userid, 'VIEW_PERMISSION' );
1099 return $evt if $evt;
1101 my $tree = $self->get_org_tree();
1102 return _find_highest_perm_org( $perm, $userid, $target->home_ou, $tree );
1106 sub _find_highest_perm_org {
1107 my ( $perm, $userid, $start_org, $org_tree ) = @_;
1108 my $org = $apputils->find_org($org_tree, $start_org );
1112 last if ($apputils->check_perms( $userid, $org->id, $perm )); # perm failed
1114 $org = $apputils->find_org( $org_tree, $org->parent_ou() );
1120 __PACKAGE__->register_method(
1121 method => 'check_user_perms4',
1122 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1124 Returns the highest org unit id at which a user has a given permission
1125 If the requestor does not match the target user, the requestor must have
1126 'VIEW_PERMISSION' rights at the home org unit of the target user
1127 @param authtoken The login session key
1128 @param userid The id of the user in question
1129 @param perms An array of perm names to check
1130 @return An array of orgId's representing the org unit
1131 highest in the org tree within which the user has the requested permission
1132 The arrah of orgId's has matches the order of the perms array
1135 sub check_user_perms4 {
1136 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1138 my( $staff, $target, $org, $evt );
1140 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1141 $authtoken, $userid, 'VIEW_PERMISSION' );
1142 return $evt if $evt;
1145 return [] unless ref($perms);
1146 my $tree = $self->get_org_tree();
1148 for my $p (@$perms) {
1149 push( @arr, _find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1157 __PACKAGE__->register_method(
1158 method => "user_fines_summary",
1159 api_name => "open-ils.actor.user.fines.summary",
1160 notes => <<" NOTES");
1161 Returns a short summary of the users total open fines, excluding voided fines
1162 Params are login_session, user_id
1163 Returns a 'mous' object.
1166 sub user_fines_summary {
1167 my( $self, $client, $login_session, $user_id ) = @_;
1169 my $user_obj = $apputils->check_user_session($login_session);
1170 if($user_obj->id ne $user_id) {
1171 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_FINES_SUMMARY")) {
1172 return OpenILS::Perm->new("VIEW_USER_FINES_SUMMARY");
1176 return $apputils->simple_scalar_request(
1178 "open-ils.storage.direct.money.open_user_summary.search.usr",
1186 __PACKAGE__->register_method(
1187 method => "user_transactions",
1188 api_name => "open-ils.actor.user.transactions",
1189 notes => <<" NOTES");
1190 Returns a list of open user transactions (mbts objects);
1191 Params are login_session, user_id
1192 Optional third parameter is the transactions type. defaults to all
1195 __PACKAGE__->register_method(
1196 method => "user_transactions",
1197 api_name => "open-ils.actor.user.transactions.have_charge",
1198 notes => <<" NOTES");
1199 Returns a list of all open user transactions (mbts objects) that have an initial charge
1200 Params are login_session, user_id
1201 Optional third parameter is the transactions type. defaults to all
1204 __PACKAGE__->register_method(
1205 method => "user_transactions",
1206 api_name => "open-ils.actor.user.transactions.have_balance",
1207 notes => <<" NOTES");
1208 Returns a list of all open user transactions (mbts objects) that have a balance
1209 Params are login_session, user_id
1210 Optional third parameter is the transactions type. defaults to all
1213 __PACKAGE__->register_method(
1214 method => "user_transactions",
1215 api_name => "open-ils.actor.user.transactions.fleshed",
1216 notes => <<" NOTES");
1217 Returns an object/hash of transaction, circ, title where transaction = an open
1218 user transactions (mbts objects), circ is the attached circluation, and title
1219 is the title the circ points to
1220 Params are login_session, user_id
1221 Optional third parameter is the transactions type. defaults to all
1224 __PACKAGE__->register_method(
1225 method => "user_transactions",
1226 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1227 notes => <<" NOTES");
1228 Returns an object/hash of transaction, circ, title where transaction = an open
1229 user transactions that has an initial charge (mbts objects), circ is the
1230 attached circluation, and title is the title the circ points to
1231 Params are login_session, user_id
1232 Optional third parameter is the transactions type. defaults to all
1235 __PACKAGE__->register_method(
1236 method => "user_transactions",
1237 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1238 notes => <<" NOTES");
1239 Returns an object/hash of transaction, circ, title where transaction = an open
1240 user transaction that has a balance (mbts objects), circ is the attached
1241 circluation, and title is the title the circ points to
1242 Params are login_session, user_id
1243 Optional third parameter is the transaction type. defaults to all
1248 sub user_transactions {
1249 my( $self, $client, $login_session, $user_id, $type ) = @_;
1251 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1252 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1253 return $evt if $evt;
1255 my $api = $self->api_name();
1259 if(defined($type)) { @xact = (xact_type => $type);
1261 } else { @xact = (); }
1263 if($api =~ /have_charge/) {
1265 $trans = $apputils->simple_scalar_request(
1267 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1268 { usr => $user_id, total_owed => { ">" => 0 }, @xact });
1270 } elsif($api =~ /have_balance/) {
1272 $trans = $apputils->simple_scalar_request(
1274 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1275 { usr => $user_id, balance_owed => { ">" => 0 }, @xact });
1279 $trans = $apputils->simple_scalar_request(
1281 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1282 { usr => $user_id, @xact });
1285 if($api !~ /fleshed/) { return $trans; }
1287 #warn "API: $api\n";
1290 for my $t (@$trans) {
1292 #warn $t->id . "\n";
1295 if( $t->xact_type ne 'circulation' ) {
1296 push @resp, {transaction => $t};
1300 my $circ = $apputils->simple_scalar_request(
1302 "open-ils.storage.direct.action.circulation.retrieve",
1307 my $title = $apputils->simple_scalar_request(
1309 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1310 $circ->target_copy );
1314 my $u = OpenILS::Utils::ModsParser->new();
1315 $u->start_mods_batch($title->marc());
1316 my $mods = $u->finish_mods_batch();
1318 push @resp, {transaction => $t, circ => $circ, record => $mods };
1328 __PACKAGE__->register_method(
1329 method => "user_perms",
1330 api_name => "open-ils.actor.permissions.user_perms.retrieve",
1332 notes => <<" NOTES");
1333 Returns a list of permissions
1336 my( $self, $client, $authtoken, $user ) = @_;
1338 my( $staff, $evt ) = $apputils->checkses($authtoken);
1339 return $evt if $evt;
1341 $user ||= $staff->id;
1343 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
1347 return $apputils->simple_scalar_request(
1349 "open-ils.storage.permission.user_perms.atomic",
1353 __PACKAGE__->register_method(
1354 method => "retrieve_perms",
1355 api_name => "open-ils.actor.permissions.retrieve",
1356 notes => <<" NOTES");
1357 Returns a list of permissions
1359 sub retrieve_perms {
1360 my( $self, $client ) = @_;
1361 return $apputils->simple_scalar_request(
1363 "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
1366 __PACKAGE__->register_method(
1367 method => "retrieve_groups",
1368 api_name => "open-ils.actor.groups.retrieve",
1369 notes => <<" NOTES");
1370 Returns a list of user groupss
1372 sub retrieve_groups {
1373 my( $self, $client ) = @_;
1374 return $apputils->simple_scalar_request(
1376 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1379 __PACKAGE__->register_method(
1380 method => "retrieve_groups_tree",
1381 api_name => "open-ils.actor.groups.tree.retrieve",
1382 notes => <<" NOTES");
1383 Returns a list of user groups
1385 sub retrieve_groups_tree {
1386 my( $self, $client ) = @_;
1387 my $groups = $apputils->simple_scalar_request(
1389 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1390 return $self->build_group_tree($groups);
1394 # turns an org list into an org tree
1395 sub build_group_tree {
1397 my( $self, $grplist) = @_;
1399 return $grplist unless (
1400 ref($grplist) and @$grplist > 1 );
1402 my @list = sort { $a->name cmp $b->name } @$grplist;
1405 for my $grp (@list) {
1407 if ($grp and !defined($grp->parent)) {
1411 my ($parent) = grep { $_->id == $grp->parent} @list;
1413 $parent->children([]) unless defined($parent->children);
1414 push( @{$parent->children}, $grp );
1422 __PACKAGE__->register_method(
1423 method => "add_user_to_groups",
1424 api_name => "open-ils.actor.user.set_groups",
1425 notes => <<" NOTES");
1426 Adds a user to one or more permission groups
1429 sub add_user_to_groups {
1430 my( $self, $client, $authtoken, $userid, $groups ) = @_;
1432 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1433 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
1434 return $evt if $evt;
1436 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1437 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
1438 return $evt if $evt;
1440 $apputils->simplereq(
1442 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
1444 for my $group (@$groups) {
1445 my $link = Fieldmapper::permission::usr_grp_map->new;
1447 $link->usr($userid);
1449 my $id = $apputils->simplereq(
1451 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
1457 __PACKAGE__->register_method(
1458 method => "get_user_perm_groups",
1459 api_name => "open-ils.actor.user.get_groups",
1460 notes => <<" NOTES");
1461 Retrieve a user's permission groups.
1465 sub get_user_perm_groups {
1466 my( $self, $client, $authtoken, $userid ) = @_;
1468 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1469 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
1470 return $evt if $evt;
1472 return $apputils->simplereq(
1474 'open-ils.storage.direct.permission.usr_grp_map.search.usr.atomic', $userid );