Koha/t/db_dependent/Overdues.t
Jonathan Druart 9d6d641d1f Bug 17600: Standardize our EXPORT_OK
On bug 17591 we discovered that there was something weird going on with
the way we export and use subroutines/modules.
This patch tries to standardize our EXPORT to use EXPORT_OK only.

That way we will need to explicitely define the subroutine we want to
use from a module.

This patch is a squashed version of:
Bug 17600: After export.pl
Bug 17600: After perlimport
Bug 17600: Manual changes
Bug 17600: Other manual changes after second perlimports run
Bug 17600: Fix tests

And a lot of other manual changes.

export.pl is a dirty script that can be found on bug 17600.

"perlimport" is:
git clone https://github.com/oalders/App-perlimports.git
cd App-perlimports/
cpanm --installdeps .
export PERL5LIB="$PERL5LIB:/kohadevbox/koha/App-perlimports/lib"
find . \( -name "*.pl" -o -name "*.pm" \) -exec perl App-perlimports/script/perlimports --inplace-edit --no-preserve-unused --filename {} \;

The ideas of this patch are to:
* use EXPORT_OK instead of EXPORT
* perltidy the EXPORT_OK list
* remove '&' before the subroutine names
* remove some uneeded use statements
* explicitely import the subroutines we need within the controllers or
modules

Note that the private subroutines (starting with _) should not be
exported (and not used from outside of the module except from tests).

