Lines 43-48
use Koha::Holds;
Link Here
|
43 |
use Koha::Libraries; |
43 |
use Koha::Libraries; |
44 |
use Koha::Items; |
44 |
use Koha::Items; |
45 |
use Koha::ItemTypes; |
45 |
use Koha::ItemTypes; |
|
|
46 |
use Koha::Patrons; |
46 |
|
47 |
|
47 |
use List::MoreUtils qw( firstidx any ); |
48 |
use List::MoreUtils qw( firstidx any ); |
48 |
use Carp; |
49 |
use Carp; |
Lines 141-146
BEGIN {
Link Here
|
141 |
&GetReservesControlBranch |
142 |
&GetReservesControlBranch |
142 |
|
143 |
|
143 |
IsItemOnHoldAndFound |
144 |
IsItemOnHoldAndFound |
|
|
145 |
|
146 |
GetMaxPatronHoldsForRecord |
144 |
); |
147 |
); |
145 |
@EXPORT_OK = qw( MergeHolds ); |
148 |
@EXPORT_OK = qw( MergeHolds ); |
146 |
} |
149 |
} |
Lines 168-179
sub AddReserve {
Link Here
|
168 |
$title, $checkitem, $found, $itemtype |
171 |
$title, $checkitem, $found, $itemtype |
169 |
) = @_; |
172 |
) = @_; |
170 |
|
173 |
|
171 |
if ( Koha::Holds->search( { borrowernumber => $borrowernumber, biblionumber => $biblionumber } )->count() > 0 ) { |
174 |
my $dbh = C4::Context->dbh; |
172 |
carp("AddReserve: borrower $borrowernumber already has a hold for biblionumber $biblionumber"); |
|
|
173 |
return; |
174 |
} |
175 |
|
176 |
my $dbh = C4::Context->dbh; |
177 |
|
175 |
|
178 |
$resdate = output_pref( { str => dt_from_string( $resdate ), dateonly => 1, dateformat => 'iso' }) |
176 |
$resdate = output_pref( { str => dt_from_string( $resdate ), dateonly => 1, dateformat => 'iso' }) |
179 |
or output_pref({ dt => dt_from_string, dateonly => 1, dateformat => 'iso' }); |
177 |
or output_pref({ dt => dt_from_string, dateonly => 1, dateformat => 'iso' }); |
Lines 458-464
sub CanItemBeReserved {
Link Here
|
458 |
|
456 |
|
459 |
my $dbh = C4::Context->dbh; |
457 |
my $dbh = C4::Context->dbh; |
460 |
my $ruleitemtype; # itemtype of the matching issuing rule |
458 |
my $ruleitemtype; # itemtype of the matching issuing rule |
461 |
my $allowedreserves = 0; |
459 |
my $allowedreserves = 0; # Total number of holds allowed across all records |
|
|
460 |
my $holds_per_record = 1; # Total number of holds allowed for this one given record |
462 |
|
461 |
|
463 |
# we retrieve borrowers and items informations # |
462 |
# we retrieve borrowers and items informations # |
464 |
# item->{itype} will come for biblioitems if necessery |
463 |
# item->{itype} will come for biblioitems if necessery |
Lines 471-496
sub CanItemBeReserved {
Link Here
|
471 |
if ( $item->{damaged} |
470 |
if ( $item->{damaged} |
472 |
&& !C4::Context->preference('AllowHoldsOnDamagedItems') ); |
471 |
&& !C4::Context->preference('AllowHoldsOnDamagedItems') ); |
473 |
|
472 |
|
474 |
#Check for the age restriction |
473 |
# Check for the age restriction |
475 |
my ( $ageRestriction, $daysToAgeRestriction ) = |
474 |
my ( $ageRestriction, $daysToAgeRestriction ) = |
476 |
C4::Circulation::GetAgeRestriction( $biblioData->{agerestriction}, $borrower ); |
475 |
C4::Circulation::GetAgeRestriction( $biblioData->{agerestriction}, $borrower ); |
477 |
return 'ageRestricted' if $daysToAgeRestriction && $daysToAgeRestriction > 0; |
476 |
return 'ageRestricted' if $daysToAgeRestriction && $daysToAgeRestriction > 0; |
478 |
|
477 |
|
479 |
my $controlbranch = C4::Context->preference('ReservesControlBranch'); |
478 |
# Check that the patron doesn't have an item level hold on this item already |
|
|
479 |
return 'itemAlreadyOnHold' |
480 |
if Koha::Holds->search( { borrowernumber => $borrowernumber, itemnumber => $itemnumber } )->count(); |
480 |
|
481 |
|
481 |
# we retrieve user rights on this itemtype and branchcode |
482 |
my $controlbranch = C4::Context->preference('ReservesControlBranch'); |
482 |
my $sth = $dbh->prepare( |
|
|
483 |
q{ |
484 |
SELECT categorycode, itemtype, branchcode, reservesallowed |
485 |
FROM issuingrules |
486 |
WHERE (categorycode in (?,'*') ) |
487 |
AND (itemtype IN (?,'*')) |
488 |
AND (branchcode IN (?,'*')) |
489 |
ORDER BY categorycode DESC, |
490 |
itemtype DESC, |
491 |
branchcode DESC |
492 |
} |
493 |
); |
494 |
|
483 |
|
495 |
my $querycount = q{ |
484 |
my $querycount = q{ |
496 |
SELECT count(*) AS count |
485 |
SELECT count(*) AS count |
Lines 514-528
sub CanItemBeReserved {
Link Here
|
514 |
} |
503 |
} |
515 |
|
504 |
|
516 |
# we retrieve rights |
505 |
# we retrieve rights |
517 |
$sth->execute( $borrower->{'categorycode'}, $item->{'itype'}, $branchcode ); |
506 |
if ( my $rights = GetHoldRule( $borrower->{'categorycode'}, $item->{'itype'}, $branchcode ) ) { |
518 |
if ( my $rights = $sth->fetchrow_hashref() ) { |
507 |
$ruleitemtype = $rights->{itemtype}; |
519 |
$ruleitemtype = $rights->{itemtype}; |
508 |
$allowedreserves = $rights->{reservesallowed}; |
520 |
$allowedreserves = $rights->{reservesallowed}; |
509 |
$holds_per_record = $rights->{holds_per_record}; |
521 |
} |
510 |
} |
522 |
else { |
511 |
else { |
523 |
$ruleitemtype = '*'; |
512 |
$ruleitemtype = '*'; |
524 |
} |
513 |
} |
525 |
|
514 |
|
|
|
515 |
my $item = Koha::Items->find( $itemnumber ); |
516 |
my $holds = Koha::Holds->search( |
517 |
{ |
518 |
borrowernumber => $borrowernumber, |
519 |
biblionumber => $item->biblionumber, |
520 |
found => undef, # Found holds don't count against a patron's holds limit |
521 |
} |
522 |
); |
523 |
if ( $holds->count() >= $holds_per_record ) { |
524 |
return "tooManyHoldsForThisRecord"; |
525 |
} |
526 |
|
526 |
# we retrieve count |
527 |
# we retrieve count |
527 |
|
528 |
|
528 |
$querycount .= "AND $branchfield = ?"; |
529 |
$querycount .= "AND $branchfield = ?"; |
Lines 752-759
sub GetReservesToBranch {
Link Here
|
752 |
my $dbh = C4::Context->dbh; |
753 |
my $dbh = C4::Context->dbh; |
753 |
my $sth = $dbh->prepare( |
754 |
my $sth = $dbh->prepare( |
754 |
"SELECT reserve_id,borrowernumber,reservedate,itemnumber,timestamp |
755 |
"SELECT reserve_id,borrowernumber,reservedate,itemnumber,timestamp |
755 |
FROM reserves |
756 |
FROM reserves |
756 |
WHERE priority='0' |
757 |
WHERE priority='0' |
757 |
AND branchcode=?" |
758 |
AND branchcode=?" |
758 |
); |
759 |
); |
759 |
$sth->execute( $frombranch ); |
760 |
$sth->execute( $frombranch ); |
Lines 778-784
sub GetReservesForBranch {
Link Here
|
778 |
|
779 |
|
779 |
my $query = " |
780 |
my $query = " |
780 |
SELECT reserve_id,borrowernumber,reservedate,itemnumber,waitingdate |
781 |
SELECT reserve_id,borrowernumber,reservedate,itemnumber,waitingdate |
781 |
FROM reserves |
782 |
FROM reserves |
782 |
WHERE priority='0' |
783 |
WHERE priority='0' |
783 |
AND found='W' |
784 |
AND found='W' |
784 |
"; |
785 |
"; |
Lines 1402-1408
sub ModReserveMinusPriority {
Link Here
|
1402 |
my $dbh = C4::Context->dbh; |
1403 |
my $dbh = C4::Context->dbh; |
1403 |
my $query = " |
1404 |
my $query = " |
1404 |
UPDATE reserves |
1405 |
UPDATE reserves |
1405 |
SET priority = 0 , itemnumber = ? |
1406 |
SET priority = 0 , itemnumber = ? |
1406 |
WHERE reserve_id = ? |
1407 |
WHERE reserve_id = ? |
1407 |
"; |
1408 |
"; |
1408 |
my $sth_upd = $dbh->prepare($query); |
1409 |
my $sth_upd = $dbh->prepare($query); |
Lines 1639-1645
sub ToggleLowestPriority {
Link Here
|
1639 |
|
1640 |
|
1640 |
my $sth = $dbh->prepare( "UPDATE reserves SET lowestPriority = NOT lowestPriority WHERE reserve_id = ?"); |
1641 |
my $sth = $dbh->prepare( "UPDATE reserves SET lowestPriority = NOT lowestPriority WHERE reserve_id = ?"); |
1641 |
$sth->execute( $reserve_id ); |
1642 |
$sth->execute( $reserve_id ); |
1642 |
|
1643 |
|
1643 |
_FixPriority({ reserve_id => $reserve_id, rank => '999999' }); |
1644 |
_FixPriority({ reserve_id => $reserve_id, rank => '999999' }); |
1644 |
} |
1645 |
} |
1645 |
|
1646 |
|
Lines 1823-1829
sub _FixPriority {
Link Here
|
1823 |
$priority[$j]->{'reserve_id'} |
1824 |
$priority[$j]->{'reserve_id'} |
1824 |
); |
1825 |
); |
1825 |
} |
1826 |
} |
1826 |
|
1827 |
|
1827 |
$sth = $dbh->prepare( "SELECT reserve_id FROM reserves WHERE lowestPriority = 1 ORDER BY priority" ); |
1828 |
$sth = $dbh->prepare( "SELECT reserve_id FROM reserves WHERE lowestPriority = 1 ORDER BY priority" ); |
1828 |
$sth->execute(); |
1829 |
$sth->execute(); |
1829 |
|
1830 |
|
Lines 2061-2067
sub _koha_notify_reserve {
Link Here
|
2061 |
if (! $notification_sent) { |
2062 |
if (! $notification_sent) { |
2062 |
&$send_notification('print', 'HOLD'); |
2063 |
&$send_notification('print', 'HOLD'); |
2063 |
} |
2064 |
} |
2064 |
|
2065 |
|
2065 |
} |
2066 |
} |
2066 |
|
2067 |
|
2067 |
=head2 _ShiftPriorityByDateAndPriority |
2068 |
=head2 _ShiftPriorityByDateAndPriority |
Lines 2490-2495
sub IsItemOnHoldAndFound {
Link Here
|
2490 |
return $found; |
2491 |
return $found; |
2491 |
} |
2492 |
} |
2492 |
|
2493 |
|
|
|
2494 |
=head2 GetMaxPatronHoldsForRecord |
2495 |
|
2496 |
my $holds_per_record = ReservesControlBranch( $borrowernumber, $biblionumber ); |
2497 |
|
2498 |
For multiple holds on a given record for a given patron, the max |
2499 |
number of record level holds that a patron can be placed is the highest |
2500 |
value of the holds_per_record rule for each item if the record for that |
2501 |
patron. This subroutine finds and returns the highest holds_per_record |
2502 |
rule value for a given patron id and record id. |
2503 |
|
2504 |
=cut |
2505 |
|
2506 |
sub GetMaxPatronHoldsForRecord { |
2507 |
my ( $borrowernumber, $biblionumber ) = @_; |
2508 |
|
2509 |
my $patron = Koha::Patrons->find($borrowernumber); |
2510 |
my @items = Koha::Items->search( { biblionumber => $biblionumber } ); |
2511 |
|
2512 |
my $controlbranch = C4::Context->preference('ReservesControlBranch'); |
2513 |
|
2514 |
my $categorycode = $patron->categorycode; |
2515 |
my $branchcode; |
2516 |
$branchcode = $patron->branchcode if ( $controlbranch eq "PatronLibrary" ); |
2517 |
|
2518 |
my $max = 0; |
2519 |
foreach my $item (@items) { |
2520 |
my $itemtype = $item->effective_itemtype(); |
2521 |
|
2522 |
$branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" ); |
2523 |
|
2524 |
my $rule = GetHoldRule( $categorycode, $itemtype, $branchcode ); |
2525 |
my $holds_per_record = $rule ? $rule->{holds_per_record} : 0; |
2526 |
$max = $holds_per_record if $holds_per_record > $max; |
2527 |
} |
2528 |
|
2529 |
return $max; |
2530 |
} |
2531 |
|
2532 |
=head2 GetHoldRule |
2533 |
|
2534 |
my $rule = GetHoldRule( $categorycode, $itemtype, $branchcode ); |
2535 |
|
2536 |
Returns the matching hold related issuingrule fields for a given |
2537 |
patron category, itemtype, and library. |
2538 |
|
2539 |
=cut |
2540 |
|
2541 |
sub GetHoldRule { |
2542 |
my ( $categorycode, $itemtype, $branchcode ) = @_; |
2543 |
|
2544 |
my $dbh = C4::Context->dbh; |
2545 |
|
2546 |
my $sth = $dbh->prepare( |
2547 |
q{ |
2548 |
SELECT categorycode, itemtype, branchcode, reservesallowed, holds_per_record |
2549 |
FROM issuingrules |
2550 |
WHERE (categorycode in (?,'*') ) |
2551 |
AND (itemtype IN (?,'*')) |
2552 |
AND (branchcode IN (?,'*')) |
2553 |
ORDER BY categorycode DESC, |
2554 |
itemtype DESC, |
2555 |
branchcode DESC |
2556 |
} |
2557 |
); |
2558 |
|
2559 |
$sth->execute( $categorycode, $itemtype, $branchcode ); |
2560 |
|
2561 |
return $sth->fetchrow_hashref(); |
2562 |
} |
2563 |
|
2493 |
=head1 AUTHOR |
2564 |
=head1 AUTHOR |
2494 |
|
2565 |
|
2495 |
Koha Development Team <http://koha-community.org/> |
2566 |
Koha Development Team <http://koha-community.org/> |