Bug 14782: Add possibility to search patrons using the username (userid)
[koha.git] / C4 / Utils / DataTables / Members.pm
1 package C4::Utils::DataTables::Members;
2
3 use C4::Branch qw/onlymine/;
4 use C4::Context;
5 use C4::Members qw/GetMemberIssuesAndFines/;
6 use C4::Utils::DataTables;
7 use Modern::Perl;
8
9 sub search {
10     my ( $params ) = @_;
11     my $searchmember = $params->{searchmember};
12     my $firstletter = $params->{firstletter};
13     my $categorycode = $params->{categorycode};
14     my $branchcode = $params->{branchcode};
15     my $searchtype = $params->{searchtype};
16     my $searchfieldstype = $params->{searchfieldstype} || 'standard';
17     my $dt_params = $params->{dt_params};
18
19     unless ( $searchmember ) {
20         $searchmember = $dt_params->{sSearch} // '';
21     }
22
23     my ($iTotalRecords, $iTotalDisplayRecords);
24
25     # If branches are independent and user is not superlibrarian
26     # The search has to be only on the user branch
27     if ( C4::Branch::onlymine ) {
28         my $userenv = C4::Context->userenv;
29         $branchcode = $userenv->{'branch'};
30
31     }
32
33     my $dbh = C4::Context->dbh;
34     my $select = "SELECT
35         borrowers.borrowernumber, borrowers.surname, borrowers.firstname,
36         borrowers.streetnumber, borrowers.streettype, borrowers.address,
37         borrowers.address2, borrowers.city, borrowers.state, borrowers.zipcode,
38         borrowers.country, cardnumber, borrowers.dateexpiry,
39         borrowers.borrowernotes, borrowers.branchcode, borrowers.email,
40         borrowers.userid, borrowers.dateofbirth, borrowers.categorycode,
41         categories.description AS category_description, categories.category_type,
42         branches.branchname";
43     my $from = "FROM borrowers
44         LEFT JOIN branches ON borrowers.branchcode = branches.branchcode
45         LEFT JOIN categories ON borrowers.categorycode = categories.categorycode";
46     my @where_args;
47     my @where_strs;
48     if(defined $firstletter and $firstletter ne '') {
49         push @where_strs, "borrowers.surname LIKE ?";
50         push @where_args, "$firstletter%";
51     }
52     if(defined $categorycode and $categorycode ne '') {
53         push @where_strs, "borrowers.categorycode = ?";
54         push @where_args, $categorycode;
55     }
56     if(defined $branchcode and $branchcode ne '') {
57         push @where_strs, "borrowers.branchcode = ?";
58         push @where_args, $branchcode;
59     }
60
61     # split on coma
62     $searchmember =~ s/,/ /g if $searchmember;
63     my $searchfields = {
64         standard => 'surname,firstname,othernames,cardnumber,userid',
65         email => 'email,emailpro,B_email',
66         borrowernumber => 'borrowernumber',
67         userid => 'userid',
68         phone => 'phone,phonepro,B_phone,altcontactphone,mobile',
69         address => 'streettype,address,address2,city,state,zipcode,country',
70         dateofbirth => 'dateofbirth',
71         sort1 => 'sort1',
72         sort2 => 'sort2',
73     };
74     foreach my $term ( split / /, $searchmember) {
75         next unless $term;
76         $searchmember =~ s/\*/%/g; # * is replaced with % for sql
77         $term .= '%' # end with anything
78             if $term !~ /%$/;
79         $term = "%$term" # begin with anythin unless start_with
80             if (defined $searchtype) && $searchtype eq "contain"
81                 && $term !~ /^%/;
82         my @where_strs_or;
83         for my $searchfield ( split /,/, $searchfields->{$searchfieldstype} ) {
84             push @where_strs_or, "borrowers." . $dbh->quote_identifier($searchfield) . " LIKE ?";
85             push @where_args, $term;
86         }
87
88         if ( C4::Context->preference('ExtendedPatronAttributes') and $searchmember ) {
89             my $matching_borrowernumbers = C4::Members::Attributes::SearchIdMatchingAttribute($searchmember);
90
91             for my $borrowernumber ( @$matching_borrowernumbers ) {
92                 push @where_strs_or, "borrowers.borrowernumber = ?";
93                 push @where_args, $borrowernumber;
94             }
95         }
96
97         push @where_strs, '('. join (' OR ', @where_strs_or) . ')'
98             if @where_strs_or;
99     }
100
101     my $where;
102     $where = " WHERE " . join (" AND ", @where_strs) if @where_strs;
103     my $orderby = dt_build_orderby($dt_params);
104
105     my $limit;
106     # If iDisplayLength == -1, we want to display all patrons
107     if ( !$dt_params->{iDisplayLength} || $dt_params->{iDisplayLength} > -1 ) {
108         # In order to avoid sql injection
109         $dt_params->{iDisplayStart} =~ s/\D//g if defined($dt_params->{iDisplayStart});
110         $dt_params->{iDisplayLength} =~ s/\D//g if defined($dt_params->{iDisplayLength});
111         $dt_params->{iDisplayStart} //= 0;
112         $dt_params->{iDisplayLength} //= 20;
113         $limit = "LIMIT $dt_params->{iDisplayStart},$dt_params->{iDisplayLength}";
114     }
115
116     my $query = join(
117         " ",
118         ($select ? $select : ""),
119         ($from ? $from : ""),
120         ($where ? $where : ""),
121         ($orderby ? $orderby : ""),
122         ($limit ? $limit : "")
123     );
124     my $sth = $dbh->prepare($query);
125     $sth->execute(@where_args);
126     my $patrons = $sth->fetchall_arrayref({});
127
128     # Get the iTotalDisplayRecords DataTable variable
129     $query = "SELECT COUNT(borrowers.borrowernumber) " . $from . ($where ? $where : "");
130     $sth = $dbh->prepare($query);
131     $sth->execute(@where_args);
132     ($iTotalDisplayRecords) = $sth->fetchrow_array;
133
134     # Get the iTotalRecords DataTable variable
135     $query = "SELECT COUNT(borrowers.borrowernumber) FROM borrowers";
136     $sth = $dbh->prepare($query);
137     $sth->execute;
138     ($iTotalRecords) = $sth->fetchrow_array;
139
140     # Get some information on patrons
141     foreach my $patron (@$patrons) {
142         ($patron->{overdues}, $patron->{issues}, $patron->{fines}) =
143             GetMemberIssuesAndFines($patron->{borrowernumber});
144         if($patron->{dateexpiry} and $patron->{dateexpiry} ne '0000-00-00') {
145             $patron->{dateexpiry} = C4::Dates->new($patron->{dateexpiry}, "iso")->output();
146         } else {
147             $patron->{dateexpiry} = '';
148         }
149         $patron->{fines} = sprintf("%.2f", $patron->{fines} || 0);
150     }
151
152     return {
153         iTotalRecords => $iTotalRecords,
154         iTotalDisplayRecords => $iTotalDisplayRecords,
155         patrons => $patrons
156     }
157 }
158
159 1;
160 __END__
161
162 =head1 NAME
163
164 C4::Utils::DataTables::Members - module for using DataTables with patrons
165
166 =head1 SYNOPSIS
167
168 This module provides (one for the moment) routines used by the patrons search
169
170 =head2 FUNCTIONS
171
172 =head3 search
173
174     my $dt_infos = C4::Utils::DataTables::Members->search($params);
175
176 $params is a hashref with some keys:
177
178 =over 4
179
180 =item searchmember
181
182   String to search in the borrowers sql table
183
184 =item firstletter
185
186   Introduced to contain 1 letter but can contain more.
187   The search will done on the borrowers.surname field
188
189 =item categorycode
190
191   Search patrons with this categorycode
192
193 =item branchcode
194
195   Search patrons with this branchcode
196
197 =item searchtype
198
199   Can be 'contain' or 'start_with'. Used for the searchmember parameter.
200
201 =item searchfieldstype
202
203   Can be 'standard', 'email', 'borrowernumber', 'phone', 'address' or 'dateofbirth', 'sort1', 'sort2'
204
205 =item dt_params
206
207   Is the reference of C4::Utils::DataTables::dt_get_params($input);
208
209 =cut
210
211 =back
212
213 =head1 LICENSE
214
215 This file is part of Koha.
216
217 Copyright 2013 BibLibre
218
219 Koha is free software; you can redistribute it and/or modify it
220 under the terms of the GNU General Public License as published by
221 the Free Software Foundation; either version 3 of the License, or
222 (at your option) any later version.
223
224 Koha is distributed in the hope that it will be useful, but
225 WITHOUT ANY WARRANTY; without even the implied warranty of
226 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
227 GNU General Public License for more details.
228
229 You should have received a copy of the GNU General Public License
230 along with Koha; if not, see <http://www.gnu.org/licenses>.