Bug 7144 followup DBrev number
[koha_gimpoz] / misc / cronjobs / fines.pl
index afc4dca..73cdf9f 100755 (executable)
 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 #
-# You should have received a copy of the GNU General Public License along with
-# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-# Suite 330, Boston, MA  02111-1307 USA
+# You should have received a copy of the GNU General Public License along
+# with Koha; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
 
+# FIXME: use FinesMode as described or change syspref description
 use strict;
+#use warnings; FIXME - Bug 2505
+
 BEGIN {
     # find Koha's Perl modules
     # test carefully before changing this
     use FindBin;
     eval { require "$FindBin::Bin/kohalib.pl" };
 }
+
+use Date::Calc qw/Date_to_Days/;
+
 use C4::Context;
 use C4::Circulation;
 use C4::Overdues;
-use C4::Calendar;
-use Date::Calc qw/Date_to_Days/;
+use C4::Calendar qw();  # don't need any exports from Calendar
 use C4::Biblio;
+use C4::Debug;  # supplying $debug and $cgi_debug
+use Getopt::Long;
+
+my $help = 0;
+my $verbose = 0;
+my $output_dir;
+
+GetOptions( 'h|help'    => \$help,
+            'v|verbose' => \$verbose,
+            'o|out:s'   => \$output_dir,
+       );
+my $usage = << 'ENDUSAGE';
+
+This script calculates and charges overdue fines
+to patron accounts.  If the Koha System Preference
+'finesMode' is set to 'production', the fines are charged
+to the patron accounts.  If set to 'test', the fines are
+calculated but not applied.
+
+This script has the following parameters :
+    -h --help: this message
+    -o --out:  ouput directory for logs (defaults to env or /tmp if !exist)
+    -v --verbose
+
+ENDUSAGE
+
+die $usage if $help;
+
+use vars qw(@borrower_fields @item_fields @other_fields);
+use vars qw($fldir $libname $control $mode $delim $dbname $today $today_iso $today_days);
+use vars qw($filename);
+
+CHECK {
+    @borrower_fields = qw(cardnumber categorycode surname firstname email phone address citystate);
+        @item_fields = qw(itemnumber barcode date_due);
+       @other_fields = qw(type days_overdue fine);
+    $libname = C4::Context->preference('LibraryName');
+    $control = C4::Context->preference('CircControl');
+    $mode    = C4::Context->preference('finesMode');
+    $dbname  = C4::Context->config('database');
+    $delim   = "\t"; # ?  C4::Context->preference('delimiter') || "\t";
 
+}
 
-my $fldir = "/tmp" ;
-
-my $libname=C4::Context->preference('LibraryName');
-my $dbname= C4::Context->config('database');
+INIT {
+    $debug and print "Each line will contain the following fields:\n",
+        "From borrowers : ", join(', ', @borrower_fields), "\n",
+        "From items : ", join(', ', @item_fields), "\n",
+        "Per overdue: ", join(', ', @other_fields), "\n",
+        "Delimiter: '$delim'\n";
+}
 
