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 15-20 Link Here
15
    <title>Koha &rsaquo; Circulation &rsaquo; Holds &rsaquo; Confirm holds</title>
15
    <title>Koha &rsaquo; Circulation &rsaquo; Holds &rsaquo; Confirm holds</title>
16
[% END %]
16
[% END %]
17
[% INCLUDE 'doc-head-close.inc' %]
17
[% INCLUDE 'doc-head-close.inc' %]
18
[% Asset.css("css/datatables.css") | $raw %]
18
</head>
19
</head>
19
20
20
<body id="circ_request" class="catalog">
21
<body id="circ_request" class="catalog">
Lines 316-324 Link Here
316
                        Hold must be record level
317
                        Hold must be record level
317
                    </span>
318
                    </span>
318
                [% ELSIF ( itemloo.available ) %]
319
                [% ELSIF ( itemloo.available ) %]
319
                    <input type="radio" name="checkitem" value="[% itemloo.itemnumber | html %]" />
320
                    <input type="checkbox" name="checkitem" value="[% itemloo.itemnumber %]" />
320
                [% ELSIF ( itemloo.override ) %]
321
                [% ELSIF ( itemloo.override ) %]
321
                    <input type="radio" name="checkitem" class="needsoverride" value="[% itemloo.itemnumber | html %]" />
322
                    <input type="checkbox" name="checkitem" class="needsoverride" value="[% itemloo.itemnumber %]" />
322
                    <i class="fa fa-exclamation-triangle fa-lg" style="color:gold" alt="Requires override of hold policy"/></i>
323
                    <i class="fa fa-exclamation-triangle fa-lg" style="color:gold" alt="Requires override of hold policy"/></i>
323
                [% ELSE %]
324
                [% ELSE %]
324
                    <span class="error">
325
                    <span class="error">
Lines 676-681 Link Here
676
        };
677
        };
677
        var MSG_NO_ITEMS_AVAILABLE = _("A hold cannot be requested on any of these items.");
678
        var MSG_NO_ITEMS_AVAILABLE = _("A hold cannot be requested on any of these items.");
678
        columns_settings_borrowers_table = [% ColumnsSettings.GetColumns( 'circ', 'circulation', 'table_borrowers', 'json' ) | $raw %]
679
        columns_settings_borrowers_table = [% ColumnsSettings.GetColumns( 'circ', 'circulation', 'table_borrowers', 'json' ) | $raw %]
680
        var MSG_EXCEEDED_HOLDS_PER_RECORD = _("Patron has exceeded the number of holds for this record.");
681
        var remainingHolds = "[% remaining_holds_for_record %]";
679
682
680
        $(document).ready(function() {
683
        $(document).ready(function() {
681
            function ToggleHoldsToPlace() {
684
            function ToggleHoldsToPlace() {
Lines 810-826 Link Here
810
                }
813
                }
811
            });
814
            });
812
            $("input[name=checkitem]").click(function() {
815
            $("input[name=checkitem]").click(function() {
813
                onechecked = 0;
816
                numchecked = 0;
814
                $("input[name=checkitem]").each(function() {
817
                $("input[name=checkitem]").each(function() {
815
                    if(this.checked){
818
                    if(this.checked){
816
                        onechecked = 1;
819
                        numchecked = 1;
817
                    }
820
                    }
818
                });
821
                });
819
                if(onechecked == 1){
822
                if(numchecked == 1){
820
                    $("#requestany").prop("checked", false);
823
                    $("#requestany").prop("checked", false);
821
                } else {
824
                } else {
822
                    $("#requestany").prop("checked",true);
825
                    $("#requestany").prop("checked",true);
823
                }
826
                }
827
                if (remainingHolds - numchecked < 0) {
828
                    alert(MSG_EXCEEDED_HOLDS_PER_RECORD);
829
                }
824
            });
830
            });
825
            var prev_rank_request;
831
            var prev_rank_request;
