From 0ca62155793ce78d613d025245650bad6ece1e14 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 Signed-off-by: Koha-us conference Signed-off-by: BWS Sandboxes --- Koha/Account/Line.pm | 46 +++++++++++++++++ .../prog/en/modules/members/boraccount.tt | 2 + members/boraccount.pl | 7 ++- t/db_dependent/Accounts.t | 57 ++++++++++++++++++++++ 4 files changed, 111 insertions(+), 1 deletion(-) 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 4a31c08..23921e9 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 @@ -123,6 +124,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 e7d769e..dc5e17c 100755 --- a/members/boraccount.pl +++ b/members/boraccount.pl @@ -49,7 +49,7 @@ 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 @@ -62,6 +62,11 @@ unless ( $patron ) { if ( $action eq 'reverse' ) { ReversePayment( scalar $input->param('accountlines_id') ); } +elsif ( $action eq 'void' ) { + my $payment_id = scalar $input->param('accountlines_id'); + my $payment = Koha::Account::Lines->find( $payment_id ); + $payment->void(); +} if ( $patron->category->category_type eq 'C') { my $patron_categories = Koha::Patron::Categories->search_limited({ category_type => 'A' }, {order_by => ['categorycode']}); diff --git a/t/db_dependent/Accounts.t b/t/db_dependent/Accounts.t index 60c010d..182e442 100644 --- a/t/db_dependent/Accounts.t +++ b/t/db_dependent/Accounts.t @@ -630,4 +630,61 @@ subtest "Koha::Account::chargelostitem tests" => sub { is( $procfee->amount, "2.040000", "Processing fee if processing fee"); }; +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