1 package Koha::Account::Line;
3 # This file is part of Koha.
5 # Koha is free software; you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation; either version 3 of the License, or (at your option) any later
10 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License along
15 # with Koha; if not, write to the Free Software Foundation, Inc.,
16 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 use C4::Log qw(logaction);
25 use Koha::Account::Offsets;
27 use Koha::Exceptions::Account;
30 use base qw(Koha::Object);
36 Koha::Account::Line - Koha accountline Object class
46 Return the item linked to this account line if exists
52 my $rs = $self->_result->itemnumber;
54 return Koha::Item->_new_from_dbic( $rs );
59 Return the checkout linked to this account line if exists
65 return unless $self->issue_id ;
67 $self->{_checkout} ||= Koha::Checkouts->find( $self->issue_id );
68 $self->{_checkout} ||= Koha::Old::Checkouts->find( $self->issue_id );
69 return $self->{_checkout};
74 $payment_accountline->void();
76 Used to 'void' (or reverse) a payment/credit. It will role back any offsets
77 created by the application of this credit upon any debits and mark the credit
78 as 'void' by updating it's status to "VOID".
85 # Make sure it is a payment we are voiding
86 return unless $self->amount < 0;
89 Koha::Account::Offsets->search(
90 { credit_id => $self->id, amount => { '<' => 0 } } );
92 $self->_result->result_source->schema->txn_do(
94 foreach my $account_offset (@account_offsets) {
96 Koha::Account::Lines->find( $account_offset->debit_id );
98 next unless $fee_paid;
100 my $amount_paid = $account_offset->amount * -1; # amount paid is stored as a negative amount
101 my $new_amount = $fee_paid->amountoutstanding + $amount_paid;
102 $fee_paid->amountoutstanding($new_amount);
105 Koha::Account::Offset->new(
107 credit_id => $self->id,
108 debit_id => $fee_paid->id,
109 amount => $amount_paid,
110 type => 'Void Payment',
115 if ( C4::Context->preference("FinesLog") ) {
118 $self->borrowernumber,
121 action => 'void_payment',
122 borrowernumber => $self->borrowernumber,
123 amount => $self->amount,
124 amountoutstanding => $self->amountoutstanding,
125 description => $self->description,
126 accounttype => $self->accounttype,
127 payment_type => $self->payment_type,
129 itemnumber => $self->itemnumber,
130 manager_id => $self->manager_id,
132 [ map { $_->unblessed } @account_offsets ],
141 amountoutstanding => 0,
153 my $debits = $account->outstanding_debits;
154 my $outstanding_amount = $credit->apply( { debits => $debits, [ offset_type => $offset_type ] } );
156 Applies the credit to a given debits set.
158 =head4 arguments hashref
162 =item debits - Koha::Account::Lines object set of debits
164 =item offset_type (optional) - a string indicating the offset type (valid values are those from
165 the 'account_offset_types' table)
172 my ( $self, $params ) = @_;
174 my $debits = $params->{debits};
175 my $offset_type = $params->{offset_type} // 'Credit Applied';
177 unless ( $self->is_credit ) {
178 Koha::Exceptions::Account::IsNotCredit->throw(
179 error => 'Account line ' . $self->id . ' is not a credit'
183 my $available_credit = $self->amountoutstanding * -1;
185 unless ( $available_credit > 0 ) {
186 Koha::Exceptions::Account::NoAvailableCredit->throw(
187 error => 'Outstanding credit is ' . $available_credit . ' and cannot be applied'
191 my $schema = Koha::Database->new->schema;
193 $schema->txn_do( sub {
194 while ( my $debit = $debits->next ) {
196 unless ( $debit->is_debit ) {
197 Koha::Exceptions::Account::IsNotDebit->throw(
198 error => 'Account line ' . $debit->id . 'is not a debit'
201 my $amount_to_cancel;
202 my $owed = $debit->amountoutstanding;
204 if ( $available_credit >= $owed ) {
205 $amount_to_cancel = $owed;
207 else { # $available_credit < $debit->amountoutstanding
208 $amount_to_cancel = $available_credit;
211 # record the account offset
212 Koha::Account::Offset->new(
213 { credit_id => $self->id,
214 debit_id => $debit->id,
215 amount => $amount_to_cancel * -1,
216 type => $offset_type,
220 $available_credit -= $amount_to_cancel;
222 $self->amountoutstanding( $available_credit * -1 )->store;
223 $debit->amountoutstanding( $owed - $amount_to_cancel )->store;
227 return $available_credit;
232 This method allows updating a debit or credit on a patron's account
234 $account_line->adjust(
237 type => $update_type,
238 interface => $interface
242 $update_type can be any of:
245 Authors Note: The intention here is that this method is only used
246 to adjust accountlines where the final amount is not yet known/fixed.
247 Incrementing fines are the only existing case at the time of writing,
248 all other forms of 'adjustment' should be recorded as distinct credits
249 or debits and applied, via an offset, to the corresponding debit or credit.
254 my ( $self, $params ) = @_;
256 my $amount = $params->{amount};
257 my $update_type = $params->{type};
258 my $interface = $params->{interface};
260 unless ( exists($Koha::Account::Line::allowed_update->{$update_type}) ) {
261 Koha::Exceptions::Account::UnrecognisedType->throw(
262 error => 'Update type not recognised'
266 my $account_type = $self->accounttype;
267 my $account_status = $self->status;
271 $Koha::Account::Line::allowed_update->{$update_type}
274 && ( $Koha::Account::Line::allowed_update->{$update_type}
275 ->{$account_type} eq $account_status )
279 Koha::Exceptions::Account::UnrecognisedType->throw(
280 error => 'Update type not allowed on this accounttype' );
283 my $schema = Koha::Database->new->schema;
288 my $amount_before = $self->amount;
289 my $amount_outstanding_before = $self->amountoutstanding;
290 my $difference = $amount - $amount_before;
291 my $new_outstanding = $amount_outstanding_before + $difference;
293 my $offset_type = $account_type;
294 $offset_type .= ( $difference > 0 ) ? "_INCREASE" : "_DECREASE";
296 # Catch cases that require patron refunds
297 if ( $new_outstanding < 0 ) {
299 Koha::Patrons->find( $self->borrowernumber )->account;
300 my $credit = $account->add_credit(
302 amount => $new_outstanding * -1,
303 description => 'Overpayment refund',
305 interface => $interface,
306 ( $update_type eq 'overdue_update' ? ( item_id => $self->itemnumber ) : ()),
309 $new_outstanding = 0;
312 # Update the account line
317 amountoutstanding => $new_outstanding,
321 # Record the account offset
322 my $account_offset = Koha::Account::Offset->new(
324 debit_id => $self->id,
325 type => $offset_type,
326 amount => $difference
330 if ( C4::Context->preference("FinesLog") ) {
332 "FINES", 'UPDATE', #undef becomes UPDATE in UpdateFine
333 $self->borrowernumber,
335 { action => $update_type,
336 borrowernumber => $self->borrowernumber,
338 description => undef,
339 amountoutstanding => $new_outstanding,
340 accounttype => $self->accounttype,
342 itemnumber => $self->itemnumber,
346 ) if ( $update_type eq 'overdue_update' );
356 my $bool = $line->is_credit;
363 return ( $self->amount < 0 );
368 my $bool = $line->is_debit;
375 return !$self->is_credit;
378 =head2 Internal methods
387 return 'Accountline';
394 =head3 $allowed_update
398 our $allowed_update = { 'overdue_update' => { 'OVERDUE' => 'UNRETURNED' } };
402 Kyle M Hall <kyle@bywatersolutions.com >
403 Tomás Cohen Arazi <tomascohen@theke.io>
404 Martin Renvoize <martin.renvoize@ptfs-europe.com>