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

(-)a/C4/Reserves.pm (-1 / +1 lines)
Lines 4-9 package C4::Reserves; Link Here
4
#           2006 SAN Ouest Provence
4
#           2006 SAN Ouest Provence
5
#           2007-2010 BibLibre Paul POULAIN
5
#           2007-2010 BibLibre Paul POULAIN
6
#           2011 Catalyst IT
6
#           2011 Catalyst IT
7
#           2018 Catalyst IT
7
#
8
#
8
# This file is part of Koha.
9
# This file is part of Koha.
9
#
10
#
Lines 275-281 See CanItemBeReserved() for possible return values. Link Here
275
276
276
sub CanBookBeReserved{
277
sub CanBookBeReserved{
277
    my ($borrowernumber, $biblionumber, $pickup_branchcode) = @_;
278
    my ($borrowernumber, $biblionumber, $pickup_branchcode) = @_;
278
279
    my @itemnumbers = Koha::Items->search({ biblionumber => $biblionumber})->get_column("itemnumber");
279
    my @itemnumbers = Koha::Items->search({ biblionumber => $biblionumber})->get_column("itemnumber");
280
    #get items linked via host records
280
    #get items linked via host records
281
    my @hostitems = get_hostitemnumbers_of($biblionumber);
281
    my @hostitems = get_hostitemnumbers_of($biblionumber);
(-)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/intranet-tmpl/prog/en/modules/reserve/request.tt (-5 / +22 lines)
Lines 248-254 Link Here
248
          [% IF remaining_holds_for_record > 1 %]
248
          [% IF remaining_holds_for_record > 1 %]
249
              <li>
249
              <li>
250
                   <label for="holds_to_place_count">Holds to place (count)</label>
250
                   <label for="holds_to_place_count">Holds to place (count)</label>
251
                   <input type="number" name="holds_to_place_count" min="1" max="[% remaining_holds_for_record | html %]" step="1" value="1" />
251
                   <input type="number" name="holds_to_place_count" min="1" max="[% lowest_value | html %]" step="1" value="1" />
252
              </li>
252
              </li>
253
            [% ELSE %]
253
            [% ELSE %]
254
                <input type="hidden" name="holds_to_place_count" value="1" />
254
                <input type="hidden" name="holds_to_place_count" value="1" />
Lines 670-678 Link Here
670
            [% END %][% END %][% END %]
670
            [% END %][% END %][% END %]
671
        };
671
        };
672
        var MSG_NO_ITEMS_AVAILABLE = _("A hold cannot be requested on any of these items.");
672
        var MSG_NO_ITEMS_AVAILABLE = _("A hold cannot be requested on any of these items.");
673
        var MSG_EXCEEDED_HOLDS_PER_RECORD = _("Patron has exceeded the number of holds for this record.");
673
        var MSG_EXCEEDED_HOLDS_PER_RECORD = _("Patron reached the maximum number of holds for this record.");
674
        var MSG_EXCEEDED_HOLDS_PER_DAY =  _("Patron reached the maximum number of holds allowed today.");
675
        var MSG_EXCEEDED_MAXRESERVES_SYSPREF = _("Patron reached the maximum number of holds allowed at once");
674
        var remainingHolds = "[% remaining_holds_for_record | html %]";
676
        var remainingHolds = "[% remaining_holds_for_record | html %]";
675
677
        var remainingHoldsToday = "[% remaining_holds_allowed_today | html %]";
678
        var maxreserves = "[% maxreserves | html %]";
