Bug 27636: Add payin_amount to Koha::Account

This patch adds a `payin_amount` method to the Koha::Account as a modern
replacement to the `pay` method.

The new method uses the `add_credit` and `Koha::Account::Line->apply`
methods internally for consistency and returns the created credit
Koha::Account::Line result.

Test plan
1/ Run t/db_dependent/Koha/Account.t

Signed-off-by: David Nind <david@davidnind.com>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
This commit is contained in:
Martin Renvoize 2021-02-05 12:56:43 +00:00 committed by Jonathan Druart
parent 1c29873160
commit 4bb73229b8
2 changed files with 217 additions and 1 deletions

View File

@ -485,6 +485,95 @@ sub add_credit {
return $line;
}
=head3 payin_amount
my $credit = $account->payin_amount(
{
amount => $amount,
credit_type => $credit_type,
payment_type => $payment_type,
cash_register => $register_id,
interface => $interface,
library_id => $branchcode,
user_id => $staff_id,
debits => $debit_lines,
description => $description,
note => $note
}
);
This method allows an amount to be paid into a patrons account and immediately applied against debts.
You can optionally pass a debts parameter which consists of an arrayref of Koha::Account::Line debit lines.
$credit_type can be any of:
- 'PAYMENT'
- 'WRITEOFF'
- 'FORGIVEN'
=cut
sub payin_amount {
my ( $self, $params ) = @_;
# check for mandatory params
my @mandatory = ( 'interface', 'amount', 'type' );
for my $param (@mandatory) {
unless ( defined( $params->{$param} ) ) {
Koha::Exceptions::MissingParameter->throw(
error => "The $param parameter is mandatory" );
}
}
# Check for mandatory register
Koha::Exceptions::Account::RegisterRequired->throw()
if ( C4::Context->preference("UseCashRegisters")
&& defined( $params->{payment_type} )
&& ( $params->{payment_type} eq 'CASH' )
&& !defined($params->{cash_register}) );
# amount should always be passed as a positive value
my $amount = $params->{amount};
unless ( $amount > 0 ) {
Koha::Exceptions::Account::AmountNotPositive->throw(
error => 'Payin amount passed is not positive' );
}
my $credit;
my $schema = Koha::Database->new->schema;
$schema->txn_do(
sub {
# Add payin credit
$credit = $self->add_credit($params);
# Offset debts passed first
if ( exists( $params->{debits} ) ) {
$credit = $credit->apply(
{
debits => $params->{debits},
offset_type => $params->{type}
}
);
}
# Offset against remaining balance if AutoReconcile
if ( C4::Context->preference("AccountAutoReconcile")
&& $credit->amountoutstanding != 0 )
{
$credit = $credit->apply(
{
debits => [ $self->outstanding_debits->as_list ],
offset_type => $params->{type}
}
);
}
}
);
return $credit;
}
=head3 add_debit
This method allows adding debits to a patron's account

View File

