| 
      
            Lines 44-50
          BEGIN {
      
      
        Link Here
      
     | 
  
        
          | 44 | 
          	#Get data  | 
          44 | 
          	#Get data  | 
        
        
          | 45 | 
          	push @EXPORT, qw(  | 
          45 | 
          	push @EXPORT, qw(  | 
        
        
          | 46 | 
          		&Search  | 
          46 | 
          		&Search  | 
        
            
              | 47 | 
              		&SearchMember   | 
               | 
               | 
            
        
          | 48 | 
          		&GetMemberDetails  | 
          47 | 
          		&GetMemberDetails  | 
        
        
          | 49 | 
                  &GetMemberRelatives  | 
          48 | 
                  &GetMemberRelatives  | 
        
        
          | 50 | 
          		&GetMember  | 
          49 | 
          		&GetMember  | 
        
  
    | 
      
            Lines 141-318
          This module contains routines for adding, modifying and deleting members/patrons
      
      
        Link Here
      
     | 
  
        
          | 141 | 
           | 
          140 | 
           | 
        
        
          | 142 | 
          =head1 FUNCTIONS  | 
          141 | 
          =head1 FUNCTIONS  | 
        
        
          | 143 | 
           | 
          142 | 
           | 
        
          
            
              | 144 | 
              =head2 SearchMember  | 
              143 | 
              =head2 Search  | 
            
            
              | 145 | 
               | 
               | 
               | 
            
            
              | 146 | 
                ($count, $borrowers) = &SearchMember($searchstring, $type,   | 
            
            
              | 147 | 
                                   $category_type, $filter, $showallbranches);  | 
            
        
          | 148 | 
           | 
          144 | 
           | 
        
          
            
              | 149 | 
              Looks up patrons (borrowers) by name.  | 
              145 | 
                $borrowers_result_array_ref = &Search($filter,$orderby, $limit,   | 
            
            
               | 
               | 
              146 | 
                                     $columns_out, $search_on_fields,$searchtype);  | 
            
        
          | 150 | 
           | 
          147 | 
           | 
        
          
            
              | 151 | 
              BUGFIX 499: C<$type> is now used to determine type of search.  | 
              148 | 
              Looks up patrons (borrowers) on filter. A wrapper for SearchInTable('borrowers'). | 
            
            
              | 152 | 
              if $type is "simple", search is performed on the first letter of the  | 
               | 
               | 
            
            
              | 153 | 
              surname only.  | 
            
        
          | 154 | 
           | 
          149 | 
           | 
        
          
            
              | 155 | 
              $category_type is used to get a specified type of user.   | 
              150 | 
              For C<$filter>, C<$orderby>, C<$limit>, C<&columns_out>, C<&search_on_fields> and C<&searchtype>  | 
            
            
              | 156 | 
              (mainly adults when creating a child.)  | 
              151 | 
              refer to C4::SQLHelper:SearchInTable().  | 
            
        
          | 157 | 
           | 
          152 | 
           | 
        
          
            
              | 158 | 
              C<$searchstring> is a space-separated list of search terms. Each term  | 
              153 | 
              Special C<$filter> key '' is effectively expanded to search on surname firstname othernamescw  | 
            
            
              | 159 | 
              must match the beginning a borrower's surname, first name, or other  | 
              154 | 
              and cardnumber unless C<&search_on_fields> is defined  | 
            
            
              | 160 | 
              name.  | 
               | 
               | 
            
        
          | 161 | 
           | 
          155 | 
           | 
        
          
            
              | 162 | 
              C<$filter> is assumed to be a list of elements to filter results on  | 
              156 | 
              Examples:  | 
            
        
          | 163 | 
           | 
          157 | 
           | 
        
          
            
              | 164 | 
              C<$showallbranches> is used in IndependantBranches Context to display all branches results.  | 
              158 | 
                $borrowers = Search('abcd', 'cardnumber'); | 
            
        
          | 165 | 
           | 
          159 | 
           | 
        
          
            
              | 166 | 
              C<&SearchMember> returns a two-element list. C<$borrowers> is a  | 
              160 | 
                $borrowers = Search({''=>'abcd', category_type=>'I'}, 'surname'); | 
            
            
              | 167 | 
              reference-to-array; each element is a reference-to-hash, whose keys  | 
               | 
               | 
            
            
              | 168 | 
              are the fields of the C<borrowers> table in the Koha database.  | 
            
            
              | 169 | 
              C<$count> is the number of elements in C<$borrowers>.  | 
            
        
          | 170 | 
           | 
          161 | 
           | 
        
        
          | 171 | 
          =cut  | 
          162 | 
          =cut  | 
        
        
          | 172 | 
           | 
          163 | 
           | 
        
          
            
              | 173 | 
              #'  | 
              164 | 
              sub _express_member_find { | 
            
            
              | 174 | 
              #used by member enquiries from the intranet  | 
              165 | 
                  my ($filter) = @_;  | 
            
            
              | 175 | 
              sub SearchMember { | 
              166 | 
               | 
            
            
              | 176 | 
                  my ($searchstring, $orderby, $type,$category_type,$filter,$showallbranches ) = @_;  | 
               | 
               | 
            
            
              | 177 | 
                  my $dbh   = C4::Context->dbh;  | 
            
            
              | 178 | 
                  my $query = "";  | 
            
            
              | 179 | 
                  my $count;  | 
            
            
              | 180 | 
                  my @data;  | 
            
            
              | 181 | 
                  my @bind = ();  | 
            
            
              | 182 | 
                    | 
            
        
          | 183 | 
              # this is used by circulation everytime a new borrowers cardnumber is scanned  | 
          167 | 
              # this is used by circulation everytime a new borrowers cardnumber is scanned  | 
        
        
          | 184 | 
              # so we can check an exact match first, if that works return, otherwise do the rest  | 
          168 | 
              # so we can check an exact match first, if that works return, otherwise do the rest  | 
        
          
            
              | 185 | 
                  $query = "SELECT * FROM borrowers  | 
              169 | 
                  my $dbh   = C4::Context->dbh;  | 
            
            
              | 186 | 
                      LEFT JOIN categories ON borrowers.categorycode=categories.categorycode  | 
              170 | 
                  my $query = "SELECT borrowernumber FROM borrowers WHERE cardnumber = ?";  | 
            
            
              | 187 | 
                      ";  | 
              171 | 
                  if ( my $borrowernumber = $dbh->selectrow_array($query, undef, $filter) ) { | 
            
            
              | 188 | 
                  my $sth = $dbh->prepare("$query WHERE cardnumber = ?"); | 
              172 | 
                      return( {"borrowernumber"=>$borrowernumber} ); | 
            
            
              | 189 | 
                  $sth->execute($searchstring);  | 
               | 
               | 
            
            
              | 190 | 
                  my $data = $sth->fetchall_arrayref({}); | 
            
            
              | 191 | 
                  if (@$data){ | 
            
            
              | 192 | 
                      return ( scalar(@$data), $data );  | 
            
            
              | 193 | 
                  }  | 
            
            
              | 194 | 
               | 
            
            
              | 195 | 
                  if ( $type eq "simple" )    # simple search for one letter only  | 
            
            
              | 196 | 
                  { | 
            
            
              | 197 | 
                      $query .= ($category_type ? " AND category_type = ".$dbh->quote($category_type) : "");   | 
            
            
              | 198 | 
                      $query .= " WHERE (surname LIKE ? OR cardnumber like ?) ";  | 
            
            
              | 199 | 
                      if (C4::Context->preference("IndependantBranches") && !$showallbranches){ | 
            
            
              | 200 | 
                        if (C4::Context->userenv && C4::Context->userenv->{flags} % 2 !=1 && C4::Context->userenv->{'branch'}){ | 
            
            
              | 201 | 
                          $query.=" AND borrowers.branchcode =".$dbh->quote(C4::Context->userenv->{'branch'}) unless (C4::Context->userenv->{'branch'} eq "insecure"); | 
            
            
              | 202 | 
                        }  | 
            
            
              | 203 | 
                      }  | 
            
            
              | 204 | 
                      $query.=" ORDER BY $orderby";  | 
            
            
              | 205 | 
                      @bind = ("$searchstring%","$searchstring"); | 
            
        
          | 206 | 
              }  | 
          173 | 
              }  | 
        
            
              | 207 | 
                  else    # advanced search looking in surname, firstname and othernames  | 
               | 
               | 
            
            
              | 208 | 
                  { | 
            
            
              | 209 | 
                      @data  = split( ' ', $searchstring );  | 
            
            
              | 210 | 
                      $count = @data;  | 
            
            
              | 211 | 
                      $query .= " WHERE ";  | 
            
            
              | 212 | 
                      if (C4::Context->preference("IndependantBranches") && !$showallbranches){ | 
            
            
              | 213 | 
                        if (C4::Context->userenv && C4::Context->userenv->{flags} % 2 !=1 && C4::Context->userenv->{'branch'}){ | 
            
            
              | 214 | 
                          $query.=" borrowers.branchcode =".$dbh->quote(C4::Context->userenv->{'branch'})." AND " unless (C4::Context->userenv->{'branch'} eq "insecure"); | 
            
            
              | 215 | 
                        }        | 
            
            
              | 216 | 
                      }       | 
            
            
              | 217 | 
                      $query.="((surname LIKE ? OR (surname LIKE ? AND surname REGEXP ?)  | 
            
            
              | 218 | 
                              OR firstname  LIKE ? OR (firstname LIKE ? AND firstname REGEXP ?)  | 
            
            
              | 219 | 
                              OR othernames LIKE ? OR (othernames LIKE ? AND othernames REGEXP ?))  | 
            
            
              | 220 | 
                      " .  | 
            
            
              | 221 | 
                      ($category_type?" AND category_type = ".$dbh->quote($category_type):"");  | 
            
            
              | 222 | 
                      my $regex = '[[:punct:][:space:]]'.$data[0];  | 
            
            
              | 223 | 
                      @bind = (  | 
            
            
              | 224 | 
                          "$data[0]%", "%$data[0]%", $regex,   | 
            
            
              | 225 | 
                          "$data[0]%", "%$data[0]%", $regex,   | 
            
            
              | 226 | 
                          "$data[0]%", "%$data[0]%", $regex   | 
            
            
              | 227 | 
                      );  | 
            
            
              | 228 | 
                      for ( my $i = 1 ; $i < $count ; $i++ ) { | 
            
            
              | 229 | 
                          $query = $query . " AND (" . " surname LIKE ? OR (surname LIKE ? AND surname REGEXP ?) | 
            
            
              | 230 | 
                              OR firstname  LIKE ? OR (firstname LIKE ? AND firstname REGEXP ?)  | 
            
            
              | 231 | 
                              OR othernames LIKE ? OR (othernames LIKE ? AND othernames REGEXP ?))";  | 
            
            
              | 232 | 
                          $regex = '[[:punct:][:space:]]'.$data[$i];  | 
            
            
              | 233 | 
                          push( @bind,  | 
            
            
              | 234 | 
                            "$data[$i]%", "%$data[$i]%", $regex,  | 
            
            
              | 235 | 
                            "$data[$i]%", "%$data[$i]%", $regex,  | 
            
            
              | 236 | 
                            "$data[$i]%", "%$data[$i]%", $regex  | 
            
            
              | 237 | 
                          );  | 
            
            
              | 238 | 
               | 
            
            
              | 239 | 
               | 
            
            
              | 240 | 
                          # FIXME - .= <<EOT;  | 
            
            
              | 241 | 
                      }  | 
            
            
              | 242 | 
                      $query = $query . ") OR cardnumber LIKE ? ";  | 
            
            
              | 243 | 
                      push( @bind, $searchstring );  | 
            
            
              | 244 | 
                      $query .= "order by $orderby";  | 
            
        
          | 245 | 
           | 
          174 | 
           | 
        
          
            
              | 246 | 
                      # FIXME - .= <<EOT;  | 
              175 | 
                  my ($search_on_fields, $searchtype);  | 
            
            
               | 
               | 
              176 | 
                  if ( length($filter) == 1 ) { | 
            
            
              | 177 | 
                      $search_on_fields = [ qw(surname) ];  | 
            
            
              | 178 | 
                      $searchtype = 'start_with';  | 
            
            
              | 179 | 
                  } else { | 
            
            
              | 180 | 
                      $search_on_fields = [ qw(surname firstname othernames cardnumber) ];  | 
            
            
              | 181 | 
                      $searchtype = 'contain';  | 
            
        
          | 247 | 
              }  | 
          182 | 
              }  | 
        
        
          | 248 | 
           | 
          183 | 
           | 
        
          
            
              | 249 | 
                  $sth = $dbh->prepare($query);  | 
              184 | 
                  return (undef, $search_on_fields, $searchtype);  | 
            
            
              | 250 | 
               | 
               | 
               | 
            
            
              | 251 | 
                  $debug and print STDERR "Q $orderby : $query\n";  | 
            
            
              | 252 | 
                  $sth->execute(@bind);  | 
            
            
              | 253 | 
                  my @results;  | 
            
            
              | 254 | 
                  $data = $sth->fetchall_arrayref({}); | 
            
            
              | 255 | 
               | 
            
            
              | 256 | 
                  return ( scalar(@$data), $data );  | 
            
        
          | 257 | 
          }  | 
          185 | 
          }  | 
        
        
          | 258 | 
           | 
          186 | 
           | 
        
            
              | 259 | 
              =head2 Search  | 
               | 
               | 
            
            
              | 260 | 
               | 
            
            
              | 261 | 
                $borrowers_result_array_ref = &Search($filter,$orderby, $limit,   | 
            
            
              | 262 | 
                                     $columns_out, $search_on_fields,$searchtype);  | 
            
            
              | 263 | 
               | 
            
            
              | 264 | 
              Looks up patrons (borrowers) on filter.  | 
            
            
              | 265 | 
               | 
            
            
              | 266 | 
              BUGFIX 499: C<$type> is now used to determine type of search.  | 
            
            
              | 267 | 
              if $type is "simple", search is performed on the first letter of the  | 
            
            
              | 268 | 
              surname only.  | 
            
            
              | 269 | 
               | 
            
            
              | 270 | 
              $category_type is used to get a specified type of user.   | 
            
            
              | 271 | 
              (mainly adults when creating a child.)  | 
            
            
              | 272 | 
               | 
            
            
              | 273 | 
              C<$filter> can be  | 
            
            
              | 274 | 
                 - a space-separated list of search terms. Implicit AND is done on them  | 
            
            
              | 275 | 
                 - a hash ref containing fieldnames associated with queried value  | 
            
            
              | 276 | 
                 - an array ref combining the two previous elements Implicit OR is done between each array element  | 
            
            
              | 277 | 
               | 
            
            
              | 278 | 
               | 
            
            
              | 279 | 
              C<$orderby> is an arrayref of hashref. Contains the name of the field and 0 or 1 depending if order is ascending or descending  | 
            
            
              | 280 | 
               | 
            
            
              | 281 | 
              C<$limit> is there to allow limiting number of results returned  | 
            
            
              | 282 | 
               | 
            
            
              | 283 | 
              C<&columns_out> is an array ref to the fieldnames you want to see in the result list  | 
            
            
              | 284 | 
               | 
            
            
              | 285 | 
              C<&search_on_fields> is an array ref to the fieldnames you want to limit search on when you are using string search  | 
            
            
              | 286 | 
               | 
            
            
              | 287 | 
              C<&searchtype> is a string telling the type of search you want todo : start_with, exact or contains are allowed  | 
            
            
              | 288 | 
               | 
            
            
              | 289 | 
              =cut  | 
            
            
              | 290 | 
               | 
            
        
          | 291 | 
          sub Search { | 
          187 | 
          sub Search { | 
        
        
          | 292 | 
              my ( $filter, $orderby, $limit, $columns_out, $search_on_fields, $searchtype ) = @_;  | 
          188 | 
              my ( $filter, $orderby, $limit, $columns_out, $search_on_fields, $searchtype ) = @_;  | 
        
          
            
              | 293 | 
                  my @filters;  | 
              189 | 
               | 
            
            
              | 294 | 
                  my %filtersmatching_record;  | 
              190 | 
                  my $search_string;  | 
            
            
              | 295 | 
                  my @finalfilter;  | 
              191 | 
                  my $found_borrower;  | 
            
            
              | 296 | 
                  if ( ref($filter) eq "ARRAY" ) { | 
              192 | 
               | 
            
            
              | 297 | 
                      push @filters, @$filter;  | 
              193 | 
                  if ( my $fr = ref $filter ) { | 
            
            
              | 298 | 
                  } else { | 
              194 | 
                      if ( $fr eq "HASH" ) { | 
            
            
              | 299 | 
                      push @filters, $filter;  | 
              195 | 
                          if ( my $search_string = $filter->{''} ) { | 
            
            
               | 
               | 
              196 | 
                              my ($member_filter, $member_search_on_fields, $member_searchtype) = _express_member_find($search_string);  | 
            
            
              | 197 | 
                              if ($member_filter) { | 
            
            
              | 198 | 
                                  $filter = $member_filter;  | 
            
            
              | 199 | 
                                  $found_borrower = 1;  | 
            
            
              | 200 | 
                              } else { | 
            
            
              | 201 | 
                                  $search_on_fields ||= $member_search_on_fields;  | 
            
            
              | 202 | 
                                  $searchtype ||= $member_searchtype;  | 
            
            
              | 203 | 
                              }  | 
            
            
              | 204 | 
                          }  | 
            
            
              | 205 | 
                      }  | 
            
            
              | 206 | 
                      else { | 
            
            
              | 207 | 
                          $search_string = $filter;  | 
            
            
              | 208 | 
                      }  | 
            
            
              | 209 | 
                  }  | 
            
            
              | 210 | 
                  else { | 
            
            
              | 211 | 
                      $search_string = $filter;  | 
            
            
              | 212 | 
                      my ($member_filter, $member_search_on_fields, $member_searchtype) = _express_member_find($search_string);  | 
            
            
              | 213 | 
                      if ($member_filter) { | 
            
            
              | 214 | 
                          $filter = $member_filter;  | 
            
            
              | 215 | 
                          $found_borrower = 1;  | 
            
            
              | 216 | 
                      } else { | 
            
            
              | 217 | 
                          $search_on_fields ||= $member_search_on_fields;  | 
            
            
              | 218 | 
                          $searchtype ||= $member_searchtype;  | 
            
            
              | 219 | 
                      }  | 
            
        
          | 300 | 
              }  | 
          220 | 
              }  | 
        
          
            
              | 301 | 
                  if ( C4::Context->preference('ExtendedPatronAttributes') ) { | 
              221 | 
               | 
            
            
              | 302 | 
                      my $matching_records = C4::Members::Attributes::SearchIdMatchingAttribute($filter);  | 
              222 | 
                  if ( !$found_borrower && C4::Context->preference('ExtendedPatronAttributes') && $search_string ) { | 
            
            
               | 
               | 
              223 | 
                      my $matching_records = C4::Members::Attributes::SearchIdMatchingAttribute($search_string);  | 
            
        
          | 303 | 
                  if(scalar(@$matching_records)>0) { | 
          224 | 
                  if(scalar(@$matching_records)>0) { | 
        
          
            
              | 304 | 
              			foreach my $matching_record (@$matching_records) { | 
              225 | 
                          if ( my $fr = ref $filter ) { | 
            
            
              | 305 | 
              				$filtersmatching_record{$$matching_record[0]}=1; | 
              226 | 
                              if ( $fr eq "HASH" ) { | 
            
            
              | 306 | 
              			}  | 
              227 | 
                                  my %f = %$filter;  | 
            
            
              | 307 | 
              			foreach my $k (keys(%filtersmatching_record)) { | 
              228 | 
                                  $filter = [ $filter ];  | 
            
            
              | 308 | 
              				push @filters, {"borrowernumber"=>$k}; | 
              229 | 
                                  delete $f{''}; | 
            
            
              | 309 | 
              			}  | 
              230 | 
                                  push @$filter, { %f, "borrowernumber"=>$$matching_records }; | 
            
            
               | 
               | 
              231 | 
                              }  | 
            
            
              | 232 | 
                              else { | 
            
            
              | 233 | 
                                  push @$filter, {"borrowernumber"=>$matching_records}; | 
            
            
              | 234 | 
                              }  | 
            
            
              | 235 | 
                          }  | 
            
            
              | 236 | 
                          else { | 
            
            
              | 237 | 
                              $filter = [ $filter ];  | 
            
            
              | 238 | 
                              push @$filter, {"borrowernumber"=>$matching_records}; | 
            
            
              | 239 | 
                          }  | 
            
        
          | 310 | 
          		}  | 
          240 | 
          		}  | 
        
        
          | 311 | 
              }  | 
          241 | 
              }  | 
        
            
               | 
               | 
              242 | 
               | 
            
            
              | 243 | 
                  # $showallbranches was not used at the time SearchMember() was mainstreamed into Search().  | 
            
            
              | 244 | 
                  # Mentioning for the reference  | 
            
            
              | 245 | 
               | 
            
            
              | 246 | 
                  if ( C4::Context->preference("IndependantBranches") ) { # && !$showallbranches){ | 
            
            
              | 247 | 
                      if ( my $userenv = C4::Context->userenv ) { | 
            
            
              | 248 | 
                          my $branch =  $userenv->{'branch'}; | 
            
            
              | 249 | 
                          if ( ($userenv->{flags} % 2 !=1) && | 
            
            
              | 250 | 
                               $branch && $branch ne "insecure" ){ | 
            
            
              | 251 | 
               | 
            
            
              | 252 | 
                              if (my $fr = ref $filter) { | 
            
            
              | 253 | 
                                  if ( $fr eq "HASH" ) { | 
            
            
              | 254 | 
                                      $filter->{branchcode} = $branch; | 
            
            
              | 255 | 
                                  }  | 
            
            
              | 256 | 
                                  else { | 
            
            
              | 257 | 
                                      foreach (@$filter) { | 
            
            
              | 258 | 
                                          $_ = { '' => $_ } unless ref $_; | 
            
            
              | 259 | 
                                          $_->{branchcode} = $branch; | 
            
            
              | 260 | 
                                      }  | 
            
            
              | 261 | 
                                  }  | 
            
            
              | 262 | 
                              }  | 
            
            
              | 263 | 
                              else { | 
            
            
              | 264 | 
                                  $filter = { '' => $filter, branchcode => $branch }; | 
            
            
              | 265 | 
                              }  | 
            
            
              | 266 | 
                          }        | 
            
            
              | 267 | 
                      }  | 
            
            
              | 268 | 
                  }  | 
            
            
              | 269 | 
               | 
            
            
              | 270 | 
                  if ($found_borrower) { | 
            
            
              | 271 | 
                      $searchtype = "exact";  | 
            
            
              | 272 | 
                  }  | 
            
        
          | 312 | 
              $searchtype ||= "start_with";  | 
          273 | 
              $searchtype ||= "start_with";  | 
        
          
            
              | 313 | 
              	push @finalfilter, \@filters;  | 
              274 | 
               | 
            
            
              | 314 | 
              	my $data = SearchInTable( "borrowers", \@finalfilter, $orderby, $limit, $columns_out, $search_on_fields, $searchtype );  | 
              275 | 
              	return SearchInTable( "borrowers", $filter, $orderby, $limit, $columns_out, $search_on_fields, $searchtype );  | 
            
            
              | 315 | 
                  return ($data);  | 
               | 
               | 
            
        
          | 316 | 
          }  | 
          276 | 
          }  | 
        
        
          | 317 | 
           | 
          277 | 
           | 
        
        
          | 318 | 
          =head2 GetMemberDetails  | 
          278 | 
          =head2 GetMemberDetails  |