676
        $(document).ready(function() {
679
        $(document).ready(function() {
677
            function ToggleHoldsToPlace() {
680
            function ToggleHoldsToPlace() {
678
                if ( $("#requestany").prop('checked') ) {
681
                if ( $("#requestany").prop('checked') ) {
Lines 685-691 Link Here
685
            $("#requestany").on('change', function(){
688
            $("#requestany").on('change', function(){
686
                ToggleHoldsToPlace();
689
                ToggleHoldsToPlace();
687
            });
690
            });
688
689
            [% IF AutoResumeSuspendedHolds %]
691
            [% IF AutoResumeSuspendedHolds %]
690
                $(".suspend_until_datepicker, .datepickerfrom, .datepickerto").datepicker("option", "minDate", 1);
692
                $(".suspend_until_datepicker, .datepickerfrom, .datepickerto").datepicker("option", "minDate", 1);
691
            [% END %]
693
            [% END %]
Lines 807-814 Link Here
807
                } else {
809
                } else {
808
                    $("#requestany").prop("checked",true);
810
                    $("#requestany").prop("checked",true);
809
                }
811
                }
810
                if (remainingHolds - numchecked < 0) {
812
                if (remainingHolds - numchecked <= 0) {
811
                    alert(MSG_EXCEEDED_HOLDS_PER_RECORD);
813
                    alert(MSG_EXCEEDED_HOLDS_PER_RECORD);
814
                    [% IF !(Koha.Preference('AllowHoldPolicyOverride')) %]
815
                        $('input[name=checkitem]:not(:checked)').attr('disabled', 'disabled');
816
                    [% END %]
817
                }
818
                if (remainingHoldsToday - numchecked <= 0) {
819
                    alert(MSG_EXCEEDED_HOLDS_PER_DAY);
820
                    [% IF !(Koha.Preference('AllowHoldPolicyOverride')) %]
821
                        $('input[name=checkitem]:not(:checked)').attr('disabled', 'disabled');
822
                    [% END %]
823
                }
824
                if (maxreserves - numchecked <= 0) {
825
                    alert(MSG_EXCEEDED_MAXRESERVES_SYSPREF);
826
                    [% IF !(Koha.Preference('AllowHoldPolicyOverride')) %]
827
                        $('input[name=checkitem]:not(:checked)').attr('disabled', 'disabled');
828
                    [% END %]
812
                }
829
                }
813
            });
830
            });
814
            var prev_rank_request;
831
            var prev_rank_request;
(-)a/koha-tmpl/opac-tmpl/bootstrap/css/src/opac.scss (+1 lines)
Lines 3004-3009 button.closebtn { Link Here
3004
3004
3005
.hold-options {
3005
.hold-options {
3006
    clear: both;
3006
    clear: both;
3007
    width: auto;
3007
}
3008
}
3008
3009
3009
.toggle-hold-options {
3010
.toggle-hold-options {
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt (-4 / +46 lines)
Lines 151-156 Link Here
151
                                [% FOREACH bibitemloo IN bibitemloop %]
151
                                [% FOREACH bibitemloo IN bibitemloop %]
152
                                    <div class="holdrow">
152
                                    <div class="holdrow">
153
                                        <input id="remaining_holds_[% bibitemloo.biblionumber | html %]" type="hidden" value="[% bibitemloo.remaining_holds_for_record | html %]"/>
153
                                        <input id="remaining_holds_[% bibitemloo.biblionumber | html %]" type="hidden" value="[% bibitemloo.remaining_holds_for_record | html %]"/>
154
                                        <input id="remaining_holds_allowed_today[% bibitemloo.biblionumber | html %]" type="hidden" value="[% bibitemloo.remaining_holds_allowed_today | html %]"/>
154
                                        <p>
155
                                        <p>
155
                                            [% IF ( bibitemloo.holdable ) %]
156
                                            [% IF ( bibitemloo.holdable ) %]
156
                                                <span title="[% bibitemloo.biblionumber | html %]" style="padding:.3em">
157
                                                <span title="[% bibitemloo.biblionumber | html %]" style="padding:.3em">
Lines 298-305 Link Here
298
                                                            </li>
299
                                                            </li>
299
                                                        [% END # / IF OpacHoldNotes %]
300
                                                        [% END # / IF OpacHoldNotes %]
300
301
302
                                                        [% IF bibitemloo.itemholdable %]
301
                                                        <!-- ITEM HOLDS -->
303
                                                        <!-- ITEM HOLDS -->
302
                                                        <li class="lradio place_on_type" style="display:none;">
304
                                                        <li class="lradio place_on_type" style="display:none;">
305
                                                            [% IF NOT bibitemloo.force_hold %]
303
                                                                <label class="radio inline" for="reqany_[% bibitemloo.biblionumber | html %]">Next available item</label>
306
                                                                <label class="radio inline" for="reqany_[% bibitemloo.biblionumber | html %]">Next available item</label>
304
                                                                <input type="radio" name="reqtype_[% bibitemloo.biblionumber | html %]"
307
                                                                <input type="radio" name="reqtype_[% bibitemloo.biblionumber | html %]"
305
                                                                        id="reqany_[% bibitemloo.biblionumber | html %]"
308
                                                                        id="reqany_[% bibitemloo.biblionumber | html %]"
Lines 307-312 Link Here
307
                                                                        value="Any"
310
                                                                        value="Any"
308
                                                                        checked="checked"
311
                                                                        checked="checked"
309
                                                                />
312
                                                                />
313
                                                            [% END %]
310
                                                            <label class="radio inline" for="reqspecific_[% bibitemloo.biblionumber | html %]">A specific item</label>
314
                                                            <label class="radio inline" for="reqspecific_[% bibitemloo.biblionumber | html %]">A specific item</label>
311
                                                            <input type="radio" name="reqtype_[% bibitemloo.biblionumber | html %]"
315
                                                            <input type="radio" name="reqtype_[% bibitemloo.biblionumber | html %]"
312
                                                                   id="reqspecific_[% bibitemloo.biblionumber | html %]"
316
                                                                   id="reqspecific_[% bibitemloo.biblionumber | html %]"
Lines 314-319 Link Here
314
                                                                   value="Specific"
318
                                                                   value="Specific"
315
                                                            />
319
                                                            />
316
                                                        </li>
320
                                                        </li>
321
                                                        [% END # / IF bibitemloo.itemholdable %]
317
                                                    </ul>
322
                                                    </ul>
318
323
319
                                                    [% IF bibitemloo.remaining_holds_for_record > 1 %]
324
                                                    [% IF bibitemloo.remaining_holds_for_record > 1 %]
Lines 321-327 Link Here
321
                                                        <div id="holds_to_place_[% bibitemloo.biblionumber | html %]" class="hold-options holds-to-place">
326
                                                        <div id="holds_to_place_[% bibitemloo.biblionumber | html %]" class="hold-options holds-to-place">
322
                                                            <label>Holds to place (count)</label>
327
                                                            <label>Holds to place (count)</label>
323
                                                            <select name="holds_to_place_count_[% bibitemloo.biblionumber | html %]">
328
                                                            <select name="holds_to_place_count_[% bibitemloo.biblionumber | html %]">
324
                                                            [% WHILE count <= bibitemloo.remaining_holds_for_record %]
329
                                                            [% WHILE count <= bibitemloo.lowest_value %]
325
                                                                <option value="[% count | html %]">[% count | html %]</option>
330
                                                                <option value="[% count | html %]">[% count | html %]</option>
326
                                                                [% SET count = count + 1 %]
331
                                                                [% SET count = count + 1 %]
327
                                                            [% END %]
332
                                                            [% END %]
Lines 458-464 Link Here
458
<script>
463
<script>
459
// <![CDATA[
464
// <![CDATA[
460
    var MSG_NO_ITEM_SELECTED = _("Expecting a specific item selection.");
465
    var MSG_NO_ITEM_SELECTED = _("Expecting a specific item selection.");
461
    var MSG_MAX_HOLDS_EXCEEDED = _("Maximum number of reserve exceded.");
466
    var MSG_MAX_HOLDS_EXCEEDED = _("Maximum number of holds for this record reached.");
467
    var MSG_EXCEEDED_HOLDS_PER_DAY =  _("Maximum number of holds allowed today reached.");
468
    var MSG_EXCEEDED_MAXRESERVES_SYSPREF = _("Maximum number of holds allowed at once reached");
462
469
463
        // Clear the contents of an input field
470
        // Clear the contents of an input field
464
        $(".clearfield").on("click",function(e){
471
        $(".clearfield").on("click",function(e){
Lines 494-505 Link Here
494
            var bibNum = suffixOf($(this).attr("name"), "_");
501
            var bibNum = suffixOf($(this).attr("name"), "_");
495
            var nbCheked = $("input[name='checkitem_"+bibNum+"']:checked").length;
502
            var nbCheked = $("input[name='checkitem_"+bibNum+"']:checked").length;
496
            var remaining = $("input[id='remaining_holds_"+bibNum+"']").val();
503
            var remaining = $("input[id='remaining_holds_"+bibNum+"']").val();
504
            var remaining_holds_today = $("input[id='remaining_holds_allowed_today"+bibNum+"']").val();
505
            var maxreserves = "[% maxreserves | html %]";
497
            if (nbCheked >= remaining) {
506
            if (nbCheked >= remaining) {
507
                alert(MSG_MAX_HOLDS_EXCEEDED);
508
                $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled');
509
            }
510
            else if (nbCheked >= remaining_holds_today) {
511
                alert(MSG_EXCEEDED_HOLDS_PER_DAY);
512
                $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled');
513
            }
514
            else if (nbCheked >= maxreserves) {
515
                alert(MSG_EXCEEDED_MAXRESERVES_SYSPREF);
498
                $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled');
516
                $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled');
499
            }
517
            }
500
            else {
518
            else {
501
                $('.checkitem_'+bibNum).attr('disabled', false);
519
                $('.checkitem_'+bibNum).attr('disabled', false);
502
            }
520
            }
521
503
        });
522
        });
504
523
505
        $(".toggle-hold-options").on("click",function(e){
524
        $(".toggle-hold-options").on("click",function(e){
Lines 526-533 Link Here
526
                    $("#toggle-hold-options-[% bibitemloo.biblionumber | html %]").click();
545
                    $("#toggle-hold-options-[% bibitemloo.biblionumber | html %]").click();
527
                    $("#reqany_[% bibitemloo.biblionumber | html %]").attr('checked', true);
546
                    $("#reqany_[% bibitemloo.biblionumber | html %]").attr('checked', true);
528
                [% END %]
547
                [% END %]
529
                $("#reqany_[% bibitemloo.biblionumber | html %]").attr('disabled', 'disabled');
530
                $("#reqspecific_[% bibitemloo.biblionumber | html %]").attr('disabled', 'disabled');
531
            [% END %]
548
            [% END %]
532
            [% IF bibitemloo.reqholdnotes %]
549
            [% IF bibitemloo.reqholdnotes %]
533
                $("#holdnotes_[% bibitemloo.biblionumber | html %]").attr( 'required', true );
550
                $("#holdnotes_[% bibitemloo.biblionumber | html %]").attr( 'required', true );
Lines 558-563 Link Here
558
            if ( $(checkbox).is(":checked") && select_specific ) {
575
            if ( $(checkbox).is(":checked") && select_specific ) {
559
                $(newCopiesRowId).show();
576
                $(newCopiesRowId).show();
560
                $(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
                   if (remaining != '1') {
586
                      alert(MSG_MAX_HOLDS_EXCEEDED);
587
                   }
588
                   $("input[name='checkitem_"+biblioNum+"']:not(:checked)").attr('disabled', 'disabled');
589
                }
590
                else if (nbCheked == remaining_holds_today) {
591
                   if (remaining_holds_today != '1') {
592
                       alert(MSG_EXCEEDED_HOLDS_PER_DAY);
593
                   }
594
                   $("input[name='checkitem_"+biblioNum+"']:not(:checked)").attr('disabled', 'disabled');
595
                }
596
                else if (nbCheked == maxreserves) {
597
                   if (maxreserves != '1') {
598
                       alert(MSG_EXCEEDED_MAXRESERVES_SYSPREF);
599
                   }
600
                   $("input[name='checkitem_"+biblioNum+"']:not(:checked)").attr('disabled', 'disabled');
601
                }
602
561
            } else {
603
            } else {
562
                $(newCopiesRowId).hide();
604
                $(newCopiesRowId).hide();
563
                $(holdsToPlaceCountId).show();
605
                $(holdsToPlaceCountId).show();
(-)a/opac/opac-reserve.pl (-4 / +21 lines)
Lines 44-49 use Koha::Libraries; Link Here
44
use Koha::Patrons;
44
use Koha::Patrons;
45
use Date::Calc qw/Today Date_to_Days/;
45
use Date::Calc qw/Today Date_to_Days/;
46
use List::MoreUtils qw/uniq/;
46
use List::MoreUtils qw/uniq/;
47
use List::Util qw[min max];
48
use Data::Dumper;
47
49
48
my $maxreserves = C4::Context->preference("maxreserves");
50
my $maxreserves = C4::Context->preference("maxreserves");
49
51
Lines 65-70 my ( $template, $borrowernumber, $cookie ) = get_template_and_user( Link Here
65
    }
67
    }
66
);
68
);
67
69
70
$template->param(maxreserves => $maxreserves);
71
68
my ($show_holds_count, $show_priority);
72
my ($show_holds_count, $show_priority);
69
for ( C4::Context->preference("OPACShowHoldQueueDetails") ) {
73
for ( C4::Context->preference("OPACShowHoldQueueDetails") ) {
70
    m/holds/o and $show_holds_count = 1;
74
    m/holds/o and $show_holds_count = 1;
Lines 113-119 my @biblionumbers = ref($query->param('biblionumbers')) eq 'Array' Link Here
113
    : split(/\//, $query->param('biblionumbers'));
117
    : split(/\//, $query->param('biblionumbers'));
114
118
115
unless (@biblionumbers) {
119
unless (@biblionumbers) {
116
    push(@biblionumbers, $query->param('biblionumber'));
120
    push(@biblionumbers, $query->multi_param('biblionumber'));
117
}
121
}
118
122
119
# Pass the numbers to the page so they can be fed back
123
# Pass the numbers to the page so they can be fed back
Lines 282-289 if ( $query->param('place_reserve') ) { Link Here
282
            print $query->redirect("/cgi-bin/koha/opac-user.pl?" . ( $failed_holds ? "failed_holds=$failed_holds" : q|| ) . "#opac-user-holds");
286
            print $query->redirect("/cgi-bin/koha/opac-user.pl?" . ( $failed_holds ? "failed_holds=$failed_holds" : q|| ) . "#opac-user-holds");
283
            exit;
287
            exit;
284
        }
288
        }
285
        $canreserve = 0 unless CanBookBeReserved( $borrowernumber, $biblioNum ) eq 'OK';
289
        $canreserve = 0 unless CanBookBeReserved( $borrowernumber, $biblioNum )->{status} eq 'OK';
286
287
        unless ( $can_place_hold_if_available_at_pickup ) {
290
        unless ( $can_place_hold_if_available_at_pickup ) {
288
            my $items_in_this_library = Koha::Items->search({ biblionumber => $biblioNum, holdingbranch => $branch });
291
            my $items_in_this_library = Koha::Items->search({ biblionumber => $biblioNum, holdingbranch => $branch });
289
            my $nb_of_items_issued = $items_in_this_library->search({ 'issue.itemnumber' => { not => undef }}, { join => 'issue' })->count;
292
            my $nb_of_items_issued = $items_in_this_library->search({ 'issue.itemnumber' => { not => undef }}, { join => 'issue' })->count;
Lines 295-301 if ( $query->param('place_reserve') ) { Link Here
295
298
296
        my $itemtype = $query->param('itemtype') || undef;
299
        my $itemtype = $query->param('itemtype') || undef;
297
        $itemtype = undef if $itemNum;
300
        $itemtype = undef if $itemNum;
298
299
        # Here we actually do the reserveration. Stage 3.
301
        # Here we actually do the reserveration. Stage 3.
300
        if ($canreserve) {
302
        if ($canreserve) {
301
            for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) {
303
            for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) {
Lines 622-629 foreach my $biblioNum (@biblionumbers) { Link Here
622
624
623
    my $max_holds_for_record = GetMaxPatronHoldsForRecord( $borrowernumber, $biblioNum );
625
    my $max_holds_for_record = GetMaxPatronHoldsForRecord( $borrowernumber, $biblioNum );
624
    my $remaining_holds_for_record = $max_holds_for_record - $holds->count();
626
    my $remaining_holds_for_record = $max_holds_for_record - $holds->count();
627
628
    my $today_holds = Koha::Holds->search({
629
       borrowernumber => $borrowernumber,
630
       reservedate    => dt_from_string->date
631
    });
632
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 );
636
    my $remaining_holds_allowed_today = $holds_allowed_on_record_today - $today_holds->count();
637
625
    $biblioLoopIter{remaining_holds_for_record} = $remaining_holds_for_record;
638
    $biblioLoopIter{remaining_holds_for_record} = $remaining_holds_for_record;
639
    $biblioLoopIter{remaining_holds_allowed_today} = $remaining_holds_allowed_today;
626
640
641
    #Determine what is the lowest value
642
    my $lowestvalue = min($maxreserves, $remaining_holds_for_record, $remaining_holds_allowed_today);
643
    $biblioLoopIter{lowest_value} = $lowestvalue;
627
644
628
    push @$biblioLoop, \%biblioLoopIter;
645
    push @$biblioLoop, \%biblioLoopIter;
629
646
(-)a/reserve/request.pl (+26 lines)
Lines 53-58 use Koha::Items; Link Here
53
use Koha::ItemTypes;
53
use Koha::ItemTypes;
54
use Koha::Libraries;
54
use Koha::Libraries;
55
use Koha::Patrons;
55
use Koha::Patrons;
56
use List::Util qw[min max];
56
57
57
my $dbh = C4::Context->dbh;
58
my $dbh = C4::Context->dbh;
58
my $input = new CGI;
59
my $input = new CGI;
Lines 264-273 foreach my $biblionumber (@biblionumbers) { Link Here
264
        # we must find out what the maximum number of holds they can place for the patron is
265
        # we must find out what the maximum number of holds they can place for the patron is
265
        my $max_holds_for_record = GetMaxPatronHoldsForRecord( $patron->borrowernumber, $biblionumber );
266
        my $max_holds_for_record = GetMaxPatronHoldsForRecord( $patron->borrowernumber, $biblionumber );
266
        my $remaining_holds_for_record = $max_holds_for_record - $holds->count();
267
        my $remaining_holds_for_record = $max_holds_for_record - $holds->count();
268
269
        # Determine how many holds the patron can place per day on this biblio record.
270
        # Then calculate how many holds the patron can place subtracting holds already placed today
271
        my $today_holds = Koha::Holds->search({
272
            borrowernumber => $patron->borrowernumber,
273
            reservedate    => dt_from_string->date
274
        });
275
276
277
        my $biblio_record = Koha::Biblios->find( $biblionumber );
278
        my $patron_obj = Koha::Patrons->find( $patron->borrowernumber );
279
        my $holds_allowed_on_record_today = $biblio_record->allowed_holds( $patron_obj );
280
        my $remaining_holds_allowed_today = $holds_allowed_on_record_today - $today_holds->count();
281
282
        my $maxreserves = C4::Context->preference('maxreserves');
283
267
        $biblioloopiter{remaining_holds_for_record} = $max_holds_for_record;
284
        $biblioloopiter{remaining_holds_for_record} = $max_holds_for_record;
285
        $biblioloopiter{remaining_holds_allowed_today} = $holds_allowed_on_record_today;
286
287
        #Determine what is the lowest value
288
        my $lowestvalue = min($maxreserves, $biblioloopiter{remaining_holds_for_record}, $biblioloopiter{remaining_holds_allowed_today});
289
        $template->param( lowest_value => $lowestvalue );
268
        $template->param( max_holds_for_record => $max_holds_for_record );
290
        $template->param( max_holds_for_record => $max_holds_for_record );
269
        $template->param( remaining_holds_for_record => $remaining_holds_for_record );
291
        $template->param( remaining_holds_for_record => $remaining_holds_for_record );
270
292
293
        $template->param( holds_allowed_on_record_today => $holds_allowed_on_record_today );
294
        $template->param( remaining_holds_allowed_today => $remaining_holds_allowed_today );
295
        $template->param( maxreserves => $maxreserves );
296
271
        { # alreadypossession
297
        { # alreadypossession
272
            # Check to see if patron is allowed to place holds on records where the
298
            # Check to see if patron is allowed to place holds on records where the
273
            # patron already has an item from that record checked out
299
            # patron already has an item from that record checked out
(-)a/t/db_dependent/Reserves/MultiplePerRecord.t (-2 / +19 lines)
Lines 1-6 Link Here
1
#!/usr/bin/perl
1
#!/usr/bin/perl
2
2
3
# Copyright 2016 ByWater Solutions
3
# Copyright 2016 ByWater Solutions
4
# Copyright 2018 Catalyst IT
4
#
5
#
5
# This file is part of Koha.
6
# This file is part of Koha.
6
#
7
#
Lines 19-25 Link Here
19
20
20
use Modern::Perl;
21
use Modern::Perl;
21
22
22
use Test::More tests => 38;
23
use Test::More tests => 42;
23
use t::lib::TestBuilder;
24
use t::lib::TestBuilder;
24
use t::lib::Mocks;
25
use t::lib::Mocks;
25
26
Lines 197-207 my $rule4 = $rules_rs->new( Link Here
197
        branchcode       => '*',
198
        branchcode       => '*',
198
        reservesallowed  => 4,
199
        reservesallowed  => 4,
199
        holds_per_record => 4,
200
        holds_per_record => 4,
201
        holds_per_day    => 4,
200
    }
202
    }
201
)->insert();
203
)->insert();
202
204
203
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
205
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
204
is( $max, 4, 'GetMaxPatronHoldsForRecord returns max of 4' );
206
is( $max, 4, 'GetMaxPatronHoldsForRecord returns max of 4' );
207
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 );
212
is( $holds_per_day, 4, 'GetAllowedHoldsForPatronToday returns max of 4' );
213
205
$rule = C4::Reserves::GetHoldRule(
214
$rule = C4::Reserves::GetHoldRule(
206
    $category->{categorycode},
215
    $category->{categorycode},
207
    $itemtype2->{itemtype},
216
    $itemtype2->{itemtype},
Lines 212-217 is( $rule->{itemtype}, $itemtype2->{itemtype}, 'Got rule with univers Link Here
212
is( $rule->{branchcode},       '*',                       'Got rule with universal branchcode' );
221
is( $rule->{branchcode},       '*',                       'Got rule with universal branchcode' );
213
is( $rule->{reservesallowed},  4,                         'Got reservesallowed of 4' );
222
is( $rule->{reservesallowed},  4,                         'Got reservesallowed of 4' );
214
is( $rule->{holds_per_record}, 4,                         'Got holds_per_record of 4' );
223
is( $rule->{holds_per_record}, 4,                         'Got holds_per_record of 4' );
224
is( $rule->{holds_per_day}, 4,                            'Got holds_per_day of 4' );
215
225
216
my $rule5 = $rules_rs->new(
226
my $rule5 = $rules_rs->new(
217
    {
227
    {
Lines 220-230 my $rule5 = $rules_rs->new( Link Here
220
        branchcode       => $library->{branchcode},
230
        branchcode       => $library->{branchcode},
221
        reservesallowed  => 5,
231
        reservesallowed  => 5,
222
        holds_per_record => 5,
232
        holds_per_record => 5,
233
        holds_per_day    => 5,
223
    }
234
    }
224
)->insert();
235
)->insert();
225
236
226
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
237
$max = GetMaxPatronHoldsForRecord( $patron->{borrowernumber}, $biblio->{biblionumber} );
227
is( $max, 5, 'GetMaxPatronHoldsForRecord returns max of 1' );
238
is( $max, 5, 'GetMaxPatronHoldsForRecord returns max of 1' );
239
240
$holds_per_day = $biblio_record->allowed_holds( $patron_obj );
241
is( $holds_per_day, 5, 'GetAllowedHoldsForPatronToday returns max of 5' );
242
243
228
$rule = C4::Reserves::GetHoldRule(
244
$rule = C4::Reserves::GetHoldRule(
229
    $category->{categorycode},
245
    $category->{categorycode},
230
    $itemtype2->{itemtype},
246
    $itemtype2->{itemtype},
Lines 235-240 is( $rule->{itemtype}, $itemtype2->{itemtype}, 'Got rule with univers Link Here
235
is( $rule->{branchcode},       $library->{branchcode},    'Got rule with specific branchcode' );
251
is( $rule->{branchcode},       $library->{branchcode},    'Got rule with specific branchcode' );
236
is( $rule->{reservesallowed},  5,                         'Got reservesallowed of 5' );
252
is( $rule->{reservesallowed},  5,                         'Got reservesallowed of 5' );
237
is( $rule->{holds_per_record}, 5,                         'Got holds_per_record of 5' );
253
is( $rule->{holds_per_record}, 5,                         'Got holds_per_record of 5' );
254
is( $rule->{holds_per_day}, 5,                         'Got holds_per_day of 5' );
238
255
239
$rule1->delete();
256
$rule1->delete();
240
$rule2->delete();
257
$rule2->delete();
Lines 273-278 $rule = $rules_rs->new( Link Here
273
        branchcode       => '*',
290
        branchcode       => '*',
274
        reservesallowed  => 2,
291
        reservesallowed  => 2,
275
        holds_per_record => 2,
292
        holds_per_record => 2,
293
        holds_per_day    => 2,
276
    }
294
    }
277
)->insert();
295
)->insert();
278
296
279
- 

Return to bug 15565