Bugzilla – Attachment 178165 Details for
Bug 36135
Add tool to batch modify holds
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 36135: Use API and datatables to display holds to modify
0013-Bug-36135-Use-API-and-datatables-to-display-holds-to.patch (text/plain), 47.79 KB, created by
Emmi Takkinen
on 2025-02-18 06:36:14 UTC
(
hide
)
Description:
Bug 36135: Use API and datatables to display holds to modify
Filename:
MIME Type:
Creator:
Emmi Takkinen
Created:
2025-02-18 06:36:14 UTC
Size:
47.79 KB
patch
obsolete
>From 2cc7450a1b7c65e0d0822b761187136da53b09f5 Mon Sep 17 00:00:00 2001 >From: Emmi Takkinen <emmi.takkinen@koha-suomi.fi> >Date: Wed, 22 Jan 2025 13:50:26 +0200 >Subject: [PATCH 13/14] Bug 36135: Use API and datatables to display holds to > modify > >--- > admin/columns_settings.yml | 47 +- > .../en/modules/tools/batch_modify_holds.tt | 648 +++++++++++++----- > tools/batch_modify_holds.pl | 103 +-- > 3 files changed, 514 insertions(+), 284 deletions(-) > >diff --git a/admin/columns_settings.yml b/admin/columns_settings.yml >index 2a632acc25..4a9bcbc70a 100644 >--- a/admin/columns_settings.yml >+++ b/admin/columns_settings.yml >@@ -1955,7 +1955,52 @@ modules: > columnname: suspend > - > columnname: print_slip >- >+ holds_to_modify: >+ default_display_length: 20 >+ columns: >+ - >+ columnname: checkbox >+ cannot_be_toggled: 1 >+ cannot_be_modified: 1 >+ - >+ columnname: expiration_date >+ - >+ columnname: title >+ - >+ columnname: barcode >+ - >+ columnname: patron >+ - >+ columnname: status >+ - >+ columnname: pickup_library >+ - >+ columnname: suspended >+ - >+ columnname: suspended_until >+ - >+ columnname: notes >+ modified_holds: >+ default_display_length: 20 >+ columns: >+ - >+ columnname: expiration_date >+ - >+ columnname: title >+ - >+ columnname: barcode >+ - >+ columnname: patron >+ - >+ columnname: status >+ - >+ columnname: pickup_library >+ - >+ columnname: suspended >+ - >+ columnname: suspended_until >+ - >+ columnname: notes > holdsratios: > holds-ratios: > default_display_length: 20 >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batch_modify_holds.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batch_modify_holds.tt >index 166bdd04bc..c92914f9cb 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batch_modify_holds.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batch_modify_holds.tt >@@ -5,6 +5,8 @@ > [% USE Categories %] > [% USE KohaDates %] > [% USE ItemTypes %] >+[% USE TablesSettings %] >+[% USE To %] > [% PROCESS 'html_helpers.inc' %] > > [% INCLUDE 'doc-head-open.inc' %] >@@ -35,22 +37,20 @@ > [% END #/ WRAPPER breadcrumbs %] > [% END #/ WRAPPER sub-header.inc %] > >- <div class="main container-fluid"> >- <div class="row"> >- <div class="col-sm-10 order-md-2 order-sm-1"> >- <main> >- >- <h1>Batch modify holds</h1> >- >- [% IF view == 'form' %] >+<div class="main container-fluid"> >+ <div class="row"> >+ <div class="col-sm-10 col-sm-push-2 order-sm-1"> >+ <main> >+ <h1>Batch modify holds</h1> >+ [% IF view == "form" %] >+ <div id="modify_holds_search"> > <form method="get" action="/cgi-bin/koha/tools/batch_modify_holds.pl" id="modify_holds_form"> > <fieldset class="rows"> > <legend>Hold search criteria:</legend> >- <span class="hint">NOTE! Column patron_expiration_date is used as a main filter for expiration date field. Otherwise column expirationdate is used.</span> > <ol> > <li> > <label for="expirationdate_from">Expiration date from:</label> >- <input type="text" size="10" id="expirationdate_from" name="expirationdate_from" class="flatpickr" data-date_to="to" /> >+ <input type="text" size="10" id="expirationdate_from" name="expirationdate_from" class="flatpickr" data-date_to="expirationdate_to" /> > </li> > <li> > <label for="expirationdate_to">Expiration date to:</label> >@@ -81,238 +81,379 @@ > </li> > <li> > <label for="suspend_until_from">Suspended until from:</label> >- <input type="text" size="10" id="suspend_until_from" name="suspend_until_from" class="flatpickr" data-date_to="to" /> >+ <input type="text" size="10" id="suspend_until_from" name="suspend_until_from" class="flatpickr" data-date_to="suspend_until_to" /> > </li> > <li> > <label for="suspend_until_to">Suspended until to:</label> > <input type="text" size="10" id="suspend_until_to" name="suspend_until_to" class="flatpickr"/> > </li> > <li> >- <label for="reservenotes">Hold note:</label> >- <input type="text" id="reservenotes" name="reservenotes"/> >+ <label for="holdnotes">Hold note:</label> >+ <input type="text" id="holdnotes" name="holdnotes"/> > </li> > </ol> > </fieldset> > <fieldset class="action"> >- <input type="hidden" name="op" value="list"/> >- <input type="submit" class="btn btn-primary" value="Continue"/> >- <a class="cancel" href="/cgi-bin/koha/tools/tools-home.pl">Cancel</a> >+ <input type="submit" class="btn btn-primary" value="Search"/> > </fieldset> > </form> <!-- /#modify_holds_form --> >- [% ELSIF view == 'list' %] >- <form action="/cgi-bin/koha/tools/batch_modify_holds.pl" method="post" id="process"> >+ </div> <!-- /#modify_holds_search --> >+ [% ELSIF view == "report" %] >+ <div id="modified_holds_results-wrapper"> >+ <div id="modified_holds_results" class="page-section"> >+ <table id="modified_holds"></table> >+ </div> <!-- /#modified_holds_results --> >+ <fieldset class="action"> >+ <a href="/cgi-bin/koha/tools/batch_modify_holds.pl">Return to batch hold modification</a> >+ </fieldset > >+ </div> <!-- /#modified_holds_results-wrapper --> >+ [% END %] >+ <div id="modify_holds_results-wrapper" style="display:none;"> >+ <div id="toolbar" class="btn-toolbar"> >+ <a href="#" id="edit_search" class="btn btn-default"><i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit search</a> >+ </div> <!-- /#toolbar --> >+ <form action="/cgi-bin/koha/tools/batch_modify_holds.pl" method="post" id="process_mods"> > [% INCLUDE 'csrf-token.inc' %] >- [% IF holds.count %] >- <div><p>Found [% holds.count | html %][% IF holds.count > 1 %] holds [% ELSE %] hold [% END %]to modify.</p></div> >- <div class="page-section"> >- <div class="btn-toolbar selections-toolbar"> >- <a id="selectall" href="#"><i class="fa fa-check"></i> Select all</a> >- <a id="clearall" href="#"><i class="fa fa-remove"></i> Clear all</a> >- </div> >- <table id="found_holds"> >- <thead> >- <tr> >- <th> </th> >- <th>Expiration date</th> >- <th>Patron expiration date</th> >- <th>Title</th> >- <th>Barcode</th> >- <th>Status</th> >- <th>Hold pickup library</th> >- <th>Suspended</th> >- <th>Suspended until</th> >- <th>Note</th> >- </tr> >- </thead> >- <tbody> >- [% FOREACH hold IN holds %] >- <tr> >- <td><input type="checkbox" name="hold_id" value="[% hold.reserve_id | html %]"/></td> >- <td>[% hold.expirationdate | $KohaDates %]</td> >- <td>[% hold.patron_expiration_date | $KohaDates %]</td> >- <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% hold.biblionumber | uri %]">[% hold.biblio.title | html %]</a></td> >- <td><a href="/cgi-bin/koha/catalogue/moredetail.pl?itemnumber=[% hold.itemnumber | uri %]&biblionumber=[% hold.biblionumber | uri %]&bi=[% hold.biblionumber | uri %]#item[% hold.itemnumber | uri %]">[% hold.item.barcode | html %]</a></td> >- <td class="found_status" data-found="[% hold.found | html %]"> >- [% IF hold.found == "T" %] >- In transit >- [% ELSIF hold.found == "P" %] >- In processing >- [% ELSIF hold.found == "W" %] >- Waiting >- [% ELSE %] >- No status >- [% END %] >- </td> >- <td>[% Branches.GetName( hold.branchcode ) | html %]</td> >- <td>[% IF hold.suspend %]Yes[% ELSE %]No[% END %]</td> >- <td>[% hold.suspend_until | $KohaDates %]</td> >- <td>[% hold.reservenotes | html %]</td> >- </tr> >- [% END %] >- </tbody> >- </table> <!-- /#holds --> >- </div> <!-- /.page-section --> >- <h2>Modify holds</h2> >- <div class="page-section"> >- <table id="hold_modifies"> >- <thead> >- <tr> >- <th>New expiration date</th> >- <th>New pickup library</th> >- <th>Suspend holds</th> >- <th>Suspend until</th> >- <th>New reserve note</th> >- </tr> >- </thead> >- <tbody> >- <tr> >- <td> >- <input type="text" id="new_expiration_date" name="new_expiration_date" class="flatpickr" data-flatpickr-futuredate="true"/> >- </td> >- <td> >- <select id="new_pickup_loc" name="new_pickup_loc"> >- <option value="" selected="selected"></option> >- [% PROCESS options_for_libraries libraries => Branches.pickup_locations(selected = "") %] >- </select> >- </td> >- <td> >- <select id="new_suspend_status" name="new_suspend_status"> >- <option value="" selected="selected"></option> >- <option value="not_suspended">Not suspended</option> >- <option value="suspend">Suspend</option> >- </select> >- </td> >- <td> >- <input type="text" id="new_suspend_date" name="new_suspend_date" class="flatpickr" data-flatpickr-futuredate="true"/> >- </td> >- <td> >- <input type="text" id="new_reserve_note" name="new_reserve_note"/> >- </td> >- </tr> >- </tbody> >- </table> <!-- /#hold_modifies --> >- </div> >- <fieldset class="action"> >- <input type="hidden" name="op" value="cud-modify"/> >- <input type="submit" class="btn btn-primary" value="Modify selected holds"/> >- <a class="cancel" href="/cgi-bin/koha/tools/batch_modify_holds.pl">Cancel</a> >- </fieldset> >- </form> <!-- /#process --> >- [% ELSE %] >- <div class="dialog message"> >- No holds were found for the selected filters. >+ <div id="modify_holds_results" class="page-section"> >+ <div id="searchheader" class="searchheader"> >+ <a id="select_all" href="#" class="btn btn-link"><i class="fa fa-check"></i> Select all visible rows</a> >+ | <a id="clear_all" href="#" class="btn btn-link"><i class="fa fa-times"></i> Clear selections</a> > </div> >- <a class="cancel" href="/cgi-bin/koha/tools/batch_modify_holds.pl">Return</a> >- [% END %] >- [% ELSIF view == 'report' %] >- <div class="dialog message"> >- [% updated_holds.count | html %] holds have been modified! >- </div> >- <div class="page-section"> >- <table id="holds"> >+ <h3>Holds found for: <span class="searchpattern"></span></h3> >+ <table id="holds_to_modify"></table> >+ </div> <!-- /#modify_holds_results --> >+ <div id="modify_holds_form_options" class="page-section"> >+ <h2>Modify holds</h2> >+ <table id="modify_holds_options"> > <thead> > <tr> >- <th>Expiration date</th> >- <th>Title</th> >- <th>Barcode</th> >- <th>Hold pickup library</th> >- <th>Suspended</th> >- <th>Suspended until</th> >- <th>Note</th> >+ <th>New expiration date</th> >+ <th>New pickup library</th> >+ <th>Suspend holds</th> >+ <th>Suspend until</th> >+ <th>New hold note</th> > </tr> > </thead> > <tbody> >- [% FOREACH hold IN updated_holds %] >- <tr> >- <td>[% hold.expirationdate | $KohaDates %]</td> >- <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% hold.biblionumber | uri %]">[% hold.biblio.title | html %]</a></td> >- <td><a href="/cgi-bin/koha/catalogue/moredetail.pl?itemnumber=[% hold.itemnumber | uri %]&biblionumber=[% hold.biblionumber | uri %]&bi=[% hold.biblionumber | uri %]#item[% hold.itemnumber | uri %]">[% hold.item.barcode | html %]</a></td> >- <td>[% Branches.GetName( hold.branchcode ) | html %]</td> >- <td>[% IF hold.suspend == 0 %]No[% ELSE %]Yes[% END %]</td> >- <td>[% hold.suspend_until | $KohaDates %]</td> >- <td>[% hold.reservenotes | html %]</td> >- </tr> >- [% END %] >+ <tr> >+ <td> >+ <input type="text" id="new_expiration_date" name="new_expiration_date" class="flatpickr" data-flatpickr-futuredate="true" /> >+ </td> >+ <td> >+ <select name="new_pickup_loc" id="new_pickup_loc"> >+ <option value="" selected="selected"></option> >+ [% PROCESS options_for_libraries libraries => Branches.pickup_locations({ selected => "" }) %] >+ </select> >+ </td> >+ <td> >+ <select id="new_suspend_status" name="new_suspend_status"> >+ <option value="" selected="selected"></option> >+ <option value="0">Not suspended</option> >+ <option value="1">Suspend</option> >+ </select> >+ </td> >+ <td> >+ <input type="text" id="new_suspend_date" name="new_suspend_date" class="flatpickr" data-flatpickr-futuredate="true" /> >+ </td> >+ <td> >+ <input type="text" id="new_hold_note" name="new_hold_note"/> >+ </td> >+ </tr> > </tbody> >- </table> <!-- /#holds --> >- </div> <!-- /.page-section --> >- <a class="cancel" href="/cgi-bin/koha/tools/batch_modify_holds.pl">Return to batch hold modification</a> >- [% END %] >- </main> >- </div> <!-- /.col-sm-10 col-sm-push-2 --> >- >- >- <div class="col-sm-2 col-sm-pull-10"> >- <aside> >- [% INCLUDE 'tools-menu.inc' %] >- </aside> >- </div> <!-- /.col-sm-2 col-sm-pull-10 --> >- </div> <!-- /.row --> >+ </table> <!-- /#modify_holds_options --> >+ </div> <!-- /#modify_holds_options --> >+ <fieldset class="action"> >+ <input type="hidden" name="op" value="cud-modify" /> >+ <input type="submit" class="btn btn-primary" value="Modify holds" /> >+ <a class="cancel" href="/cgi-bin/koha/tools/batch_modify_holds.pl">Cancel</a> >+ </fieldset> >+ </form> <!-- /#process_mods --> >+ </div> <!-- /#modify_holds_results-wrapper --> >+ </main> >+ </div> <!-- /.col-sm-10 col-sm-push-2 --> >+ <div class="col-sm-2 col-sm-pull-10"> >+ <aside> >+ [% INCLUDE 'tools-menu.inc' %] >+ </aside> >+ </div> <!-- /.col-sm-2 col-sm-pull-10 --> > </div> > [% MACRO jsinclude BLOCK %] > [% Asset.js("js/tools-menu.js") | $raw %] > [% INCLUDE 'calendar.inc' %] > [% INCLUDE 'datatables.inc' %] >+ [% INCLUDE 'js-patron-format.inc' %] > [% Asset.js("lib/jquery/plugins/humanmsg.js") | $raw %] > <script> >+ let hide_patron_name = [% IF Koha.Preference('HidePatronName') %]true[% ELSE %]false[% END %]; >+ let hold_ids = [% IF updated_holds %] [% updated_holds | $raw %] [% ELSE %] [] [% END %]; >+ > $(document).ready(function() { > >- $("#selectall").click(function(e){ >+ $("#select_all").click(function(e){ > e.preventDefault(); >- $("#found_holds input[type='checkbox']").each(function(){ >+ $("#holds_to_modify input[type='checkbox']").each(function(){ > $(this).prop("checked", true); > }); > }); > >- $("#clearall").click(function(e){ >+ $("#clear_all").click(function(e){ > e.preventDefault(); >- $("#found_holds input[type='checkbox']").each(function(){ >+ $("#holds_to_modify input[type='checkbox']").each(function(){ > $(this).prop("checked", false); > }); > }); > >- $("#selectall").click(); >+ $('#modify_holds_form').submit(function() { >+ var modify_holds_form = $(this); >+ search_holds(modify_holds_form); >+ $("#modify_holds_search").hide(); >+ $('#edit_search').show(); >+ return false; >+ }); >+ >+ $("#edit_search").on("click", function(e){ >+ e.preventDefault(); >+ $('#modify_holds_search').show(); >+ $('#edit_search').hide(); >+ }); >+ >+ function search_holds(modify_holds_form){ >+ var table_settings = [% TablesSettings.GetTableSettings( 'circ', 'holds', 'holds_to_modify', 'json' ) | $raw %]; >+ var searchpattern = ""; >+ var filters = { >+ "me.expirationdate": function(){ >+ var expirationdate_from = modify_holds_form.find("#expirationdate_from").val(); >+ var expirationdate_to = modify_holds_form.find("#expirationdate_to").val(); >+ >+ searchpattern += expirationdate_from && expirationdate_to ? _("expiration date between ")+ expirationdate_from + " and " + expirationdate_to + " ": ""; >+ >+ return expirationdate_from && expirationdate_to ? {"-between": [expirationdate_from, expirationdate_to]} : ""; >+ }, >+ "me.branchcode": function(){ >+ var branchcodes = modify_holds_form.find("#branchcodes").val(); >+ if( branchcodes.length > 0 ){ >+ searchpattern += _("from libraries "); >+ var selected_libraries = modify_holds_form.find("#branchcodes option:selected"); >+ $.each(selected_libraries, function(key, value) { >+ searchpattern += value.text + " "; >+ }); >+ return {"-in": branchcodes }; >+ } >+ }, >+ "me.status": function(){ >+ var found_status = modify_holds_form.find("#found_status").val(); >+ if( found_status.length > 0 ){ >+ var filters = [{"-in": found_status}]; >+ if(jQuery.inArray("NULL", found_status) !== -1){ >+ filters.push({"=": null}); >+ } >+ searchpattern += _("found status in "); >+ $.each(found_status, function(key, value) { >+ let status = _("No status "); >+ if ( value == "T" ) { >+ status = _("In transit "); >+ } else if( value == "P" ) { >+ status = _("In processing "); >+ } else if( value == "W" ) { >+ status = _("Waiting "); >+ } >+ searchpattern += status; >+ }); >+ return filters; >+ } >+ }, >+ "me.suspended": function(){ >+ var suspend_status = modify_holds_form.find("#suspend_status").val(); >+ >+ if(suspend_status != "none"){ >+ var suspended_text = suspend_status == 0 ? _("Not suspended") : _("Suspended"); >+ searchpattern += _("with suspend status ") + suspended_text; >+ >+ return {"=": suspend_status}; >+ } >+ }, >+ "me.suspend_until": function(){ >+ var suspend_until_from = modify_holds_form.find("#suspend_until_from").val(); >+ var suspend_until_to = modify_holds_form.find("#suspend_until_to").val(); >+ >+ searchpattern += suspend_until_from && suspend_until_to ? _("suspend date between ")+ suspend_until_from +"-"+suspend_until_to : ""; >+ >+ return suspend_until_from && suspend_until_to ? {"-between": [suspend_until_from, suspend_until_to]} : ""; >+ }, >+ "me.notes": function(){ >+ var holdnotes = modify_holds_form.find("#holdnotes").val(); >+ >+ searchpattern += holdnotes ? _("hold notes like ") + holdnotes : ""; >+ >+ return holdnotes ? {"-like": "%"+holdnotes+"%"} : ""; >+ } >+ } >+ >+ var holds_modify_table = $("#holds_to_modify").kohaTable({ >+ "ajax": { >+ "url": "/api/v1/holds" >+ }, >+ "embed": [ >+ "biblio", >+ "item", >+ "pickup_library", >+ "patron" >+ ], >+ "destroy": true, >+ "autoWidth": false, >+ "processing": true, >+ "columns": [ >+ { >+ "data": "hold_id", >+ "name": "checkbox", >+ "orderable": false, >+ "render": function(data, type, row, meta) { >+ return '<input type="checkbox" name="hold_id" value="'+ encodeURIComponent(data) +'"/>' >+ } >+ }, >+ { >+ "data": "expiration_date", >+ "name": "expiration_date", >+ "type": "date", >+ "title": _("Expiration date"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return $date(data); >+ } >+ }, >+ { >+ "data": "biblio.title", >+ "name": "title", >+ "title": _("Title"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return '<a href="/cgi-bin/koha/catalogue/detail.pl?' + >+ 'biblionumber=' + encodeURIComponent( row.biblio_id ) + '">' + escape_str( data ) + '</a>'; >+ } >+ }, >+ { >+ "data": "item.external_id", >+ "name": "barcode", >+ "title": _("Barcode"), >+ "defaultContent": _(""), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ if( row.item ){ >+ let item_id = encodeURIComponent( row.item_id ); >+ let biblio_id = encodeURIComponent( row.biblio_id ); >+ return '<a href="/cgi-bin/koha/catalogue/moredetail.pl?' + >+ 'itemnumber='+ item_id +'&biblionumber='+ biblio_id +'&' + >+ 'bi='+ biblio_id +'#item'+ item_id +'">' + escape_str( data ) + '</a>' >+ } >+ } >+ }, >+ { >+ "data": "patron_id", >+ "name": "patron", >+ "title": _("Patron"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ let patron_to_html = $patron_to_html(row.patron, { url: true, display_cardnumber: true, hide_patron_name }); >+ return patron_to_html; >+ } >+ }, >+ { >+ "data": "status", >+ "name": "status", >+ "className": "found_status", >+ "title": _("Status"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ let status = _("No status"); >+ if ( data == "T" ) { >+ status = _("In transit"); >+ } else if( data == "P" ) { >+ status = _("In processing"); >+ } else if( data == "W" ) { >+ status = _("Waiting"); >+ } >+ return status; >+ } >+ }, >+ { >+ "data": "pickup_library_id", >+ "name": "pickup_library", >+ "title": _("Hold pickup library"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return escape_str( row.pickup_library.name ); >+ } >+ }, >+ { >+ "data": "suspended", >+ "name": "suspended", >+ "title": _("Suspended"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return data == 0 ? _("No") : _("Yes"); >+ } >+ }, >+ { >+ "data": "suspended_until", >+ "name": "suspended_until", >+ "title": _("Suspended until"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return $date( data ); >+ } >+ }, >+ { >+ "data": "notes", >+ "name": "notes", >+ "title": _("Notes"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return escape_str( data ); >+ } >+ } >+ ] >+ }, table_settings, 0, filters); >+ >+ $(".searchpattern").text(searchpattern); > >- $("#found_holds").dataTable($.extend(true, {}, dataTablesDefaults, { >- "aoColumnDefs": [ >- { "aTargets": [0], "bSortable": false, "bSearchable": false }, >- ], >- "sDom": 't', >- "aaSorting": [], >- "bPaginate": false >- })); >+ $("#modify_holds_results-wrapper").show(); >+ } > >- $("#process").on('submit', function(e) { >+ $("#process_mods").on('submit', function(e) { >+ >+ var hold_ids = []; > var errors = []; >- var reserve_ids = $("input[type=checkbox][name='hold_id']:checked"); >+ var holds_checked = $("input[type=checkbox][name='hold_id']:checked"); > >- var new_pickup_loc = $("#new_pickup_loc").val(); >- var new_suspend_status = $("#new_suspend_status").val(); >- var new_suspend_date = $("#new_suspend_date").val(); >+ var new_expiration_date = $("#new_expiration_date").val(); >+ var new_pickup_loc = $("#new_pickup_loc").val(); >+ var new_suspend_status = $("#new_suspend_status").val(); >+ var new_suspend_date = $("#new_suspend_date").val(); >+ var new_hold_note = $("#new_hold_note").val(); > >- if ( reserve_ids.length == 0 ) { >+ if ( holds_checked.length == 0 ) { > e.preventDefault(); > errors.push(_("Please select at least one hold to process.")); >- return false; > } >+ > if( new_pickup_loc || new_suspend_status ){ >- reserve_ids.each(function(){ >- if($(this).parents("tr").children(".found_status").data("found") != ""){ >+ var found = false; >+ holds_checked.each(function(){ >+ if($(this).parents("tr").children(".found_status").html() !== "No status"){ > e.preventDefault(); >- if( new_suspend_status ){ >- errors.push(_("One or more holds have found status and can't be suspended.")); >- } >- if( new_pickup_loc ){ >- errors.push(_("One or more holds have found status and their pick up location can't be changed.")); >- } >- return false; >+ found = true; > } >- }) >+ }); >+ if( new_suspend_status && found ){ >+ errors.push(_("One or more holds have found status and can't be suspended.")); >+ } >+ if( new_pickup_loc && found ){ >+ errors.push(_("One or more holds have found status and their pick up location can't be changed.")); >+ } > } >- if( ( !new_suspend_status || new_suspend_status == "not_suspended") && new_suspend_date ){ >+ if( ( !new_suspend_status || new_suspend_status == "0") && new_suspend_date ){ > e.preventDefault(); > errors.push(_("You have to suspend holds if new suspend until date is set.")); >- return false; > } > > if (errors.length > 0) { >@@ -324,6 +465,135 @@ > > return true; > }); >+ >+ //Modified holds table >+ var table_settings = [% TablesSettings.GetTableSettings( 'circ', 'holds', 'modified_holds', 'json' ) | $raw %]; >+ var filters = { >+ "me.hold_id": function(){ >+ return {"-in": hold_ids}; >+ } >+ } >+ >+ var holds_modified_table = $("#modified_holds").kohaTable({ >+ "ajax": { >+ "url": "/api/v1/holds" >+ }, >+ "embed": [ >+ "biblio", >+ "item", >+ "pickup_library", >+ "patron" >+ ], >+ "destroy": true, >+ "autoWidth": false, >+ "processing": true, >+ "columns": [ >+ { >+ "data": "expiration_date", >+ "name": "expiration_date", >+ "type": "date", >+ "title": _("Expiration date"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return $date(data); >+ } >+ }, >+ { >+ "data": "biblio.title", >+ "name": "title", >+ "title": _("Title"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return '<a href="/cgi-bin/koha/catalogue/detail.pl?' + >+ 'biblionumber=' + encodeURIComponent( row.biblio_id ) + '">' + escape_str( data ) + '</a>'; >+ } >+ }, >+ { >+ "data": "item.external_id", >+ "name": "barcode", >+ "title": _("Barcode"), >+ "defaultContent": _(""), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ if( row.item ){ >+ let item_id = encodeURIComponent( row.item_id ); >+ let biblio_id = encodeURIComponent( row.biblio_id ); >+ return '<a href="/cgi-bin/koha/catalogue/moredetail.pl?' + >+ 'itemnumber='+ item_id +'&biblionumber='+ biblio_id +'&' + >+ 'bi='+ biblio_id +'#item'+ item_id +'">' + escape_str( data ) + '</a>' >+ } >+ } >+ }, >+ { >+ "data": "patron_id", >+ "name": "patron", >+ "title": _("Patron"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ let patron_to_html = $patron_to_html(row.patron, { url: true, display_cardnumber: true, hide_patron_name }); >+ return patron_to_html; >+ } >+ }, >+ { >+ "data": "status", >+ "name": "status", >+ "className": "found_status", >+ "title": _("Status"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ let status = _("No status"); >+ if ( data == "T" ) { >+ status = _("In transit"); >+ } else if( data == "P" ) { >+ status = _("In processing"); >+ } else if( data == "W" ) { >+ status = _("Waiting"); >+ } >+ return status; >+ } >+ }, >+ { >+ "data": "pickup_library_id", >+ "name": "pickup_library", >+ "title": _("Hold pickup library"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return escape_str( row.pickup_library.name ); >+ } >+ }, >+ { >+ "data": "suspended", >+ "name": "suspended", >+ "title": _("Suspended"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return data == 0 ? _("No") : _("Yes"); >+ } >+ }, >+ { >+ "data": "suspended_until", >+ "name": "suspended_until", >+ "title": _("Suspended until"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return $date( data ); >+ } >+ }, >+ { >+ "data": "notes", >+ "name": "notes", >+ "title": _("Notes"), >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return escape_str( data ); >+ } >+ } >+ ] >+ }, table_settings, 0, filters); >+ >+ var modified_message = '<div class="alert alert-info">'+hold_ids.length+' hold(s) have been modified!</div>'; >+ $("#modified_holds_results-wrapper").prepend(modified_message); >+ > }); > </script> > [% END %] >diff --git a/tools/batch_modify_holds.pl b/tools/batch_modify_holds.pl >index 8d3f29a59a..3c057e5559 100755 >--- a/tools/batch_modify_holds.pl >+++ b/tools/batch_modify_holds.pl >@@ -19,10 +19,11 @@ > # <http://www.gnu.org/licenses> > > use Modern::Perl; >- > use CGI; > >-use C4::Auth qw( get_template_and_user ); >+use JSON qw( to_json ); >+ >+use C4::Auth qw( get_template_and_user ); > use C4::Output qw( output_html_with_http_headers ); > > use Koha::DateUtils qw( dt_from_string ); >@@ -44,98 +45,12 @@ my @hold_ids; > > if ( $op eq 'form' ) { > $template->param( view => 'form', ); >-} elsif ( $op eq 'list' ) { >- >- my @reserve_ids = $input->multi_param('reserve_ids'); >- my $expirationdate_from = $input->param('expirationdate_from'); >- my $expirationdate_to = $input->param('expirationdate_to'); >- my @branchcodes = $input->multi_param('branchcodes'); >- my @found_status = $input->multi_param('found_status'); >- my $suspend_status = $input->param('suspend_status'); >- my $suspend_until_from = $input->param('suspend_until_from'); >- my $suspend_until_to = $input->param('suspend_until_to'); >- my $reservenotes = $input->param('reservenotes'); >- >- my $search_params; >- >- if (@reserve_ids) { >- $search_params->{'me.reserve_id'} = { -in => \@reserve_ids }; >- } else { >- if ( $expirationdate_from && $expirationdate_to ) { >- my $expirationdate_params = { >- -or => { >- patron_expiration_date => { >- -between => [ >- $expirationdate_from, >- $expirationdate_to >- ] >- }, >- expirationdate => { >- -between => [ >- $expirationdate_from, >- $expirationdate_to >- ] >- } >- } >- }; >- >- $search_params = $expirationdate_params; >- } >- >- if (@branchcodes) { >- $search_params->{'me.branchcode'} = { -in => \@branchcodes }; >- } >- >- if (@found_status) { >- my $found_params = {}; >- >- # if NULL is used as filter, use it as "is" param >- if ( grep { $_ eq "NULL" } @found_status ) { >- $found_params->{'-or'}{'-is'} = undef; >- $found_params->{'-or'}{'-in'} = \@found_status; >- } else { >- $found_params = { -in => \@found_status }; >- } >- >- $search_params->{'me.found'} = $found_params; >- } >- >- if ( $suspend_status ne "none" ) { >- $search_params->{'me.suspend'} = $suspend_status; >- } >- >- if ( $suspend_until_from && $suspend_until_to ) { >- $search_params->{'me.suspend_until'} = { >- -between => [ >- $suspend_until_from, >- $suspend_until_to, >- ] >- }; >- } >- >- if ($reservenotes) { >- $search_params->{'me.reservenotes'} = { -like => "%" . $reservenotes . "%" }; >- } >- } >- >- my $holds = Koha::Holds->search( >- $search_params, >- { join => [ "item", "biblio" ] } >- ); >- >- $template->param( >- holds => $holds, >- view => 'list', >- ); >-} >- >-if ( $op eq 'cud-modify' ) { >- >+} elsif ( $op eq 'cud-modify' ) { > my $new_expiration_date = $input->param('new_expiration_date'); > my $new_pickup_loc = $input->param('new_pickup_loc'); > my $new_suspend_status = $input->param('new_suspend_status'); > my $new_suspend_date = $input->param('new_suspend_date'); >- my $new_reserve_note = $input->param('new_reserve_note'); >+ my $new_hold_note = $input->param('new_hold_note'); > > @hold_ids = $input->multi_param('hold_id'); > >@@ -153,7 +68,7 @@ if ( $op eq 'cud-modify' ) { > } > > if ( $new_suspend_status && !$hold->is_found ) { >- if ( $new_suspend_status eq "suspend" ) { >+ if ($new_suspend_status) { > $hold->suspend(1)->store; > if ($new_suspend_date) { > $hold->suspend_until($new_suspend_date)->store; >@@ -166,13 +81,13 @@ if ( $op eq 'cud-modify' ) { > } > } > >- if ($new_reserve_note) { >- $hold->reservenotes($new_reserve_note)->store; >+ if ($new_hold_note) { >+ $hold->reservenotes($new_hold_note)->store; > } > } > > $template->param( >- updated_holds => $holds_to_update, >+ updated_holds => to_json( \@hold_ids ), > view => 'report', > ); > >-- >2.34.1 >
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 36135
:
163021
|
163022
|
163023
|
163024
|
163529
|
163530
|
163540
|
163541
|
163542
|
163543
|
163544
|
163796
|
164037
|
164051
|
164057
|
164058
|
164059
|
164060
|
164061
|
164062
|
164063
|
177518
|
177519
|
177959
|
177960
|
177961
|
177962
|
177963
|
177964
|
177965
|
177966
|
177967
|
177968
|
177969
|
177975
|
177976
|
177981
|
177982
|
178154
|
178155
|
178156
|
178157
|
178158
|
178159
|
178160
|
178161
|
178162
|
178163
|
178164
| 178165 |
178166
|
178167