From f2b6fc39d646019394a971ad19034f2d5861fa5e Mon Sep 17 00:00:00 2001 From: Aleisha Amohia Date: Fri, 8 Oct 2021 16:09:11 +1300 Subject: [PATCH] Bug 31415: Script to automate converting reserves to recalls This patch adds a script which can be used to automatically convert the oldest reserve on a record to a recall, if there are a specified minimum number of reserves on the record. To test: 1) Enable UseRecalls and configure circulation rules relevant to recalls. Keep the 'on shelf recalls allowed' setting to 'any' for the sake of testing ('all' would require all items to be checked out for the reserve to be converted to a recall) 2) Check out items from multiple records (at least 2 different records) to Patron A. 3) Place multiple reserves on each record (at least 2 reserves). 4) Place multiple reserves on another record which has no items checked out. 5) We now have multiple records where the oldest reserve is eligible for recall, plus a record where the oldest reserve is NOT eligible for recall (because no items are checked out). 6) In your terminal, get into the shell and run the script. -v means verbose and will print the reserves that are converted into recalls. --min 1 means there must be more than 1 reserve on the record to be considered. sudo koha-shell INSTANCE perl misc/cronjobs/recalls/convert_reserves_to_recalls.pl -v --min 1 7) Confirm that, for the records where items are checked out and there are multiple reserves, the oldest reserve was converted into a recall 8) Confirm that, for the record where no items are checked out, the reserves all remain and not converted into a recall. 9) Confirm documentation for the script looks good perldoc misc/cronjobs/recalls/convert_reserves_to_recalls.pl Sponsored-by: Auckland University of Technology --- .../recalls/convert_reserves_to_recalls.pl | 135 +++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100755 misc/cronjobs/recalls/convert_reserves_to_recalls.pl diff --git a/misc/cronjobs/recalls/convert_reserves_to_recalls.pl b/misc/cronjobs/recalls/convert_reserves_to_recalls.pl new file mode 100755 index 0000000000..e47ffff821 --- /dev/null +++ b/misc/cronjobs/recalls/convert_reserves_to_recalls.pl @@ -0,0 +1,135 @@ +#!/usr/bin/perl + +# Copyright 2021 Aleisha Amohia +# +# 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 . + +use Modern::Perl; +use Getopt::Long; + +BEGIN { + # find Koha's Perl modules + # test carefully before changing this + use FindBin; + eval { require "$FindBin::Bin/../kohalib.pl" }; +} + +use Koha::Script -cron; +use Koha::DateUtils qw( dt_from_string ); +use Koha::Recalls; +use C4::Log; + +cronlogaction(); + +=head1 NAME + +convert_reserves_to_recalls.pl + +=head1 SYNOPSIS + + convert_reserves_to_recalls.pl [-v] [--min X] + +This script converts reserves to recalls when a record has a set minimum number of reserves placed. + +If a record is found to have the specified minimum number of reserves, the script will find the oldest reserve and convert it to a recall, as long as it would be a legal recall. + +It will only convert the single oldest reserve. Once converted, the script will move on to the next record, it will not continue to convert reserves on this record. + + Options: + -v verbose + --min X minimum number of reserves + +=head1 OPTIONS + +=over 8 + +=item B<-v> | B<--verbose> + +Verbose. Without this flag set, only fatal errors are reported. + +=item B<-m> | B<--min> + +The minimum number of reserves that may exist on a record for it to be selected for conversion + +=back + +=cut + +my $min = 5; +my $verbose; + +GetOptions( + 'min|m=i' => \$min, + 'verbose|v' => \$verbose +) or pod2usage(1); + +# get reserves where there is more than $min reserves on one biblio +my @bib_reserves = Koha::Holds->search({}, { + select => [ + 'biblionumber', + { count => 'biblionumber', -as => 'bibcount' } + ], + group_by => 'biblionumber', + having => { 'bibcount' => { '>=', $min } }, +})->as_list; + +my $count = 0; +foreach my $bib ( @bib_reserves ) { + $bib = $bib->unblessed; + if ( $bib->{bibcount} >= $min ) { + # If there are $min or more holds on the same record, convert the oldest hold to a recall + + my @reserves = Koha::Holds->search({ biblionumber => $bib->{biblionumber} }, { order_by => { -asc => 'reservedate' } })->as_list; + my $reserve_to_convert = $reserves[0]; + foreach my $res ( @reserves ) { + if ( dt_from_string($res->reservedate) < dt_from_string($reserve_to_convert->reservedate) ) { + $reserve_to_convert = $res; + } + } + + my $patron = Koha::Patrons->find( $reserve_to_convert->borrowernumber ); + my $biblio = Koha::Biblios->find( $reserve_to_convert->biblionumber ); + my $item; + my $can_convert; + if ( $reserve_to_convert->item_level_hold ) { + $item = Koha::Items->find( $reserve_to_convert->itemnumber ); + if ( $item->can_be_recalled({ patron => $patron, hold_convert => 1 }) ) { + $can_convert = 1; + } + } else { + if ( $biblio->can_be_recalled({ patron => $patron, hold_convert => 1 }) ) { + $can_convert = 1; + } + } + if ( $can_convert ) { + my ( $recall, $due_interval, $due_date ) = Koha::Recalls->add_recall({ + patron => $patron, + biblio => $biblio, + branchcode => $reserve_to_convert->branchcode, + item => $item, + expirationdate => $reserve_to_convert->expirationdate, + interface => 'commandline', + }); + $reserve_to_convert->cancel({ cancellation_reason => 'RECALLED' }); + $count++; + if ( $verbose ) { + my $reserve_id = $reserve_to_convert->reserve_id; + my $biblionumber = $reserve_to_convert->biblionumber; + print "$count. Hold converted to recall (reserve_id: $reserve_id, biblionumber: $biblionumber).\n"; + } + } + } +} -- 2.11.0