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;
143 my $patron = $e->retrieve_actor_user($user_id) or return $e->event;
144 if($e->requestor->id != $user_id) {
145 return $e->event unless $e->allowed('VIEW_USER', $patron->home_ou);
149 my $val = $e->search_actor_user_setting({usr => $user_id, name => $setting})->[0];
150 return OpenSRF::Utils::JSON->JSON2perl($val->value);
152 my $s = $e->search_actor_user_setting({usr => $user_id});
153 return { map { ( $_->name => OpenSRF::Utils::JSON->JSON2perl($_->value) ) } @$s };
159 __PACKAGE__->register_method(
160 method => "ou_settings",
161 api_name => "open-ils.actor.org_unit.settings.retrieve",
164 my( $self, $client, $ouid ) = @_;
166 $logger->info("Fetching org unit settings for org $ouid");
168 my $s = $apputils->simplereq(
170 'open-ils.cstore.direct.actor.org_unit_setting.search.atomic', {org_unit => $ouid});
172 return { map { ( $_->name => OpenSRF::Utils::JSON->JSON2perl($_->value) ) } @$s };
177 __PACKAGE__->register_method(
178 api_name => 'open-ils.actor.ou_setting.ancestor_default',
179 method => 'ou_ancestor_setting',
182 # ------------------------------------------------------------------
183 # Attempts to find the org setting value for a given org. if not
184 # found at the requested org, searches up the org tree until it
185 # finds a parent that has the requested setting.
186 # when found, returns { org => $id, value => $value }
187 # otherwise, returns NULL
188 # ------------------------------------------------------------------
189 sub ou_ancestor_setting {
190 my( $self, $client, $orgid, $name ) = @_;
191 return $U->ou_ancestor_setting($orgid, $name);
194 __PACKAGE__->register_method(
195 api_name => 'open-ils.actor.ou_setting.ancestor_default.batch',
196 method => 'ou_ancestor_setting_batch',
198 sub ou_ancestor_setting_batch {
199 my( $self, $client, $orgid, $name_list ) = @_;
201 $values{$_} = $U->ou_ancestor_setting($orgid, $_) for @$name_list;
208 __PACKAGE__->register_method (
209 method => "ou_setting_delete",
210 api_name => 'open-ils.actor.org_setting.delete',
212 Deletes a specific org unit setting for a specific location
213 @param authtoken The login session key
214 @param orgid The org unit whose setting we're changing
215 @param setting The name of the setting to delete
216 @return True value on success.
220 sub ou_setting_delete {
221 my( $self, $conn, $authtoken, $orgid, $setting ) = @_;
222 my( $reqr, $evt) = $U->checkses($authtoken);
224 $evt = $U->check_perms($reqr->id, $orgid, 'UPDATE_ORG_SETTING');
227 my $id = $U->cstorereq(
228 'open-ils.cstore.direct.actor.org_unit_setting.id_list',
229 { name => $setting, org_unit => $orgid } );
231 $logger->debug("Retrieved setting $id in org unit setting delete");
233 my $s = $U->cstorereq(
234 'open-ils.cstore.direct.actor.org_unit_setting.delete', $id );
236 $logger->activity("User ".$reqr->id." deleted org unit setting $id") if $s;
250 __PACKAGE__->register_method(
251 method => "update_patron",
252 api_name => "open-ils.actor.patron.update",);
255 my( $self, $client, $user_session, $patron ) = @_;
257 my $session = $apputils->start_db_session();
261 $logger->info("Creating new patron...") if $patron->isnew;
262 $logger->info("Updating Patron: " . $patron->id) unless $patron->isnew;
264 my( $user_obj, $evt ) = $U->checkses($user_session);
267 $evt = check_group_perm($session, $user_obj, $patron);
271 # $new_patron is the patron in progress. $patron is the original patron
272 # passed in with the method. new_patron will change as the components
273 # of patron are added/updated.
277 # unflesh the real items on the patron
278 $patron->card( $patron->card->id ) if(ref($patron->card));
279 $patron->billing_address( $patron->billing_address->id )
280 if(ref($patron->billing_address));
281 $patron->mailing_address( $patron->mailing_address->id )
282 if(ref($patron->mailing_address));
284 # create/update the patron first so we can use his id
285 if($patron->isnew()) {
286 ( $new_patron, $evt ) = _add_patron($session, _clone_patron($patron), $user_obj);
288 } else { $new_patron = $patron; }
290 ( $new_patron, $evt ) = _add_update_addresses($session, $patron, $new_patron, $user_obj);
293 ( $new_patron, $evt ) = _add_update_cards($session, $patron, $new_patron, $user_obj);
296 ( $new_patron, $evt ) = _add_survey_responses($session, $patron, $new_patron, $user_obj);
299 # re-update the patron if anything has happened to him during this process
300 if($new_patron->ischanged()) {
301 ( $new_patron, $evt ) = _update_patron($session, $new_patron, $user_obj);
305 ($new_patron, $evt) = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
308 ($new_patron, $evt) = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
311 ($new_patron, $evt) = _create_standing_penalties($session, $user_session, $patron, $new_patron, $user_obj);
314 $logger->activity("user ".$user_obj->id." updating/creating user ".$new_patron->id);
317 if(!$patron->isnew) {
318 $opatron = new_editor()->retrieve_actor_user($new_patron->id);
321 $apputils->commit_db_session($session);
322 my $fuser = flesh_user($new_patron->id());
325 # Log the new and old patron for investigation
326 $logger->info("$user_session updating patron object. orig patron object = ".
327 OpenSRF::Utils::JSON->perl2JSON($opatron). " |||| new patron = ".OpenSRF::Utils::JSON->perl2JSON($fuser));
337 return new_flesh_user($id, [
340 "standing_penalties",
344 "stat_cat_entries" ] );
352 # clone and clear stuff that would break the database
356 my $new_patron = $patron->clone;
358 $new_patron->clear_billing_address();
359 $new_patron->clear_mailing_address();
360 $new_patron->clear_addresses();
361 $new_patron->clear_card();
362 $new_patron->clear_cards();
363 $new_patron->clear_id();
364 $new_patron->clear_isnew();
365 $new_patron->clear_ischanged();
366 $new_patron->clear_isdeleted();
367 $new_patron->clear_stat_cat_entries();
368 $new_patron->clear_permissions();
369 $new_patron->clear_standing_penalties();
379 my $user_obj = shift;
381 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'CREATE_USER');
382 return (undef, $evt) if $evt;
384 my $ex = $session->request(
385 'open-ils.storage.direct.actor.user.search.usrname', $patron->usrname())->gather(1);
387 return (undef, OpenILS::Event->new('USERNAME_EXISTS'));
390 $logger->info("Creating new user in the DB with username: ".$patron->usrname());
392 my $id = $session->request(
393 "open-ils.storage.direct.actor.user.create", $patron)->gather(1);
394 return (undef, $U->DB_UPDATE_FAILED($patron)) unless $id;
396 $logger->info("Successfully created new user [$id] in DB");
398 return ( $session->request(
399 "open-ils.storage.direct.actor.user.retrieve", $id)->gather(1), undef );
403 sub check_group_perm {
404 my( $session, $requestor, $patron ) = @_;
407 # first let's see if the requestor has
408 # priveleges to update this user in any way
409 if( ! $patron->isnew ) {
410 my $p = $session->request(
411 'open-ils.storage.direct.actor.user.retrieve', $patron->id )->gather(1);
413 # If we are the requestor (trying to update our own account)
414 # and we are not trying to change our profile, we're good
415 if( $p->id == $requestor->id and
416 $p->profile == $patron->profile ) {
421 $evt = group_perm_failed($session, $requestor, $p);
425 # They are allowed to edit this patron.. can they put the
426 # patron into the group requested?
427 $evt = group_perm_failed($session, $requestor, $patron);
433 sub group_perm_failed {
434 my( $session, $requestor, $patron ) = @_;
438 my $grpid = $patron->profile;
442 $logger->debug("user update looking for group perm for group $grpid");
443 $grp = $session->request(
444 'open-ils.storage.direct.permission.grp_tree.retrieve', $grpid )->gather(1);
445 return OpenILS::Event->new('PERMISSION_GRP_TREE_NOT_FOUND') unless $grp;
447 } while( !($perm = $grp->application_perm) and ($grpid = $grp->parent) );
449 $logger->info("user update checking perm $perm on user ".
450 $requestor->id." for update/create on user username=".$patron->usrname);
452 my $evt = $U->check_perms($requestor->id, $patron->home_ou, $perm);
460 my( $session, $patron, $user_obj, $noperm) = @_;
462 $logger->info("Updating patron ".$patron->id." in DB");
467 $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'UPDATE_USER');
468 return (undef, $evt) if $evt;
471 # update the password by itself to avoid the password protection magic
472 if( $patron->passwd ) {
473 my $s = $session->request(
474 'open-ils.storage.direct.actor.user.remote_update',
475 {id => $patron->id}, {passwd => $patron->passwd})->gather(1);
476 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($s);
477 $patron->clear_passwd;
480 if(!$patron->ident_type) {
481 $patron->clear_ident_type;
482 $patron->clear_ident_value;
485 $evt = verify_last_xact($session, $patron);
486 return (undef, $evt) if $evt;
488 my $stat = $session->request(
489 "open-ils.storage.direct.actor.user.update",$patron )->gather(1);
490 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($stat);
495 sub verify_last_xact {
496 my( $session, $patron ) = @_;
497 return undef unless $patron->id and $patron->id > 0;
498 my $p = $session->request(
499 'open-ils.storage.direct.actor.user.retrieve', $patron->id)->gather(1);
500 my $xact = $p->last_xact_id;
501 return undef unless $xact;
502 $logger->info("user xact = $xact, saving with xact " . $patron->last_xact_id);
503 return OpenILS::Event->new('XACT_COLLISION')
504 if $xact != $patron->last_xact_id;
509 sub _check_dup_ident {
510 my( $session, $patron ) = @_;
512 return undef unless $patron->ident_value;
515 ident_type => $patron->ident_type,
516 ident_value => $patron->ident_value,
519 $logger->debug("patron update searching for dup ident values: " .
520 $patron->ident_type . ':' . $patron->ident_value);
522 $search->{id} = {'!=' => $patron->id} if $patron->id and $patron->id > 0;
524 my $dups = $session->request(
525 'open-ils.storage.direct.actor.user.search_where.atomic', $search )->gather(1);
528 return OpenILS::Event->new('PATRON_DUP_IDENT1', payload => $patron )
535 sub _add_update_addresses {
539 my $new_patron = shift;
543 my $current_id; # id of the address before creation
545 for my $address (@{$patron->addresses()}) {
547 next unless ref $address;
548 $current_id = $address->id();
550 if( $patron->billing_address() and
551 $patron->billing_address() == $current_id ) {
552 $logger->info("setting billing addr to $current_id");
553 $new_patron->billing_address($address->id());
554 $new_patron->ischanged(1);
557 if( $patron->mailing_address() and
558 $patron->mailing_address() == $current_id ) {
559 $new_patron->mailing_address($address->id());
560 $logger->info("setting mailing addr to $current_id");
561 $new_patron->ischanged(1);
565 if($address->isnew()) {
567 $address->usr($new_patron->id());
569 ($address, $evt) = _add_address($session,$address);
570 return (undef, $evt) if $evt;
572 # we need to get the new id
573 if( $patron->billing_address() and
574 $patron->billing_address() == $current_id ) {
575 $new_patron->billing_address($address->id());
576 $logger->info("setting billing addr to $current_id");
577 $new_patron->ischanged(1);
580 if( $patron->mailing_address() and
581 $patron->mailing_address() == $current_id ) {
582 $new_patron->mailing_address($address->id());
583 $logger->info("setting mailing addr to $current_id");
584 $new_patron->ischanged(1);
587 } elsif($address->ischanged() ) {
589 ($address, $evt) = _update_address($session, $address);
590 return (undef, $evt) if $evt;
592 } elsif($address->isdeleted() ) {
594 if( $address->id() == $new_patron->mailing_address() ) {
595 $new_patron->clear_mailing_address();
596 ($new_patron, $evt) = _update_patron($session, $new_patron);
597 return (undef, $evt) if $evt;
600 if( $address->id() == $new_patron->billing_address() ) {
601 $new_patron->clear_billing_address();
602 ($new_patron, $evt) = _update_patron($session, $new_patron);
603 return (undef, $evt) if $evt;
606 $evt = _delete_address($session, $address);
607 return (undef, $evt) if $evt;
611 return ( $new_patron, undef );
615 # adds an address to the db and returns the address with new id
617 my($session, $address) = @_;
618 $address->clear_id();
620 $logger->info("Creating new address at street ".$address->street1);
622 # put the address into the database
623 my $id = $session->request(
624 "open-ils.storage.direct.actor.user_address.create", $address )->gather(1);
625 return (undef, $U->DB_UPDATE_FAILED($address)) unless $id;
628 return ($address, undef);
632 sub _update_address {
633 my( $session, $address ) = @_;
635 $logger->info("Updating address ".$address->id." in the DB");
637 my $stat = $session->request(
638 "open-ils.storage.direct.actor.user_address.update", $address )->gather(1);
640 return (undef, $U->DB_UPDATE_FAILED($address)) unless defined($stat);
641 return ($address, undef);
646 sub _add_update_cards {
650 my $new_patron = shift;
654 my $virtual_id; #id of the card before creation
655 for my $card (@{$patron->cards()}) {
657 $card->usr($new_patron->id());
659 if(ref($card) and $card->isnew()) {
661 $virtual_id = $card->id();
662 ( $card, $evt ) = _add_card($session,$card);
663 return (undef, $evt) if $evt;
665 #if(ref($patron->card)) { $patron->card($patron->card->id); }
666 if($patron->card() == $virtual_id) {
667 $new_patron->card($card->id());
668 $new_patron->ischanged(1);
671 } elsif( ref($card) and $card->ischanged() ) {
672 $evt = _update_card($session, $card);
673 return (undef, $evt) if $evt;
677 return ( $new_patron, undef );
681 # adds an card to the db and returns the card with new id
683 my( $session, $card ) = @_;
686 $logger->info("Adding new patron card ".$card->barcode);
688 my $id = $session->request(
689 "open-ils.storage.direct.actor.card.create", $card )->gather(1);
690 return (undef, $U->DB_UPDATE_FAILED($card)) unless $id;
691 $logger->info("Successfully created patron card $id");
694 return ( $card, undef );
698 # returns event on error. returns undef otherwise
700 my( $session, $card ) = @_;
701 $logger->info("Updating patron card ".$card->id);
703 my $stat = $session->request(
704 "open-ils.storage.direct.actor.card.update", $card )->gather(1);
705 return $U->DB_UPDATE_FAILED($card) unless defined($stat);
712 # returns event on error. returns undef otherwise
713 sub _delete_address {
714 my( $session, $address ) = @_;
716 $logger->info("Deleting address ".$address->id." from DB");
718 my $stat = $session->request(
719 "open-ils.storage.direct.actor.user_address.delete", $address )->gather(1);
721 return $U->DB_UPDATE_FAILED($address) unless defined($stat);
727 sub _add_survey_responses {
728 my ($session, $patron, $new_patron) = @_;
730 $logger->info( "Updating survey responses for patron ".$new_patron->id );
732 my $responses = $patron->survey_responses;
736 $_->usr($new_patron->id) for (@$responses);
738 my $evt = $U->simplereq( "open-ils.circ",
739 "open-ils.circ.survey.submit.user_id", $responses );
741 return (undef, $evt) if defined($U->event_code($evt));
745 return ( $new_patron, undef );
749 sub _create_stat_maps {
751 my($session, $user_session, $patron, $new_patron) = @_;
753 my $maps = $patron->stat_cat_entries();
755 for my $map (@$maps) {
757 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
759 if ($map->isdeleted()) {
760 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.delete";
762 } elsif ($map->isnew()) {
763 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
768 $map->target_usr($new_patron->id);
771 $logger->info("Updating stat entry with method $method and map $map");
773 my $stat = $session->request($method, $map)->gather(1);
774 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
778 return ($new_patron, undef);
781 sub _create_perm_maps {
783 my($session, $user_session, $patron, $new_patron) = @_;
785 my $maps = $patron->permissions;
787 for my $map (@$maps) {
789 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
790 if ($map->isdeleted()) {
791 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
792 } elsif ($map->isnew()) {
793 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
798 $map->usr($new_patron->id);
800 #warn( "Updating permissions with method $method and session $user_session and map $map" );
801 $logger->info( "Updating permissions with method $method and map $map" );
803 my $stat = $session->request($method, $map)->gather(1);
804 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
808 return ($new_patron, undef);
812 __PACKAGE__->register_method(
813 method => "set_user_work_ous",
814 api_name => "open-ils.actor.user.work_ous.update",
817 sub set_user_work_ous {
823 my( $requestor, $evt ) = $apputils->checksesperm( $ses, 'ASSIGN_WORK_ORG_UNIT' );
826 my $session = $apputils->start_db_session();
828 for my $map (@$maps) {
830 my $method = "open-ils.storage.direct.permission.usr_work_ou_map.update";
831 if ($map->isdeleted()) {
832 $method = "open-ils.storage.direct.permission.usr_work_ou_map.delete";
833 } elsif ($map->isnew()) {
834 $method = "open-ils.storage.direct.permission.usr_work_ou_map.create";
838 #warn( "Updating permissions with method $method and session $ses and map $map" );
839 $logger->info( "Updating work_ou map with method $method and map $map" );
841 my $stat = $session->request($method, $map)->gather(1);
842 $logger->warn( "update failed: ".$U->DB_UPDATE_FAILED($map) ) unless defined($stat);
846 $apputils->commit_db_session($session);
848 return scalar(@$maps);
852 __PACKAGE__->register_method(
853 method => "set_user_perms",
854 api_name => "open-ils.actor.user.permissions.update",
863 my $session = $apputils->start_db_session();
865 my( $user_obj, $evt ) = $U->checkses($ses);
868 my $perms = $session->request('open-ils.storage.permission.user_perms.atomic', $user_obj->id)->gather(1);
871 $all = 1 if ($U->is_true($user_obj->super_user()));
872 $all = 1 unless ($U->check_perms($user_obj->id, $user_obj->home_ou, 'EVERYTHING'));
874 for my $map (@$maps) {
876 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
877 if ($map->isdeleted()) {
878 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
879 } elsif ($map->isnew()) {
880 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
884 next if (!$all and !grep { $_->perm eq $map->perm and $U->is_true($_->grantable) and $_->depth <= $map->depth } @$perms);
885 #warn( "Updating permissions with method $method and session $ses and map $map" );
886 $logger->info( "Updating permissions with method $method and map $map" );
888 my $stat = $session->request($method, $map)->gather(1);
889 $logger->warn( "update failed: ".$U->DB_UPDATE_FAILED($map) ) unless defined($stat);
893 $apputils->commit_db_session($session);
895 return scalar(@$maps);
899 sub _create_standing_penalties {
901 my($session, $user_session, $patron, $new_patron) = @_;
903 my $maps = $patron->standing_penalties;
906 for my $map (@$maps) {
908 if ($map->isdeleted()) {
909 $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
910 } elsif ($map->isnew()) {
911 $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
917 $map->usr($new_patron->id);
919 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
921 my $stat = $session->request($method, $map)->gather(1);
922 return (undef, $U->DB_UPDATE_FAILED($map)) unless $stat;
925 return ($new_patron, undef);
930 __PACKAGE__->register_method(
931 method => "search_username",
932 api_name => "open-ils.actor.user.search.username",
935 sub search_username {
936 my($self, $client, $username) = @_;
937 return new_editor()->search_actor_user({usrname=>$username});
943 __PACKAGE__->register_method(
944 method => "user_retrieve_by_barcode",
946 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
948 sub user_retrieve_by_barcode {
949 my($self, $client, $user_session, $barcode) = @_;
951 $logger->debug("Searching for user with barcode $barcode");
952 my ($user_obj, $evt) = $apputils->checkses($user_session);
955 my $card = OpenILS::Application::AppUtils->simple_scalar_request(
957 "open-ils.cstore.direct.actor.card.search.atomic",
958 { barcode => $barcode }
961 if(!$card || !$card->[0]) {
962 return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' );
966 my $user = flesh_user($card->usr());
968 $evt = $U->check_perms($user_obj->id, $user->home_ou, 'VIEW_USER');
971 if(!$user) { return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' ); }
978 __PACKAGE__->register_method(
979 method => "get_user_by_id",
980 api_name => "open-ils.actor.user.retrieve",);
983 my ($self, $client, $auth, $id) = @_;
984 my $e = new_editor(authtoken=>$auth);
985 return $e->event unless $e->checkauth;
986 my $user = $e->retrieve_actor_user($id)
988 return $e->event unless $e->allowed('VIEW_USER', $user->home_ou);
994 __PACKAGE__->register_method(
995 method => "get_org_types",
996 api_name => "open-ils.actor.org_types.retrieve",);
999 return $U->get_org_types();
1004 __PACKAGE__->register_method(
1005 method => "get_user_ident_types",
1006 api_name => "open-ils.actor.user.ident_types.retrieve",
1009 sub get_user_ident_types {
1010 return $ident_types if $ident_types;
1011 return $ident_types =
1012 new_editor()->retrieve_all_config_identification_type();
1018 __PACKAGE__->register_method(
1019 method => "get_org_unit",
1020 api_name => "open-ils.actor.org_unit.retrieve",
1024 my( $self, $client, $user_session, $org_id ) = @_;
1025 my $e = new_editor(authtoken => $user_session);
1027 return $e->event unless $e->checkauth;
1028 $org_id = $e->requestor->ws_ou;
1030 my $o = $e->retrieve_actor_org_unit($org_id)
1031 or return $e->event;
1035 __PACKAGE__->register_method(
1036 method => "search_org_unit",
1037 api_name => "open-ils.actor.org_unit_list.search",
1040 sub search_org_unit {
1042 my( $self, $client, $field, $value ) = @_;
1044 my $list = OpenILS::Application::AppUtils->simple_scalar_request(
1046 "open-ils.cstore.direct.actor.org_unit.search.atomic",
1047 { $field => $value } );
1053 # build the org tree
1055 __PACKAGE__->register_method(
1056 method => "get_org_tree",
1057 api_name => "open-ils.actor.org_tree.retrieve",
1059 note => "Returns the entire org tree structure",
1065 return $U->get_org_tree($client->session->session_locale);
1069 __PACKAGE__->register_method(
1070 method => "get_org_descendants",
1071 api_name => "open-ils.actor.org_tree.descendants.retrieve"
1074 # depth is optional. org_unit is the id
1075 sub get_org_descendants {
1076 my( $self, $client, $org_unit, $depth ) = @_;
1078 if(ref $org_unit eq 'ARRAY') {
1081 for my $i (0..scalar(@$org_unit)-1) {
1082 my $list = $U->simple_scalar_request(
1084 "open-ils.storage.actor.org_unit.descendants.atomic",
1085 $org_unit->[$i], $depth->[$i] );
1086 push(@trees, $U->build_org_tree($list));
1091 my $orglist = $apputils->simple_scalar_request(
1093 "open-ils.storage.actor.org_unit.descendants.atomic",
1094 $org_unit, $depth );
1095 return $U->build_org_tree($orglist);
1100 __PACKAGE__->register_method(
1101 method => "get_org_ancestors",
1102 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
1105 # depth is optional. org_unit is the id
1106 sub get_org_ancestors {
1107 my( $self, $client, $org_unit, $depth ) = @_;
1108 my $orglist = $apputils->simple_scalar_request(
1110 "open-ils.storage.actor.org_unit.ancestors.atomic",
1111 $org_unit, $depth );
1112 return $U->build_org_tree($orglist);
1116 __PACKAGE__->register_method(
1117 method => "get_standings",
1118 api_name => "open-ils.actor.standings.retrieve"
1123 return $user_standings if $user_standings;
1124 return $user_standings =
1125 $apputils->simple_scalar_request(
1127 "open-ils.cstore.direct.config.standing.search.atomic",
1128 { id => { "!=" => undef } }
1134 __PACKAGE__->register_method(
1135 method => "get_my_org_path",
1136 api_name => "open-ils.actor.org_unit.full_path.retrieve"
1139 sub get_my_org_path {
1140 my( $self, $client, $auth, $org_id ) = @_;
1141 my $e = new_editor(authtoken=>$auth);
1142 return $e->event unless $e->checkauth;
1143 $org_id = $e->requestor->ws_ou unless defined $org_id;
1145 return $apputils->simple_scalar_request(
1147 "open-ils.storage.actor.org_unit.full_path.atomic",
1152 __PACKAGE__->register_method(
1153 method => "patron_adv_search",
1154 api_name => "open-ils.actor.patron.search.advanced" );
1155 sub patron_adv_search {
1156 my( $self, $client, $auth, $search_hash,
1157 $search_limit, $search_sort, $include_inactive, $search_depth ) = @_;
1159 my $e = new_editor(authtoken=>$auth);
1160 return $e->event unless $e->checkauth;
1161 return $e->event unless $e->allowed('VIEW_USER');
1162 return $U->storagereq(
1163 "open-ils.storage.actor.user.crazy_search", $search_hash,
1164 $search_limit, $search_sort, $include_inactive, $e->requestor->ws_ou, $search_depth);
1168 __PACKAGE__->register_method(
1169 method => "update_passwd",
1171 api_name => "open-ils.actor.user.password.update");
1173 __PACKAGE__->register_method(
1174 method => "update_passwd",
1175 api_name => "open-ils.actor.user.username.update");
1177 __PACKAGE__->register_method(
1178 method => "update_passwd",
1179 api_name => "open-ils.actor.user.email.update");
1182 my( $self, $conn, $auth, $new_val, $orig_pw ) = @_;
1183 my $e = new_editor(xact=>1, authtoken=>$auth);
1184 return $e->die_event unless $e->checkauth;
1186 my $db_user = $e->retrieve_actor_user($e->requestor->id)
1187 or return $e->die_event;
1188 my $api = $self->api_name;
1190 if( $api =~ /password/o ) {
1192 # make sure the original password matches the in-database password
1193 return OpenILS::Event->new('INCORRECT_PASSWORD')
1194 if md5_hex($orig_pw) ne $db_user->passwd;
1195 $db_user->passwd($new_val);
1199 # if we don't clear the password, the user will be updated with
1200 # a hashed version of the hashed version of their password
1201 $db_user->clear_passwd;
1203 if( $api =~ /username/o ) {
1205 # make sure no one else has this username
1206 my $exist = $e->search_actor_user({usrname=>$new_val},{idlist=>1});
1207 return OpenILS::Event->new('USERNAME_EXISTS') if @$exist;
1208 $db_user->usrname($new_val);
1210 } elsif( $api =~ /email/o ) {
1211 $db_user->email($new_val);
1215 $e->update_actor_user($db_user) or return $e->die_event;
1223 __PACKAGE__->register_method(
1224 method => "check_user_perms",
1225 api_name => "open-ils.actor.user.perm.check",
1226 notes => <<" NOTES");
1227 Takes a login session, user id, an org id, and an array of perm type strings. For each
1228 perm type, if the user does *not* have the given permission it is added
1229 to a list which is returned from the method. If all permissions
1230 are allowed, an empty list is returned
1231 if the logged in user does not match 'user_id', then the logged in user must
1232 have VIEW_PERMISSION priveleges.
1235 sub check_user_perms {
1236 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1238 my( $staff, $evt ) = $apputils->checkses($login_session);
1239 return $evt if $evt;
1241 if($staff->id ne $user_id) {
1242 if( $evt = $apputils->check_perms(
1243 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1249 for my $perm (@$perm_types) {
1250 if($apputils->check_perms($user_id, $org_id, $perm)) {
1251 push @not_allowed, $perm;
1255 return \@not_allowed
1258 __PACKAGE__->register_method(
1259 method => "check_user_perms2",
1260 api_name => "open-ils.actor.user.perm.check.multi_org",
1262 Checks the permissions on a list of perms and orgs for a user
1263 @param authtoken The login session key
1264 @param user_id The id of the user to check
1265 @param orgs The array of org ids
1266 @param perms The array of permission names
1267 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1268 if the logged in user does not match 'user_id', then the logged in user must
1269 have VIEW_PERMISSION priveleges.
1272 sub check_user_perms2 {
1273 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1275 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1276 $authtoken, $user_id, 'VIEW_PERMISSION' );
1277 return $evt if $evt;
1280 for my $org (@$orgs) {
1281 for my $perm (@$perms) {
1282 if($apputils->check_perms($user_id, $org, $perm)) {
1283 push @not_allowed, [ $org, $perm ];
1288 return \@not_allowed
1292 __PACKAGE__->register_method(
1293 method => 'check_user_perms3',
1294 api_name => 'open-ils.actor.user.perm.highest_org',
1296 Returns the highest org unit id at which a user has a given permission
1297 If the requestor does not match the target user, the requestor must have
1298 'VIEW_PERMISSION' rights at the home org unit of the target user
1299 @param authtoken The login session key
1300 @param userid The id of the user in question
1301 @param perm The permission to check
1302 @return The org unit highest in the org tree within which the user has
1303 the requested permission
1306 sub check_user_perms3 {
1307 my($self, $client, $authtoken, $user_id, $perm) = @_;
1308 my $e = new_editor(authtoken=>$authtoken);
1309 return $e->event unless $e->checkauth;
1311 my $tree = $U->get_org_tree();
1313 unless($e->requestor->id == $user_id) {
1314 my $user = $e->retrieve_actor_user($user_id)
1315 or return $e->event;
1316 return $e->event unless $e->allowed('VIEW_PERMISSION', $user->home_ou);
1317 return $U->find_highest_perm_org($perm, $user_id, $user->home_ou, $tree );
1320 return $U->find_highest_perm_org($perm, $user_id, $e->requestor->ws_ou, $tree);
1324 __PACKAGE__->register_method(
1325 method => 'check_user_work_perms',
1326 api_name => 'open-ils.actor.user.work_perm.highest_org_set',
1330 Returns a set of org units which represent the highest orgs in
1331 the org tree where the user has the requested permission. The
1332 purpose of this method is to return the smallest set of org units
1333 which represent the full expanse of the user's ability to perform
1334 the requested action. The user whose perms this method should
1335 check is implied by the authtoken. /,
1337 {desc => 'authtoken', type => 'string'},
1338 {desc => 'permission name', type => 'string'},
1339 {desc => 'options hash, including "descendants", which will include all child orgs of the found perm orgs', type => 'hash'}
1341 return => {desc => 'An array of org IDs'}
1345 __PACKAGE__->register_method(
1346 method => 'check_user_work_perms',
1347 api_name => 'open-ils.actor.user.work_perm.org_tree_list',
1350 @see open-ils.actor.user.work_perm.highest_org_set
1351 Returns a list of org trees. The root of each tree
1352 is the highest org in the organization hierarchy where the user has the
1353 requested permission. Below each tree root is its full tree of descendants.
1357 __PACKAGE__->register_method(
1358 method => 'check_user_work_perms',
1359 api_name => 'open-ils.actor.user.work_perm.org_unit_list',
1362 @see open-ils.actor.user.work_perm.highest_org_set
1363 Returns a list of list of all of the org_units where the user
1364 has the requested permission. The first item in each list
1365 is the highest permission org for that section of the
1366 org tree. The remaining items in each sub-list are the
1367 descendants of that org.
1372 __PACKAGE__->register_method(
1373 method => 'check_user_work_perms',
1374 api_name => 'open-ils.actor.user.work_perm.org_id_list',
1377 @see open-ils.actor.user.work_perm.highest_org_set
1378 Returns a list of lists of all of the org_unit IDs where the user
1379 has the requested permission. The first item in each list
1380 is the highest permission org for that section of the
1381 org tree. The remaining items in each sub-list are the
1382 descendants of that org.
1386 __PACKAGE__->register_method(
1387 method => 'check_user_work_perms_batch',
1388 api_name => 'open-ils.actor.user.work_perm.highest_org_set.batch',
1391 __PACKAGE__->register_method(
1392 method => 'check_user_work_perms_batch',
1393 api_name => 'open-ils.actor.user.work_perm.org_tree_list.batch',
1396 __PACKAGE__->register_method(
1397 method => 'check_user_work_perms_batch',
1398 api_name => 'open-ils.actor.user.work_perm.org_unit_list.batch',
1401 __PACKAGE__->register_method(
1402 method => 'check_user_work_perms_batch',
1403 api_name => 'open-ils.actor.user.work_perm.org_id_list.batch',
1408 sub check_user_work_perms {
1409 my($self, $conn, $auth, $perm, $options) = @_;
1410 my $e = new_editor(authtoken=>$auth);
1411 return $e->event unless $e->checkauth;
1412 return check_user_work_perms_impl($self, $conn, $e, $perm, $options);
1415 sub check_user_work_perms_batch {
1416 my($self, $conn, $auth, $perm_list, $options) = @_;
1417 my $e = new_editor(authtoken=>$auth);
1418 return $e->event unless $e->checkauth;
1420 $map->{$_} = check_user_work_perms_impl($self, $conn, $e, $_, $options) for @$perm_list;
1424 sub check_user_work_perms_impl {
1425 my($self, $conn, $e, $perm, $options) = @_;
1426 my $orglist = $U->find_highest_work_orgs($e, $perm, $options);
1428 return $orglist if $self->api_name =~ /highest_org_set/;
1430 # build a list of org trees
1431 return get_org_descendants($self, $conn, $orglist)
1432 if $self->api_name =~ /org_tree_list/;
1435 for my $orgid (@$orglist) {
1436 my @sublist = grep {$_ ne $orgid} @{$U->get_org_descendants($orgid)};
1437 unshift @sublist, $orgid; # make sure it's at the front of the list
1438 if($self->api_name =~ /org_id_list/) {
1439 push(@list, @sublist);
1441 push(@list, @{$e->batch_retrieve_actor_org_unit(\@sublist)});
1449 __PACKAGE__->register_method(
1450 method => 'check_user_perms4',
1451 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1453 Returns the highest org unit id at which a user has a given permission
1454 If the requestor does not match the target user, the requestor must have
1455 'VIEW_PERMISSION' rights at the home org unit of the target user
1456 @param authtoken The login session key
1457 @param userid The id of the user in question
1458 @param perms An array of perm names to check
1459 @return An array of orgId's representing the org unit
1460 highest in the org tree within which the user has the requested permission
1461 The arrah of orgId's has matches the order of the perms array
1464 sub check_user_perms4 {
1465 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1467 my( $staff, $target, $org, $evt );
1469 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1470 $authtoken, $userid, 'VIEW_PERMISSION' );
1471 return $evt if $evt;
1474 return [] unless ref($perms);
1475 my $tree = $U->get_org_tree();
1477 for my $p (@$perms) {
1478 push( @arr, $U->find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1486 __PACKAGE__->register_method(
1487 method => "user_fines_summary",
1488 api_name => "open-ils.actor.user.fines.summary",
1490 notes => <<" NOTES");
1491 Returns a short summary of the users total open fines, excluding voided fines
1492 Params are login_session, user_id
1493 Returns a 'mous' object.
1496 sub user_fines_summary {
1497 my( $self, $client, $auth, $user_id ) = @_;
1498 my $e = new_editor(authtoken=>$auth);
1499 return $e->event unless $e->checkauth;
1500 my $user = $e->retrieve_actor_user($user_id)
1501 or return $e->event;
1503 if( $user_id ne $e->requestor->id ) {
1504 return $e->event unless
1505 $e->allowed('VIEW_USER_FINES_SUMMARY', $user->home_ou);
1508 # run this inside a transaction to prevent replication delay errors
1509 my $ses = $U->start_db_session();
1510 my $s = $ses->request(
1511 'open-ils.storage.money.open_user_summary.search', $user_id )->gather(1);
1512 $U->rollback_db_session($ses);
1519 __PACKAGE__->register_method(
1520 method => "user_transactions",
1521 api_name => "open-ils.actor.user.transactions",
1522 notes => <<" NOTES");
1523 Returns a list of open user transactions (mbts objects);
1524 Params are login_session, user_id
1525 Optional third parameter is the transactions type. defaults to all
1528 __PACKAGE__->register_method(
1529 method => "user_transactions",
1530 api_name => "open-ils.actor.user.transactions.have_charge",
1531 notes => <<" NOTES");
1532 Returns a list of all open user transactions (mbts objects) that have an initial charge
1533 Params are login_session, user_id
1534 Optional third parameter is the transactions type. defaults to all
1537 __PACKAGE__->register_method(
1538 method => "user_transactions",
1539 api_name => "open-ils.actor.user.transactions.have_balance",
1540 notes => <<" NOTES");
1541 Returns a list of all open user transactions (mbts objects) that have a balance
1542 Params are login_session, user_id
1543 Optional third parameter is the transactions type. defaults to all
1546 __PACKAGE__->register_method(
1547 method => "user_transactions",
1548 api_name => "open-ils.actor.user.transactions.fleshed",
1549 notes => <<" NOTES");
1550 Returns an object/hash of transaction, circ, title where transaction = an open
1551 user transactions (mbts objects), circ is the attached circluation, and title
1552 is the title the circ points to
1553 Params are login_session, user_id
1554 Optional third parameter is the transactions type. defaults to all
1557 __PACKAGE__->register_method(
1558 method => "user_transactions",
1559 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1560 notes => <<" NOTES");
1561 Returns an object/hash of transaction, circ, title where transaction = an open
1562 user transactions that has an initial charge (mbts objects), circ is the
1563 attached circluation, and title is the title the circ points to
1564 Params are login_session, user_id
1565 Optional third parameter is the transactions type. defaults to all
1568 __PACKAGE__->register_method(
1569 method => "user_transactions",
1570 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1571 notes => <<" NOTES");
1572 Returns an object/hash of transaction, circ, title where transaction = an open
1573 user transaction that has a balance (mbts objects), circ is the attached
1574 circluation, and title is the title the circ points to
1575 Params are login_session, user_id
1576 Optional third parameter is the transaction type. defaults to all
1579 __PACKAGE__->register_method(
1580 method => "user_transactions",
1581 api_name => "open-ils.actor.user.transactions.count",
1582 notes => <<" NOTES");
1583 Returns an object/hash of transaction, circ, title where transaction = an open
1584 user transactions (mbts objects), circ is the attached circluation, and title
1585 is the title the circ points to
1586 Params are login_session, user_id
1587 Optional third parameter is the transactions type. defaults to all
1590 __PACKAGE__->register_method(
1591 method => "user_transactions",
1592 api_name => "open-ils.actor.user.transactions.have_charge.count",
1593 notes => <<" NOTES");
1594 Returns an object/hash of transaction, circ, title where transaction = an open
1595 user transactions that has an initial charge (mbts objects), circ is the
1596 attached circluation, and title is the title the circ points to
1597 Params are login_session, user_id
1598 Optional third parameter is the transactions type. defaults to all
1601 __PACKAGE__->register_method(
1602 method => "user_transactions",
1603 api_name => "open-ils.actor.user.transactions.have_balance.count",
1604 notes => <<" NOTES");
1605 Returns an object/hash of transaction, circ, title where transaction = an open
1606 user transaction that has a balance (mbts objects), circ is the attached
1607 circluation, and title is the title the circ points to
1608 Params are login_session, user_id
1609 Optional third parameter is the transaction type. defaults to all
1612 __PACKAGE__->register_method(
1613 method => "user_transactions",
1614 api_name => "open-ils.actor.user.transactions.have_balance.total",
1615 notes => <<" NOTES");
1616 Returns an object/hash of transaction, circ, title where transaction = an open
1617 user transaction that has a balance (mbts objects), circ is the attached
1618 circluation, and title is the title the circ points to
1619 Params are login_session, user_id
1620 Optional third parameter is the transaction type. defaults to all
1625 sub user_transactions {
1626 my( $self, $client, $login_session, $user_id, $type ) = @_;
1628 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1629 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1630 return $evt if $evt;
1632 my $api = $self->api_name();
1636 if(defined($type)) { @xact = (xact_type => $type);
1638 } else { @xact = (); }
1641 ->method_lookup('open-ils.actor.user.transactions.history.still_open')
1642 ->run($login_session => $user_id => $type);
1644 if($api =~ /have_charge/o) {
1646 $trans = [ grep { int($_->total_owed * 100) > 0 } @$trans ];
1648 } elsif($api =~ /have_balance/o) {
1650 $trans = [ grep { int($_->balance_owed * 100) != 0 } @$trans ];
1653 $trans = [ grep { int($_->total_owed * 100) > 0 } @$trans ];
1657 if($api =~ /total/o) {
1659 for my $t (@$trans) {
1660 $total += $t->balance_owed;
1663 $logger->debug("Total balance owed by user $user_id: $total");
1667 if($api =~ /count/o) { return scalar @$trans; }
1668 if($api !~ /fleshed/o) { return $trans; }
1671 for my $t (@$trans) {
1673 if( $t->xact_type ne 'circulation' ) {
1674 push @resp, {transaction => $t};
1678 my $circ = $apputils->simple_scalar_request(
1680 "open-ils.cstore.direct.action.circulation.retrieve",
1685 my $title = $apputils->simple_scalar_request(
1687 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1688 $circ->target_copy );
1692 my $u = OpenILS::Utils::ModsParser->new();
1693 $u->start_mods_batch($title->marc());
1694 my $mods = $u->finish_mods_batch();
1695 $mods->doc_id($title->id) if $mods;
1697 push @resp, {transaction => $t, circ => $circ, record => $mods };
1705 __PACKAGE__->register_method(
1706 method => "user_transaction_retrieve",
1707 api_name => "open-ils.actor.user.transaction.fleshed.retrieve",
1709 notes => <<" NOTES");
1710 Returns a fleshedtransaction record
1712 __PACKAGE__->register_method(
1713 method => "user_transaction_retrieve",
1714 api_name => "open-ils.actor.user.transaction.retrieve",
1716 notes => <<" NOTES");
1717 Returns a transaction record
1719 sub user_transaction_retrieve {
1720 my( $self, $client, $login_session, $bill_id ) = @_;
1722 # XXX I think I'm deprecated... make sure
1724 my $trans = $apputils->simple_scalar_request(
1726 "open-ils.cstore.direct.money.billable_transaction_summary.retrieve",
1730 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1731 $login_session, $trans->usr, 'VIEW_USER_TRANSACTIONS' );
1732 return $evt if $evt;
1734 my $api = $self->api_name();
1735 if($api !~ /fleshed/o) { return $trans; }
1737 if( $trans->xact_type ne 'circulation' ) {
1738 $logger->debug("Returning non-circ transaction");
1739 return {transaction => $trans};
1742 my $circ = $apputils->simple_scalar_request(
1744 "open-ils..direct.action.circulation.retrieve",
1747 return {transaction => $trans} unless $circ;
1748 $logger->debug("Found the circ transaction");
1750 my $title = $apputils->simple_scalar_request(
1752 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1753 $circ->target_copy );
1755 return {transaction => $trans, circ => $circ } unless $title;
1756 $logger->debug("Found the circ title");
1760 my $u = OpenILS::Utils::ModsParser->new();
1761 $u->start_mods_batch($title->marc());
1762 $mods = $u->finish_mods_batch();
1764 if ($title->id == OILS_PRECAT_RECORD) {
1765 my $copy = $apputils->simple_scalar_request(
1767 "open-ils.cstore.direct.asset.copy.retrieve",
1768 $circ->target_copy );
1770 $mods = new Fieldmapper::metabib::virtual_record;
1771 $mods->doc_id(OILS_PRECAT_RECORD);
1772 $mods->title($copy->dummy_title);
1773 $mods->author($copy->dummy_author);
1777 $logger->debug("MODSized the circ title");
1779 return {transaction => $trans, circ => $circ, record => $mods };
1783 __PACKAGE__->register_method(
1784 method => "hold_request_count",
1785 api_name => "open-ils.actor.user.hold_requests.count",
1788 notes => <<" NOTES");
1789 Returns hold ready/total counts
1791 sub hold_request_count {
1792 my( $self, $client, $login_session, $userid ) = @_;
1794 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1795 $login_session, $userid, 'VIEW_HOLD' );
1796 return $evt if $evt;
1799 my $holds = $apputils->simple_scalar_request(
1801 "open-ils.cstore.direct.action.hold_request.search.atomic",
1804 fulfillment_time => {"=" => undef },
1805 cancel_time => undef,
1810 for my $h (@$holds) {
1811 next unless $h->capture_time and $h->current_copy;
1813 my $copy = $apputils->simple_scalar_request(
1815 "open-ils.cstore.direct.asset.copy.retrieve",
1819 if ($copy and $copy->status == 8) {
1824 return { total => scalar(@$holds), ready => scalar(@ready) };
1828 __PACKAGE__->register_method(
1829 method => "checkedout_count",
1830 api_name => "open-ils.actor.user.checked_out.count__",
1832 notes => <<" NOTES");
1833 Returns a transaction record
1837 sub checkedout_count {
1838 my( $self, $client, $login_session, $userid ) = @_;
1840 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1841 $login_session, $userid, 'VIEW_CIRCULATIONS' );
1842 return $evt if $evt;
1844 my $circs = $apputils->simple_scalar_request(
1846 "open-ils.cstore.direct.action.circulation.search.atomic",
1847 { usr => $userid, stop_fines => undef }
1848 #{ usr => $userid, checkin_time => {"=" => undef } }
1851 my $parser = DateTime::Format::ISO8601->new;
1854 for my $c (@$circs) {
1855 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1856 my $due = $due_dt->epoch;
1858 if ($due < DateTime->today->epoch) {
1863 return { total => scalar(@$circs), overdue => scalar(@overdue) };
1867 __PACKAGE__->register_method(
1868 method => "checked_out",
1869 api_name => "open-ils.actor.user.checked_out",
1873 Returns a structure of circulations objects sorted by
1874 out, overdue, lost, claims_returned, long_overdue.
1875 A list of IDs are returned of each type.
1876 lost, long_overdue, and claims_returned circ will not
1877 be "finished" (there is an outstanding balance or some
1878 other pending action on the circ).
1880 The .count method also includes a 'total' field which
1881 sums all "open" circs
1885 __PACKAGE__->register_method(
1886 method => "checked_out",
1887 api_name => "open-ils.actor.user.checked_out.count",
1890 signature => q/@see open-ils.actor.user.checked_out/
1894 my( $self, $conn, $auth, $userid ) = @_;
1896 my $e = new_editor(authtoken=>$auth);
1897 return $e->event unless $e->checkauth;
1899 if( $userid ne $e->requestor->id ) {
1900 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
1903 my $count = $self->api_name =~ /count/;
1904 return _checked_out( $count, $e, $userid );
1908 my( $iscount, $e, $userid ) = @_;
1909 my $meth = 'open-ils.storage.actor.user.checked_out';
1910 $meth = "$meth.count" if $iscount;
1911 return $U->storagereq($meth, $userid);
1915 sub _checked_out_WHAT {
1916 my( $iscount, $e, $userid ) = @_;
1918 my $circs = $e->search_action_circulation(
1919 { usr => $userid, stop_fines => undef });
1921 my $mcircs = $e->search_action_circulation(
1924 checkin_time => undef,
1925 xact_finish => undef,
1929 push( @$circs, @$mcircs );
1931 my $parser = DateTime::Format::ISO8601->new;
1933 # split the circs up into overdue and not-overdue circs
1935 for my $c (@$circs) {
1936 if( $c->due_date ) {
1937 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1938 my $due = $due_dt->epoch;
1939 if ($due < DateTime->today->epoch) {
1940 push @overdue, $c->id;
1949 # grab all of the lost, claims-returned, and longoverdue circs
1950 #my $open = $e->search_action_circulation(
1951 # {usr => $userid, stop_fines => { '!=' => undef }, xact_finish => undef });
1954 # these items have stop_fines, but no xact_finish, so money
1955 # is owed on them and they have not been checked in
1956 my $open = $e->search_action_circulation(
1959 stop_fines => { in => [ qw/LOST CLAIMSRETURNED LONGOVERDUE/ ] },
1960 xact_finish => undef,
1961 checkin_time => undef,
1966 my( @lost, @cr, @lo );
1967 for my $c (@$open) {
1968 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1969 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1970 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
1976 total => @$circs + @lost + @cr + @lo,
1977 out => scalar(@out),
1978 overdue => scalar(@overdue),
1979 lost => scalar(@lost),
1980 claims_returned => scalar(@cr),
1981 long_overdue => scalar(@lo)
1987 overdue => \@overdue,
1989 claims_returned => \@cr,
1990 long_overdue => \@lo
1996 __PACKAGE__->register_method(
1997 method => "checked_in_with_fines",
1998 api_name => "open-ils.actor.user.checked_in_with_fines",
2001 signature => q/@see open-ils.actor.user.checked_out/
2003 sub checked_in_with_fines {
2004 my( $self, $conn, $auth, $userid ) = @_;
2006 my $e = new_editor(authtoken=>$auth);
2007 return $e->event unless $e->checkauth;
2009 if( $userid ne $e->requestor->id ) {
2010 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
2013 # money is owed on these items and they are checked in
2014 my $open = $e->search_action_circulation(
2017 xact_finish => undef,
2018 checkin_time => { "!=" => undef },
2023 my( @lost, @cr, @lo );
2024 for my $c (@$open) {
2025 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
2026 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
2027 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
2032 claims_returned => \@cr,
2033 long_overdue => \@lo
2045 __PACKAGE__->register_method(
2046 method => "user_transaction_history",
2047 api_name => "open-ils.actor.user.transactions.history",
2049 notes => <<" NOTES");
2050 Returns a list of billable transaction ids for a user, optionally by type
2052 __PACKAGE__->register_method(
2053 method => "user_transaction_history",
2054 api_name => "open-ils.actor.user.transactions.history.have_charge",
2056 notes => <<" NOTES");
2057 Returns a list of billable transaction ids for a user that have an initial charge, optionally by type
2059 __PACKAGE__->register_method(
2060 method => "user_transaction_history",
2061 api_name => "open-ils.actor.user.transactions.history.have_balance",
2064 notes => <<" NOTES");
2065 Returns a list of billable transaction ids for a user that have a balance, optionally by type
2067 __PACKAGE__->register_method(
2068 method => "user_transaction_history",
2069 api_name => "open-ils.actor.user.transactions.history.still_open",
2071 notes => <<" NOTES");
2072 Returns a list of billable transaction ids for a user that are not finished
2074 __PACKAGE__->register_method(
2075 method => "user_transaction_history",
2076 api_name => "open-ils.actor.user.transactions.history.have_bill",
2079 notes => <<" NOTES");
2080 Returns a list of billable transaction ids for a user that has billings
2083 sub user_transaction_history {
2084 my( $self, $conn, $auth, $userid, $type ) = @_;
2086 # run inside of a transaction to prevent replication delays
2087 my $e = new_editor(xact=>1, authtoken=>$auth);
2088 return $e->die_event unless $e->checkauth;
2090 if( $e->requestor->id ne $userid ) {
2091 return $e->die_event
2092 unless $e->allowed('VIEW_USER_TRANSACTIONS');
2095 my $api = $self->api_name;
2096 my @xact_finish = (xact_finish => undef ) if ($api =~ /history.still_open$/);
2098 my @xacts = @{ $e->search_money_billable_transaction(
2099 [ { usr => $userid, @xact_finish },
2101 flesh_fields => { mbt => [ qw/billings payments grocery circulation/ ] },
2102 order_by => { mbt => 'xact_start DESC' },
2110 #my @mbts = _make_mbts( @xacts );
2111 my @mbts = $U->make_mbts( @xacts );
2113 if(defined($type)) {
2114 @mbts = grep { $_->xact_type eq $type } @mbts;
2117 if($api =~ /have_balance/o) {
2118 @mbts = grep { int($_->balance_owed * 100) != 0 } @mbts;
2121 if($api =~ /have_charge/o) {
2122 @mbts = grep { defined($_->last_billing_ts) } @mbts;
2125 if($api =~ /have_bill/o) {
2126 @mbts = grep { int($_->total_owed * 100) != 0 } @mbts;
2134 __PACKAGE__->register_method(
2135 method => "user_perms",
2136 api_name => "open-ils.actor.permissions.user_perms.retrieve",
2138 notes => <<" NOTES");
2139 Returns a list of permissions
2142 my( $self, $client, $authtoken, $user ) = @_;
2144 my( $staff, $evt ) = $apputils->checkses($authtoken);
2145 return $evt if $evt;
2147 $user ||= $staff->id;
2149 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
2153 return $apputils->simple_scalar_request(
2155 "open-ils.storage.permission.user_perms.atomic",
2159 __PACKAGE__->register_method(
2160 method => "retrieve_perms",
2161 api_name => "open-ils.actor.permissions.retrieve",
2162 notes => <<" NOTES");
2163 Returns a list of permissions
2165 sub retrieve_perms {
2166 my( $self, $client ) = @_;
2167 return $apputils->simple_scalar_request(
2169 "open-ils.cstore.direct.permission.perm_list.search.atomic",
2170 { id => { '!=' => undef } }
2174 __PACKAGE__->register_method(
2175 method => "retrieve_groups",
2176 api_name => "open-ils.actor.groups.retrieve",
2177 notes => <<" NOTES");
2178 Returns a list of user groupss
2180 sub retrieve_groups {
2181 my( $self, $client ) = @_;
2182 return new_editor()->retrieve_all_permission_grp_tree();
2185 __PACKAGE__->register_method(
2186 method => "retrieve_org_address",
2187 api_name => "open-ils.actor.org_unit.address.retrieve",
2188 notes => <<' NOTES');
2189 Returns an org_unit address by ID
2190 @param An org_address ID
2192 sub retrieve_org_address {
2193 my( $self, $client, $id ) = @_;
2194 return $apputils->simple_scalar_request(
2196 "open-ils.cstore.direct.actor.org_address.retrieve",
2201 __PACKAGE__->register_method(
2202 method => "retrieve_groups_tree",
2203 api_name => "open-ils.actor.groups.tree.retrieve",
2204 notes => <<" NOTES");
2205 Returns a list of user groups
2207 sub retrieve_groups_tree {
2208 my( $self, $client ) = @_;
2209 return new_editor()->search_permission_grp_tree(
2214 flesh_fields => { pgt => ["children"] },
2215 order_by => { pgt => 'name'}
2222 __PACKAGE__->register_method(
2223 method => "add_user_to_groups",
2224 api_name => "open-ils.actor.user.set_groups",
2225 notes => <<" NOTES");
2226 Adds a user to one or more permission groups
2229 sub add_user_to_groups {
2230 my( $self, $client, $authtoken, $userid, $groups ) = @_;
2232 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2233 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
2234 return $evt if $evt;
2236 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2237 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
2238 return $evt if $evt;
2240 $apputils->simplereq(
2242 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
2244 for my $group (@$groups) {
2245 my $link = Fieldmapper::permission::usr_grp_map->new;
2247 $link->usr($userid);
2249 my $id = $apputils->simplereq(
2251 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
2257 __PACKAGE__->register_method(
2258 method => "get_user_perm_groups",
2259 api_name => "open-ils.actor.user.get_groups",
2260 notes => <<" NOTES");
2261 Retrieve a user's permission groups.
2265 sub get_user_perm_groups {
2266 my( $self, $client, $authtoken, $userid ) = @_;
2268 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2269 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
2270 return $evt if $evt;
2272 return $apputils->simplereq(
2274 'open-ils.cstore.direct.permission.usr_grp_map.search.atomic', { usr => $userid } );
2278 __PACKAGE__->register_method(
2279 method => "get_user_work_ous",
2280 api_name => "open-ils.actor.user.get_work_ous",
2281 notes => <<" NOTES");
2282 Retrieve a user's work org units.
2284 __PACKAGE__->register_method(
2285 method => "get_user_work_ous",
2286 api_name => "open-ils.actor.user.get_work_ous.ids",
2287 notes => <<" NOTES");
2288 Retrieve a user's work org units.
2292 sub get_user_work_ous {
2293 my( $self, $client, $auth, $userid ) = @_;
2294 my $e = new_editor(authtoken=>$auth);
2295 return $e->event unless $e->checkauth;
2296 $userid ||= $e->requestor->id;
2298 if($e->requestor->id != $userid) {
2299 my $user = $e->retrieve_actor_user($userid)
2300 or return $e->event;
2301 return $e->event unless $e->allowed('ASSIGN_WORK_ORG_UNIT', $user->home_ou);
2304 return $e->search_permission_usr_work_ou_map({usr => $userid})
2305 unless $self->api_name =~ /.ids$/;
2307 # client just wants a list of org IDs
2308 return $U->get_user_work_ou_ids($e, $userid);
2314 __PACKAGE__->register_method (
2315 method => 'register_workstation',
2316 api_name => 'open-ils.actor.workstation.register.override',
2317 signature => q/@see open-ils.actor.workstation.register/);
2319 __PACKAGE__->register_method (
2320 method => 'register_workstation',
2321 api_name => 'open-ils.actor.workstation.register',
2323 Registers a new workstion in the system
2324 @param authtoken The login session key
2325 @param name The name of the workstation id
2326 @param owner The org unit that owns this workstation
2327 @return The workstation id on success, WORKSTATION_NAME_EXISTS
2328 if the name is already in use.
2331 sub register_workstation {
2332 my( $self, $conn, $authtoken, $name, $owner ) = @_;
2334 my $e = new_editor(authtoken=>$authtoken, xact=>1);
2335 return $e->die_event unless $e->checkauth;
2336 return $e->die_event unless $e->allowed('REGISTER_WORKSTATION', $owner);
2337 my $existing = $e->search_actor_workstation({name => $name})->[0];
2341 if( $self->api_name =~ /override/o ) {
2342 # workstation with the given name exists.
2344 if($owner ne $existing->owning_lib) {
2345 # if necessary, update the owning_lib of the workstation
2347 $logger->info("changing owning lib of workstation ".$existing->id.
2348 " from ".$existing->owning_lib." to $owner");
2349 return $e->die_event unless
2350 $e->allowed('UPDATE_WORKSTATION', $existing->owning_lib);
2352 return $e->die_event unless $e->allowed('UPDATE_WORKSTATION', $owner);
2354 $existing->owning_lib($owner);
2355 return $e->die_event unless $e->update_actor_workstation($existing);
2361 "attempt to register an existing workstation. returning existing ID");
2364 return $existing->id;
2367 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS')
2371 my $ws = Fieldmapper::actor::workstation->new;
2372 $ws->owning_lib($owner);
2374 $e->create_actor_workstation($ws) or return $e->die_event;
2376 return $ws->id; # note: editor sets the id on the new object for us
2379 __PACKAGE__->register_method (
2380 method => 'workstation_list',
2381 api_name => 'open-ils.actor.workstation.list',
2383 Returns a list of workstations registered at the given location
2384 @param authtoken The login session key
2385 @param ids A list of org_unit.id's for the workstation owners
2388 sub workstation_list {
2389 my( $self, $conn, $authtoken, @orgs ) = @_;
2391 my $e = new_editor(authtoken=>$authtoken);
2392 return $e->event unless $e->checkauth;
2397 unless $e->allowed('REGISTER_WORKSTATION', $o);
2398 $results{$o} = $e->search_actor_workstation({owning_lib=>$o});
2409 __PACKAGE__->register_method (
2410 method => 'fetch_patron_note',
2411 api_name => 'open-ils.actor.note.retrieve.all',
2414 Returns a list of notes for a given user
2415 Requestor must have VIEW_USER permission if pub==false and
2416 @param authtoken The login session key
2417 @param args Hash of params including
2418 patronid : the patron's id
2419 pub : true if retrieving only public notes
2423 sub fetch_patron_note {
2424 my( $self, $conn, $authtoken, $args ) = @_;
2425 my $patronid = $$args{patronid};
2427 my($reqr, $evt) = $U->checkses($authtoken);
2428 return $evt if $evt;
2431 ($patron, $evt) = $U->fetch_user($patronid);
2432 return $evt if $evt;
2435 if( $patronid ne $reqr->id ) {
2436 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2437 return $evt if $evt;
2439 return $U->cstorereq(
2440 'open-ils.cstore.direct.actor.usr_note.search.atomic',
2441 { usr => $patronid, pub => 't' } );
2444 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2445 return $evt if $evt;
2447 return $U->cstorereq(
2448 'open-ils.cstore.direct.actor.usr_note.search.atomic', { usr => $patronid } );
2451 __PACKAGE__->register_method (
2452 method => 'create_user_note',
2453 api_name => 'open-ils.actor.note.create',
2455 Creates a new note for the given user
2456 @param authtoken The login session key
2457 @param note The note object
2460 sub create_user_note {
2461 my( $self, $conn, $authtoken, $note ) = @_;
2462 my $e = new_editor(xact=>1, authtoken=>$authtoken);
2463 return $e->die_event unless $e->checkauth;
2465 my $user = $e->retrieve_actor_user($note->usr)
2466 or return $e->die_event;
2468 return $e->die_event unless
2469 $e->allowed('UPDATE_USER',$user->home_ou);
2471 $note->creator($e->requestor->id);
2472 $e->create_actor_usr_note($note) or return $e->die_event;
2478 __PACKAGE__->register_method (
2479 method => 'delete_user_note',
2480 api_name => 'open-ils.actor.note.delete',
2482 Deletes a note for the given user
2483 @param authtoken The login session key
2484 @param noteid The note id
2487 sub delete_user_note {
2488 my( $self, $conn, $authtoken, $noteid ) = @_;
2490 my $e = new_editor(xact=>1, authtoken=>$authtoken);
2491 return $e->die_event unless $e->checkauth;
2492 my $note = $e->retrieve_actor_usr_note($noteid)
2493 or return $e->die_event;
2494 my $user = $e->retrieve_actor_user($note->usr)
2495 or return $e->die_event;
2496 return $e->die_event unless
2497 $e->allowed('UPDATE_USER', $user->home_ou);
2499 $e->delete_actor_usr_note($note) or return $e->die_event;
2505 __PACKAGE__->register_method (
2506 method => 'update_user_note',
2507 api_name => 'open-ils.actor.note.update',
2509 @param authtoken The login session key
2510 @param note The note
2514 sub update_user_note {
2515 my( $self, $conn, $auth, $note ) = @_;
2516 my $e = new_editor(authtoken=>$auth, xact=>1);
2517 return $e->event unless $e->checkauth;
2518 my $patron = $e->retrieve_actor_user($note->usr)
2519 or return $e->event;
2520 return $e->event unless
2521 $e->allowed('UPDATE_USER', $patron->home_ou);
2522 $e->update_actor_user_note($note)
2523 or return $e->event;
2531 __PACKAGE__->register_method (
2532 method => 'create_closed_date',
2533 api_name => 'open-ils.actor.org_unit.closed_date.create',
2535 Creates a new closing entry for the given org_unit
2536 @param authtoken The login session key
2537 @param note The closed_date object
2540 sub create_closed_date {
2541 my( $self, $conn, $authtoken, $cd ) = @_;
2543 my( $user, $evt ) = $U->checkses($authtoken);
2544 return $evt if $evt;
2546 $evt = $U->check_perms($user->id, $cd->org_unit, 'CREATE_CLOSEING');
2547 return $evt if $evt;
2549 $logger->activity("user ".$user->id." creating library closing for ".$cd->org_unit);
2551 my $id = $U->storagereq(
2552 'open-ils.storage.direct.actor.org_unit.closed_date.create', $cd );
2553 return $U->DB_UPDATE_FAILED($cd) unless $id;
2558 __PACKAGE__->register_method (
2559 method => 'delete_closed_date',
2560 api_name => 'open-ils.actor.org_unit.closed_date.delete',
2562 Deletes a closing entry for the given org_unit
2563 @param authtoken The login session key
2564 @param noteid The close_date id
2567 sub delete_closed_date {
2568 my( $self, $conn, $authtoken, $cd ) = @_;
2570 my( $user, $evt ) = $U->checkses($authtoken);
2571 return $evt if $evt;
2574 ($cd_obj, $evt) = fetch_closed_date($cd);
2575 return $evt if $evt;
2577 $evt = $U->check_perms($user->id, $cd->org_unit, 'DELETE_CLOSEING');
2578 return $evt if $evt;
2580 $logger->activity("user ".$user->id." deleting library closing for ".$cd->org_unit);
2582 my $stat = $U->storagereq(
2583 'open-ils.storage.direct.actor.org_unit.closed_date.delete', $cd );
2584 return $U->DB_UPDATE_FAILED($cd) unless $stat;
2589 __PACKAGE__->register_method(
2590 method => 'usrname_exists',
2591 api_name => 'open-ils.actor.username.exists',
2593 Returns 1 if the requested username exists, returns 0 otherwise
2597 sub usrname_exists {
2598 my( $self, $conn, $auth, $usrname ) = @_;
2599 my $e = new_editor(authtoken=>$auth);
2600 return $e->event unless $e->checkauth;
2601 my $a = $e->search_actor_user({usrname => $usrname, deleted=>'f'}, {idlist=>1});
2602 return $$a[0] if $a and @$a;
2606 __PACKAGE__->register_method(
2607 method => 'barcode_exists',
2608 api_name => 'open-ils.actor.barcode.exists',
2611 Returns 1 if the requested barcode exists, returns 0 otherwise
2615 sub barcode_exists {
2616 my( $self, $conn, $auth, $barcode ) = @_;
2617 my $e = new_editor(authtoken=>$auth);
2618 return $e->event unless $e->checkauth;
2619 my $card = $e->search_actor_card({barcode => $barcode});
2625 #return undef unless @$card;
2626 #return $card->[0]->usr;
2630 __PACKAGE__->register_method(
2631 method => 'retrieve_net_levels',
2632 api_name => 'open-ils.actor.net_access_level.retrieve.all',
2635 sub retrieve_net_levels {
2636 my( $self, $conn, $auth ) = @_;
2637 my $e = new_editor(authtoken=>$auth);
2638 return $e->event unless $e->checkauth;
2639 return $e->retrieve_all_config_net_access_level();
2643 __PACKAGE__->register_method(
2644 method => 'fetch_org_by_shortname',
2645 api_name => 'open-ils.actor.org_unit.retrieve_by_shorname',
2647 sub fetch_org_by_shortname {
2648 my( $self, $conn, $sname ) = @_;
2649 my $e = new_editor();
2650 my $org = $e->search_actor_org_unit({ shortname => uc($sname)})->[0];
2651 return $e->event unless $org;
2656 __PACKAGE__->register_method(
2657 method => 'session_home_lib',
2658 api_name => 'open-ils.actor.session.home_lib',
2661 sub session_home_lib {
2662 my( $self, $conn, $auth ) = @_;
2663 my $e = new_editor(authtoken=>$auth);
2664 return undef unless $e->checkauth;
2665 my $org = $e->retrieve_actor_org_unit($e->requestor->home_ou);
2666 return $org->shortname;
2669 __PACKAGE__->register_method(
2670 method => 'session_safe_token',
2671 api_name => 'open-ils.actor.session.safe_token',
2673 Returns a hashed session ID that is safe for export to the world.
2674 This safe token will expire after 1 hour of non-use.
2675 @param auth Active authentication token
2679 sub session_safe_token {
2680 my( $self, $conn, $auth ) = @_;
2681 my $e = new_editor(authtoken=>$auth);
2682 return undef unless $e->checkauth;
2684 my $safe_token = md5_hex($auth);
2686 $cache ||= OpenSRF::Utils::Cache->new("global", 0);
2688 # Add more like the following if needed...
2690 "safe-token-home_lib-shortname-$safe_token",
2691 $e->retrieve_actor_org_unit(
2692 $e->requestor->home_ou
2701 __PACKAGE__->register_method(
2702 method => 'safe_token_home_lib',
2703 api_name => 'open-ils.actor.safe_token.home_lib.shortname',
2705 Returns the home library shortname from the session
2706 asscociated with a safe token from generated by
2707 open-ils.actor.session.safe_token.
2708 @param safe_token Active safe token
2712 sub safe_token_home_lib {
2713 my( $self, $conn, $safe_token ) = @_;
2715 $cache ||= OpenSRF::Utils::Cache->new("global", 0);
2716 return $cache->get_cache( 'safe-token-home_lib-shortname-'. $safe_token );
2721 __PACKAGE__->register_method(
2722 method => 'slim_tree',
2723 api_name => "open-ils.actor.org_tree.slim_hash.retrieve",
2726 my $tree = new_editor()->search_actor_org_unit(
2728 {"parent_ou" => undef },
2731 flesh_fields => { aou => ['children'] },
2732 order_by => { aou => 'name'},
2733 select => { aou => ["id","shortname", "name"]},
2738 return trim_tree($tree);
2744 return undef unless $tree;
2746 code => $tree->shortname,
2747 name => $tree->name,
2749 if( $tree->children and @{$tree->children} ) {
2750 $htree->{children} = [];
2751 for my $c (@{$tree->children}) {
2752 push( @{$htree->{children}}, trim_tree($c) );
2760 __PACKAGE__->register_method(
2761 method => "update_penalties",
2762 api_name => "open-ils.actor.user.penalties.update");
2763 sub update_penalties {
2764 my( $self, $conn, $auth, $userid ) = @_;
2765 my $e = new_editor(authtoken=>$auth);
2766 return $e->event unless $e->checkauth;
2767 $U->update_patron_penalties(
2769 patronid => $userid,
2776 __PACKAGE__->register_method(
2777 method => "user_retrieve_fleshed_by_id",
2778 api_name => "open-ils.actor.user.fleshed.retrieve",);
2780 sub user_retrieve_fleshed_by_id {
2781 my( $self, $client, $auth, $user_id, $fields ) = @_;
2782 my $e = new_editor(authtoken => $auth);
2783 return $e->event unless $e->checkauth;
2785 if( $e->requestor->id != $user_id ) {
2786 return $e->event unless $e->allowed('VIEW_USER');
2792 "standing_penalties",
2796 "stat_cat_entries" ];
2797 return new_flesh_user($user_id, $fields, $e);
2801 sub new_flesh_user {
2804 my $fields = shift || [];
2805 my $e = shift || new_editor(xact=>1);
2807 my $user = $e->retrieve_actor_user(
2812 "flesh_fields" => { "au" => $fields }
2815 ) or return $e->event;
2818 if( grep { $_ eq 'addresses' } @$fields ) {
2820 $user->addresses([]) unless @{$user->addresses};
2822 if( ref $user->billing_address ) {
2823 unless( grep { $user->billing_address->id == $_->id } @{$user->addresses} ) {
2824 push( @{$user->addresses}, $user->billing_address );
2828 if( ref $user->mailing_address ) {
2829 unless( grep { $user->mailing_address->id == $_->id } @{$user->addresses} ) {
2830 push( @{$user->addresses}, $user->mailing_address );
2836 $user->clear_passwd();
2843 __PACKAGE__->register_method(
2844 method => "user_retrieve_parts",
2845 api_name => "open-ils.actor.user.retrieve.parts",);
2847 sub user_retrieve_parts {
2848 my( $self, $client, $auth, $user_id, $fields ) = @_;
2849 my $e = new_editor(authtoken => $auth);
2850 return $e->event unless $e->checkauth;
2851 if( $e->requestor->id != $user_id ) {
2852 return $e->event unless $e->allowed('VIEW_USER');
2855 my $user = $e->retrieve_actor_user($user_id) or return $e->event;
2856 push(@resp, $user->$_()) for(@$fields);
2862 __PACKAGE__->register_method(
2863 method => 'user_opt_in_enabled',
2864 api_name => 'open-ils.actor.user.org_unit_opt_in.enabled',
2866 @return 1 if user opt-in is globally enabled, 0 otherwise.
2869 sub user_opt_in_enabled {
2870 my($self, $conn) = @_;
2871 my $sc = OpenSRF::Utils::SettingsClient->new;
2872 return 1 if lc($sc->config_value(share => user => 'opt_in')) eq 'true';
2877 __PACKAGE__->register_method(
2878 method => 'user_opt_in_at_org',
2879 api_name => 'open-ils.actor.user.org_unit_opt_in.check',
2881 @param $auth The auth token
2882 @param user_id The ID of the user to test
2883 @return 1 if the user has opted in at the specified org,
2884 event on error, and 0 otherwise. /);
2885 sub user_opt_in_at_org {
2886 my($self, $conn, $auth, $user_id) = @_;
2888 # see if we even need to enforce the opt-in value
2889 return 1 unless user_opt_in_enabled($self);
2891 my $e = new_editor(authtoken => $auth);
2892 return $e->event unless $e->checkauth;
2893 my $org_id = $e->requestor->ws_ou;
2895 my $user = $e->retrieve_actor_user($user_id) or return $e->event;
2896 return $e->event unless $e->allowed('VIEW_USER', $user->home_ou);
2898 # user is automatically opted-in at the home org
2899 return 1 if $user->home_ou eq $org_id;
2901 my $vals = $e->search_actor_usr_org_unit_opt_in(
2902 {org_unit=>$org_id, usr=>$user_id},{idlist=>1});
2908 __PACKAGE__->register_method(
2909 method => 'create_user_opt_in_at_org',
2910 api_name => 'open-ils.actor.user.org_unit_opt_in.create',
2912 @param $auth The auth token
2913 @param user_id The ID of the user to test
2914 @return The ID of the newly created object, event on error./);
2916 sub create_user_opt_in_at_org {
2917 my($self, $conn, $auth, $user_id) = @_;
2919 my $e = new_editor(authtoken => $auth, xact=>1);
2920 return $e->die_event unless $e->checkauth;
2921 my $org_id = $e->requestor->ws_ou;
2923 my $user = $e->retrieve_actor_user($user_id) or return $e->die_event;
2924 return $e->die_event unless $e->allowed('UPDATE_USER', $user->home_ou);
2926 my $opt_in = Fieldmapper::actor::usr_org_unit_opt_in->new;
2928 $opt_in->org_unit($org_id);
2929 $opt_in->usr($user_id);
2930 $opt_in->staff($e->requestor->id);
2931 $opt_in->opt_in_ts('now');
2932 $opt_in->opt_in_ws($e->requestor->wsid);
2934 $opt_in = $e->create_actor_usr_org_unit_opt_in($opt_in)
2935 or return $e->die_event;
2943 __PACKAGE__->register_method (
2944 method => 'retrieve_org_hours',
2945 api_name => 'open-ils.actor.org_unit.hours_of_operation.retrieve',
2947 Returns the hours of operation for a specified org unit
2948 @param authtoken The login session key
2949 @param org_id The org_unit ID
2953 sub retrieve_org_hours {
2954 my($self, $conn, $auth, $org_id) = @_;
2955 my $e = new_editor(authtoken => $auth);
2956 return $e->die_event unless $e->checkauth;
2957 $org_id ||= $e->requestor->ws_ou;
2958 return $e->retrieve_actor_org_unit_hours_of_operation($org_id);