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 $user_id = $e->requestor->id unless defined $user_id;
62 unless($e->requestor->id == $user_id) {
63 my $user = $e->retrieve_actor_user($user_id) or return $e->die_event;
64 return $e->die_event unless $e->allowed('UPDATE_USER', $user->home_ou);
67 for my $name (keys %$settings) {
68 my $val = $$settings{$name};
69 my $set = $e->search_actor_user_setting({usr => $user_id, name => $name})->[0];
72 $val = OpenSRF::Utils::JSON->perl2JSON($val);
75 $e->update_actor_user_setting($set) or return $e->die_event;
77 $set = Fieldmapper::actor::user_setting->new;
81 $e->create_actor_user_setting($set) or return $e->die_event;
84 $e->delete_actor_user_setting($set) or return $e->die_event;
93 __PACKAGE__->register_method(
94 method => "set_ou_settings",
95 api_name => "open-ils.actor.org_unit.settings.update",
98 my( $self, $client, $auth, $org_id, $settings ) = @_;
100 my $e = new_editor(authtoken => $auth, xact => 1);
101 return $e->die_event unless $e->checkauth;
103 for my $name (keys %$settings) {
104 my $val = $$settings{$name};
105 my $set = $e->search_actor_org_unit_setting({org_unit => $org_id, name => $name})->[0];
107 return $e->die_event unless $e->allowed("UPDATE_ORG_UNIT_SETTING.$name", $org_id);
110 $val = OpenSRF::Utils::JSON->perl2JSON($val);
113 $e->update_actor_org_unit_setting($set) or return $e->die_event;
115 $set = Fieldmapper::actor::org_unit_setting->new;
116 $set->org_unit($org_id);
119 $e->create_actor_org_unit_setting($set) or return $e->die_event;
122 $e->delete_actor_org_unit_setting($set) or return $e->die_event;
130 my $fetch_user_settings;
131 my $fetch_ou_settings;
133 __PACKAGE__->register_method(
134 method => "user_settings",
135 api_name => "open-ils.actor.patron.settings.retrieve",
138 my( $self, $client, $auth, $user_id, $setting ) = @_;
140 my $e = new_editor(authtoken => $auth);
141 return $e->event unless $e->checkauth;
142 $user_id = $e->requestor->id unless defined $user_id;
144 my $patron = $e->retrieve_actor_user($user_id) or return $e->event;
145 if($e->requestor->id != $user_id) {
146 return $e->event unless $e->allowed('VIEW_USER', $patron->home_ou);
150 my $val = $e->search_actor_user_setting({usr => $user_id, name => $setting})->[0];
151 return OpenSRF::Utils::JSON->JSON2perl($val->value);
153 my $s = $e->search_actor_user_setting({usr => $user_id});
154 return { map { ( $_->name => OpenSRF::Utils::JSON->JSON2perl($_->value) ) } @$s };
160 __PACKAGE__->register_method(
161 method => "ou_settings",
162 api_name => "open-ils.actor.org_unit.settings.retrieve",
165 my( $self, $client, $ouid ) = @_;
167 $logger->info("Fetching org unit settings for org $ouid");
169 my $s = $apputils->simplereq(
171 'open-ils.cstore.direct.actor.org_unit_setting.search.atomic', {org_unit => $ouid});
173 return { map { ( $_->name => OpenSRF::Utils::JSON->JSON2perl($_->value) ) } @$s };
178 __PACKAGE__->register_method(
179 api_name => 'open-ils.actor.ou_setting.ancestor_default',
180 method => 'ou_ancestor_setting',
183 # ------------------------------------------------------------------
184 # Attempts to find the org setting value for a given org. if not
185 # found at the requested org, searches up the org tree until it
186 # finds a parent that has the requested setting.
187 # when found, returns { org => $id, value => $value }
188 # otherwise, returns NULL
189 # ------------------------------------------------------------------
190 sub ou_ancestor_setting {
191 my( $self, $client, $orgid, $name ) = @_;
192 return $U->ou_ancestor_setting($orgid, $name);
195 __PACKAGE__->register_method(
196 api_name => 'open-ils.actor.ou_setting.ancestor_default.batch',
197 method => 'ou_ancestor_setting_batch',
199 sub ou_ancestor_setting_batch {
200 my( $self, $client, $orgid, $name_list ) = @_;
202 $values{$_} = $U->ou_ancestor_setting($orgid, $_) for @$name_list;
209 __PACKAGE__->register_method (
210 method => "ou_setting_delete",
211 api_name => 'open-ils.actor.org_setting.delete',
213 Deletes a specific org unit setting for a specific location
214 @param authtoken The login session key
215 @param orgid The org unit whose setting we're changing
216 @param setting The name of the setting to delete
217 @return True value on success.
221 sub ou_setting_delete {
222 my( $self, $conn, $authtoken, $orgid, $setting ) = @_;
223 my( $reqr, $evt) = $U->checkses($authtoken);
225 $evt = $U->check_perms($reqr->id, $orgid, 'UPDATE_ORG_SETTING');
228 my $id = $U->cstorereq(
229 'open-ils.cstore.direct.actor.org_unit_setting.id_list',
230 { name => $setting, org_unit => $orgid } );
232 $logger->debug("Retrieved setting $id in org unit setting delete");
234 my $s = $U->cstorereq(
235 'open-ils.cstore.direct.actor.org_unit_setting.delete', $id );
237 $logger->activity("User ".$reqr->id." deleted org unit setting $id") if $s;
251 __PACKAGE__->register_method(
252 method => "update_patron",
253 api_name => "open-ils.actor.patron.update",);
256 my( $self, $client, $user_session, $patron ) = @_;
258 my $session = $apputils->start_db_session();
262 $logger->info("Creating new patron...") if $patron->isnew;
263 $logger->info("Updating Patron: " . $patron->id) unless $patron->isnew;
265 my( $user_obj, $evt ) = $U->checkses($user_session);
268 $evt = check_group_perm($session, $user_obj, $patron);
272 # $new_patron is the patron in progress. $patron is the original patron
273 # passed in with the method. new_patron will change as the components
274 # of patron are added/updated.
278 # unflesh the real items on the patron
279 $patron->card( $patron->card->id ) if(ref($patron->card));
280 $patron->billing_address( $patron->billing_address->id )
281 if(ref($patron->billing_address));
282 $patron->mailing_address( $patron->mailing_address->id )
283 if(ref($patron->mailing_address));
285 # create/update the patron first so we can use his id
286 if($patron->isnew()) {
287 ( $new_patron, $evt ) = _add_patron($session, _clone_patron($patron), $user_obj);
289 } else { $new_patron = $patron; }
291 ( $new_patron, $evt ) = _add_update_addresses($session, $patron, $new_patron, $user_obj);
294 ( $new_patron, $evt ) = _add_update_cards($session, $patron, $new_patron, $user_obj);
297 ( $new_patron, $evt ) = _add_survey_responses($session, $patron, $new_patron, $user_obj);
300 # re-update the patron if anything has happened to him during this process
301 if($new_patron->ischanged()) {
302 ( $new_patron, $evt ) = _update_patron($session, $new_patron, $user_obj);
306 ($new_patron, $evt) = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
309 ($new_patron, $evt) = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
312 ($new_patron, $evt) = _create_standing_penalties($session, $user_session, $patron, $new_patron, $user_obj);
315 $logger->activity("user ".$user_obj->id." updating/creating user ".$new_patron->id);
318 if(!$patron->isnew) {
319 $opatron = new_editor()->retrieve_actor_user($new_patron->id);
322 $apputils->commit_db_session($session);
323 my $fuser = flesh_user($new_patron->id());
326 # Log the new and old patron for investigation
327 $logger->info("$user_session updating patron object. orig patron object = ".
328 OpenSRF::Utils::JSON->perl2JSON($opatron). " |||| new patron = ".OpenSRF::Utils::JSON->perl2JSON($fuser));
338 return new_flesh_user($id, [
341 "standing_penalties",
345 "stat_cat_entries" ] );
353 # clone and clear stuff that would break the database
357 my $new_patron = $patron->clone;
359 $new_patron->clear_billing_address();
360 $new_patron->clear_mailing_address();
361 $new_patron->clear_addresses();
362 $new_patron->clear_card();
363 $new_patron->clear_cards();
364 $new_patron->clear_id();
365 $new_patron->clear_isnew();
366 $new_patron->clear_ischanged();
367 $new_patron->clear_isdeleted();
368 $new_patron->clear_stat_cat_entries();
369 $new_patron->clear_permissions();
370 $new_patron->clear_standing_penalties();
380 my $user_obj = shift;
382 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'CREATE_USER');
383 return (undef, $evt) if $evt;
385 my $ex = $session->request(
386 'open-ils.storage.direct.actor.user.search.usrname', $patron->usrname())->gather(1);
388 return (undef, OpenILS::Event->new('USERNAME_EXISTS'));
391 $logger->info("Creating new user in the DB with username: ".$patron->usrname());
393 my $id = $session->request(
394 "open-ils.storage.direct.actor.user.create", $patron)->gather(1);
395 return (undef, $U->DB_UPDATE_FAILED($patron)) unless $id;
397 $logger->info("Successfully created new user [$id] in DB");
399 return ( $session->request(
400 "open-ils.storage.direct.actor.user.retrieve", $id)->gather(1), undef );
404 sub check_group_perm {
405 my( $session, $requestor, $patron ) = @_;
408 # first let's see if the requestor has
409 # priveleges to update this user in any way
410 if( ! $patron->isnew ) {
411 my $p = $session->request(
412 'open-ils.storage.direct.actor.user.retrieve', $patron->id )->gather(1);
414 # If we are the requestor (trying to update our own account)
415 # and we are not trying to change our profile, we're good
416 if( $p->id == $requestor->id and
417 $p->profile == $patron->profile ) {
422 $evt = group_perm_failed($session, $requestor, $p);
426 # They are allowed to edit this patron.. can they put the
427 # patron into the group requested?
428 $evt = group_perm_failed($session, $requestor, $patron);
434 sub group_perm_failed {
435 my( $session, $requestor, $patron ) = @_;
439 my $grpid = $patron->profile;
443 $logger->debug("user update looking for group perm for group $grpid");
444 $grp = $session->request(
445 'open-ils.storage.direct.permission.grp_tree.retrieve', $grpid )->gather(1);
446 return OpenILS::Event->new('PERMISSION_GRP_TREE_NOT_FOUND') unless $grp;
448 } while( !($perm = $grp->application_perm) and ($grpid = $grp->parent) );
450 $logger->info("user update checking perm $perm on user ".
451 $requestor->id." for update/create on user username=".$patron->usrname);
453 my $evt = $U->check_perms($requestor->id, $patron->home_ou, $perm);
461 my( $session, $patron, $user_obj, $noperm) = @_;
463 $logger->info("Updating patron ".$patron->id." in DB");
468 $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'UPDATE_USER');
469 return (undef, $evt) if $evt;
472 # update the password by itself to avoid the password protection magic
473 if( $patron->passwd ) {
474 my $s = $session->request(
475 'open-ils.storage.direct.actor.user.remote_update',
476 {id => $patron->id}, {passwd => $patron->passwd})->gather(1);
477 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($s);
478 $patron->clear_passwd;
481 if(!$patron->ident_type) {
482 $patron->clear_ident_type;
483 $patron->clear_ident_value;
486 $evt = verify_last_xact($session, $patron);
487 return (undef, $evt) if $evt;
489 my $stat = $session->request(
490 "open-ils.storage.direct.actor.user.update",$patron )->gather(1);
491 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($stat);
496 sub verify_last_xact {
497 my( $session, $patron ) = @_;
498 return undef unless $patron->id and $patron->id > 0;
499 my $p = $session->request(
500 'open-ils.storage.direct.actor.user.retrieve', $patron->id)->gather(1);
501 my $xact = $p->last_xact_id;
502 return undef unless $xact;
503 $logger->info("user xact = $xact, saving with xact " . $patron->last_xact_id);
504 return OpenILS::Event->new('XACT_COLLISION')
505 if $xact != $patron->last_xact_id;
510 sub _check_dup_ident {
511 my( $session, $patron ) = @_;
513 return undef unless $patron->ident_value;
516 ident_type => $patron->ident_type,
517 ident_value => $patron->ident_value,
520 $logger->debug("patron update searching for dup ident values: " .
521 $patron->ident_type . ':' . $patron->ident_value);
523 $search->{id} = {'!=' => $patron->id} if $patron->id and $patron->id > 0;
525 my $dups = $session->request(
526 'open-ils.storage.direct.actor.user.search_where.atomic', $search )->gather(1);
529 return OpenILS::Event->new('PATRON_DUP_IDENT1', payload => $patron )
536 sub _add_update_addresses {
540 my $new_patron = shift;
544 my $current_id; # id of the address before creation
546 for my $address (@{$patron->addresses()}) {
548 next unless ref $address;
549 $current_id = $address->id();
551 if( $patron->billing_address() and
552 $patron->billing_address() == $current_id ) {
553 $logger->info("setting billing addr to $current_id");
554 $new_patron->billing_address($address->id());
555 $new_patron->ischanged(1);
558 if( $patron->mailing_address() and
559 $patron->mailing_address() == $current_id ) {
560 $new_patron->mailing_address($address->id());
561 $logger->info("setting mailing addr to $current_id");
562 $new_patron->ischanged(1);
566 if($address->isnew()) {
568 $address->usr($new_patron->id());
570 ($address, $evt) = _add_address($session,$address);
571 return (undef, $evt) if $evt;
573 # we need to get the new id
574 if( $patron->billing_address() and
575 $patron->billing_address() == $current_id ) {
576 $new_patron->billing_address($address->id());
577 $logger->info("setting billing addr to $current_id");
578 $new_patron->ischanged(1);
581 if( $patron->mailing_address() and
582 $patron->mailing_address() == $current_id ) {
583 $new_patron->mailing_address($address->id());
584 $logger->info("setting mailing addr to $current_id");
585 $new_patron->ischanged(1);
588 } elsif($address->ischanged() ) {
590 ($address, $evt) = _update_address($session, $address);
591 return (undef, $evt) if $evt;
593 } elsif($address->isdeleted() ) {
595 if( $address->id() == $new_patron->mailing_address() ) {
596 $new_patron->clear_mailing_address();
597 ($new_patron, $evt) = _update_patron($session, $new_patron);
598 return (undef, $evt) if $evt;
601 if( $address->id() == $new_patron->billing_address() ) {
602 $new_patron->clear_billing_address();
603 ($new_patron, $evt) = _update_patron($session, $new_patron);
604 return (undef, $evt) if $evt;
607 $evt = _delete_address($session, $address);
608 return (undef, $evt) if $evt;
612 return ( $new_patron, undef );
616 # adds an address to the db and returns the address with new id
618 my($session, $address) = @_;
619 $address->clear_id();
621 $logger->info("Creating new address at street ".$address->street1);
623 # put the address into the database
624 my $id = $session->request(
625 "open-ils.storage.direct.actor.user_address.create", $address )->gather(1);
626 return (undef, $U->DB_UPDATE_FAILED($address)) unless $id;
629 return ($address, undef);
633 sub _update_address {
634 my( $session, $address ) = @_;
636 $logger->info("Updating address ".$address->id." in the DB");
638 my $stat = $session->request(
639 "open-ils.storage.direct.actor.user_address.update", $address )->gather(1);
641 return (undef, $U->DB_UPDATE_FAILED($address)) unless defined($stat);
642 return ($address, undef);
647 sub _add_update_cards {
651 my $new_patron = shift;
655 my $virtual_id; #id of the card before creation
656 for my $card (@{$patron->cards()}) {
658 $card->usr($new_patron->id());
660 if(ref($card) and $card->isnew()) {
662 $virtual_id = $card->id();
663 ( $card, $evt ) = _add_card($session,$card);
664 return (undef, $evt) if $evt;
666 #if(ref($patron->card)) { $patron->card($patron->card->id); }
667 if($patron->card() == $virtual_id) {
668 $new_patron->card($card->id());
669 $new_patron->ischanged(1);
672 } elsif( ref($card) and $card->ischanged() ) {
673 $evt = _update_card($session, $card);
674 return (undef, $evt) if $evt;
678 return ( $new_patron, undef );
682 # adds an card to the db and returns the card with new id
684 my( $session, $card ) = @_;
687 $logger->info("Adding new patron card ".$card->barcode);
689 my $id = $session->request(
690 "open-ils.storage.direct.actor.card.create", $card )->gather(1);
691 return (undef, $U->DB_UPDATE_FAILED($card)) unless $id;
692 $logger->info("Successfully created patron card $id");
695 return ( $card, undef );
699 # returns event on error. returns undef otherwise
701 my( $session, $card ) = @_;
702 $logger->info("Updating patron card ".$card->id);
704 my $stat = $session->request(
705 "open-ils.storage.direct.actor.card.update", $card )->gather(1);
706 return $U->DB_UPDATE_FAILED($card) unless defined($stat);
713 # returns event on error. returns undef otherwise
714 sub _delete_address {
715 my( $session, $address ) = @_;
717 $logger->info("Deleting address ".$address->id." from DB");
719 my $stat = $session->request(
720 "open-ils.storage.direct.actor.user_address.delete", $address )->gather(1);
722 return $U->DB_UPDATE_FAILED($address) unless defined($stat);
728 sub _add_survey_responses {
729 my ($session, $patron, $new_patron) = @_;
731 $logger->info( "Updating survey responses for patron ".$new_patron->id );
733 my $responses = $patron->survey_responses;
737 $_->usr($new_patron->id) for (@$responses);
739 my $evt = $U->simplereq( "open-ils.circ",
740 "open-ils.circ.survey.submit.user_id", $responses );
742 return (undef, $evt) if defined($U->event_code($evt));
746 return ( $new_patron, undef );
750 sub _create_stat_maps {
752 my($session, $user_session, $patron, $new_patron) = @_;
754 my $maps = $patron->stat_cat_entries();
756 for my $map (@$maps) {
758 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
760 if ($map->isdeleted()) {
761 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.delete";
763 } elsif ($map->isnew()) {
764 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
769 $map->target_usr($new_patron->id);
772 $logger->info("Updating stat entry with method $method and map $map");
774 my $stat = $session->request($method, $map)->gather(1);
775 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
779 return ($new_patron, undef);
782 sub _create_perm_maps {
784 my($session, $user_session, $patron, $new_patron) = @_;
786 my $maps = $patron->permissions;
788 for my $map (@$maps) {
790 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
791 if ($map->isdeleted()) {
792 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
793 } elsif ($map->isnew()) {
794 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
799 $map->usr($new_patron->id);
801 #warn( "Updating permissions with method $method and session $user_session and map $map" );
802 $logger->info( "Updating permissions with method $method and map $map" );
804 my $stat = $session->request($method, $map)->gather(1);
805 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
809 return ($new_patron, undef);
813 __PACKAGE__->register_method(
814 method => "set_user_work_ous",
815 api_name => "open-ils.actor.user.work_ous.update",
818 sub set_user_work_ous {
824 my( $requestor, $evt ) = $apputils->checksesperm( $ses, 'ASSIGN_WORK_ORG_UNIT' );
827 my $session = $apputils->start_db_session();
829 for my $map (@$maps) {
831 my $method = "open-ils.storage.direct.permission.usr_work_ou_map.update";
832 if ($map->isdeleted()) {
833 $method = "open-ils.storage.direct.permission.usr_work_ou_map.delete";
834 } elsif ($map->isnew()) {
835 $method = "open-ils.storage.direct.permission.usr_work_ou_map.create";
839 #warn( "Updating permissions with method $method and session $ses and map $map" );
840 $logger->info( "Updating work_ou map with method $method and map $map" );
842 my $stat = $session->request($method, $map)->gather(1);
843 $logger->warn( "update failed: ".$U->DB_UPDATE_FAILED($map) ) unless defined($stat);
847 $apputils->commit_db_session($session);
849 return scalar(@$maps);
853 __PACKAGE__->register_method(
854 method => "set_user_perms",
855 api_name => "open-ils.actor.user.permissions.update",
864 my $session = $apputils->start_db_session();
866 my( $user_obj, $evt ) = $U->checkses($ses);
869 my $perms = $session->request('open-ils.storage.permission.user_perms.atomic', $user_obj->id)->gather(1);
872 $all = 1 if ($U->is_true($user_obj->super_user()));
873 $all = 1 unless ($U->check_perms($user_obj->id, $user_obj->home_ou, 'EVERYTHING'));
875 for my $map (@$maps) {
877 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
878 if ($map->isdeleted()) {
879 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
880 } elsif ($map->isnew()) {
881 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
885 next if (!$all and !grep { $_->perm eq $map->perm and $U->is_true($_->grantable) and $_->depth <= $map->depth } @$perms);
886 #warn( "Updating permissions with method $method and session $ses and map $map" );
887 $logger->info( "Updating permissions with method $method and map $map" );
889 my $stat = $session->request($method, $map)->gather(1);
890 $logger->warn( "update failed: ".$U->DB_UPDATE_FAILED($map) ) unless defined($stat);
894 $apputils->commit_db_session($session);
896 return scalar(@$maps);
900 sub _create_standing_penalties {
902 my($session, $user_session, $patron, $new_patron) = @_;
904 my $maps = $patron->standing_penalties;
907 for my $map (@$maps) {
909 if ($map->isdeleted()) {
910 $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
911 } elsif ($map->isnew()) {
912 $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
918 $map->usr($new_patron->id);
920 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
922 my $stat = $session->request($method, $map)->gather(1);
923 return (undef, $U->DB_UPDATE_FAILED($map)) unless $stat;
926 return ($new_patron, undef);
931 __PACKAGE__->register_method(
932 method => "search_username",
933 api_name => "open-ils.actor.user.search.username",
936 sub search_username {
937 my($self, $client, $username) = @_;
938 return new_editor()->search_actor_user({usrname=>$username});
944 __PACKAGE__->register_method(
945 method => "user_retrieve_by_barcode",
947 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
949 sub user_retrieve_by_barcode {
950 my($self, $client, $user_session, $barcode) = @_;
952 $logger->debug("Searching for user with barcode $barcode");
953 my ($user_obj, $evt) = $apputils->checkses($user_session);
956 my $card = OpenILS::Application::AppUtils->simple_scalar_request(
958 "open-ils.cstore.direct.actor.card.search.atomic",
959 { barcode => $barcode }
962 if(!$card || !$card->[0]) {
963 return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' );
967 my $user = flesh_user($card->usr());
969 $evt = $U->check_perms($user_obj->id, $user->home_ou, 'VIEW_USER');
972 if(!$user) { return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' ); }
979 __PACKAGE__->register_method(
980 method => "get_user_by_id",
981 api_name => "open-ils.actor.user.retrieve",);
984 my ($self, $client, $auth, $id) = @_;
985 my $e = new_editor(authtoken=>$auth);
986 return $e->event unless $e->checkauth;
987 my $user = $e->retrieve_actor_user($id)
989 return $e->event unless $e->allowed('VIEW_USER', $user->home_ou);
995 __PACKAGE__->register_method(
996 method => "get_org_types",
997 api_name => "open-ils.actor.org_types.retrieve",);
1000 return $U->get_org_types();
1005 __PACKAGE__->register_method(
1006 method => "get_user_ident_types",
1007 api_name => "open-ils.actor.user.ident_types.retrieve",
1010 sub get_user_ident_types {
1011 return $ident_types if $ident_types;
1012 return $ident_types =
1013 new_editor()->retrieve_all_config_identification_type();
1019 __PACKAGE__->register_method(
1020 method => "get_org_unit",
1021 api_name => "open-ils.actor.org_unit.retrieve",
1025 my( $self, $client, $user_session, $org_id ) = @_;
1026 my $e = new_editor(authtoken => $user_session);
1028 return $e->event unless $e->checkauth;
1029 $org_id = $e->requestor->ws_ou;
1031 my $o = $e->retrieve_actor_org_unit($org_id)
1032 or return $e->event;
1036 __PACKAGE__->register_method(
1037 method => "search_org_unit",
1038 api_name => "open-ils.actor.org_unit_list.search",
1041 sub search_org_unit {
1043 my( $self, $client, $field, $value ) = @_;
1045 my $list = OpenILS::Application::AppUtils->simple_scalar_request(
1047 "open-ils.cstore.direct.actor.org_unit.search.atomic",
1048 { $field => $value } );
1054 # build the org tree
1056 __PACKAGE__->register_method(
1057 method => "get_org_tree",
1058 api_name => "open-ils.actor.org_tree.retrieve",
1060 note => "Returns the entire org tree structure",
1066 return $U->get_org_tree($client->session->session_locale);
1070 __PACKAGE__->register_method(
1071 method => "get_org_descendants",
1072 api_name => "open-ils.actor.org_tree.descendants.retrieve"
1075 # depth is optional. org_unit is the id
1076 sub get_org_descendants {
1077 my( $self, $client, $org_unit, $depth ) = @_;
1079 if(ref $org_unit eq 'ARRAY') {
1082 for my $i (0..scalar(@$org_unit)-1) {
1083 my $list = $U->simple_scalar_request(
1085 "open-ils.storage.actor.org_unit.descendants.atomic",
1086 $org_unit->[$i], $depth->[$i] );
1087 push(@trees, $U->build_org_tree($list));
1092 my $orglist = $apputils->simple_scalar_request(
1094 "open-ils.storage.actor.org_unit.descendants.atomic",
1095 $org_unit, $depth );
1096 return $U->build_org_tree($orglist);
1101 __PACKAGE__->register_method(
1102 method => "get_org_ancestors",
1103 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
1106 # depth is optional. org_unit is the id
1107 sub get_org_ancestors {
1108 my( $self, $client, $org_unit, $depth ) = @_;
1109 my $orglist = $apputils->simple_scalar_request(
1111 "open-ils.storage.actor.org_unit.ancestors.atomic",
1112 $org_unit, $depth );
1113 return $U->build_org_tree($orglist);
1117 __PACKAGE__->register_method(
1118 method => "get_standings",
1119 api_name => "open-ils.actor.standings.retrieve"
1124 return $user_standings if $user_standings;
1125 return $user_standings =
1126 $apputils->simple_scalar_request(
1128 "open-ils.cstore.direct.config.standing.search.atomic",
1129 { id => { "!=" => undef } }
1135 __PACKAGE__->register_method(
1136 method => "get_my_org_path",
1137 api_name => "open-ils.actor.org_unit.full_path.retrieve"
1140 sub get_my_org_path {
1141 my( $self, $client, $auth, $org_id ) = @_;
1142 my $e = new_editor(authtoken=>$auth);
1143 return $e->event unless $e->checkauth;
1144 $org_id = $e->requestor->ws_ou unless defined $org_id;
1146 return $apputils->simple_scalar_request(
1148 "open-ils.storage.actor.org_unit.full_path.atomic",
1153 __PACKAGE__->register_method(
1154 method => "patron_adv_search",
1155 api_name => "open-ils.actor.patron.search.advanced" );
1156 sub patron_adv_search {
1157 my( $self, $client, $auth, $search_hash,
1158 $search_limit, $search_sort, $include_inactive, $search_depth ) = @_;
1160 my $e = new_editor(authtoken=>$auth);
1161 return $e->event unless $e->checkauth;
1162 return $e->event unless $e->allowed('VIEW_USER');
1163 return $U->storagereq(
1164 "open-ils.storage.actor.user.crazy_search", $search_hash,
1165 $search_limit, $search_sort, $include_inactive, $e->requestor->ws_ou, $search_depth);
1169 __PACKAGE__->register_method(
1170 method => "update_passwd",
1172 api_name => "open-ils.actor.user.password.update");
1174 __PACKAGE__->register_method(
1175 method => "update_passwd",
1176 api_name => "open-ils.actor.user.username.update");
1178 __PACKAGE__->register_method(
1179 method => "update_passwd",
1180 api_name => "open-ils.actor.user.email.update");
1183 my( $self, $conn, $auth, $new_val, $orig_pw ) = @_;
1184 my $e = new_editor(xact=>1, authtoken=>$auth);
1185 return $e->die_event unless $e->checkauth;
1187 my $db_user = $e->retrieve_actor_user($e->requestor->id)
1188 or return $e->die_event;
1189 my $api = $self->api_name;
1191 if( $api =~ /password/o ) {
1193 # make sure the original password matches the in-database password
1194 return OpenILS::Event->new('INCORRECT_PASSWORD')
1195 if md5_hex($orig_pw) ne $db_user->passwd;
1196 $db_user->passwd($new_val);
1200 # if we don't clear the password, the user will be updated with
1201 # a hashed version of the hashed version of their password
1202 $db_user->clear_passwd;
1204 if( $api =~ /username/o ) {
1206 # make sure no one else has this username
1207 my $exist = $e->search_actor_user({usrname=>$new_val},{idlist=>1});
1208 return OpenILS::Event->new('USERNAME_EXISTS') if @$exist;
1209 $db_user->usrname($new_val);
1211 } elsif( $api =~ /email/o ) {
1212 $db_user->email($new_val);
1216 $e->update_actor_user($db_user) or return $e->die_event;
1224 __PACKAGE__->register_method(
1225 method => "check_user_perms",
1226 api_name => "open-ils.actor.user.perm.check",
1227 notes => <<" NOTES");
1228 Takes a login session, user id, an org id, and an array of perm type strings. For each
1229 perm type, if the user does *not* have the given permission it is added
1230 to a list which is returned from the method. If all permissions
1231 are allowed, an empty list is returned
1232 if the logged in user does not match 'user_id', then the logged in user must
1233 have VIEW_PERMISSION priveleges.
1236 sub check_user_perms {
1237 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1239 my( $staff, $evt ) = $apputils->checkses($login_session);
1240 return $evt if $evt;
1242 if($staff->id ne $user_id) {
1243 if( $evt = $apputils->check_perms(
1244 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1250 for my $perm (@$perm_types) {
1251 if($apputils->check_perms($user_id, $org_id, $perm)) {
1252 push @not_allowed, $perm;
1256 return \@not_allowed
1259 __PACKAGE__->register_method(
1260 method => "check_user_perms2",
1261 api_name => "open-ils.actor.user.perm.check.multi_org",
1263 Checks the permissions on a list of perms and orgs for a user
1264 @param authtoken The login session key
1265 @param user_id The id of the user to check
1266 @param orgs The array of org ids
1267 @param perms The array of permission names
1268 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1269 if the logged in user does not match 'user_id', then the logged in user must
1270 have VIEW_PERMISSION priveleges.
1273 sub check_user_perms2 {
1274 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1276 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1277 $authtoken, $user_id, 'VIEW_PERMISSION' );
1278 return $evt if $evt;
1281 for my $org (@$orgs) {
1282 for my $perm (@$perms) {
1283 if($apputils->check_perms($user_id, $org, $perm)) {
1284 push @not_allowed, [ $org, $perm ];
1289 return \@not_allowed
1293 __PACKAGE__->register_method(
1294 method => 'check_user_perms3',
1295 api_name => 'open-ils.actor.user.perm.highest_org',
1297 Returns the highest org unit id at which a user has a given permission
1298 If the requestor does not match the target user, the requestor must have
1299 'VIEW_PERMISSION' rights at the home org unit of the target user
1300 @param authtoken The login session key
1301 @param userid The id of the user in question
1302 @param perm The permission to check
1303 @return The org unit highest in the org tree within which the user has
1304 the requested permission
1307 sub check_user_perms3 {
1308 my($self, $client, $authtoken, $user_id, $perm) = @_;
1309 my $e = new_editor(authtoken=>$authtoken);
1310 return $e->event unless $e->checkauth;
1312 my $tree = $U->get_org_tree();
1314 unless($e->requestor->id == $user_id) {
1315 my $user = $e->retrieve_actor_user($user_id)
1316 or return $e->event;
1317 return $e->event unless $e->allowed('VIEW_PERMISSION', $user->home_ou);
1318 return $U->find_highest_perm_org($perm, $user_id, $user->home_ou, $tree );
1321 return $U->find_highest_perm_org($perm, $user_id, $e->requestor->ws_ou, $tree);
1325 __PACKAGE__->register_method(
1326 method => 'check_user_work_perms',
1327 api_name => 'open-ils.actor.user.work_perm.highest_org_set',
1331 Returns a set of org units which represent the highest orgs in
1332 the org tree where the user has the requested permission. The
1333 purpose of this method is to return the smallest set of org units
1334 which represent the full expanse of the user's ability to perform
1335 the requested action. The user whose perms this method should
1336 check is implied by the authtoken. /,
1338 {desc => 'authtoken', type => 'string'},
1339 {desc => 'permission name', type => 'string'},
1340 {desc => 'options hash, including "descendants", which will include all child orgs of the found perm orgs', type => 'hash'}
1342 return => {desc => 'An array of org IDs'}
1346 __PACKAGE__->register_method(
1347 method => 'check_user_work_perms',
1348 api_name => 'open-ils.actor.user.work_perm.org_tree_list',
1351 @see open-ils.actor.user.work_perm.highest_org_set
1352 Returns a list of org trees. The root of each tree
1353 is the highest org in the organization hierarchy where the user has the
1354 requested permission. Below each tree root is its full tree of descendants.
1358 __PACKAGE__->register_method(
1359 method => 'check_user_work_perms',
1360 api_name => 'open-ils.actor.user.work_perm.org_unit_list',
1363 @see open-ils.actor.user.work_perm.highest_org_set
1364 Returns a list of list of all of the org_units where the user
1365 has the requested permission. The first item in each list
1366 is the highest permission org for that section of the
1367 org tree. The remaining items in each sub-list are the
1368 descendants of that org.
1373 __PACKAGE__->register_method(
1374 method => 'check_user_work_perms',
1375 api_name => 'open-ils.actor.user.work_perm.org_id_list',
1378 @see open-ils.actor.user.work_perm.highest_org_set
1379 Returns a list of lists of all of the org_unit IDs where the user
1380 has the requested permission. The first item in each list
1381 is the highest permission org for that section of the
1382 org tree. The remaining items in each sub-list are the
1383 descendants of that org.
1387 __PACKAGE__->register_method(
1388 method => 'check_user_work_perms_batch',
1389 api_name => 'open-ils.actor.user.work_perm.highest_org_set.batch',
1392 __PACKAGE__->register_method(
1393 method => 'check_user_work_perms_batch',
1394 api_name => 'open-ils.actor.user.work_perm.org_tree_list.batch',
1397 __PACKAGE__->register_method(
1398 method => 'check_user_work_perms_batch',
1399 api_name => 'open-ils.actor.user.work_perm.org_unit_list.batch',
1402 __PACKAGE__->register_method(
1403 method => 'check_user_work_perms_batch',
1404 api_name => 'open-ils.actor.user.work_perm.org_id_list.batch',
1409 sub check_user_work_perms {
1410 my($self, $conn, $auth, $perm, $options) = @_;
1411 my $e = new_editor(authtoken=>$auth);
1412 return $e->event unless $e->checkauth;
1413 return check_user_work_perms_impl($self, $conn, $e, $perm, $options);
1416 sub check_user_work_perms_batch {
1417 my($self, $conn, $auth, $perm_list, $options) = @_;
1418 my $e = new_editor(authtoken=>$auth);
1419 return $e->event unless $e->checkauth;
1421 $map->{$_} = check_user_work_perms_impl($self, $conn, $e, $_, $options) for @$perm_list;
1425 sub check_user_work_perms_impl {
1426 my($self, $conn, $e, $perm, $options) = @_;
1427 my $orglist = $U->find_highest_work_orgs($e, $perm, $options);
1429 return $orglist if $self->api_name =~ /highest_org_set/;
1431 # build a list of org trees
1432 return get_org_descendants($self, $conn, $orglist)
1433 if $self->api_name =~ /org_tree_list/;
1436 for my $orgid (@$orglist) {
1437 my @sublist = grep {$_ ne $orgid} @{$U->get_org_descendants($orgid)};
1438 unshift @sublist, $orgid; # make sure it's at the front of the list
1439 if($self->api_name =~ /org_id_list/) {
1440 push(@list, @sublist);
1442 push(@list, @{$e->batch_retrieve_actor_org_unit(\@sublist)});
1450 __PACKAGE__->register_method(
1451 method => 'check_user_perms4',
1452 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1454 Returns the highest org unit id at which a user has a given permission
1455 If the requestor does not match the target user, the requestor must have
1456 'VIEW_PERMISSION' rights at the home org unit of the target user
1457 @param authtoken The login session key
1458 @param userid The id of the user in question
1459 @param perms An array of perm names to check
1460 @return An array of orgId's representing the org unit
1461 highest in the org tree within which the user has the requested permission
1462 The arrah of orgId's has matches the order of the perms array
1465 sub check_user_perms4 {
1466 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1468 my( $staff, $target, $org, $evt );
1470 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1471 $authtoken, $userid, 'VIEW_PERMISSION' );
1472 return $evt if $evt;
1475 return [] unless ref($perms);
1476 my $tree = $U->get_org_tree();
1478 for my $p (@$perms) {
1479 push( @arr, $U->find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1487 __PACKAGE__->register_method(
1488 method => "user_fines_summary",
1489 api_name => "open-ils.actor.user.fines.summary",
1491 notes => <<" NOTES");
1492 Returns a short summary of the users total open fines, excluding voided fines
1493 Params are login_session, user_id
1494 Returns a 'mous' object.
1497 sub user_fines_summary {
1498 my( $self, $client, $auth, $user_id ) = @_;
1499 my $e = new_editor(authtoken=>$auth);
1500 return $e->event unless $e->checkauth;
1501 my $user = $e->retrieve_actor_user($user_id)
1502 or return $e->event;
1504 if( $user_id ne $e->requestor->id ) {
1505 return $e->event unless
1506 $e->allowed('VIEW_USER_FINES_SUMMARY', $user->home_ou);
1509 # run this inside a transaction to prevent replication delay errors
1510 my $ses = $U->start_db_session();
1511 my $s = $ses->request(
1512 'open-ils.storage.money.open_user_summary.search', $user_id )->gather(1);
1513 $U->rollback_db_session($ses);
1520 __PACKAGE__->register_method(
1521 method => "user_transactions",
1522 api_name => "open-ils.actor.user.transactions",
1523 notes => <<" NOTES");
1524 Returns a list of open user transactions (mbts objects);
1525 Params are login_session, user_id
1526 Optional third parameter is the transactions type. defaults to all
1529 __PACKAGE__->register_method(
1530 method => "user_transactions",
1531 api_name => "open-ils.actor.user.transactions.have_charge",
1532 notes => <<" NOTES");
1533 Returns a list of all open user transactions (mbts objects) that have an initial charge
1534 Params are login_session, user_id
1535 Optional third parameter is the transactions type. defaults to all
1538 __PACKAGE__->register_method(
1539 method => "user_transactions",
1540 api_name => "open-ils.actor.user.transactions.have_balance",
1541 notes => <<" NOTES");
1542 Returns a list of all open user transactions (mbts objects) that have a balance
1543 Params are login_session, user_id
1544 Optional third parameter is the transactions type. defaults to all
1547 __PACKAGE__->register_method(
1548 method => "user_transactions",
1549 api_name => "open-ils.actor.user.transactions.fleshed",
1550 notes => <<" NOTES");
1551 Returns an object/hash of transaction, circ, title where transaction = an open
1552 user transactions (mbts objects), circ is the attached circluation, and title
1553 is the title the circ points to
1554 Params are login_session, user_id
1555 Optional third parameter is the transactions type. defaults to all
1558 __PACKAGE__->register_method(
1559 method => "user_transactions",
1560 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1561 notes => <<" NOTES");
1562 Returns an object/hash of transaction, circ, title where transaction = an open
1563 user transactions that has an initial charge (mbts objects), circ is the
1564 attached circluation, and title is the title the circ points to
1565 Params are login_session, user_id
1566 Optional third parameter is the transactions type. defaults to all
1569 __PACKAGE__->register_method(
1570 method => "user_transactions",
1571 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1572 notes => <<" NOTES");
1573 Returns an object/hash of transaction, circ, title where transaction = an open
1574 user transaction that has a balance (mbts objects), circ is the attached
1575 circluation, and title is the title the circ points to
1576 Params are login_session, user_id
1577 Optional third parameter is the transaction type. defaults to all
1580 __PACKAGE__->register_method(
1581 method => "user_transactions",
1582 api_name => "open-ils.actor.user.transactions.count",
1583 notes => <<" NOTES");
1584 Returns an object/hash of transaction, circ, title where transaction = an open
1585 user transactions (mbts objects), circ is the attached circluation, and title
1586 is the title the circ points to
1587 Params are login_session, user_id
1588 Optional third parameter is the transactions type. defaults to all
1591 __PACKAGE__->register_method(
1592 method => "user_transactions",
1593 api_name => "open-ils.actor.user.transactions.have_charge.count",
1594 notes => <<" NOTES");
1595 Returns an object/hash of transaction, circ, title where transaction = an open
1596 user transactions that has an initial charge (mbts objects), circ is the
1597 attached circluation, and title is the title the circ points to
1598 Params are login_session, user_id
1599 Optional third parameter is the transactions type. defaults to all
1602 __PACKAGE__->register_method(
1603 method => "user_transactions",
1604 api_name => "open-ils.actor.user.transactions.have_balance.count",
1605 notes => <<" NOTES");
1606 Returns an object/hash of transaction, circ, title where transaction = an open
1607 user transaction that has a balance (mbts objects), circ is the attached
1608 circluation, and title is the title the circ points to
1609 Params are login_session, user_id
1610 Optional third parameter is the transaction type. defaults to all
1613 __PACKAGE__->register_method(
1614 method => "user_transactions",
1615 api_name => "open-ils.actor.user.transactions.have_balance.total",
1616 notes => <<" NOTES");
1617 Returns an object/hash of transaction, circ, title where transaction = an open
1618 user transaction that has a balance (mbts objects), circ is the attached
1619 circluation, and title is the title the circ points to
1620 Params are login_session, user_id
1621 Optional third parameter is the transaction type. defaults to all
1626 sub user_transactions {
1627 my( $self, $client, $login_session, $user_id, $type ) = @_;
1629 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1630 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1631 return $evt if $evt;
1633 my $api = $self->api_name();
1637 if(defined($type)) { @xact = (xact_type => $type);
1639 } else { @xact = (); }
1642 ->method_lookup('open-ils.actor.user.transactions.history.still_open')
1643 ->run($login_session => $user_id => $type);
1645 if($api =~ /have_charge/o) {
1647 $trans = [ grep { int($_->total_owed * 100) > 0 } @$trans ];
1649 } elsif($api =~ /have_balance/o) {
1651 $trans = [ grep { int($_->balance_owed * 100) != 0 } @$trans ];
1654 $trans = [ grep { int($_->total_owed * 100) > 0 } @$trans ];
1658 if($api =~ /total/o) {
1660 for my $t (@$trans) {
1661 $total += $t->balance_owed;
1664 $logger->debug("Total balance owed by user $user_id: $total");
1668 if($api =~ /count/o) { return scalar @$trans; }
1669 if($api !~ /fleshed/o) { return $trans; }
1672 for my $t (@$trans) {
1674 if( $t->xact_type ne 'circulation' ) {
1675 push @resp, {transaction => $t};
1679 my $circ = $apputils->simple_scalar_request(
1681 "open-ils.cstore.direct.action.circulation.retrieve",
1686 my $title = $apputils->simple_scalar_request(
1688 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1689 $circ->target_copy );
1693 my $u = OpenILS::Utils::ModsParser->new();
1694 $u->start_mods_batch($title->marc());
1695 my $mods = $u->finish_mods_batch();
1696 $mods->doc_id($title->id) if $mods;
1698 push @resp, {transaction => $t, circ => $circ, record => $mods };
1706 __PACKAGE__->register_method(
1707 method => "user_transaction_retrieve",
1708 api_name => "open-ils.actor.user.transaction.fleshed.retrieve",
1710 notes => <<" NOTES");
1711 Returns a fleshedtransaction record
1713 __PACKAGE__->register_method(
1714 method => "user_transaction_retrieve",
1715 api_name => "open-ils.actor.user.transaction.retrieve",
1717 notes => <<" NOTES");
1718 Returns a transaction record
1720 sub user_transaction_retrieve {
1721 my( $self, $client, $login_session, $bill_id ) = @_;
1723 # XXX I think I'm deprecated... make sure
1725 my $trans = $apputils->simple_scalar_request(
1727 "open-ils.cstore.direct.money.billable_transaction_summary.retrieve",
1731 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1732 $login_session, $trans->usr, 'VIEW_USER_TRANSACTIONS' );
1733 return $evt if $evt;
1735 my $api = $self->api_name();
1736 if($api !~ /fleshed/o) { return $trans; }
1738 if( $trans->xact_type ne 'circulation' ) {
1739 $logger->debug("Returning non-circ transaction");
1740 return {transaction => $trans};
1743 my $circ = $apputils->simple_scalar_request(
1745 "open-ils..direct.action.circulation.retrieve",
1748 return {transaction => $trans} unless $circ;
1749 $logger->debug("Found the circ transaction");
1751 my $title = $apputils->simple_scalar_request(
1753 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1754 $circ->target_copy );
1756 return {transaction => $trans, circ => $circ } unless $title;
1757 $logger->debug("Found the circ title");
1761 my $u = OpenILS::Utils::ModsParser->new();
1762 $u->start_mods_batch($title->marc());
1763 $mods = $u->finish_mods_batch();
1765 if ($title->id == OILS_PRECAT_RECORD) {
1766 my $copy = $apputils->simple_scalar_request(
1768 "open-ils.cstore.direct.asset.copy.retrieve",
1769 $circ->target_copy );
1771 $mods = new Fieldmapper::metabib::virtual_record;
1772 $mods->doc_id(OILS_PRECAT_RECORD);
1773 $mods->title($copy->dummy_title);
1774 $mods->author($copy->dummy_author);
1778 $logger->debug("MODSized the circ title");
1780 return {transaction => $trans, circ => $circ, record => $mods };
1784 __PACKAGE__->register_method(
1785 method => "hold_request_count",
1786 api_name => "open-ils.actor.user.hold_requests.count",
1789 notes => <<" NOTES");
1790 Returns hold ready/total counts
1792 sub hold_request_count {
1793 my( $self, $client, $login_session, $userid ) = @_;
1795 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1796 $login_session, $userid, 'VIEW_HOLD' );
1797 return $evt if $evt;
1800 my $holds = $apputils->simple_scalar_request(
1802 "open-ils.cstore.direct.action.hold_request.search.atomic",
1805 fulfillment_time => {"=" => undef },
1806 cancel_time => undef,
1811 for my $h (@$holds) {
1812 next unless $h->capture_time and $h->current_copy;
1814 my $copy = $apputils->simple_scalar_request(
1816 "open-ils.cstore.direct.asset.copy.retrieve",
1820 if ($copy and $copy->status == 8) {
1825 return { total => scalar(@$holds), ready => scalar(@ready) };
1829 __PACKAGE__->register_method(
1830 method => "checkedout_count",
1831 api_name => "open-ils.actor.user.checked_out.count__",
1833 notes => <<" NOTES");
1834 Returns a transaction record
1838 sub checkedout_count {
1839 my( $self, $client, $login_session, $userid ) = @_;
1841 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1842 $login_session, $userid, 'VIEW_CIRCULATIONS' );
1843 return $evt if $evt;
1845 my $circs = $apputils->simple_scalar_request(
1847 "open-ils.cstore.direct.action.circulation.search.atomic",
1848 { usr => $userid, stop_fines => undef }
1849 #{ usr => $userid, checkin_time => {"=" => undef } }
1852 my $parser = DateTime::Format::ISO8601->new;
1855 for my $c (@$circs) {
1856 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1857 my $due = $due_dt->epoch;
1859 if ($due < DateTime->today->epoch) {
1864 return { total => scalar(@$circs), overdue => scalar(@overdue) };
1868 __PACKAGE__->register_method(
1869 method => "checked_out",
1870 api_name => "open-ils.actor.user.checked_out",
1874 Returns a structure of circulations objects sorted by
1875 out, overdue, lost, claims_returned, long_overdue.
1876 A list of IDs are returned of each type.
1877 lost, long_overdue, and claims_returned circ will not
1878 be "finished" (there is an outstanding balance or some
1879 other pending action on the circ).
1881 The .count method also includes a 'total' field which
1882 sums all "open" circs
1886 __PACKAGE__->register_method(
1887 method => "checked_out",
1888 api_name => "open-ils.actor.user.checked_out.count",
1891 signature => q/@see open-ils.actor.user.checked_out/
1895 my( $self, $conn, $auth, $userid ) = @_;
1897 my $e = new_editor(authtoken=>$auth);
1898 return $e->event unless $e->checkauth;
1900 if( $userid ne $e->requestor->id ) {
1901 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
1904 my $count = $self->api_name =~ /count/;
1905 return _checked_out( $count, $e, $userid );
1909 my( $iscount, $e, $userid ) = @_;
1910 my $meth = 'open-ils.storage.actor.user.checked_out';
1911 $meth = "$meth.count" if $iscount;
1912 return $U->storagereq($meth, $userid);
1916 sub _checked_out_WHAT {
1917 my( $iscount, $e, $userid ) = @_;
1919 my $circs = $e->search_action_circulation(
1920 { usr => $userid, stop_fines => undef });
1922 my $mcircs = $e->search_action_circulation(
1925 checkin_time => undef,
1926 xact_finish => undef,
1930 push( @$circs, @$mcircs );
1932 my $parser = DateTime::Format::ISO8601->new;
1934 # split the circs up into overdue and not-overdue circs
1936 for my $c (@$circs) {
1937 if( $c->due_date ) {
1938 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1939 my $due = $due_dt->epoch;
1940 if ($due < DateTime->today->epoch) {
1941 push @overdue, $c->id;
1950 # grab all of the lost, claims-returned, and longoverdue circs
1951 #my $open = $e->search_action_circulation(
1952 # {usr => $userid, stop_fines => { '!=' => undef }, xact_finish => undef });
1955 # these items have stop_fines, but no xact_finish, so money
1956 # is owed on them and they have not been checked in
1957 my $open = $e->search_action_circulation(
1960 stop_fines => { in => [ qw/LOST CLAIMSRETURNED LONGOVERDUE/ ] },
1961 xact_finish => undef,
1962 checkin_time => undef,
1967 my( @lost, @cr, @lo );
1968 for my $c (@$open) {
1969 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1970 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1971 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
1977 total => @$circs + @lost + @cr + @lo,
1978 out => scalar(@out),
1979 overdue => scalar(@overdue),
1980 lost => scalar(@lost),
1981 claims_returned => scalar(@cr),
1982 long_overdue => scalar(@lo)
1988 overdue => \@overdue,
1990 claims_returned => \@cr,
1991 long_overdue => \@lo
1997 __PACKAGE__->register_method(
1998 method => "checked_in_with_fines",
1999 api_name => "open-ils.actor.user.checked_in_with_fines",
2002 signature => q/@see open-ils.actor.user.checked_out/
2004 sub checked_in_with_fines {
2005 my( $self, $conn, $auth, $userid ) = @_;
2007 my $e = new_editor(authtoken=>$auth);
2008 return $e->event unless $e->checkauth;
2010 if( $userid ne $e->requestor->id ) {
2011 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
2014 # money is owed on these items and they are checked in
2015 my $open = $e->search_action_circulation(
2018 xact_finish => undef,
2019 checkin_time => { "!=" => undef },
2024 my( @lost, @cr, @lo );
2025 for my $c (@$open) {
2026 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
2027 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
2028 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
2033 claims_returned => \@cr,
2034 long_overdue => \@lo
2046 __PACKAGE__->register_method(
2047 method => "user_transaction_history",
2048 api_name => "open-ils.actor.user.transactions.history",
2050 notes => <<" NOTES");
2051 Returns a list of billable transaction ids for a user, optionally by type
2053 __PACKAGE__->register_method(
2054 method => "user_transaction_history",
2055 api_name => "open-ils.actor.user.transactions.history.have_charge",
2057 notes => <<" NOTES");
2058 Returns a list of billable transaction ids for a user that have an initial charge, optionally by type
2060 __PACKAGE__->register_method(
2061 method => "user_transaction_history",
2062 api_name => "open-ils.actor.user.transactions.history.have_balance",
2065 notes => <<" NOTES");
2066 Returns a list of billable transaction ids for a user that have a balance, optionally by type
2068 __PACKAGE__->register_method(
2069 method => "user_transaction_history",
2070 api_name => "open-ils.actor.user.transactions.history.still_open",
2072 notes => <<" NOTES");
2073 Returns a list of billable transaction ids for a user that are not finished
2075 __PACKAGE__->register_method(
2076 method => "user_transaction_history",
2077 api_name => "open-ils.actor.user.transactions.history.have_bill",
2080 notes => <<" NOTES");
2081 Returns a list of billable transaction ids for a user that has billings
2084 sub user_transaction_history {
2085 my( $self, $conn, $auth, $userid, $type ) = @_;
2087 # run inside of a transaction to prevent replication delays
2088 my $e = new_editor(xact=>1, authtoken=>$auth);
2089 return $e->die_event unless $e->checkauth;
2091 if( $e->requestor->id ne $userid ) {
2092 return $e->die_event
2093 unless $e->allowed('VIEW_USER_TRANSACTIONS');
2096 my $api = $self->api_name;
2097 my @xact_finish = (xact_finish => undef ) if ($api =~ /history.still_open$/);
2099 my @xacts = @{ $e->search_money_billable_transaction(
2100 [ { usr => $userid, @xact_finish },
2102 flesh_fields => { mbt => [ qw/billings payments grocery circulation/ ] },
2103 order_by => { mbt => 'xact_start DESC' },
2111 #my @mbts = _make_mbts( @xacts );
2112 my @mbts = $U->make_mbts( @xacts );
2114 if(defined($type)) {
2115 @mbts = grep { $_->xact_type eq $type } @mbts;
2118 if($api =~ /have_balance/o) {
2119 @mbts = grep { int($_->balance_owed * 100) != 0 } @mbts;
2122 if($api =~ /have_charge/o) {
2123 @mbts = grep { defined($_->last_billing_ts) } @mbts;
2126 if($api =~ /have_bill/o) {
2127 @mbts = grep { int($_->total_owed * 100) != 0 } @mbts;
2135 __PACKAGE__->register_method(
2136 method => "user_perms",
2137 api_name => "open-ils.actor.permissions.user_perms.retrieve",
2139 notes => <<" NOTES");
2140 Returns a list of permissions
2143 my( $self, $client, $authtoken, $user ) = @_;
2145 my( $staff, $evt ) = $apputils->checkses($authtoken);
2146 return $evt if $evt;
2148 $user ||= $staff->id;
2150 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
2154 return $apputils->simple_scalar_request(
2156 "open-ils.storage.permission.user_perms.atomic",
2160 __PACKAGE__->register_method(
2161 method => "retrieve_perms",
2162 api_name => "open-ils.actor.permissions.retrieve",
2163 notes => <<" NOTES");
2164 Returns a list of permissions
2166 sub retrieve_perms {
2167 my( $self, $client ) = @_;
2168 return $apputils->simple_scalar_request(
2170 "open-ils.cstore.direct.permission.perm_list.search.atomic",
2171 { id => { '!=' => undef } }
2175 __PACKAGE__->register_method(
2176 method => "retrieve_groups",
2177 api_name => "open-ils.actor.groups.retrieve",
2178 notes => <<" NOTES");
2179 Returns a list of user groupss
2181 sub retrieve_groups {
2182 my( $self, $client ) = @_;
2183 return new_editor()->retrieve_all_permission_grp_tree();
2186 __PACKAGE__->register_method(
2187 method => "retrieve_org_address",
2188 api_name => "open-ils.actor.org_unit.address.retrieve",
2189 notes => <<' NOTES');
2190 Returns an org_unit address by ID
2191 @param An org_address ID
2193 sub retrieve_org_address {
2194 my( $self, $client, $id ) = @_;
2195 return $apputils->simple_scalar_request(
2197 "open-ils.cstore.direct.actor.org_address.retrieve",
2202 __PACKAGE__->register_method(
2203 method => "retrieve_groups_tree",
2204 api_name => "open-ils.actor.groups.tree.retrieve",
2205 notes => <<" NOTES");
2206 Returns a list of user groups
2208 sub retrieve_groups_tree {
2209 my( $self, $client ) = @_;
2210 return new_editor()->search_permission_grp_tree(
2215 flesh_fields => { pgt => ["children"] },
2216 order_by => { pgt => 'name'}
2223 __PACKAGE__->register_method(
2224 method => "add_user_to_groups",
2225 api_name => "open-ils.actor.user.set_groups",
2226 notes => <<" NOTES");
2227 Adds a user to one or more permission groups
2230 sub add_user_to_groups {
2231 my( $self, $client, $authtoken, $userid, $groups ) = @_;
2233 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2234 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
2235 return $evt if $evt;
2237 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2238 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
2239 return $evt if $evt;
2241 $apputils->simplereq(
2243 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
2245 for my $group (@$groups) {
2246 my $link = Fieldmapper::permission::usr_grp_map->new;
2248 $link->usr($userid);
2250 my $id = $apputils->simplereq(
2252 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
2258 __PACKAGE__->register_method(
2259 method => "get_user_perm_groups",
2260 api_name => "open-ils.actor.user.get_groups",
2261 notes => <<" NOTES");
2262 Retrieve a user's permission groups.
2266 sub get_user_perm_groups {
2267 my( $self, $client, $authtoken, $userid ) = @_;
2269 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2270 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
2271 return $evt if $evt;
2273 return $apputils->simplereq(
2275 'open-ils.cstore.direct.permission.usr_grp_map.search.atomic', { usr => $userid } );
2279 __PACKAGE__->register_method(
2280 method => "get_user_work_ous",
2281 api_name => "open-ils.actor.user.get_work_ous",
2282 notes => <<" NOTES");
2283 Retrieve a user's work org units.
2285 __PACKAGE__->register_method(
2286 method => "get_user_work_ous",
2287 api_name => "open-ils.actor.user.get_work_ous.ids",
2288 notes => <<" NOTES");
2289 Retrieve a user's work org units.
2293 sub get_user_work_ous {
2294 my( $self, $client, $auth, $userid ) = @_;
2295 my $e = new_editor(authtoken=>$auth);
2296 return $e->event unless $e->checkauth;
2297 $userid ||= $e->requestor->id;
2299 if($e->requestor->id != $userid) {
2300 my $user = $e->retrieve_actor_user($userid)
2301 or return $e->event;
2302 return $e->event unless $e->allowed('ASSIGN_WORK_ORG_UNIT', $user->home_ou);
2305 return $e->search_permission_usr_work_ou_map({usr => $userid})
2306 unless $self->api_name =~ /.ids$/;
2308 # client just wants a list of org IDs
2309 return $U->get_user_work_ou_ids($e, $userid);
2315 __PACKAGE__->register_method (
2316 method => 'register_workstation',
2317 api_name => 'open-ils.actor.workstation.register.override',
2318 signature => q/@see open-ils.actor.workstation.register/);
2320 __PACKAGE__->register_method (
2321 method => 'register_workstation',
2322 api_name => 'open-ils.actor.workstation.register',
2324 Registers a new workstion in the system
2325 @param authtoken The login session key
2326 @param name The name of the workstation id
2327 @param owner The org unit that owns this workstation
2328 @return The workstation id on success, WORKSTATION_NAME_EXISTS
2329 if the name is already in use.
2332 sub register_workstation {
2333 my( $self, $conn, $authtoken, $name, $owner ) = @_;
2335 my $e = new_editor(authtoken=>$authtoken, xact=>1);
2336 return $e->die_event unless $e->checkauth;
2337 return $e->die_event unless $e->allowed('REGISTER_WORKSTATION', $owner);
2338 my $existing = $e->search_actor_workstation({name => $name})->[0];
2342 if( $self->api_name =~ /override/o ) {
2343 # workstation with the given name exists.
2345 if($owner ne $existing->owning_lib) {
2346 # if necessary, update the owning_lib of the workstation
2348 $logger->info("changing owning lib of workstation ".$existing->id.
2349 " from ".$existing->owning_lib." to $owner");
2350 return $e->die_event unless
2351 $e->allowed('UPDATE_WORKSTATION', $existing->owning_lib);
2353 return $e->die_event unless $e->allowed('UPDATE_WORKSTATION', $owner);
2355 $existing->owning_lib($owner);
2356 return $e->die_event unless $e->update_actor_workstation($existing);
2362 "attempt to register an existing workstation. returning existing ID");
2365 return $existing->id;
2368 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS')
2372 my $ws = Fieldmapper::actor::workstation->new;
2373 $ws->owning_lib($owner);
2375 $e->create_actor_workstation($ws) or return $e->die_event;
2377 return $ws->id; # note: editor sets the id on the new object for us
2380 __PACKAGE__->register_method (
2381 method => 'workstation_list',
2382 api_name => 'open-ils.actor.workstation.list',
2384 Returns a list of workstations registered at the given location
2385 @param authtoken The login session key
2386 @param ids A list of org_unit.id's for the workstation owners
2389 sub workstation_list {
2390 my( $self, $conn, $authtoken, @orgs ) = @_;
2392 my $e = new_editor(authtoken=>$authtoken);
2393 return $e->event unless $e->checkauth;
2398 unless $e->allowed('REGISTER_WORKSTATION', $o);
2399 $results{$o} = $e->search_actor_workstation({owning_lib=>$o});
2410 __PACKAGE__->register_method (
2411 method => 'fetch_patron_note',
2412 api_name => 'open-ils.actor.note.retrieve.all',
2415 Returns a list of notes for a given user
2416 Requestor must have VIEW_USER permission if pub==false and
2417 @param authtoken The login session key
2418 @param args Hash of params including
2419 patronid : the patron's id
2420 pub : true if retrieving only public notes
2424 sub fetch_patron_note {
2425 my( $self, $conn, $authtoken, $args ) = @_;
2426 my $patronid = $$args{patronid};
2428 my($reqr, $evt) = $U->checkses($authtoken);
2429 return $evt if $evt;
2432 ($patron, $evt) = $U->fetch_user($patronid);
2433 return $evt if $evt;
2436 if( $patronid ne $reqr->id ) {
2437 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2438 return $evt if $evt;
2440 return $U->cstorereq(
2441 'open-ils.cstore.direct.actor.usr_note.search.atomic',
2442 { usr => $patronid, pub => 't' } );
2445 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2446 return $evt if $evt;
2448 return $U->cstorereq(
2449 'open-ils.cstore.direct.actor.usr_note.search.atomic', { usr => $patronid } );
2452 __PACKAGE__->register_method (
2453 method => 'create_user_note',
2454 api_name => 'open-ils.actor.note.create',
2456 Creates a new note for the given user
2457 @param authtoken The login session key
2458 @param note The note object
2461 sub create_user_note {
2462 my( $self, $conn, $authtoken, $note ) = @_;
2463 my $e = new_editor(xact=>1, authtoken=>$authtoken);
2464 return $e->die_event unless $e->checkauth;
2466 my $user = $e->retrieve_actor_user($note->usr)
2467 or return $e->die_event;
2469 return $e->die_event unless
2470 $e->allowed('UPDATE_USER',$user->home_ou);
2472 $note->creator($e->requestor->id);
2473 $e->create_actor_usr_note($note) or return $e->die_event;
2479 __PACKAGE__->register_method (
2480 method => 'delete_user_note',
2481 api_name => 'open-ils.actor.note.delete',
2483 Deletes a note for the given user
2484 @param authtoken The login session key
2485 @param noteid The note id
2488 sub delete_user_note {
2489 my( $self, $conn, $authtoken, $noteid ) = @_;
2491 my $e = new_editor(xact=>1, authtoken=>$authtoken);
2492 return $e->die_event unless $e->checkauth;
2493 my $note = $e->retrieve_actor_usr_note($noteid)
2494 or return $e->die_event;
2495 my $user = $e->retrieve_actor_user($note->usr)
2496 or return $e->die_event;
2497 return $e->die_event unless
2498 $e->allowed('UPDATE_USER', $user->home_ou);
2500 $e->delete_actor_usr_note($note) or return $e->die_event;
2506 __PACKAGE__->register_method (
2507 method => 'update_user_note',
2508 api_name => 'open-ils.actor.note.update',
2510 @param authtoken The login session key
2511 @param note The note
2515 sub update_user_note {
2516 my( $self, $conn, $auth, $note ) = @_;
2517 my $e = new_editor(authtoken=>$auth, xact=>1);
2518 return $e->event unless $e->checkauth;
2519 my $patron = $e->retrieve_actor_user($note->usr)
2520 or return $e->event;
2521 return $e->event unless
2522 $e->allowed('UPDATE_USER', $patron->home_ou);
2523 $e->update_actor_user_note($note)
2524 or return $e->event;
2532 __PACKAGE__->register_method (
2533 method => 'create_closed_date',
2534 api_name => 'open-ils.actor.org_unit.closed_date.create',
2536 Creates a new closing entry for the given org_unit
2537 @param authtoken The login session key
2538 @param note The closed_date object
2541 sub create_closed_date {
2542 my( $self, $conn, $authtoken, $cd ) = @_;
2544 my( $user, $evt ) = $U->checkses($authtoken);
2545 return $evt if $evt;
2547 $evt = $U->check_perms($user->id, $cd->org_unit, 'CREATE_CLOSEING');
2548 return $evt if $evt;
2550 $logger->activity("user ".$user->id." creating library closing for ".$cd->org_unit);
2552 my $id = $U->storagereq(
2553 'open-ils.storage.direct.actor.org_unit.closed_date.create', $cd );
2554 return $U->DB_UPDATE_FAILED($cd) unless $id;
2559 __PACKAGE__->register_method (
2560 method => 'delete_closed_date',
2561 api_name => 'open-ils.actor.org_unit.closed_date.delete',
2563 Deletes a closing entry for the given org_unit
2564 @param authtoken The login session key
2565 @param noteid The close_date id
2568 sub delete_closed_date {
2569 my( $self, $conn, $authtoken, $cd ) = @_;
2571 my( $user, $evt ) = $U->checkses($authtoken);
2572 return $evt if $evt;
2575 ($cd_obj, $evt) = fetch_closed_date($cd);
2576 return $evt if $evt;
2578 $evt = $U->check_perms($user->id, $cd->org_unit, 'DELETE_CLOSEING');
2579 return $evt if $evt;
2581 $logger->activity("user ".$user->id." deleting library closing for ".$cd->org_unit);
2583 my $stat = $U->storagereq(
2584 'open-ils.storage.direct.actor.org_unit.closed_date.delete', $cd );
2585 return $U->DB_UPDATE_FAILED($cd) unless $stat;
2590 __PACKAGE__->register_method(
2591 method => 'usrname_exists',
2592 api_name => 'open-ils.actor.username.exists',
2594 Returns 1 if the requested username exists, returns 0 otherwise
2598 sub usrname_exists {
2599 my( $self, $conn, $auth, $usrname ) = @_;
2600 my $e = new_editor(authtoken=>$auth);
2601 return $e->event unless $e->checkauth;
2602 my $a = $e->search_actor_user({usrname => $usrname, deleted=>'f'}, {idlist=>1});
2603 return $$a[0] if $a and @$a;
2607 __PACKAGE__->register_method(
2608 method => 'barcode_exists',
2609 api_name => 'open-ils.actor.barcode.exists',
2612 Returns 1 if the requested barcode exists, returns 0 otherwise
2616 sub barcode_exists {
2617 my( $self, $conn, $auth, $barcode ) = @_;
2618 my $e = new_editor(authtoken=>$auth);
2619 return $e->event unless $e->checkauth;
2620 my $card = $e->search_actor_card({barcode => $barcode});
2626 #return undef unless @$card;
2627 #return $card->[0]->usr;
2631 __PACKAGE__->register_method(
2632 method => 'retrieve_net_levels',
2633 api_name => 'open-ils.actor.net_access_level.retrieve.all',
2636 sub retrieve_net_levels {
2637 my( $self, $conn, $auth ) = @_;
2638 my $e = new_editor(authtoken=>$auth);
2639 return $e->event unless $e->checkauth;
2640 return $e->retrieve_all_config_net_access_level();
2644 __PACKAGE__->register_method(
2645 method => 'fetch_org_by_shortname',
2646 api_name => 'open-ils.actor.org_unit.retrieve_by_shorname',
2648 sub fetch_org_by_shortname {
2649 my( $self, $conn, $sname ) = @_;
2650 my $e = new_editor();
2651 my $org = $e->search_actor_org_unit({ shortname => uc($sname)})->[0];
2652 return $e->event unless $org;
2657 __PACKAGE__->register_method(
2658 method => 'session_home_lib',
2659 api_name => 'open-ils.actor.session.home_lib',
2662 sub session_home_lib {
2663 my( $self, $conn, $auth ) = @_;
2664 my $e = new_editor(authtoken=>$auth);
2665 return undef unless $e->checkauth;
2666 my $org = $e->retrieve_actor_org_unit($e->requestor->home_ou);
2667 return $org->shortname;
2670 __PACKAGE__->register_method(
2671 method => 'session_safe_token',
2672 api_name => 'open-ils.actor.session.safe_token',
2674 Returns a hashed session ID that is safe for export to the world.
2675 This safe token will expire after 1 hour of non-use.
2676 @param auth Active authentication token
2680 sub session_safe_token {
2681 my( $self, $conn, $auth ) = @_;
2682 my $e = new_editor(authtoken=>$auth);
2683 return undef unless $e->checkauth;
2685 my $safe_token = md5_hex($auth);
2687 $cache ||= OpenSRF::Utils::Cache->new("global", 0);
2689 # Add more like the following if needed...
2691 "safe-token-home_lib-shortname-$safe_token",
2692 $e->retrieve_actor_org_unit(
2693 $e->requestor->home_ou
2702 __PACKAGE__->register_method(
2703 method => 'safe_token_home_lib',
2704 api_name => 'open-ils.actor.safe_token.home_lib.shortname',
2706 Returns the home library shortname from the session
2707 asscociated with a safe token from generated by
2708 open-ils.actor.session.safe_token.
2709 @param safe_token Active safe token
2713 sub safe_token_home_lib {
2714 my( $self, $conn, $safe_token ) = @_;
2716 $cache ||= OpenSRF::Utils::Cache->new("global", 0);
2717 return $cache->get_cache( 'safe-token-home_lib-shortname-'. $safe_token );
2722 __PACKAGE__->register_method(
2723 method => 'slim_tree',
2724 api_name => "open-ils.actor.org_tree.slim_hash.retrieve",
2727 my $tree = new_editor()->search_actor_org_unit(
2729 {"parent_ou" => undef },
2732 flesh_fields => { aou => ['children'] },
2733 order_by => { aou => 'name'},
2734 select => { aou => ["id","shortname", "name"]},
2739 return trim_tree($tree);
2745 return undef unless $tree;
2747 code => $tree->shortname,
2748 name => $tree->name,
2750 if( $tree->children and @{$tree->children} ) {
2751 $htree->{children} = [];
2752 for my $c (@{$tree->children}) {
2753 push( @{$htree->{children}}, trim_tree($c) );
2761 __PACKAGE__->register_method(
2762 method => "update_penalties",
2763 api_name => "open-ils.actor.user.penalties.update");
2764 sub update_penalties {
2765 my( $self, $conn, $auth, $userid ) = @_;
2766 my $e = new_editor(authtoken=>$auth);
2767 return $e->event unless $e->checkauth;
2768 $U->update_patron_penalties(
2770 patronid => $userid,
2777 __PACKAGE__->register_method(
2778 method => "user_retrieve_fleshed_by_id",
2779 api_name => "open-ils.actor.user.fleshed.retrieve",);
2781 sub user_retrieve_fleshed_by_id {
2782 my( $self, $client, $auth, $user_id, $fields ) = @_;
2783 my $e = new_editor(authtoken => $auth);
2784 return $e->event unless $e->checkauth;
2786 if( $e->requestor->id != $user_id ) {
2787 return $e->event unless $e->allowed('VIEW_USER');
2793 "standing_penalties",
2797 "stat_cat_entries" ];
2798 return new_flesh_user($user_id, $fields, $e);
2802 sub new_flesh_user {
2805 my $fields = shift || [];
2806 my $e = shift || new_editor(xact=>1);
2808 my $user = $e->retrieve_actor_user(
2813 "flesh_fields" => { "au" => $fields }
2816 ) or return $e->event;
2819 if( grep { $_ eq 'addresses' } @$fields ) {
2821 $user->addresses([]) unless @{$user->addresses};
2823 if( ref $user->billing_address ) {
2824 unless( grep { $user->billing_address->id == $_->id } @{$user->addresses} ) {
2825 push( @{$user->addresses}, $user->billing_address );
2829 if( ref $user->mailing_address ) {
2830 unless( grep { $user->mailing_address->id == $_->id } @{$user->addresses} ) {
2831 push( @{$user->addresses}, $user->mailing_address );
2837 $user->clear_passwd();
2844 __PACKAGE__->register_method(
2845 method => "user_retrieve_parts",
2846 api_name => "open-ils.actor.user.retrieve.parts",);
2848 sub user_retrieve_parts {
2849 my( $self, $client, $auth, $user_id, $fields ) = @_;
2850 my $e = new_editor(authtoken => $auth);
2851 return $e->event unless $e->checkauth;
2852 if( $e->requestor->id != $user_id ) {
2853 return $e->event unless $e->allowed('VIEW_USER');
2856 my $user = $e->retrieve_actor_user($user_id) or return $e->event;
2857 push(@resp, $user->$_()) for(@$fields);
2863 __PACKAGE__->register_method(
2864 method => 'user_opt_in_enabled',
2865 api_name => 'open-ils.actor.user.org_unit_opt_in.enabled',
2867 @return 1 if user opt-in is globally enabled, 0 otherwise.
2870 sub user_opt_in_enabled {
2871 my($self, $conn) = @_;
2872 my $sc = OpenSRF::Utils::SettingsClient->new;
2873 return 1 if lc($sc->config_value(share => user => 'opt_in')) eq 'true';
2878 __PACKAGE__->register_method(
2879 method => 'user_opt_in_at_org',
2880 api_name => 'open-ils.actor.user.org_unit_opt_in.check',
2882 @param $auth The auth token
2883 @param user_id The ID of the user to test
2884 @return 1 if the user has opted in at the specified org,
2885 event on error, and 0 otherwise. /);
2886 sub user_opt_in_at_org {
2887 my($self, $conn, $auth, $user_id) = @_;
2889 # see if we even need to enforce the opt-in value
2890 return 1 unless user_opt_in_enabled($self);
2892 my $e = new_editor(authtoken => $auth);
2893 return $e->event unless $e->checkauth;
2894 my $org_id = $e->requestor->ws_ou;
2896 my $user = $e->retrieve_actor_user($user_id) or return $e->event;
2897 return $e->event unless $e->allowed('VIEW_USER', $user->home_ou);
2899 # user is automatically opted-in at the home org
2900 return 1 if $user->home_ou eq $org_id;
2902 my $vals = $e->search_actor_usr_org_unit_opt_in(
2903 {org_unit=>$org_id, usr=>$user_id},{idlist=>1});
2909 __PACKAGE__->register_method(
2910 method => 'create_user_opt_in_at_org',
2911 api_name => 'open-ils.actor.user.org_unit_opt_in.create',
2913 @param $auth The auth token
2914 @param user_id The ID of the user to test
2915 @return The ID of the newly created object, event on error./);
2917 sub create_user_opt_in_at_org {
2918 my($self, $conn, $auth, $user_id) = @_;
2920 my $e = new_editor(authtoken => $auth, xact=>1);
2921 return $e->die_event unless $e->checkauth;
2922 my $org_id = $e->requestor->ws_ou;
2924 my $user = $e->retrieve_actor_user($user_id) or return $e->die_event;
2925 return $e->die_event unless $e->allowed('UPDATE_USER', $user->home_ou);
2927 my $opt_in = Fieldmapper::actor::usr_org_unit_opt_in->new;
2929 $opt_in->org_unit($org_id);
2930 $opt_in->usr($user_id);
2931 $opt_in->staff($e->requestor->id);
2932 $opt_in->opt_in_ts('now');
2933 $opt_in->opt_in_ws($e->requestor->wsid);
2935 $opt_in = $e->create_actor_usr_org_unit_opt_in($opt_in)
2936 or return $e->die_event;
2944 __PACKAGE__->register_method (
2945 method => 'retrieve_org_hours',
2946 api_name => 'open-ils.actor.org_unit.hours_of_operation.retrieve',
2948 Returns the hours of operation for a specified org unit
2949 @param authtoken The login session key
2950 @param org_id The org_unit ID
2954 sub retrieve_org_hours {
2955 my($self, $conn, $auth, $org_id) = @_;
2956 my $e = new_editor(authtoken => $auth);
2957 return $e->die_event unless $e->checkauth;
2958 $org_id ||= $e->requestor->ws_ou;
2959 return $e->retrieve_actor_org_unit_hours_of_operation($org_id);