3 # This file is part of Koha.
5 # Copyright (C) 2014 Hochschule für Gesundheit (hsg), Germany
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
22 automatic_renewals.pl - cron script to renew loans
26 ./automatic_renewals.pl [-c|--confirm] [-s|--send-notices] [-d|--digest] [-b|--digest-per-branch] [-v|--verbose]
29 # Once every day for digest messages
30 0 3 * * * automatic_renewals.pl -c -d
31 # Three times a day for non digest messages
32 0 0,8,16 * * * automatic_renewals.pl -c
36 This script searches for issues scheduled for automatic renewal
37 (issues.auto_renew). If there are still renews left (Renewals allowed)
38 and the renewal isn't premature (No Renewal before) the issue is renewed.
44 =item B<-s|--send-notices>
46 DEPRECATED: The system preference AutoRenewalNotices should be used to determine
47 whether notices are sent or not
48 Send AUTO_RENEWALS notices to patrons if the auto renewal has been done.
52 Print report to standard out.
56 Without this parameter no changes will be made
58 =item B<-b|--digest-per-branch>
60 Flag to indicate that generation of message digests should be
61 performed separately for each branch.
63 A patron could potentially have loans at several different branches
64 There is no natural branch to set as the sender on the aggregated
65 message in this situation so the default behavior is to use the
66 borrowers home branch. This could surprise to the borrower when
67 message sender is a library where they have not borrowed anything.
69 Enabling this flag ensures that the issuing library is the sender of
70 the digested message. It has no effect unless the borrower has
71 chosen 'Digests only' on the advance messages.
81 use Koha::Script -cron;
90 my ( $help, $send_notices, $verbose, $confirm, $digest_per_branch );
93 's|send-notices' => \$send_notices,
94 'v|verbose' => \$verbose,
95 'c|confirm' => \$confirm,
96 'b|digest-per-branch' => \$digest_per_branch,
99 pod2usage(0) if $help;
101 my $send_notices_pref = C4::Context->preference('AutoRenewalNotices')
102 if ( $send_notices_pref = 'cron' ) {
105 The "AutoRenewalNotices" syspref is set to 'Follow the cron switch'.
106 The send_notices switch for this script is deprecated, you should either set the preference
107 to 'Never send emails' or 'Follow patron messaging preferences'
111 # If not following cron then we should not send if set to never
112 # and always send any generated according to preferences if following those
113 $send_notices = $send_notices_pref eq 'never' ? 0 : 1;
116 # Since advance notice options are not visible in the web-interface
117 # unless EnhancedMessagingPreferences is on, let the user know that
118 # this script probably isn't going to do much
119 if ( ! C4::Context->preference('EnhancedMessagingPreferences') ) {
122 The "EnhancedMessagingPreferences" syspref is off.
123 Therefore, it is unlikely that this script will actually produce any messages to be sent.
124 To change this, edit the "EnhancedMessagingPreferences" syspref.
131 $verbose = 1 unless $verbose or $confirm;
132 print "Test run only\n" unless $confirm;
134 print "getting auto renewals\n" if $verbose;
135 my $auto_renews = Koha::Checkouts->search({ auto_renew => 1, 'borrower.autorenew_checkouts' => 1 },{ join => 'borrower'});
136 print "found " . $auto_renews->count . " auto renewals\n" if $verbose;
138 my $renew_digest = {};
140 while ( my $auto_renew = $auto_renews->next ) {
141 print "examining item '" . $auto_renew->itemnumber . "' to auto renew\n" if $verbose;
143 my $borrower_preferences;
144 $borrower_preferences = C4::Members::Messaging::GetMessagingPreferences( { borrowernumber => $auto_renew->borrowernumber,
145 message_name => 'auto_renewals' } ) if $send_notices_pref eq 'preferences';
147 # CanBookBeRenewed returns 'auto_renew' when the renewal should be done by this script
148 my ( $ok, $error ) = CanBookBeRenewed( $auto_renew->borrowernumber, $auto_renew->itemnumber, undef, 1 );
149 if ( $error eq 'auto_renew' ) {
151 say sprintf "Issue id: %s for borrower: %s and item: %s %s be renewed.",
152 $auto_renew->issue_id, $auto_renew->borrowernumber, $auto_renew->itemnumber, $confirm ? 'will' : 'would';
155 my $date_due = AddRenewal( $auto_renew->borrowernumber, $auto_renew->itemnumber, $auto_renew->branchcode, undef, undef, undef, 0 );
156 $auto_renew->auto_renew_error(undef)->store;
158 push @{ $report{ $auto_renew->borrowernumber } }, $auto_renew unless $borrower_preferences && (!$borrower_preferences->{transports} || !$borrower_preferences->{transports}->{email} || $borrower_preferences->{'wants_digest'});
159 } elsif ( $error eq 'too_many'
160 or $error eq 'on_reserve'
161 or $error eq 'restriction'
162 or $error eq 'overdue'
163 or $error eq 'too_unseen'
164 or $error eq 'auto_account_expired'
165 or $error eq 'auto_too_late'
166 or $error eq 'auto_too_much_oweing'
167 or $error eq 'auto_too_soon'
168 or $error eq 'item_denied_renewal' ) {
170 say sprintf "Issue id: %s for borrower: %s and item: %s %s not be renewed. (%s)",
171 $auto_renew->issue_id, $auto_renew->borrowernumber, $auto_renew->itemnumber, $confirm ? 'will' : 'would', $error;
173 if ( not $auto_renew->auto_renew_error or $error ne $auto_renew->auto_renew_error ) {
174 $auto_renew->auto_renew_error($error)->store if $confirm;
175 push @{ $report{ $auto_renew->borrowernumber } }, $auto_renew
176 if $error ne 'auto_too_soon' && (!$borrower_preferences || ($borrower_preferences->{transports} && $borrower_preferences->{transports}->{email} && !$borrower_preferences->{'wants_digest'})); # Do not notify if it's too soon
180 if ( $borrower_preferences && $borrower_preferences->{transports} && $borrower_preferences->{transports}->{email} && $borrower_preferences->{'wants_digest'} ) {
181 # cache this one to process after we've run through all of the items.
182 if ($digest_per_branch) {
183 $renew_digest->{ $auto_renew->branchcode }->{ $auto_renew->borrowernumber }->{success}++ if $error eq 'auto_renew';
184 $renew_digest->{ $auto_renew->branchcode }->{ $auto_renew->borrowernumber }->{error}++ unless $error eq 'auto_renew' || $error == 'auto_too_soon' ;
186 $renew_digest->{ $auto_renew->borrowernumber }->{success} ++ if $error eq 'auto_renew';
187 $renew_digest->{ $auto_renew->borrowernumber }->{error}++ unless $error eq 'auto_renew' || $error eq 'auto_too_soon' ;
193 if ( $send_notices && $confirm ) {
194 for my $borrowernumber ( keys %report ) {
195 my $patron = Koha::Patrons->find($borrowernumber);
196 for my $issue ( @{ $report{$borrowernumber} } ) {
197 my $item = Koha::Items->find( $issue->itemnumber );
198 my $letter = C4::Letters::GetPreparedLetter(
199 module => 'circulation',
200 letter_code => 'AUTO_RENEWALS',
202 borrowers => $patron->borrowernumber,
203 issues => $issue->itemnumber,
204 items => $issue->itemnumber,
205 biblio => $item->biblionumber,
207 lang => $patron->lang,
210 my $library = Koha::Libraries->find( $patron->branchcode );
211 my $admin_email_address = $library->branchemail || C4::Context->preference('KohaAdminEmailAddress');
213 C4::Letters::EnqueueLetter(
215 borrowernumber => $borrowernumber,
216 message_transport_type => 'email',
217 from_address => $admin_email_address,
223 if ($digest_per_branch) {
224 while (my ($branchcode, $digests) = each %$renew_digest) {
227 branchcode => $branchcode,
228 letter_code => 'AUTO_RENEWALS_DGST',
233 digests => $renew_digest,
234 letter_code => 'AUTO_RENEWALS_DGST',
248 Enqueue digested letters.
256 Reference to the array of digested messages.
258 =item C<$letter_code>
260 String that denote the letter code.
269 my $admin_email_address = C4::Context->preference('KohaAdminEmailAddress');
271 PATRON: while ( my ( $borrowernumber, $digest ) = each %{$params->{digests}} ) {
272 my $borrower_preferences =
273 C4::Members::Messaging::GetMessagingPreferences(
275 borrowernumber => $borrowernumber,
276 message_name => 'auto_renewals'
280 next PATRON unless $borrower_preferences; # how could this happen?
282 my $patron = Koha::Patrons->find( $borrowernumber );
283 my $library = Koha::Libraries->find( $params->{branchcode} );
284 my $from_address = $library->{branchemail} || $admin_email_address;
286 foreach my $transport ( keys %{ $borrower_preferences->{'transports'} } ) {
287 my $letter = C4::Letters::GetPreparedLetter (
288 module => 'circulation',
289 letter_code => $params->{letter_code},
290 branchcode => $params->{branchcode},
291 lang => $patron->lang,
293 error => $digest->{error}||0,
294 success => $digest->{success}||0,
297 borrowers => $patron->borrowernumber,
299 message_transport_type => $transport,
300 ) || warn "no letter of type '$params->{letter_code}' found for borrowernumber $borrowernumber. Please see sample_notices.sql";
304 C4::Letters::EnqueueLetter({
306 borrowernumber => $borrowernumber,
307 from_address => $from_address,
308 message_transport_type => $transport