|
Lines 68-80
This modules provides somes functions to deal with reservations.
Link Here
|
| 68 |
The complete workflow is : |
68 |
The complete workflow is : |
| 69 |
==== 1st use case ==== |
69 |
==== 1st use case ==== |
| 70 |
patron request a document, 1st available : P >0, F=NULL, I=NULL |
70 |
patron request a document, 1st available : P >0, F=NULL, I=NULL |
| 71 |
a library having it run "transfertodo", and clic on the list |
71 |
a library having it run "transfertodo", and clic on the list |
| 72 |
if there is no transfer to do, the reserve waiting |
72 |
if there is no transfer to do, the reserve waiting |
| 73 |
patron can pick it up P =0, F=W, I=filled |
73 |
patron can pick it up P =0, F=W, I=filled |
| 74 |
if there is a transfer to do, write in branchtransfer P =0, F=T, I=filled |
74 |
if there is a transfer to do, write in branchtransfer P =0, F=T, I=filled |
| 75 |
The pickup library recieve the book, it check in P =0, F=W, I=filled |
75 |
The pickup library recieve the book, it check in P =0, F=W, I=filled |
| 76 |
The patron borrow the book P =0, F=F, I=filled |
76 |
The patron borrow the book P =0, F=F, I=filled |
| 77 |
|
77 |
|
| 78 |
==== 2nd use case ==== |
78 |
==== 2nd use case ==== |
| 79 |
patron requests a document, a given item, |
79 |
patron requests a document, a given item, |
| 80 |
If pickup is holding branch P =0, F=W, I=filled |
80 |
If pickup is holding branch P =0, F=W, I=filled |
|
Lines 93-99
BEGIN {
Link Here
|
| 93 |
@ISA = qw(Exporter); |
93 |
@ISA = qw(Exporter); |
| 94 |
@EXPORT = qw( |
94 |
@EXPORT = qw( |
| 95 |
&AddReserve |
95 |
&AddReserve |
| 96 |
|
96 |
|
| 97 |
&GetReservesFromItemnumber |
97 |
&GetReservesFromItemnumber |
| 98 |
&GetReservesFromBiblionumber |
98 |
&GetReservesFromBiblionumber |
| 99 |
&GetReservesFromBorrowernumber |
99 |
&GetReservesFromBorrowernumber |
|
Lines 103-111
BEGIN {
Link Here
|
| 103 |
&GetReserveFee |
103 |
&GetReserveFee |
| 104 |
&GetReserveInfo |
104 |
&GetReserveInfo |
| 105 |
&GetReserveStatus |
105 |
&GetReserveStatus |
| 106 |
|
106 |
|
| 107 |
&GetOtherReserves |
107 |
&GetOtherReserves |
| 108 |
|
108 |
|
| 109 |
&ModReserveFill |
109 |
&ModReserveFill |
| 110 |
&ModReserveAffect |
110 |
&ModReserveAffect |
| 111 |
&ModReserve |
111 |
&ModReserve |
|
Lines 113-119
BEGIN {
Link Here
|
| 113 |
&ModReserveCancelAll |
113 |
&ModReserveCancelAll |
| 114 |
&ModReserveMinusPriority |
114 |
&ModReserveMinusPriority |
| 115 |
&MoveReserve |
115 |
&MoveReserve |
| 116 |
|
116 |
|
| 117 |
&CheckReserves |
117 |
&CheckReserves |
| 118 |
&CanBookBeReserved |
118 |
&CanBookBeReserved |
| 119 |
&CanItemBeReserved |
119 |
&CanItemBeReserved |
|
Lines 123-129
BEGIN {
Link Here
|
| 123 |
&AutoUnsuspendReserves |
123 |
&AutoUnsuspendReserves |
| 124 |
|
124 |
|
| 125 |
&IsAvailableForItemLevelRequest |
125 |
&IsAvailableForItemLevelRequest |
| 126 |
|
126 |
|
|
|
127 |
&OPACItemHoldsAllowed |
| 128 |
|
| 127 |
&AlterPriority |
129 |
&AlterPriority |
| 128 |
&ToggleLowestPriority |
130 |
&ToggleLowestPriority |
| 129 |
|
131 |
|
|
Lines 132-138
BEGIN {
Link Here
|
| 132 |
&SuspendAll |
134 |
&SuspendAll |
| 133 |
); |
135 |
); |
| 134 |
@EXPORT_OK = qw( MergeHolds ); |
136 |
@EXPORT_OK = qw( MergeHolds ); |
| 135 |
} |
137 |
} |
| 136 |
|
138 |
|
| 137 |
=head2 AddReserve |
139 |
=head2 AddReserve |
| 138 |
|
140 |
|
|
Lines 240-246
sub AddReserve {
Link Here
|
| 240 |
foreach (@$bibitems) { |
242 |
foreach (@$bibitems) { |
| 241 |
$sth->execute($borrowernumber, $biblionumber, $resdate, $_); |
243 |
$sth->execute($borrowernumber, $biblionumber, $resdate, $_); |
| 242 |
} |
244 |
} |
| 243 |
|
245 |
|
| 244 |
return; # FIXME: why not have a useful return value? |
246 |
return; # FIXME: why not have a useful return value? |
| 245 |
} |
247 |
} |
| 246 |
|
248 |
|
|
Lines 302-308
sub GetReservesFromBiblionumber {
Link Here
|
| 302 |
push( @bibitemno, $bibitemnos ); # FIXME: inefficient: use fetchall_arrayref |
304 |
push( @bibitemno, $bibitemnos ); # FIXME: inefficient: use fetchall_arrayref |
| 303 |
} |
305 |
} |
| 304 |
my $count = scalar @bibitemno; |
306 |
my $count = scalar @bibitemno; |
| 305 |
|
307 |
|
| 306 |
# if we have two or more different specific itemtypes |
308 |
# if we have two or more different specific itemtypes |
| 307 |
# reserved by same person on same day |
309 |
# reserved by same person on same day |
| 308 |
my $bdata; |
310 |
my $bdata; |
|
Lines 417-446
This function return 1 if an item can be issued by this borrower.
Link Here
|
| 417 |
|
419 |
|
| 418 |
sub CanItemBeReserved{ |
420 |
sub CanItemBeReserved{ |
| 419 |
my ($borrowernumber, $itemnumber) = @_; |
421 |
my ($borrowernumber, $itemnumber) = @_; |
| 420 |
|
422 |
|
| 421 |
my $dbh = C4::Context->dbh; |
423 |
my $dbh = C4::Context->dbh; |
| 422 |
my $allowedreserves = 0; |
424 |
my $allowedreserves = 0; |
| 423 |
|
425 |
|
| 424 |
my $controlbranch = C4::Context->preference('ReservesControlBranch'); |
426 |
my $controlbranch = C4::Context->preference('ReservesControlBranch'); |
| 425 |
my $itype = C4::Context->preference('item-level_itypes') ? "itype" : "itemtype"; |
427 |
my $itype = C4::Context->preference('item-level_itypes') ? "itype" : "itemtype"; |
| 426 |
|
428 |
|
| 427 |
# we retrieve borrowers and items informations # |
429 |
# we retrieve borrowers and items informations # |
| 428 |
my $item = GetItem($itemnumber); |
430 |
my $item = GetItem($itemnumber); |
| 429 |
my $borrower = C4::Members::GetMember('borrowernumber'=>$borrowernumber); |
431 |
my $borrower = C4::Members::GetMember('borrowernumber'=>$borrowernumber); |
| 430 |
|
432 |
|
| 431 |
# we retrieve user rights on this itemtype and branchcode |
433 |
# we retrieve user rights on this itemtype and branchcode |
| 432 |
my $sth = $dbh->prepare("SELECT categorycode, itemtype, branchcode, reservesallowed |
434 |
my $sth = $dbh->prepare("SELECT categorycode, itemtype, branchcode, reservesallowed |
| 433 |
FROM issuingrules |
435 |
FROM issuingrules |
| 434 |
WHERE (categorycode in (?,'*') ) |
436 |
WHERE (categorycode in (?,'*') ) |
| 435 |
AND (itemtype IN (?,'*')) |
437 |
AND (itemtype IN (?,'*')) |
| 436 |
AND (branchcode IN (?,'*')) |
438 |
AND (branchcode IN (?,'*')) |
| 437 |
ORDER BY |
439 |
ORDER BY |
| 438 |
categorycode DESC, |
440 |
categorycode DESC, |
| 439 |
itemtype DESC, |
441 |
itemtype DESC, |
| 440 |
branchcode DESC;" |
442 |
branchcode DESC;" |
| 441 |
); |
443 |
); |
| 442 |
|
444 |
|
| 443 |
my $querycount ="SELECT |
445 |
my $querycount ="SELECT |
| 444 |
count(*) as count |
446 |
count(*) as count |
| 445 |
FROM reserves |
447 |
FROM reserves |
| 446 |
LEFT JOIN items USING (itemnumber) |
448 |
LEFT JOIN items USING (itemnumber) |
|
Lines 448-460
sub CanItemBeReserved{
Link Here
|
| 448 |
LEFT JOIN borrowers USING (borrowernumber) |
450 |
LEFT JOIN borrowers USING (borrowernumber) |
| 449 |
WHERE borrowernumber = ? |
451 |
WHERE borrowernumber = ? |
| 450 |
"; |
452 |
"; |
| 451 |
|
453 |
|
| 452 |
|
454 |
|
| 453 |
my $itemtype = $item->{$itype}; |
455 |
my $itemtype = $item->{$itype}; |
| 454 |
my $categorycode = $borrower->{categorycode}; |
456 |
my $categorycode = $borrower->{categorycode}; |
| 455 |
my $branchcode = ""; |
457 |
my $branchcode = ""; |
| 456 |
my $branchfield = "reserves.branchcode"; |
458 |
my $branchfield = "reserves.branchcode"; |
| 457 |
|
459 |
|
| 458 |
if( $controlbranch eq "ItemHomeLibrary" ){ |
460 |
if( $controlbranch eq "ItemHomeLibrary" ){ |
| 459 |
$branchfield = "items.homebranch"; |
461 |
$branchfield = "items.homebranch"; |
| 460 |
$branchcode = $item->{homebranch}; |
462 |
$branchcode = $item->{homebranch}; |
|
Lines 462-495
sub CanItemBeReserved{
Link Here
|
| 462 |
$branchfield = "borrowers.branchcode"; |
464 |
$branchfield = "borrowers.branchcode"; |
| 463 |
$branchcode = $borrower->{branchcode}; |
465 |
$branchcode = $borrower->{branchcode}; |
| 464 |
} |
466 |
} |
| 465 |
|
467 |
|
| 466 |
# we retrieve rights |
468 |
# we retrieve rights |
| 467 |
$sth->execute($categorycode, $itemtype, $branchcode); |
469 |
$sth->execute($categorycode, $itemtype, $branchcode); |
| 468 |
if(my $rights = $sth->fetchrow_hashref()){ |
470 |
if(my $rights = $sth->fetchrow_hashref()){ |
| 469 |
$itemtype = $rights->{itemtype}; |
471 |
$itemtype = $rights->{itemtype}; |
| 470 |
$allowedreserves = $rights->{reservesallowed}; |
472 |
$allowedreserves = $rights->{reservesallowed}; |
| 471 |
}else{ |
473 |
}else{ |
| 472 |
$itemtype = '*'; |
474 |
$itemtype = '*'; |
| 473 |
} |
475 |
} |
| 474 |
|
476 |
|
| 475 |
# we retrieve count |
477 |
# we retrieve count |
| 476 |
|
478 |
|
| 477 |
$querycount .= "AND $branchfield = ?"; |
479 |
$querycount .= "AND $branchfield = ?"; |
| 478 |
|
480 |
|
| 479 |
$querycount .= " AND $itype = ?" if ($itemtype ne "*"); |
481 |
$querycount .= " AND $itype = ?" if ($itemtype ne "*"); |
| 480 |
my $sthcount = $dbh->prepare($querycount); |
482 |
my $sthcount = $dbh->prepare($querycount); |
| 481 |
|
483 |
|
| 482 |
if($itemtype eq "*"){ |
484 |
if($itemtype eq "*"){ |
| 483 |
$sthcount->execute($borrowernumber, $branchcode); |
485 |
$sthcount->execute($borrowernumber, $branchcode); |
| 484 |
}else{ |
486 |
}else{ |
| 485 |
$sthcount->execute($borrowernumber, $branchcode, $itemtype); |
487 |
$sthcount->execute($borrowernumber, $branchcode, $itemtype); |
| 486 |
} |
488 |
} |
| 487 |
|
489 |
|
| 488 |
my $reservecount = "0"; |
490 |
my $reservecount = "0"; |
| 489 |
if(my $rowcount = $sthcount->fetchrow_hashref()){ |
491 |
if(my $rowcount = $sthcount->fetchrow_hashref()){ |
| 490 |
$reservecount = $rowcount->{count}; |
492 |
$reservecount = $rowcount->{count}; |
| 491 |
} |
493 |
} |
| 492 |
|
|
|
| 493 |
# we check if it's ok or not |
494 |
# we check if it's ok or not |
| 494 |
if( $reservecount < $allowedreserves ){ |
495 |
if( $reservecount < $allowedreserves ){ |
| 495 |
return 1; |
496 |
return 1; |
|
Lines 688-695
sub GetReservesToBranch {
Link Here
|
| 688 |
my $dbh = C4::Context->dbh; |
689 |
my $dbh = C4::Context->dbh; |
| 689 |
my $sth = $dbh->prepare( |
690 |
my $sth = $dbh->prepare( |
| 690 |
"SELECT borrowernumber,reservedate,itemnumber,timestamp |
691 |
"SELECT borrowernumber,reservedate,itemnumber,timestamp |
| 691 |
FROM reserves |
692 |
FROM reserves |
| 692 |
WHERE priority='0' |
693 |
WHERE priority='0' |
| 693 |
AND branchcode=?" |
694 |
AND branchcode=?" |
| 694 |
); |
695 |
); |
| 695 |
$sth->execute( $frombranch ); |
696 |
$sth->execute( $frombranch ); |
|
Lines 712-718
sub GetReservesForBranch {
Link Here
|
| 712 |
my ($frombranch) = @_; |
713 |
my ($frombranch) = @_; |
| 713 |
my $dbh = C4::Context->dbh; |
714 |
my $dbh = C4::Context->dbh; |
| 714 |
my $query = "SELECT borrowernumber,reservedate,itemnumber,waitingdate |
715 |
my $query = "SELECT borrowernumber,reservedate,itemnumber,waitingdate |
| 715 |
FROM reserves |
716 |
FROM reserves |
| 716 |
WHERE priority='0' |
717 |
WHERE priority='0' |
| 717 |
AND found='W' "; |
718 |
AND found='W' "; |
| 718 |
if ($frombranch){ |
719 |
if ($frombranch){ |
|
Lines 737-747
sub GetReservesForBranch {
Link Here
|
| 737 |
|
738 |
|
| 738 |
sub GetReserveStatus { |
739 |
sub GetReserveStatus { |
| 739 |
my ($itemnumber) = @_; |
740 |
my ($itemnumber) = @_; |
| 740 |
|
741 |
|
| 741 |
my $dbh = C4::Context->dbh; |
742 |
my $dbh = C4::Context->dbh; |
| 742 |
|
743 |
|
| 743 |
my $itemstatus = $dbh->prepare("SELECT found FROM reserves WHERE itemnumber = ?"); |
744 |
my $itemstatus = $dbh->prepare("SELECT found FROM reserves WHERE itemnumber = ?"); |
| 744 |
|
745 |
|
| 745 |
$itemstatus->execute($itemnumber); |
746 |
$itemstatus->execute($itemnumber); |
| 746 |
my ($found) = $itemstatus->fetchrow_array; |
747 |
my ($found) = $itemstatus->fetchrow_array; |
| 747 |
return $found; |
748 |
return $found; |
|
Lines 803-809
sub CheckReserves {
Link Here
|
| 803 |
LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype |
804 |
LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype |
| 804 |
"; |
805 |
"; |
| 805 |
} |
806 |
} |
| 806 |
|
807 |
|
| 807 |
if ($item) { |
808 |
if ($item) { |
| 808 |
$sth = $dbh->prepare("$select WHERE itemnumber = ?"); |
809 |
$sth = $dbh->prepare("$select WHERE itemnumber = ?"); |
| 809 |
$sth->execute($item); |
810 |
$sth->execute($item); |
|
Lines 818-824
sub CheckReserves {
Link Here
|
| 818 |
return ( '' ) unless $itemnumber; # bail if we got nothing. |
819 |
return ( '' ) unless $itemnumber; # bail if we got nothing. |
| 819 |
|
820 |
|
| 820 |
# if item is not for loan it cannot be reserved either..... |
821 |
# if item is not for loan it cannot be reserved either..... |
| 821 |
# execpt where items.notforloan < 0 : This indicates the item is holdable. |
822 |
# execpt where items.notforloan < 0 : This indicates the item is holdable. |
| 822 |
return ( '' ) if ( $notforloan_per_item > 0 ) or $notforloan_per_itemtype; |
823 |
return ( '' ) if ( $notforloan_per_item > 0 ) or $notforloan_per_itemtype; |
| 823 |
|
824 |
|
| 824 |
# Find this item in the reserves |
825 |
# Find this item in the reserves |
|
Lines 873-879
sub CancelExpiredReserves {
Link Here
|
| 873 |
# Cancel reserves that have passed their expiration date. |
874 |
# Cancel reserves that have passed their expiration date. |
| 874 |
my $dbh = C4::Context->dbh; |
875 |
my $dbh = C4::Context->dbh; |
| 875 |
my $sth = $dbh->prepare( " |
876 |
my $sth = $dbh->prepare( " |
| 876 |
SELECT * FROM reserves WHERE DATE(expirationdate) < DATE( CURDATE() ) |
877 |
SELECT * FROM reserves WHERE DATE(expirationdate) < DATE( CURDATE() ) |
| 877 |
AND expirationdate IS NOT NULL |
878 |
AND expirationdate IS NOT NULL |
| 878 |
AND found IS NULL |
879 |
AND found IS NULL |
| 879 |
" ); |
880 |
" ); |
|
Lines 882-888
sub CancelExpiredReserves {
Link Here
|
| 882 |
while ( my $res = $sth->fetchrow_hashref() ) { |
883 |
while ( my $res = $sth->fetchrow_hashref() ) { |
| 883 |
CancelReserve( $res->{'biblionumber'}, '', $res->{'borrowernumber'} ); |
884 |
CancelReserve( $res->{'biblionumber'}, '', $res->{'borrowernumber'} ); |
| 884 |
} |
885 |
} |
| 885 |
|
886 |
|
| 886 |
# Cancel reserves that have been waiting too long |
887 |
# Cancel reserves that have been waiting too long |
| 887 |
if ( C4::Context->preference("ExpireReservesMaxPickUpDelay") ) { |
888 |
if ( C4::Context->preference("ExpireReservesMaxPickUpDelay") ) { |
| 888 |
my $max_pickup_delay = C4::Context->preference("ReservesMaxPickUpDelay"); |
889 |
my $max_pickup_delay = C4::Context->preference("ReservesMaxPickUpDelay"); |
|
Lines 1038-1049
If C<$rank> is 'del', the hold request is cancelled.
Link Here
|
| 1038 |
|
1039 |
|
| 1039 |
If C<$rank> is an integer greater than zero, the priority of |
1040 |
If C<$rank> is an integer greater than zero, the priority of |
| 1040 |
the request is set to that value. Since priority != 0 means |
1041 |
the request is set to that value. Since priority != 0 means |
| 1041 |
that the item is not waiting on the hold shelf, setting the |
1042 |
that the item is not waiting on the hold shelf, setting the |
| 1042 |
priority to a non-zero value also sets the request's found |
1043 |
priority to a non-zero value also sets the request's found |
| 1043 |
status and waiting date to NULL. |
1044 |
status and waiting date to NULL. |
| 1044 |
|
1045 |
|
| 1045 |
The optional C<$itemnumber> parameter is used only when |
1046 |
The optional C<$itemnumber> parameter is used only when |
| 1046 |
C<$rank> is a non-zero integer; if supplied, the itemnumber |
1047 |
C<$rank> is a non-zero integer; if supplied, the itemnumber |
| 1047 |
of the hold request is set accordingly; if omitted, the itemnumber |
1048 |
of the hold request is set accordingly; if omitted, the itemnumber |
| 1048 |
is cleared. |
1049 |
is cleared. |
| 1049 |
|
1050 |
|
|
Lines 1073-1092
sub ModReserve {
Link Here
|
| 1073 |
$query = qq/ |
1074 |
$query = qq/ |
| 1074 |
INSERT INTO old_reserves |
1075 |
INSERT INTO old_reserves |
| 1075 |
SELECT * |
1076 |
SELECT * |
| 1076 |
FROM reserves |
1077 |
FROM reserves |
| 1077 |
WHERE biblionumber = ? |
1078 |
WHERE biblionumber = ? |
| 1078 |
AND borrowernumber = ? |
1079 |
AND borrowernumber = ? |
| 1079 |
/; |
1080 |
/; |
| 1080 |
$sth = $dbh->prepare($query); |
1081 |
$sth = $dbh->prepare($query); |
| 1081 |
$sth->execute( $biblio, $borrower ); |
1082 |
$sth->execute( $biblio, $borrower ); |
| 1082 |
$query = qq/ |
1083 |
$query = qq/ |
| 1083 |
DELETE FROM reserves |
1084 |
DELETE FROM reserves |
| 1084 |
WHERE biblionumber = ? |
1085 |
WHERE biblionumber = ? |
| 1085 |
AND borrowernumber = ? |
1086 |
AND borrowernumber = ? |
| 1086 |
/; |
1087 |
/; |
| 1087 |
$sth = $dbh->prepare($query); |
1088 |
$sth = $dbh->prepare($query); |
| 1088 |
$sth->execute( $biblio, $borrower ); |
1089 |
$sth->execute( $biblio, $borrower ); |
| 1089 |
|
1090 |
|
| 1090 |
} |
1091 |
} |
| 1091 |
elsif ($rank =~ /^\d+/ and $rank > 0) { |
1092 |
elsif ($rank =~ /^\d+/ and $rank > 0) { |
| 1092 |
my $query = " |
1093 |
my $query = " |
|
Lines 1171-1177
sub ModReserveFill {
Link Here
|
| 1171 |
"; |
1172 |
"; |
| 1172 |
$sth = $dbh->prepare($query); |
1173 |
$sth = $dbh->prepare($query); |
| 1173 |
$sth->execute( $biblionumber, $resdate, $borrowernumber ); |
1174 |
$sth->execute( $biblionumber, $resdate, $borrowernumber ); |
| 1174 |
|
1175 |
|
| 1175 |
# now fix the priority on the others (if the priority wasn't |
1176 |
# now fix the priority on the others (if the priority wasn't |
| 1176 |
# already sorted!).... |
1177 |
# already sorted!).... |
| 1177 |
unless ( $priority == 0 ) { |
1178 |
unless ( $priority == 0 ) { |
|
Lines 1216-1222
with the biblionumber & the borrowernumber, we can affect the itemnumber
Link Here
|
| 1216 |
to the correct reserve. |
1217 |
to the correct reserve. |
| 1217 |
|
1218 |
|
| 1218 |
if $transferToDo is not set, then the status is set to "Waiting" as well. |
1219 |
if $transferToDo is not set, then the status is set to "Waiting" as well. |
| 1219 |
otherwise, a transfer is on the way, and the end of the transfer will |
1220 |
otherwise, a transfer is on the way, and the end of the transfer will |
| 1220 |
take care of the waiting status |
1221 |
take care of the waiting status |
| 1221 |
|
1222 |
|
| 1222 |
=cut |
1223 |
=cut |
|
Lines 1297-1303
sub ModReserveCancelAll {
Link Here
|
| 1297 |
|
1298 |
|
| 1298 |
&ModReserveMinusPriority($itemnumber,$borrowernumber,$biblionumber) |
1299 |
&ModReserveMinusPriority($itemnumber,$borrowernumber,$biblionumber) |
| 1299 |
|
1300 |
|
| 1300 |
Reduce the values of queuded list |
1301 |
Reduce the values of queuded list |
| 1301 |
|
1302 |
|
| 1302 |
=cut |
1303 |
=cut |
| 1303 |
|
1304 |
|
|
Lines 1308-1314
sub ModReserveMinusPriority {
Link Here
|
| 1308 |
my $dbh = C4::Context->dbh; |
1309 |
my $dbh = C4::Context->dbh; |
| 1309 |
my $query = " |
1310 |
my $query = " |
| 1310 |
UPDATE reserves |
1311 |
UPDATE reserves |
| 1311 |
SET priority = 0 , itemnumber = ? |
1312 |
SET priority = 0 , itemnumber = ? |
| 1312 |
WHERE borrowernumber=? |
1313 |
WHERE borrowernumber=? |
| 1313 |
AND biblionumber=? |
1314 |
AND biblionumber=? |
| 1314 |
"; |
1315 |
"; |
|
Lines 1330-1371
Current implementation this query should have a single result.
Link Here
|
| 1330 |
sub GetReserveInfo { |
1331 |
sub GetReserveInfo { |
| 1331 |
my ( $borrowernumber, $biblionumber ) = @_; |
1332 |
my ( $borrowernumber, $biblionumber ) = @_; |
| 1332 |
my $dbh = C4::Context->dbh; |
1333 |
my $dbh = C4::Context->dbh; |
| 1333 |
my $strsth="SELECT |
1334 |
my $strsth="SELECT |
| 1334 |
reservedate, |
1335 |
reservedate, |
| 1335 |
reservenotes, |
1336 |
reservenotes, |
| 1336 |
reserves.borrowernumber, |
1337 |
reserves.borrowernumber, |
| 1337 |
reserves.biblionumber, |
1338 |
reserves.biblionumber, |
| 1338 |
reserves.branchcode, |
1339 |
reserves.branchcode, |
| 1339 |
reserves.waitingdate, |
1340 |
reserves.waitingdate, |
| 1340 |
notificationdate, |
1341 |
notificationdate, |
| 1341 |
reminderdate, |
1342 |
reminderdate, |
| 1342 |
priority, |
1343 |
priority, |
| 1343 |
found, |
1344 |
found, |
| 1344 |
firstname, |
1345 |
firstname, |
| 1345 |
surname, |
1346 |
surname, |
| 1346 |
phone, |
1347 |
phone, |
| 1347 |
email, |
1348 |
email, |
| 1348 |
address, |
1349 |
address, |
| 1349 |
address2, |
1350 |
address2, |
| 1350 |
cardnumber, |
1351 |
cardnumber, |
| 1351 |
city, |
1352 |
city, |
| 1352 |
zipcode, |
1353 |
zipcode, |
| 1353 |
biblio.title, |
1354 |
biblio.title, |
| 1354 |
biblio.author, |
1355 |
biblio.author, |
| 1355 |
items.holdingbranch, |
1356 |
items.holdingbranch, |
| 1356 |
items.itemcallnumber, |
1357 |
items.itemcallnumber, |
| 1357 |
items.itemnumber, |
1358 |
items.itemnumber, |
| 1358 |
items.location, |
1359 |
items.location, |
| 1359 |
barcode, |
1360 |
barcode, |
| 1360 |
notes |
1361 |
notes |
| 1361 |
FROM reserves |
1362 |
FROM reserves |
| 1362 |
LEFT JOIN items USING(itemnumber) |
1363 |
LEFT JOIN items USING(itemnumber) |
| 1363 |
LEFT JOIN borrowers USING(borrowernumber) |
1364 |
LEFT JOIN borrowers USING(borrowernumber) |
| 1364 |
LEFT JOIN biblio ON (reserves.biblionumber=biblio.biblionumber) |
1365 |
LEFT JOIN biblio ON (reserves.biblionumber=biblio.biblionumber) |
| 1365 |
WHERE |
1366 |
WHERE |
| 1366 |
reserves.borrowernumber=? |
1367 |
reserves.borrowernumber=? |
| 1367 |
AND reserves.biblionumber=?"; |
1368 |
AND reserves.biblionumber=?"; |
| 1368 |
my $sth = $dbh->prepare($strsth); |
1369 |
my $sth = $dbh->prepare($strsth); |
| 1369 |
$sth->execute($borrowernumber,$biblionumber); |
1370 |
$sth->execute($borrowernumber,$biblionumber); |
| 1370 |
|
1371 |
|
| 1371 |
my $data = $sth->fetchrow_hashref; |
1372 |
my $data = $sth->fetchrow_hashref; |
|
Lines 1375-1396
sub GetReserveInfo {
Link Here
|
| 1375 |
|
1376 |
|
| 1376 |
=head2 IsAvailableForItemLevelRequest |
1377 |
=head2 IsAvailableForItemLevelRequest |
| 1377 |
|
1378 |
|
| 1378 |
my $is_available = IsAvailableForItemLevelRequest($itemnumber); |
1379 |
my $is_available = IsAvailableForItemLevelRequest($item_record,$borrower_record); |
| 1379 |
|
1380 |
|
| 1380 |
Checks whether a given item record is available for an |
1381 |
Checks whether a given item record is available for an |
| 1381 |
item-level hold request. An item is available if |
1382 |
item-level hold request. An item is available if |
| 1382 |
|
1383 |
|
| 1383 |
* it is not lost AND |
1384 |
* it is not lost AND |
| 1384 |
* it is not damaged AND |
1385 |
* it is not damaged AND |
| 1385 |
* it is not withdrawn AND |
1386 |
* it is not withdrawn AND |
| 1386 |
* does not have a not for loan value > 0 |
1387 |
* does not have a not for loan value > 0 |
| 1387 |
|
1388 |
|
| 1388 |
Whether or not the item is currently on loan is |
1389 |
Need to check the issuingrules onshelfholds column, |
| 1389 |
also checked - if the AllowOnShelfHolds system preference |
1390 |
if this is set items on the shelf can be placed on hold |
| 1390 |
is ON, an item can be requested even if it is currently |
|
|
| 1391 |
on loan to somebody else. If the system preference |
| 1392 |
is OFF, an item that is currently checked out cannot |
| 1393 |
be the target of an item-level hold request. |
| 1394 |
|
1391 |
|
| 1395 |
Note that IsAvailableForItemLevelRequest() does not |
1392 |
Note that IsAvailableForItemLevelRequest() does not |
| 1396 |
check if the staff operator is authorized to place |
1393 |
check if the staff operator is authorized to place |
|
Lines 1401-1450
and canreservefromotherbranches.
Link Here
|
| 1401 |
=cut |
1398 |
=cut |
| 1402 |
|
1399 |
|
| 1403 |
sub IsAvailableForItemLevelRequest { |
1400 |
sub IsAvailableForItemLevelRequest { |
| 1404 |
my $itemnumber = shift; |
1401 |
my $item = shift; |
| 1405 |
|
1402 |
my $borrower = shift; |
| 1406 |
my $item = GetItem($itemnumber); |
|
|
| 1407 |
|
1403 |
|
|
|
1404 |
my $dbh = C4::Context->dbh; |
| 1408 |
# must check the notforloan setting of the itemtype |
1405 |
# must check the notforloan setting of the itemtype |
| 1409 |
# FIXME - a lot of places in the code do this |
1406 |
# FIXME - a lot of places in the code do this |
| 1410 |
# or something similar - need to be |
1407 |
# or something similar - need to be |
| 1411 |
# consolidated |
1408 |
# consolidated |
| 1412 |
my $dbh = C4::Context->dbh; |
1409 |
my $itype; |
| 1413 |
my $notforloan_query; |
|
|
| 1414 |
if (C4::Context->preference('item-level_itypes')) { |
1410 |
if (C4::Context->preference('item-level_itypes')) { |
| 1415 |
$notforloan_query = "SELECT itemtypes.notforloan |
1411 |
# We cant trust GetItem to honour the syspref, so safest to do it ourselves |
| 1416 |
FROM items |
1412 |
# When GetItem is fixed, we can remove this |
| 1417 |
JOIN itemtypes ON (itemtypes.itemtype = items.itype) |
1413 |
$itype = $item->{itype}; |
| 1418 |
WHERE itemnumber = ?"; |
|
|
| 1419 |
} else { |
| 1420 |
$notforloan_query = "SELECT itemtypes.notforloan |
| 1421 |
FROM items |
| 1422 |
JOIN biblioitems USING (biblioitemnumber) |
| 1423 |
JOIN itemtypes USING (itemtype) |
| 1424 |
WHERE itemnumber = ?"; |
| 1425 |
} |
1414 |
} |
| 1426 |
my $sth = $dbh->prepare($notforloan_query); |
1415 |
else { |
| 1427 |
$sth->execute($itemnumber); |
1416 |
# XXX This is a bit dodgy. It relies on biblio itemtype column having different name. |
| 1428 |
my $notforloan_per_itemtype = 0; |
1417 |
# So if we already have a biblioitems join when calling this function, |
| 1429 |
if (my ($notforloan) = $sth->fetchrow_array) { |
1418 |
# we don't need to access the database again |
| 1430 |
$notforloan_per_itemtype = 1 if $notforloan; |
1419 |
$itype = $item->{itemtype}; |
| 1431 |
} |
1420 |
} |
|
|
1421 |
unless ($itype) { |
| 1422 |
my $query = "SELECT itemtype FROM biblioitems WHERE biblioitemnumber = ? "; |
| 1423 |
my $sth = $dbh->prepare($query); |
| 1424 |
$sth->execute($item->{biblioitemnumber}); |
| 1425 |
if (my $data = $sth->fetchrow_hashref()){ |
| 1426 |
$itype = $data->{itemtype}; |
| 1427 |
} |
| 1428 |
} |
| 1429 |
|
| 1430 |
my $notforloan_per_itemtype |
| 1431 |
= $dbh->selectrow_array("SELECT notforloan FROM itemtypes WHERE itemtype = ?", |
| 1432 |
undef, $itype); |
| 1432 |
|
1433 |
|
| 1433 |
my $available_per_item = 1; |
1434 |
return 0 if |
| 1434 |
$available_per_item = 0 if $item->{itemlost} or |
1435 |
$notforloan_per_itemtype || |
| 1435 |
( $item->{notforloan} > 0 ) or |
1436 |
$item->{itemlost} || |
| 1436 |
($item->{damaged} and not C4::Context->preference('AllowHoldsOnDamagedItems')) or |
1437 |
$item->{notforloan} > 0 || |
| 1437 |
$item->{wthdrawn} or |
1438 |
$item->{wthdrawn} || |
| 1438 |
$notforloan_per_itemtype; |
1439 |
($item->{damaged} && !C4::Context->preference('AllowHoldsOnDamagedItems')); |
| 1439 |
|
1440 |
|
| 1440 |
|
1441 |
|
| 1441 |
if (C4::Context->preference('AllowOnShelfHolds')) { |
1442 |
if (OnShelfHoldsAllowed($itype,$borrower->{categorycode},$item->{holdingbranch})) { |
| 1442 |
return $available_per_item; |
1443 |
return 1; |
| 1443 |
} else { |
1444 |
} else { |
| 1444 |
return ($available_per_item and ($item->{onloan} or GetReserveStatus($itemnumber) eq "W")); |
1445 |
return $item->{onloan} || GetReserveStatus($item->{itemnumber}) eq "W"; |
| 1445 |
} |
1446 |
} |
| 1446 |
} |
1447 |
} |
| 1447 |
|
1448 |
|
|
|
1449 |
=head2 OnShelfHoldsAllowed |
| 1450 |
|
| 1451 |
OnShelfHoldsAllowed($itemtype,$borrowercategory,$branchcode); |
| 1452 |
|
| 1453 |
Checks issuingrules, using the borrowers categorycode, the itemtype, and branchcode to see if onshelf |
| 1454 |
holds are allowed, returns true if so. |
| 1455 |
|
| 1456 |
=cut |
| 1457 |
|
| 1458 |
sub OnShelfHoldsAllowed { |
| 1459 |
my ($itype,$borrowercategory,$branchcode) = @_; |
| 1460 |
|
| 1461 |
my $query = "SELECT onshelfholds FROM issuingrules WHERE |
| 1462 |
(issuingrules.categorycode = ? OR issuingrules.categorycode = '*') |
| 1463 |
AND |
| 1464 |
(issuingrules.itemtype = ? OR issuingrules.itemtype = '*') |
| 1465 |
AND |
| 1466 |
(issuingrules.branchcode = ? OR issuingrules.branchcode = '*') |
| 1467 |
ORDER BY |
| 1468 |
issuingrules.categorycode desc, |
| 1469 |
issuingrules.itemtype desc, |
| 1470 |
issuingrules.branchcode desc |
| 1471 |
LIMIT 1"; |
| 1472 |
my $dbh = C4::Context->dbh; |
| 1473 |
my $onshelfholds = $dbh->selectrow_array($query, undef, $borrowercategory,$itype,$branchcode); |
| 1474 |
return $onshelfholds; |
| 1475 |
} |
| 1476 |
|
| 1448 |
=head2 AlterPriority |
1477 |
=head2 AlterPriority |
| 1449 |
|
1478 |
|
| 1450 |
AlterPriority( $where, $borrowernumber, $biblionumber, $reservedate ); |
1479 |
AlterPriority( $where, $borrowernumber, $biblionumber, $reservedate ); |
|
Lines 1466-1473
sub AlterPriority {
Link Here
|
| 1466 |
$sth->finish(); |
1495 |
$sth->finish(); |
| 1467 |
|
1496 |
|
| 1468 |
if ( $where eq 'up' || $where eq 'down' ) { |
1497 |
if ( $where eq 'up' || $where eq 'down' ) { |
| 1469 |
|
1498 |
|
| 1470 |
my $priority = $reserve->{'priority'}; |
1499 |
my $priority = $reserve->{'priority'}; |
| 1471 |
$priority = $where eq 'up' ? $priority - 1 : $priority + 1; |
1500 |
$priority = $where eq 'up' ? $priority - 1 : $priority + 1; |
| 1472 |
_FixPriority( $biblionumber, $borrowernumber, $priority ) |
1501 |
_FixPriority( $biblionumber, $borrowernumber, $priority ) |
| 1473 |
|
1502 |
|
|
Lines 1505-1511
sub ToggleLowestPriority {
Link Here
|
| 1505 |
$borrowernumber, |
1534 |
$borrowernumber, |
| 1506 |
); |
1535 |
); |
| 1507 |
$sth->finish; |
1536 |
$sth->finish; |
| 1508 |
|
1537 |
|
| 1509 |
_FixPriority( $biblionumber, $borrowernumber, '999999' ); |
1538 |
_FixPriority( $biblionumber, $borrowernumber, '999999' ); |
| 1510 |
} |
1539 |
} |
| 1511 |
|
1540 |
|
|
Lines 1612-1618
the array index (+1 as array starts from 0)
Link Here
|
| 1612 |
and if $rank is supplied will splice item from the array and splice it back in again |
1641 |
and if $rank is supplied will splice item from the array and splice it back in again |
| 1613 |
in new priority rank |
1642 |
in new priority rank |
| 1614 |
|
1643 |
|
| 1615 |
=cut |
1644 |
=cut |
| 1616 |
|
1645 |
|
| 1617 |
sub _FixPriority { |
1646 |
sub _FixPriority { |
| 1618 |
my ( $biblio, $borrowernumber, $rank, $ignoreSetLowestRank ) = @_; |
1647 |
my ( $biblio, $borrowernumber, $rank, $ignoreSetLowestRank ) = @_; |
|
Lines 1691-1700
sub _FixPriority {
Link Here
|
| 1691 |
); |
1720 |
); |
| 1692 |
$sth->finish; |
1721 |
$sth->finish; |
| 1693 |
} |
1722 |
} |
| 1694 |
|
1723 |
|
| 1695 |
$sth = $dbh->prepare( "SELECT borrowernumber FROM reserves WHERE lowestPriority = 1 ORDER BY priority" ); |
1724 |
$sth = $dbh->prepare( "SELECT borrowernumber FROM reserves WHERE lowestPriority = 1 ORDER BY priority" ); |
| 1696 |
$sth->execute(); |
1725 |
$sth->execute(); |
| 1697 |
|
1726 |
|
| 1698 |
unless ( $ignoreSetLowestRank ) { |
1727 |
unless ( $ignoreSetLowestRank ) { |
| 1699 |
while ( my $res = $sth->fetchrow_hashref() ) { |
1728 |
while ( my $res = $sth->fetchrow_hashref() ) { |
| 1700 |
_FixPriority( $biblio, $res->{'borrowernumber'}, '999999', 1 ); |
1729 |
_FixPriority( $biblio, $res->{'borrowernumber'}, '999999', 1 ); |
|
Lines 1754-1760
sub _Findgroupreserve {
Link Here
|
| 1754 |
push( @results, $data ); |
1783 |
push( @results, $data ); |
| 1755 |
} |
1784 |
} |
| 1756 |
return @results if @results; |
1785 |
return @results if @results; |
| 1757 |
|
1786 |
|
| 1758 |
# check for title-level targetted match |
1787 |
# check for title-level targetted match |
| 1759 |
my $title_level_target_query = qq/ |
1788 |
my $title_level_target_query = qq/ |
| 1760 |
SELECT reserves.biblionumber AS biblionumber, |
1789 |
SELECT reserves.biblionumber AS biblionumber, |
|
Lines 1833-1839
sub _koha_notify_reserve {
Link Here
|
| 1833 |
|
1862 |
|
| 1834 |
my $dbh = C4::Context->dbh; |
1863 |
my $dbh = C4::Context->dbh; |
| 1835 |
my $borrower = C4::Members::GetMember(borrowernumber => $borrowernumber); |
1864 |
my $borrower = C4::Members::GetMember(borrowernumber => $borrowernumber); |
| 1836 |
|
1865 |
|
| 1837 |
# Try to get the borrower's email address |
1866 |
# Try to get the borrower's email address |
| 1838 |
my $to_address; |
1867 |
my $to_address; |
| 1839 |
my $which_address = C4::Context->preference('AutoEmailPrimaryAddress'); |
1868 |
my $which_address = C4::Context->preference('AutoEmailPrimaryAddress'); |
|
Lines 1843-1849
sub _koha_notify_reserve {
Link Here
|
| 1843 |
} else { |
1872 |
} else { |
| 1844 |
$to_address = $borrower->{$which_address}; |
1873 |
$to_address = $borrower->{$which_address}; |
| 1845 |
} |
1874 |
} |
| 1846 |
|
1875 |
|
| 1847 |
my $letter_code; |
1876 |
my $letter_code; |
| 1848 |
my $print_mode = 0; |
1877 |
my $print_mode = 0; |
| 1849 |
my $messagingprefs; |
1878 |
my $messagingprefs; |
|
Lines 1888-1894
sub _koha_notify_reserve {
Link Here
|
| 1888 |
borrowernumber => $borrowernumber, |
1917 |
borrowernumber => $borrowernumber, |
| 1889 |
message_transport_type => 'print', |
1918 |
message_transport_type => 'print', |
| 1890 |
} ); |
1919 |
} ); |
| 1891 |
|
1920 |
|
| 1892 |
return; |
1921 |
return; |
| 1893 |
} |
1922 |
} |
| 1894 |
|
1923 |
|
|
Lines 1967-1972
sub _ShiftPriorityByDateAndPriority {
Link Here
|
| 1967 |
return $new_priority; # so the caller knows what priority they wind up receiving |
1996 |
return $new_priority; # so the caller knows what priority they wind up receiving |
| 1968 |
} |
1997 |
} |
| 1969 |
|
1998 |
|
|
|
1999 |
=head2 OPACItemHoldsAllowed |
| 2000 |
|
| 2001 |
OPACItemHoldsAllowed($item_record,$borrower_record); |
| 2002 |
|
| 2003 |
Checks issuingrules, using the borrowers categorycode, the itemtype, and branchcode to see |
| 2004 |
if specific item holds are allowed, returns true if so. |
| 2005 |
|
| 2006 |
=cut |
| 2007 |
|
| 2008 |
sub OPACItemHoldsAllowed { |
| 2009 |
my ($item,$borrower) = @_; |
| 2010 |
|
| 2011 |
my $branchcode = $item->{homebranch} or die "No homebranch"; |
| 2012 |
my $itype; |
| 2013 |
my $dbh = C4::Context->dbh; |
| 2014 |
if (C4::Context->preference('item-level_itypes')) { |
| 2015 |
# We cant trust GetItem to honour the syspref, so safest to do it ourselves |
| 2016 |
# When GetItem is fixed, we can remove this |
| 2017 |
$itype = $item->{itype}; |
| 2018 |
} |
| 2019 |
else { |
| 2020 |
my $query = "SELECT itemtype FROM biblioitems WHERE biblioitemnumber = ? "; |
| 2021 |
my $sth = $dbh->prepare($query); |
| 2022 |
$sth->execute($item->{biblioitemnumber}); |
| 2023 |
if (my $data = $sth->fetchrow_hashref()){ |
| 2024 |
$itype = $data->{itemtype}; |
| 2025 |
} |
| 2026 |
} |
| 2027 |
|
| 2028 |
my $query = "SELECT opacitemholds,categorycode,itemtype,branchcode FROM issuingrules WHERE |
| 2029 |
(issuingrules.categorycode = ? OR issuingrules.categorycode = '*') |
| 2030 |
AND |
| 2031 |
(issuingrules.itemtype = ? OR issuingrules.itemtype = '*') |
| 2032 |
AND |
| 2033 |
(issuingrules.branchcode = ? OR issuingrules.branchcode = '*') |
| 2034 |
ORDER BY |
| 2035 |
issuingrules.categorycode desc, |
| 2036 |
issuingrules.itemtype desc, |
| 2037 |
issuingrules.branchcode desc |
| 2038 |
LIMIT 1"; |
| 2039 |
my $sth = $dbh->prepare($query); |
| 2040 |
$sth->execute($borrower->{categorycode},$itype,$branchcode); |
| 2041 |
my $data = $sth->fetchrow_hashref; |
| 2042 |
if ($data->{opacitemholds}){ |
| 2043 |
return 1; |
| 2044 |
} |
| 2045 |
else { |
| 2046 |
return 0; |
| 2047 |
} |
| 2048 |
} |
| 2049 |
|
| 1970 |
=head2 MoveReserve |
2050 |
=head2 MoveReserve |
| 1971 |
|
2051 |
|
| 1972 |
MoveReserve( $itemnumber, $borrowernumber, $cancelreserve ) |
2052 |
MoveReserve( $itemnumber, $borrowernumber, $cancelreserve ) |