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);
13 use OpenILS::Application::AppUtils;
15 use OpenILS::Utils::Fieldmapper;
16 use OpenILS::Utils::ModsParser;
17 use OpenSRF::Utils::Logger qw/$logger/;
18 use OpenSRF::Utils qw/:datetime/;
20 use OpenSRF::Utils::Cache;
24 use DateTime::Format::ISO8601;
25 use OpenILS::Const qw/:const/;
27 use OpenILS::Application::Actor::Container;
28 use OpenILS::Application::Actor::ClosedDates;
30 use OpenILS::Utils::CStoreEditor qw/:funcs/;
32 use OpenILS::Application::Actor::UserGroups;
34 OpenILS::Application::Actor::Container->initialize();
35 OpenILS::Application::Actor::UserGroups->initialize();
36 OpenILS::Application::Actor::ClosedDates->initialize();
39 my $apputils = "OpenILS::Application::AppUtils";
42 sub _d { warn "Patron:\n" . Dumper(shift()); }
47 my $set_user_settings;
50 __PACKAGE__->register_method(
51 method => "set_user_settings",
52 api_name => "open-ils.actor.patron.settings.update",
54 sub set_user_settings {
55 my( $self, $client, $user_session, $uid, $settings ) = @_;
57 $logger->debug("Setting user settings: $user_session, $uid, " . Dumper($settings));
59 my( $staff, $user, $evt ) =
60 $apputils->checkses_requestor( $user_session, $uid, 'UPDATE_USER' );
64 [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
66 $_->[1]->{value} = JSON->perl2JSON($_->[1]->{value}) for @params;
68 $logger->activity("User " . $staff->id . " updating user $uid settings with: " . Dumper(\@params));
70 my $ses = $U->start_db_session();
71 my $stat = $ses->request(
72 'open-ils.storage.direct.actor.user_setting.batch.merge', @params )->gather(1);
73 $U->commit_db_session($ses);
80 __PACKAGE__->register_method(
81 method => "set_ou_settings",
82 api_name => "open-ils.actor.org_unit.settings.update",
85 my( $self, $client, $user_session, $ouid, $settings ) = @_;
87 my( $staff, $evt ) = $apputils->checkses( $user_session );
89 $evt = $apputils->check_perms( $staff->id, $ouid, 'UPDATE_ORG_SETTING' );
93 for my $set (keys %$settings) {
95 my $json = JSON->perl2JSON($$settings{$set});
96 $logger->activity("updating org_unit.setting: $ouid : $set : $json");
99 { org_unit => $ouid, name => $set },
100 { value => $json } );
103 my $ses = $U->start_db_session();
104 my $stat = $ses->request(
105 'open-ils.storage.direct.actor.org_unit_setting.merge', @params )->gather(1);
106 $U->commit_db_session($ses);
112 my $fetch_user_settings;
113 my $fetch_ou_settings;
115 __PACKAGE__->register_method(
116 method => "user_settings",
117 api_name => "open-ils.actor.patron.settings.retrieve",
120 my( $self, $client, $user_session, $uid, $setting ) = @_;
122 my( $staff, $user, $evt ) =
123 $apputils->checkses_requestor( $user_session, $uid, 'VIEW_USER' );
126 $logger->debug("User " . $staff->id . " fetching user $uid\n");
127 my $s = $apputils->simplereq(
129 'open-ils.cstore.direct.actor.user_setting.search.atomic', { usr => $uid } );
131 my $settings = { map { ( $_->name => JSON->JSON2perl($_->value) ) } @$s };
133 return $$settings{$setting} if $setting;
139 __PACKAGE__->register_method(
140 method => "ou_settings",
141 api_name => "open-ils.actor.org_unit.settings.retrieve",
144 my( $self, $client, $ouid ) = @_;
146 $logger->info("Fetching org unit settings for org $ouid");
148 my $s = $apputils->simplereq(
150 'open-ils.cstore.direct.actor.org_unit_setting.search.atomic', {org_unit => $ouid});
152 return { map { ( $_->name => JSON->JSON2perl($_->value) ) } @$s };
157 __PACKAGE__->register_method(
158 api_name => 'open-ils.actor.ou_setting.ancestor_default',
159 method => 'ou_ancestor_setting',
162 # ------------------------------------------------------------------
163 # Attempts to find the org setting value for a given org. if not
164 # found at the requested org, searches up the org tree until it
165 # finds a parent that has the requested setting.
166 # when found, returns { org => $id, value => $value }
167 # otherwise, returns NULL
168 # ------------------------------------------------------------------
169 sub ou_ancestor_setting {
170 my( $self, $client, $orgid, $name ) = @_;
171 my $e = new_editor();
174 my $setting = $e->search_actor_org_unit_setting({org_unit=>$orgid, name=>$name})->[0];
177 $logger->info("found org_setting $name at org $orgid : " . $setting->value);
178 return { org => $orgid, value => JSON->JSON2perl($setting->value) };
181 my $org = $e->retrieve_actor_org_unit($orgid) or return $e->event;
182 $orgid = $org->parent_ou or return undef;
192 __PACKAGE__->register_method (
193 method => "ou_setting_delete",
194 api_name => 'open-ils.actor.org_setting.delete',
196 Deletes a specific org unit setting for a specific location
197 @param authtoken The login session key
198 @param orgid The org unit whose setting we're changing
199 @param setting The name of the setting to delete
200 @return True value on success.
204 sub ou_setting_delete {
205 my( $self, $conn, $authtoken, $orgid, $setting ) = @_;
206 my( $reqr, $evt) = $U->checkses($authtoken);
208 $evt = $U->check_perms($reqr->id, $orgid, 'UPDATE_ORG_SETTING');
211 my $id = $U->cstorereq(
212 'open-ils.cstore.direct.actor.org_unit_setting.id_list',
213 { name => $setting, org_unit => $orgid } );
215 $logger->debug("Retrieved setting $id in org unit setting delete");
217 my $s = $U->cstorereq(
218 'open-ils.cstore.direct.actor.org_unit_setting.delete', $id );
220 $logger->activity("User ".$reqr->id." deleted org unit setting $id") if $s;
226 __PACKAGE__->register_method(
227 method => "update_patron",
228 api_name => "open-ils.actor.patron.update",);
231 my( $self, $client, $user_session, $patron ) = @_;
233 my $session = $apputils->start_db_session();
237 $logger->info("Creating new patron...") if $patron->isnew;
238 $logger->info("Updating Patron: " . $patron->id) unless $patron->isnew;
240 my( $user_obj, $evt ) = $U->checkses($user_session);
243 $evt = check_group_perm($session, $user_obj, $patron);
247 # XXX does this user have permission to add/create users. Granularity?
248 # $new_patron is the patron in progress. $patron is the original patron
249 # passed in with the method. new_patron will change as the components
250 # of patron are added/updated.
254 # unflesh the real items on the patron
255 $patron->card( $patron->card->id ) if(ref($patron->card));
256 $patron->billing_address( $patron->billing_address->id )
257 if(ref($patron->billing_address));
258 $patron->mailing_address( $patron->mailing_address->id )
259 if(ref($patron->mailing_address));
261 # create/update the patron first so we can use his id
262 if($patron->isnew()) {
263 ( $new_patron, $evt ) = _add_patron($session, _clone_patron($patron), $user_obj);
265 } else { $new_patron = $patron; }
267 ( $new_patron, $evt ) = _add_update_addresses($session, $patron, $new_patron, $user_obj);
270 ( $new_patron, $evt ) = _add_update_cards($session, $patron, $new_patron, $user_obj);
273 ( $new_patron, $evt ) = _add_survey_responses($session, $patron, $new_patron, $user_obj);
276 # re-update the patron if anything has happened to him during this process
277 if($new_patron->ischanged()) {
278 ( $new_patron, $evt ) = _update_patron($session, $new_patron, $user_obj);
282 ($new_patron, $evt) = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
285 ($new_patron, $evt) = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
288 ($new_patron, $evt) = _create_standing_penalties($session, $user_session, $patron, $new_patron, $user_obj);
291 $logger->activity("user ".$user_obj->id." updating/creating user ".$new_patron->id);
294 if(!$patron->isnew) {
295 $opatron = new_editor()->retrieve_actor_user($new_patron->id);
298 $apputils->commit_db_session($session);
299 my $fuser = flesh_user($new_patron->id());
302 # Log the new and old patron for investigation
303 $logger->info("$user_session updating patron object. orig patron object = ".
304 JSON->perl2JSON($opatron). " |||| new patron = ".JSON->perl2JSON($fuser));
314 return new_flesh_user($id, [
317 "standing_penalties",
321 "stat_cat_entries" ] );
329 # clone and clear stuff that would break the database
333 my $new_patron = $patron->clone;
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 $new_patron->clear_permissions();
346 $new_patron->clear_standing_penalties();
356 my $user_obj = shift;
358 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'CREATE_USER');
359 return (undef, $evt) if $evt;
361 my $ex = $session->request(
362 'open-ils.storage.direct.actor.user.search.usrname', $patron->usrname())->gather(1);
364 return (undef, OpenILS::Event->new('USERNAME_EXISTS'));
367 $logger->info("Creating new user in the DB with username: ".$patron->usrname());
369 my $id = $session->request(
370 "open-ils.storage.direct.actor.user.create", $patron)->gather(1);
371 return (undef, $U->DB_UPDATE_FAILED($patron)) unless $id;
373 $logger->info("Successfully created new user [$id] in DB");
375 return ( $session->request(
376 "open-ils.storage.direct.actor.user.retrieve", $id)->gather(1), undef );
380 sub check_group_perm {
381 my( $session, $requestor, $patron ) = @_;
384 # first let's see if the requestor has
385 # priveleges to update this user in any way
386 if( ! $patron->isnew ) {
387 my $p = $session->request(
388 'open-ils.storage.direct.actor.user.retrieve', $patron->id )->gather(1);
390 # If we are the requestor (trying to update our own account)
391 # and we are not trying to change our profile, we're good
392 if( $p->id == $requestor->id and
393 $p->profile == $patron->profile ) {
398 $evt = group_perm_failed($session, $requestor, $p);
402 # They are allowed to edit this patron.. can they put the
403 # patron into the group requested?
404 $evt = group_perm_failed($session, $requestor, $patron);
410 sub group_perm_failed {
411 my( $session, $requestor, $patron ) = @_;
415 my $grpid = $patron->profile;
419 $logger->debug("user update looking for group perm for group $grpid");
420 $grp = $session->request(
421 'open-ils.storage.direct.permission.grp_tree.retrieve', $grpid )->gather(1);
422 return OpenILS::Event->new('PERMISSION_GRP_TREE_NOT_FOUND') unless $grp;
424 } while( !($perm = $grp->application_perm) and ($grpid = $grp->parent) );
426 $logger->info("user update checking perm $perm on user ".
427 $requestor->id." for update/create on user username=".$patron->usrname);
429 my $evt = $U->check_perms($requestor->id, $patron->home_ou, $perm);
437 my( $session, $patron, $user_obj, $noperm) = @_;
439 $logger->info("Updating patron ".$patron->id." in DB");
444 $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'UPDATE_USER');
445 return (undef, $evt) if $evt;
448 # update the password by itself to avoid the password protection magic
449 if( $patron->passwd ) {
450 my $s = $session->request(
451 'open-ils.storage.direct.actor.user.remote_update',
452 {id => $patron->id}, {passwd => $patron->passwd})->gather(1);
453 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($s);
454 $patron->clear_passwd;
457 if(!$patron->ident_type) {
458 $patron->clear_ident_type;
459 $patron->clear_ident_value;
462 my $stat = $session->request(
463 "open-ils.storage.direct.actor.user.update",$patron )->gather(1);
464 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($stat);
469 sub _check_dup_ident {
470 my( $session, $patron ) = @_;
472 return undef unless $patron->ident_value;
475 ident_type => $patron->ident_type,
476 ident_value => $patron->ident_value,
479 $logger->debug("patron update searching for dup ident values: " .
480 $patron->ident_type . ':' . $patron->ident_value);
482 $search->{id} = {'!=' => $patron->id} if $patron->id and $patron->id > 0;
484 my $dups = $session->request(
485 'open-ils.storage.direct.actor.user.search_where.atomic', $search )->gather(1);
488 return OpenILS::Event->new('PATRON_DUP_IDENT1', payload => $patron )
495 sub _add_update_addresses {
499 my $new_patron = shift;
503 my $current_id; # id of the address before creation
505 for my $address (@{$patron->addresses()}) {
507 next unless ref $address;
508 $current_id = $address->id();
510 if( $patron->billing_address() and
511 $patron->billing_address() == $current_id ) {
512 $logger->info("setting billing addr to $current_id");
513 $new_patron->billing_address($address->id());
514 $new_patron->ischanged(1);
517 if( $patron->mailing_address() and
518 $patron->mailing_address() == $current_id ) {
519 $new_patron->mailing_address($address->id());
520 $logger->info("setting mailing addr to $current_id");
521 $new_patron->ischanged(1);
525 if($address->isnew()) {
527 $address->usr($new_patron->id());
529 ($address, $evt) = _add_address($session,$address);
530 return (undef, $evt) if $evt;
532 # we need to get the new id
533 if( $patron->billing_address() and
534 $patron->billing_address() == $current_id ) {
535 $new_patron->billing_address($address->id());
536 $logger->info("setting billing addr to $current_id");
537 $new_patron->ischanged(1);
540 if( $patron->mailing_address() and
541 $patron->mailing_address() == $current_id ) {
542 $new_patron->mailing_address($address->id());
543 $logger->info("setting mailing addr to $current_id");
544 $new_patron->ischanged(1);
547 } elsif($address->ischanged() ) {
549 ($address, $evt) = _update_address($session, $address);
550 return (undef, $evt) if $evt;
552 } elsif($address->isdeleted() ) {
554 if( $address->id() == $new_patron->mailing_address() ) {
555 $new_patron->clear_mailing_address();
556 ($new_patron, $evt) = _update_patron($session, $new_patron);
557 return (undef, $evt) if $evt;
560 if( $address->id() == $new_patron->billing_address() ) {
561 $new_patron->clear_billing_address();
562 ($new_patron, $evt) = _update_patron($session, $new_patron);
563 return (undef, $evt) if $evt;
566 $evt = _delete_address($session, $address);
567 return (undef, $evt) if $evt;
571 return ( $new_patron, undef );
575 # adds an address to the db and returns the address with new id
577 my($session, $address) = @_;
578 $address->clear_id();
580 $logger->info("Creating new address at street ".$address->street1);
582 # put the address into the database
583 my $id = $session->request(
584 "open-ils.storage.direct.actor.user_address.create", $address )->gather(1);
585 return (undef, $U->DB_UPDATE_FAILED($address)) unless $id;
588 return ($address, undef);
592 sub _update_address {
593 my( $session, $address ) = @_;
595 $logger->info("Updating address ".$address->id." in the DB");
597 my $stat = $session->request(
598 "open-ils.storage.direct.actor.user_address.update", $address )->gather(1);
600 return (undef, $U->DB_UPDATE_FAILED($address)) unless defined($stat);
601 return ($address, undef);
606 sub _add_update_cards {
610 my $new_patron = shift;
614 my $virtual_id; #id of the card before creation
615 for my $card (@{$patron->cards()}) {
617 $card->usr($new_patron->id());
619 if(ref($card) and $card->isnew()) {
621 $virtual_id = $card->id();
622 ( $card, $evt ) = _add_card($session,$card);
623 return (undef, $evt) if $evt;
625 #if(ref($patron->card)) { $patron->card($patron->card->id); }
626 if($patron->card() == $virtual_id) {
627 $new_patron->card($card->id());
628 $new_patron->ischanged(1);
631 } elsif( ref($card) and $card->ischanged() ) {
632 $evt = _update_card($session, $card);
633 return (undef, $evt) if $evt;
637 return ( $new_patron, undef );
641 # adds an card to the db and returns the card with new id
643 my( $session, $card ) = @_;
646 $logger->info("Adding new patron card ".$card->barcode);
648 my $id = $session->request(
649 "open-ils.storage.direct.actor.card.create", $card )->gather(1);
650 return (undef, $U->DB_UPDATE_FAILED($card)) unless $id;
651 $logger->info("Successfully created patron card $id");
654 return ( $card, undef );
658 # returns event on error. returns undef otherwise
660 my( $session, $card ) = @_;
661 $logger->info("Updating patron card ".$card->id);
663 my $stat = $session->request(
664 "open-ils.storage.direct.actor.card.update", $card )->gather(1);
665 return $U->DB_UPDATE_FAILED($card) unless defined($stat);
672 # returns event on error. returns undef otherwise
673 sub _delete_address {
674 my( $session, $address ) = @_;
676 $logger->info("Deleting address ".$address->id." from DB");
678 my $stat = $session->request(
679 "open-ils.storage.direct.actor.user_address.delete", $address )->gather(1);
681 return $U->DB_UPDATE_FAILED($address) unless defined($stat);
687 sub _add_survey_responses {
688 my ($session, $patron, $new_patron) = @_;
690 $logger->info( "Updating survey responses for patron ".$new_patron->id );
692 my $responses = $patron->survey_responses;
696 $_->usr($new_patron->id) for (@$responses);
698 my $evt = $U->simplereq( "open-ils.circ",
699 "open-ils.circ.survey.submit.user_id", $responses );
701 return (undef, $evt) if defined($U->event_code($evt));
705 return ( $new_patron, undef );
709 sub _create_stat_maps {
711 my($session, $user_session, $patron, $new_patron) = @_;
713 my $maps = $patron->stat_cat_entries();
715 for my $map (@$maps) {
717 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
719 if ($map->isdeleted()) {
720 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.delete";
722 } elsif ($map->isnew()) {
723 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
728 $map->target_usr($new_patron->id);
731 $logger->info("Updating stat entry with method $method and map $map");
733 my $stat = $session->request($method, $map)->gather(1);
734 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
738 return ($new_patron, undef);
741 sub _create_perm_maps {
743 my($session, $user_session, $patron, $new_patron) = @_;
745 my $maps = $patron->permissions;
747 for my $map (@$maps) {
749 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
750 if ($map->isdeleted()) {
751 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
752 } elsif ($map->isnew()) {
753 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
758 $map->usr($new_patron->id);
760 #warn( "Updating permissions with method $method and session $user_session and map $map" );
761 $logger->info( "Updating permissions with method $method and map $map" );
763 my $stat = $session->request($method, $map)->gather(1);
764 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
768 return ($new_patron, undef);
772 __PACKAGE__->register_method(
773 method => "set_user_perms",
774 api_name => "open-ils.actor.user.permissions.update",
783 my $session = $apputils->start_db_session();
785 my( $user_obj, $evt ) = $U->checkses($ses);
788 my $perms = $session->request('open-ils.storage.permission.user_perms.atomic', $user_obj->id)->gather(1);
791 $all = 1 if ($user_obj->super_user());
792 $all = 1 unless ($U->check_perms($user_obj->id, $user_obj->home_ou, 'EVERYTHING'));
794 for my $map (@$maps) {
796 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
797 if ($map->isdeleted()) {
798 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
799 } elsif ($map->isnew()) {
800 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
804 next if (!$all || !grep { $_->perm eq $map->perm and $_->grantable == 1 and $_->depth <= $map->depth } @$perms);
806 #warn( "Updating permissions with method $method and session $ses and map $map" );
807 $logger->info( "Updating permissions with method $method and map $map" );
809 my $stat = $session->request($method, $map)->gather(1);
810 $logger->warn( "update failed: ".$U->DB_UPDATE_FAILED($map) ) unless defined($stat);
814 $apputils->commit_db_session($session);
816 return scalar(@$maps);
820 sub _create_standing_penalties {
822 my($session, $user_session, $patron, $new_patron) = @_;
824 my $maps = $patron->standing_penalties;
827 for my $map (@$maps) {
829 if ($map->isdeleted()) {
830 $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
831 } elsif ($map->isnew()) {
832 $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
838 $map->usr($new_patron->id);
840 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
842 my $stat = $session->request($method, $map)->gather(1);
843 return (undef, $U->DB_UPDATE_FAILED($map)) unless $stat;
846 return ($new_patron, undef);
851 __PACKAGE__->register_method(
852 method => "search_username",
853 api_name => "open-ils.actor.user.search.username",
856 sub search_username {
857 my($self, $client, $username) = @_;
858 my $users = OpenILS::Application::AppUtils->simple_scalar_request(
860 "open-ils.cstore.direct.actor.user.search.atomic",
861 { usrname => $username }
869 __PACKAGE__->register_method(
870 method => "user_retrieve_by_barcode",
871 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
873 sub user_retrieve_by_barcode {
874 my($self, $client, $user_session, $barcode) = @_;
876 $logger->debug("Searching for user with barcode $barcode");
877 my ($user_obj, $evt) = $apputils->checkses($user_session);
880 my $card = OpenILS::Application::AppUtils->simple_scalar_request(
882 "open-ils.cstore.direct.actor.card.search.atomic",
883 { barcode => $barcode }
886 if(!$card || !$card->[0]) {
887 return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' );
891 my $user = flesh_user($card->usr());
893 $evt = $U->check_perms($user_obj->id, $user->home_ou, 'VIEW_USER');
896 if(!$user) { return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' ); }
903 __PACKAGE__->register_method(
904 method => "get_user_by_id",
905 api_name => "open-ils.actor.user.retrieve",);
908 my ($self, $client, $auth, $id) = @_;
909 my $e = new_editor(authtoken=>$auth);
910 return $e->event unless $e->checkauth;
911 my $user = $e->retrieve_actor_user($id)
913 return $e->event unless $e->allowed('VIEW_USER', $user->home_ou);
919 __PACKAGE__->register_method(
920 method => "get_org_types",
921 api_name => "open-ils.actor.org_types.retrieve",);
925 my($self, $client) = @_;
926 return $org_types if $org_types;
927 return $org_types = new_editor()->retrieve_all_actor_org_unit_type();
932 __PACKAGE__->register_method(
933 method => "get_user_ident_types",
934 api_name => "open-ils.actor.user.ident_types.retrieve",
937 sub get_user_ident_types {
938 return $ident_types if $ident_types;
939 return $ident_types =
940 new_editor()->retrieve_all_config_identification_type();
946 __PACKAGE__->register_method(
947 method => "get_org_unit",
948 api_name => "open-ils.actor.org_unit.retrieve",
952 my( $self, $client, $user_session, $org_id ) = @_;
953 my $e = new_editor(authtoken => $user_session);
955 return $e->event unless $e->checkauth;
956 $org_id = $e->requestor->ws_ou;
958 my $o = $e->retrieve_actor_org_unit($org_id)
963 __PACKAGE__->register_method(
964 method => "search_org_unit",
965 api_name => "open-ils.actor.org_unit_list.search",
968 sub search_org_unit {
970 my( $self, $client, $field, $value ) = @_;
972 my $list = OpenILS::Application::AppUtils->simple_scalar_request(
974 "open-ils.cstore.direct.actor.org_unit.search.atomic",
975 { $field => $value } );
983 __PACKAGE__->register_method(
984 method => "get_org_tree",
985 api_name => "open-ils.actor.org_tree.retrieve",
987 note => "Returns the entire org tree structure",
991 my( $self, $client) = @_;
993 $cache = OpenSRF::Utils::Cache->new("global", 0) unless $cache;
994 my $tree = $cache->get_cache('orgtree');
995 return $tree if $tree;
997 $tree = new_editor()->search_actor_org_unit(
999 {"parent_ou" => undef },
1002 flesh_fields => { aou => ['children'] },
1003 order_by => { aou => 'name'}
1008 $cache->put_cache('orgtree', $tree);
1013 # turns an org list into an org tree
1014 sub build_org_tree {
1016 my( $self, $orglist) = @_;
1018 return $orglist unless (
1019 ref($orglist) and @$orglist > 1 );
1022 $a->ou_type <=> $b->ou_type ||
1023 $a->name cmp $b->name } @$orglist;
1025 for my $org (@list) {
1027 next unless ($org and defined($org->parent_ou));
1028 my ($parent) = grep { $_->id == $org->parent_ou } @list;
1029 next unless $parent;
1031 $parent->children([]) unless defined($parent->children);
1032 push( @{$parent->children}, $org );
1040 __PACKAGE__->register_method(
1041 method => "get_org_descendants",
1042 api_name => "open-ils.actor.org_tree.descendants.retrieve"
1045 # depth is optional. org_unit is the id
1046 sub get_org_descendants {
1047 my( $self, $client, $org_unit, $depth ) = @_;
1048 my $orglist = $apputils->simple_scalar_request(
1050 "open-ils.storage.actor.org_unit.descendants.atomic",
1051 $org_unit, $depth );
1052 return $self->build_org_tree($orglist);
1056 __PACKAGE__->register_method(
1057 method => "get_org_ancestors",
1058 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
1061 # depth is optional. org_unit is the id
1062 sub get_org_ancestors {
1063 my( $self, $client, $org_unit, $depth ) = @_;
1064 my $orglist = $apputils->simple_scalar_request(
1066 "open-ils.storage.actor.org_unit.ancestors.atomic",
1067 $org_unit, $depth );
1068 return $self->build_org_tree($orglist);
1072 __PACKAGE__->register_method(
1073 method => "get_standings",
1074 api_name => "open-ils.actor.standings.retrieve"
1079 return $user_standings if $user_standings;
1080 return $user_standings =
1081 $apputils->simple_scalar_request(
1083 "open-ils.cstore.direct.config.standing.search.atomic",
1084 { id => { "!=" => undef } }
1090 __PACKAGE__->register_method(
1091 method => "get_my_org_path",
1092 api_name => "open-ils.actor.org_unit.full_path.retrieve"
1095 sub get_my_org_path {
1096 my( $self, $client, $auth, $org_id ) = @_;
1097 my $e = new_editor(authtoken=>$auth);
1098 return $e->event unless $e->checkauth;
1099 $org_id = $e->requestor->ws_ou unless defined $org_id;
1101 return $apputils->simple_scalar_request(
1103 "open-ils.storage.actor.org_unit.full_path.atomic",
1108 __PACKAGE__->register_method(
1109 method => "patron_adv_search",
1110 api_name => "open-ils.actor.patron.search.advanced" );
1111 sub patron_adv_search {
1112 my( $self, $client, $auth, $search_hash, $search_limit, $search_sort, $include_inactive ) = @_;
1113 my $e = new_editor(authtoken=>$auth);
1114 return $e->event unless $e->checkauth;
1115 return $e->event unless $e->allowed('VIEW_USER');
1116 return $U->storagereq(
1117 "open-ils.storage.actor.user.crazy_search",
1118 $search_hash, $search_limit, $search_sort, $include_inactive);
1123 sub _verify_password {
1124 my($user_session, $password) = @_;
1125 my $user_obj = $apputils->check_user_session($user_session);
1127 #grab the user with password
1128 $user_obj = $apputils->simple_scalar_request(
1130 "open-ils.cstore.direct.actor.user.retrieve",
1133 if($user_obj->passwd eq $password) {
1141 __PACKAGE__->register_method(
1142 method => "update_password",
1143 api_name => "open-ils.actor.user.password.update");
1145 __PACKAGE__->register_method(
1146 method => "update_password",
1147 api_name => "open-ils.actor.user.username.update");
1149 __PACKAGE__->register_method(
1150 method => "update_password",
1151 api_name => "open-ils.actor.user.email.update");
1153 sub update_password {
1154 my( $self, $client, $user_session, $new_value, $current_password ) = @_;
1158 my $user_obj = $apputils->check_user_session($user_session);
1160 if($self->api_name =~ /password/o) {
1162 #make sure they know the current password
1163 if(!_verify_password($user_session, md5_hex($current_password))) {
1164 return OpenILS::Event->new('INCORRECT_PASSWORD');
1167 $logger->debug("update_password setting new password $new_value");
1168 $user_obj->passwd($new_value);
1170 } elsif($self->api_name =~ /username/o) {
1171 my $users = search_username(undef, undef, $new_value);
1172 if( $users and $users->[0] ) {
1173 return OpenILS::Event->new('USERNAME_EXISTS');
1175 $user_obj->usrname($new_value);
1177 } elsif($self->api_name =~ /email/o) {
1178 #warn "Updating email to $new_value\n";
1179 $user_obj->email($new_value);
1182 my $session = $apputils->start_db_session();
1184 ( $user_obj, $evt ) = _update_patron($session, $user_obj, $user_obj, 1);
1185 return $evt if $evt;
1187 $apputils->commit_db_session($session);
1189 if($user_obj) { return 1; }
1194 __PACKAGE__->register_method(
1195 method => "check_user_perms",
1196 api_name => "open-ils.actor.user.perm.check",
1197 notes => <<" NOTES");
1198 Takes a login session, user id, an org id, and an array of perm type strings. For each
1199 perm type, if the user does *not* have the given permission it is added
1200 to a list which is returned from the method. If all permissions
1201 are allowed, an empty list is returned
1202 if the logged in user does not match 'user_id', then the logged in user must
1203 have VIEW_PERMISSION priveleges.
1206 sub check_user_perms {
1207 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1209 my( $staff, $evt ) = $apputils->checkses($login_session);
1210 return $evt if $evt;
1212 if($staff->id ne $user_id) {
1213 if( $evt = $apputils->check_perms(
1214 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1220 for my $perm (@$perm_types) {
1221 if($apputils->check_perms($user_id, $org_id, $perm)) {
1222 push @not_allowed, $perm;
1226 return \@not_allowed
1229 __PACKAGE__->register_method(
1230 method => "check_user_perms2",
1231 api_name => "open-ils.actor.user.perm.check.multi_org",
1233 Checks the permissions on a list of perms and orgs for a user
1234 @param authtoken The login session key
1235 @param user_id The id of the user to check
1236 @param orgs The array of org ids
1237 @param perms The array of permission names
1238 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1239 if the logged in user does not match 'user_id', then the logged in user must
1240 have VIEW_PERMISSION priveleges.
1243 sub check_user_perms2 {
1244 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1246 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1247 $authtoken, $user_id, 'VIEW_PERMISSION' );
1248 return $evt if $evt;
1251 for my $org (@$orgs) {
1252 for my $perm (@$perms) {
1253 if($apputils->check_perms($user_id, $org, $perm)) {
1254 push @not_allowed, [ $org, $perm ];
1259 return \@not_allowed
1263 __PACKAGE__->register_method(
1264 method => 'check_user_perms3',
1265 api_name => 'open-ils.actor.user.perm.highest_org',
1267 Returns the highest org unit id at which a user has a given permission
1268 If the requestor does not match the target user, the requestor must have
1269 'VIEW_PERMISSION' rights at the home org unit of the target user
1270 @param authtoken The login session key
1271 @param userid The id of the user in question
1272 @param perm The permission to check
1273 @return The org unit highest in the org tree within which the user has
1274 the requested permission
1277 sub check_user_perms3 {
1278 my( $self, $client, $authtoken, $userid, $perm ) = @_;
1280 my( $staff, $target, $org, $evt );
1282 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1283 $authtoken, $userid, 'VIEW_PERMISSION' );
1284 return $evt if $evt;
1286 my $tree = $self->get_org_tree();
1287 return _find_highest_perm_org( $perm, $userid, $target->ws_ou, $tree );
1291 sub _find_highest_perm_org {
1292 my ( $perm, $userid, $start_org, $org_tree ) = @_;
1293 my $org = $apputils->find_org($org_tree, $start_org );
1297 last if ($apputils->check_perms( $userid, $org->id, $perm )); # perm failed
1299 $org = $apputils->find_org( $org_tree, $org->parent_ou() );
1305 __PACKAGE__->register_method(
1306 method => 'check_user_perms4',
1307 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1309 Returns the highest org unit id at which a user has a given permission
1310 If the requestor does not match the target user, the requestor must have
1311 'VIEW_PERMISSION' rights at the home org unit of the target user
1312 @param authtoken The login session key
1313 @param userid The id of the user in question
1314 @param perms An array of perm names to check
1315 @return An array of orgId's representing the org unit
1316 highest in the org tree within which the user has the requested permission
1317 The arrah of orgId's has matches the order of the perms array
1320 sub check_user_perms4 {
1321 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1323 my( $staff, $target, $org, $evt );
1325 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1326 $authtoken, $userid, 'VIEW_PERMISSION' );
1327 return $evt if $evt;
1330 return [] unless ref($perms);
1331 my $tree = $self->get_org_tree();
1333 for my $p (@$perms) {
1334 push( @arr, _find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1342 __PACKAGE__->register_method(
1343 method => "user_fines_summary",
1344 api_name => "open-ils.actor.user.fines.summary",
1345 notes => <<" NOTES");
1346 Returns a short summary of the users total open fines, excluding voided fines
1347 Params are login_session, user_id
1348 Returns a 'mous' object.
1351 sub user_fines_summary {
1352 my( $self, $client, $auth, $user_id ) = @_;
1353 my $e = new_editor(authtoken=>$auth);
1354 return $e->event unless $e->checkauth;
1355 my $user = $e->retrieve_actor_user($user_id)
1356 or return $e->event;
1358 if( $user_id ne $e->requestor->id ) {
1359 return $e->event unless
1360 $e->allowed('VIEW_USER_FINES_SUMMARY', $user->home_ou);
1363 # run this inside a transaction to prevent replication delay errors
1364 my $ses = $U->start_db_session();
1365 my $s = $ses->request(
1366 'open-ils.storage.money.open_user_summary.search', $user_id )->gather(1);
1367 $U->rollback_db_session($ses);
1374 __PACKAGE__->register_method(
1375 method => "user_transactions",
1376 api_name => "open-ils.actor.user.transactions",
1377 notes => <<" NOTES");
1378 Returns a list of open user transactions (mbts objects);
1379 Params are login_session, user_id
1380 Optional third parameter is the transactions type. defaults to all
1383 __PACKAGE__->register_method(
1384 method => "user_transactions",
1385 api_name => "open-ils.actor.user.transactions.have_charge",
1386 notes => <<" NOTES");
1387 Returns a list of all open user transactions (mbts objects) that have an initial charge
1388 Params are login_session, user_id
1389 Optional third parameter is the transactions type. defaults to all
1392 __PACKAGE__->register_method(
1393 method => "user_transactions",
1394 api_name => "open-ils.actor.user.transactions.have_balance",
1395 notes => <<" NOTES");
1396 Returns a list of all open user transactions (mbts objects) that have a balance
1397 Params are login_session, user_id
1398 Optional third parameter is the transactions type. defaults to all
1401 __PACKAGE__->register_method(
1402 method => "user_transactions",
1403 api_name => "open-ils.actor.user.transactions.fleshed",
1404 notes => <<" NOTES");
1405 Returns an object/hash of transaction, circ, title where transaction = an open
1406 user transactions (mbts objects), circ is the attached circluation, and title
1407 is the title the circ points to
1408 Params are login_session, user_id
1409 Optional third parameter is the transactions type. defaults to all
1412 __PACKAGE__->register_method(
1413 method => "user_transactions",
1414 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1415 notes => <<" NOTES");
1416 Returns an object/hash of transaction, circ, title where transaction = an open
1417 user transactions that has an initial charge (mbts objects), circ is the
1418 attached circluation, and title is the title the circ points to
1419 Params are login_session, user_id
1420 Optional third parameter is the transactions type. defaults to all
1423 __PACKAGE__->register_method(
1424 method => "user_transactions",
1425 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1426 notes => <<" NOTES");
1427 Returns an object/hash of transaction, circ, title where transaction = an open
1428 user transaction that has a balance (mbts objects), circ is the attached
1429 circluation, and title is the title the circ points to
1430 Params are login_session, user_id
1431 Optional third parameter is the transaction type. defaults to all
1434 __PACKAGE__->register_method(
1435 method => "user_transactions",
1436 api_name => "open-ils.actor.user.transactions.count",
1437 notes => <<" NOTES");
1438 Returns an object/hash of transaction, circ, title where transaction = an open
1439 user transactions (mbts objects), circ is the attached circluation, and title
1440 is the title the circ points to
1441 Params are login_session, user_id
1442 Optional third parameter is the transactions type. defaults to all
1445 __PACKAGE__->register_method(
1446 method => "user_transactions",
1447 api_name => "open-ils.actor.user.transactions.have_charge.count",
1448 notes => <<" NOTES");
1449 Returns an object/hash of transaction, circ, title where transaction = an open
1450 user transactions that has an initial charge (mbts objects), circ is the
1451 attached circluation, and title is the title the circ points to
1452 Params are login_session, user_id
1453 Optional third parameter is the transactions type. defaults to all
1456 __PACKAGE__->register_method(
1457 method => "user_transactions",
1458 api_name => "open-ils.actor.user.transactions.have_balance.count",
1459 notes => <<" NOTES");
1460 Returns an object/hash of transaction, circ, title where transaction = an open
1461 user transaction that has a balance (mbts objects), circ is the attached
1462 circluation, and title is the title the circ points to
1463 Params are login_session, user_id
1464 Optional third parameter is the transaction type. defaults to all
1467 __PACKAGE__->register_method(
1468 method => "user_transactions",
1469 api_name => "open-ils.actor.user.transactions.have_balance.total",
1470 notes => <<" NOTES");
1471 Returns an object/hash of transaction, circ, title where transaction = an open
1472 user transaction that has a balance (mbts objects), circ is the attached
1473 circluation, and title is the title the circ points to
1474 Params are login_session, user_id
1475 Optional third parameter is the transaction type. defaults to all
1480 sub user_transactions {
1481 my( $self, $client, $login_session, $user_id, $type ) = @_;
1483 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1484 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1485 return $evt if $evt;
1487 my $api = $self->api_name();
1491 if(defined($type)) { @xact = (xact_type => $type);
1493 } else { @xact = (); }
1496 ->method_lookup('open-ils.actor.user.transactions.history.still_open')
1497 ->run($login_session => $user_id => $type);
1499 if($api =~ /have_charge/o) {
1501 $trans = [ grep { int($_->total_owed * 100) > 0 } @$trans ];
1503 } elsif($api =~ /have_balance/o) {
1505 $trans = [ grep { int($_->balance_owed * 100) != 0 } @$trans ];
1508 $trans = [ grep { int($_->total_owed * 100) > 0 } @$trans ];
1512 if($api =~ /total/o) {
1514 for my $t (@$trans) {
1515 $total += $t->balance_owed;
1518 $logger->debug("Total balance owed by user $user_id: $total");
1522 if($api =~ /count/o) { return scalar @$trans; }
1523 if($api !~ /fleshed/o) { return $trans; }
1526 for my $t (@$trans) {
1528 if( $t->xact_type ne 'circulation' ) {
1529 push @resp, {transaction => $t};
1533 my $circ = $apputils->simple_scalar_request(
1535 "open-ils.cstore.direct.action.circulation.retrieve",
1540 my $title = $apputils->simple_scalar_request(
1542 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1543 $circ->target_copy );
1547 my $u = OpenILS::Utils::ModsParser->new();
1548 $u->start_mods_batch($title->marc());
1549 my $mods = $u->finish_mods_batch();
1550 $mods->doc_id($title->id) if $mods;
1552 push @resp, {transaction => $t, circ => $circ, record => $mods };
1560 __PACKAGE__->register_method(
1561 method => "user_transaction_retrieve",
1562 api_name => "open-ils.actor.user.transaction.fleshed.retrieve",
1564 notes => <<" NOTES");
1565 Returns a fleshedtransaction record
1567 __PACKAGE__->register_method(
1568 method => "user_transaction_retrieve",
1569 api_name => "open-ils.actor.user.transaction.retrieve",
1571 notes => <<" NOTES");
1572 Returns a transaction record
1574 sub user_transaction_retrieve {
1575 my( $self, $client, $login_session, $bill_id ) = @_;
1577 # XXX I think I'm deprecated... make sure
1579 my $trans = $apputils->simple_scalar_request(
1581 "open-ils.cstore.direct.money.billable_transaction_summary.retrieve",
1585 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1586 $login_session, $trans->usr, 'VIEW_USER_TRANSACTIONS' );
1587 return $evt if $evt;
1589 my $api = $self->api_name();
1590 if($api !~ /fleshed/o) { return $trans; }
1592 if( $trans->xact_type ne 'circulation' ) {
1593 $logger->debug("Returning non-circ transaction");
1594 return {transaction => $trans};
1597 my $circ = $apputils->simple_scalar_request(
1599 "open-ils..direct.action.circulation.retrieve",
1602 return {transaction => $trans} unless $circ;
1603 $logger->debug("Found the circ transaction");
1605 my $title = $apputils->simple_scalar_request(
1607 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1608 $circ->target_copy );
1610 return {transaction => $trans, circ => $circ } unless $title;
1611 $logger->debug("Found the circ title");
1615 my $u = OpenILS::Utils::ModsParser->new();
1616 $u->start_mods_batch($title->marc());
1617 $mods = $u->finish_mods_batch();
1619 if ($title->id == OILS_PRECAT_RECORD) {
1620 my $copy = $apputils->simple_scalar_request(
1622 "open-ils.cstore.direct.asset.copy.retrieve",
1623 $circ->target_copy );
1625 $mods = new Fieldmapper::metabib::virtual_record;
1626 $mods->doc_id(OILS_PRECAT_RECORD);
1627 $mods->title($copy->dummy_title);
1628 $mods->author($copy->dummy_author);
1632 $logger->debug("MODSized the circ title");
1634 return {transaction => $trans, circ => $circ, record => $mods };
1638 __PACKAGE__->register_method(
1639 method => "hold_request_count",
1640 api_name => "open-ils.actor.user.hold_requests.count",
1642 notes => <<" NOTES");
1643 Returns hold ready/total counts
1645 sub hold_request_count {
1646 my( $self, $client, $login_session, $userid ) = @_;
1648 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1649 $login_session, $userid, 'VIEW_HOLD' );
1650 return $evt if $evt;
1653 my $holds = $apputils->simple_scalar_request(
1655 "open-ils.cstore.direct.action.hold_request.search.atomic",
1658 fulfillment_time => {"=" => undef },
1659 cancel_time => undef,
1664 for my $h (@$holds) {
1665 next unless $h->capture_time and $h->current_copy;
1667 my $copy = $apputils->simple_scalar_request(
1669 "open-ils.cstore.direct.asset.copy.retrieve",
1673 if ($copy and $copy->status == 8) {
1678 return { total => scalar(@$holds), ready => scalar(@ready) };
1682 __PACKAGE__->register_method(
1683 method => "checkedout_count",
1684 api_name => "open-ils.actor.user.checked_out.count__",
1686 notes => <<" NOTES");
1687 Returns a transaction record
1691 sub checkedout_count {
1692 my( $self, $client, $login_session, $userid ) = @_;
1694 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1695 $login_session, $userid, 'VIEW_CIRCULATIONS' );
1696 return $evt if $evt;
1698 my $circs = $apputils->simple_scalar_request(
1700 "open-ils.cstore.direct.action.circulation.search.atomic",
1701 { usr => $userid, stop_fines => undef }
1702 #{ usr => $userid, checkin_time => {"=" => undef } }
1705 my $parser = DateTime::Format::ISO8601->new;
1708 for my $c (@$circs) {
1709 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1710 my $due = $due_dt->epoch;
1712 if ($due < DateTime->today->epoch) {
1717 return { total => scalar(@$circs), overdue => scalar(@overdue) };
1721 __PACKAGE__->register_method(
1722 method => "checked_out",
1723 api_name => "open-ils.actor.user.checked_out",
1726 Returns a structure of circulations objects sorted by
1727 out, overdue, lost, claims_returned, long_overdue.
1728 A list of IDs are returned of each type.
1729 lost, long_overdue, and claims_returned circ will not
1730 be "finished" (there is an outstanding balance or some
1731 other pending action on the circ).
1733 The .count method also includes a 'total' field which
1734 sums all "open" circs
1738 __PACKAGE__->register_method(
1739 method => "checked_out",
1740 api_name => "open-ils.actor.user.checked_out.count",
1742 signature => q/@see open-ils.actor.user.checked_out/
1746 my( $self, $conn, $auth, $userid ) = @_;
1748 my $e = new_editor(authtoken=>$auth);
1749 return $e->event unless $e->checkauth;
1751 if( $userid ne $e->requestor->id ) {
1752 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
1755 my $count = $self->api_name =~ /count/;
1756 return _checked_out( $count, $e, $userid );
1760 my( $iscount, $e, $userid ) = @_;
1763 my $meth = 'open-ils.storage.actor.user.checked_out';
1764 $meth = "$meth.count" if $iscount;
1765 return $U->storagereq($meth, $userid);
1767 # XXX Old code - moved to storage
1768 #------------------------------------------------------------------------------
1769 #------------------------------------------------------------------------------
1770 my $circs = $e->search_action_circulation(
1771 { usr => $userid, checkin_time => undef });
1773 my $parser = DateTime::Format::ISO8601->new;
1775 # split the circs up into overdue and not-overdue circs
1777 for my $c (@$circs) {
1778 if( $c->due_date ) {
1779 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1780 my $due = $due_dt->epoch;
1781 if ($due < DateTime->today->epoch) {
1791 my( @open, @od, @lost, @cr, @lo );
1793 while (my $c = shift(@out)) {
1794 push( @open, $c->id ) if (!$c->stop_fines || $c->stop_fines eq 'MAXFINES' || $c->stop_fines eq 'RENEW');
1795 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1796 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1797 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
1800 while (my $c = shift(@overdue)) {
1801 push( @od, $c->id ) if (!$c->stop_fines || $c->stop_fines eq 'MAXFINES' || $c->stop_fines eq 'RENEW');
1802 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1803 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1804 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
1809 total => @open + @od + @lost + @cr + @lo,
1810 out => scalar(@open),
1811 overdue => scalar(@od),
1812 lost => scalar(@lost),
1813 claims_returned => scalar(@cr),
1814 long_overdue => scalar(@lo)
1822 claims_returned => \@cr,
1823 long_overdue => \@lo
1828 sub _checked_out_WHAT {
1829 my( $iscount, $e, $userid ) = @_;
1831 my $circs = $e->search_action_circulation(
1832 { usr => $userid, stop_fines => undef });
1834 my $mcircs = $e->search_action_circulation(
1837 checkin_time => undef,
1838 xact_finish => undef,
1842 push( @$circs, @$mcircs );
1844 my $parser = DateTime::Format::ISO8601->new;
1846 # split the circs up into overdue and not-overdue circs
1848 for my $c (@$circs) {
1849 if( $c->due_date ) {
1850 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1851 my $due = $due_dt->epoch;
1852 if ($due < DateTime->today->epoch) {
1853 push @overdue, $c->id;
1862 # grab all of the lost, claims-returned, and longoverdue circs
1863 #my $open = $e->search_action_circulation(
1864 # {usr => $userid, stop_fines => { '!=' => undef }, xact_finish => undef });
1867 # these items have stop_fines, but no xact_finish, so money
1868 # is owed on them and they have not been checked in
1869 my $open = $e->search_action_circulation(
1872 stop_fines => { in => [ qw/LOST CLAIMSRETURNED LONGOVERDUE/ ] },
1873 xact_finish => undef,
1874 checkin_time => undef,
1879 my( @lost, @cr, @lo );
1880 for my $c (@$open) {
1881 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1882 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1883 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
1889 total => @$circs + @lost + @cr + @lo,
1890 out => scalar(@out),
1891 overdue => scalar(@overdue),
1892 lost => scalar(@lost),
1893 claims_returned => scalar(@cr),
1894 long_overdue => scalar(@lo)
1900 overdue => \@overdue,
1902 claims_returned => \@cr,
1903 long_overdue => \@lo
1909 __PACKAGE__->register_method(
1910 method => "checked_in_with_fines",
1911 api_name => "open-ils.actor.user.checked_in_with_fines",
1913 signature => q/@see open-ils.actor.user.checked_out/
1915 sub checked_in_with_fines {
1916 my( $self, $conn, $auth, $userid ) = @_;
1918 my $e = new_editor(authtoken=>$auth);
1919 return $e->event unless $e->checkauth;
1921 if( $userid ne $e->requestor->id ) {
1922 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
1925 # money is owed on these items and they are checked in
1926 my $open = $e->search_action_circulation(
1929 xact_finish => undef,
1930 checkin_time => { "!=" => undef },
1935 my( @lost, @cr, @lo );
1936 for my $c (@$open) {
1937 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1938 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1939 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
1944 claims_returned => \@cr,
1945 long_overdue => \@lo
1957 __PACKAGE__->register_method(
1958 method => "user_transaction_history",
1959 api_name => "open-ils.actor.user.transactions.history",
1961 notes => <<" NOTES");
1962 Returns a list of billable transaction ids for a user, optionally by type
1964 __PACKAGE__->register_method(
1965 method => "user_transaction_history",
1966 api_name => "open-ils.actor.user.transactions.history.have_charge",
1968 notes => <<" NOTES");
1969 Returns a list of billable transaction ids for a user that have an initial charge, optionally by type
1971 __PACKAGE__->register_method(
1972 method => "user_transaction_history",
1973 api_name => "open-ils.actor.user.transactions.history.have_balance",
1975 notes => <<" NOTES");
1976 Returns a list of billable transaction ids for a user that have a balance, optionally by type
1978 __PACKAGE__->register_method(
1979 method => "user_transaction_history",
1980 api_name => "open-ils.actor.user.transactions.history.still_open",
1982 notes => <<" NOTES");
1983 Returns a list of billable transaction ids for a user that are not finished
1985 __PACKAGE__->register_method(
1986 method => "user_transaction_history",
1987 api_name => "open-ils.actor.user.transactions.history.have_bill",
1989 notes => <<" NOTES");
1990 Returns a list of billable transaction ids for a user that has billings
1996 sub _user_transaction_history {
1997 my( $self, $client, $login_session, $user_id, $type ) = @_;
1999 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
2000 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
2001 return $evt if $evt;
2003 my $api = $self->api_name();
2008 @xact = (xact_type => $type) if(defined($type));
2009 @balance = (balance_owed => { "!=" => 0}) if($api =~ /have_balance/);
2010 @charge = (last_billing_ts => { "<>" => undef }) if $api =~ /have_charge/;
2012 $logger->debug("searching for transaction history: @xact : @balance, @charge");
2014 my $trans = $apputils->simple_scalar_request(
2016 "open-ils.cstore.direct.money.billable_transaction_summary.search.atomic",
2017 { usr => $user_id, @xact, @charge, @balance }, { order_by => { mbts => 'xact_start DESC' } });
2019 return [ map { $_->id } @$trans ];
2023 =head SEE APPUTILS.PM
2028 for my $x (@xacts) {
2029 my $s = new Fieldmapper::money::billable_transaction_summary;
2032 $s->xact_start( $x->xact_start );
2033 $s->xact_finish( $x->xact_finish );
2037 for my $b (@{ $x->billings }) {
2038 next if ($U->is_true($b->voided));
2039 $to += ($b->amount * 100);
2040 $lb ||= $b->billing_ts;
2041 if ($b->billing_ts ge $lb) {
2042 $lb = $b->billing_ts;
2043 $s->last_billing_note($b->note);
2044 $s->last_billing_ts($b->billing_ts);
2045 $s->last_billing_type($b->billing_type);
2049 $s->total_owed( sprintf('%0.2f', $to / 100 ) );
2053 for my $p (@{ $x->payments }) {
2054 next if ($U->is_true($p->voided));
2055 $tp += ($p->amount * 100);
2056 $lp ||= $p->payment_ts;
2057 if ($p->payment_ts ge $lp) {
2058 $lp = $p->payment_ts;
2059 $s->last_payment_note($p->note);
2060 $s->last_payment_ts($p->payment_ts);
2061 $s->last_payment_type($p->payment_type);
2064 $s->total_paid( sprintf('%0.2f', $tp / 100 ) );
2066 $s->balance_owed( sprintf('%0.2f', ($to - $tp) / 100) );
2068 $s->xact_type( 'grocery' ) if ($x->grocery);
2069 $s->xact_type( 'circulation' ) if ($x->circulation);
2078 sub user_transaction_history {
2079 my( $self, $conn, $auth, $userid, $type ) = @_;
2081 # run inside of a transaction to prevent replication delays
2082 my $e = new_editor(xact=>1, authtoken=>$auth);
2083 return $e->die_event unless $e->checkauth;
2085 if( $e->requestor->id ne $userid ) {
2086 return $e->die_event
2087 unless $e->allowed('VIEW_USER_TRANSACTIONS');
2090 my $api = $self->api_name;
2091 my @xact_finish = (xact_finish => undef ) if ($api =~ /history.still_open$/);
2093 my @xacts = @{ $e->search_money_billable_transaction(
2094 [ { usr => $userid, @xact_finish },
2096 flesh_fields => { mbt => [ qw/billings payments grocery circulation/ ] },
2097 order_by => { mbt => 'xact_start DESC' },
2105 #my @mbts = _make_mbts( @xacts );
2106 my @mbts = $U->make_mbts( @xacts );
2108 if(defined($type)) {
2109 @mbts = grep { $_->xact_type eq $type } @mbts;
2112 if($api =~ /have_balance/o) {
2113 @mbts = grep { int($_->balance_owed * 100) != 0 } @mbts;
2116 if($api =~ /have_charge/o) {
2117 @mbts = grep { defined($_->last_billing_ts) } @mbts;
2120 if($api =~ /have_bill/o) {
2121 @mbts = grep { int($_->total_owed * 100) != 0 } @mbts;
2129 __PACKAGE__->register_method(
2130 method => "user_perms",
2131 api_name => "open-ils.actor.permissions.user_perms.retrieve",
2133 notes => <<" NOTES");
2134 Returns a list of permissions
2137 my( $self, $client, $authtoken, $user ) = @_;
2139 my( $staff, $evt ) = $apputils->checkses($authtoken);
2140 return $evt if $evt;
2142 $user ||= $staff->id;
2144 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
2148 return $apputils->simple_scalar_request(
2150 "open-ils.storage.permission.user_perms.atomic",
2154 __PACKAGE__->register_method(
2155 method => "retrieve_perms",
2156 api_name => "open-ils.actor.permissions.retrieve",
2157 notes => <<" NOTES");
2158 Returns a list of permissions
2160 sub retrieve_perms {
2161 my( $self, $client ) = @_;
2162 return $apputils->simple_scalar_request(
2164 "open-ils.cstore.direct.permission.perm_list.search.atomic",
2165 { id => { '!=' => undef } }
2169 __PACKAGE__->register_method(
2170 method => "retrieve_groups",
2171 api_name => "open-ils.actor.groups.retrieve",
2172 notes => <<" NOTES");
2173 Returns a list of user groupss
2175 sub retrieve_groups {
2176 my( $self, $client ) = @_;
2177 return new_editor()->retrieve_all_permission_grp_tree();
2180 __PACKAGE__->register_method(
2181 method => "retrieve_org_address",
2182 api_name => "open-ils.actor.org_unit.address.retrieve",
2183 notes => <<' NOTES');
2184 Returns an org_unit address by ID
2185 @param An org_address ID
2187 sub retrieve_org_address {
2188 my( $self, $client, $id ) = @_;
2189 return $apputils->simple_scalar_request(
2191 "open-ils.cstore.direct.actor.org_address.retrieve",
2196 __PACKAGE__->register_method(
2197 method => "retrieve_groups_tree",
2198 api_name => "open-ils.actor.groups.tree.retrieve",
2199 notes => <<" NOTES");
2200 Returns a list of user groups
2202 sub retrieve_groups_tree {
2203 my( $self, $client ) = @_;
2204 return new_editor()->search_permission_grp_tree(
2209 flesh_fields => { pgt => ["children"] },
2210 order_by => { pgt => 'name'}
2217 # turns an org list into an org tree
2219 sub build_group_tree {
2221 my( $self, $grplist) = @_;
2223 return $grplist unless (
2224 ref($grplist) and @$grplist > 1 );
2226 my @list = sort { $a->name cmp $b->name } @$grplist;
2229 for my $grp (@list) {
2231 if ($grp and !defined($grp->parent)) {
2235 my ($parent) = grep { $_->id == $grp->parent} @list;
2237 $parent->children([]) unless defined($parent->children);
2238 push( @{$parent->children}, $grp );
2246 __PACKAGE__->register_method(
2247 method => "add_user_to_groups",
2248 api_name => "open-ils.actor.user.set_groups",
2249 notes => <<" NOTES");
2250 Adds a user to one or more permission groups
2253 sub add_user_to_groups {
2254 my( $self, $client, $authtoken, $userid, $groups ) = @_;
2256 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2257 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
2258 return $evt if $evt;
2260 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2261 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
2262 return $evt if $evt;
2264 $apputils->simplereq(
2266 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
2268 for my $group (@$groups) {
2269 my $link = Fieldmapper::permission::usr_grp_map->new;
2271 $link->usr($userid);
2273 my $id = $apputils->simplereq(
2275 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
2281 __PACKAGE__->register_method(
2282 method => "get_user_perm_groups",
2283 api_name => "open-ils.actor.user.get_groups",
2284 notes => <<" NOTES");
2285 Retrieve a user's permission groups.
2289 sub get_user_perm_groups {
2290 my( $self, $client, $authtoken, $userid ) = @_;
2292 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2293 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
2294 return $evt if $evt;
2296 return $apputils->simplereq(
2298 'open-ils.cstore.direct.permission.usr_grp_map.search.atomic', { usr => $userid } );
2303 __PACKAGE__->register_method (
2304 method => 'register_workstation',
2305 api_name => 'open-ils.actor.workstation.register.override',
2306 signature => q/@see open-ils.actor.workstation.register/);
2308 __PACKAGE__->register_method (
2309 method => 'register_workstation',
2310 api_name => 'open-ils.actor.workstation.register',
2312 Registers a new workstion in the system
2313 @param authtoken The login session key
2314 @param name The name of the workstation id
2315 @param owner The org unit that owns this workstation
2316 @return The workstation id on success, WORKSTATION_NAME_EXISTS
2317 if the name is already in use.
2320 sub _register_workstation {
2321 my( $self, $connection, $authtoken, $name, $owner ) = @_;
2322 my( $requestor, $evt ) = $U->checkses($authtoken);
2323 return $evt if $evt;
2324 $evt = $U->check_perms($requestor->id, $owner, 'REGISTER_WORKSTATION');
2325 return $evt if $evt;
2327 my $ws = $U->cstorereq(
2328 'open-ils.cstore.direct.actor.workstation.search', { name => $name } );
2329 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS') if $ws;
2331 $ws = Fieldmapper::actor::workstation->new;
2332 $ws->owning_lib($owner);
2335 my $id = $U->storagereq(
2336 'open-ils.storage.direct.actor.workstation.create', $ws );
2337 return $U->DB_UPDATE_FAILED($ws) unless $id;
2343 sub register_workstation {
2344 my( $self, $conn, $authtoken, $name, $owner ) = @_;
2346 my $e = new_editor(authtoken=>$authtoken, xact=>1);
2347 return $e->event unless $e->checkauth;
2348 return $e->event unless $e->allowed('REGISTER_WORKSTATION'); # XXX rely on editor perms
2349 my $existing = $e->search_actor_workstation({name => $name});
2352 if( $self->api_name =~ /override/o ) {
2353 return $e->event unless $e->allowed('DELETE_WORKSTATION'); # XXX rely on editor perms
2354 return $e->event unless $e->delete_actor_workstation($$existing[0]);
2356 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS')
2360 my $ws = Fieldmapper::actor::workstation->new;
2361 $ws->owning_lib($owner);
2363 $e->create_actor_workstation($ws) or return $e->event;
2365 return $ws->id; # note: editor sets the id on the new object for us
2369 __PACKAGE__->register_method (
2370 method => 'fetch_patron_note',
2371 api_name => 'open-ils.actor.note.retrieve.all',
2373 Returns a list of notes for a given user
2374 Requestor must have VIEW_USER permission if pub==false and
2375 @param authtoken The login session key
2376 @param args Hash of params including
2377 patronid : the patron's id
2378 pub : true if retrieving only public notes
2382 sub fetch_patron_note {
2383 my( $self, $conn, $authtoken, $args ) = @_;
2384 my $patronid = $$args{patronid};
2386 my($reqr, $evt) = $U->checkses($authtoken);
2387 return $evt if $evt;
2390 ($patron, $evt) = $U->fetch_user($patronid);
2391 return $evt if $evt;
2394 if( $patronid ne $reqr->id ) {
2395 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2396 return $evt if $evt;
2398 return $U->cstorereq(
2399 'open-ils.cstore.direct.actor.usr_note.search.atomic',
2400 { usr => $patronid, pub => 't' } );
2403 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2404 return $evt if $evt;
2406 return $U->cstorereq(
2407 'open-ils.cstore.direct.actor.usr_note.search.atomic', { usr => $patronid } );
2410 __PACKAGE__->register_method (
2411 method => 'create_user_note',
2412 api_name => 'open-ils.actor.note.create',
2414 Creates a new note for the given user
2415 @param authtoken The login session key
2416 @param note The note object
2419 sub create_user_note {
2420 my( $self, $conn, $authtoken, $note ) = @_;
2421 my $e = new_editor(xact=>1, authtoken=>$authtoken);
2422 return $e->die_event unless $e->checkauth;
2424 my $user = $e->retrieve_actor_user($note->usr)
2425 or return $e->die_event;
2427 return $e->die_event unless
2428 $e->allowed('UPDATE_USER',$user->home_ou);
2430 $note->creator($e->requestor->id);
2431 $e->create_actor_usr_note($note) or return $e->die_event;
2437 __PACKAGE__->register_method (
2438 method => 'delete_user_note',
2439 api_name => 'open-ils.actor.note.delete',
2441 Deletes a note for the given user
2442 @param authtoken The login session key
2443 @param noteid The note id
2446 sub delete_user_note {
2447 my( $self, $conn, $authtoken, $noteid ) = @_;
2449 my $e = new_editor(xact=>1, authtoken=>$authtoken);
2450 return $e->die_event unless $e->checkauth;
2451 my $note = $e->retrieve_actor_usr_note($noteid)
2452 or return $e->die_event;
2453 my $user = $e->retrieve_actor_user($note->usr)
2454 or return $e->die_event;
2455 return $e->die_event unless
2456 $e->allowed('UPDATE_USER', $user->home_ou);
2458 $e->delete_actor_usr_note($note) or return $e->die_event;
2464 __PACKAGE__->register_method (
2465 method => 'update_user_note',
2466 api_name => 'open-ils.actor.note.update',
2468 @param authtoken The login session key
2469 @param note The note
2473 sub update_user_note {
2474 my( $self, $conn, $auth, $note ) = @_;
2475 my $e = new_editor(authtoken=>$auth, xact=>1);
2476 return $e->event unless $e->checkauth;
2477 my $patron = $e->retrieve_actor_user($note->usr)
2478 or return $e->event;
2479 return $e->event unless
2480 $e->allowed('UPDATE_USER', $patron->home_ou);
2481 $e->update_actor_user_note($note)
2482 or return $e->event;
2490 __PACKAGE__->register_method (
2491 method => 'create_closed_date',
2492 api_name => 'open-ils.actor.org_unit.closed_date.create',
2494 Creates a new closing entry for the given org_unit
2495 @param authtoken The login session key
2496 @param note The closed_date object
2499 sub create_closed_date {
2500 my( $self, $conn, $authtoken, $cd ) = @_;
2502 my( $user, $evt ) = $U->checkses($authtoken);
2503 return $evt if $evt;
2505 $evt = $U->check_perms($user->id, $cd->org_unit, 'CREATE_CLOSEING');
2506 return $evt if $evt;
2508 $logger->activity("user ".$user->id." creating library closing for ".$cd->org_unit);
2510 my $id = $U->storagereq(
2511 'open-ils.storage.direct.actor.org_unit.closed_date.create', $cd );
2512 return $U->DB_UPDATE_FAILED($cd) unless $id;
2517 __PACKAGE__->register_method (
2518 method => 'delete_closed_date',
2519 api_name => 'open-ils.actor.org_unit.closed_date.delete',
2521 Deletes a closing entry for the given org_unit
2522 @param authtoken The login session key
2523 @param noteid The close_date id
2526 sub delete_closed_date {
2527 my( $self, $conn, $authtoken, $cd ) = @_;
2529 my( $user, $evt ) = $U->checkses($authtoken);
2530 return $evt if $evt;
2533 ($cd_obj, $evt) = fetch_closed_date($cd);
2534 return $evt if $evt;
2536 $evt = $U->check_perms($user->id, $cd->org_unit, 'DELETE_CLOSEING');
2537 return $evt if $evt;
2539 $logger->activity("user ".$user->id." deleting library closing for ".$cd->org_unit);
2541 my $stat = $U->storagereq(
2542 'open-ils.storage.direct.actor.org_unit.closed_date.delete', $cd );
2543 return $U->DB_UPDATE_FAILED($cd) unless $stat;
2548 __PACKAGE__->register_method(
2549 method => 'usrname_exists',
2550 api_name => 'open-ils.actor.username.exists',
2552 Returns 1 if the requested username exists, returns 0 otherwise
2556 sub usrname_exists {
2557 my( $self, $conn, $auth, $usrname ) = @_;
2558 my $e = new_editor(authtoken=>$auth);
2559 return $e->event unless $e->checkauth;
2560 my $a = $e->search_actor_user({usrname => $usrname, deleted=>'f'}, {idlist=>1});
2561 return $$a[0] if $a and @$a;
2565 __PACKAGE__->register_method(
2566 method => 'barcode_exists',
2567 api_name => 'open-ils.actor.barcode.exists',
2569 Returns 1 if the requested barcode exists, returns 0 otherwise
2573 sub barcode_exists {
2574 my( $self, $conn, $auth, $barcode ) = @_;
2575 my $e = new_editor(authtoken=>$auth);
2576 return $e->event unless $e->checkauth;
2577 my $a = $e->search_actor_card({barcode => $barcode}, {idlist=>1});
2578 return $$a[0] if $a and @$a;
2583 __PACKAGE__->register_method(
2584 method => 'retrieve_net_levels',
2585 api_name => 'open-ils.actor.net_access_level.retrieve.all',
2588 sub retrieve_net_levels {
2589 my( $self, $conn, $auth ) = @_;
2590 my $e = new_editor(authtoken=>$auth);
2591 return $e->event unless $e->checkauth;
2592 return $e->retrieve_all_config_net_access_level();
2596 __PACKAGE__->register_method(
2597 method => 'fetch_org_by_shortname',
2598 api_name => 'open-ils.actor.org_unit.retrieve_by_shorname',
2600 sub fetch_org_by_shortname {
2601 my( $self, $conn, $sname ) = @_;
2602 my $e = new_editor();
2603 my $org = $e->search_actor_org_unit({ shortname => uc($sname)})->[0];
2604 return $e->event unless $org;
2609 __PACKAGE__->register_method(
2610 method => 'session_home_lib',
2611 api_name => 'open-ils.actor.session.home_lib',
2614 sub session_home_lib {
2615 my( $self, $conn, $auth ) = @_;
2616 my $e = new_editor(authtoken=>$auth);
2617 return undef unless $e->checkauth;
2618 my $org = $e->retrieve_actor_org_unit($e->requestor->home_ou);
2619 return $org->shortname;
2622 __PACKAGE__->register_method(
2623 method => 'session_safe_token',
2624 api_name => 'open-ils.actor.session.safe_token',
2626 Returns a hashed session ID that is safe for export to the world.
2627 This safe token will expire after 1 hour of non-use.
2628 @param auth Active authentication token
2632 sub session_safe_token {
2633 my( $self, $conn, $auth ) = @_;
2634 my $e = new_editor(authtoken=>$auth);
2635 return undef unless $e->checkauth;
2637 my $safe_token = md5_hex($auth);
2639 $cache ||= OpenSRF::Utils::Cache->new("global", 0);
2641 # Add more like the following if needed...
2643 "safe-token-home_lib-shortname-$safe_token",
2644 $e->retrieve_actor_org_unit(
2645 $e->requestor->home_ou
2654 __PACKAGE__->register_method(
2655 method => 'safe_token_home_lib',
2656 api_name => 'open-ils.actor.safe_token.home_lib.shortname',
2658 Returns the home library shortname from the session
2659 asscociated with a safe token from generated by
2660 open-ils.actor.session.safe_token.
2661 @param safe_token Active safe token
2665 sub safe_token_home_lib {
2666 my( $self, $conn, $safe_token ) = @_;
2668 $cache ||= OpenSRF::Utils::Cache->new("global", 0);
2669 return $cache->get_cache( 'safe-token-home_lib-shortname-'. $safe_token );
2674 __PACKAGE__->register_method(
2675 method => 'slim_tree',
2676 api_name => "open-ils.actor.org_tree.slim_hash.retrieve",
2679 my $tree = new_editor()->search_actor_org_unit(
2681 {"parent_ou" => undef },
2684 flesh_fields => { aou => ['children'] },
2685 order_by => { aou => 'name'},
2686 select => { aou => ["id","shortname", "name"]},
2691 return trim_tree($tree);
2697 return undef unless $tree;
2699 code => $tree->shortname,
2700 name => $tree->name,
2702 if( $tree->children and @{$tree->children} ) {
2703 $htree->{children} = [];
2704 for my $c (@{$tree->children}) {
2705 push( @{$htree->{children}}, trim_tree($c) );
2713 __PACKAGE__->register_method(
2714 method => "update_penalties",
2715 api_name => "open-ils.actor.user.penalties.update");
2716 sub update_penalties {
2717 my( $self, $conn, $auth, $userid ) = @_;
2718 my $e = new_editor(authtoken=>$auth);
2719 return $e->event unless $e->checkauth;
2720 $U->update_patron_penalties(
2722 patronid => $userid,
2729 __PACKAGE__->register_method(
2730 method => "user_retrieve_fleshed_by_id",
2731 api_name => "open-ils.actor.user.fleshed.retrieve",);
2733 sub user_retrieve_fleshed_by_id {
2734 my( $self, $client, $auth, $user_id, $fields ) = @_;
2735 my $e = new_editor(authtoken => $auth);
2736 return $e->event unless $e->checkauth;
2738 if( $e->requestor->id != $user_id ) {
2739 return $e->event unless $e->allowed('VIEW_USER');
2745 "standing_penalties",
2749 "stat_cat_entries" ];
2750 return new_flesh_user($user_id, $fields, $e);
2754 sub new_flesh_user {
2757 my $fields = shift || [];
2758 my $e = shift || new_editor(xact=>1);
2760 my $user = $e->retrieve_actor_user(
2765 "flesh_fields" => { "au" => $fields }
2768 ) or return $e->event;
2771 if( grep { $_ eq 'addresses' } @$fields ) {
2773 $user->addresses([]) unless @{$user->addresses};
2775 if( ref $user->billing_address ) {
2776 unless( grep { $user->billing_address->id == $_->id } @{$user->addresses} ) {
2777 push( @{$user->addresses}, $user->billing_address );
2781 if( ref $user->mailing_address ) {
2782 unless( grep { $user->mailing_address->id == $_->id } @{$user->addresses} ) {
2783 push( @{$user->addresses}, $user->mailing_address );
2789 $user->clear_passwd();
2796 __PACKAGE__->register_method(
2797 method => "user_retrieve_parts",
2798 api_name => "open-ils.actor.user.retrieve.parts",);
2800 sub user_retrieve_parts {
2801 my( $self, $client, $auth, $user_id, $fields ) = @_;
2802 my $e = new_editor(authtoken => $auth);
2803 return $e->event unless $e->checkauth;
2804 if( $e->requestor->id != $user_id ) {
2805 return $e->event unless $e->allowed('VIEW_USER');
2808 my $user = $e->retrieve_actor_user($user_id) or return $e->event;
2809 push(@resp, $user->$_()) for(@$fields);