1 package C4
::Utils
::DataTables
::Members
;
5 use C4
::Utils
::DataTables
;
7 use C4
::Members
::Attributes
qw(SearchIdMatchingAttribute );
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
} || 'contain';
16 my $searchfieldstype = $params->{searchfieldstype
} || 'standard';
17 my $dt_params = $params->{dt_params
};
19 unless ( $searchmember ) {
20 $searchmember = $dt_params->{sSearch
} // '';
23 # If branches are independent and user is not superlibrarian
24 # The search has to be only on the user branch
25 my $userenv = C4
::Context
->userenv;
26 my $logged_in_user = Koha
::Patrons
->find( $userenv->{number
} );
27 my @restricted_branchcodes = $logged_in_user->libraries_where_can_see_patrons;
29 my ($sth, $query, $iTotalQuery, $iTotalRecords, $iTotalDisplayRecords);
30 my $dbh = C4
::Context
->dbh;
31 # Get the iTotalRecords DataTable variable
32 $query = $iTotalQuery = "SELECT COUNT(borrowers.borrowernumber) FROM borrowers";
33 if ( @restricted_branchcodes ) {
34 $iTotalQuery .= " WHERE borrowers.branchcode IN (" . join( ',', ('?') x
@restricted_branchcodes ) . ")";
36 ($iTotalRecords) = $dbh->selectrow_array( $iTotalQuery, undef, @restricted_branchcodes );
38 # Do that after iTotalQuery!
39 if ( defined $branchcode and $branchcode ) {
40 @restricted_branchcodes = @restricted_branchcodes
41 ?
grep { /^$branchcode$/ } @restricted_branchcodes
43 : (undef) # Do not return any results
47 if ( $searchfieldstype eq 'dateofbirth' ) {
48 # Return an empty list if the date of birth is not correctly formatted
49 $searchmember = eval { output_pref
( { str
=> $searchmember, dateformat
=> 'iso', dateonly
=> 1 } ); };
50 if ( $@
or not $searchmember ) {
52 iTotalRecords
=> $iTotalRecords,
53 iTotalDisplayRecords
=> 0,
60 borrowers.borrowernumber, borrowers.surname, borrowers.firstname,
61 borrowers.streetnumber, borrowers.streettype, borrowers.address,
62 borrowers.address2, borrowers.city, borrowers.state, borrowers.zipcode,
63 borrowers.country, cardnumber, borrowers.dateexpiry,
64 borrowers.borrowernotes, borrowers.branchcode, borrowers.email,
65 borrowers.userid, borrowers.dateofbirth, borrowers.categorycode,
66 categories.description AS category_description, categories.category_type,
67 branches.branchname, borrowers.phone";
68 my $from = "FROM borrowers
69 LEFT JOIN branches ON borrowers.branchcode = branches.branchcode
70 LEFT JOIN categories ON borrowers.categorycode = categories.categorycode";
73 if(defined $firstletter and $firstletter ne '') {
74 push @where_strs, "borrowers.surname LIKE ?";
75 push @where_args, "$firstletter%";
77 if(defined $categorycode and $categorycode ne '') {
78 push @where_strs, "borrowers.categorycode = ?";
79 push @where_args, $categorycode;
81 if(@restricted_branchcodes ) {
82 push @where_strs, "borrowers.branchcode IN (" . join( ',', ('?') x
@restricted_branchcodes ) . ")";
83 push @where_args, @restricted_branchcodes;
87 standard
=> C4
::Context
->preference('DefaultPatronSearchFields') || 'surname,firstname,othernames,cardnumber,userid',
89 email
=> 'email,emailpro,B_email',
90 borrowernumber
=> 'borrowernumber',
92 phone
=> 'phone,phonepro,B_phone,altcontactphone,mobile',
93 address
=> 'streettype,address,address2,city,state,zipcode,country',
94 dateofbirth
=> 'dateofbirth',
99 # * is replaced with % for sql
100 $searchmember =~ s/\*/%/g;
102 # split into search terms
104 # consider coma as space
105 $searchmember =~ s/,/ /g;
106 if ( $searchtype eq 'contain' ) {
107 @terms = split / /, $searchmember;
109 @terms = ($searchmember);
112 foreach my $term (@terms) {
115 my $term_dt = eval { local $SIG{__WARN__
} = {}; output_pref
( { str
=> $term, dateonly
=> 1, dateformat
=> 'sql' } ); };
120 $term .= '%' # end with anything
122 $term = "%$term" # begin with anythin unless start_with
123 if $searchtype eq 'contain' && $term !~ /^%/;
127 for my $searchfield ( split /,/, $searchfields->{$searchfieldstype} ) {
128 push @where_strs_or, "borrowers." . $dbh->quote_identifier($searchfield) . " LIKE ?";
129 push @where_args, $term;
132 if ( $searchfieldstype eq 'standard' and C4
::Context
->preference('ExtendedPatronAttributes') and $searchmember ) {
133 my $matching_borrowernumbers = C4
::Members
::Attributes
::SearchIdMatchingAttribute
($searchmember);
135 for my $borrowernumber ( @
$matching_borrowernumbers ) {
136 push @where_strs_or, "borrowers.borrowernumber = ?";
137 push @where_args, $borrowernumber;
141 push @where_strs, '('. join (' OR ', @where_strs_or) . ')'
146 $where = " WHERE " . join (" AND ", @where_strs) if @where_strs;
147 my $orderby = dt_build_orderby
($dt_params);
150 # If iDisplayLength == -1, we want to display all patrons
151 if ( !$dt_params->{iDisplayLength
} || $dt_params->{iDisplayLength
} > -1 ) {
152 # In order to avoid sql injection
153 $dt_params->{iDisplayStart
} =~ s/\D//g if defined($dt_params->{iDisplayStart
});
154 $dt_params->{iDisplayLength
} =~ s/\D//g if defined($dt_params->{iDisplayLength
});
155 $dt_params->{iDisplayStart
} //= 0;
156 $dt_params->{iDisplayLength
} //= 20;
157 $limit = "LIMIT $dt_params->{iDisplayStart},$dt_params->{iDisplayLength}";
162 ($select ?
$select : ""),
163 ($from ?
$from : ""),
164 ($where ?
$where : ""),
165 ($orderby ?
$orderby : ""),
166 ($limit ?
$limit : "")
168 $sth = $dbh->prepare($query);
169 $sth->execute(@where_args);
170 my $patrons = $sth->fetchall_arrayref({});
172 # Get the iTotalDisplayRecords DataTable variable
173 $query = "SELECT COUNT(borrowers.borrowernumber) " . $from . ($where ?
$where : "");
174 $sth = $dbh->prepare($query);
175 $sth->execute(@where_args);
176 ($iTotalDisplayRecords) = $sth->fetchrow_array;
178 # Get some information on patrons
179 foreach my $patron (@
$patrons) {
180 my $patron_object = Koha
::Patrons
->find( $patron->{borrowernumber
} );
181 $patron->{overdues
} = $patron_object->get_overdues->count;
182 $patron->{issues
} = $patron_object->checkouts->count;
183 my $balance = $patron_object->account->balance;
184 # FIXME Should be formatted from the template
185 $patron->{fines
} = sprintf("%.2f", $balance);
187 if( $patron->{dateexpiry
} ) {
188 # FIXME We should not format the date here, do it in template-side instead
189 $patron->{dateexpiry
} = output_pref
( { dt
=> scalar dt_from_string
( $patron->{dateexpiry
}, 'iso'), dateonly
=> 1} );
191 $patron->{dateexpiry
} = '';
196 iTotalRecords
=> $iTotalRecords,
197 iTotalDisplayRecords
=> $iTotalDisplayRecords,
207 C4::Utils::DataTables::Members - module for using DataTables with patrons
211 This module provides (one for the moment) routines used by the patrons search
217 my $dt_infos = C4::Utils::DataTables::Members->search($params);
219 $params is a hashref with some keys:
225 String to search in the borrowers sql table
229 Introduced to contain 1 letter but can contain more.
230 The search will done on the borrowers.surname field
234 Search patrons with this categorycode
238 Search patrons with this branchcode
242 Can be 'start_with' or 'contain' (default value). Used for the searchmember parameter.
244 =item searchfieldstype
246 Can be 'standard' (default value), 'email', 'borrowernumber', 'phone', 'address' or 'dateofbirth', 'sort1', 'sort2'
250 Is the reference of C4::Utils::DataTables::dt_get_params($input);
258 This file is part of Koha.
260 Copyright 2013 BibLibre
262 Koha is free software; you can redistribute it and/or modify it
263 under the terms of the GNU General Public License as published by
264 the Free Software Foundation; either version 3 of the License, or
265 (at your option) any later version.
267 Koha is distributed in the hope that it will be useful, but
268 WITHOUT ANY WARRANTY; without even the implied warranty of
269 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
270 GNU General Public License for more details.
272 You should have received a copy of the GNU General Public License
273 along with Koha; if not, see <http://www.gnu.org/licenses>.