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::Utils::ModsParser;
17 use OpenSRF::Utils::Logger qw/$logger/;
18 use OpenSRF::Utils qw/:datetime/;
20 use OpenSRF::Utils::Cache;
23 use DateTime::Format::ISO8601;
25 use OpenILS::Application::Actor::Container;
26 use OpenILS::Application::Actor::ClosedDates;
28 use OpenILS::Utils::Editor qw/:funcs/;
30 use OpenILS::Application::Actor::UserGroups;
32 OpenILS::Application::Actor::Container->initialize();
33 OpenILS::Application::Actor::UserGroups->initialize();
34 OpenILS::Application::Actor::ClosedDates->initialize();
37 my $apputils = "OpenILS::Application::AppUtils";
40 sub _d { warn "Patron:\n" . Dumper(shift()); }
45 my $set_user_settings;
48 __PACKAGE__->register_method(
49 method => "set_user_settings",
50 api_name => "open-ils.actor.patron.settings.update",
52 sub set_user_settings {
53 my( $self, $client, $user_session, $uid, $settings ) = @_;
55 $logger->debug("Setting user settings: $user_session, $uid, " . Dumper($settings));
57 my( $staff, $user, $evt ) =
58 $apputils->checkses_requestor( $user_session, $uid, 'UPDATE_USER' );
63 # [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
66 [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
68 $logger->activity("User " . $staff->id . " updating user $uid settings with: " . Dumper(\@params));
70 return $apputils->simplereq(
72 'open-ils.storage.direct.actor.user_setting.batch.merge', @params );
78 __PACKAGE__->register_method(
79 method => "set_ou_settings",
80 api_name => "open-ils.actor.org_unit.settings.update",
83 my( $self, $client, $user_session, $ouid, $settings ) = @_;
85 my( $staff, $evt ) = $apputils->checkses( $user_session );
87 $evt = $apputils->check_perms( $staff->id, $ouid, 'UPDATE_ORG_UNIT' );
92 map { [{ org_unit => $ouid, name => $_}, {value => $$settings{$_}}] } keys %$settings;
94 $logger->activity("Updating org unit [$ouid] settings with: " . Dumper($params));
96 return $apputils->simplereq(
98 'open-ils.storage.direct.actor.org_unit_setting.merge', @$params );
102 my $fetch_user_settings;
103 my $fetch_ou_settings;
105 __PACKAGE__->register_method(
106 method => "user_settings",
107 api_name => "open-ils.actor.patron.settings.retrieve",
110 my( $self, $client, $user_session, $uid ) = @_;
112 my( $staff, $user, $evt ) =
113 $apputils->checkses_requestor( $user_session, $uid, 'VIEW_USER' );
116 $logger->debug("User " . $staff->id . " fetching user $uid\n");
117 my $s = $apputils->simplereq(
119 'open-ils.storage.direct.actor.user_setting.search.usr.atomic',$uid );
121 return { map { ($_->name,$_->value) } @$s };
126 __PACKAGE__->register_method(
127 method => "ou_settings",
128 api_name => "open-ils.actor.org_unit.settings.retrieve",
131 my( $self, $client, $ouid ) = @_;
133 $logger->info("Fetching org unit settings for org $ouid");
135 my $s = $apputils->simplereq(
137 'open-ils.storage.direct.actor.org_unit_setting.search.org_unit.atomic', $ouid);
139 return { map { ($_->name,$_->value) } @$s };
142 __PACKAGE__->register_method (
143 method => "ou_setting_delete",
144 api_name => 'open-ils.actor.org_setting.delete',
146 Deletes a specific org unit setting for a specific location
147 @param authtoken The login session key
148 @param orgid The org unit whose setting we're changing
149 @param setting The name of the setting to delete
150 @return True value on success.
154 sub ou_setting_delete {
155 my( $self, $conn, $authtoken, $orgid, $setting ) = @_;
156 my( $reqr, $evt) = $U->checkses($authtoken);
158 $evt = $U->check_perms($reqr->id, $orgid, 'UPDATE_ORG_SETTING');
161 my $id = $U->storagereq(
162 'open-ils.storage.id_list.actor.org_unit_setting.search_where',
163 { name => $setting, org_unit => $orgid } );
165 $logger->debug("Retrieved setting $id in org unit setting delete");
167 my $s = $U->storagereq(
168 'open-ils.storage.direct.actor.org_unit_setting.delete', $id );
170 $logger->activity("User ".$reqr->id." deleted org unit setting $id") if $s;
176 __PACKAGE__->register_method(
177 method => "update_patron",
178 api_name => "open-ils.actor.patron.update",);
181 my( $self, $client, $user_session, $patron ) = @_;
183 my $session = $apputils->start_db_session();
186 $logger->info("Creating new patron...") if $patron->isnew;
187 $logger->info("Updating Patron: " . $patron->id) unless $patron->isnew;
189 my( $user_obj, $evt ) = $U->checkses($user_session);
192 # XXX does this user have permission to add/create users. Granularity?
193 # $new_patron is the patron in progress. $patron is the original patron
194 # passed in with the method. new_patron will change as the components
195 # of patron are added/updated.
199 # unflesh the real items on the patron
200 $patron->card( $patron->card->id ) if(ref($patron->card));
201 $patron->billing_address( $patron->billing_address->id )
202 if(ref($patron->billing_address));
203 $patron->mailing_address( $patron->mailing_address->id )
204 if(ref($patron->mailing_address));
206 # create/update the patron first so we can use his id
207 if($patron->isnew()) {
208 ( $new_patron, $evt ) = _add_patron($session, _clone_patron($patron), $user_obj);
210 } else { $new_patron = $patron; }
212 ( $new_patron, $evt ) = _add_update_addresses($session, $patron, $new_patron, $user_obj);
215 ( $new_patron, $evt ) = _add_update_cards($session, $patron, $new_patron, $user_obj);
218 ( $new_patron, $evt ) = _add_survey_responses($session, $patron, $new_patron, $user_obj);
221 # re-update the patron if anything has happened to him during this process
222 if($new_patron->ischanged()) {
223 ( $new_patron, $evt ) = _update_patron($session, $new_patron, $user_obj);
227 #$session = OpenSRF::AppSession->create("open-ils.storage"); # why did i put this here?
229 ($new_patron, $evt) = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
232 ($new_patron, $evt) = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
235 ($new_patron, $evt) = _create_standing_penalties($session, $user_session, $patron, $new_patron, $user_obj);
238 $logger->activity("user ".$user_obj->id." updating/creating user ".$new_patron->id);
239 $apputils->commit_db_session($session);
241 #warn "Patron Update/Create complete\n";
242 return flesh_user($new_patron->id());
248 __PACKAGE__->register_method(
249 method => "user_retrieve_fleshed_by_id",
250 api_name => "open-ils.actor.user.fleshed.retrieve",);
252 sub user_retrieve_fleshed_by_id {
253 my( $self, $client, $user_session, $user_id ) = @_;
255 my( $requestor, $target, $evt ) = $apputils->
256 checkses_requestor( $user_session, $user_id, 'VIEW_USER' );
259 return flesh_user($user_id);
263 # fleshes: card, cards, address, addresses, stat_cat_entries, standing_penalties
271 $session = OpenSRF::AppSession->create("open-ils.storage");
275 # grab the user with the given id
276 my $ureq = $session->request(
277 "open-ils.storage.direct.actor.user.retrieve", $id);
278 my $user = $ureq->gather(1);
280 if(!$user) { return undef; }
283 my $cards_req = $session->request(
284 "open-ils.storage.direct.actor.card.search.usr.atomic",
286 $user->cards( $cards_req->gather(1) );
288 for my $c(@{$user->cards}) {
289 if($c->id == $user->card || $c->id eq $user->card ) {
290 #warn "Setting my card to " . $c->id . "\n";
295 my $add_req = $session->request(
296 "open-ils.storage.direct.actor.user_address.search.usr.atomic",
298 $user->addresses( $add_req->gather(1) );
300 if( @{$user->addresses} ) {
301 if( ! grep { $_->id eq $user->billing_address } @{$user->addresses} ) {
302 my $ba = $session->request(
303 'open-ils.storage.direct.actor.user_address.retrieve',
304 $user->billing_address)->gather(1);
305 push( @{$user->addresses}, $ba );
308 if( ! grep { $_->id eq $user->mailing_address } @{$user->addresses} ) {
309 my $ba = $session->request(
310 'open-ils.storage.direct.actor.user_address.retrieve',
311 $user->mailing_address)->gather(1);
312 push( @{$user->addresses}, $ba );
317 for my $c(@{$user->addresses}) {
318 if($c->id eq $user->billing_address ) { $user->billing_address($c); }
319 if($c->id eq $user->mailing_address ) { $user->mailing_address($c); }
322 my $stat_req = $session->request(
323 "open-ils.storage.direct.actor.stat_cat_entry_user_map.search.target_usr.atomic",
325 $user->stat_cat_entries($stat_req->gather(1));
327 my $standing_penalties_req = $session->request(
328 "open-ils.storage.direct.actor.user_standing_penalty.search.usr.atomic",
330 $user->standing_penalties($standing_penalties_req->gather(1));
332 if($kill) { $session->disconnect(); }
333 $user->clear_passwd();
339 # clone and clear stuff that would break the database
343 my $new_patron = $patron->clone;
345 # Using the Fieldmapper clone method
346 #my $new_patron = Fieldmapper::actor::user->new();
348 #my $fmap = $Fieldmapper::fieldmap;
349 #no strict; # shallow clone, may be useful in the fieldmapper
351 # (keys %{$fmap->{"Fieldmapper::actor::user"}->{'fields'}}) {
352 # $new_patron->$field( $patron->$field() );
357 $new_patron->clear_billing_address();
358 $new_patron->clear_mailing_address();
359 $new_patron->clear_addresses();
360 $new_patron->clear_card();
361 $new_patron->clear_cards();
362 $new_patron->clear_id();
363 $new_patron->clear_isnew();
364 $new_patron->clear_ischanged();
365 $new_patron->clear_isdeleted();
366 $new_patron->clear_stat_cat_entries();
367 $new_patron->clear_permissions();
368 $new_patron->clear_standing_penalties();
378 my $user_obj = shift;
380 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'CREATE_USER');
381 return (undef, $evt) if $evt;
383 my $ex = $session->request(
384 'open-ils.storage.direct.actor.user.search.usrname', $patron->usrname())->gather(1);
386 return (undef, OpenILS::Event->new('USERNAME_EXISTS'));
389 $logger->info("Creating new user in the DB with username: ".$patron->usrname());
391 my $id = $session->request(
392 "open-ils.storage.direct.actor.user.create", $patron)->gather(1);
393 return (undef, $U->DB_UPDATE_FAILED($patron)) unless $id;
395 $logger->info("Successfully created new user [$id] in DB");
397 return ( $session->request(
398 "open-ils.storage.direct.actor.user.retrieve", $id)->gather(1), undef );
403 my( $session, $patron, $user_obj, $noperm) = @_;
405 $logger->info("Updating patron ".$patron->id." in DB");
408 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'UPDATE_USER');
409 return (undef, $evt) if $evt;
412 # update the password by itself to avoid the password protection magic
413 if( $patron->passwd ) {
414 my $s = $session->request(
415 'open-ils.storage.direct.actor.user.remote_update',
416 {id => $patron->id}, {passwd => $patron->passwd})->gather(1);
417 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($s);
418 $patron->clear_passwd;
421 if(!$patron->ident_type) {
422 $patron->clear_ident_type;
423 $patron->clear_ident_value;
426 if(!$patron->ident_type2) {
427 $patron->clear_ident_type2;
428 $patron->clear_ident_value2;
431 my $stat = $session->request(
432 "open-ils.storage.direct.actor.user.update",$patron )->gather(1);
433 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($stat);
439 sub _add_update_addresses {
443 my $new_patron = shift;
447 my $current_id; # id of the address before creation
449 for my $address (@{$patron->addresses()}) {
451 next unless ref $address;
452 $current_id = $address->id();
454 if( $patron->billing_address() and
455 $patron->billing_address() == $current_id ) {
456 $logger->info("setting billing addr to $current_id");
457 $new_patron->billing_address($address->id());
458 $new_patron->ischanged(1);
461 if( $patron->mailing_address() and
462 $patron->mailing_address() == $current_id ) {
463 $new_patron->mailing_address($address->id());
464 $logger->info("setting mailing addr to $current_id");
465 $new_patron->ischanged(1);
469 if($address->isnew()) {
471 $address->usr($new_patron->id());
473 ($address, $evt) = _add_address($session,$address);
474 return (undef, $evt) if $evt;
476 # we need to get the new id
477 if( $patron->billing_address() and
478 $patron->billing_address() == $current_id ) {
479 $new_patron->billing_address($address->id());
480 $logger->info("setting billing addr to $current_id");
481 $new_patron->ischanged(1);
484 if( $patron->mailing_address() and
485 $patron->mailing_address() == $current_id ) {
486 $new_patron->mailing_address($address->id());
487 $logger->info("setting mailing addr to $current_id");
488 $new_patron->ischanged(1);
491 } elsif($address->ischanged() ) {
493 ($address, $evt) = _update_address($session, $address);
494 return (undef, $evt) if $evt;
496 } elsif($address->isdeleted() ) {
498 if( $address->id() == $new_patron->mailing_address() ) {
499 $new_patron->clear_mailing_address();
500 ($new_patron, $evt) = _update_patron($session, $new_patron);
501 return (undef, $evt) if $evt;
504 if( $address->id() == $new_patron->billing_address() ) {
505 $new_patron->clear_billing_address();
506 ($new_patron, $evt) = _update_patron($session, $new_patron);
507 return (undef, $evt) if $evt;
510 $evt = _delete_address($session, $address);
511 return (undef, $evt) if $evt;
515 return ( $new_patron, undef );
519 # adds an address to the db and returns the address with new id
521 my($session, $address) = @_;
522 $address->clear_id();
524 $logger->info("Creating new address at street ".$address->street1);
526 # put the address into the database
527 my $id = $session->request(
528 "open-ils.storage.direct.actor.user_address.create", $address )->gather(1);
529 return (undef, $U->DB_UPDATE_FAILED($address)) unless $id;
532 return ($address, undef);
536 sub _update_address {
537 my( $session, $address ) = @_;
539 $logger->info("Updating address ".$address->id." in the DB");
541 my $stat = $session->request(
542 "open-ils.storage.direct.actor.user_address.update", $address )->gather(1);
544 return (undef, $U->DB_UPDATE_FAILED($address)) unless defined($stat);
545 return ($address, undef);
550 sub _add_update_cards {
554 my $new_patron = shift;
558 my $virtual_id; #id of the card before creation
559 for my $card (@{$patron->cards()}) {
561 $card->usr($new_patron->id());
563 if(ref($card) and $card->isnew()) {
565 $virtual_id = $card->id();
566 ( $card, $evt ) = _add_card($session,$card);
567 return (undef, $evt) if $evt;
569 #if(ref($patron->card)) { $patron->card($patron->card->id); }
570 if($patron->card() == $virtual_id) {
571 $new_patron->card($card->id());
572 $new_patron->ischanged(1);
575 } elsif( ref($card) and $card->ischanged() ) {
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",
876 my( $self, $client, $user_session, $org_id ) = @_;
877 my $e = new_editor(authtoken => $user_session);
879 return $e->event unless $e->checkauth;
880 $org_id = $e->requestor->ws_ou;
882 my $o = $e->retrieve_actor_org_unit($org_id)
887 __PACKAGE__->register_method(
888 method => "search_org_unit",
889 api_name => "open-ils.actor.org_unit_list.search",
892 sub search_org_unit {
894 my( $self, $client, $field, $value ) = @_;
896 my $list = OpenILS::Application::AppUtils->simple_scalar_request(
898 "open-ils.storage.direct.actor.org_unit.search.$field.atomic",
907 __PACKAGE__->register_method(
908 method => "get_org_tree",
909 api_name => "open-ils.actor.org_tree.retrieve",
911 note => "Returns the entire org tree structure",
915 my( $self, $client) = @_;
918 $cache_client = OpenSRF::Utils::Cache->new("global", 0);
920 # see if it's in the cache
921 #warn "Getting ORG Tree\n";
922 my $tree = $cache_client->get_cache('orgtree');
924 #warn "Found orgtree in cache. returning...\n";
928 my $orglist = $apputils->simple_scalar_request(
930 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
933 #warn "found org list\n";
936 $tree = $self->build_org_tree($orglist);
937 $cache_client->put_cache('orgtree', $tree);
943 # turns an org list into an org tree
946 my( $self, $orglist) = @_;
948 return $orglist unless (
949 ref($orglist) and @$orglist > 1 );
952 $a->ou_type <=> $b->ou_type ||
953 $a->name cmp $b->name } @$orglist;
955 for my $org (@list) {
957 next unless ($org and defined($org->parent_ou));
958 my ($parent) = grep { $_->id == $org->parent_ou } @list;
961 $parent->children([]) unless defined($parent->children);
962 push( @{$parent->children}, $org );
970 __PACKAGE__->register_method(
971 method => "get_org_descendants",
972 api_name => "open-ils.actor.org_tree.descendants.retrieve"
975 # depth is optional. org_unit is the id
976 sub get_org_descendants {
977 my( $self, $client, $org_unit, $depth ) = @_;
978 my $orglist = $apputils->simple_scalar_request(
980 "open-ils.storage.actor.org_unit.descendants.atomic",
982 return $self->build_org_tree($orglist);
986 __PACKAGE__->register_method(
987 method => "get_org_ancestors",
988 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
991 # depth is optional. org_unit is the id
992 sub get_org_ancestors {
993 my( $self, $client, $org_unit, $depth ) = @_;
994 my $orglist = $apputils->simple_scalar_request(
996 "open-ils.storage.actor.org_unit.ancestors.atomic",
998 return $self->build_org_tree($orglist);
1002 __PACKAGE__->register_method(
1003 method => "get_standings",
1004 api_name => "open-ils.actor.standings.retrieve"
1009 return $user_standings if $user_standings;
1010 return $user_standings =
1011 $apputils->simple_scalar_request(
1013 "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
1018 __PACKAGE__->register_method(
1019 method => "get_my_org_path",
1020 api_name => "open-ils.actor.org_unit.full_path.retrieve"
1023 sub get_my_org_path {
1024 my( $self, $client, $user_session, $org_id ) = @_;
1025 my $user_obj = $apputils->check_user_session($user_session);
1026 if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
1028 return $apputils->simple_scalar_request(
1030 "open-ils.storage.actor.org_unit.full_path.atomic",
1035 __PACKAGE__->register_method(
1036 method => "patron_adv_search",
1037 api_name => "open-ils.actor.patron.search.advanced" );
1038 sub patron_adv_search {
1039 my( $self, $client, $auth, $search_hash, $search_limit, $search_sort ) = @_;
1040 my $e = OpenILS::Utils::Editor->new(authtoken=>$auth);
1041 return $e->event unless $e->checkauth;
1042 return $e->event unless $e->allowed('VIEW_USER');
1044 "open-ils.storage.actor.user.crazy_search",
1045 $search_hash, $search_limit, $search_sort);
1050 sub _verify_password {
1051 my($user_session, $password) = @_;
1052 my $user_obj = $apputils->check_user_session($user_session);
1054 #grab the user with password
1055 $user_obj = $apputils->simple_scalar_request(
1057 "open-ils.storage.direct.actor.user.retrieve",
1060 if($user_obj->passwd eq $password) {
1068 __PACKAGE__->register_method(
1069 method => "update_password",
1070 api_name => "open-ils.actor.user.password.update");
1072 __PACKAGE__->register_method(
1073 method => "update_password",
1074 api_name => "open-ils.actor.user.username.update");
1076 __PACKAGE__->register_method(
1077 method => "update_password",
1078 api_name => "open-ils.actor.user.email.update");
1080 sub update_password {
1081 my( $self, $client, $user_session, $new_value, $current_password ) = @_;
1085 my $user_obj = $apputils->check_user_session($user_session);
1087 if($self->api_name =~ /password/o) {
1089 #make sure they know the current password
1090 if(!_verify_password($user_session, md5_hex($current_password))) {
1091 return OpenILS::Event->new('INCORRECT_PASSWORD');
1094 $logger->debug("update_password setting new password $new_value");
1095 $user_obj->passwd($new_value);
1097 } elsif($self->api_name =~ /username/o) {
1098 my $users = search_username(undef, undef, $new_value);
1099 if( $users and $users->[0] ) {
1100 return OpenILS::Event->new('USERNAME_EXISTS');
1102 $user_obj->usrname($new_value);
1104 } elsif($self->api_name =~ /email/o) {
1105 #warn "Updating email to $new_value\n";
1106 $user_obj->email($new_value);
1109 my $session = $apputils->start_db_session();
1111 ( $user_obj, $evt ) = _update_patron($session, $user_obj, $user_obj, 1);
1112 return $evt if $evt;
1114 $apputils->commit_db_session($session);
1116 if($user_obj) { return 1; }
1121 __PACKAGE__->register_method(
1122 method => "check_user_perms",
1123 api_name => "open-ils.actor.user.perm.check",
1124 notes => <<" NOTES");
1125 Takes a login session, user id, an org id, and an array of perm type strings. For each
1126 perm type, if the user does *not* have the given permission it is added
1127 to a list which is returned from the method. If all permissions
1128 are allowed, an empty list is returned
1129 if the logged in user does not match 'user_id', then the logged in user must
1130 have VIEW_PERMISSION priveleges.
1133 sub check_user_perms {
1134 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1136 my( $staff, $evt ) = $apputils->checkses($login_session);
1137 return $evt if $evt;
1139 if($staff->id ne $user_id) {
1140 if( my $evt = $apputils->check_perms(
1141 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1147 for my $perm (@$perm_types) {
1148 if($apputils->check_perms($user_id, $org_id, $perm)) {
1149 push @not_allowed, $perm;
1153 return \@not_allowed
1156 __PACKAGE__->register_method(
1157 method => "check_user_perms2",
1158 api_name => "open-ils.actor.user.perm.check.multi_org",
1160 Checks the permissions on a list of perms and orgs for a user
1161 @param authtoken The login session key
1162 @param user_id The id of the user to check
1163 @param orgs The array of org ids
1164 @param perms The array of permission names
1165 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1166 if the logged in user does not match 'user_id', then the logged in user must
1167 have VIEW_PERMISSION priveleges.
1170 sub check_user_perms2 {
1171 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1173 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1174 $authtoken, $user_id, 'VIEW_PERMISSION' );
1175 return $evt if $evt;
1178 for my $org (@$orgs) {
1179 for my $perm (@$perms) {
1180 if($apputils->check_perms($user_id, $org, $perm)) {
1181 push @not_allowed, [ $org, $perm ];
1186 return \@not_allowed
1190 __PACKAGE__->register_method(
1191 method => 'check_user_perms3',
1192 api_name => 'open-ils.actor.user.perm.highest_org',
1194 Returns the highest org unit id at which a user has a given permission
1195 If the requestor does not match the target user, the requestor must have
1196 'VIEW_PERMISSION' rights at the home org unit of the target user
1197 @param authtoken The login session key
1198 @param userid The id of the user in question
1199 @param perm The permission to check
1200 @return The org unit highest in the org tree within which the user has
1201 the requested permission
1204 sub check_user_perms3 {
1205 my( $self, $client, $authtoken, $userid, $perm ) = @_;
1207 my( $staff, $target, $org, $evt );
1209 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1210 $authtoken, $userid, 'VIEW_PERMISSION' );
1211 return $evt if $evt;
1213 my $tree = $self->get_org_tree();
1214 return _find_highest_perm_org( $perm, $userid, $target->ws_ou, $tree );
1218 sub _find_highest_perm_org {
1219 my ( $perm, $userid, $start_org, $org_tree ) = @_;
1220 my $org = $apputils->find_org($org_tree, $start_org );
1224 last if ($apputils->check_perms( $userid, $org->id, $perm )); # perm failed
1226 $org = $apputils->find_org( $org_tree, $org->parent_ou() );
1232 __PACKAGE__->register_method(
1233 method => 'check_user_perms4',
1234 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1236 Returns the highest org unit id at which a user has a given permission
1237 If the requestor does not match the target user, the requestor must have
1238 'VIEW_PERMISSION' rights at the home org unit of the target user
1239 @param authtoken The login session key
1240 @param userid The id of the user in question
1241 @param perms An array of perm names to check
1242 @return An array of orgId's representing the org unit
1243 highest in the org tree within which the user has the requested permission
1244 The arrah of orgId's has matches the order of the perms array
1247 sub check_user_perms4 {
1248 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1250 my( $staff, $target, $org, $evt );
1252 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1253 $authtoken, $userid, 'VIEW_PERMISSION' );
1254 return $evt if $evt;
1257 return [] unless ref($perms);
1258 my $tree = $self->get_org_tree();
1260 for my $p (@$perms) {
1261 push( @arr, _find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1269 __PACKAGE__->register_method(
1270 method => "user_fines_summary",
1271 api_name => "open-ils.actor.user.fines.summary",
1272 notes => <<" NOTES");
1273 Returns a short summary of the users total open fines, excluding voided fines
1274 Params are login_session, user_id
1275 Returns a 'mous' object.
1278 sub user_fines_summary {
1279 my( $self, $client, $login_session, $user_id ) = @_;
1281 my $user_obj = $apputils->check_user_session($login_session);
1282 if($user_obj->id ne $user_id) {
1283 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_FINES_SUMMARY")) {
1284 return OpenILS::Perm->new("VIEW_USER_FINES_SUMMARY");
1288 return $apputils->simple_scalar_request(
1290 "open-ils.storage.direct.money.open_user_summary.search.usr",
1298 __PACKAGE__->register_method(
1299 method => "user_transactions",
1300 api_name => "open-ils.actor.user.transactions",
1301 notes => <<" NOTES");
1302 Returns a list of open user transactions (mbts objects);
1303 Params are login_session, user_id
1304 Optional third parameter is the transactions type. defaults to all
1307 __PACKAGE__->register_method(
1308 method => "user_transactions",
1309 api_name => "open-ils.actor.user.transactions.have_charge",
1310 notes => <<" NOTES");
1311 Returns a list of all open user transactions (mbts objects) that have an initial charge
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_balance",
1319 notes => <<" NOTES");
1320 Returns a list of all open user transactions (mbts objects) that have a balance
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.fleshed",
1328 notes => <<" NOTES");
1329 Returns an object/hash of transaction, circ, title where transaction = an open
1330 user transactions (mbts objects), circ is the attached circluation, and title
1331 is the title the circ points to
1332 Params are login_session, user_id
1333 Optional third parameter is the transactions type. defaults to all
1336 __PACKAGE__->register_method(
1337 method => "user_transactions",
1338 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1339 notes => <<" NOTES");
1340 Returns an object/hash of transaction, circ, title where transaction = an open
1341 user transactions that has an initial charge (mbts objects), circ is the
1342 attached circluation, and title is the title the circ points to
1343 Params are login_session, user_id
1344 Optional third parameter is the transactions type. defaults to all
1347 __PACKAGE__->register_method(
1348 method => "user_transactions",
1349 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1350 notes => <<" NOTES");
1351 Returns an object/hash of transaction, circ, title where transaction = an open
1352 user transaction that has a balance (mbts objects), circ is the attached
1353 circluation, and title is the title the circ points to
1354 Params are login_session, user_id
1355 Optional third parameter is the transaction type. defaults to all
1358 __PACKAGE__->register_method(
1359 method => "user_transactions",
1360 api_name => "open-ils.actor.user.transactions.count",
1361 notes => <<" NOTES");
1362 Returns an object/hash of transaction, circ, title where transaction = an open
1363 user transactions (mbts objects), circ is the attached circluation, and title
1364 is the title the circ points to
1365 Params are login_session, user_id
1366 Optional third parameter is the transactions type. defaults to all
1369 __PACKAGE__->register_method(
1370 method => "user_transactions",
1371 api_name => "open-ils.actor.user.transactions.have_charge.count",
1372 notes => <<" NOTES");
1373 Returns an object/hash of transaction, circ, title where transaction = an open
1374 user transactions that has an initial charge (mbts objects), circ is the
1375 attached circluation, and title is the title the circ points to
1376 Params are login_session, user_id
1377 Optional third parameter is the transactions type. defaults to all
1380 __PACKAGE__->register_method(
1381 method => "user_transactions",
1382 api_name => "open-ils.actor.user.transactions.have_balance.count",
1383 notes => <<" NOTES");
1384 Returns an object/hash of transaction, circ, title where transaction = an open
1385 user transaction that has a balance (mbts objects), circ is the attached
1386 circluation, and title is the title the circ points to
1387 Params are login_session, user_id
1388 Optional third parameter is the transaction type. defaults to all
1391 __PACKAGE__->register_method(
1392 method => "user_transactions",
1393 api_name => "open-ils.actor.user.transactions.have_balance.total",
1394 notes => <<" NOTES");
1395 Returns an object/hash of transaction, circ, title where transaction = an open
1396 user transaction that has a balance (mbts objects), circ is the attached
1397 circluation, and title is the title the circ points to
1398 Params are login_session, user_id
1399 Optional third parameter is the transaction type. defaults to all
1404 sub user_transactions {
1405 my( $self, $client, $login_session, $user_id, $type ) = @_;
1407 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1408 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1409 return $evt if $evt;
1411 my $api = $self->api_name();
1415 if(defined($type)) { @xact = (xact_type => $type);
1417 } else { @xact = (); }
1419 if($api =~ /have_charge/o) {
1421 $trans = $apputils->simple_scalar_request(
1423 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1424 { usr => $user_id, total_owed => { ">" => 0 }, @xact });
1426 } elsif($api =~ /have_balance/o) {
1428 $trans = $apputils->simple_scalar_request(
1430 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1431 { usr => $user_id, balance_owed => { "<>" => 0 }, @xact });
1435 $trans = $apputils->simple_scalar_request(
1437 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1438 { usr => $user_id, @xact });
1441 if($api =~ /total/o) {
1443 for my $t (@$trans) {
1444 $total += $t->balance_owed;
1447 $logger->debug("Total balance owed by user $user_id: $total");
1451 if($api =~ /count/o) { return scalar @$trans; }
1452 if($api !~ /fleshed/o) { return $trans; }
1455 for my $t (@$trans) {
1457 if( $t->xact_type ne 'circulation' ) {
1458 push @resp, {transaction => $t};
1462 my $circ = $apputils->simple_scalar_request(
1464 "open-ils.storage.direct.action.circulation.retrieve",
1469 my $title = $apputils->simple_scalar_request(
1471 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1472 $circ->target_copy );
1476 my $u = OpenILS::Utils::ModsParser->new();
1477 $u->start_mods_batch($title->marc());
1478 my $mods = $u->finish_mods_batch();
1480 push @resp, {transaction => $t, circ => $circ, record => $mods };
1488 __PACKAGE__->register_method(
1489 method => "user_transaction_retrieve",
1490 api_name => "open-ils.actor.user.transaction.fleshed.retrieve",
1492 notes => <<" NOTES");
1493 Returns a fleshedtransaction record
1495 __PACKAGE__->register_method(
1496 method => "user_transaction_retrieve",
1497 api_name => "open-ils.actor.user.transaction.retrieve",
1499 notes => <<" NOTES");
1500 Returns a transaction record
1502 sub user_transaction_retrieve {
1503 my( $self, $client, $login_session, $bill_id ) = @_;
1505 my $trans = $apputils->simple_scalar_request(
1507 "open-ils.storage.direct.money.billable_transaction_summary.retrieve",
1511 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1512 $login_session, $trans->usr, 'VIEW_USER_TRANSACTIONS' );
1513 return $evt if $evt;
1515 my $api = $self->api_name();
1516 if($api !~ /fleshed/o) { return $trans; }
1518 if( $trans->xact_type ne 'circulation' ) {
1519 $logger->debug("Returning non-circ transaction");
1520 return {transaction => $trans};
1523 my $circ = $apputils->simple_scalar_request(
1525 "open-ils.storage.direct.action.circulation.retrieve",
1528 return {transaction => $trans} unless $circ;
1529 $logger->debug("Found the circ transaction");
1531 my $title = $apputils->simple_scalar_request(
1533 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1534 $circ->target_copy );
1536 return {transaction => $trans, circ => $circ } unless $title;
1537 $logger->debug("Found the circ title");
1541 my $u = OpenILS::Utils::ModsParser->new();
1542 $u->start_mods_batch($title->marc());
1543 $mods = $u->finish_mods_batch();
1545 if ($title->id == -1) {
1546 my $copy = $apputils->simple_scalar_request(
1548 "open-ils.storage.direct.asset.copy.retrieve",
1549 $circ->target_copy );
1551 $mods = new Fieldmapper::metabib::virtual_record;
1553 $mods->title($copy->dummy_title);
1554 $mods->author($copy->dummy_author);
1558 $logger->debug("MODSized the circ title");
1560 return {transaction => $trans, circ => $circ, record => $mods };
1564 __PACKAGE__->register_method(
1565 method => "hold_request_count",
1566 api_name => "open-ils.actor.user.hold_requests.count",
1568 notes => <<" NOTES");
1569 Returns hold ready/total counts
1571 sub hold_request_count {
1572 my( $self, $client, $login_session, $userid ) = @_;
1574 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1575 $login_session, $userid, 'VIEW_HOLD' );
1576 return $evt if $evt;
1579 my $holds = $apputils->simple_scalar_request(
1581 "open-ils.storage.direct.action.hold_request.search_where.atomic",
1583 fulfillment_time => {"=" => undef } }
1587 for my $h (@$holds) {
1588 next unless $h->capture_time;
1590 my $copy = $apputils->simple_scalar_request(
1592 "open-ils.storage.direct.asset.copy.retrieve",
1596 if ($copy->status == 8) {
1601 return { total => scalar(@$holds), ready => scalar(@ready) };
1605 __PACKAGE__->register_method(
1606 method => "checkedout_count",
1607 api_name => "open-ils.actor.user.checked_out.count__",
1609 notes => <<" NOTES");
1610 Returns a transaction record
1614 sub checkedout_count {
1615 my( $self, $client, $login_session, $userid ) = @_;
1617 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1618 $login_session, $userid, 'VIEW_CIRCULATIONS' );
1619 return $evt if $evt;
1621 my $circs = $apputils->simple_scalar_request(
1623 "open-ils.storage.direct.action.circulation.search_where.atomic",
1624 { usr => $userid, stop_fines => undef }
1625 #{ usr => $userid, checkin_time => {"=" => undef } }
1628 my $parser = DateTime::Format::ISO8601->new;
1631 for my $c (@$circs) {
1632 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1633 my $due = $due_dt->epoch;
1635 if ($due < DateTime->today->epoch) {
1640 return { total => scalar(@$circs), overdue => scalar(@overdue) };
1644 __PACKAGE__->register_method(
1645 method => "checked_out",
1646 api_name => "open-ils.actor.user.checked_out",
1649 Returns a structure of circulations objects sorted by
1650 out, overdue, lost, claims_returned, long_overdue.
1651 A list of IDs are returned of each type.
1652 lost, long_overdue, and claims_returned circ will not
1653 be "finished" (there is an outstanding balance or some
1654 other pending action on the circ).
1656 The .count method also includes a 'total' field which
1657 sums all "open" circs
1661 __PACKAGE__->register_method(
1662 method => "checked_out",
1663 api_name => "open-ils.actor.user.checked_out.count",
1665 signature => q/@see open-ils.actor.user.checked_out/
1669 my( $self, $conn, $auth, $userid ) = @_;
1671 my $e = new_editor(authtoken=>$auth);
1672 return $e->event unless $e->checkauth;
1674 if( $userid ne $e->requestor->id ) {
1675 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
1678 my $count = $self->api_name =~ /count/;
1679 return _checked_out( $count, $e, $userid );
1683 my( $iscount, $e, $userid ) = @_;
1685 my $circs = $e->search_action_circulation(
1686 { usr => $userid, stop_fines => undef });
1688 my $parser = DateTime::Format::ISO8601->new;
1690 # split the circs up into overdue and not-overdue circs
1692 for my $c (@$circs) {
1693 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1694 my $due = $due_dt->epoch;
1695 if ($due < DateTime->today->epoch) {
1696 push @overdue, $c->id;
1702 # grab all of the lost, claims-returned, and longoverdue circs
1703 my $open = $e->search_action_circulation(
1704 {usr => $userid, stop_fines => { '!=' => undef }, xact_finish => undef });
1706 my( @lost, @cr, @lo );
1707 for my $c (@$open) {
1708 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1709 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1710 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
1716 total => @$circs + @lost + @cr + @lo,
1717 out => scalar(@out),
1718 overdue => scalar(@overdue),
1719 lost => scalar(@lost),
1720 claims_returned => scalar(@cr),
1721 long_overdue => scalar(@lo)
1727 overdue => \@overdue,
1729 claims_returned => \@cr,
1730 long_overdue => \@lo
1742 __PACKAGE__->register_method(
1743 method => "user_transaction_history",
1744 api_name => "open-ils.actor.user.transactions.history",
1746 notes => <<" NOTES");
1747 Returns a list of billable transaction ids for a user, optionally by type
1749 __PACKAGE__->register_method(
1750 method => "user_transaction_history",
1751 api_name => "open-ils.actor.user.transactions.history.have_charge",
1753 notes => <<" NOTES");
1754 Returns a list of billable transaction ids for a user that have an initial charge, optionally by type
1756 sub user_transaction_history {
1757 my( $self, $client, $login_session, $user_id, $type ) = @_;
1759 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1760 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1761 return $evt if $evt;
1763 my $api = $self->api_name();
1767 @xact = (xact_type => $type) if(defined($type));
1768 @charge = (total_owed => { ">" => 0}) if($api =~ /have_charge/);
1770 my $trans = $apputils->simple_scalar_request(
1772 "open-ils.storage.direct.money.billable_transaction_summary.search_where.atomic",
1773 { usr => $user_id, @xact, @charge }, { order_by => 'xact_start DESC' });
1775 return [ map { $_->id } @$trans ];
1779 __PACKAGE__->register_method(
1780 method => "user_perms",
1781 api_name => "open-ils.actor.permissions.user_perms.retrieve",
1783 notes => <<" NOTES");
1784 Returns a list of permissions
1787 my( $self, $client, $authtoken, $user ) = @_;
1789 my( $staff, $evt ) = $apputils->checkses($authtoken);
1790 return $evt if $evt;
1792 $user ||= $staff->id;
1794 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
1798 return $apputils->simple_scalar_request(
1800 "open-ils.storage.permission.user_perms.atomic",
1804 __PACKAGE__->register_method(
1805 method => "retrieve_perms",
1806 api_name => "open-ils.actor.permissions.retrieve",
1807 notes => <<" NOTES");
1808 Returns a list of permissions
1810 sub retrieve_perms {
1811 my( $self, $client ) = @_;
1812 return $apputils->simple_scalar_request(
1814 "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
1817 __PACKAGE__->register_method(
1818 method => "retrieve_groups",
1819 api_name => "open-ils.actor.groups.retrieve",
1820 notes => <<" NOTES");
1821 Returns a list of user groupss
1823 sub retrieve_groups {
1824 my( $self, $client ) = @_;
1825 return $apputils->simple_scalar_request(
1827 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1830 __PACKAGE__->register_method(
1831 method => "retrieve_org_address",
1832 api_name => "open-ils.actor.org_unit.address.retrieve",
1833 notes => <<' NOTES');
1834 Returns an org_unit address by ID
1835 @param An org_address ID
1837 sub retrieve_org_address {
1838 my( $self, $client, $id ) = @_;
1839 return $apputils->simple_scalar_request(
1841 "open-ils.storage.direct.actor.org_address.retrieve",
1846 __PACKAGE__->register_method(
1847 method => "retrieve_groups_tree",
1848 api_name => "open-ils.actor.groups.tree.retrieve",
1849 notes => <<" NOTES");
1850 Returns a list of user groups
1852 sub retrieve_groups_tree {
1853 my( $self, $client ) = @_;
1854 my $groups = $apputils->simple_scalar_request(
1856 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1857 return $self->build_group_tree($groups);
1861 # turns an org list into an org tree
1862 sub build_group_tree {
1864 my( $self, $grplist) = @_;
1866 return $grplist unless (
1867 ref($grplist) and @$grplist > 1 );
1869 my @list = sort { $a->name cmp $b->name } @$grplist;
1872 for my $grp (@list) {
1874 if ($grp and !defined($grp->parent)) {
1878 my ($parent) = grep { $_->id == $grp->parent} @list;
1880 $parent->children([]) unless defined($parent->children);
1881 push( @{$parent->children}, $grp );
1889 __PACKAGE__->register_method(
1890 method => "add_user_to_groups",
1891 api_name => "open-ils.actor.user.set_groups",
1892 notes => <<" NOTES");
1893 Adds a user to one or more permission groups
1896 sub add_user_to_groups {
1897 my( $self, $client, $authtoken, $userid, $groups ) = @_;
1899 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1900 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
1901 return $evt if $evt;
1903 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1904 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
1905 return $evt if $evt;
1907 $apputils->simplereq(
1909 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
1911 for my $group (@$groups) {
1912 my $link = Fieldmapper::permission::usr_grp_map->new;
1914 $link->usr($userid);
1916 my $id = $apputils->simplereq(
1918 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
1924 __PACKAGE__->register_method(
1925 method => "get_user_perm_groups",
1926 api_name => "open-ils.actor.user.get_groups",
1927 notes => <<" NOTES");
1928 Retrieve a user's permission groups.
1932 sub get_user_perm_groups {
1933 my( $self, $client, $authtoken, $userid ) = @_;
1935 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1936 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
1937 return $evt if $evt;
1939 return $apputils->simplereq(
1941 'open-ils.storage.direct.permission.usr_grp_map.search.usr.atomic', $userid );
1946 __PACKAGE__->register_method (
1947 method => 'register_workstation',
1948 api_name => 'open-ils.actor.workstation.register.override',
1949 signature => q/@see open-ils.actor.workstation.register/);
1951 __PACKAGE__->register_method (
1952 method => 'register_workstation',
1953 api_name => 'open-ils.actor.workstation.register',
1955 Registers a new workstion in the system
1956 @param authtoken The login session key
1957 @param name The name of the workstation id
1958 @param owner The org unit that owns this workstation
1959 @return The workstation id on success, WORKSTATION_NAME_EXISTS
1960 if the name is already in use.
1963 sub _register_workstation {
1964 my( $self, $connection, $authtoken, $name, $owner ) = @_;
1965 my( $requestor, $evt ) = $U->checkses($authtoken);
1966 return $evt if $evt;
1967 $evt = $U->check_perms($requestor->id, $owner, 'REGISTER_WORKSTATION');
1968 return $evt if $evt;
1970 my $ws = $U->storagereq(
1971 'open-ils.storage.direct.actor.workstation.search.name', $name );
1972 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS') if $ws;
1974 $ws = Fieldmapper::actor::workstation->new;
1975 $ws->owning_lib($owner);
1978 my $id = $U->storagereq(
1979 'open-ils.storage.direct.actor.workstation.create', $ws );
1980 return $U->DB_UPDATE_FAILED($ws) unless $id;
1986 sub register_workstation {
1987 my( $self, $conn, $authtoken, $name, $owner ) = @_;
1989 my $e = OpenILS::Utils::Editor->new(authtoken=>$authtoken, xact=>1);
1990 return $e->event unless $e->checkauth;
1991 return $e->event unless $e->allowed('REGISTER_WORKSTATION'); # XXX rely on editor perms
1992 my $existing = $e->search_actor_workstation({name => $name});
1995 if( $self->api_name =~ /override/o ) {
1996 return $e->event unless $e->allowed('DELETE_WORKSTATION'); # XXX rely on editor perms
1997 return $e->event unless $e->delete_actor_workstation($$existing[0]);
1999 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS')
2003 my $ws = Fieldmapper::actor::workstation->new;
2004 $ws->owning_lib($owner);
2006 $e->create_actor_workstation($ws) or return $e->event;
2008 return $ws->id; # note: editor sets the id on the new object for us
2012 __PACKAGE__->register_method (
2013 method => 'fetch_patron_note',
2014 api_name => 'open-ils.actor.note.retrieve.all',
2016 Returns a list of notes for a given user
2017 Requestor must have VIEW_USER permission if pub==false and
2018 @param authtoken The login session key
2019 @param args Hash of params including
2020 patronid : the patron's id
2021 pub : true if retrieving only public notes
2025 sub fetch_patron_note {
2026 my( $self, $conn, $authtoken, $args ) = @_;
2027 my $patronid = $$args{patronid};
2029 my($reqr, $evt) = $U->checkses($authtoken);
2032 ($patron, $evt) = $U->fetch_user($patronid);
2033 return $evt if $evt;
2036 if( $patronid ne $reqr->id ) {
2037 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2038 return $evt if $evt;
2040 return $U->storagereq(
2041 'open-ils.storage.direct.actor.usr_note.search_where.atomic',
2042 { usr => $patronid, pub => 't' } );
2045 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2046 return $evt if $evt;
2048 return $U->storagereq(
2049 'open-ils.storage.direct.actor.usr_note.search.usr.atomic', $patronid );
2052 __PACKAGE__->register_method (
2053 method => 'create_user_note',
2054 api_name => 'open-ils.actor.note.create',
2056 Creates a new note for the given user
2057 @param authtoken The login session key
2058 @param note The note object
2061 sub create_user_note {
2062 my( $self, $conn, $authtoken, $note ) = @_;
2063 my( $reqr, $patron, $evt ) =
2064 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
2065 return $evt if $evt;
2066 $logger->activity("user ".$reqr->id." creating note for user ".$note->usr);
2068 $note->pub('f') unless $note->pub;
2069 $note->creator($reqr->id);
2070 my $id = $U->storagereq(
2071 'open-ils.storage.direct.actor.usr_note.create', $note );
2072 return $U->DB_UPDATE_FAILED($note) unless $id;
2077 __PACKAGE__->register_method (
2078 method => 'delete_user_note',
2079 api_name => 'open-ils.actor.note.delete',
2081 Deletes a note for the given user
2082 @param authtoken The login session key
2083 @param noteid The note id
2086 sub delete_user_note {
2087 my( $self, $conn, $authtoken, $noteid ) = @_;
2089 my $note = $U->storagereq(
2090 'open-ils.storage.direct.actor.usr_note.retrieve', $noteid);
2091 return OpenILS::Event->new('ACTOR_USER_NOTE_NOT_FOUND') unless $note;
2093 my( $reqr, $patron, $evt ) =
2094 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
2095 return $evt if $evt;
2096 $logger->activity("user ".$reqr->id." deleting note [$noteid] for user ".$note->usr);
2098 my $stat = $U->storagereq(
2099 'open-ils.storage.direct.actor.usr_note.delete', $noteid );
2100 return $U->DB_UPDATE_FAILED($note) unless defined $stat;
2106 __PACKAGE__->register_method (
2107 method => 'create_closed_date',
2108 api_name => 'open-ils.actor.org_unit.closed_date.create',
2110 Creates a new closing entry for the given org_unit
2111 @param authtoken The login session key
2112 @param note The closed_date object
2115 sub create_closed_date {
2116 my( $self, $conn, $authtoken, $cd ) = @_;
2118 my( $user, $evt ) = $U->checkses($authtoken);
2119 return $evt if $evt;
2121 $evt = $U->check_perms($user->id, $cd->org_unit, 'CREATE_CLOSEING');
2122 return $evt if $evt;
2124 $logger->activity("user ".$user->id." creating library closing for ".$cd->org_unit);
2126 my $id = $U->storagereq(
2127 'open-ils.storage.direct.actor.org_unit.closed_date.create', $cd );
2128 return $U->DB_UPDATE_FAILED($cd) unless $id;
2133 __PACKAGE__->register_method (
2134 method => 'delete_closed_date',
2135 api_name => 'open-ils.actor.org_unit.closed_date.delete',
2137 Deletes a closing entry for the given org_unit
2138 @param authtoken The login session key
2139 @param noteid The close_date id
2142 sub delete_closed_date {
2143 my( $self, $conn, $authtoken, $cd ) = @_;
2145 my( $user, $evt ) = $U->checkses($authtoken);
2146 return $evt if $evt;
2149 ($cd_obj, $evt) = fetch_closed_date($cd);
2150 return $evt if $evt;
2152 $evt = $U->check_perms($user->id, $cd->org_unit, 'DELETE_CLOSEING');
2153 return $evt if $evt;
2155 $logger->activity("user ".$user->id." deleting library closing for ".$cd->org_unit);
2157 my $stat = $U->storagereq(
2158 'open-ils.storage.direct.actor.org_unit.closed_date.delete', $cd );
2159 return $U->DB_UPDATE_FAILED($cd) unless $stat;
2164 __PACKAGE__->register_method(
2165 method => 'usrname_exists',
2166 api_name => 'open-ils.actor.username.exists',
2168 Returns 1 if the requested username exists, returns 0 otherwise
2172 sub usrname_exists {
2173 my( $self, $conn, $auth, $usrname ) = @_;
2174 my $e = new_editor(authtoken=>$auth);
2175 return $e->event unless $e->checkauth;
2176 my $a = $e->search_actor_user({usrname => $usrname}, {idlist=>1});
2177 return $$a[0] if $a and @$a;
2181 __PACKAGE__->register_method(
2182 method => 'barcode_exists',
2183 api_name => 'open-ils.actor.barcode.exists',
2185 Returns 1 if the requested barcode exists, returns 0 otherwise
2189 sub barcode_exists {
2190 my( $self, $conn, $auth, $barcode ) = @_;
2191 my $e = new_editor(authtoken=>$auth);
2192 return $e->event unless $e->checkauth;
2193 my $a = $e->search_actor_card({barcode => $barcode}, {idlist=>1});
2194 return $$a[0] if $a and @$a;
2199 __PACKAGE__->register_method(
2200 method => 'retrieve_net_levels',
2201 api_name => 'open-ils.actor.net_access_level.retrieve.all',
2204 sub retrieve_net_levels {
2205 my( $self, $conn, $auth ) = @_;
2206 my $e = new_editor(authtoken=>$auth);
2207 return $e->event unless $e->checkauth;
2208 return $e->retrieve_all_config_net_access_level();