From 43769a5e9f0a2ec99e363fa750b501b0a5d2917f Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Sat, 10 Jun 2017 11:34:56 +0000 Subject: [PATCH] Bug 18790 - Add ability to void payments We've had the ability to 'reverse' a payment for a long time, but it would be much better if we had a true void payment function that replaces the paid amounts into the fee so that it appears as if the payment was never made. Test Plan: 1) Apply this patch and dependent patches 2) Run updatedatabase.pl 3) Create some fines 4) Pay those fines 5) Use the new 'void' button to void the payments 6) Note the fines were restored to their pre-payment amounts --- Koha/Account/Line.pm | 46 +++++++++++++++++ .../prog/en/modules/members/boraccount.tt | 2 + members/boraccount.pl | 9 +++- t/db_dependent/Accounts.t | 59 +++++++++++++++++++++- 4 files changed, 113 insertions(+), 3 deletions(-) diff --git a/Koha/Account/Line.pm b/Koha/Account/Line.pm index f7578e7..a2468d0 100644 --- a/Koha/Account/Line.pm +++ b/Koha/Account/Line.pm @@ -20,6 +20,7 @@ use Modern::Perl; use Carp; use Koha::Database; +use Koha::Account::Offsets; use base qw(Koha::Object); @@ -33,6 +34,51 @@ Koha::Account::Lines - Koha accountline Object class =cut +=head3 void + +$payment_accountline->void(); + +=cut + +sub void { + my ($self) = @_; + + # Make sure it is a payment we are voiding + return unless $self->accounttype =~ /^Pay/; + + my @account_offsets = + Koha::Account::Offsets->search( { credit_id => $self->id, type => 'Payment' } ); + + foreach my $account_offset (@account_offsets) { + my $fee_paid = Koha::Account::Lines->find( $account_offset->debit_id ); + + next unless $fee_paid; + + my $amount_paid = $account_offset->amount * -1; # amount paid is stored as a negative amount + my $new_amount = $fee_paid->amountoutstanding + $amount_paid; + $fee_paid->amountoutstanding($new_amount); + $fee_paid->store(); + + Koha::Account::Offset->new( + { + credit_id => $self->id, + debit_id => $fee_paid->id, + amount => $amount_paid, + type => 'Void Payment', + } + ); + } + + $self->set( + { + accounttype => 'VOID', + amountoutstanding => 0, + amount => 0, + } + ); + $self->store(); +} + =head3 type =cut diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt index 1fd2070..ba06227 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt @@ -90,6 +90,7 @@ $(document).ready(function() { [% CASE 'Pay00' %]Payment, thanks (cash via SIP2) [% CASE 'Pay01' %]Payment, thanks (VISA via SIP2) [% CASE 'Pay02' %]Payment, thanks (credit card via SIP2) + [% CASE 'VOID' %]Payment, Voided [% CASE 'N' %]New card [% CASE 'F' %]Fine [% CASE 'A' %]Account management fee @@ -122,6 +123,7 @@ $(document).ready(function() { [% IF ( reverse_col) %] [% IF ( account.payment ) %] Reverse + Void [% ELSE %]   [% END %] diff --git a/members/boraccount.pl b/members/boraccount.pl index 8abb373..cd13d47 100755 --- a/members/boraccount.pl +++ b/members/boraccount.pl @@ -49,14 +49,19 @@ my ($template, $loggedinuser, $cookie) = get_template_and_user( } ); -my $borrowernumber=$input->param('borrowernumber'); +my $borrowernumber = $input->param('borrowernumber'); my $action = $input->param('action') || ''; #get patron details my $patron = Koha::Patrons->find( $borrowernumber ); if ( $action eq 'reverse' ) { - ReversePayment( $input->param('accountlines_id') ); + ReversePayment( $input->param('accountlines_id') ); +} +elsif ( $action eq 'void' ) { + my $payment_id = $input->param('accountlines_id'); + my $payment = Koha::Account::Lines->find( $payment_id ); + $payment->void(); } if ( $patron->category->category_type eq 'C') { diff --git a/t/db_dependent/Accounts.t b/t/db_dependent/Accounts.t index 3c89cbd..80124a7 100644 --- a/t/db_dependent/Accounts.t +++ b/t/db_dependent/Accounts.t @@ -18,7 +18,7 @@ use Modern::Perl; -use Test::More tests => 22; +use Test::More tests => 23; use Test::MockModule; use Test::Warn; @@ -490,4 +490,61 @@ subtest 'balance' => sub { $patron->delete; }; +subtest "Koha::Account::Line::void tests" => sub { + + plan tests => 12; + + # 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 })->store(); + my $line2 = Koha::Account::Line->new({ borrowernumber => $borrower->borrowernumber, amount => 20, amountoutstanding => 20 })->store(); + + is( $account->balance(), "30.000000", "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.000000", "Account balance is 0" ); + + $line1->_result->discard_changes(); + $line2->_result->discard_changes(); + is( $line1->amountoutstanding, '0.000000', 'First fee has amount outstanding of 0' ); + is( $line2->amountoutstanding, '0.000000', 'Second fee has amount outstanding of 0' ); + + $account_payment->void(); + + is( $account->balance(), "30.000000", "Account balance is again 30" ); + + $account_payment->_result->discard_changes(); + $line1->_result->discard_changes(); + $line2->_result->discard_changes(); + + is( $account_payment->accounttype, 'VOID', 'Voided payment accounttype is VOID' ); + is( $account_payment->amount, '0.000000', 'Voided payment amount is 0' ); + is( $account_payment->amountoutstanding, '0.000000', 'Voided payment amount outstanding is 0' ); + + is( $line1->amountoutstanding, '10.000000', 'First fee again has amount outstanding of 10' ); + is( $line2->amountoutstanding, '20.000000', 'Second fee again has amount outstanding of 20' ); +}; + 1; -- 2.10.2