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()); }
49 my $set_user_settings;
52 __PACKAGE__->register_method(
53 method => "set_user_settings",
54 api_name => "open-ils.actor.patron.settings.update",
56 sub set_user_settings {
57 my( $self, $client, $user_session, $uid, $settings ) = @_;
59 $logger->debug("Setting user settings: $user_session, $uid, " . Dumper($settings));
61 my( $staff, $user, $evt ) =
62 $apputils->checkses_requestor( $user_session, $uid, 'UPDATE_USER' );
66 [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
68 $_->[1]->{value} = OpenSRF::Utils::JSON->perl2JSON($_->[1]->{value}) for @params;
70 $logger->activity("User " . $staff->id . " updating user $uid settings with: " . Dumper(\@params));
72 my $ses = $U->start_db_session();
73 my $stat = $ses->request(
74 'open-ils.storage.direct.actor.user_setting.batch.merge', @params )->gather(1);
75 $U->commit_db_session($ses);
81 __PACKAGE__->register_method(
82 method => "set_ou_settings",
83 api_name => "open-ils.actor.org_unit.settings.update",
86 my( $self, $client, $auth, $org_id, $settings ) = @_;
88 my $e = new_editor(authtoken => $auth, xact => 1);
89 return $e->die_event unless $e->checkauth;
90 return $e->die_event unless $e->allowed('UPDATE_ORG_SETTING', $org_id);
92 for my $name (keys %$settings) {
93 my $val = $$settings{$name};
94 my $set = $e->search_actor_org_unit_setting({org_unit => $org_id, name => $name})->[0];
97 $val = OpenSRF::Utils::JSON->perl2JSON($val);
100 $e->update_actor_org_unit_setting($set) or return $e->die_event;
102 $set = Fieldmapper::actor::org_unit_setting->new;
103 $set->org_unit($org_id);
106 $e->create_actor_org_unit_setting($set) or return $e->die_event;
109 $e->delete_actor_org_unit_setting($set) or return $e->die_event;
117 my $fetch_user_settings;
118 my $fetch_ou_settings;
120 __PACKAGE__->register_method(
121 method => "user_settings",
122 api_name => "open-ils.actor.patron.settings.retrieve",
125 my( $self, $client, $auth, $user_id, $setting ) = @_;
127 my $e = new_editor(authtoken => $auth);
128 return $e->event unless $e->checkauth;
130 my $patron = $e->retrieve_actor_user($user_id) or return $e->event;
131 if($e->requestor->id != $user_id) {
132 return $e->event unless $e->allowed('VIEW_USER', $patron->home_ou);
135 my $s = $e->search_actor_user_setting({usr => $user_id});
136 my $settings = { map { ( $_->name => OpenSRF::Utils::JSON->JSON2perl($_->value) ) } @$s };
138 return $$settings{$setting} if $setting;
144 __PACKAGE__->register_method(
145 method => "ou_settings",
146 api_name => "open-ils.actor.org_unit.settings.retrieve",
149 my( $self, $client, $ouid ) = @_;
151 $logger->info("Fetching org unit settings for org $ouid");
153 my $s = $apputils->simplereq(
155 'open-ils.cstore.direct.actor.org_unit_setting.search.atomic', {org_unit => $ouid});
157 return { map { ( $_->name => OpenSRF::Utils::JSON->JSON2perl($_->value) ) } @$s };
162 __PACKAGE__->register_method(
163 api_name => 'open-ils.actor.ou_setting.ancestor_default',
164 method => 'ou_ancestor_setting',
167 # ------------------------------------------------------------------
168 # Attempts to find the org setting value for a given org. if not
169 # found at the requested org, searches up the org tree until it
170 # finds a parent that has the requested setting.
171 # when found, returns { org => $id, value => $value }
172 # otherwise, returns NULL
173 # ------------------------------------------------------------------
174 sub ou_ancestor_setting {
175 my( $self, $client, $orgid, $name ) = @_;
176 return $U->ou_ancestor_setting($orgid, $name);
182 __PACKAGE__->register_method (
183 method => "ou_setting_delete",
184 api_name => 'open-ils.actor.org_setting.delete',
186 Deletes a specific org unit setting for a specific location
187 @param authtoken The login session key
188 @param orgid The org unit whose setting we're changing
189 @param setting The name of the setting to delete
190 @return True value on success.
194 sub ou_setting_delete {
195 my( $self, $conn, $authtoken, $orgid, $setting ) = @_;
196 my( $reqr, $evt) = $U->checkses($authtoken);
198 $evt = $U->check_perms($reqr->id, $orgid, 'UPDATE_ORG_SETTING');
201 my $id = $U->cstorereq(
202 'open-ils.cstore.direct.actor.org_unit_setting.id_list',
203 { name => $setting, org_unit => $orgid } );
205 $logger->debug("Retrieved setting $id in org unit setting delete");
207 my $s = $U->cstorereq(
208 'open-ils.cstore.direct.actor.org_unit_setting.delete', $id );
210 $logger->activity("User ".$reqr->id." deleted org unit setting $id") if $s;
224 __PACKAGE__->register_method(
225 method => "update_patron",
226 api_name => "open-ils.actor.patron.update",);
229 my( $self, $client, $user_session, $patron ) = @_;
231 my $session = $apputils->start_db_session();
235 $logger->info("Creating new patron...") if $patron->isnew;
236 $logger->info("Updating Patron: " . $patron->id) unless $patron->isnew;
238 my( $user_obj, $evt ) = $U->checkses($user_session);
241 $evt = check_group_perm($session, $user_obj, $patron);
245 # $new_patron is the patron in progress. $patron is the original patron
246 # passed in with the method. new_patron will change as the components
247 # of patron are added/updated.
251 # unflesh the real items on the patron
252 $patron->card( $patron->card->id ) if(ref($patron->card));
253 $patron->billing_address( $patron->billing_address->id )
254 if(ref($patron->billing_address));
255 $patron->mailing_address( $patron->mailing_address->id )
256 if(ref($patron->mailing_address));
258 # create/update the patron first so we can use his id
259 if($patron->isnew()) {
260 ( $new_patron, $evt ) = _add_patron($session, _clone_patron($patron), $user_obj);
262 } else { $new_patron = $patron; }
264 ( $new_patron, $evt ) = _add_update_addresses($session, $patron, $new_patron, $user_obj);
267 ( $new_patron, $evt ) = _add_update_cards($session, $patron, $new_patron, $user_obj);
270 ( $new_patron, $evt ) = _add_survey_responses($session, $patron, $new_patron, $user_obj);
273 # re-update the patron if anything has happened to him during this process
274 if($new_patron->ischanged()) {
275 ( $new_patron, $evt ) = _update_patron($session, $new_patron, $user_obj);
279 ($new_patron, $evt) = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
282 ($new_patron, $evt) = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
285 ($new_patron, $evt) = _create_standing_penalties($session, $user_session, $patron, $new_patron, $user_obj);
288 $logger->activity("user ".$user_obj->id." updating/creating user ".$new_patron->id);
291 if(!$patron->isnew) {
292 $opatron = new_editor()->retrieve_actor_user($new_patron->id);
295 $apputils->commit_db_session($session);
296 my $fuser = flesh_user($new_patron->id());
299 # Log the new and old patron for investigation
300 $logger->info("$user_session updating patron object. orig patron object = ".
301 OpenSRF::Utils::JSON->perl2JSON($opatron). " |||| new patron = ".OpenSRF::Utils::JSON->perl2JSON($fuser));
311 return new_flesh_user($id, [
314 "standing_penalties",
318 "stat_cat_entries" ] );
326 # clone and clear stuff that would break the database
330 my $new_patron = $patron->clone;
332 $new_patron->clear_billing_address();
333 $new_patron->clear_mailing_address();
334 $new_patron->clear_addresses();
335 $new_patron->clear_card();
336 $new_patron->clear_cards();
337 $new_patron->clear_id();
338 $new_patron->clear_isnew();
339 $new_patron->clear_ischanged();
340 $new_patron->clear_isdeleted();
341 $new_patron->clear_stat_cat_entries();
342 $new_patron->clear_permissions();
343 $new_patron->clear_standing_penalties();
353 my $user_obj = shift;
355 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'CREATE_USER');
356 return (undef, $evt) if $evt;
358 my $ex = $session->request(
359 'open-ils.storage.direct.actor.user.search.usrname', $patron->usrname())->gather(1);
361 return (undef, OpenILS::Event->new('USERNAME_EXISTS'));
364 $logger->info("Creating new user in the DB with username: ".$patron->usrname());
366 my $id = $session->request(
367 "open-ils.storage.direct.actor.user.create", $patron)->gather(1);
368 return (undef, $U->DB_UPDATE_FAILED($patron)) unless $id;
370 $logger->info("Successfully created new user [$id] in DB");
372 return ( $session->request(
373 "open-ils.storage.direct.actor.user.retrieve", $id)->gather(1), undef );
377 sub check_group_perm {
378 my( $session, $requestor, $patron ) = @_;
381 # first let's see if the requestor has
382 # priveleges to update this user in any way
383 if( ! $patron->isnew ) {
384 my $p = $session->request(
385 'open-ils.storage.direct.actor.user.retrieve', $patron->id )->gather(1);
387 # If we are the requestor (trying to update our own account)
388 # and we are not trying to change our profile, we're good
389 if( $p->id == $requestor->id and
390 $p->profile == $patron->profile ) {
395 $evt = group_perm_failed($session, $requestor, $p);
399 # They are allowed to edit this patron.. can they put the
400 # patron into the group requested?
401 $evt = group_perm_failed($session, $requestor, $patron);
407 sub group_perm_failed {
408 my( $session, $requestor, $patron ) = @_;
412 my $grpid = $patron->profile;
416 $logger->debug("user update looking for group perm for group $grpid");
417 $grp = $session->request(
418 'open-ils.storage.direct.permission.grp_tree.retrieve', $grpid )->gather(1);
419 return OpenILS::Event->new('PERMISSION_GRP_TREE_NOT_FOUND') unless $grp;
421 } while( !($perm = $grp->application_perm) and ($grpid = $grp->parent) );
423 $logger->info("user update checking perm $perm on user ".
424 $requestor->id." for update/create on user username=".$patron->usrname);
426 my $evt = $U->check_perms($requestor->id, $patron->home_ou, $perm);
434 my( $session, $patron, $user_obj, $noperm) = @_;
436 $logger->info("Updating patron ".$patron->id." in DB");
441 $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'UPDATE_USER');
442 return (undef, $evt) if $evt;
445 # update the password by itself to avoid the password protection magic
446 if( $patron->passwd ) {
447 my $s = $session->request(
448 'open-ils.storage.direct.actor.user.remote_update',
449 {id => $patron->id}, {passwd => $patron->passwd})->gather(1);
450 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($s);
451 $patron->clear_passwd;
454 if(!$patron->ident_type) {
455 $patron->clear_ident_type;
456 $patron->clear_ident_value;
459 $evt = verify_last_xact($session, $patron);
460 return (undef, $evt) if $evt;
462 my $stat = $session->request(
463 "open-ils.storage.direct.actor.user.update",$patron )->gather(1);
464 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($stat);
469 sub verify_last_xact {
470 my( $session, $patron ) = @_;
471 return undef unless $patron->id and $patron->id > 0;
472 my $p = $session->request(
473 'open-ils.storage.direct.actor.user.retrieve', $patron->id)->gather(1);
474 my $xact = $p->last_xact_id;
475 return undef unless $xact;
476 $logger->info("user xact = $xact, saving with xact " . $patron->last_xact_id);
477 return OpenILS::Event->new('XACT_COLLISION')
478 if $xact != $patron->last_xact_id;
483 sub _check_dup_ident {
484 my( $session, $patron ) = @_;
486 return undef unless $patron->ident_value;
489 ident_type => $patron->ident_type,
490 ident_value => $patron->ident_value,
493 $logger->debug("patron update searching for dup ident values: " .
494 $patron->ident_type . ':' . $patron->ident_value);
496 $search->{id} = {'!=' => $patron->id} if $patron->id and $patron->id > 0;
498 my $dups = $session->request(
499 'open-ils.storage.direct.actor.user.search_where.atomic', $search )->gather(1);
502 return OpenILS::Event->new('PATRON_DUP_IDENT1', payload => $patron )
509 sub _add_update_addresses {
513 my $new_patron = shift;
517 my $current_id; # id of the address before creation
519 for my $address (@{$patron->addresses()}) {
521 next unless ref $address;
522 $current_id = $address->id();
524 if( $patron->billing_address() and
525 $patron->billing_address() == $current_id ) {
526 $logger->info("setting billing addr to $current_id");
527 $new_patron->billing_address($address->id());
528 $new_patron->ischanged(1);
531 if( $patron->mailing_address() and
532 $patron->mailing_address() == $current_id ) {
533 $new_patron->mailing_address($address->id());
534 $logger->info("setting mailing addr to $current_id");
535 $new_patron->ischanged(1);
539 if($address->isnew()) {
541 $address->usr($new_patron->id());
543 ($address, $evt) = _add_address($session,$address);
544 return (undef, $evt) if $evt;
546 # we need to get the new id
547 if( $patron->billing_address() and
548 $patron->billing_address() == $current_id ) {
549 $new_patron->billing_address($address->id());
550 $logger->info("setting billing addr to $current_id");
551 $new_patron->ischanged(1);
554 if( $patron->mailing_address() and
555 $patron->mailing_address() == $current_id ) {
556 $new_patron->mailing_address($address->id());
557 $logger->info("setting mailing addr to $current_id");
558 $new_patron->ischanged(1);
561 } elsif($address->ischanged() ) {
563 ($address, $evt) = _update_address($session, $address);
564 return (undef, $evt) if $evt;
566 } elsif($address->isdeleted() ) {
568 if( $address->id() == $new_patron->mailing_address() ) {
569 $new_patron->clear_mailing_address();
570 ($new_patron, $evt) = _update_patron($session, $new_patron);
571 return (undef, $evt) if $evt;
574 if( $address->id() == $new_patron->billing_address() ) {
575 $new_patron->clear_billing_address();
576 ($new_patron, $evt) = _update_patron($session, $new_patron);
577 return (undef, $evt) if $evt;
580 $evt = _delete_address($session, $address);
581 return (undef, $evt) if $evt;
585 return ( $new_patron, undef );
589 # adds an address to the db and returns the address with new id
591 my($session, $address) = @_;
592 $address->clear_id();
594 $logger->info("Creating new address at street ".$address->street1);
596 # put the address into the database
597 my $id = $session->request(
598 "open-ils.storage.direct.actor.user_address.create", $address )->gather(1);
599 return (undef, $U->DB_UPDATE_FAILED($address)) unless $id;
602 return ($address, undef);
606 sub _update_address {
607 my( $session, $address ) = @_;
609 $logger->info("Updating address ".$address->id." in the DB");
611 my $stat = $session->request(
612 "open-ils.storage.direct.actor.user_address.update", $address )->gather(1);
614 return (undef, $U->DB_UPDATE_FAILED($address)) unless defined($stat);
615 return ($address, undef);
620 sub _add_update_cards {
624 my $new_patron = shift;
628 my $virtual_id; #id of the card before creation
629 for my $card (@{$patron->cards()}) {
631 $card->usr($new_patron->id());
633 if(ref($card) and $card->isnew()) {
635 $virtual_id = $card->id();
636 ( $card, $evt ) = _add_card($session,$card);
637 return (undef, $evt) if $evt;
639 #if(ref($patron->card)) { $patron->card($patron->card->id); }
640 if($patron->card() == $virtual_id) {
641 $new_patron->card($card->id());
642 $new_patron->ischanged(1);
645 } elsif( ref($card) and $card->ischanged() ) {
646 $evt = _update_card($session, $card);
647 return (undef, $evt) if $evt;
651 return ( $new_patron, undef );
655 # adds an card to the db and returns the card with new id
657 my( $session, $card ) = @_;
660 $logger->info("Adding new patron card ".$card->barcode);
662 my $id = $session->request(
663 "open-ils.storage.direct.actor.card.create", $card )->gather(1);
664 return (undef, $U->DB_UPDATE_FAILED($card)) unless $id;
665 $logger->info("Successfully created patron card $id");
668 return ( $card, undef );
672 # returns event on error. returns undef otherwise
674 my( $session, $card ) = @_;
675 $logger->info("Updating patron card ".$card->id);
677 my $stat = $session->request(
678 "open-ils.storage.direct.actor.card.update", $card )->gather(1);
679 return $U->DB_UPDATE_FAILED($card) unless defined($stat);
686 # returns event on error. returns undef otherwise
687 sub _delete_address {
688 my( $session, $address ) = @_;
690 $logger->info("Deleting address ".$address->id." from DB");
692 my $stat = $session->request(
693 "open-ils.storage.direct.actor.user_address.delete", $address )->gather(1);
695 return $U->DB_UPDATE_FAILED($address) unless defined($stat);
701 sub _add_survey_responses {
702 my ($session, $patron, $new_patron) = @_;
704 $logger->info( "Updating survey responses for patron ".$new_patron->id );
706 my $responses = $patron->survey_responses;
710 $_->usr($new_patron->id) for (@$responses);
712 my $evt = $U->simplereq( "open-ils.circ",
713 "open-ils.circ.survey.submit.user_id", $responses );
715 return (undef, $evt) if defined($U->event_code($evt));
719 return ( $new_patron, undef );
723 sub _create_stat_maps {
725 my($session, $user_session, $patron, $new_patron) = @_;
727 my $maps = $patron->stat_cat_entries();
729 for my $map (@$maps) {
731 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
733 if ($map->isdeleted()) {
734 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.delete";
736 } elsif ($map->isnew()) {
737 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
742 $map->target_usr($new_patron->id);
745 $logger->info("Updating stat entry with method $method and map $map");
747 my $stat = $session->request($method, $map)->gather(1);
748 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
752 return ($new_patron, undef);
755 sub _create_perm_maps {
757 my($session, $user_session, $patron, $new_patron) = @_;
759 my $maps = $patron->permissions;
761 for my $map (@$maps) {
763 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
764 if ($map->isdeleted()) {
765 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
766 } elsif ($map->isnew()) {
767 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
772 $map->usr($new_patron->id);
774 #warn( "Updating permissions with method $method and session $user_session and map $map" );
775 $logger->info( "Updating permissions with method $method and map $map" );
777 my $stat = $session->request($method, $map)->gather(1);
778 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
782 return ($new_patron, undef);
786 __PACKAGE__->register_method(
787 method => "set_user_work_ous",
788 api_name => "open-ils.actor.user.work_ous.update",
791 sub set_user_work_ous {
797 my( $requestor, $evt ) = $apputils->checksesperm( $ses, 'ASSIGN_WORK_ORG_UNIT' );
800 my $session = $apputils->start_db_session();
802 for my $map (@$maps) {
804 my $method = "open-ils.storage.direct.permission.usr_work_ou_map.update";
805 if ($map->isdeleted()) {
806 $method = "open-ils.storage.direct.permission.usr_work_ou_map.delete";
807 } elsif ($map->isnew()) {
808 $method = "open-ils.storage.direct.permission.usr_work_ou_map.create";
812 #warn( "Updating permissions with method $method and session $ses and map $map" );
813 $logger->info( "Updating work_ou map with method $method and map $map" );
815 my $stat = $session->request($method, $map)->gather(1);
816 $logger->warn( "update failed: ".$U->DB_UPDATE_FAILED($map) ) unless defined($stat);
820 $apputils->commit_db_session($session);
822 return scalar(@$maps);
826 __PACKAGE__->register_method(
827 method => "set_user_perms",
828 api_name => "open-ils.actor.user.permissions.update",
837 my $session = $apputils->start_db_session();
839 my( $user_obj, $evt ) = $U->checkses($ses);
842 my $perms = $session->request('open-ils.storage.permission.user_perms.atomic', $user_obj->id)->gather(1);
845 $all = 1 if ($U->is_true($user_obj->super_user()));
846 $all = 1 unless ($U->check_perms($user_obj->id, $user_obj->home_ou, 'EVERYTHING'));
848 for my $map (@$maps) {
850 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
851 if ($map->isdeleted()) {
852 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
853 } elsif ($map->isnew()) {
854 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
858 next if (!$all and !grep { $_->perm eq $map->perm and $U->is_true($_->grantable) and $_->depth <= $map->depth } @$perms);
859 #warn( "Updating permissions with method $method and session $ses and map $map" );
860 $logger->info( "Updating permissions with method $method and map $map" );
862 my $stat = $session->request($method, $map)->gather(1);
863 $logger->warn( "update failed: ".$U->DB_UPDATE_FAILED($map) ) unless defined($stat);
867 $apputils->commit_db_session($session);
869 return scalar(@$maps);
873 sub _create_standing_penalties {
875 my($session, $user_session, $patron, $new_patron) = @_;
877 my $maps = $patron->standing_penalties;
880 for my $map (@$maps) {
882 if ($map->isdeleted()) {
883 $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
884 } elsif ($map->isnew()) {
885 $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
891 $map->usr($new_patron->id);
893 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
895 my $stat = $session->request($method, $map)->gather(1);
896 return (undef, $U->DB_UPDATE_FAILED($map)) unless $stat;
899 return ($new_patron, undef);
904 __PACKAGE__->register_method(
905 method => "search_username",
906 api_name => "open-ils.actor.user.search.username",
909 sub search_username {
910 my($self, $client, $username) = @_;
911 return new_editor()->search_actor_user({usrname=>$username});
917 __PACKAGE__->register_method(
918 method => "user_retrieve_by_barcode",
920 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
922 sub user_retrieve_by_barcode {
923 my($self, $client, $user_session, $barcode) = @_;
925 $logger->debug("Searching for user with barcode $barcode");
926 my ($user_obj, $evt) = $apputils->checkses($user_session);
929 my $card = OpenILS::Application::AppUtils->simple_scalar_request(
931 "open-ils.cstore.direct.actor.card.search.atomic",
932 { barcode => $barcode }
935 if(!$card || !$card->[0]) {
936 return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' );
940 my $user = flesh_user($card->usr());
942 $evt = $U->check_perms($user_obj->id, $user->home_ou, 'VIEW_USER');
945 if(!$user) { return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' ); }
952 __PACKAGE__->register_method(
953 method => "get_user_by_id",
954 api_name => "open-ils.actor.user.retrieve",);
957 my ($self, $client, $auth, $id) = @_;
958 my $e = new_editor(authtoken=>$auth);
959 return $e->event unless $e->checkauth;
960 my $user = $e->retrieve_actor_user($id)
962 return $e->event unless $e->allowed('VIEW_USER', $user->home_ou);
968 __PACKAGE__->register_method(
969 method => "get_org_types",
970 api_name => "open-ils.actor.org_types.retrieve",);
973 return $U->get_org_types();
978 __PACKAGE__->register_method(
979 method => "get_user_ident_types",
980 api_name => "open-ils.actor.user.ident_types.retrieve",
983 sub get_user_ident_types {
984 return $ident_types if $ident_types;
985 return $ident_types =
986 new_editor()->retrieve_all_config_identification_type();
992 __PACKAGE__->register_method(
993 method => "get_org_unit",
994 api_name => "open-ils.actor.org_unit.retrieve",
998 my( $self, $client, $user_session, $org_id ) = @_;
999 my $e = new_editor(authtoken => $user_session);
1001 return $e->event unless $e->checkauth;
1002 $org_id = $e->requestor->ws_ou;
1004 my $o = $e->retrieve_actor_org_unit($org_id)
1005 or return $e->event;
1009 __PACKAGE__->register_method(
1010 method => "search_org_unit",
1011 api_name => "open-ils.actor.org_unit_list.search",
1014 sub search_org_unit {
1016 my( $self, $client, $field, $value ) = @_;
1018 my $list = OpenILS::Application::AppUtils->simple_scalar_request(
1020 "open-ils.cstore.direct.actor.org_unit.search.atomic",
1021 { $field => $value } );
1027 # build the org tree
1029 __PACKAGE__->register_method(
1030 method => "get_org_tree",
1031 api_name => "open-ils.actor.org_tree.retrieve",
1033 note => "Returns the entire org tree structure",
1039 return $U->get_org_tree($client->session->session_locale);
1043 __PACKAGE__->register_method(
1044 method => "get_org_descendants",
1045 api_name => "open-ils.actor.org_tree.descendants.retrieve"
1048 # depth is optional. org_unit is the id
1049 sub get_org_descendants {
1050 my( $self, $client, $org_unit, $depth ) = @_;
1052 if(ref $org_unit eq 'ARRAY') {
1055 for my $i (0..scalar(@$org_unit)-1) {
1056 my $list = $U->simple_scalar_request(
1058 "open-ils.storage.actor.org_unit.descendants.atomic",
1059 $org_unit->[$i], $depth->[$i] );
1060 push(@trees, $U->build_org_tree($list));
1065 my $orglist = $apputils->simple_scalar_request(
1067 "open-ils.storage.actor.org_unit.descendants.atomic",
1068 $org_unit, $depth );
1069 return $U->build_org_tree($orglist);
1074 __PACKAGE__->register_method(
1075 method => "get_org_ancestors",
1076 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
1079 # depth is optional. org_unit is the id
1080 sub get_org_ancestors {
1081 my( $self, $client, $org_unit, $depth ) = @_;
1082 my $orglist = $apputils->simple_scalar_request(
1084 "open-ils.storage.actor.org_unit.ancestors.atomic",
1085 $org_unit, $depth );
1086 return $U->build_org_tree($orglist);
1090 __PACKAGE__->register_method(
1091 method => "get_standings",
1092 api_name => "open-ils.actor.standings.retrieve"
1097 return $user_standings if $user_standings;
1098 return $user_standings =
1099 $apputils->simple_scalar_request(
1101 "open-ils.cstore.direct.config.standing.search.atomic",
1102 { id => { "!=" => undef } }
1108 __PACKAGE__->register_method(
1109 method => "get_my_org_path",
1110 api_name => "open-ils.actor.org_unit.full_path.retrieve"
1113 sub get_my_org_path {
1114 my( $self, $client, $auth, $org_id ) = @_;
1115 my $e = new_editor(authtoken=>$auth);
1116 return $e->event unless $e->checkauth;
1117 $org_id = $e->requestor->ws_ou unless defined $org_id;
1119 return $apputils->simple_scalar_request(
1121 "open-ils.storage.actor.org_unit.full_path.atomic",
1126 __PACKAGE__->register_method(
1127 method => "patron_adv_search",
1128 api_name => "open-ils.actor.patron.search.advanced" );
1129 sub patron_adv_search {
1130 my( $self, $client, $auth, $search_hash,
1131 $search_limit, $search_sort, $include_inactive, $search_depth ) = @_;
1133 my $e = new_editor(authtoken=>$auth);
1134 return $e->event unless $e->checkauth;
1135 return $e->event unless $e->allowed('VIEW_USER');
1136 return $U->storagereq(
1137 "open-ils.storage.actor.user.crazy_search", $search_hash,
1138 $search_limit, $search_sort, $include_inactive, $e->requestor->ws_ou, $search_depth);
1142 __PACKAGE__->register_method(
1143 method => "update_passwd",
1145 api_name => "open-ils.actor.user.password.update");
1147 __PACKAGE__->register_method(
1148 method => "update_passwd",
1149 api_name => "open-ils.actor.user.username.update");
1151 __PACKAGE__->register_method(
1152 method => "update_passwd",
1153 api_name => "open-ils.actor.user.email.update");
1156 my( $self, $conn, $auth, $new_val, $orig_pw ) = @_;
1157 my $e = new_editor(xact=>1, authtoken=>$auth);
1158 return $e->die_event unless $e->checkauth;
1160 my $db_user = $e->retrieve_actor_user($e->requestor->id)
1161 or return $e->die_event;
1162 my $api = $self->api_name;
1164 if( $api =~ /password/o ) {
1166 # make sure the original password matches the in-database password
1167 return OpenILS::Event->new('INCORRECT_PASSWORD')
1168 if md5_hex($orig_pw) ne $db_user->passwd;
1169 $db_user->passwd($new_val);
1173 # if we don't clear the password, the user will be updated with
1174 # a hashed version of the hashed version of their password
1175 $db_user->clear_passwd;
1177 if( $api =~ /username/o ) {
1179 # make sure no one else has this username
1180 my $exist = $e->search_actor_user({usrname=>$new_val},{idlist=>1});
1181 return OpenILS::Event->new('USERNAME_EXISTS') if @$exist;
1182 $db_user->usrname($new_val);
1184 } elsif( $api =~ /email/o ) {
1185 $db_user->email($new_val);
1189 $e->update_actor_user($db_user) or return $e->die_event;
1197 __PACKAGE__->register_method(
1198 method => "check_user_perms",
1199 api_name => "open-ils.actor.user.perm.check",
1200 notes => <<" NOTES");
1201 Takes a login session, user id, an org id, and an array of perm type strings. For each
1202 perm type, if the user does *not* have the given permission it is added
1203 to a list which is returned from the method. If all permissions
1204 are allowed, an empty list is returned
1205 if the logged in user does not match 'user_id', then the logged in user must
1206 have VIEW_PERMISSION priveleges.
1209 sub check_user_perms {
1210 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1212 my( $staff, $evt ) = $apputils->checkses($login_session);
1213 return $evt if $evt;
1215 if($staff->id ne $user_id) {
1216 if( $evt = $apputils->check_perms(
1217 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1223 for my $perm (@$perm_types) {
1224 if($apputils->check_perms($user_id, $org_id, $perm)) {
1225 push @not_allowed, $perm;
1229 return \@not_allowed
1232 __PACKAGE__->register_method(
1233 method => "check_user_perms2",
1234 api_name => "open-ils.actor.user.perm.check.multi_org",
1236 Checks the permissions on a list of perms and orgs for a user
1237 @param authtoken The login session key
1238 @param user_id The id of the user to check
1239 @param orgs The array of org ids
1240 @param perms The array of permission names
1241 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1242 if the logged in user does not match 'user_id', then the logged in user must
1243 have VIEW_PERMISSION priveleges.
1246 sub check_user_perms2 {
1247 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1249 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1250 $authtoken, $user_id, 'VIEW_PERMISSION' );
1251 return $evt if $evt;
1254 for my $org (@$orgs) {
1255 for my $perm (@$perms) {
1256 if($apputils->check_perms($user_id, $org, $perm)) {
1257 push @not_allowed, [ $org, $perm ];
1262 return \@not_allowed
1266 __PACKAGE__->register_method(
1267 method => 'check_user_perms3',
1268 api_name => 'open-ils.actor.user.perm.highest_org',
1270 Returns the highest org unit id at which a user has a given permission
1271 If the requestor does not match the target user, the requestor must have
1272 'VIEW_PERMISSION' rights at the home org unit of the target user
1273 @param authtoken The login session key
1274 @param userid The id of the user in question
1275 @param perm The permission to check
1276 @return The org unit highest in the org tree within which the user has
1277 the requested permission
1280 sub check_user_perms3 {
1281 my( $self, $client, $authtoken, $userid, $perm ) = @_;
1283 my( $staff, $target, $org, $evt );
1285 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1286 $authtoken, $userid, 'VIEW_PERMISSION' );
1287 return $evt if $evt;
1289 my $tree = $U->get_org_tree();
1290 return $U->find_highest_perm_org( $perm, $userid, $target->ws_ou, $tree );
1294 __PACKAGE__->register_method(
1295 method => 'check_user_work_perms',
1296 api_name => 'open-ils.actor.user.work_perm.highest_org_set',
1300 Returns a set of org units which represent the highest orgs in
1301 the org tree where the user has the requested permission. The
1302 purpose of this method is to return the smallest set of org units
1303 which represent the full expanse of the user's ability to perform
1304 the requested action. The user whose perms this method should
1305 check is implied by the authtoken. /,
1307 {desc => 'authtoken', type => 'string'},
1308 {desc => 'permission name', type => 'string'},
1309 {desc => 'options hash, including "descendants", which will include all child orgs of the found perm orgs', type => 'hash'}
1311 return => {desc => 'An array of org IDs'}
1315 __PACKAGE__->register_method(
1316 method => 'check_user_work_perms',
1317 api_name => 'open-ils.actor.user.work_perm.org_tree_list',
1320 @see open-ils.actor.user.work_perm.highest_org_set
1321 Returns a list of org trees. The root of each tree
1322 is the highest org in the organization hierarchy where the user has the
1323 requested permission. Below each tree root is its full tree of descendants.
1327 __PACKAGE__->register_method(
1328 method => 'check_user_work_perms',
1329 api_name => 'open-ils.actor.user.work_perm.org_unit_list',
1332 @see open-ils.actor.user.work_perm.highest_org_set
1333 Returns a list of list of all of the org_units where the user
1334 has the requested permission. The first item in each list
1335 is the highest permission org for that section of the
1336 org tree. The remaining items in each sub-list are the
1337 descendants of that org.
1342 __PACKAGE__->register_method(
1343 method => 'check_user_work_perms',
1344 api_name => 'open-ils.actor.user.work_perm.org_id_list',
1347 @see open-ils.actor.user.work_perm.highest_org_set
1348 Returns a list of lists of all of the org_unit IDs where the user
1349 has the requested permission. The first item in each list
1350 is the highest permission org for that section of the
1351 org tree. The remaining items in each sub-list are the
1352 descendants of that org.
1356 __PACKAGE__->register_method(
1357 method => 'check_user_work_perms_batch',
1358 api_name => 'open-ils.actor.user.work_perm.highest_org_set.batch',
1361 __PACKAGE__->register_method(
1362 method => 'check_user_work_perms_batch',
1363 api_name => 'open-ils.actor.user.work_perm.org_tree_list.batch',
1366 __PACKAGE__->register_method(
1367 method => 'check_user_work_perms_batch',
1368 api_name => 'open-ils.actor.user.work_perm.org_unit_list.batch',
1371 __PACKAGE__->register_method(
1372 method => 'check_user_work_perms_batch',
1373 api_name => 'open-ils.actor.user.work_perm.org_id_list.batch',
1378 sub check_user_work_perms {
1379 my($self, $conn, $auth, $perm, $options) = @_;
1380 my $e = new_editor(authtoken=>$auth);
1381 return $e->event unless $e->checkauth;
1382 return check_user_work_perms_impl($self, $conn, $e, $perm, $options);
1385 sub check_user_work_perms_batch {
1386 my($self, $conn, $auth, $perm_list, $options) = @_;
1387 my $e = new_editor(authtoken=>$auth);
1388 return $e->event unless $e->checkauth;
1390 $map->{$_} = check_user_work_perms_impl($self, $conn, $e, $_, $options) for @$perm_list;
1394 sub check_user_work_perms_impl {
1395 my($self, $conn, $e, $perm, $options) = @_;
1396 my $orglist = $U->find_highest_work_orgs($e, $perm, $options);
1398 return $orglist if $self->api_name =~ /highest_org_set/;
1400 # build a list of org trees
1401 return get_org_descendants($self, $conn, $orglist)
1402 if $self->api_name =~ /org_tree_list/;
1405 for my $orgid (@$orglist) {
1406 my @sublist = grep {$_ ne $orgid} @{$U->get_org_descendants($orgid)};
1407 unshift @sublist, $orgid; # make sure it's at the front of the list
1408 if($self->api_name =~ /org_id_list/) {
1409 push(@list, @sublist);
1411 push(@list, @{$e->batch_retrieve_actor_org_unit(\@sublist)});
1419 __PACKAGE__->register_method(
1420 method => 'check_user_perms4',
1421 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1423 Returns the highest org unit id at which a user has a given permission
1424 If the requestor does not match the target user, the requestor must have
1425 'VIEW_PERMISSION' rights at the home org unit of the target user
1426 @param authtoken The login session key
1427 @param userid The id of the user in question
1428 @param perms An array of perm names to check
1429 @return An array of orgId's representing the org unit
1430 highest in the org tree within which the user has the requested permission
1431 The arrah of orgId's has matches the order of the perms array
1434 sub check_user_perms4 {
1435 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1437 my( $staff, $target, $org, $evt );
1439 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1440 $authtoken, $userid, 'VIEW_PERMISSION' );
1441 return $evt if $evt;
1444 return [] unless ref($perms);
1445 my $tree = $U->get_org_tree();
1447 for my $p (@$perms) {
1448 push( @arr, $U->find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1456 __PACKAGE__->register_method(
1457 method => "user_fines_summary",
1458 api_name => "open-ils.actor.user.fines.summary",
1460 notes => <<" NOTES");
1461 Returns a short summary of the users total open fines, excluding voided fines
1462 Params are login_session, user_id
1463 Returns a 'mous' object.
1466 sub user_fines_summary {
1467 my( $self, $client, $auth, $user_id ) = @_;
1468 my $e = new_editor(authtoken=>$auth);
1469 return $e->event unless $e->checkauth;
1470 my $user = $e->retrieve_actor_user($user_id)
1471 or return $e->event;
1473 if( $user_id ne $e->requestor->id ) {
1474 return $e->event unless
1475 $e->allowed('VIEW_USER_FINES_SUMMARY', $user->home_ou);
1478 # run this inside a transaction to prevent replication delay errors
1479 my $ses = $U->start_db_session();
1480 my $s = $ses->request(
1481 'open-ils.storage.money.open_user_summary.search', $user_id )->gather(1);
1482 $U->rollback_db_session($ses);
1489 __PACKAGE__->register_method(
1490 method => "user_transactions",
1491 api_name => "open-ils.actor.user.transactions",
1492 notes => <<" NOTES");
1493 Returns a list of open user transactions (mbts objects);
1494 Params are login_session, user_id
1495 Optional third parameter is the transactions type. defaults to all
1498 __PACKAGE__->register_method(
1499 method => "user_transactions",
1500 api_name => "open-ils.actor.user.transactions.have_charge",
1501 notes => <<" NOTES");
1502 Returns a list of all open user transactions (mbts objects) that have an initial charge
1503 Params are login_session, user_id
1504 Optional third parameter is the transactions type. defaults to all
1507 __PACKAGE__->register_method(
1508 method => "user_transactions",
1509 api_name => "open-ils.actor.user.transactions.have_balance",
1510 notes => <<" NOTES");
1511 Returns a list of all open user transactions (mbts objects) that have a balance
1512 Params are login_session, user_id
1513 Optional third parameter is the transactions type. defaults to all
1516 __PACKAGE__->register_method(
1517 method => "user_transactions",
1518 api_name => "open-ils.actor.user.transactions.fleshed",
1519 notes => <<" NOTES");
1520 Returns an object/hash of transaction, circ, title where transaction = an open
1521 user transactions (mbts objects), circ is the attached circluation, and title
1522 is the title the circ points to
1523 Params are login_session, user_id
1524 Optional third parameter is the transactions type. defaults to all
1527 __PACKAGE__->register_method(
1528 method => "user_transactions",
1529 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1530 notes => <<" NOTES");
1531 Returns an object/hash of transaction, circ, title where transaction = an open
1532 user transactions that has an initial charge (mbts objects), circ is the
1533 attached circluation, and title is the title the circ points to
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.fleshed",
1541 notes => <<" NOTES");
1542 Returns an object/hash of transaction, circ, title where transaction = an open
1543 user transaction that has a balance (mbts objects), circ is the attached
1544 circluation, and title is the title the circ points to
1545 Params are login_session, user_id
1546 Optional third parameter is the transaction type. defaults to all
1549 __PACKAGE__->register_method(
1550 method => "user_transactions",
1551 api_name => "open-ils.actor.user.transactions.count",
1552 notes => <<" NOTES");
1553 Returns an object/hash of transaction, circ, title where transaction = an open
1554 user transactions (mbts objects), circ is the attached circluation, and title
1555 is the title the circ points to
1556 Params are login_session, user_id
1557 Optional third parameter is the transactions type. defaults to all
1560 __PACKAGE__->register_method(
1561 method => "user_transactions",
1562 api_name => "open-ils.actor.user.transactions.have_charge.count",
1563 notes => <<" NOTES");
1564 Returns an object/hash of transaction, circ, title where transaction = an open
1565 user transactions that has an initial charge (mbts objects), circ is the
1566 attached circluation, and title is the title the circ points to
1567 Params are login_session, user_id
1568 Optional third parameter is the transactions type. defaults to all
1571 __PACKAGE__->register_method(
1572 method => "user_transactions",
1573 api_name => "open-ils.actor.user.transactions.have_balance.count",
1574 notes => <<" NOTES");
1575 Returns an object/hash of transaction, circ, title where transaction = an open
1576 user transaction that has a balance (mbts objects), circ is the attached
1577 circluation, and title is the title the circ points to
1578 Params are login_session, user_id
1579 Optional third parameter is the transaction type. defaults to all
1582 __PACKAGE__->register_method(
1583 method => "user_transactions",
1584 api_name => "open-ils.actor.user.transactions.have_balance.total",
1585 notes => <<" NOTES");
1586 Returns an object/hash of transaction, circ, title where transaction = an open
1587 user transaction that has a balance (mbts objects), circ is the attached
1588 circluation, and title is the title the circ points to
1589 Params are login_session, user_id
1590 Optional third parameter is the transaction type. defaults to all
1595 sub user_transactions {
1596 my( $self, $client, $login_session, $user_id, $type ) = @_;
1598 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1599 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1600 return $evt if $evt;
1602 my $api = $self->api_name();
1606 if(defined($type)) { @xact = (xact_type => $type);
1608 } else { @xact = (); }
1611 ->method_lookup('open-ils.actor.user.transactions.history.still_open')
1612 ->run($login_session => $user_id => $type);
1614 if($api =~ /have_charge/o) {
1616 $trans = [ grep { int($_->total_owed * 100) > 0 } @$trans ];
1618 } elsif($api =~ /have_balance/o) {
1620 $trans = [ grep { int($_->balance_owed * 100) != 0 } @$trans ];
1623 $trans = [ grep { int($_->total_owed * 100) > 0 } @$trans ];
1627 if($api =~ /total/o) {
1629 for my $t (@$trans) {
1630 $total += $t->balance_owed;
1633 $logger->debug("Total balance owed by user $user_id: $total");
1637 if($api =~ /count/o) { return scalar @$trans; }
1638 if($api !~ /fleshed/o) { return $trans; }
1641 for my $t (@$trans) {
1643 if( $t->xact_type ne 'circulation' ) {
1644 push @resp, {transaction => $t};
1648 my $circ = $apputils->simple_scalar_request(
1650 "open-ils.cstore.direct.action.circulation.retrieve",
1655 my $title = $apputils->simple_scalar_request(
1657 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1658 $circ->target_copy );
1662 my $u = OpenILS::Utils::ModsParser->new();
1663 $u->start_mods_batch($title->marc());
1664 my $mods = $u->finish_mods_batch();
1665 $mods->doc_id($title->id) if $mods;
1667 push @resp, {transaction => $t, circ => $circ, record => $mods };
1675 __PACKAGE__->register_method(
1676 method => "user_transaction_retrieve",
1677 api_name => "open-ils.actor.user.transaction.fleshed.retrieve",
1679 notes => <<" NOTES");
1680 Returns a fleshedtransaction record
1682 __PACKAGE__->register_method(
1683 method => "user_transaction_retrieve",
1684 api_name => "open-ils.actor.user.transaction.retrieve",
1686 notes => <<" NOTES");
1687 Returns a transaction record
1689 sub user_transaction_retrieve {
1690 my( $self, $client, $login_session, $bill_id ) = @_;
1692 # XXX I think I'm deprecated... make sure
1694 my $trans = $apputils->simple_scalar_request(
1696 "open-ils.cstore.direct.money.billable_transaction_summary.retrieve",
1700 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1701 $login_session, $trans->usr, 'VIEW_USER_TRANSACTIONS' );
1702 return $evt if $evt;
1704 my $api = $self->api_name();
1705 if($api !~ /fleshed/o) { return $trans; }
1707 if( $trans->xact_type ne 'circulation' ) {
1708 $logger->debug("Returning non-circ transaction");
1709 return {transaction => $trans};
1712 my $circ = $apputils->simple_scalar_request(
1714 "open-ils..direct.action.circulation.retrieve",
1717 return {transaction => $trans} unless $circ;
1718 $logger->debug("Found the circ transaction");
1720 my $title = $apputils->simple_scalar_request(
1722 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1723 $circ->target_copy );
1725 return {transaction => $trans, circ => $circ } unless $title;
1726 $logger->debug("Found the circ title");
1730 my $u = OpenILS::Utils::ModsParser->new();
1731 $u->start_mods_batch($title->marc());
1732 $mods = $u->finish_mods_batch();
1734 if ($title->id == OILS_PRECAT_RECORD) {
1735 my $copy = $apputils->simple_scalar_request(
1737 "open-ils.cstore.direct.asset.copy.retrieve",
1738 $circ->target_copy );
1740 $mods = new Fieldmapper::metabib::virtual_record;
1741 $mods->doc_id(OILS_PRECAT_RECORD);
1742 $mods->title($copy->dummy_title);
1743 $mods->author($copy->dummy_author);
1747 $logger->debug("MODSized the circ title");
1749 return {transaction => $trans, circ => $circ, record => $mods };
1753 __PACKAGE__->register_method(
1754 method => "hold_request_count",
1755 api_name => "open-ils.actor.user.hold_requests.count",
1758 notes => <<" NOTES");
1759 Returns hold ready/total counts
1761 sub hold_request_count {
1762 my( $self, $client, $login_session, $userid ) = @_;
1764 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1765 $login_session, $userid, 'VIEW_HOLD' );
1766 return $evt if $evt;
1769 my $holds = $apputils->simple_scalar_request(
1771 "open-ils.cstore.direct.action.hold_request.search.atomic",
1774 fulfillment_time => {"=" => undef },
1775 cancel_time => undef,
1780 for my $h (@$holds) {
1781 next unless $h->capture_time and $h->current_copy;
1783 my $copy = $apputils->simple_scalar_request(
1785 "open-ils.cstore.direct.asset.copy.retrieve",
1789 if ($copy and $copy->status == 8) {
1794 return { total => scalar(@$holds), ready => scalar(@ready) };
1798 __PACKAGE__->register_method(
1799 method => "checkedout_count",
1800 api_name => "open-ils.actor.user.checked_out.count__",
1802 notes => <<" NOTES");
1803 Returns a transaction record
1807 sub checkedout_count {
1808 my( $self, $client, $login_session, $userid ) = @_;
1810 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1811 $login_session, $userid, 'VIEW_CIRCULATIONS' );
1812 return $evt if $evt;
1814 my $circs = $apputils->simple_scalar_request(
1816 "open-ils.cstore.direct.action.circulation.search.atomic",
1817 { usr => $userid, stop_fines => undef }
1818 #{ usr => $userid, checkin_time => {"=" => undef } }
1821 my $parser = DateTime::Format::ISO8601->new;
1824 for my $c (@$circs) {
1825 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1826 my $due = $due_dt->epoch;
1828 if ($due < DateTime->today->epoch) {
1833 return { total => scalar(@$circs), overdue => scalar(@overdue) };
1837 __PACKAGE__->register_method(
1838 method => "checked_out",
1839 api_name => "open-ils.actor.user.checked_out",
1843 Returns a structure of circulations objects sorted by
1844 out, overdue, lost, claims_returned, long_overdue.
1845 A list of IDs are returned of each type.
1846 lost, long_overdue, and claims_returned circ will not
1847 be "finished" (there is an outstanding balance or some
1848 other pending action on the circ).
1850 The .count method also includes a 'total' field which
1851 sums all "open" circs
1855 __PACKAGE__->register_method(
1856 method => "checked_out",
1857 api_name => "open-ils.actor.user.checked_out.count",
1860 signature => q/@see open-ils.actor.user.checked_out/
1864 my( $self, $conn, $auth, $userid ) = @_;
1866 my $e = new_editor(authtoken=>$auth);
1867 return $e->event unless $e->checkauth;
1869 if( $userid ne $e->requestor->id ) {
1870 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
1873 my $count = $self->api_name =~ /count/;
1874 return _checked_out( $count, $e, $userid );
1878 my( $iscount, $e, $userid ) = @_;
1879 my $meth = 'open-ils.storage.actor.user.checked_out';
1880 $meth = "$meth.count" if $iscount;
1881 return $U->storagereq($meth, $userid);
1885 sub _checked_out_WHAT {
1886 my( $iscount, $e, $userid ) = @_;
1888 my $circs = $e->search_action_circulation(
1889 { usr => $userid, stop_fines => undef });
1891 my $mcircs = $e->search_action_circulation(
1894 checkin_time => undef,
1895 xact_finish => undef,
1899 push( @$circs, @$mcircs );
1901 my $parser = DateTime::Format::ISO8601->new;
1903 # split the circs up into overdue and not-overdue circs
1905 for my $c (@$circs) {
1906 if( $c->due_date ) {
1907 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1908 my $due = $due_dt->epoch;
1909 if ($due < DateTime->today->epoch) {
1910 push @overdue, $c->id;
1919 # grab all of the lost, claims-returned, and longoverdue circs
1920 #my $open = $e->search_action_circulation(
1921 # {usr => $userid, stop_fines => { '!=' => undef }, xact_finish => undef });
1924 # these items have stop_fines, but no xact_finish, so money
1925 # is owed on them and they have not been checked in
1926 my $open = $e->search_action_circulation(
1929 stop_fines => { in => [ qw/LOST CLAIMSRETURNED LONGOVERDUE/ ] },
1930 xact_finish => undef,
1931 checkin_time => undef,
1936 my( @lost, @cr, @lo );
1937 for my $c (@$open) {
1938 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1939 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1940 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
1946 total => @$circs + @lost + @cr + @lo,
1947 out => scalar(@out),
1948 overdue => scalar(@overdue),
1949 lost => scalar(@lost),
1950 claims_returned => scalar(@cr),
1951 long_overdue => scalar(@lo)
1957 overdue => \@overdue,
1959 claims_returned => \@cr,
1960 long_overdue => \@lo
1966 __PACKAGE__->register_method(
1967 method => "checked_in_with_fines",
1968 api_name => "open-ils.actor.user.checked_in_with_fines",
1971 signature => q/@see open-ils.actor.user.checked_out/
1973 sub checked_in_with_fines {
1974 my( $self, $conn, $auth, $userid ) = @_;
1976 my $e = new_editor(authtoken=>$auth);
1977 return $e->event unless $e->checkauth;
1979 if( $userid ne $e->requestor->id ) {
1980 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
1983 # money is owed on these items and they are checked in
1984 my $open = $e->search_action_circulation(
1987 xact_finish => undef,
1988 checkin_time => { "!=" => undef },
1993 my( @lost, @cr, @lo );
1994 for my $c (@$open) {
1995 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1996 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1997 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
2002 claims_returned => \@cr,
2003 long_overdue => \@lo
2015 __PACKAGE__->register_method(
2016 method => "user_transaction_history",
2017 api_name => "open-ils.actor.user.transactions.history",
2019 notes => <<" NOTES");
2020 Returns a list of billable transaction ids for a user, optionally by type
2022 __PACKAGE__->register_method(
2023 method => "user_transaction_history",
2024 api_name => "open-ils.actor.user.transactions.history.have_charge",
2026 notes => <<" NOTES");
2027 Returns a list of billable transaction ids for a user that have an initial charge, optionally by type
2029 __PACKAGE__->register_method(
2030 method => "user_transaction_history",
2031 api_name => "open-ils.actor.user.transactions.history.have_balance",
2034 notes => <<" NOTES");
2035 Returns a list of billable transaction ids for a user that have a balance, optionally by type
2037 __PACKAGE__->register_method(
2038 method => "user_transaction_history",
2039 api_name => "open-ils.actor.user.transactions.history.still_open",
2041 notes => <<" NOTES");
2042 Returns a list of billable transaction ids for a user that are not finished
2044 __PACKAGE__->register_method(
2045 method => "user_transaction_history",
2046 api_name => "open-ils.actor.user.transactions.history.have_bill",
2049 notes => <<" NOTES");
2050 Returns a list of billable transaction ids for a user that has billings
2053 sub user_transaction_history {
2054 my( $self, $conn, $auth, $userid, $type ) = @_;
2056 # run inside of a transaction to prevent replication delays
2057 my $e = new_editor(xact=>1, authtoken=>$auth);
2058 return $e->die_event unless $e->checkauth;
2060 if( $e->requestor->id ne $userid ) {
2061 return $e->die_event
2062 unless $e->allowed('VIEW_USER_TRANSACTIONS');
2065 my $api = $self->api_name;
2066 my @xact_finish = (xact_finish => undef ) if ($api =~ /history.still_open$/);
2068 my @xacts = @{ $e->search_money_billable_transaction(
2069 [ { usr => $userid, @xact_finish },
2071 flesh_fields => { mbt => [ qw/billings payments grocery circulation/ ] },
2072 order_by => { mbt => 'xact_start DESC' },
2080 #my @mbts = _make_mbts( @xacts );
2081 my @mbts = $U->make_mbts( @xacts );
2083 if(defined($type)) {
2084 @mbts = grep { $_->xact_type eq $type } @mbts;
2087 if($api =~ /have_balance/o) {
2088 @mbts = grep { int($_->balance_owed * 100) != 0 } @mbts;
2091 if($api =~ /have_charge/o) {
2092 @mbts = grep { defined($_->last_billing_ts) } @mbts;
2095 if($api =~ /have_bill/o) {
2096 @mbts = grep { int($_->total_owed * 100) != 0 } @mbts;
2104 __PACKAGE__->register_method(
2105 method => "user_perms",
2106 api_name => "open-ils.actor.permissions.user_perms.retrieve",
2108 notes => <<" NOTES");
2109 Returns a list of permissions
2112 my( $self, $client, $authtoken, $user ) = @_;
2114 my( $staff, $evt ) = $apputils->checkses($authtoken);
2115 return $evt if $evt;
2117 $user ||= $staff->id;
2119 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
2123 return $apputils->simple_scalar_request(
2125 "open-ils.storage.permission.user_perms.atomic",
2129 __PACKAGE__->register_method(
2130 method => "retrieve_perms",
2131 api_name => "open-ils.actor.permissions.retrieve",
2132 notes => <<" NOTES");
2133 Returns a list of permissions
2135 sub retrieve_perms {
2136 my( $self, $client ) = @_;
2137 return $apputils->simple_scalar_request(
2139 "open-ils.cstore.direct.permission.perm_list.search.atomic",
2140 { id => { '!=' => undef } }
2144 __PACKAGE__->register_method(
2145 method => "retrieve_groups",
2146 api_name => "open-ils.actor.groups.retrieve",
2147 notes => <<" NOTES");
2148 Returns a list of user groupss
2150 sub retrieve_groups {
2151 my( $self, $client ) = @_;
2152 return new_editor()->retrieve_all_permission_grp_tree();
2155 __PACKAGE__->register_method(
2156 method => "retrieve_org_address",
2157 api_name => "open-ils.actor.org_unit.address.retrieve",
2158 notes => <<' NOTES');
2159 Returns an org_unit address by ID
2160 @param An org_address ID
2162 sub retrieve_org_address {
2163 my( $self, $client, $id ) = @_;
2164 return $apputils->simple_scalar_request(
2166 "open-ils.cstore.direct.actor.org_address.retrieve",
2171 __PACKAGE__->register_method(
2172 method => "retrieve_groups_tree",
2173 api_name => "open-ils.actor.groups.tree.retrieve",
2174 notes => <<" NOTES");
2175 Returns a list of user groups
2177 sub retrieve_groups_tree {
2178 my( $self, $client ) = @_;
2179 return new_editor()->search_permission_grp_tree(
2184 flesh_fields => { pgt => ["children"] },
2185 order_by => { pgt => 'name'}
2192 __PACKAGE__->register_method(
2193 method => "add_user_to_groups",
2194 api_name => "open-ils.actor.user.set_groups",
2195 notes => <<" NOTES");
2196 Adds a user to one or more permission groups
2199 sub add_user_to_groups {
2200 my( $self, $client, $authtoken, $userid, $groups ) = @_;
2202 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2203 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
2204 return $evt if $evt;
2206 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2207 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
2208 return $evt if $evt;
2210 $apputils->simplereq(
2212 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
2214 for my $group (@$groups) {
2215 my $link = Fieldmapper::permission::usr_grp_map->new;
2217 $link->usr($userid);
2219 my $id = $apputils->simplereq(
2221 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
2227 __PACKAGE__->register_method(
2228 method => "get_user_perm_groups",
2229 api_name => "open-ils.actor.user.get_groups",
2230 notes => <<" NOTES");
2231 Retrieve a user's permission groups.
2235 sub get_user_perm_groups {
2236 my( $self, $client, $authtoken, $userid ) = @_;
2238 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
2239 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
2240 return $evt if $evt;
2242 return $apputils->simplereq(
2244 'open-ils.cstore.direct.permission.usr_grp_map.search.atomic', { usr => $userid } );
2248 __PACKAGE__->register_method(
2249 method => "get_user_work_ous",
2250 api_name => "open-ils.actor.user.get_work_ous",
2251 notes => <<" NOTES");
2252 Retrieve a user's work org units.
2254 __PACKAGE__->register_method(
2255 method => "get_user_work_ous",
2256 api_name => "open-ils.actor.user.get_work_ous.ids",
2257 notes => <<" NOTES");
2258 Retrieve a user's work org units.
2262 sub get_user_work_ous {
2263 my( $self, $client, $auth, $userid ) = @_;
2264 my $e = new_editor(authtoken=>$auth);
2265 return $e->event unless $e->checkauth;
2266 $userid ||= $e->requestor->id;
2268 if($e->requestor->id != $userid) {
2269 my $user = $e->retrieve_actor_user($userid)
2270 or return $e->event;
2271 return $e->event unless $e->allowed('ASSIGN_WORK_ORG_UNIT', $user->home_ou);
2274 return $e->search_permission_usr_work_ou_map({usr => $userid})
2275 unless $self->api_name =~ /.ids$/;
2277 # client just wants a list of org IDs
2278 return $U->get_user_work_ou_ids($e, $userid);
2284 __PACKAGE__->register_method (
2285 method => 'register_workstation',
2286 api_name => 'open-ils.actor.workstation.register.override',
2287 signature => q/@see open-ils.actor.workstation.register/);
2289 __PACKAGE__->register_method (
2290 method => 'register_workstation',
2291 api_name => 'open-ils.actor.workstation.register',
2293 Registers a new workstion in the system
2294 @param authtoken The login session key
2295 @param name The name of the workstation id
2296 @param owner The org unit that owns this workstation
2297 @return The workstation id on success, WORKSTATION_NAME_EXISTS
2298 if the name is already in use.
2301 sub register_workstation {
2302 my( $self, $conn, $authtoken, $name, $owner ) = @_;
2304 my $e = new_editor(authtoken=>$authtoken, xact=>1);
2305 return $e->die_event unless $e->checkauth;
2306 return $e->die_event unless $e->allowed('REGISTER_WORKSTATION', $owner);
2307 my $existing = $e->search_actor_workstation({name => $name})->[0];
2311 if( $self->api_name =~ /override/o ) {
2312 # workstation with the given name exists.
2314 if($owner ne $existing->owning_lib) {
2315 # if necessary, update the owning_lib of the workstation
2317 $logger->info("changing owning lib of workstation ".$existing->id.
2318 " from ".$existing->owning_lib." to $owner");
2319 return $e->die_event unless
2320 $e->allowed('UPDATE_WORKSTATION', $existing->owning_lib);
2322 return $e->die_event unless $e->allowed('UPDATE_WORKSTATION', $owner);
2324 $existing->owning_lib($owner);
2325 return $e->die_event unless $e->update_actor_workstation($existing);
2331 "attempt to register an existing workstation. returning existing ID");
2334 return $existing->id;
2337 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS')
2341 my $ws = Fieldmapper::actor::workstation->new;
2342 $ws->owning_lib($owner);
2344 $e->create_actor_workstation($ws) or return $e->die_event;
2346 return $ws->id; # note: editor sets the id on the new object for us
2349 __PACKAGE__->register_method (
2350 method => 'workstation_list',
2351 api_name => 'open-ils.actor.workstation.list',
2353 Returns a list of workstations registered at the given location
2354 @param authtoken The login session key
2355 @param ids A list of org_unit.id's for the workstation owners
2358 sub workstation_list {
2359 my( $self, $conn, $authtoken, @orgs ) = @_;
2361 my $e = new_editor(authtoken=>$authtoken);
2362 return $e->event unless $e->checkauth;
2367 unless $e->allowed('REGISTER_WORKSTATION', $o);
2368 $results{$o} = $e->search_actor_workstation({owning_lib=>$o});
2379 __PACKAGE__->register_method (
2380 method => 'fetch_patron_note',
2381 api_name => 'open-ils.actor.note.retrieve.all',
2384 Returns a list of notes for a given user
2385 Requestor must have VIEW_USER permission if pub==false and
2386 @param authtoken The login session key
2387 @param args Hash of params including
2388 patronid : the patron's id
2389 pub : true if retrieving only public notes
2393 sub fetch_patron_note {
2394 my( $self, $conn, $authtoken, $args ) = @_;
2395 my $patronid = $$args{patronid};
2397 my($reqr, $evt) = $U->checkses($authtoken);
2398 return $evt if $evt;
2401 ($patron, $evt) = $U->fetch_user($patronid);
2402 return $evt if $evt;
2405 if( $patronid ne $reqr->id ) {
2406 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2407 return $evt if $evt;
2409 return $U->cstorereq(
2410 'open-ils.cstore.direct.actor.usr_note.search.atomic',
2411 { usr => $patronid, pub => 't' } );
2414 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2415 return $evt if $evt;
2417 return $U->cstorereq(
2418 'open-ils.cstore.direct.actor.usr_note.search.atomic', { usr => $patronid } );
2421 __PACKAGE__->register_method (
2422 method => 'create_user_note',
2423 api_name => 'open-ils.actor.note.create',
2425 Creates a new note for the given user
2426 @param authtoken The login session key
2427 @param note The note object
2430 sub create_user_note {
2431 my( $self, $conn, $authtoken, $note ) = @_;
2432 my $e = new_editor(xact=>1, authtoken=>$authtoken);
2433 return $e->die_event unless $e->checkauth;
2435 my $user = $e->retrieve_actor_user($note->usr)
2436 or return $e->die_event;
2438 return $e->die_event unless
2439 $e->allowed('UPDATE_USER',$user->home_ou);
2441 $note->creator($e->requestor->id);
2442 $e->create_actor_usr_note($note) or return $e->die_event;
2448 __PACKAGE__->register_method (
2449 method => 'delete_user_note',
2450 api_name => 'open-ils.actor.note.delete',
2452 Deletes a note for the given user
2453 @param authtoken The login session key
2454 @param noteid The note id
2457 sub delete_user_note {
2458 my( $self, $conn, $authtoken, $noteid ) = @_;
2460 my $e = new_editor(xact=>1, authtoken=>$authtoken);
2461 return $e->die_event unless $e->checkauth;
2462 my $note = $e->retrieve_actor_usr_note($noteid)
2463 or return $e->die_event;
2464 my $user = $e->retrieve_actor_user($note->usr)
2465 or return $e->die_event;
2466 return $e->die_event unless
2467 $e->allowed('UPDATE_USER', $user->home_ou);
2469 $e->delete_actor_usr_note($note) or return $e->die_event;
2475 __PACKAGE__->register_method (
2476 method => 'update_user_note',
2477 api_name => 'open-ils.actor.note.update',
2479 @param authtoken The login session key
2480 @param note The note
2484 sub update_user_note {
2485 my( $self, $conn, $auth, $note ) = @_;
2486 my $e = new_editor(authtoken=>$auth, xact=>1);
2487 return $e->event unless $e->checkauth;
2488 my $patron = $e->retrieve_actor_user($note->usr)
2489 or return $e->event;
2490 return $e->event unless
2491 $e->allowed('UPDATE_USER', $patron->home_ou);
2492 $e->update_actor_user_note($note)
2493 or return $e->event;
2501 __PACKAGE__->register_method (
2502 method => 'create_closed_date',
2503 api_name => 'open-ils.actor.org_unit.closed_date.create',
2505 Creates a new closing entry for the given org_unit
2506 @param authtoken The login session key
2507 @param note The closed_date object
2510 sub create_closed_date {
2511 my( $self, $conn, $authtoken, $cd ) = @_;
2513 my( $user, $evt ) = $U->checkses($authtoken);
2514 return $evt if $evt;
2516 $evt = $U->check_perms($user->id, $cd->org_unit, 'CREATE_CLOSEING');
2517 return $evt if $evt;
2519 $logger->activity("user ".$user->id." creating library closing for ".$cd->org_unit);
2521 my $id = $U->storagereq(
2522 'open-ils.storage.direct.actor.org_unit.closed_date.create', $cd );
2523 return $U->DB_UPDATE_FAILED($cd) unless $id;
2528 __PACKAGE__->register_method (
2529 method => 'delete_closed_date',
2530 api_name => 'open-ils.actor.org_unit.closed_date.delete',
2532 Deletes a closing entry for the given org_unit
2533 @param authtoken The login session key
2534 @param noteid The close_date id
2537 sub delete_closed_date {
2538 my( $self, $conn, $authtoken, $cd ) = @_;
2540 my( $user, $evt ) = $U->checkses($authtoken);
2541 return $evt if $evt;
2544 ($cd_obj, $evt) = fetch_closed_date($cd);
2545 return $evt if $evt;
2547 $evt = $U->check_perms($user->id, $cd->org_unit, 'DELETE_CLOSEING');
2548 return $evt if $evt;
2550 $logger->activity("user ".$user->id." deleting library closing for ".$cd->org_unit);
2552 my $stat = $U->storagereq(
2553 'open-ils.storage.direct.actor.org_unit.closed_date.delete', $cd );
2554 return $U->DB_UPDATE_FAILED($cd) unless $stat;
2559 __PACKAGE__->register_method(
2560 method => 'usrname_exists',
2561 api_name => 'open-ils.actor.username.exists',
2563 Returns 1 if the requested username exists, returns 0 otherwise
2567 sub usrname_exists {
2568 my( $self, $conn, $auth, $usrname ) = @_;
2569 my $e = new_editor(authtoken=>$auth);
2570 return $e->event unless $e->checkauth;
2571 my $a = $e->search_actor_user({usrname => $usrname, deleted=>'f'}, {idlist=>1});
2572 return $$a[0] if $a and @$a;
2576 __PACKAGE__->register_method(
2577 method => 'barcode_exists',
2578 api_name => 'open-ils.actor.barcode.exists',
2581 Returns 1 if the requested barcode exists, returns 0 otherwise
2585 sub barcode_exists {
2586 my( $self, $conn, $auth, $barcode ) = @_;
2587 my $e = new_editor(authtoken=>$auth);
2588 return $e->event unless $e->checkauth;
2589 my $card = $e->search_actor_card({barcode => $barcode});
2590 return undef unless @$card;
2591 return $card->[0]->usr;
2595 __PACKAGE__->register_method(
2596 method => 'retrieve_net_levels',
2597 api_name => 'open-ils.actor.net_access_level.retrieve.all',
2600 sub retrieve_net_levels {
2601 my( $self, $conn, $auth ) = @_;
2602 my $e = new_editor(authtoken=>$auth);
2603 return $e->event unless $e->checkauth;
2604 return $e->retrieve_all_config_net_access_level();
2608 __PACKAGE__->register_method(
2609 method => 'fetch_org_by_shortname',
2610 api_name => 'open-ils.actor.org_unit.retrieve_by_shorname',
2612 sub fetch_org_by_shortname {
2613 my( $self, $conn, $sname ) = @_;
2614 my $e = new_editor();
2615 my $org = $e->search_actor_org_unit({ shortname => uc($sname)})->[0];
2616 return $e->event unless $org;
2621 __PACKAGE__->register_method(
2622 method => 'session_home_lib',
2623 api_name => 'open-ils.actor.session.home_lib',
2626 sub session_home_lib {
2627 my( $self, $conn, $auth ) = @_;
2628 my $e = new_editor(authtoken=>$auth);
2629 return undef unless $e->checkauth;
2630 my $org = $e->retrieve_actor_org_unit($e->requestor->home_ou);
2631 return $org->shortname;
2634 __PACKAGE__->register_method(
2635 method => 'session_safe_token',
2636 api_name => 'open-ils.actor.session.safe_token',
2638 Returns a hashed session ID that is safe for export to the world.
2639 This safe token will expire after 1 hour of non-use.
2640 @param auth Active authentication token
2644 sub session_safe_token {
2645 my( $self, $conn, $auth ) = @_;
2646 my $e = new_editor(authtoken=>$auth);
2647 return undef unless $e->checkauth;
2649 my $safe_token = md5_hex($auth);
2651 $cache ||= OpenSRF::Utils::Cache->new("global", 0);
2653 # Add more like the following if needed...
2655 "safe-token-home_lib-shortname-$safe_token",
2656 $e->retrieve_actor_org_unit(
2657 $e->requestor->home_ou
2666 __PACKAGE__->register_method(
2667 method => 'safe_token_home_lib',
2668 api_name => 'open-ils.actor.safe_token.home_lib.shortname',
2670 Returns the home library shortname from the session
2671 asscociated with a safe token from generated by
2672 open-ils.actor.session.safe_token.
2673 @param safe_token Active safe token
2677 sub safe_token_home_lib {
2678 my( $self, $conn, $safe_token ) = @_;
2680 $cache ||= OpenSRF::Utils::Cache->new("global", 0);
2681 return $cache->get_cache( 'safe-token-home_lib-shortname-'. $safe_token );
2686 __PACKAGE__->register_method(
2687 method => 'slim_tree',
2688 api_name => "open-ils.actor.org_tree.slim_hash.retrieve",
2691 my $tree = new_editor()->search_actor_org_unit(
2693 {"parent_ou" => undef },
2696 flesh_fields => { aou => ['children'] },
2697 order_by => { aou => 'name'},
2698 select => { aou => ["id","shortname", "name"]},
2703 return trim_tree($tree);
2709 return undef unless $tree;
2711 code => $tree->shortname,
2712 name => $tree->name,
2714 if( $tree->children and @{$tree->children} ) {
2715 $htree->{children} = [];
2716 for my $c (@{$tree->children}) {
2717 push( @{$htree->{children}}, trim_tree($c) );
2725 __PACKAGE__->register_method(
2726 method => "update_penalties",
2727 api_name => "open-ils.actor.user.penalties.update");
2728 sub update_penalties {
2729 my( $self, $conn, $auth, $userid ) = @_;
2730 my $e = new_editor(authtoken=>$auth);
2731 return $e->event unless $e->checkauth;
2732 $U->update_patron_penalties(
2734 patronid => $userid,
2741 __PACKAGE__->register_method(
2742 method => "user_retrieve_fleshed_by_id",
2743 api_name => "open-ils.actor.user.fleshed.retrieve",);
2745 sub user_retrieve_fleshed_by_id {
2746 my( $self, $client, $auth, $user_id, $fields ) = @_;
2747 my $e = new_editor(authtoken => $auth);
2748 return $e->event unless $e->checkauth;
2750 if( $e->requestor->id != $user_id ) {
2751 return $e->event unless $e->allowed('VIEW_USER');
2757 "standing_penalties",
2761 "stat_cat_entries" ];
2762 return new_flesh_user($user_id, $fields, $e);
2766 sub new_flesh_user {
2769 my $fields = shift || [];
2770 my $e = shift || new_editor(xact=>1);
2772 my $user = $e->retrieve_actor_user(
2777 "flesh_fields" => { "au" => $fields }
2780 ) or return $e->event;
2783 if( grep { $_ eq 'addresses' } @$fields ) {
2785 $user->addresses([]) unless @{$user->addresses};
2787 if( ref $user->billing_address ) {
2788 unless( grep { $user->billing_address->id == $_->id } @{$user->addresses} ) {
2789 push( @{$user->addresses}, $user->billing_address );
2793 if( ref $user->mailing_address ) {
2794 unless( grep { $user->mailing_address->id == $_->id } @{$user->addresses} ) {
2795 push( @{$user->addresses}, $user->mailing_address );
2801 $user->clear_passwd();
2808 __PACKAGE__->register_method(
2809 method => "user_retrieve_parts",
2810 api_name => "open-ils.actor.user.retrieve.parts",);
2812 sub user_retrieve_parts {
2813 my( $self, $client, $auth, $user_id, $fields ) = @_;
2814 my $e = new_editor(authtoken => $auth);
2815 return $e->event unless $e->checkauth;
2816 if( $e->requestor->id != $user_id ) {
2817 return $e->event unless $e->allowed('VIEW_USER');
2820 my $user = $e->retrieve_actor_user($user_id) or return $e->event;
2821 push(@resp, $user->$_()) for(@$fields);
2827 __PACKAGE__->register_method(
2828 method => 'user_opt_in_enabled',
2829 api_name => 'open-ils.actor.user.org_unit_opt_in.enabled',
2831 @return 1 if user opt-in is globally enabled, 0 otherwise.
2834 sub user_opt_in_enabled {
2835 my($self, $conn) = @_;
2836 my $sc = OpenSRF::Utils::SettingsClient->new;
2837 return 1 if lc($sc->config_value(share => user => 'opt_in')) eq 'true';
2842 __PACKAGE__->register_method(
2843 method => 'user_opt_in_at_org',
2844 api_name => 'open-ils.actor.user.org_unit_opt_in.check',
2846 @param $auth The auth token
2847 @param user_id The ID of the user to test
2848 @return 1 if the user has opted in at the specified org,
2849 event on error, and 0 otherwise. /);
2850 sub user_opt_in_at_org {
2851 my($self, $conn, $auth, $user_id) = @_;
2853 # see if we even need to enforce the opt-in value
2854 return 1 unless user_opt_in_enabled($self);
2856 my $e = new_editor(authtoken => $auth);
2857 return $e->event unless $e->checkauth;
2858 my $org_id = $e->requestor->ws_ou;
2860 my $user = $e->retrieve_actor_user($user_id) or return $e->event;
2861 return $e->event unless $e->allowed('VIEW_USER', $user->home_ou);
2863 # user is automatically opted-in at the home org
2864 return 1 if $user->home_ou eq $org_id;
2866 my $vals = $e->search_actor_usr_org_unit_opt_in(
2867 {org_unit=>$org_id, usr=>$user_id},{idlist=>1});
2873 __PACKAGE__->register_method(
2874 method => 'create_user_opt_in_at_org',
2875 api_name => 'open-ils.actor.user.org_unit_opt_in.create',
2877 @param $auth The auth token
2878 @param user_id The ID of the user to test
2879 @return The ID of the newly created object, event on error./);
2881 sub create_user_opt_in_at_org {
2882 my($self, $conn, $auth, $user_id) = @_;
2884 my $e = new_editor(authtoken => $auth, xact=>1);
2885 return $e->die_event unless $e->checkauth;
2886 my $org_id = $e->requestor->ws_ou;
2888 my $user = $e->retrieve_actor_user($user_id) or return $e->die_event;
2889 return $e->die_event unless $e->allowed('UPDATE_USER', $user->home_ou);
2891 my $opt_in = Fieldmapper::actor::usr_org_unit_opt_in->new;
2893 $opt_in->org_unit($org_id);
2894 $opt_in->usr($user_id);
2895 $opt_in->staff($e->requestor->id);
2896 $opt_in->opt_in_ts('now');
2897 $opt_in->opt_in_ws($e->requestor->wsid);
2899 $opt_in = $e->create_actor_usr_org_unit_opt_in($opt_in)
2900 or return $e->die_event;
2908 __PACKAGE__->register_method (
2909 method => 'retrieve_org_hours',
2910 api_name => 'open-ils.actor.org_unit.hours_of_operation.retrieve',
2912 Returns the hours of operation for a specified org unit
2913 @param authtoken The login session key
2914 @param org_id The org_unit ID
2918 sub retrieve_org_hours {
2919 my($self, $conn, $auth, $org_id) = @_;
2920 my $e = new_editor(authtoken => $auth);
2921 return $e->die_event unless $e->checkauth;
2922 $org_id ||= $e->requestor->ws_ou;
2923 return $e->retrieve_actor_org_unit_hours_of_operation($org_id);