Bugzilla – Attachment 87979 Details for
Bug 15565
Place multiple item-level holds at once for the same record
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 15565: Place multiple holds at once for the same record on staff and OPAC.
Bug-15565-Place-multiple-holds-at-once-for-the-sam.patch (text/plain), 39.81 KB, created by
Aleisha Amohia
on 2019-04-15 02:47:13 UTC
(
hide
)
Description:
Bug 15565: Place multiple holds at once for the same record on staff and OPAC.
Filename:
MIME Type:
Creator:
Aleisha Amohia
Created:
2019-04-15 02:47:13 UTC
Size:
39.81 KB
patch
obsolete
>From 2731c8c68ba508d8502adf3db770df90f03b9fc9 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] Bug 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 > >Test plan: >1. Create an circulation rule to use for testing the patches on this bug >report. Ensure it has a value greater than 1 for 'Holds >allowed', 'Holds per record (count)', and 'Item level holds' is enabled. > >2. Also ensure the 'RequestOnOpac' syspref is set to 'Allow'. > >3. Go to the reservation page (request.pl) of a biblio in the staff client with more >than one item. > >4. Notice beside each item a radio button is displayed preventing you >from being able to select multiple items to place a hold on. > >5. Go to the reservation page (opac-reserve.pl) of the same biblio in the OPAC >also notice a radio button is displayed beside every item. > >6. Apply patches > >7. Repeat step 3 and 5 and notice in both the staff client and OPAC >checkboxes rather than radio buttons are displayed beside each item so >you can select multiple items for reservation at a time. > >8. From staff interface, place several item-level holds for the same user >on the same record at once: > > - check that you are warned if you exceed "Holds per record (count)" >(circulation rules) for this record. > - check also maxReserves system preference. > >9. From opac, place several item-level and record level holds >for the same user on the same record at once: > > - check that can't exceed "Holds per record (count)" for > this record. > This is enforced by all unticked item checkboxes being > disabled after the number of ticked checkboxes equals the 'Holds per record (count)' (circulation rules) value. > > - check also maxReserves system preference. > >Do the same in OPAC and staff by selecting several >record (multi-hold). > >Signed-off-by: Séverine QUEUNE <severine.queune@bulac.fr> > >Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com> >Signed-off-by: Benjamin Rokseth <benjamin.rokseth@deichman.no> > >Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de> >--- > .../prog/en/modules/reserve/request.tt | 16 +- > .../opac-tmpl/bootstrap/en/modules/opac-reserve.tt | 200 ++++++++++----------- > opac/opac-reserve.pl | 167 ++++++++--------- > reserve/placerequest.pl | 38 ++-- > 4 files changed, 210 insertions(+), 211 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 36d6a30..aa55c67 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >@@ -15,6 +15,7 @@ > <title>Koha › Circulation › Holds › Confirm holds</title> > [% END %] > [% INCLUDE 'doc-head-close.inc' %] >+[% Asset.css("css/datatables.css") | $raw %] > </head> > > <body id="circ_request" class="catalog"> >@@ -316,9 +317,9 @@ > Hold must be record level > </span> > [% ELSIF ( itemloo.available ) %] >- <input type="radio" name="checkitem" value="[% itemloo.itemnumber | html %]" /> >+ <input type="checkbox" name="checkitem" value="[% itemloo.itemnumber %]" /> > [% ELSIF ( itemloo.override ) %] >- <input type="radio" name="checkitem" class="needsoverride" value="[% itemloo.itemnumber | html %]" /> >+ <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"> >@@ -676,6 +677,8 @@ > }; > var MSG_NO_ITEMS_AVAILABLE = _("A hold cannot be requested on any of these items."); > columns_settings_borrowers_table = [% ColumnsSettings.GetColumns( 'circ', 'circulation', 'table_borrowers', 'json' ) | $raw %] >+ 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() { >@@ -810,17 +813,20 @@ > } > }); > $("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 == 1){ > $("#requestany").prop("checked", false); > } else { > $("#requestany").prop("checked",true); > } >+ if (remainingHolds - numchecked < 0) { >+ alert(MSG_EXCEEDED_HOLDS_PER_RECORD); >+ } > }); > var prev_rank_request; > $("select[name=rank-request]").on("focus", function() { >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 d643c80..491415e 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt >@@ -151,20 +151,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 | html %]"/> >- <span class="confirmjs_hold" title="[% bibitemloo.biblionumber | html %]" style="padding:.3em"></span> >- <span class="confirm_nonjs"> >- <input type="radio" class="confirmbox checkitem [% bibitemloo.biblionumber | html %]" name="[% bibitemloo.biblionumber | html %]" checked="checked" id="single_[% bibitemloo.biblionumber | html %]" value="any" /> >- <label class="confirm_label" for="single_[% bibitemloo.biblionumber | html %]">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 %] > >@@ -230,7 +228,7 @@ > <li class="branch"> > <label for="branch_[% bibitemloo.biblionumber | html %]">Pick up location:</label> > [% UNLESS ( bibitemloo.holdable ) %] >- <select name="branch" id="branch_[% bibitemloo.biblionumber | html %]" disabled="disabled"> >+ <select name="branch_[% bibitemloo.biblionumber %]" id="branch_[% bibitemloo.biblionumber | html %]" disabled="disabled"> > [% PROCESS options_for_libraries libraries => Branches.pickup_locations( biblio => bibitemloo.biblionumber, selected => branch ) %] > </select> > [% ELSE %] >@@ -304,30 +302,40 @@ > </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 | html %]">Next available item</label> >- <input type="radio" name="reqtype_[% bibitemloo.biblionumber | html %]" >- id="reqany_[% bibitemloo.biblionumber | html %]" >- class="selectany" >- value="Any" >- checked="checked" >- /> >- [% END %] >- <label class="radio inline" for="reqspecific_[% bibitemloo.biblionumber | html %]">A specific item</label> >- <input type="radio" name="reqtype_[% bibitemloo.biblionumber | html %]" >- id="reqspecific_[% bibitemloo.biblionumber | html %]" >- class="selectspecific" >- value="Specific" >+ <!-- 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="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 %] >- <table class="copiesrow table table-bordered table-striped" id="copiesrow_[% bibitemloo.biblionumber | html %]"> >+ [% 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> > <th>Copy number</th> >@@ -353,9 +361,9 @@ > <tr class="[% itemLoo.backgroundcolor | html %]"> > <td class="copynumber"> > [% IF ( itemLoo.available ) %] >- <input type="radio" class="checkitem checkitem_[% bibitemloo.biblionumber | html %]" name="checkitem_[% bibitemloo.biblionumber | html %]" value="[% itemLoo.itemnumber | html %]" /> >+ <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 | html %]" >+ <input disabled="disabled" type="checkbox" class="checkitem" name="checkitem" value="[% itemLoo.itemnumber %]" > style="display:none;" /> > <img src="[% interface | html %]/lib/famfamfam/cross.png" alt="Cannot be put on hold" title="Cannot be put on hold" /> > [% END %] >@@ -431,9 +439,8 @@ > </td> > </tr> > [% END # / FOREACH itemLoo IN bibitemloo.itemLoop%] >- </table> <!-- / #copiesrow_[% bibitemloo.biblionumber | html %] --> >- [% END # / IF ( bibitemloo.itemholdable )%] >- </div> <!-- / #hold-options-[% bibitemloo.biblionumber | html %] --> >+ </table> <!-- / #copiesrow_[% bibitemloo.biblionumber %] --> >+ </div> <!-- / #hold-options-[% bibitemloo.biblionumber %] --> > </fieldset> > [% END # / IF ( bibitemloo.holdable ) %] > </div> <!-- / .holdrow --> >@@ -455,6 +462,7 @@ > <script> > // <![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){ >@@ -464,8 +472,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() { >@@ -486,14 +494,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){ >@@ -508,15 +518,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 | html %]").click(); >- $("#reqspecific_[% bibitemloo.biblionumber | html %]").click(); >- $("#copiesrow_[% bibitemloo.biblionumber | html %]").show(); >- [% END %] >- [% IF bibitemloo.reqholdnotes %] >- $("#holdnotes_[% bibitemloo.biblionumber | html %]").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(){ >@@ -533,40 +552,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 >@@ -575,8 +591,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") ) { >@@ -598,35 +614,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 | html %] ) { >- 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() == '' ) { >@@ -643,18 +646,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; > }); > >@@ -662,9 +655,6 @@ > return false; > } > >- $("#selections").val(selections); >- $("#biblionumbers").val(biblionumbers); >- > return true; > }); > >diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl >index 725b31d..4b332e8 100755 >--- a/opac/opac-reserve.pl >+++ b/opac/opac-reserve.pl >@@ -106,34 +106,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.... >@@ -201,39 +186,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 || ! C4::Context->preference("OPACAllowUserToChooseBranch") ) >@@ -255,7 +223,7 @@ if ( $query->param('place_reserve') ) { > } > } > >-#item may belong to a host biblio, if yes change biblioNum to hosts bilbionumber >+ # 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; >@@ -277,23 +245,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. > my $rank = $biblioData->{rank}; >- if ( $itemNum ne '' ) { >- $canreserve = 1 if CanItemBeReserved( $borrowernumber, $itemNum )->{status} eq 'OK'; >- } >- else { >- $canreserve = 1 if CanBookBeReserved( $borrowernumber, $biblioNum )->{status} 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 }); >@@ -309,14 +298,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; >+ } > } > } > >@@ -376,6 +367,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 ); >@@ -550,7 +545,7 @@ foreach my $biblioNum (@biblionumbers) { > if ( $opac_hold_policy ne 'N' ) { # If Y or F > $itemLoopIter->{available} = 1; > $numCopiesOPACAvailable++; >- $biblioLoopIter{force_hold} = 1 if $opac_hold_policy eq 'F'; >+ $biblioLoopIter{force_hold} = 'item' if $opac_hold_policy eq 'F'; > } > $numCopiesAvailable++; > >@@ -617,18 +612,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 1e49a4b..f06c6d3 100755 >--- a/reserve/placerequest.pl >+++ b/reserve/placerequest.pl >@@ -49,7 +49,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; > >@@ -60,6 +60,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; >@@ -70,7 +71,17 @@ foreach my $bibnum (@biblionumbers) { > $bibinfos{$bibnum} = \%bibinfo; > } > >-my $found; >+my @found; >+ >+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 = GetItem($checkitem); >+ if ( $item->{'holdingbranch'} eq $branch ){ >+ push @found, 'W' unless C4::Context->preference('ReservesNeedReturns'); >+ } >+} > > if ( $type eq 'str8' && $borrower ) { > >@@ -88,27 +99,18 @@ if ( $type eq 'str8' && $borrower ) { > } > } > >- if ( defined $checkitem && $checkitem ne '' ) { >- my $item = Koha::Items->find($checkitem); >- if ( $item->biblionumber ne $biblionumber ) { >- $biblionumber = $item->biblionumber; >- } >- } >- > if ($multi_hold) { > my $bibinfo = $bibinfos{$biblionumber}; >- if ( CanBookBeReserved($borrower->{'borrowernumber'}, $biblionumber)->{status} eq 'OK' ) { >- 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++ ) { >- if ( CanBookBeReserved($borrower->{'borrowernumber'}, $biblionumber)->{status} eq 'OK' ) { >- AddReserve( $branch, $borrower->{'borrowernumber'}, >- $biblionumber, \@realbi, $rank[0], $startdate, $expirationdate, $notes, $title, >- $checkitem, $found, $itemtype ); >- } >+ my $item = GetItem($checkitems[$i]); >+ AddReserve( $branch, $borrower->{'borrowernumber'}, >+ $item->{biblionumber}, \@realbi, $rank[0], $startdate, $expirationdate, $notes, $title, >+ $checkitems[$i], $found[$i] ); > } > } > } >-- >2.1.4
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 15565
:
47527
|
47551
|
47552
|
50068
|
50069
|
50392
|
50393
|
56229
|
56230
|
56231
|
56232
|
56458
|
56510
|
56511
|
56512
|
56513
|
56514
|
56515
|
56517
|
56518
|
56519
|
56520
|
56521
|
56522
|
56523
|
56524
|
61244
|
61245
|
61246
|
61247
|
61248
|
61576
|
61577
|
61578
|
61579
|
61580
|
64590
|
64591
|
64592
|
64593
|
64594
|
66594
|
66595
|
66596
|
66597
|
66598
|
68759
|
68760
|
68761
|
68762
|
68763
|
71643
|
71644
|
71645
|
71646
|
71647
|
71648
|
72644
|
72645
|
72646
|
72647
|
72648
|
72649
|
78242
|
78243
|
78244
|
78245
|
78246
|
78247
|
78248
|
78266
|
78305
|
78417
|
78418
|
78419
|
78420
|
78421
|
78422
|
78423
|
78424
|
78425
|
78426
|
78712
|
78713
|
78714
|
78715
|
78716
|
78717
|
78718
|
78719
|
78720
|
78815
|
78816
|
78817
|
78818
|
78819
|
78820
|
78821
|
78822
|
78823
|
81419
|
81420
|
81421
|
81422
|
81423
|
81424
|
81425
|
81426
|
81427
|
81431
|
81449
|
81570
|
81571
|
81572
|
81573
|
81574
|
81575
|
81576
|
81577
|
81578
|
81579
|
81580
|
81581
|
82205
|
82206
|
82207
|
82208
|
82209
|
82210
|
82211
|
82212
|
82213
|
82214
|
82215
|
82216
|
82220
|
82221
|
83331
|
83332
|
83333
|
83334
|
83335
|
83336
|
83337
|
83338
|
83339
|
83340
|
83341
|
83342
|
83378
|
83380
|
83381
|
84541
|
84542
|
84543
|
84544
|
84545
|
84546
|
84547
|
84548
|
84549
|
84550
|
84551
|
84552
|
84553
|
87979
|
87980
|
87981
|
87982
|
87983
|
87984
|
87985
|
87986
|
87987
|
87988
|
87989
|
87990
|
87991
|
117128
|
117129
|
117130
|
117131
|
117132
|
117133
|
120365
|
120366
|
120367
|
120639
|
120640
|
120641
|
121941
|
122098
|
162071
|
162072
|
162073
|
162074
|
163052
|
163053
|
163054
|
163055
|
163092
|
163093
|
166005
|
166006
|
166007
|
166008
|
166009