]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Actor.pm
more batch committing
[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
6 use Digest::MD5 qw(md5_hex);
7
8 use OpenSRF::EX qw(:try);
9 use OpenILS::EX;
10
11 use OpenILS::Application::AppUtils;
12 use OpenILS::Utils::Fieldmapper;
13 use OpenILS::Application::Search::Actor;
14
15 my $apputils = "OpenILS::Application::AppUtils";
16 sub _d { warn "Patron:\n" . Dumper(shift()); }
17 my $cache_client = OpenSRF::Utils::Cache->new("global", 0);
18
19
20 __PACKAGE__->register_method(
21         method  => "update_patron",
22         api_name        => "open-ils.actor.patron.update",);
23
24 sub update_patron {
25         my( $self, $client, $user_session, $patron ) = @_;
26
27         my $session = $apputils->start_db_session();
28         my $err = undef;
29
30         warn $user_session . " " . $patron . "\n";
31         _d($patron);
32
33         my $user_obj = 
34                 OpenILS::Application::AppUtils->check_user_session( 
35                                 $user_session ); #throws EX on error
36
37         # XXX does this user have permission to add/create users.  Granularity?
38
39         # $new_patron is the patron in progress.  $patron is the original patron
40         # passed in with the method.  new_patron will change as the components
41         # of patron are added/updated.
42
43         my $new_patron;
44
45         #try {
46                 # create/update the patron first so we can use his id
47                 if($patron->isnew()) {
48                         $new_patron = _add_patron(
49                                         $session, _clone_patron($patron));
50                         if(UNIVERSAL::isa($new_patron, "OpenILS::EX")) {
51                                 $client->respond_complete($new_patron->ex);
52                                 return undef;
53                         }
54
55                 } else { 
56                         $new_patron = $patron; 
57                 }
58
59                 $new_patron = _add_update_addresses($session, $patron, $new_patron);
60                 $new_patron = _add_update_cards($session, $patron, $new_patron);
61
62                 if(UNIVERSAL::isa($new_patron,"OpenILS::EX")) {
63                         $client->respond_complete($new_patron->ex);
64                         return undef;
65                 }
66
67                 $new_patron = _add_survey_responses($session, $patron, $new_patron);
68                 $new_patron     = _create_stat_maps($session, $user_session, $patron, $new_patron);
69
70                 # re-update the patron if anything has happened to him during this process
71                 if($new_patron->ischanged()) {
72                         $new_patron = _update_patron($session, $new_patron);
73                 }
74                 $apputils->commit_db_session($session);
75
76 =head
77         } catch Error with { 
78                 my $e = shift;
79                 $err =  "-*- Failure adding user: $e";
80                 $apputils->rollback_db_session($session);
81                 warn $err;
82         };
83
84         if($err) { throw OpenSRF::EX::ERROR ($err); }
85 =cut
86
87         warn "Patron Update/Create complete\n";
88         return flesh_user($new_patron->id());
89 }
90
91
92
93
94 __PACKAGE__->register_method(
95         method  => "user_retrieve_fleshed_by_id",
96         api_name        => "open-ils.actor.user.fleshed.retrieve",);
97
98 sub user_retrieve_fleshed_by_id {
99         my( $self, $client, $user_session, $user_id ) = @_;
100         my $user_obj = $apputils->check_user_session( $user_session ); 
101         return flesh_user($user_id);
102 }
103
104
105 sub flesh_user {
106         my $id = shift;
107         my $session = shift;
108
109         my $kill = 0;
110
111         if(!$session) {
112                 $session = OpenSRF::AppSession->create("open-ils.storage");
113                 $kill = 1;
114         }
115
116         # grab the user with the given card
117         my $ureq = $session->request(
118                         "open-ils.storage.direct.actor.user.retrieve",
119                         $id);
120         my $user = $ureq->gather(1);
121
122         # grab the cards
123         my $cards_req = $session->request(
124                         "open-ils.storage.direct.actor.card.search.usr",
125                         $user->id() );
126         $user->cards( $cards_req->gather(1) );
127
128         my $add_req = $session->request(
129                         "open-ils.storage.direct.actor.user_address.search.usr",
130                         $user->id() );
131         $user->addresses( $add_req->gather(1) );
132
133         my $stat_req = $session->request(
134                 "open-ils.storage.direct.actor.stat_cat_entry_user_map.search.target_usr",
135                 $user->id() );
136         $user->stat_cat_entries($stat_req->gather(1));
137
138         if($kill) { $session->disconnect(); }
139         $user->clear_passwd();
140         warn Dumper $user;
141
142         return $user;
143
144 }
145
146
147 # clone and clear stuff that would break the database
148 sub _clone_patron {
149         my $patron = shift;
150
151         my $new_patron = Fieldmapper::actor::user->new();
152
153         my $fmap = $Fieldmapper::fieldmap;
154         no strict; # shallow clone, may be useful in the fieldmapper
155         for my $field 
156                 (keys %{$fmap->{"Fieldmapper::actor::user"}->{'fields'}}) {
157                         $new_patron->$field( $patron->$field() );
158         }
159         use strict;
160
161         # clear these
162         $new_patron->clear_billing_address();
163         $new_patron->clear_mailing_address();
164         $new_patron->clear_addresses();
165         $new_patron->clear_card();
166         $new_patron->clear_cards();
167         $new_patron->clear_id();
168         $new_patron->clear_isnew();
169         $new_patron->clear_changed();
170         $new_patron->clear_deleted();
171         $new_patron->clear_stat_cat_entries();
172
173         return $new_patron;
174 }
175
176
177 sub _add_patron {
178         my $session             = shift;
179         my $patron              = shift;
180
181         warn "Creating new patron\n";
182         _d($patron);
183
184         my $req = $session->request(
185                 "open-ils.storage.direct.actor.user.create",$patron);
186         my $id = $req->gather(1);
187         if(!$id) { 
188                 return OpenILS::EX->new("DUPLICATE_USER_USERNAME");
189         }
190
191         # retrieve the patron from the db to collect defaults
192         my $ureq = $session->request(
193                         "open-ils.storage.direct.actor.user.retrieve",
194                         $id);
195
196         warn "Created new patron with id $id\n";
197
198         return $ureq->gather(1);
199 }
200
201
202 sub _update_patron {
203         my( $session, $patron) = @_;
204
205         warn "updating patron " . Dumper($patron) . "\n";
206
207         my $req = $session->request(
208                 "open-ils.storage.direct.actor.user.update",$patron );
209         my $status = $req->gather(1);
210         if(!defined($status)) { 
211                 throw OpenSRF::EX::ERROR 
212                         ("Unknown error updating patron"); 
213         }
214         return $patron;
215 }
216
217
218 sub _add_update_addresses {
219         my $session = shift;
220         my $patron = shift;
221         my $new_patron = shift;
222
223         my $current_id; # id of the address before creation
224
225         for my $address (@{$patron->addresses()}) {
226
227                 $address->usr($new_patron->id());
228
229                 if(ref($address) and $address->isnew()) {
230                         warn "Adding new address at street " . $address->street1() . "\n";
231
232                         $current_id = $address->id();
233                         $address = _add_address($session,$address);
234
235                         if( $patron->billing_address() and 
236                                         $patron->billing_address() == $current_id ) {
237                                 $new_patron->billing_address($address->id());
238                                 $new_patron->ischanged(1);
239                         }
240
241                         if( $patron->mailing_address() and
242                                         $patron->mailing_address() == $current_id ) {
243                                 $new_patron->mailing_address($address->id());
244                                 $new_patron->ischanged(1);
245                         }
246
247                 } elsif( ref($address) and $address->ischanged() ) {
248                         warn "Updating address at street " . $address->street1();
249                         $address->usr($new_patron->id());
250                         _update_address($session,$address);
251
252                 } elsif( ref($address) and $address->isdeleted() ) {
253                         warn "Deleting address at street " . $address->street1();
254
255                         if( $address->id() == $new_patron->mailing_address() ) {
256                                 $new_patron->clear_mailing_address();
257                                 _update_patron($session, $new_patron);
258                         }
259
260                         if( $address->id() == $new_patron->billing_address() ) {
261                                 $new_patron->clear_billing_address();
262                                 _update_patron($session, $new_patron);
263                         }
264
265                         _delete_address($session,$address);
266                 }
267         }
268
269         return $new_patron;
270 }
271
272
273 # adds an address to the db and returns the address with new id
274 sub _add_address {
275         my($session, $address) = @_;
276         $address->clear_id();
277
278         # put the address into the database
279         my $req = $session->request(
280                 "open-ils.storage.direct.actor.user_address.create",
281                 $address );
282
283         #update the id
284         my $id = $req->gather(1);
285         if(!$id) { 
286                 throw OpenSRF::EX::ERROR 
287                         ("Unable to create new user address"); 
288         }
289
290         warn "Created address with id $id\n";
291
292         # update all the necessary id's
293         $address->id( $id );
294         return $address;
295 }
296
297
298 sub _update_address {
299         my( $session, $address ) = @_;
300         my $req = $session->request(
301                 "open-ils.storage.direct.actor.user_address.update",
302                 $address );
303         my $status = $req->gather(1);
304         if(!defined($status)) { 
305                 throw OpenSRF::EX::ERROR 
306                         ("Unknown error updating address"); 
307         }
308         return $address;
309 }
310
311
312
313 sub _add_update_cards {
314
315         my $session = shift;
316         my $patron = shift;
317         my $new_patron = shift;
318
319         my $virtual_id; #id of the card before creation
320         for my $card (@{$patron->cards()}) {
321
322                 $card->usr($new_patron->id());
323
324                 if(ref($card) and $card->isnew()) {
325
326                         $virtual_id = $card->id();
327                         $card = _add_card($session,$card);
328                         if(UNIVERSAL::isa($card,"OpenILS::EX")) {
329                                 return $card;
330                         }
331
332                         if($patron->card() == $virtual_id) {
333                                 $new_patron->card($card->id());
334                                 $new_patron->ischanged(1);
335                         }
336
337                 } elsif( ref($card) and $card->ischanged() ) {
338                         $card->usr($new_patron->id());
339                         _update_card($session, $card);
340                 }
341         }
342         return $new_patron;
343 }
344
345
346 # adds an card to the db and returns the card with new id
347 sub _add_card {
348         my( $session, $card ) = @_;
349         $card->clear_id();
350
351         warn "Adding card with barcode " . $card->barcode() . "\n";
352         my $req = $session->request(
353                 "open-ils.storage.direct.actor.card.create",
354                 $card );
355
356         my $id = $req->gather(1);
357         if(!$id) { 
358                 return OpenILS::EX->new("DUPLICATE_INVALID_USER_BARCODE");
359         }
360
361         $card->id($id);
362         warn "Created patron card with id $id\n";
363         return $card;
364 }
365
366
367 sub _update_card {
368         my( $session, $card ) = @_;
369         warn Dumper $card;
370
371         my $req = $session->request(
372                 "open-ils.storage.direct.actor.card.update",
373                 $card );
374         my $status = $req->gather(1);
375         if(!defined($status)) { 
376                 throw OpenSRF::EX::ERROR 
377                         ("Unknown error updating card"); 
378         }
379         return $card;
380 }
381
382
383
384
385 sub _delete_address {
386         my( $session, $address ) = @_;
387
388         warn "Deleting address " . $address->street1() . "\n";
389
390         my $req = $session->request(
391                 "open-ils.storage.direct.actor.user_address.delete",
392                 $address );
393         my $status = $req->gather(1);
394         if(!defined($status)) { 
395                 throw OpenSRF::EX::ERROR 
396                         ("Unknown error updating address"); 
397         }
398         warn "Delete address status is $status\n";
399 }
400
401
402
403 sub _add_survey_responses {
404         my ($session, $patron, $new_patron) = @_;
405
406         warn "updating responses for user " . $new_patron->id . "\n";
407
408         my $responses = $patron->survey_responses;
409         for my $resp( @$responses ) {
410                 $resp->usr($new_patron->id);
411         }
412
413         my $status = $apputils->simple_scalar_request(
414                 "open-ils.circ", 
415                 "open-ils.circ.survey.submit.user_id",
416                 $responses );
417
418         return $new_patron;
419 }
420
421
422 sub _create_stat_maps {
423
424         my($session, $user_session, $patron, $new_patron) = @_;
425
426         my $maps = $patron->stat_cat_entries();
427
428         for my $map (@$maps) {
429
430                 next unless($map->isnew() || $map->ischanged());
431
432                 my $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.update";
433                 if($map->isnew()) {
434                         $method = "open-ils.storage.direct.actor.stat_cat_entry_user_map.create";
435                 }
436
437                 $map->target_usr($new_patron->id);
438
439                 warn "Updating stat entry with method $method and session $user_session and map $map\n";
440
441                 my $req = $session->request($method, $map);
442                 my $status = $req->gather(1);
443
444                 warn "Updated\n";
445
446                 if(!$status) {
447                         throw OpenSRF::EX::ERROR 
448                                 ("Error updating stat map with method $method");        
449                 }
450         }
451
452         return $new_patron;
453 }
454
455
456
457 __PACKAGE__->register_method(
458         method  => "search_username",
459         api_name        => "open-ils.actor.user.search.username",
460 );
461
462 sub search_username {
463         my($self, $client, $username) = @_;
464         my $users = OpenILS::Application::AppUtils->simple_scalar_request(
465                         "open-ils.storage", 
466                         "open-ils.storage.direct.actor.user.search.usrname",
467                         $username );
468         return $users;
469 }
470
471
472
473
474 __PACKAGE__->register_method(
475         method  => "user_retrieve_by_barcode",
476         api_name        => "open-ils.actor.user.fleshed.retrieve_by_barcode",);
477
478 sub user_retrieve_by_barcode {
479         my($self, $client, $user_session, $barcode) = @_;
480         warn "Searching for user with barcode $barcode\n";
481         my $user_obj = $apputils->check_user_session( $user_session ); 
482
483         my $session = OpenSRF::AppSession->create("open-ils.storage");
484
485         # find the card with the given barcode
486         my $creq        = $session->request(
487                         "open-ils.storage.direct.actor.card.search.barcode",
488                         $barcode );
489         my $card = $creq->gather(1);
490
491         if(!$card || !$card->[0]) {
492                 $session->disconnect();
493                 return undef;
494         }
495
496         $card = $card->[0];
497         my $user = flesh_user($card->usr(), $session);
498         $session->disconnect();
499         return $user;
500
501 }
502
503
504
505 __PACKAGE__->register_method(
506         method  => "get_user_by_id",
507         api_name        => "open-ils.actor.user.retrieve",);
508
509 sub get_user_by_id {
510         my ($self, $client, $user_session, $id) = @_;
511
512         my $user_obj = $apputils->check_user_session( $user_session ); 
513
514         return $apputils->simple_scalar_request(
515                 "open-ils.storage",
516                 "open-ils.storage.direct.actor.user.retrieve",
517                 $id );
518 }
519
520
521
522 __PACKAGE__->register_method(
523         method  => "get_org_types",
524         api_name        => "open-ils.actor.org_types.retrieve",);
525
526 my $org_types;
527 sub get_org_types {
528         my($self, $client) = @_;
529
530         return $org_types if $org_types;
531          return $org_types = 
532                  $apputils->simple_scalar_request(
533                         "open-ils.storage",
534                         "open-ils.storage.direct.actor.org_unit_type.retrieve.all.atomic" );
535 }
536
537
538
539 __PACKAGE__->register_method(
540         method  => "get_user_profiles",
541         api_name        => "open-ils.actor.user.profiles.retrieve",
542 );
543
544 my $user_profiles;
545 sub get_user_profiles {
546         return $user_profiles if $user_profiles;
547
548         return $user_profiles = 
549                 $apputils->simple_scalar_request(
550                         "open-ils.storage",
551                         "open-ils.storage.direct.actor.profile.retrieve.all.atomic");
552 }
553
554
555
556 __PACKAGE__->register_method(
557         method  => "get_user_ident_types",
558         api_name        => "open-ils.actor.user.ident_types.retrieve",
559 );
560 my $ident_types;
561 sub get_user_ident_types {
562         return $ident_types if $ident_types;
563         return $ident_types = 
564                 $apputils->simple_scalar_request(
565                 "open-ils.storage",
566                 "open-ils.storage.direct.config.identification_type.retrieve.all.atomic" );
567 }
568
569
570
571
572 __PACKAGE__->register_method(
573         method  => "get_org_unit",
574         api_name        => "open-ils.actor.org_unit.retrieve",
575 );
576
577 sub get_org_unit {
578
579         my( $self, $client, $user_session, $org_id ) = @_;
580
581         my $user_obj = 
582                 OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
583
584         if(!$org_id) {
585                 $org_id = $user_obj->home_ou;
586         }
587
588         my $home_ou = OpenILS::Application::AppUtils->simple_scalar_request(
589                 "open-ils.storage",
590                 "open-ils.storage.direct.actor.org_unit.retrieve", 
591                 $org_id );
592
593         return $home_ou;
594 }
595
596
597 # build the org tree
598
599 __PACKAGE__->register_method(
600         method  => "get_org_tree",
601         api_name        => "open-ils.actor.org_tree.retrieve",
602         argc            => 1, 
603         note            => "Returns the entire org tree structure",
604 );
605
606 sub get_org_tree {
607         my( $self, $client) = @_;
608
609         # see if it's in the cache
610         warn "Getting ORG Tree\n";
611         my $tree = $cache_client->get_cache('orgtree');
612         if($tree) { 
613                 warn "Found orgtree in cache. returning...\n";
614                 return $tree; 
615         }
616
617         my $orglist = $apputils->simple_scalar_request( 
618                 "open-ils.storage", 
619                 "open-ils.storage.direct.actor.org_unit.retrieve.all.atomic" );
620
621         $tree = $self->build_org_tree($orglist);
622         $cache_client->put_cache('orgtree', $tree);
623
624         return $tree;
625
626 }
627
628 # turns an org list into an org tree
629 sub build_org_tree {
630
631         my( $self, $orglist) = @_;
632
633         return $orglist unless ( 
634                         ref($orglist) and @$orglist > 1 );
635
636         my @list = sort { 
637                 $a->ou_type <=> $b->ou_type ||
638                 $a->name cmp $b->name } @$orglist;
639
640         for my $org (@list) {
641
642                 next unless ($org and defined($org->parent_ou));
643                 my ($parent) = grep { $_->id == $org->parent_ou } @list;
644                 next unless $parent;
645
646                 $parent->children([]) unless defined($parent->children); 
647                 push( @{$parent->children}, $org );
648         }
649
650         return $list[0];
651
652 }
653
654
655 __PACKAGE__->register_method(
656         method  => "get_org_descendants",
657         api_name        => "open-ils.actor.org_tree.descendants.retrieve"
658 );
659
660 # depth is optional.  org_unit is the id
661 sub get_org_descendants {
662         my( $self, $client, $org_unit, $depth ) = @_;
663         my $orglist = $apputils->simple_scalar_request(
664                         "open-ils.storage", 
665                         "open-ils.storage.actor.org_unit.descendants.atomic",
666                         $org_unit, $depth );
667         return $self->build_org_tree($orglist);
668 }
669
670
671 __PACKAGE__->register_method(
672         method  => "get_org_ancestors",
673         api_name        => "open-ils.actor.org_tree.ancestors.retrieve"
674 );
675
676 # depth is optional.  org_unit is the id
677 sub get_org_ancestors {
678         my( $self, $client, $org_unit, $depth ) = @_;
679         my $orglist = $apputils->simple_scalar_request(
680                         "open-ils.storage", 
681                         "open-ils.storage.actor.org_unit.ancestors.atomic",
682                         $org_unit, $depth );
683         return $self->build_org_tree($orglist);
684 }
685
686
687 __PACKAGE__->register_method(
688         method  => "get_standings",
689         api_name        => "open-ils.actor.standings.retrieve"
690 );
691
692 my $user_standings;
693 sub get_standings {
694         return $user_standings if $user_standings;
695         return $user_standings = 
696                 $apputils->simple_scalar_request(
697                         "open-ils.storage",
698                         "open-ils.storage.direct.config.standing.retrieve.all.atomic" );
699 }
700
701
702
703 __PACKAGE__->register_method(
704         method  => "get_my_org_path",
705         api_name        => "open-ils.actor.org_unit.full_path.retrieve"
706 );
707
708 sub get_my_org_path {
709         my( $self, $client, $user_session, $org_id ) = @_;
710         my $user_obj = $apputils->check_user_session($user_session); 
711         if(!defined($org_id)) { $org_id = $user_obj->home_ou; }
712
713         return $apputils->simple_scalar_request(
714                 "open-ils.storage",
715                 "open-ils.storage.actor.org_unit.full_path.atomic",
716                 $org_id );
717 }
718
719
720 __PACKAGE__->register_method(
721         method  => "patron_adv_search",
722         api_name        => "open-ils.actor.patron.search.advanced" );
723
724 sub patron_adv_search {
725         my( $self, $client, $staff_login, $search_hash ) = @_;
726
727         use Data::Dumper;
728         warn "patron adv with $staff_login and search " . 
729                 Dumper($search_hash) . "\n";
730
731         my $session = OpenSRF::AppSession->create("open-ils.storage");
732         my $req = $session->request(
733                 "open-ils.storage.actor.user.crazy_search", $search_hash);
734
735         my $ans = $req->gather(1);
736
737         my %hash = map { ($_ =>1) } @$ans;
738         $ans = [ keys %hash ];
739
740         warn "Returning @$ans\n";
741
742         $session->disconnect();
743         return $ans;
744
745 }
746
747
748
749 sub _verify_password {
750         my($user_session, $password) = @_;
751         my $user_obj = $apputils->check_user_session($user_session); 
752
753         #grab the user with password
754         $user_obj = $apputils->simple_scalar_request(
755                 "open-ils.storage", 
756                 "open-ils.storage.direct.actor.user.retrieve",
757                 $user_obj->id );
758
759         if($user_obj->passwd eq $password) {
760                 return 1;
761         }
762
763         return 0;
764 }
765
766
767 __PACKAGE__->register_method(
768         method  => "update_password",
769         api_name        => "open-ils.actor.user.password.update");
770
771 __PACKAGE__->register_method(
772         method  => "update_password",
773         api_name        => "open-ils.actor.user.username.update");
774
775 __PACKAGE__->register_method(
776         method  => "update_password",
777         api_name        => "open-ils.actor.user.email.update");
778
779 sub update_password {
780         my( $self, $client, $user_session, $new_value, $current_password ) = @_;
781
782         my $user_obj = $apputils->check_user_session($user_session); 
783         warn "Updating user with method " .$self->api_name . "\n";
784
785         if($self->api_name =~ /password/) {
786
787                 #make sure they know the current password
788                 if(!_verify_password($user_session, md5_hex($current_password))) {
789                         return OpenILS::EX->new("USER_WRONG_PASSWORD")->ex;
790                 }
791
792                 $user_obj->passwd($new_value);
793         } 
794         elsif($self->api_name =~ /username/) {
795                 $user_obj->usrname($new_value);
796         }
797
798         elsif($self->api_name =~ /email/) {
799                 $user_obj->email($new_value);
800         }
801
802         my $session = $apputils->start_db_session();
803         $user_obj = _update_patron($session, $user_obj);
804         $apputils->commit_db_session($session);
805
806         if($user_obj) { return 1; }
807         return undef;
808 }
809
810
811
812
813
814
815
816 1;
817
818
819
820
821 __END__
822
823
824 some old methods that may be good to keep around for now
825
826 sub _delete_card {
827         my( $session, $card ) = @_;
828
829         warn "Deleting card with barcode " . $card->barcode() . "\n";
830         my $req = $session->request(
831                 "open-ils.storage.direct.actor.card.delete",
832                 $card );
833         my $status = $req->gather(1);
834         if(!defined($status)) { 
835                 throw OpenSRF::EX::ERROR 
836                         ("Unknown error updating card"); 
837         }
838 }
839
840
841
842 # deletes the patron and any attached addresses and cards
843 __PACKAGE__->register_method(
844         method  => "delete_patron",
845         api_name        => "open-ils.actor.patron.delete",
846 );
847
848 sub delete_patron {
849
850         my( $self, $client, $patron ) = @_;
851         my $session = $apputils->start_db_session();
852         my $err = undef;
853
854         try {
855
856                 $patron->clear_mailing_address();
857                 $patron->clear_billing_address();
858                 $patron->ischanged(1);
859
860                 _update_patron($session, $patron);
861                 _delete_address($session,$_) for (@{$patron->addresses()});
862                 _delete_card($session,$_) for (@{$patron->cards()});
863                 _delete_patron($session,$patron);
864                 $apputils->commit_db_session($session);
865
866         } catch Error with {
867                 my $e = shift;
868                 $err =  "-*- Failure deleting user: $e";
869                 $apputils->rollback_db_session($session);
870                 warn $err;
871         };
872
873         if($err) { throw OpenSRF::EX::ERROR ($err); }
874         warn "Patron Delete complete\n";
875         return 1;
876 }
877
878 sub _delete_patron {
879         my( $session, $patron ) = @_;
880
881         warn "Deleting patron " . $patron->usrname() . "\n";
882
883         my $req = $session->request(
884                 "open-ils.storage.direct.actor.user.delete",
885                 $patron );
886         my $status = $req->gather(1);
887         if(!defined($status)) { 
888                 throw OpenSRF::EX::ERROR 
889                         ("Unknown error updating patron"); 
890         }
891 }
892
893