@ -19,7 +19,7 @@
use Modern::Perl;
use Test::More tests => 14;
use Test::More tests => 15;
use Test::MockModule;
use Test::Exception;
@ -1303,3 +1303,130 @@ subtest 'Koha::Account::payout_amount() tests' => sub {
$schema->storage->txn_rollback;
};
subtest 'Koha::Account::payin_amount() tests' => sub {
plan tests => 36;
$schema->storage->txn_begin;
# delete logs and statistics
my $action_logs = $schema->resultset('ActionLog')->search()->count;
my $statistics = $schema->resultset('Statistic')->search()->count;
my $staff = $builder->build_object( { class => 'Koha::Patrons' } );
my $library = $builder->build_object( { class => 'Koha::Libraries' } );
my $register =
$builder->build_object( { class => 'Koha::Cash::Registers' } );
my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
my $account =
Koha::Account->new( { patron_id => $patron->borrowernumber } );
is( $account->balance, 0, 'Test patron has no balance' );
my $payin_params = {
type => 'PAYMENT',
payment_type => 'CASH',
branch => $library->id,
register_id => $register->id,
staff_id => $staff->id,
interface => 'intranet',
amount => -10,
};
my @required_fields =
( 'interface', 'amount', 'type' );
for my $required_field (@required_fields) {
my $this_payin = { %{$payin_params} };
delete $this_payin->{$required_field};
throws_ok {
$account->payin_amount($this_payin);
}
'Koha::Exceptions::MissingParameter',
"Exception thrown if $required_field parameter missing";
}
throws_ok {
$account->payin_amount($payin_params);
}
'Koha::Exceptions::Account::AmountNotPositive',
'Expected validation exception thrown (amount not positive)';
$payin_params->{amount} = 10;
# Enable cash registers
t::lib::Mocks::mock_preference( 'UseCashRegisters', 1 );
throws_ok {
$account->payin_amount($payin_params);
}
'Koha::Exceptions::Account::RegisterRequired',
'Exception thrown for UseCashRegisters:1 + payment_type:CASH + cash_register:undef';
# Disable cash registers
t::lib::Mocks::mock_preference( 'UseCashRegisters', 0 );
# Enable AccountAutoReconcile
t::lib::Mocks::mock_preference( 'AccountAutoReconcile', 1 );
# Add some outstanding debits
my $debit_1 = $account->add_debit( { amount => 2, interface => 'commandline', type => 'OVERDUE' } );
my $debit_2 = $account->add_debit( { amount => 3, interface => 'commandline', type => 'OVERDUE' } );
my $debit_3 = $account->add_debit( { amount => 5, interface => 'commandline', type => 'OVERDUE' } );
my $debit_4 = $account->add_debit( { amount => 10, interface => 'commandline', type => 'OVERDUE' } );
my $debits = $account->outstanding_debits();
is( $debits->count, 4, "Found 4 debits with outstanding amounts" );
is( $debits->total_outstanding + 0, 20, "Total 20 outstanding debit" );
my $payin = $account->payin_amount($payin_params);
is(ref($payin), 'Koha::Account::Line', 'Return the Koha::Account::Line object for the payin');
is($payin->amount + 0, -10, "Payin amount recorded correctly");
is($payin->amountoutstanding + 0, 0, "Full amount was used to pay debts");
$debits = $account->outstanding_debits();
is($debits->count, 1, "Payin was applied against oldest outstanding debits first");
is($debits->total_outstanding + 0, 10, "Total of 10 outstanding debit remaining");
my $offsets = Koha::Account::Offsets->search( { credit_id => $payin->id } );
is( $offsets->count, 4, 'Four offsets generated' );
my $offset = $offsets->next;
is( $offset->type, 'Payment', 'Payment offset added for payin line' );
is( $offset->amount * 1, -10, 'Correct offset amount recorded' );
$offset = $offsets->next;
is( $offset->debit_id, $debit_1->id, "Offset added against debit_1");
is( $offset->type, 'PAYMENT', "Payment used for offset_type" );
is( $offset->amount * 1, -2, 'Correct amount offset against debit_1' );
$offset = $offsets->next;
is( $offset->debit_id, $debit_2->id, "Offset added against debit_2");
is( $offset->type, 'PAYMENT', "Payment used for offset_type" );
is( $offset->amount * 1, -3, 'Correct amount offset against debit_2' );
$offset = $offsets->next;
is( $offset->debit_id, $debit_3->id, "Offset added against debit_3");
is( $offset->type, 'PAYMENT', "Payment used for offset_type" );
is( $offset->amount * 1, -5, 'Correct amount offset against debit_3' );
my $debit_5 = $account->add_debit( { amount => 5, interface => 'commandline', type => 'OVERDUE' } );
$debits = $account->outstanding_debits();
is($debits->count, 2, "New debit added");
$payin_params->{amount} = 2.50;
$payin_params->{debits} = [$debit_5];
$payin = $account->payin_amount($payin_params);
$debits = $account->outstanding_debits();
is($debits->count, 2, "Second debit not fully paid off");
is($debits->total_outstanding + 0, 12.50, "12.50 outstanding debit remaining");
$debit_4->discard_changes;
$debit_5->discard_changes;
is($debit_4->amountoutstanding + 0, 10, "Debit 4 unaffected when debit_5 was passed to payin_amount");
is($debit_5->amountoutstanding + 0, 2.50, "Debit 5 correctly reduced when payin_amount called with debit_5 passed");
$offsets = Koha::Account::Offsets->search( { credit_id => $payin->id } );
is( $offsets->count, 2, 'Two offsets generated' );
$offset = $offsets->next;
is( $offset->type, 'Payment', 'Payment offset added for payin line' );
is( $offset->amount * 1, -2.50, 'Correct offset amount recorded' );
$offset = $offsets->next;
is( $offset->debit_id, $debit_5->id, "Offset added against debit_5");
is( $offset->type, 'PAYMENT', "PAYMENT used for offset_type" );
is( $offset->amount * 1, -2.50, 'Correct amount offset against debit_5' );
$schema->storage->txn_rollback;
};