|
Lines 41-46
use Koha::Database;
Link Here
|
| 41 |
use Koha::Hold; |
41 |
use Koha::Hold; |
| 42 |
use Koha::Holds; |
42 |
use Koha::Holds; |
| 43 |
use Koha::Libraries; |
43 |
use Koha::Libraries; |
|
|
44 |
use Koha::Patrons; |
| 44 |
|
45 |
|
| 45 |
use List::MoreUtils qw( firstidx any ); |
46 |
use List::MoreUtils qw( firstidx any ); |
| 46 |
use Carp; |
47 |
use Carp; |
|
Lines 139-144
BEGIN {
Link Here
|
| 139 |
&GetReservesControlBranch |
140 |
&GetReservesControlBranch |
| 140 |
|
141 |
|
| 141 |
IsItemOnHoldAndFound |
142 |
IsItemOnHoldAndFound |
|
|
143 |
|
| 144 |
GetMaxPatronHoldsForRecord |
| 142 |
); |
145 |
); |
| 143 |
@EXPORT_OK = qw( MergeHolds ); |
146 |
@EXPORT_OK = qw( MergeHolds ); |
| 144 |
} |
147 |
} |
|
Lines 166-177
sub AddReserve {
Link Here
|
| 166 |
$title, $checkitem, $found |
169 |
$title, $checkitem, $found |
| 167 |
) = @_; |
170 |
) = @_; |
| 168 |
|
171 |
|
| 169 |
if ( Koha::Holds->search( { borrowernumber => $borrowernumber, biblionumber => $biblionumber } )->count() > 0 ) { |
172 |
my $dbh = C4::Context->dbh; |
| 170 |
carp("AddReserve: borrower $borrowernumber already has a hold for biblionumber $biblionumber"); |
|
|
| 171 |
return; |
| 172 |
} |
| 173 |
|
| 174 |
my $dbh = C4::Context->dbh; |
| 175 |
|
173 |
|
| 176 |
$resdate = output_pref( { str => dt_from_string( $resdate ), dateonly => 1, dateformat => 'iso' }) |
174 |
$resdate = output_pref( { str => dt_from_string( $resdate ), dateonly => 1, dateformat => 'iso' }) |
| 177 |
or output_pref({ dt => dt_from_string, dateonly => 1, dateformat => 'iso' }); |
175 |
or output_pref({ dt => dt_from_string, dateonly => 1, dateformat => 'iso' }); |
|
Lines 451-457
sub CanItemBeReserved {
Link Here
|
| 451 |
|
449 |
|
| 452 |
my $dbh = C4::Context->dbh; |
450 |
my $dbh = C4::Context->dbh; |
| 453 |
my $ruleitemtype; # itemtype of the matching issuing rule |
451 |
my $ruleitemtype; # itemtype of the matching issuing rule |
| 454 |
my $allowedreserves = 0; |
452 |
my $allowedreserves = 0; # Total number of holds allowed across all records |
|
|
453 |
my $holds_per_record = 1; # Total number of holds allowed for this one given record |
| 455 |
|
454 |
|
| 456 |
# we retrieve borrowers and items informations # |
455 |
# we retrieve borrowers and items informations # |
| 457 |
# item->{itype} will come for biblioitems if necessery |
456 |
# item->{itype} will come for biblioitems if necessery |
|
Lines 464-489
sub CanItemBeReserved {
Link Here
|
| 464 |
if ( $item->{damaged} |
463 |
if ( $item->{damaged} |
| 465 |
&& !C4::Context->preference('AllowHoldsOnDamagedItems') ); |
464 |
&& !C4::Context->preference('AllowHoldsOnDamagedItems') ); |
| 466 |
|
465 |
|
| 467 |
#Check for the age restriction |
466 |
# Check for the age restriction |
| 468 |
my ( $ageRestriction, $daysToAgeRestriction ) = |
467 |
my ( $ageRestriction, $daysToAgeRestriction ) = |
| 469 |
C4::Circulation::GetAgeRestriction( $biblioData->{agerestriction}, $borrower ); |
468 |
C4::Circulation::GetAgeRestriction( $biblioData->{agerestriction}, $borrower ); |
| 470 |
return 'ageRestricted' if $daysToAgeRestriction && $daysToAgeRestriction > 0; |
469 |
return 'ageRestricted' if $daysToAgeRestriction && $daysToAgeRestriction > 0; |
| 471 |
|
470 |
|
| 472 |
my $controlbranch = C4::Context->preference('ReservesControlBranch'); |
471 |
# Check that the patron doesn't have an item level hold on this item already |
|
|
472 |
return 'itemAlreadyOnHold' |
| 473 |
if Koha::Holds->search( { borrowernumber => $borrowernumber, itemnumber => $itemnumber } )->count(); |
| 473 |
|
474 |
|
| 474 |
# we retrieve user rights on this itemtype and branchcode |
475 |
my $controlbranch = C4::Context->preference('ReservesControlBranch'); |
| 475 |
my $sth = $dbh->prepare( |
|
|
| 476 |
q{ |
| 477 |
SELECT categorycode, itemtype, branchcode, reservesallowed |
| 478 |
FROM issuingrules |
| 479 |
WHERE (categorycode in (?,'*') ) |
| 480 |
AND (itemtype IN (?,'*')) |
| 481 |
AND (branchcode IN (?,'*')) |
| 482 |
ORDER BY categorycode DESC, |
| 483 |
itemtype DESC, |
| 484 |
branchcode DESC |
| 485 |
} |
| 486 |
); |
| 487 |
|
476 |
|
| 488 |
my $querycount = q{ |
477 |
my $querycount = q{ |
| 489 |
SELECT count(*) AS count |
478 |
SELECT count(*) AS count |
|
Lines 507-521
sub CanItemBeReserved {
Link Here
|
| 507 |
} |
496 |
} |
| 508 |
|
497 |
|
| 509 |
# we retrieve rights |
498 |
# we retrieve rights |
| 510 |
$sth->execute( $borrower->{'categorycode'}, $item->{'itype'}, $branchcode ); |
499 |
if ( my $rights = GetHoldRule( $borrower->{'categorycode'}, $item->{'itype'}, $branchcode ) ) { |
| 511 |
if ( my $rights = $sth->fetchrow_hashref() ) { |
500 |
$ruleitemtype = $rights->{itemtype}; |
| 512 |
$ruleitemtype = $rights->{itemtype}; |
501 |
$allowedreserves = $rights->{reservesallowed}; |
| 513 |
$allowedreserves = $rights->{reservesallowed}; |
502 |
$holds_per_record = $rights->{holds_per_record}; |
| 514 |
} |
503 |
} |
| 515 |
else { |
504 |
else { |
| 516 |
$ruleitemtype = '*'; |
505 |
$ruleitemtype = '*'; |
| 517 |
} |
506 |
} |
| 518 |
|
507 |
|
|
|
508 |
my $item = Koha::Items->find( $itemnumber ); |
| 509 |
my $holds = Koha::Holds->search( |
| 510 |
{ |
| 511 |
borrowernumber => $borrowernumber, |
| 512 |
biblionumber => $item->biblionumber, |
| 513 |
found => undef, # Found holds don't count against a patron's holds limit |
| 514 |
} |
| 515 |
); |
| 516 |
if ( $holds->count() >= $holds_per_record ) { |
| 517 |
return "tooManyHoldsForThisRecord"; |
| 518 |
} |
| 519 |
|
| 519 |
# we retrieve count |
520 |
# we retrieve count |
| 520 |
|
521 |
|
| 521 |
$querycount .= "AND $branchfield = ?"; |
522 |
$querycount .= "AND $branchfield = ?"; |
|
Lines 745-752
sub GetReservesToBranch {
Link Here
|
| 745 |
my $dbh = C4::Context->dbh; |
746 |
my $dbh = C4::Context->dbh; |
| 746 |
my $sth = $dbh->prepare( |
747 |
my $sth = $dbh->prepare( |
| 747 |
"SELECT reserve_id,borrowernumber,reservedate,itemnumber,timestamp |
748 |
"SELECT reserve_id,borrowernumber,reservedate,itemnumber,timestamp |
| 748 |
FROM reserves |
749 |
FROM reserves |
| 749 |
WHERE priority='0' |
750 |
WHERE priority='0' |
| 750 |
AND branchcode=?" |
751 |
AND branchcode=?" |
| 751 |
); |
752 |
); |
| 752 |
$sth->execute( $frombranch ); |
753 |
$sth->execute( $frombranch ); |
|
Lines 771-777
sub GetReservesForBranch {
Link Here
|
| 771 |
|
772 |
|
| 772 |
my $query = " |
773 |
my $query = " |
| 773 |
SELECT reserve_id,borrowernumber,reservedate,itemnumber,waitingdate |
774 |
SELECT reserve_id,borrowernumber,reservedate,itemnumber,waitingdate |
| 774 |
FROM reserves |
775 |
FROM reserves |
| 775 |
WHERE priority='0' |
776 |
WHERE priority='0' |
| 776 |
AND found='W' |
777 |
AND found='W' |
| 777 |
"; |
778 |
"; |
|
Lines 1393-1399
sub ModReserveMinusPriority {
Link Here
|
| 1393 |
my $dbh = C4::Context->dbh; |
1394 |
my $dbh = C4::Context->dbh; |
| 1394 |
my $query = " |
1395 |
my $query = " |
| 1395 |
UPDATE reserves |
1396 |
UPDATE reserves |
| 1396 |
SET priority = 0 , itemnumber = ? |
1397 |
SET priority = 0 , itemnumber = ? |
| 1397 |
WHERE reserve_id = ? |
1398 |
WHERE reserve_id = ? |
| 1398 |
"; |
1399 |
"; |
| 1399 |
my $sth_upd = $dbh->prepare($query); |
1400 |
my $sth_upd = $dbh->prepare($query); |
|
Lines 1608-1614
sub ToggleLowestPriority {
Link Here
|
| 1608 |
|
1609 |
|
| 1609 |
my $sth = $dbh->prepare( "UPDATE reserves SET lowestPriority = NOT lowestPriority WHERE reserve_id = ?"); |
1610 |
my $sth = $dbh->prepare( "UPDATE reserves SET lowestPriority = NOT lowestPriority WHERE reserve_id = ?"); |
| 1610 |
$sth->execute( $reserve_id ); |
1611 |
$sth->execute( $reserve_id ); |
| 1611 |
|
1612 |
|
| 1612 |
_FixPriority({ reserve_id => $reserve_id, rank => '999999' }); |
1613 |
_FixPriority({ reserve_id => $reserve_id, rank => '999999' }); |
| 1613 |
} |
1614 |
} |
| 1614 |
|
1615 |
|
|
Lines 1792-1798
sub _FixPriority {
Link Here
|
| 1792 |
$priority[$j]->{'reserve_id'} |
1793 |
$priority[$j]->{'reserve_id'} |
| 1793 |
); |
1794 |
); |
| 1794 |
} |
1795 |
} |
| 1795 |
|
1796 |
|
| 1796 |
$sth = $dbh->prepare( "SELECT reserve_id FROM reserves WHERE lowestPriority = 1 ORDER BY priority" ); |
1797 |
$sth = $dbh->prepare( "SELECT reserve_id FROM reserves WHERE lowestPriority = 1 ORDER BY priority" ); |
| 1797 |
$sth->execute(); |
1798 |
$sth->execute(); |
| 1798 |
|
1799 |
|
|
Lines 2027-2033
sub _koha_notify_reserve {
Link Here
|
| 2027 |
if (! $notification_sent) { |
2028 |
if (! $notification_sent) { |
| 2028 |
&$send_notification('print', 'HOLD'); |
2029 |
&$send_notification('print', 'HOLD'); |
| 2029 |
} |
2030 |
} |
| 2030 |
|
2031 |
|
| 2031 |
} |
2032 |
} |
| 2032 |
|
2033 |
|
| 2033 |
=head2 _ShiftPriorityByDateAndPriority |
2034 |
=head2 _ShiftPriorityByDateAndPriority |
|
Lines 2456-2461
sub IsItemOnHoldAndFound {
Link Here
|
| 2456 |
return $found; |
2457 |
return $found; |
| 2457 |
} |
2458 |
} |
| 2458 |
|
2459 |
|
|
|
2460 |
=head2 GetMaxPatronHoldsForRecord |
| 2461 |
|
| 2462 |
my $holds_per_record = ReservesControlBranch( $borrowernumber, $biblionumber ); |
| 2463 |
|
| 2464 |
For multiple holds on a given record for a given patron, the max |
| 2465 |
number of record level holds that a patron can be placed is the highest |
| 2466 |
value of the holds_per_record rule for each item if the record for that |
| 2467 |
patron. This subroutine finds and returns the highest holds_per_record |
| 2468 |
rule value for a given patron id and record id. |
| 2469 |
|
| 2470 |
=cut |
| 2471 |
|
| 2472 |
sub GetMaxPatronHoldsForRecord { |
| 2473 |
my ( $borrowernumber, $biblionumber ) = @_; |
| 2474 |
|
| 2475 |
my $patron = Koha::Patrons->find($borrowernumber); |
| 2476 |
my @items = Koha::Items->search( { biblionumber => $biblionumber } ); |
| 2477 |
|
| 2478 |
my $controlbranch = C4::Context->preference('ReservesControlBranch'); |
| 2479 |
|
| 2480 |
my $categorycode = $patron->categorycode; |
| 2481 |
my $branchcode; |
| 2482 |
$branchcode = $patron->branchcode if ( $controlbranch eq "PatronLibrary" ); |
| 2483 |
|
| 2484 |
my $max = 0; |
| 2485 |
foreach my $item (@items) { |
| 2486 |
my $itemtype = $item->effective_itemtype(); |
| 2487 |
|
| 2488 |
$branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" ); |
| 2489 |
|
| 2490 |
my $rule = GetHoldRule( $categorycode, $itemtype, $branchcode ); |
| 2491 |
my $holds_per_record = $rule ? $rule->{holds_per_record} : 0; |
| 2492 |
$max = $holds_per_record if $holds_per_record > $max; |
| 2493 |
} |
| 2494 |
|
| 2495 |
return $max; |
| 2496 |
} |
| 2497 |
|
| 2498 |
=head2 GetHoldRule |
| 2499 |
|
| 2500 |
my $rule = GetHoldRule( $categorycode, $itemtype, $branchcode ); |
| 2501 |
|
| 2502 |
Returns the matching hold related issuingrule fields for a given |
| 2503 |
patron category, itemtype, and library. |
| 2504 |
|
| 2505 |
=cut |
| 2506 |
|
| 2507 |
sub GetHoldRule { |
| 2508 |
my ( $categorycode, $itemtype, $branchcode ) = @_; |
| 2509 |
|
| 2510 |
my $dbh = C4::Context->dbh; |
| 2511 |
|
| 2512 |
my $sth = $dbh->prepare( |
| 2513 |
q{ |
| 2514 |
SELECT categorycode, itemtype, branchcode, reservesallowed, holds_per_record |
| 2515 |
FROM issuingrules |
| 2516 |
WHERE (categorycode in (?,'*') ) |
| 2517 |
AND (itemtype IN (?,'*')) |
| 2518 |
AND (branchcode IN (?,'*')) |
| 2519 |
ORDER BY categorycode DESC, |
| 2520 |
itemtype DESC, |
| 2521 |
branchcode DESC |
| 2522 |
} |
| 2523 |
); |
| 2524 |
|
| 2525 |
$sth->execute( $categorycode, $itemtype, $branchcode ); |
| 2526 |
|
| 2527 |
return $sth->fetchrow_hashref(); |
| 2528 |
} |
| 2529 |
|
| 2459 |
=head1 AUTHOR |
2530 |
=head1 AUTHOR |
| 2460 |
|
2531 |
|
| 2461 |
Koha Development Team <http://koha-community.org/> |
2532 |
Koha Development Team <http://koha-community.org/> |