← Index
NYTProf Performance Profile   « block view • line view • sub view »
For /usr/share/koha/opac/cgi-bin/opac/opac-search.pl
  Run on Tue Oct 15 17:10:45 2013
Reported on Tue Oct 15 17:12:36 2013

Filename/usr/share/koha/lib/C4/Reserves.pm
StatementsExecuted 787 statements in 123ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
11122.4ms185msC4::Reserves::::BEGIN@27C4::Reserves::BEGIN@27
11114.7ms18.7msC4::Reserves::::BEGIN@29C4::Reserves::BEGIN@29
64226.58ms184msC4::Reserves::::GetReserveStatusC4::Reserves::GetReserveStatus
1114.77ms47.0msC4::Reserves::::BEGIN@36C4::Reserves::BEGIN@36
1114.17ms4.87msC4::Reserves::::BEGIN@31C4::Reserves::BEGIN@31
1111.11ms1.23msC4::Reserves::::BEGIN@34C4::Reserves::BEGIN@34
11137µs43µsC4::Reserves::::BEGIN@28C4::Reserves::BEGIN@28
11126µs31µsC4::Reserves::::BEGIN@30C4::Reserves::BEGIN@30
11123µs23µsC4::Reserves::::BEGIN@89C4::Reserves::BEGIN@89
11121µs59µsC4::Reserves::::BEGIN@42C4::Reserves::BEGIN@42
11118µs23µsC4::Reserves::::BEGIN@24C4::Reserves::BEGIN@24
11115µs57µsC4::Reserves::::BEGIN@37C4::Reserves::BEGIN@37
11113µs46µsC4::Reserves::::BEGIN@38C4::Reserves::BEGIN@38
11113µs74µsC4::Reserves::::BEGIN@40C4::Reserves::BEGIN@40
11112µs142µsC4::Reserves::::BEGIN@44C4::Reserves::BEGIN@44
11110µs12µsC4::Reserves::::BEGIN@26C4::Reserves::BEGIN@26
1116µs6µsC4::Reserves::::BEGIN@35C4::Reserves::BEGIN@35
0000s0sC4::Reserves::::AddReserveC4::Reserves::AddReserve
0000s0sC4::Reserves::::AlterPriorityC4::Reserves::AlterPriority
0000s0sC4::Reserves::::AutoUnsuspendReservesC4::Reserves::AutoUnsuspendReserves
0000s0sC4::Reserves::::CanBookBeReservedC4::Reserves::CanBookBeReserved
0000s0sC4::Reserves::::CanItemBeReservedC4::Reserves::CanItemBeReserved
0000s0sC4::Reserves::::CancelExpiredReservesC4::Reserves::CancelExpiredReserves
0000s0sC4::Reserves::::CancelReserveC4::Reserves::CancelReserve
0000s0sC4::Reserves::::CheckReservesC4::Reserves::CheckReserves
0000s0sC4::Reserves::::GetOtherReservesC4::Reserves::GetOtherReserves
0000s0sC4::Reserves::::GetReserveCountC4::Reserves::GetReserveCount
0000s0sC4::Reserves::::GetReserveFeeC4::Reserves::GetReserveFee
0000s0sC4::Reserves::::GetReserveInfoC4::Reserves::GetReserveInfo
0000s0sC4::Reserves::::GetReservesForBranchC4::Reserves::GetReservesForBranch
0000s0sC4::Reserves::::GetReservesFromBiblionumberC4::Reserves::GetReservesFromBiblionumber
0000s0sC4::Reserves::::GetReservesFromBorrowernumberC4::Reserves::GetReservesFromBorrowernumber
0000s0sC4::Reserves::::GetReservesFromItemnumberC4::Reserves::GetReservesFromItemnumber
0000s0sC4::Reserves::::GetReservesToBranchC4::Reserves::GetReservesToBranch
0000s0sC4::Reserves::::IsAvailableForItemLevelRequestC4::Reserves::IsAvailableForItemLevelRequest
0000s0sC4::Reserves::::MergeHoldsC4::Reserves::MergeHolds
0000s0sC4::Reserves::::ModReserveC4::Reserves::ModReserve
0000s0sC4::Reserves::::ModReserveAffectC4::Reserves::ModReserveAffect
0000s0sC4::Reserves::::ModReserveCancelAllC4::Reserves::ModReserveCancelAll
0000s0sC4::Reserves::::ModReserveFillC4::Reserves::ModReserveFill
0000s0sC4::Reserves::::ModReserveMinusPriorityC4::Reserves::ModReserveMinusPriority
0000s0sC4::Reserves::::ModReserveStatusC4::Reserves::ModReserveStatus
0000s0sC4::Reserves::::MoveReserveC4::Reserves::MoveReserve
0000s0sC4::Reserves::::ReserveSlipC4::Reserves::ReserveSlip
0000s0sC4::Reserves::::RevertWaitingStatusC4::Reserves::RevertWaitingStatus
0000s0sC4::Reserves::::SuspendAllC4::Reserves::SuspendAll
0000s0sC4::Reserves::::ToggleLowestPriorityC4::Reserves::ToggleLowestPriority
0000s0sC4::Reserves::::ToggleSuspendC4::Reserves::ToggleSuspend
0000s0sC4::Reserves::::_FindgroupreserveC4::Reserves::_Findgroupreserve
0000s0sC4::Reserves::::_FixPriorityC4::Reserves::_FixPriority
0000s0sC4::Reserves::::_ShiftPriorityByDateAndPriorityC4::Reserves::_ShiftPriorityByDateAndPriority
0000s0sC4::Reserves::::_koha_notify_reserveC4::Reserves::_koha_notify_reserve
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package C4::Reserves;
2
3# Copyright 2000-2002 Katipo Communications
4# 2006 SAN Ouest Provence
5# 2007-2010 BibLibre Paul POULAIN
6# 2011 Catalyst IT
7#
8# This file is part of Koha.
9#
10# Koha is free software; you can redistribute it and/or modify it under the
11# terms of the GNU General Public License as published by the Free Software
12# Foundation; either version 2 of the License, or (at your option) any later
13# version.
14#
15# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
16# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License along
20# with Koha; if not, write to the Free Software Foundation, Inc.,
21# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23
24330µs227µs
# spent 23µs (18+4) within C4::Reserves::BEGIN@24 which was called: # once (18µs+4µs) by C4::Circulation::BEGIN@27 at line 24
use strict;
# spent 23µs making 1 call to C4::Reserves::BEGIN@24 # spent 4µs making 1 call to strict::import
25#use warnings; FIXME - Bug 2505
26326µs214µs
# spent 12µs (10+2) within C4::Reserves::BEGIN@26 which was called: # once (10µs+2µs) by C4::Circulation::BEGIN@27 at line 26
use C4::Context;
# spent 12µs making 1 call to C4::Reserves::BEGIN@26 # spent 2µs making 1 call to C4::Context::import
273171µs2187ms
# spent 185ms (22.4+163) within C4::Reserves::BEGIN@27 which was called: # once (22.4ms+163ms) by C4::Circulation::BEGIN@27 at line 27
use C4::Biblio;
# spent 185ms making 1 call to C4::Reserves::BEGIN@27 # spent 1.40ms making 1 call to Exporter::import
28372µs249µs
# spent 43µs (37+6) within C4::Reserves::BEGIN@28 which was called: # once (37µs+6µs) by C4::Circulation::BEGIN@27 at line 28
use C4::Members;
# spent 43µs making 1 call to C4::Reserves::BEGIN@28 # spent 6µs making 1 call to UNIVERSAL::import
293234µs219.0ms
# spent 18.7ms (14.7+3.94) within C4::Reserves::BEGIN@29 which was called: # once (14.7ms+3.94ms) by C4::Circulation::BEGIN@27 at line 29
use C4::Items;
# spent 18.7ms making 1 call to C4::Reserves::BEGIN@29 # spent 309µs making 1 call to Exporter::import
30342µs235µs
# spent 31µs (26+4) within C4::Reserves::BEGIN@30 which was called: # once (26µs+4µs) by C4::Circulation::BEGIN@27 at line 30
use C4::Circulation;
# spent 31µs making 1 call to C4::Reserves::BEGIN@30 # spent 4µs making 1 call to UNIVERSAL::import
313155µs25.09ms
# spent 4.87ms (4.17+701µs) within C4::Reserves::BEGIN@31 which was called: # once (4.17ms+701µs) by C4::Circulation::BEGIN@27 at line 31
use C4::Accounts;
# spent 4.87ms making 1 call to C4::Reserves::BEGIN@31 # spent 216µs making 1 call to Exporter::import
32
33# for _koha_notify_reserve
343151µs21.23ms
# spent 1.23ms (1.11+125µs) within C4::Reserves::BEGIN@34 which was called: # once (1.11ms+125µs) by C4::Circulation::BEGIN@27 at line 34
use C4::Members::Messaging;
# spent 1.23ms making 1 call to C4::Reserves::BEGIN@34 # spent 3µs making 1 call to UNIVERSAL::import
35326µs16µs
# spent 6µs within C4::Reserves::BEGIN@35 which was called: # once (6µs+0s) by C4::Circulation::BEGIN@27 at line 35
use C4::Members qw();
# spent 6µs making 1 call to C4::Reserves::BEGIN@35
363146µs247.3ms
# spent 47.0ms (4.77+42.2) within C4::Reserves::BEGIN@36 which was called: # once (4.77ms+42.2ms) by C4::Circulation::BEGIN@27 at line 36
use C4::Letters;
# spent 47.0ms making 1 call to C4::Reserves::BEGIN@36 # spent 284µs making 1 call to Exporter::import
37335µs2100µs
# spent 57µs (15+43) within C4::Reserves::BEGIN@37 which was called: # once (15µs+43µs) by C4::Circulation::BEGIN@27 at line 37
use C4::Branch qw( GetBranchDetail );
# spent 57µs making 1 call to C4::Reserves::BEGIN@37 # spent 43µs making 1 call to Exporter::import
38334µs279µs
# spent 46µs (13+33) within C4::Reserves::BEGIN@38 which was called: # once (13µs+33µs) by C4::Circulation::BEGIN@27 at line 38
use C4::Dates qw( format_date_in_iso );
# spent 46µs making 1 call to C4::Reserves::BEGIN@38 # spent 33µs making 1 call to Exporter::import
39
40339µs2134µs
# spent 74µs (13+61) within C4::Reserves::BEGIN@40 which was called: # once (13µs+61µs) by C4::Circulation::BEGIN@27 at line 40
use Koha::DateUtils;
# spent 74µs making 1 call to C4::Reserves::BEGIN@40 # spent 61µs making 1 call to Exporter::import
41
42360µs297µs
# spent 59µs (21+38) within C4::Reserves::BEGIN@42 which was called: # once (21µs+38µs) by C4::Circulation::BEGIN@27 at line 42
use List::MoreUtils qw( firstidx );
# spent 59µs making 1 call to C4::Reserves::BEGIN@42 # spent 38µs making 1 call to Exporter::import
43
443139µs2271µs
# spent 142µs (12+129) within C4::Reserves::BEGIN@44 which was called: # once (12µs+129µs) by C4::Circulation::BEGIN@27 at line 44
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
# spent 142µs making 1 call to C4::Reserves::BEGIN@44 # spent 129µs making 1 call to vars::import
45
46=head1 NAME
47
- -
89
# spent 23µs within C4::Reserves::BEGIN@89 which was called: # once (23µs+0s) by C4::Circulation::BEGIN@27 at line 135
BEGIN {
90 # set the version for version checking
9111µs $VERSION = 3.07.00.049;
921900ns require Exporter;
9319µs @ISA = qw(Exporter);
9415µs @EXPORT = qw(
95 &AddReserve
96
97 &GetReservesFromItemnumber
98 &GetReservesFromBiblionumber
99 &GetReservesFromBorrowernumber
100 &GetReservesForBranch
101 &GetReservesToBranch
102 &GetReserveCount
103 &GetReserveFee
104 &GetReserveInfo
105 &GetReserveStatus
106
107 &GetOtherReserves
108
109 &ModReserveFill
110 &ModReserveAffect
111 &ModReserve
112 &ModReserveStatus
113 &ModReserveCancelAll
114 &ModReserveMinusPriority
115 &MoveReserve
116
117 &CheckReserves
118 &CanBookBeReserved
119 &CanItemBeReserved
120 &CancelReserve
121 &CancelExpiredReserves
122
123 &AutoUnsuspendReserves
124
125 &IsAvailableForItemLevelRequest
126
127 &AlterPriority
128 &ToggleLowestPriority
129
130 &ReserveSlip
131 &ToggleSuspend
132 &SuspendAll
133 );
13416µs @EXPORT_OK = qw( MergeHolds );
13516.08ms123µs}
# spent 23µs making 1 call to C4::Reserves::BEGIN@89
136
137=head2 AddReserve
138
- -
143sub AddReserve {
144 my (
145 $branch, $borrowernumber, $biblionumber,
146 $constraint, $bibitems, $priority, $resdate, $expdate, $notes,
147 $title, $checkitem, $found
148 ) = @_;
149 my $fee =
150 GetReserveFee($borrowernumber, $biblionumber, $constraint,
151 $bibitems );
152 my $dbh = C4::Context->dbh;
153 my $const = lc substr( $constraint, 0, 1 );
154 $resdate = format_date_in_iso( $resdate ) if ( $resdate );
155 $resdate = C4::Dates->today( 'iso' ) unless ( $resdate );
156 if ($expdate) {
157 $expdate = format_date_in_iso( $expdate );
158 } else {
159 undef $expdate; # make reserves.expirationdate default to null rather than '0000-00-00'
160 }
161 if ( C4::Context->preference( 'AllowHoldDateInFuture' ) ) {
162 # Make room in reserves for this before those of a later reserve date
163 $priority = _ShiftPriorityByDateAndPriority( $biblionumber, $resdate, $priority );
164 }
165 my $waitingdate;
166
167 # If the reserv had the waiting status, we had the value of the resdate
168 if ( $found eq 'W' ) {
169 $waitingdate = $resdate;
170 }
171
172 #eval {
173 # updates take place here
174 if ( $fee > 0 ) {
175 my $nextacctno = &getnextacctno( $borrowernumber );
176 my $query = qq/
177 INSERT INTO accountlines
178 (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
179 VALUES
180 (?,?,now(),?,?,'Res',?)
181 /;
182 my $usth = $dbh->prepare($query);
183 $usth->execute( $borrowernumber, $nextacctno, $fee,
184 "Reserve Charge - $title", $fee );
185 }
186
187 #if ($const eq 'a'){
188 my $query = qq/
189 INSERT INTO reserves
190 (borrowernumber,biblionumber,reservedate,branchcode,constrainttype,
191 priority,reservenotes,itemnumber,found,waitingdate,expirationdate)
192 VALUES
193 (?,?,?,?,?,
194 ?,?,?,?,?,?)
195 /;
196 my $sth = $dbh->prepare($query);
197 $sth->execute(
198 $borrowernumber, $biblionumber, $resdate, $branch,
199 $const, $priority, $notes, $checkitem,
200 $found, $waitingdate, $expdate
201 );
202
203 # Send e-mail to librarian if syspref is active
204 if(C4::Context->preference("emailLibrarianWhenHoldIsPlaced")){
205 my $borrower = C4::Members::GetMember(borrowernumber => $borrowernumber);
206 my $branch_details = C4::Branch::GetBranchDetail($borrower->{branchcode});
207 if ( my $letter = C4::Letters::GetPreparedLetter (
208 module => 'reserves',
209 letter_code => 'HOLDPLACED',
210 branchcode => $branch,
211 tables => {
212 'branches' => $branch_details,
213 'borrowers' => $borrower,
214 'biblio' => $biblionumber,
215 },
216 ) ) {
217
218 my $admin_email_address =$branch_details->{'branchemail'} || C4::Context->preference('KohaAdminEmailAddress');
219
220 C4::Letters::EnqueueLetter(
221 { letter => $letter,
222 borrowernumber => $borrowernumber,
223 message_transport_type => 'email',
224 from_address => $admin_email_address,
225 to_address => $admin_email_address,
226 }
227 );
228 }
229 }
230
231 #}
232 ($const eq "o" || $const eq "e") or return; # FIXME: why not have a useful return value?
233 $query = qq/
234 INSERT INTO reserveconstraints
235 (borrowernumber,biblionumber,reservedate,biblioitemnumber)
236 VALUES
237 (?,?,?,?)
238 /;
239 $sth = $dbh->prepare($query); # keep prepare outside the loop!
240 foreach (@$bibitems) {
241 $sth->execute($borrowernumber, $biblionumber, $resdate, $_);
242 }
243
244 return; # FIXME: why not have a useful return value?
245}
246
247=head2 GetReservesFromBiblionumber
248
- -
256sub GetReservesFromBiblionumber {
257 my ($biblionumber) = shift or return (0, []);
258 my ($all_dates) = shift;
259 my $dbh = C4::Context->dbh;
260
261 # Find the desired items in the reserves
262 my $query = "
263 SELECT branchcode,
264 timestamp AS rtimestamp,
265 priority,
266 biblionumber,
267 borrowernumber,
268 reservedate,
269 constrainttype,
270 found,
271 itemnumber,
272 reservenotes,
273 expirationdate,
274 lowestPriority,
275 suspend,
276 suspend_until
277 FROM reserves
278 WHERE biblionumber = ? ";
279 unless ( $all_dates ) {
280 $query .= "AND reservedate <= CURRENT_DATE()";
281 }
282 $query .= "ORDER BY priority";
283 my $sth = $dbh->prepare($query);
284 $sth->execute($biblionumber);
285 my @results;
286 my $i = 0;
287 while ( my $data = $sth->fetchrow_hashref ) {
288
289 # FIXME - What is this doing? How do constraints work?
290 if ($data->{constrainttype} eq 'o') {
291 $query = '
292 SELECT biblioitemnumber
293 FROM reserveconstraints
294 WHERE biblionumber = ?
295 AND borrowernumber = ?
296 AND reservedate = ?
297 ';
298 my $csth = $dbh->prepare($query);
299 $csth->execute($data->{biblionumber}, $data->{borrowernumber}, $data->{reservedate});
300 my @bibitemno;
301 while ( my $bibitemnos = $csth->fetchrow_array ) {
302 push( @bibitemno, $bibitemnos ); # FIXME: inefficient: use fetchall_arrayref
303 }
304 my $count = scalar @bibitemno;
305
306 # if we have two or more different specific itemtypes
307 # reserved by same person on same day
308 my $bdata;
309 if ( $count > 1 ) {
310 $bdata = GetBiblioItemData( $bibitemno[$i] ); # FIXME: This doesn't make sense.
311 $i++; # $i can increase each pass, but the next @bibitemno might be smaller?
312 }
313 else {
314 # Look up the book we just found.
315 $bdata = GetBiblioItemData( $bibitemno[0] );
316 }
317 # Add the results of this latest search to the current
318 # results.
319 # FIXME - An 'each' would probably be more efficient.
320 foreach my $key ( keys %$bdata ) {
321 $data->{$key} = $bdata->{$key};
322 }
323 }
324 push @results, $data;
325 }
326 return ( $#results + 1, \@results );
327}
328
329=head2 GetReservesFromItemnumber
330
- -
337sub GetReservesFromItemnumber {
338 my ( $itemnumber, $all_dates ) = @_;
339 my $dbh = C4::Context->dbh;
340 my $query = "
341 SELECT reservedate,borrowernumber,branchcode
342 FROM reserves
343 WHERE itemnumber=?
344 ";
345 unless ( $all_dates ) {
346 $query .= " AND reservedate <= CURRENT_DATE()";
347 }
348 my $sth_res = $dbh->prepare($query);
349 $sth_res->execute($itemnumber);
350 my ( $reservedate, $borrowernumber,$branchcode ) = $sth_res->fetchrow_array;
351 return ( $reservedate, $borrowernumber, $branchcode );
352}
353
354=head2 GetReservesFromBorrowernumber
355
- -
362sub GetReservesFromBorrowernumber {
363 my ( $borrowernumber, $status ) = @_;
364 my $dbh = C4::Context->dbh;
365 my $sth;
366 if ($status) {
367 $sth = $dbh->prepare("
368 SELECT *
369 FROM reserves
370 WHERE borrowernumber=?
371 AND found =?
372 ORDER BY reservedate
373 ");
374 $sth->execute($borrowernumber,$status);
375 } else {
376 $sth = $dbh->prepare("
377 SELECT *
378 FROM reserves
379 WHERE borrowernumber=?
380 ORDER BY reservedate
381 ");
382 $sth->execute($borrowernumber);
383 }
384 my $data = $sth->fetchall_arrayref({});
385 return @$data;
386}
387#-------------------------------------------------------------------------------------
388=head2 CanBookBeReserved
389
- -
394sub CanBookBeReserved{
395 my ($borrowernumber, $biblionumber) = @_;
396
397 my $items = GetItemnumbersForBiblio($biblionumber);
398 #get items linked via host records
399 my @hostitems = get_hostitemnumbers_of($biblionumber);
400 if (@hostitems){
401 push (@$items,@hostitems);
402 }
403
404 foreach my $item (@$items){
405 return 1 if CanItemBeReserved($borrowernumber, $item);
406 }
407 return 0;
408}
409
410=head2 CanItemBeReserved
411
- -
418sub CanItemBeReserved{
419 my ($borrowernumber, $itemnumber) = @_;
420
421 my $dbh = C4::Context->dbh;
422 my $allowedreserves = 0;
423
424 my $controlbranch = C4::Context->preference('ReservesControlBranch');
425 my $itype = C4::Context->preference('item-level_itypes') ? "itype" : "itemtype";
426
427 # we retrieve borrowers and items informations #
428 my $item = GetItem($itemnumber);
429 my $borrower = C4::Members::GetMember('borrowernumber'=>$borrowernumber);
430
431 # we retrieve user rights on this itemtype and branchcode
432 my $sth = $dbh->prepare("SELECT categorycode, itemtype, branchcode, reservesallowed
433 FROM issuingrules
434 WHERE (categorycode in (?,'*') )
435 AND (itemtype IN (?,'*'))
436 AND (branchcode IN (?,'*'))
437 ORDER BY
438 categorycode DESC,
439 itemtype DESC,
440 branchcode DESC;"
441 );
442
443 my $querycount ="SELECT
444 count(*) as count
445 FROM reserves
446 LEFT JOIN items USING (itemnumber)
447 LEFT JOIN biblioitems ON (reserves.biblionumber=biblioitems.biblionumber)
448 LEFT JOIN borrowers USING (borrowernumber)
449 WHERE borrowernumber = ?
450 ";
451
452
453 my $itemtype = $item->{$itype};
454 my $categorycode = $borrower->{categorycode};
455 my $branchcode = "";
456 my $branchfield = "reserves.branchcode";
457
458 if( $controlbranch eq "ItemHomeLibrary" ){
459 $branchfield = "items.homebranch";
460 $branchcode = $item->{homebranch};
461 }elsif( $controlbranch eq "PatronLibrary" ){
462 $branchfield = "borrowers.branchcode";
463 $branchcode = $borrower->{branchcode};
464 }
465
466 # we retrieve rights
467 $sth->execute($categorycode, $itemtype, $branchcode);
468 if(my $rights = $sth->fetchrow_hashref()){
469 $itemtype = $rights->{itemtype};
470 $allowedreserves = $rights->{reservesallowed};
471 }else{
472 $itemtype = '*';
473 }
474
475 # we retrieve count
476
477 $querycount .= "AND $branchfield = ?";
478
479 $querycount .= " AND $itype = ?" if ($itemtype ne "*");
480 my $sthcount = $dbh->prepare($querycount);
481
482 if($itemtype eq "*"){
483 $sthcount->execute($borrowernumber, $branchcode);
484 }else{
485 $sthcount->execute($borrowernumber, $branchcode, $itemtype);
486 }
487
488 my $reservecount = "0";
489 if(my $rowcount = $sthcount->fetchrow_hashref()){
490 $reservecount = $rowcount->{count};
491 }
492
493 # we check if it's ok or not
494 if( $reservecount < $allowedreserves ){
495 return 1;
496 }else{
497 return 0;
498 }
499}
500#--------------------------------------------------------------------------------
501=head2 GetReserveCount
502
- -
509sub GetReserveCount {
510 my ($borrowernumber) = @_;
511
512 my $dbh = C4::Context->dbh;
513
514 my $query = '
515 SELECT COUNT(*) AS counter
516 FROM reserves
517 WHERE borrowernumber = ?
518 ';
519 my $sth = $dbh->prepare($query);
520 $sth->execute($borrowernumber);
521 my $row = $sth->fetchrow_hashref;
522 return $row->{counter};
523}
524
525=head2 GetOtherReserves
526
- -
533sub GetOtherReserves {
534 my ($itemnumber) = @_;
535 my $messages;
536 my $nextreservinfo;
537 my ( undef, $checkreserves, undef ) = CheckReserves($itemnumber);
538 if ($checkreserves) {
539 my $iteminfo = GetItem($itemnumber);
540 if ( $iteminfo->{'holdingbranch'} ne $checkreserves->{'branchcode'} ) {
541 $messages->{'transfert'} = $checkreserves->{'branchcode'};
542 #minus priorities of others reservs
543 ModReserveMinusPriority(
544 $itemnumber,
545 $checkreserves->{'borrowernumber'},
546 $iteminfo->{'biblionumber'}
547 );
548
549 #launch the subroutine dotransfer
550 C4::Items::ModItemTransfer(
551 $itemnumber,
552 $iteminfo->{'holdingbranch'},
553 $checkreserves->{'branchcode'}
554 ),
555 ;
556 }
557
558 #step 2b : case of a reservation on the same branch, set the waiting status
559 else {
560 $messages->{'waiting'} = 1;
561 ModReserveMinusPriority(
562 $itemnumber,
563 $checkreserves->{'borrowernumber'},
564 $iteminfo->{'biblionumber'}
565 );
566 ModReserveStatus($itemnumber,'W');
567 }
568
569 $nextreservinfo = $checkreserves->{'borrowernumber'};
570 }
571
572 return ( $messages, $nextreservinfo );
573}
574
575=head2 GetReserveFee
576
- -
583sub GetReserveFee {
584 my ($borrowernumber, $biblionumber, $constraint, $bibitems ) = @_;
585
586 #check for issues;
587 my $dbh = C4::Context->dbh;
588 my $const = lc substr( $constraint, 0, 1 );
589 my $query = qq/
590 SELECT * FROM borrowers
591 LEFT JOIN categories ON borrowers.categorycode = categories.categorycode
592 WHERE borrowernumber = ?
593 /;
594 my $sth = $dbh->prepare($query);
595 $sth->execute($borrowernumber);
596 my $data = $sth->fetchrow_hashref;
597 $sth->finish();
598 my $fee = $data->{'reservefee'};
599 my $cntitems = @- > $bibitems;
600
601 if ( $fee > 0 ) {
602
603 # check for items on issue
604 # first find biblioitem records
605 my @biblioitems;
606 my $sth1 = $dbh->prepare(
607 "SELECT * FROM biblio LEFT JOIN biblioitems on biblio.biblionumber = biblioitems.biblionumber
608 WHERE (biblio.biblionumber = ?)"
609 );
610 $sth1->execute($biblionumber);
611 while ( my $data1 = $sth1->fetchrow_hashref ) {
612 if ( $const eq "a" ) {
613 push @biblioitems, $data1;
614 }
615 else {
616 my $found = 0;
617 my $x = 0;
618 while ( $x < $cntitems ) {
619 if ( @$bibitems->{'biblioitemnumber'} ==
620 $data->{'biblioitemnumber'} )
621 {
622 $found = 1;
623 }
624 $x++;
625 }
626 if ( $const eq 'o' ) {
627 if ( $found == 1 ) {
628 push @biblioitems, $data1;
629 }
630 }
631 else {
632 if ( $found == 0 ) {
633 push @biblioitems, $data1;
634 }
635 }
636 }
637 }
638 $sth1->finish;
639 my $cntitemsfound = @biblioitems;
640 my $issues = 0;
641 my $x = 0;
642 my $allissued = 1;
643 while ( $x < $cntitemsfound ) {
644 my $bitdata = $biblioitems[$x];
645 my $sth2 = $dbh->prepare(
646 "SELECT * FROM items
647 WHERE biblioitemnumber = ?"
648 );
649 $sth2->execute( $bitdata->{'biblioitemnumber'} );
650 while ( my $itdata = $sth2->fetchrow_hashref ) {
651 my $sth3 = $dbh->prepare(
652 "SELECT * FROM issues
653 WHERE itemnumber = ?"
654 );
655 $sth3->execute( $itdata->{'itemnumber'} );
656 if ( my $isdata = $sth3->fetchrow_hashref ) {
657 }
658 else {
659 $allissued = 0;
660 }
661 }
662 $x++;
663 }
664 if ( $allissued == 0 ) {
665 my $rsth =
666 $dbh->prepare("SELECT * FROM reserves WHERE biblionumber = ?");
667 $rsth->execute($biblionumber);
668 if ( my $rdata = $rsth->fetchrow_hashref ) {
669 }
670 else {
671 $fee = 0;
672 }
673 }
674 }
675 return $fee;
676}
677
678=head2 GetReservesToBranch
679
- -
686sub GetReservesToBranch {
687 my ( $frombranch ) = @_;
688 my $dbh = C4::Context->dbh;
689 my $sth = $dbh->prepare(
690 "SELECT borrowernumber,reservedate,itemnumber,timestamp
691 FROM reserves
692 WHERE priority='0'
693 AND branchcode=?"
694 );
695 $sth->execute( $frombranch );
696 my @transreserv;
697 my $i = 0;
698 while ( my $data = $sth->fetchrow_hashref ) {
699 $transreserv[$i] = $data;
700 $i++;
701 }
702 return (@transreserv);
703}
704
705=head2 GetReservesForBranch
706
- -
711sub GetReservesForBranch {
712 my ($frombranch) = @_;
713 my $dbh = C4::Context->dbh;
714 my $query = "SELECT borrowernumber,reservedate,itemnumber,waitingdate
715 FROM reserves
716 WHERE priority='0'
717 AND found='W' ";
718 if ($frombranch){
719 $query .= " AND branchcode=? ";
720 }
721 $query .= "ORDER BY waitingdate" ;
722 my $sth = $dbh->prepare($query);
723 if ($frombranch){
724 $sth->execute($frombranch);
725 }
726 else {
727 $sth->execute();
728 }
729 my @transreserv;
730 my $i = 0;
731 while ( my $data = $sth->fetchrow_hashref ) {
732 $transreserv[$i] = $data;
733 $i++;
734 }
735 return (@transreserv);
736}
737
738=head2 GetReserveStatus
739
- -
747
# spent 184ms (6.58+178) within C4::Reserves::GetReserveStatus which was called 64 times, avg 2.88ms/call: # 32 times (4.15ms+113ms) by C4::Search::searchResults at line 1926 of /usr/share/koha/lib/C4/Search.pm, avg 3.67ms/call # 32 times (2.43ms+64.6ms) by C4::XSLT::buildKohaItemsNamespace at line 267 of /usr/share/koha/lib/C4/XSLT.pm, avg 2.09ms/call
sub GetReserveStatus {
74864131µs my ($itemnumber, $biblionumber) = @_;
749
75064406µs6461.0ms my $dbh = C4::Context->dbh;
# spent 61.0ms making 64 calls to C4::Context::dbh, avg 954µs/call
751
7526469µs my ($sth, $found, $priority);
75364108µs if ( $itemnumber ) {
754641.30ms12811.5ms $sth = $dbh->prepare("SELECT found, priority FROM reserves WHERE itemnumber = ? order by priority LIMIT 1");
# spent 6.26ms making 64 calls to DBI::db::prepare, avg 98µs/call # spent 5.20ms making 64 calls to DBD::mysql::db::prepare, avg 81µs/call
7556469.4ms6468.5ms $sth->execute($itemnumber);
# spent 68.5ms making 64 calls to DBI::st::execute, avg 1.07ms/call
756641.81ms64951µs ($found, $priority) = $sth->fetchrow_array;
# spent 951µs making 64 calls to DBI::st::fetchrow_array, avg 15µs/call
757 }
758
75964104µs if ( $biblionumber and not defined $found and not defined $priority ) {
760321.54ms645.58ms $sth = $dbh->prepare("SELECT found, priority FROM reserves WHERE biblionumber = ? order by priority LIMIT 1");
# spent 2.99ms making 32 calls to DBI::db::prepare, avg 93µs/call # spent 2.59ms making 32 calls to DBD::mysql::db::prepare, avg 81µs/call
7613236.9ms12836.8ms $sth->execute($biblionumber);
# spent 36.4ms making 32 calls to DBI::st::execute, avg 1.14ms/call # spent 277µs making 64 calls to DBI::common::DESTROY, avg 4µs/call # spent 75µs making 32 calls to DBD::_mem::common::DESTROY, avg 2µs/call
76232706µs32403µs ($found, $priority) = $sth->fetchrow_array;
# spent 403µs making 32 calls to DBI::st::fetchrow_array, avg 13µs/call
763 }
764
7656447µs if(defined $found) {
766 return 'Waiting' if $found eq 'W' and $priority == 0;
767 return 'Finished' if $found eq 'F';
768 return 'Reserved' if $priority > 0;
769 }
770642.76ms return '';
771 #empty string here will remove need for checking undef, or less log lines
772}
773
774=head2 CheckReserves
775
- -
801sub CheckReserves {
802 my ( $item, $barcode ) = @_;
803 my $dbh = C4::Context->dbh;
804 my $sth;
805 my $select;
806 if (C4::Context->preference('item-level_itypes')){
807 $select = "
808 SELECT items.biblionumber,
809 items.biblioitemnumber,
810 itemtypes.notforloan,
811 items.notforloan AS itemnotforloan,
812 items.itemnumber
813 FROM items
814 LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
815 LEFT JOIN itemtypes ON items.itype = itemtypes.itemtype
816 ";
817 }
818 else {
819 $select = "
820 SELECT items.biblionumber,
821 items.biblioitemnumber,
822 itemtypes.notforloan,
823 items.notforloan AS itemnotforloan,
824 items.itemnumber
825 FROM items
826 LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
827 LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
828 ";
829 }
830
831 if ($item) {
832 $sth = $dbh->prepare("$select WHERE itemnumber = ?");
833 $sth->execute($item);
834 }
835 else {
836 $sth = $dbh->prepare("$select WHERE barcode = ?");
837 $sth->execute($barcode);
838 }
839 # note: we get the itemnumber because we might have started w/ just the barcode. Now we know for sure we have it.
840 my ( $biblio, $bibitem, $notforloan_per_itemtype, $notforloan_per_item, $itemnumber ) = $sth->fetchrow_array;
841
842 return ( '' ) unless $itemnumber; # bail if we got nothing.
843
844 # if item is not for loan it cannot be reserved either.....
845 # execpt where items.notforloan < 0 : This indicates the item is holdable.
846 return ( '' ) if ( $notforloan_per_item > 0 ) or $notforloan_per_itemtype;
847
848 # Find this item in the reserves
849 my @reserves = _Findgroupreserve( $bibitem, $biblio, $itemnumber );
850
851 # $priority and $highest are used to find the most important item
852 # in the list returned by &_Findgroupreserve. (The lower $priority,
853 # the more important the item.)
854 # $highest is the most important item we've seen so far.
855 my $highest;
856 if (scalar @reserves) {
857 my $priority = 10000000;
858 foreach my $res (@reserves) {
859 if ( $res->{'itemnumber'} == $itemnumber && $res->{'priority'} == 0) {
860 return ( "Waiting", $res, \@reserves ); # Found it
861 } else {
862 # See if this item is more important than what we've got so far
863 if ( $res->{'priority'} && $res->{'priority'} < $priority ) {
864 my $borrowerinfo=C4::Members::GetMember(borrowernumber => $res->{'borrowernumber'});
865 my $iteminfo=C4::Items::GetItem($itemnumber);
866 my $branch=C4::Circulation::_GetCircControlBranch($iteminfo,$borrowerinfo);
867 my $branchitemrule = C4::Circulation::GetBranchItemRule($branch,$iteminfo->{'itype'});
868 next if ($branchitemrule->{'holdallowed'} == 0);
869 next if (($branchitemrule->{'holdallowed'} == 1) && ($branch ne $borrowerinfo->{'branchcode'}));
870 $priority = $res->{'priority'};
871 $highest = $res;
872 }
873 }
874 }
875 }
876
877 # If we get this far, then no exact match was found.
878 # We return the most important (i.e. next) reservation.
879 if ($highest) {
880 $highest->{'itemnumber'} = $item;
881 return ( "Reserved", $highest, \@reserves );
882 }
883
884 return ( '' );
885}
886
887=head2 CancelExpiredReserves
888
- -
895sub CancelExpiredReserves {
896
897 # Cancel reserves that have passed their expiration date.
898 my $dbh = C4::Context->dbh;
899 my $sth = $dbh->prepare( "
900 SELECT * FROM reserves WHERE DATE(expirationdate) < DATE( CURDATE() )
901 AND expirationdate IS NOT NULL
902 AND found IS NULL
903 " );
904 $sth->execute();
905
906 while ( my $res = $sth->fetchrow_hashref() ) {
907 CancelReserve( $res->{'biblionumber'}, '', $res->{'borrowernumber'} );
908 }
909
910 # Cancel reserves that have been waiting too long
911 if ( C4::Context->preference("ExpireReservesMaxPickUpDelay") ) {
912 my $max_pickup_delay = C4::Context->preference("ReservesMaxPickUpDelay");
913 my $charge = C4::Context->preference("ExpireReservesMaxPickUpDelayCharge");
914
915 my $query = "SELECT * FROM reserves WHERE TO_DAYS( NOW() ) - TO_DAYS( waitingdate ) > ? AND found = 'W' AND priority = 0";
916 $sth = $dbh->prepare( $query );
917 $sth->execute( $max_pickup_delay );
918
919 while (my $res = $sth->fetchrow_hashref ) {
920 if ( $charge ) {
921 manualinvoice($res->{'borrowernumber'}, $res->{'itemnumber'}, 'Hold waiting too long', 'F', $charge);
922 }
923
924 CancelReserve( $res->{'biblionumber'}, '', $res->{'borrowernumber'} );
925 }
926 }
927
928}
929
930=head2 AutoUnsuspendReserves
931
- -
938sub AutoUnsuspendReserves {
939
940 my $dbh = C4::Context->dbh;
941
942 my $query = "UPDATE reserves SET suspend = 0, suspend_until = NULL WHERE DATE( suspend_until ) < DATE( CURDATE() )";
943 my $sth = $dbh->prepare( $query );
944 $sth->execute();
945
946}
947
948=head2 CancelReserve
949
- -
966sub CancelReserve {
967 my ( $biblio, $item, $borr ) = @_;
968 my $dbh = C4::Context->dbh;
969 if ( $item and $borr ) {
970 # removing a waiting reserve record....
971 # update the database...
972 my $query = "
973 UPDATE reserves
974 SET cancellationdate = now(),
975 found = Null,
976 priority = 0
977 WHERE itemnumber = ?
978 AND borrowernumber = ?
979 ";
980 my $sth = $dbh->prepare($query);
981 $sth->execute( $item, $borr );
982 $sth->finish;
983 $query = "
984 INSERT INTO old_reserves
985 SELECT * FROM reserves
986 WHERE itemnumber = ?
987 AND borrowernumber = ?
988 ";
989 $sth = $dbh->prepare($query);
990 $sth->execute( $item, $borr );
991 $query = "
992 DELETE FROM reserves
993 WHERE itemnumber = ?
994 AND borrowernumber = ?
995 ";
996 $sth = $dbh->prepare($query);
997 $sth->execute( $item, $borr );
998 }
999 else {
1000 # removing a reserve record....
1001 # get the prioritiy on this record....
1002 my $priority;
1003 my $query = qq/
1004 SELECT priority FROM reserves
1005 WHERE biblionumber = ?
1006 AND borrowernumber = ?
1007 AND cancellationdate IS NULL
1008 AND itemnumber IS NULL
1009 /;
1010 my $sth = $dbh->prepare($query);
1011 $sth->execute( $biblio, $borr );
1012 ($priority) = $sth->fetchrow_array;
1013 $sth->finish;
1014 $query = qq/
1015 UPDATE reserves
1016 SET cancellationdate = now(),
1017 found = Null,
1018 priority = 0
1019 WHERE biblionumber = ?
1020 AND borrowernumber = ?
1021 /;
1022
1023 # update the database, removing the record...
1024 $sth = $dbh->prepare($query);
1025 $sth->execute( $biblio, $borr );
1026 $sth->finish;
1027
1028 $query = qq/
1029 INSERT INTO old_reserves
1030 SELECT * FROM reserves
1031 WHERE biblionumber = ?
1032 AND borrowernumber = ?
1033 /;
1034 $sth = $dbh->prepare($query);
1035 $sth->execute( $biblio, $borr );
1036
1037 $query = qq/
1038 DELETE FROM reserves
1039 WHERE biblionumber = ?
1040 AND borrowernumber = ?
1041 /;
1042 $sth = $dbh->prepare($query);
1043 $sth->execute( $biblio, $borr );
1044
1045 # now fix the priority on the others....
1046 _FixPriority( $biblio, $borr );
1047 }
1048}
1049
1050=head2 ModReserve
1051
- -
1081sub ModReserve {
1082 #subroutine to update a reserve
1083 my ( $rank, $biblio, $borrower, $branch , $itemnumber, $suspend_until) = @_;
1084 return if $rank eq "W";
1085 return if $rank eq "n";
1086 my $dbh = C4::Context->dbh;
1087 if ( $rank eq "del" ) {
1088 my $query = qq/
1089 UPDATE reserves
1090 SET cancellationdate=now()
1091 WHERE biblionumber = ?
1092 AND borrowernumber = ?
1093 /;
1094 my $sth = $dbh->prepare($query);
1095 $sth->execute( $biblio, $borrower );
1096 $sth->finish;
1097 $query = qq/
1098 INSERT INTO old_reserves
1099 SELECT *
1100 FROM reserves
1101 WHERE biblionumber = ?
1102 AND borrowernumber = ?
1103 /;
1104 $sth = $dbh->prepare($query);
1105 $sth->execute( $biblio, $borrower );
1106 $query = qq/
1107 DELETE FROM reserves
1108 WHERE biblionumber = ?
1109 AND borrowernumber = ?
1110 /;
1111 $sth = $dbh->prepare($query);
1112 $sth->execute( $biblio, $borrower );
1113
1114 }
1115 elsif ($rank =~ /^\d+/ and $rank > 0) {
1116 my $query = "
1117 UPDATE reserves SET priority = ? ,branchcode = ?, itemnumber = ?, found = NULL, waitingdate = NULL
1118 WHERE biblionumber = ?
1119 AND borrowernumber = ?
1120 ";
1121 my $sth = $dbh->prepare($query);
1122 $sth->execute( $rank, $branch,$itemnumber, $biblio, $borrower);
1123 $sth->finish;
1124
1125 if ( defined( $suspend_until ) ) {
1126 if ( $suspend_until ) {
1127 $suspend_until = C4::Dates->new( $suspend_until )->output("iso");
1128 $dbh->do("UPDATE reserves SET suspend = 1, suspend_until = ? WHERE biblionumber = ? AND borrowernumber = ?", undef, ( $suspend_until, $biblio, $borrower ) );
1129 } else {
1130 $dbh->do("UPDATE reserves SET suspend_until = NULL WHERE biblionumber = ? AND borrowernumber = ?", undef, ( $biblio, $borrower ) );
1131 }
1132 }
1133
1134 _FixPriority( $biblio, $borrower, $rank);
1135 }
1136}
1137
1138=head2 ModReserveFill
1139
- -
1150sub ModReserveFill {
1151 my ($res) = @_;
1152 my $dbh = C4::Context->dbh;
1153 # fill in a reserve record....
1154 my $biblionumber = $res->{'biblionumber'};
1155 my $borrowernumber = $res->{'borrowernumber'};
1156 my $resdate = $res->{'reservedate'};
1157
1158 # get the priority on this record....
1159 my $priority;
1160 my $query = "SELECT priority
1161 FROM reserves
1162 WHERE biblionumber = ?
1163 AND borrowernumber = ?
1164 AND reservedate = ?";
1165 my $sth = $dbh->prepare($query);
1166 $sth->execute( $biblionumber, $borrowernumber, $resdate );
1167 ($priority) = $sth->fetchrow_array;
1168 $sth->finish;
1169
1170 # update the database...
1171 $query = "UPDATE reserves
1172 SET found = 'F',
1173 priority = 0
1174 WHERE biblionumber = ?
1175 AND reservedate = ?
1176 AND borrowernumber = ?
1177 ";
1178 $sth = $dbh->prepare($query);
1179 $sth->execute( $biblionumber, $resdate, $borrowernumber );
1180 $sth->finish;
1181
1182 # move to old_reserves
1183 $query = "INSERT INTO old_reserves
1184 SELECT * FROM reserves
1185 WHERE biblionumber = ?
1186 AND reservedate = ?
1187 AND borrowernumber = ?
1188 ";
1189 $sth = $dbh->prepare($query);
1190 $sth->execute( $biblionumber, $resdate, $borrowernumber );
1191 $query = "DELETE FROM reserves
1192 WHERE biblionumber = ?
1193 AND reservedate = ?
1194 AND borrowernumber = ?
1195 ";
1196 $sth = $dbh->prepare($query);
1197 $sth->execute( $biblionumber, $resdate, $borrowernumber );
1198
1199 # now fix the priority on the others (if the priority wasn't
1200 # already sorted!)....
1201 unless ( $priority == 0 ) {
1202 _FixPriority( $biblionumber, $borrowernumber );
1203 }
1204}
1205
1206=head2 ModReserveStatus
1207
- -
1218sub ModReserveStatus {
1219
1220 #first : check if we have a reservation for this item .
1221 my ($itemnumber, $newstatus) = @_;
1222 my $dbh = C4::Context->dbh;
1223
1224 my $query = "UPDATE reserves SET found = ?, waitingdate = NOW() WHERE itemnumber = ? AND found IS NULL AND priority = 0";
1225 my $sth_set = $dbh->prepare($query);
1226 $sth_set->execute( $newstatus, $itemnumber );
1227
1228 if ( C4::Context->preference("ReturnToShelvingCart") && $newstatus ) {
1229 CartToShelf( $itemnumber );
1230 }
1231}
1232
1233=head2 ModReserveAffect
1234
- -
1248sub ModReserveAffect {
1249 my ( $itemnumber, $borrowernumber,$transferToDo ) = @_;
1250 my $dbh = C4::Context->dbh;
1251
1252 # we want to attach $itemnumber to $borrowernumber, find the biblionumber
1253 # attached to $itemnumber
1254 my $sth = $dbh->prepare("SELECT biblionumber FROM items WHERE itemnumber=?");
1255 $sth->execute($itemnumber);
1256 my ($biblionumber) = $sth->fetchrow;
1257
1258 # get request - need to find out if item is already
1259 # waiting in order to not send duplicate hold filled notifications
1260 my $request = GetReserveInfo($borrowernumber, $biblionumber);
1261 my $already_on_shelf = ($request && $request->{found} eq 'W') ? 1 : 0;
1262
1263 # If we affect a reserve that has to be transfered, don't set to Waiting
1264 my $query;
1265 if ($transferToDo) {
1266 $query = "
1267 UPDATE reserves
1268 SET priority = 0,
1269 itemnumber = ?,
1270 found = 'T'
1271 WHERE borrowernumber = ?
1272 AND biblionumber = ?
1273 ";
1274 }
1275 else {
1276 # affect the reserve to Waiting as well.
1277 $query = "
1278 UPDATE reserves
1279 SET priority = 0,
1280 found = 'W',
1281 waitingdate = NOW(),
1282 itemnumber = ?
1283 WHERE borrowernumber = ?
1284 AND biblionumber = ?
1285 ";
1286 }
1287 $sth = $dbh->prepare($query);
1288 $sth->execute( $itemnumber, $borrowernumber,$biblionumber);
1289 _koha_notify_reserve( $itemnumber, $borrowernumber, $biblionumber ) if ( !$transferToDo && !$already_on_shelf );
1290
1291 if ( C4::Context->preference("ReturnToShelvingCart") ) {
1292 CartToShelf( $itemnumber );
1293 }
1294
1295 return;
1296}
1297
1298=head2 ModReserveCancelAll
1299
- -
1306sub ModReserveCancelAll {
1307 my $messages;
1308 my $nextreservinfo;
1309 my ( $itemnumber, $borrowernumber ) = @_;
1310
1311 #step 1 : cancel the reservation
1312 my $CancelReserve = CancelReserve( undef, $itemnumber, $borrowernumber );
1313
1314 #step 2 launch the subroutine of the others reserves
1315 ( $messages, $nextreservinfo ) = GetOtherReserves($itemnumber);
1316
1317 return ( $messages, $nextreservinfo );
1318}
1319
1320=head2 ModReserveMinusPriority
1321
- -
1328sub ModReserveMinusPriority {
1329 my ( $itemnumber, $borrowernumber, $biblionumber ) = @_;
1330
1331 #first step update the value of the first person on reserv
1332 my $dbh = C4::Context->dbh;
1333 my $query = "
1334 UPDATE reserves
1335 SET priority = 0 , itemnumber = ?
1336 WHERE borrowernumber=?
1337 AND biblionumber=?
1338 ";
1339 my $sth_upd = $dbh->prepare($query);
1340 $sth_upd->execute( $itemnumber, $borrowernumber, $biblionumber );
1341 # second step update all others reservs
1342 _FixPriority($biblionumber, $borrowernumber, '0');
1343}
1344
1345=head2 GetReserveInfo
1346
- -
1354sub GetReserveInfo {
1355 my ( $borrowernumber, $biblionumber ) = @_;
1356 my $dbh = C4::Context->dbh;
1357 my $strsth="SELECT
1358 reservedate,
1359 reservenotes,
1360 reserves.borrowernumber,
1361 reserves.biblionumber,
1362 reserves.branchcode,
1363 reserves.waitingdate,
1364 notificationdate,
1365 reminderdate,
1366 priority,
1367 found,
1368 firstname,
1369 surname,
1370 phone,
1371 email,
1372 address,
1373 address2,
1374 cardnumber,
1375 city,
1376 zipcode,
1377 biblio.title,
1378 biblio.author,
1379 items.holdingbranch,
1380 items.itemcallnumber,
1381 items.itemnumber,
1382 items.location,
1383 barcode,
1384 notes
1385 FROM reserves
1386 LEFT JOIN items USING(itemnumber)
1387 LEFT JOIN borrowers USING(borrowernumber)
1388 LEFT JOIN biblio ON (reserves.biblionumber=biblio.biblionumber)
1389 WHERE
1390 reserves.borrowernumber=?
1391 AND reserves.biblionumber=?";
1392 my $sth = $dbh->prepare($strsth);
1393 $sth->execute($borrowernumber,$biblionumber);
1394
1395 my $data = $sth->fetchrow_hashref;
1396 return $data;
1397
1398}
1399
1400=head2 IsAvailableForItemLevelRequest
1401
- -
1427sub IsAvailableForItemLevelRequest {
1428 my $itemnumber = shift;
1429
1430 my $item = GetItem($itemnumber);
1431
1432 # must check the notforloan setting of the itemtype
1433 # FIXME - a lot of places in the code do this
1434 # or something similar - need to be
1435 # consolidated
1436 my $dbh = C4::Context->dbh;
1437 my $notforloan_query;
1438 if (C4::Context->preference('item-level_itypes')) {
1439 $notforloan_query = "SELECT itemtypes.notforloan
1440 FROM items
1441 JOIN itemtypes ON (itemtypes.itemtype = items.itype)
1442 WHERE itemnumber = ?";
1443 } else {
1444 $notforloan_query = "SELECT itemtypes.notforloan
1445 FROM items
1446 JOIN biblioitems USING (biblioitemnumber)
1447 JOIN itemtypes USING (itemtype)
1448 WHERE itemnumber = ?";
1449 }
1450 my $sth = $dbh->prepare($notforloan_query);
1451 $sth->execute($itemnumber);
1452 my $notforloan_per_itemtype = 0;
1453 if (my ($notforloan) = $sth->fetchrow_array) {
1454 $notforloan_per_itemtype = 1 if $notforloan;
1455 }
1456
1457 my $available_per_item = 1;
1458 $available_per_item = 0 if $item->{itemlost} or
1459 ( $item->{notforloan} > 0 ) or
1460 ($item->{damaged} and not C4::Context->preference('AllowHoldsOnDamagedItems')) or
1461 $item->{wthdrawn} or
1462 $notforloan_per_itemtype;
1463
1464
1465 if (C4::Context->preference('AllowOnShelfHolds')) {
1466 return $available_per_item;
1467 } else {
1468 return ($available_per_item and ($item->{onloan} or GetReserveStatus($itemnumber) eq "Waiting"));
1469 }
1470}
1471
1472=head2 AlterPriority
1473
- -
1481sub AlterPriority {
1482 my ( $where, $borrowernumber, $biblionumber ) = @_;
1483
1484 my $dbh = C4::Context->dbh;
1485
1486 ## Find this reserve
1487 my $sth = $dbh->prepare('SELECT * FROM reserves WHERE biblionumber = ? AND borrowernumber = ? AND cancellationdate IS NULL');
1488 $sth->execute( $biblionumber, $borrowernumber );
1489 my $reserve = $sth->fetchrow_hashref();
1490 $sth->finish();
1491
1492 if ( $where eq 'up' || $where eq 'down' ) {
1493
1494 my $priority = $reserve->{'priority'};
1495 $priority = $where eq 'up' ? $priority - 1 : $priority + 1;
1496 _FixPriority( $biblionumber, $borrowernumber, $priority )
1497
1498 } elsif ( $where eq 'top' ) {
1499
1500 _FixPriority( $biblionumber, $borrowernumber, '1' )
1501
1502 } elsif ( $where eq 'bottom' ) {
1503
1504 _FixPriority( $biblionumber, $borrowernumber, '999999' )
1505
1506 }
1507}
1508
1509=head2 ToggleLowestPriority
1510
- -
1517sub ToggleLowestPriority {
1518 my ( $borrowernumber, $biblionumber ) = @_;
1519
1520 my $dbh = C4::Context->dbh;
1521
1522 my $sth = $dbh->prepare(
1523 "UPDATE reserves SET lowestPriority = NOT lowestPriority
1524 WHERE biblionumber = ?
1525 AND borrowernumber = ?"
1526 );
1527 $sth->execute(
1528 $biblionumber,
1529 $borrowernumber,
1530 );
1531 $sth->finish;
1532
1533 _FixPriority( $biblionumber, $borrowernumber, '999999' );
1534}
1535
1536=head2 ToggleSuspend
1537
- -
1546sub ToggleSuspend {
1547 my ( $borrowernumber, $biblionumber, $suspend_until ) = @_;
1548
1549 $suspend_until = output_pref( dt_from_string( $suspend_until ), 'iso' ) if ( $suspend_until );
1550
1551 my $do_until = ( $suspend_until ) ? '?' : 'NULL';
1552
1553 my $dbh = C4::Context->dbh;
1554
1555 my $sth = $dbh->prepare(
1556 "UPDATE reserves SET suspend = NOT suspend,
1557 suspend_until = CASE WHEN suspend = 0 THEN NULL ELSE $do_until END
1558 WHERE biblionumber = ?
1559 AND borrowernumber = ?
1560 ");
1561
1562 my @params;
1563 push( @params, $suspend_until ) if ( $suspend_until );
1564 push( @params, $biblionumber );
1565 push( @params, $borrowernumber );
1566
1567 $sth->execute( @params );
1568 $sth->finish;
1569}
1570
1571=head2 SuspendAll
1572
- -
1587sub SuspendAll {
1588 my %params = @_;
1589
1590 my $borrowernumber = $params{'borrowernumber'} || undef;
1591 my $biblionumber = $params{'biblionumber'} || undef;
1592 my $suspend_until = $params{'suspend_until'} || undef;
1593 my $suspend = defined( $params{'suspend'} ) ? $params{'suspend'} : 1;
1594
1595 $suspend_until = C4::Dates->new( $suspend_until )->output("iso") if ( defined( $suspend_until ) );
1596
1597 return unless ( $borrowernumber || $biblionumber );
1598
1599 my ( $query, $sth, $dbh, @query_params );
1600
1601 $query = "UPDATE reserves SET suspend = ? ";
1602 push( @query_params, $suspend );
1603 if ( !$suspend ) {
1604 $query .= ", suspend_until = NULL ";
1605 } elsif ( $suspend_until ) {
1606 $query .= ", suspend_until = ? ";
1607 push( @query_params, $suspend_until );
1608 }
1609 $query .= " WHERE ";
1610 if ( $borrowernumber ) {
1611 $query .= " borrowernumber = ? ";
1612 push( @query_params, $borrowernumber );
1613 }
1614 $query .= " AND " if ( $borrowernumber && $biblionumber );
1615 if ( $biblionumber ) {
1616 $query .= " biblionumber = ? ";
1617 push( @query_params, $biblionumber );
1618 }
1619 $query .= " AND found IS NULL ";
1620
1621 $dbh = C4::Context->dbh;
1622 $sth = $dbh->prepare( $query );
1623 $sth->execute( @query_params );
1624 $sth->finish;
1625}
1626
1627
1628=head2 _FixPriority
1629
- -
1641sub _FixPriority {
1642 my ( $biblio, $borrowernumber, $rank, $ignoreSetLowestRank ) = @_;
1643 my $dbh = C4::Context->dbh;
1644 if ( $rank eq "del" ) {
1645 CancelReserve( $biblio, undef, $borrowernumber );
1646 }
1647 if ( $rank eq "W" || $rank eq "0" ) {
1648
1649 # make sure priority for waiting or in-transit items is 0
1650 my $query = qq/
1651 UPDATE reserves
1652 SET priority = 0
1653 WHERE biblionumber = ?
1654 AND borrowernumber = ?
1655 AND found IN ('W', 'T')
1656 /;
1657 my $sth = $dbh->prepare($query);
1658 $sth->execute( $biblio, $borrowernumber );
1659 }
1660 my @priority;
1661 my @reservedates;
1662
1663 # get whats left
1664# FIXME adding a new security in returned elements for changing priority,
1665# now, we don't care anymore any reservations with itemnumber linked (suppose a waiting reserve)
1666 # This is wrong a waiting reserve has W set
1667 # The assumption that having an itemnumber set means waiting is wrong and should be corrected any place it occurs
1668 my $query = qq/
1669 SELECT borrowernumber, reservedate, constrainttype
1670 FROM reserves
1671 WHERE biblionumber = ?
1672 AND ((found <> 'W' AND found <> 'T') or found is NULL)
1673 ORDER BY priority ASC
1674 /;
1675 my $sth = $dbh->prepare($query);
1676 $sth->execute($biblio);
1677 while ( my $line = $sth->fetchrow_hashref ) {
1678 push( @reservedates, $line );
1679 push( @priority, $line );
1680 }
1681
1682 # To find the matching index
1683 my $i;
1684 my $key = -1; # to allow for 0 to be a valid result
1685 for ( $i = 0 ; $i < @priority ; $i++ ) {
1686 if ( $borrowernumber == $priority[$i]->{'borrowernumber'} ) {
1687 $key = $i; # save the index
1688 last;
1689 }
1690 }
1691
1692 # if index exists in array then move it to new position
1693 if ( $key > -1 && $rank ne 'del' && $rank > 0 ) {
1694 my $new_rank = $rank -
1695 1; # $new_rank is what you want the new index to be in the array
1696 my $moving_item = splice( @priority, $key, 1 );
1697 splice( @priority, $new_rank, 0, $moving_item );
1698 }
1699
1700 # now fix the priority on those that are left....
1701 $query = "
1702 UPDATE reserves
1703 SET priority = ?
1704 WHERE biblionumber = ?
1705 AND borrowernumber = ?
1706 AND reservedate = ?
1707 AND found IS NULL
1708 ";
1709 $sth = $dbh->prepare($query);
1710 for ( my $j = 0 ; $j < @priority ; $j++ ) {
1711 $sth->execute(
1712 $j + 1, $biblio,
1713 $priority[$j]->{'borrowernumber'},
1714 $priority[$j]->{'reservedate'}
1715 );
1716 $sth->finish;
1717 }
1718
1719 $sth = $dbh->prepare( "SELECT borrowernumber FROM reserves WHERE lowestPriority = 1 ORDER BY priority" );
1720 $sth->execute();
1721
1722 unless ( $ignoreSetLowestRank ) {
1723 while ( my $res = $sth->fetchrow_hashref() ) {
1724 _FixPriority( $biblio, $res->{'borrowernumber'}, '999999', 1 );
1725 }
1726 }
1727}
1728
1729=head2 _Findgroupreserve
1730
- -
1746sub _Findgroupreserve {
1747 my ( $bibitem, $biblio, $itemnumber ) = @_;
1748 my $dbh = C4::Context->dbh;
1749
1750 # TODO: consolidate at least the SELECT portion of the first 2 queries to a common $select var.
1751 # check for exact targetted match
1752 my $item_level_target_query = qq/
1753 SELECT reserves.biblionumber AS biblionumber,
1754 reserves.borrowernumber AS borrowernumber,
1755 reserves.reservedate AS reservedate,
1756 reserves.branchcode AS branchcode,
1757 reserves.cancellationdate AS cancellationdate,
1758 reserves.found AS found,
1759 reserves.reservenotes AS reservenotes,
1760 reserves.priority AS priority,
1761 reserves.timestamp AS timestamp,
1762 biblioitems.biblioitemnumber AS biblioitemnumber,
1763 reserves.itemnumber AS itemnumber
1764 FROM reserves
1765 JOIN biblioitems USING (biblionumber)
1766 JOIN hold_fill_targets USING (biblionumber, borrowernumber, itemnumber)
1767 WHERE found IS NULL
1768 AND priority > 0
1769 AND item_level_request = 1
1770 AND itemnumber = ?
1771 AND reservedate <= CURRENT_DATE()
1772 AND suspend = 0
1773 /;
1774 my $sth = $dbh->prepare($item_level_target_query);
1775 $sth->execute($itemnumber);
1776 my @results;
1777 if ( my $data = $sth->fetchrow_hashref ) {
1778 push( @results, $data );
1779 }
1780 return @results if @results;
1781
1782 # check for title-level targetted match
1783 my $title_level_target_query = qq/
1784 SELECT reserves.biblionumber AS biblionumber,
1785 reserves.borrowernumber AS borrowernumber,
1786 reserves.reservedate AS reservedate,
1787 reserves.branchcode AS branchcode,
1788 reserves.cancellationdate AS cancellationdate,
1789 reserves.found AS found,
1790 reserves.reservenotes AS reservenotes,
1791 reserves.priority AS priority,
1792 reserves.timestamp AS timestamp,
1793 biblioitems.biblioitemnumber AS biblioitemnumber,
1794 reserves.itemnumber AS itemnumber
1795 FROM reserves
1796 JOIN biblioitems USING (biblionumber)
1797 JOIN hold_fill_targets USING (biblionumber, borrowernumber)
1798 WHERE found IS NULL
1799 AND priority > 0
1800 AND item_level_request = 0
1801 AND hold_fill_targets.itemnumber = ?
1802 AND reservedate <= CURRENT_DATE()
1803 AND suspend = 0
1804 /;
1805 $sth = $dbh->prepare($title_level_target_query);
1806 $sth->execute($itemnumber);
1807 @results = ();
1808 if ( my $data = $sth->fetchrow_hashref ) {
1809 push( @results, $data );
1810 }
1811 return @results if @results;
1812
1813 my $query = qq/
1814 SELECT reserves.biblionumber AS biblionumber,
1815 reserves.borrowernumber AS borrowernumber,
1816 reserves.reservedate AS reservedate,
1817 reserves.waitingdate AS waitingdate,
1818 reserves.branchcode AS branchcode,
1819 reserves.cancellationdate AS cancellationdate,
1820 reserves.found AS found,
1821 reserves.reservenotes AS reservenotes,
1822 reserves.priority AS priority,
1823 reserves.timestamp AS timestamp,
1824 reserveconstraints.biblioitemnumber AS biblioitemnumber,
1825 reserves.itemnumber AS itemnumber
1826 FROM reserves
1827 LEFT JOIN reserveconstraints ON reserves.biblionumber = reserveconstraints.biblionumber
1828 WHERE reserves.biblionumber = ?
1829 AND ( ( reserveconstraints.biblioitemnumber = ?
1830 AND reserves.borrowernumber = reserveconstraints.borrowernumber
1831 AND reserves.reservedate = reserveconstraints.reservedate )
1832 OR reserves.constrainttype='a' )
1833 AND (reserves.itemnumber IS NULL OR reserves.itemnumber = ?)
1834 AND reserves.reservedate <= CURRENT_DATE()
1835 AND suspend = 0
1836 /;
1837 $sth = $dbh->prepare($query);
1838 $sth->execute( $biblio, $bibitem, $itemnumber );
1839 @results = ();
1840 while ( my $data = $sth->fetchrow_hashref ) {
1841 push( @results, $data );
1842 }
1843 return @results;
1844}
1845
1846=head2 _koha_notify_reserve
1847
- -
1855sub _koha_notify_reserve {
1856 my ($itemnumber, $borrowernumber, $biblionumber) = @_;
1857
1858 my $dbh = C4::Context->dbh;
1859 my $borrower = C4::Members::GetMember(borrowernumber => $borrowernumber);
1860
1861 # Try to get the borrower's email address
1862 my $to_address = C4::Members::GetNoticeEmailAddress($borrowernumber);
1863
1864 my $letter_code;
1865 my $print_mode = 0;
1866 my $messagingprefs;
1867 if ( $to_address || $borrower->{'smsalertnumber'} ) {
1868 $messagingprefs = C4::Members::Messaging::GetMessagingPreferences( { borrowernumber => $borrowernumber, message_name => 'Hold_Filled' } );
1869 } else {
1870 $print_mode = 1;
1871 }
1872
1873 my $sth = $dbh->prepare("
1874 SELECT *
1875 FROM reserves
1876 WHERE borrowernumber = ?
1877 AND biblionumber = ?
1878 ");
1879 $sth->execute( $borrowernumber, $biblionumber );
1880 my $reserve = $sth->fetchrow_hashref;
1881 my $branch_details = GetBranchDetail( $reserve->{'branchcode'} );
1882
1883 my $admin_email_address = $branch_details->{'branchemail'} || C4::Context->preference('KohaAdminEmailAddress');
1884
1885 my %letter_params = (
1886 module => 'reserves',
1887 branchcode => $reserve->{branchcode},
1888 tables => {
1889 'branches' => $branch_details,
1890 'borrowers' => $borrower,
1891 'biblio' => $biblionumber,
1892 'reserves' => $reserve,
1893 'items', $reserve->{'itemnumber'},
1894 },
1895 substitute => { today => C4::Dates->new()->output() },
1896 );
1897
1898
1899 if ( $print_mode ) {
1900 $letter_params{ 'letter_code' } = 'HOLD_PRINT';
1901 my $letter = C4::Letters::GetPreparedLetter ( %letter_params ) or die "Could not find a letter called '$letter_params{'letter_code'}' in the 'reserves' module";
1902
1903 C4::Letters::EnqueueLetter( {
1904 letter => $letter,
1905 borrowernumber => $borrowernumber,
1906 message_transport_type => 'print',
1907 } );
1908
1909 return;
1910 }
1911
1912 if ( $to_address && defined $messagingprefs->{transports}->{'email'} ) {
1913 $letter_params{ 'letter_code' } = $messagingprefs->{transports}->{'email'};
1914 my $letter = C4::Letters::GetPreparedLetter ( %letter_params ) or die "Could not find a letter called '$letter_params{'letter_code'}' in the 'reserves' module";
1915
1916 C4::Letters::EnqueueLetter(
1917 { letter => $letter,
1918 borrowernumber => $borrowernumber,
1919 message_transport_type => 'email',
1920 from_address => $admin_email_address,
1921 }
1922 );
1923 }
1924
1925 if ( $borrower->{'smsalertnumber'} && defined $messagingprefs->{transports}->{'sms'} ) {
1926 $letter_params{ 'letter_code' } = $messagingprefs->{transports}->{'sms'};
1927 my $letter = C4::Letters::GetPreparedLetter ( %letter_params ) or die "Could not find a letter called '$letter_params{'letter_code'}' in the 'reserves' module";
1928
1929 C4::Letters::EnqueueLetter(
1930 { letter => $letter,
1931 borrowernumber => $borrowernumber,
1932 message_transport_type => 'sms',
1933 }
1934 );
1935 }
1936}
1937
1938=head2 _ShiftPriorityByDateAndPriority
1939
- -
1956sub _ShiftPriorityByDateAndPriority {
1957 my ( $biblio, $resdate, $new_priority ) = @_;
1958
1959 my $dbh = C4::Context->dbh;
1960 my $query = "SELECT priority FROM reserves WHERE biblionumber = ? AND ( reservedate > ? OR priority > ? ) ORDER BY priority ASC LIMIT 1";
1961 my $sth = $dbh->prepare( $query );
1962 $sth->execute( $biblio, $resdate, $new_priority );
1963 my $min_priority = $sth->fetchrow;
1964 # if no such matches are found, $new_priority remains as original value
1965 $new_priority = $min_priority if ( $min_priority );
1966
1967 # Shift the priority up by one; works in conjunction with the next SQL statement
1968 $query = "UPDATE reserves
1969 SET priority = priority+1
1970 WHERE biblionumber = ?
1971 AND borrowernumber = ?
1972 AND reservedate = ?
1973 AND found IS NULL";
1974 my $sth_update = $dbh->prepare( $query );
1975
1976 # Select all reserves for the biblio with priority greater than $new_priority, and order greatest to least
1977 $query = "SELECT borrowernumber, reservedate FROM reserves WHERE priority >= ? AND biblionumber = ? ORDER BY priority DESC";
1978 $sth = $dbh->prepare( $query );
1979 $sth->execute( $new_priority, $biblio );
1980 while ( my $row = $sth->fetchrow_hashref ) {
1981 $sth_update->execute( $biblio, $row->{borrowernumber}, $row->{reservedate} );
1982 }
1983
1984 return $new_priority; # so the caller knows what priority they wind up receiving
1985}
1986
1987=head2 MoveReserve
1988
- -
1996sub MoveReserve {
1997 my ( $itemnumber, $borrowernumber, $cancelreserve ) = @_;
1998
1999 my ( $restype, $res, $all_reserves ) = CheckReserves( $itemnumber );
2000 return unless $res;
2001
2002 my $biblionumber = $res->{biblionumber};
2003 my $biblioitemnumber = $res->{biblioitemnumber};
2004
2005 if ($res->{borrowernumber} == $borrowernumber) {
2006 ModReserveFill($res);
2007 }
2008 else {
2009 # warn "Reserved";
2010 # The item is reserved by someone else.
2011 # Find this item in the reserves
2012
2013 my $borr_res;
2014 foreach (@$all_reserves) {
2015 $_->{'borrowernumber'} == $borrowernumber or next;
2016 $_->{'biblionumber'} == $biblionumber or next;
2017
2018 $borr_res = $_;
2019 last;
2020 }
2021
2022 if ( $borr_res ) {
2023 # The item is reserved by the current patron
2024 ModReserveFill($borr_res);
2025 }
2026
2027 if ( $cancelreserve eq 'revert' ) { ## Revert waiting reserve to priority 1
2028 RevertWaitingStatus({ itemnumber => $itemnumber });
2029 }
2030 elsif ( $cancelreserve eq 'cancel' || $cancelreserve ) { # cancel reserves on this item
2031 CancelReserve(0, $res->{'itemnumber'}, $res->{'borrowernumber'});
2032 CancelReserve($res->{'biblionumber'}, 0, $res->{'borrowernumber'});
2033 }
2034 }
2035}
2036
2037=head2 MergeHolds
2038
- -
2045sub MergeHolds {
2046 my ( $dbh, $to_biblio, $from_biblio ) = @_;
2047 my $sth = $dbh->prepare(
2048 "SELECT count(*) as reservenumber FROM reserves WHERE biblionumber = ?"
2049 );
2050 $sth->execute($from_biblio);
2051 if ( my $data = $sth->fetchrow_hashref() ) {
2052
2053 # holds exist on old record, if not we don't need to do anything
2054 $sth = $dbh->prepare(
2055 "UPDATE reserves SET biblionumber = ? WHERE biblionumber = ?");
2056 $sth->execute( $to_biblio, $from_biblio );
2057
2058 # Reorder by date
2059 # don't reorder those already waiting
2060
2061 $sth = $dbh->prepare(
2062"SELECT * FROM reserves WHERE biblionumber = ? AND (found <> ? AND found <> ? OR found is NULL) ORDER BY reservedate ASC"
2063 );
2064 my $upd_sth = $dbh->prepare(
2065"UPDATE reserves SET priority = ? WHERE biblionumber = ? AND borrowernumber = ?
2066 AND reservedate = ? AND constrainttype = ? AND (itemnumber = ? or itemnumber is NULL) "
2067 );
2068 $sth->execute( $to_biblio, 'W', 'T' );
2069 my $priority = 1;
2070 while ( my $reserve = $sth->fetchrow_hashref() ) {
2071 $upd_sth->execute(
2072 $priority, $to_biblio,
2073 $reserve->{'borrowernumber'}, $reserve->{'reservedate'},
2074 $reserve->{'constrainttype'}, $reserve->{'itemnumber'}
2075 );
2076 $priority++;
2077 }
2078 }
2079}
2080
2081=head2 RevertWaitingStatus
2082
- -
2095sub RevertWaitingStatus {
2096 my ( $params ) = @_;
2097 my $itemnumber = $params->{'itemnumber'};
2098
2099 return unless ( $itemnumber );
2100
2101 my $dbh = C4::Context->dbh;
2102
2103 ## Get the waiting reserve we want to revert
2104 my $query = "
2105 SELECT * FROM reserves
2106 WHERE itemnumber = ?
2107 AND found IS NOT NULL
2108 ";
2109 my $sth = $dbh->prepare( $query );
2110 $sth->execute( $itemnumber );
2111 my $reserve = $sth->fetchrow_hashref();
2112
2113 ## Increment the priority of all other non-waiting
2114 ## reserves for this bib record
2115 $query = "
2116 UPDATE reserves
2117 SET
2118 priority = priority + 1
2119 WHERE
2120 biblionumber = ?
2121 AND
2122 priority > 0
2123 ";
2124 $sth = $dbh->prepare( $query );
2125 $sth->execute( $reserve->{'biblionumber'} );
2126
2127 ## Fix up the currently waiting reserve
2128 $query = "
2129 UPDATE reserves
2130 SET
2131 priority = 1,
2132 found = NULL,
2133 waitingdate = NULL
2134 WHERE
2135 reserve_id = ?
2136 ";
2137 $sth = $dbh->prepare( $query );
2138 return $sth->execute( $reserve->{'reserve_id'} );
2139}
2140
2141=head2 ReserveSlip
2142
- -
2149sub ReserveSlip {
2150 my ($branch, $borrowernumber, $biblionumber) = @_;
2151
2152# return unless ( C4::Context->boolean_preference('printreserveslips') );
2153
2154 my $reserve = GetReserveInfo($borrowernumber,$biblionumber )
2155 or return;
2156
2157 return C4::Letters::GetPreparedLetter (
2158 module => 'circulation',
2159 letter_code => 'RESERVESLIP',
2160 branchcode => $branch,
2161 tables => {
2162 'reserves' => $reserve,
2163 'branches' => $reserve->{branchcode},
2164 'borrowers' => $reserve->{borrowernumber},
2165 'biblio' => $reserve->{biblionumber},
2166 'items' => $reserve->{itemnumber},
2167 },
2168 );
2169}
2170
2171=head1 AUTHOR
2172
- -
217714µs1;