From f7d9d0a104ea82aae9c4c8475c21c6e465817177 Mon Sep 17 00:00:00 2001 From: Alex Arnaud <alex.arnaud@biblibre.com> Date: Wed, 12 Oct 2016 07:02:19 +0000 Subject: [PATCH] Bz 15565 - Place multiple holds at once for the same record on staff and OPAC. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Séverine QUEUNE <severine.queune@bulac.fr> --- .../prog/en/modules/reserve/request.tt | 16 +- .../opac-tmpl/bootstrap/en/modules/opac-reserve.tt | 192 ++++++++++----------- koha-tmpl/opac-tmpl/bootstrap/less/opac.less | 3 + opac/opac-reserve.pl | 174 +++++++++---------- reserve/placerequest.pl | 34 ++-- 5 files changed, 202 insertions(+), 217 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt index 27dd2de..9912dbc 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt @@ -25,6 +25,8 @@ var override_items = {[% FOREACH bibitemloo IN bibitemloop %][% FOREACH itemloo [% END %][% END %][% END %] }; var MSG_NO_ITEMS_AVAILABLE = _("A hold cannot be requested on any of these items."); +var MSG_EXCEEDED_HOLDS_PER_RECORD = _("Patron has exceeded the number of holds for this record."); +var remainingHolds = "[% remaining_holds_for_record %]"; $(document).ready(function() { function ToggleHoldsToPlace() { @@ -149,17 +151,21 @@ function checkMultiHold() { } }); $("input[name=checkitem]").click(function() { - onechecked = 0; + numchecked = 0; $("input[name=checkitem]").each(function() { if(this.checked){ - onechecked = 1; + numchecked = 1; } }); - if(onechecked == 1){ + if(numchecked > 0){ $("#requestany").prop("checked", false); } else { $("#requestany").prop("checked",true); } + + if (remainingHolds - numchecked < 0) { + alert(MSG_EXCEEDED_HOLDS_PER_RECORD); + } }); $(".clear-date").on("click",function(e){ @@ -493,9 +499,9 @@ function checkMultiHold() { Hold must be record level </span> [% ELSIF ( itemloo.available ) %] - <input type="radio" name="checkitem" value="[% itemloo.itemnumber %]" /> + <input type="checkbox" name="checkitem" value="[% itemloo.itemnumber %]" /> [% ELSIF ( itemloo.override ) %] - <input type="radio" name="checkitem" class="needsoverride" value="[% itemloo.itemnumber %]" /> + <input type="checkbox" name="checkitem" class="needsoverride" value="[% itemloo.itemnumber %]" /> <i class="fa fa-exclamation-triangle fa-lg" style="color:gold" alt="Requires override of hold policy"/></i> [% ELSE %] <span class="error"> diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt index 0f2f4eb..e529885 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt @@ -138,20 +138,18 @@ <form action="/cgi-bin/koha/opac-reserve.pl" method="post" id="hold-request-form"> <input type="hidden" name="place_reserve" value="1"/> <!-- These values are set dynamically by js --> - <input type="hidden" name="biblionumbers" id="biblionumbers"/> - <input type="hidden" name="selecteditems" id="selections"/> <div id="bigloop"> [% FOREACH bibitemloo IN bibitemloop %] <div class="holdrow"> + <input id="remaining_holds_[% bibitemloo.biblionumber %]" type="hidden" value="[% bibitemloo.remaining_holds_for_record %]"/> <p> [% IF ( bibitemloo.holdable ) %] - <input class="reserve_mode" name="reserve_mode" type="hidden" value="single"/> - <input class="single_bib" name="single_bib" type="hidden" value="[% bibitemloo.biblionumber %]"/> - <span class="confirmjs_hold" title="[% bibitemloo.biblionumber %]" style="padding:.3em"></span> - <span class="confirm_nonjs"> - <input type="radio" class="confirmbox checkitem [% bibitemloo.biblionumber %]" name="[% bibitemloo.biblionumber %]" checked="checked" id="single_[% bibitemloo.biblionumber %]" value="any" /> - <label class="confirm_label" for="single_[% bibitemloo.biblionumber %]">Place a hold on </label> + <span title="[% bibitemloo.biblionumber %]" style="padding:.3em"> + <label> + <input class="biblionumbers" name="biblionumbers" type="checkbox" value="[% bibitemloo.biblionumber %]" checked="checked"> + Place a hold on + </label> </span> [% END # / bibitemloo.holdable %] @@ -218,7 +216,7 @@ <li class="branch"> <label for="branch_[% bibitemloo.biblionumber %]">Pick up location:</label> [% UNLESS ( bibitemloo.holdable ) %] - <select name="branch" id="branch_[% bibitemloo.biblionumber %]" disabled="disabled"> + <select name="branch_[% bibitemloo.biblionumber %]" id="branch_[% bibitemloo.biblionumber %]" disabled="disabled"> [% PROCESS options_for_libraries libraries => Branches.all( selected => branch ) %] </select> [% ELSE %] @@ -292,29 +290,39 @@ </li> [% END # / IF OpacHoldNotes %] - [% IF bibitemloo.itemholdable %] - <!-- ITEM HOLDS --> - <li class="lradio place_on_type" style="display:none;"> - [% IF NOT bibitemloo.force_hold %] - <label class="radio inline" for="reqany_[% bibitemloo.biblionumber %]">Next available item</label> - <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]" - id="reqany_[% bibitemloo.biblionumber %]" - class="selectany" - value="Any" - checked="checked" - /> - [% END %] - <label class="radio inline" for="reqspecific_[% bibitemloo.biblionumber %]">A specific item</label> + <!-- ITEM HOLDS --> + <li class="lradio place_on_type" style="display:none;"> + <label class="radio inline" for="reqany_[% bibitemloo.biblionumber %]">Next available item</label> <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]" - id="reqspecific_[% bibitemloo.biblionumber %]" - class="selectspecific" - value="Specific" + id="reqany_[% bibitemloo.biblionumber %]" + class="selectany" + value="Any" + checked="checked" /> - </li> - [% END # / IF bibitemloo.itemholdable %] + <label class="radio inline" for="reqspecific_[% bibitemloo.biblionumber %]">A specific item</label> + <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]" + id="reqspecific_[% bibitemloo.biblionumber %]" + class="selectspecific" + value="Specific" + /> + </li> </ul> - [% IF bibitemloo.itemholdable %] + [% IF bibitemloo.remaining_holds_for_record > 1 %] + [% SET count = 1 %] + <div id="holds_to_place_[% bibitemloo.biblionumber %]" class="hold-options holds-to-place"> + <label>Holds to place (count)</label> + <select name="holds_to_place_count_[% bibitemloo.biblionumber %]"> + [% WHILE count <= bibitemloo.remaining_holds_for_record %] + <option value="[% count %]">[% count %]</option> + [% SET count = count + 1 %] + [% END %] + </select> + </div> + [% ELSE %] + <input type="hidden" name="holds_to_place_count_[% bibitemloo.biblionumber %]" value="1" /> + [% END %] + <table class="copiesrow table table-bordered table-striped" id="copiesrow_[% bibitemloo.biblionumber %]"> <caption>Select a specific item:</caption> <tr> @@ -338,9 +346,9 @@ <tr class="[% itemLoo.backgroundcolor %]"> <td class="copynumber"> [% IF ( itemLoo.available ) %] - <input type="radio" class="checkitem checkitem_[% bibitemloo.biblionumber %]" name="checkitem_[% bibitemloo.biblionumber %]" value="[% itemLoo.itemnumber %]" /> + <input type="checkbox" class="checkitem checkitem_[% bibitemloo.biblionumber %]" name="checkitem_[% bibitemloo.biblionumber %]" value="[% itemLoo.itemnumber %]" /> [% ELSE %] - <input disabled="disabled" type="radio" class="checkitem" name="checkitem" value="[% itemLoo.itemnumber %]" + <input disabled="disabled" type="checkbox" class="checkitem" name="checkitem" value="[% itemLoo.itemnumber %]" style="display:none;" /> <img src="[% interface %]/lib/famfamfam/silk/cross.png" alt="Cannot be put on hold" title="Cannot be put on hold" /> [% END %] @@ -414,7 +422,6 @@ </tr> [% END # / FOREACH itemLoo IN bibitemloo.itemLoop%] </table> <!-- / #copiesrow_[% bibitemloo.biblionumber %] --> - [% END # / IF ( bibitemloo.itemholdable )%] </div> <!-- / #hold-options-[% bibitemloo.biblionumber %] --> </fieldset> [% END # / IF ( bibitemloo.holdable ) %] @@ -437,6 +444,7 @@ <script type="text/javascript"> // <![CDATA[ var MSG_NO_ITEM_SELECTED = _("Expecting a specific item selection."); + var MSG_MAX_HOLDS_EXCEEDED = _("Maximum number of reserve exceded."); // Clear the contents of an input field $(".clearfield").on("click",function(e){ @@ -446,8 +454,8 @@ // Select the first item available function select_first_available(id){ - var radios = $("input:radio[name='checkitem_" + id + "']"); - $(radios).first().attr("checked", "checked"); + var checkboxes = $("input:checkbox[name='checkitem_" + id + "']"); + $(checkboxes).first().attr("checked", "checked"); } $(document).ready(function() { @@ -468,14 +476,16 @@ } }); - // click on a first td check the confirmjs checkbox - $("td.hold").click(function(e){ - if(e.target.tagName.toLowerCase() == 'td'){ - $(this).find("input.confirmjs").each( function() { - $(this).attr('checked', !$(this).attr('checked')); - $(this).change(); - }); - } + $('.checkitem').click(function(e) { + var bibNum = suffixOf($(this).attr("name"), "_"); + var nbCheked = $("input[name='checkitem_"+bibNum+"']:checked").length; + var remaining = $("input[id='remaining_holds_"+bibNum+"']").val(); + if (nbCheked >= remaining) { + $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled'); + } + else { + $('.checkitem_'+bibNum).attr('disabled', false); + } }); $(".toggle-hold-options").on("click",function(e){ @@ -490,15 +500,24 @@ // Hides all 'specific copy' table rows on load. $(".copiesrow").hide(); + $(".holds-to-place").show(); [% FOREACH bibitemloo IN bibitemloop %] - [% IF bibitemloo.force_hold %] - $("#toggle-hold-options-[% bibitemloo.biblionumber %]").click(); - $("#reqspecific_[% bibitemloo.biblionumber %]").click(); - $("#copiesrow_[% bibitemloo.biblionumber %]").show(); - [% END %] - [% IF bibitemloo.reqholdnotes %] - $("#holdnotes_[% bibitemloo.biblionumber %]").attr( 'required', true ); - [% END %] + [% IF bibitemloo.force_hold %] + [% IF bibitemloo.force_hold == 'item' %] + $("#toggle-hold-options-[% bibitemloo.biblionumber %]").click(); + $("#reqspecific_[% bibitemloo.biblionumber %]").attr('checked', true); + $("#holds_to_place_[% bibitemloo.biblionumber %]").hide(); + $("#copiesrow_[% bibitemloo.biblionumber %]").show(); + [% ELSIF bibitemloo.force_hold == 'record' %] + $("#toggle-hold-options-[% bibitemloo.biblionumber %]").click(); + $("#reqany_[% bibitemloo.biblionumber %]").attr('checked', true); + [% END %] + $("#reqany_[% bibitemloo.biblionumber %]").attr('disabled', 'disabled'); + $("#reqspecific_[% bibitemloo.biblionumber %]").attr('disabled', 'disabled'); + [% END %] + [% IF bibitemloo.reqholdnotes %] + $("#holdnotes_[% bibitemloo.biblionumber %]").attr( 'required', true ); + [% END %] [% END %] $(".date-format").each(function(){ @@ -515,40 +534,37 @@ $("#" + op + fieldID).val(""); }); - // Replace non-JS single-selection with multi-selection capability. - $(".reserve_mode").val("multi"); - $(".confirm_nonjs").remove(); - $(".confirmjs_hold").each(function(){ - var bib = $(this).attr("title"); - var html = "<label><input type =\"checkbox\" class=\"confirmjs\" checked=\"checked\""; - html += "value=\"" + bib + "\" id=\"" + bib + "\" /> " + _("Place a hold on") + " </label> "; - $(this).html(html); - }); - $(".confirmjs_nohold").each(function(){ - var bib = $(this).attr("title"); - var html = "<label><input type =\"checkbox\" class=\"confirmjs\" disabled=\"disabled\""; - html += "value=\"" + bib + "\" id=\"" + bib + "\" />" + _("Place a hold on: ") + "</label>"; - $(this).html(html); - }); - // expand or collapse the copiesrow tr function toggle_copiesrow(biblioNum) { var checkbox = $("input:checkbox[value='"+biblioNum+"']"); newCopiesRowId = "#copiesrow_" + biblioNum; + holdsToPlaceCountId = "#holds_to_place_" + biblioNum; var select_specific = $("#reqspecific_"+biblioNum).is(":checked"); // If the checkbox is checked AND we want a specific item, we display the items block if ( $(checkbox).is(":checked") && select_specific ) { $(newCopiesRowId).show(); + $(holdsToPlaceCountId).hide(); } else { $(newCopiesRowId).hide(); + $(holdsToPlaceCountId).show(); } }; - $("#place_on_hdr").show(); + function total_requested() { + var total = 0; + $("input[name='biblionumbers']:checked").each(function() { + var biblioNum = $(this).val(); + if ($("#reqspecific_" + biblioNum + ":checked").size() > 0) { + total += parseInt($("input[name='checkitem_'"+biblioNum+"]:checked").length); + } else { + total += parseInt($("select[name='holds_to_place_count_"+biblioNum+"']").val()); + } + }); + return total; + } $(".place_on_type").show(); // onload, selectany is checked - $(".selectany").attr("checked", "checked"); // If the user is *allowed* to choose a specific item // The first one is preselected @@ -557,8 +573,8 @@ select_first_available(id); }); - // On confirmsjs change - $(".confirmjs").change(function(){ + // On biblionumbers change + $(".biblionumbers").change(function(){ var id = suffixOf($(this).attr("id"), "_"); // If I m checked, I enable radio buttons if ( $(this).is(":checked") ) { @@ -580,35 +596,22 @@ toggle_copiesrow(id); }); - // Show or hide holds notes - $(".shownotes").click(function(){ - biblioNum = suffixOf($(this).attr("id"), "_"); - $("#notesrow_"+biblioNum).toggle(); - }); - // When 'Place Hold' button is clicked $(".placehold").click(function(){ - var biblionumbers = ""; - var selections = ""; - - [% IF new_reserves_allowed %] - if ($(".confirmjs:checked").size() > [% new_reserves_allowed %] ) { - alert(MSG_MAX_HOLDS_EXCEEDED); - return false; - } - [% END %] + if (total_requested() + [% reserves_count %] > [% maxreserves %]) { + alert(MSG_MAX_HOLDS_EXCEEDED); + return false; + } - if ($(".confirmjs:checked").size() == 0) { + if ($("input[name='biblionumbers']:checked").size() == 0) { alert(MSG_NO_RECORD_SELECTED); return false; } // Find the items with the 'Hold' box checked var badBib = null; - $(".confirmjs:checked").each(function() { + $("input[name='biblionumbers']:checked").each(function() { var biblioNum = $(this).val(); - biblionumbers += biblioNum + "/"; - selections += biblioNum + "/"; // If required hold note is empty, make it visible if( $("#holdnotes_"+biblioNum).attr( 'required' ) && $("#holdnotes_"+biblioNum).val() == '' ) { @@ -625,18 +628,8 @@ alert(MSG_NO_ITEM_SELECTED); badBib = biblioNum; return false; - } else { - selections += $(item).val(); } } - selections += "/"; - - // Add the pickup location - var branchSel = $("#branch_" + biblioNum); - if (branchSel.size() > 0) { - selections += $(branchSel).val(); - } - selections += "/"; return true; }); @@ -644,9 +637,6 @@ return false; } - $("#selections").val(selections); - $("#biblionumbers").val(biblionumbers); - return true; }); diff --git a/koha-tmpl/opac-tmpl/bootstrap/less/opac.less b/koha-tmpl/opac-tmpl/bootstrap/less/opac.less index 63961e8..80d49c4 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/less/opac.less +++ b/koha-tmpl/opac-tmpl/bootstrap/less/opac.less @@ -2389,6 +2389,9 @@ td img { margin: 1em 0; padding: .5em; } +.hold-option select { + width: auto; +} .copiesrow { clear : both; } diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl index 95204b3..e70af52 100755 --- a/opac/opac-reserve.pl +++ b/opac/opac-reserve.pl @@ -105,34 +105,19 @@ if ( $reservefee > 0){ my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; -# There are two ways of calling this script, with a single biblio num -# or multiple biblio nums. -my $biblionumbers = $query->param('biblionumbers'); -my $reserveMode = $query->param('reserve_mode'); -if ($reserveMode && ($reserveMode eq 'single')) { - my $bib = $query->param('single_bib'); - $biblionumbers = "$bib/"; -} -if (! $biblionumbers) { - $biblionumbers = $query->param('biblionumber'); -} - -if ((! $biblionumbers) && (! $query->param('place_reserve'))) { - $template->param(message=>1, no_biblionumber=>1); - &get_out($query, $cookie, $template->output); +# Coming from opac-search biblionumbers param is a string, coming from +# opac-reserve, it's an array. +my @biblionumbers = ref($query->param('biblionumbers')) eq 'Array' + ? $query->param('biblionumbers') + : split(/\//, $query->param('biblionumbers')); + +unless (@biblionumbers) { + push(@biblionumbers, $query->param('biblionumber')); } # Pass the numbers to the page so they can be fed back # when the hold is confirmed. TODO: Not necessary? -$template->param( biblionumbers => $biblionumbers ); - -# Each biblio number is suffixed with '/', e.g. "1/2/3/" -my @biblionumbers = split /\//, $biblionumbers; -if (($#biblionumbers < 0) && (! $query->param('place_reserve'))) { - # TODO: New message? - $template->param(message=>1, no_biblionumber=>1); - &get_out($query, $cookie, $template->output); -} +$template->param( biblionumbers => @biblionumbers ); # pass the pickup branch along.... @@ -204,39 +189,22 @@ if ( $query->param('place_reserve') ) { $reserve_cnt = $patron->holds->count; } - # List is composed of alternating biblio/item/branch - my $selectedItems = $query->param('selecteditems'); - - if ($query->param('reserve_mode') eq 'single') { - # This indicates non-JavaScript mode, so there was - # only a single biblio number selected. - my $bib = $query->param('single_bib'); - my $item = $query->param("checkitem_$bib"); - if ($item eq 'any') { - $item = ''; - } - my $branch = $query->param('branch'); - $selectedItems = "$bib/$item/$branch/"; - } - - $selectedItems =~ s!/$!!; - my @selectedItems = split /\//, $selectedItems, -1; - - # Make sure there is a biblionum/itemnum/branch triplet for each item. - # The itemnum can be 'any', meaning next available. - my $selectionCount = @selectedItems; - if (($selectionCount == 0) || (($selectionCount % 3) != 0)) { - $template->param(message=>1, bad_data=>1); - &get_out($query, $cookie, $template->output); - } - my $failed_holds = 0; - while (@selectedItems) { - my $biblioNum = shift(@selectedItems); - my $itemNum = shift(@selectedItems); - my $branch = shift(@selectedItems); # i.e., branch code, not name - - my $canreserve = 0; + foreach my $biblioNum (@biblionumbers) { + my $itemNum = $query->param("checkitem_$biblioNum"); + my @itemnumbers = $query->param("checkitem_$biblioNum"); + my $branch = $query->param("branch_$biblioNum"); + my $reqtype = $query->param("reqtype_$biblioNum"); + my $holds_to_place_count = $query->param("holds_to_place_count_$biblioNum") || 1; + my $notes = $query->param('notes_'.$biblioNum) || ''; + my $nbRequested = $reqtype eq 'Specific' ? @itemnumbers : $holds_to_place_count; + + my $canreserve = 1; + if ( $maxreserves + && $reserve_cnt + $nbRequested >= $maxreserves ) + { + $canreserve = 0; + } my $singleBranchMode = Koha::Libraries->search->count == 1; if ( $singleBranchMode || !$OPACChooseBranch ) @@ -244,7 +212,6 @@ if ( $query->param('place_reserve') ) { $branch = $patron->branchcode; } -#item may belong to a host biblio, if yes change biblioNum to hosts bilbionumber if ( $itemNum ne '' ) { my $item = Koha::Items->find( $itemNum ); my $hostbiblioNum = $item->biblio->biblionumber; @@ -266,31 +233,44 @@ if ( $query->param('place_reserve') ) { my $expiration_date = $query->param("expiration_date_$biblioNum"); - # If a specific item was selected and the pickup branch is the same as the - # holdingbranch, force the value $rank and $found. + # If a specific item was selected and the pickup branch is the same as the + # holdingbranch, force the value $rank and $found. my $rank = $biblioData->{rank}; - if ( $itemNum ne '' ) { - $canreserve = 1 if CanItemBeReserved( $borrowernumber, $itemNum ) eq 'OK'; - $rank = '0' unless C4::Context->preference('ReservesNeedReturns'); - my $item = GetItem($itemNum); - if ( $item->{'holdingbranch'} eq $branch ) { - $found = 'W' - unless C4::Context->preference('ReservesNeedReturns'); - } - } - else { - $canreserve = 1 if CanBookBeReserved( $borrowernumber, $biblioNum ) eq 'OK'; + if ( $reqtype eq 'Specific') { + foreach my $itemnumber (@itemnumbers) { + my $biblionumber = $biblioNum; + + #item may belong to a host biblio, if yes change biblioNum to hosts bilbionumber + my $hostbiblioNum = GetBiblionumberFromItemnumber($itemnumber); + if ( $hostbiblioNum ne $biblioNum ) { + $biblionumber = $hostbiblioNum; + } - # Inserts a null into the 'itemnumber' field of 'reserves' table. - $itemNum = undef; - } - my $notes = $query->param('notes_'.$biblioNum)||''; + $canreserve = 0 unless CanItemBeReserved( $borrowernumber, $itemnumber ) eq 'OK'; + $rank = '0' unless C4::Context->preference('ReservesNeedReturns'); + my $item = GetItem($itemnumber); + if ( $item->{'holdingbranch'} eq $branch ) { + $found = 'W' + unless C4::Context->preference('ReservesNeedReturns'); + } - if ( $maxreserves - && $reserve_cnt >= $maxreserves ) - { - $canreserve = 0; + if ($canreserve) { + my $reserve_id = AddReserve( + $branch, $borrowernumber, + $biblionumber, + [$biblionumber], $rank, + $startdate, $expiration_date, + $notes, $biblioData->{title}, + $itemnumber, $found + ); + $failed_holds++ unless $reserve_id; + ++$reserve_cnt; + } + } + print $query->redirect("/cgi-bin/koha/opac-user.pl?" . ( $failed_holds ? "failed_holds=$failed_holds" : q|| ) . "#opac-user-holds"); + exit; } + $canreserve = 0 unless CanBookBeReserved( $borrowernumber, $biblioNum ) eq 'OK'; unless ( $can_place_hold_if_available_at_pickup ) { my $items_in_this_library = Koha::Items->search({ biblionumber => $biblioNum, holdingbranch => $branch }); @@ -306,14 +286,16 @@ if ( $query->param('place_reserve') ) { # Here we actually do the reserveration. Stage 3. if ($canreserve) { - my $reserve_id = AddReserve( - $branch, $borrowernumber, $biblioNum, - [$biblioNum], $rank, $startdate, - $expiration_date, $notes, $biblioData->{title}, - $itemNum, $found, $itemtype, - ); - $failed_holds++ unless $reserve_id; - ++$reserve_cnt; + for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) { + my $reserve_id = AddReserve( + $branch, $borrowernumber, $biblioNum, + [$biblioNum], $rank, $startdate, + $expiration_date, $notes, $biblioData->{title}, + $itemNum, $found, $itemtype, + ); + $failed_holds++ unless $reserve_id; + ++$reserve_cnt; + } } } @@ -373,6 +355,10 @@ if ( $maxreserves && ( $reserves_count >= $maxreserves ) ) { } unless ( $noreserves ) { + $template->param( + maxreserves => $maxreserves, + reserves_count => $reserves_count + ); my $requested_reserves_count = scalar( @biblionumbers ); if ( $maxreserves && ( $reserves_count + $requested_reserves_count > $maxreserves ) ) { $template->param( new_reserves_allowed => $maxreserves - $reserves_count ); @@ -542,7 +528,7 @@ foreach my $biblioNum (@biblionumbers) { if ( my $hold_allowed = OPACItemHoldsAllowed( $itemInfo, $patron_unblessed ) ) { $itemLoopIter->{available} = 1; $numCopiesOPACAvailable++; - $biblioLoopIter{force_hold} = 1 if $hold_allowed eq 'F'; + $biblioLoopIter{force_hold} = 'item' if $hold_allowed eq 'F'; } $numCopiesAvailable++; @@ -602,18 +588,24 @@ foreach my $biblioNum (@biblionumbers) { # patron placed a record level hold, all the holds the patron places must # be record level. If the patron placed an item level hold, all holds # the patron places must be item level - my $forced_hold_level = Koha::Holds->search( + my $holds = Koha::Holds->search( { borrowernumber => $borrowernumber, biblionumber => $biblioNum, found => undef, } - )->forced_hold_level(); + ); + my $forced_hold_level = $holds->forced_hold_level(); if ($forced_hold_level) { - $biblioLoopIter{force_hold} = 1 if $forced_hold_level eq 'item'; - $biblioLoopIter{itemholdable} = 0 if $forced_hold_level eq 'record'; + #$biblioLoopIter{force_hold} = 1 if $forced_hold_level eq 'item'; + #$biblioLoopIter{itemholdable} = 0 if $forced_hold_level eq 'record'; + $biblioLoopIter{force_hold} = $forced_hold_level; } + my $max_holds_for_record = GetMaxPatronHoldsForRecord( $borrowernumber, $biblioNum ); + my $remaining_holds_for_record = $max_holds_for_record - $holds->count(); + $biblioLoopIter{remaining_holds_for_record} = $remaining_holds_for_record; + push @$biblioLoop, \%biblioLoopIter; diff --git a/reserve/placerequest.pl b/reserve/placerequest.pl index 403321c..9532a6d 100755 --- a/reserve/placerequest.pl +++ b/reserve/placerequest.pl @@ -48,7 +48,7 @@ my $startdate = $input->param('reserve_date') || ''; my @rank = $input->multi_param('rank-request'); my $type = $input->param('type'); my $title = $input->param('title'); -my $checkitem = $input->param('checkitem'); +my @checkitems = $input->param('checkitem'); my $expirationdate = $input->param('expiration_date'); my $itemtype = $input->param('itemtype') || undef; @@ -59,6 +59,7 @@ my $multi_hold = $input->param('multi_hold'); my $biblionumbers = $multi_hold ? $input->param('biblionumbers') : ($biblionumber . '/'); my $bad_bibs = $input->param('bad_bibs'); my $holds_to_place_count = $input->param('holds_to_place_count') || 1; +$holds_to_place_count = scalar(@checkitems) if scalar(@checkitems); my %bibinfos = (); my @biblionumbers = split '/', $biblionumbers; @@ -69,17 +70,15 @@ foreach my $bibnum (@biblionumbers) { $bibinfos{$bibnum} = \%bibinfo; } -my $found; +my @found; -# if we have an item selectionned, and the pickup branch is the same as the holdingbranch -# of the document, we force the value $rank and $found . -if (defined $checkitem && $checkitem ne ''){ - $holds_to_place_count = 1; +foreach my $checkitem (@checkitems) { + # if we have an item selectionned, and the pickup branch is the same as the holdingbranch + # of the document, we force the value $rank and $found . $rank[0] = '0' unless C4::Context->preference('ReservesNeedReturns'); - my $item = $checkitem; - $item = GetItem($item); + my $item = GetItem($checkitem); if ( $item->{'holdingbranch'} eq $branch ){ - $found = 'W' unless C4::Context->preference('ReservesNeedReturns'); + push @found, 'W' unless C4::Context->preference('ReservesNeedReturns'); } } @@ -99,23 +98,18 @@ if ( $type eq 'str8' && $borrower ) { } } - if ( defined $checkitem && $checkitem ne '' ) { - my $item = GetItem($checkitem); - if ( $item->{'biblionumber'} ne $biblionumber ) { - $biblionumber = $item->{'biblionumber'}; - } - } - if ($multi_hold) { my $bibinfo = $bibinfos{$biblionumber}; - AddReserve($branch,$borrower->{'borrowernumber'},$biblionumber,[$biblionumber], - $bibinfo->{rank},$startdate,$expirationdate,$notes,$bibinfo->{title},$checkitem,$found); + AddReserve( $branch, $borrower->{'borrowernumber'}, + $biblionumber, [$biblionumber], + $bibinfo->{rank}, $startdate, $expirationdate, $notes,$bibinfo->{title}); } else { # place a request on 1st available for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) { + my $item = GetItem($checkitems[$i]); AddReserve( $branch, $borrower->{'borrowernumber'}, - $biblionumber, \@realbi, $rank[0], $startdate, $expirationdate, $notes, $title, - $checkitem, $found, $itemtype ); + $item->{biblionumber}, \@realbi, $rank[0], $startdate, $expirationdate, $notes, $title, + $checkitems[$i], $found[$i] ); } } } -- 2.1.4