/
longoverdue.pl
executable file
·225 lines (191 loc) · 7.54 KB
/
longoverdue.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#!/usr/bin/env perl
#-----------------------------------
# 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;
use warnings;
BEGIN {
# find Koha's Perl modules
# test carefully before changing this
use FindBin;
eval { require "$FindBin::Bin/../kohalib.pl" };
}
use Koha;
use C4::Context;
use C4::Items;
use C4::LostItems;
use C4::Accounts;
use C4::Circulation;
use Getopt::Long;
my ($lost_start, $longodue_start, $confirm, $debug, $verbose);
my $endrange = 366; # FIXME hardcoded - don't deal with anything overdue by more than this num days.
GetOptions(
'lost=i' => \$lost_start,
'longoverdue=i' => \$longodue_start,
'confirm' => \$confirm,
'verbose' => \$verbose,
'debug' => \$debug,
);
my $usage = << 'ENDUSAGE';
longoverdue.pl : This cron script sets lost values on overdue items, charging the patron's account
for the item's replacement price for the value 'lost'. It is designed to be run as a nightly job.
The command line options exist primarily for testing purposes.
Generally, parameters should be taken from the OverdueRules syspref.
This script takes the following parameters :
--lost integer, num days overdue to set to 'lost' and charge patron.
--longoverdue integer, num days overdue to set to 'longoverdue'. Patron is not charged.
--verbose | v verbose. (or use --debug for more)
--confirm confirm. without this option, the script will report the number of affected items and
return without modifying any records.
examples :
$PERL5LIB/misc/cronjobs/longoverdue.pl --lost 30
Would set LOST='lost' after 30 days (up to one year). The account will be charged.
$PERL5LIB/misc/cronjobs/longoverdue.pl --longoverdue 20 --lost 40
Would set the item to longoverdue after 20 days, and lost after 40 days.
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
# FIXME: We need three pieces of data to operate:
# ~ lower bound (number of days),
# ~ upper bound (number of days),
# ~ new lost value.
# Right now we get only two, causing the endrange hack. This is a design-level failure.
# FIXME: do checks on --lost ranges to make sure they are exclusive.
# FIXME: do checks on --lost ranges to make sure the authorized values exist.
# FIXME: do checks on --lost ranges to make sure don't go past endrange.
# FIXME: convert to using pod2usage
# FIXME: allow --help or -h
#
$verbose = 1 if($debug);
if(!defined $longodue_start){
if(C4::Context->preference("OverdueRules") =~ /longoverdue:(\d+)/){
$longodue_start = $1;
}
}
if(!defined $lost_start){
if(C4::Context->preference("OverdueRules") =~ /lost:(\d+)/){
$lost_start = $1;
}
}
if( $longodue_start && $longodue_start > $lost_start){
print "Invalid overdue rules.\n" if $verbose;
exit 1;
}
if( ! $lost_start && ! $longodue_start ){
print "No lost settings specified.\n" if $verbose;
exit;
}
unless ($confirm) {
$verbose = 1; # If you're not running it for real, then the whole point is the print output.
print "### TEST MODE -- NO ACTIONS TAKEN ###\n";
}
# In my opinion, this line is safe SQL to have outside the API. --atz
our $bounds_sth = C4::Context->dbh->prepare("SELECT DATE_SUB(CURDATE(), INTERVAL ? DAY)");
sub bounds ($) {
$bounds_sth->execute(shift);
return $bounds_sth->fetchrow;
}
# FIXME - This sql should be inside the API.
sub longoverdue_sth {
my $query = "
SELECT issues.*,items.barcode,items.holdingbranch,items.homebranch,items.itemlost
FROM issues, items
WHERE items.itemnumber = issues.itemnumber
AND issues.date_due >= ?
AND issues.date_due < ?
AND ( itemlost IS NULL OR itemlost <> ? )
ORDER BY issues.date_due
";
return C4::Context->dbh->prepare($query);
}
#FIXME - Should add a 'system' user and get suitable userenv for it for logging, etc.
my $count;
my @report;
my $total = 0;
my $i = 0;
my $sth_items = longoverdue_sth();
if($longodue_start){
my $longodue_end = $lost_start || $endrange;
my ($startdate) = bounds($longodue_end); # yes, range is backwards from date.
my ($enddate) = bounds($longodue_start);
$verbose and printf "\nlongoverdue:\nDue %d - %d days ago (%s to %s), itemlost => longoverdue\n",
$longodue_start, $longodue_end, $startdate, $enddate;
$sth_items->execute($startdate, $enddate, 'longoverdue');
$count=0;
while (my $row=$sth_items->fetchrow_hashref) {
printf ("Due %s: item %d from borrower %d to lost: %s\n", $row->{date_due}, $row->{itemnumber}, $row->{borrowernumber}, 'longoverdue') if($debug);
ModItemLost($row->{'biblionumber'}, $row->{'itemnumber'}, 'longoverdue') if $confirm;
$count++;
}
push @report, {
startrange => $longodue_end,
endrange => $longodue_start,
range => "$longodue_start - $longodue_end",
date1 => $startdate,
date2 => $enddate,
lostvalue => 'longoverdue',
count => $count,
};
$total += $count;
};
if($lost_start){
my ($startdate) = bounds($endrange);
my ($enddate) = bounds($lost_start);
$verbose and
printf "\nlost:\nDue %d - %d days ago (%s to %s), itemlost => lost\n",
$lost_start, $endrange, $startdate, $enddate;
$sth_items->execute($startdate, $enddate, 'lost');
$count=0;
while (my $row=$sth_items->fetchrow_hashref) {
printf ("Due %s: item %d from borrower %d to lost: %s\n", $row->{date_due}, $row->{itemnumber}, $row->{borrowernumber}, 'lost') if($debug);
if ($confirm){
my $lost_id = C4::LostItems::CreateLostItem($row->{'itemnumber'}, $row->{'borrowernumber'});
C4::Accounts::chargelostitem($lost_id);
ModItemLost($row->{'biblionumber'}, $row->{'itemnumber'}, 'lost');
}
$count++;
}
push @report, {
startrange => $endrange,
endrange => $lost_start,
range => "$lost_start - $endrange",
date1 => $startdate,
date2 => $enddate,
lostvalue => 'lost',
count => $count,
};
$total += $count;
}
sub summarize ($$) {
my $arg = shift; # ref to array
my $got_items = shift || 0; # print "count" line for items
my @report = @$arg or return undef;
my $i = 0;
for my $range (@report) {
printf "\nDue %3s - %3s days ago (%s to %s), itemlost => %s\n",
map {$range->{$_}} qw(startrange endrange date1 date2 lostvalue);
$got_items and printf " %4s items\n", $range->{count};
}
}
print "\n### LONGOVERDUE SUMMARY ###";
summarize (\@report, 1);
print "\nTOTAL: $total items\n";