|
Lines 36-41
use Koha::Account::Lines;
Link Here
|
| 36 |
use Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue; |
36 |
use Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue; |
| 37 |
use Koha::Biblios; |
37 |
use Koha::Biblios; |
| 38 |
use Koha::Calendar; |
38 |
use Koha::Calendar; |
|
|
39 |
use Koha::Cache::Memory::Lite; |
| 39 |
use Koha::CirculationRules; |
40 |
use Koha::CirculationRules; |
| 40 |
use Koha::Database; |
41 |
use Koha::Database; |
| 41 |
use Koha::DateUtils qw( dt_from_string output_pref ); |
42 |
use Koha::DateUtils qw( dt_from_string output_pref ); |
|
Lines 419-427
sub CanBookBeReserved{
Link Here
|
| 419 |
|
420 |
|
| 420 |
=cut |
421 |
=cut |
| 421 |
|
422 |
|
|
|
423 |
our $CanItemBeReserved_cache_key; |
| 424 |
sub _cache { |
| 425 |
my ( $return ) = @_; |
| 426 |
my $memory_cache = Koha::Cache::Memory::Lite->get_instance(); |
| 427 |
$memory_cache->set_in_cache( $CanItemBeReserved_cache_key, $return ); |
| 428 |
return $return; |
| 429 |
} |
| 430 |
|
| 422 |
sub CanItemBeReserved { |
431 |
sub CanItemBeReserved { |
| 423 |
my ( $patron, $item, $pickup_branchcode, $params ) = @_; |
432 |
my ( $patron, $item, $pickup_branchcode, $params ) = @_; |
| 424 |
|
433 |
|
|
|
434 |
my $memory_cache = Koha::Cache::Memory::Lite->get_instance(); |
| 435 |
$CanItemBeReserved_cache_key = sprintf "Hold_CanItemBeReserved:%s:%s:%s", $patron->borrowernumber, $item->itemnumber, $pickup_branchcode || ""; |
| 436 |
if ( $params->{get_from_cache} ) { |
| 437 |
my $cached = $memory_cache->get_from_cache($CanItemBeReserved_cache_key); |
| 438 |
return $cached if $cached; |
| 439 |
} |
| 440 |
|
| 425 |
my $dbh = C4::Context->dbh; |
441 |
my $dbh = C4::Context->dbh; |
| 426 |
my $ruleitemtype; # itemtype of the matching issuing rule |
442 |
my $ruleitemtype; # itemtype of the matching issuing rule |
| 427 |
my $allowedreserves = 0; # Total number of holds allowed across all records, default to none |
443 |
my $allowedreserves = 0; # Total number of holds allowed across all records, default to none |
|
Lines 432-438
sub CanItemBeReserved {
Link Here
|
| 432 |
and !C4::Context->preference('canreservefromotherbranches') ) |
448 |
and !C4::Context->preference('canreservefromotherbranches') ) |
| 433 |
{ |
449 |
{ |
| 434 |
if ( $item->homebranch ne $patron->branchcode ) { |
450 |
if ( $item->homebranch ne $patron->branchcode ) { |
| 435 |
return { status => 'cannotReserveFromOtherBranches' }; |
451 |
return _cache { status => 'cannotReserveFromOtherBranches' }; |
| 436 |
} |
452 |
} |
| 437 |
} |
453 |
} |
| 438 |
|
454 |
|
|
Lines 441-447
sub CanItemBeReserved {
Link Here
|
| 441 |
my $borrower = $patron->unblessed; |
457 |
my $borrower = $patron->unblessed; |
| 442 |
|
458 |
|
| 443 |
# If an item is damaged and we don't allow holds on damaged items, we can stop right here |
459 |
# If an item is damaged and we don't allow holds on damaged items, we can stop right here |
| 444 |
return { status =>'damaged' } |
460 |
return _cache { status =>'damaged' } |
| 445 |
if ( $item->damaged |
461 |
if ( $item->damaged |
| 446 |
&& !C4::Context->preference('AllowHoldsOnDamagedItems') ); |
462 |
&& !C4::Context->preference('AllowHoldsOnDamagedItems') ); |
| 447 |
|
463 |
|
|
Lines 450-470
sub CanItemBeReserved {
Link Here
|
| 450 |
# Check for the age restriction |
466 |
# Check for the age restriction |
| 451 |
my ( $ageRestriction, $daysToAgeRestriction ) = |
467 |
my ( $ageRestriction, $daysToAgeRestriction ) = |
| 452 |
C4::Circulation::GetAgeRestriction( $biblio->biblioitem->agerestriction, $borrower ); |
468 |
C4::Circulation::GetAgeRestriction( $biblio->biblioitem->agerestriction, $borrower ); |
| 453 |
return { status => 'ageRestricted' } if $daysToAgeRestriction && $daysToAgeRestriction > 0; |
469 |
return _cache { status => 'ageRestricted' } if $daysToAgeRestriction && $daysToAgeRestriction > 0; |
| 454 |
} |
470 |
} |
| 455 |
|
471 |
|
| 456 |
# Check that the patron doesn't have an item level hold on this item already |
472 |
# Check that the patron doesn't have an item level hold on this item already |
| 457 |
return { status =>'itemAlreadyOnHold' } |
473 |
return _cache { status =>'itemAlreadyOnHold' } |
| 458 |
if ( !$params->{ignore_hold_counts} && Koha::Holds->search( { borrowernumber => $patron->borrowernumber, itemnumber => $item->itemnumber } )->count() ); |
474 |
if ( !$params->{ignore_hold_counts} && Koha::Holds->search( { borrowernumber => $patron->borrowernumber, itemnumber => $item->itemnumber } )->count() ); |
| 459 |
|
475 |
|
| 460 |
# Check that patron have not checked out this biblio (if AllowHoldsOnPatronsPossessions set) |
476 |
# Check that patron have not checked out this biblio (if AllowHoldsOnPatronsPossessions set) |
| 461 |
if ( !C4::Context->preference('AllowHoldsOnPatronsPossessions') |
477 |
if ( !C4::Context->preference('AllowHoldsOnPatronsPossessions') |
| 462 |
&& C4::Circulation::CheckIfIssuedToPatron( $patron->borrowernumber, $item->biblionumber ) ) { |
478 |
&& C4::Circulation::CheckIfIssuedToPatron( $patron->borrowernumber, $item->biblionumber ) ) { |
| 463 |
return { status =>'alreadypossession' }; |
479 |
return _cache { status =>'alreadypossession' }; |
| 464 |
} |
480 |
} |
| 465 |
|
481 |
|
| 466 |
# check if a recall exists on this item from this borrower |
482 |
# check if a recall exists on this item from this borrower |
| 467 |
return { status => 'recall' } |
483 |
return _cache { status => 'recall' } |
| 468 |
if $patron->recalls->filter_by_current->search({ item_id => $item->itemnumber })->count; |
484 |
if $patron->recalls->filter_by_current->search({ item_id => $item->itemnumber })->count; |
| 469 |
|
485 |
|
| 470 |
my $controlbranch = C4::Context->preference('ReservesControlBranch'); |
486 |
my $controlbranch = C4::Context->preference('ReservesControlBranch'); |
|
Lines 508-514
sub CanItemBeReserved {
Link Here
|
| 508 |
|
524 |
|
| 509 |
if ( defined $holds_per_record && $holds_per_record ne '' ){ |
525 |
if ( defined $holds_per_record && $holds_per_record ne '' ){ |
| 510 |
if ( $holds_per_record == 0 ) { |
526 |
if ( $holds_per_record == 0 ) { |
| 511 |
return { status => "noReservesAllowed" }; |
527 |
return _cache { status => "noReservesAllowed" }; |
| 512 |
} |
528 |
} |
| 513 |
if ( !$params->{ignore_hold_counts} ) { |
529 |
if ( !$params->{ignore_hold_counts} ) { |
| 514 |
my $search_params = { |
530 |
my $search_params = { |
|
Lines 516-522
sub CanItemBeReserved {
Link Here
|
| 516 |
biblionumber => $item->biblionumber, |
532 |
biblionumber => $item->biblionumber, |
| 517 |
}; |
533 |
}; |
| 518 |
my $holds = Koha::Holds->search($search_params); |
534 |
my $holds = Koha::Holds->search($search_params); |
| 519 |
return { status => "tooManyHoldsForThisRecord", limit => $holds_per_record } if $holds->count() >= $holds_per_record; |
535 |
return _cache { status => "tooManyHoldsForThisRecord", limit => $holds_per_record } if $holds->count() >= $holds_per_record; |
| 520 |
} |
536 |
} |
| 521 |
} |
537 |
} |
| 522 |
|
538 |
|
|
Lines 526-538
sub CanItemBeReserved {
Link Here
|
| 526 |
borrowernumber => $patron->borrowernumber, |
542 |
borrowernumber => $patron->borrowernumber, |
| 527 |
reservedate => dt_from_string->date |
543 |
reservedate => dt_from_string->date |
| 528 |
}); |
544 |
}); |
| 529 |
return { status => 'tooManyReservesToday', limit => $holds_per_day } if $today_holds->count() >= $holds_per_day; |
545 |
return _cache { status => 'tooManyReservesToday', limit => $holds_per_day } if $today_holds->count() >= $holds_per_day; |
| 530 |
} |
546 |
} |
| 531 |
|
547 |
|
| 532 |
# we check if it's ok or not |
548 |
# we check if it's ok or not |
| 533 |
if ( defined $allowedreserves && $allowedreserves ne '' ){ |
549 |
if ( defined $allowedreserves && $allowedreserves ne '' ){ |
| 534 |
if( $allowedreserves == 0 ){ |
550 |
if( $allowedreserves == 0 ){ |
| 535 |
return { status => 'noReservesAllowed' }; |
551 |
return _cache { status => 'noReservesAllowed' }; |
| 536 |
} |
552 |
} |
| 537 |
if ( !$params->{ignore_hold_counts} ) { |
553 |
if ( !$params->{ignore_hold_counts} ) { |
| 538 |
# we retrieve count |
554 |
# we retrieve count |
|
Lines 577-583
sub CanItemBeReserved {
Link Here
|
| 577 |
$reservecount = $rowcount->{count}; |
593 |
$reservecount = $rowcount->{count}; |
| 578 |
} |
594 |
} |
| 579 |
|
595 |
|
| 580 |
return { status => 'tooManyReserves', limit => $allowedreserves } if $reservecount >= $allowedreserves; |
596 |
return _cache { status => 'tooManyReserves', limit => $allowedreserves } if $reservecount >= $allowedreserves; |
| 581 |
} |
597 |
} |
| 582 |
} |
598 |
} |
| 583 |
|
599 |
|
|
Lines 596-621
sub CanItemBeReserved {
Link Here
|
| 596 |
} |
612 |
} |
| 597 |
)->count(); |
613 |
)->count(); |
| 598 |
|
614 |
|
| 599 |
return { status => 'tooManyReserves', limit => $rule->rule_value} if $total_holds_count >= $rule->rule_value; |
615 |
return _cache { status => 'tooManyReserves', limit => $rule->rule_value} if $total_holds_count >= $rule->rule_value; |
| 600 |
} |
616 |
} |
| 601 |
|
617 |
|
| 602 |
my $branchitemrule = |
618 |
my $branchitemrule = |
| 603 |
C4::Circulation::GetBranchItemRule( $reserves_control_branch, $item->effective_itemtype ); |
619 |
C4::Circulation::GetBranchItemRule( $reserves_control_branch, $item->effective_itemtype ); |
| 604 |
|
620 |
|
| 605 |
if ( $branchitemrule->{holdallowed} eq 'not_allowed' ) { |
621 |
if ( $branchitemrule->{holdallowed} eq 'not_allowed' ) { |
| 606 |
return { status => 'notReservable' }; |
622 |
return _cache { status => 'notReservable' }; |
| 607 |
} |
623 |
} |
| 608 |
|
624 |
|
| 609 |
if ( $branchitemrule->{holdallowed} eq 'from_home_library' |
625 |
if ( $branchitemrule->{holdallowed} eq 'from_home_library' |
| 610 |
&& $borrower->{branchcode} ne $item->homebranch ) |
626 |
&& $borrower->{branchcode} ne $item->homebranch ) |
| 611 |
{ |
627 |
{ |
| 612 |
return { status => 'cannotReserveFromOtherBranches' }; |
628 |
return _cache { status => 'cannotReserveFromOtherBranches' }; |
| 613 |
} |
629 |
} |
| 614 |
|
630 |
|
| 615 |
my $item_library = Koha::Libraries->find( {branchcode => $item->homebranch} ); |
631 |
my $item_library = Koha::Libraries->find( {branchcode => $item->homebranch} ); |
| 616 |
if ( $branchitemrule->{holdallowed} eq 'from_local_hold_group') { |
632 |
if ( $branchitemrule->{holdallowed} eq 'from_local_hold_group') { |
| 617 |
if($patron->branchcode ne $item->homebranch && !$item_library->validate_hold_sibling( {branchcode => $patron->branchcode} )) { |
633 |
if($patron->branchcode ne $item->homebranch && !$item_library->validate_hold_sibling( {branchcode => $patron->branchcode} )) { |
| 618 |
return { status => 'branchNotInHoldGroup' }; |
634 |
return _cache { status => 'branchNotInHoldGroup' }; |
| 619 |
} |
635 |
} |
| 620 |
} |
636 |
} |
| 621 |
|
637 |
|
|
Lines 625-647
sub CanItemBeReserved {
Link Here
|
| 625 |
}); |
641 |
}); |
| 626 |
|
642 |
|
| 627 |
unless ($destination) { |
643 |
unless ($destination) { |
| 628 |
return { status => 'libraryNotFound' }; |
644 |
return _cache { status => 'libraryNotFound' }; |
| 629 |
} |
645 |
} |
| 630 |
unless ($destination->pickup_location) { |
646 |
unless ($destination->pickup_location) { |
| 631 |
return { status => 'libraryNotPickupLocation' }; |
647 |
return _cache { status => 'libraryNotPickupLocation' }; |
| 632 |
} |
648 |
} |
| 633 |
unless ($item->can_be_transferred({ to => $destination })) { |
649 |
unless ($item->can_be_transferred({ to => $destination })) { |
| 634 |
return { status => 'cannotBeTransferred' }; |
650 |
return _cache { status => 'cannotBeTransferred' }; |
| 635 |
} |
651 |
} |
| 636 |
if ($branchitemrule->{hold_fulfillment_policy} eq 'holdgroup' && !$item_library->validate_hold_sibling( {branchcode => $pickup_branchcode} )) { |
652 |
if ($branchitemrule->{hold_fulfillment_policy} eq 'holdgroup' && !$item_library->validate_hold_sibling( {branchcode => $pickup_branchcode} )) { |
| 637 |
return { status => 'pickupNotInHoldGroup' }; |
653 |
return _cache { status => 'pickupNotInHoldGroup' }; |
| 638 |
} |
654 |
} |
| 639 |
if ($branchitemrule->{hold_fulfillment_policy} eq 'patrongroup' && !Koha::Libraries->find({branchcode => $borrower->{branchcode}})->validate_hold_sibling({branchcode => $pickup_branchcode})) { |
655 |
if ($branchitemrule->{hold_fulfillment_policy} eq 'patrongroup' && !Koha::Libraries->find({branchcode => $borrower->{branchcode}})->validate_hold_sibling({branchcode => $pickup_branchcode})) { |
| 640 |
return { status => 'pickupNotInHoldGroup' }; |
656 |
return _cache { status => 'pickupNotInHoldGroup' }; |
| 641 |
} |
657 |
} |
| 642 |
} |
658 |
} |
| 643 |
|
659 |
|
| 644 |
return { status => 'OK' }; |
660 |
return _cache { status => 'OK' }; |
| 645 |
} |
661 |
} |
| 646 |
|
662 |
|
| 647 |
=head2 CanReserveBeCanceledFromOpac |
663 |
=head2 CanReserveBeCanceledFromOpac |