Koha/misc/cronjobs/update_patrons_category.pl
Nick Clemens 19f2684d5a Bug 28503: Unit tests
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
2021-06-15 16:41:47 +02:00

295 lines
9.4 KiB
Perl
Executable file

#!/usr/bin/perl
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use Modern::Perl;
BEGIN {
# find Koha's Perl modules
# test carefully before changing this
use FindBin;
eval { require "$FindBin::Bin/../kohalib.pl" };
}
use C4::Context;
use Getopt::Long;
use Pod::Usage;
use Koha::Logger;
use Koha::Patrons;
use Koha::Patron::Categories;
use Koha::DateUtils;
use Koha::Script -cron;
=head1 NAME
update_patrons_category.pl - Given a set of parameters update selected patrons from one catgeory to another. Options are cumulative.
=head1 SYNOPSIS
update_patrons_category.pl -f=categorycode -t=categorycode
[-b=branchcode] [--too_old] [--too_young] [-fo=X] [-fu=X]
[-rb=date] [-ra=date] [-v]
[--field column=value ...]
update_patrons_category.pl --help | --man
Options:
--help brief help message
--man full documentation
-too_old update if over maximum age for current category
-too_young update if under minimuum age current category
-fo=X --fineover=X update if fines over X amount
-fu=X --fineunder=X update if fines under X amount
-rb=date --regbefore update if registration date is before given date
-ra=date --regafter update if registration date is after a given date
-d --field name=value where <name> is a column in the borrowers table, patrons will be updated if the field is equal to given <value>
--where <conditions> where clause to add to the query
-v -verbose verbose mode
-c --confirm commit changes to db, no action will be taken unless this switch is included
-b --branch <branchname> only deal with patrons from this library/branch
-f --from <categorycode> change patron category from this category
-t --to <categorycode> change patron category to this category
=head1 OPTIONS
=over 8
=item B<--help>
Print a brief help message and exits.
=item B<--man>
Prints the manual page and exits.
=item B<--verbose | -v>
Verbose. Without this flag set, only fatal errors are reported.
=item B<--confirm | -c>
Commit changes. Unless this flag set is, the script will report changes but not actually execute them on the database.
=item B<--branch | -b>
changes patrons for one specific branch. Use the value in the
branches.branchcode table.
=item B<--from | -f>
*required* defines the category to update. Expects the code from categories.categorycode.
=item B<--to | -t>
*required* defines the category patrons will be converted to. Expects the code from categories.categorycode.
=item B<--too_old>
Update patron only if they are above the maximum age range specified for the 'from' category.
=item B<--too_young>
Update patron only if they are below the minimum age range specified for the 'from' category.
=item B<--fineover=X | -fo=X>
Supply a number and only account with fines over this number will be updated.
=item B<--fineunder=X | -fu=X>
Supply a number and only account with fines under this number will be updated.
=item B<--regbefore=date | -rb=date>
Enter a date in ISO format YYYY-MM-DD and only patrons registered before this date wil be updated.
=item B<--regafter=date | -ra=date>
Enter a date in ISO format YYYY-MM-DD and only patrons registered after this date wil be updated.
=item B<--field column=value | -d column=value>
Use this flag to specify a column in the borrowers table and update only patrons whose value in that column equals the value supplied (repeatable)
A value of null will check for a field that is not set.
e.g.
--field dateexpiry=2016-01-01
will update all patrons who expired on that date, useful for schools etc.
=item B<--where $conditions>
Use this option to specify a condition built with columns from the borrowers table
e.g.
--where 'email IS NULL'
will update all patrons with no value for email
--where 'categorycode LIKE "%CHILD"'
will update all patrons with a category ending in CHILD.
--where 'categorycode LIKE RESIDENT%'
will update all patrons whose category does not begin with RESIDENT.
=back
=head1 DESCRIPTION
This script is designed to update patrons from one category to another.
=head1 USAGE EXAMPLES
C<update_patron_categories.pl> - Suggests that you read this help. :)
C<update_patron_categories.pl> -b=<branchcode> -f=<categorycode> -t=<categorycode> --confirm - Processes a single branch, and updates the patron categories from fromcat to tocat.
C<update_patron_categories.pl> -b=<branchcode> -f=<categorycode> -t=<categorycode> --too_old --confirm - Processes a single branch, and updates the patron categories from fromcat to tocat for patrons over the age range of fromcat.
C<update_patron_categories.pl> -f=<categorycode> -t=<categorycode> -v - Processes all branches, shows all messages, and reports the patrons who would be affected. Takes no action on the database.
=cut
# These variables are set by command line options.
# They are initially set to default values.
my $help = 0;
my $man = 0;
my $verbose = 0;
my $doit = 0;
my $ageunder;
my $ageover;
my $remove_guarantors = 0;
my $fine_min;
my $fine_max;
my $fromcat;
my $tocat;
my $reg_bef;
my $reg_aft;
my $branch_lim;
my %fields;
my @where;
GetOptions(
'help|?' => \$help,
'man' => \$man,
'v|verbose' => \$verbose,
'c|confirm' => \$doit,
'f|from=s' => \$fromcat,
't|to=s' => \$tocat,
'too_old' => \$ageover,
'too_young' => \$ageunder,
'fo|finesover=s' => \$fine_min,
'fu|finesunder=s' => \$fine_max,
'rb|regbefore=s' => \$reg_bef,
'ra|regafter=s' => \$reg_aft,
'b|branch=s' => \$branch_lim,
'd|field=s' => \%fields,
'where=s' => \@where,
);
pod2usage(1) if $help;
pod2usage( -verbose => 2 ) if $man;
if ( not $fromcat && $tocat ) { #make sure we've specified the info we need.
print "Must supply category from and to (-f & -t) please specify -help for usage tips.\n";
pod2usage(1);
exit;
}
( $verbose && !$doit ) and print "No actions will be taken (test mode)\n";
$verbose and print "Will update patrons from $fromcat to $tocat with conditions below (if any)\n";
my %params;
if ( $reg_bef || $reg_aft ) {
my $date_bef;
my $date_aft;
if ( defined $reg_bef ) {
eval { $date_bef = dt_from_string( $reg_bef, 'iso' ); };
}
die "$reg_bef is not a valid date before, aborting! Use a date in format YYYY-MM-DD.$@"
if $@;
if ( defined $reg_aft ) {
eval { $date_aft = dt_from_string( $reg_aft, 'iso' ); };
}
die "$reg_bef is not a valid date after, aborting! Use a date in format YYYY-MM-DD.$@"
if $@;
$params{dateenrolled}{'<='} = $reg_bef if defined $date_bef;
$params{dateenrolled}{'>='} = $reg_aft if defined $date_aft;
}
my $cat_from = Koha::Patron::Categories->find($fromcat);
my $cat_to = Koha::Patron::Categories->find($tocat);
die "Categories not found" unless $cat_from && $cat_to;
$params{"me.categorycode"} = $fromcat;
$params{"me.branchcode"} = $branch_lim if $branch_lim;
if ($verbose) {
print "Conditions:\n";
print " Registered before $reg_bef\n" if $reg_bef;
print " Registered after $reg_aft\n" if $reg_aft;
print " Total fines more than $fine_min\n" if $fine_min;
print " Total fines less than $fine_max\n" if $fine_max;
print " Age below minimum for " . $cat_from->description . "\n" if $ageunder;
print " Age above maximum for " . $cat_from->description . "\n" if $ageover;
if ( defined $branch_lim ) {
print " Branchcode of patron is $branch_lim\n";
}
}
while ( my ( $key, $value ) = each %fields ) {
$verbose and print " Borrower column $key is $value\n";
$value = undef if lc($value) eq 'null';
$params{ "me." . $key } = $value;
}
my $where_literal = join ' AND ', @where;
my $target_patrons = Koha::Patrons->search( \%params );
$target_patrons = $target_patrons->search( \$where_literal ) if @where;
$target_patrons = $target_patrons->search_patrons_to_update_category(
{
from => $fromcat,
search_params => \%params,
too_young => $ageunder,
too_old => $ageover,
fine_min => $fine_min,
fine_max => $fine_max,
}
);
my $patrons_found = $target_patrons->count;
my $actually_updated = 0;
my $testdisplay = $doit ? "" : "WOULD HAVE ";
if ($verbose) {
while ( my $target_patron = $target_patrons->next() ) {
$target_patron->discard_changes();
$verbose
and print $testdisplay
. "Updated "
. $target_patron->firstname() . " "
. $target_patron->surname()
. " from $fromcat to $tocat\n";
}
$target_patrons->reset;
}
if ($doit) {
$actually_updated = $target_patrons->update_category_to( { category => $tocat } );
}
$verbose and print "$patrons_found found, $actually_updated updated\n";