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