826
            $("select[name=rank-request]").on("focus", function() {
832
            $("select[name=rank-request]").on("focus", function() {
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt (-105 / +95 lines)
Lines 151-170 Link Here
151
                        <form action="/cgi-bin/koha/opac-reserve.pl" method="post" id="hold-request-form">
151
                        <form action="/cgi-bin/koha/opac-reserve.pl" method="post" id="hold-request-form">
152
                            <input type="hidden" name="place_reserve" value="1"/>
152
                            <input type="hidden" name="place_reserve" value="1"/>
153
                            <!-- These values are set dynamically by js -->
153
                            <!-- These values are set dynamically by js -->
154
                            <input type="hidden" name="biblionumbers" id="biblionumbers"/>
155
                            <input type="hidden" name="selecteditems" id="selections"/>
156
                            <div id="bigloop">
154
                            <div id="bigloop">
157
155
158
                                [% FOREACH bibitemloo IN bibitemloop %]
156
                                [% FOREACH bibitemloo IN bibitemloop %]
159
                                    <div class="holdrow">
157
                                    <div class="holdrow">
158
                                        <input id="remaining_holds_[% bibitemloo.biblionumber %]" type="hidden" value="[% bibitemloo.remaining_holds_for_record %]"/>
160
                                        <p>
159
                                        <p>
161
                                            [% IF ( bibitemloo.holdable ) %]
160
                                            [% IF ( bibitemloo.holdable ) %]
162
                                                <input class="reserve_mode" name="reserve_mode" type="hidden" value="single"/>
161
                                                <span title="[% bibitemloo.biblionumber %]" style="padding:.3em">
163
                                                <input class="single_bib" name="single_bib" type="hidden" value="[% bibitemloo.biblionumber | html %]"/>
162
                                                    <label>
164
                                                <span class="confirmjs_hold" title="[% bibitemloo.biblionumber | html %]" style="padding:.3em"></span>
163
                                                        <input class="biblionumbers" name="biblionumbers" type="checkbox" value="[% bibitemloo.biblionumber %]" checked="checked">
165
                                                <span class="confirm_nonjs">
164
                                                        Place a hold on
166
                                                    <input type="radio" class="confirmbox checkitem [% bibitemloo.biblionumber | html %]" name="[% bibitemloo.biblionumber | html %]" checked="checked" id="single_[% bibitemloo.biblionumber | html %]" value="any" />
165
                                                    </label>
167
                                                    <label class="confirm_label" for="single_[% bibitemloo.biblionumber | html %]">Place a hold on </label>
168
                                                </span>
166
                                                </span>
169
                                            [% END # / bibitemloo.holdable %]
167
                                            [% END # / bibitemloo.holdable %]
170
168
Lines 230-236 Link Here
230
                                                            <li class="branch">
228
                                                            <li class="branch">
231
                                                                <label for="branch_[% bibitemloo.biblionumber | html %]">Pick up location:</label>
229
                                                                <label for="branch_[% bibitemloo.biblionumber | html %]">Pick up location:</label>
232
                                                                [% UNLESS ( bibitemloo.holdable ) %]
230
                                                                [% UNLESS ( bibitemloo.holdable ) %]
233
                                                                    <select name="branch" id="branch_[% bibitemloo.biblionumber | html %]" disabled="disabled">
231
                                                                    <select name="branch_[% bibitemloo.biblionumber %]" id="branch_[% bibitemloo.biblionumber | html %]" disabled="disabled">
234
                                                                        [% PROCESS options_for_libraries libraries => Branches.pickup_locations( biblio => bibitemloo.biblionumber, selected => branch ) %]
232
                                                                        [% PROCESS options_for_libraries libraries => Branches.pickup_locations( biblio => bibitemloo.biblionumber, selected => branch ) %]
235
                                                                    </select>
233
                                                                    </select>
236
                                                                [% ELSE %]
234
                                                                [% ELSE %]
Lines 304-333 Link Here
304
                                                            </li>
302
                                                            </li>
305
                                                        [% END # / IF OpacHoldNotes %]
303
                                                        [% END # / IF OpacHoldNotes %]
306
304
307
                                                        [% IF bibitemloo.itemholdable %]
305
                                                        <!-- ITEM HOLDS -->
308
                                                            <!-- ITEM HOLDS -->
306
                                                        <li class="lradio place_on_type" style="display:none;">
309
                                                            <li class="lradio place_on_type" style="display:none;">
307
                                                                <label class="radio inline" for="reqany_[% bibitemloo.biblionumber %]">Next available item</label>
310
                                                                [% IF NOT bibitemloo.force_hold %]
308
                                                                <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]"
311
                                                                    <label class="radio inline" for="reqany_[% bibitemloo.biblionumber | html %]">Next available item</label>
309
                                                                        id="reqany_[% bibitemloo.biblionumber %]"
312
                                                                    <input type="radio" name="reqtype_[% bibitemloo.biblionumber | html %]"
310
                                                                        class="selectany"
313
                                                                            id="reqany_[% bibitemloo.biblionumber | html %]"
311
                                                                        value="Any"
314
                                                                            class="selectany"
312
                                                                        checked="checked"
315
                                                                            value="Any"
316
                                                                            checked="checked"
317
                                                                    />
318
                                                                [% END %]
319
                                                                <label class="radio inline" for="reqspecific_[% bibitemloo.biblionumber | html %]">A specific item</label>
320
                                                                <input type="radio" name="reqtype_[% bibitemloo.biblionumber | html %]"
321
                                                                       id="reqspecific_[% bibitemloo.biblionumber | html %]"
322
                                                                       class="selectspecific"
323
                                                                       value="Specific"
324
                                                                />
313
                                                                />
325
                                                            </li>
314
                                                            <label class="radio inline" for="reqspecific_[% bibitemloo.biblionumber %]">A specific item</label>
326
                                                        [% END # / IF bibitemloo.itemholdable %]
315
                                                            <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]"
316
                                                                   id="reqspecific_[% bibitemloo.biblionumber %]"
317
                                                                   class="selectspecific"
318
                                                                   value="Specific"
319
                                                            />
320
                                                        </li>
327
                                                    </ul>
321
                                                    </ul>
328
322
329
                                                    [% IF bibitemloo.itemholdable %]
323
                                                    [% IF bibitemloo.remaining_holds_for_record > 1 %]
330
                                                        <table class="copiesrow table table-bordered table-striped" id="copiesrow_[% bibitemloo.biblionumber | html %]">
324
                                                        [% SET count = 1 %]
325
                                                        <div id="holds_to_place_[% bibitemloo.biblionumber %]" class="hold-options holds-to-place">
326
                                                            <label>Holds to place (count)</label>
327
                                                            <select name="holds_to_place_count_[% bibitemloo.biblionumber %]">
328
                                                            [% WHILE count <= bibitemloo.remaining_holds_for_record %]
329
                                                                <option value="[% count %]">[% count %]</option>
330
                                                                [% SET count = count + 1 %]
331
                                                            [% END %]
332
                                                            </select>
333
                                                        </div>
334
                                                    [% ELSE %]
335
                                                        <input type="hidden" name="holds_to_place_count_[% bibitemloo.biblionumber %]" value="1" />
336
                                                    [% END %]
337
338
                                                        <table class="copiesrow table table-bordered table-striped" id="copiesrow_[% bibitemloo.biblionumber %]">
331
                                                            <caption>Select a specific item:</caption>
339
                                                            <caption>Select a specific item:</caption>
332
                                                            <tr>
340
                                                            <tr>
333
                                                                <th>Copy number</th>
341
                                                                <th>Copy number</th>
Lines 353-361 Link Here
353
                                                                <tr class="[% itemLoo.backgroundcolor | html %]">
361
                                                                <tr class="[% itemLoo.backgroundcolor | html %]">
354
                                                                    <td class="copynumber">
362
                                                                    <td class="copynumber">
355
                                                                        [% IF ( itemLoo.available ) %]
363
                                                                        [% IF ( itemLoo.available ) %]
356
                                                                            <input type="radio" class="checkitem checkitem_[% bibitemloo.biblionumber | html %]" name="checkitem_[% bibitemloo.biblionumber | html %]" value="[% itemLoo.itemnumber | html %]" />
364
                                                                            <input type="checkbox" class="checkitem checkitem_[% bibitemloo.biblionumber %]" name="checkitem_[% bibitemloo.biblionumber %]" value="[% itemLoo.itemnumber %]" />
357
                                                                        [% ELSE %]
365
                                                                        [% ELSE %]
358
                                                                            <input disabled="disabled" type="radio" class="checkitem" name="checkitem" value="[% itemLoo.itemnumber | html %]"
366
                                                                            <input disabled="disabled" type="checkbox" class="checkitem" name="checkitem" value="[% itemLoo.itemnumber %]"
359
                                                                                   style="display:none;" />
367
                                                                                   style="display:none;" />
360
                                                                            <img src="[% interface | html %]/lib/famfamfam/cross.png" alt="Cannot be put on hold" title="Cannot be put on hold" />
368
                                                                            <img src="[% interface | html %]/lib/famfamfam/cross.png" alt="Cannot be put on hold" title="Cannot be put on hold" />
361
                                                                        [% END %]
369
                                                                        [% END %]
Lines 431-439 Link Here
431
                                                                    </td>
439
                                                                    </td>
432
                                                                </tr>
440
                                                                </tr>
433
                                                            [% END # / FOREACH itemLoo IN bibitemloo.itemLoop%]
441
                                                            [% END # / FOREACH itemLoo IN bibitemloo.itemLoop%]
434
                                                        </table> <!-- / #copiesrow_[% bibitemloo.biblionumber | html %] -->
442
                                                        </table> <!-- / #copiesrow_[% bibitemloo.biblionumber %] -->
435
                                                    [% END # / IF ( bibitemloo.itemholdable )%]
443
                                                </div> <!-- / #hold-options-[% bibitemloo.biblionumber %] -->
436
                                                </div> <!-- / #hold-options-[% bibitemloo.biblionumber | html %] -->
437
                                            </fieldset>
444
                                            </fieldset>
438
                                        [% END # / IF ( bibitemloo.holdable ) %]
445
                                        [% END # / IF ( bibitemloo.holdable ) %]
439
                                    </div> <!-- / .holdrow -->
446
                                    </div> <!-- / .holdrow -->
Lines 455-460 Link Here
455
<script>
462
<script>
456
// <![CDATA[
463
// <![CDATA[
457
    var MSG_NO_ITEM_SELECTED = _("Expecting a specific item selection.");
464
    var MSG_NO_ITEM_SELECTED = _("Expecting a specific item selection.");
465
    var MSG_MAX_HOLDS_EXCEEDED = _("Maximum number of reserve exceded.");
458
466
459
        // Clear the contents of an input field
467
        // Clear the contents of an input field
460
        $(".clearfield").on("click",function(e){
468
        $(".clearfield").on("click",function(e){
Lines 464-471 Link Here
464
472
465
    // Select the first item available
473
    // Select the first item available
466
    function select_first_available(id){
474
    function select_first_available(id){
467
        var radios = $("input:radio[name='checkitem_" + id + "']");
475
        var checkboxes = $("input:checkbox[name='checkitem_" + id + "']");
468
        $(radios).first().attr("checked", "checked");
476
        $(checkboxes).first().attr("checked", "checked");
469
    }
477
    }
470
478
471
    $(document).ready(function() {
479
    $(document).ready(function() {
Lines 486-499 Link Here
486
            }
494
            }
487
        });
495
        });
488
496
489
        // click on a first td check the confirmjs checkbox
497
        $('.checkitem').click(function(e) {
490
        $("td.hold").click(function(e){
498
            var bibNum = suffixOf($(this).attr("name"), "_");
491
          if(e.target.tagName.toLowerCase() == 'td'){
499
            var nbCheked = $("input[name='checkitem_"+bibNum+"']:checked").length;
492
            $(this).find("input.confirmjs").each( function() {
500
            var remaining = $("input[id='remaining_holds_"+bibNum+"']").val();
493
               $(this).attr('checked', !$(this).attr('checked'));
501
            if (nbCheked >= remaining) {
494
               $(this).change();
502
                $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled');
495
            });
503
            }
496
          }
504
            else {
505
                $('.checkitem_'+bibNum).attr('disabled', false);
506
            }
497
        });
507
        });
498
508
499
        $(".toggle-hold-options").on("click",function(e){
509
        $(".toggle-hold-options").on("click",function(e){
Lines 508-522 Link Here
508
        // Hides all 'specific copy' table rows on load.
518
        // Hides all 'specific copy' table rows on load.
509
        $(".copiesrow").hide();
519
        $(".copiesrow").hide();
510
520
521
        $(".holds-to-place").show();
511
        [% FOREACH bibitemloo IN bibitemloop %]
522
        [% FOREACH bibitemloo IN bibitemloop %]
512
          [% IF bibitemloo.force_hold %]
523
            [% IF bibitemloo.force_hold %]
513
            $("#toggle-hold-options-[% bibitemloo.biblionumber | html %]").click();
524
                [% IF bibitemloo.force_hold == 'item' %]
514
            $("#reqspecific_[% bibitemloo.biblionumber | html %]").click();
525
                    $("#toggle-hold-options-[% bibitemloo.biblionumber %]").click();
515
            $("#copiesrow_[% bibitemloo.biblionumber | html %]").show();
526
                    $("#reqspecific_[% bibitemloo.biblionumber %]").attr('checked', true);
516
          [% END %]
527
                    $("#holds_to_place_[% bibitemloo.biblionumber %]").hide();
517
          [% IF bibitemloo.reqholdnotes %]
528
                    $("#copiesrow_[% bibitemloo.biblionumber %]").show();
518
              $("#holdnotes_[% bibitemloo.biblionumber | html %]").attr( 'required', true );
529
                [% ELSIF bibitemloo.force_hold == 'record' %]
519
          [% END %]
530
                    $("#toggle-hold-options-[% bibitemloo.biblionumber %]").click();
531
                    $("#reqany_[% bibitemloo.biblionumber %]").attr('checked', true);
532
                [% END %]
533
                $("#reqany_[% bibitemloo.biblionumber %]").attr('disabled', 'disabled');
534
                $("#reqspecific_[% bibitemloo.biblionumber %]").attr('disabled', 'disabled');
535
            [% END %]
536
            [% IF bibitemloo.reqholdnotes %]
537
                $("#holdnotes_[% bibitemloo.biblionumber %]").attr( 'required', true );
538
            [% END %]
520
        [% END %]
539
        [% END %]
521
540
522
        $(".date-format").each(function(){
541
        $(".date-format").each(function(){
Lines 533-572 Link Here
533
            $("#" + op + fieldID).val("");
552
            $("#" + op + fieldID).val("");
534
        });
553
        });
535
554
536
        // Replace non-JS single-selection with multi-selection capability.
537
        $(".reserve_mode").val("multi");
538
        $(".confirm_nonjs").remove();
539
        $(".confirmjs_hold").each(function(){
540
            var bib = $(this).attr("title");
541
            var html = "<label><input type =\"checkbox\" class=\"confirmjs\" checked=\"checked\"";
542
            html += "value=\"" + bib + "\" id=\"" + bib + "\" /> " + _("Place a hold on") + " </label> ";
543
            $(this).html(html);
544
        });
545
        $(".confirmjs_nohold").each(function(){
546
            var bib = $(this).attr("title");
547
            var html = "<label><input type =\"checkbox\" class=\"confirmjs\" disabled=\"disabled\"";
548
            html += "value=\"" + bib + "\" id=\"" + bib + "\" />" + _("Place a hold on: ") + "</label>";
549
            $(this).html(html);
550
        });
551
552
        // expand or collapse the copiesrow tr
555
        // expand or collapse the copiesrow tr
553
        function toggle_copiesrow(biblioNum) {
556
        function toggle_copiesrow(biblioNum) {
554
            var checkbox = $("input:checkbox[value='"+biblioNum+"']");
557
            var checkbox = $("input:checkbox[value='"+biblioNum+"']");
555
            newCopiesRowId = "#copiesrow_" + biblioNum;
558
            newCopiesRowId = "#copiesrow_" + biblioNum;
559
            holdsToPlaceCountId = "#holds_to_place_" + biblioNum;
556
            var select_specific = $("#reqspecific_"+biblioNum).is(":checked");
560
            var select_specific = $("#reqspecific_"+biblioNum).is(":checked");
557
            // If the checkbox is checked AND we want a specific item, we display the items block
561
            // If the checkbox is checked AND we want a specific item, we display the items block
558
            if ( $(checkbox).is(":checked") && select_specific ) {
562
            if ( $(checkbox).is(":checked") && select_specific ) {
559
                $(newCopiesRowId).show();
563
                $(newCopiesRowId).show();
564
                $(holdsToPlaceCountId).hide();
560
            } else {
565
            } else {
561
                $(newCopiesRowId).hide();
566
                $(newCopiesRowId).hide();
567
                $(holdsToPlaceCountId).show();
562
             }
568
             }
563
        };
569
        };
564
570
565
        $("#place_on_hdr").show();
571
        function total_requested() {
572
            var total = 0;
573
            $("input[name='biblionumbers']:checked").each(function() {
574
                var biblioNum = $(this).val();
575
                if ($("#reqspecific_" + biblioNum + ":checked").size() > 0) {
576
                    total += parseInt($("input[name='checkitem_'"+biblioNum+"]:checked").length);
577
                } else {
578
                    total += parseInt($("select[name='holds_to_place_count_"+biblioNum+"']").val());
579
                }
580
            });
581
            return total;
582
        }
566
583
567
        $(".place_on_type").show();
584
        $(".place_on_type").show();
568
        // onload, selectany is checked
585
        // onload, selectany is checked
569
        $(".selectany").attr("checked", "checked");
570
586
571
        // If the user is *allowed* to choose a specific item
587
        // If the user is *allowed* to choose a specific item
572
        // The first one is preselected
588
        // The first one is preselected
Lines 575-582 Link Here
575
            select_first_available(id);
591
            select_first_available(id);
576
        });
592
        });
577
593
578
        // On confirmsjs change
594
        // On biblionumbers change
579
        $(".confirmjs").change(function(){
595
        $(".biblionumbers").change(function(){
580
            var id = suffixOf($(this).attr("id"), "_");
596
            var id = suffixOf($(this).attr("id"), "_");
581
            // If I m checked, I enable radio buttons
597
            // If I m checked, I enable radio buttons
582
            if ( $(this).is(":checked") ) {
598
            if ( $(this).is(":checked") ) {
Lines 598-632 Link Here
598
            toggle_copiesrow(id);
614
            toggle_copiesrow(id);
599
        });
615
        });
600
616
601
        // Show or hide holds notes
602
        $(".shownotes").click(function(){
603
            biblioNum = suffixOf($(this).attr("id"), "_");
604
            $("#notesrow_"+biblioNum).toggle();
605
        });
606
607
        // When 'Place Hold' button is clicked
617
        // When 'Place Hold' button is clicked
608
        $(".placehold").click(function(){
618
        $(".placehold").click(function(){
609
            var biblionumbers = "";
619
            if (total_requested() + [% reserves_count %] > [% maxreserves %]) {
610
            var selections = "";
620
                alert(MSG_MAX_HOLDS_EXCEEDED);
611
621
                return false;
612
            [% IF new_reserves_allowed %]
622
            }
613
                if ($(".confirmjs:checked").size() > [% new_reserves_allowed | html %] ) {
614
                    alert(MSG_MAX_HOLDS_EXCEEDED);
615
                    return false;
616
                }
617
            [% END %]
618
623
619
            if ($(".confirmjs:checked").size() == 0) {
624
            if ($("input[name='biblionumbers']:checked").size() == 0) {
620
                alert(MSG_NO_RECORD_SELECTED);
625
                alert(MSG_NO_RECORD_SELECTED);
621
                return false;
626
                return false;
622
            }
627
            }
623
628
624
            // Find the items with the 'Hold' box checked
629
            // Find the items with the 'Hold' box checked
625
            var badBib = null;
630
            var badBib = null;
626
            $(".confirmjs:checked").each(function() {
631
            $("input[name='biblionumbers']:checked").each(function() {
627
                var biblioNum = $(this).val();
632
                var biblioNum = $(this).val();
628
                biblionumbers += biblioNum + "/";
629
                selections += biblioNum + "/";
630
633
631
                // If required hold note is empty, make it visible
634
                // If required hold note is empty, make it visible
632
                if( $("#holdnotes_"+biblioNum).attr( 'required' ) && $("#holdnotes_"+biblioNum).val() == '' ) {
635
                if( $("#holdnotes_"+biblioNum).attr( 'required' ) && $("#holdnotes_"+biblioNum).val() == '' ) {
Lines 643-660 Link Here
643
                        alert(MSG_NO_ITEM_SELECTED);
646
                        alert(MSG_NO_ITEM_SELECTED);
644
                        badBib = biblioNum;
647
                        badBib = biblioNum;
645
                        return false;
648
                        return false;
646
                    } else {
647
                      selections += $(item).val();
648
                    }
649
                    }
649
                }
650
                }
650
                selections += "/";
651
652
                // Add the pickup location
653
                var branchSel = $("#branch_" + biblioNum);
654
                if (branchSel.size() > 0) {
655
                    selections += $(branchSel).val();
656
                }
657
                selections += "/";
658
                return true;
651
                return true;
659
            });
652
            });
660
653
Lines 662-670 Link Here
662
                return false;
655
                return false;
663
            }
656
            }
664
657
665
            $("#selections").val(selections);
666
            $("#biblionumbers").val(biblionumbers);
667
668
            return true;
658
            return true;
669
        });
659
        });
670
660
(-)a/opac/opac-reserve.pl (-83 / +84 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 201-239 if ( $query->param('place_reserve') ) { Link Here
201
        $reserve_cnt = $patron->holds->count;
186
        $reserve_cnt = $patron->holds->count;
202
    }
187
    }
203
188
204
    # List is composed of alternating biblio/item/branch
205
    my $selectedItems = $query->param('selecteditems');
206
207
    if ($query->param('reserve_mode') eq 'single') {
208
        # This indicates non-JavaScript mode, so there was
209
        # only a single biblio number selected.
210
        my $bib = $query->param('single_bib');
211
        my $item = $query->param("checkitem_$bib");
212
        if ($item eq 'any') {
213
            $item = '';
214
        }
215
        my $branch = $query->param('branch');
216
        $selectedItems = "$bib/$item/$branch/";
217
    }
218
219
    $selectedItems =~ s!/$!!;
220
    my @selectedItems = split /\//, $selectedItems, -1;
221
222
    # Make sure there is a biblionum/itemnum/branch triplet for each item.
223
    # The itemnum can be 'any', meaning next available.
224
    my $selectionCount = @selectedItems;
225
    if (($selectionCount == 0) || (($selectionCount % 3) != 0)) {
226
        $template->param(message=>1, bad_data=>1);
227
        &get_out($query, $cookie, $template->output);
228
    }
229
230
    my $failed_holds = 0;
189
    my $failed_holds = 0;
231
    while (@selectedItems) {
190
    foreach my $biblioNum (@biblionumbers) {
232
        my $biblioNum = shift(@selectedItems);
191
        my $itemNum = $query->param("checkitem_$biblioNum");
233
        my $itemNum   = shift(@selectedItems);
192
        my @itemnumbers = $query->param("checkitem_$biblioNum");
234
        my $branch    = shift(@selectedItems);    # i.e., branch code, not name
193
        my $branch = $query->param("branch_$biblioNum");
235
194
        my $reqtype = $query->param("reqtype_$biblioNum");
236
        my $canreserve = 0;
195
        my $holds_to_place_count = $query->param("holds_to_place_count_$biblioNum") || 1;
196
        my $notes = $query->param('notes_'.$biblioNum) || '';
197
        my $nbRequested = $reqtype eq 'Specific' ? @itemnumbers : $holds_to_place_count;
198
199
        my $canreserve = 1;
200
        if (   $maxreserves
201
            && $reserve_cnt + $nbRequested >= $maxreserves )
202
        {
203
            $canreserve = 0;
204
        }
237
205
238
        my $singleBranchMode = Koha::Libraries->search->count == 1;
206
        my $singleBranchMode = Koha::Libraries->search->count == 1;
239
        if ( $singleBranchMode || ! C4::Context->preference("OPACAllowUserToChooseBranch") )
207
        if ( $singleBranchMode || ! C4::Context->preference("OPACAllowUserToChooseBranch") )
Lines 255-261 if ( $query->param('place_reserve') ) { Link Here
255
            }
223
            }
256
        }
224
        }
257
225
258
#item may belong to a host biblio, if yes change biblioNum to hosts bilbionumber
226
        # item may belong to a host biblio, if yes change biblioNum to hosts bilbionumber
259
        if ( $itemNum ne '' ) {
227
        if ( $itemNum ne '' ) {
260
            my $item = Koha::Items->find( $itemNum );
228
            my $item = Koha::Items->find( $itemNum );
261
            my $hostbiblioNum = $item->biblio->biblionumber;
229
            my $hostbiblioNum = $item->biblio->biblionumber;
Lines 277-299 if ( $query->param('place_reserve') ) { Link Here
277
245
278
        my $expiration_date = $query->param("expiration_date_$biblioNum");
246
        my $expiration_date = $query->param("expiration_date_$biblioNum");
279
247
248
        # If a specific item was selected and the pickup branch is the same as the
249
        # holdingbranch, force the value $rank and $found.
280
        my $rank = $biblioData->{rank};
250
        my $rank = $biblioData->{rank};
281
        if ( $itemNum ne '' ) {
251
        if ( $reqtype eq 'Specific') {
282
            $canreserve = 1 if CanItemBeReserved( $borrowernumber, $itemNum )->{status} eq 'OK';
252
            foreach my $itemnumber (@itemnumbers) {
283
        }
253
                my $biblionumber = $biblioNum;
284
        else {
254
285
            $canreserve = 1 if CanBookBeReserved( $borrowernumber, $biblioNum )->{status} eq 'OK';
255
                #item may belong to a host biblio, if yes change biblioNum to hosts bilbionumber
256
                my $hostbiblioNum = GetBiblionumberFromItemnumber($itemnumber);
257
                if ( $hostbiblioNum ne $biblioNum ) {
258
                    $biblionumber = $hostbiblioNum;
259
                }
286
260
287
            # Inserts a null into the 'itemnumber' field of 'reserves' table.
261
                $canreserve = 0 unless CanItemBeReserved( $borrowernumber, $itemnumber ) eq 'OK';
288
            $itemNum = undef;
262
                $rank = '0' unless C4::Context->preference('ReservesNeedReturns');
289
        }
263
                my $item = GetItem($itemnumber);
290
        my $notes = $query->param('notes_'.$biblioNum)||'';
264
                if ( $item->{'holdingbranch'} eq $branch ) {
265
                    $found = 'W'
266
                      unless C4::Context->preference('ReservesNeedReturns');
267
                }
291
268
292
        if (   $maxreserves
269
                if ($canreserve) {
293
            && $reserve_cnt >= $maxreserves )
270
                    my $reserve_id = AddReserve(
294
        {
271
                        $branch,         $borrowernumber,
295
            $canreserve = 0;
272
                        $biblionumber,
273
                        [$biblionumber], $rank,
274
                        $startdate,      $expiration_date,
275
                        $notes,          $biblioData->{title},
276
                        $itemnumber,     $found
277
                    );
278
                    $failed_holds++ unless $reserve_id;
279
                    ++$reserve_cnt;
280
                }
281
            }
282
            print $query->redirect("/cgi-bin/koha/opac-user.pl?" . ( $failed_holds ? "failed_holds=$failed_holds" : q|| ) . "#opac-user-holds");
283
            exit;
296
        }
284
        }
285
        $canreserve = 0 unless CanBookBeReserved( $borrowernumber, $biblioNum ) eq 'OK';
297
286
298
        unless ( $can_place_hold_if_available_at_pickup ) {
287
        unless ( $can_place_hold_if_available_at_pickup ) {
299
            my $items_in_this_library = Koha::Items->search({ biblionumber => $biblioNum, holdingbranch => $branch });
288
            my $items_in_this_library = Koha::Items->search({ biblionumber => $biblioNum, holdingbranch => $branch });
Lines 309-322 if ( $query->param('place_reserve') ) { Link Here
309
298
310
        # Here we actually do the reserveration. Stage 3.
299
        # Here we actually do the reserveration. Stage 3.
311
        if ($canreserve) {
300
        if ($canreserve) {
312
            my $reserve_id = AddReserve(
301
            for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) {
313
                $branch,          $borrowernumber, $biblioNum,
302
                my $reserve_id = AddReserve(
314
                [$biblioNum],     $rank,           $startdate,
303
                    $branch,          $borrowernumber, $biblioNum,
315
                $expiration_date, $notes,          $biblioData->{title},
304
                    [$biblioNum],     $rank,           $startdate,
316
                $itemNum,         $found,          $itemtype,
305
                    $expiration_date, $notes,          $biblioData->{title},
317
            );
306
                    $itemNum,         $found,          $itemtype,
318
            $failed_holds++ unless $reserve_id;
307
                );
319
            ++$reserve_cnt;
308
                $failed_holds++ unless $reserve_id;
309
                ++$reserve_cnt;
310
            }
320
        }
311
        }
321
    }
312
    }
322
313
Lines 376-381 if ( $maxreserves && ( $reserves_count >= $maxreserves ) ) { Link Here
376
}
367
}
377
368
378
unless ( $noreserves ) {
369
unless ( $noreserves ) {
370
    $template->param(
371
        maxreserves => $maxreserves,
372
        reserves_count => $reserves_count
373
    );
379
    my $requested_reserves_count = scalar( @biblionumbers );
374
    my $requested_reserves_count = scalar( @biblionumbers );
380
    if ( $maxreserves && ( $reserves_count + $requested_reserves_count > $maxreserves ) ) {
375
    if ( $maxreserves && ( $reserves_count + $requested_reserves_count > $maxreserves ) ) {
381
        $template->param( new_reserves_allowed => $maxreserves - $reserves_count );
376
        $template->param( new_reserves_allowed => $maxreserves - $reserves_count );
Lines 550-556 foreach my $biblioNum (@biblionumbers) { Link Here
550
            if ( $opac_hold_policy ne 'N' ) { # If Y or F
545
            if ( $opac_hold_policy ne 'N' ) { # If Y or F
551
                $itemLoopIter->{available} = 1;
546
                $itemLoopIter->{available} = 1;
552
                $numCopiesOPACAvailable++;
547
                $numCopiesOPACAvailable++;
553
                $biblioLoopIter{force_hold} = 1 if $opac_hold_policy eq 'F';
548
                $biblioLoopIter{force_hold} = 'item' if $opac_hold_policy eq 'F';
554
            }
549
            }
555
            $numCopiesAvailable++;
550
            $numCopiesAvailable++;
556
551
Lines 617-634 foreach my $biblioNum (@biblionumbers) { Link Here
617
    # patron placed a record level hold, all the holds the patron places must
612
    # patron placed a record level hold, all the holds the patron places must
618
    # be record level. If the patron placed an item level hold, all holds
613
    # be record level. If the patron placed an item level hold, all holds
619
    # the patron places must be item level
614
    # the patron places must be item level
620
    my $forced_hold_level = Koha::Holds->search(
615
    my $holds = Koha::Holds->search(
621
        {
616
        {
622
            borrowernumber => $borrowernumber,
617
            borrowernumber => $borrowernumber,
623
            biblionumber   => $biblioNum,
618
            biblionumber   => $biblioNum,
624
            found          => undef,
619
            found          => undef,
625
        }
620
        }
626
    )->forced_hold_level();
621
    );
622
    my $forced_hold_level = $holds->forced_hold_level();
627
    if ($forced_hold_level) {
623
    if ($forced_hold_level) {
628
        $biblioLoopIter{force_hold}   = 1 if $forced_hold_level eq 'item';
624
        #$biblioLoopIter{force_hold}   = 1 if $forced_hold_level eq 'item';
629
        $biblioLoopIter{itemholdable} = 0 if $forced_hold_level eq 'record';
625
        #$biblioLoopIter{itemholdable} = 0 if $forced_hold_level eq 'record';
626
        $biblioLoopIter{force_hold} = $forced_hold_level;
630
    }
627
    }
631
628
629
    my $max_holds_for_record = GetMaxPatronHoldsForRecord( $borrowernumber, $biblioNum );
630
    my $remaining_holds_for_record = $max_holds_for_record - $holds->count();
631
    $biblioLoopIter{remaining_holds_for_record} = $remaining_holds_for_record;
632
632
633
633
    push @$biblioLoop, \%biblioLoopIter;
634
    push @$biblioLoop, \%biblioLoopIter;
634
635
(-)a/reserve/placerequest.pl (-19 / +20 lines)
Lines 49-55 my $startdate = $input->param('reserve_date') || ''; Link Here
49
my @rank           = $input->multi_param('rank-request');
49
my @rank           = $input->multi_param('rank-request');
50
my $type           = $input->param('type');
50
my $type           = $input->param('type');
51
my $title          = $input->param('title');
51
my $title          = $input->param('title');
52
my $checkitem      = $input->param('checkitem');
52
my @checkitems     = $input->param('checkitem');
53
my $expirationdate = $input->param('expiration_date');
53
my $expirationdate = $input->param('expiration_date');
54
my $itemtype       = $input->param('itemtype') || undef;
54
my $itemtype       = $input->param('itemtype') || undef;
55
55
Lines 60-65 my $multi_hold = $input->param('multi_hold'); Link Here
60
my $biblionumbers = $multi_hold ? $input->param('biblionumbers') : ($biblionumber . '/');
60
my $biblionumbers = $multi_hold ? $input->param('biblionumbers') : ($biblionumber . '/');
61
my $bad_bibs = $input->param('bad_bibs');
61
my $bad_bibs = $input->param('bad_bibs');
62
my $holds_to_place_count = $input->param('holds_to_place_count') || 1;
62
my $holds_to_place_count = $input->param('holds_to_place_count') || 1;
63
$holds_to_place_count = scalar(@checkitems) if scalar(@checkitems);
63
64
64
my %bibinfos = ();
65
my %bibinfos = ();
65
my @biblionumbers = split '/', $biblionumbers;
66
my @biblionumbers = split '/', $biblionumbers;
Lines 70-76 foreach my $bibnum (@biblionumbers) { Link Here
70
    $bibinfos{$bibnum} = \%bibinfo;
71
    $bibinfos{$bibnum} = \%bibinfo;
71
}
72
}
72
73
73
my $found;
74
my @found;
75
76
foreach my $checkitem (@checkitems) {
77
    # if we have an item selectionned, and the pickup branch is the same as the holdingbranch
78
    # of the document, we force the value $rank and $found .
79
    $rank[0] = '0' unless C4::Context->preference('ReservesNeedReturns');
80
    my $item = GetItem($checkitem);
81
    if ( $item->{'holdingbranch'} eq $branch ){
82
        push @found, 'W' unless C4::Context->preference('ReservesNeedReturns');
83
    }
84
}
74
85
75
if ( $type eq 'str8' && $borrower ) {
86
if ( $type eq 'str8' && $borrower ) {
76
87
Lines 88-114 if ( $type eq 'str8' && $borrower ) { Link Here
88
            }
99
            }
89
        }
100
        }
90
101
91
        if ( defined $checkitem && $checkitem ne '' ) {
92
            my $item = Koha::Items->find($checkitem);
93
            if ( $item->biblionumber ne $biblionumber ) {
94
                $biblionumber = $item->biblionumber;
95
            }
96
        }
97
98
        if ($multi_hold) {
102
        if ($multi_hold) {
99
            my $bibinfo = $bibinfos{$biblionumber};
103
            my $bibinfo = $bibinfos{$biblionumber};
100
            if ( CanBookBeReserved($borrower->{'borrowernumber'}, $biblionumber)->{status} eq 'OK' ) {
104
            AddReserve( $branch, $borrower->{'borrowernumber'},
101
                AddReserve($branch,$borrower->{'borrowernumber'},$biblionumber,[$biblionumber],
105
                        $biblionumber, [$biblionumber],
102
                           $bibinfo->{rank},$startdate,$expirationdate,$notes,$bibinfo->{title},$checkitem,$found);
106
                        $bibinfo->{rank}, $startdate, $expirationdate, $notes,$bibinfo->{title});
103
            }
104
        } else {
107
        } else {
105
            # place a request on 1st available
108
            # place a request on 1st available
106
            for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) {
109
            for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) {
107
                if ( CanBookBeReserved($borrower->{'borrowernumber'}, $biblionumber)->{status} eq 'OK' ) {
110
                my $item = GetItem($checkitems[$i]);
108
                    AddReserve( $branch, $borrower->{'borrowernumber'},
111
                AddReserve( $branch, $borrower->{'borrowernumber'},
109
                        $biblionumber, \@realbi, $rank[0], $startdate, $expirationdate, $notes, $title,
112
                    $item->{biblionumber}, \@realbi, $rank[0], $startdate, $expirationdate, $notes, $title,
110
                        $checkitem, $found, $itemtype );
113
                    $checkitems[$i], $found[$i] );
111
                }
112
            }
114
            }
113
        }
115
        }
114
    }
116
    }
115
- 

Return to bug 15565