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;
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 $card->usr($new_patron->id());
576 $evt = _update_card($session, $card);
577 return (undef, $evt) if $evt;
581 return ( $new_patron, undef );
585 # adds an card to the db and returns the card with new id
587 my( $session, $card ) = @_;
590 $logger->info("Adding new patron card ".$card->barcode);
592 my $id = $session->request(
593 "open-ils.storage.direct.actor.card.create", $card )->gather(1);
594 return (undef, $U->DB_UPDATE_FAILED($card)) unless $id;
595 $logger->info("Successfully created patron card $id");
598 return ( $card, undef );
602 # returns event on error. returns undef otherwise
604 my( $session, $card ) = @_;
605 $logger->info("Updating patron card ".$card->id);
607 my $stat = $session->request(
608 "open-ils.storage.direct.actor.card.update", $card )->gather(1);
609 return $U->DB_UPDATE_FAILED($card) unless defined($stat);
616 # returns event on error. returns undef otherwise
617 sub _delete_address {
618 my( $session, $address ) = @_;
620 $logger->info("Deleting address ".$address->id." from DB");
622 my $stat = $session->request(
623 "open-ils.storage.direct.actor.user_address.delete", $address )->gather(1);
625 return $U->DB_UPDATE_FAILED($address) unless defined($stat);
631 sub _add_survey_responses {
632 my ($session, $patron, $new_patron) = @_;
634 $logger->info( "Updating survey responses for patron ".$new_patron->id );
636 my $responses = $patron->survey_responses;
640 $_->usr($new_patron->id) for (@$responses);
642 my $evt = $U->simplereq( "open-ils.circ",
643 "open-ils.circ.survey.submit.user_id", $responses );
645 return (undef, $evt) if defined($U->event_code($evt));
649 return ( $new_patron, undef );
653 sub _create_stat_maps {
655 my($session, $user_session, $patron, $new_patron) = @_;
657 my $maps = $patron->stat_cat_entries();
659 for my $map (@$maps) {
661 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
663 if ($map->isdeleted()) {
664 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.delete";
666 } elsif ($map->isnew()) {
667 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
672 $map->target_usr($new_patron->id);
675 $logger->info("Updating stat entry with method $method and map $map");
677 my $stat = $session->request($method, $map)->gather(1);
678 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
682 return ($new_patron, undef);
685 sub _create_perm_maps {
687 my($session, $user_session, $patron, $new_patron) = @_;
689 my $maps = $patron->permissions;
691 for my $map (@$maps) {
693 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
694 if ($map->isdeleted()) {
695 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
696 } elsif ($map->isnew()) {
697 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
702 $map->usr($new_patron->id);
704 #warn( "Updating permissions with method $method and session $user_session and map $map" );
705 $logger->info( "Updating permissions with method $method and map $map" );
707 my $stat = $session->request($method, $map)->gather(1);
708 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
712 return ($new_patron, undef);
716 sub _create_standing_penalties {
718 my($session, $user_session, $patron, $new_patron) = @_;
720 my $maps = $patron->standing_penalties;
723 for my $map (@$maps) {
725 if ($map->isdeleted()) {
726 $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
727 } elsif ($map->isnew()) {
728 $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
734 $map->usr($new_patron->id);
736 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
738 my $stat = $session->request($method, $map)->gather(1);
739 return (undef, $U->DB_UPDATE_FAILED($map)) unless $stat;
742 return ($new_patron, undef);
747 __PACKAGE__->register_method(
748 method => "search_username",
749 api_name => "open-ils.actor.user.search.username",
752 sub search_username {
753 my($self, $client, $username) = @_;
754 my $users = OpenILS::Application::AppUtils->simple_scalar_request(
756 "open-ils.storage.direct.actor.user.search.usrname.atomic",
764 __PACKAGE__->register_method(
765 method => "user_retrieve_by_barcode",
766 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
768 sub user_retrieve_by_barcode {
769 my($self, $client, $user_session, $barcode) = @_;
771 $logger->debug("Searching for user with barcode $barcode");
772 my ($user_obj, $evt) = $apputils->checkses($user_session);
776 my $session = OpenSRF::AppSession->create("open-ils.storage");
778 # find the card with the given barcode
779 my $creq = $session->request(
780 "open-ils.storage.direct.actor.card.search.barcode.atomic",
782 my $card = $creq->gather(1);
784 if(!$card || !$card->[0]) {
785 $session->disconnect();
786 return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' );
790 my $user = flesh_user($card->usr(), $session);
792 $evt = $U->check_perms($user_obj->id, $user->home_ou, 'VIEW_USER');
795 $session->disconnect();
796 if(!$user) { return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' ); }
803 __PACKAGE__->register_method(
804 method => "get_user_by_id",
805 api_name => "open-ils.actor.user.retrieve",);
808 my ($self, $client, $user_session, $id) = @_;
810 my $user_obj = $apputils->check_user_session( $user_session );
812 return $apputils->simple_scalar_request(
814 "open-ils.storage.direct.actor.user.retrieve",
820 __PACKAGE__->register_method(
821 method => "get_org_types",
822 api_name => "open-ils.actor.org_types.retrieve",);
826 my($self, $client) = @_;
828 return $org_types if $org_types;
830 $apputils->simple_scalar_request(
832 "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
837 __PACKAGE__->register_method(
838 method => "get_user_profiles",
839 api_name => "open-ils.actor.user.profiles.retrieve",
843 sub get_user_profiles {
844 return $user_profiles if $user_profiles;
846 return $user_profiles =
847 $apputils->simple_scalar_request(
849 "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
854 __PACKAGE__->register_method(
855 method => "get_user_ident_types",
856 api_name => "open-ils.actor.user.ident_types.retrieve",
859 sub get_user_ident_types {
860 return $ident_types if $ident_types;
861 return $ident_types =
862 $apputils->simple_scalar_request(
864 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
870 __PACKAGE__->register_method(
871 method => "get_org_unit",
872 api_name => "open-ils.actor.org_unit.retrieve",
877 my( $self, $client, $user_session, $org_id ) = @_;
879 if(defined($user_session) && !defined($org_id)) {
881 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
882 if(!defined($org_id)) {
883 $org_id = $user_obj->home_ou;
888 my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
890 "open-ils.storage.direct.actor.org_unit.retrieve",
896 __PACKAGE__->register_method(
897 method => "search_org_unit",
898 api_name => "open-ils.actor.org_unit_list.search",
901 sub search_org_unit {
903 my( $self, $client, $field, $value ) = @_;
905 my $list = OpenILS::Application::AppUtils->simple_scalar_request(
907 "open-ils.storage.direct.actor.org_unit.search.$field.atomic",
916 __PACKAGE__->register_method(
917 method => "get_org_tree",
918 api_name => "open-ils.actor.org_tree.retrieve",
920 note => "Returns the entire org tree structure",
924 my( $self, $client) = @_;
927 $cache_client = OpenSRF::Utils::Cache->new("global", 0);
929 # see if it's in the cache
930 #warn "Getting ORG Tree\n";
931 my $tree = $cache_client->get_cache('orgtree');
933 #warn "Found orgtree in cache. returning...\n";
937 my $orglist = $apputils->simple_scalar_request(
939 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
942 #warn "found org list\n";
945 $tree = $self->build_org_tree($orglist);
946 $cache_client->put_cache('orgtree', $tree);
952 # turns an org list into an org tree
955 my( $self, $orglist) = @_;
957 return $orglist unless (
958 ref($orglist) and @$orglist > 1 );
961 $a->ou_type <=> $b->ou_type ||
962 $a->name cmp $b->name } @$orglist;
964 for my $org (@list) {
966 next unless ($org and defined($org->parent_ou));
967 my ($parent) = grep { $_->id == $org->parent_ou } @list;
970 $parent->children([]) unless defined($parent->children);
971 push( @{$parent->children}, $org );
979 __PACKAGE__->register_method(
980 method => "get_org_descendants",
981 api_name => "open-ils.actor.org_tree.descendants.retrieve"
984 # depth is optional. org_unit is the id
985 sub get_org_descendants {
986 my( $self, $client, $org_unit, $depth ) = @_;
987 my $orglist = $apputils->simple_scalar_request(
989 "open-ils.storage.actor.org_unit.descendants.atomic",
991 return $self->build_org_tree($orglist);
995 __PACKAGE__->register_method(
996 method => "get_org_ancestors",
997 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
1000 # depth is optional. org_unit is the id
1001 sub get_org_ancestors {
1002 my( $self, $client, $org_unit, $depth ) = @_;
1003 my $orglist = $apputils->simple_scalar_request(
1005 "open-ils.storage.actor.org_unit.ancestors.atomic",
1006 $org_unit, $depth );
1007 return $self->build_org_tree($orglist);
1011 __PACKAGE__->register_method(
1012 method => "get_standings",
1013 api_name => "open-ils.actor.standings.retrieve"
1018 return $user_standings if $user_standings;
1019 return $user_standings =
1020 $apputils->simple_scalar_request(
1022 "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
1027 __PACKAGE__->register_method(
1028 method => "get_my_org_path",
1029 api_name => "open-ils.actor.org_unit.full_path.retrieve"
1032 sub get_my_org_path {
1033 my( $self, $client, $user_session, $org_id ) = @_;
1034 my $user_obj = $apputils->check_user_session($user_session);
1035 if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
1037 return $apputils->simple_scalar_request(
1039 "open-ils.storage.actor.org_unit.full_path.atomic",
1044 __PACKAGE__->register_method(
1045 method => "patron_adv_search",
1046 api_name => "open-ils.actor.patron.search.advanced" );
1047 sub patron_adv_search {
1048 my( $self, $client, $auth, $search_hash, $search_limit, $search_sort ) = @_;
1049 my $e = OpenILS::Utils::Editor->new(authtoken=>$auth);
1050 return $e->event unless $e->checkauth;
1051 return $e->event unless $e->allowed('VIEW_USER');
1053 "open-ils.storage.actor.user.crazy_search",
1054 $search_hash, $search_limit, $search_sort);
1059 sub _verify_password {
1060 my($user_session, $password) = @_;
1061 my $user_obj = $apputils->check_user_session($user_session);
1063 #grab the user with password
1064 $user_obj = $apputils->simple_scalar_request(
1066 "open-ils.storage.direct.actor.user.retrieve",
1069 if($user_obj->passwd eq $password) {
1077 __PACKAGE__->register_method(
1078 method => "update_password",
1079 api_name => "open-ils.actor.user.password.update");
1081 __PACKAGE__->register_method(
1082 method => "update_password",
1083 api_name => "open-ils.actor.user.username.update");
1085 __PACKAGE__->register_method(
1086 method => "update_password",
1087 api_name => "open-ils.actor.user.email.update");
1089 sub update_password {
1090 my( $self, $client, $user_session, $new_value, $current_password ) = @_;
1094 my $user_obj = $apputils->check_user_session($user_session);
1096 if($self->api_name =~ /password/o) {
1098 #make sure they know the current password
1099 if(!_verify_password($user_session, md5_hex($current_password))) {
1100 return OpenILS::Event->new('INCORRECT_PASSWORD');
1103 $logger->debug("update_password setting new password $new_value");
1104 $user_obj->passwd($new_value);
1106 } elsif($self->api_name =~ /username/o) {
1107 my $users = search_username(undef, undef, $new_value);
1108 if( $users and $users->[0] ) {
1109 return OpenILS::Event->new('USERNAME_EXISTS');
1111 $user_obj->usrname($new_value);
1113 } elsif($self->api_name =~ /email/o) {
1114 #warn "Updating email to $new_value\n";
1115 $user_obj->email($new_value);
1118 my $session = $apputils->start_db_session();
1120 ( $user_obj, $evt ) = _update_patron($session, $user_obj, $user_obj, 1);
1121 return $evt if $evt;
1123 $apputils->commit_db_session($session);
1125 if($user_obj) { return 1; }
1130 __PACKAGE__->register_method(
1131 method => "check_user_perms",
1132 api_name => "open-ils.actor.user.perm.check",
1133 notes => <<" NOTES");
1134 Takes a login session, user id, an org id, and an array of perm type strings. For each
1135 perm type, if the user does *not* have the given permission it is added
1136 to a list which is returned from the method. If all permissions
1137 are allowed, an empty list is returned
1138 if the logged in user does not match 'user_id', then the logged in user must
1139 have VIEW_PERMISSION priveleges.
1142 sub check_user_perms {
1143 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1145 my( $staff, $evt ) = $apputils->checkses($login_session);
1146 return $evt if $evt;
1148 if($staff->id ne $user_id) {
1149 if( my $evt = $apputils->check_perms(
1150 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1156 for my $perm (@$perm_types) {
1157 if($apputils->check_perms($user_id, $org_id, $perm)) {
1158 push @not_allowed, $perm;
1162 return \@not_allowed
1165 __PACKAGE__->register_method(
1166 method => "check_user_perms2",
1167 api_name => "open-ils.actor.user.perm.check.multi_org",
1169 Checks the permissions on a list of perms and orgs for a user
1170 @param authtoken The login session key
1171 @param user_id The id of the user to check
1172 @param orgs The array of org ids
1173 @param perms The array of permission names
1174 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1175 if the logged in user does not match 'user_id', then the logged in user must
1176 have VIEW_PERMISSION priveleges.
1179 sub check_user_perms2 {
1180 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1182 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1183 $authtoken, $user_id, 'VIEW_PERMISSION' );
1184 return $evt if $evt;
1187 for my $org (@$orgs) {
1188 for my $perm (@$perms) {
1189 if($apputils->check_perms($user_id, $org, $perm)) {
1190 push @not_allowed, [ $org, $perm ];
1195 return \@not_allowed
1199 __PACKAGE__->register_method(
1200 method => 'check_user_perms3',
1201 api_name => 'open-ils.actor.user.perm.highest_org',
1203 Returns the highest org unit id at which a user has a given permission
1204 If the requestor does not match the target user, the requestor must have
1205 'VIEW_PERMISSION' rights at the home org unit of the target user
1206 @param authtoken The login session key
1207 @param userid The id of the user in question
1208 @param perm The permission to check
1209 @return The org unit highest in the org tree within which the user has
1210 the requested permission
1213 sub check_user_perms3 {
1214 my( $self, $client, $authtoken, $userid, $perm ) = @_;
1216 my( $staff, $target, $org, $evt );
1218 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1219 $authtoken, $userid, 'VIEW_PERMISSION' );
1220 return $evt if $evt;
1222 my $tree = $self->get_org_tree();
1223 return _find_highest_perm_org( $perm, $userid, $target->home_ou, $tree );
1227 sub _find_highest_perm_org {
1228 my ( $perm, $userid, $start_org, $org_tree ) = @_;
1229 my $org = $apputils->find_org($org_tree, $start_org );
1233 last if ($apputils->check_perms( $userid, $org->id, $perm )); # perm failed
1235 $org = $apputils->find_org( $org_tree, $org->parent_ou() );
1241 __PACKAGE__->register_method(
1242 method => 'check_user_perms4',
1243 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1245 Returns the highest org unit id at which a user has a given permission
1246 If the requestor does not match the target user, the requestor must have
1247 'VIEW_PERMISSION' rights at the home org unit of the target user
1248 @param authtoken The login session key
1249 @param userid The id of the user in question
1250 @param perms An array of perm names to check
1251 @return An array of orgId's representing the org unit
1252 highest in the org tree within which the user has the requested permission
1253 The arrah of orgId's has matches the order of the perms array
1256 sub check_user_perms4 {
1257 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1259 my( $staff, $target, $org, $evt );
1261 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1262 $authtoken, $userid, 'VIEW_PERMISSION' );
1263 return $evt if $evt;
1266 return [] unless ref($perms);
1267 my $tree = $self->get_org_tree();
1269 for my $p (@$perms) {
1270 push( @arr, _find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1278 __PACKAGE__->register_method(
1279 method => "user_fines_summary",
1280 api_name => "open-ils.actor.user.fines.summary",
1281 notes => <<" NOTES");
1282 Returns a short summary of the users total open fines, excluding voided fines
1283 Params are login_session, user_id
1284 Returns a 'mous' object.
1287 sub user_fines_summary {
1288 my( $self, $client, $login_session, $user_id ) = @_;
1290 my $user_obj = $apputils->check_user_session($login_session);
1291 if($user_obj->id ne $user_id) {
1292 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_FINES_SUMMARY")) {
1293 return OpenILS::Perm->new("VIEW_USER_FINES_SUMMARY");
1297 return $apputils->simple_scalar_request(
1299 "open-ils.storage.direct.money.open_user_summary.search.usr",
1307 __PACKAGE__->register_method(
1308 method => "user_transactions",
1309 api_name => "open-ils.actor.user.transactions",
1310 notes => <<" NOTES");
1311 Returns a list of open user transactions (mbts objects);
1312 Params are login_session, user_id
1313 Optional third parameter is the transactions type. defaults to all
1316 __PACKAGE__->register_method(
1317 method => "user_transactions",
1318 api_name => "open-ils.actor.user.transactions.have_charge",
1319 notes => <<" NOTES");
1320 Returns a list of all open user transactions (mbts objects) that have an initial charge
1321 Params are login_session, user_id
1322 Optional third parameter is the transactions type. defaults to all
1325 __PACKAGE__->register_method(
1326 method => "user_transactions",
1327 api_name => "open-ils.actor.user.transactions.have_balance",
1328 notes => <<" NOTES");
1329 Returns a list of all open user transactions (mbts objects) that have a balance
1330 Params are login_session, user_id
1331 Optional third parameter is the transactions type. defaults to all
1334 __PACKAGE__->register_method(
1335 method => "user_transactions",
1336 api_name => "open-ils.actor.user.transactions.fleshed",
1337 notes => <<" NOTES");
1338 Returns an object/hash of transaction, circ, title where transaction = an open
1339 user transactions (mbts objects), circ is the attached circluation, and title
1340 is the title the circ points to
1341 Params are login_session, user_id
1342 Optional third parameter is the transactions type. defaults to all
1345 __PACKAGE__->register_method(
1346 method => "user_transactions",
1347 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1348 notes => <<" NOTES");
1349 Returns an object/hash of transaction, circ, title where transaction = an open
1350 user transactions that has an initial charge (mbts objects), circ is the
1351 attached circluation, and title is the title the circ points to
1352 Params are login_session, user_id
1353 Optional third parameter is the transactions type. defaults to all
1356 __PACKAGE__->register_method(
1357 method => "user_transactions",
1358 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1359 notes => <<" NOTES");
1360 Returns an object/hash of transaction, circ, title where transaction = an open
1361 user transaction that has a balance (mbts objects), circ is the attached
1362 circluation, and title is the title the circ points to
1363 Params are login_session, user_id
1364 Optional third parameter is the transaction type. defaults to all
1367 __PACKAGE__->register_method(
1368 method => "user_transactions",
1369 api_name => "open-ils.actor.user.transactions.count",
1370 notes => <<" NOTES");
1371 Returns an object/hash of transaction, circ, title where transaction = an open
1372 user transactions (mbts objects), circ is the attached circluation, and title
1373 is the title the circ points to
1374 Params are login_session, user_id
1375 Optional third parameter is the transactions type. defaults to all
1378 __PACKAGE__->register_method(
1379 method => "user_transactions",
1380 api_name => "open-ils.actor.user.transactions.have_charge.count",
1381 notes => <<" NOTES");
1382 Returns an object/hash of transaction, circ, title where transaction = an open
1383 user transactions that has an initial charge (mbts objects), circ is the
1384 attached circluation, and title is the title the circ points to
1385 Params are login_session, user_id
1386 Optional third parameter is the transactions type. defaults to all
1389 __PACKAGE__->register_method(
1390 method => "user_transactions",
1391 api_name => "open-ils.actor.user.transactions.have_balance.count",
1392 notes => <<" NOTES");
1393 Returns an object/hash of transaction, circ, title where transaction = an open
1394 user transaction that has a balance (mbts objects), circ is the attached
1395 circluation, and title is the title the circ points to
1396 Params are login_session, user_id
1397 Optional third parameter is the transaction type. defaults to all
1400 __PACKAGE__->register_method(
1401 method => "user_transactions",
1402 api_name => "open-ils.actor.user.transactions.have_balance.total",
1403 notes => <<" NOTES");
1404 Returns an object/hash of transaction, circ, title where transaction = an open
1405 user transaction that has a balance (mbts objects), circ is the attached
1406 circluation, and title is the title the circ points to
1407 Params are login_session, user_id
1408 Optional third parameter is the transaction type. defaults to all
1413 sub user_transactions {
1414 my( $self, $client, $login_session, $user_id, $type ) = @_;
1416 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1417 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1418 return $evt if $evt;
1420 my $api = $self->api_name();
1424 if(defined($type)) { @xact = (xact_type => $type);
1426 } else { @xact = (); }
1428 if($api =~ /have_charge/o) {
1430 $trans = $apputils->simple_scalar_request(
1432 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1433 { usr => $user_id, total_owed => { ">" => 0 }, @xact });
1435 } elsif($api =~ /have_balance/o) {
1437 $trans = $apputils->simple_scalar_request(
1439 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1440 { usr => $user_id, balance_owed => { "<>" => 0 }, @xact });
1444 $trans = $apputils->simple_scalar_request(
1446 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1447 { usr => $user_id, @xact });
1450 if($api =~ /total/o) {
1452 for my $t (@$trans) {
1453 $total += $t->balance_owed;
1456 $logger->debug("Total balance owed by user $user_id: $total");
1460 if($api =~ /count/o) { return scalar @$trans; }
1461 if($api !~ /fleshed/o) { return $trans; }
1464 for my $t (@$trans) {
1466 if( $t->xact_type ne 'circulation' ) {
1467 push @resp, {transaction => $t};
1471 my $circ = $apputils->simple_scalar_request(
1473 "open-ils.storage.direct.action.circulation.retrieve",
1478 my $title = $apputils->simple_scalar_request(
1480 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1481 $circ->target_copy );
1485 my $u = OpenILS::Utils::ModsParser->new();
1486 $u->start_mods_batch($title->marc());
1487 my $mods = $u->finish_mods_batch();
1489 push @resp, {transaction => $t, circ => $circ, record => $mods };
1497 __PACKAGE__->register_method(
1498 method => "user_transaction_retrieve",
1499 api_name => "open-ils.actor.user.transaction.fleshed.retrieve",
1501 notes => <<" NOTES");
1502 Returns a fleshedtransaction record
1504 __PACKAGE__->register_method(
1505 method => "user_transaction_retrieve",
1506 api_name => "open-ils.actor.user.transaction.retrieve",
1508 notes => <<" NOTES");
1509 Returns a transaction record
1511 sub user_transaction_retrieve {
1512 my( $self, $client, $login_session, $bill_id ) = @_;
1514 my $trans = $apputils->simple_scalar_request(
1516 "open-ils.storage.direct.money.billable_transaction_summary.retrieve",
1520 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1521 $login_session, $trans->usr, 'VIEW_USER_TRANSACTIONS' );
1522 return $evt if $evt;
1524 my $api = $self->api_name();
1525 if($api !~ /fleshed/o) { return $trans; }
1527 if( $trans->xact_type ne 'circulation' ) {
1528 $logger->debug("Returning non-circ transaction");
1529 return {transaction => $trans};
1532 my $circ = $apputils->simple_scalar_request(
1534 "open-ils.storage.direct.action.circulation.retrieve",
1537 return {transaction => $trans} unless $circ;
1538 $logger->debug("Found the circ transaction");
1540 my $title = $apputils->simple_scalar_request(
1542 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1543 $circ->target_copy );
1545 return {transaction => $trans, circ => $circ } unless $title;
1546 $logger->debug("Found the circ title");
1550 my $u = OpenILS::Utils::ModsParser->new();
1551 $u->start_mods_batch($title->marc());
1552 $mods = $u->finish_mods_batch();
1554 if ($title->id == -1) {
1555 my $copy = $apputils->simple_scalar_request(
1557 "open-ils.storage.direct.asset.copy.retrieve",
1558 $circ->target_copy );
1560 $mods = new Fieldmapper::metabib::virtual_record;
1562 $mods->title($copy->dummy_title);
1563 $mods->author($copy->dummy_author);
1567 $logger->debug("MODSized the circ title");
1569 return {transaction => $trans, circ => $circ, record => $mods };
1573 __PACKAGE__->register_method(
1574 method => "hold_request_count",
1575 api_name => "open-ils.actor.user.hold_requests.count",
1577 notes => <<" NOTES");
1578 Returns hold ready/total counts
1580 sub hold_request_count {
1581 my( $self, $client, $login_session, $userid ) = @_;
1583 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1584 $login_session, $userid, 'VIEW_HOLD' );
1585 return $evt if $evt;
1588 my $holds = $apputils->simple_scalar_request(
1590 "open-ils.storage.direct.action.hold_request.search_where.atomic",
1592 fulfillment_time => {"=" => undef } }
1596 for my $h (@$holds) {
1597 next unless $h->capture_time;
1599 my $copy = $apputils->simple_scalar_request(
1601 "open-ils.storage.direct.asset.copy.retrieve",
1605 if ($copy->status == 8) {
1610 return { total => scalar(@$holds), ready => scalar(@ready) };
1614 __PACKAGE__->register_method(
1615 method => "checkedout_count",
1616 api_name => "open-ils.actor.user.checked_out.count",
1618 notes => <<" NOTES");
1619 Returns a transaction record
1621 sub checkedout_count {
1622 my( $self, $client, $login_session, $userid ) = @_;
1624 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1625 $login_session, $userid, 'VIEW_CIRCULATIONS' );
1626 return $evt if $evt;
1628 my $circs = $apputils->simple_scalar_request(
1630 "open-ils.storage.direct.action.circulation.search_where.atomic",
1631 { usr => $userid, stop_fines => undef }
1632 #{ usr => $userid, checkin_time => {"=" => undef } }
1635 my $parser = DateTime::Format::ISO8601->new;
1638 for my $c (@$circs) {
1639 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1640 my $due = $due_dt->epoch;
1642 if ($due < DateTime->today->epoch) {
1647 return { total => scalar(@$circs), overdue => scalar(@overdue) };
1650 __PACKAGE__->register_method(
1651 method => "user_transaction_history",
1652 api_name => "open-ils.actor.user.transactions.history",
1654 notes => <<" NOTES");
1655 Returns a list of billable transaction ids for a user, optionally by type
1657 __PACKAGE__->register_method(
1658 method => "user_transaction_history",
1659 api_name => "open-ils.actor.user.transactions.history.have_charge",
1661 notes => <<" NOTES");
1662 Returns a list of billable transaction ids for a user that have an initial charge, optionally by type
1664 sub user_transaction_history {
1665 my( $self, $client, $login_session, $user_id, $type ) = @_;
1667 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1668 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1669 return $evt if $evt;
1671 my $api = $self->api_name();
1675 @xact = (xact_type => $type) if(defined($type));
1676 @charge = (total_owed => { ">" => 0}) if($api =~ /have_charge/);
1678 my $trans = $apputils->simple_scalar_request(
1680 "open-ils.storage.direct.money.billable_transaction_summary.search_where.atomic",
1681 { usr => $user_id, @xact, @charge }, { order_by => 'xact_start DESC' });
1683 return [ map { $_->id } @$trans ];
1687 __PACKAGE__->register_method(
1688 method => "user_perms",
1689 api_name => "open-ils.actor.permissions.user_perms.retrieve",
1691 notes => <<" NOTES");
1692 Returns a list of permissions
1695 my( $self, $client, $authtoken, $user ) = @_;
1697 my( $staff, $evt ) = $apputils->checkses($authtoken);
1698 return $evt if $evt;
1700 $user ||= $staff->id;
1702 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
1706 return $apputils->simple_scalar_request(
1708 "open-ils.storage.permission.user_perms.atomic",
1712 __PACKAGE__->register_method(
1713 method => "retrieve_perms",
1714 api_name => "open-ils.actor.permissions.retrieve",
1715 notes => <<" NOTES");
1716 Returns a list of permissions
1718 sub retrieve_perms {
1719 my( $self, $client ) = @_;
1720 return $apputils->simple_scalar_request(
1722 "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
1725 __PACKAGE__->register_method(
1726 method => "retrieve_groups",
1727 api_name => "open-ils.actor.groups.retrieve",
1728 notes => <<" NOTES");
1729 Returns a list of user groupss
1731 sub retrieve_groups {
1732 my( $self, $client ) = @_;
1733 return $apputils->simple_scalar_request(
1735 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1738 __PACKAGE__->register_method(
1739 method => "retrieve_org_address",
1740 api_name => "open-ils.actor.org_unit.address.retrieve",
1741 notes => <<' NOTES');
1742 Returns an org_unit address by ID
1743 @param An org_address ID
1745 sub retrieve_org_address {
1746 my( $self, $client, $id ) = @_;
1747 return $apputils->simple_scalar_request(
1749 "open-ils.storage.direct.actor.org_address.retrieve",
1754 __PACKAGE__->register_method(
1755 method => "retrieve_groups_tree",
1756 api_name => "open-ils.actor.groups.tree.retrieve",
1757 notes => <<" NOTES");
1758 Returns a list of user groups
1760 sub retrieve_groups_tree {
1761 my( $self, $client ) = @_;
1762 my $groups = $apputils->simple_scalar_request(
1764 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1765 return $self->build_group_tree($groups);
1769 # turns an org list into an org tree
1770 sub build_group_tree {
1772 my( $self, $grplist) = @_;
1774 return $grplist unless (
1775 ref($grplist) and @$grplist > 1 );
1777 my @list = sort { $a->name cmp $b->name } @$grplist;
1780 for my $grp (@list) {
1782 if ($grp and !defined($grp->parent)) {
1786 my ($parent) = grep { $_->id == $grp->parent} @list;
1788 $parent->children([]) unless defined($parent->children);
1789 push( @{$parent->children}, $grp );
1797 __PACKAGE__->register_method(
1798 method => "add_user_to_groups",
1799 api_name => "open-ils.actor.user.set_groups",
1800 notes => <<" NOTES");
1801 Adds a user to one or more permission groups
1804 sub add_user_to_groups {
1805 my( $self, $client, $authtoken, $userid, $groups ) = @_;
1807 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1808 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
1809 return $evt if $evt;
1811 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1812 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
1813 return $evt if $evt;
1815 $apputils->simplereq(
1817 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
1819 for my $group (@$groups) {
1820 my $link = Fieldmapper::permission::usr_grp_map->new;
1822 $link->usr($userid);
1824 my $id = $apputils->simplereq(
1826 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
1832 __PACKAGE__->register_method(
1833 method => "get_user_perm_groups",
1834 api_name => "open-ils.actor.user.get_groups",
1835 notes => <<" NOTES");
1836 Retrieve a user's permission groups.
1840 sub get_user_perm_groups {
1841 my( $self, $client, $authtoken, $userid ) = @_;
1843 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1844 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
1845 return $evt if $evt;
1847 return $apputils->simplereq(
1849 'open-ils.storage.direct.permission.usr_grp_map.search.usr.atomic', $userid );
1854 __PACKAGE__->register_method (
1855 method => 'register_workstation',
1856 api_name => 'open-ils.actor.workstation.register.override',
1857 signature => q/@see open-ils.actor.workstation.register/);
1859 __PACKAGE__->register_method (
1860 method => 'register_workstation',
1861 api_name => 'open-ils.actor.workstation.register',
1863 Registers a new workstion in the system
1864 @param authtoken The login session key
1865 @param name The name of the workstation id
1866 @param owner The org unit that owns this workstation
1867 @return The workstation id on success, WORKSTATION_NAME_EXISTS
1868 if the name is already in use.
1871 sub _register_workstation {
1872 my( $self, $connection, $authtoken, $name, $owner ) = @_;
1873 my( $requestor, $evt ) = $U->checkses($authtoken);
1874 return $evt if $evt;
1875 $evt = $U->check_perms($requestor->id, $owner, 'REGISTER_WORKSTATION');
1876 return $evt if $evt;
1878 my $ws = $U->storagereq(
1879 'open-ils.storage.direct.actor.workstation.search.name', $name );
1880 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS') if $ws;
1882 $ws = Fieldmapper::actor::workstation->new;
1883 $ws->owning_lib($owner);
1886 my $id = $U->storagereq(
1887 'open-ils.storage.direct.actor.workstation.create', $ws );
1888 return $U->DB_UPDATE_FAILED($ws) unless $id;
1894 sub register_workstation {
1895 my( $self, $conn, $authtoken, $name, $owner ) = @_;
1897 my $e = OpenILS::Utils::Editor->new(authtoken=>$authtoken, xact=>1);
1898 return $e->event unless $e->checkauth;
1899 return $e->event unless $e->allowed('REGISTER_WORKSTATION'); # XXX rely on editor perms
1900 my $existing = $e->search_actor_workstation({name => $name});
1903 if( $self->api_name =~ /override/o ) {
1904 return $e->event unless $e->allowed('DELETE_WORKSTATION'); # XXX rely on editor perms
1905 return $e->event unless $e->delete_actor_workstation($$existing[0]);
1907 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS')
1911 my $ws = Fieldmapper::actor::workstation->new;
1912 $ws->owning_lib($owner);
1914 $e->create_actor_workstation($ws) or return $e->event;
1916 return $ws->id; # note: editor sets the id on the new object for us
1920 __PACKAGE__->register_method (
1921 method => 'fetch_patron_note',
1922 api_name => 'open-ils.actor.note.retrieve.all',
1924 Returns a list of notes for a given user
1925 Requestor must have VIEW_USER permission if pub==false and
1926 @param authtoken The login session key
1927 @param args Hash of params including
1928 patronid : the patron's id
1929 pub : true if retrieving only public notes
1933 sub fetch_patron_note {
1934 my( $self, $conn, $authtoken, $args ) = @_;
1935 my $patronid = $$args{patronid};
1937 my($reqr, $evt) = $U->checkses($authtoken);
1940 ($patron, $evt) = $U->fetch_user($patronid);
1941 return $evt if $evt;
1944 if( $patronid ne $reqr->id ) {
1945 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
1946 return $evt if $evt;
1948 return $U->storagereq(
1949 'open-ils.storage.direct.actor.usr_note.search_where.atomic',
1950 { usr => $patronid, pub => 't' } );
1953 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
1954 return $evt if $evt;
1956 return $U->storagereq(
1957 'open-ils.storage.direct.actor.usr_note.search.usr.atomic', $patronid );
1960 __PACKAGE__->register_method (
1961 method => 'create_user_note',
1962 api_name => 'open-ils.actor.note.create',
1964 Creates a new note for the given user
1965 @param authtoken The login session key
1966 @param note The note object
1969 sub create_user_note {
1970 my( $self, $conn, $authtoken, $note ) = @_;
1971 my( $reqr, $patron, $evt ) =
1972 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
1973 return $evt if $evt;
1974 $logger->activity("user ".$reqr->id." creating note for user ".$note->usr);
1976 $note->pub('f') unless $note->pub;
1977 $note->creator($reqr->id);
1978 my $id = $U->storagereq(
1979 'open-ils.storage.direct.actor.usr_note.create', $note );
1980 return $U->DB_UPDATE_FAILED($note) unless $id;
1985 __PACKAGE__->register_method (
1986 method => 'delete_user_note',
1987 api_name => 'open-ils.actor.note.delete',
1989 Deletes a note for the given user
1990 @param authtoken The login session key
1991 @param noteid The note id
1994 sub delete_user_note {
1995 my( $self, $conn, $authtoken, $noteid ) = @_;
1997 my $note = $U->storagereq(
1998 'open-ils.storage.direct.actor.usr_note.retrieve', $noteid);
1999 return OpenILS::Event->new('ACTOR_USER_NOTE_NOT_FOUND') unless $note;
2001 my( $reqr, $patron, $evt ) =
2002 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
2003 return $evt if $evt;
2004 $logger->activity("user ".$reqr->id." deleting note [$noteid] for user ".$note->usr);
2006 my $stat = $U->storagereq(
2007 'open-ils.storage.direct.actor.usr_note.delete', $noteid );
2008 return $U->DB_UPDATE_FAILED($note) unless defined $stat;
2014 __PACKAGE__->register_method (
2015 method => 'create_closed_date',
2016 api_name => 'open-ils.actor.org_unit.closed_date.create',
2018 Creates a new closing entry for the given org_unit
2019 @param authtoken The login session key
2020 @param note The closed_date object
2023 sub create_closed_date {
2024 my( $self, $conn, $authtoken, $cd ) = @_;
2026 my( $user, $evt ) = $U->checkses($authtoken);
2027 return $evt if $evt;
2029 $evt = $U->check_perms($user->id, $cd->org_unit, 'CREATE_CLOSEING');
2030 return $evt if $evt;
2032 $logger->activity("user ".$user->id." creating library closing for ".$cd->org_unit);
2034 my $id = $U->storagereq(
2035 'open-ils.storage.direct.actor.org_unit.closed_date.create', $cd );
2036 return $U->DB_UPDATE_FAILED($cd) unless $id;
2041 __PACKAGE__->register_method (
2042 method => 'delete_closed_date',
2043 api_name => 'open-ils.actor.org_unit.closed_date.delete',
2045 Deletes a closing entry for the given org_unit
2046 @param authtoken The login session key
2047 @param noteid The close_date id
2050 sub delete_closed_date {
2051 my( $self, $conn, $authtoken, $cd ) = @_;
2053 my( $user, $evt ) = $U->checkses($authtoken);
2054 return $evt if $evt;
2057 ($cd_obj, $evt) = fetch_closed_date($cd);
2058 return $evt if $evt;
2060 $evt = $U->check_perms($user->id, $cd->org_unit, 'DELETE_CLOSEING');
2061 return $evt if $evt;
2063 $logger->activity("user ".$user->id." deleting library closing for ".$cd->org_unit);
2065 my $stat = $U->storagereq(
2066 'open-ils.storage.direct.actor.org_unit.closed_date.delete', $cd );
2067 return $U->DB_UPDATE_FAILED($cd) unless $stat;
2072 __PACKAGE__->register_method(
2073 method => 'usrname_exists',
2074 api_name => 'open-ils.actor.username.exists',
2076 Returns 1 if the requested username exists, returns 0 otherwise
2080 sub usrname_exists {
2081 my( $self, $conn, $usrname ) = @_;
2082 my $e = OpenILS::Utils::Editor->new;
2083 my $a = $e->search_actor_user({usrname => $usrname}, {idlist=>1});
2084 return 1 if $a and @$a;