1 package OpenILS::Application::Actor;
2 use OpenILS::Application;
3 use base qw/OpenILS::Application/;
4 use strict; use warnings;
6 $Data::Dumper::Indent = 0;
9 use Digest::MD5 qw(md5_hex);
11 use OpenSRF::EX qw(:try);
14 use OpenILS::Application::AppUtils;
16 use OpenILS::Utils::Fieldmapper;
17 use OpenILS::Utils::ModsParser;
18 use OpenSRF::Utils::Logger qw/$logger/;
19 use OpenSRF::Utils qw/:datetime/;
20 use OpenSRF::Utils::SettingsClient;
22 use OpenSRF::Utils::Cache;
24 use OpenSRF::Utils::JSON;
26 use DateTime::Format::ISO8601;
27 use OpenILS::Const qw/:const/;
29 use OpenILS::Application::Actor::Container;
30 use OpenILS::Application::Actor::ClosedDates;
32 use OpenILS::Utils::CStoreEditor qw/:funcs/;
34 use OpenILS::Application::Actor::UserGroups;
36 OpenILS::Application::Actor::Container->initialize();
37 OpenILS::Application::Actor::UserGroups->initialize();
38 OpenILS::Application::Actor::ClosedDates->initialize();
41 my $apputils = "OpenILS::Application::AppUtils";
44 sub _d { warn "Patron:\n" . Dumper(shift()); }
47 my $set_user_settings;
51 __PACKAGE__->register_method(
52 method => "update_user_setting",
53 api_name => "open-ils.actor.patron.settings.update",
55 sub update_user_setting {
56 my($self, $conn, $auth, $user_id, $settings) = @_;
57 my $e = new_editor(xact => 1, authtoken => $auth);
58 return $e->die_event unless $e->checkauth;
60 unless($e->requestor->id == $user_id) {
61 my $user = $e->retrieve_actor_user($user_id) or return $e->die_event;
62 return $e->die_event unless $e->allowed('UPDATE_USER', $user->home_ou);
65 for my $name (keys %$settings) {
66 my $val = $$settings{$name};
67 my $set = $e->search_actor_user_setting({usr => $user_id, name => $name})->[0];
70 $val = OpenSRF::Utils::JSON->perl2JSON($val);
73 $e->update_actor_user_setting($set) or return $e->die_event;
75 $set = Fieldmapper::actor::user_setting->new;
79 $e->create_actor_user_setting($set) or return $e->die_event;
82 $e->delete_actor_user_setting($set) or return $e->die_event;
91 __PACKAGE__->register_method(
92 method => "set_ou_settings",
93 api_name => "open-ils.actor.org_unit.settings.update",
96 my( $self, $client, $auth, $org_id, $settings ) = @_;
98 my $e = new_editor(authtoken => $auth, xact => 1);
99 return $e->die_event unless $e->checkauth;
101 for my $name (keys %$settings) {
102 my $val = $$settings{$name};
103 my $set = $e->search_actor_org_unit_setting({org_unit => $org_id, name => $name})->[0];
105 return $e->die_event unless $e->allowed("UPDATE_ORG_UNIT_SETTING.$name", $org_id);
108 $val = OpenSRF::Utils::JSON->perl2JSON($val);
111 $e->update_actor_org_unit_setting($set) or return $e->die_event;
113 $set = Fieldmapper::actor::org_unit_setting->new;
114 $set->org_unit($org_id);
117 $e->create_actor_org_unit_setting($set) or return $e->die_event;
120 $e->delete_actor_org_unit_setting($set) or return $e->die_event;
128 my $fetch_user_settings;
129 my $fetch_ou_settings;
131 __PACKAGE__->register_method(
132 method => "user_settings",
133 api_name => "open-ils.actor.patron.settings.retrieve",
136 my( $self, $client, $auth, $user_id, $setting ) = @_;
138 my $e = new_editor(authtoken => $auth);
139 return $e->event unless $e->checkauth;
141 my $patron = $e->retrieve_actor_user($user_id) or return $e->event;
142 if($e->requestor->id != $user_id) {
143 return $e->event unless $e->allowed('VIEW_USER', $patron->home_ou);
146 my $s = $e->search_actor_user_setting({usr => $user_id});
147 my $settings = { map { ( $_->name => OpenSRF::Utils::JSON->JSON2perl($_->value) ) } @$s };
149 return $$settings{$setting} if $setting;
155 __PACKAGE__->register_method(
156 method => "ou_settings",
157 api_name => "open-ils.actor.org_unit.settings.retrieve",
160 my( $self, $client, $ouid ) = @_;
162 $logger->info("Fetching org unit settings for org $ouid");
164 my $s = $apputils->simplereq(
166 'open-ils.cstore.direct.actor.org_unit_setting.search.atomic', {org_unit => $ouid});
168 return { map { ( $_->name => OpenSRF::Utils::JSON->JSON2perl($_->value) ) } @$s };
173 __PACKAGE__->register_method(
174 api_name => 'open-ils.actor.ou_setting.ancestor_default',
175 method => 'ou_ancestor_setting',
178 # ------------------------------------------------------------------
179 # Attempts to find the org setting value for a given org. if not
180 # found at the requested org, searches up the org tree until it
181 # finds a parent that has the requested setting.
182 # when found, returns { org => $id, value => $value }
183 # otherwise, returns NULL
184 # ------------------------------------------------------------------
185 sub ou_ancestor_setting {
186 my( $self, $client, $orgid, $name ) = @_;
187 return $U->ou_ancestor_setting($orgid, $name);
190 __PACKAGE__->register_method(
191 api_name => 'open-ils.actor.ou_setting.ancestor_default.batch',
192 method => 'ou_ancestor_setting_batch',
194 sub ou_ancestor_setting_batch {
195 my( $self, $client, $orgid, $name_list ) = @_;
197 $values{$_} = $U->ou_ancestor_setting($orgid, $_) for @$name_list;
204 __PACKAGE__->register_method (
205 method => "ou_setting_delete",
206 api_name => 'open-ils.actor.org_setting.delete',
208 Deletes a specific org unit setting for a specific location
209 @param authtoken The login session key
210 @param orgid The org unit whose setting we're changing
211 @param setting The name of the setting to delete
212 @return True value on success.
216 sub ou_setting_delete {
217 my( $self, $conn, $authtoken, $orgid, $setting ) = @_;
218 my( $reqr, $evt) = $U->checkses($authtoken);
220 $evt = $U->check_perms($reqr->id, $orgid, 'UPDATE_ORG_SETTING');
223 my $id = $U->cstorereq(
224 'open-ils.cstore.direct.actor.org_unit_setting.id_list',
225 { name => $setting, org_unit => $orgid } );
227 $logger->debug("Retrieved setting $id in org unit setting delete");
229 my $s = $U->cstorereq(
230 'open-ils.cstore.direct.actor.org_unit_setting.delete', $id );
232 $logger->activity("User ".$reqr->id." deleted org unit setting $id") if $s;
246 __PACKAGE__->register_method(
247 method => "update_patron",
248 api_name => "open-ils.actor.patron.update",);
251 my( $self, $client, $user_session, $patron ) = @_;
253 my $session = $apputils->start_db_session();
257 $logger->info("Creating new patron...") if $patron->isnew;
258 $logger->info("Updating Patron: " . $patron->id) unless $patron->isnew;
260 my( $user_obj, $evt ) = $U->checkses($user_session);
263 $evt = check_group_perm($session, $user_obj, $patron);
267 # $new_patron is the patron in progress. $patron is the original patron
268 # passed in with the method. new_patron will change as the components
269 # of patron are added/updated.
273 # unflesh the real items on the patron
274 $patron->card( $patron->card->id ) if(ref($patron->card));
275 $patron->billing_address( $patron->billing_address->id )
276 if(ref($patron->billing_address));
277 $patron->mailing_address( $patron->mailing_address->id )
278 if(ref($patron->mailing_address));
280 # create/update the patron first so we can use his id
281 if($patron->isnew()) {
282 ( $new_patron, $evt ) = _add_patron($session, _clone_patron($patron), $user_obj);
284 } else { $new_patron = $patron; }
286 ( $new_patron, $evt ) = _add_update_addresses($session, $patron, $new_patron, $user_obj);
289 ( $new_patron, $evt ) = _add_update_cards($session, $patron, $new_patron, $user_obj);
292 ( $new_patron, $evt ) = _add_survey_responses($session, $patron, $new_patron, $user_obj);
295 # re-update the patron if anything has happened to him during this process
296 if($new_patron->ischanged()) {
297 ( $new_patron, $evt ) = _update_patron($session, $new_patron, $user_obj);
301 ($new_patron, $evt) = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
304 ($new_patron, $evt) = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
307 ($new_patron, $evt) = _create_standing_penalties($session, $user_session, $patron, $new_patron, $user_obj);
310 $logger->activity("user ".$user_obj->id." updating/creating user ".$new_patron->id);
313 if(!$patron->isnew) {
314 $opatron = new_editor()->retrieve_actor_user($new_patron->id);
317 $apputils->commit_db_session($session);
318 my $fuser = flesh_user($new_patron->id());
321 # Log the new and old patron for investigation
322 $logger->info("$user_session updating patron object. orig patron object = ".
323 OpenSRF::Utils::JSON->perl2JSON($opatron). " |||| new patron = ".OpenSRF::Utils::JSON->perl2JSON($fuser));
333 return new_flesh_user($id, [
336 "standing_penalties",
340 "stat_cat_entries" ] );
348 # clone and clear stuff that would break the database
352 my $new_patron = $patron->clone;
354 $new_patron->clear_billing_address();
355 $new_patron->clear_mailing_address();
356 $new_patron->clear_addresses();
357 $new_patron->clear_card();
358 $new_patron->clear_cards();
359 $new_patron->clear_id();
360 $new_patron->clear_isnew();
361 $new_patron->clear_ischanged();
362 $new_patron->clear_isdeleted();
363 $new_patron->clear_stat_cat_entries();
364 $new_patron->clear_permissions();
365 $new_patron->clear_standing_penalties();
375 my $user_obj = shift;
377 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'CREATE_USER');
378 return (undef, $evt) if $evt;
380 my $ex = $session->request(
381 'open-ils.storage.direct.actor.user.search.usrname', $patron->usrname())->gather(1);
383 return (undef, OpenILS::Event->new('USERNAME_EXISTS'));
386 $logger->info("Creating new user in the DB with username: ".$patron->usrname());
388 my $id = $session->request(
389 "open-ils.storage.direct.actor.user.create", $patron)->gather(1);
390 return (undef, $U->DB_UPDATE_FAILED($patron)) unless $id;
392 $logger->info("Successfully created new user [$id] in DB");
394 return ( $session->request(
395 "open-ils.storage.direct.actor.user.retrieve", $id)->gather(1), undef );
399 sub check_group_perm {
400 my( $session, $requestor, $patron ) = @_;
403 # first let's see if the requestor has
404 # priveleges to update this user in any way
405 if( ! $patron->isnew ) {
406 my $p = $session->request(
407 'open-ils.storage.direct.actor.user.retrieve', $patron->id )->gather(1);
409 # If we are the requestor (trying to update our own account)
410 # and we are not trying to change our profile, we're good
411 if( $p->id == $requestor->id and
412 $p->profile == $patron->profile ) {
417 $evt = group_perm_failed($session, $requestor, $p);
421 # They are allowed to edit this patron.. can they put the
422 # patron into the group requested?
423 $evt = group_perm_failed($session, $requestor, $patron);
429 sub group_perm_failed {
430 my( $session, $requestor, $patron ) = @_;
434 my $grpid = $patron->profile;
438 $logger->debug("user update looking for group perm for group $grpid");
439 $grp = $session->request(
440 'open-ils.storage.direct.permission.grp_tree.retrieve', $grpid )->gather(1);
441 return OpenILS::Event->new('PERMISSION_GRP_TREE_NOT_FOUND') unless $grp;
443 } while( !($perm = $grp->application_perm) and ($grpid = $grp->parent) );
445 $logger->info("user update checking perm $perm on user ".
446 $requestor->id." for update/create on user username=".$patron->usrname);
448 my $evt = $U->check_perms($requestor->id, $patron->home_ou, $perm);
456 my( $session, $patron, $user_obj, $noperm) = @_;
458 $logger->info("Updating patron ".$patron->id." in DB");
463 $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'UPDATE_USER');
464 return (undef, $evt) if $evt;
467 # update the password by itself to avoid the password protection magic
468 if( $patron->passwd ) {
469 my $s = $session->request(
470 'open-ils.storage.direct.actor.user.remote_update',
471 {id => $patron->id}, {passwd => $patron->passwd})->gather(1);
472 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($s);
473 $patron->clear_passwd;
476 if(!$patron->ident_type) {
477 $patron->clear_ident_type;
478 $patron->clear_ident_value;
481 $evt = verify_last_xact($session, $patron);
482 return (undef, $evt) if $evt;
484 my $stat = $session->request(
485 "open-ils.storage.direct.actor.user.update",$patron )->gather(1);
486 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($stat);
491 sub verify_last_xact {
492 my( $session, $patron ) = @_;
493 return undef unless $patron->id and $patron->id > 0;
494 my $p = $session->request(
495 'open-ils.storage.direct.actor.user.retrieve', $patron->id)->gather(1);
496 my $xact = $p->last_xact_id;
497 return undef unless $xact;
498 $logger->info("user xact = $xact, saving with xact " . $patron->last_xact_id);
499 return OpenILS::Event->new('XACT_COLLISION')
500 if $xact != $patron->last_xact_id;
505 sub _check_dup_ident {
506 my( $session, $patron ) = @_;
508 return undef unless $patron->ident_value;
511 ident_type => $patron->ident_type,
512 ident_value => $patron->ident_value,
515 $logger->debug("patron update searching for dup ident values: " .
516 $patron->ident_type . ':' . $patron->ident_value);
518 $search->{id} = {'!=' => $patron->id} if $patron->id and $patron->id > 0;
520 my $dups = $session->request(
521 'open-ils.storage.direct.actor.user.search_where.atomic', $search )->gather(1);
524 return OpenILS::Event->new('PATRON_DUP_IDENT1', payload => $patron )
531 sub _add_update_addresses {
535 my $new_patron = shift;
539 my $current_id; # id of the address before creation
541 for my $address (@{$patron->addresses()}) {
543 next unless ref $address;
544 $current_id = $address->id();
546 if( $patron->billing_address() and
547 $patron->billing_address() == $current_id ) {
548 $logger->info("setting billing addr to $current_id");
549 $new_patron->billing_address($address->id());
550 $new_patron->ischanged(1);
553 if( $patron->mailing_address() and
554 $patron->mailing_address() == $current_id ) {
555 $new_patron->mailing_address($address->id());
556 $logger->info("setting mailing addr to $current_id");
557 $new_patron->ischanged(1);
561 if($address->isnew()) {
563 $address->usr($new_patron->id());
565 ($address, $evt) = _add_address($session,$address);
566 return (undef, $evt) if $evt;
568 # we need to get the new id
569 if( $patron->billing_address() and
570 $patron->billing_address() == $current_id ) {
571 $new_patron->billing_address($address->id());
572 $logger->info("setting billing addr to $current_id");
573 $new_patron->ischanged(1);
576 if( $patron->mailing_address() and
577 $patron->mailing_address() == $current_id ) {
578 $new_patron->mailing_address($address->id());
579 $logger->info("setting mailing addr to $current_id");
580 $new_patron->ischanged(1);
583 } elsif($address->ischanged() ) {
585 ($address, $evt) = _update_address($session, $address);
586 return (undef, $evt) if $evt;
588 } elsif($address->isdeleted() ) {
590 if( $address->id() == $new_patron->mailing_address() ) {
591 $new_patron->clear_mailing_address();
592 ($new_patron, $evt) = _update_patron($session, $new_patron);
593 return (undef, $evt) if $evt;
596 if( $address->id() == $new_patron->billing_address() ) {
597 $new_patron->clear_billing_address();
598 ($new_patron, $evt) = _update_patron($session, $new_patron);
599 return (undef, $evt) if $evt;
602 $evt = _delete_address($session, $address);
603 return (undef, $evt) if $evt;
607 return ( $new_patron, undef );
611 # adds an address to the db and returns the address with new id
613 my($session, $address) = @_;
614 $address->clear_id();
616 $logger->info("Creating new address at street ".$address->street1);
618 # put the address into the database
619 my $id = $session->request(
620 "open-ils.storage.direct.actor.user_address.create", $address )->gather(1);
621 return (undef, $U->DB_UPDATE_FAILED($address)) unless $id;
624 return ($address, undef);
628 sub _update_address {
629 my( $session, $address ) = @_;
631 $logger->info("Updating address ".$address->id." in the DB");
633 my $stat = $session->request(
634 "open-ils.storage.direct.actor.user_address.update", $address )->gather(1);
636 return (undef, $U->DB_UPDATE_FAILED($address)) unless defined($stat);
637 return ($address, undef);
642 sub _add_update_cards {
646 my $new_patron = shift;
650 my $virtual_id; #id of the card before creation
651 for my $card (@{$patron->cards()}) {
653 $card->usr($new_patron->id());
655 if(ref($card) and $card->isnew()) {
657 $virtual_id = $card->id();
658 ( $card, $evt ) = _add_card($session,$card);
659 return (undef, $evt) if $evt;
661 #if(ref($patron->card)) { $patron->card($patron->card->id); }
662 if($patron->card() == $virtual_id) {
663 $new_patron->card($card->id());
664 $new_patron->ischanged(1);
667 } elsif( ref($card) and $card->ischanged() ) {
668 $evt = _update_card($session, $card);
669 return (undef, $evt) if $evt;
673 return ( $new_patron, undef );
677 # adds an card to the db and returns the card with new id
679 my( $session, $card ) = @_;
682 $logger->info("Adding new patron card ".$card->barcode);
684 my $id = $session->request(
685 "open-ils.storage.direct.actor.card.create", $card )->gather(1);
686 return (undef, $U->DB_UPDATE_FAILED($card)) unless $id;
687 $logger->info("Successfully created patron card $id");
690 return ( $card, undef );
694 # returns event on error. returns undef otherwise
696 my( $session, $card ) = @_;
697 $logger->info("Updating patron card ".$card->id);
699 my $stat = $session->request(
700 "open-ils.storage.direct.actor.card.update", $card )->gather(1);
701 return $U->DB_UPDATE_FAILED($card) unless defined($stat);
708 # returns event on error. returns undef otherwise
709 sub _delete_address {
710 my( $session, $address ) = @_;
712 $logger->info("Deleting address ".$address->id." from DB");
714 my $stat = $session->request(
715 "open-ils.storage.direct.actor.user_address.delete", $address )->gather(1);
717 return $U->DB_UPDATE_FAILED($address) unless defined($stat);
723 sub _add_survey_responses {
724 my ($session, $patron, $new_patron) = @_;
726 $logger->info( "Updating survey responses for patron ".$new_patron->id );
728 my $responses = $patron->survey_responses;
732 $_->usr($new_patron->id) for (@$responses);
734 my $evt = $U->simplereq( "open-ils.circ",
735 "open-ils.circ.survey.submit.user_id", $responses );
737 return (undef, $evt) if defined($U->event_code($evt));
741 return ( $new_patron, undef );
745 sub _create_stat_maps {
747 my($session, $user_session, $patron, $new_patron) = @_;
749 my $maps = $patron->stat_cat_entries();
751 for my $map (@$maps) {
753 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
755 if ($map->isdeleted()) {
756 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.delete";
758 } elsif ($map->isnew()) {
759 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
764 $map->target_usr($new_patron->id);
767 $logger->info("Updating stat entry with method $method and map $map");
769 my $stat = $session->request($method, $map)->gather(1);
770 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
774 return ($new_patron, undef);
777 sub _create_perm_maps {
779 my($session, $user_session, $patron, $new_patron) = @_;
781 my $maps = $patron->permissions;
783 for my $map (@$maps) {
785 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
786 if ($map->isdeleted()) {
787 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
788 } elsif ($map->isnew()) {
789 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
794 $map->usr($new_patron->id);
796 #warn( "Updating permissions with method $method and session $user_session and map $map" );
797 $logger->info( "Updating permissions with method $method and map $map" );
799 my $stat = $session->request($method, $map)->gather(1);
800 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
804 return ($new_patron, undef);
808 __PACKAGE__->register_method(
809 method => "set_user_work_ous",
810 api_name => "open-ils.actor.user.work_ous.update",
813 sub set_user_work_ous {
819 my( $requestor, $evt ) = $apputils->checksesperm( $ses, 'ASSIGN_WORK_ORG_UNIT' );
822 my $session = $apputils->start_db_session();
824 for my $map (@$maps) {
826 my $method = "open-ils.storage.direct.permission.usr_work_ou_map.update";
827 if ($map->isdeleted()) {
828 $method = "open-ils.storage.direct.permission.usr_work_ou_map.delete";
829 } elsif ($map->isnew()) {
830 $method = "open-ils.storage.direct.permission.usr_work_ou_map.create";
834 #warn( "Updating permissions with method $method and session $ses and map $map" );
835 $logger->info( "Updating work_ou map with method $method and map $map" );
837 my $stat = $session->request($method, $map)->gather(1);
838 $logger->warn( "update failed: ".$U->DB_UPDATE_FAILED($map) ) unless defined($stat);
842 $apputils->commit_db_session($session);
844 return scalar(@$maps);
848 __PACKAGE__->register_method(
849 method => "set_user_perms",
850 api_name => "open-ils.actor.user.permissions.update",
859 my $session = $apputils->start_db_session();
861 my( $user_obj, $evt ) = $U->checkses($ses);
864 my $perms = $session->request('open-ils.storage.permission.user_perms.atomic', $user_obj->id)->gather(1);
867 $all = 1 if ($U->is_true($user_obj->super_user()));
868 $all = 1 unless ($U->check_perms($user_obj->id, $user_obj->home_ou, 'EVERYTHING'));
870 for my $map (@$maps) {
872 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
873 if ($map->isdeleted()) {
874 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
875 } elsif ($map->isnew()) {
876 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
880 next if (!$all and !grep { $_->perm eq $map->perm and $U->is_true($_->grantable) and $_->depth <= $map->depth } @$perms);
881 #warn( "Updating permissions with method $method and session $ses and map $map" );
882 $logger->info( "Updating permissions with method $method and map $map" );
884 my $stat = $session->request($method, $map)->gather(1);
885 $logger->warn( "update failed: ".$U->DB_UPDATE_FAILED($map) ) unless defined($stat);
889 $apputils->commit_db_session($session);
891 return scalar(@$maps);
895 sub _create_standing_penalties {
897 my($session, $user_session, $patron, $new_patron) = @_;
899 my $maps = $patron->standing_penalties;
902 for my $map (@$maps) {
904 if ($map->isdeleted()) {
905 $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
906 } elsif ($map->isnew()) {
907 $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
913 $map->usr($new_patron->id);
915 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
917 my $stat = $session->request($method, $map)->gather(1);
918 return (undef, $U->DB_UPDATE_FAILED($map)) unless $stat;
921 return ($new_patron, undef);
926 __PACKAGE__->register_method(
927 method => "search_username",
928 api_name => "open-ils.actor.user.search.username",
931 sub search_username {
932 my($self, $client, $username) = @_;
933 return new_editor()->search_actor_user({usrname=>$username});
939 __PACKAGE__->register_method(
940 method => "user_retrieve_by_barcode",
942 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
944 sub user_retrieve_by_barcode {
945 my($self, $client, $user_session, $barcode) = @_;
947 $logger->debug("Searching for user with barcode $barcode");
948 my ($user_obj, $evt) = $apputils->checkses($user_session);
951 my $card = OpenILS::Application::AppUtils->simple_scalar_request(
953 "open-ils.cstore.direct.actor.card.search.atomic",
954 { barcode => $barcode }
957 if(!$card || !$card->[0]) {
958 return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' );
962 my $user = flesh_user($card->usr());
964 $evt = $U->check_perms($user_obj->id, $user->home_ou, 'VIEW_USER');
967 if(!$user) { return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' ); }
974 __PACKAGE__->register_method(
975 method => "get_user_by_id",
976 api_name => "open-ils.actor.user.retrieve",);
979 my ($self, $client, $auth, $id) = @_;
980 my $e = new_editor(authtoken=>$auth);
981 return $e->event unless $e->checkauth;
982 my $user = $e->retrieve_actor_user($id)
984 return $e->event unless $e->allowed('VIEW_USER', $user->home_ou);
990 __PACKAGE__->register_method(
991 method => "get_org_types",
992 api_name => "open-ils.actor.org_types.retrieve",);
995 return $U->get_org_types();
1000 __PACKAGE__->register_method(
1001 method => "get_user_ident_types",
1002 api_name => "open-ils.actor.user.ident_types.retrieve",
1005 sub get_user_ident_types {
1006 return $ident_types if $ident_types;
1007 return $ident_types =
1008 new_editor()->retrieve_all_config_identification_type();
1014 __PACKAGE__->register_method(
1015 method => "get_org_unit",
1016 api_name => "open-ils.actor.org_unit.retrieve",
1020 my( $self, $client, $user_session, $org_id ) = @_;
1021 my $e = new_editor(authtoken => $user_session);
1023 return $e->event unless $e->checkauth;
1024 $org_id = $e->requestor->ws_ou;
1026 my $o = $e->retrieve_actor_org_unit($org_id)
1027 or return $e->event;
1031 __PACKAGE__->register_method(
1032 method => "search_org_unit",
1033 api_name => "open-ils.actor.org_unit_list.search",
1036 sub search_org_unit {
1038 my( $self, $client, $field, $value ) = @_;
1040 my $list = OpenILS::Application::AppUtils->simple_scalar_request(
1042 "open-ils.cstore.direct.actor.org_unit.search.atomic",
1043 { $field => $value } );
1049 # build the org tree
1051 __PACKAGE__->register_method(
1052 method => "get_org_tree",
1053 api_name => "open-ils.actor.org_tree.retrieve",
1055 note => "Returns the entire org tree structure",
1061 return $U->get_org_tree($client->session->session_locale);
1065 __PACKAGE__->register_method(
1066 method => "get_org_descendants",
1067 api_name => "open-ils.actor.org_tree.descendants.retrieve"
1070 # depth is optional. org_unit is the id
1071 sub get_org_descendants {
1072 my( $self, $client, $org_unit, $depth ) = @_;
1074 if(ref $org_unit eq 'ARRAY') {
1077 for my $i (0..scalar(@$org_unit)-1) {
1078 my $list = $U->simple_scalar_request(
1080 "open-ils.storage.actor.org_unit.descendants.atomic",
1081 $org_unit->[$i], $depth->[$i] );
1082 push(@trees, $U->build_org_tree($list));
1087 my $orglist = $apputils->simple_scalar_request(
1089 "open-ils.storage.actor.org_unit.descendants.atomic",
1090 $org_unit, $depth );
1091 return $U->build_org_tree($orglist);
1096 __PACKAGE__->register_method(
1097 method => "get_org_ancestors",
1098 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
1101 # depth is optional. org_unit is the id
1102 sub get_org_ancestors {
1103 my( $self, $client, $org_unit, $depth ) = @_;
1104 my $orglist = $apputils->simple_scalar_request(
1106 "open-ils.storage.actor.org_unit.ancestors.atomic",
1107 $org_unit, $depth );
1108 return $U->build_org_tree($orglist);
1112 __PACKAGE__->register_method(
1113 method => "get_standings",
1114 api_name => "open-ils.actor.standings.retrieve"
1119 return $user_standings if $user_standings;
1120 return $user_standings =
1121 $apputils->simple_scalar_request(
1123 "open-ils.cstore.direct.config.standing.search.atomic",
1124 { id => { "!=" => undef } }
1130 __PACKAGE__->register_method(
1131 method => "get_my_org_path",
1132 api_name => "open-ils.actor.org_unit.full_path.retrieve"
1135 sub get_my_org_path {
1136 my( $self, $client, $auth, $org_id ) = @_;
1137 my $e = new_editor(authtoken=>$auth);
1138 return $e->event unless $e->checkauth;
1139 $org_id = $e->requestor->ws_ou unless defined $org_id;
1141 return $apputils->simple_scalar_request(
1143 "open-ils.storage.actor.org_unit.full_path.atomic",
1148 __PACKAGE__->register_method(
1149 method => "patron_adv_search",
1150 api_name => "open-ils.actor.patron.search.advanced" );
1151 sub patron_adv_search {
1152 my( $self, $client, $auth, $search_hash,
1153 $search_limit, $search_sort, $include_inactive, $search_depth ) = @_;
1155 my $e = new_editor(authtoken=>$auth);
1156 return $e->event unless $e->checkauth;
1157 return $e->event unless $e->allowed('VIEW_USER');
1158 return $U->storagereq(
1159 "open-ils.storage.actor.user.crazy_search", $search_hash,
1160 $search_limit, $search_sort, $include_inactive, $e->requestor->ws_ou, $search_depth);
1164 __PACKAGE__->register_method(
1165 method => "update_passwd",
1167 api_name => "open-ils.actor.user.password.update");
1169 __PACKAGE__->register_method(
1170 method => "update_passwd",
1171 api_name => "open-ils.actor.user.username.update");
1173 __PACKAGE__->register_method(
1174 method => "update_passwd",
1175 api_name => "open-ils.actor.user.email.update");
1178 my( $self, $conn, $auth, $new_val, $orig_pw ) = @_;
1179 my $e = new_editor(xact=>1, authtoken=>$auth);
1180 return $e->die_event unless $e->checkauth;
1182 my $db_user = $e->retrieve_actor_user($e->requestor->id)
1183 or return $e->die_event;
1184 my $api = $self->api_name;
1186 if( $api =~ /password/o ) {
1188 # make sure the original password matches the in-database password
1189 return OpenILS::Event->new('INCORRECT_PASSWORD')
1190 if md5_hex($orig_pw) ne $db_user->passwd;
1191 $db_user->passwd($new_val);
1195 # if we don't clear the password, the user will be updated with
1196 # a hashed version of the hashed version of their password
1197 $db_user->clear_passwd;
1199 if( $api =~ /username/o ) {
1201 # make sure no one else has this username
1202 my $exist = $e->search_actor_user({usrname=>$new_val},{idlist=>1});
1203 return OpenILS::Event->new('USERNAME_EXISTS') if @$exist;
1204 $db_user->usrname($new_val);
1206 } elsif( $api =~ /email/o ) {
1207 $db_user->email($new_val);
1211 $e->update_actor_user($db_user) or return $e->die_event;
1219 __PACKAGE__->register_method(
1220 method => "check_user_perms",
1221 api_name => "open-ils.actor.user.perm.check",
1222 notes => <<" NOTES");
1223 Takes a login session, user id, an org id, and an array of perm type strings. For each
1224 perm type, if the user does *not* have the given permission it is added
1225 to a list which is returned from the method. If all permissions
1226 are allowed, an empty list is returned
1227 if the logged in user does not match 'user_id', then the logged in user must
1228 have VIEW_PERMISSION priveleges.
1231 sub check_user_perms {
1232 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1234 my( $staff, $evt ) = $apputils->checkses($login_session);
1235 return $evt if $evt;
1237 if($staff->id ne $user_id) {
1238 if( $evt = $apputils->check_perms(
1239 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1245 for my $perm (@$perm_types) {
1246 if($apputils->check_perms($user_id, $org_id, $perm)) {
1247 push @not_allowed, $perm;
1251 return \@not_allowed
1254 __PACKAGE__->register_method(
1255 method => "check_user_perms2",
1256 api_name => "open-ils.actor.user.perm.check.multi_org",
1258 Checks the permissions on a list of perms and orgs for a user
1259 @param authtoken The login session key
1260 @param user_id The id of the user to check
1261 @param orgs The array of org ids
1262 @param perms The array of permission names
1263 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1264 if the logged in user does not match 'user_id', then the logged in user must
1265 have VIEW_PERMISSION priveleges.
1268 sub check_user_perms2 {
1269 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1271 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1272 $authtoken, $user_id, 'VIEW_PERMISSION' );
1273 return $evt if $evt;
1276 for my $org (@$orgs) {
1277 for my $perm (@$perms) {
1278 if($apputils->check_perms($user_id, $org, $perm)) {
1279 push @not_allowed, [ $org, $perm ];
1284 return \@not_allowed
1288 __PACKAGE__->register_method(
1289 method => 'check_user_perms3',
1290 api_name => 'open-ils.actor.user.perm.highest_org',
1292 Returns the highest org unit id at which a user has a given permission
1293 If the requestor does not match the target user, the requestor must have
1294 'VIEW_PERMISSION' rights at the home org unit of the target user
1295 @param authtoken The login session key
1296 @param userid The id of the user in question
1297 @param perm The permission to check
1298 @return The org unit highest in the org tree within which the user has
1299 the requested permission
1302 sub check_user_perms3 {
1303 my($self, $client, $authtoken, $user_id, $perm) = @_;
1304 my $e = new_editor(authtoken=>$authtoken);
1305 return $e->event unless $e->checkauth;
1307 my $tree = $U->get_org_tree();
1309 unless($e->requestor->id == $user_id) {
1310 my $user = $e->retrieve_actor_user($user_id)
1311 or return $e->event;
1312 return $e->event unless $e->allowed('VIEW_PERMISSION', $user->home_ou);
1313 return $U->find_highest_perm_org($perm, $user_id, $user->home_ou, $tree );
1316 return $U->find_highest_perm_org($perm, $user_id, $e->requestor->ws_ou, $tree);
1320 __PACKAGE__->register_method(
1321 method => 'check_user_work_perms',
1322 api_name => 'open-ils.actor.user.work_perm.highest_org_set',
1326 Returns a set of org units which represent the highest orgs in
1327 the org tree where the user has the requested permission. The
1328 purpose of this method is to return the smallest set of org units
1329 which represent the full expanse of the user's ability to perform
1330 the requested action. The user whose perms this method should
1331 check is implied by the authtoken. /,
1333 {desc => 'authtoken', type => 'string'},
1334 {desc => 'permission name', type => 'string'},
1335 {desc => 'options hash, including "descendants", which will include all child orgs of the found perm orgs', type => 'hash'}
1337 return => {desc => 'An array of org IDs'}
1341 __PACKAGE__->register_method(
1342 method => 'check_user_work_perms',
1343 api_name => 'open-ils.actor.user.work_perm.org_tree_list',
1346 @see open-ils.actor.user.work_perm.highest_org_set
1347 Returns a list of org trees. The root of each tree
1348 is the highest org in the organization hierarchy where the user has the
1349 requested permission. Below each tree root is its full tree of descendants.
1353 __PACKAGE__->register_method(
1354 method => 'check_user_work_perms',
1355 api_name => 'open-ils.actor.user.work_perm.org_unit_list',
1358 @see open-ils.actor.user.work_perm.highest_org_set
1359 Returns a list of list of all of the org_units where the user
1360 has the requested permission. The first item in each list
1361 is the highest permission org for that section of the
1362 org tree. The remaining items in each sub-list are the
1363 descendants of that org.
1368 __PACKAGE__->register_method(
1369 method => 'check_user_work_perms',
1370 api_name => 'open-ils.actor.user.work_perm.org_id_list',
1373 @see open-ils.actor.user.work_perm.highest_org_set
1374 Returns a list of lists of all of the org_unit IDs where the user
1375 has the requested permission. The first item in each list
1376 is the highest permission org for that section of the
1377 org tree. The remaining items in each sub-list are the
1378 descendants of that org.
1382 __PACKAGE__->register_method(
1383 method => 'check_user_work_perms_batch',
1384 api_name => 'open-ils.actor.user.work_perm.highest_org_set.batch',
1387 __PACKAGE__->register_method(
1388 method => 'check_user_work_perms_batch',
1389 api_name => 'open-ils.actor.user.work_perm.org_tree_list.batch',
1392 __PACKAGE__->register_method(
1393 method => 'check_user_work_perms_batch',
1394 api_name => 'open-ils.actor.user.work_perm.org_unit_list.batch',
1397 __PACKAGE__->register_method(
1398 method => 'check_user_work_perms_batch',
1399 api_name => 'open-ils.actor.user.work_perm.org_id_list.batch',
1404 sub check_user_work_perms {
1405 my($self, $conn, $auth, $perm, $options) = @_;
1406 my $e = new_editor(authtoken=>$auth);
1407 return $e->event unless $e->checkauth;
1408 return check_user_work_perms_impl($self, $conn, $e, $perm, $options);
1411 sub check_user_work_perms_batch {
1412 my($self, $conn, $auth, $perm_list, $options) = @_;
1413 my $e = new_editor(authtoken=>$auth);
1414 return $e->event unless $e->checkauth;
1416 $map->{$_} = check_user_work_perms_impl($self, $conn, $e, $_, $options) for @$perm_list;
1420 sub check_user_work_perms_impl {
1421 my($self, $conn, $e, $perm, $options) = @_;
1422 my $orglist = $U->find_highest_work_orgs($e, $perm, $options);
1424 return $orglist if $self->api_name =~ /highest_org_set/;
1426 # build a list of org trees
1427 return get_org_descendants($self, $conn, $orglist)
1428 if $self->api_name =~ /org_tree_list/;
1431 for my $orgid (@$orglist) {
1432 my @sublist = grep {$_ ne $orgid} @{$U->get_org_descendants($orgid)};
1433 unshift @sublist, $orgid; # make sure it's at the front of the list
1434 if($self->api_name =~ /org_id_list/) {
1435 push(@list, @sublist);
1437 push(@list, @{$e->batch_retrieve_actor_org_unit(\@sublist)});
1445 __PACKAGE__->register_method(
1446 method => 'check_user_perms4',
1447 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1449 Returns the highest org unit id at which a user has a given permission
1450 If the requestor does not match the target user, the requestor must have
1451 'VIEW_PERMISSION' rights at the home org unit of the target user
1452 @param authtoken The login session key
1453 @param userid The id of the user in question
1454 @param perms An array of perm names to check
1455 @return An array of orgId's representing the org unit
1456 highest in the org tree within which the user has the requested permission
1457 The arrah of orgId's has matches the order of the perms array
1460 sub check_user_perms4 {
1461 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1463 my( $staff, $target, $org, $evt );
1465 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1466 $authtoken, $userid, 'VIEW_PERMISSION' );
1467 return $evt if $evt;
1470 return [] unless ref($perms);
1471 my $tree = $U->get_org_tree();
1473 for my $p (@$perms) {
1474 push( @arr, $U->find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1482 __PACKAGE__->register_method(
1483 method => "user_fines_summary",
1484 api_name => "open-ils.actor.user.fines.summary",
1486 notes => <<" NOTES");
1487 Returns a short summary of the users total open fines, excluding voided fines
1488 Params are login_session, user_id
1489 Returns a 'mous' object.
1492 sub user_fines_summary {
1493 my( $self, $client, $auth, $user_id ) = @_;
1494 my $e = new_editor(authtoken=>$auth);
1495 return $e->event unless $e->checkauth;
1496 my $user = $e->retrieve_actor_user($user_id)
1497 or return $e->event;
1499 if( $user_id ne $e->requestor->id ) {
1500 return $e->event unless
1501 $e->allowed('VIEW_USER_FINES_SUMMARY', $user->home_ou);
1504 # run this inside a transaction to prevent replication delay errors
1505 my $ses = $U->start_db_session();
1506 my $s = $ses->request(
1507 'open-ils.storage.money.open_user_summary.search', $user_id )->gather(1);
1508 $U->rollback_db_session($ses);
1515 __PACKAGE__->register_method(
1516 method => "user_transactions",
1517 api_name => "open-ils.actor.user.transactions",
1518 notes => <<" NOTES");
1519 Returns a list of open user transactions (mbts objects);
1520 Params are login_session, user_id
1521 Optional third parameter is the transactions type. defaults to all
1524 __PACKAGE__->register_method(
1525 method => "user_transactions",
1526 api_name => "open-ils.actor.user.transactions.have_charge",
1527 notes => <<" NOTES");
1528 Returns a list of all open user transactions (mbts objects) that have an initial charge
1529 Params are login_session, user_id
1530 Optional third parameter is the transactions type. defaults to all
1533 __PACKAGE__->register_method(
1534 method => "user_transactions",
1535 api_name => "open-ils.actor.user.transactions.have_balance",
1536 notes => <<" NOTES");
1537 Returns a list of all open user transactions (mbts objects) that have a balance
1538 Params are login_session, user_id
1539 Optional third parameter is the transactions type. defaults to all
1542 __PACKAGE__->register_method(
1543 method => "user_transactions",
1544 api_name => "open-ils.actor.user.transactions.fleshed",
1545 notes => <<" NOTES");
1546 Returns an object/hash of transaction, circ, title where transaction = an open
1547 user transactions (mbts objects), circ is the attached circluation, and title
1548 is the title the circ points to
1549 Params are login_session, user_id
1550 Optional third parameter is the transactions type. defaults to all
1553 __PACKAGE__->register_method(
1554 method => "user_transactions",
1555 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1556 notes => <<" NOTES");
1557 Returns an object/hash of transaction, circ, title where transaction = an open
1558 user transactions that has an initial charge (mbts objects), circ is the
1559 attached circluation, and title is the title the circ points to
1560 Params are login_session, user_id
1561 Optional third parameter is the transactions type. defaults to all
1564 __PACKAGE__->register_method(
1565 method => "user_transactions",
1566 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1567 notes => <<" NOTES");
1568 Returns an object/hash of transaction, circ, title where transaction = an open
1569 user transaction that has a balance (mbts objects), circ is the attached
1570 circluation, and title is the title the circ points to
1571 Params are login_session, user_id
1572 Optional third parameter is the transaction type. defaults to all
1575 __PACKAGE__->register_method(
1576 method => "user_transactions",
1577 api_name => "open-ils.actor.user.transactions.count",
1578 notes => <<" NOTES");
1579 Returns an object/hash of transaction, circ, title where transaction = an open
1580 user transactions (mbts objects), circ is the attached circluation, and title
1581 is the title the circ points to
1582 Params are login_session, user_id
1583 Optional third parameter is the transactions type. defaults to all
1586 __PACKAGE__->register_method(
1587 method => "user_transactions",
1588 api_name => "open-ils.actor.user.transactions.have_charge.count",
1589 notes => <<" NOTES");
1590 Returns an object/hash of transaction, circ, title where transaction = an open
1591 user transactions that has an initial charge (mbts objects), circ is the
1592 attached circluation, and title is the title the circ points to
1593 Params are login_session, user_id
1594 Optional third parameter is the transactions type. defaults to all
1597 __PACKAGE__->register_method(
1598 method => "user_transactions",
1599 api_name => "open-ils.actor.user.transactions.have_balance.count",
1600 notes => <<" NOTES");
1601 Returns an object/hash of transaction, circ, title where transaction = an open
1602 user transaction that has a balance (mbts objects), circ is the attached
1603 circluation, and title is the title the circ points to
1604 Params are login_session, user_id
1605 Optional third parameter is the transaction type. defaults to all
1608 __PACKAGE__->register_method(
1609 method => "user_transactions",
1610 api_name => "open-ils.actor.user.transactions.have_balance.total",
1611 notes => <<" NOTES");
1612 Returns an object/hash of transaction, circ, title where transaction = an open
1613 user transaction that has a balance (mbts objects), circ is the attached
1614 circluation, and title is the title the circ points to
1615 Params are login_session, user_id
1616 Optional third parameter is the transaction type. defaults to all
1621 sub user_transactions {
1622 my( $self, $client, $login_session, $user_id, $type ) = @_;
1624 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1625 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1626 return $evt if $evt;
1628 my $api = $self->api_name();
1632 if(defined($type)) { @xact = (xact_type => $type);
1634 } else { @xact = (); }
1637 ->method_lookup('open-ils.actor.user.transactions.history.still_open')
1638 ->run($login_session => $user_id => $type);
1640 if($api =~ /have_charge/o) {
1642 $trans = [ grep { int($_->total_owed * 100) > 0 } @$trans ];
1644 } elsif($api =~ /have_balance/o) {
1646 $trans = [ grep { int($_->balance_owed * 100) != 0 } @$trans ];
1649 $trans = [ grep { int($_->total_owed * 100) > 0 } @$trans ];
1653 if($api =~ /total/o) {
1655 for my $t (@$trans) {
1656 $total += $t->balance_owed;
1659 $logger->debug("Total balance owed by user $user_id: $total");
1663 if($api =~ /count/o) { return scalar @$trans; }
1664 if($api !~ /fleshed/o) { return $trans; }
1667 for my $t (@$trans) {
1669 if( $t->xact_type ne 'circulation' ) {
1670 push @resp, {transaction => $t};
1674 my $circ = $apputils->simple_scalar_request(
1676 "open-ils.cstore.direct.action.circulation.retrieve",
1681 my $title = $apputils->simple_scalar_request(
1683 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1684 $circ->target_copy );
1688 my $u = OpenILS::Utils::ModsParser->new();
1689 $u->start_mods_batch($title->marc());
1690 my $mods = $u->finish_mods_batch();
1691 $mods->doc_id($title->id) if $mods;
1693 push @resp, {transaction => $t, circ => $circ, record => $mods };
1701 __PACKAGE__->register_method(
1702 method => "user_transaction_retrieve",
1703 api_name => "open-ils.actor.user.transaction.fleshed.retrieve",
1705 notes => <<" NOTES");
1706 Returns a fleshedtransaction record
1708 __PACKAGE__->register_method(
1709 method => "user_transaction_retrieve",
1710 api_name => "open-ils.actor.user.transaction.retrieve",
1712 notes => <<" NOTES");
1713 Returns a transaction record
1715 sub user_transaction_retrieve {
1716 my( $self, $client, $login_session, $bill_id ) = @_;
1718 # XXX I think I'm deprecated... make sure
1720 my $trans = $apputils->simple_scalar_request(
1722 "open-ils.cstore.direct.money.billable_transaction_summary.retrieve",
1726 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1727 $login_session, $trans->usr, 'VIEW_USER_TRANSACTIONS' );
1728 return $evt if $evt;
1730 my $api = $self->api_name();
1731 if($api !~ /fleshed/o) { return $trans; }
1733 if( $trans->xact_type ne 'circulation' ) {
1734 $logger->debug("Returning non-circ transaction");
1735 return {transaction => $trans};
1738 my $circ = $apputils->simple_scalar_request(
1740 "open-ils..direct.action.circulation.retrieve",
1743 return {transaction => $trans} unless $circ;
1744 $logger->debug("Found the circ transaction");
1746 my $title = $apputils->simple_scalar_request(
1748 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1749 $circ->target_copy );
1751 return {transaction => $trans, circ => $circ } unless $title;
1752 $logger->debug("Found the circ title");
1756 my $u = OpenILS::Utils::ModsParser->new();
1757 $u->start_mods_batch($title->marc());
1758 $mods = $u->finish_mods_batch();
1760 if ($title->id == OILS_PRECAT_RECORD) {
1761 my $copy = $apputils->simple_scalar_request(
1763 "open-ils.cstore.direct.asset.copy.retrieve",
1764 $circ->target_copy );
1766 $mods = new Fieldmapper::metabib::virtual_record;
1767 $mods->doc_id(OILS_PRECAT_RECORD);
1768 $mods->title($copy->dummy_title);
1769 $mods->author($copy->dummy_author);
1773 $logger->debug("MODSized the circ title");
1775 return {transaction => $trans, circ => $circ, record => $mods };
1779 __PACKAGE__->register_method(
1780 method => "hold_request_count",
1781 api_name => "open-ils.actor.user.hold_requests.count",
1784 notes => <<" NOTES");
1785 Returns hold ready/total counts
1787 sub hold_request_count {
1788 my( $self, $client, $login_session, $userid ) = @_;
1790 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1791 $login_session, $userid, 'VIEW_HOLD' );
1792 return $evt if $evt;
1795 my $holds = $apputils->simple_scalar_request(
1797 "open-ils.cstore.direct.action.hold_request.search.atomic",
1800 fulfillment_time => {"=" => undef },
1801 cancel_time => undef,
1806 for my $h (@$holds) {
1807 next unless $h->capture_time and $h->current_copy;
1809 my $copy = $apputils->simple_scalar_request(
1811 "open-ils.cstore.direct.asset.copy.retrieve",
1815 if ($copy and $copy->status == 8) {
1820 return { total => scalar(@$holds), ready => scalar(@ready) };
1824 __PACKAGE__->register_method(
1825 method => "checkedout_count",
1826 api_name => "open-ils.actor.user.checked_out.count__",
1828 notes => <<" NOTES");
1829 Returns a transaction record
1833 sub checkedout_count {
1834 my( $self, $client, $login_session, $userid ) = @_;
1836 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1837 $login_session, $userid, 'VIEW_CIRCULATIONS' );
1838 return $evt if $evt;
1840 my $circs = $apputils->simple_scalar_request(
1842 "open-ils.cstore.direct.action.circulation.search.atomic",
1843 { usr => $userid, stop_fines => undef }
1844 #{ usr => $userid, checkin_time => {"=" => undef } }
1847 my $parser = DateTime::Format::ISO8601->new;
1850 for my $c (@$circs) {
1851 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1852 my $due = $due_dt->epoch;
1854 if ($due < DateTime->today->epoch) {
1859 return { total => scalar(@$circs), overdue => scalar(@overdue) };
1863 __PACKAGE__->register_method(
1864 method => "checked_out",
1865 api_name => "open-ils.actor.user.checked_out",
1869 Returns a structure of circulations objects sorted by
1870 out, overdue, lost, claims_returned, long_overdue.
1871 A list of IDs are returned of each type.
1872 lost, long_overdue, and claims_returned circ will not
1873 be "finished" (there is an outstanding balance or some
1874 other pending action on the circ).
1876 The .count method also includes a 'total' field which
1877 sums all "open" circs
1881 __PACKAGE__->register_method(
1882 method => "checked_out",
1883 api_name => "open-ils.actor.user.checked_out.count",
1886 signature => q/@see open-ils.actor.user.checked_out/
1890 my( $self, $conn, $auth, $userid ) = @_;
1892 my $e = new_editor(authtoken=>$auth);
1893 return $e->event unless $e->checkauth;
1895 if( $userid ne $e->requestor->id ) {
1896 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
1899 my $count = $self->api_name =~ /count/;
1900 return _checked_out( $count, $e, $userid );
1904 my( $iscount, $e, $userid ) = @_;
1905 my $meth = 'open-ils.storage.actor.user.checked_out';
1906 $meth = "$meth.count" if $iscount;
1907 return $U->storagereq($meth, $userid);
1911 sub _checked_out_WHAT {
1912 my( $iscount, $e, $userid ) = @_;
1914 my $circs = $e->search_action_circulation(
1915 { usr => $userid, stop_fines => undef });
1917 my $mcircs = $e->search_action_circulation(
1920 checkin_time => undef,
1921 xact_finish => undef,
1925 push( @$circs, @$mcircs );
1927 my $parser = DateTime::Format::ISO8601->new;
1929 # split the circs up into overdue and not-overdue circs
1931 for my $c (@$circs) {
1932 if( $c->due_date ) {
1933 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1934 my $due = $due_dt->epoch;
1935 if ($due < DateTime->today->epoch) {
1936 push @overdue, $c->id;
1945 # grab all of the lost, claims-returned, and longoverdue circs
1946 #my $open = $e->search_action_circulation(
1947 # {usr => $userid, stop_fines => { '!=' => undef }, xact_finish => undef });
1950 # these items have stop_fines, but no xact_finish, so money
1951 # is owed on them and they have not been checked in
1952 my $open = $e->search_action_circulation(
1955 stop_fines => { in => [ qw/LOST CLAIMSRETURNED LONGOVERDUE/ ] },
1956 xact_finish => undef,
1957 checkin_time => undef,
1962 my( @lost, @cr, @lo );
1963 for my $c (@$open) {
1964 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1965 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1966 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
1972 total => @$circs + @lost + @cr + @lo,
1973 out => scalar(@out),
1974 overdue => scalar(@overdue),
1975 lost => scalar(@lost),
1976 claims_returned => scalar(@cr),
1977 long_overdue => scalar(@lo)
1983 overdue => \@overdue,
1985 claims_returned => \@cr,
1986 long_overdue => \@lo
1992 __PACKAGE__->register_method(
1993 method => "checked_in_with_fines",
1994 api_name => "open-ils.actor.user.checked_in_with_fines",
1997 signature => q/@see open-ils.actor.user.checked_out/
1999 sub checked_in_with_fines {
2000 my( $self, $conn, $auth, $userid ) = @_;
2002 my $e = new_editor(authtoken=>$auth);
2003 return $e->event unless $e->checkauth;
2005 if( $userid ne $e->requestor->id ) {
2006 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
2009 # money is owed on these items and they are checked in
2010 my $open = $e->search_action_circulation(
2013 xact_finish => undef,
2014 checkin_time => { "!=" => undef },
2019 my( @lost, @cr, @lo );
2020 for my $c (@$open) {
2021 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
2022 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
2023 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
2028 claims_returned => \@cr,
2029 long_overdue => \@lo
2041 __PACKAGE__->register_method(
2042 method => "user_transaction_history",
2043 api_name => "open-ils.actor.user.transactions.history",
2045 notes => <<" NOTES");
2046 Returns a list of billable transaction ids for a user, optionally by type
2048 __PACKAGE__->register_method(
2049 method => "user_transaction_history",
2050 api_name => "open-ils.actor.user.transactions.history.have_charge",
2052 notes => <<" NOTES");
2053 Returns a list of billable transaction ids for a user that have an initial charge, optionally by type
2055 __PACKAGE__->register_method(
2056 method => "user_transaction_history",
2057 api_name => "open-ils.actor.user.transactions.history.have_balance",
2060 notes => <<" NOTES");
2061 Returns a list of billable transaction ids for a user that have a balance, optionally by type
2063 __PACKAGE__->register_method(
2064 method => "user_transaction_history",
2065 api_name => "open-ils.actor.user.transactions.history.still_open",
2067 notes => <<" NOTES");
2068 Returns a list of billable transaction ids for a user that are not finished
2070 __PACKAGE__->register_method(
2071 method => "user_transaction_history",
2072 api_name => "open-ils.actor.user.transactions.history.have_bill",
2075 notes => <<" NOTES");
2076 Returns a list of billable transaction ids for a user that has billings
2079 sub user_transaction_history {
2080 my( $self, $conn, $auth, $userid, $type ) = @_;
2082 # run inside of a transaction to prevent replication delays
2083 my $e = new_editor(xact=>1, authtoken=>$auth);
2084 return $e->die_event unless $e->checkauth;
2086 if( $e->requestor->id ne $userid ) {
2087 return $e->die_event
2088 unless $e->allowed('VIEW_USER_TRANSACTIONS');
2091 my $api = $self->api_name;
2092 my @xact_finish = (xact_finish => undef ) if ($api =~ /history.still_open$/);
2094 my @xacts = @{ $e->search_money_billable_transaction(
2095 [ { usr => $userid, @xact_finish },
2097 flesh_fields => { mbt => [ qw/billings payments grocery circulation/ ] },
2098 order_by => { mbt => 'xact_start DESC' },
2106 #my @mbts = _make_mbts( @xacts );
2107 my @mbts = $U->make_mbts( @xacts );
2109 if(defined($type)) {
2110 @mbts = grep { $_->xact_type eq $type } @mbts;
2113 if($api =~ /have_balance/o) {
2114 @mbts = grep { int($_->balance_owed * 100) != 0 } @mbts;
2117 if($api =~ /have_charge/o) {
2118 @mbts = grep { defined($_->last_billing_ts) } @mbts;
2121 if($api =~ /have_bill/o) {
2122 @mbts = grep { int($_->total_owed * 100) != 0 } @mbts;
2130 __PACKAGE__->register_method(
2131 method => "user_perms",
2132 api_name => "open-ils.actor.permissions.user_perms.retrieve",
2134 notes => <<" NOTES");
2135 Returns a list of permissions
2138 my( $self, $client, $authtoken, $user ) = @_;
2140 my( $staff, $evt ) = $apputils->checkses($authtoken);
2141 return $evt if $evt;
2143 $user ||= $staff->id;
2145 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
2149 return $apputils->simple_scalar_request(
2151 "open-ils.storage.permission.user_perms.atomic",
2155 __PACKAGE__->register_method(
2156 method => "retrieve_perms",
2157 api_name => "open-ils.actor.permissions.retrieve",
2158 notes => <<" NOTES");
2159 Returns a list of permissions
2161 sub retrieve_perms {
2162 my( $self, $client ) = @_;
2163 return $apputils->simple_scalar_request(
2165 "open-ils.cstore.direct.permission.perm_list.search.atomic",
2166 { id => { '!=' => undef } }
2170 __PACKAGE__->register_method(
2171 method => "retrieve_groups",
2172 api_name => "open-ils.actor.groups.retrieve",
2173 notes => <<" NOTES");
2174 Returns a list of user groupss
2176 sub retrieve_groups {
2177 my( $self, $client ) = @_;
2178 return new_editor()->retrieve_all_permission_grp_tree();
2181 __PACKAGE__->register_method(
2182 method => "retrieve_org_address",
2183 api_name => "open-ils.actor.org_unit.address.retrieve",
2184 notes => <<' NOTES');
2185 Returns an org_unit address by ID
2186 @param An org_address ID
2188 sub retrieve_org_address {
2189 my( $self, $client, $id ) = @_;
2190 return $apputils->simple_scalar_request(
2192 "open-ils.cstore.direct.actor.org_address.retrieve",
2197 __PACKAGE__->register_method(
2198 method => "retrieve_groups_tree",
2199 api_name => "open-ils.actor.groups.tree.retrieve",
2200 notes => <<" NOTES");
2201 Returns a list of user groups
2203 sub retrieve_groups_tree {
2204 my( $self, $client ) = @_;
2205 return new_editor()->search_permission_grp_tree(
2210 flesh_fields => { pgt => ["children"] },
2211 order_by => { pgt => 'name'}
2218 __PACKAGE__->register_method(
2219 method => "add_user_to_groups",
2220 api_name => "open-ils.actor.user.set_groups",
2221 notes => <<" NOTES");
2222 Adds a user to one or more permission groups
2225 sub add_user_to_groups {
2226 my( $self, $client, $authtoken, $userid, $groups ) = @_;
2228 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2229 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
2230 return $evt if $evt;
2232 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2233 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
2234 return $evt if $evt;
2236 $apputils->simplereq(
2238 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
2240 for my $group (@$groups) {
2241 my $link = Fieldmapper::permission::usr_grp_map->new;
2243 $link->usr($userid);
2245 my $id = $apputils->simplereq(
2247 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
2253 __PACKAGE__->register_method(
2254 method => "get_user_perm_groups",
2255 api_name => "open-ils.actor.user.get_groups",
2256 notes => <<" NOTES");
2257 Retrieve a user's permission groups.
2261 sub get_user_perm_groups {
2262 my( $self, $client, $authtoken, $userid ) = @_;
2264 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2265 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
2266 return $evt if $evt;
2268 return $apputils->simplereq(
2270 'open-ils.cstore.direct.permission.usr_grp_map.search.atomic', { usr => $userid } );
2274 __PACKAGE__->register_method(
2275 method => "get_user_work_ous",
2276 api_name => "open-ils.actor.user.get_work_ous",
2277 notes => <<" NOTES");
2278 Retrieve a user's work org units.
2280 __PACKAGE__->register_method(
2281 method => "get_user_work_ous",
2282 api_name => "open-ils.actor.user.get_work_ous.ids",
2283 notes => <<" NOTES");
2284 Retrieve a user's work org units.
2288 sub get_user_work_ous {
2289 my( $self, $client, $auth, $userid ) = @_;
2290 my $e = new_editor(authtoken=>$auth);
2291 return $e->event unless $e->checkauth;
2292 $userid ||= $e->requestor->id;
2294 if($e->requestor->id != $userid) {
2295 my $user = $e->retrieve_actor_user($userid)
2296 or return $e->event;
2297 return $e->event unless $e->allowed('ASSIGN_WORK_ORG_UNIT', $user->home_ou);
2300 return $e->search_permission_usr_work_ou_map({usr => $userid})
2301 unless $self->api_name =~ /.ids$/;
2303 # client just wants a list of org IDs
2304 return $U->get_user_work_ou_ids($e, $userid);
2310 __PACKAGE__->register_method (
2311 method => 'register_workstation',
2312 api_name => 'open-ils.actor.workstation.register.override',
2313 signature => q/@see open-ils.actor.workstation.register/);
2315 __PACKAGE__->register_method (
2316 method => 'register_workstation',
2317 api_name => 'open-ils.actor.workstation.register',
2319 Registers a new workstion in the system
2320 @param authtoken The login session key
2321 @param name The name of the workstation id
2322 @param owner The org unit that owns this workstation
2323 @return The workstation id on success, WORKSTATION_NAME_EXISTS
2324 if the name is already in use.
2327 sub register_workstation {
2328 my( $self, $conn, $authtoken, $name, $owner ) = @_;
2330 my $e = new_editor(authtoken=>$authtoken, xact=>1);
2331 return $e->die_event unless $e->checkauth;
2332 return $e->die_event unless $e->allowed('REGISTER_WORKSTATION', $owner);
2333 my $existing = $e->search_actor_workstation({name => $name})->[0];
2337 if( $self->api_name =~ /override/o ) {
2338 # workstation with the given name exists.
2340 if($owner ne $existing->owning_lib) {
2341 # if necessary, update the owning_lib of the workstation
2343 $logger->info("changing owning lib of workstation ".$existing->id.
2344 " from ".$existing->owning_lib." to $owner");
2345 return $e->die_event unless
2346 $e->allowed('UPDATE_WORKSTATION', $existing->owning_lib);
2348 return $e->die_event unless $e->allowed('UPDATE_WORKSTATION', $owner);
2350 $existing->owning_lib($owner);
2351 return $e->die_event unless $e->update_actor_workstation($existing);
2357 "attempt to register an existing workstation. returning existing ID");
2360 return $existing->id;
2363 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS')
2367 my $ws = Fieldmapper::actor::workstation->new;
2368 $ws->owning_lib($owner);
2370 $e->create_actor_workstation($ws) or return $e->die_event;
2372 return $ws->id; # note: editor sets the id on the new object for us
2375 __PACKAGE__->register_method (
2376 method => 'workstation_list',
2377 api_name => 'open-ils.actor.workstation.list',
2379 Returns a list of workstations registered at the given location
2380 @param authtoken The login session key
2381 @param ids A list of org_unit.id's for the workstation owners
2384 sub workstation_list {
2385 my( $self, $conn, $authtoken, @orgs ) = @_;
2387 my $e = new_editor(authtoken=>$authtoken);
2388 return $e->event unless $e->checkauth;
2393 unless $e->allowed('REGISTER_WORKSTATION', $o);
2394 $results{$o} = $e->search_actor_workstation({owning_lib=>$o});
2405 __PACKAGE__->register_method (
2406 method => 'fetch_patron_note',
2407 api_name => 'open-ils.actor.note.retrieve.all',
2410 Returns a list of notes for a given user
2411 Requestor must have VIEW_USER permission if pub==false and
2412 @param authtoken The login session key
2413 @param args Hash of params including
2414 patronid : the patron's id
2415 pub : true if retrieving only public notes
2419 sub fetch_patron_note {
2420 my( $self, $conn, $authtoken, $args ) = @_;
2421 my $patronid = $$args{patronid};
2423 my($reqr, $evt) = $U->checkses($authtoken);
2424 return $evt if $evt;
2427 ($patron, $evt) = $U->fetch_user($patronid);
2428 return $evt if $evt;
2431 if( $patronid ne $reqr->id ) {
2432 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2433 return $evt if $evt;
2435 return $U->cstorereq(
2436 'open-ils.cstore.direct.actor.usr_note.search.atomic',
2437 { usr => $patronid, pub => 't' } );
2440 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2441 return $evt if $evt;
2443 return $U->cstorereq(
2444 'open-ils.cstore.direct.actor.usr_note.search.atomic', { usr => $patronid } );
2447 __PACKAGE__->register_method (
2448 method => 'create_user_note',
2449 api_name => 'open-ils.actor.note.create',
2451 Creates a new note for the given user
2452 @param authtoken The login session key
2453 @param note The note object
2456 sub create_user_note {
2457 my( $self, $conn, $authtoken, $note ) = @_;
2458 my $e = new_editor(xact=>1, authtoken=>$authtoken);
2459 return $e->die_event unless $e->checkauth;
2461 my $user = $e->retrieve_actor_user($note->usr)
2462 or return $e->die_event;
2464 return $e->die_event unless
2465 $e->allowed('UPDATE_USER',$user->home_ou);
2467 $note->creator($e->requestor->id);
2468 $e->create_actor_usr_note($note) or return $e->die_event;
2474 __PACKAGE__->register_method (
2475 method => 'delete_user_note',
2476 api_name => 'open-ils.actor.note.delete',
2478 Deletes a note for the given user
2479 @param authtoken The login session key
2480 @param noteid The note id
2483 sub delete_user_note {
2484 my( $self, $conn, $authtoken, $noteid ) = @_;
2486 my $e = new_editor(xact=>1, authtoken=>$authtoken);
2487 return $e->die_event unless $e->checkauth;
2488 my $note = $e->retrieve_actor_usr_note($noteid)
2489 or return $e->die_event;
2490 my $user = $e->retrieve_actor_user($note->usr)
2491 or return $e->die_event;
2492 return $e->die_event unless
2493 $e->allowed('UPDATE_USER', $user->home_ou);
2495 $e->delete_actor_usr_note($note) or return $e->die_event;
2501 __PACKAGE__->register_method (
2502 method => 'update_user_note',
2503 api_name => 'open-ils.actor.note.update',
2505 @param authtoken The login session key
2506 @param note The note
2510 sub update_user_note {
2511 my( $self, $conn, $auth, $note ) = @_;
2512 my $e = new_editor(authtoken=>$auth, xact=>1);
2513 return $e->event unless $e->checkauth;
2514 my $patron = $e->retrieve_actor_user($note->usr)
2515 or return $e->event;
2516 return $e->event unless
2517 $e->allowed('UPDATE_USER', $patron->home_ou);
2518 $e->update_actor_user_note($note)
2519 or return $e->event;
2527 __PACKAGE__->register_method (
2528 method => 'create_closed_date',
2529 api_name => 'open-ils.actor.org_unit.closed_date.create',
2531 Creates a new closing entry for the given org_unit
2532 @param authtoken The login session key
2533 @param note The closed_date object
2536 sub create_closed_date {
2537 my( $self, $conn, $authtoken, $cd ) = @_;
2539 my( $user, $evt ) = $U->checkses($authtoken);
2540 return $evt if $evt;
2542 $evt = $U->check_perms($user->id, $cd->org_unit, 'CREATE_CLOSEING');
2543 return $evt if $evt;
2545 $logger->activity("user ".$user->id." creating library closing for ".$cd->org_unit);
2547 my $id = $U->storagereq(
2548 'open-ils.storage.direct.actor.org_unit.closed_date.create', $cd );
2549 return $U->DB_UPDATE_FAILED($cd) unless $id;
2554 __PACKAGE__->register_method (
2555 method => 'delete_closed_date',
2556 api_name => 'open-ils.actor.org_unit.closed_date.delete',
2558 Deletes a closing entry for the given org_unit
2559 @param authtoken The login session key
2560 @param noteid The close_date id
2563 sub delete_closed_date {
2564 my( $self, $conn, $authtoken, $cd ) = @_;
2566 my( $user, $evt ) = $U->checkses($authtoken);
2567 return $evt if $evt;
2570 ($cd_obj, $evt) = fetch_closed_date($cd);
2571 return $evt if $evt;
2573 $evt = $U->check_perms($user->id, $cd->org_unit, 'DELETE_CLOSEING');
2574 return $evt if $evt;
2576 $logger->activity("user ".$user->id." deleting library closing for ".$cd->org_unit);
2578 my $stat = $U->storagereq(
2579 'open-ils.storage.direct.actor.org_unit.closed_date.delete', $cd );
2580 return $U->DB_UPDATE_FAILED($cd) unless $stat;
2585 __PACKAGE__->register_method(
2586 method => 'usrname_exists',
2587 api_name => 'open-ils.actor.username.exists',
2589 Returns 1 if the requested username exists, returns 0 otherwise
2593 sub usrname_exists {
2594 my( $self, $conn, $auth, $usrname ) = @_;
2595 my $e = new_editor(authtoken=>$auth);
2596 return $e->event unless $e->checkauth;
2597 my $a = $e->search_actor_user({usrname => $usrname, deleted=>'f'}, {idlist=>1});
2598 return $$a[0] if $a and @$a;
2602 __PACKAGE__->register_method(
2603 method => 'barcode_exists',
2604 api_name => 'open-ils.actor.barcode.exists',
2607 Returns 1 if the requested barcode exists, returns 0 otherwise
2611 sub barcode_exists {
2612 my( $self, $conn, $auth, $barcode ) = @_;
2613 my $e = new_editor(authtoken=>$auth);
2614 return $e->event unless $e->checkauth;
2615 my $card = $e->search_actor_card({barcode => $barcode});
2621 #return undef unless @$card;
2622 #return $card->[0]->usr;
2626 __PACKAGE__->register_method(
2627 method => 'retrieve_net_levels',
2628 api_name => 'open-ils.actor.net_access_level.retrieve.all',
2631 sub retrieve_net_levels {
2632 my( $self, $conn, $auth ) = @_;
2633 my $e = new_editor(authtoken=>$auth);
2634 return $e->event unless $e->checkauth;
2635 return $e->retrieve_all_config_net_access_level();
2639 __PACKAGE__->register_method(
2640 method => 'fetch_org_by_shortname',
2641 api_name => 'open-ils.actor.org_unit.retrieve_by_shorname',
2643 sub fetch_org_by_shortname {
2644 my( $self, $conn, $sname ) = @_;
2645 my $e = new_editor();
2646 my $org = $e->search_actor_org_unit({ shortname => uc($sname)})->[0];
2647 return $e->event unless $org;
2652 __PACKAGE__->register_method(
2653 method => 'session_home_lib',
2654 api_name => 'open-ils.actor.session.home_lib',
2657 sub session_home_lib {
2658 my( $self, $conn, $auth ) = @_;
2659 my $e = new_editor(authtoken=>$auth);
2660 return undef unless $e->checkauth;
2661 my $org = $e->retrieve_actor_org_unit($e->requestor->home_ou);
2662 return $org->shortname;
2665 __PACKAGE__->register_method(
2666 method => 'session_safe_token',
2667 api_name => 'open-ils.actor.session.safe_token',
2669 Returns a hashed session ID that is safe for export to the world.
2670 This safe token will expire after 1 hour of non-use.
2671 @param auth Active authentication token
2675 sub session_safe_token {
2676 my( $self, $conn, $auth ) = @_;
2677 my $e = new_editor(authtoken=>$auth);
2678 return undef unless $e->checkauth;
2680 my $safe_token = md5_hex($auth);
2682 $cache ||= OpenSRF::Utils::Cache->new("global", 0);
2684 # Add more like the following if needed...
2686 "safe-token-home_lib-shortname-$safe_token",
2687 $e->retrieve_actor_org_unit(
2688 $e->requestor->home_ou
2697 __PACKAGE__->register_method(
2698 method => 'safe_token_home_lib',
2699 api_name => 'open-ils.actor.safe_token.home_lib.shortname',
2701 Returns the home library shortname from the session
2702 asscociated with a safe token from generated by
2703 open-ils.actor.session.safe_token.
2704 @param safe_token Active safe token
2708 sub safe_token_home_lib {
2709 my( $self, $conn, $safe_token ) = @_;
2711 $cache ||= OpenSRF::Utils::Cache->new("global", 0);
2712 return $cache->get_cache( 'safe-token-home_lib-shortname-'. $safe_token );
2717 __PACKAGE__->register_method(
2718 method => 'slim_tree',
2719 api_name => "open-ils.actor.org_tree.slim_hash.retrieve",
2722 my $tree = new_editor()->search_actor_org_unit(
2724 {"parent_ou" => undef },
2727 flesh_fields => { aou => ['children'] },
2728 order_by => { aou => 'name'},
2729 select => { aou => ["id","shortname", "name"]},
2734 return trim_tree($tree);
2740 return undef unless $tree;
2742 code => $tree->shortname,
2743 name => $tree->name,
2745 if( $tree->children and @{$tree->children} ) {
2746 $htree->{children} = [];
2747 for my $c (@{$tree->children}) {
2748 push( @{$htree->{children}}, trim_tree($c) );
2756 __PACKAGE__->register_method(
2757 method => "update_penalties",
2758 api_name => "open-ils.actor.user.penalties.update");
2759 sub update_penalties {
2760 my( $self, $conn, $auth, $userid ) = @_;
2761 my $e = new_editor(authtoken=>$auth);
2762 return $e->event unless $e->checkauth;
2763 $U->update_patron_penalties(
2765 patronid => $userid,
2772 __PACKAGE__->register_method(
2773 method => "user_retrieve_fleshed_by_id",
2774 api_name => "open-ils.actor.user.fleshed.retrieve",);
2776 sub user_retrieve_fleshed_by_id {
2777 my( $self, $client, $auth, $user_id, $fields ) = @_;
2778 my $e = new_editor(authtoken => $auth);
2779 return $e->event unless $e->checkauth;
2781 if( $e->requestor->id != $user_id ) {
2782 return $e->event unless $e->allowed('VIEW_USER');
2788 "standing_penalties",
2792 "stat_cat_entries" ];
2793 return new_flesh_user($user_id, $fields, $e);
2797 sub new_flesh_user {
2800 my $fields = shift || [];
2801 my $e = shift || new_editor(xact=>1);
2803 my $user = $e->retrieve_actor_user(
2808 "flesh_fields" => { "au" => $fields }
2811 ) or return $e->event;
2814 if( grep { $_ eq 'addresses' } @$fields ) {
2816 $user->addresses([]) unless @{$user->addresses};
2818 if( ref $user->billing_address ) {
2819 unless( grep { $user->billing_address->id == $_->id } @{$user->addresses} ) {
2820 push( @{$user->addresses}, $user->billing_address );
2824 if( ref $user->mailing_address ) {
2825 unless( grep { $user->mailing_address->id == $_->id } @{$user->addresses} ) {
2826 push( @{$user->addresses}, $user->mailing_address );
2832 $user->clear_passwd();
2839 __PACKAGE__->register_method(
2840 method => "user_retrieve_parts",
2841 api_name => "open-ils.actor.user.retrieve.parts",);
2843 sub user_retrieve_parts {
2844 my( $self, $client, $auth, $user_id, $fields ) = @_;
2845 my $e = new_editor(authtoken => $auth);
2846 return $e->event unless $e->checkauth;
2847 if( $e->requestor->id != $user_id ) {
2848 return $e->event unless $e->allowed('VIEW_USER');
2851 my $user = $e->retrieve_actor_user($user_id) or return $e->event;
2852 push(@resp, $user->$_()) for(@$fields);
2858 __PACKAGE__->register_method(
2859 method => 'user_opt_in_enabled',
2860 api_name => 'open-ils.actor.user.org_unit_opt_in.enabled',
2862 @return 1 if user opt-in is globally enabled, 0 otherwise.
2865 sub user_opt_in_enabled {
2866 my($self, $conn) = @_;
2867 my $sc = OpenSRF::Utils::SettingsClient->new;
2868 return 1 if lc($sc->config_value(share => user => 'opt_in')) eq 'true';
2873 __PACKAGE__->register_method(
2874 method => 'user_opt_in_at_org',
2875 api_name => 'open-ils.actor.user.org_unit_opt_in.check',
2877 @param $auth The auth token
2878 @param user_id The ID of the user to test
2879 @return 1 if the user has opted in at the specified org,
2880 event on error, and 0 otherwise. /);
2881 sub user_opt_in_at_org {
2882 my($self, $conn, $auth, $user_id) = @_;
2884 # see if we even need to enforce the opt-in value
2885 return 1 unless user_opt_in_enabled($self);
2887 my $e = new_editor(authtoken => $auth);
2888 return $e->event unless $e->checkauth;
2889 my $org_id = $e->requestor->ws_ou;
2891 my $user = $e->retrieve_actor_user($user_id) or return $e->event;
2892 return $e->event unless $e->allowed('VIEW_USER', $user->home_ou);
2894 # user is automatically opted-in at the home org
2895 return 1 if $user->home_ou eq $org_id;
2897 my $vals = $e->search_actor_usr_org_unit_opt_in(
2898 {org_unit=>$org_id, usr=>$user_id},{idlist=>1});
2904 __PACKAGE__->register_method(
2905 method => 'create_user_opt_in_at_org',
2906 api_name => 'open-ils.actor.user.org_unit_opt_in.create',
2908 @param $auth The auth token
2909 @param user_id The ID of the user to test
2910 @return The ID of the newly created object, event on error./);
2912 sub create_user_opt_in_at_org {
2913 my($self, $conn, $auth, $user_id) = @_;
2915 my $e = new_editor(authtoken => $auth, xact=>1);
2916 return $e->die_event unless $e->checkauth;
2917 my $org_id = $e->requestor->ws_ou;
2919 my $user = $e->retrieve_actor_user($user_id) or return $e->die_event;
2920 return $e->die_event unless $e->allowed('UPDATE_USER', $user->home_ou);
2922 my $opt_in = Fieldmapper::actor::usr_org_unit_opt_in->new;
2924 $opt_in->org_unit($org_id);
2925 $opt_in->usr($user_id);
2926 $opt_in->staff($e->requestor->id);
2927 $opt_in->opt_in_ts('now');
2928 $opt_in->opt_in_ws($e->requestor->wsid);
2930 $opt_in = $e->create_actor_usr_org_unit_opt_in($opt_in)
2931 or return $e->die_event;
2939 __PACKAGE__->register_method (
2940 method => 'retrieve_org_hours',
2941 api_name => 'open-ils.actor.org_unit.hours_of_operation.retrieve',
2943 Returns the hours of operation for a specified org unit
2944 @param authtoken The login session key
2945 @param org_id The org_unit ID
2949 sub retrieve_org_hours {
2950 my($self, $conn, $auth, $org_id) = @_;
2951 my $e = new_editor(authtoken => $auth);
2952 return $e->die_event unless $e->checkauth;
2953 $org_id ||= $e->requestor->ws_ou;
2954 return $e->retrieve_actor_org_unit_hours_of_operation($org_id);