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;
1629 my $circs = $apputils->simple_scalar_request(
1631 "open-ils.storage.direct.action.circulation.search_where.atomic",
1633 checkin_time => {"=" => undef } }
1636 my $parser = DateTime::Format::ISO8601->new;
1639 for my $c (@$circs) {
1640 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1641 my $due = $due_dt->epoch;
1643 if ($due < DateTime->today->epoch) {
1648 return { total => scalar(@$circs), overdue => scalar(@overdue) };
1651 __PACKAGE__->register_method(
1652 method => "user_transaction_history",
1653 api_name => "open-ils.actor.user.transactions.history",
1655 notes => <<" NOTES");
1656 Returns a list of billable transaction ids for a user, optionally by type
1658 __PACKAGE__->register_method(
1659 method => "user_transaction_history",
1660 api_name => "open-ils.actor.user.transactions.history.have_charge",
1662 notes => <<" NOTES");
1663 Returns a list of billable transaction ids for a user that have an initial charge, optionally by type
1665 sub user_transaction_history {
1666 my( $self, $client, $login_session, $user_id, $type ) = @_;
1668 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1669 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1670 return $evt if $evt;
1672 my $api = $self->api_name();
1676 @xact = (xact_type => $type) if(defined($type));
1677 @charge = (total_owed => { ">" => 0}) if($api =~ /have_charge/);
1679 my $trans = $apputils->simple_scalar_request(
1681 "open-ils.storage.direct.money.billable_transaction_summary.search_where.atomic",
1682 { usr => $user_id, @xact, @charge }, { order_by => 'xact_start DESC' });
1684 return [ map { $_->id } @$trans ];
1688 __PACKAGE__->register_method(
1689 method => "user_perms",
1690 api_name => "open-ils.actor.permissions.user_perms.retrieve",
1692 notes => <<" NOTES");
1693 Returns a list of permissions
1696 my( $self, $client, $authtoken, $user ) = @_;
1698 my( $staff, $evt ) = $apputils->checkses($authtoken);
1699 return $evt if $evt;
1701 $user ||= $staff->id;
1703 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
1707 return $apputils->simple_scalar_request(
1709 "open-ils.storage.permission.user_perms.atomic",
1713 __PACKAGE__->register_method(
1714 method => "retrieve_perms",
1715 api_name => "open-ils.actor.permissions.retrieve",
1716 notes => <<" NOTES");
1717 Returns a list of permissions
1719 sub retrieve_perms {
1720 my( $self, $client ) = @_;
1721 return $apputils->simple_scalar_request(
1723 "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
1726 __PACKAGE__->register_method(
1727 method => "retrieve_groups",
1728 api_name => "open-ils.actor.groups.retrieve",
1729 notes => <<" NOTES");
1730 Returns a list of user groupss
1732 sub retrieve_groups {
1733 my( $self, $client ) = @_;
1734 return $apputils->simple_scalar_request(
1736 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1739 __PACKAGE__->register_method(
1740 method => "retrieve_org_address",
1741 api_name => "open-ils.actor.org_unit.address.retrieve",
1742 notes => <<' NOTES');
1743 Returns an org_unit address by ID
1744 @param An org_address ID
1746 sub retrieve_org_address {
1747 my( $self, $client, $id ) = @_;
1748 return $apputils->simple_scalar_request(
1750 "open-ils.storage.direct.actor.org_address.retrieve",
1755 __PACKAGE__->register_method(
1756 method => "retrieve_groups_tree",
1757 api_name => "open-ils.actor.groups.tree.retrieve",
1758 notes => <<" NOTES");
1759 Returns a list of user groups
1761 sub retrieve_groups_tree {
1762 my( $self, $client ) = @_;
1763 my $groups = $apputils->simple_scalar_request(
1765 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1766 return $self->build_group_tree($groups);
1770 # turns an org list into an org tree
1771 sub build_group_tree {
1773 my( $self, $grplist) = @_;
1775 return $grplist unless (
1776 ref($grplist) and @$grplist > 1 );
1778 my @list = sort { $a->name cmp $b->name } @$grplist;
1781 for my $grp (@list) {
1783 if ($grp and !defined($grp->parent)) {
1787 my ($parent) = grep { $_->id == $grp->parent} @list;
1789 $parent->children([]) unless defined($parent->children);
1790 push( @{$parent->children}, $grp );
1798 __PACKAGE__->register_method(
1799 method => "add_user_to_groups",
1800 api_name => "open-ils.actor.user.set_groups",
1801 notes => <<" NOTES");
1802 Adds a user to one or more permission groups
1805 sub add_user_to_groups {
1806 my( $self, $client, $authtoken, $userid, $groups ) = @_;
1808 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1809 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
1810 return $evt if $evt;
1812 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1813 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
1814 return $evt if $evt;
1816 $apputils->simplereq(
1818 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
1820 for my $group (@$groups) {
1821 my $link = Fieldmapper::permission::usr_grp_map->new;
1823 $link->usr($userid);
1825 my $id = $apputils->simplereq(
1827 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
1833 __PACKAGE__->register_method(
1834 method => "get_user_perm_groups",
1835 api_name => "open-ils.actor.user.get_groups",
1836 notes => <<" NOTES");
1837 Retrieve a user's permission groups.
1841 sub get_user_perm_groups {
1842 my( $self, $client, $authtoken, $userid ) = @_;
1844 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1845 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
1846 return $evt if $evt;
1848 return $apputils->simplereq(
1850 'open-ils.storage.direct.permission.usr_grp_map.search.usr.atomic', $userid );
1855 __PACKAGE__->register_method (
1856 method => 'register_workstation',
1857 api_name => 'open-ils.actor.workstation.register.override',
1858 signature => q/@see open-ils.actor.workstation.register/);
1860 __PACKAGE__->register_method (
1861 method => 'register_workstation',
1862 api_name => 'open-ils.actor.workstation.register',
1864 Registers a new workstion in the system
1865 @param authtoken The login session key
1866 @param name The name of the workstation id
1867 @param owner The org unit that owns this workstation
1868 @return The workstation id on success, WORKSTATION_NAME_EXISTS
1869 if the name is already in use.
1872 sub _register_workstation {
1873 my( $self, $connection, $authtoken, $name, $owner ) = @_;
1874 my( $requestor, $evt ) = $U->checkses($authtoken);
1875 return $evt if $evt;
1876 $evt = $U->check_perms($requestor->id, $owner, 'REGISTER_WORKSTATION');
1877 return $evt if $evt;
1879 my $ws = $U->storagereq(
1880 'open-ils.storage.direct.actor.workstation.search.name', $name );
1881 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS') if $ws;
1883 $ws = Fieldmapper::actor::workstation->new;
1884 $ws->owning_lib($owner);
1887 my $id = $U->storagereq(
1888 'open-ils.storage.direct.actor.workstation.create', $ws );
1889 return $U->DB_UPDATE_FAILED($ws) unless $id;
1895 sub register_workstation {
1896 my( $self, $conn, $authtoken, $name, $owner ) = @_;
1898 my $e = OpenILS::Utils::Editor->new(authtoken=>$authtoken, xact=>1);
1899 return $e->event unless $e->checkauth;
1900 return $e->event unless $e->allowed('REGISTER_WORKSTATION'); # XXX rely on editor perms
1901 my $existing = $e->search_actor_workstation({name => $name});
1904 if( $self->api_name =~ /override/o ) {
1905 return $e->event unless $e->allowed('DELETE_WORKSTATION'); # XXX rely on editor perms
1906 return $e->event unless $e->delete_actor_workstation($$existing[0]);
1908 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS')
1912 my $ws = Fieldmapper::actor::workstation->new;
1913 $ws->owning_lib($owner);
1915 $e->create_actor_workstation($ws) or return $e->event;
1917 return $ws->id; # note: editor sets the id on the new object for us
1921 __PACKAGE__->register_method (
1922 method => 'fetch_patron_note',
1923 api_name => 'open-ils.actor.note.retrieve.all',
1925 Returns a list of notes for a given user
1926 Requestor must have VIEW_USER permission if pub==false and
1927 @param authtoken The login session key
1928 @param args Hash of params including
1929 patronid : the patron's id
1930 pub : true if retrieving only public notes
1934 sub fetch_patron_note {
1935 my( $self, $conn, $authtoken, $args ) = @_;
1936 my $patronid = $$args{patronid};
1938 my($reqr, $evt) = $U->checkses($authtoken);
1941 ($patron, $evt) = $U->fetch_user($patronid);
1942 return $evt if $evt;
1945 if( $patronid ne $reqr->id ) {
1946 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
1947 return $evt if $evt;
1949 return $U->storagereq(
1950 'open-ils.storage.direct.actor.usr_note.search_where.atomic',
1951 { usr => $patronid, pub => 't' } );
1954 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
1955 return $evt if $evt;
1957 return $U->storagereq(
1958 'open-ils.storage.direct.actor.usr_note.search.usr.atomic', $patronid );
1961 __PACKAGE__->register_method (
1962 method => 'create_user_note',
1963 api_name => 'open-ils.actor.note.create',
1965 Creates a new note for the given user
1966 @param authtoken The login session key
1967 @param note The note object
1970 sub create_user_note {
1971 my( $self, $conn, $authtoken, $note ) = @_;
1972 my( $reqr, $patron, $evt ) =
1973 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
1974 return $evt if $evt;
1975 $logger->activity("user ".$reqr->id." creating note for user ".$note->usr);
1977 $note->pub('f') unless $note->pub;
1978 $note->creator($reqr->id);
1979 my $id = $U->storagereq(
1980 'open-ils.storage.direct.actor.usr_note.create', $note );
1981 return $U->DB_UPDATE_FAILED($note) unless $id;
1986 __PACKAGE__->register_method (
1987 method => 'delete_user_note',
1988 api_name => 'open-ils.actor.note.delete',
1990 Deletes a note for the given user
1991 @param authtoken The login session key
1992 @param noteid The note id
1995 sub delete_user_note {
1996 my( $self, $conn, $authtoken, $noteid ) = @_;
1998 my $note = $U->storagereq(
1999 'open-ils.storage.direct.actor.usr_note.retrieve', $noteid);
2000 return OpenILS::Event->new('ACTOR_USER_NOTE_NOT_FOUND') unless $note;
2002 my( $reqr, $patron, $evt ) =
2003 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
2004 return $evt if $evt;
2005 $logger->activity("user ".$reqr->id." deleting note [$noteid] for user ".$note->usr);
2007 my $stat = $U->storagereq(
2008 'open-ils.storage.direct.actor.usr_note.delete', $noteid );
2009 return $U->DB_UPDATE_FAILED($note) unless defined $stat;
2015 __PACKAGE__->register_method (
2016 method => 'create_closed_date',
2017 api_name => 'open-ils.actor.org_unit.closed_date.create',
2019 Creates a new closing entry for the given org_unit
2020 @param authtoken The login session key
2021 @param note The closed_date object
2024 sub create_closed_date {
2025 my( $self, $conn, $authtoken, $cd ) = @_;
2027 my( $user, $evt ) = $U->checkses($authtoken);
2028 return $evt if $evt;
2030 $evt = $U->check_perms($user->id, $cd->org_unit, 'CREATE_CLOSEING');
2031 return $evt if $evt;
2033 $logger->activity("user ".$user->id." creating library closing for ".$cd->org_unit);
2035 my $id = $U->storagereq(
2036 'open-ils.storage.direct.actor.org_unit.closed_date.create', $cd );
2037 return $U->DB_UPDATE_FAILED($cd) unless $id;
2042 __PACKAGE__->register_method (
2043 method => 'delete_closed_date',
2044 api_name => 'open-ils.actor.org_unit.closed_date.delete',
2046 Deletes a closing entry for the given org_unit
2047 @param authtoken The login session key
2048 @param noteid The close_date id
2051 sub delete_closed_date {
2052 my( $self, $conn, $authtoken, $cd ) = @_;
2054 my( $user, $evt ) = $U->checkses($authtoken);
2055 return $evt if $evt;
2058 ($cd_obj, $evt) = fetch_closed_date($cd);
2059 return $evt if $evt;
2061 $evt = $U->check_perms($user->id, $cd->org_unit, 'DELETE_CLOSEING');
2062 return $evt if $evt;
2064 $logger->activity("user ".$user->id." deleting library closing for ".$cd->org_unit);
2066 my $stat = $U->storagereq(
2067 'open-ils.storage.direct.actor.org_unit.closed_date.delete', $cd );
2068 return $U->DB_UPDATE_FAILED($cd) unless $stat;
2073 __PACKAGE__->register_method(
2074 method => 'usrname_exists',
2075 api_name => 'open-ils.actor.username.exists',
2077 Returns 1 if the requested username exists, returns 0 otherwise
2081 sub usrname_exists {
2082 my( $self, $conn, $usrname ) = @_;
2083 my $e = OpenILS::Utils::Editor->new;
2084 my $a = $e->search_actor_user({usrname => $usrname}, {idlist=>1});
2085 return 1 if $a and @$a;