From 5aebd71ebb7e8d32104b7115fb7dc8c8e0c1b754 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Wed, 2 Feb 2022 18:00:58 +0100 Subject: [PATCH] Bug 30055: Make patron searches use the REST API This patch will rewrite some of our patron searches to make them use the REST API routes (and so the powerful the DataTables wrapper which will bring all the nice DT feature to filter, sort, etc.) The patron searches we will take into account here are those that we use to select a patron in a pop-up: * Guarantor * Suggestion's manager * Patron's card * Serial routing list * Users to notify when order is received * Manager of an acquisition basket * Owner and users of a fund Regarding permissions there are two main problematics: * Filter a patron set by patrons having a specific subpermissions (in case of adding a manager to a suggestion or when we deal with acquisition and funds). We added a new Koha::Patrons->filter_by_have_subpermission method that will take in parameter a subpermission. To make thing transparent for the callers we are adding new routes, like /suggestions/managers to list the possible managers of suggestions. * Restrict/allow access to the default patron searches /patrons We need to access it when a logged in patron does not have borrowers permission. Ideally we need a separate "search_borrowers" subpermissions but it's considered outside the scope of this change. For each patch you will take care of testing the different permissions that are into effect (either for the logged in patron or the patrons returned by the search). The tables should contain the same columns as prior to this patch, except for "categories" and "library". We have the filter on top of the page and so we need to add them to the table as new columns if they weren't there before. Test plan (for this patch): Search for guarantor and select Test plan (for all patches): Add/Select patrons from the correct place where you can search for patrons, play extensively with the filters/pagination/etc Signed-off-by: Jonathan Druart Signed-off-by: Tomas Cohen Arazi --- .../prog/en/includes/js-patron-format.inc | 2 +- .../prog/en/modules/common/patron_search.tt | 312 --------------- .../prog/en/modules/members/search.tt | 368 ++++++++++++++++++ .../members/tables/guarantor_search.tt | 36 -- koha-tmpl/intranet-tmpl/prog/js/datatables.js | 63 ++- koha-tmpl/intranet-tmpl/prog/js/members.js | 8 +- members/{guarantor_search.pl => search.pl} | 22 +- 7 files changed, 433 insertions(+), 378 deletions(-) delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/common/patron_search.tt create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/search.tt delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/tables/guarantor_search.tt rename members/{guarantor_search.pl => search.pl} (69%) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/js-patron-format.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/js-patron-format.inc index 4dd4798564..0c1daae17f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/js-patron-format.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/js-patron-format.inc @@ -26,7 +26,7 @@ firstname += ' (' + escape_str(patron.other_name) + ')'; } if ( config && config.invert_name ) { - name = surname + ', ' + firstname; + name = surname + ( firstname ? ', ' + firstname : '' ); } else { name = firstname + ' ' + surname; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/common/patron_search.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/common/patron_search.tt deleted file mode 100644 index 9009d7a187..0000000000 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/common/patron_search.tt +++ /dev/null @@ -1,312 +0,0 @@ -[% USE raw %] -[% USE Asset %] -[% USE Koha %] -[% USE Branches %] -[% SET footerjs = 1 %] -[% INCLUDE 'doc-head-open.inc' %] -Patron search › Koha -[% INCLUDE 'doc-head-close.inc' %] - - - - - - -[% MACRO jsinclude BLOCK %] - [% INCLUDE 'datatables.inc' %] - - -[% END %] - -[% SET popup_window = 1 %] -[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/search.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/search.tt new file mode 100644 index 0000000000..0bcc2cfd1d --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/search.tt @@ -0,0 +1,368 @@ +[% USE raw %] +[% USE To %] +[% USE Asset %] +[% USE Koha %] +[% USE Branches %] +[% USE Categories %] +[% SET footerjs = 1 %] +[% INCLUDE 'doc-head-open.inc' %] +[% SET libraries = Branches.all %] +[% SET categories = Categories.all.unblessed %] +Patron search › Koha +[% INCLUDE 'doc-head-close.inc' %] + + + + + + +[% MACRO jsinclude BLOCK %] + + [% INCLUDE 'datatables.inc' %] + [% INCLUDE 'js-date-format.inc' %] + [% INCLUDE 'js-patron-get-age.inc' %] + [% INCLUDE 'js-patron-format.inc' %] + [% INCLUDE 'js-patron-format-address.inc' %] + + +[% END %] + +[% SET popup_window = 1 %] +[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/tables/guarantor_search.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/tables/guarantor_search.tt deleted file mode 100644 index fd55506c11..0000000000 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/tables/guarantor_search.tt +++ /dev/null @@ -1,36 +0,0 @@ -[% USE raw %] -[% USE To %] -[% USE Branches %] -[% USE KohaDates %] -{ - "sEcho": [% sEcho | html %], - "iTotalRecords": [% iTotalRecords | html %], - "iTotalDisplayRecords": [% iTotalDisplayRecords | html %], - "aaData": [ - [% FOREACH data IN aaData %] - { - "dt_cardnumber": - "[% data.cardnumber | html %]", - "dt_name": - "[% INCLUDE 'patron-title.inc' borrowernumber = data.borrowernumber category_type = data.category_type firstname = data.firstname surname = data.surname othernames = data.othernames cardnumber = data.cardnumber invert_name = 1%]", - "dt_dateofbirth": - "[% INCLUDE 'patron-age.inc' patron = data %]", - "dt_address": - "[% INCLUDE escape_address data=data %]", - "dt_action": - "Select" - }[% UNLESS loop.last %],[% END %] - [% END %] - ] -} -[% BLOCK escape_address %] -[%~ SET address = data.streetnumber _ ' ' %] -[%~ IF data.address %][% SET address = address _ data.address _ ' ' %][% END %] -[%~ IF data.address2 %][% SET address = address _ data.address2 _ ' ' %][% END %] -[%~ IF data.city %][% SET address = address _ data.city _ ' ' %][% END %] -[%~ IF data.state %][% SET address = address _ data.state _ ' ' %][% END %] -[%~ IF data.zipcode %][% SET address = address _ data.zipcode _ ' ' %][% END %] -[%~ IF data.country %][% SET address = address _ data.country _ ' ' %][% END %] -[%~ SET address = address _ Branches.GetName( data.branchcode ) %] -[%~ address | html | $To ~%] -[% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/js/datatables.js b/koha-tmpl/intranet-tmpl/prog/js/datatables.js index 2d88fcdd05..c41866745e 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/datatables.js +++ b/koha-tmpl/intranet-tmpl/prog/js/datatables.js @@ -599,7 +599,20 @@ jQuery.fn.dataTable.ext.errMode = function(settings, note, message) { }); if ( default_filters ) { - and_query_parameters.push(default_filters); + let additional_filters = {}; + for ( f in default_filters ) { + if ( typeof(default_filters[f]) === 'function' ) { + let val = default_filters[f](); + if ( val != undefined && val != "" ) { + additional_filters[f] = val; + } + } else { + additional_filters[f] = default_filters[f]; + } + } + if ( Object.keys(additional_filters).length ) { + and_query_parameters.push(additional_filters); + } } query_parameters = and_query_parameters; if ( or_query_parameters.length) { @@ -775,16 +788,50 @@ jQuery.fn.dataTable.ext.errMode = function(settings, note, message) { $(this).find('thead tr:eq(1) th').each( function (i) { var is_searchable = table_dt.settings()[0].aoColumns[i].bSearchable; if ( is_searchable ) { - var title = $(this).text(); - var existing_search = table_dt.column(i).search(); - if ( existing_search ) { - $(this).html( ''.format(existing_search) ); + let input_type = 'input'; + if ( $(this).data('filter') ) { + input_type = 'select' + let filter_type = $(this).data('filter'); + if ( filter_type == 'libraries' ) { + var existing_search = table_dt.column(i).search(); + let select = $('%s'.format(this.categorycode, this.description)); + if ( existing_search == this.categorycode ) { + o.prop("selected", "selected"); + } + o.appendTo(select); + }); + $(this).html( select ); + } else { + console.log("Unknown filter " + filter_type); + return; + } } else { - var search_title = _("%s search").format(title); - $(this).html( ''.format(search_title) ); + var title = $(this).text(); + var existing_search = table_dt.column(i).search(); + if ( existing_search ) { + $(this).html( ''.format(existing_search) ); + } else { + var search_title = _("%s search").format(title); + $(this).html( ''.format(search_title) ); + } } - $( 'input', this ).on( 'keyup change', function () { + $( input_type, this ).on( 'keyup change', function () { if ( table_dt.column(i).search() !== this.value ) { table_dt .column(i) diff --git a/koha-tmpl/intranet-tmpl/prog/js/members.js b/koha-tmpl/intranet-tmpl/prog/js/members.js index a9e6a870ae..5559ac0363 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/members.js +++ b/koha-tmpl/intranet-tmpl/prog/js/members.js @@ -77,12 +77,12 @@ function update_category_code(category_code) { } function select_user(borrowernumber, borrower, relationship) { - let is_guarantor = $(`.guarantor-details[data-borrowernumber=${borrower.borrowernumber}]`).length; + let is_guarantor = $(`.guarantor-details[data-borrowernumber=${borrowernumber}]`).length; if ( is_guarantor ) { alert("Patron is already a guarantor for this patron"); } else { - $('#guarantor_id').val(borrower.borrowernumber); + $('#guarantor_id').val(borrowernumber); $('#guarantor_surname').val(borrower.surname); $('#guarantor_firstname').val(borrower.firstname); @@ -113,7 +113,7 @@ function select_user(borrowernumber, borrower, relationship) { fieldset.find('.new_guarantor_relationship').first().val( guarantor_relationship ); $('#relationship').find('option:eq(0)').prop('selected', true); - fieldset.find('.guarantor-details').first().attr( 'data-borrowernumber', borrower.borrowernumber ); + fieldset.find('.guarantor-details').first().attr( 'data-borrowernumber', borrowernumber ); $('#guarantor_relationships').append( fieldset ); fieldset.show(); @@ -197,7 +197,7 @@ $(document).ready(function(){ $('body').on('click', '#guarantor_search', function(e) { e.preventDefault(); - var newin = window.open('guarantor_search.pl','popup','width=800,height=600,resizable=no,toolbar=false,scrollbars=yes,top'); + var newin = window.open('/cgi-bin/koha/members/search.pl?columns=cardnumber,name,category,branch,dateofbirth,address,action','popup','width=800,height=600,resizable=no,toolbar=false,scrollbars=yes,top'); }); $('#guarantor_relationships').on('click', '.guarantor_cancel', function(e) { diff --git a/members/guarantor_search.pl b/members/search.pl similarity index 69% rename from members/guarantor_search.pl rename to members/search.pl index 40142eb913..630f509177 100755 --- a/members/guarantor_search.pl +++ b/members/search.pl @@ -2,8 +2,6 @@ # This file is part of Koha. # -# Copyright 2014 BibLibre -# # Koha is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or @@ -22,35 +20,25 @@ use Modern::Perl; use CGI qw ( -utf8 ); use C4::Auth qw( get_template_and_user ); use C4::Output qw( output_html_with_http_headers ); -use C4::Members; - -use Koha::Patron::Categories; my $input = CGI->new; -my $dbh = C4::Context->dbh; - my ( $template, $loggedinuser, $cookie, $staff_flags ) = get_template_and_user( - { template_name => "common/patron_search.tt", + { template_name => "members/search.tt", query => $input, type => "intranet", - flagsrequired => { borrowers => 'edit_borrowers' }, + flagsrequired => { catalogue => '*' }, } ); -my $q = $input->param('q') || ''; -my $op = $input->param('op') || ''; - my $referer = $input->referer(); -my $patron_categories = Koha::Patron::Categories->search_with_library_limits; +my @columns = split ',', $input->param('columns'); + $template->param( view => ( $input->request_method() eq "GET" ) ? "show_form" : "show_results", - columns => ['cardnumber', 'name', 'dateofbirth', 'address', 'action' ], - json_template => 'members/tables/guarantor_search.tt', + columns => \@columns, selection_type => 'select', alphabet => ( C4::Context->preference('alphabet') || join ' ', 'A' .. 'Z' ), - categories => $patron_categories, - aaSorting => 1, ); output_html_with_http_headers( $input, $cookie, $template->output ); -- 2.35.1