Lines 2-8
Link Here
|
2 |
|
2 |
|
3 |
# This file is part of Koha. |
3 |
# This file is part of Koha. |
4 |
# |
4 |
# |
5 |
# Copyright (C) 2014 Hochschule für Gesundheit (hsg), Germany |
5 |
# Copyright (C) 2014 Hochschule für Gesundheit (hsg), Germany |
6 |
# |
6 |
# |
7 |
# Koha is free software; you can redistribute it and/or modify it |
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 |
8 |
# under the terms of the GNU General Public License as published by |
Lines 23-32
automatic_renewals.pl - cron script to renew loans
Link Here
|
23 |
|
23 |
|
24 |
=head1 SYNOPSIS |
24 |
=head1 SYNOPSIS |
25 |
|
25 |
|
26 |
./automatic_renewals.pl [-c|--confirm] [--send-notices] |
26 |
./automatic_renewals.pl [-c|--confirm] [-s|--send-notices] [-d|--digest] [-b|--digest-per-branch] [-v|--verbose] |
27 |
|
27 |
|
28 |
or, in crontab: |
28 |
or, in crontab: |
29 |
0 3 * * * automatic_renewals.pl -c |
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 |
30 |
|
33 |
|
31 |
=head1 DESCRIPTION |
34 |
=head1 DESCRIPTION |
32 |
|
35 |
|
Lines 38-49
and the renewal isn't premature (No Renewal before) the issue is renewed.
Link Here
|
38 |
|
41 |
|
39 |
=over |
42 |
=over |
40 |
|
43 |
|
41 |
=item B<--send-notices> |
44 |
=item B<-s|--send-notices> |
42 |
|
45 |
|
43 |
Send AUTO_RENEWALS notices to patrons if the auto renewal has been done. |
46 |
Send AUTO_RENEWALS notices to patrons if the auto renewal has been done. |
44 |
|
47 |
|
45 |
Note that this option does not support digest yet. |
|
|
46 |
|
47 |
=item B<-v|--verbose> |
48 |
=item B<-v|--verbose> |
48 |
|
49 |
|
49 |
Print report to standard out. |
50 |
Print report to standard out. |
Lines 52-57
Print report to standard out.
Link Here
|
52 |
|
53 |
|
53 |
Without this parameter no changes will be made |
54 |
Without this parameter no changes will be made |
54 |
|
55 |
|
|
|
56 |
=item B<-d|--digest> |
57 |
|
58 |
Flag to indicate that this script should process digest messages. |
59 |
|
60 |
=item B<-b|--digest-per-branch> |
61 |
|
62 |
Flag to indicate that generation of message digests should be |
63 |
performed separately for each branch. Needs --digest option. |
64 |
|
65 |
A patron could potentially have loans at several different branches |
66 |
There is no natural branch to set as the sender on the aggregated |
67 |
message in this situation so the default behavior is to use the |
68 |
borrowers home branch. This could surprise to the borrower when |
69 |
message sender is a library where they have not borrowed anything. |
70 |
|
71 |
Enabling this flag ensures that the issuing library is the sender of |
72 |
the digested message. It has no effect unless the borrower has |
73 |
chosen 'Digests only' on the advance messages. |
74 |
|
55 |
=back |
75 |
=back |
56 |
|
76 |
|
57 |
=cut |
77 |
=cut |
Lines 69-104
use Koha::Checkouts;
Link Here
|
69 |
use Koha::Libraries; |
89 |
use Koha::Libraries; |
70 |
use Koha::Patrons; |
90 |
use Koha::Patrons; |
71 |
|
91 |
|
72 |
my ( $help, $send_notices, $verbose, $confirm ); |
92 |
my ( $help, $send_notices, $verbose, $confirm, $digest, $digest_per_branch ); |
73 |
GetOptions( |
93 |
GetOptions( |
74 |
'h|help' => \$help, |
94 |
'h|help' => \$help, |
75 |
'send-notices' => \$send_notices, |
95 |
's|send-notices' => \$send_notices, |
76 |
'v|verbose' => \$verbose, |
96 |
'v|verbose' => \$verbose, |
77 |
'c|confirm' => \$confirm, |
97 |
'c|confirm' => \$confirm, |
|
|
98 |
'd|digest|' => \$digest, |
99 |
'b|digest-per-branch' => \$digest_per_branch, |
78 |
) || pod2usage(1); |
100 |
) || pod2usage(1); |
79 |
|
101 |
|
80 |
pod2usage(0) if $help; |
102 |
pod2usage(0) if $help; |
|
|
103 |
|
104 |
# Since advance notice options are not visible in the web-interface |
105 |
# unless EnhancedMessagingPreferences is on, let the user know that |
106 |
# this script probably isn't going to do much |
107 |
if ( ! C4::Context->preference('EnhancedMessagingPreferences') ) { |
108 |
warn <<'END_WARN'; |
109 |
|
110 |
The "EnhancedMessagingPreferences" syspref is off. |
111 |
Therefore, it is unlikely that this script will actually produce any messages to be sent. |
112 |
To change this, edit the "EnhancedMessagingPreferences" syspref. |
113 |
|
114 |
END_WARN |
115 |
} |
116 |
|
81 |
cronlogaction(); |
117 |
cronlogaction(); |
82 |
|
118 |
|
|
|
119 |
$verbose = 1 unless $verbose or $confirm; |
120 |
print "Test run only\n" unless $confirm; |
121 |
|
122 |
print "getting auto renewals\n" if $verbose; |
83 |
my $auto_renews = Koha::Checkouts->search({ auto_renew => 1, 'borrower.autorenew_checkouts' => 1 },{ join => 'borrower'}); |
123 |
my $auto_renews = Koha::Checkouts->search({ auto_renew => 1, 'borrower.autorenew_checkouts' => 1 },{ join => 'borrower'}); |
|
|
124 |
print "found " . $auto_renews->count . " auto renewals\n" if $verbose; |
84 |
|
125 |
|
|
|
126 |
my $renew_digest = {}; |
85 |
my %report; |
127 |
my %report; |
86 |
$verbose = 1 unless $verbose or $confirm; |
|
|
87 |
print "Test run only\n" unless $confirm; |
88 |
while ( my $auto_renew = $auto_renews->next ) { |
128 |
while ( my $auto_renew = $auto_renews->next ) { |
|
|
129 |
print "examining item '" . $auto_renew->itemnumber . "' to auto renew\n" if $verbose; |
130 |
|
131 |
my $borrower_preferences = C4::Members::Messaging::GetMessagingPreferences( { borrowernumber => $auto_renew->borrowernumber, |
132 |
message_name => 'auto_renewals' } ); |
133 |
|
134 |
next if !$digest && $borrower_preferences && $borrower_preferences->{'wants_digest'}; |
89 |
|
135 |
|
90 |
# CanBookBeRenewed returns 'auto_renew' when the renewal should be done by this script |
136 |
# CanBookBeRenewed returns 'auto_renew' when the renewal should be done by this script |
91 |
my ( $ok, $error ) = CanBookBeRenewed( $auto_renew->borrowernumber, $auto_renew->itemnumber, undef, 1 ); |
137 |
my ( $ok, $error ) = CanBookBeRenewed( $auto_renew->borrowernumber, $auto_renew->itemnumber, undef, 1 ); |
92 |
if ( $error eq 'auto_renew' ) { |
138 |
if ( $error eq 'auto_renew' ) { |
93 |
if ($verbose) { |
139 |
if ($verbose) { |
94 |
say sprintf "Issue id: %s for borrower: %s and item: %s ". ( $confirm ? 'will' : 'would') . " be renewed.", |
140 |
say sprintf "Issue id: %s for borrower: %s and item: %s %s be renewed.", |
95 |
$auto_renew->issue_id, $auto_renew->borrowernumber, $auto_renew->itemnumber; |
141 |
$auto_renew->issue_id, $auto_renew->borrowernumber, $auto_renew->itemnumber, $confirm ? 'will' : 'would'; |
96 |
} |
142 |
} |
97 |
if ($confirm){ |
143 |
if ($confirm){ |
98 |
my $date_due = AddRenewal( $auto_renew->borrowernumber, $auto_renew->itemnumber, $auto_renew->branchcode, undef, undef, undef, 0 ); |
144 |
my $date_due = AddRenewal( $auto_renew->borrowernumber, $auto_renew->itemnumber, $auto_renew->branchcode, undef, undef, undef, 0 ); |
99 |
$auto_renew->auto_renew_error(undef)->store; |
145 |
$auto_renew->auto_renew_error(undef)->store; |
100 |
} |
146 |
} |
101 |
push @{ $report{ $auto_renew->borrowernumber } }, $auto_renew; |
147 |
push @{ $report{ $auto_renew->borrowernumber } }, $auto_renew unless $borrower_preferences && (!$borrower_preferences->{transports} || !$borrower_preferences->{transports}->{email} || $borrower_preferences->{'wants_digest'}); |
102 |
} elsif ( $error eq 'too_many' |
148 |
} elsif ( $error eq 'too_many' |
103 |
or $error eq 'on_reserve' |
149 |
or $error eq 'on_reserve' |
104 |
or $error eq 'restriction' |
150 |
or $error eq 'restriction' |
Lines 110-127
while ( my $auto_renew = $auto_renews->next ) {
Link Here
|
110 |
or $error eq 'auto_too_soon' |
156 |
or $error eq 'auto_too_soon' |
111 |
or $error eq 'item_denied_renewal' ) { |
157 |
or $error eq 'item_denied_renewal' ) { |
112 |
if ( $verbose ) { |
158 |
if ( $verbose ) { |
113 |
say sprintf "Issue id: %s for borrower: %s and item: %s ". ( $confirm ? 'will' : 'would') . " not be renewed. (%s)", |
159 |
say sprintf "Issue id: %s for borrower: %s and item: %s %s not be renewed. (%s)", |
114 |
$auto_renew->issue_id, $auto_renew->borrowernumber, $auto_renew->itemnumber, $error; |
160 |
$auto_renew->issue_id, $auto_renew->borrowernumber, $auto_renew->itemnumber, $confirm ? 'will' : 'would', $error; |
115 |
} |
161 |
} |
116 |
if ( not $auto_renew->auto_renew_error or $error ne $auto_renew->auto_renew_error ) { |
162 |
if ( not $auto_renew->auto_renew_error or $error ne $auto_renew->auto_renew_error ) { |
117 |
$auto_renew->auto_renew_error($error)->store if $confirm; |
163 |
$auto_renew->auto_renew_error($error)->store if $confirm; |
118 |
push @{ $report{ $auto_renew->borrowernumber } }, $auto_renew |
164 |
push @{ $report{ $auto_renew->borrowernumber } }, $auto_renew |
119 |
if $error ne 'auto_too_soon'; # Do not notify if it's too soon |
165 |
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 |
120 |
} |
166 |
} |
121 |
} |
167 |
} |
|
|
168 |
|
169 |
if ( $borrower_preferences && $borrower_preferences->{transports} && $borrower_preferences->{transports}->{email} && $borrower_preferences->{'wants_digest'} ) { |
170 |
# cache this one to process after we've run through all of the items. |
171 |
if ($digest_per_branch) { |
172 |
$renew_digest->{ $auto_renew->branchcode }->{ $auto_renew->borrowernumber }->{success}++ if $error eq 'auto_renew'; |
173 |
$renew_digest->{ $auto_renew->branchcode }->{ $auto_renew->borrowernumber }->{error}++ unless $error eq 'auto_renew' || $error == 'auto_too_soon' ; |
174 |
} else { |
175 |
$renew_digest->{ $auto_renew->borrowernumber }->{success} ++ if $error eq 'auto_renew'; |
176 |
$renew_digest->{ $auto_renew->borrowernumber }->{error}++ unless $error eq 'auto_renew' || $error eq 'auto_too_soon' ; |
177 |
} |
178 |
} |
179 |
|
122 |
} |
180 |
} |
123 |
|
181 |
|
124 |
if ( $send_notices ) { |
182 |
if ( $send_notices && $confirm ) { |
125 |
for my $borrowernumber ( keys %report ) { |
183 |
for my $borrowernumber ( keys %report ) { |
126 |
my $patron = Koha::Patrons->find($borrowernumber); |
184 |
my $patron = Koha::Patrons->find($borrowernumber); |
127 |
for my $issue ( @{ $report{$borrowernumber} } ) { |
185 |
for my $issue ( @{ $report{$borrowernumber} } ) { |
Lines 147-153
if ( $send_notices ) {
Link Here
|
147 |
message_transport_type => 'email', |
205 |
message_transport_type => 'email', |
148 |
from_address => $admin_email_address, |
206 |
from_address => $admin_email_address, |
149 |
} |
207 |
} |
150 |
) if $confirm; |
208 |
); |
|
|
209 |
} |
210 |
} |
211 |
|
212 |
if ($digest_per_branch) { |
213 |
while (my ($branchcode, $digests) = each %$renew_digest) { |
214 |
send_digests({ |
215 |
digests => $digests, |
216 |
branchcode => $branchcode, |
217 |
letter_code => 'AUTO_RENEWALS_DGST', |
218 |
}); |
219 |
} |
220 |
} else { |
221 |
send_digests({ |
222 |
digests => $renew_digest, |
223 |
letter_code => 'AUTO_RENEWALS_DGST', |
224 |
}); |
225 |
} |
226 |
} |
227 |
|
228 |
=head1 METHODS |
229 |
|
230 |
=head2 send_digests |
231 |
|
232 |
send_digests({ |
233 |
digests => ..., |
234 |
letter_code => ..., |
235 |
}) |
236 |
|
237 |
Enqueue digested letters. |
238 |
|
239 |
Parameters: |
240 |
|
241 |
=over 4 |
242 |
|
243 |
=item C<$digests> |
244 |
|
245 |
Reference to the array of digested messages. |
246 |
|
247 |
=item C<$letter_code> |
248 |
|
249 |
String that denote the letter code. |
250 |
|
251 |
=back |
252 |
|
253 |
=cut |
254 |
|
255 |
sub send_digests { |
256 |
my $params = shift; |
257 |
|
258 |
my $admin_email_address = C4::Context->preference('KohaAdminEmailAddress'); |
259 |
|
260 |
PATRON: while ( my ( $borrowernumber, $digest ) = each %{$params->{digests}} ) { |
261 |
my $borrower_preferences = |
262 |
C4::Members::Messaging::GetMessagingPreferences( |
263 |
{ |
264 |
borrowernumber => $borrowernumber, |
265 |
message_name => 'auto_renewals' |
266 |
} |
267 |
); |
268 |
|
269 |
next PATRON unless $borrower_preferences; # how could this happen? |
270 |
|
271 |
my $patron = Koha::Patrons->find( $borrowernumber ); |
272 |
my $library = Koha::Libraries->find( $params->{branchcode} ); |
273 |
my $from_address = $library->{branchemail} || $admin_email_address; |
274 |
|
275 |
foreach my $transport ( keys %{ $borrower_preferences->{'transports'} } ) { |
276 |
my $letter = C4::Letters::GetPreparedLetter ( |
277 |
module => 'circulation', |
278 |
letter_code => $params->{letter_code}, |
279 |
branchcode => $params->{branchcode}, |
280 |
lang => $patron->lang, |
281 |
substitute => { |
282 |
error => $digest->{error}||0, |
283 |
success => $digest->{success}||0, |
284 |
}, |
285 |
tables => { |
286 |
borrowers => $patron->borrowernumber, |
287 |
}, |
288 |
message_transport_type => $transport, |
289 |
) || warn "no letter of type '$params->{letter_code}' found for borrowernumber $borrowernumber. Please see sample_notices.sql"; |
290 |
|
291 |
next unless $letter; |
292 |
|
293 |
C4::Letters::EnqueueLetter({ |
294 |
letter => $letter, |
295 |
borrowernumber => $borrowernumber, |
296 |
from_address => $from_address, |
297 |
message_transport_type => $transport |
298 |
}); |
151 |
} |
299 |
} |
152 |
} |
300 |
} |
153 |
} |
301 |
} |
154 |
- |
|
|