Bugzilla – Attachment 72496 Details for
Bug 20346
Patron filtering resulting in new search rather than filtering existing results
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 20346 - Server side patron filtering implemented
Bug-20346---Server-side-patron-filtering-implement.patch (text/plain), 16.16 KB, created by
Alex Buckley
on 2018-03-07 05:25:32 UTC
(
hide
)
Description:
Bug 20346 - Server side patron filtering implemented
Filename:
MIME Type:
Creator:
Alex Buckley
Created:
2018-03-07 05:25:32 UTC
Size:
16.16 KB
patch
obsolete
>From 939eb7748681014cc7bb28be97b653b456a0b6c5 Mon Sep 17 00:00:00 2001 >From: Alex Buckley <alexbuckley@catalyst.net.nz> >Date: Wed, 7 Mar 2018 04:51:08 +0000 >Subject: [PATCH] Bug 20346 - Server side patron filtering implemented > >Server side (in the svc/members/search file) perl logic for filtering >results returned from patron searches checks all patron data fields for >a match with the filter value. > >This filtering works in the following steps: when filtering is initiated >the original search using the original search query is run again and >then the filter value is used to filter the resulting data, thereby >using both the search and filter values to easily find a patron. > >The submitted filter value is automatically checked against >every patron value in every patron record returned from the search and >so there is no need for a specific data value to be >selected with the select dropdown box id=searchfieldstype_filter and so >that select dropdown has been removed due to this redundancy. > >This filter works for both filtering based on finding a match containing >the filter value and, filtering based on finding a match starting with >the filter value. > >Test plan: >1. Go to /members/members-home.pl and create 4 users. Make them all have >the same first and last name but vary the homebranch, email addresses >and dates of birth > >2. Perform a search by writing in the first and last name combination >shared by the 4 users and you should get 4 results > >3. Filter by writing in the email adrr > >Sponsored-By: Catalyst IT >--- > C4/Utils/DataTables/Members.pm | 80 ++++++++--------- > .../prog/en/modules/members/member.tt | 66 +++------------ > svc/members/search | 99 ++++++++++++++++------ > 3 files changed, 121 insertions(+), 124 deletions(-) > >diff --git a/C4/Utils/DataTables/Members.pm b/C4/Utils/DataTables/Members.pm >index 8912146..395d661 100644 >--- a/C4/Utils/DataTables/Members.pm >+++ b/C4/Utils/DataTables/Members.pm >@@ -9,12 +9,14 @@ use C4::Members::Attributes qw(SearchIdMatchingAttribute ); > sub search { > my ( $params ) = @_; > my $searchmember = $params->{searchmember}; >+ my $firstquery = $params->{firstquery}; > my $firstletter = $params->{firstletter}; > my $categorycode = $params->{categorycode}; > my $branchcode = $params->{branchcode}; > my $searchtype = $params->{searchtype} || 'contain'; > my $searchfieldstype = $params->{searchfieldstype} || 'standard'; > my $dt_params = $params->{dt_params}; >+ my $searchfiltering = $params->{search_filter}; > > unless ( $searchmember ) { > $searchmember = $dt_params->{sSearch} // ''; >@@ -55,46 +57,44 @@ sub search { > }; > } > } >- >- my $select = "SELECT >- borrowers.borrowernumber, borrowers.surname, borrowers.firstname, >- borrowers.streetnumber, borrowers.streettype, borrowers.address, >- borrowers.address2, borrowers.city, borrowers.state, borrowers.zipcode, >- borrowers.country, cardnumber, borrowers.dateexpiry, >- borrowers.borrowernotes, borrowers.branchcode, borrowers.email, >- borrowers.userid, borrowers.dateofbirth, borrowers.categorycode, >- categories.description AS category_description, categories.category_type, >- branches.branchname"; >- my $from = "FROM borrowers >- LEFT JOIN branches ON borrowers.branchcode = branches.branchcode >- LEFT JOIN categories ON borrowers.categorycode = categories.categorycode"; >- my @where_args; >- my @where_strs; >- if(defined $firstletter and $firstletter ne '') { >- push @where_strs, "borrowers.surname LIKE ?"; >- push @where_args, "$firstletter%"; >- } >- if(defined $categorycode and $categorycode ne '') { >- push @where_strs, "borrowers.categorycode = ?"; >- push @where_args, $categorycode; >- } >- if(@restricted_branchcodes ) { >- push @where_strs, "borrowers.branchcode IN (" . join( ',', ('?') x @restricted_branchcodes ) . ")"; >- push @where_args, @restricted_branchcodes; >- } >- >- my $searchfields = { >- standard => C4::Context->preference('DefaultPatronSearchFields') || 'surname,firstname,othernames,cardnumber,userid', >- surname => 'surname', >- email => 'email,emailpro,B_email', >- borrowernumber => 'borrowernumber', >- userid => 'userid', >- phone => 'phone,phonepro,B_phone,altcontactphone,mobile', >- address => 'streettype,address,address2,city,state,zipcode,country', >- dateofbirth => 'dateofbirth', >- sort1 => 'sort1', >- sort2 => 'sort2', >- }; >+ my $select = "SELECT >+ borrowers.borrowernumber, borrowers.surname, borrowers.firstname, >+ borrowers.streetnumber, borrowers.streettype, borrowers.address, >+ borrowers.address2, borrowers.city, borrowers.state, borrowers.zipcode, >+ borrowers.country, cardnumber, borrowers.dateexpiry, >+ borrowers.borrowernotes, borrowers.branchcode, borrowers.email, >+ borrowers.userid, borrowers.dateofbirth, borrowers.categorycode, >+ categories.description AS category_description, categories.category_type, >+ branches.branchname"; >+ my $from = "FROM borrowers >+ LEFT JOIN branches ON borrowers.branchcode = branches.branchcode >+ LEFT JOIN categories ON borrowers.categorycode = categories.categorycode"; >+ my @where_args; >+ my @where_strs; >+ if(defined $firstletter and $firstletter ne '') { >+ push @where_strs, "borrowers.surname LIKE ?"; >+ push @where_args, "$firstletter%"; >+ } >+ if(defined $categorycode and $categorycode ne '') { >+ push @where_strs, "borrowers.categorycode = ?"; >+ push @where_args, $categorycode; >+ } >+ if(@restricted_branchcodes ) { >+ push @where_strs, "borrowers.branchcode IN (" . join( ',', ('?') x @restricted_branchcodes ) . ")"; >+ push @where_args, @restricted_branchcodes; >+ } >+ my $searchfields = { >+ standard => C4::Context->preference('DefaultPatronSearchFields') || 'surname,firstname,othernames,cardnumber,userid', >+ surname => 'surname', >+ email => 'email,emailpro,B_email', >+ borrowernumber => 'borrowernumber', >+ userid => 'userid', >+ phone => 'phone,phonepro,B_phone,altcontactphone,mobile', >+ address => 'streettype,address,address2,city,state,zipcode,country', >+ dateofbirth => 'dateofbirth', >+ sort1 => 'sort1', >+ sort2 => 'sort2', >+ }; > > # * is replaced with % for sql > $searchmember =~ s/\*/%/g; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/member.tt >index b40bb03..dbc5e8b 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/member.tt >@@ -111,67 +111,13 @@ > <input type="hidden" id="firstletter_filter" value="" /> > <fieldset class="brief"> > <h3>Filters</h3> >+ <p> Filter results by entering any value and all data values in the patron record(s) will be checked </p> > <ol> > <li> > <label for="searchmember_filter">Search:</label> > <input type="text" id="searchmember_filter" value="[% searchmember %]"/> > </li> > <li> >- <label for="searchfieldstype_filter">Search fields:</label> >- <select name="searchfieldstype" id="searchfieldstype_filter"> >- [% IF searchfieldstype == "standard" %] >- <option selected="selected" value='standard'>Standard</option> >- [% ELSE %] >- <option value='standard'>Standard</option> >- [% END %] >- [% IF searchfieldstype == "surname" %] >- <option selected="selected" value='surname'>Surname</option> >- [% ELSE %] >- <option value='surname'>Surname</option> >- [% END %] >- [% IF searchfieldstype == "email" %] >- <option selected="selected" value='email'>Email</option> >- [% ELSE %] >- <option value='email'>Email</option> >- [% END %] >- [% IF searchfieldstype == "borrowernumber" %] >- <option selected="selected" value='borrowernumber'>Borrower number</option> >- [% ELSE %] >- <option value='borrowernumber'>Borrower number</option> >- [% END %] >- [% IF searchfieldstype == "userid" %] >- <option selected="selected" value='userid'>Username</option> >- [% ELSE %] >- <option value='userid'>Username</option> >- [% END %] >- [% IF searchfieldstype == "phone" %] >- <option selected="selected" value='phone'>Phone number</option> >- [% ELSE %] >- <option value='phone'>Phone number</option> >- [% END %] >- [% IF searchfieldstype == "address" %] >- <option selected="selected" value='address'>Street address</option> >- [% ELSE %] >- <option value='address'>Street address</option> >- [% END %] >- [% IF searchfieldstype == "dateofbirth" %] >- <option selected="selected" value='dateofbirth'>Date of birth</option> >- [% ELSE %] >- <option value='dateofbirth'>Date of birth</option> >- [% END %] >- [% IF searchfieldstype == "sort1" %] >- <option selected="selected" value='sort1'>Sort field 1</option> >- [% ELSE %] >- <option value='sort1'>Sort field 1</option> >- [% END %] >- [% IF searchfieldstype == "sort2" %] >- <option selected="selected" value='sort2'>Sort field 2</option> >- [% ELSE %] >- <option value='sort2'>Sort field 2</option> >- [% END %] >- </select> >- </li> >- <li> > <label for="searchtype_filter">Search type:</label> > <select name="searchtype" id="searchtype_filter"> > [% IF searchtype == "start_with" %] >@@ -324,12 +270,17 @@ > e.preventDefault(); > clearFilters(true); > }); >- $("#searchform").on("submit", filter); >+ $("#searchform").on("submit", function(e) { >+ e.preventDefault(); >+ search = 1; >+ dtMemberResults.fnDraw(); >+ }); > }); > > var dtMemberResults; > var search = 1; > $(document).ready(function() { >+ var first_query = document.getElementById("searchmember").value; > [% IF searchmember %] > $("#searchmember_filter").val("[% searchmember | html %]"); > [% END %] >@@ -390,6 +341,9 @@ > return; > } > aoData.push({ >+ 'name': 'first_query', >+ 'value': $("#searchmember").val() >+ },{ > 'name': 'searchmember', > 'value': $("#searchmember_filter").val() > },{ >diff --git a/svc/members/search b/svc/members/search >index 86c7473..533e929 100755 >--- a/svc/members/search >+++ b/svc/members/search >@@ -26,6 +26,7 @@ use C4::Utils::DataTables qw( dt_get_params ); > use C4::Utils::DataTables::Members qw( search ); > use Koha::DateUtils qw( output_pref dt_from_string ); > use Koha::Patrons; >+use Data::Dumper; > > my $input = new CGI; > >@@ -39,6 +40,7 @@ my ($template, $user, $cookie) = get_template_and_user({ > flagsrequired => { borrowers => 'edit_borrowers' } > }); > >+my $first_query = $input->param('first_query'); > my $searchmember = $input->param('searchmember'); > my $firstletter = $input->param('firstletter'); > my $categorycode = $input->param('categorycode'); >@@ -56,6 +58,9 @@ foreach (grep {$_ =~ /^mDataProp/} keys %dt_params) { > $dt_params{$_} =~ s/^dt_//; > } > >+warn $searchfieldstype; >+warn $searchtype; >+ > my $results; > # If the user filled a term, maybe it's a cardnumber. > # This cannot be the case if a first letter is given. >@@ -72,42 +77,80 @@ if ( $searchmember > } if $member; > } > >+warn $first_query; >+warn $searchmember; >+warn $searchfieldstype; >+warn $searchtype; >+ > # Perform the patrons search > $results = C4::Utils::DataTables::Members::search( >- { >- searchmember => $searchmember, >- firstletter => $firstletter, >- categorycode => $categorycode, >- branchcode => $branchcode, >- searchtype => $searchtype, >- searchfieldstype => $searchfieldstype, >- dt_params => \%dt_params, >- } >+ { >+ searchmember => $first_query, >+ firstletter => $firstletter, >+ categorycode => $categorycode, >+ branchcode => $branchcode, >+ searchtype => $searchtype, >+ searchfieldstype => $searchfieldstype, >+ dt_params => \%dt_params, >+ } > ) unless $results; > >-# It is not recommanded to use the has_permission param if you use the pagination >-# The filter is done AFTER requested the data >-if ($has_permission) { >- my ( $permission, $subpermission ) = split /\./, $has_permission; >- my @patrons_with_permission; >- for my $patron ( @{ $results->{patrons} } ) { >- my $perms = haspermission( $patron->{userid} ); >- if ( $perms->{superlibrarian} == 1 >- or $perms->{$permission} == 1 ) >- { >- push @patrons_with_permission, $patron; >- next; >+ # It is not recommanded to use the has_permission param if you use the pagination >+ # The filter is done AFTER requested the data >+ if ($has_permission) { >+ my ( $permission, $subpermission ) = split /\./, $has_permission; >+ my @patrons_with_permission; >+ for my $patron ( @{ $results->{patrons} } ) { >+ my $perms = haspermission( $patron->{userid} ); >+ if ( $perms->{superlibrarian} == 1 >+ or $perms->{$permission} == 1 ) >+ { >+ push @patrons_with_permission, $patron; >+ next; >+ } >+ >+ if ($subpermission) { >+ my $subperms = get_user_subpermissions( $patron->{userid} ); >+ push @patrons_with_permission, $patron >+ if $subperms->{$permission}->{$subpermission}; >+ } > } >+ $results->{patrons} = \@patrons_with_permission; >+ $results->{iTotalDisplayRecords} = scalar( @patrons_with_permission ); >+ } > >- if ($subpermission) { >- my $subperms = get_user_subpermissions( $patron->{userid} ); >- push @patrons_with_permission, $patron >- if $subperms->{$permission}->{$subpermission}; >+ if ($searchmember) { >+ my @filtered_patron_list; >+ my $count; >+ for my $patron ( @{ $results->{patrons} } ) { >+ my $match; >+ for my $value (values $patron) { >+ my $lc_patron_value = lc $value; >+ my $lc_searchmember = lc $searchmember; >+ warn $lc_patron_value; >+ warn $lc_searchmember; >+ if ($searchtype eq "start_with") { >+ #Find a match starting with the start of a value in the patron record >+ warn "hello"; >+ if (index($lc_patron_value, $lc_searchmember) == 0) { >+ warn $lc_patron_value; >+ warn $lc_searchmember; >+ $match = 1; >+ } >+ } else { >+ if (($lc_patron_value) =~ /($lc_searchmember)/) { >+ $match = 1; >+ } >+ } >+ } >+ if ($match) { >+ push @filtered_patron_list, $patron; >+ next; >+ } > } >+ $results->{patrons} = \@filtered_patron_list; >+ $results->{iTotalDisplayRecords} = scalar( @filtered_patron_list ); > } >- $results->{patrons} = \@patrons_with_permission; >- $results->{iTotalDisplayRecords} = scalar( @patrons_with_permission ); >-} > > $template->param( > sEcho => $sEcho, >-- >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 20346
:
72496
|
72520
|
72523
|
72623
|
72624
|
72815
|
73520