From 5bff7d091946cdaff7ea621b77435f8d974161ae Mon Sep 17 00:00:00 2001 From: Raphael Straub Date: Fri, 21 Mar 2025 10:35:00 +0000 Subject: [PATCH] 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 Signed-off-by: Martin Renvoize --- C4/Overdues.pm | 22 ++++- t/db_dependent/Koha/Plugins/Overdues.t | 111 +++++++++++++++++++++++++ t/lib/plugins/Koha/Plugin/Test.pm | 10 +++ 3 files changed, 140 insertions(+), 3 deletions(-) create mode 100755 t/db_dependent/Koha/Plugins/Overdues.t diff --git a/C4/Overdues.pm b/C4/Overdues.pm index 4d6e50f27a8..314928e4230 100644 --- a/C4/Overdues.pm +++ b/C4/Overdues.pm @@ -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) @@ -655,7 +671,7 @@ C<$itemnum> is item number C<$borrowernumber> is the borrowernumber -=cut +=cut sub GetFine { my ( $itemnum, $borrowernumber ) = @_; diff --git a/t/db_dependent/Koha/Plugins/Overdues.t b/t/db_dependent/Koha/Plugins/Overdues.t new file mode 100755 index 00000000000..38a2e013dd9 --- /dev/null +++ b/t/db_dependent/Koha/Plugins/Overdues.t @@ -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 . + +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; +}; diff --git a/t/lib/plugins/Koha/Plugin/Test.pm b/t/lib/plugins/Koha/Plugin/Test.pm index f2f10330d35..4d9904da86e 100644 --- a/t/lib/plugins/Koha/Plugin/Test.pm +++ b/t/lib/plugins/Koha/Plugin/Test.pm @@ -448,6 +448,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 ""; } -- 2.49.0