Bugzilla – Attachment 97009 Details for
Bug 23442
Add a 'refund' process to accounts
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 23442: Add 'reduce' method to Koha::Account::Line
Bug-23442-Add-reduce-method-to-KohaAccountLine.patch (text/plain), 12.13 KB, created by
Kyle M Hall (khall)
on 2020-01-08 15:53:43 UTC
(
hide
)
Description:
Bug 23442: Add 'reduce' method to Koha::Account::Line
Filename:
MIME Type:
Creator:
Kyle M Hall (khall)
Created:
2020-01-08 15:53:43 UTC
Size:
12.13 KB
patch
obsolete
>From 61b422a19ce904675931419fb785ca5430633858 Mon Sep 17 00:00:00 2001 >From: Martin Renvoize <martin.renvoize@ptfs-europe.com> >Date: Thu, 21 Nov 2019 12:10:41 +0000 >Subject: [PATCH] Bug 23442: Add 'reduce' method to Koha::Account::Line > >This enhancement adds a 'reduce' method to Koha::Account::Line which can >be used to reduce a charge/debit by adding a credit to offset against >the amount outstanding. > >It may be used to apply a discount whilst retaining the original debit >amounts or to apply a full or partial refund for example when a lost >item is found and returned. > >The created credit will be immediately applied against the debit unless >the debit has already been paid, in which case a 'zero' offset will be >added to maintain a link to the debit but the outstanding credit will be >left so it may be applied to other debts. > >Test Plan: >1) Run the included tests and verify they pass. >2) Signoff > >Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com> >--- > Koha/Account/Line.pm | 135 +++++++++++++++++++++++ > t/db_dependent/Koha/Account/Lines.t | 160 +++++++++++++++++++++++++++- > 2 files changed, 294 insertions(+), 1 deletion(-) > >diff --git a/Koha/Account/Line.pm b/Koha/Account/Line.pm >index f84d460178..4288e964a2 100644 >--- a/Koha/Account/Line.pm >+++ b/Koha/Account/Line.pm >@@ -270,6 +270,141 @@ sub void { > > } > >+=head3 reduce >+ >+ $charge_accountline->reduce({ >+ reduction_type => $reduction_type >+ }); >+ >+Used to 'reduce' a charge/debit by adding a credit to offset against the amount >+outstanding. >+ >+May be used to apply a discount whilst retaining the original debit amounts or >+to apply a full or partial refund for example when a lost item is found and >+returned. >+ >+It will immediately be applied to the given debit unless the debit has already >+been paid, in which case a 'zero' offset will be added to maintain a link to >+the debit but the outstanding credit will be left so it may be applied to other >+debts. >+ >+Reduction type may be one of: >+ >+* DISCOUNT >+* REFUND >+ >+Returns the reduction accountline (which will be a credit) >+ >+=cut >+ >+sub reduce { >+ my ( $self, $params ) = @_; >+ >+ # Make sure it is a charge we are reducing >+ unless ( $self->is_debit ) { >+ Koha::Exceptions::Account::IsNotDebit->throw( >+ error => 'Account line ' . $self->id . 'is not a debit' ); >+ } >+ >+ # Check for mandatory parameters >+ my @mandatory = ( 'interface', 'reduction_type', 'amount' ); >+ for my $param (@mandatory) { >+ unless ( defined( $params->{$param} ) ) { >+ Koha::Exceptions::MissingParameter->throw( >+ error => "The $param parameter is mandatory" ); >+ } >+ } >+ >+ # More mandatory parameters >+ if ( $params->{interface} eq 'intranet' ) { >+ my @optional = ( 'staff_id', 'branch' ); >+ for my $param (@optional) { >+ unless ( defined( $params->{$param} ) ) { >+ Koha::Exceptions::MissingParameter->throw( error => >+"The $param parameter is mandatory when interface is set to 'intranet'" >+ ); >+ } >+ } >+ } >+ >+ # Make sure the reduction isn't more than the original >+ my $original = $self->amount; >+ Koha::Exceptions::Account::AmountNotPositive->throw( >+ error => 'Reduce amount passed is not positive' ) >+ unless ( $params->{amount} > 0 ); >+ Koha::Exceptions::ParameterTooHigh->throw( error => >+"Amount to reduce ($params->{amount}) is higher than original amount ($original)" >+ ) unless ( $original >= $params->{amount} ); >+ my $reduced = >+ $self->credits( { credit_type_code => [ 'DISCOUNT', 'REFUND' ] } )->total; >+ Koha::Exceptions::ParameterTooHigh->throw( error => >+"Combined reduction ($params->{amount} + $reduced) is higher than original amount (" >+ . abs($original) >+ . ")" ) >+ unless ( $original >= ( $params->{amount} + abs($reduced) ) ); >+ >+ my $status = { 'REFUND' => 'REFUNDED', 'DISCOUNT' => 'DISCOUNTED' }; >+ >+ my $reduction; >+ $self->_result->result_source->schema->txn_do( >+ sub { >+ >+ # A 'reduction' is a 'credit' >+ $reduction = Koha::Account::Line->new( >+ { >+ date => \'NOW()', >+ amount => 0 - $params->{amount}, >+ credit_type_code => $params->{reduction_type}, >+ status => 'ADDED', >+ amountoutstanding => 0 - $params->{amount}, >+ manager_id => $params->{staff_id}, >+ borrowernumber => $self->borrowernumber, >+ interface => $params->{interface}, >+ branchcode => $params->{branch}, >+ } >+ )->store(); >+ >+ my $reduction_offset = Koha::Account::Offset->new( >+ { >+ credit_id => $reduction->accountlines_id, >+ type => uc( $params->{reduction_type} ), >+ amount => $params->{amount} >+ } >+ )->store(); >+ >+ # Link reduction to charge (and apply as required) >+ my $debit_outstanding = $self->amountoutstanding; >+ if ( $debit_outstanding >= $params->{amount} ) { >+ >+ $reduction->apply( >+ { >+ debits => [$self], >+ offset_type => $params->{reduction_type} >+ } >+ ); >+ $reduction->status('APPLIED')->store(); >+ } >+ else { >+ >+ # Zero amount offset used to link original 'debit' to reduction 'credit' >+ my $link_reduction_offset = Koha::Account::Offset->new( >+ { >+ credit_id => $reduction->accountlines_id, >+ debit_id => $self->accountlines_id, >+ type => $params->{reduction_type}, >+ amount => 0 >+ } >+ )->store(); >+ } >+ >+ # Update status of original debit >+ $self->status( $status->{ $params->{reduction_type} } )->store; >+ } >+ ); >+ >+ return $reduction->discard_changes; >+} >+ > =head3 apply > > my $debits = $account->outstanding_debits; >diff --git a/t/db_dependent/Koha/Account/Lines.t b/t/db_dependent/Koha/Account/Lines.t >index f0601354f8..873cb38739 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 => 14; >+use Test::More tests => 15; > use Test::Exception; > > use C4::Circulation qw/AddIssue AddReturn/; >@@ -1029,4 +1029,162 @@ subtest "payout() tests" => sub { > $schema->storage->txn_rollback; > }; > >+subtest "reduce() tests" => sub { >+ >+ plan tests => 25; >+ >+ $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( $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 mor than the original amount (combined reductions test)'; >+ >+ $schema->storage->txn_rollback; >+}; >+ > 1; >-- >2.21.0 (Apple Git-122.2)
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 23442
:
92954
|
92955
|
92956
|
95674
|
95675
|
95676
|
95677
|
96400
|
96401
|
96402
|
96403
|
96414
|
96415
|
96416
|
96417
|
97008
|
97009
|
97010
|
97011
|
97012
|
97062
|
97063
|
97064
|
97065
|
97066
|
97067
|
97151
|
97152
|
97153
|
97154
|
97155
|
97156