Bugzilla – Attachment 97821 Details for
Bug 23355
Add a 'cashup' process to accounts
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 23355: Split tests for Line vs Lines
Bug-23355-Split-tests-for-Line-vs-Lines.patch (text/plain), 70.46 KB, created by
Martin Renvoize (ashimema)
on 2020-01-23 14:16:02 UTC
(
hide
)
Description:
Bug 23355: Split tests for Line vs Lines
Filename:
MIME Type:
Creator:
Martin Renvoize (ashimema)
Created:
2020-01-23 14:16:02 UTC
Size:
70.46 KB
patch
obsolete
>From 9d6083776332c39aa8ee698ac227f6844ec7a24b Mon Sep 17 00:00:00 2001 >From: Martin Renvoize <martin.renvoize@ptfs-europe.com> >Date: Thu, 23 Jan 2020 13:39:44 +0000 >Subject: [PATCH] Bug 23355: Split tests for Line vs Lines > >This patch simply splits the existing tests for accountlines into two >test files, one for the singular object and one for the set. > >Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com> >--- > t/db_dependent/Koha/Account/Line.t | 913 ++++++++++++++++++++++++++++ > t/db_dependent/Koha/Account/Lines.t | 891 +-------------------------- > 2 files changed, 919 insertions(+), 885 deletions(-) > create mode 100644 t/db_dependent/Koha/Account/Line.t > >diff --git a/t/db_dependent/Koha/Account/Line.t b/t/db_dependent/Koha/Account/Line.t >new file mode 100644 >index 0000000000..d62a38d531 >--- /dev/null >+++ b/t/db_dependent/Koha/Account/Line.t >@@ -0,0 +1,913 @@ >+#!/usr/bin/perl >+ >+# Copyright 2018 Koha Development team >+# >+# 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 <http://www.gnu.org/licenses> >+ >+use Modern::Perl; >+ >+use Test::More tests => 8; >+use Test::Exception; >+ >+use C4::Circulation qw/AddIssue AddReturn/; >+use Koha::Account; >+use Koha::Account::Lines; >+use Koha::Account::Offsets; >+use Koha::Items; >+ >+use t::lib::Mocks; >+use t::lib::TestBuilder; >+ >+my $schema = Koha::Database->new->schema; >+my $builder = t::lib::TestBuilder->new; >+ >+subtest 'patron() tests' => sub { >+ >+ plan tests => 3; >+ >+ $schema->storage->txn_begin; >+ >+ my $library = $builder->build( { source => 'Branch' } ); >+ my $patron = $builder->build( { source => 'Borrower' } ); >+ >+ my $line = Koha::Account::Line->new( >+ { >+ borrowernumber => $patron->{borrowernumber}, >+ debit_type_code => "OVERDUE", >+ status => "RETURNED", >+ amount => 10, >+ interface => 'commandline', >+ })->store; >+ >+ my $account_line_patron = $line->patron; >+ is( ref( $account_line_patron ), 'Koha::Patron', 'Koha::Account::Line->patron should return a Koha::Patron' ); >+ is( $line->borrowernumber, $account_line_patron->borrowernumber, 'Koha::Account::Line->patron should return the correct borrower' ); >+ >+ $line->borrowernumber(undef)->store; >+ is( $line->patron, undef, 'Koha::Account::Line->patron should return undef if no patron linked' ); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'item() tests' => sub { >+ >+ plan tests => 3; >+ >+ $schema->storage->txn_begin; >+ >+ my $library = $builder->build( { source => 'Branch' } ); >+ my $biblioitem = $builder->build( { source => 'Biblioitem' } ); >+ my $patron = $builder->build( { source => 'Borrower' } ); >+ my $item = Koha::Item->new( >+ { >+ biblionumber => $biblioitem->{biblionumber}, >+ biblioitemnumber => $biblioitem->{biblioitemnumber}, >+ homebranch => $library->{branchcode}, >+ holdingbranch => $library->{branchcode}, >+ barcode => 'some_barcode_12', >+ itype => 'BK', >+ })->store; >+ >+ my $line = Koha::Account::Line->new( >+ { >+ borrowernumber => $patron->{borrowernumber}, >+ itemnumber => $item->itemnumber, >+ debit_type_code => "OVERDUE", >+ status => "RETURNED", >+ amount => 10, >+ interface => 'commandline', >+ })->store; >+ >+ my $account_line_item = $line->item; >+ is( ref( $account_line_item ), 'Koha::Item', 'Koha::Account::Line->item should return a Koha::Item' ); >+ is( $line->itemnumber, $account_line_item->itemnumber, 'Koha::Account::Line->item should return the correct item' ); >+ >+ $line->itemnumber(undef)->store; >+ is( $line->item, undef, 'Koha::Account::Line->item should return undef if no item linked' ); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'is_credit() and is_debit() tests' => sub { >+ >+ plan tests => 4; >+ >+ $schema->storage->txn_begin; >+ >+ my $patron = $builder->build_object({ class => 'Koha::Patrons' }); >+ my $account = $patron->account; >+ >+ my $credit = $account->add_credit({ amount => 100, user_id => $patron->id, interface => 'commandline' }); >+ >+ ok( $credit->is_credit, 'is_credit detects credits' ); >+ ok( !$credit->is_debit, 'is_debit detects credits' ); >+ >+ my $debit = Koha::Account::Line->new( >+ { >+ borrowernumber => $patron->id, >+ debit_type_code => "OVERDUE", >+ status => "RETURNED", >+ amount => 10, >+ interface => 'commandline', >+ })->store; >+ >+ ok( !$debit->is_credit, 'is_credit detects debits' ); >+ ok( $debit->is_debit, 'is_debit detects debits'); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'apply() tests' => sub { >+ >+ plan tests => 24; >+ >+ $schema->storage->txn_begin; >+ >+ my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); >+ my $account = $patron->account; >+ >+ my $credit = $account->add_credit( { amount => 100, user_id => $patron->id, interface => 'commandline' } ); >+ >+ my $debit_1 = Koha::Account::Line->new( >+ { borrowernumber => $patron->id, >+ debit_type_code => "OVERDUE", >+ status => "RETURNED", >+ amount => 10, >+ amountoutstanding => 10, >+ interface => 'commandline', >+ } >+ )->store; >+ >+ my $debit_2 = Koha::Account::Line->new( >+ { borrowernumber => $patron->id, >+ debit_type_code => "OVERDUE", >+ status => "RETURNED", >+ amount => 100, >+ amountoutstanding => 100, >+ interface => 'commandline', >+ } >+ )->store; >+ >+ $credit->discard_changes; >+ $debit_1->discard_changes; >+ >+ my $debits = Koha::Account::Lines->search({ accountlines_id => $debit_1->id }); >+ my $remaining_credit = $credit->apply( { debits => [ $debits->as_list ], 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' ); >+ >+ # re-read debit info >+ $debit_1->discard_changes; >+ is( $debit_1->amountoutstanding * 1, 0, 'Debit has been cancelled' ); >+ >+ 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_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' ); >+ >+ $debits = Koha::Account::Lines->search({ accountlines_id => $debit_2->id }); >+ $remaining_credit = $credit->apply( { debits => [ $debits->as_list ] } ); >+ 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->as_list ] }); } >+ '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({ debits => [ $debits->as_list ] }); } >+ '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, interface => 'commandline' }); >+ throws_ok >+ { $credit_3->apply({ debits => [ $debits->as_list ] }); } >+ 'Koha::Exceptions::Account::IsNotDebit', >+ '->apply() can only be applied to credits'; >+ >+ my $credit_2 = $account->add_credit({ amount => 20, interface => 'commandline' }); >+ my $debit_3 = Koha::Account::Line->new( >+ { borrowernumber => $patron->id, >+ debit_type_code => "OVERDUE", >+ status => "RETURNED", >+ amount => 100, >+ amountoutstanding => 100, >+ interface => 'commandline', >+ } >+ )->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->as_list ], 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->as_list ], 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; >+}; >+ >+subtest 'Keep account info when related patron, staff, item or cash_register is deleted' => sub { >+ >+ plan tests => 4; >+ >+ $schema->storage->txn_begin; >+ >+ my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); >+ my $staff = $builder->build_object( { class => 'Koha::Patrons' } ); >+ my $item = $builder->build_object({ class => 'Koha::Items' }); >+ my $issue = $builder->build_object( >+ { >+ class => 'Koha::Checkouts', >+ value => { itemnumber => $item->itemnumber } >+ } >+ ); >+ my $register = $builder->build_object({ class => 'Koha::Cash::Registers' }); >+ >+ my $line = Koha::Account::Line->new( >+ { >+ borrowernumber => $patron->borrowernumber, >+ manager_id => $staff->borrowernumber, >+ itemnumber => $item->itemnumber, >+ debit_type_code => "OVERDUE", >+ status => "RETURNED", >+ amount => 10, >+ interface => 'commandline', >+ register_id => $register->id >+ })->store; >+ >+ $issue->delete; >+ $item->delete; >+ $line = $line->get_from_storage; >+ is( $line->itemnumber, undef, "The account line should not be deleted when the related item is delete"); >+ >+ $staff->delete; >+ $line = $line->get_from_storage; >+ is( $line->manager_id, undef, "The account line should not be deleted when the related staff is delete"); >+ >+ $patron->delete; >+ $line = $line->get_from_storage; >+ is( $line->borrowernumber, undef, "The account line should not be deleted when the related patron is delete"); >+ >+ $register->delete; >+ $line = $line->get_from_storage; >+ is( $line->register_id, undef, "The account line should not be deleted when the related cash register is delete"); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'adjust() tests' => sub { >+ >+ plan tests => 29; >+ >+ $schema->storage->txn_begin; >+ >+ # count logs before any actions >+ my $action_logs = $schema->resultset('ActionLog')->search()->count; >+ >+ # Disable logs >+ t::lib::Mocks::mock_preference( 'FinesLog', 0 ); >+ >+ my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); >+ my $account = $patron->account; >+ >+ my $debit_1 = Koha::Account::Line->new( >+ { borrowernumber => $patron->id, >+ debit_type_code => "OVERDUE", >+ status => "RETURNED", >+ amount => 10, >+ amountoutstanding => 10, >+ interface => 'commandline', >+ } >+ )->store; >+ >+ my $debit_2 = Koha::Account::Line->new( >+ { borrowernumber => $patron->id, >+ debit_type_code => "OVERDUE", >+ status => "UNRETURNED", >+ amount => 100, >+ amountoutstanding => 100, >+ interface => 'commandline' >+ } >+ )->store; >+ >+ my $credit = $account->add_credit( { amount => 40, user_id => $patron->id, interface => 'commandline' } ); >+ >+ throws_ok { $debit_1->adjust( { amount => 50, type => 'bad', interface => 'commandline' } ) } >+ qr/Update type not recognised/, 'Exception thrown for unrecognised type'; >+ >+ throws_ok { $debit_1->adjust( { amount => 50, type => 'overdue_update', interface => 'commandline' } ) } >+ qr/Update type not allowed on this debit_type/, >+ 'Exception thrown for type conflict'; >+ >+ # Increment an unpaid fine >+ $debit_2->adjust( { amount => 150, type => 'overdue_update', interface => 'commandline' } )->discard_changes; >+ >+ is( $debit_2->amount * 1, 150, 'Fine amount was updated in full' ); >+ is( $debit_2->amountoutstanding * 1, 150, 'Fine amountoutstanding was update in full' ); >+ isnt( $debit_2->date, undef, 'Date has been set' ); >+ >+ my $offsets = Koha::Account::Offsets->search( { debit_id => $debit_2->id } ); >+ is( $offsets->count, 1, 'An offset is generated for the increment' ); >+ my $THIS_offset = $offsets->next; >+ is( $THIS_offset->amount * 1, 50, 'Amount was calculated correctly (increment by 50)' ); >+ is( $THIS_offset->type, 'OVERDUE_INCREASE', 'Adjust type stored correctly' ); >+ >+ is( $schema->resultset('ActionLog')->count(), $action_logs + 0, 'No log was added' ); >+ >+ # Update fine to partially paid >+ my $debits = Koha::Account::Lines->search({ accountlines_id => $debit_2->id }); >+ $credit->apply( { debits => [ $debits->as_list ], offset_type => 'Manual Credit' } ); >+ >+ $debit_2->discard_changes; >+ is( $debit_2->amount * 1, 150, 'Fine amount unaffected by partial payment' ); >+ is( $debit_2->amountoutstanding * 1, 110, 'Fine amountoutstanding updated by partial payment' ); >+ >+ # Enable logs >+ t::lib::Mocks::mock_preference( 'FinesLog', 1 ); >+ >+ # Increment the partially paid fine >+ $debit_2->adjust( { amount => 160, type => 'overdue_update', interface => 'commandline' } )->discard_changes; >+ >+ is( $debit_2->amount * 1, 160, 'Fine amount was updated in full' ); >+ is( $debit_2->amountoutstanding * 1, 120, 'Fine amountoutstanding was updated by difference' ); >+ >+ $offsets = Koha::Account::Offsets->search( { debit_id => $debit_2->id } ); >+ is( $offsets->count, 3, 'An offset is generated for the increment' ); >+ $THIS_offset = $offsets->last; >+ is( $THIS_offset->amount * 1, 10, 'Amount was calculated correctly (increment by 10)' ); >+ is( $THIS_offset->type, 'OVERDUE_INCREASE', 'Adjust type stored correctly' ); >+ >+ is( $schema->resultset('ActionLog')->count(), $action_logs + 1, 'Log was added' ); >+ >+ # Decrement the partially paid fine, less than what was paid >+ $debit_2->adjust( { amount => 50, type => 'overdue_update', interface => 'commandline' } )->discard_changes; >+ >+ is( $debit_2->amount * 1, 50, 'Fine amount was updated in full' ); >+ is( $debit_2->amountoutstanding * 1, 10, 'Fine amountoutstanding was updated by difference' ); >+ >+ $offsets = Koha::Account::Offsets->search( { debit_id => $debit_2->id } ); >+ is( $offsets->count, 4, 'An offset is generated for the decrement' ); >+ $THIS_offset = $offsets->last; >+ is( $THIS_offset->amount * 1, -110, 'Amount was calculated correctly (decrement by 110)' ); >+ is( $THIS_offset->type, 'OVERDUE_DECREASE', 'Adjust type stored correctly' ); >+ >+ # Decrement the partially paid fine, more than what was paid >+ $debit_2->adjust( { amount => 30, type => 'overdue_update', interface => 'commandline' } )->discard_changes; >+ is( $debit_2->amount * 1, 30, 'Fine amount was updated in full' ); >+ is( $debit_2->amountoutstanding * 1, 0, 'Fine amountoutstanding was zeroed (payment was 40)' ); >+ >+ $offsets = Koha::Account::Offsets->search( { debit_id => $debit_2->id } ); >+ is( $offsets->count, 5, 'An offset is generated for the decrement' ); >+ $THIS_offset = $offsets->last; >+ is( $THIS_offset->amount * 1, -20, 'Amount was calculated correctly (decrement by 20)' ); >+ is( $THIS_offset->type, 'OVERDUE_DECREASE', 'Adjust type stored correctly' ); >+ >+ my $overpayment_refund = $account->lines->last; >+ is( $overpayment_refund->amount * 1, -10, 'A new credit has been added' ); >+ is( $overpayment_refund->description, 'Overpayment refund', 'Credit generated with the expected description' ); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'checkout() tests' => sub { >+ plan tests => 6; >+ >+ $schema->storage->txn_begin; >+ >+ my $library = $builder->build_object( { class => 'Koha::Libraries' } ); >+ my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); >+ my $item = $builder->build_sample_item; >+ my $account = $patron->account; >+ >+ t::lib::Mocks::mock_userenv({ branchcode => $library->branchcode }); >+ my $checkout = AddIssue( $patron->unblessed, $item->barcode ); >+ >+ my $line = $account->add_debit({ >+ amount => 10, >+ interface => 'commandline', >+ item_id => $item->itemnumber, >+ issue_id => $checkout->issue_id, >+ type => 'OVERDUE', >+ }); >+ >+ my $line_checkout = $line->checkout; >+ is( ref($line_checkout), 'Koha::Checkout', 'Result type is correct' ); >+ is( $line_checkout->issue_id, $checkout->issue_id, 'Koha::Account::Line->checkout should return the correct checkout'); >+ >+ my ( $returned, undef, $old_checkout) = C4::Circulation::AddReturn( $item->barcode, $library->branchcode ); >+ is( $returned, 1, 'The item should have been returned' ); >+ >+ $line = $line->get_from_storage; >+ my $old_line_checkout = $line->checkout; >+ is( ref($old_line_checkout), 'Koha::Old::Checkout', 'Result type is correct' ); >+ is( $old_line_checkout->issue_id, $old_checkout->issue_id, 'Koha::Account::Line->checkout should return the correct old_checkout' ); >+ >+ $line->issue_id(undef)->store; >+ is( $line->checkout, undef, 'Koha::Account::Line->checkout should return undef if no checkout linked' ); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'credits() and debits() tests' => sub { >+ plan tests => 10; >+ >+ $schema->storage->txn_begin; >+ >+ my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); >+ my $account = $patron->account; >+ >+ my $debit1 = $account->add_debit({ >+ amount => 8, >+ interface => 'commandline', >+ type => 'ACCOUNT', >+ }); >+ my $debit2 = $account->add_debit({ >+ amount => 12, >+ interface => 'commandline', >+ type => 'ACCOUNT', >+ }); >+ my $credit1 = $account->add_credit({ >+ amount => 5, >+ interface => 'commandline', >+ type => 'CREDIT', >+ }); >+ my $credit2 = $account->add_credit({ >+ amount => 10, >+ interface => 'commandline', >+ type => 'CREDIT', >+ }); >+ >+ $credit1->apply({ debits => [ $debit1 ] }); >+ $credit2->apply({ debits => [ $debit1, $debit2 ] }); >+ >+ my $credits = $debit1->credits; >+ is($credits->count, 2, '2 Credits applied to debit 1'); >+ my $credit = $credits->next; >+ is($credit->amount + 0, -5, 'Correct first credit'); >+ $credit = $credits->next; >+ is($credit->amount + 0, -10, 'Correct second credit'); >+ >+ $credits = $debit2->credits; >+ is($credits->count, 1, '1 Credits applied to debit 2'); >+ $credit = $credits->next; >+ is($credit->amount + 0, -10, 'Correct first credit'); >+ >+ my $debits = $credit1->debits; >+ is($debits->count, 1, 'Credit 1 applied to 1 debit'); >+ my $debit = $debits->next; >+ is($debit->amount + 0, 8, 'Correct first debit'); >+ >+ $debits = $credit2->debits; >+ is($debits->count, 2, 'Credit 2 applied to 2 debits'); >+ $debit = $debits->next; >+ is($debit->amount + 0, 8, 'Correct first debit'); >+ $debit = $debits->next; >+ is($debit->amount + 0, 12, 'Correct second debit'); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest "void() tests" => sub { >+ >+ plan tests => 16; >+ >+ $schema->storage->txn_begin; >+ >+ # Create a borrower >+ my $categorycode = $builder->build({ source => 'Category' })->{ categorycode }; >+ my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode }; >+ >+ my $borrower = Koha::Patron->new( { >+ cardnumber => 'dariahall', >+ surname => 'Hall', >+ firstname => 'Daria', >+ } ); >+ $borrower->categorycode( $categorycode ); >+ $borrower->branchcode( $branchcode ); >+ $borrower->store; >+ >+ my $account = Koha::Account->new({ patron_id => $borrower->id }); >+ >+ my $line1 = Koha::Account::Line->new( >+ { >+ borrowernumber => $borrower->borrowernumber, >+ amount => 10, >+ amountoutstanding => 10, >+ interface => 'commandline', >+ debit_type_code => 'OVERDUE' >+ } >+ )->store(); >+ my $line2 = Koha::Account::Line->new( >+ { >+ borrowernumber => $borrower->borrowernumber, >+ amount => 20, >+ amountoutstanding => 20, >+ interface => 'commandline', >+ debit_type_code => 'OVERDUE' >+ } >+ )->store(); >+ >+ is( $account->balance(), 30, "Account balance is 30" ); >+ is( $line1->amountoutstanding, 10, 'First fee has amount outstanding of 10' ); >+ is( $line2->amountoutstanding, 20, 'Second fee has amount outstanding of 20' ); >+ >+ my $id = $account->pay( >+ { >+ lines => [$line1, $line2], >+ amount => 30, >+ } >+ ); >+ >+ my $account_payment = Koha::Account::Lines->find( $id ); >+ >+ is( $account->balance(), 0, "Account balance is 0" ); >+ >+ $line1->_result->discard_changes(); >+ $line2->_result->discard_changes(); >+ is( $line1->amountoutstanding+0, 0, 'First fee has amount outstanding of 0' ); >+ is( $line2->amountoutstanding+0, 0, 'Second fee has amount outstanding of 0' ); >+ >+ my $ret = $account_payment->void(); >+ >+ is( ref($ret), 'Koha::Account::Line', 'Void returns the account line' ); >+ is( $account->balance(), 30, "Account balance is again 30" ); >+ >+ $account_payment->_result->discard_changes(); >+ $line1->_result->discard_changes(); >+ $line2->_result->discard_changes(); >+ >+ is( $account_payment->credit_type_code, 'PAYMENT', 'Voided payment credit_type_code is still PAYMENT' ); >+ is( $account_payment->status, 'VOID', 'Voided payment status is VOID' ); >+ is( $account_payment->amount+0, 0, 'Voided payment amount is 0' ); >+ is( $account_payment->amountoutstanding+0, 0, 'Voided payment amount outstanding is 0' ); >+ >+ is( $line1->amountoutstanding+0, 10, 'First fee again has amount outstanding of 10' ); >+ is( $line2->amountoutstanding+0, 20, 'Second fee again has amount outstanding of 20' ); >+ >+ # Accountlines that are not credits should be un-voidable >+ my $line1_pre = $line1->unblessed(); >+ $ret = $line1->void(); >+ $line1->_result->discard_changes(); >+ my $line1_post = $line1->unblessed(); >+ is( $ret, undef, 'Attempted void on non-credit returns undef' ); >+ is_deeply( $line1_pre, $line1_post, 'Non-credit account line cannot be voided' ); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest "payout() tests" => sub { >+ >+ plan tests => 18; >+ >+ $schema->storage->txn_begin; >+ >+ # Create a borrower >+ my $categorycode = >+ $builder->build( { source => 'Category' } )->{categorycode}; >+ my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; >+ >+ my $borrower = Koha::Patron->new( >+ { >+ cardnumber => 'dariahall', >+ surname => 'Hall', >+ firstname => 'Daria', >+ } >+ ); >+ $borrower->categorycode($categorycode); >+ $borrower->branchcode($branchcode); >+ $borrower->store; >+ >+ my $staff = Koha::Patron->new( >+ { >+ cardnumber => 'bobby', >+ surname => 'Bloggs', >+ firstname => 'Bobby', >+ } >+ ); >+ $staff->categorycode($categorycode); >+ $staff->branchcode($branchcode); >+ $staff->store; >+ >+ my $account = Koha::Account->new( { patron_id => $borrower->id } ); >+ >+ my $debit1 = Koha::Account::Line->new( >+ { >+ borrowernumber => $borrower->borrowernumber, >+ amount => 10, >+ amountoutstanding => 10, >+ interface => 'commandline', >+ debit_type_code => 'OVERDUE' >+ } >+ )->store(); >+ my $credit1 = Koha::Account::Line->new( >+ { >+ borrowernumber => $borrower->borrowernumber, >+ amount => -20, >+ amountoutstanding => -20, >+ interface => 'commandline', >+ credit_type_code => 'CREDIT' >+ } >+ )->store(); >+ >+ is( $account->balance(), -10, "Account balance is -10" ); >+ is( $debit1->amountoutstanding + 0, >+ 10, 'Overdue fee has an amount outstanding of 10' ); >+ is( $credit1->amountoutstanding + 0, >+ -20, 'Credit has an amount outstanding of -20' ); >+ >+ my $pay_params = { >+ interface => 'intranet', >+ staff_id => $staff->borrowernumber, >+ branch => $branchcode, >+ payout_type => 'CASH', >+ amount => 20 >+ }; >+ >+ throws_ok { $debit1->payout($pay_params); } >+ 'Koha::Exceptions::Account::IsNotCredit', >+ '->payout() can only be used with credits'; >+ >+ my @required = >+ ( 'interface', 'staff_id', 'branch', 'payout_type', 'amount' ); >+ for my $required (@required) { >+ my $params = {%$pay_params}; >+ delete( $params->{$required} ); >+ throws_ok { >+ $credit1->payout($params); >+ } >+ 'Koha::Exceptions::MissingParameter', >+ "->payout() requires the `$required` parameter is passed"; >+ } >+ >+ throws_ok { >+ $credit1->payout( >+ { >+ interface => 'intranet', >+ staff_id => $staff->borrowernumber, >+ branch => $branchcode, >+ payout_type => 'CASH', >+ amount => 25 >+ } >+ ); >+ } >+ 'Koha::Exceptions::ParameterTooHigh', >+ '->payout() cannot pay out more than the amountoutstanding'; >+ >+ t::lib::Mocks::mock_preference( 'UseCashRegisters', 1 ); >+ throws_ok { >+ $credit1->payout( >+ { >+ interface => 'intranet', >+ staff_id => $staff->borrowernumber, >+ branch => $branchcode, >+ payout_type => 'CASH', >+ amount => 10 >+ } >+ ); >+ } >+ 'Koha::Exceptions::Account::RegisterRequired', >+ '->payout() requires a cash_register if payout_type is `CASH`'; >+ >+ t::lib::Mocks::mock_preference( 'UseCashRegisters', 0 ); >+ my $payout = $credit1->payout( >+ { >+ interface => 'intranet', >+ staff_id => $staff->borrowernumber, >+ branch => $branchcode, >+ payout_type => 'CASH', >+ amount => 10 >+ } >+ ); >+ >+ is( ref($payout), 'Koha::Account::Line', >+ '->payout() returns a Koha::Account::Line' ); >+ is( $payout->amount() + 0, 10, "Payout amount is 10" ); >+ is( $payout->amountoutstanding() + 0, 0, "Payout amountoutstanding is 0" ); >+ is( $account->balance() + 0, 0, "Account balance is 0" ); >+ is( $debit1->amountoutstanding + 0, >+ 10, 'Overdue fee still has an amount outstanding of 10' ); >+ is( $credit1->amountoutstanding + 0, >+ -10, 'Credit has an new amount outstanding of -10' ); >+ is( $credit1->status(), 'PAID', "Credit has a new status of PAID" ); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest "reduce() tests" => sub { >+ >+ plan tests => 27; >+ >+ $schema->storage->txn_begin; >+ >+ # Create a borrower >+ my $categorycode = >+ $builder->build( { source => 'Category' } )->{categorycode}; >+ my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; >+ >+ my $borrower = Koha::Patron->new( >+ { >+ cardnumber => 'dariahall', >+ surname => 'Hall', >+ firstname => 'Daria', >+ } >+ ); >+ $borrower->categorycode($categorycode); >+ $borrower->branchcode($branchcode); >+ $borrower->store; >+ >+ my $staff = Koha::Patron->new( >+ { >+ cardnumber => 'bobby', >+ surname => 'Bloggs', >+ firstname => 'Bobby', >+ } >+ ); >+ $staff->categorycode($categorycode); >+ $staff->branchcode($branchcode); >+ $staff->store; >+ >+ my $account = Koha::Account->new( { patron_id => $borrower->id } ); >+ >+ my $debit1 = Koha::Account::Line->new( >+ { >+ borrowernumber => $borrower->borrowernumber, >+ amount => 20, >+ amountoutstanding => 20, >+ interface => 'commandline', >+ debit_type_code => 'LOST' >+ } >+ )->store(); >+ my $credit1 = Koha::Account::Line->new( >+ { >+ borrowernumber => $borrower->borrowernumber, >+ amount => -20, >+ amountoutstanding => -20, >+ interface => 'commandline', >+ credit_type_code => 'CREDIT' >+ } >+ )->store(); >+ >+ is( $account->balance(), 0, "Account balance is 0" ); >+ is( $debit1->amountoutstanding, >+ 20, 'Overdue fee has an amount outstanding of 20' ); >+ is( $credit1->amountoutstanding, >+ -20, 'Credit has an amount outstanding of -20' ); >+ >+ my $reduce_params = { >+ interface => 'commandline', >+ reduction_type => 'REFUND', >+ amount => 5, >+ staff_id => $staff->borrowernumber, >+ branch => $branchcode >+ }; >+ >+ throws_ok { $credit1->reduce($reduce_params); } >+ 'Koha::Exceptions::Account::IsNotDebit', >+ '->reduce() can only be used with debits'; >+ >+ my @required = ( 'interface', 'reduction_type', 'amount' ); >+ for my $required (@required) { >+ my $params = {%$reduce_params}; >+ delete( $params->{$required} ); >+ throws_ok { >+ $debit1->reduce($params); >+ } >+ 'Koha::Exceptions::MissingParameter', >+ "->reduce() requires the `$required` parameter is passed"; >+ } >+ >+ $reduce_params->{interface} = 'intranet'; >+ my @dependant_required = ( 'staff_id', 'branch' ); >+ for my $d (@dependant_required) { >+ my $params = {%$reduce_params}; >+ delete( $params->{$d} ); >+ throws_ok { >+ $debit1->reduce($params); >+ } >+ 'Koha::Exceptions::MissingParameter', >+"->reduce() requires the `$d` parameter is passed when interface is intranet"; >+ } >+ >+ throws_ok { >+ $debit1->reduce( >+ { >+ interface => 'intranet', >+ staff_id => $staff->borrowernumber, >+ branch => $branchcode, >+ reduction_type => 'REFUND', >+ amount => 25 >+ } >+ ); >+ } >+ 'Koha::Exceptions::ParameterTooHigh', >+ '->reduce() cannot reduce more than original amount'; >+ >+ # Partial Reduction >+ # (Refund 5 on debt of 20) >+ my $reduction = $debit1->reduce($reduce_params); >+ >+ is( ref($reduction), 'Koha::Account::Line', >+ '->reduce() returns a Koha::Account::Line' ); >+ is( $reduction->amount() * 1, -5, "Reduce amount is -5" ); >+ is( $reduction->amountoutstanding() * 1, >+ 0, "Reduce amountoutstanding is 0" ); >+ is( $debit1->amountoutstanding() * 1, >+ 15, "Debit amountoutstanding reduced by 5 to 15" ); >+ is( $account->balance() * 1, -5, "Account balance is -5" ); >+ is( $reduction->status(), 'APPLIED', "Reduction status is 'APPLIED'" ); >+ >+ my $offsets = Koha::Account::Offsets->search( >+ { credit_id => $reduction->id, debit_id => $debit1->id } ); >+ is( $offsets->count, 1, 'Only one offset is generated' ); >+ my $THE_offset = $offsets->next; >+ is( $THE_offset->amount * 1, >+ -5, 'Correct amount was applied against debit' ); >+ is( $THE_offset->type, 'REFUND', "Offset type set to 'REFUND'" ); >+ >+ # Zero offset created when zero outstanding >+ # (Refund another 5 on paid debt of 20) >+ $credit1->apply( { debits => [$debit1] } ); >+ is( $debit1->amountoutstanding + 0, >+ 0, 'Debit1 amountoutstanding reduced to 0' ); >+ $reduction = $debit1->reduce($reduce_params); >+ is( $reduction->amount() * 1, -5, "Reduce amount is -5" ); >+ is( $reduction->amountoutstanding() * 1, >+ -5, "Reduce amountoutstanding is -5" ); >+ >+ $offsets = Koha::Account::Offsets->search( >+ { credit_id => $reduction->id, debit_id => $debit1->id } ); >+ is( $offsets->count, 1, 'Only one new offset is generated' ); >+ $THE_offset = $offsets->next; >+ is( $THE_offset->amount * 1, >+ 0, 'Zero offset created for already paid off debit' ); >+ is( $THE_offset->type, 'REFUND', "Offset type set to 'REFUND'" ); >+ >+ # Compound reduction should not allow more than original amount >+ # (Reduction of 5 + 5 + 20 > 20) >+ $reduce_params->{amount} = 20; >+ throws_ok { >+ $debit1->reduce($reduce_params); >+ } >+ 'Koha::Exceptions::ParameterTooHigh', >+'->reduce cannot reduce more than the original amount (combined reductions test)'; >+ >+ # Throw exception if attempting to reduce a payout >+ my $payout = $reduction->payout( >+ { >+ interface => 'intranet', >+ staff_id => $staff->borrowernumber, >+ branch => $branchcode, >+ payout_type => 'CASH', >+ amount => 5 >+ } >+ ); >+ throws_ok { >+ $payout->reduce($reduce_params); >+ } >+ 'Koha::Exceptions::Account::IsNotDebit', >+ '->reduce() cannot be used on a payout debit'; >+ >+ $schema->storage->txn_rollback; >+}; >+ >+1; >diff --git a/t/db_dependent/Koha/Account/Lines.t b/t/db_dependent/Koha/Account/Lines.t >index 667071f0a2..afc88fcb32 100755 >--- a/t/db_dependent/Koha/Account/Lines.t >+++ b/t/db_dependent/Koha/Account/Lines.t >@@ -19,14 +19,12 @@ > > use Modern::Perl; > >-use Test::More tests => 15; >+use Test::More tests => 4; > use Test::Exception; > >-use C4::Circulation qw/AddIssue AddReturn/; > use Koha::Account; > use Koha::Account::Lines; > use Koha::Account::Offsets; >-use Koha::Items; > > use t::lib::Mocks; > use t::lib::TestBuilder; >@@ -34,74 +32,6 @@ use t::lib::TestBuilder; > my $schema = Koha::Database->new->schema; > my $builder = t::lib::TestBuilder->new; > >-subtest 'patron() tests' => sub { >- >- plan tests => 3; >- >- $schema->storage->txn_begin; >- >- my $library = $builder->build( { source => 'Branch' } ); >- my $patron = $builder->build( { source => 'Borrower' } ); >- >- my $line = Koha::Account::Line->new( >- { >- borrowernumber => $patron->{borrowernumber}, >- debit_type_code => "OVERDUE", >- status => "RETURNED", >- amount => 10, >- interface => 'commandline', >- })->store; >- >- my $account_line_patron = $line->patron; >- is( ref( $account_line_patron ), 'Koha::Patron', 'Koha::Account::Line->patron should return a Koha::Patron' ); >- is( $line->borrowernumber, $account_line_patron->borrowernumber, 'Koha::Account::Line->patron should return the correct borrower' ); >- >- $line->borrowernumber(undef)->store; >- is( $line->patron, undef, 'Koha::Account::Line->patron should return undef if no patron linked' ); >- >- $schema->storage->txn_rollback; >-}; >- >- >-subtest 'item() tests' => sub { >- >- plan tests => 3; >- >- $schema->storage->txn_begin; >- >- my $library = $builder->build( { source => 'Branch' } ); >- my $biblioitem = $builder->build( { source => 'Biblioitem' } ); >- my $patron = $builder->build( { source => 'Borrower' } ); >- my $item = Koha::Item->new( >- { >- biblionumber => $biblioitem->{biblionumber}, >- biblioitemnumber => $biblioitem->{biblioitemnumber}, >- homebranch => $library->{branchcode}, >- holdingbranch => $library->{branchcode}, >- barcode => 'some_barcode_12', >- itype => 'BK', >- })->store; >- >- my $line = Koha::Account::Line->new( >- { >- borrowernumber => $patron->{borrowernumber}, >- itemnumber => $item->itemnumber, >- debit_type_code => "OVERDUE", >- status => "RETURNED", >- amount => 10, >- interface => 'commandline', >- })->store; >- >- my $account_line_item = $line->item; >- is( ref( $account_line_item ), 'Koha::Item', 'Koha::Account::Line->item should return a Koha::Item' ); >- is( $line->itemnumber, $account_line_item->itemnumber, 'Koha::Account::Line->item should return the correct item' ); >- >- $line->itemnumber(undef)->store; >- is( $line->item, undef, 'Koha::Account::Line->item should return undef if no item linked' ); >- >- $schema->storage->txn_rollback; >-}; >- > subtest 'total_outstanding() tests' => sub { > > plan tests => 5; >@@ -115,7 +45,7 @@ subtest 'total_outstanding() tests' => sub { > > my $debit_1 = Koha::Account::Line->new( > { borrowernumber => $patron->id, >- debit_type_code => "OVERDUE", >+ debit_type_code => "OVERDUE", > status => "RETURNED", > amount => 10, > amountoutstanding => 10, >@@ -125,7 +55,7 @@ subtest 'total_outstanding() tests' => sub { > > my $debit_2 = Koha::Account::Line->new( > { borrowernumber => $patron->id, >- debit_type_code => "OVERDUE", >+ debit_type_code => "OVERDUE", > status => "RETURNED", > amount => 10, > amountoutstanding => 10, >@@ -138,7 +68,7 @@ subtest 'total_outstanding() tests' => sub { > > my $credit_1 = Koha::Account::Line->new( > { borrowernumber => $patron->id, >- debit_type_code => "OVERDUE", >+ debit_type_code => "OVERDUE", > status => "RETURNED", > amount => -10, > amountoutstanding => -10, >@@ -151,7 +81,7 @@ subtest 'total_outstanding() tests' => sub { > > my $credit_2 = Koha::Account::Line->new( > { borrowernumber => $patron->id, >- debit_type_code => "OVERDUE", >+ debit_type_code => "OVERDUE", > status => "RETURNED", > amount => -10, > amountoutstanding => -10, >@@ -164,7 +94,7 @@ subtest 'total_outstanding() tests' => sub { > > my $credit_3 = Koha::Account::Line->new( > { borrowernumber => $patron->id, >- debit_type_code => "OVERDUE", >+ debit_type_code => "OVERDUE", > status => "RETURNED", > amount => -100, > amountoutstanding => -100, >@@ -406,813 +336,4 @@ subtest 'debits_total() tests' => sub { > $schema->storage->txn_rollback; > }; > >-subtest 'is_credit() and is_debit() tests' => sub { >- >- plan tests => 4; >- >- $schema->storage->txn_begin; >- >- my $patron = $builder->build_object({ class => 'Koha::Patrons' }); >- my $account = $patron->account; >- >- my $credit = $account->add_credit({ amount => 100, user_id => $patron->id, interface => 'commandline' }); >- >- ok( $credit->is_credit, 'is_credit detects credits' ); >- ok( !$credit->is_debit, 'is_debit detects credits' ); >- >- my $debit = Koha::Account::Line->new( >- { >- borrowernumber => $patron->id, >- debit_type_code => "OVERDUE", >- status => "RETURNED", >- amount => 10, >- interface => 'commandline', >- })->store; >- >- ok( !$debit->is_credit, 'is_credit detects debits' ); >- ok( $debit->is_debit, 'is_debit detects debits'); >- >- $schema->storage->txn_rollback; >-}; >- >-subtest 'apply() tests' => sub { >- >- plan tests => 24; >- >- $schema->storage->txn_begin; >- >- my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); >- my $account = $patron->account; >- >- my $credit = $account->add_credit( { amount => 100, user_id => $patron->id, interface => 'commandline' } ); >- >- my $debit_1 = Koha::Account::Line->new( >- { borrowernumber => $patron->id, >- debit_type_code => "OVERDUE", >- status => "RETURNED", >- amount => 10, >- amountoutstanding => 10, >- interface => 'commandline', >- } >- )->store; >- >- my $debit_2 = Koha::Account::Line->new( >- { borrowernumber => $patron->id, >- debit_type_code => "OVERDUE", >- status => "RETURNED", >- amount => 100, >- amountoutstanding => 100, >- interface => 'commandline', >- } >- )->store; >- >- $credit->discard_changes; >- $debit_1->discard_changes; >- >- my $debits = Koha::Account::Lines->search({ accountlines_id => $debit_1->id }); >- my $remaining_credit = $credit->apply( { debits => [ $debits->as_list ], 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' ); >- >- # re-read debit info >- $debit_1->discard_changes; >- is( $debit_1->amountoutstanding * 1, 0, 'Debit has been cancelled' ); >- >- 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_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' ); >- >- $debits = Koha::Account::Lines->search({ accountlines_id => $debit_2->id }); >- $remaining_credit = $credit->apply( { debits => [ $debits->as_list ] } ); >- 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->as_list ] }); } >- '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({ debits => [ $debits->as_list ] }); } >- '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, interface => 'commandline' }); >- throws_ok >- { $credit_3->apply({ debits => [ $debits->as_list ] }); } >- 'Koha::Exceptions::Account::IsNotDebit', >- '->apply() can only be applied to credits'; >- >- my $credit_2 = $account->add_credit({ amount => 20, interface => 'commandline' }); >- my $debit_3 = Koha::Account::Line->new( >- { borrowernumber => $patron->id, >- debit_type_code => "OVERDUE", >- status => "RETURNED", >- amount => 100, >- amountoutstanding => 100, >- interface => 'commandline', >- } >- )->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->as_list ], 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->as_list ], 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; >-}; >- >-subtest 'Keep account info when related patron, staff, item or cash_register is deleted' => sub { >- >- plan tests => 4; >- >- $schema->storage->txn_begin; >- >- my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); >- my $staff = $builder->build_object( { class => 'Koha::Patrons' } ); >- my $item = $builder->build_object({ class => 'Koha::Items' }); >- my $issue = $builder->build_object( >- { >- class => 'Koha::Checkouts', >- value => { itemnumber => $item->itemnumber } >- } >- ); >- my $register = $builder->build_object({ class => 'Koha::Cash::Registers' }); >- >- my $line = Koha::Account::Line->new( >- { >- borrowernumber => $patron->borrowernumber, >- manager_id => $staff->borrowernumber, >- itemnumber => $item->itemnumber, >- debit_type_code => "OVERDUE", >- status => "RETURNED", >- amount => 10, >- interface => 'commandline', >- register_id => $register->id >- })->store; >- >- $issue->delete; >- $item->delete; >- $line = $line->get_from_storage; >- is( $line->itemnumber, undef, "The account line should not be deleted when the related item is delete"); >- >- $staff->delete; >- $line = $line->get_from_storage; >- is( $line->manager_id, undef, "The account line should not be deleted when the related staff is delete"); >- >- $patron->delete; >- $line = $line->get_from_storage; >- is( $line->borrowernumber, undef, "The account line should not be deleted when the related patron is delete"); >- >- $register->delete; >- $line = $line->get_from_storage; >- is( $line->register_id, undef, "The account line should not be deleted when the related cash register is delete"); >- >- $schema->storage->txn_rollback; >-}; >- >-subtest 'adjust() tests' => sub { >- >- plan tests => 29; >- >- $schema->storage->txn_begin; >- >- # count logs before any actions >- my $action_logs = $schema->resultset('ActionLog')->search()->count; >- >- # Disable logs >- t::lib::Mocks::mock_preference( 'FinesLog', 0 ); >- >- my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); >- my $account = $patron->account; >- >- my $debit_1 = Koha::Account::Line->new( >- { borrowernumber => $patron->id, >- debit_type_code => "OVERDUE", >- status => "RETURNED", >- amount => 10, >- amountoutstanding => 10, >- interface => 'commandline', >- } >- )->store; >- >- my $debit_2 = Koha::Account::Line->new( >- { borrowernumber => $patron->id, >- debit_type_code => "OVERDUE", >- status => "UNRETURNED", >- amount => 100, >- amountoutstanding => 100, >- interface => 'commandline' >- } >- )->store; >- >- my $credit = $account->add_credit( { amount => 40, user_id => $patron->id, interface => 'commandline' } ); >- >- throws_ok { $debit_1->adjust( { amount => 50, type => 'bad', interface => 'commandline' } ) } >- qr/Update type not recognised/, 'Exception thrown for unrecognised type'; >- >- throws_ok { $debit_1->adjust( { amount => 50, type => 'overdue_update', interface => 'commandline' } ) } >- qr/Update type not allowed on this debit_type/, >- 'Exception thrown for type conflict'; >- >- # Increment an unpaid fine >- $debit_2->adjust( { amount => 150, type => 'overdue_update', interface => 'commandline' } )->discard_changes; >- >- is( $debit_2->amount * 1, 150, 'Fine amount was updated in full' ); >- is( $debit_2->amountoutstanding * 1, 150, 'Fine amountoutstanding was update in full' ); >- isnt( $debit_2->date, undef, 'Date has been set' ); >- >- my $offsets = Koha::Account::Offsets->search( { debit_id => $debit_2->id } ); >- is( $offsets->count, 1, 'An offset is generated for the increment' ); >- my $THIS_offset = $offsets->next; >- is( $THIS_offset->amount * 1, 50, 'Amount was calculated correctly (increment by 50)' ); >- is( $THIS_offset->type, 'OVERDUE_INCREASE', 'Adjust type stored correctly' ); >- >- is( $schema->resultset('ActionLog')->count(), $action_logs + 0, 'No log was added' ); >- >- # Update fine to partially paid >- my $debits = Koha::Account::Lines->search({ accountlines_id => $debit_2->id }); >- $credit->apply( { debits => [ $debits->as_list ], offset_type => 'Manual Credit' } ); >- >- $debit_2->discard_changes; >- is( $debit_2->amount * 1, 150, 'Fine amount unaffected by partial payment' ); >- is( $debit_2->amountoutstanding * 1, 110, 'Fine amountoutstanding updated by partial payment' ); >- >- # Enable logs >- t::lib::Mocks::mock_preference( 'FinesLog', 1 ); >- >- # Increment the partially paid fine >- $debit_2->adjust( { amount => 160, type => 'overdue_update', interface => 'commandline' } )->discard_changes; >- >- is( $debit_2->amount * 1, 160, 'Fine amount was updated in full' ); >- is( $debit_2->amountoutstanding * 1, 120, 'Fine amountoutstanding was updated by difference' ); >- >- $offsets = Koha::Account::Offsets->search( { debit_id => $debit_2->id } ); >- is( $offsets->count, 3, 'An offset is generated for the increment' ); >- $THIS_offset = $offsets->last; >- is( $THIS_offset->amount * 1, 10, 'Amount was calculated correctly (increment by 10)' ); >- is( $THIS_offset->type, 'OVERDUE_INCREASE', 'Adjust type stored correctly' ); >- >- is( $schema->resultset('ActionLog')->count(), $action_logs + 1, 'Log was added' ); >- >- # Decrement the partially paid fine, less than what was paid >- $debit_2->adjust( { amount => 50, type => 'overdue_update', interface => 'commandline' } )->discard_changes; >- >- is( $debit_2->amount * 1, 50, 'Fine amount was updated in full' ); >- is( $debit_2->amountoutstanding * 1, 10, 'Fine amountoutstanding was updated by difference' ); >- >- $offsets = Koha::Account::Offsets->search( { debit_id => $debit_2->id } ); >- is( $offsets->count, 4, 'An offset is generated for the decrement' ); >- $THIS_offset = $offsets->last; >- is( $THIS_offset->amount * 1, -110, 'Amount was calculated correctly (decrement by 110)' ); >- is( $THIS_offset->type, 'OVERDUE_DECREASE', 'Adjust type stored correctly' ); >- >- # Decrement the partially paid fine, more than what was paid >- $debit_2->adjust( { amount => 30, type => 'overdue_update', interface => 'commandline' } )->discard_changes; >- is( $debit_2->amount * 1, 30, 'Fine amount was updated in full' ); >- is( $debit_2->amountoutstanding * 1, 0, 'Fine amountoutstanding was zeroed (payment was 40)' ); >- >- $offsets = Koha::Account::Offsets->search( { debit_id => $debit_2->id } ); >- is( $offsets->count, 5, 'An offset is generated for the decrement' ); >- $THIS_offset = $offsets->last; >- is( $THIS_offset->amount * 1, -20, 'Amount was calculated correctly (decrement by 20)' ); >- is( $THIS_offset->type, 'OVERDUE_DECREASE', 'Adjust type stored correctly' ); >- >- my $overpayment_refund = $account->lines->last; >- is( $overpayment_refund->amount * 1, -10, 'A new credit has been added' ); >- is( $overpayment_refund->description, 'Overpayment refund', 'Credit generated with the expected description' ); >- >- $schema->storage->txn_rollback; >-}; >- >-subtest 'checkout() tests' => sub { >- plan tests => 6; >- >- $schema->storage->txn_begin; >- >- my $library = $builder->build_object( { class => 'Koha::Libraries' } ); >- my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); >- my $item = $builder->build_sample_item; >- my $account = $patron->account; >- >- t::lib::Mocks::mock_userenv({ branchcode => $library->branchcode }); >- my $checkout = AddIssue( $patron->unblessed, $item->barcode ); >- >- my $line = $account->add_debit({ >- amount => 10, >- interface => 'commandline', >- item_id => $item->itemnumber, >- issue_id => $checkout->issue_id, >- type => 'OVERDUE', >- }); >- >- my $line_checkout = $line->checkout; >- is( ref($line_checkout), 'Koha::Checkout', 'Result type is correct' ); >- is( $line_checkout->issue_id, $checkout->issue_id, 'Koha::Account::Line->checkout should return the correct checkout'); >- >- my ( $returned, undef, $old_checkout) = C4::Circulation::AddReturn( $item->barcode, $library->branchcode ); >- is( $returned, 1, 'The item should have been returned' ); >- >- $line = $line->get_from_storage; >- my $old_line_checkout = $line->checkout; >- is( ref($old_line_checkout), 'Koha::Old::Checkout', 'Result type is correct' ); >- is( $old_line_checkout->issue_id, $old_checkout->issue_id, 'Koha::Account::Line->checkout should return the correct old_checkout' ); >- >- $line->issue_id(undef)->store; >- is( $line->checkout, undef, 'Koha::Account::Line->checkout should return undef if no checkout linked' ); >- >- $schema->storage->txn_rollback; >-}; >- >-subtest 'credits() and debits() tests' => sub { >- plan tests => 10; >- >- $schema->storage->txn_begin; >- >- my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); >- my $account = $patron->account; >- >- my $debit1 = $account->add_debit({ >- amount => 8, >- interface => 'commandline', >- type => 'ACCOUNT', >- }); >- my $debit2 = $account->add_debit({ >- amount => 12, >- interface => 'commandline', >- type => 'ACCOUNT', >- }); >- my $credit1 = $account->add_credit({ >- amount => 5, >- interface => 'commandline', >- type => 'CREDIT', >- }); >- my $credit2 = $account->add_credit({ >- amount => 10, >- interface => 'commandline', >- type => 'CREDIT', >- }); >- >- $credit1->apply({ debits => [ $debit1 ] }); >- $credit2->apply({ debits => [ $debit1, $debit2 ] }); >- >- my $credits = $debit1->credits; >- is($credits->count, 2, '2 Credits applied to debit 1'); >- my $credit = $credits->next; >- is($credit->amount + 0, -5, 'Correct first credit'); >- $credit = $credits->next; >- is($credit->amount + 0, -10, 'Correct second credit'); >- >- $credits = $debit2->credits; >- is($credits->count, 1, '1 Credits applied to debit 2'); >- $credit = $credits->next; >- is($credit->amount + 0, -10, 'Correct first credit'); >- >- my $debits = $credit1->debits; >- is($debits->count, 1, 'Credit 1 applied to 1 debit'); >- my $debit = $debits->next; >- is($debit->amount + 0, 8, 'Correct first debit'); >- >- $debits = $credit2->debits; >- is($debits->count, 2, 'Credit 2 applied to 2 debits'); >- $debit = $debits->next; >- is($debit->amount + 0, 8, 'Correct first debit'); >- $debit = $debits->next; >- is($debit->amount + 0, 12, 'Correct second debit'); >- >- $schema->storage->txn_rollback; >-}; >- >-subtest "void() tests" => sub { >- >- plan tests => 16; >- >- $schema->storage->txn_begin; >- >- # Create a borrower >- my $categorycode = $builder->build({ source => 'Category' })->{ categorycode }; >- my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode }; >- >- my $borrower = Koha::Patron->new( { >- cardnumber => 'dariahall', >- surname => 'Hall', >- firstname => 'Daria', >- } ); >- $borrower->categorycode( $categorycode ); >- $borrower->branchcode( $branchcode ); >- $borrower->store; >- >- my $account = Koha::Account->new({ patron_id => $borrower->id }); >- >- my $line1 = Koha::Account::Line->new( >- { >- borrowernumber => $borrower->borrowernumber, >- amount => 10, >- amountoutstanding => 10, >- interface => 'commandline', >- debit_type_code => 'OVERDUE' >- } >- )->store(); >- my $line2 = Koha::Account::Line->new( >- { >- borrowernumber => $borrower->borrowernumber, >- amount => 20, >- amountoutstanding => 20, >- interface => 'commandline', >- debit_type_code => 'OVERDUE' >- } >- )->store(); >- >- is( $account->balance(), 30, "Account balance is 30" ); >- is( $line1->amountoutstanding, 10, 'First fee has amount outstanding of 10' ); >- is( $line2->amountoutstanding, 20, 'Second fee has amount outstanding of 20' ); >- >- my $id = $account->pay( >- { >- lines => [$line1, $line2], >- amount => 30, >- } >- ); >- >- my $account_payment = Koha::Account::Lines->find( $id ); >- >- is( $account->balance(), 0, "Account balance is 0" ); >- >- $line1->_result->discard_changes(); >- $line2->_result->discard_changes(); >- is( $line1->amountoutstanding+0, 0, 'First fee has amount outstanding of 0' ); >- is( $line2->amountoutstanding+0, 0, 'Second fee has amount outstanding of 0' ); >- >- my $ret = $account_payment->void(); >- >- is( ref($ret), 'Koha::Account::Line', 'Void returns the account line' ); >- is( $account->balance(), 30, "Account balance is again 30" ); >- >- $account_payment->_result->discard_changes(); >- $line1->_result->discard_changes(); >- $line2->_result->discard_changes(); >- >- is( $account_payment->credit_type_code, 'PAYMENT', 'Voided payment credit_type_code is still PAYMENT' ); >- is( $account_payment->status, 'VOID', 'Voided payment status is VOID' ); >- is( $account_payment->amount+0, 0, 'Voided payment amount is 0' ); >- is( $account_payment->amountoutstanding+0, 0, 'Voided payment amount outstanding is 0' ); >- >- is( $line1->amountoutstanding+0, 10, 'First fee again has amount outstanding of 10' ); >- is( $line2->amountoutstanding+0, 20, 'Second fee again has amount outstanding of 20' ); >- >- # Accountlines that are not credits should be un-voidable >- my $line1_pre = $line1->unblessed(); >- $ret = $line1->void(); >- $line1->_result->discard_changes(); >- my $line1_post = $line1->unblessed(); >- is( $ret, undef, 'Attempted void on non-credit returns undef' ); >- is_deeply( $line1_pre, $line1_post, 'Non-credit account line cannot be voided' ); >- >- $schema->storage->txn_rollback; >-}; >- >-subtest "payout() tests" => sub { >- >- plan tests => 18; >- >- $schema->storage->txn_begin; >- >- # Create a borrower >- my $categorycode = >- $builder->build( { source => 'Category' } )->{categorycode}; >- my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; >- >- my $borrower = Koha::Patron->new( >- { >- cardnumber => 'dariahall', >- surname => 'Hall', >- firstname => 'Daria', >- } >- ); >- $borrower->categorycode($categorycode); >- $borrower->branchcode($branchcode); >- $borrower->store; >- >- my $staff = Koha::Patron->new( >- { >- cardnumber => 'bobby', >- surname => 'Bloggs', >- firstname => 'Bobby', >- } >- ); >- $staff->categorycode($categorycode); >- $staff->branchcode($branchcode); >- $staff->store; >- >- my $account = Koha::Account->new( { patron_id => $borrower->id } ); >- >- my $debit1 = Koha::Account::Line->new( >- { >- borrowernumber => $borrower->borrowernumber, >- amount => 10, >- amountoutstanding => 10, >- interface => 'commandline', >- debit_type_code => 'OVERDUE' >- } >- )->store(); >- my $credit1 = Koha::Account::Line->new( >- { >- borrowernumber => $borrower->borrowernumber, >- amount => -20, >- amountoutstanding => -20, >- interface => 'commandline', >- credit_type_code => 'CREDIT' >- } >- )->store(); >- >- is( $account->balance(), -10, "Account balance is -10" ); >- is( $debit1->amountoutstanding + 0, >- 10, 'Overdue fee has an amount outstanding of 10' ); >- is( $credit1->amountoutstanding + 0, >- -20, 'Credit has an amount outstanding of -20' ); >- >- my $pay_params = { >- interface => 'intranet', >- staff_id => $staff->borrowernumber, >- branch => $branchcode, >- payout_type => 'CASH', >- amount => 20 >- }; >- >- throws_ok { $debit1->payout($pay_params); } >- 'Koha::Exceptions::Account::IsNotCredit', >- '->payout() can only be used with credits'; >- >- my @required = >- ( 'interface', 'staff_id', 'branch', 'payout_type', 'amount' ); >- for my $required (@required) { >- my $params = {%$pay_params}; >- delete( $params->{$required} ); >- throws_ok { >- $credit1->payout($params); >- } >- 'Koha::Exceptions::MissingParameter', >- "->payout() requires the `$required` parameter is passed"; >- } >- >- throws_ok { >- $credit1->payout( >- { >- interface => 'intranet', >- staff_id => $staff->borrowernumber, >- branch => $branchcode, >- payout_type => 'CASH', >- amount => 25 >- } >- ); >- } >- 'Koha::Exceptions::ParameterTooHigh', >- '->payout() cannot pay out more than the amountoutstanding'; >- >- t::lib::Mocks::mock_preference( 'UseCashRegisters', 1 ); >- throws_ok { >- $credit1->payout( >- { >- interface => 'intranet', >- staff_id => $staff->borrowernumber, >- branch => $branchcode, >- payout_type => 'CASH', >- amount => 10 >- } >- ); >- } >- 'Koha::Exceptions::Account::RegisterRequired', >- '->payout() requires a cash_register if payout_type is `CASH`'; >- >- t::lib::Mocks::mock_preference( 'UseCashRegisters', 0 ); >- my $payout = $credit1->payout( >- { >- interface => 'intranet', >- staff_id => $staff->borrowernumber, >- branch => $branchcode, >- payout_type => 'CASH', >- amount => 10 >- } >- ); >- >- is( ref($payout), 'Koha::Account::Line', >- '->payout() returns a Koha::Account::Line' ); >- is( $payout->amount() + 0, 10, "Payout amount is 10" ); >- is( $payout->amountoutstanding() + 0, 0, "Payout amountoutstanding is 0" ); >- is( $account->balance() + 0, 0, "Account balance is 0" ); >- is( $debit1->amountoutstanding + 0, >- 10, 'Overdue fee still has an amount outstanding of 10' ); >- is( $credit1->amountoutstanding + 0, >- -10, 'Credit has an new amount outstanding of -10' ); >- is( $credit1->status(), 'PAID', "Credit has a new status of PAID" ); >- >- $schema->storage->txn_rollback; >-}; >- >-subtest "reduce() tests" => sub { >- >- plan tests => 27; >- >- $schema->storage->txn_begin; >- >- # Create a borrower >- my $categorycode = >- $builder->build( { source => 'Category' } )->{categorycode}; >- my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; >- >- my $borrower = Koha::Patron->new( >- { >- cardnumber => 'dariahall', >- surname => 'Hall', >- firstname => 'Daria', >- } >- ); >- $borrower->categorycode($categorycode); >- $borrower->branchcode($branchcode); >- $borrower->store; >- >- my $staff = Koha::Patron->new( >- { >- cardnumber => 'bobby', >- surname => 'Bloggs', >- firstname => 'Bobby', >- } >- ); >- $staff->categorycode($categorycode); >- $staff->branchcode($branchcode); >- $staff->store; >- >- my $account = Koha::Account->new( { patron_id => $borrower->id } ); >- >- my $debit1 = Koha::Account::Line->new( >- { >- borrowernumber => $borrower->borrowernumber, >- amount => 20, >- amountoutstanding => 20, >- interface => 'commandline', >- debit_type_code => 'LOST' >- } >- )->store(); >- my $credit1 = Koha::Account::Line->new( >- { >- borrowernumber => $borrower->borrowernumber, >- amount => -20, >- amountoutstanding => -20, >- interface => 'commandline', >- credit_type_code => 'CREDIT' >- } >- )->store(); >- >- is( $account->balance(), 0, "Account balance is 0" ); >- is( $debit1->amountoutstanding, >- 20, 'Overdue fee has an amount outstanding of 20' ); >- is( $credit1->amountoutstanding, >- -20, 'Credit has an amount outstanding of -20' ); >- >- my $reduce_params = { >- interface => 'commandline', >- reduction_type => 'REFUND', >- amount => 5, >- staff_id => $staff->borrowernumber, >- branch => $branchcode >- }; >- >- throws_ok { $credit1->reduce($reduce_params); } >- 'Koha::Exceptions::Account::IsNotDebit', >- '->reduce() can only be used with debits'; >- >- my @required = ( 'interface', 'reduction_type', 'amount' ); >- for my $required (@required) { >- my $params = {%$reduce_params}; >- delete( $params->{$required} ); >- throws_ok { >- $debit1->reduce($params); >- } >- 'Koha::Exceptions::MissingParameter', >- "->reduce() requires the `$required` parameter is passed"; >- } >- >- $reduce_params->{interface} = 'intranet'; >- my @dependant_required = ( 'staff_id', 'branch' ); >- for my $d (@dependant_required) { >- my $params = {%$reduce_params}; >- delete( $params->{$d} ); >- throws_ok { >- $debit1->reduce($params); >- } >- 'Koha::Exceptions::MissingParameter', >-"->reduce() requires the `$d` parameter is passed when interface is intranet"; >- } >- >- throws_ok { >- $debit1->reduce( >- { >- interface => 'intranet', >- staff_id => $staff->borrowernumber, >- branch => $branchcode, >- reduction_type => 'REFUND', >- amount => 25 >- } >- ); >- } >- 'Koha::Exceptions::ParameterTooHigh', >- '->reduce() cannot reduce more than original amount'; >- >- # Partial Reduction >- # (Refund 5 on debt of 20) >- my $reduction = $debit1->reduce($reduce_params); >- >- is( ref($reduction), 'Koha::Account::Line', >- '->reduce() returns a Koha::Account::Line' ); >- is( $reduction->amount() * 1, -5, "Reduce amount is -5" ); >- is( $reduction->amountoutstanding() * 1, >- 0, "Reduce amountoutstanding is 0" ); >- is( $debit1->amountoutstanding() * 1, >- 15, "Debit amountoutstanding reduced by 5 to 15" ); >- is( $account->balance() * 1, -5, "Account balance is -5" ); >- is( $reduction->status(), 'APPLIED', "Reduction status is 'APPLIED'" ); >- >- my $offsets = Koha::Account::Offsets->search( >- { credit_id => $reduction->id, debit_id => $debit1->id } ); >- is( $offsets->count, 1, 'Only one offset is generated' ); >- my $THE_offset = $offsets->next; >- is( $THE_offset->amount * 1, >- -5, 'Correct amount was applied against debit' ); >- is( $THE_offset->type, 'REFUND', "Offset type set to 'REFUND'" ); >- >- # Zero offset created when zero outstanding >- # (Refund another 5 on paid debt of 20) >- $credit1->apply( { debits => [$debit1] } ); >- is( $debit1->amountoutstanding + 0, >- 0, 'Debit1 amountoutstanding reduced to 0' ); >- $reduction = $debit1->reduce($reduce_params); >- is( $reduction->amount() * 1, -5, "Reduce amount is -5" ); >- is( $reduction->amountoutstanding() * 1, >- -5, "Reduce amountoutstanding is -5" ); >- >- $offsets = Koha::Account::Offsets->search( >- { credit_id => $reduction->id, debit_id => $debit1->id } ); >- is( $offsets->count, 1, 'Only one new offset is generated' ); >- $THE_offset = $offsets->next; >- is( $THE_offset->amount * 1, >- 0, 'Zero offset created for already paid off debit' ); >- is( $THE_offset->type, 'REFUND', "Offset type set to 'REFUND'" ); >- >- # Compound reduction should not allow more than original amount >- # (Reduction of 5 + 5 + 20 > 20) >- $reduce_params->{amount} = 20; >- throws_ok { >- $debit1->reduce($reduce_params); >- } >- 'Koha::Exceptions::ParameterTooHigh', >-'->reduce cannot reduce more than the original amount (combined reductions test)'; >- >- # Throw exception if attempting to reduce a payout >- my $payout = $reduction->payout( >- { >- interface => 'intranet', >- staff_id => $staff->borrowernumber, >- branch => $branchcode, >- payout_type => 'CASH', >- amount => 5 >- } >- ); >- throws_ok { >- $payout->reduce($reduce_params); >- } >- 'Koha::Exceptions::Account::IsNotDebit', >- '->reduce() cannot be used on a payout debit'; >- >- $schema->storage->txn_rollback; >-}; >- > 1; >-- >2.20.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 23355
:
92941
|
92942
|
92943
|
92944
|
92945
|
92946
|
92947
|
92948
|
92949
|
92950
|
92951
|
92952
|
92953
|
97031
|
97032
|
97033
|
97034
|
97035
|
97036
|
97037
|
97038
|
97039
|
97040
|
97041
|
97043
|
97044
|
97045
|
97046
|
97047
|
97048
|
97049
|
97050
|
97051
|
97052
|
97053
|
97054
|
97077
|
97078
|
97079
|
97080
|
97081
|
97082
|
97083
|
97084
|
97085
|
97086
|
97087
|
97088
|
97089
|
97706
|
97707
|
97708
|
97709
|
97710
|
97711
|
97712
|
97713
|
97714
|
97715
|
97716
|
97784
|
97785
|
97786
|
97787
|
97788
|
97789
|
97790
|
97791
|
97792
|
97793
|
97794
|
97816
|
97817
|
97818
|
97819
|
97820
|
97821
|
97822
|
97823
|
98026
|
98027
|
98028
|
98835
|
98836
|
98837
|
98838
|
98839
|
98840
|
98841
|
98842
|
100009
|
100010
|
100011
|
100012
|
100013
|
100014
|
100015
|
100016
|
100017
|
100018
|
100019
|
100020
|
100021
|
100030
|
100090
|
101685