]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Actor.pm
added barcode existence method
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Actor.pm
1 package OpenILS::Application::Actor;
2 use base qw/OpenSRF::Application/;
3 use strict; use warnings;
4 use Data::Dumper;
5 $Data::Dumper::Indent = 0;
6 use OpenILS::Event;
7
8 use Digest::MD5 qw(md5_hex);
9
10 use OpenSRF::EX qw(:try);
11 use OpenILS::Perm;
12
13 use OpenILS::Application::AppUtils;
14
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/;
20
21 use OpenSRF::Utils::Cache;
22
23 use DateTime;
24 use DateTime::Format::ISO8601;
25
26 use OpenILS::Application::Actor::Container;
27
28 use OpenILS::Utils::Editor qw/:funcs/;
29
30 use OpenILS::Application::Actor::UserGroups;
31 sub initialize {
32         OpenILS::Application::Actor::Container->initialize();
33         OpenILS::Application::Actor::UserGroups->initialize();
34 }
35
36 my $apputils = "OpenILS::Application::AppUtils";
37 my $U = $apputils;
38
39 sub _d { warn "Patron:\n" . Dumper(shift()); }
40
41 my $cache_client;
42
43
44 my $set_user_settings;
45 my $set_ou_settings;
46
47 __PACKAGE__->register_method(
48         method  => "set_user_settings",
49         api_name        => "open-ils.actor.patron.settings.update",
50 );
51 sub set_user_settings {
52         my( $self, $client, $user_session, $uid, $settings ) = @_;
53         
54         $logger->debug("Setting user settings: $user_session, $uid, " . Dumper($settings));
55
56         my( $staff, $user, $evt ) = 
57                 $apputils->checkses_requestor( $user_session, $uid, 'UPDATE_USER' );    
58         return $evt if $evt;
59         
60
61         #my ($params) = map { 
62         #       [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
63
64         my @params = map { 
65                 [{ usr => $user->id, name => $_}, {value => $$settings{$_}}] } keys %$settings;
66
67         $logger->activity("User " . $staff->id . " updating user $uid settings with: " . Dumper(\@params));
68
69         return $apputils->simplereq(
70                 'open-ils.storage',
71                 'open-ils.storage.direct.actor.user_setting.batch.merge', @params );
72                 
73 }
74
75
76
77 __PACKAGE__->register_method(
78         method  => "set_ou_settings",
79         api_name        => "open-ils.actor.org_unit.settings.update",
80 );
81 sub set_ou_settings {
82         my( $self, $client, $user_session, $ouid, $settings ) = @_;
83         
84         my( $staff, $evt ) = $apputils->checkses( $user_session );
85         return $evt if $evt;
86         $evt = $apputils->check_perms( $staff->id, $ouid, 'UPDATE_ORG_UNIT' );
87         return $evt if $evt;
88
89
90         my ($params) = 
91                 map { [{ org_unit => $ouid, name => $_}, {value => $$settings{$_}}] } keys %$settings;
92
93         $logger->activity("Updating org unit [$ouid] settings with: " . Dumper($params));
94
95         return $apputils->simplereq(
96                 'open-ils.storage',
97                 'open-ils.storage.direct.actor.org_unit_setting.merge', @$params );
98 }
99
100
101 my $fetch_user_settings;
102 my $fetch_ou_settings;
103
104 __PACKAGE__->register_method(
105         method  => "user_settings",
106         api_name        => "open-ils.actor.patron.settings.retrieve",
107 );
108 sub user_settings {
109         my( $self, $client, $user_session, $uid ) = @_;
110         
111         my( $staff, $user, $evt ) = 
112                 $apputils->checkses_requestor( $user_session, $uid, 'VIEW_USER' );
113         return $evt if $evt;
114
115         $logger->debug("User " . $staff->id . " fetching user $uid\n");
116         my $s = $apputils->simplereq(
117                 'open-ils.storage',
118                 'open-ils.storage.direct.actor.user_setting.search.usr.atomic',$uid );
119
120         return { map { ($_->name,$_->value) } @$s };
121 }
122
123
124
125 __PACKAGE__->register_method(
126         method  => "ou_settings",
127         api_name        => "open-ils.actor.org_unit.settings.retrieve",
128 );
129 sub ou_settings {
130         my( $self, $client, $ouid ) = @_;
131         
132         $logger->info("Fetching org unit settings for org $ouid");
133
134         my $s = $apputils->simplereq(
135                 'open-ils.storage',
136                 'open-ils.storage.direct.actor.org_unit_setting.search.org_unit.atomic', $ouid);
137
138         return { map { ($_->name,$_->value) } @$s };
139 }
140
141 __PACKAGE__->register_method (
142         method          => "ou_setting_delete",
143         api_name                => 'open-ils.actor.org_setting.delete',
144         signature       => q/
145                 Deletes a specific org unit setting for a specific location
146                 @param authtoken The login session key
147                 @param orgid The org unit whose setting we're changing
148                 @param setting The name of the setting to delete
149                 @return True value on success.
150         /
151 );
152
153 sub ou_setting_delete {
154         my( $self, $conn, $authtoken, $orgid, $setting ) = @_;
155         my( $reqr, $evt) = $U->checkses($authtoken);
156         return $evt if $evt;
157         $evt = $U->check_perms($reqr->id, $orgid, 'UPDATE_ORG_SETTING');
158         return $evt if $evt;
159
160         my $id = $U->storagereq(
161                 'open-ils.storage.id_list.actor.org_unit_setting.search_where', 
162                 { name => $setting, org_unit => $orgid } );
163
164         $logger->debug("Retrieved setting $id in org unit setting delete");
165
166         my $s = $U->storagereq(
167                 'open-ils.storage.direct.actor.org_unit_setting.delete', $id );
168
169         $logger->activity("User ".$reqr->id." deleted org unit setting $id") if $s;
170         return $s;
171 }
172
173
174
175 __PACKAGE__->register_method(
176         method  => "update_patron",
177         api_name        => "open-ils.actor.patron.update",);
178
179 sub update_patron {
180         my( $self, $client, $user_session, $patron ) = @_;
181
182         my $session = $apputils->start_db_session();
183         my $err = undef;
184
185         $logger->info("Creating new patron...") if $patron->isnew; 
186         $logger->info("Updating Patron: " . $patron->id) unless $patron->isnew;
187
188         my( $user_obj, $evt ) = $U->checkses($user_session);
189         return $evt if $evt;
190
191         # XXX does this user have permission to add/create users.  Granularity?
192         # $new_patron is the patron in progress.  $patron is the original patron
193         # passed in with the method.  new_patron will change as the components
194         # of patron are added/updated.
195
196         my $new_patron;
197
198         # unflesh the real items on the patron
199         $patron->card( $patron->card->id ) if(ref($patron->card));
200         $patron->billing_address( $patron->billing_address->id ) 
201                 if(ref($patron->billing_address));
202         $patron->mailing_address( $patron->mailing_address->id ) 
203                 if(ref($patron->mailing_address));
204
205         # create/update the patron first so we can use his id
206         if($patron->isnew()) {
207                 ( $new_patron, $evt ) = _add_patron($session, _clone_patron($patron), $user_obj);
208                 return $evt if $evt;
209         } else { $new_patron = $patron; }
210
211         ( $new_patron, $evt ) = _add_update_addresses($session, $patron, $new_patron, $user_obj);
212         return $evt if $evt;
213
214         ( $new_patron, $evt ) = _add_update_cards($session, $patron, $new_patron, $user_obj);
215         return $evt if $evt;
216
217         ( $new_patron, $evt ) = _add_survey_responses($session, $patron, $new_patron, $user_obj);
218         return $evt if $evt;
219
220         # re-update the patron if anything has happened to him during this process
221         if($new_patron->ischanged()) {
222                 ( $new_patron, $evt ) = _update_patron($session, $new_patron, $user_obj);
223                 return $evt if $evt;
224         }
225
226         #$session = OpenSRF::AppSession->create("open-ils.storage");  # why did i put this here?
227
228         ($new_patron, $evt) = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
229         return $evt if $evt;
230
231         ($new_patron, $evt) = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
232         return $evt if $evt;
233
234         ($new_patron, $evt) = _create_standing_penalties($session, $user_session, $patron, $new_patron, $user_obj);
235         return $evt if $evt;
236
237         $logger->activity("user ".$user_obj->id." updating/creating  user ".$new_patron->id);
238         $apputils->commit_db_session($session);
239
240         #warn "Patron Update/Create complete\n";
241         return flesh_user($new_patron->id());
242 }
243
244
245
246
247 __PACKAGE__->register_method(
248         method  => "user_retrieve_fleshed_by_id",
249         api_name        => "open-ils.actor.user.fleshed.retrieve",);
250
251 sub user_retrieve_fleshed_by_id {
252         my( $self, $client, $user_session, $user_id ) = @_;
253
254         my( $requestor, $target, $evt ) = $apputils->
255                 checkses_requestor( $user_session, $user_id, 'VIEW_USER' );
256         return $evt if $evt;
257
258         return flesh_user($user_id);
259 }
260
261
262 # fleshes: card, cards, address, addresses, stat_cat_entries, standing_penalties
263 sub flesh_user {
264         my $id = shift;
265         my $session = shift;
266
267         my $kill = 0;
268
269         if(!$session) {
270                 $session = OpenSRF::AppSession->create("open-ils.storage");
271                 $kill = 1;
272         }
273
274         # grab the user with the given id 
275         my $ureq = $session->request(
276                         "open-ils.storage.direct.actor.user.retrieve", $id);
277         my $user = $ureq->gather(1);
278
279         if(!$user) { return undef; }
280
281         # grab the cards
282         my $cards_req = $session->request(
283                         "open-ils.storage.direct.actor.card.search.usr.atomic",
284                         $user->id() );
285         $user->cards( $cards_req->gather(1) );
286
287         for my $c(@{$user->cards}) {
288                 if($c->id == $user->card || $c->id eq $user->card ) {
289                         #warn "Setting my card to " . $c->id . "\n";
290                         $user->card($c);
291                 }
292         }
293
294         my $add_req = $session->request(
295                         "open-ils.storage.direct.actor.user_address.search.usr.atomic",
296                         $user->id() );
297         $user->addresses( $add_req->gather(1) );
298
299         if( @{$user->addresses} ) {
300                 if( ! grep { $_->id eq $user->billing_address } @{$user->addresses} ) {
301                         my $ba = $session->request(
302                                 'open-ils.storage.direct.actor.user_address.retrieve', 
303                                 $user->billing_address)->gather(1);
304                         push( @{$user->addresses}, $ba );
305                 }
306         
307                 if( ! grep { $_->id eq $user->mailing_address } @{$user->addresses} ) {
308                         my $ba = $session->request(
309                                 'open-ils.storage.direct.actor.user_address.retrieve', 
310                                 $user->mailing_address)->gather(1);
311                         push( @{$user->addresses}, $ba );
312                 }
313         }
314
315
316         for my $c(@{$user->addresses}) {
317                 if($c->id eq $user->billing_address ) { $user->billing_address($c); }
318                 if($c->id eq $user->mailing_address ) { $user->mailing_address($c); }
319         }
320
321         my $stat_req = $session->request(
322                 "open-ils.storage.direct.actor.stat_cat_entry_user_map.search.target_usr.atomic",
323                 $user->id() );
324         $user->stat_cat_entries($stat_req->gather(1));
325
326         my $standing_penalties_req = $session->request(
327                 "open-ils.storage.direct.actor.user_standing_penalty.search.usr.atomic",
328                 $user->id() );
329         $user->standing_penalties($standing_penalties_req->gather(1));
330
331         if($kill) { $session->disconnect(); }
332         $user->clear_passwd();
333
334         return $user;
335 }
336
337
338 # clone and clear stuff that would break the database
339 sub _clone_patron {
340         my $patron = shift;
341
342         my $new_patron = $patron->clone;
343
344         # Using the Fieldmapper clone method
345         #my $new_patron = Fieldmapper::actor::user->new();
346
347         #my $fmap = $Fieldmapper::fieldmap;
348         #no strict; # shallow clone, may be useful in the fieldmapper
349         #for my $field 
350         #       (keys %{$fmap->{"Fieldmapper::actor::user"}->{'fields'}}) {
351         #               $new_patron->$field( $patron->$field() );
352         #}
353         #use strict;
354
355         # clear these
356         $new_patron->clear_billing_address();
357         $new_patron->clear_mailing_address();
358         $new_patron->clear_addresses();
359         $new_patron->clear_card();
360         $new_patron->clear_cards();
361         $new_patron->clear_id();
362         $new_patron->clear_isnew();
363         $new_patron->clear_ischanged();
364         $new_patron->clear_isdeleted();
365         $new_patron->clear_stat_cat_entries();
366         $new_patron->clear_permissions();
367         $new_patron->clear_standing_penalties();
368
369         return $new_patron;
370 }
371
372
373 sub _add_patron {
374
375         my $session             = shift;
376         my $patron              = shift;
377         my $user_obj    = shift;
378
379         my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'CREATE_USER');
380         return (undef, $evt) if $evt;
381
382         my $ex = $session->request(
383                 'open-ils.storage.direct.actor.user.search.usrname', $patron->usrname())->gather(1);
384         if( $ex and @$ex ) {
385                 return (undef, OpenILS::Event->new('USERNAME_EXISTS'));
386         }
387
388         $logger->info("Creating new user in the DB with username: ".$patron->usrname());
389
390         my $id = $session->request(
391                 "open-ils.storage.direct.actor.user.create", $patron)->gather(1);
392         return (undef, $U->DB_UPDATE_FAILED($patron)) unless $id;
393
394         $logger->info("Successfully created new user [$id] in DB");
395
396         return ( $session->request( 
397                 "open-ils.storage.direct.actor.user.retrieve", $id)->gather(1), undef );
398 }
399
400
401 sub _update_patron {
402         my( $session, $patron, $user_obj, $noperm) = @_;
403
404         $logger->info("Updating patron ".$patron->id." in DB");
405
406         if(!$noperm) {
407                 my $evt = $U->check_perms($user_obj->id, $patron->home_ou, 'UPDATE_USER');
408                 return (undef, $evt) if $evt;
409         }
410
411         # update the password by itself to avoid the password protection magic
412         if( $patron->passwd ) {
413                 my $s = $session->request(
414                         'open-ils.storage.direct.actor.user.remote_update',
415                         {id => $patron->id}, {passwd => $patron->passwd})->gather(1);
416                 return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($s);
417                 $patron->clear_passwd;
418         }
419
420         if(!$patron->ident_type) {
421                 $patron->clear_ident_type;
422                 $patron->clear_ident_value;
423         }
424
425         if(!$patron->ident_type2) {
426                 $patron->clear_ident_type2;
427                 $patron->clear_ident_value2;
428         }
429
430         my $stat = $session->request(
431                 "open-ils.storage.direct.actor.user.update",$patron )->gather(1);
432         return (undef, $U->DB_UPDATE_FAILED($patron)) unless defined($stat);
433
434         return ($patron);
435 }
436
437
438 sub _add_update_addresses {
439
440         my $session = shift;
441         my $patron = shift;
442         my $new_patron = shift;
443
444         my $evt;
445
446         my $current_id; # id of the address before creation
447
448         for my $address (@{$patron->addresses()}) {
449
450                 next unless ref $address;
451                 $current_id = $address->id();
452
453                 if( $patron->billing_address() and
454                         $patron->billing_address() == $current_id ) {
455                         $logger->info("setting billing addr to $current_id");
456                         $new_patron->billing_address($address->id());
457                         $new_patron->ischanged(1);
458                 }
459         
460                 if( $patron->mailing_address() and
461                         $patron->mailing_address() == $current_id ) {
462                         $new_patron->mailing_address($address->id());
463                         $logger->info("setting mailing addr to $current_id");
464                         $new_patron->ischanged(1);
465                 }
466
467
468                 if($address->isnew()) {
469
470                         $address->usr($new_patron->id());
471
472                         ($address, $evt) = _add_address($session,$address);
473                         return (undef, $evt) if $evt;
474
475                         # we need to get the new id
476                         if( $patron->billing_address() and 
477                                         $patron->billing_address() == $current_id ) {
478                                 $new_patron->billing_address($address->id());
479                                 $logger->info("setting billing addr to $current_id");
480                                 $new_patron->ischanged(1);
481                         }
482
483                         if( $patron->mailing_address() and
484                                         $patron->mailing_address() == $current_id ) {
485                                 $new_patron->mailing_address($address->id());
486                                 $logger->info("setting mailing addr to $current_id");
487                                 $new_patron->ischanged(1);
488                         }
489
490                 } elsif($address->ischanged() ) {
491
492                         ($address, $evt) = _update_address($session, $address);
493                         return (undef, $evt) if $evt;
494
495                 } elsif($address->isdeleted() ) {
496
497                         if( $address->id() == $new_patron->mailing_address() ) {
498                                 $new_patron->clear_mailing_address();
499                                 ($new_patron, $evt) = _update_patron($session, $new_patron);
500                                 return (undef, $evt) if $evt;
501                         }
502
503                         if( $address->id() == $new_patron->billing_address() ) {
504                                 $new_patron->clear_billing_address();
505                                 ($new_patron, $evt) = _update_patron($session, $new_patron);
506                                 return (undef, $evt) if $evt;
507                         }
508
509                         $evt = _delete_address($session, $address);
510                         return (undef, $evt) if $evt;
511                 } 
512         }
513
514         return ( $new_patron, undef );
515 }
516
517
518 # adds an address to the db and returns the address with new id
519 sub _add_address {
520         my($session, $address) = @_;
521         $address->clear_id();
522
523         $logger->info("Creating new address at street ".$address->street1);
524
525         # put the address into the database
526         my $id = $session->request(
527                 "open-ils.storage.direct.actor.user_address.create", $address )->gather(1);
528         return (undef, $U->DB_UPDATE_FAILED($address)) unless $id;
529
530         $address->id( $id );
531         return ($address, undef);
532 }
533
534
535 sub _update_address {
536         my( $session, $address ) = @_;
537
538         $logger->info("Updating address ".$address->id." in the DB");
539
540         my $stat = $session->request(
541                 "open-ils.storage.direct.actor.user_address.update", $address )->gather(1);
542
543         return (undef, $U->DB_UPDATE_FAILED($address)) unless defined($stat);
544         return ($address, undef);
545 }
546
547
548
549 sub _add_update_cards {
550
551         my $session = shift;
552         my $patron = shift;
553         my $new_patron = shift;
554
555         my $evt;
556
557         my $virtual_id; #id of the card before creation
558         for my $card (@{$patron->cards()}) {
559
560                 $card->usr($new_patron->id());
561
562                 if(ref($card) and $card->isnew()) {
563
564                         $virtual_id = $card->id();
565                         ( $card, $evt ) = _add_card($session,$card);
566                         return (undef, $evt) if $evt;
567
568                         #if(ref($patron->card)) { $patron->card($patron->card->id); }
569                         if($patron->card() == $virtual_id) {
570                                 $new_patron->card($card->id());
571                                 $new_patron->ischanged(1);
572                         }
573
574                 } elsif( ref($card) and $card->ischanged() ) {
575                         $evt = _update_card($session, $card);
576                         return (undef, $evt) if $evt;
577                 }
578         }
579
580         return ( $new_patron, undef );
581 }
582
583
584 # adds an card to the db and returns the card with new id
585 sub _add_card {
586         my( $session, $card ) = @_;
587         $card->clear_id();
588
589         $logger->info("Adding new patron card ".$card->barcode);
590
591         my $id = $session->request(
592                 "open-ils.storage.direct.actor.card.create", $card )->gather(1);
593         return (undef, $U->DB_UPDATE_FAILED($card)) unless $id;
594         $logger->info("Successfully created patron card $id");
595
596         $card->id($id);
597         return ( $card, undef );
598 }
599
600
601 # returns event on error.  returns undef otherwise
602 sub _update_card {
603         my( $session, $card ) = @_;
604         $logger->info("Updating patron card ".$card->id);
605
606         my $stat = $session->request(
607                 "open-ils.storage.direct.actor.card.update", $card )->gather(1);
608         return $U->DB_UPDATE_FAILED($card) unless defined($stat);
609         return undef;
610 }
611
612
613
614
615 # returns event on error.  returns undef otherwise
616 sub _delete_address {
617         my( $session, $address ) = @_;
618
619         $logger->info("Deleting address ".$address->id." from DB");
620
621         my $stat = $session->request(
622                 "open-ils.storage.direct.actor.user_address.delete", $address )->gather(1);
623
624         return $U->DB_UPDATE_FAILED($address) unless defined($stat);
625         return undef;
626 }
627
628
629
630 sub _add_survey_responses {
631         my ($session, $patron, $new_patron) = @_;
632
633         $logger->info( "Updating survey responses for patron ".$new_patron->id );
634
635         my $responses = $patron->survey_responses;
636
637         if($responses) {
638
639                 $_->usr($new_patron->id) for (@$responses);
640
641                 my $evt = $U->simplereq( "open-ils.circ", 
642                         "open-ils.circ.survey.submit.user_id", $responses );
643
644                 return (undef, $evt) if defined($U->event_code($evt));
645
646         }
647
648         return ( $new_patron, undef );
649 }
650
651
652 sub _create_stat_maps {
653
654         my($session, $user_session, $patron, $new_patron) = @_;
655
656         my $maps = $patron->stat_cat_entries();
657
658         for my $map (@$maps) {
659
660                 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
661
662                 if ($map->isdeleted()) {
663                         $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.delete";
664
665                 } elsif ($map->isnew()) {
666                         $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
667                         $map->clear_id;
668                 }
669
670
671                 $map->target_usr($new_patron->id);
672
673                 #warn "
674                 $logger->info("Updating stat entry with method $method and map $map");
675
676                 my $stat = $session->request($method, $map)->gather(1);
677                 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
678
679         }
680
681         return ($new_patron, undef);
682 }
683
684 sub _create_perm_maps {
685
686         my($session, $user_session, $patron, $new_patron) = @_;
687
688         my $maps = $patron->permissions;
689
690         for my $map (@$maps) {
691
692                 my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
693                 if ($map->isdeleted()) {
694                         $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
695                 } elsif ($map->isnew()) {
696                         $method = "open-ils.storage.direct.permission.usr_perm_map.create";
697                         $map->clear_id;
698                 }
699
700
701                 $map->usr($new_patron->id);
702
703                 #warn( "Updating permissions with method $method and session $user_session and map $map" );
704                 $logger->info( "Updating permissions with method $method and map $map" );
705
706                 my $stat = $session->request($method, $map)->gather(1);
707                 return (undef, $U->DB_UPDATE_FAILED($map)) unless defined($stat);
708
709         }
710
711         return ($new_patron, undef);
712 }
713
714
715 sub _create_standing_penalties {
716
717         my($session, $user_session, $patron, $new_patron) = @_;
718
719         my $maps = $patron->standing_penalties;
720         my $method;
721
722         for my $map (@$maps) {
723
724                 if ($map->isdeleted()) {
725                         $method = "open-ils.storage.direct.actor.user_standing_penalty.delete";
726                 } elsif ($map->isnew()) {
727                         $method = "open-ils.storage.direct.actor.user_standing_penalty.create";
728                         $map->clear_id;
729                 } else {
730                         next;
731                 }
732
733                 $map->usr($new_patron->id);
734
735                 $logger->debug( "Updating standing penalty with method $method and session $user_session and map $map" );
736
737                 my $stat = $session->request($method, $map)->gather(1);
738                 return (undef, $U->DB_UPDATE_FAILED($map)) unless $stat;
739         }
740
741         return ($new_patron, undef);
742 }
743
744
745
746 __PACKAGE__->register_method(
747         method  => "search_username",
748         api_name        => "open-ils.actor.user.search.username",
749 );
750
751 sub search_username {
752         my($self, $client, $username) = @_;
753         my $users = OpenILS::Application::AppUtils->simple_scalar_request(
754                         "open-ils.storage", 
755                         "open-ils.storage.direct.actor.user.search.usrname.atomic",
756                         $username );
757         return $users;
758 }
759
760
761
762
763 __PACKAGE__->register_method(
764         method  => "user_retrieve_by_barcode",
765         api_name        => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
766
767 sub user_retrieve_by_barcode {
768         my($self, $client, $user_session, $barcode) = @_;
769
770         $logger->debug("Searching for user with barcode $barcode");
771         my ($user_obj, $evt) = $apputils->checkses($user_session);
772         return $evt if $evt;
773
774
775         my $session = OpenSRF::AppSession->create("open-ils.storage");
776
777         # find the card with the given barcode
778         my $creq        = $session->request(
779                         "open-ils.storage.direct.actor.card.search.barcode.atomic",
780                         $barcode );
781         my $card = $creq->gather(1);
782
783         if(!$card || !$card->[0]) {
784                 $session->disconnect();
785                 return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' );
786         }
787
788         $card = $card->[0];
789         my $user = flesh_user($card->usr(), $session);
790
791         $evt = $U->check_perms($user_obj->id, $user->home_ou, 'VIEW_USER');
792         return $evt if $evt;
793
794         $session->disconnect();
795         if(!$user) { return OpenILS::Event->new( 'ACTOR_USER_NOT_FOUND' ); }
796         return $user;
797
798 }
799
800
801
802 __PACKAGE__->register_method(
803         method  => "get_user_by_id",
804         api_name        => "open-ils.actor.user.retrieve",);
805
806 sub get_user_by_id {
807         my ($self, $client, $user_session, $id) = @_;
808
809         my $user_obj = $apputils->check_user_session( $user_session ); 
810
811         return $apputils->simple_scalar_request(
812                 "open-ils.storage",
813                 "open-ils.storage.direct.actor.user.retrieve",
814                 $id );
815 }
816
817
818
819 __PACKAGE__->register_method(
820         method  => "get_org_types",
821         api_name        => "open-ils.actor.org_types.retrieve",);
822
823 my $org_types;
824 sub get_org_types {
825         my($self, $client) = @_;
826
827         return $org_types if $org_types;
828          return $org_types = 
829                  $apputils->simple_scalar_request(
830                         "open-ils.storage",
831                         "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
832 }
833
834
835
836 __PACKAGE__->register_method(
837         method  => "get_user_profiles",
838         api_name        => "open-ils.actor.user.profiles.retrieve",
839 );
840
841 my $user_profiles;
842 sub get_user_profiles {
843         return $user_profiles if $user_profiles;
844
845         return $user_profiles = 
846                 $apputils->simple_scalar_request(
847                         "open-ils.storage",
848                         "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
849 }
850
851
852
853 __PACKAGE__->register_method(
854         method  => "get_user_ident_types",
855         api_name        => "open-ils.actor.user.ident_types.retrieve",
856 );
857 my $ident_types;
858 sub get_user_ident_types {
859         return $ident_types if $ident_types;
860         return $ident_types = 
861                 $apputils->simple_scalar_request(
862                 "open-ils.storage",
863                 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
864 }
865
866
867
868
869 __PACKAGE__->register_method(
870         method  => "get_org_unit",
871         api_name        => "open-ils.actor.org_unit.retrieve",
872 );
873
874 sub get_org_unit {
875
876         my( $self, $client, $user_session, $org_id ) = @_;
877
878         if(defined($user_session) && !defined($org_id)) {
879                 my $user_obj = 
880                         OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
881                 if(!defined($org_id)) {
882                         $org_id = $user_obj->home_ou;
883                 }
884         }
885
886
887         my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
888                 "open-ils.storage",
889                 "open-ils.storage.direct.actor.org_unit.retrieve", 
890                 $org_id );
891
892         return $home_ou;
893 }
894
895 __PACKAGE__->register_method(
896         method  => "search_org_unit",
897         api_name        => "open-ils.actor.org_unit_list.search",
898 );
899
900 sub search_org_unit {
901
902         my( $self, $client, $field, $value ) = @_;
903
904         my $list = OpenILS::Application::AppUtils->simple_scalar_request(
905                 "open-ils.storage",
906                 "open-ils.storage.direct.actor.org_unit.search.$field.atomic", 
907                 $value );
908
909         return $list;
910 }
911
912
913 # build the org tree
914
915 __PACKAGE__->register_method(
916         method  => "get_org_tree",
917         api_name        => "open-ils.actor.org_tree.retrieve",
918         argc            => 0, 
919         note            => "Returns the entire org tree structure",
920 );
921
922 sub get_org_tree {
923         my( $self, $client) = @_;
924
925         if(!$cache_client) {
926                 $cache_client = OpenSRF::Utils::Cache->new("global", 0);
927         }
928         # see if it's in the cache
929         #warn "Getting ORG Tree\n";
930         my $tree = $cache_client->get_cache('orgtree');
931         if($tree) { 
932                 #warn "Found orgtree in cache. returning...\n";
933                 return $tree; 
934         }
935
936         my $orglist = $apputils->simple_scalar_request( 
937                 "open-ils.storage", 
938                 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
939
940         #if($orglist) {
941                 #warn "found org list\n";
942         #}
943
944         $tree = $self->build_org_tree($orglist);
945         $cache_client->put_cache('orgtree', $tree);
946
947         return $tree;
948
949 }
950
951 # turns an org list into an org tree
952 sub build_org_tree {
953
954         my( $self, $orglist) = @_;
955
956         return $orglist unless ( 
957                         ref($orglist) and @$orglist > 1 );
958
959         my @list = sort { 
960                 $a->ou_type <=> $b->ou_type ||
961                 $a->name cmp $b->name } @$orglist;
962
963         for my $org (@list) {
964
965                 next unless ($org and defined($org->parent_ou));
966                 my ($parent) = grep { $_->id == $org->parent_ou } @list;
967                 next unless $parent;
968
969                 $parent->children([]) unless defined($parent->children); 
970                 push( @{$parent->children}, $org );
971         }
972
973         return $list[0];
974
975 }
976
977
978 __PACKAGE__->register_method(
979         method  => "get_org_descendants",
980         api_name        => "open-ils.actor.org_tree.descendants.retrieve"
981 );
982
983 # depth is optional.  org_unit is the id
984 sub get_org_descendants {
985         my( $self, $client, $org_unit, $depth ) = @_;
986         my $orglist = $apputils->simple_scalar_request(
987                         "open-ils.storage", 
988                         "open-ils.storage.actor.org_unit.descendants.atomic",
989                         $org_unit, $depth );
990         return $self->build_org_tree($orglist);
991 }
992
993
994 __PACKAGE__->register_method(
995         method  => "get_org_ancestors",
996         api_name        => "open-ils.actor.org_tree.ancestors.retrieve"
997 );
998
999 # depth is optional.  org_unit is the id
1000 sub get_org_ancestors {
1001         my( $self, $client, $org_unit, $depth ) = @_;
1002         my $orglist = $apputils->simple_scalar_request(
1003                         "open-ils.storage", 
1004                         "open-ils.storage.actor.org_unit.ancestors.atomic",
1005                         $org_unit, $depth );
1006         return $self->build_org_tree($orglist);
1007 }
1008
1009
1010 __PACKAGE__->register_method(
1011         method  => "get_standings",
1012         api_name        => "open-ils.actor.standings.retrieve"
1013 );
1014
1015 my $user_standings;
1016 sub get_standings {
1017         return $user_standings if $user_standings;
1018         return $user_standings = 
1019                 $apputils->simple_scalar_request(
1020                         "open-ils.storage",
1021                         "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
1022 }
1023
1024
1025
1026 __PACKAGE__->register_method(
1027         method  => "get_my_org_path",
1028         api_name        => "open-ils.actor.org_unit.full_path.retrieve"
1029 );
1030
1031 sub get_my_org_path {
1032         my( $self, $client, $user_session, $org_id ) = @_;
1033         my $user_obj = $apputils->check_user_session($user_session); 
1034         if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
1035
1036         return $apputils->simple_scalar_request(
1037                 "open-ils.storage",
1038                 "open-ils.storage.actor.org_unit.full_path.atomic",
1039                 $org_id );
1040 }
1041
1042
1043 __PACKAGE__->register_method(
1044         method  => "patron_adv_search",
1045         api_name        => "open-ils.actor.patron.search.advanced" );
1046 sub patron_adv_search {
1047         my( $self, $client, $auth, $search_hash, $search_limit, $search_sort ) = @_;
1048         my $e = OpenILS::Utils::Editor->new(authtoken=>$auth);
1049         return $e->event unless $e->checkauth;
1050         return $e->event unless $e->allowed('VIEW_USER');
1051         return $e->request(
1052                 "open-ils.storage.actor.user.crazy_search", 
1053                 $search_hash, $search_limit, $search_sort);
1054 }
1055
1056
1057
1058 sub _verify_password {
1059         my($user_session, $password) = @_;
1060         my $user_obj = $apputils->check_user_session($user_session); 
1061
1062         #grab the user with password
1063         $user_obj = $apputils->simple_scalar_request(
1064                 "open-ils.storage", 
1065                 "open-ils.storage.direct.actor.user.retrieve",
1066                 $user_obj->id );
1067
1068         if($user_obj->passwd eq $password) {
1069                 return 1;
1070         }
1071
1072         return 0;
1073 }
1074
1075
1076 __PACKAGE__->register_method(
1077         method  => "update_password",
1078         api_name        => "open-ils.actor.user.password.update");
1079
1080 __PACKAGE__->register_method(
1081         method  => "update_password",
1082         api_name        => "open-ils.actor.user.username.update");
1083
1084 __PACKAGE__->register_method(
1085         method  => "update_password",
1086         api_name        => "open-ils.actor.user.email.update");
1087
1088 sub update_password {
1089         my( $self, $client, $user_session, $new_value, $current_password ) = @_;
1090
1091         my $evt;
1092
1093         my $user_obj = $apputils->check_user_session($user_session); 
1094
1095         if($self->api_name =~ /password/o) {
1096
1097                 #make sure they know the current password
1098                 if(!_verify_password($user_session, md5_hex($current_password))) {
1099                         return OpenILS::Event->new('INCORRECT_PASSWORD');
1100                 }
1101
1102                 $logger->debug("update_password setting new password $new_value");
1103                 $user_obj->passwd($new_value);
1104
1105         } elsif($self->api_name =~ /username/o) {
1106                 my $users = search_username(undef, undef, $new_value); 
1107                 if( $users and $users->[0] ) {
1108                         return OpenILS::Event->new('USERNAME_EXISTS');
1109                 }
1110                 $user_obj->usrname($new_value);
1111
1112         } elsif($self->api_name =~ /email/o) {
1113                 #warn "Updating email to $new_value\n";
1114                 $user_obj->email($new_value);
1115         }
1116
1117         my $session = $apputils->start_db_session();
1118
1119         ( $user_obj, $evt ) = _update_patron($session, $user_obj, $user_obj, 1);
1120         return $evt if $evt;
1121
1122         $apputils->commit_db_session($session);
1123
1124         if($user_obj) { return 1; }
1125         return undef;
1126 }
1127
1128
1129 __PACKAGE__->register_method(
1130         method  => "check_user_perms",
1131         api_name        => "open-ils.actor.user.perm.check",
1132         notes           => <<"  NOTES");
1133         Takes a login session, user id, an org id, and an array of perm type strings.  For each
1134         perm type, if the user does *not* have the given permission it is added
1135         to a list which is returned from the method.  If all permissions
1136         are allowed, an empty list is returned
1137         if the logged in user does not match 'user_id', then the logged in user must
1138         have VIEW_PERMISSION priveleges.
1139         NOTES
1140
1141 sub check_user_perms {
1142         my( $self, $client, $login_session, $user_id, $org_id, $perm_types ) = @_;
1143
1144         my( $staff, $evt ) = $apputils->checkses($login_session);
1145         return $evt if $evt;
1146
1147         if($staff->id ne $user_id) {
1148                 if( my $evt = $apputils->check_perms(
1149                         $staff->id, $org_id, 'VIEW_PERMISSION') ) {
1150                         return $evt;
1151                 }
1152         }
1153
1154         my @not_allowed;
1155         for my $perm (@$perm_types) {
1156                 if($apputils->check_perms($user_id, $org_id, $perm)) {
1157                         push @not_allowed, $perm;
1158                 }
1159         }
1160
1161         return \@not_allowed
1162 }
1163
1164 __PACKAGE__->register_method(
1165         method  => "check_user_perms2",
1166         api_name        => "open-ils.actor.user.perm.check.multi_org",
1167         notes           => q/
1168                 Checks the permissions on a list of perms and orgs for a user
1169                 @param authtoken The login session key
1170                 @param user_id The id of the user to check
1171                 @param orgs The array of org ids
1172                 @param perms The array of permission names
1173                 @return An array of  [ orgId, permissionName ] arrays that FAILED the check
1174                 if the logged in user does not match 'user_id', then the logged in user must
1175                 have VIEW_PERMISSION priveleges.
1176         /);
1177
1178 sub check_user_perms2 {
1179         my( $self, $client, $authtoken, $user_id, $orgs, $perms ) = @_;
1180
1181         my( $staff, $target, $evt ) = $apputils->checkses_requestor(
1182                 $authtoken, $user_id, 'VIEW_PERMISSION' );
1183         return $evt if $evt;
1184
1185         my @not_allowed;
1186         for my $org (@$orgs) {
1187                 for my $perm (@$perms) {
1188                         if($apputils->check_perms($user_id, $org, $perm)) {
1189                                 push @not_allowed, [ $org, $perm ];
1190                         }
1191                 }
1192         }
1193
1194         return \@not_allowed
1195 }
1196
1197
1198 __PACKAGE__->register_method(
1199         method => 'check_user_perms3',
1200         api_name        => 'open-ils.actor.user.perm.highest_org',
1201         notes           => q/
1202                 Returns the highest org unit id at which a user has a given permission
1203                 If the requestor does not match the target user, the requestor must have
1204                 'VIEW_PERMISSION' rights at the home org unit of the target user
1205                 @param authtoken The login session key
1206                 @param userid The id of the user in question
1207                 @param perm The permission to check
1208                 @return The org unit highest in the org tree within which the user has
1209                 the requested permission
1210         /);
1211
1212 sub check_user_perms3 {
1213         my( $self, $client, $authtoken, $userid, $perm ) = @_;
1214
1215         my( $staff, $target, $org, $evt );
1216
1217         ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1218                 $authtoken, $userid, 'VIEW_PERMISSION' );
1219         return $evt if $evt;
1220
1221         my $tree = $self->get_org_tree();
1222         return _find_highest_perm_org( $perm, $userid, $target->home_ou, $tree );
1223 }
1224
1225
1226 sub _find_highest_perm_org {
1227         my ( $perm, $userid, $start_org, $org_tree ) = @_;
1228         my $org = $apputils->find_org($org_tree, $start_org );
1229
1230         my $lastid = undef;
1231         while( $org ) {
1232                 last if ($apputils->check_perms( $userid, $org->id, $perm )); # perm failed
1233                 $lastid = $org->id;
1234                 $org = $apputils->find_org( $org_tree, $org->parent_ou() );
1235         }
1236
1237         return $lastid;
1238 }
1239
1240 __PACKAGE__->register_method(
1241         method => 'check_user_perms4',
1242         api_name        => 'open-ils.actor.user.perm.highest_org.batch',
1243         notes           => q/
1244                 Returns the highest org unit id at which a user has a given permission
1245                 If the requestor does not match the target user, the requestor must have
1246                 'VIEW_PERMISSION' rights at the home org unit of the target user
1247                 @param authtoken The login session key
1248                 @param userid The id of the user in question
1249                 @param perms An array of perm names to check 
1250                 @return An array of orgId's  representing the org unit 
1251                 highest in the org tree within which the user has the requested permission
1252                 The arrah of orgId's has matches the order of the perms array
1253         /);
1254
1255 sub check_user_perms4 {
1256         my( $self, $client, $authtoken, $userid, $perms ) = @_;
1257         
1258         my( $staff, $target, $org, $evt );
1259
1260         ( $staff, $target, $evt ) = $apputils->checkses_requestor(
1261                 $authtoken, $userid, 'VIEW_PERMISSION' );
1262         return $evt if $evt;
1263
1264         my @arr;
1265         return [] unless ref($perms);
1266         my $tree = $self->get_org_tree();
1267
1268         for my $p (@$perms) {
1269                 push( @arr, _find_highest_perm_org( $p, $userid, $target->home_ou, $tree ) );
1270         }
1271         return \@arr;
1272 }
1273
1274
1275
1276
1277 __PACKAGE__->register_method(
1278         method  => "user_fines_summary",
1279         api_name        => "open-ils.actor.user.fines.summary",
1280         notes           => <<"  NOTES");
1281         Returns a short summary of the users total open fines, excluding voided fines
1282         Params are login_session, user_id
1283         Returns a 'mous' object.
1284         NOTES
1285
1286 sub user_fines_summary {
1287         my( $self, $client, $login_session, $user_id ) = @_;
1288
1289         my $user_obj = $apputils->check_user_session($login_session); 
1290         if($user_obj->id ne $user_id) {
1291                 if($apputils->check_user_perms($user_obj->id, $user_obj->home_ou, "VIEW_USER_FINES_SUMMARY")) {
1292                         return OpenILS::Perm->new("VIEW_USER_FINES_SUMMARY"); 
1293                 }
1294         }
1295
1296         return $apputils->simple_scalar_request( 
1297                 "open-ils.storage",
1298                 "open-ils.storage.direct.money.open_user_summary.search.usr",
1299                 $user_id );
1300
1301 }
1302
1303
1304
1305
1306 __PACKAGE__->register_method(
1307         method  => "user_transactions",
1308         api_name        => "open-ils.actor.user.transactions",
1309         notes           => <<"  NOTES");
1310         Returns a list of open user transactions (mbts objects);
1311         Params are login_session, user_id
1312         Optional third parameter is the transactions type.  defaults to all
1313         NOTES
1314
1315 __PACKAGE__->register_method(
1316         method  => "user_transactions",
1317         api_name        => "open-ils.actor.user.transactions.have_charge",
1318         notes           => <<"  NOTES");
1319         Returns a list of all open user transactions (mbts objects) that have an initial charge
1320         Params are login_session, user_id
1321         Optional third parameter is the transactions type.  defaults to all
1322         NOTES
1323
1324 __PACKAGE__->register_method(
1325         method  => "user_transactions",
1326         api_name        => "open-ils.actor.user.transactions.have_balance",
1327         notes           => <<"  NOTES");
1328         Returns a list of all open user transactions (mbts objects) that have a balance
1329         Params are login_session, user_id
1330         Optional third parameter is the transactions type.  defaults to all
1331         NOTES
1332
1333 __PACKAGE__->register_method(
1334         method  => "user_transactions",
1335         api_name        => "open-ils.actor.user.transactions.fleshed",
1336         notes           => <<"  NOTES");
1337         Returns an object/hash of transaction, circ, title where transaction = an open 
1338         user transactions (mbts objects), circ is the attached circluation, and title
1339         is the title the circ points to
1340         Params are login_session, user_id
1341         Optional third parameter is the transactions type.  defaults to all
1342         NOTES
1343
1344 __PACKAGE__->register_method(
1345         method  => "user_transactions",
1346         api_name        => "open-ils.actor.user.transactions.have_charge.fleshed",
1347         notes           => <<"  NOTES");
1348         Returns an object/hash of transaction, circ, title where transaction = an open 
1349         user transactions that has an initial charge (mbts objects), circ is the 
1350         attached circluation, and title is the title the circ points to
1351         Params are login_session, user_id
1352         Optional third parameter is the transactions type.  defaults to all
1353         NOTES
1354
1355 __PACKAGE__->register_method(
1356         method  => "user_transactions",
1357         api_name        => "open-ils.actor.user.transactions.have_balance.fleshed",
1358         notes           => <<"  NOTES");
1359         Returns an object/hash of transaction, circ, title where transaction = an open 
1360         user transaction that has a balance (mbts objects), circ is the attached 
1361         circluation, and title is the title the circ points to
1362         Params are login_session, user_id
1363         Optional third parameter is the transaction type.  defaults to all
1364         NOTES
1365
1366 __PACKAGE__->register_method(
1367         method  => "user_transactions",
1368         api_name        => "open-ils.actor.user.transactions.count",
1369         notes           => <<"  NOTES");
1370         Returns an object/hash of transaction, circ, title where transaction = an open 
1371         user transactions (mbts objects), circ is the attached circluation, and title
1372         is the title the circ points to
1373         Params are login_session, user_id
1374         Optional third parameter is the transactions type.  defaults to all
1375         NOTES
1376
1377 __PACKAGE__->register_method(
1378         method  => "user_transactions",
1379         api_name        => "open-ils.actor.user.transactions.have_charge.count",
1380         notes           => <<"  NOTES");
1381         Returns an object/hash of transaction, circ, title where transaction = an open 
1382         user transactions that has an initial charge (mbts objects), circ is the 
1383         attached circluation, and title is the title the circ points to
1384         Params are login_session, user_id
1385         Optional third parameter is the transactions type.  defaults to all
1386         NOTES
1387
1388 __PACKAGE__->register_method(
1389         method  => "user_transactions",
1390         api_name        => "open-ils.actor.user.transactions.have_balance.count",
1391         notes           => <<"  NOTES");
1392         Returns an object/hash of transaction, circ, title where transaction = an open 
1393         user transaction that has a balance (mbts objects), circ is the attached 
1394         circluation, and title is the title the circ points to
1395         Params are login_session, user_id
1396         Optional third parameter is the transaction type.  defaults to all
1397         NOTES
1398
1399 __PACKAGE__->register_method(
1400         method  => "user_transactions",
1401         api_name        => "open-ils.actor.user.transactions.have_balance.total",
1402         notes           => <<"  NOTES");
1403         Returns an object/hash of transaction, circ, title where transaction = an open 
1404         user transaction that has a balance (mbts objects), circ is the attached 
1405         circluation, and title is the title the circ points to
1406         Params are login_session, user_id
1407         Optional third parameter is the transaction type.  defaults to all
1408         NOTES
1409
1410
1411
1412 sub user_transactions {
1413         my( $self, $client, $login_session, $user_id, $type ) = @_;
1414
1415         my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1416                 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1417         return $evt if $evt;
1418         
1419         my $api = $self->api_name();
1420         my $trans;
1421         my @xact;
1422
1423         if(defined($type)) { @xact = (xact_type =>  $type); 
1424
1425         } else { @xact = (); }
1426
1427         if($api =~ /have_charge/o) {
1428
1429                 $trans = $apputils->simple_scalar_request( 
1430                         "open-ils.storage",
1431                         "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1432                         { usr => $user_id, total_owed => { ">" => 0 }, @xact });
1433
1434         } elsif($api =~ /have_balance/o) {
1435
1436                 $trans =  $apputils->simple_scalar_request( 
1437                         "open-ils.storage",
1438                         "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1439                         { usr => $user_id, balance_owed => { "<>" => 0 }, @xact });
1440
1441         } else {
1442
1443                 $trans =  $apputils->simple_scalar_request( 
1444                         "open-ils.storage",
1445                         "open-ils.storage.direct.money.open_billable_transaction_summary.search_where.atomic",
1446                         { usr => $user_id, @xact });
1447         }
1448
1449         if($api =~ /total/o) { 
1450                 my $total = 0.0;
1451                 for my $t (@$trans) {
1452                         $total += $t->balance_owed;
1453                 }
1454
1455                 $logger->debug("Total balance owed by user $user_id: $total");
1456                 return $total;
1457         }
1458
1459         if($api =~ /count/o) { return scalar @$trans; }
1460         if($api !~ /fleshed/o) { return $trans; }
1461
1462         my @resp;
1463         for my $t (@$trans) {
1464                         
1465                 if( $t->xact_type ne 'circulation' ) {
1466                         push @resp, {transaction => $t};
1467                         next;
1468                 }
1469
1470                 my $circ = $apputils->simple_scalar_request(
1471                                 "open-ils.storage",
1472                                 "open-ils.storage.direct.action.circulation.retrieve",
1473                                 $t->id );
1474
1475                 next unless $circ;
1476
1477                 my $title = $apputils->simple_scalar_request(
1478                         "open-ils.storage", 
1479                         "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1480                         $circ->target_copy );
1481
1482                 next unless $title;
1483
1484                 my $u = OpenILS::Utils::ModsParser->new();
1485                 $u->start_mods_batch($title->marc());
1486                 my $mods = $u->finish_mods_batch();
1487
1488                 push @resp, {transaction => $t, circ => $circ, record => $mods };
1489
1490         }
1491
1492         return \@resp; 
1493
1494
1495
1496 __PACKAGE__->register_method(
1497         method  => "user_transaction_retrieve",
1498         api_name        => "open-ils.actor.user.transaction.fleshed.retrieve",
1499         argc            => 1,
1500         notes           => <<"  NOTES");
1501         Returns a fleshedtransaction record
1502         NOTES
1503 __PACKAGE__->register_method(
1504         method  => "user_transaction_retrieve",
1505         api_name        => "open-ils.actor.user.transaction.retrieve",
1506         argc            => 1,
1507         notes           => <<"  NOTES");
1508         Returns a transaction record
1509         NOTES
1510 sub user_transaction_retrieve {
1511         my( $self, $client, $login_session, $bill_id ) = @_;
1512
1513         my $trans = $apputils->simple_scalar_request( 
1514                 "open-ils.storage",
1515                 "open-ils.storage.direct.money.billable_transaction_summary.retrieve",
1516                 $bill_id
1517         );
1518
1519         my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1520                 $login_session, $trans->usr, 'VIEW_USER_TRANSACTIONS' );
1521         return $evt if $evt;
1522         
1523         my $api = $self->api_name();
1524         if($api !~ /fleshed/o) { return $trans; }
1525
1526         if( $trans->xact_type ne 'circulation' ) {
1527                 $logger->debug("Returning non-circ transaction");
1528                 return {transaction => $trans};
1529         }
1530
1531         my $circ = $apputils->simple_scalar_request(
1532                         "open-ils.storage",
1533                         "open-ils.storage.direct.action.circulation.retrieve",
1534                         $trans->id );
1535
1536         return {transaction => $trans} unless $circ;
1537         $logger->debug("Found the circ transaction");
1538
1539         my $title = $apputils->simple_scalar_request(
1540                 "open-ils.storage", 
1541                 "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
1542                 $circ->target_copy );
1543
1544         return {transaction => $trans, circ => $circ } unless $title;
1545         $logger->debug("Found the circ title");
1546
1547         my $mods;
1548         try {
1549                 my $u = OpenILS::Utils::ModsParser->new();
1550                 $u->start_mods_batch($title->marc());
1551                 $mods = $u->finish_mods_batch();
1552         } otherwise {
1553                 if ($title->id == -1) {
1554                         my $copy = $apputils->simple_scalar_request(
1555                                 "open-ils.storage",
1556                                 "open-ils.storage.direct.asset.copy.retrieve",
1557                                 $circ->target_copy );
1558
1559                         $mods = new Fieldmapper::metabib::virtual_record;
1560                         $mods->doc_id(-1);
1561                         $mods->title($copy->dummy_title);
1562                         $mods->author($copy->dummy_author);
1563                 }
1564         };
1565
1566         $logger->debug("MODSized the circ title");
1567
1568         return {transaction => $trans, circ => $circ, record => $mods };
1569 }
1570
1571
1572 __PACKAGE__->register_method(
1573         method  => "hold_request_count",
1574         api_name        => "open-ils.actor.user.hold_requests.count",
1575         argc            => 1,
1576         notes           => <<"  NOTES");
1577         Returns hold ready/total counts
1578         NOTES
1579 sub hold_request_count {
1580         my( $self, $client, $login_session, $userid ) = @_;
1581
1582         my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1583                 $login_session, $userid, 'VIEW_HOLD' );
1584         return $evt if $evt;
1585         
1586
1587         my $holds = $apputils->simple_scalar_request(
1588                         "open-ils.storage",
1589                         "open-ils.storage.direct.action.hold_request.search_where.atomic",
1590                         { usr => $userid,
1591                           fulfillment_time => {"=" => undef } }
1592         );
1593
1594         my @ready;
1595         for my $h (@$holds) {
1596                 next unless $h->capture_time;
1597
1598                 my $copy = $apputils->simple_scalar_request(
1599                         "open-ils.storage",
1600                         "open-ils.storage.direct.asset.copy.retrieve",
1601                         $h->current_copy
1602                 );
1603
1604                 if ($copy->status == 8) {
1605                         push @ready, $h;
1606                 }
1607         }
1608
1609         return { total => scalar(@$holds), ready => scalar(@ready) };
1610 }
1611
1612
1613 __PACKAGE__->register_method(
1614         method  => "checkedout_count",
1615         api_name        => "open-ils.actor.user.checked_out.count",
1616         argc            => 1,
1617         notes           => <<"  NOTES");
1618         Returns a transaction record
1619         NOTES
1620
1621 # XXX Deprecate Me
1622 sub checkedout_count {
1623         my( $self, $client, $login_session, $userid ) = @_;
1624
1625         my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1626                 $login_session, $userid, 'VIEW_CIRCULATIONS' );
1627         return $evt if $evt;
1628         
1629         my $circs = $apputils->simple_scalar_request(
1630                         "open-ils.storage",
1631                         "open-ils.storage.direct.action.circulation.search_where.atomic",
1632                         { usr => $userid, stop_fines => undef }
1633                         #{ usr => $userid, checkin_time => {"=" => undef } }
1634         );
1635
1636         my $parser = DateTime::Format::ISO8601->new;
1637
1638         my (@out,@overdue);
1639         for my $c (@$circs) {
1640                 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1641                 my $due = $due_dt->epoch;
1642
1643                 if ($due < DateTime->today->epoch) {
1644                         push @overdue, $c;
1645                 }
1646         }
1647
1648         return { total => scalar(@$circs), overdue => scalar(@overdue) };
1649 }
1650
1651
1652 __PACKAGE__->register_method(
1653         method          => "checked_out",
1654         api_name                => "open-ils.actor.user.checked_out",
1655         argc                    => 2,
1656         signature       => q/
1657                 Returns a structure of circulations objects sorted by
1658                 out, overdue, lost, claims_returned, long_overdue.
1659                 A list of IDs are returned of each type.
1660                 lost, long_overdue, and claims_returned circ will not
1661                 be "finished" (there is an outstanding balance or some 
1662                 other pending action on the circ). 
1663
1664                 The .count method also includes a 'total' field which 
1665                 sums all "open" circs
1666         /
1667 );
1668
1669 __PACKAGE__->register_method(
1670         method          => "checked_out",
1671         api_name                => "open-ils.actor.user.checked_out.count_",
1672         argc                    => 2,
1673         signature       => q/@see open-ils.actor.user.checked_out/
1674 );
1675
1676 sub checked_out {
1677         my( $self, $conn, $auth, $userid ) = @_;
1678
1679         my $e = new_editor(authtoken=>$auth);
1680         return $e->event unless $e->checkauth;
1681
1682         if( $userid ne $e->requestor->id ) {
1683                 return $e->event unless $e->allowed('VIEW_CIRCULATIONS');
1684         }
1685
1686         my $circs = $e->search_action_circulation( 
1687                 { usr => $userid, stop_fines => undef });
1688
1689         my $parser = DateTime::Format::ISO8601->new;
1690
1691         # split the circs up into overdue and not-overdue circs
1692         my (@out,@overdue);
1693         for my $c (@$circs) {
1694                 my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
1695                 my $due = $due_dt->epoch;
1696                 if ($due < DateTime->today->epoch) {
1697                         push @overdue, $c->id;
1698                 } else {
1699                         push @out, $c->id;
1700                 }
1701         }
1702
1703         # grab all of the lost, claims-returned, and longoverdue circs
1704         my $open = $e->search_action_circulation(
1705                 {usr => $userid, stop_fines => { '!=' => undef }, xact_finish => undef });
1706
1707         my( @lost, @cr, @lo );
1708         for my $c (@$open) {
1709                 push( @lost, $c->id ) if $c->stop_fines eq 'LOST';
1710                 push( @cr, $c->id ) if $c->stop_fines eq 'CLAIMSRETURNED';
1711                 push( @lo, $c->id ) if $c->stop_fines eq 'LONGOVERDUE';
1712         }
1713
1714
1715         if( $self->api_name =~ /count/ ) {
1716                 return {
1717                         total           => @$circs + @lost + @cr + @lo,
1718                         out             => scalar(@out),
1719                         overdue => scalar(@overdue),
1720                         lost            => scalar(@lost),
1721                         claims_returned => scalar(@cr),
1722                         long_overdue            => scalar(@lo)
1723                 };
1724         }
1725
1726         return {
1727                 out             => \@out,
1728                 overdue => \@overdue,
1729                 lost            => \@lost,
1730                 claims_returned => \@cr,
1731                 long_overdue            => \@lo
1732         };
1733 }
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743 __PACKAGE__->register_method(
1744         method  => "user_transaction_history",
1745         api_name        => "open-ils.actor.user.transactions.history",
1746         argc            => 1,
1747         notes           => <<"  NOTES");
1748         Returns a list of billable transaction ids for a user, optionally by type
1749         NOTES
1750 __PACKAGE__->register_method(
1751         method  => "user_transaction_history",
1752         api_name        => "open-ils.actor.user.transactions.history.have_charge",
1753         argc            => 1,
1754         notes           => <<"  NOTES");
1755         Returns a list of billable transaction ids for a user that have an initial charge, optionally by type
1756         NOTES
1757 sub user_transaction_history {
1758         my( $self, $client, $login_session, $user_id, $type ) = @_;
1759
1760         my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
1761                 $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
1762         return $evt if $evt;
1763         
1764         my $api = $self->api_name();
1765         my @xact;
1766         my @charge;
1767
1768         @xact = (xact_type =>  $type) if(defined($type));
1769         @charge = (total_owed => { ">" => 0}) if($api =~ /have_charge/);
1770
1771         my $trans = $apputils->simple_scalar_request( 
1772                 "open-ils.storage",
1773                 "open-ils.storage.direct.money.billable_transaction_summary.search_where.atomic",
1774                 { usr => $user_id, @xact, @charge }, { order_by => 'xact_start DESC' });
1775
1776         return [ map { $_->id } @$trans ];
1777 }
1778
1779
1780 __PACKAGE__->register_method(
1781         method  => "user_perms",
1782         api_name        => "open-ils.actor.permissions.user_perms.retrieve",
1783         argc            => 1,
1784         notes           => <<"  NOTES");
1785         Returns a list of permissions
1786         NOTES
1787 sub user_perms {
1788         my( $self, $client, $authtoken, $user ) = @_;
1789
1790         my( $staff, $evt ) = $apputils->checkses($authtoken);
1791         return $evt if $evt;
1792
1793         $user ||= $staff->id;
1794
1795         if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
1796                 return $evt;
1797         }
1798
1799         return $apputils->simple_scalar_request(
1800                 "open-ils.storage",
1801                 "open-ils.storage.permission.user_perms.atomic",
1802                 $user);
1803 }
1804
1805 __PACKAGE__->register_method(
1806         method  => "retrieve_perms",
1807         api_name        => "open-ils.actor.permissions.retrieve",
1808         notes           => <<"  NOTES");
1809         Returns a list of permissions
1810         NOTES
1811 sub retrieve_perms {
1812         my( $self, $client ) = @_;
1813         return $apputils->simple_scalar_request(
1814                 "open-ils.storage",
1815                 "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
1816 }
1817
1818 __PACKAGE__->register_method(
1819         method  => "retrieve_groups",
1820         api_name        => "open-ils.actor.groups.retrieve",
1821         notes           => <<"  NOTES");
1822         Returns a list of user groupss
1823         NOTES
1824 sub retrieve_groups {
1825         my( $self, $client ) = @_;
1826         return $apputils->simple_scalar_request(
1827                 "open-ils.storage",
1828                 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1829 }
1830
1831 __PACKAGE__->register_method(
1832         method  => "retrieve_org_address",
1833         api_name        => "open-ils.actor.org_unit.address.retrieve",
1834         notes           => <<'  NOTES');
1835         Returns an org_unit address by ID
1836         @param An org_address ID
1837         NOTES
1838 sub retrieve_org_address {
1839         my( $self, $client, $id ) = @_;
1840         return $apputils->simple_scalar_request(
1841                 "open-ils.storage",
1842                 "open-ils.storage.direct.actor.org_address.retrieve",
1843                 $id
1844         );
1845 }
1846
1847 __PACKAGE__->register_method(
1848         method  => "retrieve_groups_tree",
1849         api_name        => "open-ils.actor.groups.tree.retrieve",
1850         notes           => <<"  NOTES");
1851         Returns a list of user groups
1852         NOTES
1853 sub retrieve_groups_tree {
1854         my( $self, $client ) = @_;
1855         my $groups = $apputils->simple_scalar_request(
1856                 "open-ils.storage",
1857                 "open-ils.storage.direct.permission.grp_tree.retrieve.all.atomic");
1858         return $self->build_group_tree($groups);        
1859 }
1860
1861
1862 # turns an org list into an org tree
1863 sub build_group_tree {
1864
1865         my( $self, $grplist) = @_;
1866
1867         return $grplist unless ( 
1868                         ref($grplist) and @$grplist > 1 );
1869
1870         my @list = sort { $a->name cmp $b->name } @$grplist;
1871
1872         my $root;
1873         for my $grp (@list) {
1874
1875                 if ($grp and !defined($grp->parent)) {
1876                         $root = $grp;
1877                         next;
1878                 }
1879                 my ($parent) = grep { $_->id == $grp->parent} @list;
1880
1881                 $parent->children([]) unless defined($parent->children); 
1882                 push( @{$parent->children}, $grp );
1883         }
1884
1885         return $root;
1886
1887 }
1888
1889
1890 __PACKAGE__->register_method(
1891         method  => "add_user_to_groups",
1892         api_name        => "open-ils.actor.user.set_groups",
1893         notes           => <<"  NOTES");
1894         Adds a user to one or more permission groups
1895         NOTES
1896
1897 sub add_user_to_groups {
1898         my( $self, $client, $authtoken, $userid, $groups ) = @_;
1899
1900         my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1901                 $authtoken, $userid, 'CREATE_USER_GROUP_LINK' );
1902         return $evt if $evt;
1903
1904         ( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1905                 $authtoken, $userid, 'REMOVE_USER_GROUP_LINK' );
1906         return $evt if $evt;
1907
1908         $apputils->simplereq(
1909                 'open-ils.storage',
1910                 'open-ils.storage.direct.permission.usr_grp_map.mass_delete', { usr => $userid } );
1911                 
1912         for my $group (@$groups) {
1913                 my $link = Fieldmapper::permission::usr_grp_map->new;
1914                 $link->grp($group);
1915                 $link->usr($userid);
1916
1917                 my $id = $apputils->simplereq(
1918                         'open-ils.storage',
1919                         'open-ils.storage.direct.permission.usr_grp_map.create', $link );
1920         }
1921
1922         return 1;
1923 }
1924
1925 __PACKAGE__->register_method(
1926         method  => "get_user_perm_groups",
1927         api_name        => "open-ils.actor.user.get_groups",
1928         notes           => <<"  NOTES");
1929         Retrieve a user's permission groups.
1930         NOTES
1931
1932
1933 sub get_user_perm_groups {
1934         my( $self, $client, $authtoken, $userid ) = @_;
1935
1936         my( $requestor, $target, $evt ) = $apputils->checkses_requestor(
1937                 $authtoken, $userid, 'VIEW_PERM_GROUPS' );
1938         return $evt if $evt;
1939
1940         return $apputils->simplereq(
1941                 'open-ils.storage',
1942                 'open-ils.storage.direct.permission.usr_grp_map.search.usr.atomic', $userid );
1943 }       
1944
1945
1946
1947 __PACKAGE__->register_method (
1948         method          => 'register_workstation',
1949         api_name                => 'open-ils.actor.workstation.register.override',
1950         signature       => q/@see open-ils.actor.workstation.register/);
1951
1952 __PACKAGE__->register_method (
1953         method          => 'register_workstation',
1954         api_name                => 'open-ils.actor.workstation.register',
1955         signature       => q/
1956                 Registers a new workstion in the system
1957                 @param authtoken The login session key
1958                 @param name The name of the workstation id
1959                 @param owner The org unit that owns this workstation
1960                 @return The workstation id on success, WORKSTATION_NAME_EXISTS
1961                 if the name is already in use.
1962         /);
1963
1964 sub _register_workstation {
1965         my( $self, $connection, $authtoken, $name, $owner ) = @_;
1966         my( $requestor, $evt ) = $U->checkses($authtoken);
1967         return $evt if $evt;
1968         $evt = $U->check_perms($requestor->id, $owner, 'REGISTER_WORKSTATION');
1969         return $evt if $evt;
1970
1971         my $ws = $U->storagereq(
1972                 'open-ils.storage.direct.actor.workstation.search.name', $name );
1973         return OpenILS::Event->new('WORKSTATION_NAME_EXISTS') if $ws;
1974
1975         $ws = Fieldmapper::actor::workstation->new;
1976         $ws->owning_lib($owner);
1977         $ws->name($name);
1978
1979         my $id = $U->storagereq(
1980                 'open-ils.storage.direct.actor.workstation.create', $ws );
1981         return $U->DB_UPDATE_FAILED($ws) unless $id;
1982
1983         $ws->id($id);
1984         return $ws->id();
1985 }
1986
1987 sub register_workstation {
1988         my( $self, $conn, $authtoken, $name, $owner ) = @_;
1989
1990         my $e = OpenILS::Utils::Editor->new(authtoken=>$authtoken, xact=>1); 
1991         return $e->event unless $e->checkauth;
1992         return $e->event unless $e->allowed('REGISTER_WORKSTATION'); # XXX rely on editor perms
1993         my $existing = $e->search_actor_workstation({name => $name});
1994
1995         if( @$existing ) {
1996                 if( $self->api_name =~ /override/o ) {
1997                         return $e->event unless $e->allowed('DELETE_WORKSTATION'); # XXX rely on editor perms
1998                         return $e->event unless $e->delete_actor_workstation($$existing[0]);
1999                 } else {
2000                         return OpenILS::Event->new('WORKSTATION_NAME_EXISTS')
2001                 }
2002         }
2003
2004         my $ws = Fieldmapper::actor::workstation->new;
2005         $ws->owning_lib($owner);
2006         $ws->name($name);
2007         $e->create_actor_workstation($ws) or return $e->event;
2008         $e->finish;
2009         return $ws->id; # note: editor sets the id on the new object for us
2010 }
2011
2012
2013 __PACKAGE__->register_method (
2014         method          => 'fetch_patron_note',
2015         api_name                => 'open-ils.actor.note.retrieve.all',
2016         signature       => q/
2017                 Returns a list of notes for a given user
2018                 Requestor must have VIEW_USER permission if pub==false and
2019                 @param authtoken The login session key
2020                 @param args Hash of params including
2021                         patronid : the patron's id
2022                         pub : true if retrieving only public notes
2023         /
2024 );
2025
2026 sub fetch_patron_note {
2027         my( $self, $conn, $authtoken, $args ) = @_;
2028         my $patronid = $$args{patronid};
2029
2030         my($reqr, $evt) = $U->checkses($authtoken);
2031
2032         my $patron;
2033         ($patron, $evt) = $U->fetch_user($patronid);
2034         return $evt if $evt;
2035
2036         if($$args{pub}) {
2037                 if( $patronid ne $reqr->id ) {
2038                         $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2039                         return $evt if $evt;
2040                 }
2041                 return $U->storagereq(
2042                         'open-ils.storage.direct.actor.usr_note.search_where.atomic', 
2043                         { usr => $patronid, pub => 't' } );
2044         }
2045
2046         $evt = $U->check_perms($reqr->id, $patron->home_ou, 'VIEW_USER');
2047         return $evt if $evt;
2048
2049         return $U->storagereq(
2050                 'open-ils.storage.direct.actor.usr_note.search.usr.atomic', $patronid );
2051 }
2052
2053 __PACKAGE__->register_method (
2054         method          => 'create_user_note',
2055         api_name                => 'open-ils.actor.note.create',
2056         signature       => q/
2057                 Creates a new note for the given user
2058                 @param authtoken The login session key
2059                 @param note The note object
2060         /
2061 );
2062 sub create_user_note {
2063         my( $self, $conn, $authtoken, $note ) = @_;
2064         my( $reqr, $patron, $evt ) = 
2065                 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
2066         return $evt if $evt;
2067         $logger->activity("user ".$reqr->id." creating note for user ".$note->usr);
2068
2069         $note->pub('f') unless $note->pub;
2070         $note->creator($reqr->id);
2071         my $id = $U->storagereq(
2072                 'open-ils.storage.direct.actor.usr_note.create', $note );
2073         return $U->DB_UPDATE_FAILED($note) unless $id;
2074         return $id;
2075 }
2076
2077
2078 __PACKAGE__->register_method (
2079         method          => 'delete_user_note',
2080         api_name                => 'open-ils.actor.note.delete',
2081         signature       => q/
2082                 Deletes a note for the given user
2083                 @param authtoken The login session key
2084                 @param noteid The note id
2085         /
2086 );
2087 sub delete_user_note {
2088         my( $self, $conn, $authtoken, $noteid ) = @_;
2089
2090         my $note = $U->storagereq(
2091                 'open-ils.storage.direct.actor.usr_note.retrieve', $noteid);
2092         return OpenILS::Event->new('ACTOR_USER_NOTE_NOT_FOUND') unless $note;
2093
2094         my( $reqr, $patron, $evt ) = 
2095                 $U->checkses_requestor($authtoken, $note->usr, 'UPDATE_USER');
2096         return $evt if $evt;
2097         $logger->activity("user ".$reqr->id." deleting note [$noteid] for user ".$note->usr);
2098
2099         my $stat = $U->storagereq(
2100                 'open-ils.storage.direct.actor.usr_note.delete', $noteid );
2101         return $U->DB_UPDATE_FAILED($note) unless defined $stat;
2102         return $stat;
2103 }
2104
2105
2106
2107 __PACKAGE__->register_method (
2108         method          => 'create_closed_date',
2109         api_name        => 'open-ils.actor.org_unit.closed_date.create',
2110         signature       => q/
2111                 Creates a new closing entry for the given org_unit
2112                 @param authtoken The login session key
2113                 @param note The closed_date object
2114         /
2115 );
2116 sub create_closed_date {
2117         my( $self, $conn, $authtoken, $cd ) = @_;
2118
2119         my( $user, $evt ) = $U->checkses($authtoken);
2120         return $evt if $evt;
2121
2122         $evt = $U->check_perms($user->id, $cd->org_unit, 'CREATE_CLOSEING');
2123         return $evt if $evt;
2124
2125         $logger->activity("user ".$user->id." creating library closing for ".$cd->org_unit);
2126
2127         my $id = $U->storagereq(
2128                 'open-ils.storage.direct.actor.org_unit.closed_date.create', $cd );
2129         return $U->DB_UPDATE_FAILED($cd) unless $id;
2130         return $id;
2131 }
2132
2133
2134 __PACKAGE__->register_method (
2135         method          => 'delete_closed_date',
2136         api_name        => 'open-ils.actor.org_unit.closed_date.delete',
2137         signature       => q/
2138                 Deletes a closing entry for the given org_unit
2139                 @param authtoken The login session key
2140                 @param noteid The close_date id
2141         /
2142 );
2143 sub delete_closed_date {
2144         my( $self, $conn, $authtoken, $cd ) = @_;
2145
2146         my( $user, $evt ) = $U->checkses($authtoken);
2147         return $evt if $evt;
2148
2149         my $cd_obj;
2150         ($cd_obj, $evt) = fetch_closed_date($cd);
2151         return $evt if $evt;
2152
2153         $evt = $U->check_perms($user->id, $cd->org_unit, 'DELETE_CLOSEING');
2154         return $evt if $evt;
2155
2156         $logger->activity("user ".$user->id." deleting library closing for ".$cd->org_unit);
2157
2158         my $stat = $U->storagereq(
2159                 'open-ils.storage.direct.actor.org_unit.closed_date.delete', $cd );
2160         return $U->DB_UPDATE_FAILED($cd) unless $stat;
2161         return $stat;
2162 }
2163
2164
2165 __PACKAGE__->register_method(
2166         method => 'usrname_exists',
2167         api_name        => 'open-ils.actor.username.exists',
2168         signature => q/
2169                 Returns 1 if the requested username exists, returns 0 otherwise
2170         /
2171 );
2172
2173 sub usrname_exists {
2174         my( $self, $conn, $auth, $usrname ) = @_;
2175         my $e = new_editor(authtoken=>$auth);
2176         return $e->event unless $e->checkauth;
2177         my $a = $e->search_actor_user({usrname => $usrname}, {idlist=>1});
2178         return $$a[0] if $a and @$a;
2179         return 0;
2180 }
2181
2182 __PACKAGE__->register_method(
2183         method => 'barcode_exists',
2184         api_name        => 'open-ils.actor.barcode.exists',
2185         signature => q/
2186                 Returns 1 if the requested barcode exists, returns 0 otherwise
2187         /
2188 );
2189
2190 sub barcode_exists {
2191         my( $self, $conn, $auth, $barcode ) = @_;
2192         my $e = new_editor(authtoken=>$auth);
2193         return $e->event unless $e->checkauth;
2194         my $a = $e->search_actor_card({barcode => $barcode}, {idlist=>1});
2195         return $$a[0] if $a and @$a;
2196         return 0;
2197 }
2198
2199
2200 __PACKAGE__->register_method(
2201         method => 'retrieve_net_levels',
2202         api_name        => 'open-ils.actor.net_access_level.retrieve.all',
2203 );
2204
2205 sub retrieve_net_levels {
2206         my( $self, $conn, $auth ) = @_;
2207         my $e = new_editor(authtoken=>$auth);
2208         return $e->event unless $e->checkauth;
2209         return $e->retrieve_all_config_net_access_level();
2210 }
2211
2212
2213
2214 1;
2215