-my $today = C4::Dates->new();
-my $datestr = $today->output('iso');
-my $today_days= Date_to_Days(split(/-/,$today->output('iso')));
-my $filename= $dbname;
-$filename =~ s/\W//;
-$filename = $fldir . '/'. $filename . $datestr . ".log";
-open (FILE,">$filename") || die "Can't open LOG";
-print FILE "cardnumber\tcategory\tsurname\tfirstname\temail\tphone\taddress\tcitystate\tbarcode\tdate_due\ttype\titemnumber\tdays_overdue\tfine\n";
-
-
-my $DEBUG =1;
-
-my $data=Getoverdues();
-my $overdueItemsCounted=0 ;
-my $borrowernumber;
-
-for (my $i=0;$i<scalar(@$data);$i++){
-  my $datedue=C4::Dates->new($data->[$i]->{'date_due'},'iso');
-  my $datedue_days = Date_to_Days(split(/-/,$datedue->output('iso')));
-  my $due_str=$datedue->output();
-  my $borrower=BorType($data->[$i]->{'borrowernumber'});
-  my $branchcode;
-  if ( C4::Context->preference('CircControl') eq 'ItemHomeLibrary' ) {
-       $branchcode = $data->[$i]->{'homebranch'};
-  } elsif ( C4::Context->preference('CircControl') eq 'PatronLibrary' ) {
-       $branchcode = $borrower->{'branchcode'};
+my $data = Getoverdues();
+my $overdueItemsCounted = 0;
+my %calendars = ();
+$today = C4::Dates->new();
+$today_iso = $today->output('iso');
+$today_days = Date_to_Days(split(/-/,$today_iso));
+if($output_dir){
+    $fldir = $output_dir if( -d $output_dir );
 } else {
-       # CircControl must be PickupLibrary. (branchcode comes from issues table here).
-       $branchcode =  $data->[$i]->{'branchcode'};
-  }
-  my $calendar = C4::Calendar->new( branchcode => $branchcode );
-
-  my $isHoliday = $calendar->isHoliday( split( '/', C4::Dates->new()->output('metric') ) );
+    $fldir = $ENV{TMPDIR} || "/tmp";
+}
+if (!-d $fldir) {
+    warn "Could not write to $fldir ... does not exist!";
+}
+$filename = $dbname;
+$filename =~ s/\W//;
+$filename = $fldir . '/'. $filename . '_' .  $today_iso . ".log";
+print "writing to $filename\n" if $verbose;
+open (FILE, ">$filename") or die "Cannot write file $filename: $!";
+print FILE join $delim, (@borrower_fields, @item_fields, @other_fields);
+print FILE "\n";
+
+for (my $i=0; $i<scalar(@$data); $i++) {
+    my $datedue = C4::Dates->new($data->[$i]->{'date_due'},'iso');
+    my $datedue_days = Date_to_Days(split(/-/,$datedue->output('iso')));
+    my $due_str = $datedue->output();
+    unless (defined $data->[$i]->{'borrowernumber'}) {
+        print STDERR "ERROR in Getoverdues line $i: issues.borrowernumber IS NULL.  Repair 'issues' table now!  Skipping record.\n";
+        next;   # Note: this doesn't solve everything.  After NULL borrowernumber, multiple issues w/ real borrowernumbers can pile up.
+    }
+    my $borrower = BorType($data->[$i]->{'borrowernumber'});
+    my $branchcode = ($control eq 'ItemHomeLibrary') ? $data->[$i]->{homebranch} :
+                     ($control eq 'PatronLibrary'  ) ?   $borrower->{branchcode} :
+                                                       $data->[$i]->{branchcode} ;
+    # In final case, CircControl must be PickupLibrary. (branchcode comes from issues table here).
+    my $calendar;
+    unless (defined ($calendars{$branchcode})) {
+        $calendars{$branchcode} = C4::Calendar->new(branchcode => $branchcode);
+    }
+    $calendar = $calendars{$branchcode};
+    my $isHoliday = $calendar->isHoliday(split '/', $today->output('metric'));
       
- if ($datedue_days <= $today_days){
-    $overdueItemsCounted++ if $DEBUG;
-    my $difference=$today_days - $datedue_days;
-    my ($amount,$type,$printout,$daycounttotal,$daycount)=
-               CalcFine($data->[$i], $borrower->{'categorycode'}, $branchcode,undef,undef, $datedue ,$today);
-    my ($delays1,$delays2,$delays3)=GetOverdueDelays($borrower->{'categorycode'});
+    ($datedue_days <= $today_days) or next; # or it's not overdue, right?
 
+    $overdueItemsCounted++;
+    my ($amount,$type,$daycounttotal,$daycount)=
+               CalcFine($data->[$i], $borrower->{'categorycode'}, $branchcode,undef,undef, $datedue, $today);
+        # FIXME: $type NEVER gets populated by anything.
+    (defined $type) or $type = '';
        # Don't update the fine if today is a holiday.  
        # This ensures that dropbox mode will remove the correct amount of fine.
-       if( (C4::Context->preference('finesMode') eq 'production') &&  ! $isHoliday ) {
-               # FIXME - $type is always null, afaict.
+       if ($mode eq 'production' and  ! $isHoliday) {
                UpdateFine($data->[$i]->{'itemnumber'},$data->[$i]->{'borrowernumber'},$amount,$type,$due_str) if( $amount > 0 ) ;
        }
-       print FILE "$printout\t$borrower->{'cardnumber'}\t$borrower->{'categorycode'}\t$borrower->{'surname'}\t$borrower->{'firstname'}\t$borrower->{'email'}\t$borrower->{'phone'}\t$borrower->{'address'}\t$borrower->{'city'}\t$data->[$i]->{'barcode'}\t$data->[$i]->{'date_due'}\t$type\t$data->[$i]->{'itemnumber'}\t$daycounttotal\t$amount\n";
- }
+    my @cells = ();
+    push @cells, map {$borrower->{$_}} @borrower_fields;
+    push @cells, map {$data->[$i]->{$_}} @item_fields;
+    push @cells, $type, $daycounttotal, $amount;
+    print FILE join($delim, @cells), "\n";
 }
 
-my $numOverdueItems=scalar(@$data);
-if ($DEBUG) {
-   print <<EOM
-
-Number of Overdue Items counted $overdueItemsCounted
-Number of Overdue Items reported $numOverdueItems
+my $numOverdueItems = scalar(@$data);
+if ($verbose) {
+   print <<EOM;
+Fines assessment -- $today_iso -- Saved to $filename
+Number of Overdue Items:
+     counted $overdueItemsCounted
+    reported $numOverdueItems
 
 EOM
 }