@@ -, +, @@
---
Koha/Account/Line.pm | 46 +++++++++++++++++
installer/data/mysql/account_offset_types.sql | 3 +-
.../prog/en/modules/members/boraccount.tt | 2 +
members/boraccount.pl | 7 ++-
t/db_dependent/Accounts.t | 59 +++++++++++++++++++++-
5 files changed, 114 insertions(+), 3 deletions(-)
--- a/Koha/Account/Line.pm
+++ a/Koha/Account/Line.pm
@@ -21,6 +21,7 @@ use Carp;
use Koha::Database;
use Koha::Items;
+use Koha::Account::Offsets;
use base qw(Koha::Object);
@@ -46,6 +47,51 @@ sub item {
return Koha::Item->_new_from_dbic( $rs );
}
+=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',
+ }
+ )->store();
+ }
+
+ $self->set(
+ {
+ accounttype => 'VOID',
+ amountoutstanding => 0,
+ amount => 0,
+ }
+ );
+ $self->store();
+}
+
=head3 _type
=cut
--- a/installer/data/mysql/account_offset_types.sql
+++ a/installer/data/mysql/account_offset_types.sql
@@ -9,4 +9,5 @@ INSERT INTO account_offset_types ( type ) VALUES
('Dropbox'),
('Rental Fee'),
('Fine Update'),
-('Fine');
+('Fine'),
+('Void Payment');
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt
@@ -60,6 +60,7 @@
[% 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
@@ -93,6 +94,7 @@
[% IF ( reverse_col) %]
[% IF ( account.payment ) %]
Reverse
+ Void
[% ELSE %][% SET footerjs = 1 %]
[% END %]
--- a/members/boraccount.pl
+++ a/members/boraccount.pl
@@ -48,7 +48,7 @@ my ($template, $loggedinuser, $cookie) = get_template_and_user(
}
);
-my $borrowernumber=$input->param('borrowernumber');
+my $borrowernumber = $input->param('borrowernumber');
my $action = $input->param('action') || '';
my $logged_in_user = Koha::Patrons->find( $loggedinuser ) or die "Not logged in";
@@ -63,6 +63,11 @@ output_and_exit_if_error( $input, $cookie, $template, { module => 'members', log
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->is_child ) {
my $patron_categories = Koha::Patron::Categories->search_limited({ category_type => 'A' }, {order_by => ['categorycode']});
--- a/t/db_dependent/Accounts.t
+++ a/t/db_dependent/Accounts.t
@@ -18,7 +18,7 @@
use Modern::Perl;
-use Test::More tests => 25;
+use Test::More tests => 26;
use Test::MockModule;
use Test::Warn;
@@ -847,4 +847,61 @@ subtest "Koha::Account::non_issues_charges tests" => sub {
is( Koha::Account::Lines->count({ borrowernumber => $patron->id }), 2 + 2, "The 2 + 2 account lines still exists, the last 2 have been deleted ok" );
};
+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, "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.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, "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;
--