3 # This file is part of Koha.
5 # Copyright 2023 Koha development team
6 # Copyright 2015 Amit Gupta (amitddng135@gmail.com)
8 # Koha is free software; you can redistribute it and/or modify it
9 # under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
13 # Koha is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with Koha; if not, see <http://www.gnu.org/licenses>.
23 membership_expiry.pl - cron script to put membership expiry reminders into the message queue
27 ./membership_expiry.pl -c
31 0 1 * * * membership_expiry.pl -c
34 --help brief help message
35 --man full documentation
36 --where <conditions> where clause to add to the query
37 -v -verbose verbose mode
38 -n --nomail if supplied, messages will be output to STDOUT and no email or sms will be sent
39 -c --confirm commit changes to db, no action will be taken unless this switch is included
40 -b --branch <branchname> only deal with patrons from this library/branch
41 --before=X include patrons expiring a number of days BEFORE the date set by the preference
42 --after=X include patrons expiring a number of days AFTER the date set by the preference
43 -l --letter <lettercode> use a specific notice rather than the default
44 --active=X only send notices to active patrons (active within X months)
45 --inactive=X only send notices to inactive patrons (inactive within X months)
49 This script sends membership expiry reminder notices to patrons, by email and sms.
50 It queues them in the message queue, which is processed by
51 the process_message_queue.pl cronjob.
59 Print a brief help message and exits.
63 Prints the manual page and exits.
67 Verbose. Without this flag set, only fatal errors are reported.
71 Do not send any email. Membership expire notices that would have been sent to
72 the patrons are printed to standard out.
76 Confirm flag: Add this option. The script will only print a usage
81 Optional branchcode to restrict the cronjob to that branch.
85 Optional parameter to extend the selection with a number of days BEFORE
86 the date set by the preference.
90 Optional parameter to extend the selection with a number of days AFTER
91 the date set by the preference.
95 Use this option to specify a condition built with columns from the borrowers table
98 --where 'lastseen IS NOT NULL'
99 will only notify patrons who have been seen.
103 Optional parameter to use another notice than the default: MEMBERSHIP_EXPIRY
107 Optional parameter to include active patrons only (active within passed number of months).
111 Optional parameter to include inactive patrons only (inactive within passed number of months).
112 This allows you to skip active patrons when you renew them automatically (see bug 28688).
118 The content of the messages is configured in Tools -> Notices and slips. Use the MEMBERSHIP_EXPIRY notice or
119 supply another via the parameters.
121 Typically, messages are prepared for each patron when the memberships are going to expire.
123 These emails are staged in the outgoing message queue, as are messages
124 produced by other features of Koha. This message queue must be
125 processed regularly by the
126 F<misc/cronjobs/process_message_queue.pl> program.
128 In the event that the C<-n> flag is passed to this program, no emails
129 are sent. Instead, messages are sent on standard output from this
132 Notices can contain variables enclosed in double angle brackets like
133 E<lt>E<lt>thisE<gt>E<gt>. Those variables will be replaced with values
134 specific to the soon expiring members.
135 Available variables are:
139 =item E<lt>E<lt>borrowers.*E<gt>E<gt>
141 any field from the borrowers table
143 =item E<lt>E<lt>branches.*E<gt>E<gt>
145 any field from the branches table
152 use Getopt::Long qw( GetOptions );
153 use Pod::Usage qw( pod2usage );
155 use Koha::Script -cron;
158 use C4::Log qw( cronlogaction );
162 # These are defaults for command line options.
163 my $confirm; # -c: Confirm that the user has read and configured this script.
164 my $nomail; # -n: No mail. Will not send any emails.
165 my $verbose = 0; # -v: verbose
170 my ( $branch, $letter_type );
175 my $command_line_options = join(" ",@ARGV);
183 'branch:s' => \$branch,
184 'before:i' => \$before,
185 'after:i' => \$after,
186 'letter:s' => \$letter_type,
187 'where=s' => \@where,
188 'active:i' => \$active,
189 'inactive:i' => \$inactive,
192 pod2usage( -verbose => 2 ) if $man;
193 pod2usage(1) if $help || !$confirm;
194 if( defined($active) && defined($inactive) ) {
195 print "Sorry, it is not possible to pass both -active as well as -inactive.\n";
199 cronlogaction({ info => $command_line_options });
201 my $expdays = C4::Context->preference('MembershipExpiryDaysNotice');
203 #If the pref is not set, we will exit
204 warn 'Exiting membership_expiry.pl: MembershipExpiryDaysNotice not set'
209 warn 'getting upcoming membership expires' if $verbose;
210 my $upcoming_mem_expires = Koha::Patrons->search_upcoming_membership_expires(
212 ( $branch ? ( 'me.branchcode' => $branch ) : () ),
218 my $where_literal = join ' AND ', @where;
219 $upcoming_mem_expires = $upcoming_mem_expires->search( \$where_literal ) if @where;
221 warn 'found ' . $upcoming_mem_expires->count . ' soon expiring members'
225 $letter_type = 'MEMBERSHIP_EXPIRY' if !$letter_type;
226 my ( $count_active, $count_inactive, $count_enqueued ) = ( 0, 0, 0 );
227 while ( my $recent = $upcoming_mem_expires->next ) {
228 my $patron_active = $recent->is_active({ months => $active // $inactive }); # checked already that only one is defined
229 if( defined($active) && !$patron_active ) {
232 } elsif( defined($inactive) && $patron_active ) {
236 my $from_address = $recent->library->from_email_address;
237 my $letter = C4::Letters::GetPreparedLetter(
239 letter_code => $letter_type,
240 branchcode => $recent->branchcode,
241 lang => $recent->lang,
243 borrowers => $recent->borrowernumber,
244 branches => $recent->branchcode,
247 last if !$letter; # Letters.pm already warned, just exit
249 print $letter->{'content'}."\n";
253 C4::Letters::EnqueueLetter({
255 borrowernumber => $recent->borrowernumber,
256 from_address => $from_address,
257 message_transport_type => 'email',
261 if ($recent->smsalertnumber) {
262 my $smsletter = C4::Letters::GetPreparedLetter(
264 letter_code => $letter_type,
265 branchcode => $recent->branchcode,
266 lang => $recent->lang,
268 borrowers => $recent->borrowernumber,
269 branches => $recent->branchcode,
271 message_transport_type => 'sms',
274 C4::Letters::EnqueueLetter({
275 letter => $smsletter,
276 borrowernumber => $recent->borrowernumber,
277 message_transport_type => 'sms',
284 print "Enqueued notices for $count_enqueued patrons\n";
285 print "Skipped $count_active active patrons\n" if $count_active;
286 print "Skipped $count_inactive inactive patrons\n" if $count_inactive;
289 cronlogaction({ action => 'End', info => "COMPLETED" });