From d0e37a483cb8445c7830764eef9603694830b56d Mon Sep 17 00:00:00 2001 From: Tomas Cohen Arazi Date: Thu, 28 Jun 2018 15:52:01 -0300 Subject: [PATCH] Bug 20997: ->apply should be applied to Koha::Account::Lines This patch makes ->apply get passed an object set class instead of single account lines. The change is fully covered by tests. Signed-off-by: Tomas Cohen Arazi Signed-off-by: Jonathan Druart Signed-off-by: Nick Clemens --- Koha/Account/Line.pm | 56 ++++++++++++----------- t/db_dependent/Koha/Account/Lines.t | 69 ++++++++++++++++++++++------- 2 files changed, 83 insertions(+), 42 deletions(-) diff --git a/Koha/Account/Line.pm b/Koha/Account/Line.pm index 1962c7de1c..5a6a0210d4 100644 --- a/Koha/Account/Line.pm +++ b/Koha/Account/Line.pm @@ -128,14 +128,15 @@ sub void { =head3 apply - my $outstanding_amount = $credit->apply({ debit => $debit, [ offset_type => $offset_type ] }); + my $debits = $account->outstanding_debits; + my $outstanding_amount = $credit->apply({ debits => $debits, [ offset_type => $offset_type ] }); =cut sub apply { my ( $self, $params ) = @_; - my $debit = $params->{debit}; + my $debits = $params->{debits}; my $offset_type = $params->{offset_type} // 'credit_applied'; unless ( $self->is_credit ) { @@ -144,12 +145,6 @@ sub apply { ); } - unless ( $debit->is_debit ) { - Koha::Exceptions::Account::IsNotDebit->throw( - error => 'Account line ' . $debit->id . 'is not a debit' - ); - } - my $available_credit = $self->amountoutstanding * -1; unless ( $available_credit > 0 ) { @@ -161,30 +156,37 @@ sub apply { my $schema = Koha::Database->new->schema; $schema->txn_do( sub { + while ( my $debit = $debits->next ) { - my $amount_to_cancel; - my $owed = $debit->amountoutstanding; - - if ( $available_credit >= $owed ) { - $amount_to_cancel = $owed; - } - else { # $available_credit < $debit->amountoutstanding - $amount_to_cancel = $available_credit; - } + unless ( $debit->is_debit ) { + Koha::Exceptions::Account::IsNotDebit->throw( + error => 'Account line ' . $debit->id . 'is not a debit' + ); + } + my $amount_to_cancel; + my $owed = $debit->amountoutstanding; - # record the account offset - Koha::Account::Offset->new( - { credit_id => $self->id, - debit_id => $debit->id, - amount => $amount_to_cancel, - type => $offset_type, + if ( $available_credit >= $owed ) { + $amount_to_cancel = $owed; + } + else { # $available_credit < $debit->amountoutstanding + $amount_to_cancel = $available_credit; } - )->store(); - $available_credit -= $amount_to_cancel; + # record the account offset + Koha::Account::Offset->new( + { credit_id => $self->id, + debit_id => $debit->id, + amount => $amount_to_cancel, + type => $offset_type, + } + )->store(); + + $available_credit -= $amount_to_cancel; - $self->amountoutstanding( $available_credit * -1 )->store; - $debit->amountoutstanding( $owed - $amount_to_cancel )->store; + $self->amountoutstanding( $available_credit * -1 )->store; + $debit->amountoutstanding( $owed - $amount_to_cancel )->store; + } }); return $available_credit; diff --git a/t/db_dependent/Koha/Account/Lines.t b/t/db_dependent/Koha/Account/Lines.t index 4a666e5833..506be99cff 100755 --- a/t/db_dependent/Koha/Account/Lines.t +++ b/t/db_dependent/Koha/Account/Lines.t @@ -19,7 +19,7 @@ use Modern::Perl; -use Test::More tests => 3; +use Test::More tests => 4; use Test::Exception; use Koha::Account; @@ -161,11 +161,11 @@ subtest 'is_credit() and is_debit() tests' => sub { subtest 'apply() tests' => sub { - plan tests => 12; + plan tests => 24; $schema->storage->txn_begin; - my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); + my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); my $account = $patron->account; my $credit = $account->add_credit( { amount => 100, user_id => $patron->id } ); @@ -189,8 +189,9 @@ subtest 'apply() tests' => sub { $credit->discard_changes; $debit_1->discard_changes; - my $remaining_credit = $credit->apply( { debit => $debit_1, offset_type => 'Manual Credit' } ); - is( $remaining_credit, 90, 'Remaining credit is correctly calculated' ); + my $debits = Koha::Account::Lines->search({ accountlines_id => $debit_1->id }); + my $remaining_credit = $credit->apply( { debits => $debits, offset_type => 'Manual Credit' } ); + is( $remaining_credit * 1, 90, 'Remaining credit is correctly calculated' ); $credit->discard_changes; is( $credit->amountoutstanding * -1, $remaining_credit, 'Remaining credit correctly stored' ); @@ -200,32 +201,70 @@ subtest 'apply() tests' => sub { my $offsets = Koha::Account::Offsets->search( { credit_id => $credit->id, debit_id => $debit_1->id } ); is( $offsets->count, 1, 'Only one offset is generated' ); - my $THE_offest = $offsets->next; - is( $THE_offest->amount * 1, 10, 'Amount was calculated correctly (less than the available credit)' ); - is( $THE_offest->type, 'Manual Credit', 'Passed type stored correctly' ); + my $THE_offset = $offsets->next; + is( $THE_offset->amount * 1, 10, 'Amount was calculated correctly (less than the available credit)' ); + is( $THE_offset->type, 'Manual Credit', 'Passed type stored correctly' ); - $remaining_credit = $credit->apply( { debit => $debit_2, offset_type => 'Manual Credit' } ); + $debits = Koha::Account::Lines->search({ accountlines_id => $debit_2->id }); + $remaining_credit = $credit->apply( { debits => $debits } ); is( $remaining_credit, 0, 'No remaining credit left' ); $credit->discard_changes; is( $credit->amountoutstanding * 1, 0, 'No outstanding credit' ); $debit_2->discard_changes; is( $debit_2->amountoutstanding * 1, 10, 'Outstanding amount decremented correctly' ); + $offsets = Koha::Account::Offsets->search( { credit_id => $credit->id, debit_id => $debit_2->id } ); + is( $offsets->count, 1, 'Only one offset is generated' ); + $THE_offset = $offsets->next; + is( $THE_offset->amount * 1, 90, 'Amount was calculated correctly (less than the available credit)' ); + is( $THE_offset->type, 'credit_applied', 'Defaults to credit_applied offset type' ); + + $debits = Koha::Account::Lines->search({ accountlines_id => $debit_1->id }); + throws_ok + { $credit->apply({ debits => $debits }); } + 'Koha::Exceptions::Account::NoAvailableCredit', + '->apply() can only be used with outstanding credits'; + + $debits = Koha::Account::Lines->search({ accountlines_id => $credit->id }); throws_ok - { $debit_1->apply({ debit => $credit }); } + { $debit_1->apply({ debits => $debits }); } 'Koha::Exceptions::Account::IsNotCredit', '->apply() can only be used with credits'; + $debits = Koha::Account::Lines->search({ accountlines_id => $credit->id }); + my $credit_3 = $account->add_credit({ amount => 1 }); throws_ok - { $credit->apply({ debit => $credit }); } + { $credit_3->apply({ debits => $debits }); } 'Koha::Exceptions::Account::IsNotDebit', '->apply() can only be applied to credits'; - throws_ok - { $credit->apply({ debit => $debit_1 }); } - 'Koha::Exceptions::Account::NoAvailableCredit', - '->apply() can only be used with outstanding credits'; + my $credit_2 = $account->add_credit({ amount => 20 }); + my $debit_3 = Koha::Account::Line->new( + { borrowernumber => $patron->id, + accounttype => "F", + amount => 100, + amountoutstanding => 100 + } + )->store; + + $debits = Koha::Account::Lines->search({ accountlines_id => { -in => [ $debit_1->id, $debit_2->id, $debit_3->id, $credit->id ] } }); + throws_ok { + $credit_2->apply( { debits => $debits, offset_type => 'Manual Credit' } ); } + 'Koha::Exceptions::Account::IsNotDebit', + '->apply() rolls back if any of the passed lines is not a debit'; + + is( $debit_1->discard_changes->amountoutstanding * 1, 0, 'No changes to already cancelled debit' ); + is( $debit_2->discard_changes->amountoutstanding * 1, 10, 'Debit cancelled' ); + is( $debit_3->discard_changes->amountoutstanding * 1, 100, 'Outstanding amount correctly calculated' ); + is( $credit_2->discard_changes->amountoutstanding * -1, 20, 'No changes made' ); + + $debits = Koha::Account::Lines->search({ accountlines_id => { -in => [ $debit_1->id, $debit_2->id, $debit_3->id ] } }); + $remaining_credit = $credit_2->apply( { debits => $debits, offset_type => 'Manual Credit' } ); + is( $debit_1->discard_changes->amountoutstanding * 1, 0, 'No changes to already cancelled debit' ); + is( $debit_2->discard_changes->amountoutstanding * 1, 0, 'Debit cancelled' ); + is( $debit_3->discard_changes->amountoutstanding * 1, 90, 'Outstanding amount correctly calculated' ); + is( $credit_2->discard_changes->amountoutstanding * 1, 0, 'No remaining credit' ); $schema->storage->txn_rollback; }; -- 2.39.5