[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Koha-cvs] koha/C4/Circulation Fines.pm [dev_week]
From: |
Kyle Hall |
Subject: |
[Koha-cvs] koha/C4/Circulation Fines.pm [dev_week] |
Date: |
Tue, 01 Apr 2008 15:18:22 +0000 |
CVSROOT: /sources/koha
Module name: koha
Branch: dev_week
Changes by: Kyle Hall <kylemhall> 08/04/01 15:18:22
Modified files:
C4/Circulation : Fines.pm
Log message:
Added a number of useful fines functions, including a 'corrent'
function for getting issuing rules, which takes into account wildcards.
Also added CreateFineOnReturn as an alternative to the nightly fines
generator.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/koha/C4/Circulation/Fines.pm?cvsroot=koha&only_with_tag=dev_week&r1=1.9.2.2.2.1&r2=1.9.2.2.2.2
Patches:
Index: Fines.pm
===================================================================
RCS file: /sources/koha/koha/C4/Circulation/Fines.pm,v
retrieving revision 1.9.2.2.2.1
retrieving revision 1.9.2.2.2.2
diff -u -b -r1.9.2.2.2.1 -r1.9.2.2.2.2
--- Fines.pm 3 Aug 2006 05:25:41 -0000 1.9.2.2.2.1
+++ Fines.pm 1 Apr 2008 15:18:21 -0000 1.9.2.2.2.2
@@ -1,6 +1,6 @@
package C4::Circulation::Fines;
-# $Id: Fines.pm,v 1.9.2.2.2.1 2006/08/03 05:25:41 kados Exp $
+# $Id: Fines.pm,v 1.9.2.2.2.2 2008/04/01 15:18:21 kylemhall Exp $
# Copyright 2000-2002 Katipo Communications
#
@@ -22,6 +22,11 @@
use strict;
require Exporter;
use DBI;
+use POSIX;
+use Date::Calc qw(
+Add_Delta_Days
+);
+
use C4::Context;
use vars qw($VERSION @ISA @EXPORT);
@@ -48,7 +53,7 @@
=cut
@ISA = qw(Exporter);
address@hidden = qw(&Getoverdues &CalcFine &BorType &UpdateFine
&ReplacementCost);
address@hidden = qw(&Getoverdues &CalcFine &BorType &UpdateFine
&ReplacementCost &CreateFineOnReturn &CalculateFine);
=item Getoverdues
@@ -348,6 +353,217 @@
return($data->{'replacementprice'});
}
+
+## Function Calculate Fine
+## A New Fine Calculator
+## $future_date is an optional date ( YYYY-MM-DD ) for estimating a fine in
the future.
+## Returns amount of fine.
+sub CalculateFine {
+ my $maxFine = 10;
+
+ my ( $itembarcode, $itemnumber, $future_date ) = @_;
+
+warn "CalculateFine( $itembarcode, $itemnumber, $future_date )";
+
+ my $return_date = sprintf("%04d-%02d-%02d", (localtime(time))[5] + 1900,
(localtime(time))[4] + 1, (localtime(time))[3]);
+ if ( $future_date ) {
+ $return_date = $future_date;
+ }
+
+warn "CalculateFine: Return Date: $return_date";
+
+ my $dbh = C4::Context->dbh;
+
+ my $fineData = _GetFineData( $itembarcode, $itemnumber, $future_date );
+
+warn "CalculateFine: Borrowernumber: " . $fineData->{'borrowernumber'};
+warn "CalculateFine: Date of Issue: " . $fineData->{'issue_date'};
+warn "CalculateFine: Date Due: " . $fineData->{'date_due'};
+warn "CalculateFine: Days Overdue: " . $fineData->{'days_overdue'};
+
+ if ( $fineData->{'days_overdue'} < 1 ) { return 0; } ## Short circuit for
speed
+
+ my $issuing_rule = _GetIssuingRule( $fineData->{'categorycode'},
$fineData->{'itemtype'}, $fineData->{'holdingbranch'} );
+
+ ## We don't charge for grace days ( i.e. firstremind ) so we need to skip
them for the number of holidays calculation
+ my ( $iYear, $iMonth, $iDay ) = split( /-/, $fineData->{'date_due'} );
+ ( $iYear, $iMonth, $iDay ) = Add_Delta_Days( $iYear, $iMonth, $iDay,
$issuing_rule->{'firstremind'} );
+ my $start_charging_date = "$iYear-$iMonth-$iDay";
+
+warn "CalculateFine: Date to Start Charging: $start_charging_date";
+warn "CalculateFine: First Remind: " . $issuing_rule->{'firstremind'};
+warn "CalculateFine: Holidays: " . _GetHolidaysBetween( $start_charging_date,
$return_date, $fineData->{'holdingbranch'} );
+
+ my $days_to_charge = $fineData->{'days_overdue'} -
$issuing_rule->{'firstremind'} - _GetHolidaysBetween( $start_charging_date,
$return_date, $fineData->{'holdingbranch'} );
+
+warn "CalculateFine: Days to Charge: $days_to_charge";
+
+ if ( $days_to_charge < 1 ) { return 0; } ## Short circuit for speed
+
+ my $fine = $days_to_charge * $issuing_rule->{'fine'} /
$issuing_rule->{'chargeperiod'};
+
+ if ( $fine > $maxFine ) { $fine = $maxFine; }
+
+warn "CalculateFine: Fine: $fine";
+
+ return $fine;
+}
+
+## Function CreateFine
+## This function accepts to arguments, $itembarcode and $itemnumber
+## Only one is required, if both are passed $itemnumber will be used.
+## NOTE: This function should be run right before an item is returned or
renewed.
+sub CreateFineOnReturn {
+ my ( $itembarcode, $itemnumber ) = @_;
+
+ warn "CreateFineOnReturn( $itembarcode, $itemnumber )";
+
+ my $dbh = C4::Context->dbh;
+
+ my $amount = CalculateFine( $itembarcode, $itemnumber );
+
+ warn "CreateFineOnReturn: Amount: $amount";
+
+ if ( $amount > 0 ) {
+ my $fineData = _GetFineData( $itembarcode, $itemnumber );
+ my $description = $fineData->{'title'} . " ( " . $fineData->{'barcode'} .
" ) on " . $fineData->{'date_due'};
+ UpdateFine( $fineData->{'itemnumber'}, $fineData->{'borrowernumber'},
$amount, my $type = 'F', $description );
+ }
+}
+
+## Function getFineData
+## This function returns an array associated array of data about the borrower
and the item
+## $future_date is an optional date ( YYYY-MM-DD ) for estimating a fine in
the future.
+sub _GetFineData {
+ my ( $itembarcode, $itemnumber, $future_date ) = @_;
+
+ my $diff_date = "NOW()";
+ if ( $future_date ) {
+ $diff_date = "DATE( $future_date )";
+ }
+
+ my $dbh = C4::Context->dbh;
+
+ my $sql = "SELECT items.itemnumber,
+ items.itemcallnumber,
+ issues.date_due,
+ issues.issue_date,
+ DATEDIFF( $diff_date, issues.date_due ) as days_overdue,
+ borrowers.borrowernumber,
+ borrowers.categorycode,
+ biblioitems.itemtype,
+ items.price,
+ items.barcode,
+ items.holdingbranch,
+ biblio.title
+ FROM items, issues, borrowers, biblio, biblioitems
+ WHERE
+ issues.itemnumber = items.itemnumber
+ AND borrowers.borrowernumber = issues.borrowernumber
+ AND items.biblionumber = biblioitems.biblionumber
+ AND items.biblionumber = biblio.biblionumber
+ AND issues.returndate IS NULL
+ ";
+
+ if ( $itembarcode ) {
+ $sql .= "AND items.barcode = ?";
+ } else {
+ $sql .= "AND items.itemnumber = ?";
+ }
+
+ my $sth = $dbh->prepare( $sql );
+
+ if ( $itembarcode ) {
+ $sth->execute( $itembarcode );
+ } else {
+ $sth->execute( $itemnumber );
+ }
+
+ my $fineData = $sth->fetchrow_hashref();
+
+ return $fineData;
+}
+
+## _GetIssuingRule takes the borrower categorycode, itemtype, and the item's
holdingbranch
+## And returns the proper issuing rule, if there is no exact issuing rule for
the combination,
+## it tries to match just the category code, if that fails it tries just the
itemtype
+## if that fails, it returns the default rule for the branch
+sub _GetIssuingRule {
+ my ( $categorycode, $itemtype, $holdingbranch ) = @_;
+
+ my $issuingrule = _CheckForIssuingRule( $categorycode, $itemtype,
$holdingbranch );
+ if ( $issuingrule ) { return $issuingrule; }
+
+ my $issuingrule = _CheckForIssuingRule( $categorycode, '', $holdingbranch );
+ if ( $issuingrule ) { return $issuingrule; }
+
+ my $issuingrule = _CheckForIssuingRule( '', $itemtype, $holdingbranch );
+ if ( $issuingrule ) { return $issuingrule; }
+
+ my $issuingrule = _CheckForIssuingRule( '', '', $holdingbranch );
+ return $issuingrule;
+
+}
+
+## Checks to see if there is an issuing rule for the given criteria
+## $categorycode and/or $itemtype can be empty to indicate wildcard
+## $holdingbranch is the current holdingbranch for the item
+## If the issuingrule exists, it returns a hashref for it, if not, it returns 0
+sub _CheckForIssuingRule {
+ my ( $categorycode, $itemtype, $holdingbranch ) = @_;
+
+ if ( ! $categorycode ) { $categorycode = "*"; }
+ if ( ! $itemtype ) { $itemtype = "*"; }
+
+ my $dbh = C4::Context->dbh;
+
+ my $sql = "SELECT * FROM issuingrules WHERE categorycode LIKE ? AND itemtype
LIKE ? AND branchcode LIKE ?";
+
+ my $sth = $dbh->prepare( $sql );
+
+ $sth->execute( $categorycode, $itemtype, $holdingbranch );
+
+ my $issuingrule = $sth->fetchrow_hashref();
+
+ return $issuingrule;
+}
+
+## Takes a starting and ending date
+## in the format YYYY-MM-DD
+## and returns the number of
+## holidays between the two dates
+sub _GetHolidaysBetween {
+ my ( $startDate, $endDate, $branchcode ) = @_;
+
+ my ( $sYear, $sMonth, $sDay ) = split( /-/, $startDate );
+ my ( $eYear, $eMonth, $eDay ) = split( /-/, $endDate );
+
+ my $holidaysCount = 0;
+
+ my $calendar = C4::Calendar->new( branchcode => $branchcode );
+
+ $holidaysCount += $calendar->isHoliday( $sDay, $sMonth, $sYear );
+
+ while ( mktime( 0, 0, 0, $sDay, $sMonth - 1, $sYear - 1900, 0, 0 ) <=
mktime( 0, 0, 0, $eDay, $eMonth - 1, $eYear - 1900, 0, 0 ) ) {
+ ( $sYear, $sMonth, $sDay ) = Add_Delta_Days( $sYear, $sMonth, $sDay, 1 );
+ $holidaysCount += $calendar->isHoliday( $sDay, $sMonth, $sYear );
+ }
+
+ return $holidaysCount;
+}
+
+1;
+__END__
+
+=back
+
+=head1 AUTHOR
+
+Koha Developement team <address@hidden>
+
+=cut
+
+
1;
__END__
- [Koha-cvs] koha/C4/Circulation Fines.pm [dev_week],
Kyle Hall <=