Bug 14585: Fixing up online help on main page
[koha.git] / misc / cronjobs / longoverdue.pl
blobb60ed236e2b04ffc40585c34e3fa39e7765656dc
1 #!/usr/bin/perl
2 #-----------------------------------
3 # Copyright 2008 LibLime
5 # This file is part of Koha.
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
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19 #-----------------------------------
21 =head1 NAME
23 longoverdue.pl cron script to set lost statuses on overdue materials.
24 Execute without options for help.
26 =cut
28 use strict;
29 use warnings;
30 BEGIN {
31 # find Koha's Perl modules
32 # test carefully before changing this
33 use FindBin;
34 eval { require "$FindBin::Bin/../kohalib.pl" };
36 use C4::Context;
37 use C4::Items;
38 use C4::Circulation qw/LostItem/;
39 use Getopt::Long;
41 my $lost; # key=lost value, value=num days.
42 my ($charge, $verbose, $confirm, $quiet);
43 my $endrange = 366;
44 my $mark_returned = 0;
46 GetOptions(
47 'lost=s%' => \$lost,
48 'c|charge=s' => \$charge,
49 'confirm' => \$confirm,
50 'verbose' => \$verbose,
51 'quiet' => \$quiet,
52 'maxdays=s' => \$endrange,
53 'mark-returned' => \$mark_returned,
56 my $usage = << 'ENDUSAGE';
57 longoverdue.pl : This cron script set lost values on overdue items and optionally sets charges the patron's account
58 for the item's replacement price. It is designed to be run as a nightly job. The command line options that globally
59 define this behavior for this script will likely be moved into Koha's core circulation / issuing rules code in a
60 near-term release, so this script is not intended to have a long lifetime.
62 This script takes the following parameters :
64 --lost | -l This option takes the form of n=lv,
65 where n is num days overdue, and lv is the lost value. See warning below.
67 --charge | -c This specifies what lost value triggers Koha to charge the account for the
68 lost item. Replacement costs are not charged if this is not specified.
70 --verbose | v verbose.
72 --confirm confirm. without this option, the script will report the number of affected items and
73 return without modifying any records.
75 --quiet suppress summary output.
77 --maxdays Specifies the end of the range of overdue days to deal with (defaults to 366). This
78 value is universal to all lost num days overdue passed.
80 --mark-returned When an item is marked lost, remove it from the borrowers issued items.
82 examples :
83 $PERL5LIB/misc/cronjobs/longoverdue.pl --lost 30=1
84 Would set LOST=1 after 30 days (up to one year), but not charge the account.
85 This would be suitable for the Koha default LOST authorized value of 1 -> 'Lost'.
87 $PERL5LIB/misc/cronjobs/longoverdue.pl --lost 60=2 --charge 2
88 Would set LOST=2 after 60 days (up to one year), and charge the account when setting LOST=2.
89 This would be suitable for the Koha default LOST authorized value of 2 -> 'Long Overdue'
91 WARNING: Flippant use of this script could set all or most of the items in your catalog to Lost and charge your
92 patrons for them!
94 WARNING: This script is known to be faulty. It is NOT recommended to use multiple --lost options.
95 See http://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=2883
97 ENDUSAGE
99 # FIXME: We need three pieces of data to operate:
100 # ~ lower bound (number of days),
101 # ~ upper bound (number of days),
102 # ~ new lost value.
103 # Right now we get only two, causing the endrange hack. This is a design-level failure.
104 # FIXME: do checks on --lost ranges to make sure they are exclusive.
105 # FIXME: do checks on --lost ranges to make sure the authorized values exist.
106 # FIXME: do checks on --lost ranges to make sure don't go past endrange.
107 # FIXME: convert to using pod2usage
108 # FIXME: allow --help or -h
110 if ( ! defined($lost) ) {
111 my $longoverdue_value = C4::Context->preference('DefaultLongOverdueLostValue');
112 my $longoverdue_days = C4::Context->preference('DefaultLongOverdueDays');
113 if(defined($longoverdue_value) and defined($longoverdue_days) and $longoverdue_value ne '' and $longoverdue_days ne '' and $longoverdue_days >= 0) {
114 $lost->{$longoverdue_days} = $longoverdue_value;
116 else {
117 print $usage;
118 die "ERROR: No --lost (-l) option defined";
121 if ( ! defined($charge) ) {
122 my $charge_value = C4::Context->preference('DefaultLongOverdueChargeValue');
123 if(defined($charge_value) and $charge_value ne '') {
124 $charge = $charge_value;
127 unless ($confirm) {
128 $verbose = 1; # If you're not running it for real, then the whole point is the print output.
129 print "### TEST MODE -- NO ACTIONS TAKEN ###\n";
132 # In my opinion, this line is safe SQL to have outside the API. --atz
133 our $bounds_sth = C4::Context->dbh->prepare("SELECT DATE_SUB(CURDATE(), INTERVAL ? DAY)");
135 sub bounds ($) {
136 $bounds_sth->execute(shift);
137 return $bounds_sth->fetchrow;
140 # FIXME - This sql should be inside the API.
141 sub longoverdue_sth {
142 my $query = "
143 SELECT items.itemnumber, borrowernumber, date_due
144 FROM issues, items
145 WHERE items.itemnumber = issues.itemnumber
146 AND DATE_SUB(CURDATE(), INTERVAL ? DAY) > date_due
147 AND DATE_SUB(CURDATE(), INTERVAL ? DAY) <= date_due
148 AND itemlost <> ?
149 ORDER BY date_due
151 return C4::Context->dbh->prepare($query);
154 #FIXME - Should add a 'system' user and get suitable userenv for it for logging, etc.
156 my $count;
157 # my @ranges = map {
158 my @report;
159 my $total = 0;
160 my $i = 0;
162 # FIXME - The item is only marked returned if you supply --charge .
163 # We need a better way to handle this.
165 my $sth_items = longoverdue_sth();
167 foreach my $startrange (sort keys %$lost) {
168 if( my $lostvalue = $lost->{$startrange} ) {
169 my ($date1) = bounds($startrange);
170 my ($date2) = bounds( $endrange);
171 # print "\nRange ", ++$i, "\nDue $startrange - $endrange days ago ($date2 to $date1), lost => $lostvalue\n" if($verbose);
172 $verbose and
173 printf "\nRange %s\nDue %3s - %3s days ago (%s to %s), lost => %s\n", ++$i,
174 $startrange, $endrange, $date2, $date1, $lostvalue;
175 $sth_items->execute($startrange, $endrange, $lostvalue);
176 $count=0;
177 while (my $row=$sth_items->fetchrow_hashref) {
178 printf ("Due %s: item %5s from borrower %5s to lost: %s\n", $row->{date_due}, $row->{itemnumber}, $row->{borrowernumber}, $lostvalue) if($verbose);
179 if($confirm) {
180 ModItem({ itemlost => $lostvalue }, $row->{'biblionumber'}, $row->{'itemnumber'});
181 LostItem($row->{'itemnumber'}, $mark_returned) if( $charge && $charge eq $lostvalue);
183 $count++;
185 push @report, {
186 startrange => $startrange,
187 endrange => $endrange,
188 range => "$startrange - $endrange",
189 date1 => $date1,
190 date2 => $date2,
191 lostvalue => $lostvalue,
192 count => $count,
194 $total += $count;
196 $endrange = $startrange;
199 sub summarize ($$) {
200 my $arg = shift; # ref to array
201 my $got_items = shift || 0; # print "count" line for items
202 my @report = @$arg or return undef;
203 my $i = 0;
204 for my $range (@report) {
205 printf "\nRange %s\nDue %3s - %3s days ago (%s to %s), lost => %s\n", ++$i,
206 map {$range->{$_}} qw(startrange endrange date2 date1 lostvalue);
207 $got_items and printf " %4s items\n", $range->{count};
211 if (!$quiet){
212 print "\n### LONGOVERDUE SUMMARY ###";
213 summarize (\@report, 1);
214 print "\nTOTAL: $total items\n";