View | Details | Raw Unified | Return to bug 30860
Collapse All | Expand All

(-)a/C4/Reserves.pm (-21 / +37 lines)
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
(-)a/opac/opac-reserve.pl (-2 / +2 lines)
Lines 264-270 if ( $query->param('place_reserve') ) { Link Here
264
        my $biblio = Koha::Biblios->find($biblioNum);
264
        my $biblio = Koha::Biblios->find($biblioNum);
265
        my $rank = $biblio->holds->search( { found => [ { "!=" => "W" }, undef ] } )->count + 1;
265
        my $rank = $biblio->holds->search( { found => [ { "!=" => "W" }, undef ] } )->count + 1;
266
        if ( $item ) {
266
        if ( $item ) {
267
            my $status = CanItemBeReserved( $patron, $item, $branch )->{status};
267
            my $status = CanItemBeReserved( $patron, $item, $branch, { get_from_cache => 1 } )->{status};
268
            if( $status eq 'OK' ){
268
            if( $status eq 'OK' ){
269
                $canreserve = 1;
269
                $canreserve = 1;
270
            } else {
270
            } else {
Lines 484-490 foreach my $biblioNum (@biblionumbers) { Link Here
484
        # items_any_available defined outside of the current loop,
484
        # items_any_available defined outside of the current loop,
485
        # so we avoiding loop inside IsAvailableForItemLevelRequest:
485
        # so we avoiding loop inside IsAvailableForItemLevelRequest:
486
        my $policy_holdallowed =
486
        my $policy_holdallowed =
487
            CanItemBeReserved( $patron, $item )->{status} eq 'OK' &&
487
            CanItemBeReserved( $patron, $item, undef, { get_from_cache => 1 } )->{status} eq 'OK' &&
488
            IsAvailableForItemLevelRequest($item, $patron, undef, $items_any_available);
488
            IsAvailableForItemLevelRequest($item, $patron, undef, $items_any_available);
489
489
490
        if ($policy_holdallowed) {
490
        if ($policy_holdallowed) {
(-)a/reserve/request.pl (-2 / +1 lines)
Lines 486-492 if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) Link Here
486
486
487
                    $item->{'holdallowed'} = $branchitemrule->{'holdallowed'};
487
                    $item->{'holdallowed'} = $branchitemrule->{'holdallowed'};
488
488
489
                    my $can_item_be_reserved = CanItemBeReserved( $patron, $item_object )->{status};
489
                    my $can_item_be_reserved = CanItemBeReserved( $patron, $item_object, undef, { get_from_cache => 1 } )->{status};
490
                    $item->{not_holdable} = $can_item_be_reserved unless ( $can_item_be_reserved eq 'OK' );
490
                    $item->{not_holdable} = $can_item_be_reserved unless ( $can_item_be_reserved eq 'OK' );
491
                    $item->{not_holdable} ||= 'notforloan' if ( $item->{notforloanitype} || $item->{notforloan} > 0 );
491
                    $item->{not_holdable} ||= 'notforloan' if ( $item->{notforloanitype} || $item->{notforloan} > 0 );
492
492
493
- 

Return to bug 30860