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;
28 use OpenILS::Utils::Editor qw/:funcs/;
30 use OpenILS::Application::Actor::UserGroups;
32 OpenILS::Application::Actor::Container->initialize();
33 OpenILS::Application::Actor::UserGroups->initialize();
36 my $apputils = "OpenILS::Application::AppUtils";
39 sub _d { warn "Patron:\n" . Dumper(shift()); }
44 my $set_user_settings;
47 __PACKAGE__->register_method(
48 method => "set_user_settings",
49 api_name => "open-ils.actor.patron.settings.update",
51 sub set_user_settings {
52 my( $self, $client, $user_session, $uid, $settings ) = @_;
54 $logger->debug("Setting user settings: $user_session, $uid, " . Dumper($settings));
56 my( $staff, $user, $evt ) =
57 $apputils->checkses_requestor( $user_session, $uid, 'UPDATE_USER' );
62 # [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
65 [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
67 $logger->activity("User " . $staff->id . " updating user $uid settings with: " . Dumper(\@params));
69 return $apputils->simplereq(
71 'open-ils.storage.direct.actor.user_setting.batch.merge', @params );
77 __PACKAGE__->register_method(
78 method => "set_ou_settings",
79 api_name => "open-ils.actor.org_unit.settings.update",
82 my( $self, $client, $user_session, $ouid, $settings ) = @_;
84 my( $staff, $evt ) = $apputils->checkses( $user_session );
86 $evt = $apputils->check_perms( $staff->id, $ouid, 'UPDATE_ORG_UNIT' );
91 map { [{ org_unit => $ouid, name => $_}, {value => $$settings{$_}}] } keys %$settings;
93 $logger->activity("Updating org unit [$ouid] settings with: " . Dumper($params));
95 return $apputils->simplereq(
97 'open-ils.storage.direct.actor.org_unit_setting.merge', @$params );
101 my $fetch_user_settings;
102 my $fetch_ou_settings;
104 __PACKAGE__->register_method(
105 method => "user_settings",
106 api_name => "open-ils.actor.patron.settings.retrieve",
109 my( $self, $client, $user_session, $uid ) = @_;
111 my( $staff, $user, $evt ) =
112 $apputils->checkses_requestor( $user_session, $uid, 'VIEW_USER' );
115 $logger->debug("User " . $staff->id . " fetching user $uid\n");
116 my $s = $apputils->simplereq(
118 'open-ils.storage.direct.actor.user_setting.search.usr.atomic',$uid );
120 return { map { ($_->name,$_->value) } @$s };
125 __PACKAGE__->register_method(
126 method => "ou_settings",
127 api_name => "open-ils.actor.org_unit.settings.retrieve",
130 my( $self, $client, $ouid ) = @_;
132 $logger->info("Fetching org unit settings for org $ouid");
134 my $s = $apputils->simplereq(
136 'open-ils.storage.direct.actor.org_unit_setting.search.org_unit.atomic', $ouid);
138 return { map { ($_->name,$_->value) } @$s };
141 __PACKAGE__->register_method (
142 method => "ou_setting_delete",
143 api_name => 'open-ils.actor.org_setting.delete',
145 Deletes a specific org unit setting for a specific location
146 @param authtoken The login session key
147 @param orgid The org unit whose setting we're changing
148 @param setting The name of the setting to delete
149 @return True value on success.
153 sub ou_setting_delete {
154 my( $self, $conn, $authtoken, $orgid, $setting ) = @_;
155 my( $reqr, $evt) = $U->checkses($authtoken);
157 $evt = $U->check_perms($reqr->id, $orgid, 'UPDATE_ORG_SETTING');
160 my $id = $U->storagereq(
161 'open-ils.storage.id_list.actor.org_unit_setting.search_where',
162 { name => $setting, org_unit => $orgid } );
164 $logger->debug("Retrieved setting $id in org unit setting delete");
166 my $s = $U->storagereq(
167 'open-ils.storage.direct.actor.org_unit_setting.delete', $id );
169 $logger->activity("User ".$reqr->id." deleted org unit setting $id") if $s;
175 __PACKAGE__->register_method(
176 method => "update_patron",
177 api_name => "open-ils.actor.patron.update",);
180 my( $self, $client, $user_session, $patron ) = @_;
182 my $session = $apputils->start_db_session();
185 $logger->info("Creating new patron...") if $patron->isnew;
186 $logger->info("Updating Patron: " . $patron->id) unless $patron->isnew;
188 my( $user_obj, $evt ) = $U->checkses($user_session);
191 # XXX does this user have permission to add/create users. Granularity?
192 # $new_patron is the patron in progress. $patron is the original patron
193 # passed in with the method. new_patron will change as the components
194 # of patron are added/updated.
198 # unflesh the real items on the patron
199 $patron->card( $patron->card->id ) if(ref($patron->card));
200 $patron->billing_address( $patron->billing_address->id )
201 if(ref($patron->billing_address));
202 $patron->mailing_address( $patron->mailing_address->id )
203 if(ref($patron->mailing_address));
205 # create/update the patron first so we can use his id
206 if($patron->isnew()) {
207 ( $new_patron, $evt ) = _add_patron($session, _clone_patron($patron), $user_obj);
209 } else { $new_patron = $patron; }
211 ( $new_patron, $evt ) = _add_update_addresses($session, $patron, $new_patron, $user_obj);
214 ( $new_patron, $evt ) = _add_update_cards($session, $patron, $new_patron, $user_obj);
217 ( $new_patron, $evt ) = _add_survey_responses($session, $patron, $new_patron, $user_obj);
220 # re-update the patron if anything has happened to him during this process
221 if($new_patron->ischanged()) {
222 ( $new_patron, $evt ) = _update_patron($session, $new_patron, $user_obj);
226 #$session = OpenSRF::AppSession->create("open-ils.storage"); # why did i put this here?
228 ($new_patron, $evt) = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
231 ($new_patron, $evt) = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
234 ($new_patron, $evt) = _create_standing_penalties($session, $user_session, $patron, $new_patron, $user_obj);
237 $logger->activity("user ".$user_obj->id." updating/creating user ".$new_patron->id);
238 $apputils->commit_db_session($session);
240 #warn "Patron Update/Create complete\n";
241 return flesh_user($new_patron->id());
247 __PACKAGE__->register_method(
248 method => "user_retrieve_fleshed_by_id",
249 api_name => "open-ils.actor.user.fleshed.retrieve",);
251 sub user_retrieve_fleshed_by_id {
252 my( $self, $client, $user_session, $user_id ) = @_;
254 my( $requestor, $target, $evt ) = $apputils->
255 checkses_requestor( $user_session, $user_id, 'VIEW_USER' );
258 return flesh_user($user_id);
262 # fleshes: card, cards, address, addresses, stat_cat_entries, standing_penalties
270 $session = OpenSRF::AppSession->create("open-ils.storage");
274 # grab the user with the given id
275 my $ureq = $session->request(
276 "open-ils.storage.direct.actor.user.retrieve", $id);
277 my $user = $ureq->gather(1);
279 if(!$user) { return undef; }
282 my $cards_req = $session->request(
283 "open-ils.storage.direct.actor.card.search.usr.atomic",
285 $user->cards( $cards_req->gather(1) );
287 for my $c(@{$user->cards}) {
288 if($c->id == $user->card || $c->id eq $user->card ) {
289 #warn "Setting my card to " . $c->id . "\n";
294 my $add_req = $session->request(
295 "open-ils.storage.direct.actor.user_address.search.usr.atomic",
297 $user->addresses( $add_req->gather(1) );
299 if( @{$user->addresses} ) {
300 if( ! grep { $_->id eq $user->billing_address } @{$user->addresses} ) {
301 my $ba = $session->request(
302 'open-ils.storage.direct.actor.user_address.retrieve',
303 $user->billing_address)->gather(1);
304 push( @{$user->addresses}, $ba );
307 if( ! grep { $_->id eq $user->mailing_address } @{$user->addresses} ) {
308 my $ba = $session->request(
309 'open-ils.storage.direct.actor.user_address.retrieve',
310 $user->mailing_address)->gather(1);
311 push( @{$user->addresses}, $ba );
316 for my $c(@{$user->addresses}) {
317 if($c->id eq $user->billing_address ) { $user->billing_address($c); }
318 if($c->id eq $user->mailing_address ) { $user->mailing_address($c); }
321 my $stat_req = $session->request(
322 "open-ils.storage.direct.actor.stat_cat_entry_user_map.search.target_usr.atomic",
324 $user->stat_cat_entries($stat_req->gather(1));
326 my $standing_penalties_req = $session->request(
327 "open-ils.storage.direct.actor.user_standing_penalty.search.usr.atomic",
329 $user->standing_penalties($standing_penalties_req->gather(1));
331 if($kill) { $session->disconnect(); }
332 $user->clear_passwd();
338 # clone and clear stuff that would break the database
342 my $new_patron = $patron->clone;
344 # Using the Fieldmapper clone method
345 #my $new_patron = Fieldmapper::actor::user->new();
347 #my $fmap = $Fieldmapper::fieldmap;
348 #no strict; # shallow clone, may be useful in the fieldmapper
350 # (keys %{$fmap->{"Fieldmapper::actor::user"}->{'fields'}}) {
351 # $new_patron->$field( $patron->$field() );
356 $new_patron->clear_billing_address();
357 $new_patron->clear_mailing_address();
358 $new_patron->clear_addresses();
359 $new_patron->clear_card();
360 $new_patron->clear_cards();
361 $new_patron->clear_id();
362 $new_patron->clear_isnew();
363 $new_patron->clear_ischanged();
364 $new_patron->clear_isdeleted();
365 $new_patron->clear_stat_cat_entries();
366 $new_patron->clear_permissions();
367 $new_patron->clear_standing_penalties();
377 my $user_obj = shift;
379 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'CREATE_USER');
380 return (undef, $evt) if $evt;
382 my $ex = $session->request(
383 'open-ils.storage.direct.actor.user.search.usrname', $patron->usrname())->gather(1);
385 return (undef, OpenILS::Event->new('USERNAME_EXISTS'));
388 $logger->info("Creating new user in the DB with username: ".$patron->usrname());
390 my $id = $session->request(
391 "open-ils.storage.direct.actor.user.create", $patron)->gather(1);
392 return (undef, $U->DB_UPDATE_FAILED($patron)) unless $id;
394 $logger->info("Successfully created new user [$id] in DB");
396 return ( $session->request(
397 "open-ils.storage.direct.actor.user.retrieve", $id)->gather(1), undef );
402 my( $session, $patron, $user_obj, $noperm) = @_;
404 $logger->info("Updating patron ".$patron->id." in DB");
407 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'UPDATE_USER');
408 return (undef, $evt) if $evt;
411 # update the password by itself to avoid the password protection magic
412 if( $patron->passwd ) {
413 my $s = $session->request(
414 'open-ils.storage.direct.actor.user.remote_update',
415 {id => $patron->id}, {passwd => $patron->passwd})->gather(1);
416 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($s);
417 $patron->clear_passwd;
420 if(!$patron->ident_type) {
421 $patron->clear_ident_type;
422 $patron->clear_ident_value;
425 if(!$patron->ident_type2) {
426 $patron->clear_ident_type2;
427 $patron->clear_ident_value2;
430 my $stat = $session->request(
431 "open-ils.storage.direct.actor.user.update",$patron )->gather(1);
432 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($stat);
438 sub _add_update_addresses {
442 my $new_patron = shift;
446 my $current_id; # id of the address before creation
448 for my $address (@{$patron->addresses()}) {
450 next unless ref $address;
451 $current_id = $address->id();
453 if( $patron->billing_address() and
454 $patron->billing_address() == $current_id ) {
455 $logger->info("setting billing addr to $current_id");
456 $new_patron->billing_address($address->id());
457 $new_patron->ischanged(1);
460 if( $patron->mailing_address() and
461 $patron->mailing_address() == $current_id ) {
462 $new_patron->mailing_address($address->id());
463 $logger->info("setting mailing addr to $current_id");
464 $new_patron->ischanged(1);
468 if($address->isnew()) {
470 $address->usr($new_patron->id());
472 ($address, $evt) = _add_address($session,$address);
473 return (undef, $evt) if $evt;
475 # we need to get the new id
476 if( $patron->billing_address() and
477 $patron->billing_address() == $current_id ) {
478 $new_patron->billing_address($address->id());
479 $logger->info("setting billing addr to $current_id");
480 $new_patron->ischanged(1);
483 if( $patron->mailing_address() and
484 $patron->mailing_address() == $current_id ) {
485 $new_patron->mailing_address($address->id());
486 $logger->info("setting mailing addr to $current_id");
487 $new_patron->ischanged(1);
490 } elsif($address->ischanged() ) {
492 ($address, $evt) = _update_address($session, $address);
493 return (undef, $evt) if $evt;
495 } elsif($address->isdeleted() ) {
497 if( $address->id() == $new_patron->mailing_address() ) {
498 $new_patron->clear_mailing_address();
499 ($new_patron, $evt) = _update_patron($session, $new_patron);
500 return (undef, $evt) if $evt;
503 if( $address->id() == $new_patron->billing_address() ) {
504 $new_patron->clear_billing_address();
505 ($new_patron, $evt) = _update_patron($session, $new_patron);
506 return (undef, $evt) if $evt;
509 $evt = _delete_address($session, $address);
510 return (undef, $evt) if $evt;
514 return ( $new_patron, undef );
518 # adds an address to the db and returns the address with new id
520 my($session, $address) = @_;
521 $address->clear_id();
523 $logger->info("Creating new address at street ".$address->street1);
525 # put the address into the database
526 my $id = $session->request(
527 "open-ils.storage.direct.actor.user_address.create", $address )->gather(1);
528 return (undef, $U->DB_UPDATE_FAILED($address)) unless $id;
531 return ($address, undef);
535 sub _update_address {
536 my( $session, $address ) = @_;
538 $logger->info("Updating address ".$address->id." in the DB");
540 my $stat = $session->request(
541 "open-ils.storage.direct.actor.user_address.update", $address )->gather(1);
543 return (undef, $U->DB_UPDATE_FAILED($address)) unless defined($stat);
544 return ($address, undef);
549 sub _add_update_cards {
553 my $new_patron = shift;
557 my $virtual_id; #id of the card before creation
558 for my $card (@{$patron->cards()}) {
560 $card->usr($new_patron->id());
562 if(ref($card) and $card->isnew()) {
564 $virtual_id = $card->id();
565 ( $card, $evt ) = _add_card($session,$card);
566 return (undef, $evt) if $evt;
568 #if(ref($patron->card)) { $patron->card($patron->card->id); }
569 if($patron->card() == $virtual_id) {
570 $new_patron->card($card->id());
571 $new_patron->ischanged(1);
574 } elsif( ref($card) and $card->ischanged() ) {
575 $evt = _update_card($session, $card);
576 return (undef, $evt) if $evt;
580 return ( $new_patron, undef );
584 # adds an card to the db and returns the card with new id
586 my( $session, $card ) = @_;
589 $logger->info("Adding new patron card ".$card->barcode);
591 my $id = $session->request(
592 "open-ils.storage.direct.actor.card.create", $card )->gather(1);
593 return (undef, $U->DB_UPDATE_FAILED($card)) unless $id;
594 $logger->info("Successfully created patron card $id");
597 return ( $card, undef );
601 # returns event on error. returns undef otherwise
603 my( $session, $card ) = @_;
604 $logger->info("Updating patron card ".$card->id);
606 my $stat = $session->request(
607 "open-ils.storage.direct.actor.card.update", $card )->gather(1);
608 return $U->DB_UPDATE_FAILED($card) unless defined($stat);
615 # returns event on error. returns undef otherwise
616 sub _delete_address {
617 my( $session, $address ) = @_;
619 $logger->info("Deleting address ".$address->id." from DB");
621 my $stat = $session->request(
622 "open-ils.storage.direct.actor.user_address.delete", $address )->gather(1);
624 return $U->DB_UPDATE_FAILED($address) unless defined($stat);
630 sub _add_survey_responses {
631 my ($session, $patron, $new_patron) = @_;
633 $logger->info( "Updating survey responses for patron ".$new_patron->id );
635 my $responses = $patron->survey_responses;
639 $_->usr($new_patron->id) for (@$responses);
641 my $evt = $U->simplereq( "open-ils.circ",
642 "open-ils.circ.survey.submit.user_id", $responses );
644 return (undef, $evt) if defined($U->event_code($evt));
648 return ( $new_patron, undef );
652 sub _create_stat_maps {
654 my($session, $user_session, $patron, $new_patron) = @_;
656 my $maps = $patron->stat_cat_entries();
658 for my $map (@$maps) {
660 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
662 if ($map->isdeleted()) {
663 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.delete";
665 } elsif ($map->isnew()) {
666 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
671 $map->target_usr($new_patron->id);
674 $logger->info("Updating stat entry with method $method and map $map");
676 my $stat = $session->request($method, $map)->gather(1);
677 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
681 return ($new_patron, undef);
684 sub _create_perm_maps {
686 my($session, $user_session, $patron, $new_patron) = @_;
688 my $maps = $patron->permissions;
690 for my $map (@$maps) {
692 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
693 if ($map->isdeleted()) {
694 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
695 } elsif ($map->isnew()) {
696 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
701 $map->usr($new_patron->id);
703 #warn( "Updating permissions with method $method and session $user_session and map $map" );
704 $logger->info( "Updating permissions with method $method and map $map" );
706 my $stat = $session->request($method, $map)->gather(1);
707 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
711 return ($new_patron, undef);
715 sub _create_standing_penalties {
717 my($session, $user_session, $patron, $new_patron) = @_;
719 my $maps = $patron->standing_penalties;
722 for my $map (@$maps) {
724 if ($map->isdeleted()) {
725 $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
726 } elsif ($map->isnew()) {
727 $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
733 $map->usr($new_patron->id);
735 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
737 my $stat = $session->request($method, $map)->gather(1);
738 return (undef, $U->DB_UPDATE_FAILED($map)) unless $stat;
741 return ($new_patron, undef);
746 __PACKAGE__->register_method(
747 method => "search_username",
748 api_name => "open-ils.actor.user.search.username",
751 sub search_username {
752 my($self, $client, $username) = @_;
753 my $users = OpenILS::Application::AppUtils->simple_scalar_request(
755 "open-ils.storage.direct.actor.user.search.usrname.atomic",
763 __PACKAGE__->register_method(
764 method => "user_retrieve_by_barcode",
765 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
767 sub user_retrieve_by_barcode {
768 my($self, $client, $user_session, $barcode) = @_;
770 $logger->debug("Searching for user with barcode $barcode");
771 my ($user_obj, $evt) = $apputils->checkses($user_session);
775 my $session = OpenSRF::AppSession->create("open-ils.storage");
777 # find the card with the given barcode
778 my $creq = $session->request(
779 "open-ils.storage.direct.actor.card.search.barcode.atomic",
781 my $card = $creq->gather(1);
783 if(!$card || !$card->[0]) {
784 $session->disconnect();
785 return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' );
789 my $user = flesh_user($card->usr(), $session);
791 $evt = $U->check_perms($user_obj->id, $user->home_ou, 'VIEW_USER');
794 $session->disconnect();
795 if(!$user) { return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' ); }
802 __PACKAGE__->register_method(
803 method => "get_user_by_id",
804 api_name => "open-ils.actor.user.retrieve",);
807 my ($self, $client, $user_session, $id) = @_;
809 my $user_obj = $apputils->check_user_session( $user_session );
811 return $apputils->simple_scalar_request(
813 "open-ils.storage.direct.actor.user.retrieve",
819 __PACKAGE__->register_method(
820 method => "get_org_types",
821 api_name => "open-ils.actor.org_types.retrieve",);
825 my($self, $client) = @_;
827 return $org_types if $org_types;
829 $apputils->simple_scalar_request(
831 "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
836 __PACKAGE__->register_method(
837 method => "get_user_profiles",
838 api_name => "open-ils.actor.user.profiles.retrieve",
842 sub get_user_profiles {
843 return $user_profiles if $user_profiles;
845 return $user_profiles =
846 $apputils->simple_scalar_request(
848 "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
853 __PACKAGE__->register_method(
854 method => "get_user_ident_types",
855 api_name => "open-ils.actor.user.ident_types.retrieve",
858 sub get_user_ident_types {
859 return $ident_types if $ident_types;
860 return $ident_types =
861 $apputils->simple_scalar_request(
863 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
869 __PACKAGE__->register_method(
870 method => "get_org_unit",
871 api_name => "open-ils.actor.org_unit.retrieve",
876 my( $self, $client, $user_session, $org_id ) = @_;
878 if(defined($user_session) && !defined($org_id)) {
880 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
881 if(!defined($org_id)) {
882 $org_id = $user_obj->home_ou;
887 my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
889 "open-ils.storage.direct.actor.org_unit.retrieve",
895 __PACKAGE__->register_method(
896 method => "search_org_unit",
897 api_name => "open-ils.actor.org_unit_list.search",
900 sub search_org_unit {
902 my( $self, $client, $field, $value ) = @_;
904 my $list = OpenILS::Application::AppUtils->simple_scalar_request(
906 "open-ils.storage.direct.actor.org_unit.search.$field.atomic",
915 __PACKAGE__->register_method(
916 method => "get_org_tree",
917 api_name => "open-ils.actor.org_tree.retrieve",
919 note => "Returns the entire org tree structure",
923 my( $self, $client) = @_;
926 $cache_client = OpenSRF::Utils::Cache->new("global", 0);
928 # see if it's in the cache
929 #warn "Getting ORG Tree\n";
930 my $tree = $cache_client->get_cache('orgtree');
932 #warn "Found orgtree in cache. returning...\n";
936 my $orglist = $apputils->simple_scalar_request(
938 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
941 #warn "found org list\n";
944 $tree = $self->build_org_tree($orglist);
945 $cache_client->put_cache('orgtree', $tree);
951 # turns an org list into an org tree
954 my( $self, $orglist) = @_;
956 return $orglist unless (
957 ref($orglist) and @$orglist > 1 );
960 $a->ou_type <=> $b->ou_type ||
961 $a->name cmp $b->name } @$orglist;
963 for my $org (@list) {
965 next unless ($org and defined($org->parent_ou));
966 my ($parent) = grep { $_->id == $org->parent_ou } @list;
969 $parent->children([]) unless defined($parent->children);
970 push( @{$parent->children}, $org );
978 __PACKAGE__->register_method(
979 method => "get_org_descendants",
980 api_name => "open-ils.actor.org_tree.descendants.retrieve"
983 # depth is optional. org_unit is the id
984 sub get_org_descendants {
985 my( $self, $client, $org_unit, $depth ) = @_;
986 my $orglist = $apputils->simple_scalar_request(
988 "open-ils.storage.actor.org_unit.descendants.atomic",
990 return $self->build_org_tree($orglist);
994 __PACKAGE__->register_method(
995 method => "get_org_ancestors",
996 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
999 # depth is optional. org_unit is the id
1000 sub get_org_ancestors {
1001 my( $self, $client, $org_unit, $depth ) = @_;
1002 my $orglist = $apputils->simple_scalar_request(
1004 "open-ils.storage.actor.org_unit.ancestors.atomic",
1005 $org_unit, $depth );
1006 return $self->build_org_tree($orglist);
1010 __PACKAGE__->register_method(
1011 method => "get_standings",
1012 api_name => "open-ils.actor.standings.retrieve"
1017 return $user_standings if $user_standings;
1018 return $user_standings =
1019 $apputils->simple_scalar_request(
1021 "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
1026 __PACKAGE__->register_method(
1027 method => "get_my_org_path",
1028 api_name => "open-ils.actor.org_unit.full_path.retrieve"
1031 sub get_my_org_path {
1032 my( $self, $client, $user_session, $org_id ) = @_;
1033 my $user_obj = $apputils->check_user_session($user_session);
1034 if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
1036 return $apputils->simple_scalar_request(
1038 "open-ils.storage.actor.org_unit.full_path.atomic",
1043 __PACKAGE__->register_method(
1044 method => "patron_adv_search",
1045 api_name => "open-ils.actor.patron.search.advanced" );
1046 sub patron_adv_search {
1047 my( $self, $client, $auth, $search_hash, $search_limit, $search_sort ) = @_;
1048 my $e = OpenILS::Utils::Editor->new(authtoken=>$auth);
1049 return $e->event unless $e->checkauth;
1050 return $e->event unless $e->allowed('VIEW_USER');
1052 "open-ils.storage.actor.user.crazy_search",
1053 $search_hash, $search_limit, $search_sort);
1058 sub _verify_password {
1059 my($user_session, $password) = @_;
1060 my $user_obj = $apputils->check_user_session($user_session);
1062 #grab the user with password
1063 $user_obj = $apputils->simple_scalar_request(
1065 "open-ils.storage.direct.actor.user.retrieve",
1068 if($user_obj->passwd eq $password) {
1076 __PACKAGE__->register_method(
1077 method => "update_password",
1078 api_name => "open-ils.actor.user.password.update");
1080 __PACKAGE__->register_method(
1081 method => "update_password",
1082 api_name => "open-ils.actor.user.username.update");
1084 __PACKAGE__->register_method(
1085 method => "update_password",
1086 api_name => "open-ils.actor.user.email.update");
1088 sub update_password {
1089 my( $self, $client, $user_session, $new_value, $current_password ) = @_;
1093 my $user_obj = $apputils->check_user_session($user_session);
1095 if($self->api_name =~ /password/o) {
1097 #make sure they know the current password
1098 if(!_verify_password($user_session, md5_hex($current_password))) {
1099 return OpenILS::Event->new('INCORRECT_PASSWORD');
1102 $logger->debug("update_password setting new password $new_value");
1103 $user_obj->passwd($new_value);
1105 } elsif($self->api_name =~ /username/o) {
1106 my $users = search_username(undef, undef, $new_value);
1107 if( $users and $users->[0] ) {
1108 return OpenILS::Event->new('USERNAME_EXISTS');
1110 $user_obj->usrname($new_value);
1112 } elsif($self->api_name =~ /email/o) {
1113 #warn "Updating email to $new_value\n";
1114 $user_obj->email($new_value);
1117 my $session = $apputils->start_db_session();
1119 ( $user_obj, $evt ) = _update_patron($session, $user_obj, $user_obj, 1);
1120 return $evt if $evt;
1122 $apputils->commit_db_session($session);
1124 if($user_obj) { return 1; }
1129 __PACKAGE__->register_method(
1130 method => "check_user_perms",
1131 api_name => "open-ils.actor.user.perm.check",
1132 notes => <<" NOTES");
1133 Takes a login session, user id, an org id, and an array of perm type strings. For each
1134 perm type, if the user does *not* have the given permission it is added
1135 to a list which is returned from the method. If all permissions
1136 are allowed, an empty list is returned
1137 if the logged in user does not match 'user_id', then the logged in user must
1138 have VIEW_PERMISSION priveleges.
1141 sub check_user_perms {
1142 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1144 my( $staff, $evt ) = $apputils->checkses($login_session);
1145 return $evt if $evt;
1147 if($staff->id ne $user_id) {
1148 if( my $evt = $apputils->check_perms(
1149 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1155 for my $perm (@$perm_types) {
1156 if($apputils->check_perms($user_id, $org_id, $perm)) {
1157 push @not_allowed, $perm;
1161 return \@not_allowed
1164 __PACKAGE__->register_method(
1165 method => "check_user_perms2",
1166 api_name => "open-ils.actor.user.perm.check.multi_org",
1168 Checks the permissions on a list of perms and orgs for a user
1169 @param authtoken The login session key
1170 @param user_id The id of the user to check
1171 @param orgs The array of org ids
1172 @param perms The array of permission names
1173 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1174 if the logged in user does not match 'user_id', then the logged in user must
1175 have VIEW_PERMISSION priveleges.
1178 sub check_user_perms2 {
1179 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1181 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1182 $authtoken, $user_id, 'VIEW_PERMISSION' );
1183 return $evt if $evt;
1186 for my $org (@$orgs) {
1187 for my $perm (@$perms) {
1188 if($apputils->check_perms($user_id, $org, $perm)) {
1189 push @not_allowed, [ $org, $perm ];
1194 return \@not_allowed
1198 __PACKAGE__->register_method(
1199 method => 'check_user_perms3',
1200 api_name => 'open-ils.actor.user.perm.highest_org',
1202 Returns the highest org unit id at which a user has a given permission
1203 If the requestor does not match the target user, the requestor must have
1204 'VIEW_PERMISSION' rights at the home org unit of the target user
1205 @param authtoken The login session key
1206 @param userid The id of the user in question
1207 @param perm The permission to check
1208 @return The org unit highest in the org tree within which the user has
1209 the requested permission
1212 sub check_user_perms3 {
1213 my( $self, $client, $authtoken, $userid, $perm ) = @_;
1215 my( $staff, $target, $org, $evt );
1217 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1218 $authtoken, $userid, 'VIEW_PERMISSION' );
1219 return $evt if $evt;
1221 my $tree = $self->get_org_tree();
1222 return _find_highest_perm_org( $perm, $userid, $target->home_ou, $tree );
1226 sub _find_highest_perm_org {
1227 my ( $perm, $userid, $start_org, $org_tree ) = @_;
1228 my $org = $apputils->find_org($org_tree, $start_org );
1232 last if ($apputils->check_perms( $userid, $org->id, $perm )); # perm failed
1234 $org = $apputils->find_org( $org_tree, $org->parent_ou() );
1240 __PACKAGE__->register_method(
1241 method => 'check_user_perms4',
1242 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1244 Returns the highest org unit id at which a user has a given permission
1245 If the requestor does not match the target user, the requestor must have
1246 'VIEW_PERMISSION' rights at the home org unit of the target user
1247 @param authtoken The login session key
1248 @param userid The id of the user in question
1249 @param perms An array of perm names to check
1250 @return An array of orgId's representing the org unit
1251 highest in the org tree within which the user has the requested permission
1252 The arrah of orgId's has matches the order of the perms array
1255 sub check_user_perms4 {
1256 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1258 my( $staff, $target, $org, $evt );
1260 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1261 $authtoken, $userid, 'VIEW_PERMISSION' );
1262 return $evt if $evt;
1265 return [] unless ref($perms);
1266 my $tree = $self->get_org_tree();
1268 for my $p (@$perms) {
1269 push( @arr, _find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1277 __PACKAGE__->register_method(
1278 method => "user_fines_summary",
1279 api_name => "open-ils.actor.user.fines.summary",
1280 notes => <<" NOTES");
1281 Returns a short summary of the users total open fines, excluding voided fines
1282 Params are login_session, user_id
1283 Returns a 'mous' object.
1286 sub user_fines_summary {
1287 my( $self, $client, $login_session, $user_id ) = @_;
1289 my $user_obj = $apputils->check_user_session($login_session);
1290 if($user_obj->id ne $user_id) {
1291 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_FINES_SUMMARY")) {
1292 return OpenILS::Perm->new("VIEW_USER_FINES_SUMMARY");
1296 return $apputils->simple_scalar_request(
1298 "open-ils.storage.direct.money.open_user_summary.search.usr",
1306 __PACKAGE__->register_method(
1307 method => "user_transactions",
1308 api_name => "open-ils.actor.user.transactions",
1309 notes => <<" NOTES");
1310 Returns a list of open user transactions (mbts objects);
1311 Params are login_session, user_id
1312 Optional third parameter is the transactions type. defaults to all
1315 __PACKAGE__->register_method(
1316 method => "user_transactions",
1317 api_name => "open-ils.actor.user.transactions.have_charge",
1318 notes => <<" NOTES");
1319 Returns a list of all open user transactions (mbts objects) that have an initial charge
1320 Params are login_session, user_id
1321 Optional third parameter is the transactions type. defaults to all
1324 __PACKAGE__->register_method(
1325 method => "user_transactions",
1326 api_name => "open-ils.actor.user.transactions.have_balance",
1327 notes => <<" NOTES");
1328 Returns a list of all open user transactions (mbts objects) that have a balance
1329 Params are login_session, user_id
1330 Optional third parameter is the transactions type. defaults to all
1333 __PACKAGE__->register_method(
1334 method => "user_transactions",
1335 api_name => "open-ils.actor.user.transactions.fleshed",
1336 notes => <<" NOTES");
1337 Returns an object/hash of transaction, circ, title where transaction = an open
1338 user transactions (mbts objects), circ is the attached circluation, and title
1339 is the title the circ points to
1340 Params are login_session, user_id
1341 Optional third parameter is the transactions type. defaults to all
1344 __PACKAGE__->register_method(
1345 method => "user_transactions",
1346 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1347 notes => <<" NOTES");
1348 Returns an object/hash of transaction, circ, title where transaction = an open
1349 user transactions that has an initial charge (mbts objects), circ is the
1350 attached circluation, and title is the title the circ points to
1351 Params are login_session, user_id
1352 Optional third parameter is the transactions type. defaults to all
1355 __PACKAGE__->register_method(
1356 method => "user_transactions",
1357 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1358 notes => <<" NOTES");
1359 Returns an object/hash of transaction, circ, title where transaction = an open
1360 user transaction that has a balance (mbts objects), circ is the attached
1361 circluation, and title is the title the circ points to
1362 Params are login_session, user_id
1363 Optional third parameter is the transaction type. defaults to all
1366 __PACKAGE__->register_method(
1367 method => "user_transactions",
1368 api_name => "open-ils.actor.user.transactions.count",
1369 notes => <<" NOTES");
1370 Returns an object/hash of transaction, circ, title where transaction = an open
1371 user transactions (mbts objects), circ is the attached circluation, and title
1372 is the title the circ points to
1373 Params are login_session, user_id
1374 Optional third parameter is the transactions type. defaults to all
1377 __PACKAGE__->register_method(
1378 method => "user_transactions",
1379 api_name => "open-ils.actor.user.transactions.have_charge.count",
1380 notes => <<" NOTES");
1381 Returns an object/hash of transaction, circ, title where transaction = an open
1382 user transactions that has an initial charge (mbts objects), circ is the
1383 attached circluation, and title is the title the circ points to
1384 Params are login_session, user_id
1385 Optional third parameter is the transactions type. defaults to all
1388 __PACKAGE__->register_method(
1389 method => "user_transactions",
1390 api_name => "open-ils.actor.user.transactions.have_balance.count",
1391 notes => <<" NOTES");
1392 Returns an object/hash of transaction, circ, title where transaction = an open
1393 user transaction that has a balance (mbts objects), circ is the attached
1394 circluation, and title is the title the circ points to
1395 Params are login_session, user_id
1396 Optional third parameter is the transaction type. defaults to all
1399 __PACKAGE__->register_method(
1400 method => "user_transactions",
1401 api_name => "open-ils.actor.user.transactions.have_balance.total",
1402 notes => <<" NOTES");
1403 Returns an object/hash of transaction, circ, title where transaction = an open
1404 user transaction that has a balance (mbts objects), circ is the attached
1405 circluation, and title is the title the circ points to
1406 Params are login_session, user_id
1407 Optional third parameter is the transaction type. defaults to all
1412 sub user_transactions {
1413 my( $self, $client, $login_session, $user_id, $type ) = @_;
1415 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1416 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1417 return $evt if $evt;
1419 my $api = $self->api_name();
1423 if(defined($type)) { @xact = (xact_type => $type);
1425 } else { @xact = (); }
1427 if($api =~ /have_charge/o) {
1429 $trans = $apputils->simple_scalar_request(
1431 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1432 { usr => $user_id, total_owed => { ">" => 0 }, @xact });
1434 } elsif($api =~ /have_balance/o) {
1436 $trans = $apputils->simple_scalar_request(
1438 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1439 { usr => $user_id, balance_owed => { "<>" => 0 }, @xact });
1443 $trans = $apputils->simple_scalar_request(
1445 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1446 { usr => $user_id, @xact });
1449 if($api =~ /total/o) {
1451 for my $t (@$trans) {
1452 $total += $t->balance_owed;
1455 $logger->debug("Total balance owed by user $user_id: $total");
1459 if($api =~ /count/o) { return scalar @$trans; }
1460 if($api !~ /fleshed/o) { return $trans; }
1463 for my $t (@$trans) {
1465 if( $t->xact_type ne 'circulation' ) {
1466 push @resp, {transaction => $t};
1470 my $circ = $apputils->simple_scalar_request(
1472 "open-ils.storage.direct.action.circulation.retrieve",
1477 my $title = $apputils->simple_scalar_request(
1479 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1480 $circ->target_copy );
1484 my $u = OpenILS::Utils::ModsParser->new();
1485 $u->start_mods_batch($title->marc());
1486 my $mods = $u->finish_mods_batch();
1488 push @resp, {transaction => $t, circ => $circ, record => $mods };
1496 __PACKAGE__->register_method(
1497 method => "user_transaction_retrieve",
1498 api_name => "open-ils.actor.user.transaction.fleshed.retrieve",
1500 notes => <<" NOTES");
1501 Returns a fleshedtransaction record
1503 __PACKAGE__->register_method(
1504 method => "user_transaction_retrieve",
1505 api_name => "open-ils.actor.user.transaction.retrieve",
1507 notes => <<" NOTES");
1508 Returns a transaction record
1510 sub user_transaction_retrieve {
1511 my( $self, $client, $login_session, $bill_id ) = @_;
1513 my $trans = $apputils->simple_scalar_request(
1515 "open-ils.storage.direct.money.billable_transaction_summary.retrieve",
1519 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1520 $login_session, $trans->usr, 'VIEW_USER_TRANSACTIONS' );
1521 return $evt if $evt;
1523 my $api = $self->api_name();
1524 if($api !~ /fleshed/o) { return $trans; }
1526 if( $trans->xact_type ne 'circulation' ) {
1527 $logger->debug("Returning non-circ transaction");
1528 return {transaction => $trans};
1531 my $circ = $apputils->simple_scalar_request(
1533 "open-ils.storage.direct.action.circulation.retrieve",
1536 return {transaction => $trans} unless $circ;
1537 $logger->debug("Found the circ transaction");
1539 my $title = $apputils->simple_scalar_request(
1541 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1542 $circ->target_copy );
1544 return {transaction => $trans, circ => $circ } unless $title;
1545 $logger->debug("Found the circ title");
1549 my $u = OpenILS::Utils::ModsParser->new();
1550 $u->start_mods_batch($title->marc());
1551 $mods = $u->finish_mods_batch();
1553 if ($title->id == -1) {
1554 my $copy = $apputils->simple_scalar_request(
1556 "open-ils.storage.direct.asset.copy.retrieve",
1557 $circ->target_copy );
1559 $mods = new Fieldmapper::metabib::virtual_record;
1561 $mods->title($copy->dummy_title);
1562 $mods->author($copy->dummy_author);
1566 $logger->debug("MODSized the circ title");
1568 return {transaction => $trans, circ => $circ, record => $mods };
1572 __PACKAGE__->register_method(
1573 method => "hold_request_count",
1574 api_name => "open-ils.actor.user.hold_requests.count",
1576 notes => <<" NOTES");
1577 Returns hold ready/total counts
1579 sub hold_request_count {
1580 my( $self, $client, $login_session, $userid ) = @_;
1582 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1583 $login_session, $userid, 'VIEW_HOLD' );
1584 return $evt if $evt;
1587 my $holds = $apputils->simple_scalar_request(
1589 "open-ils.storage.direct.action.hold_request.search_where.atomic",
1591 fulfillment_time => {"=" => undef } }
1595 for my $h (@$holds) {
1596 next unless $h->capture_time;
1598 my $copy = $apputils->simple_scalar_request(
1600 "open-ils.storage.direct.asset.copy.retrieve",
1604 if ($copy->status == 8) {
1609 return { total => scalar(@$holds), ready => scalar(@ready) };
1613 __PACKAGE__->register_method(
1614 method => "checkedout_count",
1615 api_name => "open-ils.actor.user.checked_out.count",
1617 notes => <<" NOTES");
1618 Returns a transaction record
1622 sub checkedout_count {
1623 my( $self, $client, $login_session, $userid ) = @_;
1625 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1626 $login_session, $userid, 'VIEW_CIRCULATIONS' );
1627 return $evt if $evt;
1629 my $circs = $apputils->simple_scalar_request(
1631 "open-ils.storage.direct.action.circulation.search_where.atomic",
1632 { usr => $userid, stop_fines => undef }
1633 #{ usr => $userid, checkin_time => {"=" => undef } }
1636 my $parser = DateTime::Format::ISO8601->new;
1639 for my $c (@$circs) {
1640 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1641 my $due = $due_dt->epoch;
1643 if ($due < DateTime->today->epoch) {
1648 return { total => scalar(@$circs), overdue => scalar(@overdue) };
1652 __PACKAGE__->register_method(
1653 method => "checked_out",
1654 api_name => "open-ils.actor.user.checked_out",
1657 Returns a structure of circulations objects sorted by
1658 out, overdue, lost, claims_returned, long_overdue.
1659 A list of IDs are returned of each type.
1660 lost, long_overdue, and claims_returned circ will not
1661 be "finished" (there is an outstanding balance or some
1662 other pending action on the circ).
1664 The .count method also includes a 'total' field which
1665 sums all "open" circs
1669 __PACKAGE__->register_method(
1670 method => "checked_out",
1671 api_name => "open-ils.actor.user.checked_out.count_",
1673 signature => q/@see open-ils.actor.user.checked_out/
1677 my( $self, $conn, $auth, $userid ) = @_;
1679 my $e = new_editor(authtoken=>$auth);
1680 return $e->event unless $e->checkauth;
1682 if( $userid ne $e->requestor->id ) {
1683 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
1686 my $circs = $e->search_action_circulation(
1687 { usr => $userid, stop_fines => undef });
1689 my $parser = DateTime::Format::ISO8601->new;
1691 # split the circs up into overdue and not-overdue circs
1693 for my $c (@$circs) {
1694 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1695 my $due = $due_dt->epoch;
1696 if ($due < DateTime->today->epoch) {
1697 push @overdue, $c->id;
1703 # grab all of the lost, claims-returned, and longoverdue circs
1704 my $open = $e->search_action_circulation(
1705 {usr => $userid, stop_fines => { '!=' => undef }, xact_finish => undef });
1707 my( @lost, @cr, @lo );
1708 for my $c (@$open) {
1709 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1710 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1711 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
1715 if( $self->api_name =~ /count/ ) {
1717 total => @$circs + @lost + @cr + @lo,
1718 out => scalar(@out),
1719 overdue => scalar(@overdue),
1720 lost => scalar(@lost),
1721 claims_returned => scalar(@cr),
1722 long_overdue => scalar(@lo)
1728 overdue => \@overdue,
1730 claims_returned => \@cr,
1731 long_overdue => \@lo
1743 __PACKAGE__->register_method(
1744 method => "user_transaction_history",
1745 api_name => "open-ils.actor.user.transactions.history",
1747 notes => <<" NOTES");
1748 Returns a list of billable transaction ids for a user, optionally by type
1750 __PACKAGE__->register_method(
1751 method => "user_transaction_history",
1752 api_name => "open-ils.actor.user.transactions.history.have_charge",
1754 notes => <<" NOTES");
1755 Returns a list of billable transaction ids for a user that have an initial charge, optionally by type
1757 sub user_transaction_history {
1758 my( $self, $client, $login_session, $user_id, $type ) = @_;
1760 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1761 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1762 return $evt if $evt;
1764 my $api = $self->api_name();
1768 @xact = (xact_type => $type) if(defined($type));
1769 @charge = (total_owed => { ">" => 0}) if($api =~ /have_charge/);
1771 my $trans = $apputils->simple_scalar_request(
1773 "open-ils.storage.direct.money.billable_transaction_summary.search_where.atomic",
1774 { usr => $user_id, @xact, @charge }, { order_by => 'xact_start DESC' });
1776 return [ map { $_->id } @$trans ];
1780 __PACKAGE__->register_method(
1781 method => "user_perms",
1782 api_name => "open-ils.actor.permissions.user_perms.retrieve",
1784 notes => <<" NOTES");
1785 Returns a list of permissions
1788 my( $self, $client, $authtoken, $user ) = @_;
1790 my( $staff, $evt ) = $apputils->checkses($authtoken);
1791 return $evt if $evt;
1793 $user ||= $staff->id;
1795 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
1799 return $apputils->simple_scalar_request(
1801 "open-ils.storage.permission.user_perms.atomic",
1805 __PACKAGE__->register_method(
1806 method => "retrieve_perms",
1807 api_name => "open-ils.actor.permissions.retrieve",
1808 notes => <<" NOTES");
1809 Returns a list of permissions
1811 sub retrieve_perms {
1812 my( $self, $client ) = @_;
1813 return $apputils->simple_scalar_request(
1815 "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
1818 __PACKAGE__->register_method(
1819 method => "retrieve_groups",
1820 api_name => "open-ils.actor.groups.retrieve",
1821 notes => <<" NOTES");
1822 Returns a list of user groupss
1824 sub retrieve_groups {
1825 my( $self, $client ) = @_;
1826 return $apputils->simple_scalar_request(
1828 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1831 __PACKAGE__->register_method(
1832 method => "retrieve_org_address",
1833 api_name => "open-ils.actor.org_unit.address.retrieve",
1834 notes => <<' NOTES');
1835 Returns an org_unit address by ID
1836 @param An org_address ID
1838 sub retrieve_org_address {
1839 my( $self, $client, $id ) = @_;
1840 return $apputils->simple_scalar_request(
1842 "open-ils.storage.direct.actor.org_address.retrieve",
1847 __PACKAGE__->register_method(
1848 method => "retrieve_groups_tree",
1849 api_name => "open-ils.actor.groups.tree.retrieve",
1850 notes => <<" NOTES");
1851 Returns a list of user groups
1853 sub retrieve_groups_tree {
1854 my( $self, $client ) = @_;
1855 my $groups = $apputils->simple_scalar_request(
1857 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1858 return $self->build_group_tree($groups);
1862 # turns an org list into an org tree
1863 sub build_group_tree {
1865 my( $self, $grplist) = @_;
1867 return $grplist unless (
1868 ref($grplist) and @$grplist > 1 );
1870 my @list = sort { $a->name cmp $b->name } @$grplist;
1873 for my $grp (@list) {
1875 if ($grp and !defined($grp->parent)) {
1879 my ($parent) = grep { $_->id == $grp->parent} @list;
1881 $parent->children([]) unless defined($parent->children);
1882 push( @{$parent->children}, $grp );
1890 __PACKAGE__->register_method(
1891 method => "add_user_to_groups",
1892 api_name => "open-ils.actor.user.set_groups",
1893 notes => <<" NOTES");
1894 Adds a user to one or more permission groups
1897 sub add_user_to_groups {
1898 my( $self, $client, $authtoken, $userid, $groups ) = @_;
1900 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1901 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
1902 return $evt if $evt;
1904 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1905 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
1906 return $evt if $evt;
1908 $apputils->simplereq(
1910 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
1912 for my $group (@$groups) {
1913 my $link = Fieldmapper::permission::usr_grp_map->new;
1915 $link->usr($userid);
1917 my $id = $apputils->simplereq(
1919 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
1925 __PACKAGE__->register_method(
1926 method => "get_user_perm_groups",
1927 api_name => "open-ils.actor.user.get_groups",
1928 notes => <<" NOTES");
1929 Retrieve a user's permission groups.
1933 sub get_user_perm_groups {
1934 my( $self, $client, $authtoken, $userid ) = @_;
1936 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1937 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
1938 return $evt if $evt;
1940 return $apputils->simplereq(
1942 'open-ils.storage.direct.permission.usr_grp_map.search.usr.atomic', $userid );
1947 __PACKAGE__->register_method (
1948 method => 'register_workstation',
1949 api_name => 'open-ils.actor.workstation.register.override',
1950 signature => q/@see open-ils.actor.workstation.register/);
1952 __PACKAGE__->register_method (
1953 method => 'register_workstation',
1954 api_name => 'open-ils.actor.workstation.register',
1956 Registers a new workstion in the system
1957 @param authtoken The login session key
1958 @param name The name of the workstation id
1959 @param owner The org unit that owns this workstation
1960 @return The workstation id on success, WORKSTATION_NAME_EXISTS
1961 if the name is already in use.
1964 sub _register_workstation {
1965 my( $self, $connection, $authtoken, $name, $owner ) = @_;
1966 my( $requestor, $evt ) = $U->checkses($authtoken);
1967 return $evt if $evt;
1968 $evt = $U->check_perms($requestor->id, $owner, 'REGISTER_WORKSTATION');
1969 return $evt if $evt;
1971 my $ws = $U->storagereq(
1972 'open-ils.storage.direct.actor.workstation.search.name', $name );
1973 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS') if $ws;
1975 $ws = Fieldmapper::actor::workstation->new;
1976 $ws->owning_lib($owner);
1979 my $id = $U->storagereq(
1980 'open-ils.storage.direct.actor.workstation.create', $ws );
1981 return $U->DB_UPDATE_FAILED($ws) unless $id;
1987 sub register_workstation {
1988 my( $self, $conn, $authtoken, $name, $owner ) = @_;
1990 my $e = OpenILS::Utils::Editor->new(authtoken=>$authtoken, xact=>1);
1991 return $e->event unless $e->checkauth;
1992 return $e->event unless $e->allowed('REGISTER_WORKSTATION'); # XXX rely on editor perms
1993 my $existing = $e->search_actor_workstation({name => $name});
1996 if( $self->api_name =~ /override/o ) {
1997 return $e->event unless $e->allowed('DELETE_WORKSTATION'); # XXX rely on editor perms
1998 return $e->event unless $e->delete_actor_workstation($$existing[0]);
2000 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS')
2004 my $ws = Fieldmapper::actor::workstation->new;
2005 $ws->owning_lib($owner);
2007 $e->create_actor_workstation($ws) or return $e->event;
2009 return $ws->id; # note: editor sets the id on the new object for us
2013 __PACKAGE__->register_method (
2014 method => 'fetch_patron_note',
2015 api_name => 'open-ils.actor.note.retrieve.all',
2017 Returns a list of notes for a given user
2018 Requestor must have VIEW_USER permission if pub==false and
2019 @param authtoken The login session key
2020 @param args Hash of params including
2021 patronid : the patron's id
2022 pub : true if retrieving only public notes
2026 sub fetch_patron_note {
2027 my( $self, $conn, $authtoken, $args ) = @_;
2028 my $patronid = $$args{patronid};
2030 my($reqr, $evt) = $U->checkses($authtoken);
2033 ($patron, $evt) = $U->fetch_user($patronid);
2034 return $evt if $evt;
2037 if( $patronid ne $reqr->id ) {
2038 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2039 return $evt if $evt;
2041 return $U->storagereq(
2042 'open-ils.storage.direct.actor.usr_note.search_where.atomic',
2043 { usr => $patronid, pub => 't' } );
2046 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2047 return $evt if $evt;
2049 return $U->storagereq(
2050 'open-ils.storage.direct.actor.usr_note.search.usr.atomic', $patronid );
2053 __PACKAGE__->register_method (
2054 method => 'create_user_note',
2055 api_name => 'open-ils.actor.note.create',
2057 Creates a new note for the given user
2058 @param authtoken The login session key
2059 @param note The note object
2062 sub create_user_note {
2063 my( $self, $conn, $authtoken, $note ) = @_;
2064 my( $reqr, $patron, $evt ) =
2065 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
2066 return $evt if $evt;
2067 $logger->activity("user ".$reqr->id." creating note for user ".$note->usr);
2069 $note->pub('f') unless $note->pub;
2070 $note->creator($reqr->id);
2071 my $id = $U->storagereq(
2072 'open-ils.storage.direct.actor.usr_note.create', $note );
2073 return $U->DB_UPDATE_FAILED($note) unless $id;
2078 __PACKAGE__->register_method (
2079 method => 'delete_user_note',
2080 api_name => 'open-ils.actor.note.delete',
2082 Deletes a note for the given user
2083 @param authtoken The login session key
2084 @param noteid The note id
2087 sub delete_user_note {
2088 my( $self, $conn, $authtoken, $noteid ) = @_;
2090 my $note = $U->storagereq(
2091 'open-ils.storage.direct.actor.usr_note.retrieve', $noteid);
2092 return OpenILS::Event->new('ACTOR_USER_NOTE_NOT_FOUND') unless $note;
2094 my( $reqr, $patron, $evt ) =
2095 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
2096 return $evt if $evt;
2097 $logger->activity("user ".$reqr->id." deleting note [$noteid] for user ".$note->usr);
2099 my $stat = $U->storagereq(
2100 'open-ils.storage.direct.actor.usr_note.delete', $noteid );
2101 return $U->DB_UPDATE_FAILED($note) unless defined $stat;
2107 __PACKAGE__->register_method (
2108 method => 'create_closed_date',
2109 api_name => 'open-ils.actor.org_unit.closed_date.create',
2111 Creates a new closing entry for the given org_unit
2112 @param authtoken The login session key
2113 @param note The closed_date object
2116 sub create_closed_date {
2117 my( $self, $conn, $authtoken, $cd ) = @_;
2119 my( $user, $evt ) = $U->checkses($authtoken);
2120 return $evt if $evt;
2122 $evt = $U->check_perms($user->id, $cd->org_unit, 'CREATE_CLOSEING');
2123 return $evt if $evt;
2125 $logger->activity("user ".$user->id." creating library closing for ".$cd->org_unit);
2127 my $id = $U->storagereq(
2128 'open-ils.storage.direct.actor.org_unit.closed_date.create', $cd );
2129 return $U->DB_UPDATE_FAILED($cd) unless $id;
2134 __PACKAGE__->register_method (
2135 method => 'delete_closed_date',
2136 api_name => 'open-ils.actor.org_unit.closed_date.delete',
2138 Deletes a closing entry for the given org_unit
2139 @param authtoken The login session key
2140 @param noteid The close_date id
2143 sub delete_closed_date {
2144 my( $self, $conn, $authtoken, $cd ) = @_;
2146 my( $user, $evt ) = $U->checkses($authtoken);
2147 return $evt if $evt;
2150 ($cd_obj, $evt) = fetch_closed_date($cd);
2151 return $evt if $evt;
2153 $evt = $U->check_perms($user->id, $cd->org_unit, 'DELETE_CLOSEING');
2154 return $evt if $evt;
2156 $logger->activity("user ".$user->id." deleting library closing for ".$cd->org_unit);
2158 my $stat = $U->storagereq(
2159 'open-ils.storage.direct.actor.org_unit.closed_date.delete', $cd );
2160 return $U->DB_UPDATE_FAILED($cd) unless $stat;
2165 __PACKAGE__->register_method(
2166 method => 'usrname_exists',
2167 api_name => 'open-ils.actor.username.exists',
2169 Returns 1 if the requested username exists, returns 0 otherwise
2173 sub usrname_exists {
2174 my( $self, $conn, $auth, $usrname ) = @_;
2175 my $e = new_editor(authtoken=>$auth);
2176 return $e->event unless $e->checkauth;
2177 my $a = $e->search_actor_user({usrname => $usrname}, {idlist=>1});
2178 return $$a[0] if $a and @$a;
2183 __PACKAGE__->register_method(
2184 method => 'retrieve_net_levels',
2185 api_name => 'open-ils.actor.net_access_level.retrieve.all',
2188 sub retrieve_net_levels {
2189 my( $self, $conn, $auth ) = @_;
2190 my $e = new_editor(authtoken=>$auth);
2191 return $e->event unless $e->checkauth;
2192 return $e->retrieve_all_config_net_access_level();