Bug Fixing merge_authority.pl
[koha_fer] / C4 / Members.pm
index a1ca507..385faf9 100644 (file)
@@ -67,6 +67,7 @@ BEGIN {
 
                &GetborCatFromCatType 
                &GetBorrowercategory
+    &GetBorrowercategoryList
 
                &GetBorrowersWhoHaveNotBorrowedSince
                &GetBorrowersWhoHaveNeverBorrowed
@@ -126,6 +127,8 @@ This module contains routines for adding, modifying and deleting members/patrons
 
   ($count, $borrowers) = &SearchMember($searchstring, $type,$category_type,$filter,$showallbranches);
 
+=back
+
 Looks up patrons (borrowers) by name.
 
 BUGFIX 499: C<$type> is now used to determine type of search.
@@ -245,7 +248,7 @@ AND attribute like ?
 
 =head2 GetMemberDetails
 
-($borrower, $flags) = &GetMemberDetails($borrowernumber, $cardnumber);
+($borrower) = &GetMemberDetails($borrowernumber, $cardnumber);
 
 Looks up a patron and returns information about him or her. If
 C<$borrowernumber> is true (nonzero), C<&GetMemberDetails> looks
@@ -337,6 +340,12 @@ fields from the reserves table of the Koha database.
 
 =back
 
+C<$borrower-E<gt>{authflags}> is a hash giving more detailed information
+about the top-level permissions flags set for the borrower.  For example,
+if a user has the "editcatalogue" permission,
+C<$borrower-E<gt>{authflags}-E<gt>{editcatalogue}> will exist and have
+the value "1".
+
 =cut
 
 sub GetMemberDetails {
@@ -492,7 +501,7 @@ sub patronflags {
 }
 
 
-=item GetMember
+=head2 GetMember
 
   $borrower = &GetMember($information, $type);
 
@@ -517,7 +526,7 @@ SELECT borrowers.*, categories.category_type, categories.description
 FROM borrowers 
 LEFT JOIN categories on borrowers.categorycode=categories.categorycode 
 ";
-    if ($type eq 'cardnumber' || $type eq 'firstname'|| $type eq 'userid'|| $type eq 'borrowernumber'){
+    if ( defined $type && ( $type eq 'cardnumber' || $type eq 'firstname'|| $type eq 'userid'|| $type eq 'borrowernumber' ) ){
         $information = uc $information;
         $sth = $dbh->prepare("$select WHERE $type=?");
     } else {
@@ -538,7 +547,7 @@ LEFT JOIN categories on borrowers.categorycode=categories.categorycode
     return undef;        
 }
 
-=item GetMemberIssuesAndFines
+=head2 GetMemberIssuesAndFines
 
   ($overdue_count, $issue_count, $total_fines) = &GetMemberIssuesAndFines($borrowernumber);
 
@@ -581,17 +590,27 @@ sub GetMemberIssuesAndFines {
     return ($overdue_count, $issue_count, $total_fines);
 }
 
+sub columns(;$) {
+    return @{C4::Context->dbh->selectcol_arrayref("SHOW columns from borrowers")};
+}
+
 =head2
 
-=item ModMember
+=head2 ModMember
+
+=over 4
 
-  &ModMember($borrowernumber);
+my $success = ModMember(borrowernumber => $borrowernumber, [ field => value ]... );
 
 Modify borrower's data.  All date fields should ALREADY be in ISO format.
 
+return :
+true on success, or false on failure
+
+=back
+
 =cut
 
-#'
 sub ModMember {
     my (%data) = @_;
     my $dbh = C4::Context->dbh;
@@ -600,57 +619,69 @@ sub ModMember {
         if (my $tempdate = $data{$_}) {                                 # assignment, not comparison
             ($tempdate =~ /$iso_re/) and next;                          # Congatulations, you sent a valid ISO date.
             warn "ModMember given $_ not in ISO format ($tempdate)";
-            if (my $tempdate2 = format_date_in_iso($tempdate)) {        # assignment, not comparison
-                $data{$_} = $tempdate2;
-            } else {
-                warn "ModMember cannot convert '$tempdate' (from syspref)";
+            my $tempdate2 = format_date_in_iso($tempdate);
+            if (!$tempdate2 or $tempdate2 eq '0000-00-00') {
+                warn "ModMember cannot convert '$tempdate' (from syspref to ISO)";
+                next;
             }
+            $data{$_} = $tempdate2;
         }
     }
     if (!$data{'dateofbirth'}){
-        undef $data{'dateofbirth'};
-    }
-    my $qborrower=$dbh->prepare("SHOW columns from borrowers");
-    $qborrower->execute;
-    my %hashborrowerfields;  
-    while (my ($field)=$qborrower->fetchrow){
-      $hashborrowerfields{$field}=1;
-    }  
+        delete $data{'dateofbirth'};
+    }
+    my @columns = &columns;
+    my %hashborrowerfields = (map {$_=>1} @columns);
     my $query = "UPDATE borrowers SET \n";
     my $sth;
     my @parameters;  
     
     # test to know if you must update or not the borrower password
-    if ( $data{'password'} eq '****' ) {
-        delete $data{'password'};
-    } else {
-        $data{'password'} = md5_base64( $data{'password'} )  if ($data{'password'} ne "");
-        delete $data{'password'} if ($data{password} eq "");
+    if (exists $data{password}) {
+        if ($data{password} eq '****' or $data{password} eq '') {
+            delete $data{password};
+        } else {
+            $data{password} = md5_base64($data{password});
+        }
     }
-    foreach (keys %data)
-    { push @parameters,"$_ = ".$dbh->quote($data{$_}) if ($_ ne 'borrowernumber' and $_ ne 'flags' and $hashborrowerfields{$_}); }
-    $query .= join (',',@parameters) . "\n WHERE borrowernumber=? \n";
+    my @badkeys;
+    foreach (keys %data) {  
+        next if ($_ eq 'borrowernumber' or $_ eq 'flags');
+        if ($hashborrowerfields{$_}){
+            $query .= " $_=?, "; 
+            push @parameters,$data{$_};
+        } else {
+            push @badkeys, $_;
+            delete $data{$_};
+        }
+    }
+    (@badkeys) and warn scalar(@badkeys) . " Illegal key(s) passed to ModMember: " . join(',',@badkeys);
+    $query =~ s/, $//;
+    $query .= " WHERE borrowernumber=?";
+    push @parameters, $data{'borrowernumber'};
     $debug and print STDERR "$query (executed w/ arg: $data{'borrowernumber'})";
     $sth = $dbh->prepare($query);
-    $sth->execute($data{'borrowernumber'});
+    my $execute_success = $sth->execute(@parameters);
     $sth->finish;
 
 # ok if its an adult (type) it may have borrowers that depend on it as a guarantor
 # so when we update information for an adult we should check for guarantees and update the relevant part
 # of their records, ie addresses and phone numbers
     my $borrowercategory= GetBorrowercategory( $data{'category_type'} );
-    if ( $borrowercategory->{'category_type'} eq ('A' || 'S') ) {
+    if ( exists  $borrowercategory->{'category_type'} && $borrowercategory->{'category_type'} eq ('A' || 'S') ) {
         # is adult check guarantees;
         UpdateGuarantees(%data);
     }
     logaction("MEMBERS", "MODIFY", $data{'borrowernumber'}, "$query (executed w/ arg: $data{'borrowernumber'})") 
         if C4::Context->preference("BorrowersLog");
+
+    return $execute_success;
 }
 
 
 =head2
 
-=item AddMember
+=head2 AddMember
 
   $borrowernumber = &AddMember(%borrower);
 
@@ -745,7 +776,7 @@ sub AddMember {
     $sth = $dbh->prepare("SELECT enrolmentfee FROM categories WHERE categorycode=?");
     $sth->execute($data{'categorycode'});
     my ($enrolmentfee) = $sth->fetchrow;
-    if ($enrolmentfee) {
+    if ($enrolmentfee && $enrolmentfee > 0) {
         # insert fee in patron debts
         manualinvoice($data{'borrowernumber'}, '', '', 'A', $enrolmentfee);
     }
@@ -799,7 +830,7 @@ sub changepassword {
 
 
 
-=item fixup_cardnumber
+=head2 fixup_cardnumber
 
 Warning: The caller is responsible for locking the members table in write
 mode, to avoid database corruption.
@@ -1315,13 +1346,14 @@ to category descriptions.
 #'
 sub GetborCatFromCatType {
     my ( $category_type, $action ) = @_;
+       # FIXME - This API  seems both limited and dangerous. 
     my $dbh     = C4::Context->dbh;
     my $request = qq|   SELECT categorycode,description 
             FROM categories 
             $action
             ORDER BY categorycode|;
     my $sth = $dbh->prepare($request);
-    if ($action) {
+       if ($action) {
         $sth->execute($category_type);
     }
     else {
@@ -1367,18 +1399,29 @@ sub GetBorrowercategory {
         $sth->finish();
         return $data;
     } 
-    else {
-        my $sth       =
-        $dbh->prepare(
-    "SELECT *
-    FROM categories order by description"
+    return;  
+}    # sub getborrowercategory
+
+=head2 GetBorrowercategoryList
+  $arrayref_hashref = &GetBorrowercategoryList;
+If no category code provided, the function returns all the categories.
+
+=cut
+
+sub GetBorrowercategoryList {
+    my $dbh       = C4::Context->dbh;
+    my $sth       =
+    $dbh->prepare(
+    "SELECT * 
+    FROM categories 
+    ORDER BY description"
         );
-        $sth->execute;
-        my $data =
-        $sth->fetchall_arrayref({});
-        $sth->finish();
-        return $data;
-    }  
+    $sth->execute;
+    my $data =
+    $sth->fetchall_arrayref({});
+    $sth->finish();
+    return $data;
 }    # sub getborrowercategory
 
 =head2 ethnicitycategories
@@ -1745,7 +1788,7 @@ sub GetPatronImage {
     my ($cardnumber) = @_;
     warn "Cardnumber passed to GetPatronImage is $cardnumber" if $debug;
     my $dbh = C4::Context->dbh;
-    my $query = "SELECT mimetype, imagefile FROM patronimage WHERE cardnumber = ?;";
+    my $query = 'SELECT mimetype, imagefile FROM patronimage WHERE cardnumber = ?';
     my $sth = $dbh->prepare($query);
     $sth->execute($cardnumber);
     my $imagedata = $sth->fetchrow_hashref;
@@ -1844,11 +1887,13 @@ sub GetBorrowersWhoHaveNotBorrowedSince {
     my $query = "
         SELECT borrowers.borrowernumber,max(issues.timestamp) as latestissue
         FROM   borrowers
-          LEFT JOIN issues ON borrowers.borrowernumber = issues.borrowernumber
+        JOIN   categories USING (categorycode)
+        LEFT JOIN issues ON borrowers.borrowernumber = issues.borrowernumber
+        WHERE  category_type <> 'S'
    ";
     my @query_params;
     if ($filterbranch && $filterbranch ne ""){ 
-        $query.=" WHERE branchcode= ?";
+        $query.=" AND borrowers.branchcode= ?";
         push @query_params,$filterbranch;
     }    
     $query.=" GROUP BY borrowers.borrowernumber";
@@ -1899,7 +1944,7 @@ sub GetBorrowersWhoHaveNeverBorrowed {
    ";
     my @query_params;
     if ($filterbranch && $filterbranch ne ""){ 
-        $query.=" AND branchcode= ?";
+        $query.=" AND borrowers.branchcode= ?";
         push @query_params,$filterbranch;
     }
     warn $query if $debug;
@@ -1989,14 +2034,40 @@ sub GetBorrowersNamesAndLatestIssue {
     my $results = $sth->fetchall_arrayref({});
     return $results;
 }
+
+=head2 DebarMember
+
+=over 4
+
+my $success = DebarMember( $borrowernumber );
+
+marks a Member as debarred, and therefore unable to checkout any more
+items.
+
+return :
+true on success, false on failure
+
+=back
+
+=cut
+
+sub DebarMember {
+    my $borrowernumber = shift;
+
+    return unless defined $borrowernumber;
+    return unless $borrowernumber =~ /^\d+$/;
+
+    return ModMember( borrowernumber => $borrowernumber,
+                      debarred       => 1 );
+    
+}
+
 END { }    # module clean-up code here (global destructor)
 
 1;
 
 __END__
 
-=back
-
 =head1 AUTHOR
 
 Koha Team