]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/lib/OpenILS/SIP.pm
LP 1889628: Use Workstation in SIP Username Lookup
[Evergreen.git] / Open-ILS / src / perlmods / lib / OpenILS / SIP.pm
1 #
2 # ILS.pm: Test ILS interface module
3 #
4
5 package OpenILS::SIP;
6 use warnings; use strict;
7
8 use Sys::Syslog qw(syslog);
9 use Time::HiRes q/time/;
10
11 use OpenILS::SIP::Item;
12 use OpenILS::SIP::Patron;
13 use OpenILS::SIP::Transaction;
14 use OpenILS::SIP::Transaction::Checkout;
15 use OpenILS::SIP::Transaction::Checkin;
16 use OpenILS::SIP::Transaction::Renew;
17 use OpenILS::SIP::Transaction::RenewAll;
18 use OpenILS::SIP::Transaction::FeePayment;
19 use OpenILS::SIP::Transaction::Hold;
20
21 use OpenSRF::System;
22 use OpenSRF::AppSession;
23 use OpenILS::Utils::Fieldmapper;
24 use OpenSRF::Utils::SettingsClient;
25 use OpenILS::Application::AppUtils;
26 use OpenILS::Utils::DateTime qw/:datetime/;
27 use DateTime::Format::ISO8601;
28
29 my $U = 'OpenILS::Application::AppUtils';
30
31 my $editor;
32 my $config;
33 my $login_account;
34 my $target_encoding;    # FIXME: this is configured at the institution level. 
35
36 use Digest::MD5 qw(md5_hex);
37
38 # Copied from Sip::Constants
39 use constant {
40     SIP_DATETIME => "%Y%m%d    %H%M%S",
41 };
42
43 sub disconnect {
44      OpenSRF::Transport::PeerHandle->retrieve->disconnect
45 }
46
47 sub new {
48     my ($class, $institution, $login, $state) = @_;
49     my $type = ref($class) || $class;
50     my $self = {};
51
52     $self->{login} = $login_account = $login;
53
54     $config = $institution;
55     syslog("LOG_DEBUG", "OILS: new ILS '%s'", $institution->{id});
56     $self->{institution} = $institution;
57
58     my $bsconfig     = $institution->{implementation_config}->{bootstrap};
59     $target_encoding = $institution->{implementation_config}->{encoding} || 'ascii';
60
61     syslog('LOG_DEBUG', "OILS: loading bootstrap config: $bsconfig");
62
63     # ingress will persist throughout
64     OpenSRF::AppSession->ingress('sip2');
65     
66     local $/ = "\n";    # why?
67     OpenSRF::System->bootstrap_client(config_file => $bsconfig);
68     syslog('LOG_DEBUG', "OILS: bootstrap loaded..");
69
70     $self->{osrf_config} = OpenSRF::Utils::SettingsClient->new;
71
72     Fieldmapper->import($self->{osrf_config}->config_value('IDL'));
73
74     bless( $self, $type );
75
76     return undef unless 
77         $self->login( $login->{id}, $login->{password}, $state );
78
79     return $self;
80 }
81
82 sub fetch_session {
83     my $self = shift;
84
85     my $ses = $U->simplereq( 
86         'open-ils.auth',
87         'open-ils.auth.session.retrieve',  $self->{authtoken});
88
89     return undef if $U->event_code($ses); # auth timed out
90     return $self->{login_session} = $ses;
91 }
92
93 sub verify_session {
94     my $self = shift;
95
96     return 1 if $self->fetch_session;
97
98     syslog('LOG_INFO', "OILS: Logging back after session timeout as user ".$self->{login}->{id});
99     return $self->login( $self->{login}->{id}, $self->{login}->{password} );
100 }
101
102 sub editor {
103     return $editor = make_editor();
104 }
105
106 sub config {
107     return $config;
108 }
109 sub login_account {
110     return $login_account;
111 }
112
113 sub get_option_value {
114     my($self, $option) = @_;
115     my $ops = $config->{implementation_config}->{options}->{option};
116     $ops = [$ops] unless ref $ops eq 'ARRAY';
117     my @vals = grep { $_->{name} eq $option } @$ops;
118     return @vals ? $vals[0]->{value} : undef;
119 }
120
121
122 # Creates the global editor object
123 my $cstore_init = 1; # call init on first use
124 sub make_editor {
125     OpenILS::Utils::CStoreEditor::init() if $cstore_init;
126     $cstore_init = 0;
127     return OpenILS::Utils::CStoreEditor->new;
128 }
129
130 my %org_sn_cache;
131 sub shortname_from_id {
132     my $id = shift or return;
133     return $id->shortname if ref $id;
134     return $org_sn_cache{$id} if $org_sn_cache{$id};
135     return $org_sn_cache{$id} = editor()->retrieve_actor_org_unit($id)->shortname;
136 }
137 sub patron_barcode_from_id {
138     my $id = shift or return;
139     return editor()->search_actor_card({ usr => $id, active => 't' })->[0]->barcode;
140 }
141
142 sub format_date {
143     my $class = shift;
144     my $date = shift;
145     my $type = shift || '';
146
147     return "" unless $date;
148
149     my $dt = DateTime::Format::ISO8601->new->
150         parse_datetime(clean_ISO8601($date));
151
152     # actor.usr.dob stores dates without time/timezone, which causes
153     # DateTime to assume the date is stored as UTC.  Tell DateTime
154     # to use the local time zone, instead.
155     # Other dates will have time zones and should be parsed as-is.
156     $dt->set_time_zone('local') if $type eq 'dob';
157
158     my @time = localtime($dt->epoch);
159
160     my $year   = $time[5]+1900;
161     my $mon    = $time[4]+1;
162     my $day    = $time[3];
163     my $hour   = $time[2];
164     my $minute = $time[1];
165     my $second = $time[0];
166   
167     $date = sprintf("%04d%02d%02d", $year, $mon, $day);
168
169     # Due dates need hyphen separators and time of day as well
170     if ($type eq 'due') {
171
172         my $use_sdf = $class->get_option_value('use_sip_date_format') || '';
173
174         if ($use_sdf =~ /true/i) {
175             $date = $dt->strftime(SIP_DATETIME);
176
177         } else {
178             $date = sprintf("%04d-%02d-%02d %02d:%02d:%02d", 
179                 $year, $mon, $day, $hour, $minute, $second);
180         }
181     }
182
183     syslog('LOG_DEBUG', "OILS: formatted date [type=$type]: $date");
184     return $date;
185 }
186
187
188
189 sub login {
190     my( $self, $username, $password, $state ) = @_;
191     syslog('LOG_DEBUG', "OILS: Logging in with username $username");
192
193
194     if ($state and ref $state and $$state{authtoken}) {
195         $self->{authtoken} = $$state{authtoken};
196         return $self->{authtoken} if ($self->fetch_session); # fetch the session
197     }
198
199     my $nonce = rand($$);
200
201     my $seed = $U->simplereq(
202         'open-ils.auth',
203         'open-ils.auth.authenticate.init', $username, $nonce );
204
205     my $opts =
206         {
207             username => $username,
208             password => md5_hex($seed . md5_hex($password)),
209             type     => 'opac',
210             nonce    => $nonce
211         };
212
213     if ($self->{login}->{location}) {
214         $opts->{workstation} = $self->{login}->{location};
215     }
216
217     my $response = $U->simplereq(
218         'open-ils.auth',
219         'open-ils.auth.authenticate.complete',
220         $opts
221     );
222
223     if( my $code = $U->event_code($response) ) {
224         my $txt = $response->{textcode};
225         syslog('LOG_WARNING', "OILS: Login failed for $username.  $txt:$code");
226         return undef;
227     }
228
229     my $key = $response->{payload}->{authtoken};
230     syslog('LOG_INFO', "OILS: Login succeeded for $username : authkey = $key");
231
232     $self->{authtoken} = $key;
233
234     $self->fetch_session; # to cache the login
235
236     return $key;
237 }
238
239 sub state {
240     my $self = shift;
241     return { authtoken => $self->{authtoken} };
242 }
243
244 sub get_ou_setting {
245     my $self = shift;
246     my $setting = shift;
247     my $sess = $self->fetch_session;
248     my $ou = (ref($sess->home_ou)) ? $sess->home_ou->id : $sess->home_ou;
249     if ($sess->ws_ou) {
250         $ou = (ref($sess->ws_ou)) ? $sess->ws_ou->id : $sess->ws_ou;
251     }
252     return $U->ou_ancestor_setting_value($ou, $setting);
253 }
254
255 sub get_barcode_regex {
256     my $self = shift;
257     if (!defined($self->{bc_regex})) {
258         $self->{bc_regex} = $self->get_ou_setting('opac.barcode_regex');
259         $self->{bc_regex} = '^\d' unless ($self->{bc_regex});
260     }
261     return $self->{bc_regex};
262 }
263
264 #
265 # find_patron($barcode);
266 # find_patron(barcode => $barcode);   # same as above
267 # find_patron(usr => $id);
268 # find_patron(usrname => $usrname);
269
270 sub find_patron {
271     my $self = shift;
272     my $key  =  (@_ > 1) ? shift : 'barcode';  # if we have multiple args, the first is the key index (default barcode)
273     my $patron_id = shift;
274
275     # Check for usrname or barcode in the same, simple way that the OPAC does.
276     my $bc_regex = $self->get_barcode_regex();
277     if ($key eq 'barcode' && $patron_id !~ /$bc_regex/) {
278         $key = 'usrname';
279     }
280
281     $self->verify_session;
282     return OpenILS::SIP::Patron->new($key => $patron_id, authtoken => $self->{authtoken}, @_);
283 }
284
285
286 sub find_item {
287     my $self = shift;
288     $self->verify_session;
289     return OpenILS::SIP::Item->new(@_);
290 }
291
292
293 sub institution {
294     my $self = shift;
295     return $self->{institution}->{id};  # consider making this return the whole institution
296 }
297
298 sub institution_id {
299     my $self = shift;
300     return $self->{institution}->{id};  # then use this for just the ID
301 }
302
303 sub supports {
304     my ($self, $op) = @_;
305     my ($i) = grep { $_->{name} eq $op }  
306         @{$config->{implementation_config}->{supports}->{item}};
307     return to_bool($i->{value});
308 }
309
310 sub check_inst_id {
311     my ($self, $id, $whence) = @_;
312     if ($id ne $self->{institution}->{id}) {
313         syslog("LOG_WARNING", "OILS: %s: received institution '%s', expected '%s'", $whence, $id, $self->{institution}->{id});
314         # Just an FYI check, we don't expect the user to change location from that in SIPconfig.xml
315     }
316 }
317
318
319 sub to_bool {
320     my $bool = shift;
321     # If it's defined, and matches a true sort of string, or is
322     # a non-zero number, then it's true.
323     defined($bool) or return;                   # false
324     ($bool =~ /true|y|yes/i) and return 1;      # true
325     return ($bool =~ /^\d+$/ and $bool != 0);   # true for non-zero numbers, false otherwise
326 }
327
328 sub checkout_ok {
329     return to_bool($config->{policy}->{checkout});
330 }
331
332 sub checkin_ok {
333     return to_bool($config->{policy}->{checkin});
334 }
335
336 sub renew_ok {
337     return to_bool($config->{policy}->{renewal});
338 }
339
340 sub status_update_ok {
341     return to_bool($config->{policy}->{status_update});
342 }
343
344 sub offline_ok {
345     return to_bool($config->{policy}->{offline});
346 }
347
348
349
350 ##
351 ## Checkout(patron_id, item_id, sc_renew, fee_ack):
352 ##    patron_id & item_id are the identifiers send by the terminal
353 ##    sc_renew is the renewal policy configured on the terminal
354 ## returns a status opject that can be queried for the various bits
355 ## of information that the protocol (SIP or NCIP) needs to generate
356 ## the response.
357 ##    fee_ack is the fee_acknowledged field (BO) sent from the sc
358 ## when doing chargeable loans.
359 ##
360
361 sub checkout {
362     my ($self, $patron_id, $item_id, $sc_renew, $fee_ack) = @_;
363     # In order to allow renewals the selfcheck AND the config have to say they are allowed
364     $sc_renew = (chr($sc_renew) eq 'Y' && $self->renew_ok());
365
366     $self->verify_session;
367
368     syslog('LOG_DEBUG', "OILS: OpenILS::Checkout attempt: patron=$patron_id, item=$item_id");
369
370     my $xact   = OpenILS::SIP::Transaction::Checkout->new( authtoken => $self->{authtoken} );
371     my $patron = $self->find_patron($patron_id);
372     my $item   = $self->find_item($item_id);
373
374     $xact->patron($patron);
375     $xact->item($item);
376
377     if (!$patron) {
378         $xact->screen_msg("Invalid Patron Barcode '$patron_id'");
379         return $xact;
380     }
381
382     if (!$patron->charge_ok) {
383         $xact->screen_msg("Patron Blocked");
384         return $xact;
385     }
386
387     if( !$item ) {
388         $xact->screen_msg("Invalid Item Barcode: '$item_id'");
389         return $xact;
390     }
391
392     syslog('LOG_DEBUG', "OILS: OpenILS::Checkout data loaded OK, checking out...");
393
394     if ($item->{patron} && ($item->{patron} eq $patron_id)) {
395         $xact->renew_ok(1); # So that accept/reject responses have the correct value later
396         if($sc_renew) {
397             syslog('LOG_INFO', "OILS: OpenILS::Checkout data loaded OK, doing renew...");
398         } else {
399             syslog('LOG_INFO', "OILS: OpenILS::Checkout appears to be renew, but renewal disallowed...");
400             $xact->screen_msg("Renewals not permitted");
401             $xact->ok(0);
402             return $xact; # Don't attempt later
403         }
404     } elsif ($item->{patron} && ($item->{patron} ne $patron_id)) {
405         # I can't deal with this right now
406         # XXX check in then check out?
407         $xact->screen_msg("Item checked out to another patron");
408         $xact->ok(0);
409         return $xact; # Don't wipe out the screen message later
410     } else {
411         $sc_renew = 0;
412     } 
413
414     # Check for fee and $fee_ack. If there is a fee, and $fee_ack
415     # is 'Y', we proceed, otherwise we reject the checkout.
416     if ($item->fee > 0.0) {
417         $xact->fee_amount($item->fee);
418         $xact->sip_fee_type($item->sip_fee_type);
419         $xact->sip_currency($item->fee_currency);
420         if ($fee_ack && $fee_ack eq 'Y') {
421             $xact->fee_ack(1);
422         } else {
423             $xact->screen_msg('Fee required');
424             $xact->ok(0);
425             return $xact;
426         }
427     }
428
429     $xact->do_checkout($sc_renew);
430     $xact->desensitize(!$item->magnetic);
431
432     if( $xact->ok ) {
433         #editor()->commit;
434         syslog("LOG_DEBUG", "OILS: OpenILS::Checkout: " .
435             "patron %s checkout %s succeeded", $patron_id, $item_id);
436     } else {
437         #editor()->xact_rollback;
438         syslog("LOG_DEBUG", "OILS: OpenILS::Checkout: " .
439             "patron %s checkout %s FAILED, rolling back xact...", $patron_id, $item_id);
440     }
441
442     return $xact;
443 }
444
445
446 sub checkin {
447     my ($self, $item_id, $inst_id, $trans_date, $return_date,
448         $current_loc, $item_props, $cancel) = @_;
449
450     my $start_time = time();
451
452     $self->verify_session;
453
454     syslog('LOG_DEBUG', "OILS: OpenILS::Checkin of item=$item_id (to $inst_id)");
455     
456     my $xact = OpenILS::SIP::Transaction::Checkin->new(authtoken => $self->{authtoken});
457     my $item = OpenILS::SIP::Item->new($item_id);
458
459     unless ( $xact->item($item) ) {
460         $xact->ok(0);
461         # $circ->alert(1); $circ->alert_type(99);
462         $xact->screen_msg("Invalid Item Barcode: '$item_id'");
463         syslog('LOG_INFO', "OILS: Checkin failed.  " . $xact->screen_msg() );
464         return $xact;
465     }
466
467     $xact->do_checkin( $self, $inst_id, $trans_date, $return_date, $current_loc, $item_props );
468     
469     if ($xact->ok) {
470         $xact->patron($self->find_patron(usr => $xact->{circ_user_id}, slim_user => 1)) if $xact->{circ_user_id};
471         delete $item->{patron};
472         delete $item->{due_date};
473         syslog('LOG_INFO', "OILS: Checkin succeeded");
474     } else {
475         syslog('LOG_WARNING', "OILS: Checkin failed");
476     }
477
478     syslog('LOG_INFO', "OILS: SIP Checkin request took %0.3f seconds", (time() - $start_time));
479     return $xact;
480 }
481
482 ## If the ILS caches patron information, this lets it free it up.
483 ## Also, this could be used for centrally logging session duration.
484 ## We don't do anything with it.
485 sub end_patron_session {
486     my ($self, $patron_id) = @_;
487     return (1, 'Thank you!', '');
488 }
489
490
491 sub pay_fee {
492     my ($self, $patron_id, $patron_pwd, $fee_amt, $fee_type,
493     $pay_type, $fee_id, $trans_id, $currency) = @_;
494
495     $self->verify_session;
496
497     my $xact = OpenILS::SIP::Transaction::FeePayment->new(authtoken => $self->{authtoken});
498     my $patron = $self->find_patron($patron_id);
499
500     if (!$patron) {
501         $xact->screen_msg("Invalid Patron Barcode '$patron_id'");
502         $xact->ok(0);
503         return $xact;
504     }
505
506     $xact->patron($patron);
507     $xact->sip_currency($currency);
508     $xact->fee_amount($fee_amt);
509     $xact->sip_fee_type($fee_type);
510     $xact->transaction_id($trans_id);
511     $xact->fee_id($fee_id);
512     $xact->sip_payment_type($pay_type);
513     # We don't presently use this, but we might in the future.
514     $xact->patron_password($patron_pwd);
515
516     $xact->do_fee_payment();
517
518     return $xact;
519 }
520
521 #sub add_hold {
522 #    my ($self, $patron_id, $patron_pwd, $item_id, $title_id,
523 #    $expiry_date, $pickup_location, $hold_type, $fee_ack) = @_;
524 #    my ($patron, $item);
525 #    my $hold;
526 #    my $trans;
527 #
528 #
529 #    $trans = new ILS::Transaction::Hold;
530 #
531 #    # BEGIN TRANSACTION
532 #    $patron = new ILS::Patron $patron_id;
533 #    if (!$patron
534 #    || (defined($patron_pwd) && !$patron->check_password($patron_pwd))) {
535 #    $trans->screen_msg("Invalid Patron.");
536 #
537 #    return $trans;
538 #    }
539 #
540 #    $item = new ILS::Item ($item_id || $title_id);
541 #    if (!$item) {
542 #    $trans->screen_msg("No such item.");
543 #
544 #    # END TRANSACTION (conditionally)
545 #    return $trans;
546 #    } elsif ($item->fee && ($fee_ack ne 'Y')) {
547 #    $trans->screen_msg = "Fee required to place hold.";
548 #
549 #    # END TRANSACTION (conditionally)
550 #    return $trans;
551 #    }
552 #
553 #    $hold = {
554 #    item_id         => $item->id,
555 #    patron_id       => $patron->id,
556 #    expiration_date => $expiry_date,
557 #    pickup_location => $pickup_location,
558 #    hold_type       => $hold_type,
559 #    };
560 #
561 #    $trans->ok(1);
562 #    $trans->patron($patron);
563 #    $trans->item($item);
564 #    $trans->pickup_location($pickup_location);
565 #
566 #    push(@{$item->hold_queue}, $hold);
567 #    push(@{$patron->{hold_items}}, $hold);
568 #
569 #
570 #    # END TRANSACTION
571 #    return $trans;
572 #}
573 #
574
575 # Note: item_id in this context is the hold id
576 sub cancel_hold {
577     my ($self, $patron_id, $patron_pwd, $item_id, $title_id) = @_;
578
579     my $trans = OpenILS::SIP::Transaction::Hold->new(authtoken => $self->{authtoken});
580     my $patron = $self->find_patron($patron_id);
581
582     if (!$patron) {
583         $trans->screen_msg("Invalid patron barcode.");
584         $trans->ok(0);
585         return $trans;
586     }
587
588     if (defined($patron_pwd) && !$patron->check_password($patron_pwd)) {
589         $trans->screen_msg('Invalid patron password.');
590         $trans->ok(0);
591         return $trans;
592     }
593
594     $trans->patron($patron);
595     my $hold = $patron->find_hold_from_copy($item_id);
596
597     if (!$hold) {
598         syslog('LOG_WARNING', "OILS: No hold found from copy $item_id");
599         $trans->screen_msg("No such hold.");
600         $trans->ok(0);
601         return $trans;
602     }
603
604     if ($hold->usr ne $patron->{user}->id) {
605         $trans->screen_msg("No such hold on patron record.");
606         $trans->ok(0);
607         return $trans;
608     }
609
610     $trans->hold($hold);
611     $trans->do_hold_cancel($self);
612
613     if ($trans->cancel_ok) {
614         $trans->screen_msg("Hold Cancelled.");
615     } else {
616         $trans->screen_msg("Hold was not cancelled.");
617     }
618
619     # if the hold had no current_copy, use the representative
620     # item as the item for the hold.  Without this, the SIP 
621     # server gets angry.
622     $trans->item($self->find_item($item_id)) unless $trans->item;
623
624     return $trans;
625 }
626
627 #
628 ## The patron and item id's can't be altered, but the
629 ## date, location, and type can.
630 #sub alter_hold {
631 #    my ($self, $patron_id, $patron_pwd, $item_id, $title_id,
632 #    $expiry_date, $pickup_location, $hold_type, $fee_ack) = @_;
633 #    my ($patron, $item);
634 #    my $hold;
635 #    my $trans;
636 #
637 #    $trans = new ILS::Transaction::Hold;
638 #
639 #    # BEGIN TRANSACTION
640 #    $patron = new ILS::Patron $patron_id;
641 #    if (!$patron) {
642 #    $trans->screen_msg("Invalid patron barcode.");
643 #
644 #    return $trans;
645 #    }
646 #
647 #    foreach my $i (0 .. scalar @{$patron->{hold_items}}) {
648 #    $hold = $patron->{hold_items}[$i];
649 #
650 #    if ($hold->{item_id} eq $item_id) {
651 #        # Found it.  So fix it.
652 #        $hold->{expiration_date} = $expiry_date if $expiry_date;
653 #        $hold->{pickup_location} = $pickup_location if $pickup_location;
654 #        $hold->{hold_type} = $hold_type if $hold_type;
655 #
656 #        $trans->ok(1);
657 #        $trans->screen_msg("Hold updated.");
658 #        $trans->patron($patron);
659 #        $trans->item(new ILS::Item $hold->{item_id});
660 #        last;
661 #    }
662 #    }
663 #
664 #    # The same hold structure is linked into both the patron's
665 #    # list of hold items and into the queue of outstanding holds
666 #    # for the item, so we don't need to search the hold queue for
667 #    # the item, since it's already been updated by the patron code.
668 #
669 #    if (!$trans->ok) {
670 #    $trans->screen_msg("No such outstanding hold.");
671 #    }
672 #
673 #    return $trans;
674 #}
675
676
677 sub renew {
678     my ($self, $patron_id, $patron_pwd, $item_id, $title_id,
679         $no_block, $nb_due_date, $third_party, $item_props, $fee_ack) = @_;
680
681     $self->verify_session;
682
683     my $trans = OpenILS::SIP::Transaction::Renew->new( authtoken => $self->{authtoken} );
684     $trans->patron($self->find_patron($patron_id));
685     $trans->item($self->find_item($item_id));
686
687     if(!$trans->patron) {
688         $trans->screen_msg("Invalid patron barcode.");
689         $trans->ok(0);
690         return $trans;
691     }
692
693     if(!$trans->patron->renew_ok) {
694         $trans->screen_msg("Renewals not allowed.");
695         $trans->ok(0);
696         return $trans;
697     }
698
699     if(!$trans->item) {
700         if( $title_id ) {
701             $trans->screen_msg("Title ID renewal not supported.  Use item barcode.");
702         } else {
703             $trans->screen_msg("Invalid item barcode.");
704         }
705         $trans->ok(0);
706         return $trans;
707     }
708
709     if(!$trans->item->{patron} or 
710             $trans->item->{patron} ne $patron_id) {
711         $trans->screen_msg("Item not checked out to " . $trans->patron->name);
712         $trans->ok(0);
713         return $trans;
714     }
715
716     # Perform the renewal
717     $trans->do_renew();
718
719     $trans->desensitize(0);    # It's already checked out
720     $trans->item->{due_date} = $nb_due_date if $no_block eq 'Y';
721     $trans->item->{sip_item_properties} = $item_props if $item_props;
722
723     return $trans;
724 }
725
726
727 sub renew_all {
728     my ($self, $patron_id, $patron_pwd, $fee_ack) = @_;
729
730     $self->verify_session;
731
732     my $trans = OpenILS::SIP::Transaction::RenewAll->new(authtoken => $self->{authtoken});
733     $trans->patron($self->find_patron($patron_id));
734
735     if(!$trans->patron) {
736         $trans->screen_msg("Invalid patron barcode.");
737         $trans->ok(0);
738         return $trans;
739     }
740
741     if(!$trans->patron->renew_ok) {
742         $trans->screen_msg("Renewals not allowed.");
743         $trans->ok(0);
744         return $trans;
745     }
746
747     $trans->do_renew_all($self);
748     return $trans;
749 }
750
751
752 #
753 #sub renew_all {
754 #    my ($self, $patron_id, $patron_pwd, $fee_ack) = @_;
755 #    my ($patron, $item_id);
756 #    my $trans;
757 #
758 #    $trans = new ILS::Transaction::RenewAll;
759 #
760 #    $trans->patron($patron = new ILS::Patron $patron_id);
761 #    if (defined $patron) {
762 #    syslog("LOG_DEBUG", "ILS::renew_all: patron '%s': renew_ok: %s",
763 #           $patron->name, $patron->renew_ok);
764 #    } else {
765 #    syslog("LOG_DEBUG", "ILS::renew_all: Invalid patron id: '%s'",
766 #           $patron_id);
767 #    }
768 #
769 #    if (!defined($patron)) {
770 #    $trans->screen_msg("Invalid patron barcode.");
771 #    return $trans;
772 #    } elsif (!$patron->renew_ok) {
773 #    $trans->screen_msg("Renewals not allowed.");
774 #    return $trans;
775 #    } elsif (defined($patron_pwd) && !$patron->check_password($patron_pwd)) {
776 #    $trans->screen_msg("Invalid patron password.");
777 #    return $trans;
778 #    }
779 #
780 #    foreach $item_id (@{$patron->{items}}) {
781 #    my $item = new ILS::Item $item_id;
782 #
783 #    if (!defined($item)) {
784 #        syslog("LOG_WARNING",
785 #           "renew_all: Invalid item id associated with patron '%s'",
786 #           $patron->id);
787 #        next;
788 #    }
789 #
790 #    if (@{$item->hold_queue}) {
791 #        # Can't renew if there are outstanding holds
792 #        push @{$trans->unrenewed}, $item_id;
793 #    } else {
794 #        $item->{due_date} = time + (14*24*60*60); # two weeks hence
795 #        push @{$trans->renewed}, $item_id;
796 #    }
797 #    }
798 #
799 #    $trans->ok(1);
800 #
801 #    return $trans;
802 #}
803
804 1;