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

(-)a/C4/Reserves.pm (-34 lines)
Lines 140-146 BEGIN { Link Here
140
        IsItemOnHoldAndFound
140
        IsItemOnHoldAndFound
141
141
142
        GetMaxPatronHoldsForRecord
142
        GetMaxPatronHoldsForRecord
143
        GetAllowedHoldsForPatronToday
144
    );
143
    );
145
    @EXPORT_OK = qw( MergeHolds );
144
    @EXPORT_OK = qw( MergeHolds );
146
}
145
}
Lines 2122-2160 sub GetMaxPatronHoldsForRecord { Link Here
2122
    return $max;
2121
    return $max;
2123
}
2122
}
2124
2123
2125
=head2 GetAllowedHoldsForPatronToday
2126
2127
my $holds_allowed_on_record_today = GetAllowedHoldsForPatronToday( $patron->borrowernumber, $biblionumber );
2128
2129
Calculates and returns the number of item-level holds a borrower is allowed to place on the record on a single day.
2130
2131
=cut
2132
2133
sub GetAllowedHoldsForPatronToday {
2134
    my ( $borrowernumber, $biblionumber ) = @_;
2135
2136
    my $patron = Koha::Patrons->find($borrowernumber);
2137
    my @items = Koha::Items->search( { biblionumber => $biblionumber } );
2138
2139
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
2140
2141
    my $categorycode = $patron->categorycode;
2142
    my $branchcode;
2143
    $branchcode = $patron->branchcode if ( $controlbranch eq "PatronLibrary" );
2144
2145
    my $holds_allowed = 0;
2146
    foreach my $item (@items) {
2147
        my $itemtype = $item->effective_itemtype();
2148
2149
        $branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" );
2150
2151
        my $rule = GetHoldRule( $categorycode, $itemtype, $branchcode );
2152
        my $holds_per_day = $rule ? $rule->{holds_per_day} : 0;
2153
        $holds_allowed = $holds_per_day if $holds_per_day > $holds_allowed;
2154
    }
2155
    return $holds_allowed;
2156
}
2157
2158
=head2 GetHoldRule
2124
=head2 GetHoldRule
2159
2125
2160
my $rule = GetHoldRule( $categorycode, $itemtype, $branchcode );
2126
my $rule = GetHoldRule( $categorycode, $itemtype, $branchcode );
(-)a/Koha/Biblio.pm (+31 lines)
Lines 425-430 sub has_items_waiting_or_intransit { Link Here
425
    return 0;
425
    return 0;
426
}
426
}
427
427
428
=head3 allowed_holds
429
430
    my $holds_allowed_on_record_today = $biblio->allowed_holds( $patron_obj );
431
432
    Calculates and returns the number of item-level holds a borrower is allowed to place on the record on a single day.
433
434
=cut
435
436
sub allowed_holds {
437
    my ( $self, $patron ) = @_;
438
439
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
440
441
    my $categorycode = $patron->categorycode;
442
    my $branchcode;
443
    $branchcode = $patron->branchcode if ( $controlbranch eq "PatronLibrary" );
444
445
    my $holds_allowed = 0;
446
    foreach my $item ( $self->items()->as_list() ) {
447
       my $itemtype = $item->effective_itemtype();
448
       $branchcode = $item->homebranch if ( $controlbranch eq "ItemHomeLibrary" );
449
450
       my $rule = C4::Reserves::GetHoldRule( $categorycode, $itemtype, $branchcode );
451
       my $holds_per_day = $rule ? $rule->{holds_per_day} : 0;
452
       if ( $holds_per_day ) {
453
            $holds_allowed = $holds_per_day if $holds_per_day > $holds_allowed;
454
       }
455
    }
456
    return $holds_allowed;
457
}
458
428
=head3 type
459
=head3 type
429
460
430
=cut
461
=cut
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt (-15 / +25 lines)
Lines 463-469 Link Here
463
<script>
463
<script>
464
// <![CDATA[
464
// <![CDATA[
465
    var MSG_NO_ITEM_SELECTED = _("Expecting a specific item selection.");
465
    var MSG_NO_ITEM_SELECTED = _("Expecting a specific item selection.");
466
    var MSG_MAX_HOLDS_EXCEEDED = _("Maximum number of reserve exceded.");
466
    var MSG_MAX_HOLDS_EXCEEDED = _("Maximum number of reserves for this record reached.");
467
    var MSG_EXCEEDED_HOLDS_PER_DAY =  _("Maximum number of reserves allowed today reached.");
