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 |