1 package OpenILS::Application::Actor;
2 use base qw/OpenSRF::Application/;
3 use strict; use warnings;
5 $Data::Dumper::Indent = 0;
8 use Digest::MD5 qw(md5_hex);
10 use OpenSRF::EX qw(:try);
13 use OpenILS::Application::AppUtils;
15 use OpenILS::Utils::Fieldmapper;
16 use OpenILS::Application::Search::Actor;
17 use OpenILS::Utils::ModsParser;
18 use OpenSRF::Utils::Logger qw/$logger/;
19 use OpenSRF::Utils qw/:datetime/;
21 use OpenSRF::Utils::Cache;
24 use DateTime::Format::ISO8601;
26 use OpenILS::Application::Actor::Container;
27 use OpenILS::Application::Actor::ClosedDates;
29 use OpenILS::Utils::Editor qw/:funcs/;
31 use OpenILS::Application::Actor::UserGroups;
33 OpenILS::Application::Actor::Container->initialize();
34 OpenILS::Application::Actor::UserGroups->initialize();
35 OpenILS::Application::Actor::ClosedDates->initialize();
38 my $apputils = "OpenILS::Application::AppUtils";
41 sub _d { warn "Patron:\n" . Dumper(shift()); }
46 my $set_user_settings;
49 __PACKAGE__->register_method(
50 method => "set_user_settings",
51 api_name => "open-ils.actor.patron.settings.update",
53 sub set_user_settings {
54 my( $self, $client, $user_session, $uid, $settings ) = @_;
56 $logger->debug("Setting user settings: $user_session, $uid, " . Dumper($settings));
58 my( $staff, $user, $evt ) =
59 $apputils->checkses_requestor( $user_session, $uid, 'UPDATE_USER' );
64 # [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
67 [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
69 $logger->activity("User " . $staff->id . " updating user $uid settings with: " . Dumper(\@params));
71 return $apputils->simplereq(
73 'open-ils.storage.direct.actor.user_setting.batch.merge', @params );
79 __PACKAGE__->register_method(
80 method => "set_ou_settings",
81 api_name => "open-ils.actor.org_unit.settings.update",
84 my( $self, $client, $user_session, $ouid, $settings ) = @_;
86 my( $staff, $evt ) = $apputils->checkses( $user_session );
88 $evt = $apputils->check_perms( $staff->id, $ouid, 'UPDATE_ORG_UNIT' );
93 map { [{ org_unit => $ouid, name => $_}, {value => $$settings{$_}}] } keys %$settings;
95 $logger->activity("Updating org unit [$ouid] settings with: " . Dumper($params));
97 return $apputils->simplereq(
99 'open-ils.storage.direct.actor.org_unit_setting.merge', @$params );
103 my $fetch_user_settings;
104 my $fetch_ou_settings;
106 __PACKAGE__->register_method(
107 method => "user_settings",
108 api_name => "open-ils.actor.patron.settings.retrieve",
111 my( $self, $client, $user_session, $uid ) = @_;
113 my( $staff, $user, $evt ) =
114 $apputils->checkses_requestor( $user_session, $uid, 'VIEW_USER' );
117 $logger->debug("User " . $staff->id . " fetching user $uid\n");
118 my $s = $apputils->simplereq(
120 'open-ils.storage.direct.actor.user_setting.search.usr.atomic',$uid );
122 return { map { ($_->name,$_->value) } @$s };
127 __PACKAGE__->register_method(
128 method => "ou_settings",
129 api_name => "open-ils.actor.org_unit.settings.retrieve",
132 my( $self, $client, $ouid ) = @_;
134 $logger->info("Fetching org unit settings for org $ouid");
136 my $s = $apputils->simplereq(
138 'open-ils.storage.direct.actor.org_unit_setting.search.org_unit.atomic', $ouid);
140 return { map { ($_->name,$_->value) } @$s };
143 __PACKAGE__->register_method (
144 method => "ou_setting_delete",
145 api_name => 'open-ils.actor.org_setting.delete',
147 Deletes a specific org unit setting for a specific location
148 @param authtoken The login session key
149 @param orgid The org unit whose setting we're changing
150 @param setting The name of the setting to delete
151 @return True value on success.
155 sub ou_setting_delete {
156 my( $self, $conn, $authtoken, $orgid, $setting ) = @_;
157 my( $reqr, $evt) = $U->checkses($authtoken);
159 $evt = $U->check_perms($reqr->id, $orgid, 'UPDATE_ORG_SETTING');
162 my $id = $U->storagereq(
163 'open-ils.storage.id_list.actor.org_unit_setting.search_where',
164 { name => $setting, org_unit => $orgid } );
166 $logger->debug("Retrieved setting $id in org unit setting delete");
168 my $s = $U->storagereq(
169 'open-ils.storage.direct.actor.org_unit_setting.delete', $id );
171 $logger->activity("User ".$reqr->id." deleted org unit setting $id") if $s;
177 __PACKAGE__->register_method(
178 method => "update_patron",
179 api_name => "open-ils.actor.patron.update",);
182 my( $self, $client, $user_session, $patron ) = @_;
184 my $session = $apputils->start_db_session();
187 $logger->info("Creating new patron...") if $patron->isnew;
188 $logger->info("Updating Patron: " . $patron->id) unless $patron->isnew;
190 my( $user_obj, $evt ) = $U->checkses($user_session);
193 # XXX does this user have permission to add/create users. Granularity?
194 # $new_patron is the patron in progress. $patron is the original patron
195 # passed in with the method. new_patron will change as the components
196 # of patron are added/updated.
200 # unflesh the real items on the patron
201 $patron->card( $patron->card->id ) if(ref($patron->card));
202 $patron->billing_address( $patron->billing_address->id )
203 if(ref($patron->billing_address));
204 $patron->mailing_address( $patron->mailing_address->id )
205 if(ref($patron->mailing_address));
207 # create/update the patron first so we can use his id
208 if($patron->isnew()) {
209 ( $new_patron, $evt ) = _add_patron($session, _clone_patron($patron), $user_obj);
211 } else { $new_patron = $patron; }
213 ( $new_patron, $evt ) = _add_update_addresses($session, $patron, $new_patron, $user_obj);
216 ( $new_patron, $evt ) = _add_update_cards($session, $patron, $new_patron, $user_obj);
219 ( $new_patron, $evt ) = _add_survey_responses($session, $patron, $new_patron, $user_obj);
222 # re-update the patron if anything has happened to him during this process
223 if($new_patron->ischanged()) {
224 ( $new_patron, $evt ) = _update_patron($session, $new_patron, $user_obj);
228 #$session = OpenSRF::AppSession->create("open-ils.storage"); # why did i put this here?
230 ($new_patron, $evt) = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
233 ($new_patron, $evt) = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
236 ($new_patron, $evt) = _create_standing_penalties($session, $user_session, $patron, $new_patron, $user_obj);
239 $logger->activity("user ".$user_obj->id." updating/creating user ".$new_patron->id);
240 $apputils->commit_db_session($session);
242 #warn "Patron Update/Create complete\n";
243 return flesh_user($new_patron->id());
249 __PACKAGE__->register_method(
250 method => "user_retrieve_fleshed_by_id",
251 api_name => "open-ils.actor.user.fleshed.retrieve",);
253 sub user_retrieve_fleshed_by_id {
254 my( $self, $client, $user_session, $user_id ) = @_;
256 my( $requestor, $target, $evt ) = $apputils->
257 checkses_requestor( $user_session, $user_id, 'VIEW_USER' );
260 return flesh_user($user_id);
264 # fleshes: card, cards, address, addresses, stat_cat_entries, standing_penalties
272 $session = OpenSRF::AppSession->create("open-ils.storage");
276 # grab the user with the given id
277 my $ureq = $session->request(
278 "open-ils.storage.direct.actor.user.retrieve", $id);
279 my $user = $ureq->gather(1);
281 if(!$user) { return undef; }
284 my $cards_req = $session->request(
285 "open-ils.storage.direct.actor.card.search.usr.atomic",
287 $user->cards( $cards_req->gather(1) );
289 for my $c(@{$user->cards}) {
290 if($c->id == $user->card || $c->id eq $user->card ) {
291 #warn "Setting my card to " . $c->id . "\n";
296 my $add_req = $session->request(
297 "open-ils.storage.direct.actor.user_address.search.usr.atomic",
299 $user->addresses( $add_req->gather(1) );
301 if( @{$user->addresses} ) {
302 if( ! grep { $_->id eq $user->billing_address } @{$user->addresses} ) {
303 my $ba = $session->request(
304 'open-ils.storage.direct.actor.user_address.retrieve',
305 $user->billing_address)->gather(1);
306 push( @{$user->addresses}, $ba );
309 if( ! grep { $_->id eq $user->mailing_address } @{$user->addresses} ) {
310 my $ba = $session->request(
311 'open-ils.storage.direct.actor.user_address.retrieve',
312 $user->mailing_address)->gather(1);
313 push( @{$user->addresses}, $ba );
318 for my $c(@{$user->addresses}) {
319 if($c->id eq $user->billing_address ) { $user->billing_address($c); }
320 if($c->id eq $user->mailing_address ) { $user->mailing_address($c); }
323 my $stat_req = $session->request(
324 "open-ils.storage.direct.actor.stat_cat_entry_user_map.search.target_usr.atomic",
326 $user->stat_cat_entries($stat_req->gather(1));
328 my $standing_penalties_req = $session->request(
329 "open-ils.storage.direct.actor.user_standing_penalty.search.usr.atomic",
331 $user->standing_penalties($standing_penalties_req->gather(1));
333 if($kill) { $session->disconnect(); }
334 $user->clear_passwd();
340 # clone and clear stuff that would break the database
344 my $new_patron = $patron->clone;
346 # Using the Fieldmapper clone method
347 #my $new_patron = Fieldmapper::actor::user->new();
349 #my $fmap = $Fieldmapper::fieldmap;
350 #no strict; # shallow clone, may be useful in the fieldmapper
352 # (keys %{$fmap->{"Fieldmapper::actor::user"}->{'fields'}}) {
353 # $new_patron->$field( $patron->$field() );
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 );
404 my( $session, $patron, $user_obj, $noperm) = @_;
406 $logger->info("Updating patron ".$patron->id." in DB");
409 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'UPDATE_USER');
410 return (undef, $evt) if $evt;
413 # update the password by itself to avoid the password protection magic
414 if( $patron->passwd ) {
415 my $s = $session->request(
416 'open-ils.storage.direct.actor.user.remote_update',
417 {id => $patron->id}, {passwd => $patron->passwd})->gather(1);
418 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($s);
419 $patron->clear_passwd;
422 if(!$patron->ident_type) {
423 $patron->clear_ident_type;
424 $patron->clear_ident_value;
427 if(!$patron->ident_type2) {
428 $patron->clear_ident_type2;
429 $patron->clear_ident_value2;
432 my $stat = $session->request(
433 "open-ils.storage.direct.actor.user.update",$patron )->gather(1);
434 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($stat);
440 sub _add_update_addresses {
444 my $new_patron = shift;
448 my $current_id; # id of the address before creation
450 for my $address (@{$patron->addresses()}) {
452 next unless ref $address;
453 $current_id = $address->id();
455 if( $patron->billing_address() and
456 $patron->billing_address() == $current_id ) {
457 $logger->info("setting billing addr to $current_id");
458 $new_patron->billing_address($address->id());
459 $new_patron->ischanged(1);
462 if( $patron->mailing_address() and
463 $patron->mailing_address() == $current_id ) {
464 $new_patron->mailing_address($address->id());
465 $logger->info("setting mailing addr to $current_id");
466 $new_patron->ischanged(1);
470 if($address->isnew()) {
472 $address->usr($new_patron->id());
474 ($address, $evt) = _add_address($session,$address);
475 return (undef, $evt) if $evt;
477 # we need to get the new id
478 if( $patron->billing_address() and
479 $patron->billing_address() == $current_id ) {
480 $new_patron->billing_address($address->id());
481 $logger->info("setting billing addr to $current_id");
482 $new_patron->ischanged(1);
485 if( $patron->mailing_address() and
486 $patron->mailing_address() == $current_id ) {
487 $new_patron->mailing_address($address->id());
488 $logger->info("setting mailing addr to $current_id");
489 $new_patron->ischanged(1);
492 } elsif($address->ischanged() ) {
494 ($address, $evt) = _update_address($session, $address);
495 return (undef, $evt) if $evt;
497 } elsif($address->isdeleted() ) {
499 if( $address->id() == $new_patron->mailing_address() ) {
500 $new_patron->clear_mailing_address();
501 ($new_patron, $evt) = _update_patron($session, $new_patron);
502 return (undef, $evt) if $evt;
505 if( $address->id() == $new_patron->billing_address() ) {
506 $new_patron->clear_billing_address();
507 ($new_patron, $evt) = _update_patron($session, $new_patron);
508 return (undef, $evt) if $evt;
511 $evt = _delete_address($session, $address);
512 return (undef, $evt) if $evt;
516 return ( $new_patron, undef );
520 # adds an address to the db and returns the address with new id
522 my($session, $address) = @_;
523 $address->clear_id();
525 $logger->info("Creating new address at street ".$address->street1);
527 # put the address into the database
528 my $id = $session->request(
529 "open-ils.storage.direct.actor.user_address.create", $address )->gather(1);
530 return (undef, $U->DB_UPDATE_FAILED($address)) unless $id;
533 return ($address, undef);
537 sub _update_address {
538 my( $session, $address ) = @_;
540 $logger->info("Updating address ".$address->id." in the DB");
542 my $stat = $session->request(
543 "open-ils.storage.direct.actor.user_address.update", $address )->gather(1);
545 return (undef, $U->DB_UPDATE_FAILED($address)) unless defined($stat);
546 return ($address, undef);
551 sub _add_update_cards {
555 my $new_patron = shift;
559 my $virtual_id; #id of the card before creation
560 for my $card (@{$patron->cards()}) {
562 $card->usr($new_patron->id());
564 if(ref($card) and $card->isnew()) {
566 $virtual_id = $card->id();
567 ( $card, $evt ) = _add_card($session,$card);
568 return (undef, $evt) if $evt;
570 #if(ref($patron->card)) { $patron->card($patron->card->id); }
571 if($patron->card() == $virtual_id) {
572 $new_patron->card($card->id());
573 $new_patron->ischanged(1);
576 } elsif( ref($card) and $card->ischanged() ) {
577 $evt = _update_card($session, $card);
578 return (undef, $evt) if $evt;
582 return ( $new_patron, undef );
586 # adds an card to the db and returns the card with new id
588 my( $session, $card ) = @_;
591 $logger->info("Adding new patron card ".$card->barcode);
593 my $id = $session->request(
594 "open-ils.storage.direct.actor.card.create", $card )->gather(1);
595 return (undef, $U->DB_UPDATE_FAILED($card)) unless $id;
596 $logger->info("Successfully created patron card $id");
599 return ( $card, undef );
603 # returns event on error. returns undef otherwise
605 my( $session, $card ) = @_;
606 $logger->info("Updating patron card ".$card->id);
608 my $stat = $session->request(
609 "open-ils.storage.direct.actor.card.update", $card )->gather(1);
610 return $U->DB_UPDATE_FAILED($card) unless defined($stat);
617 # returns event on error. returns undef otherwise
618 sub _delete_address {
619 my( $session, $address ) = @_;
621 $logger->info("Deleting address ".$address->id." from DB");
623 my $stat = $session->request(
624 "open-ils.storage.direct.actor.user_address.delete", $address )->gather(1);
626 return $U->DB_UPDATE_FAILED($address) unless defined($stat);
632 sub _add_survey_responses {
633 my ($session, $patron, $new_patron) = @_;
635 $logger->info( "Updating survey responses for patron ".$new_patron->id );
637 my $responses = $patron->survey_responses;
641 $_->usr($new_patron->id) for (@$responses);
643 my $evt = $U->simplereq( "open-ils.circ",
644 "open-ils.circ.survey.submit.user_id", $responses );
646 return (undef, $evt) if defined($U->event_code($evt));
650 return ( $new_patron, undef );
654 sub _create_stat_maps {
656 my($session, $user_session, $patron, $new_patron) = @_;
658 my $maps = $patron->stat_cat_entries();
660 for my $map (@$maps) {
662 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
664 if ($map->isdeleted()) {
665 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.delete";
667 } elsif ($map->isnew()) {
668 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
673 $map->target_usr($new_patron->id);
676 $logger->info("Updating stat entry with method $method and map $map");
678 my $stat = $session->request($method, $map)->gather(1);
679 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
683 return ($new_patron, undef);
686 sub _create_perm_maps {
688 my($session, $user_session, $patron, $new_patron) = @_;
690 my $maps = $patron->permissions;
692 for my $map (@$maps) {
694 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
695 if ($map->isdeleted()) {
696 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
697 } elsif ($map->isnew()) {
698 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
703 $map->usr($new_patron->id);
705 #warn( "Updating permissions with method $method and session $user_session and map $map" );
706 $logger->info( "Updating permissions with method $method and map $map" );
708 my $stat = $session->request($method, $map)->gather(1);
709 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
713 return ($new_patron, undef);
717 sub _create_standing_penalties {
719 my($session, $user_session, $patron, $new_patron) = @_;
721 my $maps = $patron->standing_penalties;
724 for my $map (@$maps) {
726 if ($map->isdeleted()) {
727 $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
728 } elsif ($map->isnew()) {
729 $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
735 $map->usr($new_patron->id);
737 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
739 my $stat = $session->request($method, $map)->gather(1);
740 return (undef, $U->DB_UPDATE_FAILED($map)) unless $stat;
743 return ($new_patron, undef);
748 __PACKAGE__->register_method(
749 method => "search_username",
750 api_name => "open-ils.actor.user.search.username",
753 sub search_username {
754 my($self, $client, $username) = @_;
755 my $users = OpenILS::Application::AppUtils->simple_scalar_request(
757 "open-ils.storage.direct.actor.user.search.usrname.atomic",
765 __PACKAGE__->register_method(
766 method => "user_retrieve_by_barcode",
767 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
769 sub user_retrieve_by_barcode {
770 my($self, $client, $user_session, $barcode) = @_;
772 $logger->debug("Searching for user with barcode $barcode");
773 my ($user_obj, $evt) = $apputils->checkses($user_session);
777 my $session = OpenSRF::AppSession->create("open-ils.storage");
779 # find the card with the given barcode
780 my $creq = $session->request(
781 "open-ils.storage.direct.actor.card.search.barcode.atomic",
783 my $card = $creq->gather(1);
785 if(!$card || !$card->[0]) {
786 $session->disconnect();
787 return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' );
791 my $user = flesh_user($card->usr(), $session);
793 $evt = $U->check_perms($user_obj->id, $user->home_ou, 'VIEW_USER');
796 $session->disconnect();
797 if(!$user) { return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' ); }
804 __PACKAGE__->register_method(
805 method => "get_user_by_id",
806 api_name => "open-ils.actor.user.retrieve",);
809 my ($self, $client, $user_session, $id) = @_;
811 my $user_obj = $apputils->check_user_session( $user_session );
813 return $apputils->simple_scalar_request(
815 "open-ils.storage.direct.actor.user.retrieve",
821 __PACKAGE__->register_method(
822 method => "get_org_types",
823 api_name => "open-ils.actor.org_types.retrieve",);
827 my($self, $client) = @_;
829 return $org_types if $org_types;
831 $apputils->simple_scalar_request(
833 "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
838 __PACKAGE__->register_method(
839 method => "get_user_profiles",
840 api_name => "open-ils.actor.user.profiles.retrieve",
844 sub get_user_profiles {
845 return $user_profiles if $user_profiles;
847 return $user_profiles =
848 $apputils->simple_scalar_request(
850 "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
855 __PACKAGE__->register_method(
856 method => "get_user_ident_types",
857 api_name => "open-ils.actor.user.ident_types.retrieve",
860 sub get_user_ident_types {
861 return $ident_types if $ident_types;
862 return $ident_types =
863 $apputils->simple_scalar_request(
865 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
871 __PACKAGE__->register_method(
872 method => "get_org_unit",
873 api_name => "open-ils.actor.org_unit.retrieve",
877 my( $self, $client, $user_session, $org_id ) = @_;
878 my $e = new_editor(authtoken => $user_session);
880 return $e->event unless $e->checkauth;
881 $org_id = $e->requestor->ws_ou;
883 my $o = $e->retrieve_actor_org_unit($org_id)
888 __PACKAGE__->register_method(
889 method => "search_org_unit",
890 api_name => "open-ils.actor.org_unit_list.search",
893 sub search_org_unit {
895 my( $self, $client, $field, $value ) = @_;
897 my $list = OpenILS::Application::AppUtils->simple_scalar_request(
899 "open-ils.storage.direct.actor.org_unit.search.$field.atomic",
908 __PACKAGE__->register_method(
909 method => "get_org_tree",
910 api_name => "open-ils.actor.org_tree.retrieve",
912 note => "Returns the entire org tree structure",
916 my( $self, $client) = @_;
919 $cache_client = OpenSRF::Utils::Cache->new("global", 0);
921 # see if it's in the cache
922 #warn "Getting ORG Tree\n";
923 my $tree = $cache_client->get_cache('orgtree');
925 #warn "Found orgtree in cache. returning...\n";
929 my $orglist = $apputils->simple_scalar_request(
931 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
934 #warn "found org list\n";
937 $tree = $self->build_org_tree($orglist);
938 $cache_client->put_cache('orgtree', $tree);
944 # turns an org list into an org tree
947 my( $self, $orglist) = @_;
949 return $orglist unless (
950 ref($orglist) and @$orglist > 1 );
953 $a->ou_type <=> $b->ou_type ||
954 $a->name cmp $b->name } @$orglist;
956 for my $org (@list) {
958 next unless ($org and defined($org->parent_ou));
959 my ($parent) = grep { $_->id == $org->parent_ou } @list;
962 $parent->children([]) unless defined($parent->children);
963 push( @{$parent->children}, $org );
971 __PACKAGE__->register_method(
972 method => "get_org_descendants",
973 api_name => "open-ils.actor.org_tree.descendants.retrieve"
976 # depth is optional. org_unit is the id
977 sub get_org_descendants {
978 my( $self, $client, $org_unit, $depth ) = @_;
979 my $orglist = $apputils->simple_scalar_request(
981 "open-ils.storage.actor.org_unit.descendants.atomic",
983 return $self->build_org_tree($orglist);
987 __PACKAGE__->register_method(
988 method => "get_org_ancestors",
989 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
992 # depth is optional. org_unit is the id
993 sub get_org_ancestors {
994 my( $self, $client, $org_unit, $depth ) = @_;
995 my $orglist = $apputils->simple_scalar_request(
997 "open-ils.storage.actor.org_unit.ancestors.atomic",
999 return $self->build_org_tree($orglist);
1003 __PACKAGE__->register_method(
1004 method => "get_standings",
1005 api_name => "open-ils.actor.standings.retrieve"
1010 return $user_standings if $user_standings;
1011 return $user_standings =
1012 $apputils->simple_scalar_request(
1014 "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
1019 __PACKAGE__->register_method(
1020 method => "get_my_org_path",
1021 api_name => "open-ils.actor.org_unit.full_path.retrieve"
1024 sub get_my_org_path {
1025 my( $self, $client, $user_session, $org_id ) = @_;
1026 my $user_obj = $apputils->check_user_session($user_session);
1027 if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
1029 return $apputils->simple_scalar_request(
1031 "open-ils.storage.actor.org_unit.full_path.atomic",
1036 __PACKAGE__->register_method(
1037 method => "patron_adv_search",
1038 api_name => "open-ils.actor.patron.search.advanced" );
1039 sub patron_adv_search {
1040 my( $self, $client, $auth, $search_hash, $search_limit, $search_sort ) = @_;
1041 my $e = OpenILS::Utils::Editor->new(authtoken=>$auth);
1042 return $e->event unless $e->checkauth;
1043 return $e->event unless $e->allowed('VIEW_USER');
1045 "open-ils.storage.actor.user.crazy_search",
1046 $search_hash, $search_limit, $search_sort);
1051 sub _verify_password {
1052 my($user_session, $password) = @_;
1053 my $user_obj = $apputils->check_user_session($user_session);
1055 #grab the user with password
1056 $user_obj = $apputils->simple_scalar_request(
1058 "open-ils.storage.direct.actor.user.retrieve",
1061 if($user_obj->passwd eq $password) {
1069 __PACKAGE__->register_method(
1070 method => "update_password",
1071 api_name => "open-ils.actor.user.password.update");
1073 __PACKAGE__->register_method(
1074 method => "update_password",
1075 api_name => "open-ils.actor.user.username.update");
1077 __PACKAGE__->register_method(
1078 method => "update_password",
1079 api_name => "open-ils.actor.user.email.update");
1081 sub update_password {
1082 my( $self, $client, $user_session, $new_value, $current_password ) = @_;
1086 my $user_obj = $apputils->check_user_session($user_session);
1088 if($self->api_name =~ /password/o) {
1090 #make sure they know the current password
1091 if(!_verify_password($user_session, md5_hex($current_password))) {
1092 return OpenILS::Event->new('INCORRECT_PASSWORD');
1095 $logger->debug("update_password setting new password $new_value");
1096 $user_obj->passwd($new_value);
1098 } elsif($self->api_name =~ /username/o) {
1099 my $users = search_username(undef, undef, $new_value);
1100 if( $users and $users->[0] ) {
1101 return OpenILS::Event->new('USERNAME_EXISTS');
1103 $user_obj->usrname($new_value);
1105 } elsif($self->api_name =~ /email/o) {
1106 #warn "Updating email to $new_value\n";
1107 $user_obj->email($new_value);
1110 my $session = $apputils->start_db_session();
1112 ( $user_obj, $evt ) = _update_patron($session, $user_obj, $user_obj, 1);
1113 return $evt if $evt;
1115 $apputils->commit_db_session($session);
1117 if($user_obj) { return 1; }
1122 __PACKAGE__->register_method(
1123 method => "check_user_perms",
1124 api_name => "open-ils.actor.user.perm.check",
1125 notes => <<" NOTES");
1126 Takes a login session, user id, an org id, and an array of perm type strings. For each
1127 perm type, if the user does *not* have the given permission it is added
1128 to a list which is returned from the method. If all permissions
1129 are allowed, an empty list is returned
1130 if the logged in user does not match 'user_id', then the logged in user must
1131 have VIEW_PERMISSION priveleges.
1134 sub check_user_perms {
1135 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1137 my( $staff, $evt ) = $apputils->checkses($login_session);
1138 return $evt if $evt;
1140 if($staff->id ne $user_id) {
1141 if( my $evt = $apputils->check_perms(
1142 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1148 for my $perm (@$perm_types) {
1149 if($apputils->check_perms($user_id, $org_id, $perm)) {
1150 push @not_allowed, $perm;
1154 return \@not_allowed
1157 __PACKAGE__->register_method(
1158 method => "check_user_perms2",
1159 api_name => "open-ils.actor.user.perm.check.multi_org",
1161 Checks the permissions on a list of perms and orgs for a user
1162 @param authtoken The login session key
1163 @param user_id The id of the user to check
1164 @param orgs The array of org ids
1165 @param perms The array of permission names
1166 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1167 if the logged in user does not match 'user_id', then the logged in user must
1168 have VIEW_PERMISSION priveleges.
1171 sub check_user_perms2 {
1172 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1174 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1175 $authtoken, $user_id, 'VIEW_PERMISSION' );
1176 return $evt if $evt;
1179 for my $org (@$orgs) {
1180 for my $perm (@$perms) {
1181 if($apputils->check_perms($user_id, $org, $perm)) {
1182 push @not_allowed, [ $org, $perm ];
1187 return \@not_allowed
1191 __PACKAGE__->register_method(
1192 method => 'check_user_perms3',
1193 api_name => 'open-ils.actor.user.perm.highest_org',
1195 Returns the highest org unit id at which a user has a given permission
1196 If the requestor does not match the target user, the requestor must have
1197 'VIEW_PERMISSION' rights at the home org unit of the target user
1198 @param authtoken The login session key
1199 @param userid The id of the user in question
1200 @param perm The permission to check
1201 @return The org unit highest in the org tree within which the user has
1202 the requested permission
1205 sub check_user_perms3 {
1206 my( $self, $client, $authtoken, $userid, $perm ) = @_;
1208 my( $staff, $target, $org, $evt );
1210 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1211 $authtoken, $userid, 'VIEW_PERMISSION' );
1212 return $evt if $evt;
1214 my $tree = $self->get_org_tree();
1215 return _find_highest_perm_org( $perm, $userid, $target->ws_ou, $tree );
1219 sub _find_highest_perm_org {
1220 my ( $perm, $userid, $start_org, $org_tree ) = @_;
1221 my $org = $apputils->find_org($org_tree, $start_org );
1225 last if ($apputils->check_perms( $userid, $org->id, $perm )); # perm failed
1227 $org = $apputils->find_org( $org_tree, $org->parent_ou() );
1233 __PACKAGE__->register_method(
1234 method => 'check_user_perms4',
1235 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1237 Returns the highest org unit id at which a user has a given permission
1238 If the requestor does not match the target user, the requestor must have
1239 'VIEW_PERMISSION' rights at the home org unit of the target user
1240 @param authtoken The login session key
1241 @param userid The id of the user in question
1242 @param perms An array of perm names to check
1243 @return An array of orgId's representing the org unit
1244 highest in the org tree within which the user has the requested permission
1245 The arrah of orgId's has matches the order of the perms array
1248 sub check_user_perms4 {
1249 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1251 my( $staff, $target, $org, $evt );
1253 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1254 $authtoken, $userid, 'VIEW_PERMISSION' );
1255 return $evt if $evt;
1258 return [] unless ref($perms);
1259 my $tree = $self->get_org_tree();
1261 for my $p (@$perms) {
1262 push( @arr, _find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1270 __PACKAGE__->register_method(
1271 method => "user_fines_summary",
1272 api_name => "open-ils.actor.user.fines.summary",
1273 notes => <<" NOTES");
1274 Returns a short summary of the users total open fines, excluding voided fines
1275 Params are login_session, user_id
1276 Returns a 'mous' object.
1279 sub user_fines_summary {
1280 my( $self, $client, $login_session, $user_id ) = @_;
1282 my $user_obj = $apputils->check_user_session($login_session);
1283 if($user_obj->id ne $user_id) {
1284 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_FINES_SUMMARY")) {
1285 return OpenILS::Perm->new("VIEW_USER_FINES_SUMMARY");
1289 return $apputils->simple_scalar_request(
1291 "open-ils.storage.direct.money.open_user_summary.search.usr",
1299 __PACKAGE__->register_method(
1300 method => "user_transactions",
1301 api_name => "open-ils.actor.user.transactions",
1302 notes => <<" NOTES");
1303 Returns a list of open user transactions (mbts objects);
1304 Params are login_session, user_id
1305 Optional third parameter is the transactions type. defaults to all
1308 __PACKAGE__->register_method(
1309 method => "user_transactions",
1310 api_name => "open-ils.actor.user.transactions.have_charge",
1311 notes => <<" NOTES");
1312 Returns a list of all open user transactions (mbts objects) that have an initial charge
1313 Params are login_session, user_id
1314 Optional third parameter is the transactions type. defaults to all
1317 __PACKAGE__->register_method(
1318 method => "user_transactions",
1319 api_name => "open-ils.actor.user.transactions.have_balance",
1320 notes => <<" NOTES");
1321 Returns a list of all open user transactions (mbts objects) that have a balance
1322 Params are login_session, user_id
1323 Optional third parameter is the transactions type. defaults to all
1326 __PACKAGE__->register_method(
1327 method => "user_transactions",
1328 api_name => "open-ils.actor.user.transactions.fleshed",
1329 notes => <<" NOTES");
1330 Returns an object/hash of transaction, circ, title where transaction = an open
1331 user transactions (mbts objects), circ is the attached circluation, and title
1332 is the title the circ points to
1333 Params are login_session, user_id
1334 Optional third parameter is the transactions type. defaults to all
1337 __PACKAGE__->register_method(
1338 method => "user_transactions",
1339 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1340 notes => <<" NOTES");
1341 Returns an object/hash of transaction, circ, title where transaction = an open
1342 user transactions that has an initial charge (mbts objects), circ is the
1343 attached circluation, and title is the title the circ points to
1344 Params are login_session, user_id
1345 Optional third parameter is the transactions type. defaults to all
1348 __PACKAGE__->register_method(
1349 method => "user_transactions",
1350 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1351 notes => <<" NOTES");
1352 Returns an object/hash of transaction, circ, title where transaction = an open
1353 user transaction that has a balance (mbts objects), circ is the attached
1354 circluation, and title is the title the circ points to
1355 Params are login_session, user_id
1356 Optional third parameter is the transaction type. defaults to all
1359 __PACKAGE__->register_method(
1360 method => "user_transactions",
1361 api_name => "open-ils.actor.user.transactions.count",
1362 notes => <<" NOTES");
1363 Returns an object/hash of transaction, circ, title where transaction = an open
1364 user transactions (mbts objects), circ is the attached circluation, and title
1365 is the title the circ points to
1366 Params are login_session, user_id
1367 Optional third parameter is the transactions type. defaults to all
1370 __PACKAGE__->register_method(
1371 method => "user_transactions",
1372 api_name => "open-ils.actor.user.transactions.have_charge.count",
1373 notes => <<" NOTES");
1374 Returns an object/hash of transaction, circ, title where transaction = an open
1375 user transactions that has an initial charge (mbts objects), circ is the
1376 attached circluation, and title is the title the circ points to
1377 Params are login_session, user_id
1378 Optional third parameter is the transactions type. defaults to all
1381 __PACKAGE__->register_method(
1382 method => "user_transactions",
1383 api_name => "open-ils.actor.user.transactions.have_balance.count",
1384 notes => <<" NOTES");
1385 Returns an object/hash of transaction, circ, title where transaction = an open
1386 user transaction that has a balance (mbts objects), circ is the attached
1387 circluation, and title is the title the circ points to
1388 Params are login_session, user_id
1389 Optional third parameter is the transaction type. defaults to all
1392 __PACKAGE__->register_method(
1393 method => "user_transactions",
1394 api_name => "open-ils.actor.user.transactions.have_balance.total",
1395 notes => <<" NOTES");
1396 Returns an object/hash of transaction, circ, title where transaction = an open
1397 user transaction that has a balance (mbts objects), circ is the attached
1398 circluation, and title is the title the circ points to
1399 Params are login_session, user_id
1400 Optional third parameter is the transaction type. defaults to all
1405 sub user_transactions {
1406 my( $self, $client, $login_session, $user_id, $type ) = @_;
1408 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1409 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1410 return $evt if $evt;
1412 my $api = $self->api_name();
1416 if(defined($type)) { @xact = (xact_type => $type);
1418 } else { @xact = (); }
1420 if($api =~ /have_charge/o) {
1422 $trans = $apputils->simple_scalar_request(
1424 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1425 { usr => $user_id, total_owed => { ">" => 0 }, @xact });
1427 } elsif($api =~ /have_balance/o) {
1429 $trans = $apputils->simple_scalar_request(
1431 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1432 { usr => $user_id, balance_owed => { "<>" => 0 }, @xact });
1436 $trans = $apputils->simple_scalar_request(
1438 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1439 { usr => $user_id, @xact });
1442 if($api =~ /total/o) {
1444 for my $t (@$trans) {
1445 $total += $t->balance_owed;
1448 $logger->debug("Total balance owed by user $user_id: $total");
1452 if($api =~ /count/o) { return scalar @$trans; }
1453 if($api !~ /fleshed/o) { return $trans; }
1456 for my $t (@$trans) {
1458 if( $t->xact_type ne 'circulation' ) {
1459 push @resp, {transaction => $t};
1463 my $circ = $apputils->simple_scalar_request(
1465 "open-ils.storage.direct.action.circulation.retrieve",
1470 my $title = $apputils->simple_scalar_request(
1472 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1473 $circ->target_copy );
1477 my $u = OpenILS::Utils::ModsParser->new();
1478 $u->start_mods_batch($title->marc());
1479 my $mods = $u->finish_mods_batch();
1481 push @resp, {transaction => $t, circ => $circ, record => $mods };
1489 __PACKAGE__->register_method(
1490 method => "user_transaction_retrieve",
1491 api_name => "open-ils.actor.user.transaction.fleshed.retrieve",
1493 notes => <<" NOTES");
1494 Returns a fleshedtransaction record
1496 __PACKAGE__->register_method(
1497 method => "user_transaction_retrieve",
1498 api_name => "open-ils.actor.user.transaction.retrieve",
1500 notes => <<" NOTES");
1501 Returns a transaction record
1503 sub user_transaction_retrieve {
1504 my( $self, $client, $login_session, $bill_id ) = @_;
1506 my $trans = $apputils->simple_scalar_request(
1508 "open-ils.storage.direct.money.billable_transaction_summary.retrieve",
1512 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1513 $login_session, $trans->usr, 'VIEW_USER_TRANSACTIONS' );
1514 return $evt if $evt;
1516 my $api = $self->api_name();
1517 if($api !~ /fleshed/o) { return $trans; }
1519 if( $trans->xact_type ne 'circulation' ) {
1520 $logger->debug("Returning non-circ transaction");
1521 return {transaction => $trans};
1524 my $circ = $apputils->simple_scalar_request(
1526 "open-ils.storage.direct.action.circulation.retrieve",
1529 return {transaction => $trans} unless $circ;
1530 $logger->debug("Found the circ transaction");
1532 my $title = $apputils->simple_scalar_request(
1534 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1535 $circ->target_copy );
1537 return {transaction => $trans, circ => $circ } unless $title;
1538 $logger->debug("Found the circ title");
1542 my $u = OpenILS::Utils::ModsParser->new();
1543 $u->start_mods_batch($title->marc());
1544 $mods = $u->finish_mods_batch();
1546 if ($title->id == -1) {
1547 my $copy = $apputils->simple_scalar_request(
1549 "open-ils.storage.direct.asset.copy.retrieve",
1550 $circ->target_copy );
1552 $mods = new Fieldmapper::metabib::virtual_record;
1554 $mods->title($copy->dummy_title);
1555 $mods->author($copy->dummy_author);
1559 $logger->debug("MODSized the circ title");
1561 return {transaction => $trans, circ => $circ, record => $mods };
1565 __PACKAGE__->register_method(
1566 method => "hold_request_count",
1567 api_name => "open-ils.actor.user.hold_requests.count",
1569 notes => <<" NOTES");
1570 Returns hold ready/total counts
1572 sub hold_request_count {
1573 my( $self, $client, $login_session, $userid ) = @_;
1575 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1576 $login_session, $userid, 'VIEW_HOLD' );
1577 return $evt if $evt;
1580 my $holds = $apputils->simple_scalar_request(
1582 "open-ils.storage.direct.action.hold_request.search_where.atomic",
1584 fulfillment_time => {"=" => undef } }
1588 for my $h (@$holds) {
1589 next unless $h->capture_time;
1591 my $copy = $apputils->simple_scalar_request(
1593 "open-ils.storage.direct.asset.copy.retrieve",
1597 if ($copy->status == 8) {
1602 return { total => scalar(@$holds), ready => scalar(@ready) };
1606 __PACKAGE__->register_method(
1607 method => "checkedout_count",
1608 api_name => "open-ils.actor.user.checked_out.count__",
1610 notes => <<" NOTES");
1611 Returns a transaction record
1615 sub checkedout_count {
1616 my( $self, $client, $login_session, $userid ) = @_;
1618 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1619 $login_session, $userid, 'VIEW_CIRCULATIONS' );
1620 return $evt if $evt;
1622 my $circs = $apputils->simple_scalar_request(
1624 "open-ils.storage.direct.action.circulation.search_where.atomic",
1625 { usr => $userid, stop_fines => undef }
1626 #{ usr => $userid, checkin_time => {"=" => undef } }
1629 my $parser = DateTime::Format::ISO8601->new;
1632 for my $c (@$circs) {
1633 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1634 my $due = $due_dt->epoch;
1636 if ($due < DateTime->today->epoch) {
1641 return { total => scalar(@$circs), overdue => scalar(@overdue) };
1645 __PACKAGE__->register_method(
1646 method => "checked_out",
1647 api_name => "open-ils.actor.user.checked_out",
1650 Returns a structure of circulations objects sorted by
1651 out, overdue, lost, claims_returned, long_overdue.
1652 A list of IDs are returned of each type.
1653 lost, long_overdue, and claims_returned circ will not
1654 be "finished" (there is an outstanding balance or some
1655 other pending action on the circ).
1657 The .count method also includes a 'total' field which
1658 sums all "open" circs
1662 __PACKAGE__->register_method(
1663 method => "checked_out",
1664 api_name => "open-ils.actor.user.checked_out.count",
1666 signature => q/@see open-ils.actor.user.checked_out/
1670 my( $self, $conn, $auth, $userid ) = @_;
1672 my $e = new_editor(authtoken=>$auth);
1673 return $e->event unless $e->checkauth;
1675 if( $userid ne $e->requestor->id ) {
1676 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
1679 return _checked_out( $self->api_name =~ /count/, $e, $userid );
1683 my( $iscount, $e, $userid ) = @_;
1685 my $circs = $e->search_action_circulation(
1686 { usr => $userid, stop_fines => undef });
1688 my $parser = DateTime::Format::ISO8601->new;
1690 # split the circs up into overdue and not-overdue circs
1692 for my $c (@$circs) {
1693 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1694 my $due = $due_dt->epoch;
1695 if ($due < DateTime->today->epoch) {
1696 push @overdue, $c->id;
1702 # grab all of the lost, claims-returned, and longoverdue circs
1703 my $open = $e->search_action_circulation(
1704 {usr => $userid, stop_fines => { '!=' => undef }, xact_finish => undef });
1706 my( @lost, @cr, @lo );
1707 for my $c (@$open) {
1708 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1709 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1710 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
1716 total => @$circs + @lost + @cr + @lo,
1717 out => scalar(@out),
1718 overdue => scalar(@overdue),
1719 lost => scalar(@lost),
1720 claims_returned => scalar(@cr),
1721 long_overdue => scalar(@lo)
1727 overdue => \@overdue,
1729 claims_returned => \@cr,
1730 long_overdue => \@lo
1742 __PACKAGE__->register_method(
1743 method => "user_transaction_history",
1744 api_name => "open-ils.actor.user.transactions.history",
1746 notes => <<" NOTES");
1747 Returns a list of billable transaction ids for a user, optionally by type
1749 __PACKAGE__->register_method(
1750 method => "user_transaction_history",
1751 api_name => "open-ils.actor.user.transactions.history.have_charge",
1753 notes => <<" NOTES");
1754 Returns a list of billable transaction ids for a user that have an initial charge, optionally by type
1756 sub user_transaction_history {
1757 my( $self, $client, $login_session, $user_id, $type ) = @_;
1759 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1760 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1761 return $evt if $evt;
1763 my $api = $self->api_name();
1767 @xact = (xact_type => $type) if(defined($type));
1768 @charge = (total_owed => { ">" => 0}) if($api =~ /have_charge/);
1770 my $trans = $apputils->simple_scalar_request(
1772 "open-ils.storage.direct.money.billable_transaction_summary.search_where.atomic",
1773 { usr => $user_id, @xact, @charge }, { order_by => 'xact_start DESC' });
1775 return [ map { $_->id } @$trans ];
1779 __PACKAGE__->register_method(
1780 method => "user_perms",
1781 api_name => "open-ils.actor.permissions.user_perms.retrieve",
1783 notes => <<" NOTES");
1784 Returns a list of permissions
1787 my( $self, $client, $authtoken, $user ) = @_;
1789 my( $staff, $evt ) = $apputils->checkses($authtoken);
1790 return $evt if $evt;
1792 $user ||= $staff->id;
1794 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
1798 return $apputils->simple_scalar_request(
1800 "open-ils.storage.permission.user_perms.atomic",
1804 __PACKAGE__->register_method(
1805 method => "retrieve_perms",
1806 api_name => "open-ils.actor.permissions.retrieve",
1807 notes => <<" NOTES");
1808 Returns a list of permissions
1810 sub retrieve_perms {
1811 my( $self, $client ) = @_;
1812 return $apputils->simple_scalar_request(
1814 "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
1817 __PACKAGE__->register_method(
1818 method => "retrieve_groups",
1819 api_name => "open-ils.actor.groups.retrieve",
1820 notes => <<" NOTES");
1821 Returns a list of user groupss
1823 sub retrieve_groups {
1824 my( $self, $client ) = @_;
1825 return $apputils->simple_scalar_request(
1827 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1830 __PACKAGE__->register_method(
1831 method => "retrieve_org_address",
1832 api_name => "open-ils.actor.org_unit.address.retrieve",
1833 notes => <<' NOTES');
1834 Returns an org_unit address by ID
1835 @param An org_address ID
1837 sub retrieve_org_address {
1838 my( $self, $client, $id ) = @_;
1839 return $apputils->simple_scalar_request(
1841 "open-ils.storage.direct.actor.org_address.retrieve",
1846 __PACKAGE__->register_method(
1847 method => "retrieve_groups_tree",
1848 api_name => "open-ils.actor.groups.tree.retrieve",
1849 notes => <<" NOTES");
1850 Returns a list of user groups
1852 sub retrieve_groups_tree {
1853 my( $self, $client ) = @_;
1854 my $groups = $apputils->simple_scalar_request(
1856 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1857 return $self->build_group_tree($groups);
1861 # turns an org list into an org tree
1862 sub build_group_tree {
1864 my( $self, $grplist) = @_;
1866 return $grplist unless (
1867 ref($grplist) and @$grplist > 1 );
1869 my @list = sort { $a->name cmp $b->name } @$grplist;
1872 for my $grp (@list) {
1874 if ($grp and !defined($grp->parent)) {
1878 my ($parent) = grep { $_->id == $grp->parent} @list;
1880 $parent->children([]) unless defined($parent->children);
1881 push( @{$parent->children}, $grp );
1889 __PACKAGE__->register_method(
1890 method => "add_user_to_groups",
1891 api_name => "open-ils.actor.user.set_groups",
1892 notes => <<" NOTES");
1893 Adds a user to one or more permission groups
1896 sub add_user_to_groups {
1897 my( $self, $client, $authtoken, $userid, $groups ) = @_;
1899 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1900 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
1901 return $evt if $evt;
1903 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1904 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
1905 return $evt if $evt;
1907 $apputils->simplereq(
1909 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
1911 for my $group (@$groups) {
1912 my $link = Fieldmapper::permission::usr_grp_map->new;
1914 $link->usr($userid);
1916 my $id = $apputils->simplereq(
1918 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
1924 __PACKAGE__->register_method(
1925 method => "get_user_perm_groups",
1926 api_name => "open-ils.actor.user.get_groups",
1927 notes => <<" NOTES");
1928 Retrieve a user's permission groups.
1932 sub get_user_perm_groups {
1933 my( $self, $client, $authtoken, $userid ) = @_;
1935 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1936 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
1937 return $evt if $evt;
1939 return $apputils->simplereq(
1941 'open-ils.storage.direct.permission.usr_grp_map.search.usr.atomic', $userid );
1946 __PACKAGE__->register_method (
1947 method => 'register_workstation',
1948 api_name => 'open-ils.actor.workstation.register.override',
1949 signature => q/@see open-ils.actor.workstation.register/);
1951 __PACKAGE__->register_method (
1952 method => 'register_workstation',
1953 api_name => 'open-ils.actor.workstation.register',
1955 Registers a new workstion in the system
1956 @param authtoken The login session key
1957 @param name The name of the workstation id
1958 @param owner The org unit that owns this workstation
1959 @return The workstation id on success, WORKSTATION_NAME_EXISTS
1960 if the name is already in use.
1963 sub _register_workstation {
1964 my( $self, $connection, $authtoken, $name, $owner ) = @_;
1965 my( $requestor, $evt ) = $U->checkses($authtoken);
1966 return $evt if $evt;
1967 $evt = $U->check_perms($requestor->id, $owner, 'REGISTER_WORKSTATION');
1968 return $evt if $evt;
1970 my $ws = $U->storagereq(
1971 'open-ils.storage.direct.actor.workstation.search.name', $name );
1972 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS') if $ws;
1974 $ws = Fieldmapper::actor::workstation->new;
1975 $ws->owning_lib($owner);
1978 my $id = $U->storagereq(
1979 'open-ils.storage.direct.actor.workstation.create', $ws );
1980 return $U->DB_UPDATE_FAILED($ws) unless $id;
1986 sub register_workstation {
1987 my( $self, $conn, $authtoken, $name, $owner ) = @_;
1989 my $e = OpenILS::Utils::Editor->new(authtoken=>$authtoken, xact=>1);
1990 return $e->event unless $e->checkauth;
1991 return $e->event unless $e->allowed('REGISTER_WORKSTATION'); # XXX rely on editor perms
1992 my $existing = $e->search_actor_workstation({name => $name});
1995 if( $self->api_name =~ /override/o ) {
1996 return $e->event unless $e->allowed('DELETE_WORKSTATION'); # XXX rely on editor perms
1997 return $e->event unless $e->delete_actor_workstation($$existing[0]);
1999 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS')
2003 my $ws = Fieldmapper::actor::workstation->new;
2004 $ws->owning_lib($owner);
2006 $e->create_actor_workstation($ws) or return $e->event;
2008 return $ws->id; # note: editor sets the id on the new object for us
2012 __PACKAGE__->register_method (
2013 method => 'fetch_patron_note',
2014 api_name => 'open-ils.actor.note.retrieve.all',
2016 Returns a list of notes for a given user
2017 Requestor must have VIEW_USER permission if pub==false and
2018 @param authtoken The login session key
2019 @param args Hash of params including
2020 patronid : the patron's id
2021 pub : true if retrieving only public notes
2025 sub fetch_patron_note {
2026 my( $self, $conn, $authtoken, $args ) = @_;
2027 my $patronid = $$args{patronid};
2029 my($reqr, $evt) = $U->checkses($authtoken);
2032 ($patron, $evt) = $U->fetch_user($patronid);
2033 return $evt if $evt;
2036 if( $patronid ne $reqr->id ) {
2037 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2038 return $evt if $evt;
2040 return $U->storagereq(
2041 'open-ils.storage.direct.actor.usr_note.search_where.atomic',
2042 { usr => $patronid, pub => 't' } );
2045 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2046 return $evt if $evt;
2048 return $U->storagereq(
2049 'open-ils.storage.direct.actor.usr_note.search.usr.atomic', $patronid );
2052 __PACKAGE__->register_method (
2053 method => 'create_user_note',
2054 api_name => 'open-ils.actor.note.create',
2056 Creates a new note for the given user
2057 @param authtoken The login session key
2058 @param note The note object
2061 sub create_user_note {
2062 my( $self, $conn, $authtoken, $note ) = @_;
2063 my( $reqr, $patron, $evt ) =
2064 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
2065 return $evt if $evt;
2066 $logger->activity("user ".$reqr->id." creating note for user ".$note->usr);
2068 $note->pub('f') unless $note->pub;
2069 $note->creator($reqr->id);
2070 my $id = $U->storagereq(
2071 'open-ils.storage.direct.actor.usr_note.create', $note );
2072 return $U->DB_UPDATE_FAILED($note) unless $id;
2077 __PACKAGE__->register_method (
2078 method => 'delete_user_note',
2079 api_name => 'open-ils.actor.note.delete',
2081 Deletes a note for the given user
2082 @param authtoken The login session key
2083 @param noteid The note id
2086 sub delete_user_note {
2087 my( $self, $conn, $authtoken, $noteid ) = @_;
2089 my $note = $U->storagereq(
2090 'open-ils.storage.direct.actor.usr_note.retrieve', $noteid);
2091 return OpenILS::Event->new('ACTOR_USER_NOTE_NOT_FOUND') unless $note;
2093 my( $reqr, $patron, $evt ) =
2094 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
2095 return $evt if $evt;
2096 $logger->activity("user ".$reqr->id." deleting note [$noteid] for user ".$note->usr);
2098 my $stat = $U->storagereq(
2099 'open-ils.storage.direct.actor.usr_note.delete', $noteid );
2100 return $U->DB_UPDATE_FAILED($note) unless defined $stat;
2106 __PACKAGE__->register_method (
2107 method => 'create_closed_date',
2108 api_name => 'open-ils.actor.org_unit.closed_date.create',
2110 Creates a new closing entry for the given org_unit
2111 @param authtoken The login session key
2112 @param note The closed_date object
2115 sub create_closed_date {
2116 my( $self, $conn, $authtoken, $cd ) = @_;
2118 my( $user, $evt ) = $U->checkses($authtoken);
2119 return $evt if $evt;
2121 $evt = $U->check_perms($user->id, $cd->org_unit, 'CREATE_CLOSEING');
2122 return $evt if $evt;
2124 $logger->activity("user ".$user->id." creating library closing for ".$cd->org_unit);
2126 my $id = $U->storagereq(
2127 'open-ils.storage.direct.actor.org_unit.closed_date.create', $cd );
2128 return $U->DB_UPDATE_FAILED($cd) unless $id;
2133 __PACKAGE__->register_method (
2134 method => 'delete_closed_date',
2135 api_name => 'open-ils.actor.org_unit.closed_date.delete',
2137 Deletes a closing entry for the given org_unit
2138 @param authtoken The login session key
2139 @param noteid The close_date id
2142 sub delete_closed_date {
2143 my( $self, $conn, $authtoken, $cd ) = @_;
2145 my( $user, $evt ) = $U->checkses($authtoken);
2146 return $evt if $evt;
2149 ($cd_obj, $evt) = fetch_closed_date($cd);
2150 return $evt if $evt;
2152 $evt = $U->check_perms($user->id, $cd->org_unit, 'DELETE_CLOSEING');
2153 return $evt if $evt;
2155 $logger->activity("user ".$user->id." deleting library closing for ".$cd->org_unit);
2157 my $stat = $U->storagereq(
2158 'open-ils.storage.direct.actor.org_unit.closed_date.delete', $cd );
2159 return $U->DB_UPDATE_FAILED($cd) unless $stat;
2164 __PACKAGE__->register_method(
2165 method => 'usrname_exists',
2166 api_name => 'open-ils.actor.username.exists',
2168 Returns 1 if the requested username exists, returns 0 otherwise
2172 sub usrname_exists {
2173 my( $self, $conn, $auth, $usrname ) = @_;
2174 my $e = new_editor(authtoken=>$auth);
2175 return $e->event unless $e->checkauth;
2176 my $a = $e->search_actor_user({usrname => $usrname}, {idlist=>1});
2177 return $$a[0] if $a and @$a;
2181 __PACKAGE__->register_method(
2182 method => 'barcode_exists',
2183 api_name => 'open-ils.actor.barcode.exists',
2185 Returns 1 if the requested barcode exists, returns 0 otherwise
2189 sub barcode_exists {
2190 my( $self, $conn, $auth, $barcode ) = @_;
2191 my $e = new_editor(authtoken=>$auth);
2192 return $e->event unless $e->checkauth;
2193 my $a = $e->search_actor_card({barcode => $barcode}, {idlist=>1});
2194 return $$a[0] if $a and @$a;
2199 __PACKAGE__->register_method(
2200 method => 'retrieve_net_levels',
2201 api_name => 'open-ils.actor.net_access_level.retrieve.all',
2204 sub retrieve_net_levels {
2205 my( $self, $conn, $auth ) = @_;
2206 my $e = new_editor(authtoken=>$auth);
2207 return $e->event unless $e->checkauth;
2208 return $e->retrieve_all_config_net_access_level();