468
    var MSG_EXCEEDED_MAXRESERVES_SYSPREF = _("Maximum number of holds allowed at once reached");
467
469
468
        // Clear the contents of an input field
470
        // Clear the contents of an input field
469
        $(".clearfield").on("click",function(e){
471
        $(".clearfield").on("click",function(e){
Lines 475-494 Link Here
475
    function select_first_available(id){
477
    function select_first_available(id){
476
        var checkboxes = $("input:checkbox[name='checkitem_" + id + "']");
478
        var checkboxes = $("input:checkbox[name='checkitem_" + id + "']");
477
        $(checkboxes).first().attr("checked", "checked");
479
        $(checkboxes).first().attr("checked", "checked");
478
479
        var nbCheked = 1;
480
        var remaining = $("input[id='remaining_holds_"+id+"']").val();
481
        var remaining_holds_today = $("input[id='remaining_holds_allowed_today"+id+"']").val();
482
        var maxreserves = "[% maxreserves | html %]";
483
        if (nbCheked == remaining) {
484
            $("input[name='checkitem_"+id+"']:not(:checked)").attr('disabled', 'disabled');
485
        }
486
        else if (nbCheked == remaining_holds_today) {
487
            $("input[name='checkitem_"+id+"']:not(:checked)").attr('disabled', 'disabled');
488
        }
489
        else if (nbCheked == maxreserves) {
490
            $("input[name='checkitem_"+id+"']:not(:checked)").attr('disabled', 'disabled');
491
        }
492
    }
480
    }
493
481
494
    $(document).ready(function() {
482
    $(document).ready(function() {
Lines 516-527 Link Here
516
            var remaining_holds_today = $("input[id='remaining_holds_allowed_today"+bibNum+"']").val();
504
            var remaining_holds_today = $("input[id='remaining_holds_allowed_today"+bibNum+"']").val();
517
            var maxreserves = "[% maxreserves | html %]";
505
            var maxreserves = "[% maxreserves | html %]";
518
            if (nbCheked >= remaining) {
506
            if (nbCheked >= remaining) {
507
                alert(MSG_MAX_HOLDS_EXCEEDED);
519
                $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled');
508
                $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled');
520
            }
509
            }
521
            else if (nbCheked >= remaining_holds_today) {
510
            else if (nbCheked >= remaining_holds_today) {
511
                alert(MSG_EXCEEDED_HOLDS_PER_DAY);
522
                $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled');
512
                $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled');
523
            }
513
            }
524
            else if (nbCheked >= maxreserves) {
514
            else if (nbCheked >= maxreserves) {
515
                alert(MSG_EXCEEDED_MAXRESERVES_SYSPREF);
525
                $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled');
516
                $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled');
526
            }
517
            }
527
            else {
518
            else {
Lines 584-589 Link Here
584
            if ( $(checkbox).is(":checked") && select_specific ) {
575
            if ( $(checkbox).is(":checked") && select_specific ) {
585
                $(newCopiesRowId).show();
576
                $(newCopiesRowId).show();
586
                $(holdsToPlaceCountId).hide();
577
                $(holdsToPlaceCountId).hide();
578
579
                //Check if maximum holds is reached and if it has then disable un-checked item checkboxes and display message
580
                var nbCheked = 1;
581
                var remaining = $("input[id='remaining_holds_"+biblioNum+"']").val();
582
                var remaining_holds_today = $("input[id='remaining_holds_allowed_today"+biblioNum+"']").val();
583
                var maxreserves = "[% maxreserves | html %]";
584
                if (nbCheked == remaining) {
585
                   alert(MSG_MAX_HOLDS_EXCEEDED);
586
                   $("input[name='checkitem_"+biblioNum+"']:not(:checked)").attr('disabled', 'disabled');
587
                }
588
                else if (nbCheked == remaining_holds_today) {
589
                   alert(MSG_EXCEEDED_HOLDS_PER_DAY);
590
                   $("input[name='checkitem_"+biblioNum+"']:not(:checked)").attr('disabled', 'disabled');
591
                }
592
                else if (nbCheked == maxreserves) {
593
                   alert(MSG_EXCEEDED_MAXRESERVES_SYSPREF);
594
                   $("input[name='checkitem_"+biblioNum+"']:not(:checked)").attr('disabled', 'disabled');
595
                }
596
587
            } else {
597
            } else {
588
                $(newCopiesRowId).hide();
598
                $(newCopiesRowId).hide();
589
                $(holdsToPlaceCountId).show();
599
                $(holdsToPlaceCountId).show();
(-)a/opac/opac-reserve.pl (-1 / +3 lines)
Lines 630-636 foreach my $biblioNum (@biblionumbers) { Link Here
630
       reservedate    => dt_from_string->date
630
       reservedate    => dt_from_string->date
631
    });
631
    });
632
632
633
    my $holds_allowed_on_record_today = GetAllowedHoldsForPatronToday( $borrowernumber, $biblioNum );
633
    my $biblio_record = Koha::Biblios->find( $biblioNum );
634
    my $patron_obj = Koha::Patrons->find( $borrowernumber );
635
    my $holds_allowed_on_record_today = $biblio_record->allowed_holds( $patron_obj );
634
    my $remaining_holds_allowed_today = $holds_allowed_on_record_today - $today_holds->count();
636
    my $remaining_holds_allowed_today = $holds_allowed_on_record_today - $today_holds->count();
635
637
636
    $biblioLoopIter{remaining_holds_for_record} = $remaining_holds_for_record;
638
    $biblioLoopIter{remaining_holds_for_record} = $remaining_holds_for_record;
(-)a/reserve/request.pl (-1 / +4 lines)
Lines 267-273 foreach my $biblionumber (@biblionumbers) { Link Here
267
            reservedate    => dt_from_string->date
267
            reservedate    => dt_from_string->date
268
        });
268
        });
269
269
270
        my $holds_allowed_on_record_today = GetAllowedHoldsForPatronToday( $patron->borrowernumber, $biblionumber );
270
271
        my $biblio_record = Koha::Biblios->find( $biblionumber );
272
        my $patron_obj = Koha::Patrons->find( $patron->borrowernumber );
273
        my $holds_allowed_on_record_today = $biblio_record->allowed_holds( $patron_obj );
271
        my $remaining_holds_allowed_today = $holds_allowed_on_record_today - $today_holds->count();
274
        my $remaining_holds_allowed_today = $holds_allowed_on_record_today - $today_holds->count();
272
275
273
        my $maxreserves = C4::Context->preference('maxreserves');
276
        my $maxreserves = C4::Context->preference('maxreserves');
(-)a/t/db_dependent/Reserves/MultiplePerRecord.t (-4 / +6 lines)
Lines 24-30 use Test::More tests => 42; Link Here
24
use t::lib::TestBuilder;
24
use t::lib::TestBuilder;
25
use t::lib::Mocks;
25
use t::lib::Mocks;
26
26
27
use C4::Reserves qw( GetMaxPatronHoldsForRecord GetAllowedHoldsForPatronToday AddReserve CanBookBeReserved );
27
use C4::Reserves qw( GetMaxPatronHoldsForRecord AddReserve CanBookBeReserved );
28
use Koha::Database;
28
use Koha::Database;
29
use Koha::Holds;
29
use Koha::Holds;
30
30
Lines 205-211 my $rule4 = $rules_rs->new( Link Here
205
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
205
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
206
is( $max, 4, 'GetMaxPatronHoldsForRecord returns max of 4' );
206
is( $max, 4, 'GetMaxPatronHoldsForRecord returns max of 4' );
207
207
208
my $holds_per_day = GetAllowedHoldsForPatronToday( $patron->{borrowernumber}, $biblio->{biblionumber} );
208
my $biblio_record = Koha::Biblios->find( $biblio->{biblionumber} );
209
my $patron_obj = Koha::Patrons->find( $patron->{borrowernumber} );
210
211
my $holds_per_day = $biblio_record->allowed_holds( $patron_obj );
209
is( $holds_per_day, 4, 'GetAllowedHoldsForPatronToday returns max of 4' );
212
is( $holds_per_day, 4, 'GetAllowedHoldsForPatronToday returns max of 4' );
210
213
211
$rule = C4::Reserves::GetHoldRule(
214
$rule = C4::Reserves::GetHoldRule(
Lines 234-240 my $rule5 = $rules_rs->new( Link Here
234
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
237
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
235
is( $max, 5, 'GetMaxPatronHoldsForRecord returns max of 1' );
238
is( $max, 5, 'GetMaxPatronHoldsForRecord returns max of 1' );
236
239
237
$holds_per_day = GetAllowedHoldsForPatronToday( $patron->{borrowernumber}, $biblio->{biblionumber} );
240
$holds_per_day = $biblio_record->allowed_holds( $patron_obj );
238
is( $holds_per_day, 5, 'GetAllowedHoldsForPatronToday returns max of 5' );
241
is( $holds_per_day, 5, 'GetAllowedHoldsForPatronToday returns max of 5' );
239
242
240
243
241
- 

Return to bug 15565