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:
parent
1c29873160
commit
4bb73229b8
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue