Bug 19204: Make the debarment date calculation depends on finesCalendar
[koha.git] / circ / pendingreserves.pl
blob5e6418b22c1ec00d5e4e7fd0fcfe09ce91e81815
1 #!/usr/bin/perl
3 # Copyright 2000-2002 Katipo Communications
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>.
20 use Modern::Perl;
22 use constant PULL_INTERVAL => 2;
24 use C4::Context;
25 use C4::Output;
26 use CGI qw ( -utf8 );
27 use C4::Auth;
28 use C4::Debug;
29 use C4::Items qw( ModItem ModItemTransfer );
30 use C4::Reserves qw( ModReserveCancelAll );
31 use Koha::Biblios;
32 use Koha::DateUtils;
33 use Koha::Holds;
34 use DateTime::Duration;
36 my $input = new CGI;
37 my $startdate = $input->param('from');
38 my $enddate = $input->param('to');
39 my $theme = $input->param('theme'); # only used if allowthemeoverride is set
40 my $op = $input->param('op') || '';
41 my $borrowernumber = $input->param('borrowernumber');
42 my $reserve_id = $input->param('reserve_id');
44 my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
46 template_name => "circ/pendingreserves.tt",
47 query => $input,
48 type => "intranet",
49 authnotrequired => 0,
50 flagsrequired => { circulate => "circulate_remaining_permissions" },
51 debug => 1,
55 my @messages;
56 if ( $op eq 'cancel_reserve' and $reserve_id ) {
57 my $hold = Koha::Holds->find( $reserve_id );
58 if ( $hold ) {
59 $hold->cancel;
60 push @messages, { type => 'message', code => 'hold_cancelled' };
62 } elsif ( $op =~ m|^mark_as_lost| ) {
63 my $hold = Koha::Holds->find( $reserve_id );
64 die "wrong reserve_id" unless $hold; # This is a bit rude, but we are not supposed to get a wrong reserve_id
65 my $item = $hold->item;
66 if ( $item and C4::Context->preference('CanMarkHoldsToPullAsLost') =~ m|^allow| ) {
67 my $patron = $hold->borrower;
68 C4::Circulation::LostItem( $item->itemnumber, "pendingreserves" );
69 if ( $op eq 'mark_as_lost_and_notify' and C4::Context->preference('CanMarkHoldsToPullAsLost') eq 'allow_and_notify' ) {
70 my $library = $hold->branch;
71 my $letter = C4::Letters::GetPreparedLetter(
72 module => 'reserves',
73 letter_code => 'CANCEL_HOLD_ON_LOST',
74 branchcode => $patron->homebranch,
75 lang => $patron->lang,
76 tables => {
77 branches => $library->branchcode,
78 borrowers => $patron->borrowernumber,
79 items => $item->itemnumber,
80 biblio => $hold->biblionumber,
81 biblioitems => $hold->biblionumber,
82 reserves => $hold->unblessed,
85 if ( $letter ) {
86 my $admin_email_address = $library->branchemail || C4::Context->preference('KohaAdminEmailAddress');
88 C4::Letters::EnqueueLetter(
89 { letter => $letter,
90 borrowernumber => $patron->borrowernumber,
91 message_transport_type => 'email',
92 from_address => $admin_email_address,
95 unless ( $patron->notice_email_address ) {
96 push @messages, {type => 'alert', code => 'no_email_address', };
98 push @messages, { type => 'message', code => 'letter_enqueued' };
99 } else {
100 push @messages, { type => 'error', code => 'no_template_notice' };
103 $hold->cancel;
104 if ( $item->homebranch ne $item->holdingbranch ) {
105 C4::Items::ModItemTransfer( $item->itemnumber, $item->holdingbranch, $item->homebranch );
108 if ( my $yaml = C4::Context->preference('UpdateItemWhenLostFromHoldList') ) {
109 $yaml = "$yaml\n\n"; # YAML is anal on ending \n. Surplus does not hurt
110 my $assignments;
111 eval { $assignments = YAML::Load($yaml); };
112 if ($@) {
113 warn "Unable to parse UpdateItemWhenLostFromHoldList syspref : $@" if $@;
115 else {
116 eval {
117 C4::Items::ModItem( $assignments, undef, $item->itemnumber );
119 warn "Unable to modify item itemnumber=" . $item->itemnumber . ": $@" if $@;
123 } elsif ( not $item ) {
124 push @messages, { type => 'alert', code => 'hold_placed_at_biblio_level'};
125 } # else the url parameters have been modified and the user is not allowed to continue
129 my $today = dt_from_string;
131 if ( $startdate ) {
132 $startdate =~ s/^\s+//;
133 $startdate =~ s/\s+$//;
134 $startdate = eval{dt_from_string( $startdate )};
136 unless ( $startdate ){
137 # changed from delivered range of 10 years-yesterday to 2 days ago-today
138 # Find two days ago for the default shelf pull start date, unless HoldsToPullStartDate sys pref is set.
139 $startdate = $today - DateTime::Duration->new( days => C4::Context->preference('HoldsToPullStartDate') || PULL_INTERVAL );
142 if ( $enddate ) {
143 $enddate =~ s/^\s+//;
144 $enddate =~ s/\s+$//;
145 $enddate = eval{dt_from_string( $enddate )};
147 unless ( $enddate ) {
148 #similarly: calculate end date with ConfirmFutureHolds (days)
149 $enddate = $today + DateTime::Duration->new( days => C4::Context->preference('ConfirmFutureHolds') || 0 );
152 my @reservedata;
153 my $dbh = C4::Context->dbh;
154 my $sqldatewhere = "";
155 my $startdate_iso = output_pref({ dt => $startdate, dateformat => 'iso', dateonly => 1 });
156 my $enddate_iso = output_pref({ dt => $enddate, dateformat => 'iso', dateonly => 1 });
158 $debug and warn $startdate_iso. "\n" . $enddate_iso;
160 my @query_params = ();
162 if ($startdate_iso) {
163 $sqldatewhere .= " AND reservedate >= ?";
164 push @query_params, $startdate_iso;
166 if ($enddate_iso) {
167 $sqldatewhere .= " AND reservedate <= ?";
168 push @query_params, $enddate_iso;
171 my $strsth =
172 "SELECT min(reservedate) as l_reservedate,
173 reserves.reserve_id,
174 reserves.borrowernumber as borrowernumber,
176 GROUP_CONCAT(DISTINCT items.holdingbranch
177 ORDER BY items.itemnumber SEPARATOR '|') l_holdingbranch,
178 reserves.biblionumber,
179 reserves.branchcode as l_branch,
180 reserves.itemnumber,
181 items.holdingbranch,
182 items.homebranch,
183 GROUP_CONCAT(DISTINCT items.itype
184 ORDER BY items.itemnumber SEPARATOR '|') l_itype,
185 GROUP_CONCAT(DISTINCT items.location
186 ORDER BY items.itemnumber SEPARATOR '|') l_location,
187 GROUP_CONCAT(DISTINCT items.itemcallnumber
188 ORDER BY items.itemnumber SEPARATOR '<br/>') l_itemcallnumber,
189 GROUP_CONCAT(DISTINCT items.enumchron
190 ORDER BY items.itemnumber SEPARATOR '<br/>') l_enumchron,
191 GROUP_CONCAT(DISTINCT items.copynumber
192 ORDER BY items.itemnumber SEPARATOR '<br/>') l_copynumber,
193 biblio.title,
194 biblio.author,
195 count(DISTINCT items.itemnumber) as icount,
196 count(DISTINCT reserves.borrowernumber) as rcount,
197 borrowers.firstname,
198 borrowers.surname
199 FROM reserves
200 LEFT JOIN items ON items.biblionumber=reserves.biblionumber
201 LEFT JOIN biblio ON reserves.biblionumber=biblio.biblionumber
202 LEFT JOIN branchtransfers ON items.itemnumber=branchtransfers.itemnumber
203 LEFT JOIN issues ON items.itemnumber=issues.itemnumber
204 LEFT JOIN borrowers ON reserves.borrowernumber=borrowers.borrowernumber
205 WHERE
206 reserves.found IS NULL
207 $sqldatewhere
208 AND (reserves.itemnumber IS NULL OR reserves.itemnumber = items.itemnumber)
209 AND items.itemnumber NOT IN (SELECT itemnumber FROM branchtransfers where datearrived IS NULL)
210 AND items.itemnumber NOT IN (select itemnumber FROM reserves where found IS NOT NULL)
211 AND issues.itemnumber IS NULL
212 AND reserves.priority <> 0
213 AND reserves.suspend = 0
214 AND notforloan = 0 AND damaged = 0 AND itemlost = 0 AND withdrawn = 0
216 # GROUP BY reserves.biblionumber allows only items that are not checked out, else multiples occur when
217 # multiple patrons have a hold on an item
220 if (C4::Context->preference('IndependentBranches')){
221 $strsth .= " AND items.holdingbranch=? ";
222 push @query_params, C4::Context->userenv->{'branch'};
224 $strsth .= " GROUP BY reserves.biblionumber ORDER BY biblio.title ";
226 my $sth = $dbh->prepare($strsth);
227 $sth->execute(@query_params);
229 while ( my $data = $sth->fetchrow_hashref ) {
230 my $record = Koha::Biblios->find($data->{biblionumber});
231 if ($record){
232 $data->{subtitle} = [ $record->subtitles ];
234 push(
235 @reservedata, {
236 reservedate => $data->{l_reservedate},
237 firstname => $data->{firstname} || '',
238 surname => $data->{surname},
239 title => $data->{title},
240 subtitle => $data->{subtitle},
241 author => $data->{author},
242 borrowernumber => $data->{borrowernumber},
243 biblionumber => $data->{biblionumber},
244 holdingbranches => [split('\|', $data->{l_holdingbranch})],
245 branch => $data->{l_branch},
246 itemcallnumber => $data->{l_itemcallnumber},
247 enumchron => $data->{l_enumchron},
248 copyno => $data->{l_copynumber},
249 count => $data->{icount},
250 rcount => $data->{rcount},
251 pullcount => $data->{icount} <= $data->{rcount} ? $data->{icount} : $data->{rcount},
252 itypes => [split('\|', $data->{l_itype})],
253 locations => [split('\|', $data->{l_location})],
254 reserve_id => $data->{reserve_id},
255 holdingbranch => $data->{holdingbranch},
256 homebranch => $data->{homebranch},
257 itemnumber => $data->{itemnumber},
261 $sth->finish;
263 $template->param(
264 todaysdate => $today,
265 from => $startdate,
266 to => $enddate,
267 reserveloop => \@reservedata,
268 "BiblioDefaultView".C4::Context->preference("BiblioDefaultView") => 1,
269 HoldsToPullStartDate => C4::Context->preference('HoldsToPullStartDate') || PULL_INTERVAL,
270 HoldsToPullEndDate => C4::Context->preference('ConfirmFutureHolds') || 0,
271 messages => \@messages,
274 output_html_with_http_headers $input, $cookie, $template->output;