From 49ffa55a2e309679d6b08cb2b0a0229fa4ac0e3a Mon Sep 17 00:00:00 2001 From: Ryan Higgins Date: Sun, 10 Aug 2008 15:42:29 -0500 Subject: [PATCH] Update longoverdue.pl cron job to manage setting lost values. This patch deprecates the NoReturnSetLost system preference, which, as it turns out, was not implemented anyway. New longoverdue script allows one to specify on the commandline system-wide delays for changing items to different lost statuses, and optionally charge for the item. Signed-off-by: Joshua Ferraro --- C4/Accounts.pm | 51 ++++++- catalogue/updateitem.pl | 38 +----- .../data/mysql/en/mandatory/sysprefs.sql | 1 - .../unimarc_standard_systemprefs.sql | 1 - misc/cronjobs/longoverdue.pl | 128 +++++++++++++++--- 5 files changed, 158 insertions(+), 61 deletions(-) diff --git a/C4/Accounts.pm b/C4/Accounts.pm index 3a57154b69..34dcedee28 100644 --- a/C4/Accounts.pm +++ b/C4/Accounts.pm @@ -23,7 +23,7 @@ use C4::Context; use C4::Stats; use C4::Members; use C4::Items; -use C4::Circulation; +use C4::Circulation qw(MarkIssueReturned); use vars qw($VERSION @ISA @EXPORT); @@ -35,7 +35,7 @@ BEGIN { @EXPORT = qw( &recordpayment &makepayment &manualinvoice &getnextacctno &reconcileaccount &getcharges &getcredits - &getrefunds + &getrefunds &chargelostitem ); # removed &fixaccounts } @@ -262,7 +262,7 @@ EOT =cut -sub returnlost { +sub returnlost{ my ( $borrowernumber, $itemnum ) = @_; C4::Circulation::MarkIssueReturned( $borrowernumber, $itemnum ); my $borrower = C4::Members::GetMember( $borrowernumber, 'borrowernumber' ); @@ -272,6 +272,51 @@ sub returnlost { ModItem({ paidfor => "Paid for by $bor $date" }, undef, $itemnum); } + +sub chargelostitem{ +# http://wiki.koha.org/doku.php?id=en:development:kohastatuses +# lost ==1 Lost, lost==2 longoverdue, lost==3 lost and paid for +# FIXME: itemlost should be set to 3 after payment is made, should be a warning to the interface that +# a charge has been added +# FIXME : if no replacement price, borrower just doesn't get charged? + + my $dbh = C4::Context->dbh(); + my ($itemnumber) = @_; + my $sth=$dbh->prepare("SELECT * FROM issues, items WHERE issues.itemnumber=items.itemnumber and issues.itemnumber=?"); + $sth->execute($itemnumber); + my $issues=$sth->fetchrow_hashref(); + + # if a borrower lost the item, add a replacement cost to the their record + if ( $issues->{borrowernumber} ){ + + # first make sure the borrower hasn't already been charged for this item + my $sth1=$dbh->prepare("SELECT * from accountlines + WHERE borrowernumber=? AND itemnumber=? and accounttype='L'"); + $sth1->execute($issues->{'borrowernumber'},$itemnumber); + my $existing_charge_hashref=$sth1->fetchrow_hashref(); + + # OK, they haven't + unless ($existing_charge_hashref) { + # This item is on issue ... add replacement cost to the borrower's record and mark it returned + # Note that we add this to the account even if there's no replacement price, allowing some other + # process (or person) to update it, since we don't handle any defaults for replacement prices. + my $accountno = getnextacctno($issues->{'borrowernumber'}); + my $sth2=$dbh->prepare("INSERT INTO accountlines + (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding,itemnumber) + VALUES (?,?,now(),?,?,'L',?,?)"); + $sth2->execute($issues->{'borrowernumber'},$accountno,$issues->{'replacementprice'}, + "Lost Item $issues->{'title'} $issues->{'barcode'}", + $issues->{'replacementprice'},$itemnumber); + $sth2->finish; + # FIXME: Log this ? + } + #FIXME : Should probably have a way to distinguish this from an item that really was returned. + warn " $issues->{'borrowernumber'} / $itemnumber "; + C4::Circulation::MarkIssueReturned($issues->{borrowernumber},$itemnumber); + } + $sth->finish; +} + =head2 manualinvoice &manualinvoice($borrowernumber, $itemnumber, $description, $type, diff --git a/catalogue/updateitem.pl b/catalogue/updateitem.pl index 26a99fef28..7b0b673727 100755 --- a/catalogue/updateitem.pl +++ b/catalogue/updateitem.pl @@ -74,42 +74,6 @@ if (defined $itemnotes) { # i.e., itemnotes parameter passed from form ModItem($item_changes, $biblionumber, $itemnumber); -# check issues iff itemlost. -# http://wiki.koha.org/doku.php?id=en:development:kohastatuses -# lost ==1 Lost, lost==2 longoverdue, lost==3 lost and paid for -# FIXME: itemlost should be set to 3 after payment is made, should be a warning to the interface that -# a charge has been added -# FIXME : if no replacement price, borrower just doesn't get charged? -if ($itemlost==1) { - my $sth=$dbh->prepare("SELECT * FROM issues WHERE itemnumber=?"); - $sth->execute($itemnumber); - my $issues=$sth->fetchrow_hashref(); - - # if a borrower lost the item, add a replacement cost to the their record - if ( ($issues->{borrowernumber}) && ($itemlost==1) ){ - - # first make sure the borrower hasn't already been charged for this item - my $sth1=$dbh->prepare("SELECT * from accountlines - WHERE borrowernumber=? AND itemnumber=?"); - $sth1->execute($issues->{'borrowernumber'},$itemnumber); - my $existing_charge_hashref=$sth1->fetchrow_hashref(); - - # OK, they haven't - unless ($existing_charge_hashref) { - # This item is on issue ... add replacement cost to the borrower's record and mark it returned - my $accountno = getnextacctno($issues->{'borrowernumber'}); - my $sth2=$dbh->prepare("INSERT INTO accountlines - (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding,itemnumber) - VALUES - (?,?,now(),?,?,'L',?,?)"); - $sth2->execute($issues->{'borrowernumber'},$accountno,$item_data_hashref->{'replacementprice'}, - "Lost Item $item_data_hashref->{'title'} $item_data_hashref->{'barcode'}", - $item_data_hashref->{'replacementprice'},$itemnumber); - $sth2->finish; - # FIXME: Log this ? - } - } - $sth->finish; -} +C4::Accounts::chargelostitem($itemnumber) if ($itemlost==1) ; print $cgi->redirect("moredetail.pl?biblionumber=$biblionumber&itemnumber=$itemnumber#item$itemnumber"); diff --git a/installer/data/mysql/en/mandatory/sysprefs.sql b/installer/data/mysql/en/mandatory/sysprefs.sql index 30ae54535b..00f8254eaa 100755 --- a/installer/data/mysql/en/mandatory/sysprefs.sql +++ b/installer/data/mysql/en/mandatory/sysprefs.sql @@ -58,7 +58,6 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('memberofinstitution',0,'If ON, patrons can be linked to institutions',NULL,'YesNo'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('MIME','EXCEL','Define the default application for exporting report data','EXCEL|OPENOFFICE.ORG','Choice'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('noissuescharge',5,'Define maximum amount withstanding before check outs are blocked','','Integer'); -INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('NoReturnSetLost',99,'(if you have fines only) After this limit a non returned item is automatically marked as lost, and the itemprice is charged to the patron','','Integer'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('NotifyBorrowerDeparture',30,'Define number of days before expiry where circulation is warned about patron account expiry',NULL,'Integer'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('OpacAuthorities',1,'If ON, enables the search authorities link on OPAC',NULL,'YesNo'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('opacbookbag',1,'If ON, enables display of Cart feature','','YesNo'); diff --git a/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql b/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql index 59d9930e3f..d0749560e0 100755 --- a/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql +++ b/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql @@ -59,7 +59,6 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('memberofinstitution', '0', 'Vos adhérents sont ils membres d''une institution ?', NULL, 'YesNo'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('MIME', 'OPENOFFICE.ORG', 'Ce paramètre définit l''application par défaut à ouvrir lorsqu''on télécharge un fichier (OpenOffice.org ou MS-Excel habituellement)', 'EXCEL|OPENOFFICE.ORG', 'Choice'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('noissuescharge', '5', 'Ce paramètre définit le montant maximal des dettes au delà duquel le lecteur ne peut plus emprunter', '', 'Integer'); -INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('NoReturnSetLost','99','(uniquement si vous avez des amendes) Après cette limite, un document non retourné est automatiquement marqué perdu, et le cout du document est imputé à l''adhérent ','','Integer'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('NotifyBorrowerDeparture', '0', 'Ce paramètre permet d''être prévenu N jours avant l''expiration de la carte d''un adhérent, à la banque de prêt.', '', 'Integer'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('DebugLevel', '2', 'Définit le niveau d''affichage des erreurs en cas de problème : 0= aucun affichage, 1= un peu, 2=tout (peut être risqué pour la sécurité)', '0|1|2', 'Choice'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('NoZebra','1','If ON, Zebra indexing is turned off, simpler setup, but slower searches','','YesNo'); diff --git a/misc/cronjobs/longoverdue.pl b/misc/cronjobs/longoverdue.pl index 56b834faf3..13c0e90c80 100755 --- a/misc/cronjobs/longoverdue.pl +++ b/misc/cronjobs/longoverdue.pl @@ -1,17 +1,30 @@ #!/usr/bin/perl -w #----------------------------------- -# Script Name: longoverdue.pl -# Script Version: 1.0.0 -# Date: 2004/04/01 -# Author: Stephen Hedges shedges@skemotah.com -# Description: set itemlost status to '2' -# ("long overdue") on items more than 90 -# days overdue. -# Usage: longoverdue.pl. -# Revision History: -# 1.0.0 2004/04/01: original version +# Copyright 2008 LibLime +# +# 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA #----------------------------------- +=head1 NAME + +longoverdue.pl cron script to set lost statuses on overdue materials. + Execute without options for help. + +=cut + use strict; BEGIN { # find Koha's Perl modules @@ -21,20 +34,97 @@ BEGIN { } use C4::Context; use C4::Items; +use C4::Accounts; +use Getopt::Long; + +my $lost; # key=lost value, value=num days. +my ($charge, $verbose, $confirm); + +GetOptions( + 'l|lost=s%' => \$lost, + 'c|charge=s' => \$charge, + 'confirm' => \$confirm, + 'v|verbose' => \$verbose, + ); +my $usage = << 'ENDUSAGE'; +longoverdue.pl : This cron script set lost values on overdue items and optionally sets charges the patron's account +for the item's replacement price. It is designed to be run as a nightly job. The command line options that globally +define this behavior for this script will likely be moved into Koha's core circulation / issuing rules code in a +near-term release, so this script is not intended to have a long lifetime. -my $dbh = C4::Context->dbh; +This script takes the following parameters : -my $itemnos_sth=$dbh->prepare("SELECT items.itemnumber FROM issues,items WHERE items.itemnumber=issues.itemnumber AND DATE_SUB(CURDATE(),INTERVAL 90 DAY) > date_due AND (itemlost=0 OR itemlost IS NULL)"); + --lost | -l This option may be used multiple times, and takes the form of n=lv , + where n is num days overdue, and lv is the lost value. -# get itemnumbers of items more than 90 days overdue -$itemnos_sth->execute(); + --charge | -c This specifies what lost value triggers Koha to charge the account for the + lost item. Replacement costs are not charged if this is not specified. -while (my $row=$itemnos_sth->fetchrow_arrayref) { - my $itemnumber=$row->[0]; + --verbose | v verbose. - ModItem({ itemlost => 2 }, undef, $itemnumber); -# print "$item\n"; + --confirm confirm. without -c, this script will report the number of affected items and + return without modifying any records. + + example : $PERL5LIB/misc/cronjobs/longoverdue.pl --lost 30=2 --lost 60=1 --charge 1 + would set LOST= 1 after 30 days, LOST= 2 after 60 days, and charge the account when setting LOST= 2 (i.e., 60 days). + This would be suitable for the Koha default LOST authorized values of 1 -> 'Lost' and 2 -> 'Long Overdue' + +WARNING: Flippant use of this script could set all or most of the items in your catalog to Lost and charge your +patrons for them! + +ENDUSAGE + +if ( ! defined($lost) ) { + print $usage; + die; } -$itemnos_sth->finish; +my $dbh = C4::Context->dbh(); + +#FIXME - Should add a 'system' user and get suitable userenv for it for logging, etc. + +my $endrange = 366; # hardcoded - don't deal with anything overdue by more than this num days. + +my @interval = sort keys %$lost; + +my $count; +my @report; + +# FIXME - The item is only marked returned if you supply --charge . +# We need a better way to handle this. +# +# FIXME - no sql should be outside the API. + +my $query = "SELECT items.itemnumber,borrowernumber FROM issues,items WHERE items.itemnumber=issues.itemnumber AND + DATE_SUB( CURDATE(), INTERVAL ? DAY) > date_due AND DATE_SUB( CURDATE(), INTERVAL ? DAY ) <= date_due AND itemlost <> ? "; +my $sth_items = $dbh->prepare($query); +while ( my $startrange = shift @interval ) { + if( my $lostvalue = $lost->{$startrange} ) { + #warn "query: $query \\with\\ params: $startrange,$endrange, $lostvalue "if($verbose); + warn "starting range: $startrange - $endrange with lost value $lostvalue" if($verbose); + $sth_items->execute( $startrange,$endrange, $lostvalue ); + $count=0; + while (my $row=$sth_items->fetchrow_hashref) { + warn "updating $row->{'itemnumber'} for borrower $row->{'borrowernumber'} to lost: $lostvalue" if($verbose); + if($confirm) { + ModItem({ itemlost => $lostvalue }, $row->{'biblionumber'}, $row->{'itemnumber'}); + chargelostitem($row->{'itemnumber'}) if( $charge && $charge eq $lostvalue); + } + $count++; + } + push @report, { range => "$startrange - $endrange", + lostvalue => $lostvalue, + count => $count, + }; + } + $endrange = $startrange; +} +for my $range (@report) { + for my $var (keys %$range) { + warn "$var : $range->{$var}"; + } +} + + +$sth_items->finish; $dbh->disconnect; -- 2.39.5