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
1620 sub checkedout_count {
1621 my( $self, $client, $login_session, $userid ) = @_;
1623 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1624 $login_session, $userid, 'VIEW_CIRCULATIONS' );
1625 return $evt if $evt;
1627 my $circs = $apputils->simple_scalar_request(
1629 "open-ils.storage.direct.action.circulation.search_where.atomic",
1630 { usr => $userid, stop_fines => undef }
1631 #{ usr => $userid, checkin_time => {"=" => undef } }
1634 my $parser = DateTime::Format::ISO8601->new;
1637 for my $c (@$circs) {
1638 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1639 my $due = $due_dt->epoch;
1641 if ($due < DateTime->today->epoch) {
1646 return { total => scalar(@$circs), overdue => scalar(@overdue) };
1649 __PACKAGE__->register_method(
1650 method => "user_transaction_history",
1651 api_name => "open-ils.actor.user.transactions.history",
1653 notes => <<" NOTES");
1654 Returns a list of billable transaction ids for a user, optionally by type
1656 __PACKAGE__->register_method(
1657 method => "user_transaction_history",
1658 api_name => "open-ils.actor.user.transactions.history.have_charge",
1660 notes => <<" NOTES");
1661 Returns a list of billable transaction ids for a user that have an initial charge, optionally by type
1663 sub user_transaction_history {
1664 my( $self, $client, $login_session, $user_id, $type ) = @_;
1666 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1667 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1668 return $evt if $evt;
1670 my $api = $self->api_name();
1674 @xact = (xact_type => $type) if(defined($type));
1675 @charge = (total_owed => { ">" => 0}) if($api =~ /have_charge/);
1677 my $trans = $apputils->simple_scalar_request(
1679 "open-ils.storage.direct.money.billable_transaction_summary.search_where.atomic",
1680 { usr => $user_id, @xact, @charge }, { order_by => 'xact_start DESC' });
1682 return [ map { $_->id } @$trans ];
1686 __PACKAGE__->register_method(
1687 method => "user_perms",
1688 api_name => "open-ils.actor.permissions.user_perms.retrieve",
1690 notes => <<" NOTES");
1691 Returns a list of permissions
1694 my( $self, $client, $authtoken, $user ) = @_;
1696 my( $staff, $evt ) = $apputils->checkses($authtoken);
1697 return $evt if $evt;
1699 $user ||= $staff->id;
1701 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
1705 return $apputils->simple_scalar_request(
1707 "open-ils.storage.permission.user_perms.atomic",
1711 __PACKAGE__->register_method(
1712 method => "retrieve_perms",
1713 api_name => "open-ils.actor.permissions.retrieve",
1714 notes => <<" NOTES");
1715 Returns a list of permissions
1717 sub retrieve_perms {
1718 my( $self, $client ) = @_;
1719 return $apputils->simple_scalar_request(
1721 "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
1724 __PACKAGE__->register_method(
1725 method => "retrieve_groups",
1726 api_name => "open-ils.actor.groups.retrieve",
1727 notes => <<" NOTES");
1728 Returns a list of user groupss
1730 sub retrieve_groups {
1731 my( $self, $client ) = @_;
1732 return $apputils->simple_scalar_request(
1734 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1737 __PACKAGE__->register_method(
1738 method => "retrieve_org_address",
1739 api_name => "open-ils.actor.org_unit.address.retrieve",
1740 notes => <<' NOTES');
1741 Returns an org_unit address by ID
1742 @param An org_address ID
1744 sub retrieve_org_address {
1745 my( $self, $client, $id ) = @_;
1746 return $apputils->simple_scalar_request(
1748 "open-ils.storage.direct.actor.org_address.retrieve",
1753 __PACKAGE__->register_method(
1754 method => "retrieve_groups_tree",
1755 api_name => "open-ils.actor.groups.tree.retrieve",
1756 notes => <<" NOTES");
1757 Returns a list of user groups
1759 sub retrieve_groups_tree {
1760 my( $self, $client ) = @_;
1761 my $groups = $apputils->simple_scalar_request(
1763 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1764 return $self->build_group_tree($groups);
1768 # turns an org list into an org tree
1769 sub build_group_tree {
1771 my( $self, $grplist) = @_;
1773 return $grplist unless (
1774 ref($grplist) and @$grplist > 1 );
1776 my @list = sort { $a->name cmp $b->name } @$grplist;
1779 for my $grp (@list) {
1781 if ($grp and !defined($grp->parent)) {
1785 my ($parent) = grep { $_->id == $grp->parent} @list;
1787 $parent->children([]) unless defined($parent->children);
1788 push( @{$parent->children}, $grp );
1796 __PACKAGE__->register_method(
1797 method => "add_user_to_groups",
1798 api_name => "open-ils.actor.user.set_groups",
1799 notes => <<" NOTES");
1800 Adds a user to one or more permission groups
1803 sub add_user_to_groups {
1804 my( $self, $client, $authtoken, $userid, $groups ) = @_;
1806 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1807 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
1808 return $evt if $evt;
1810 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1811 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
1812 return $evt if $evt;
1814 $apputils->simplereq(
1816 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
1818 for my $group (@$groups) {
1819 my $link = Fieldmapper::permission::usr_grp_map->new;
1821 $link->usr($userid);
1823 my $id = $apputils->simplereq(
1825 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
1831 __PACKAGE__->register_method(
1832 method => "get_user_perm_groups",
1833 api_name => "open-ils.actor.user.get_groups",
1834 notes => <<" NOTES");
1835 Retrieve a user's permission groups.
1839 sub get_user_perm_groups {
1840 my( $self, $client, $authtoken, $userid ) = @_;
1842 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1843 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
1844 return $evt if $evt;
1846 return $apputils->simplereq(
1848 'open-ils.storage.direct.permission.usr_grp_map.search.usr.atomic', $userid );
1853 __PACKAGE__->register_method (
1854 method => 'register_workstation',
1855 api_name => 'open-ils.actor.workstation.register.override',
1856 signature => q/@see open-ils.actor.workstation.register/);
1858 __PACKAGE__->register_method (
1859 method => 'register_workstation',
1860 api_name => 'open-ils.actor.workstation.register',
1862 Registers a new workstion in the system
1863 @param authtoken The login session key
1864 @param name The name of the workstation id
1865 @param owner The org unit that owns this workstation
1866 @return The workstation id on success, WORKSTATION_NAME_EXISTS
1867 if the name is already in use.
1870 sub _register_workstation {
1871 my( $self, $connection, $authtoken, $name, $owner ) = @_;
1872 my( $requestor, $evt ) = $U->checkses($authtoken);
1873 return $evt if $evt;
1874 $evt = $U->check_perms($requestor->id, $owner, 'REGISTER_WORKSTATION');
1875 return $evt if $evt;
1877 my $ws = $U->storagereq(
1878 'open-ils.storage.direct.actor.workstation.search.name', $name );
1879 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS') if $ws;
1881 $ws = Fieldmapper::actor::workstation->new;
1882 $ws->owning_lib($owner);
1885 my $id = $U->storagereq(
1886 'open-ils.storage.direct.actor.workstation.create', $ws );
1887 return $U->DB_UPDATE_FAILED($ws) unless $id;
1893 sub register_workstation {
1894 my( $self, $conn, $authtoken, $name, $owner ) = @_;
1896 my $e = OpenILS::Utils::Editor->new(authtoken=>$authtoken, xact=>1);
1897 return $e->event unless $e->checkauth;
1898 return $e->event unless $e->allowed('REGISTER_WORKSTATION'); # XXX rely on editor perms
1899 my $existing = $e->search_actor_workstation({name => $name});
1902 if( $self->api_name =~ /override/o ) {
1903 return $e->event unless $e->allowed('DELETE_WORKSTATION'); # XXX rely on editor perms
1904 return $e->event unless $e->delete_actor_workstation($$existing[0]);
1906 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS')
1910 my $ws = Fieldmapper::actor::workstation->new;
1911 $ws->owning_lib($owner);
1913 $e->create_actor_workstation($ws) or return $e->event;
1915 return $ws->id; # note: editor sets the id on the new object for us
1919 __PACKAGE__->register_method (
1920 method => 'fetch_patron_note',
1921 api_name => 'open-ils.actor.note.retrieve.all',
1923 Returns a list of notes for a given user
1924 Requestor must have VIEW_USER permission if pub==false and
1925 @param authtoken The login session key
1926 @param args Hash of params including
1927 patronid : the patron's id
1928 pub : true if retrieving only public notes
1932 sub fetch_patron_note {
1933 my( $self, $conn, $authtoken, $args ) = @_;
1934 my $patronid = $$args{patronid};
1936 my($reqr, $evt) = $U->checkses($authtoken);
1939 ($patron, $evt) = $U->fetch_user($patronid);
1940 return $evt if $evt;
1943 if( $patronid ne $reqr->id ) {
1944 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
1945 return $evt if $evt;
1947 return $U->storagereq(
1948 'open-ils.storage.direct.actor.usr_note.search_where.atomic',
1949 { usr => $patronid, pub => 't' } );
1952 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
1953 return $evt if $evt;
1955 return $U->storagereq(
1956 'open-ils.storage.direct.actor.usr_note.search.usr.atomic', $patronid );
1959 __PACKAGE__->register_method (
1960 method => 'create_user_note',
1961 api_name => 'open-ils.actor.note.create',
1963 Creates a new note for the given user
1964 @param authtoken The login session key
1965 @param note The note object
1968 sub create_user_note {
1969 my( $self, $conn, $authtoken, $note ) = @_;
1970 my( $reqr, $patron, $evt ) =
1971 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
1972 return $evt if $evt;
1973 $logger->activity("user ".$reqr->id." creating note for user ".$note->usr);
1975 $note->pub('f') unless $note->pub;
1976 $note->creator($reqr->id);
1977 my $id = $U->storagereq(
1978 'open-ils.storage.direct.actor.usr_note.create', $note );
1979 return $U->DB_UPDATE_FAILED($note) unless $id;
1984 __PACKAGE__->register_method (
1985 method => 'delete_user_note',
1986 api_name => 'open-ils.actor.note.delete',
1988 Deletes a note for the given user
1989 @param authtoken The login session key
1990 @param noteid The note id
1993 sub delete_user_note {
1994 my( $self, $conn, $authtoken, $noteid ) = @_;
1996 my $note = $U->storagereq(
1997 'open-ils.storage.direct.actor.usr_note.retrieve', $noteid);
1998 return OpenILS::Event->new('ACTOR_USER_NOTE_NOT_FOUND') unless $note;
2000 my( $reqr, $patron, $evt ) =
2001 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
2002 return $evt if $evt;
2003 $logger->activity("user ".$reqr->id." deleting note [$noteid] for user ".$note->usr);
2005 my $stat = $U->storagereq(
2006 'open-ils.storage.direct.actor.usr_note.delete', $noteid );
2007 return $U->DB_UPDATE_FAILED($note) unless defined $stat;
2013 __PACKAGE__->register_method (
2014 method => 'create_closed_date',
2015 api_name => 'open-ils.actor.org_unit.closed_date.create',
2017 Creates a new closing entry for the given org_unit
2018 @param authtoken The login session key
2019 @param note The closed_date object
2022 sub create_closed_date {
2023 my( $self, $conn, $authtoken, $cd ) = @_;
2025 my( $user, $evt ) = $U->checkses($authtoken);
2026 return $evt if $evt;
2028 $evt = $U->check_perms($user->id, $cd->org_unit, 'CREATE_CLOSEING');
2029 return $evt if $evt;
2031 $logger->activity("user ".$user->id." creating library closing for ".$cd->org_unit);
2033 my $id = $U->storagereq(
2034 'open-ils.storage.direct.actor.org_unit.closed_date.create', $cd );
2035 return $U->DB_UPDATE_FAILED($cd) unless $id;
2040 __PACKAGE__->register_method (
2041 method => 'delete_closed_date',
2042 api_name => 'open-ils.actor.org_unit.closed_date.delete',
2044 Deletes a closing entry for the given org_unit
2045 @param authtoken The login session key
2046 @param noteid The close_date id
2049 sub delete_closed_date {
2050 my( $self, $conn, $authtoken, $cd ) = @_;
2052 my( $user, $evt ) = $U->checkses($authtoken);
2053 return $evt if $evt;
2056 ($cd_obj, $evt) = fetch_closed_date($cd);
2057 return $evt if $evt;
2059 $evt = $U->check_perms($user->id, $cd->org_unit, 'DELETE_CLOSEING');
2060 return $evt if $evt;
2062 $logger->activity("user ".$user->id." deleting library closing for ".$cd->org_unit);
2064 my $stat = $U->storagereq(
2065 'open-ils.storage.direct.actor.org_unit.closed_date.delete', $cd );
2066 return $U->DB_UPDATE_FAILED($cd) unless $stat;
2071 __PACKAGE__->register_method(
2072 method => 'usrname_exists',
2073 api_name => 'open-ils.actor.username.exists',
2075 Returns 1 if the requested username exists, returns 0 otherwise
2079 sub usrname_exists {
2080 my( $self, $conn, $auth, $usrname ) = @_;
2081 my $e = new_editor(authtoken=>$auth);
2082 return $e->event unless $e->checkauth;
2083 my $a = $e->search_actor_user({usrname => $usrname}, {idlist=>1});
2084 return $$a[0] if $a and @$a;
2089 __PACKAGE__->register_method(
2090 method => 'retrieve_net_levels',
2091 api_name => 'open-ils.actor.net_access_level.retrieve.all',
2094 sub retrieve_net_levels {
2095 my( $self, $conn, $auth ) = @_;
2096 my $e = new_editor(authtoken=>$auth);
2097 return $e->event unless $e->checkauth;
2098 return $e->retrieve_all_config_net_access_level();