Lines 70-82
This modules provides somes functions to deal with reservations.
Link Here
|
70 |
The complete workflow is : |
70 |
The complete workflow is : |
71 |
==== 1st use case ==== |
71 |
==== 1st use case ==== |
72 |
patron request a document, 1st available : P >0, F=NULL, I=NULL |
72 |
patron request a document, 1st available : P >0, F=NULL, I=NULL |
73 |
a library having it run "transfertodo", and clic on the list |
73 |
a library having it run "transfertodo", and clic on the list |
74 |
if there is no transfer to do, the reserve waiting |
74 |
if there is no transfer to do, the reserve waiting |
75 |
patron can pick it up P =0, F=W, I=filled |
75 |
patron can pick it up P =0, F=W, I=filled |
76 |
if there is a transfer to do, write in branchtransfer P =0, F=T, I=filled |
76 |
if there is a transfer to do, write in branchtransfer P =0, F=T, I=filled |
77 |
The pickup library recieve the book, it check in P =0, F=W, I=filled |
77 |
The pickup library recieve the book, it check in P =0, F=W, I=filled |
78 |
The patron borrow the book P =0, F=F, I=filled |
78 |
The patron borrow the book P =0, F=F, I=filled |
79 |
|
79 |
|
80 |
==== 2nd use case ==== |
80 |
==== 2nd use case ==== |
81 |
patron requests a document, a given item, |
81 |
patron requests a document, a given item, |
82 |
If pickup is holding branch P =0, F=W, I=filled |
82 |
If pickup is holding branch P =0, F=W, I=filled |
Lines 106-114
BEGIN {
Link Here
|
106 |
&GetReserveFee |
106 |
&GetReserveFee |
107 |
&GetReserveInfo |
107 |
&GetReserveInfo |
108 |
&GetReserveStatus |
108 |
&GetReserveStatus |
109 |
|
109 |
|
110 |
&GetOtherReserves |
110 |
&GetOtherReserves |
111 |
|
111 |
|
112 |
&ModReserveFill |
112 |
&ModReserveFill |
113 |
&ModReserveAffect |
113 |
&ModReserveAffect |
114 |
&ModReserve |
114 |
&ModReserve |
Lines 116-122
BEGIN {
Link Here
|
116 |
&ModReserveCancelAll |
116 |
&ModReserveCancelAll |
117 |
&ModReserveMinusPriority |
117 |
&ModReserveMinusPriority |
118 |
&MoveReserve |
118 |
&MoveReserve |
119 |
|
119 |
|
120 |
&CheckReserves |
120 |
&CheckReserves |
121 |
&CanBookBeReserved |
121 |
&CanBookBeReserved |
122 |
&CanItemBeReserved |
122 |
&CanItemBeReserved |
Lines 127-133
BEGIN {
Link Here
|
127 |
&AutoUnsuspendReserves |
127 |
&AutoUnsuspendReserves |
128 |
|
128 |
|
129 |
&IsAvailableForItemLevelRequest |
129 |
&IsAvailableForItemLevelRequest |
130 |
|
130 |
|
|
|
131 |
&OPACItemHoldsAllowed |
132 |
|
131 |
&AlterPriority |
133 |
&AlterPriority |
132 |
&ToggleLowestPriority |
134 |
&ToggleLowestPriority |
133 |
|
135 |
|
Lines 140-146
BEGIN {
Link Here
|
140 |
IsItemOnHoldAndFound |
142 |
IsItemOnHoldAndFound |
141 |
); |
143 |
); |
142 |
@EXPORT_OK = qw( MergeHolds ); |
144 |
@EXPORT_OK = qw( MergeHolds ); |
143 |
} |
145 |
} |
144 |
|
146 |
|
145 |
=head2 AddReserve |
147 |
=head2 AddReserve |
146 |
|
148 |
|
Lines 351-357
sub GetReservesFromBiblionumber {
Link Here
|
351 |
push( @bibitemno, $bibitemnos ); # FIXME: inefficient: use fetchall_arrayref |
353 |
push( @bibitemno, $bibitemnos ); # FIXME: inefficient: use fetchall_arrayref |
352 |
} |
354 |
} |
353 |
my $count = scalar @bibitemno; |
355 |
my $count = scalar @bibitemno; |
354 |
|
356 |
|
355 |
# if we have two or more different specific itemtypes |
357 |
# if we have two or more different specific itemtypes |
356 |
# reserved by same person on same day |
358 |
# reserved by same person on same day |
357 |
my $bdata; |
359 |
my $bdata; |
Lines 491-497
sub CanBookBeReserved{
Link Here
|
491 |
|
493 |
|
492 |
sub CanItemBeReserved{ |
494 |
sub CanItemBeReserved{ |
493 |
my ($borrowernumber, $itemnumber) = @_; |
495 |
my ($borrowernumber, $itemnumber) = @_; |
494 |
|
496 |
|
495 |
my $dbh = C4::Context->dbh; |
497 |
my $dbh = C4::Context->dbh; |
496 |
my $ruleitemtype; # itemtype of the matching issuing rule |
498 |
my $ruleitemtype; # itemtype of the matching issuing rule |
497 |
my $allowedreserves = 0; |
499 |
my $allowedreserves = 0; |
Lines 513-530
sub CanItemBeReserved{
Link Here
|
513 |
my $itemtypefield = C4::Context->preference('item-level_itypes') ? "itype" : "itemtype"; |
515 |
my $itemtypefield = C4::Context->preference('item-level_itypes') ? "itype" : "itemtype"; |
514 |
|
516 |
|
515 |
# we retrieve user rights on this itemtype and branchcode |
517 |
# we retrieve user rights on this itemtype and branchcode |
516 |
my $sth = $dbh->prepare("SELECT categorycode, itemtype, branchcode, reservesallowed |
518 |
my $sth = $dbh->prepare("SELECT categorycode, itemtype, branchcode, reservesallowed |
517 |
FROM issuingrules |
519 |
FROM issuingrules |
518 |
WHERE (categorycode in (?,'*') ) |
520 |
WHERE (categorycode in (?,'*') ) |
519 |
AND (itemtype IN (?,'*')) |
521 |
AND (itemtype IN (?,'*')) |
520 |
AND (branchcode IN (?,'*')) |
522 |
AND (branchcode IN (?,'*')) |
521 |
ORDER BY |
523 |
ORDER BY |
522 |
categorycode DESC, |
524 |
categorycode DESC, |
523 |
itemtype DESC, |
525 |
itemtype DESC, |
524 |
branchcode DESC;" |
526 |
branchcode DESC;" |
525 |
); |
527 |
); |
526 |
|
528 |
|
527 |
my $querycount ="SELECT |
529 |
my $querycount ="SELECT |
528 |
count(*) as count |
530 |
count(*) as count |
529 |
FROM reserves |
531 |
FROM reserves |
530 |
LEFT JOIN items USING (itemnumber) |
532 |
LEFT JOIN items USING (itemnumber) |
Lines 536-542
sub CanItemBeReserved{
Link Here
|
536 |
|
538 |
|
537 |
my $branchcode = ""; |
539 |
my $branchcode = ""; |
538 |
my $branchfield = "reserves.branchcode"; |
540 |
my $branchfield = "reserves.branchcode"; |
539 |
|
541 |
|
540 |
if( $controlbranch eq "ItemHomeLibrary" ){ |
542 |
if( $controlbranch eq "ItemHomeLibrary" ){ |
541 |
$branchfield = "items.homebranch"; |
543 |
$branchfield = "items.homebranch"; |
542 |
$branchcode = $item->{homebranch}; |
544 |
$branchcode = $item->{homebranch}; |
Lines 553-561
sub CanItemBeReserved{
Link Here
|
553 |
}else{ |
555 |
}else{ |
554 |
$ruleitemtype = '*'; |
556 |
$ruleitemtype = '*'; |
555 |
} |
557 |
} |
556 |
|
558 |
|
557 |
# we retrieve count |
559 |
# we retrieve count |
558 |
|
560 |
|
559 |
$querycount .= "AND $branchfield = ?"; |
561 |
$querycount .= "AND $branchfield = ?"; |
560 |
|
562 |
|
561 |
$querycount .= " AND $itemtypefield = ?" if ($ruleitemtype ne "*"); |
563 |
$querycount .= " AND $itemtypefield = ?" if ($ruleitemtype ne "*"); |
Lines 566-577
sub CanItemBeReserved{
Link Here
|
566 |
}else{ |
568 |
}else{ |
567 |
$sthcount->execute($borrowernumber, $branchcode, $ruleitemtype); |
569 |
$sthcount->execute($borrowernumber, $branchcode, $ruleitemtype); |
568 |
} |
570 |
} |
569 |
|
571 |
|
570 |
my $reservecount = "0"; |
572 |
my $reservecount = "0"; |
571 |
if(my $rowcount = $sthcount->fetchrow_hashref()){ |
573 |
if(my $rowcount = $sthcount->fetchrow_hashref()){ |
572 |
$reservecount = $rowcount->{count}; |
574 |
$reservecount = $rowcount->{count}; |
573 |
} |
575 |
} |
574 |
|
|
|
575 |
# we check if it's ok or not |
576 |
# we check if it's ok or not |
576 |
if( $reservecount >= $allowedreserves ){ |
577 |
if( $reservecount >= $allowedreserves ){ |
577 |
return 'tooManyReserves'; |
578 |
return 'tooManyReserves'; |
Lines 955-961
sub CheckReserves {
Link Here
|
955 |
LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype |
956 |
LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype |
956 |
"; |
957 |
"; |
957 |
} |
958 |
} |
958 |
|
959 |
|
959 |
if ($item) { |
960 |
if ($item) { |
960 |
$sth = $dbh->prepare("$select WHERE itemnumber = ?"); |
961 |
$sth = $dbh->prepare("$select WHERE itemnumber = ?"); |
961 |
$sth->execute($item); |
962 |
$sth->execute($item); |
Lines 1053-1059
sub CancelExpiredReserves {
Link Here
|
1053 |
# Cancel reserves that have passed their expiration date. |
1054 |
# Cancel reserves that have passed their expiration date. |
1054 |
my $dbh = C4::Context->dbh; |
1055 |
my $dbh = C4::Context->dbh; |
1055 |
my $sth = $dbh->prepare( " |
1056 |
my $sth = $dbh->prepare( " |
1056 |
SELECT * FROM reserves WHERE DATE(expirationdate) < DATE( CURDATE() ) |
1057 |
SELECT * FROM reserves WHERE DATE(expirationdate) < DATE( CURDATE() ) |
1057 |
AND expirationdate IS NOT NULL |
1058 |
AND expirationdate IS NOT NULL |
1058 |
AND found IS NULL |
1059 |
AND found IS NULL |
1059 |
" ); |
1060 |
" ); |
Lines 1062-1068
sub CancelExpiredReserves {
Link Here
|
1062 |
while ( my $res = $sth->fetchrow_hashref() ) { |
1063 |
while ( my $res = $sth->fetchrow_hashref() ) { |
1063 |
CancelReserve({ reserve_id => $res->{'reserve_id'} }); |
1064 |
CancelReserve({ reserve_id => $res->{'reserve_id'} }); |
1064 |
} |
1065 |
} |
1065 |
|
1066 |
|
1066 |
# Cancel reserves that have been waiting too long |
1067 |
# Cancel reserves that have been waiting too long |
1067 |
if ( C4::Context->preference("ExpireReservesMaxPickUpDelay") ) { |
1068 |
if ( C4::Context->preference("ExpireReservesMaxPickUpDelay") ) { |
1068 |
my $max_pickup_delay = C4::Context->preference("ReservesMaxPickUpDelay"); |
1069 |
my $max_pickup_delay = C4::Context->preference("ReservesMaxPickUpDelay"); |
Lines 1188-1199
If C<$rank> is 'del', the hold request is cancelled.
Link Here
|
1188 |
|
1189 |
|
1189 |
If C<$rank> is an integer greater than zero, the priority of |
1190 |
If C<$rank> is an integer greater than zero, the priority of |
1190 |
the request is set to that value. Since priority != 0 means |
1191 |
the request is set to that value. Since priority != 0 means |
1191 |
that the item is not waiting on the hold shelf, setting the |
1192 |
that the item is not waiting on the hold shelf, setting the |
1192 |
priority to a non-zero value also sets the request's found |
1193 |
priority to a non-zero value also sets the request's found |
1193 |
status and waiting date to NULL. |
1194 |
status and waiting date to NULL. |
1194 |
|
1195 |
|
1195 |
The optional C<$itemnumber> parameter is used only when |
1196 |
The optional C<$itemnumber> parameter is used only when |
1196 |
C<$rank> is a non-zero integer; if supplied, the itemnumber |
1197 |
C<$rank> is a non-zero integer; if supplied, the itemnumber |
1197 |
of the hold request is set accordingly; if omitted, the itemnumber |
1198 |
of the hold request is set accordingly; if omitted, the itemnumber |
1198 |
is cleared. |
1199 |
is cleared. |
1199 |
|
1200 |
|
Lines 1305-1311
sub ModReserveFill {
Link Here
|
1305 |
"; |
1306 |
"; |
1306 |
$sth = $dbh->prepare($query); |
1307 |
$sth = $dbh->prepare($query); |
1307 |
$sth->execute( $biblionumber, $resdate, $borrowernumber ); |
1308 |
$sth->execute( $biblionumber, $resdate, $borrowernumber ); |
1308 |
|
1309 |
|
1309 |
# now fix the priority on the others (if the priority wasn't |
1310 |
# now fix the priority on the others (if the priority wasn't |
1310 |
# already sorted!).... |
1311 |
# already sorted!).... |
1311 |
unless ( $priority == 0 ) { |
1312 |
unless ( $priority == 0 ) { |
Lines 1350-1356
with the biblionumber & the borrowernumber, we can affect the itemnumber
Link Here
|
1350 |
to the correct reserve. |
1351 |
to the correct reserve. |
1351 |
|
1352 |
|
1352 |
if $transferToDo is not set, then the status is set to "Waiting" as well. |
1353 |
if $transferToDo is not set, then the status is set to "Waiting" as well. |
1353 |
otherwise, a transfer is on the way, and the end of the transfer will |
1354 |
otherwise, a transfer is on the way, and the end of the transfer will |
1354 |
take care of the waiting status |
1355 |
take care of the waiting status |
1355 |
|
1356 |
|
1356 |
=cut |
1357 |
=cut |
Lines 1511-1532
sub GetReserveInfo {
Link Here
|
1511 |
|
1512 |
|
1512 |
=head2 IsAvailableForItemLevelRequest |
1513 |
=head2 IsAvailableForItemLevelRequest |
1513 |
|
1514 |
|
1514 |
my $is_available = IsAvailableForItemLevelRequest($itemnumber); |
1515 |
my $is_available = IsAvailableForItemLevelRequest($item_record,$borrower_record); |
1515 |
|
1516 |
|
1516 |
Checks whether a given item record is available for an |
1517 |
Checks whether a given item record is available for an |
1517 |
item-level hold request. An item is available if |
1518 |
item-level hold request. An item is available if |
1518 |
|
1519 |
|
1519 |
* it is not lost AND |
1520 |
* it is not lost AND |
1520 |
* it is not damaged AND |
1521 |
* it is not damaged AND |
1521 |
* it is not withdrawn AND |
1522 |
* it is not withdrawn AND |
1522 |
* does not have a not for loan value > 0 |
1523 |
* does not have a not for loan value > 0 |
1523 |
|
1524 |
|
1524 |
Whether or not the item is currently on loan is |
1525 |
Need to check the issuingrules onshelfholds column, |
1525 |
also checked - if the AllowOnShelfHolds system preference |
1526 |
if this is set items on the shelf can be placed on hold |
1526 |
is ON, an item can be requested even if it is currently |
|
|
1527 |
on loan to somebody else. If the system preference |
1528 |
is OFF, an item that is currently checked out cannot |
1529 |
be the target of an item-level hold request. |
1530 |
|
1527 |
|
1531 |
Note that IsAvailableForItemLevelRequest() does not |
1528 |
Note that IsAvailableForItemLevelRequest() does not |
1532 |
check if the staff operator is authorized to place |
1529 |
check if the staff operator is authorized to place |
Lines 1537-1584
and canreservefromotherbranches.
Link Here
|
1537 |
=cut |
1534 |
=cut |
1538 |
|
1535 |
|
1539 |
sub IsAvailableForItemLevelRequest { |
1536 |
sub IsAvailableForItemLevelRequest { |
1540 |
my $itemnumber = shift; |
1537 |
my $item = shift; |
1541 |
|
1538 |
my $borrower = shift; |
1542 |
my $item = GetItem($itemnumber); |
|
|
1543 |
|
1539 |
|
|
|
1540 |
my $dbh = C4::Context->dbh; |
1544 |
# must check the notforloan setting of the itemtype |
1541 |
# must check the notforloan setting of the itemtype |
1545 |
# FIXME - a lot of places in the code do this |
1542 |
# FIXME - a lot of places in the code do this |
1546 |
# or something similar - need to be |
1543 |
# or something similar - need to be |
1547 |
# consolidated |
1544 |
# consolidated |
1548 |
my $dbh = C4::Context->dbh; |
1545 |
my $itype = _get_itype($item); |
1549 |
my $notforloan_query; |
1546 |
my $notforloan_per_itemtype |
|
|
1547 |
= $dbh->selectrow_array("SELECT notforloan FROM itemtypes WHERE itemtype = ?", |
1548 |
undef, $itype); |
1549 |
|
1550 |
return 0 if |
1551 |
$notforloan_per_itemtype || |
1552 |
$item->{itemlost} || |
1553 |
$item->{notforloan} > 0 || |
1554 |
$item->{wthdrawn} || |
1555 |
($item->{damaged} && !C4::Context->preference('AllowHoldsOnDamagedItems')); |
1556 |
|
1557 |
|
1558 |
return 1 if _OnShelfHoldsAllowed($itype,$borrower->{categorycode},$item->{holdingbranch}); |
1559 |
|
1560 |
return $item->{onloan} || GetReserveStatus($item->{itemnumber}) eq "Waiting"; |
1561 |
} |
1562 |
|
1563 |
=head2 OnShelfHoldsAllowed |
1564 |
|
1565 |
OnShelfHoldsAllowed($itemtype,$borrowercategory,$branchcode); |
1566 |
|
1567 |
Checks issuingrules, using the borrowers categorycode, the itemtype, and branchcode to see if onshelf |
1568 |
holds are allowed, returns true if so. |
1569 |
|
1570 |
=cut |
1571 |
|
1572 |
sub OnShelfHoldsAllowed { |
1573 |
my ($item, $borrower) = @_; |
1574 |
|
1575 |
my $itype = _get_itype($item); |
1576 |
return _OnShelfHoldsAllowed($itype,$borrower->{categorycode},$item->{holdingbranch}); |
1577 |
} |
1578 |
|
1579 |
sub _get_itype { |
1580 |
my $item = shift; |
1581 |
|
1582 |
my $itype; |
1550 |
if (C4::Context->preference('item-level_itypes')) { |
1583 |
if (C4::Context->preference('item-level_itypes')) { |
1551 |
$notforloan_query = "SELECT itemtypes.notforloan |
1584 |
# We cant trust GetItem to honour the syspref, so safest to do it ourselves |
1552 |
FROM items |
1585 |
# When GetItem is fixed, we can remove this |
1553 |
JOIN itemtypes ON (itemtypes.itemtype = items.itype) |
1586 |
$itype = $item->{itype}; |
1554 |
WHERE itemnumber = ?"; |
|
|
1555 |
} else { |
1556 |
$notforloan_query = "SELECT itemtypes.notforloan |
1557 |
FROM items |
1558 |
JOIN biblioitems USING (biblioitemnumber) |
1559 |
JOIN itemtypes USING (itemtype) |
1560 |
WHERE itemnumber = ?"; |
1561 |
} |
1587 |
} |
1562 |
my $sth = $dbh->prepare($notforloan_query); |
1588 |
else { |
1563 |
$sth->execute($itemnumber); |
1589 |
# XXX This is a bit dodgy. It relies on biblio itemtype column having different name. |
1564 |
my $notforloan_per_itemtype = 0; |
1590 |
# So if we already have a biblioitems join when calling this function, |
1565 |
if (my ($notforloan) = $sth->fetchrow_array) { |
1591 |
# we don't need to access the database again |
1566 |
$notforloan_per_itemtype = 1 if $notforloan; |
1592 |
$itype = $item->{itemtype}; |
|
|
1593 |
} |
1594 |
unless ($itype) { |
1595 |
my $dbh = C4::Context->dbh; |
1596 |
my $query = "SELECT itemtype FROM biblioitems WHERE biblioitemnumber = ? "; |
1597 |
my $sth = $dbh->prepare($query); |
1598 |
$sth->execute($item->{biblioitemnumber}); |
1599 |
if (my $data = $sth->fetchrow_hashref()){ |
1600 |
$itype = $data->{itemtype}; |
1601 |
} |
1567 |
} |
1602 |
} |
|
|
1603 |
return $itype; |
1604 |
} |
1568 |
|
1605 |
|
1569 |
my $available_per_item = 1; |
1606 |
sub _OnShelfHoldsAllowed { |
1570 |
$available_per_item = 0 if $item->{itemlost} or |
1607 |
my ($itype,$borrowercategory,$branchcode) = @_; |
1571 |
( $item->{notforloan} > 0 ) or |
|
|
1572 |
($item->{damaged} and not C4::Context->preference('AllowHoldsOnDamagedItems')) or |
1573 |
$item->{withdrawn} or |
1574 |
$notforloan_per_itemtype; |
1575 |
|
1576 |
|
1608 |
|
1577 |
if (C4::Context->preference('AllowOnShelfHolds')) { |
1609 |
my $rule = C4::Circulation::GetIssuingRule($borrowercategory, $itype, $branchcode); |
1578 |
return $available_per_item; |
1610 |
return $rule->{onshelfholds}; |
1579 |
} else { |
|
|
1580 |
return ($available_per_item and ($item->{onloan} or GetReserveStatus($itemnumber) eq "Waiting")); |
1581 |
} |
1582 |
} |
1611 |
} |
1583 |
|
1612 |
|
1584 |
=head2 AlterPriority |
1613 |
=head2 AlterPriority |
Lines 1846-1852
sub _FixPriority {
Link Here
|
1846 |
|
1875 |
|
1847 |
$sth = $dbh->prepare( "SELECT reserve_id FROM reserves WHERE lowestPriority = 1 ORDER BY priority" ); |
1876 |
$sth = $dbh->prepare( "SELECT reserve_id FROM reserves WHERE lowestPriority = 1 ORDER BY priority" ); |
1848 |
$sth->execute(); |
1877 |
$sth->execute(); |
1849 |
|
1878 |
|
1850 |
unless ( $ignoreSetLowestRank ) { |
1879 |
unless ( $ignoreSetLowestRank ) { |
1851 |
while ( my $res = $sth->fetchrow_hashref() ) { |
1880 |
while ( my $res = $sth->fetchrow_hashref() ) { |
1852 |
_FixPriority({ |
1881 |
_FixPriority({ |
Lines 1914-1920
sub _Findgroupreserve {
Link Here
|
1914 |
unless any{ $data->{borrowernumber} eq $_ } @$ignore_borrowers ; |
1943 |
unless any{ $data->{borrowernumber} eq $_ } @$ignore_borrowers ; |
1915 |
} |
1944 |
} |
1916 |
return @results if @results; |
1945 |
return @results if @results; |
1917 |
|
1946 |
|
1918 |
# check for title-level targetted match |
1947 |
# check for title-level targetted match |
1919 |
my $title_level_target_query = qq{ |
1948 |
my $title_level_target_query = qq{ |
1920 |
SELECT reserves.biblionumber AS biblionumber, |
1949 |
SELECT reserves.biblionumber AS biblionumber, |
Lines 1999-2005
sub _koha_notify_reserve {
Link Here
|
1999 |
|
2028 |
|
2000 |
my $dbh = C4::Context->dbh; |
2029 |
my $dbh = C4::Context->dbh; |
2001 |
my $borrower = C4::Members::GetMember(borrowernumber => $borrowernumber); |
2030 |
my $borrower = C4::Members::GetMember(borrowernumber => $borrowernumber); |
2002 |
|
2031 |
|
2003 |
# Try to get the borrower's email address |
2032 |
# Try to get the borrower's email address |
2004 |
my $to_address = C4::Members::GetNoticeEmailAddress($borrowernumber); |
2033 |
my $to_address = C4::Members::GetNoticeEmailAddress($borrowernumber); |
2005 |
|
2034 |
|
Lines 2119-2124
sub _ShiftPriorityByDateAndPriority {
Link Here
|
2119 |
return $new_priority; # so the caller knows what priority they wind up receiving |
2148 |
return $new_priority; # so the caller knows what priority they wind up receiving |
2120 |
} |
2149 |
} |
2121 |
|
2150 |
|
|
|
2151 |
=head2 OPACItemHoldsAllowed |
2152 |
|
2153 |
OPACItemHoldsAllowed($item_record,$borrower_record); |
2154 |
|
2155 |
Checks issuingrules, using the borrowers categorycode, the itemtype, and branchcode to see |
2156 |
if specific item holds are allowed, returns true if so. |
2157 |
|
2158 |
=cut |
2159 |
|
2160 |
sub OPACItemHoldsAllowed { |
2161 |
my ($item,$borrower) = @_; |
2162 |
|
2163 |
my $branchcode = $item->{homebranch} or die "No homebranch"; |
2164 |
my $itype; |
2165 |
my $dbh = C4::Context->dbh; |
2166 |
if (C4::Context->preference('item-level_itypes')) { |
2167 |
# We cant trust GetItem to honour the syspref, so safest to do it ourselves |
2168 |
# When GetItem is fixed, we can remove this |
2169 |
$itype = $item->{itype}; |
2170 |
} |
2171 |
else { |
2172 |
my $query = "SELECT itemtype FROM biblioitems WHERE biblioitemnumber = ? "; |
2173 |
my $sth = $dbh->prepare($query); |
2174 |
$sth->execute($item->{biblioitemnumber}); |
2175 |
if (my $data = $sth->fetchrow_hashref()){ |
2176 |
$itype = $data->{itemtype}; |
2177 |
} |
2178 |
} |
2179 |
|
2180 |
my $query = "SELECT opacitemholds,categorycode,itemtype,branchcode FROM issuingrules WHERE |
2181 |
(issuingrules.categorycode = ? OR issuingrules.categorycode = '*') |
2182 |
AND |
2183 |
(issuingrules.itemtype = ? OR issuingrules.itemtype = '*') |
2184 |
AND |
2185 |
(issuingrules.branchcode = ? OR issuingrules.branchcode = '*') |
2186 |
ORDER BY |
2187 |
issuingrules.categorycode desc, |
2188 |
issuingrules.itemtype desc, |
2189 |
issuingrules.branchcode desc |
2190 |
LIMIT 1"; |
2191 |
my $sth = $dbh->prepare($query); |
2192 |
$sth->execute($borrower->{categorycode},$itype,$branchcode); |
2193 |
my $data = $sth->fetchrow_hashref; |
2194 |
my $opacitemholds = uc substr ($data->{opacitemholds}, 0, 1); |
2195 |
return '' if $opacitemholds eq 'N'; |
2196 |
return $opacitemholds; |
2197 |
} |
2198 |
|
2122 |
=head2 MoveReserve |
2199 |
=head2 MoveReserve |
2123 |
|
2200 |
|
2124 |
MoveReserve( $itemnumber, $borrowernumber, $cancelreserve ) |
2201 |
MoveReserve( $itemnumber, $borrowernumber, $cancelreserve ) |