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

(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt (-5 / +11 lines)
Lines 26-31 var override_items = {[% FOREACH bibitemloo IN bibitemloop %][% FOREACH itemloo Link Here
26
[% END %][% END %][% END %]
26
[% END %][% END %][% END %]
27
};
27
};
28
var MSG_NO_ITEMS_AVAILABLE = _("A hold cannot be requested on any of these items.");
28
var MSG_NO_ITEMS_AVAILABLE = _("A hold cannot be requested on any of these items.");
29
var MSG_EXCEEDED_HOLDS_PER_RECORD = _("Patron has exceeded the number of holds for this record.");
30
var remainingHolds = "[% remaining_holds_for_record %]";
29
31
30
$(document).ready(function() {
32
$(document).ready(function() {
31
    function ToggleHoldsToPlace() {
33
    function ToggleHoldsToPlace() {
Lines 150-166 function checkMultiHold() { Link Here
150
        }
152
        }
151
    });
153
    });
152
    $("input[name=checkitem]").click(function() {
154
    $("input[name=checkitem]").click(function() {
153
        onechecked = 0;
155
        numchecked = 0;
154
        $("input[name=checkitem]").each(function() {
156
        $("input[name=checkitem]").each(function() {
155
            if(this.checked){
157
            if(this.checked){
156
                onechecked = 1;
158
                numchecked = 1;
157
            }
159
            }
158
        });
160
        });
159
        if(onechecked == 1){
161
        if(numchecked > 0){
160
            $("#requestany").prop("checked", false);
162
            $("#requestany").prop("checked", false);
161
        } else {
163
        } else {
162
            $("#requestany").prop("checked",true);
164
            $("#requestany").prop("checked",true);
163
        }
165
        }
166
167
        if (remainingHolds - numchecked < 0) {
168
            alert(MSG_EXCEEDED_HOLDS_PER_RECORD);
169
        }
164
    });
170
    });
165
    var prev_rank_request;
171
    var prev_rank_request;
166
    $("select[name=rank-request]").on("focus", function() {
172
    $("select[name=rank-request]").on("focus", function() {
Lines 514-522 function checkMultiHold() { Link Here
514
                        Hold must be record level
520
                        Hold must be record level
515
                    </span>
521
                    </span>
516
                [% ELSIF ( itemloo.available ) %]
522
                [% ELSIF ( itemloo.available ) %]
517
                    <input type="radio" name="checkitem" value="[% itemloo.itemnumber %]" />
523
                    <input type="checkbox" name="checkitem" value="[% itemloo.itemnumber %]" />
518
                [% ELSIF ( itemloo.override ) %]
524
                [% ELSIF ( itemloo.override ) %]
519
                    <input type="radio" name="checkitem" class="needsoverride" value="[% itemloo.itemnumber %]" />
525
                    <input type="checkbox" name="checkitem" class="needsoverride" value="[% itemloo.itemnumber %]" />
520
                    <i class="fa fa-exclamation-triangle fa-lg" style="color:gold" alt="Requires override of hold policy"/></i>
526
                    <i class="fa fa-exclamation-triangle fa-lg" style="color:gold" alt="Requires override of hold policy"/></i>
521
                [% ELSE %]
527
                [% ELSE %]
522
                    <span class="error">
528
                    <span class="error">
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt (-101 / +91 lines)
Lines 138-157 Link Here
138
                        <form action="/cgi-bin/koha/opac-reserve.pl" method="post" id="hold-request-form">
138
                        <form action="/cgi-bin/koha/opac-reserve.pl" method="post" id="hold-request-form">
139
                            <input type="hidden" name="place_reserve" value="1"/>
139
                            <input type="hidden" name="place_reserve" value="1"/>
140
                            <!-- These values are set dynamically by js -->
140
                            <!-- These values are set dynamically by js -->
141
                            <input type="hidden" name="biblionumbers" id="biblionumbers"/>
142
                            <input type="hidden" name="selecteditems" id="selections"/>
143
                            <div id="bigloop">
141
                            <div id="bigloop">
144
142
145
                                [% FOREACH bibitemloo IN bibitemloop %]
143
                                [% FOREACH bibitemloo IN bibitemloop %]
146
                                    <div class="holdrow">
144
                                    <div class="holdrow">
145
                                        <input id="remaining_holds_[% bibitemloo.biblionumber %]" type="hidden" value="[% bibitemloo.remaining_holds_for_record %]"/>
147
                                        <p>
146
                                        <p>
148
                                            [% IF ( bibitemloo.holdable ) %]
147
                                            [% IF ( bibitemloo.holdable ) %]
149
                                                <input class="reserve_mode" name="reserve_mode" type="hidden" value="single"/>
148
                                                <span title="[% bibitemloo.biblionumber %]" style="padding:.3em">
150
                                                <input class="single_bib" name="single_bib" type="hidden" value="[% bibitemloo.biblionumber %]"/>
149
                                                    <label>
151
                                                <span class="confirmjs_hold" title="[% bibitemloo.biblionumber %]" style="padding:.3em"></span>
150
                                                        <input class="biblionumbers" name="biblionumbers" type="checkbox" value="[% bibitemloo.biblionumber %]" checked="checked">
152
                                                <span class="confirm_nonjs">
151
                                                        Place a hold on
153
                                                    <input type="radio" class="confirmbox checkitem [% bibitemloo.biblionumber %]" name="[% bibitemloo.biblionumber %]" checked="checked" id="single_[% bibitemloo.biblionumber %]" value="any" />
152
                                                    </label>
154
                                                    <label class="confirm_label" for="single_[% bibitemloo.biblionumber %]">Place a hold on </label>
155
                                                </span>
153
                                                </span>
156
                                            [% END # / bibitemloo.holdable %]
154
                                            [% END # / bibitemloo.holdable %]
157
155
Lines 218-224 Link Here
218
                                                            <li class="branch">
216
                                                            <li class="branch">
219
                                                                <label for="branch_[% bibitemloo.biblionumber %]">Pick up location:</label>
217
                                                                <label for="branch_[% bibitemloo.biblionumber %]">Pick up location:</label>
220
                                                                [% UNLESS ( bibitemloo.holdable ) %]
218
                                                                [% UNLESS ( bibitemloo.holdable ) %]
221
                                                                    <select name="branch" id="branch_[% bibitemloo.biblionumber %]" disabled="disabled">
219
                                                                    <select name="branch_[% bibitemloo.biblionumber %]" id="branch_[% bibitemloo.biblionumber %]" disabled="disabled">
222
                                                                        [% PROCESS options_for_libraries libraries => Branches.all( selected => branch ) %]
220
                                                                        [% PROCESS options_for_libraries libraries => Branches.all( selected => branch ) %]
223
                                                                    </select>
221
                                                                    </select>
224
                                                                [% ELSE %]
222
                                                                [% ELSE %]
Lines 292-320 Link Here
292
                                                            </li>
290
                                                            </li>
293
                                                        [% END # / IF OpacHoldNotes %]
291
                                                        [% END # / IF OpacHoldNotes %]
294
292
295
                                                        [% IF bibitemloo.itemholdable %]
293
                                                        <!-- ITEM HOLDS -->
296
                                                            <!-- ITEM HOLDS -->
294
                                                        <li class="lradio place_on_type" style="display:none;">
297
                                                            <li class="lradio place_on_type" style="display:none;">
295
                                                                <label class="radio inline" for="reqany_[% bibitemloo.biblionumber %]">Next available item</label>
298
                                                                [% IF NOT bibitemloo.force_hold %]
299
                                                                    <label class="radio inline" for="reqany_[% bibitemloo.biblionumber %]">Next available item</label>
300
                                                                    <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]"
301
                                                                            id="reqany_[% bibitemloo.biblionumber %]"
302
                                                                            class="selectany"
303
                                                                            value="Any"
304
                                                                            checked="checked"
305
                                                                    />
306
                                                                [% END %]
307
                                                                <label class="radio inline" for="reqspecific_[% bibitemloo.biblionumber %]">A specific item</label>
308
                                                                <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]"
296
                                                                <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]"
309
                                                                       id="reqspecific_[% bibitemloo.biblionumber %]"
297
                                                                        id="reqany_[% bibitemloo.biblionumber %]"
310
                                                                       class="selectspecific"
298
                                                                        class="selectany"
311
                                                                       value="Specific"
299
                                                                        value="Any"
300
                                                                        checked="checked"
312
                                                                />
301
                                                                />
313
                                                            </li>
302
                                                            <label class="radio inline" for="reqspecific_[% bibitemloo.biblionumber %]">A specific item</label>
314
                                                        [% END # / IF bibitemloo.itemholdable %]
303
                                                            <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]"
304
                                                                   id="reqspecific_[% bibitemloo.biblionumber %]"
305
                                                                   class="selectspecific"
306
                                                                   value="Specific"
307
                                                            />
308
                                                        </li>
315
                                                    </ul>
309
                                                    </ul>
316
310
317
                                                    [% IF bibitemloo.itemholdable %]
311
                                                    [% IF bibitemloo.remaining_holds_for_record > 1 %]
312
                                                        [% SET count = 1 %]
313
                                                        <div id="holds_to_place_[% bibitemloo.biblionumber %]" class="hold-options holds-to-place">
314
                                                            <label>Holds to place (count)</label>
315
                                                            <select name="holds_to_place_count_[% bibitemloo.biblionumber %]">
316
                                                            [% WHILE count <= bibitemloo.remaining_holds_for_record %]
317
                                                                <option value="[% count %]">[% count %]</option>
318
                                                                [% SET count = count + 1 %]
319
                                                            [% END %]
320
                                                            </select>
321
                                                        </div>
322
                                                    [% ELSE %]
323
                                                        <input type="hidden" name="holds_to_place_count_[% bibitemloo.biblionumber %]" value="1" />
324
                                                    [% END %]
325
318
                                                        <table class="copiesrow table table-bordered table-striped" id="copiesrow_[% bibitemloo.biblionumber %]">
326
                                                        <table class="copiesrow table table-bordered table-striped" id="copiesrow_[% bibitemloo.biblionumber %]">
319
                                                            <caption>Select a specific item:</caption>
327
                                                            <caption>Select a specific item:</caption>
320
                                                            <tr>
328
                                                            <tr>
Lines 338-346 Link Here
338
                                                                <tr class="[% itemLoo.backgroundcolor %]">
346
                                                                <tr class="[% itemLoo.backgroundcolor %]">
339
                                                                    <td class="copynumber">
347
                                                                    <td class="copynumber">
340
                                                                        [% IF ( itemLoo.available ) %]
348
                                                                        [% IF ( itemLoo.available ) %]
341
                                                                            <input type="radio" class="checkitem checkitem_[% bibitemloo.biblionumber %]" name="checkitem_[% bibitemloo.biblionumber %]" value="[% itemLoo.itemnumber %]" />
349
                                                                            <input type="checkbox" class="checkitem checkitem_[% bibitemloo.biblionumber %]" name="checkitem_[% bibitemloo.biblionumber %]" value="[% itemLoo.itemnumber %]" />
342
                                                                        [% ELSE %]
350
                                                                        [% ELSE %]
343
                                                                            <input disabled="disabled" type="radio" class="checkitem" name="checkitem" value="[% itemLoo.itemnumber %]"
351
                                                                            <input disabled="disabled" type="checkbox" class="checkitem" name="checkitem" value="[% itemLoo.itemnumber %]"
344
                                                                                   style="display:none;" />
352
                                                                                   style="display:none;" />
345
                                                                            <img src="[% interface %]/lib/famfamfam/silk/cross.png" alt="Cannot be put on hold" title="Cannot be put on hold" />
353
                                                                            <img src="[% interface %]/lib/famfamfam/silk/cross.png" alt="Cannot be put on hold" title="Cannot be put on hold" />
346
                                                                        [% END %]
354
                                                                        [% END %]
Lines 414-420 Link Here
414
                                                                </tr>
422
                                                                </tr>
415
                                                            [% END # / FOREACH itemLoo IN bibitemloo.itemLoop%]
423
                                                            [% END # / FOREACH itemLoo IN bibitemloo.itemLoop%]
416
                                                        </table> <!-- / #copiesrow_[% bibitemloo.biblionumber %] -->
424
                                                        </table> <!-- / #copiesrow_[% bibitemloo.biblionumber %] -->
417
                                                    [% END # / IF ( bibitemloo.itemholdable )%]
418
                                                </div> <!-- / #hold-options-[% bibitemloo.biblionumber %] -->
425
                                                </div> <!-- / #hold-options-[% bibitemloo.biblionumber %] -->
419
                                            </fieldset>
426
                                            </fieldset>
420
                                        [% END # / IF ( bibitemloo.holdable ) %]
427
                                        [% END # / IF ( bibitemloo.holdable ) %]
Lines 437-442 Link Here
437
<script type="text/javascript">
444
<script type="text/javascript">
438
// <![CDATA[
445
// <![CDATA[
439
    var MSG_NO_ITEM_SELECTED = _("Expecting a specific item selection.");
446
    var MSG_NO_ITEM_SELECTED = _("Expecting a specific item selection.");
447
    var MSG_MAX_HOLDS_EXCEEDED = _("Maximum number of reserve exceded.");
440
448
441
        // Clear the contents of an input field
449
        // Clear the contents of an input field
442
        $(".clearfield").on("click",function(e){
450
        $(".clearfield").on("click",function(e){
Lines 446-453 Link Here
446
454
447
    // Select the first item available
455
    // Select the first item available
448
    function select_first_available(id){
456
    function select_first_available(id){
449
        var radios = $("input:radio[name='checkitem_" + id + "']");
457
        var checkboxes = $("input:checkbox[name='checkitem_" + id + "']");
450
        $(radios).first().attr("checked", "checked");
458
        $(checkboxes).first().attr("checked", "checked");
451
    }
459
    }
452
460
453
    $(document).ready(function() {
461
    $(document).ready(function() {
Lines 468-481 Link Here
468
            }
476
            }
469
        });
477
        });
470
478
471
        // click on a first td check the confirmjs checkbox
479
        $('.checkitem').click(function(e) {
472
        $("td.hold").click(function(e){
480
            var bibNum = suffixOf($(this).attr("name"), "_");
473
          if(e.target.tagName.toLowerCase() == 'td'){
481
            var nbCheked = $("input[name='checkitem_"+bibNum+"']:checked").length;
474
            $(this).find("input.confirmjs").each( function() {
482
            var remaining = $("input[id='remaining_holds_"+bibNum+"']").val();
475
               $(this).attr('checked', !$(this).attr('checked'));
483
            if (nbCheked >= remaining) {
476
               $(this).change();
484
                $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled');
477
            });
485
            }
478
          }
486
            else {
487
                $('.checkitem_'+bibNum).attr('disabled', false);
488
            }
479
        });
489
        });
480
490
481
        $(".toggle-hold-options").on("click",function(e){
491
        $(".toggle-hold-options").on("click",function(e){
Lines 490-504 Link Here
490
        // Hides all 'specific copy' table rows on load.
500
        // Hides all 'specific copy' table rows on load.
491
        $(".copiesrow").hide();
501
        $(".copiesrow").hide();
492
502
503
        $(".holds-to-place").show();
493
        [% FOREACH bibitemloo IN bibitemloop %]
504
        [% FOREACH bibitemloo IN bibitemloop %]
494
          [% IF bibitemloo.force_hold %]
505
            [% IF bibitemloo.force_hold %]
495
            $("#toggle-hold-options-[% bibitemloo.biblionumber %]").click();
506
                [% IF bibitemloo.force_hold == 'item' %]
496
            $("#reqspecific_[% bibitemloo.biblionumber %]").click();
507
                    $("#toggle-hold-options-[% bibitemloo.biblionumber %]").click();
497
            $("#copiesrow_[% bibitemloo.biblionumber %]").show();
508
                    $("#reqspecific_[% bibitemloo.biblionumber %]").attr('checked', true);
498
          [% END %]
509
                    $("#holds_to_place_[% bibitemloo.biblionumber %]").hide();
499
          [% IF bibitemloo.reqholdnotes %]
510
                    $("#copiesrow_[% bibitemloo.biblionumber %]").show();
500
              $("#holdnotes_[% bibitemloo.biblionumber %]").attr( 'required', true );
511
                [% ELSIF bibitemloo.force_hold == 'record' %]
501
          [% END %]
512
                    $("#toggle-hold-options-[% bibitemloo.biblionumber %]").click();
513
                    $("#reqany_[% bibitemloo.biblionumber %]").attr('checked', true);
514
                [% END %]
515
                $("#reqany_[% bibitemloo.biblionumber %]").attr('disabled', 'disabled');
516
                $("#reqspecific_[% bibitemloo.biblionumber %]").attr('disabled', 'disabled');
517
            [% END %]
518
            [% IF bibitemloo.reqholdnotes %]
519
                $("#holdnotes_[% bibitemloo.biblionumber %]").attr( 'required', true );
520
            [% END %]
502
        [% END %]
521
        [% END %]
503
522
504
        $(".date-format").each(function(){
523
        $(".date-format").each(function(){
Lines 515-554 Link Here
515
            $("#" + op + fieldID).val("");
534
            $("#" + op + fieldID).val("");
516
        });
535
        });
517
536
518
        // Replace non-JS single-selection with multi-selection capability.
519
        $(".reserve_mode").val("multi");
520
        $(".confirm_nonjs").remove();
521
        $(".confirmjs_hold").each(function(){
522
            var bib = $(this).attr("title");
523
            var html = "<label><input type =\"checkbox\" class=\"confirmjs\" checked=\"checked\"";
524
            html += "value=\"" + bib + "\" id=\"" + bib + "\" /> " + _("Place a hold on") + " </label> ";
525
            $(this).html(html);
526
        });
527
        $(".confirmjs_nohold").each(function(){
528
            var bib = $(this).attr("title");
529
            var html = "<label><input type =\"checkbox\" class=\"confirmjs\" disabled=\"disabled\"";
530
            html += "value=\"" + bib + "\" id=\"" + bib + "\" />" + _("Place a hold on: ") + "</label>";
531
            $(this).html(html);
532
        });
533
534
        // expand or collapse the copiesrow tr
537
        // expand or collapse the copiesrow tr
535
        function toggle_copiesrow(biblioNum) {
538
        function toggle_copiesrow(biblioNum) {
536
            var checkbox = $("input:checkbox[value='"+biblioNum+"']");
539
            var checkbox = $("input:checkbox[value='"+biblioNum+"']");
537
            newCopiesRowId = "#copiesrow_" + biblioNum;
540
            newCopiesRowId = "#copiesrow_" + biblioNum;
541
            holdsToPlaceCountId = "#holds_to_place_" + biblioNum;
538
            var select_specific = $("#reqspecific_"+biblioNum).is(":checked");
542
            var select_specific = $("#reqspecific_"+biblioNum).is(":checked");
539
            // If the checkbox is checked AND we want a specific item, we display the items block
543
            // If the checkbox is checked AND we want a specific item, we display the items block
540
            if ( $(checkbox).is(":checked") && select_specific ) {
544
            if ( $(checkbox).is(":checked") && select_specific ) {
541
                $(newCopiesRowId).show();
545
                $(newCopiesRowId).show();
546
                $(holdsToPlaceCountId).hide();
542
            } else {
547
            } else {
543
                $(newCopiesRowId).hide();
548
                $(newCopiesRowId).hide();
549
                $(holdsToPlaceCountId).show();
544
             }
550
             }
545
        };
551
        };
546
552
547
        $("#place_on_hdr").show();
553
        function total_requested() {
554
            var total = 0;
555
            $("input[name='biblionumbers']:checked").each(function() {
556
                var biblioNum = $(this).val();
557
                if ($("#reqspecific_" + biblioNum + ":checked").size() > 0) {
558
                    total += parseInt($("input[name='checkitem_'"+biblioNum+"]:checked").length);
559
                } else {
560
                    total += parseInt($("select[name='holds_to_place_count_"+biblioNum+"']").val());
561
                }
562
            });
563
            return total;
564
        }
548
565
549
        $(".place_on_type").show();
566
        $(".place_on_type").show();
550
        // onload, selectany is checked
567
        // onload, selectany is checked
551
        $(".selectany").attr("checked", "checked");
552
568
553
        // If the user is *allowed* to choose a specific item
569
        // If the user is *allowed* to choose a specific item
554
        // The first one is preselected
570
        // The first one is preselected
Lines 557-564 Link Here
557
            select_first_available(id);
573
            select_first_available(id);
558
        });
574
        });
559
575
560
        // On confirmsjs change
576
        // On biblionumbers change
561
        $(".confirmjs").change(function(){
577
        $(".biblionumbers").change(function(){
562
            var id = suffixOf($(this).attr("id"), "_");
578
            var id = suffixOf($(this).attr("id"), "_");
563
            // If I m checked, I enable radio buttons
579
            // If I m checked, I enable radio buttons
564
            if ( $(this).is(":checked") ) {
580
            if ( $(this).is(":checked") ) {
Lines 580-614 Link Here
580
            toggle_copiesrow(id);
596
            toggle_copiesrow(id);
581
        });
597
        });
582
598
583
        // Show or hide holds notes
584
        $(".shownotes").click(function(){
585
            biblioNum = suffixOf($(this).attr("id"), "_");
586
            $("#notesrow_"+biblioNum).toggle();
587
        });
588
589
        // When 'Place Hold' button is clicked
599
        // When 'Place Hold' button is clicked
590
        $(".placehold").click(function(){
600
        $(".placehold").click(function(){
591
            var biblionumbers = "";
601
            if (total_requested() + [% reserves_count %] > [% maxreserves %]) {
592
            var selections = "";
602
                alert(MSG_MAX_HOLDS_EXCEEDED);
593
603
                return false;
594
            [% IF new_reserves_allowed %]
604
            }
595
                if ($(".confirmjs:checked").size() > [% new_reserves_allowed %] ) {
596
                    alert(MSG_MAX_HOLDS_EXCEEDED);
597
                    return false;
598
                }
599
            [% END %]
600
605
601
            if ($(".confirmjs:checked").size() == 0) {
606
            if ($("input[name='biblionumbers']:checked").size() == 0) {
602
                alert(MSG_NO_RECORD_SELECTED);
607
                alert(MSG_NO_RECORD_SELECTED);
603
                return false;
608
                return false;
604
            }
609
            }
605
610
606
            // Find the items with the 'Hold' box checked
611
            // Find the items with the 'Hold' box checked
607
            var badBib = null;
612
            var badBib = null;
608
            $(".confirmjs:checked").each(function() {
613
            $("input[name='biblionumbers']:checked").each(function() {
609
                var biblioNum = $(this).val();
614
                var biblioNum = $(this).val();
610
                biblionumbers += biblioNum + "/";
611
                selections += biblioNum + "/";
612
615
613
                // If required hold note is empty, make it visible
616
                // If required hold note is empty, make it visible
614
                if( $("#holdnotes_"+biblioNum).attr( 'required' ) && $("#holdnotes_"+biblioNum).val() == '' ) {
617
                if( $("#holdnotes_"+biblioNum).attr( 'required' ) && $("#holdnotes_"+biblioNum).val() == '' ) {
Lines 625-642 Link Here
625
                        alert(MSG_NO_ITEM_SELECTED);
628
                        alert(MSG_NO_ITEM_SELECTED);
626
                        badBib = biblioNum;
629
                        badBib = biblioNum;
627
                        return false;
630
                        return false;
628
                    } else {
629
                      selections += $(item).val();
630
                    }
631
                    }
631
                }
632
                }
632
                selections += "/";
633
634
                // Add the pickup location
635
                var branchSel = $("#branch_" + biblioNum);
636
                if (branchSel.size() > 0) {
637
                    selections += $(branchSel).val();
638
                }
639
                selections += "/";
640
                return true;
633
                return true;
641
            });
634
            });
642
635
Lines 644-652 Link Here
644
                return false;
637
                return false;
645
            }
638
            }
646
639
647
            $("#selections").val(selections);
648
            $("#biblionumbers").val(biblionumbers);
649
650
            return true;
640
            return true;
651
        });
641
        });
652
642
(-)a/koha-tmpl/opac-tmpl/bootstrap/less/opac.less (+3 lines)
Lines 2393-2398 td img { Link Here
2393
    margin: 1em 0;
2393
    margin: 1em 0;
2394
    padding: .5em;
2394
    padding: .5em;
2395
}
2395
}
2396
.hold-option select {
2397
    width: auto;
2398
}
2396
.copiesrow {
2399
.copiesrow {
2397
    clear : both;
2400
    clear : both;
2398
}
2401
}
(-)a/opac/opac-reserve.pl (-91 / +83 lines)
Lines 106-139 if ( $reservefee > 0){ Link Here
106
106
107
my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } };
107
my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } };
108
108
109
# There are two ways of calling this script, with a single biblio num
109
# Coming from opac-search biblionumbers param is a string, coming from
110
# or multiple biblio nums.
110
# opac-reserve, it's an array.
111
my $biblionumbers = $query->param('biblionumbers');
111
my @biblionumbers = ref($query->param('biblionumbers')) eq 'Array'
112
my $reserveMode = $query->param('reserve_mode');
112
    ? $query->param('biblionumbers')
113
if ($reserveMode && ($reserveMode eq 'single')) {
113
    : split(/\//, $query->param('biblionumbers'));
114
    my $bib = $query->param('single_bib');
114
115
    $biblionumbers = "$bib/";
115
unless (@biblionumbers) {
116
}
116
    push(@biblionumbers, $query->param('biblionumber'));
117
if (! $biblionumbers) {
118
    $biblionumbers = $query->param('biblionumber');
119
}
120
121
if ((! $biblionumbers) && (! $query->param('place_reserve'))) {
122
    $template->param(message=>1, no_biblionumber=>1);
123
    &get_out($query, $cookie, $template->output);
124
}
117
}
125
118
126
# Pass the numbers to the page so they can be fed back
119
# Pass the numbers to the page so they can be fed back
127
# when the hold is confirmed. TODO: Not necessary?
120
# when the hold is confirmed. TODO: Not necessary?
128
$template->param( biblionumbers => $biblionumbers );
121
$template->param( biblionumbers => @biblionumbers );
129
130
# Each biblio number is suffixed with '/', e.g. "1/2/3/"
131
my @biblionumbers = split /\//, $biblionumbers;
132
if (($#biblionumbers < 0) && (! $query->param('place_reserve'))) {
133
    # TODO: New message?
134
    $template->param(message=>1, no_biblionumber=>1);
135
    &get_out($query, $cookie, $template->output);
136
}
137
122
138
123
139
# pass the pickup branch along....
124
# pass the pickup branch along....
Lines 205-243 if ( $query->param('place_reserve') ) { Link Here
205
        $reserve_cnt = $patron->holds->count;
190
        $reserve_cnt = $patron->holds->count;
206
    }
191
    }
207
192
208
    # List is composed of alternating biblio/item/branch
209
    my $selectedItems = $query->param('selecteditems');
210
211
    if ($query->param('reserve_mode') eq 'single') {
212
        # This indicates non-JavaScript mode, so there was
213
        # only a single biblio number selected.
214
        my $bib = $query->param('single_bib');
215
        my $item = $query->param("checkitem_$bib");
216
        if ($item eq 'any') {
217
            $item = '';
218
        }
219
        my $branch = $query->param('branch');
220
        $selectedItems = "$bib/$item/$branch/";
221
    }
222
223
    $selectedItems =~ s!/$!!;
224
    my @selectedItems = split /\//, $selectedItems, -1;
225
226
    # Make sure there is a biblionum/itemnum/branch triplet for each item.
227
    # The itemnum can be 'any', meaning next available.
228
    my $selectionCount = @selectedItems;
229
    if (($selectionCount == 0) || (($selectionCount % 3) != 0)) {
230
        $template->param(message=>1, bad_data=>1);
231
        &get_out($query, $cookie, $template->output);
232
    }
233
234
    my $failed_holds = 0;
193
    my $failed_holds = 0;
235
    while (@selectedItems) {
194
    foreach my $biblioNum (@biblionumbers) {
236
        my $biblioNum = shift(@selectedItems);
195
        my $itemNum = $query->param("checkitem_$biblioNum");
237
        my $itemNum   = shift(@selectedItems);
196
        my @itemnumbers = $query->param("checkitem_$biblioNum");
238
        my $branch    = shift(@selectedItems);    # i.e., branch code, not name
197
        my $branch = $query->param("branch_$biblioNum");
239
198
        my $reqtype = $query->param("reqtype_$biblioNum");
240
        my $canreserve = 0;
199
        my $holds_to_place_count = $query->param("holds_to_place_count_$biblioNum") || 1;
200
        my $notes = $query->param('notes_'.$biblioNum) || '';
201
        my $nbRequested = $reqtype eq 'Specific' ? @itemnumbers : $holds_to_place_count;
202
203
        my $canreserve = 1;
204
        if (   $maxreserves
205
            && $reserve_cnt + $nbRequested >= $maxreserves )
206
        {
207
            $canreserve = 0;
208
        }
241
209
242
        my $singleBranchMode = Koha::Libraries->search->count == 1;
210
        my $singleBranchMode = Koha::Libraries->search->count == 1;
243
        if ( $singleBranchMode || !$OPACChooseBranch )
211
        if ( $singleBranchMode || !$OPACChooseBranch )
Lines 245-251 if ( $query->param('place_reserve') ) { Link Here
245
            $branch = $patron->branchcode;
213
            $branch = $patron->branchcode;
246
        }
214
        }
247
215
248
#item may belong to a host biblio, if yes change biblioNum to hosts bilbionumber
249
        if ( $itemNum ne '' ) {
216
        if ( $itemNum ne '' ) {
250
            my $item = Koha::Items->find( $itemNum );
217
            my $item = Koha::Items->find( $itemNum );
251
            my $hostbiblioNum = $item->biblio->biblionumber;
218
            my $hostbiblioNum = $item->biblio->biblionumber;
Lines 267-297 if ( $query->param('place_reserve') ) { Link Here
267
234
268
        my $expiration_date = $query->param("expiration_date_$biblioNum");
235
        my $expiration_date = $query->param("expiration_date_$biblioNum");
269
236
270
      # If a specific item was selected and the pickup branch is the same as the
237
        # If a specific item was selected and the pickup branch is the same as the
271
      # holdingbranch, force the value $rank and $found.
238
        # holdingbranch, force the value $rank and $found.
272
        my $rank = $biblioData->{rank};
239
        my $rank = $biblioData->{rank};
273
        if ( $itemNum ne '' ) {
240
        if ( $reqtype eq 'Specific') {
274
            $canreserve = 1 if CanItemBeReserved( $borrowernumber, $itemNum ) eq 'OK';
241
            foreach my $itemnumber (@itemnumbers) {
275
            $rank = '0' unless C4::Context->preference('ReservesNeedReturns');
242
                my $biblionumber = $biblioNum;
276
            my $item = GetItem($itemNum);
243
277
            if ( $item->{'holdingbranch'} eq $branch ) {
244
                #item may belong to a host biblio, if yes change biblioNum to hosts bilbionumber
278
                $found = 'W'
245
                my $hostbiblioNum = GetBiblionumberFromItemnumber($itemnumber);
279
                  unless C4::Context->preference('ReservesNeedReturns');
246
                if ( $hostbiblioNum ne $biblioNum ) {
280
            }
247
                    $biblionumber = $hostbiblioNum;
281
        }
248
                }
282
        else {
283
            $canreserve = 1 if CanBookBeReserved( $borrowernumber, $biblioNum ) eq 'OK';
284
249
285
            # Inserts a null into the 'itemnumber' field of 'reserves' table.
250
                $canreserve = 0 unless CanItemBeReserved( $borrowernumber, $itemnumber ) eq 'OK';
286
            $itemNum = undef;
251
                $rank = '0' unless C4::Context->preference('ReservesNeedReturns');
287
        }
252
                my $item = GetItem($itemnumber);
288
        my $notes = $query->param('notes_'.$biblioNum)||'';
253
                if ( $item->{'holdingbranch'} eq $branch ) {
254
                    $found = 'W'
255
                      unless C4::Context->preference('ReservesNeedReturns');
256
                }
289
257
290
        if (   $maxreserves
258
                if ($canreserve) {
291
            && $reserve_cnt >= $maxreserves )
259
                    my $reserve_id = AddReserve(
292
        {
260
                        $branch,         $borrowernumber,
293
            $canreserve = 0;
261
                        $biblionumber,
262
                        [$biblionumber], $rank,
263
                        $startdate,      $expiration_date,
264
                        $notes,          $biblioData->{title},
265
                        $itemnumber,     $found
266
                    );
267
                    $failed_holds++ unless $reserve_id;
268
                    ++$reserve_cnt;
269
                }
270
            }
271
            print $query->redirect("/cgi-bin/koha/opac-user.pl?" . ( $failed_holds ? "failed_holds=$failed_holds" : q|| ) . "#opac-user-holds");
272
            exit;
294
        }
273
        }
274
        $canreserve = 0 unless CanBookBeReserved( $borrowernumber, $biblioNum ) eq 'OK';
295
275
296
        unless ( $can_place_hold_if_available_at_pickup ) {
276
        unless ( $can_place_hold_if_available_at_pickup ) {
297
            my $items_in_this_library = Koha::Items->search({ biblionumber => $biblioNum, holdingbranch => $branch });
277
            my $items_in_this_library = Koha::Items->search({ biblionumber => $biblioNum, holdingbranch => $branch });
Lines 307-320 if ( $query->param('place_reserve') ) { Link Here
307
287
308
        # Here we actually do the reserveration. Stage 3.
288
        # Here we actually do the reserveration. Stage 3.
309
        if ($canreserve) {
289
        if ($canreserve) {
310
            my $reserve_id = AddReserve(
290
            for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) {
311
                $branch,          $borrowernumber, $biblioNum,
291
                my $reserve_id = AddReserve(
312
                [$biblioNum],     $rank,           $startdate,
292
                    $branch,          $borrowernumber, $biblioNum,
313
                $expiration_date, $notes,          $biblioData->{title},
293
                    [$biblioNum],     $rank,           $startdate,
314
                $itemNum,         $found,          $itemtype,
294
                    $expiration_date, $notes,          $biblioData->{title},
315
            );
295
                    $itemNum,         $found,          $itemtype,
316
            $failed_holds++ unless $reserve_id;
296
                );
317
            ++$reserve_cnt;
297
                $failed_holds++ unless $reserve_id;
298
                ++$reserve_cnt;
299
            }
318
        }
300
        }
319
    }
301
    }
320
302
Lines 374-379 if ( $maxreserves && ( $reserves_count >= $maxreserves ) ) { Link Here
374
}
356
}
375
357
376
unless ( $noreserves ) {
358
unless ( $noreserves ) {
359
    $template->param(
360
        maxreserves => $maxreserves,
361
        reserves_count => $reserves_count
362
    );
377
    my $requested_reserves_count = scalar( @biblionumbers );
363
    my $requested_reserves_count = scalar( @biblionumbers );
378
    if ( $maxreserves && ( $reserves_count + $requested_reserves_count > $maxreserves ) ) {
364
    if ( $maxreserves && ( $reserves_count + $requested_reserves_count > $maxreserves ) ) {
379
        $template->param( new_reserves_allowed => $maxreserves - $reserves_count );
365
        $template->param( new_reserves_allowed => $maxreserves - $reserves_count );
Lines 540-546 foreach my $biblioNum (@biblionumbers) { Link Here
540
            if ( $opac_hold_policy ne 'N' ) { # If Y or F
526
            if ( $opac_hold_policy ne 'N' ) { # If Y or F
541
                $itemLoopIter->{available} = 1;
527
                $itemLoopIter->{available} = 1;
542
                $numCopiesOPACAvailable++;
528
                $numCopiesOPACAvailable++;
543
                $biblioLoopIter{force_hold} = 1 if $opac_hold_policy eq 'F';
529
                $biblioLoopIter{force_hold} = 'item' if $opac_hold_policy eq 'F';
544
            }
530
            }
545
            $numCopiesAvailable++;
531
            $numCopiesAvailable++;
546
532
Lines 600-617 foreach my $biblioNum (@biblionumbers) { Link Here
600
    # patron placed a record level hold, all the holds the patron places must
586
    # patron placed a record level hold, all the holds the patron places must
601
    # be record level. If the patron placed an item level hold, all holds
587
    # be record level. If the patron placed an item level hold, all holds
602
    # the patron places must be item level
588
    # the patron places must be item level
603
    my $forced_hold_level = Koha::Holds->search(
589
    my $holds = Koha::Holds->search(
604
        {
590
        {
605
            borrowernumber => $borrowernumber,
591
            borrowernumber => $borrowernumber,
606
            biblionumber   => $biblioNum,
592
            biblionumber   => $biblioNum,
607
            found          => undef,
593
            found          => undef,
608
        }
594
        }
609
    )->forced_hold_level();
595
    );
596
    my $forced_hold_level = $holds->forced_hold_level();
610
    if ($forced_hold_level) {
597
    if ($forced_hold_level) {
611
        $biblioLoopIter{force_hold}   = 1 if $forced_hold_level eq 'item';
598
        #$biblioLoopIter{force_hold}   = 1 if $forced_hold_level eq 'item';
612
        $biblioLoopIter{itemholdable} = 0 if $forced_hold_level eq 'record';
599
        #$biblioLoopIter{itemholdable} = 0 if $forced_hold_level eq 'record';
600
        $biblioLoopIter{force_hold} = $forced_hold_level;
613
    }
601
    }
614
602
603
    my $max_holds_for_record = GetMaxPatronHoldsForRecord( $borrowernumber, $biblioNum );
604
    my $remaining_holds_for_record = $max_holds_for_record - $holds->count();
605
    $biblioLoopIter{remaining_holds_for_record} = $remaining_holds_for_record;
606
615
607
616
    push @$biblioLoop, \%biblioLoopIter;
608
    push @$biblioLoop, \%biblioLoopIter;
617
609
(-)a/reserve/placerequest.pl (-21 / +14 lines)
Lines 47-53 my $startdate = $input->param('reserve_date') || ''; Link Here
47
my @rank           = $input->multi_param('rank-request');
47
my @rank           = $input->multi_param('rank-request');
48
my $type           = $input->param('type');
48
my $type           = $input->param('type');
49
my $title          = $input->param('title');
49
my $title          = $input->param('title');
50
my $checkitem      = $input->param('checkitem');
50
my @checkitems     = $input->param('checkitem');
51
my $expirationdate = $input->param('expiration_date');
51
my $expirationdate = $input->param('expiration_date');
52
my $itemtype       = $input->param('itemtype') || undef;
52
my $itemtype       = $input->param('itemtype') || undef;
53
53
Lines 58-63 my $multi_hold = $input->param('multi_hold'); Link Here
58
my $biblionumbers = $multi_hold ? $input->param('biblionumbers') : ($biblionumber . '/');
58
my $biblionumbers = $multi_hold ? $input->param('biblionumbers') : ($biblionumber . '/');
59
my $bad_bibs = $input->param('bad_bibs');
59
my $bad_bibs = $input->param('bad_bibs');
60
my $holds_to_place_count = $input->param('holds_to_place_count') || 1;
60
my $holds_to_place_count = $input->param('holds_to_place_count') || 1;
61
$holds_to_place_count = scalar(@checkitems) if scalar(@checkitems);
61
62
62
my %bibinfos = ();
63
my %bibinfos = ();
63
my @biblionumbers = split '/', $biblionumbers;
64
my @biblionumbers = split '/', $biblionumbers;
Lines 68-84 foreach my $bibnum (@biblionumbers) { Link Here
68
    $bibinfos{$bibnum} = \%bibinfo;
69
    $bibinfos{$bibnum} = \%bibinfo;
69
}
70
}
70
71
71
my $found;
72
my @found;
72
73
73
# if we have an item selectionned, and the pickup branch is the same as the holdingbranch
74
foreach my $checkitem (@checkitems) {
74
# of the document, we force the value $rank and $found .
75
    # if we have an item selectionned, and the pickup branch is the same as the holdingbranch
75
if (defined $checkitem && $checkitem ne ''){
76
    # of the document, we force the value $rank and $found .
76
    $holds_to_place_count = 1;
77
    $rank[0] = '0' unless C4::Context->preference('ReservesNeedReturns');
77
    $rank[0] = '0' unless C4::Context->preference('ReservesNeedReturns');
78
    my $item = $checkitem;
78
    my $item = GetItem($checkitem);
79
    $item = GetItem($item);
80
    if ( $item->{'holdingbranch'} eq $branch ){
79
    if ( $item->{'holdingbranch'} eq $branch ){
81
        $found = 'W' unless C4::Context->preference('ReservesNeedReturns');
80
        push @found, 'W' unless C4::Context->preference('ReservesNeedReturns');
82
    }
81
    }
83
}
82
}
84
83
Lines 98-120 if ( $type eq 'str8' && $borrower ) { Link Here
98
            }
97
            }
99
        }
98
        }
100
99
101
        if ( defined $checkitem && $checkitem ne '' ) {
102
            my $item = GetItem($checkitem);
103
            if ( $item->{'biblionumber'} ne $biblionumber ) {
104
                $biblionumber = $item->{'biblionumber'};
105
            }
106
        }
107
108
        if ($multi_hold) {
100
        if ($multi_hold) {
109
            my $bibinfo = $bibinfos{$biblionumber};
101
            my $bibinfo = $bibinfos{$biblionumber};
110
            AddReserve($branch,$borrower->{'borrowernumber'},$biblionumber,[$biblionumber],
102
            AddReserve( $branch, $borrower->{'borrowernumber'},
111
                       $bibinfo->{rank},$startdate,$expirationdate,$notes,$bibinfo->{title},$checkitem,$found);
103
                        $biblionumber, [$biblionumber],
104
                        $bibinfo->{rank}, $startdate, $expirationdate, $notes,$bibinfo->{title});
112
        } else {
105
        } else {
113
            # place a request on 1st available
106
            # place a request on 1st available
114
            for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) {
107
            for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) {
108
                my $item = GetItem($checkitems[$i]);
115
                AddReserve( $branch, $borrower->{'borrowernumber'},
109
                AddReserve( $branch, $borrower->{'borrowernumber'},
116
                    $biblionumber, \@realbi, $rank[0], $startdate, $expirationdate, $notes, $title,
110
                    $item->{biblionumber}, \@realbi, $rank[0], $startdate, $expirationdate, $notes, $title,
117
                    $checkitem, $found, $itemtype );
111
                    $checkitems[$i], $found[$i] );
118
            }
112
            }
119
        }
113
        }
120
    }
114
    }
121
- 

Return to bug 15565