Bug 39405: Add hook overwrite_calc_fine to override CalcFine in Overdues.pm

This new hook allows to overwrite the koha standard calculation of fines.
This can be useful if your library has a fine policy with graduated fines
per overdue letter.

To test:
1) Apply patch.
2) Run prove -v t/db_dependent/Circulation/CalcFine.t
3) Run prove -v t/db_dependent/Koha/Plugins/Overdues.t
4) Sign off.

Sponsored-by: Karlsruhe Institute of Technology (KIT)
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
This commit is contained in:
Raphael Straub 2025-03-21 10:35:00 +00:00 committed by Katrin Fischer
parent 6e1d50f6a9
commit fa329e4a09
No known key found for this signature in database
GPG Key ID: 0EF6E2C03357A834
3 changed files with 140 additions and 3 deletions

View File

@ -93,14 +93,14 @@ sub Getoverdues {
if ( C4::Context->preference('item-level_itypes') ) {
$statement = "
SELECT issues.*, items.itype as itemtype, items.homebranch, items.barcode, items.itemlost, items.replacementprice, items.biblionumber, items.holdingbranch
FROM issues
FROM issues
LEFT JOIN items USING (itemnumber)
WHERE date_due < NOW()
";
} else {
$statement = "
SELECT issues.*, biblioitems.itemtype, items.itype, items.homebranch, items.barcode, items.itemlost, replacementprice, items.biblionumber, items.holdingbranch
FROM issues
FROM issues
LEFT JOIN items USING (itemnumber)
LEFT JOIN biblioitems USING (biblioitemnumber)
WHERE date_due < NOW()
@ -222,6 +222,22 @@ sub CalcFine {
# Skip calculations if item is not overdue
return ( 0, 0, 0 ) unless ( DateTime->compare( $due_dt, $end_date ) == -1 );
# Call the plugin hook overwrite_calc_fine of all plugins and return
# the first defined fine.
my @fines = Koha::Plugins->call(
'overwrite_calc_fine',
{
itemnumber => $item->{itemnumber},
categorycode => $bortype,
branchcode => $branchcode,
due_date => $due_dt,
end_date => $end_date,
}
);
foreach my $fine (@fines) {
return @$fine if ( defined $fine );
}
my $start_date = $due_dt->clone();
# get issuingrules (fines part will be used)
@ -661,7 +677,7 @@ C<$itemnum> is item number
C<$borrowernumber> is the borrowernumber
=cut
=cut
sub GetFine {
my ( $itemnum, $borrowernumber ) = @_;

View File

@ -0,0 +1,111 @@
#!/usr/bin/perl
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
# 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, see <http://www.gnu.org/licenses>.
use Modern::Perl;
use Test::NoWarnings;
use Test::More tests => 6;
use C4::Overdues qw(CalcFine);
use File::Basename;
use t::lib::Mocks;
use t::lib::TestBuilder;
BEGIN {
# Mock pluginsdir before loading Plugins module
my $path = dirname(__FILE__) . '/../../../lib/plugins';
t::lib::Mocks::mock_config( 'pluginsdir', $path );
use_ok('C4::Overdues');
use_ok('Koha::Plugins');
use_ok('Koha::Plugins::Handler');
use_ok('Koha::Plugin::Test');
}
t::lib::Mocks::mock_config( 'enable_plugins', 1 );
my $builder = t::lib::TestBuilder->new;
my $branch = $builder->build(
{
source => 'Branch',
}
);
my $category = $builder->build(
{
source => 'Category',
}
);
my $item = $builder->build_sample_item;
subtest 'overwrite_calc_fine hook tests' => sub {
plan tests => 6;
my $schema = Koha::Database->new->schema;
$schema->storage->txn_begin;
my $plugins = Koha::Plugins->new;
$plugins->InstallPlugins;
Koha::Plugin::Test->new->enable;
Koha::CirculationRules->set_rules(
{
branchcode => undef,
categorycode => undef,
itemtype => undef,
rules => {
fine => '2.00',
lengthunit => 'days',
finedays => 0,
firstremind => 0,
chargeperiod => 1,
overduefinescap => '0',
cap_fine_to_replacement_price => 0,
}
},
);
my $due_date = DateTime->new(
year => 2000,
month => 1,
day => 1,
);
my $end_date = DateTime->new(
year => 2000,
month => 1,
day => 30,
);
my ( $amount, $units, $chargable_units ) = CalcFine( $item->{itemnumber}, undef, undef, $due_date, $end_date );
is( $amount, 87, 'Amount is calculated correctly with custom function' );
is( $units, 29, 'Units are calculated correctly with custom function' );
is( $chargable_units, 27, 'Chargable units are calculated correctly with custom function' );
( $amount, $units, $chargable_units ) =
CalcFine( $item->{itemnumber}, $category->{categorycode}, $branch->{branchcode}, $due_date, $end_date );
is( $amount, 58, 'Amount is calculated correctly with original function' );
is( $units, 29, 'Units are calculated correctly with original function' );
is( $chargable_units, 29, 'Chargable units are calculated correctly with original function' );
Koha::Plugins->RemovePlugins;
$schema->storage->txn_rollback;
};

View File

@ -453,6 +453,16 @@ sub auth_client_get_user {
return;
}
sub overwrite_calc_fine {
my ( $self, $params ) = @_;
my $days = $params->{end_date}->delta_days( $params->{due_date} )->delta_days;
return $params->{categorycode} && $params->{branchcode}
? undef
: [ 3 * $days, $days, $days - 2 ];
}
sub _private_sub {
return "";
}