EXPORT vs EXPORT_OK (from
https://www.thegeekstuff.com/2010/06/perl-exporter-examples/)
"""
Export allows to export the functions and variables of modules to user’s namespace using the standard import method. This way, we don’t need to create the objects for the modules to access it’s members.

@EXPORT and @EXPORT_OK are the two main variables used during export operation.

@EXPORT contains list of symbols (subroutines and variables) of the module to be exported into the caller namespace.

@EXPORT_OK does export of symbols on demand basis.
"""

If this patch caused a conflict with a patch you wrote prior to its
push:
* Make sure you are not reintroducing a "use" statement that has been
removed
* "$subroutine" is not exported by the C4::$MODULE module
means that you need to add the subroutine to the @EXPORT_OK list
* Bareword "$subroutine" not allowed while "strict subs"
means that you didn't imported the subroutine from the module:
  - use $MODULE qw( $subroutine list );
You can also use the fully qualified namespace: C4::$MODULE::$subroutine

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
2021-07-16 08:58:47 +02:00

565 lines
23 KiB
Perl
Executable file

#!/usr/bin/perl;
use Modern::Perl;
use Test::More tests => 17;
use Test::Warn;
use C4::Context;
use Koha::Database;
use Koha::Libraries;
use t::lib::Mocks;
use t::lib::TestBuilder;
use_ok('C4::Overdues', qw( GetOverdueMessageTransportTypes GetBranchcodesWithOverdueRules UpdateFine ));
can_ok('C4::Overdues', 'GetOverdueMessageTransportTypes');
can_ok('C4::Overdues', 'GetBranchcodesWithOverdueRules');
my $schema = Koha::Database->new->schema;
my $builder = t::lib::TestBuilder->new;
$schema->storage->txn_begin;
my $dbh = C4::Context->dbh;
$dbh->do(q|DELETE FROM letter|);
$dbh->do(q|DELETE FROM message_queue|);
$dbh->do(q|DELETE FROM message_transport_types|);
$dbh->do(q|DELETE FROM overduerules|);
$dbh->do(q|DELETE FROM overduerules_transport_types|);
$dbh->do(q|
INSERT INTO message_transport_types( message_transport_type ) VALUES ('email'), ('phone'), ('print'), ('sms')
|);
$dbh->do(q|
INSERT INTO overduerules ( overduerules_id, branchcode, categorycode ) VALUES
(1, 'CPL', 'PT'),
(2, 'CPL', 'YA'),
(3, '', 'PT'),
(4, '', 'YA')
|);
$dbh->do(q|INSERT INTO overduerules_transport_types (overduerules_id, letternumber, message_transport_type) VALUES
(1, 1, 'email'),
(1, 2, 'sms'),
(1, 3, 'email'),
(2, 3, 'print'),
(3, 1, 'email'),
(3, 2, 'email'),
(3, 2, 'sms'),
(3, 3, 'sms'),
(3, 3, 'email'),
(3, 3, 'print'),
(4, 2, 'sms')
|);
my $mtts;
$mtts = C4::Overdues::GetOverdueMessageTransportTypes('CPL', 'PT');
is( $mtts, undef, 'GetOverdueMessageTransportTypes: returns undef if no letternumber given' );
$mtts = C4::Overdues::GetOverdueMessageTransportTypes('CPL', undef, 1);
is( $mtts, undef, 'GetOverdueMessageTransportTypes: returns undef if no categorycode given' );
$mtts = C4::Overdues::GetOverdueMessageTransportTypes('CPL');
is( $mtts, undef, 'GetOverdueMessageTransportTypes: returns undef if no letternumber and categorycode given' );
$mtts = C4::Overdues::GetOverdueMessageTransportTypes('CPL', 'PT', 1);
is_deeply( $mtts, ['email'], 'GetOverdueMessageTransportTypes: first overdue is by email for PT (CPL)' );
$mtts = C4::Overdues::GetOverdueMessageTransportTypes('CPL', 'PT', 2);
is_deeply( $mtts, ['sms'], 'GetOverdueMessageTransportTypes: second overdue is by sms for PT (CPL)' );
$mtts = C4::Overdues::GetOverdueMessageTransportTypes('CPL', 'PT', 3);
is_deeply( $mtts, ['email'], 'GetOverdueMessageTransportTypes: third overdue is by email for PT (CPL)' );
$mtts = C4::Overdues::GetOverdueMessageTransportTypes('', 'PT', 1);
is_deeply( $mtts, ['email'], 'GetOverdueMessageTransportTypes: first overdue is by email for PT (default)' );
$mtts = C4::Overdues::GetOverdueMessageTransportTypes('', 'PT', 2);
is_deeply( $mtts, ['email', 'sms'], 'GetOverdueMessageTransportTypes: second overdue is by email and sms for PT (default)' );
$mtts = C4::Overdues::GetOverdueMessageTransportTypes('', 'PT', 3);
is_deeply( $mtts, ['print', 'sms', 'email'], 'GetOverdueMessageTransportTypes: third overdue is by print, sms and email for PT (default). With print in first.' );
# Test GetBranchcodesWithOverdueRules
$dbh->do(q|DELETE FROM overduerules|);
$dbh->do(q|
INSERT INTO overduerules
( branchcode,categorycode, delay1,letter1,debarred1, delay2,letter2,debarred2, delay3,letter3,debarred3 )
VALUES
( '', '', 1, 'LETTER_CODE1', 1, 5, 'LETTER_CODE2', 1, 10, 'LETTER_CODE3', 1 )
|);
my @branchcodes = map { $_->branchcode } Koha::Libraries->search;
my @overdue_branches = C4::Overdues::GetBranchcodesWithOverdueRules();
is_deeply( [ sort @overdue_branches ], [ sort @branchcodes ], 'If a default rule exists, all branches should be returned' );
$dbh->do(q|
INSERT INTO overduerules
( branchcode,categorycode, delay1,letter1,debarred1, delay2,letter2,debarred2, delay3,letter3,debarred3 )
VALUES
( 'CPL', '', 1, 'LETTER_CODE1', 1, 5, 'LETTER_CODE2', 1, 10, 'LETTER_CODE3', 1 )
|);
@overdue_branches = C4::Overdues::GetBranchcodesWithOverdueRules();
is_deeply( [ sort @overdue_branches ], [ sort @branchcodes ], 'If a default rule exists and a specific rule exists, all branches should be returned' );
$dbh->do(q|DELETE FROM overduerules|);
$dbh->do(q|
INSERT INTO overduerules
( branchcode,categorycode, delay1,letter1,debarred1, delay2,letter2,debarred2, delay3,letter3,debarred3 )
VALUES
( 'CPL', '', 1, 'LETTER_CODE1', 1, 5, 'LETTER_CODE2', 1, 10, 'LETTER_CODE3', 1 )
|);
@overdue_branches = C4::Overdues::GetBranchcodesWithOverdueRules();
is_deeply( \@overdue_branches, ['CPL'] , 'If only a specific rule exist, only 1 branch should be returned' );
$dbh->do(q|DELETE FROM overduerules|);
$dbh->do(q|
INSERT INTO overduerules
( branchcode,categorycode, delay1,letter1,debarred1, delay2,letter2,debarred2, delay3,letter3,debarred3 )
VALUES
( 'CPL', '', 1, 'LETTER_CODE1_CPL', 1, 5, 'LETTER_CODE2_CPL', 1, 10, 'LETTER_CODE3_CPL', 1 ),
( 'MPL', '', 1, 'LETTER_CODE1_MPL', 1, 5, 'LETTER_CODE2_MPL', 1, 10, 'LETTER_CODE3_MPL', 1 )
|);
@overdue_branches = C4::Overdues::GetBranchcodesWithOverdueRules();
is_deeply( \@overdue_branches, ['CPL', 'MPL'] , 'If only 2 specific rules exist, 2 branches should be returned' );
$schema->storage->txn_rollback;
subtest 'UpdateFine tests' => sub {
plan tests => 75;
$schema->storage->txn_begin;
t::lib::Mocks::mock_preference( 'MaxFine', '100' );
my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
my $item1 = $builder->build_sample_item();
my $item2 = $builder->build_sample_item();
my $checkout1 = $builder->build_object(
{
class => 'Koha::Checkouts',
value => { itemnumber => $item1->itemnumber, borrowernumber => $patron->id }
}
);
my $checkout2 = $builder->build_object(
{
class => 'Koha::Checkouts',
value => { itemnumber => $item2->itemnumber, borrowernumber => $patron->id }
}
);
# Try to add 0 amount fine
UpdateFine(
{
issue_id => $checkout1->issue_id,
itemnumber => $item1->itemnumber,
borrowernumber => $patron->borrowernumber,
amount => '0',
due => $checkout1->date_due
}
);
my $fines = Koha::Account::Lines->search(
{ borrowernumber => $patron->borrowernumber } );
is( $fines->count, 0, "No fine added when amount is 0" );
# Total : Outstanding : MaxFine
# 0 : 0 : 100
# Add fine 1 - First Item Overdue
UpdateFine(
{
issue_id => $checkout1->issue_id,
itemnumber => $item1->itemnumber,
borrowernumber => $patron->borrowernumber,
amount => '50',
due => $checkout1->date_due
}
);
$fines = Koha::Account::Lines->search(
{ borrowernumber => $patron->borrowernumber } );
is( $fines->count, 1, "Fine added when amount is greater than 0" );
my $fine = $fines->next;
is( $fine->amount+0, 50, "Fine amount correctly set to 50" );
is( $fine->amountoutstanding+0, 50, "Fine amountoutstanding correctly set to 50" );
is( $fine->issue_id, $checkout1->issue_id, "Fine is associated with the correct issue" );
is( $fine->itemnumber, $checkout1->itemnumber, "Fine is associated with the correct item" );
# Total : Outstanding : MaxFine
# 50 : 50 : 100
# Increase fine 1 - First Item Overdue
UpdateFine(
{
issue_id => $checkout1->issue_id,
itemnumber => $item1->itemnumber,
borrowernumber => $patron->borrowernumber,
amount => '80',
due => $checkout1->date_due
}
);
$fines = Koha::Account::Lines->search(
{ borrowernumber => $patron->borrowernumber } );
is( $fines->count, 1, "Existing fine updated" );
$fine = $fines->next;
is( $fine->amount+0, 80, "Fine amount correctly updated to 80" );
is( $fine->amountoutstanding+0, 80, "Fine amountoutstanding correctly updated to 80" );
# Total : Outstanding : MaxFine
# 80 : 80 : 100
# Add fine 2 - Second Item Overdue
UpdateFine(
{
issue_id => $checkout2->issue_id,
itemnumber => $item2->itemnumber,
borrowernumber => $patron->borrowernumber,
amount => '30',
due => $checkout2->date_due
}
);
$fines = Koha::Account::Lines->search(
{ borrowernumber => $patron->borrowernumber },
{ order_by => { '-asc' => 'accountlines_id' } }
);
is( $fines->count, 2, "New fine added for second checkout" );
$fine = $fines->next;
is( $fine->amount+0, 80, "First fine amount unchanged" );
is( $fine->amountoutstanding+0, 80, "First fine amountoutstanding unchanged" );
my $fine2 = $fines->next;
is( $fine2->amount+0, 20, "Second fine capped at '20' by MaxFine" );
is( $fine2->amountoutstanding+0, 20, "Second fine amountoutstanding capped at '20' by MaxFine" );
is( $fine2->issue_id, $checkout2->issue_id, "Second fine is associated with the correct issue" );
is( $fine2->itemnumber, $checkout2->itemnumber, "Second fine is associated with the correct item" );
is( $fine->amount + $fine2->amount, '100', "Total fines = 100" );
is( $fine->amountoutstanding + $fine2->amountoutstanding, '100', "Total outstanding = 100" );
# Total : Outstanding : MaxFine
# 100 : 100 : 100
# A day passes, the item is still overdue, update fine is called again
# we don't expect to increase above MaxFine of 100
UpdateFine(
{
issue_id => $checkout2->issue_id,
itemnumber => $item2->itemnumber,
borrowernumber => $patron->borrowernumber,
amount => '40',
due => $checkout2->date_due
}
);
$fines = Koha::Account::Lines->search(
{ borrowernumber => $patron->borrowernumber },
{ order_by => { '-asc' => 'accountlines_id' } }
);
is( $fines->count, 2, "Existing fine updated for second checkout, no new fine added" );
$fine = $fines->next;
is( $fine->amount+0, 80, "First fine amount unchanged" );
is( $fine->amountoutstanding+0, 80, "First fine amountoutstanding unchanged" );
$fine2 = $fines->next;
is( $fine2->amount+0, 20, "Second fine capped at '20' by MaxFine" );
is( $fine2->amountoutstanding+0, 20, "Second fine amountoutstanding capped at '20' by MaxFine" );
is( $fine2->issue_id, $checkout2->issue_id, "Second fine is associated with the correct issue" );
is( $fine2->itemnumber, $checkout2->itemnumber, "Second fine is associated with the correct item" );
is( $fine->amount + $fine2->amount, '100', "Total fines = 100" );
is( $fine->amountoutstanding + $fine2->amountoutstanding, '100', "Total outstanding = 100" );
# Total : Outstanding : MaxFine
# 100 : 100 : 100
# Partial pay fine 1
$fine->amountoutstanding(50)->store;
# Total : Outstanding : MaxFine
# 100 : 50 : 100
# Increase fine 2 - Second item overdue
UpdateFine(
{
issue_id => $checkout2->issue_id,
itemnumber => $item2->itemnumber,
borrowernumber => $patron->borrowernumber,
amount => '30',
due => $checkout2->date_due
}
);
$fines = Koha::Account::Lines->search(
{ borrowernumber => $patron->borrowernumber },
{ order_by => { '-asc' => 'accountlines_id' } }
);
is( $fines->count, 2, "Still two fines after second checkout update" );
$fine = $fines->next;
is( $fine->amount+0, 80, "First fine amount unchanged" );
is( $fine->amountoutstanding+0, 50, "First fine amountoutstanding unchanged" );
$fine2 = $fines->next;
is( $fine2->amount+0, 30, "Second fine increased after partial payment of first" );
is( $fine2->amountoutstanding+0, 30, "Second fine amountoutstanding increased after partial payment of first" );
is( $fine->amount + $fine2->amount, '110', "Total fines = 100" );
is( $fine->amountoutstanding + $fine2->amountoutstanding, '80', "Total outstanding = 80" );
# Total : Outstanding : MaxFine
# 110 : 80 : 100
# Fix fine 1 - First item renewed
$fine->status('RETURNED')->store;
# Add fine 3 - First item second overdue
UpdateFine(
{
issue_id => $checkout1->issue_id,
itemnumber => $item1->itemnumber,
borrowernumber => $patron->borrowernumber,
amount => '30',
due => $checkout1->date_due
}
);
$fines = Koha::Account::Lines->search(
{ borrowernumber => $patron->borrowernumber },
{ order_by => { '-asc' => 'accountlines_id' } }
);
is( $fines->count, 3, "Third fine added for overdue renewal" );
$fine = $fines->next;
is( $fine->amount+0, 80, "First fine amount unchanged" );
is( $fine->amountoutstanding+0, 50, "First fine amountoutstanding unchanged" );
$fine2 = $fines->next;
is( $fine2->amount+0, 30, "Second fine amount unchanged" );
is( $fine2->amountoutstanding+0, 30, "Second fine amountoutstanding unchanged" );
my $fine3 = $fines->next;
is( $fine3->amount+0, 20, "Third fine amount capped due to MaxFine" );
is( $fine3->amountoutstanding+0, 20, "Third fine amountoutstanding capped at '20' by MaxFine" );
is( $fine3->issue_id, $checkout1->issue_id, "Third fine is associated with the correct issue" );
is( $fine3->itemnumber, $checkout1->itemnumber, "Third fine is associated with the correct item" );
is( $fine->amount + $fine2->amount + $fine3->amount, '130', "Total fines = 130" );
is( $fine->amountoutstanding + $fine2->amountoutstanding + $fine3->amountoutstanding, '100', "Total outstanding = 100" );
# Total : Outstanding : MaxFine
# 130 : 100 : 100
# Payoff accruing fine and ensure next increment doesn't create a new one (bug #24146)
$fine3->amountoutstanding('0')->store;
is( $fine->amount + $fine2->amount + $fine3->amount, '130', "Total fines = 130" );
is( $fine->amountoutstanding + $fine2->amountoutstanding + $fine3->amountoutstanding, '80', "Total outstanding = 80" );
# Total : Outstanding : MaxFine
# 130 : 80 : 100
# Increase fine 3 - First item, second overdue increase
UpdateFine(
{
issue_id => $checkout1->issue_id,
itemnumber => $item1->itemnumber,
borrowernumber => $patron->borrowernumber,
amount => '50',
due => $checkout1->date_due
}
);
$fines = Koha::Account::Lines->search(
{ borrowernumber => $patron->borrowernumber },
{ order_by => { '-asc' => 'accountlines_id' } }
);
is( $fines->count, 3, "Still three fines after third checkout update" );
$fine = $fines->next;
is( $fine->amount+0, 80, "First fine amount unchanged" );
is( $fine->amountoutstanding+0, 50, "First fine amountoutstanding unchanged" );
$fine2 = $fines->next;
is( $fine2->amount+0, 30, "Second fine amount unchanged" );
is( $fine2->amountoutstanding+0, 30, "Second fine amountoutstanding unchanged" );
$fine3 = $fines->next;
is( $fine3->amount+0, 40, "Third fine amount capped due to MaxFine" );
is( $fine3->amountoutstanding+0, 20, "Third fine amountoutstanding increased ..." );
is( $fine3->issue_id, $checkout1->issue_id, "Third fine is associated with the correct issue" );
is( $fine3->itemnumber, $checkout1->itemnumber, "Third fine is associated with the correct item" );
is( $fine->amount + $fine2->amount + $fine3->amount, '150', "Total fines = 150" );
is( $fine->amountoutstanding + $fine2->amountoutstanding + $fine3->amountoutstanding, '100', "Total outstanding = 100" );
# Total : Outstanding : MaxFine
# 150 : 100 : 100
# FIXME: Add test to check whether sundry/manual charges are included within MaxFine.
# FIXME: Add test to ensure other charges are not included within MaxFine.
# Disable MaxFine
t::lib::Mocks::mock_preference( 'MaxFine', '0' );
UpdateFine(
{
issue_id => $checkout1->issue_id,
itemnumber => $item1->itemnumber,
borrowernumber => $patron->borrowernumber,
amount => '50',
due => $checkout1->date_due
}
);
$fines = Koha::Account::Lines->search(
{ borrowernumber => $patron->borrowernumber },
{ order_by => { '-asc' => 'accountlines_id' } }
);
is( $fines->count, 3, "Still only three fines after MaxFine cap removed" );
$fine = $fines->next;
is( $fine->amount+0, 80, "First fine amount unchanged" );
$fine2 = $fines->next;
is( $fine2->amount+0, 30, "Second fine amount unchanged" );
$fine3 = $fines->next;
is( $fine3->amount+0, 50, "Third fine increased now MaxFine cap is disabled" );
is( $fine3->amountoutstanding+0, 30, "Third fine increased now MaxFine cap is disabled" );
# If somehow the fine should be reduced, we changed rules or checkout date or something
UpdateFine(
{
issue_id => $checkout1->issue_id,
itemnumber => $item1->itemnumber,
borrowernumber => $patron->borrowernumber,
amount => '30',
due => $checkout1->date_due
}
);
$fines = Koha::Account::Lines->search(
{ borrowernumber => $patron->borrowernumber },
{ order_by => { '-asc' => 'accountlines_id' } }
);
is( $fines->count, 3, "Still only three fines after MaxFine cap removed and third fine altered" );
$fine = $fines->next;
is( $fine->amount+0, 80, "First fine amount unchanged" );
$fine2 = $fines->next;
is( $fine2->amount+0, 30, "Second fine amount unchanged" );
$fine3 = $fines->next;
is( $fine3->amount+0, 30, "Third fine reduced" );
is( $fine3->amountoutstanding+0, 10, "Third fine amount outstanding is reduced" );
# Ensure maxfine calculations work correctly for floats (bug #25127)
# 7.2 (maxfine) - 7.2 (total_amount_other) != 8.88178419700125e-16 (😢)
t::lib::Mocks::mock_preference( 'MaxFine', '7.2' );
my $patron_1 = $builder->build_object( { class => 'Koha::Patrons' } );
my $item_1 = $builder->build_sample_item();
my $item_2 = $builder->build_sample_item();
my $checkout_1 = $builder->build_object(
{
class => 'Koha::Checkouts',
value => {
itemnumber => $item_1->itemnumber,
borrowernumber => $patron_1->id
}
}
);
my $checkout_2 = $builder->build_object(
{
class => 'Koha::Checkouts',
value => {
itemnumber => $item_2->itemnumber,
borrowernumber => $patron->id
}
}
);
my $account = $patron_1->account;
$account->add_debit(
{
type => 'OVERDUE',
amount => '6.99',
issue_id => $checkout_1->issue_id,
interface => 'TEST'
}
);
$account->add_debit(
{
type => 'OVERDUE',
amount => '.10',
issue_id => $checkout_1->issue_id,
interface => 'TEST'
}
);
$account->add_debit(
{
type => 'OVERDUE',
amount => '.10',
issue_id => $checkout_1->issue_id,
interface => 'TEST'
}
);
$account->add_debit(
{
type => 'OVERDUE',
amount => '.01',
issue_id => $checkout_1->issue_id,
interface => 'TEST'
}
);
UpdateFine(
{
issue_id => $checkout_2->issue_id,
itemnumber => $item_2->itemnumber,
borrowernumber => $patron_1->borrowernumber,
amount => '.1',
due => $checkout_2->date_due
}
);
$fines = Koha::Account::Lines->search(
{ borrowernumber => $patron_1->borrowernumber },
{ order_by => { '-asc' => 'accountlines_id' } }
);
is( $fines->count, 4, "New amount should be 0 so no fine added" );
ok( C4::Circulation::AddReturn( $item_1->barcode, $item_1->homebranch, 1), "Returning the item and forgiving fines succeeds");
t::lib::Mocks::mock_preference( 'MaxFine', 0 );
# Ensure CalcFine calculations work correctly for floats (bug #27079)
# 1.800000 (amount from database) != 1.8~ (CalcFine of 0.15cents * 12units) (😢)
my $amount = 0.15 * 12;
UpdateFine(
{
issue_id => $checkout_2->issue_id,
itemnumber => $item_2->itemnumber,
borrowernumber => $patron_1->borrowernumber,
amount => $amount,
due => $checkout_2->date_due
}
);
$fine = Koha::Account::Lines->search({ issue_id => $checkout_2->issue_id })->single;
ok( $fine, 'Fine added for checkout 2');
is( $fine->amount, "1.800000", "Fine amount is 1.800000 as expected");
$fine->amountoutstanding(0)->store;
$fine->discard_changes;
is( $fine->amountoutstanding + 0, 0, "Fine was paid off");
UpdateFine(
{
issue_id => $checkout_2->issue_id,
itemnumber => $item_2->itemnumber,
borrowernumber => $patron_1->borrowernumber,
amount => $amount,
due => $checkout_2->date_due
}
);
my $refunds = Koha::Account::Lines->search({ itemnumber => $item_2->itemnumber, credit_type_code => 'OVERPAYMENT' });
is( $refunds->count, 0, "Overpayment refund not added when the amounts are equal" );
# Adding an OVERDUE fine not linked with a checkout (possible with historical OVERDUE fines)
$builder->build_object(
{
class => "Koha::Account::Lines",
value => {
borrowernumber => $patron_1->borrowernumber,
issue_id => undef,
debit_type_code => 'OVERDUE',
}
}
);
$fine->issue_id(undef)->store;
warnings_are {
UpdateFine(
{
issue_id => $checkout_2->issue_id,
itemnumber => $item_2->itemnumber,
borrowernumber => $patron_1->borrowernumber,
amount => $amount,
due => $checkout_2->date_due
}
);
} [], 'No warning generated if fine is not linked with a checkout';
$schema->storage->txn_rollback;
};