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;
27 use OpenILS::Application::Actor::ClosedDates;
29 use OpenILS::Utils::Editor qw/:funcs/;
31 use OpenILS::Application::Actor::UserGroups;
33 OpenILS::Application::Actor::Container->initialize();
34 OpenILS::Application::Actor::UserGroups->initialize();
35 OpenILS::Application::Actor::ClosedDates->initialize();
38 my $apputils = "OpenILS::Application::AppUtils";
41 sub _d { warn "Patron:\n" . Dumper(shift()); }
46 my $set_user_settings;
49 __PACKAGE__->register_method(
50 method => "set_user_settings",
51 api_name => "open-ils.actor.patron.settings.update",
53 sub set_user_settings {
54 my( $self, $client, $user_session, $uid, $settings ) = @_;
56 $logger->debug("Setting user settings: $user_session, $uid, " . Dumper($settings));
58 my( $staff, $user, $evt ) =
59 $apputils->checkses_requestor( $user_session, $uid, 'UPDATE_USER' );
64 # [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
67 [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
69 $logger->activity("User " . $staff->id . " updating user $uid settings with: " . Dumper(\@params));
71 return $apputils->simplereq(
73 'open-ils.storage.direct.actor.user_setting.batch.merge', @params );
79 __PACKAGE__->register_method(
80 method => "set_ou_settings",
81 api_name => "open-ils.actor.org_unit.settings.update",
84 my( $self, $client, $user_session, $ouid, $settings ) = @_;
86 my( $staff, $evt ) = $apputils->checkses( $user_session );
88 $evt = $apputils->check_perms( $staff->id, $ouid, 'UPDATE_ORG_UNIT' );
93 map { [{ org_unit => $ouid, name => $_}, {value => $$settings{$_}}] } keys %$settings;
95 $logger->activity("Updating org unit [$ouid] settings with: " . Dumper($params));
97 return $apputils->simplereq(
99 'open-ils.storage.direct.actor.org_unit_setting.merge', @$params );
103 my $fetch_user_settings;
104 my $fetch_ou_settings;
106 __PACKAGE__->register_method(
107 method => "user_settings",
108 api_name => "open-ils.actor.patron.settings.retrieve",
111 my( $self, $client, $user_session, $uid ) = @_;
113 my( $staff, $user, $evt ) =
114 $apputils->checkses_requestor( $user_session, $uid, 'VIEW_USER' );
117 $logger->debug("User " . $staff->id . " fetching user $uid\n");
118 my $s = $apputils->simplereq(
120 'open-ils.storage.direct.actor.user_setting.search.usr.atomic',$uid );
122 return { map { ($_->name,$_->value) } @$s };
127 __PACKAGE__->register_method(
128 method => "ou_settings",
129 api_name => "open-ils.actor.org_unit.settings.retrieve",
132 my( $self, $client, $ouid ) = @_;
134 $logger->info("Fetching org unit settings for org $ouid");
136 my $s = $apputils->simplereq(
138 'open-ils.storage.direct.actor.org_unit_setting.search.org_unit.atomic', $ouid);
140 return { map { ($_->name,$_->value) } @$s };
143 __PACKAGE__->register_method (
144 method => "ou_setting_delete",
145 api_name => 'open-ils.actor.org_setting.delete',
147 Deletes a specific org unit setting for a specific location
148 @param authtoken The login session key
149 @param orgid The org unit whose setting we're changing
150 @param setting The name of the setting to delete
151 @return True value on success.
155 sub ou_setting_delete {
156 my( $self, $conn, $authtoken, $orgid, $setting ) = @_;
157 my( $reqr, $evt) = $U->checkses($authtoken);
159 $evt = $U->check_perms($reqr->id, $orgid, 'UPDATE_ORG_SETTING');
162 my $id = $U->storagereq(
163 'open-ils.storage.id_list.actor.org_unit_setting.search_where',
164 { name => $setting, org_unit => $orgid } );
166 $logger->debug("Retrieved setting $id in org unit setting delete");
168 my $s = $U->storagereq(
169 'open-ils.storage.direct.actor.org_unit_setting.delete', $id );
171 $logger->activity("User ".$reqr->id." deleted org unit setting $id") if $s;
177 __PACKAGE__->register_method(
178 method => "update_patron",
179 api_name => "open-ils.actor.patron.update",);
182 my( $self, $client, $user_session, $patron ) = @_;
184 my $session = $apputils->start_db_session();
187 $logger->info("Creating new patron...") if $patron->isnew;
188 $logger->info("Updating Patron: " . $patron->id) unless $patron->isnew;
190 my( $user_obj, $evt ) = $U->checkses($user_session);
193 # XXX does this user have permission to add/create users. Granularity?
194 # $new_patron is the patron in progress. $patron is the original patron
195 # passed in with the method. new_patron will change as the components
196 # of patron are added/updated.
200 # unflesh the real items on the patron
201 $patron->card( $patron->card->id ) if(ref($patron->card));
202 $patron->billing_address( $patron->billing_address->id )
203 if(ref($patron->billing_address));
204 $patron->mailing_address( $patron->mailing_address->id )
205 if(ref($patron->mailing_address));
207 # create/update the patron first so we can use his id
208 if($patron->isnew()) {
209 ( $new_patron, $evt ) = _add_patron($session, _clone_patron($patron), $user_obj);
211 } else { $new_patron = $patron; }
213 ( $new_patron, $evt ) = _add_update_addresses($session, $patron, $new_patron, $user_obj);
216 ( $new_patron, $evt ) = _add_update_cards($session, $patron, $new_patron, $user_obj);
219 ( $new_patron, $evt ) = _add_survey_responses($session, $patron, $new_patron, $user_obj);
222 # re-update the patron if anything has happened to him during this process
223 if($new_patron->ischanged()) {
224 ( $new_patron, $evt ) = _update_patron($session, $new_patron, $user_obj);
228 #$session = OpenSRF::AppSession->create("open-ils.storage"); # why did i put this here?
230 ($new_patron, $evt) = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
233 ($new_patron, $evt) = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
236 ($new_patron, $evt) = _create_standing_penalties($session, $user_session, $patron, $new_patron, $user_obj);
239 $logger->activity("user ".$user_obj->id." updating/creating user ".$new_patron->id);
240 $apputils->commit_db_session($session);
242 #warn "Patron Update/Create complete\n";
243 return flesh_user($new_patron->id());
249 __PACKAGE__->register_method(
250 method => "user_retrieve_fleshed_by_id",
251 api_name => "open-ils.actor.user.fleshed.retrieve",);
253 sub user_retrieve_fleshed_by_id {
254 my( $self, $client, $user_session, $user_id ) = @_;
256 my( $requestor, $target, $evt ) = $apputils->
257 checkses_requestor( $user_session, $user_id, 'VIEW_USER' );
260 return flesh_user($user_id);
264 # fleshes: card, cards, address, addresses, stat_cat_entries, standing_penalties
272 $session = OpenSRF::AppSession->create("open-ils.storage");
276 # grab the user with the given id
277 my $ureq = $session->request(
278 "open-ils.storage.direct.actor.user.retrieve", $id);
279 my $user = $ureq->gather(1);
281 if(!$user) { return undef; }
284 my $cards_req = $session->request(
285 "open-ils.storage.direct.actor.card.search.usr.atomic",
287 $user->cards( $cards_req->gather(1) );
289 for my $c(@{$user->cards}) {
290 if($c->id == $user->card || $c->id eq $user->card ) {
291 #warn "Setting my card to " . $c->id . "\n";
296 my $add_req = $session->request(
297 "open-ils.storage.direct.actor.user_address.search.usr.atomic",
299 $user->addresses( $add_req->gather(1) );
301 if( @{$user->addresses} ) {
302 if( ! grep { $_->id eq $user->billing_address } @{$user->addresses} ) {
303 my $ba = $session->request(
304 'open-ils.storage.direct.actor.user_address.retrieve',
305 $user->billing_address)->gather(1);
306 push( @{$user->addresses}, $ba );
309 if( ! grep { $_->id eq $user->mailing_address } @{$user->addresses} ) {
310 my $ba = $session->request(
311 'open-ils.storage.direct.actor.user_address.retrieve',
312 $user->mailing_address)->gather(1);
313 push( @{$user->addresses}, $ba );
318 for my $c(@{$user->addresses}) {
319 if($c->id eq $user->billing_address ) { $user->billing_address($c); }
320 if($c->id eq $user->mailing_address ) { $user->mailing_address($c); }
323 my $stat_req = $session->request(
324 "open-ils.storage.direct.actor.stat_cat_entry_user_map.search.target_usr.atomic",
326 $user->stat_cat_entries($stat_req->gather(1));
328 my $standing_penalties_req = $session->request(
329 "open-ils.storage.direct.actor.user_standing_penalty.search.usr.atomic",
331 $user->standing_penalties($standing_penalties_req->gather(1));
333 if($kill) { $session->disconnect(); }
334 $user->clear_passwd();
340 # clone and clear stuff that would break the database
344 my $new_patron = $patron->clone;
346 # Using the Fieldmapper clone method
347 #my $new_patron = Fieldmapper::actor::user->new();
349 #my $fmap = $Fieldmapper::fieldmap;
350 #no strict; # shallow clone, may be useful in the fieldmapper
352 # (keys %{$fmap->{"Fieldmapper::actor::user"}->{'fields'}}) {
353 # $new_patron->$field( $patron->$field() );
358 $new_patron->clear_billing_address();
359 $new_patron->clear_mailing_address();
360 $new_patron->clear_addresses();
361 $new_patron->clear_card();
362 $new_patron->clear_cards();
363 $new_patron->clear_id();
364 $new_patron->clear_isnew();
365 $new_patron->clear_ischanged();
366 $new_patron->clear_isdeleted();
367 $new_patron->clear_stat_cat_entries();
368 $new_patron->clear_permissions();
369 $new_patron->clear_standing_penalties();
379 my $user_obj = shift;
381 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'CREATE_USER');
382 return (undef, $evt) if $evt;
384 my $ex = $session->request(
385 'open-ils.storage.direct.actor.user.search.usrname', $patron->usrname())->gather(1);
387 return (undef, OpenILS::Event->new('USERNAME_EXISTS'));
390 $logger->info("Creating new user in the DB with username: ".$patron->usrname());
392 my $id = $session->request(
393 "open-ils.storage.direct.actor.user.create", $patron)->gather(1);
394 return (undef, $U->DB_UPDATE_FAILED($patron)) unless $id;
396 $logger->info("Successfully created new user [$id] in DB");
398 return ( $session->request(
399 "open-ils.storage.direct.actor.user.retrieve", $id)->gather(1), undef );
404 my( $session, $patron, $user_obj, $noperm) = @_;
406 $logger->info("Updating patron ".$patron->id." in DB");
409 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'UPDATE_USER');
410 return (undef, $evt) if $evt;
413 # update the password by itself to avoid the password protection magic
414 if( $patron->passwd ) {
415 my $s = $session->request(
416 'open-ils.storage.direct.actor.user.remote_update',
417 {id => $patron->id}, {passwd => $patron->passwd})->gather(1);
418 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($s);
419 $patron->clear_passwd;
422 if(!$patron->ident_type) {
423 $patron->clear_ident_type;
424 $patron->clear_ident_value;
427 if(!$patron->ident_type2) {
428 $patron->clear_ident_type2;
429 $patron->clear_ident_value2;
432 my $stat = $session->request(
433 "open-ils.storage.direct.actor.user.update",$patron )->gather(1);
434 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($stat);
440 sub _add_update_addresses {
444 my $new_patron = shift;
448 my $current_id; # id of the address before creation
450 for my $address (@{$patron->addresses()}) {
452 next unless ref $address;
453 $current_id = $address->id();
455 if( $patron->billing_address() and
456 $patron->billing_address() == $current_id ) {
457 $logger->info("setting billing addr to $current_id");
458 $new_patron->billing_address($address->id());
459 $new_patron->ischanged(1);
462 if( $patron->mailing_address() and
463 $patron->mailing_address() == $current_id ) {
464 $new_patron->mailing_address($address->id());
465 $logger->info("setting mailing addr to $current_id");
466 $new_patron->ischanged(1);
470 if($address->isnew()) {
472 $address->usr($new_patron->id());
474 ($address, $evt) = _add_address($session,$address);
475 return (undef, $evt) if $evt;
477 # we need to get the new id
478 if( $patron->billing_address() and
479 $patron->billing_address() == $current_id ) {
480 $new_patron->billing_address($address->id());
481 $logger->info("setting billing addr to $current_id");
482 $new_patron->ischanged(1);
485 if( $patron->mailing_address() and
486 $patron->mailing_address() == $current_id ) {
487 $new_patron->mailing_address($address->id());
488 $logger->info("setting mailing addr to $current_id");
489 $new_patron->ischanged(1);
492 } elsif($address->ischanged() ) {
494 ($address, $evt) = _update_address($session, $address);
495 return (undef, $evt) if $evt;
497 } elsif($address->isdeleted() ) {
499 if( $address->id() == $new_patron->mailing_address() ) {
500 $new_patron->clear_mailing_address();
501 ($new_patron, $evt) = _update_patron($session, $new_patron);
502 return (undef, $evt) if $evt;
505 if( $address->id() == $new_patron->billing_address() ) {
506 $new_patron->clear_billing_address();
507 ($new_patron, $evt) = _update_patron($session, $new_patron);
508 return (undef, $evt) if $evt;
511 $evt = _delete_address($session, $address);
512 return (undef, $evt) if $evt;
516 return ( $new_patron, undef );
520 # adds an address to the db and returns the address with new id
522 my($session, $address) = @_;
523 $address->clear_id();
525 $logger->info("Creating new address at street ".$address->street1);
527 # put the address into the database
528 my $id = $session->request(
529 "open-ils.storage.direct.actor.user_address.create", $address )->gather(1);
530 return (undef, $U->DB_UPDATE_FAILED($address)) unless $id;
533 return ($address, undef);
537 sub _update_address {
538 my( $session, $address ) = @_;
540 $logger->info("Updating address ".$address->id." in the DB");
542 my $stat = $session->request(
543 "open-ils.storage.direct.actor.user_address.update", $address )->gather(1);
545 return (undef, $U->DB_UPDATE_FAILED($address)) unless defined($stat);
546 return ($address, undef);
551 sub _add_update_cards {
555 my $new_patron = shift;
559 my $virtual_id; #id of the card before creation
560 for my $card (@{$patron->cards()}) {
562 $card->usr($new_patron->id());
564 if(ref($card) and $card->isnew()) {
566 $virtual_id = $card->id();
567 ( $card, $evt ) = _add_card($session,$card);
568 return (undef, $evt) if $evt;
570 #if(ref($patron->card)) { $patron->card($patron->card->id); }
571 if($patron->card() == $virtual_id) {
572 $new_patron->card($card->id());
573 $new_patron->ischanged(1);
576 } elsif( ref($card) and $card->ischanged() ) {
577 $evt = _update_card($session, $card);
578 return (undef, $evt) if $evt;
582 return ( $new_patron, undef );
586 # adds an card to the db and returns the card with new id
588 my( $session, $card ) = @_;
591 $logger->info("Adding new patron card ".$card->barcode);
593 my $id = $session->request(
594 "open-ils.storage.direct.actor.card.create", $card )->gather(1);
595 return (undef, $U->DB_UPDATE_FAILED($card)) unless $id;
596 $logger->info("Successfully created patron card $id");
599 return ( $card, undef );
603 # returns event on error. returns undef otherwise
605 my( $session, $card ) = @_;
606 $logger->info("Updating patron card ".$card->id);
608 my $stat = $session->request(
609 "open-ils.storage.direct.actor.card.update", $card )->gather(1);
610 return $U->DB_UPDATE_FAILED($card) unless defined($stat);
617 # returns event on error. returns undef otherwise
618 sub _delete_address {
619 my( $session, $address ) = @_;
621 $logger->info("Deleting address ".$address->id." from DB");
623 my $stat = $session->request(
624 "open-ils.storage.direct.actor.user_address.delete", $address )->gather(1);
626 return $U->DB_UPDATE_FAILED($address) unless defined($stat);
632 sub _add_survey_responses {
633 my ($session, $patron, $new_patron) = @_;
635 $logger->info( "Updating survey responses for patron ".$new_patron->id );
637 my $responses = $patron->survey_responses;
641 $_->usr($new_patron->id) for (@$responses);
643 my $evt = $U->simplereq( "open-ils.circ",
644 "open-ils.circ.survey.submit.user_id", $responses );
646 return (undef, $evt) if defined($U->event_code($evt));
650 return ( $new_patron, undef );
654 sub _create_stat_maps {
656 my($session, $user_session, $patron, $new_patron) = @_;
658 my $maps = $patron->stat_cat_entries();
660 for my $map (@$maps) {
662 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
664 if ($map->isdeleted()) {
665 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.delete";
667 } elsif ($map->isnew()) {
668 $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
673 $map->target_usr($new_patron->id);
676 $logger->info("Updating stat entry with method $method and map $map");
678 my $stat = $session->request($method, $map)->gather(1);
679 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
683 return ($new_patron, undef);
686 sub _create_perm_maps {
688 my($session, $user_session, $patron, $new_patron) = @_;
690 my $maps = $patron->permissions;
692 for my $map (@$maps) {
694 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
695 if ($map->isdeleted()) {
696 $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
697 } elsif ($map->isnew()) {
698 $method = "open-ils.storage.direct.permission.usr_perm_map.create";
703 $map->usr($new_patron->id);
705 #warn( "Updating permissions with method $method and session $user_session and map $map" );
706 $logger->info( "Updating permissions with method $method and map $map" );
708 my $stat = $session->request($method, $map)->gather(1);
709 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
713 return ($new_patron, undef);
717 sub _create_standing_penalties {
719 my($session, $user_session, $patron, $new_patron) = @_;
721 my $maps = $patron->standing_penalties;
724 for my $map (@$maps) {
726 if ($map->isdeleted()) {
727 $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
728 } elsif ($map->isnew()) {
729 $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
735 $map->usr($new_patron->id);
737 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
739 my $stat = $session->request($method, $map)->gather(1);
740 return (undef, $U->DB_UPDATE_FAILED($map)) unless $stat;
743 return ($new_patron, undef);
748 __PACKAGE__->register_method(
749 method => "search_username",
750 api_name => "open-ils.actor.user.search.username",
753 sub search_username {
754 my($self, $client, $username) = @_;
755 my $users = OpenILS::Application::AppUtils->simple_scalar_request(
757 "open-ils.storage.direct.actor.user.search.usrname.atomic",
765 __PACKAGE__->register_method(
766 method => "user_retrieve_by_barcode",
767 api_name => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
769 sub user_retrieve_by_barcode {
770 my($self, $client, $user_session, $barcode) = @_;
772 $logger->debug("Searching for user with barcode $barcode");
773 my ($user_obj, $evt) = $apputils->checkses($user_session);
777 my $session = OpenSRF::AppSession->create("open-ils.storage");
779 # find the card with the given barcode
780 my $creq = $session->request(
781 "open-ils.storage.direct.actor.card.search.barcode.atomic",
783 my $card = $creq->gather(1);
785 if(!$card || !$card->[0]) {
786 $session->disconnect();
787 return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' );
791 my $user = flesh_user($card->usr(), $session);
793 $evt = $U->check_perms($user_obj->id, $user->home_ou, 'VIEW_USER');
796 $session->disconnect();
797 if(!$user) { return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' ); }
804 __PACKAGE__->register_method(
805 method => "get_user_by_id",
806 api_name => "open-ils.actor.user.retrieve",);
809 my ($self, $client, $user_session, $id) = @_;
811 my $user_obj = $apputils->check_user_session( $user_session );
813 return $apputils->simple_scalar_request(
815 "open-ils.storage.direct.actor.user.retrieve",
821 __PACKAGE__->register_method(
822 method => "get_org_types",
823 api_name => "open-ils.actor.org_types.retrieve",);
827 my($self, $client) = @_;
829 return $org_types if $org_types;
831 $apputils->simple_scalar_request(
833 "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
838 __PACKAGE__->register_method(
839 method => "get_user_profiles",
840 api_name => "open-ils.actor.user.profiles.retrieve",
844 sub get_user_profiles {
845 return $user_profiles if $user_profiles;
847 return $user_profiles =
848 $apputils->simple_scalar_request(
850 "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
855 __PACKAGE__->register_method(
856 method => "get_user_ident_types",
857 api_name => "open-ils.actor.user.ident_types.retrieve",
860 sub get_user_ident_types {
861 return $ident_types if $ident_types;
862 return $ident_types =
863 $apputils->simple_scalar_request(
865 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
871 __PACKAGE__->register_method(
872 method => "get_org_unit",
873 api_name => "open-ils.actor.org_unit.retrieve",
878 my( $self, $client, $user_session, $org_id ) = @_;
880 if(defined($user_session) && !defined($org_id)) {
882 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
883 if(!defined($org_id)) {
884 $org_id = $user_obj->home_ou;
889 my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
891 "open-ils.storage.direct.actor.org_unit.retrieve",
897 __PACKAGE__->register_method(
898 method => "search_org_unit",
899 api_name => "open-ils.actor.org_unit_list.search",
902 sub search_org_unit {
904 my( $self, $client, $field, $value ) = @_;
906 my $list = OpenILS::Application::AppUtils->simple_scalar_request(
908 "open-ils.storage.direct.actor.org_unit.search.$field.atomic",
917 __PACKAGE__->register_method(
918 method => "get_org_tree",
919 api_name => "open-ils.actor.org_tree.retrieve",
921 note => "Returns the entire org tree structure",
925 my( $self, $client) = @_;
928 $cache_client = OpenSRF::Utils::Cache->new("global", 0);
930 # see if it's in the cache
931 #warn "Getting ORG Tree\n";
932 my $tree = $cache_client->get_cache('orgtree');
934 #warn "Found orgtree in cache. returning...\n";
938 my $orglist = $apputils->simple_scalar_request(
940 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
943 #warn "found org list\n";
946 $tree = $self->build_org_tree($orglist);
947 $cache_client->put_cache('orgtree', $tree);
953 # turns an org list into an org tree
956 my( $self, $orglist) = @_;
958 return $orglist unless (
959 ref($orglist) and @$orglist > 1 );
962 $a->ou_type <=> $b->ou_type ||
963 $a->name cmp $b->name } @$orglist;
965 for my $org (@list) {
967 next unless ($org and defined($org->parent_ou));
968 my ($parent) = grep { $_->id == $org->parent_ou } @list;
971 $parent->children([]) unless defined($parent->children);
972 push( @{$parent->children}, $org );
980 __PACKAGE__->register_method(
981 method => "get_org_descendants",
982 api_name => "open-ils.actor.org_tree.descendants.retrieve"
985 # depth is optional. org_unit is the id
986 sub get_org_descendants {
987 my( $self, $client, $org_unit, $depth ) = @_;
988 my $orglist = $apputils->simple_scalar_request(
990 "open-ils.storage.actor.org_unit.descendants.atomic",
992 return $self->build_org_tree($orglist);
996 __PACKAGE__->register_method(
997 method => "get_org_ancestors",
998 api_name => "open-ils.actor.org_tree.ancestors.retrieve"
1001 # depth is optional. org_unit is the id
1002 sub get_org_ancestors {
1003 my( $self, $client, $org_unit, $depth ) = @_;
1004 my $orglist = $apputils->simple_scalar_request(
1006 "open-ils.storage.actor.org_unit.ancestors.atomic",
1007 $org_unit, $depth );
1008 return $self->build_org_tree($orglist);
1012 __PACKAGE__->register_method(
1013 method => "get_standings",
1014 api_name => "open-ils.actor.standings.retrieve"
1019 return $user_standings if $user_standings;
1020 return $user_standings =
1021 $apputils->simple_scalar_request(
1023 "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
1028 __PACKAGE__->register_method(
1029 method => "get_my_org_path",
1030 api_name => "open-ils.actor.org_unit.full_path.retrieve"
1033 sub get_my_org_path {
1034 my( $self, $client, $user_session, $org_id ) = @_;
1035 my $user_obj = $apputils->check_user_session($user_session);
1036 if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
1038 return $apputils->simple_scalar_request(
1040 "open-ils.storage.actor.org_unit.full_path.atomic",
1045 __PACKAGE__->register_method(
1046 method => "patron_adv_search",
1047 api_name => "open-ils.actor.patron.search.advanced" );
1048 sub patron_adv_search {
1049 my( $self, $client, $auth, $search_hash, $search_limit, $search_sort ) = @_;
1050 my $e = OpenILS::Utils::Editor->new(authtoken=>$auth);
1051 return $e->event unless $e->checkauth;
1052 return $e->event unless $e->allowed('VIEW_USER');
1054 "open-ils.storage.actor.user.crazy_search",
1055 $search_hash, $search_limit, $search_sort);
1060 sub _verify_password {
1061 my($user_session, $password) = @_;
1062 my $user_obj = $apputils->check_user_session($user_session);
1064 #grab the user with password
1065 $user_obj = $apputils->simple_scalar_request(
1067 "open-ils.storage.direct.actor.user.retrieve",
1070 if($user_obj->passwd eq $password) {
1078 __PACKAGE__->register_method(
1079 method => "update_password",
1080 api_name => "open-ils.actor.user.password.update");
1082 __PACKAGE__->register_method(
1083 method => "update_password",
1084 api_name => "open-ils.actor.user.username.update");
1086 __PACKAGE__->register_method(
1087 method => "update_password",
1088 api_name => "open-ils.actor.user.email.update");
1090 sub update_password {
1091 my( $self, $client, $user_session, $new_value, $current_password ) = @_;
1095 my $user_obj = $apputils->check_user_session($user_session);
1097 if($self->api_name =~ /password/o) {
1099 #make sure they know the current password
1100 if(!_verify_password($user_session, md5_hex($current_password))) {
1101 return OpenILS::Event->new('INCORRECT_PASSWORD');
1104 $logger->debug("update_password setting new password $new_value");
1105 $user_obj->passwd($new_value);
1107 } elsif($self->api_name =~ /username/o) {
1108 my $users = search_username(undef, undef, $new_value);
1109 if( $users and $users->[0] ) {
1110 return OpenILS::Event->new('USERNAME_EXISTS');
1112 $user_obj->usrname($new_value);
1114 } elsif($self->api_name =~ /email/o) {
1115 #warn "Updating email to $new_value\n";
1116 $user_obj->email($new_value);
1119 my $session = $apputils->start_db_session();
1121 ( $user_obj, $evt ) = _update_patron($session, $user_obj, $user_obj, 1);
1122 return $evt if $evt;
1124 $apputils->commit_db_session($session);
1126 if($user_obj) { return 1; }
1131 __PACKAGE__->register_method(
1132 method => "check_user_perms",
1133 api_name => "open-ils.actor.user.perm.check",
1134 notes => <<" NOTES");
1135 Takes a login session, user id, an org id, and an array of perm type strings. For each
1136 perm type, if the user does *not* have the given permission it is added
1137 to a list which is returned from the method. If all permissions
1138 are allowed, an empty list is returned
1139 if the logged in user does not match 'user_id', then the logged in user must
1140 have VIEW_PERMISSION priveleges.
1143 sub check_user_perms {
1144 my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1146 my( $staff, $evt ) = $apputils->checkses($login_session);
1147 return $evt if $evt;
1149 if($staff->id ne $user_id) {
1150 if( my $evt = $apputils->check_perms(
1151 $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1157 for my $perm (@$perm_types) {
1158 if($apputils->check_perms($user_id, $org_id, $perm)) {
1159 push @not_allowed, $perm;
1163 return \@not_allowed
1166 __PACKAGE__->register_method(
1167 method => "check_user_perms2",
1168 api_name => "open-ils.actor.user.perm.check.multi_org",
1170 Checks the permissions on a list of perms and orgs for a user
1171 @param authtoken The login session key
1172 @param user_id The id of the user to check
1173 @param orgs The array of org ids
1174 @param perms The array of permission names
1175 @return An array of [ orgId, permissionName ] arrays that FAILED the check
1176 if the logged in user does not match 'user_id', then the logged in user must
1177 have VIEW_PERMISSION priveleges.
1180 sub check_user_perms2 {
1181 my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1183 my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1184 $authtoken, $user_id, 'VIEW_PERMISSION' );
1185 return $evt if $evt;
1188 for my $org (@$orgs) {
1189 for my $perm (@$perms) {
1190 if($apputils->check_perms($user_id, $org, $perm)) {
1191 push @not_allowed, [ $org, $perm ];
1196 return \@not_allowed
1200 __PACKAGE__->register_method(
1201 method => 'check_user_perms3',
1202 api_name => 'open-ils.actor.user.perm.highest_org',
1204 Returns the highest org unit id at which a user has a given permission
1205 If the requestor does not match the target user, the requestor must have
1206 'VIEW_PERMISSION' rights at the home org unit of the target user
1207 @param authtoken The login session key
1208 @param userid The id of the user in question
1209 @param perm The permission to check
1210 @return The org unit highest in the org tree within which the user has
1211 the requested permission
1214 sub check_user_perms3 {
1215 my( $self, $client, $authtoken, $userid, $perm ) = @_;
1217 my( $staff, $target, $org, $evt );
1219 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1220 $authtoken, $userid, 'VIEW_PERMISSION' );
1221 return $evt if $evt;
1223 my $tree = $self->get_org_tree();
1224 return _find_highest_perm_org( $perm, $userid, $target->home_ou, $tree );
1228 sub _find_highest_perm_org {
1229 my ( $perm, $userid, $start_org, $org_tree ) = @_;
1230 my $org = $apputils->find_org($org_tree, $start_org );
1234 last if ($apputils->check_perms( $userid, $org->id, $perm )); # perm failed
1236 $org = $apputils->find_org( $org_tree, $org->parent_ou() );
1242 __PACKAGE__->register_method(
1243 method => 'check_user_perms4',
1244 api_name => 'open-ils.actor.user.perm.highest_org.batch',
1246 Returns the highest org unit id at which a user has a given permission
1247 If the requestor does not match the target user, the requestor must have
1248 'VIEW_PERMISSION' rights at the home org unit of the target user
1249 @param authtoken The login session key
1250 @param userid The id of the user in question
1251 @param perms An array of perm names to check
1252 @return An array of orgId's representing the org unit
1253 highest in the org tree within which the user has the requested permission
1254 The arrah of orgId's has matches the order of the perms array
1257 sub check_user_perms4 {
1258 my( $self, $client, $authtoken, $userid, $perms ) = @_;
1260 my( $staff, $target, $org, $evt );
1262 ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1263 $authtoken, $userid, 'VIEW_PERMISSION' );
1264 return $evt if $evt;
1267 return [] unless ref($perms);
1268 my $tree = $self->get_org_tree();
1270 for my $p (@$perms) {
1271 push( @arr, _find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1279 __PACKAGE__->register_method(
1280 method => "user_fines_summary",
1281 api_name => "open-ils.actor.user.fines.summary",
1282 notes => <<" NOTES");
1283 Returns a short summary of the users total open fines, excluding voided fines
1284 Params are login_session, user_id
1285 Returns a 'mous' object.
1288 sub user_fines_summary {
1289 my( $self, $client, $login_session, $user_id ) = @_;
1291 my $user_obj = $apputils->check_user_session($login_session);
1292 if($user_obj->id ne $user_id) {
1293 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_FINES_SUMMARY")) {
1294 return OpenILS::Perm->new("VIEW_USER_FINES_SUMMARY");
1298 return $apputils->simple_scalar_request(
1300 "open-ils.storage.direct.money.open_user_summary.search.usr",
1308 __PACKAGE__->register_method(
1309 method => "user_transactions",
1310 api_name => "open-ils.actor.user.transactions",
1311 notes => <<" NOTES");
1312 Returns a list of open user transactions (mbts objects);
1313 Params are login_session, user_id
1314 Optional third parameter is the transactions type. defaults to all
1317 __PACKAGE__->register_method(
1318 method => "user_transactions",
1319 api_name => "open-ils.actor.user.transactions.have_charge",
1320 notes => <<" NOTES");
1321 Returns a list of all open user transactions (mbts objects) that have an initial charge
1322 Params are login_session, user_id
1323 Optional third parameter is the transactions type. defaults to all
1326 __PACKAGE__->register_method(
1327 method => "user_transactions",
1328 api_name => "open-ils.actor.user.transactions.have_balance",
1329 notes => <<" NOTES");
1330 Returns a list of all open user transactions (mbts objects) that have a balance
1331 Params are login_session, user_id
1332 Optional third parameter is the transactions type. defaults to all
1335 __PACKAGE__->register_method(
1336 method => "user_transactions",
1337 api_name => "open-ils.actor.user.transactions.fleshed",
1338 notes => <<" NOTES");
1339 Returns an object/hash of transaction, circ, title where transaction = an open
1340 user transactions (mbts objects), circ is the attached circluation, and title
1341 is the title the circ points to
1342 Params are login_session, user_id
1343 Optional third parameter is the transactions type. defaults to all
1346 __PACKAGE__->register_method(
1347 method => "user_transactions",
1348 api_name => "open-ils.actor.user.transactions.have_charge.fleshed",
1349 notes => <<" NOTES");
1350 Returns an object/hash of transaction, circ, title where transaction = an open
1351 user transactions that has an initial charge (mbts objects), circ is the
1352 attached circluation, and title is the title the circ points to
1353 Params are login_session, user_id
1354 Optional third parameter is the transactions type. defaults to all
1357 __PACKAGE__->register_method(
1358 method => "user_transactions",
1359 api_name => "open-ils.actor.user.transactions.have_balance.fleshed",
1360 notes => <<" NOTES");
1361 Returns an object/hash of transaction, circ, title where transaction = an open
1362 user transaction that has a balance (mbts objects), circ is the attached
1363 circluation, and title is the title the circ points to
1364 Params are login_session, user_id
1365 Optional third parameter is the transaction type. defaults to all
1368 __PACKAGE__->register_method(
1369 method => "user_transactions",
1370 api_name => "open-ils.actor.user.transactions.count",
1371 notes => <<" NOTES");
1372 Returns an object/hash of transaction, circ, title where transaction = an open
1373 user transactions (mbts objects), circ is the attached circluation, and title
1374 is the title the circ points to
1375 Params are login_session, user_id
1376 Optional third parameter is the transactions type. defaults to all
1379 __PACKAGE__->register_method(
1380 method => "user_transactions",
1381 api_name => "open-ils.actor.user.transactions.have_charge.count",
1382 notes => <<" NOTES");
1383 Returns an object/hash of transaction, circ, title where transaction = an open
1384 user transactions that has an initial charge (mbts objects), circ is the
1385 attached circluation, and title is the title the circ points to
1386 Params are login_session, user_id
1387 Optional third parameter is the transactions type. defaults to all
1390 __PACKAGE__->register_method(
1391 method => "user_transactions",
1392 api_name => "open-ils.actor.user.transactions.have_balance.count",
1393 notes => <<" NOTES");
1394 Returns an object/hash of transaction, circ, title where transaction = an open
1395 user transaction that has a balance (mbts objects), circ is the attached
1396 circluation, and title is the title the circ points to
1397 Params are login_session, user_id
1398 Optional third parameter is the transaction type. defaults to all
1401 __PACKAGE__->register_method(
1402 method => "user_transactions",
1403 api_name => "open-ils.actor.user.transactions.have_balance.total",
1404 notes => <<" NOTES");
1405 Returns an object/hash of transaction, circ, title where transaction = an open
1406 user transaction that has a balance (mbts objects), circ is the attached
1407 circluation, and title is the title the circ points to
1408 Params are login_session, user_id
1409 Optional third parameter is the transaction type. defaults to all
1414 sub user_transactions {
1415 my( $self, $client, $login_session, $user_id, $type ) = @_;
1417 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1418 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1419 return $evt if $evt;
1421 my $api = $self->api_name();
1425 if(defined($type)) { @xact = (xact_type => $type);
1427 } else { @xact = (); }
1429 if($api =~ /have_charge/o) {
1431 $trans = $apputils->simple_scalar_request(
1433 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1434 { usr => $user_id, total_owed => { ">" => 0 }, @xact });
1436 } elsif($api =~ /have_balance/o) {
1438 $trans = $apputils->simple_scalar_request(
1440 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1441 { usr => $user_id, balance_owed => { "<>" => 0 }, @xact });
1445 $trans = $apputils->simple_scalar_request(
1447 "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1448 { usr => $user_id, @xact });
1451 if($api =~ /total/o) {
1453 for my $t (@$trans) {
1454 $total += $t->balance_owed;
1457 $logger->debug("Total balance owed by user $user_id: $total");
1461 if($api =~ /count/o) { return scalar @$trans; }
1462 if($api !~ /fleshed/o) { return $trans; }
1465 for my $t (@$trans) {
1467 if( $t->xact_type ne 'circulation' ) {
1468 push @resp, {transaction => $t};
1472 my $circ = $apputils->simple_scalar_request(
1474 "open-ils.storage.direct.action.circulation.retrieve",
1479 my $title = $apputils->simple_scalar_request(
1481 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1482 $circ->target_copy );
1486 my $u = OpenILS::Utils::ModsParser->new();
1487 $u->start_mods_batch($title->marc());
1488 my $mods = $u->finish_mods_batch();
1490 push @resp, {transaction => $t, circ => $circ, record => $mods };
1498 __PACKAGE__->register_method(
1499 method => "user_transaction_retrieve",
1500 api_name => "open-ils.actor.user.transaction.fleshed.retrieve",
1502 notes => <<" NOTES");
1503 Returns a fleshedtransaction record
1505 __PACKAGE__->register_method(
1506 method => "user_transaction_retrieve",
1507 api_name => "open-ils.actor.user.transaction.retrieve",
1509 notes => <<" NOTES");
1510 Returns a transaction record
1512 sub user_transaction_retrieve {
1513 my( $self, $client, $login_session, $bill_id ) = @_;
1515 my $trans = $apputils->simple_scalar_request(
1517 "open-ils.storage.direct.money.billable_transaction_summary.retrieve",
1521 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1522 $login_session, $trans->usr, 'VIEW_USER_TRANSACTIONS' );
1523 return $evt if $evt;
1525 my $api = $self->api_name();
1526 if($api !~ /fleshed/o) { return $trans; }
1528 if( $trans->xact_type ne 'circulation' ) {
1529 $logger->debug("Returning non-circ transaction");
1530 return {transaction => $trans};
1533 my $circ = $apputils->simple_scalar_request(
1535 "open-ils.storage.direct.action.circulation.retrieve",
1538 return {transaction => $trans} unless $circ;
1539 $logger->debug("Found the circ transaction");
1541 my $title = $apputils->simple_scalar_request(
1543 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1544 $circ->target_copy );
1546 return {transaction => $trans, circ => $circ } unless $title;
1547 $logger->debug("Found the circ title");
1551 my $u = OpenILS::Utils::ModsParser->new();
1552 $u->start_mods_batch($title->marc());
1553 $mods = $u->finish_mods_batch();
1555 if ($title->id == -1) {
1556 my $copy = $apputils->simple_scalar_request(
1558 "open-ils.storage.direct.asset.copy.retrieve",
1559 $circ->target_copy );
1561 $mods = new Fieldmapper::metabib::virtual_record;
1563 $mods->title($copy->dummy_title);
1564 $mods->author($copy->dummy_author);
1568 $logger->debug("MODSized the circ title");
1570 return {transaction => $trans, circ => $circ, record => $mods };
1574 __PACKAGE__->register_method(
1575 method => "hold_request_count",
1576 api_name => "open-ils.actor.user.hold_requests.count",
1578 notes => <<" NOTES");
1579 Returns hold ready/total counts
1581 sub hold_request_count {
1582 my( $self, $client, $login_session, $userid ) = @_;
1584 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1585 $login_session, $userid, 'VIEW_HOLD' );
1586 return $evt if $evt;
1589 my $holds = $apputils->simple_scalar_request(
1591 "open-ils.storage.direct.action.hold_request.search_where.atomic",
1593 fulfillment_time => {"=" => undef } }
1597 for my $h (@$holds) {
1598 next unless $h->capture_time;
1600 my $copy = $apputils->simple_scalar_request(
1602 "open-ils.storage.direct.asset.copy.retrieve",
1606 if ($copy->status == 8) {
1611 return { total => scalar(@$holds), ready => scalar(@ready) };
1615 __PACKAGE__->register_method(
1616 method => "checkedout_count",
1617 api_name => "open-ils.actor.user.checked_out.count__",
1619 notes => <<" NOTES");
1620 Returns a transaction record
1624 sub checkedout_count {
1625 my( $self, $client, $login_session, $userid ) = @_;
1627 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1628 $login_session, $userid, 'VIEW_CIRCULATIONS' );
1629 return $evt if $evt;
1631 my $circs = $apputils->simple_scalar_request(
1633 "open-ils.storage.direct.action.circulation.search_where.atomic",
1634 { usr => $userid, stop_fines => undef }
1635 #{ usr => $userid, checkin_time => {"=" => undef } }
1638 my $parser = DateTime::Format::ISO8601->new;
1641 for my $c (@$circs) {
1642 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1643 my $due = $due_dt->epoch;
1645 if ($due < DateTime->today->epoch) {
1650 return { total => scalar(@$circs), overdue => scalar(@overdue) };
1654 __PACKAGE__->register_method(
1655 method => "checked_out",
1656 api_name => "open-ils.actor.user.checked_out",
1659 Returns a structure of circulations objects sorted by
1660 out, overdue, lost, claims_returned, long_overdue.
1661 A list of IDs are returned of each type.
1662 lost, long_overdue, and claims_returned circ will not
1663 be "finished" (there is an outstanding balance or some
1664 other pending action on the circ).
1666 The .count method also includes a 'total' field which
1667 sums all "open" circs
1671 __PACKAGE__->register_method(
1672 method => "checked_out",
1673 api_name => "open-ils.actor.user.checked_out.count",
1675 signature => q/@see open-ils.actor.user.checked_out/
1679 my( $self, $conn, $auth, $userid ) = @_;
1681 my $e = new_editor(authtoken=>$auth);
1682 return $e->event unless $e->checkauth;
1684 if( $userid ne $e->requestor->id ) {
1685 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
1688 my $circs = $e->search_action_circulation(
1689 { usr => $userid, stop_fines => undef });
1691 my $parser = DateTime::Format::ISO8601->new;
1693 # split the circs up into overdue and not-overdue circs
1695 for my $c (@$circs) {
1696 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1697 my $due = $due_dt->epoch;
1698 if ($due < DateTime->today->epoch) {
1699 push @overdue, $c->id;
1705 # grab all of the lost, claims-returned, and longoverdue circs
1706 my $open = $e->search_action_circulation(
1707 {usr => $userid, stop_fines => { '!=' => undef }, xact_finish => undef });
1709 my( @lost, @cr, @lo );
1710 for my $c (@$open) {
1711 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1712 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1713 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
1717 if( $self->api_name =~ /count/ ) {
1719 total => @$circs + @lost + @cr + @lo,
1720 out => scalar(@out),
1721 overdue => scalar(@overdue),
1722 lost => scalar(@lost),
1723 claims_returned => scalar(@cr),
1724 long_overdue => scalar(@lo)
1730 overdue => \@overdue,
1732 claims_returned => \@cr,
1733 long_overdue => \@lo
1745 __PACKAGE__->register_method(
1746 method => "user_transaction_history",
1747 api_name => "open-ils.actor.user.transactions.history",
1749 notes => <<" NOTES");
1750 Returns a list of billable transaction ids for a user, optionally by type
1752 __PACKAGE__->register_method(
1753 method => "user_transaction_history",
1754 api_name => "open-ils.actor.user.transactions.history.have_charge",
1756 notes => <<" NOTES");
1757 Returns a list of billable transaction ids for a user that have an initial charge, optionally by type
1759 sub user_transaction_history {
1760 my( $self, $client, $login_session, $user_id, $type ) = @_;
1762 my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1763 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1764 return $evt if $evt;
1766 my $api = $self->api_name();
1770 @xact = (xact_type => $type) if(defined($type));
1771 @charge = (total_owed => { ">" => 0}) if($api =~ /have_charge/);
1773 my $trans = $apputils->simple_scalar_request(
1775 "open-ils.storage.direct.money.billable_transaction_summary.search_where.atomic",
1776 { usr => $user_id, @xact, @charge }, { order_by => 'xact_start DESC' });
1778 return [ map { $_->id } @$trans ];
1782 __PACKAGE__->register_method(
1783 method => "user_perms",
1784 api_name => "open-ils.actor.permissions.user_perms.retrieve",
1786 notes => <<" NOTES");
1787 Returns a list of permissions
1790 my( $self, $client, $authtoken, $user ) = @_;
1792 my( $staff, $evt ) = $apputils->checkses($authtoken);
1793 return $evt if $evt;
1795 $user ||= $staff->id;
1797 if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
1801 return $apputils->simple_scalar_request(
1803 "open-ils.storage.permission.user_perms.atomic",
1807 __PACKAGE__->register_method(
1808 method => "retrieve_perms",
1809 api_name => "open-ils.actor.permissions.retrieve",
1810 notes => <<" NOTES");
1811 Returns a list of permissions
1813 sub retrieve_perms {
1814 my( $self, $client ) = @_;
1815 return $apputils->simple_scalar_request(
1817 "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
1820 __PACKAGE__->register_method(
1821 method => "retrieve_groups",
1822 api_name => "open-ils.actor.groups.retrieve",
1823 notes => <<" NOTES");
1824 Returns a list of user groupss
1826 sub retrieve_groups {
1827 my( $self, $client ) = @_;
1828 return $apputils->simple_scalar_request(
1830 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1833 __PACKAGE__->register_method(
1834 method => "retrieve_org_address",
1835 api_name => "open-ils.actor.org_unit.address.retrieve",
1836 notes => <<' NOTES');
1837 Returns an org_unit address by ID
1838 @param An org_address ID
1840 sub retrieve_org_address {
1841 my( $self, $client, $id ) = @_;
1842 return $apputils->simple_scalar_request(
1844 "open-ils.storage.direct.actor.org_address.retrieve",
1849 __PACKAGE__->register_method(
1850 method => "retrieve_groups_tree",
1851 api_name => "open-ils.actor.groups.tree.retrieve",
1852 notes => <<" NOTES");
1853 Returns a list of user groups
1855 sub retrieve_groups_tree {
1856 my( $self, $client ) = @_;
1857 my $groups = $apputils->simple_scalar_request(
1859 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1860 return $self->build_group_tree($groups);
1864 # turns an org list into an org tree
1865 sub build_group_tree {
1867 my( $self, $grplist) = @_;
1869 return $grplist unless (
1870 ref($grplist) and @$grplist > 1 );
1872 my @list = sort { $a->name cmp $b->name } @$grplist;
1875 for my $grp (@list) {
1877 if ($grp and !defined($grp->parent)) {
1881 my ($parent) = grep { $_->id == $grp->parent} @list;
1883 $parent->children([]) unless defined($parent->children);
1884 push( @{$parent->children}, $grp );
1892 __PACKAGE__->register_method(
1893 method => "add_user_to_groups",
1894 api_name => "open-ils.actor.user.set_groups",
1895 notes => <<" NOTES");
1896 Adds a user to one or more permission groups
1899 sub add_user_to_groups {
1900 my( $self, $client, $authtoken, $userid, $groups ) = @_;
1902 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1903 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
1904 return $evt if $evt;
1906 ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1907 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
1908 return $evt if $evt;
1910 $apputils->simplereq(
1912 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
1914 for my $group (@$groups) {
1915 my $link = Fieldmapper::permission::usr_grp_map->new;
1917 $link->usr($userid);
1919 my $id = $apputils->simplereq(
1921 'open-ils.storage.direct.permission.usr_grp_map.create', $link );
1927 __PACKAGE__->register_method(
1928 method => "get_user_perm_groups",
1929 api_name => "open-ils.actor.user.get_groups",
1930 notes => <<" NOTES");
1931 Retrieve a user's permission groups.
1935 sub get_user_perm_groups {
1936 my( $self, $client, $authtoken, $userid ) = @_;
1938 my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1939 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
1940 return $evt if $evt;
1942 return $apputils->simplereq(
1944 'open-ils.storage.direct.permission.usr_grp_map.search.usr.atomic', $userid );
1949 __PACKAGE__->register_method (
1950 method => 'register_workstation',
1951 api_name => 'open-ils.actor.workstation.register.override',
1952 signature => q/@see open-ils.actor.workstation.register/);
1954 __PACKAGE__->register_method (
1955 method => 'register_workstation',
1956 api_name => 'open-ils.actor.workstation.register',
1958 Registers a new workstion in the system
1959 @param authtoken The login session key
1960 @param name The name of the workstation id
1961 @param owner The org unit that owns this workstation
1962 @return The workstation id on success, WORKSTATION_NAME_EXISTS
1963 if the name is already in use.
1966 sub _register_workstation {
1967 my( $self, $connection, $authtoken, $name, $owner ) = @_;
1968 my( $requestor, $evt ) = $U->checkses($authtoken);
1969 return $evt if $evt;
1970 $evt = $U->check_perms($requestor->id, $owner, 'REGISTER_WORKSTATION');
1971 return $evt if $evt;
1973 my $ws = $U->storagereq(
1974 'open-ils.storage.direct.actor.workstation.search.name', $name );
1975 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS') if $ws;
1977 $ws = Fieldmapper::actor::workstation->new;
1978 $ws->owning_lib($owner);
1981 my $id = $U->storagereq(
1982 'open-ils.storage.direct.actor.workstation.create', $ws );
1983 return $U->DB_UPDATE_FAILED($ws) unless $id;
1989 sub register_workstation {
1990 my( $self, $conn, $authtoken, $name, $owner ) = @_;
1992 my $e = OpenILS::Utils::Editor->new(authtoken=>$authtoken, xact=>1);
1993 return $e->event unless $e->checkauth;
1994 return $e->event unless $e->allowed('REGISTER_WORKSTATION'); # XXX rely on editor perms
1995 my $existing = $e->search_actor_workstation({name => $name});
1998 if( $self->api_name =~ /override/o ) {
1999 return $e->event unless $e->allowed('DELETE_WORKSTATION'); # XXX rely on editor perms
2000 return $e->event unless $e->delete_actor_workstation($$existing[0]);
2002 return OpenILS::Event->new('WORKSTATION_NAME_EXISTS')
2006 my $ws = Fieldmapper::actor::workstation->new;
2007 $ws->owning_lib($owner);
2009 $e->create_actor_workstation($ws) or return $e->event;
2011 return $ws->id; # note: editor sets the id on the new object for us
2015 __PACKAGE__->register_method (
2016 method => 'fetch_patron_note',
2017 api_name => 'open-ils.actor.note.retrieve.all',
2019 Returns a list of notes for a given user
2020 Requestor must have VIEW_USER permission if pub==false and
2021 @param authtoken The login session key
2022 @param args Hash of params including
2023 patronid : the patron's id
2024 pub : true if retrieving only public notes
2028 sub fetch_patron_note {
2029 my( $self, $conn, $authtoken, $args ) = @_;
2030 my $patronid = $$args{patronid};
2032 my($reqr, $evt) = $U->checkses($authtoken);
2035 ($patron, $evt) = $U->fetch_user($patronid);
2036 return $evt if $evt;
2039 if( $patronid ne $reqr->id ) {
2040 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2041 return $evt if $evt;
2043 return $U->storagereq(
2044 'open-ils.storage.direct.actor.usr_note.search_where.atomic',
2045 { usr => $patronid, pub => 't' } );
2048 $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2049 return $evt if $evt;
2051 return $U->storagereq(
2052 'open-ils.storage.direct.actor.usr_note.search.usr.atomic', $patronid );
2055 __PACKAGE__->register_method (
2056 method => 'create_user_note',
2057 api_name => 'open-ils.actor.note.create',
2059 Creates a new note for the given user
2060 @param authtoken The login session key
2061 @param note The note object
2064 sub create_user_note {
2065 my( $self, $conn, $authtoken, $note ) = @_;
2066 my( $reqr, $patron, $evt ) =
2067 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
2068 return $evt if $evt;
2069 $logger->activity("user ".$reqr->id." creating note for user ".$note->usr);
2071 $note->pub('f') unless $note->pub;
2072 $note->creator($reqr->id);
2073 my $id = $U->storagereq(
2074 'open-ils.storage.direct.actor.usr_note.create', $note );
2075 return $U->DB_UPDATE_FAILED($note) unless $id;
2080 __PACKAGE__->register_method (
2081 method => 'delete_user_note',
2082 api_name => 'open-ils.actor.note.delete',
2084 Deletes a note for the given user
2085 @param authtoken The login session key
2086 @param noteid The note id
2089 sub delete_user_note {
2090 my( $self, $conn, $authtoken, $noteid ) = @_;
2092 my $note = $U->storagereq(
2093 'open-ils.storage.direct.actor.usr_note.retrieve', $noteid);
2094 return OpenILS::Event->new('ACTOR_USER_NOTE_NOT_FOUND') unless $note;
2096 my( $reqr, $patron, $evt ) =
2097 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
2098 return $evt if $evt;
2099 $logger->activity("user ".$reqr->id." deleting note [$noteid] for user ".$note->usr);
2101 my $stat = $U->storagereq(
2102 'open-ils.storage.direct.actor.usr_note.delete', $noteid );
2103 return $U->DB_UPDATE_FAILED($note) unless defined $stat;
2109 __PACKAGE__->register_method (
2110 method => 'create_closed_date',
2111 api_name => 'open-ils.actor.org_unit.closed_date.create',
2113 Creates a new closing entry for the given org_unit
2114 @param authtoken The login session key
2115 @param note The closed_date object
2118 sub create_closed_date {
2119 my( $self, $conn, $authtoken, $cd ) = @_;
2121 my( $user, $evt ) = $U->checkses($authtoken);
2122 return $evt if $evt;
2124 $evt = $U->check_perms($user->id, $cd->org_unit, 'CREATE_CLOSEING');
2125 return $evt if $evt;
2127 $logger->activity("user ".$user->id." creating library closing for ".$cd->org_unit);
2129 my $id = $U->storagereq(
2130 'open-ils.storage.direct.actor.org_unit.closed_date.create', $cd );
2131 return $U->DB_UPDATE_FAILED($cd) unless $id;
2136 __PACKAGE__->register_method (
2137 method => 'delete_closed_date',
2138 api_name => 'open-ils.actor.org_unit.closed_date.delete',
2140 Deletes a closing entry for the given org_unit
2141 @param authtoken The login session key
2142 @param noteid The close_date id
2145 sub delete_closed_date {
2146 my( $self, $conn, $authtoken, $cd ) = @_;
2148 my( $user, $evt ) = $U->checkses($authtoken);
2149 return $evt if $evt;
2152 ($cd_obj, $evt) = fetch_closed_date($cd);
2153 return $evt if $evt;
2155 $evt = $U->check_perms($user->id, $cd->org_unit, 'DELETE_CLOSEING');
2156 return $evt if $evt;
2158 $logger->activity("user ".$user->id." deleting library closing for ".$cd->org_unit);
2160 my $stat = $U->storagereq(
2161 'open-ils.storage.direct.actor.org_unit.closed_date.delete', $cd );
2162 return $U->DB_UPDATE_FAILED($cd) unless $stat;
2167 __PACKAGE__->register_method(
2168 method => 'usrname_exists',
2169 api_name => 'open-ils.actor.username.exists',
2171 Returns 1 if the requested username exists, returns 0 otherwise
2175 sub usrname_exists {
2176 my( $self, $conn, $auth, $usrname ) = @_;
2177 my $e = new_editor(authtoken=>$auth);
2178 return $e->event unless $e->checkauth;
2179 my $a = $e->search_actor_user({usrname => $usrname}, {idlist=>1});
2180 return $$a[0] if $a and @$a;
2184 __PACKAGE__->register_method(
2185 method => 'barcode_exists',
2186 api_name => 'open-ils.actor.barcode.exists',
2188 Returns 1 if the requested barcode exists, returns 0 otherwise
2192 sub barcode_exists {
2193 my( $self, $conn, $auth, $barcode ) = @_;
2194 my $e = new_editor(authtoken=>$auth);
2195 return $e->event unless $e->checkauth;
2196 my $a = $e->search_actor_card({barcode => $barcode}, {idlist=>1});
2197 return $$a[0] if $a and @$a;
2202 __PACKAGE__->register_method(
2203 method => 'retrieve_net_levels',
2204 api_name => 'open-ils.actor.net_access_level.retrieve.all',
2207 sub retrieve_net_levels {
2208 my( $self, $conn, $auth ) = @_;
2209 my $e = new_editor(authtoken=>$auth);
2210 return $e->event unless $e->checkauth;
2211 return $e->retrieve_all_config_net_access_level();