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}; |
|
|
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 |
} |
1431 |
} |
1428 |
} |
1432 |
|
1429 |
|
1433 |
my $available_per_item = 1; |
1430 |
my $notforloan_per_itemtype |
1434 |
$available_per_item = 0 if $item->{itemlost} or |
1431 |
= $dbh->selectrow_array("SELECT notforloan FROM itemtypes WHERE itemtype = ?", |
1435 |
( $item->{notforloan} > 0 ) or |
1432 |
undef, $itype); |
1436 |
($item->{damaged} and not C4::Context->preference('AllowHoldsOnDamagedItems')) or |
1433 |
|
1437 |
$item->{wthdrawn} or |
1434 |
return 0 if |
1438 |
$notforloan_per_itemtype; |
1435 |
$notforloan_per_itemtype || |
|
|
1436 |
$item->{itemlost} || |
1437 |
$item->{notforloan} > 0 || |
1438 |
$item->{wthdrawn} || |
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 $dbh = C4::Context->dbh; |
2040 |
my $sth = $dbh->prepare($query); |
2041 |
$sth->execute($borrower->{categorycode},$itype,$branchcode); |
2042 |
my $data = $sth->fetchrow_hashref; |
2043 |
if ($data->{opacitemholds}){ |
2044 |
return 1; |
2045 |
} |
2046 |
else { |
2047 |
return 0; |
2048 |
} |
2049 |
} |
2050 |
|
1970 |
=head2 MoveReserve |
2051 |
=head2 MoveReserve |
1971 |
|
2052 |
|
1972 |
MoveReserve( $itemnumber, $borrowernumber, $cancelreserve ) |
2053 |
MoveReserve( $itemnumber, $borrowernumber, $cancelreserve ) |