[PATCH] bug_7420: Added overduefinescap to issuingrules
Replaced existing MaxFine syspref logic with overduefinescap. Repurposed MaxFine to be the overall overdue limit for all items overdue. Implemented new MaxFine logic in UpdateFine(). Signed-off-by: Elliott Davis <elliott@bywatersolutions.com> Tested according to Srdjan's test plan and everything worked like he said it would. I set fined equal to $2 and max fine equal to $1. When I ran the fines script for overdue items fines assessed were only $1. Signed-off-by: Paul Poulain <paul.poulain@biblibre.com>
This commit is contained in:
parent
54f363c0a6
commit
381794ff4e
10 changed files with 65 additions and 25 deletions
|
@ -1623,7 +1623,7 @@ sub AddReturn {
|
|||
|
||||
if ($borrowernumber) {
|
||||
if($issue->{'overdue'}){
|
||||
my ( $amount, $type, $daycounttotal ) = C4::Overdues::CalcFine( $item, $borrower->{categorycode},$branch, $datedue, $today );
|
||||
my ( $amount, $type, $unitcounttotal ) = C4::Overdues::CalcFine( $item, $borrower->{categorycode},$branch, $datedue, $today );
|
||||
$type ||= q{};
|
||||
if ( $amount > 0 && ( C4::Context->preference('finesMode') eq 'production' )) {
|
||||
C4::Overdues::UpdateFine(
|
||||
|
|
|
@ -241,8 +241,8 @@ C<$amount> is the fine owed by the patron (see above).
|
|||
C<$chargename> is the chargename field from the applicable record in
|
||||
the categoryitem table, whatever that is.
|
||||
|
||||
C<$daycount> is the number of days between start and end dates, Calendar adjusted (where needed),
|
||||
minus any applicable grace period.
|
||||
C<$unitcount> is the number of chargeable units (days between start and end dates, Calendar adjusted where needed,
|
||||
minus any applicable grace period, or hours)
|
||||
|
||||
FIXME - What is chargename supposed to be ?
|
||||
|
||||
|
@ -268,10 +268,9 @@ sub CalcFine {
|
|||
} else {
|
||||
# a zero (or null) chargeperiod means no charge.
|
||||
}
|
||||
if(C4::Context->preference('maxFine') && ( $amount > C4::Context->preference('maxFine'))) {
|
||||
$amount = C4::Context->preference('maxFine');
|
||||
}
|
||||
return ($amount, $data->{chargename}, $units_minus_grace);
|
||||
$amount = $data->{overduefinescap} if $data->{overduefinescap} && $amount > $data->{overduefinescap};
|
||||
$debug and warn sprintf("CalcFine returning (%s, %s, %s, %s)", $amount, $data->{'chargename'}, $units_minus_grace, $chargeable_units);
|
||||
return ($amount, $data->{'chargename'}, $units_minus_grace, $chargeable_units);
|
||||
# FIXME: chargename is NEVER populated anywhere.
|
||||
}
|
||||
|
||||
|
@ -521,14 +520,39 @@ sub UpdateFine {
|
|||
# "REF" is Cash Refund
|
||||
my $sth = $dbh->prepare(
|
||||
"SELECT * FROM accountlines
|
||||
WHERE itemnumber=?
|
||||
AND borrowernumber=?
|
||||
AND accounttype IN ('FU','O','F','M')
|
||||
AND description like ? "
|
||||
WHERE borrowernumber=?
|
||||
AND accounttype IN ('FU','O','F','M')"
|
||||
);
|
||||
$sth->execute( $itemnum, $borrowernumber, "%$due%" );
|
||||
$sth->execute( $borrowernumber );
|
||||
my $data;
|
||||
my $total_amount_other = 0.00;
|
||||
my $due_qr = qr/$due/;
|
||||
# Cycle through the fines and
|
||||
# - find line that relates to the requested $itemnum
|
||||
# - accumulate fines for other items
|
||||
# so we can update $itemnum fine taking in account fine caps
|
||||
while (my $rec = $sth->fetchrow_hashref) {
|
||||
if ($rec->{itemnumber} == $itemnum && $rec->{description} =~ /$due_qr/) {
|
||||
if ($data) {
|
||||
warn "Not a unique accountlines record for item $itemnum borrower $borrowernumber";
|
||||
} else {
|
||||
$data = $rec;
|
||||
next;
|
||||
}
|
||||
}
|
||||
$total_amount_other += $rec->{'amount'};
|
||||
}
|
||||
if (my $maxfine = C4::Context->preference('MaxFine')) {
|
||||
if ($total_amount_other + $amount > $maxfine) {
|
||||
my $new_amount = $maxfine - $total_amount_other;
|
||||
warn "Reducing fine for item $itemnum borrower $borrowernumber from $amount to $new_amount - MaxFine reached";
|
||||
return if $new_amount <= 0.00;
|
||||
|
||||
if ( my $data = $sth->fetchrow_hashref ) {
|
||||
$amount = $new_amount;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $data ) {
|
||||
|
||||
# we're updating an existing fine. Only modify if amount changed
|
||||
# Note that in the current implementation, you cannot pay against an accruing fine
|
||||
|
|
|
@ -101,8 +101,8 @@ elsif ($op eq 'delete-branch-item') {
|
|||
# save the values entered
|
||||
elsif ($op eq 'add') {
|
||||
my $sth_search = $dbh->prepare('SELECT COUNT(*) AS total FROM issuingrules WHERE branchcode=? AND categorycode=? AND itemtype=?');
|
||||
my $sth_insert = $dbh->prepare('INSERT INTO issuingrules (branchcode, categorycode, itemtype, maxissueqty, renewalsallowed, reservesallowed, issuelength, lengthunit, hardduedate, hardduedatecompare, fine, finedays, firstremind, chargeperiod,rentaldiscount) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)');
|
||||
my $sth_update=$dbh->prepare("UPDATE issuingrules SET fine=?, finedays=?, firstremind=?, chargeperiod=?, maxissueqty=?, renewalsallowed=?, reservesallowed=?, issuelength=?, lengthunit = ?, hardduedate=?, hardduedatecompare=?, rentaldiscount=? WHERE branchcode=? AND categorycode=? AND itemtype=?");
|
||||
my $sth_insert = $dbh->prepare('INSERT INTO issuingrules (branchcode, categorycode, itemtype, maxissueqty, renewalsallowed, reservesallowed, issuelength, lengthunit, hardduedate, hardduedatecompare, fine, finedays, firstremind, chargeperiod,rentaldiscount, overduefinescap) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)');
|
||||
my $sth_update=$dbh->prepare("UPDATE issuingrules SET fine=?, finedays=?, firstremind=?, chargeperiod=?, maxissueqty=?, renewalsallowed=?, reservesallowed=?, issuelength=?, lengthunit = ?, hardduedate=?, hardduedatecompare=?, rentaldiscount=?, overduefinescap=? WHERE branchcode=? AND categorycode=? AND itemtype=?");
|
||||
|
||||
my $br = $branch; # branch
|
||||
my $bor = $input->param('categorycode'); # borrower category
|
||||
|
@ -122,14 +122,15 @@ elsif ($op eq 'add') {
|
|||
$hardduedate = format_date_in_iso($hardduedate);
|
||||
my $hardduedatecompare = $input->param('hardduedatecompare');
|
||||
my $rentaldiscount = $input->param('rentaldiscount');
|
||||
my $overduefinescap = $input->param('overduefinescap') || undef;
|
||||
$debug and warn "Adding $br, $bor, $cat, $fine, $maxissueqty";
|
||||
|
||||
$sth_search->execute($br,$bor,$cat);
|
||||
my $res = $sth_search->fetchrow_hashref();
|
||||
if ($res->{total}) {
|
||||
$sth_update->execute($fine, $finedays,$firstremind, $chargeperiod, $maxissueqty, $renewalsallowed,$reservesallowed, $issuelength,$lengthunit, $hardduedate,$hardduedatecompare,$rentaldiscount, $br,$bor,$cat);
|
||||
$sth_update->execute($fine, $finedays,$firstremind, $chargeperiod, $maxissueqty, $renewalsallowed,$reservesallowed, $issuelength,$lengthunit, $hardduedate,$hardduedatecompare,$rentaldiscount,$overduefinescap, $br,$bor,$cat);
|
||||
} else {
|
||||
$sth_insert->execute($br,$bor,$cat,$maxissueqty,$renewalsallowed,$reservesallowed,$issuelength,$lengthunit,$hardduedate,$hardduedatecompare,$fine,$finedays,$firstremind,$chargeperiod,$rentaldiscount);
|
||||
$sth_insert->execute($br,$bor,$cat,$maxissueqty,$renewalsallowed,$reservesallowed,$issuelength,$lengthunit,$hardduedate,$hardduedatecompare,$fine,$finedays,$firstremind,$chargeperiod,$rentaldiscount,$overduefinescap);
|
||||
}
|
||||
}
|
||||
elsif ($op eq "set-branch-defaults") {
|
||||
|
|
|
@ -998,6 +998,7 @@ CREATE TABLE `issuingrules` ( -- circulation and fine rules
|
|||
`renewalsallowed` smallint(6) NOT NULL default "0", -- how many renewals are allowed
|
||||
`reservesallowed` smallint(6) NOT NULL default "0", -- how many holds are allowed
|
||||
`branchcode` varchar(10) NOT NULL default '', -- the branch this rule is for (branches.branchcode)
|
||||
overduefinescap decimal default NULL, -- the maximum amount of an overdue fine
|
||||
PRIMARY KEY (`branchcode`,`categorycode`,`itemtype`),
|
||||
KEY `categorycode` (`categorycode`),
|
||||
KEY `itemtype` (`itemtype`)
|
||||
|
|
|
@ -62,7 +62,7 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES
|
|||
-- this is selected by the web installer now
|
||||
-- INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('marcflavour','MARC21','Define global MARC flavor (MARC21 or UNIMARC) used for character encoding','MARC21|UNIMARC','Choice');
|
||||
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('MARCOrgCode','OSt','Define MARC Organization Code - http://www.loc.gov/marc/organizations/orgshome.html','','free');
|
||||
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('MaxFine',9999,'Maximum fine a patron can have for a single late return','','Integer');
|
||||
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('MaxFine',NULL,'Maximum fine a patron can have for all late returns at one moment. Single item caps are specified in the circulation rules matrix.','','Integer');
|
||||
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('maxoutstanding',5,'maximum amount withstanding to be able make holds','','Integer');
|
||||
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('maxreserves',50,'Define maximum number of holds a patron can place','','Integer');
|
||||
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('maxItemsInSearchResults',20,'Specify the maximum number of items to display for each result on a page of results',NULL,'free');
|
||||
|
|
|
@ -5536,9 +5536,6 @@ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
|
|||
SetVersion($DBversion);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$DBversion = "3.09.00.026";
|
||||
if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
|
||||
$dbh->do("INSERT INTO permissions (module_bit, code, description) VALUES
|
||||
|
@ -5556,6 +5553,19 @@ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
|
|||
SetVersion($DBversion);
|
||||
}
|
||||
|
||||
$DBversion = '3.09.00.027';
|
||||
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
|
||||
$dbh->do("ALTER TABLE issuingrules ADD overduefinescap decimal DEFAULT NULL");
|
||||
my $maxfine = C4::Context->preference('MaxFine');
|
||||
if ($maxfine && $maxfine < 900) { # an arbitrary value that tells us it's not "some huge value"
|
||||
$dbh->do("UPDATE issuingrules SET overduefinescap=?",undef,$maxfine);
|
||||
$dbh->do("UPDATE systempreferences SET value = NULL WHERE variable = 'MaxFine'");
|
||||
}
|
||||
$dbh->do("UPDATE systempreferences SET explanation = 'Maximum fine a patron can have for all late returns at one moment. Single item caps are specified in the circulation rules matrix.' WHERE variable = 'MaxFine'");
|
||||
print "Upgrade to $DBversion done (Bug 7420 add overduefinescap to circulation matrix)\n";
|
||||
SetVersion ($DBversion);
|
||||
}
|
||||
|
||||
=head1 FUNCTIONS
|
||||
|
||||
=head2 TableExists($table)
|
||||
|
|
|
@ -74,10 +74,11 @@ Patrons:
|
|||
no: "Don't allow"
|
||||
- "staff to access a patron's checkout history (it is stored regardless)."
|
||||
-
|
||||
- The late fine for a specific checkout will only go up to
|
||||
- The late fine for all checkouts will only go up to
|
||||
- pref: MaxFine
|
||||
class: currency
|
||||
- '[% local_currency %].'
|
||||
- Empty value means no limit. Single item caps are specified in the circulation rules matrix.
|
||||
-
|
||||
- pref: memberofinstitution
|
||||
choices:
|
||||
|
|
|
@ -72,6 +72,7 @@ for="tobranch"><strong>Clone these rules to:</strong></label> <input type="hidde
|
|||
<th>Fine amount</th>
|
||||
<th>Fine charging interval</th>
|
||||
<th>Fine grace period (day)</th>
|
||||
<th>Overdue Fines Cap ($)</th>
|
||||
<th>Suspension in days (day)</th>
|
||||
<th>Renewals allowed (count)</th>
|
||||
<th>Holds allowed (count)</th>
|
||||
|
@ -116,6 +117,7 @@ for="tobranch"><strong>Clone these rules to:</strong></label> <input type="hidde
|
|||
<td>[% rule.fine %]</td>
|
||||
<td>[% rule.chargeperiod %]</td>
|
||||
<td>[% rule.firstremind %]</td>
|
||||
<td>[% rule.overduefinescap FILTER format("%.2f") %]</td>
|
||||
<td>[% rule.finedays %]</td>
|
||||
<td>[% rule.renewalsallowed %]</td>
|
||||
<td>[% rule.reservesallowed %]</td>
|
||||
|
@ -161,6 +163,7 @@ for="tobranch"><strong>Clone these rules to:</strong></label> <input type="hidde
|
|||
<td><input name="fine" size="4" /></td>
|
||||
<td><input name="chargeperiod" size="2" /></td>
|
||||
<td><input name="firstremind" size="2" /> </td>
|
||||
<td><input name="overduefinescap" size="6" /> </td>
|
||||
<td><input name="finedays" size="3" /> </td>
|
||||
<td><input name="renewalsallowed" size="2" /></td>
|
||||
<td><input name="reservesallowed" size="2" /></td>
|
||||
|
|
|
@ -110,7 +110,7 @@ for my $overdue ( @{$overdues} ) {
|
|||
}
|
||||
++$counted;
|
||||
|
||||
my ( $amount, $type, $daycounttotal ) =
|
||||
my ( $amount, $type, $unitcounttotal ) =
|
||||
CalcFine( $overdue, $borrower->{categorycode},
|
||||
$branchcode, $datedue, $today );
|
||||
|
||||
|
@ -131,7 +131,7 @@ for my $overdue ( @{$overdues} ) {
|
|||
push @cells,
|
||||
map { defined $borrower->{$_} ? $borrower->{$_} : q{} } @borrower_fields;
|
||||
push @cells, map { $overdue->{$_} } @item_fields;
|
||||
push @cells, $type, $daycounttotal, $amount;
|
||||
push @cells, $type, $unitcounttotal, $amount;
|
||||
say {$fh} join $delim, @cells;
|
||||
}
|
||||
close $fh;
|
||||
|
|
|
@ -176,7 +176,7 @@ for ( my $i = 0 ; $i < scalar(@$data) ; $i++ ) {
|
|||
( $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 );
|
||||
my ( $amount, $type, $unitcounttotal, $unitcount ) = CalcFine( $data->[$i], $borrower->{'categorycode'}, $branchcode, undef, undef, $datedue, $today );
|
||||
|
||||
# Reassign fine's amount if specified in command-line
|
||||
$amount = $catamounts{$borrower->{'categorycode'}} if (defined $catamounts{$borrower->{'categorycode'}});
|
||||
|
|
Loading…
Reference in a new issue