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();
81 # Make sure it is a payment we are voiding
82 return unless $self->amount < 0;
85 Koha::Account::Offsets->search(
86 { credit_id => $self->id, amount => { '<' => 0 } } );
88 $self->_result->result_source->schema->txn_do(
90 foreach my $account_offset (@account_offsets) {
92 Koha::Account::Lines->find( $account_offset->debit_id );
94 next unless $fee_paid;
96 my $amount_paid = $account_offset->amount * -1; # amount paid is stored as a negative amount
97 my $new_amount = $fee_paid->amountoutstanding + $amount_paid;
98 $fee_paid->amountoutstanding($new_amount);
101 Koha::Account::Offset->new(
103 credit_id => $self->id,
104 debit_id => $fee_paid->id,
105 amount => $amount_paid,
106 type => 'Void Payment',
111 if ( C4::Context->preference("FinesLog") ) {
114 $self->borrowernumber,
117 action => 'void_payment',
118 borrowernumber => $self->borrowernumber,
119 amount => $self->amount,
120 amountoutstanding => $self->amountoutstanding,
121 description => $self->description,
122 accounttype => $self->accounttype,
123 payment_type => $self->payment_type,
125 itemnumber => $self->itemnumber,
126 manager_id => $self->manager_id,
128 [ map { $_->unblessed } @account_offsets ],
136 accounttype => 'VOID',
137 amountoutstanding => 0,
149 my $debits = $account->outstanding_debits;
150 my $outstanding_amount = $credit->apply( { debits => $debits, [ offset_type => $offset_type ] } );
152 Applies the credit to a given debits set.
154 =head4 arguments hashref
158 =item debits - Koha::Account::Lines object set of debits
160 =item offset_type (optional) - a string indicating the offset type (valid values are those from
161 the 'account_offset_types' table)
168 my ( $self, $params ) = @_;
170 my $debits = $params->{debits};
171 my $offset_type = $params->{offset_type} // 'Credit Applied';
173 unless ( $self->is_credit ) {
174 Koha::Exceptions::Account::IsNotCredit->throw(
175 error => 'Account line ' . $self->id . ' is not a credit'
179 my $available_credit = $self->amountoutstanding * -1;
181 unless ( $available_credit > 0 ) {
182 Koha::Exceptions::Account::NoAvailableCredit->throw(
183 error => 'Outstanding credit is ' . $available_credit . ' and cannot be applied'
187 my $schema = Koha::Database->new->schema;
189 $schema->txn_do( sub {
190 while ( my $debit = $debits->next ) {
192 unless ( $debit->is_debit ) {
193 Koha::Exceptions::Account::IsNotDebit->throw(
194 error => 'Account line ' . $debit->id . 'is not a debit'
197 my $amount_to_cancel;
198 my $owed = $debit->amountoutstanding;
200 if ( $available_credit >= $owed ) {
201 $amount_to_cancel = $owed;
203 else { # $available_credit < $debit->amountoutstanding
204 $amount_to_cancel = $available_credit;
207 # record the account offset
208 Koha::Account::Offset->new(
209 { credit_id => $self->id,
210 debit_id => $debit->id,
211 amount => $amount_to_cancel * -1,
212 type => $offset_type,
216 $available_credit -= $amount_to_cancel;
218 $self->amountoutstanding( $available_credit * -1 )->store;
219 $debit->amountoutstanding( $owed - $amount_to_cancel )->store;
223 return $available_credit;
228 This method allows updating a debit or credit on a patron's account
230 $account_line->adjust(
233 type => $update_type,
234 interface => $interface
238 $update_type can be any of:
241 Authors Note: The intention here is that this method is only used
242 to adjust accountlines where the final amount is not yet known/fixed.
243 Incrementing fines are the only existing case at the time of writing,
244 all other forms of 'adjustment' should be recorded as distinct credits
245 or debits and applied, via an offset, to the corresponding debit or credit.
250 my ( $self, $params ) = @_;
252 my $amount = $params->{amount};
253 my $update_type = $params->{type};
254 my $interface = $params->{interface};
256 unless ( exists($Koha::Account::Line::allowed_update->{$update_type}) ) {
257 Koha::Exceptions::Account::UnrecognisedType->throw(
258 error => 'Update type not recognised'
262 my $account_type = $self->accounttype;
263 my $account_status = $self->status;
267 $Koha::Account::Line::allowed_update->{$update_type}
270 && ( $Koha::Account::Line::allowed_update->{$update_type}
271 ->{$account_type} eq $account_status )
275 Koha::Exceptions::Account::UnrecognisedType->throw(
276 error => 'Update type not allowed on this accounttype' );
279 my $schema = Koha::Database->new->schema;
284 my $amount_before = $self->amount;
285 my $amount_outstanding_before = $self->amountoutstanding;
286 my $difference = $amount - $amount_before;
287 my $new_outstanding = $amount_outstanding_before + $difference;
289 my $offset_type = $account_type;
290 $offset_type .= ( $difference > 0 ) ? "_INCREASE" : "_DECREASE";
292 # Catch cases that require patron refunds
293 if ( $new_outstanding < 0 ) {
295 Koha::Patrons->find( $self->borrowernumber )->account;
296 my $credit = $account->add_credit(
298 amount => $new_outstanding * -1,
299 description => 'Overpayment refund',
301 interface => $interface,
302 ( $update_type eq 'overdue_update' ? ( item_id => $self->itemnumber ) : ()),
305 $new_outstanding = 0;
308 # Update the account line
313 amountoutstanding => $new_outstanding,
317 # Record the account offset
318 my $account_offset = Koha::Account::Offset->new(
320 debit_id => $self->id,
321 type => $offset_type,
322 amount => $difference
326 if ( C4::Context->preference("FinesLog") ) {
328 "FINES", 'UPDATE', #undef becomes UPDATE in UpdateFine
329 $self->borrowernumber,
331 { action => $update_type,
332 borrowernumber => $self->borrowernumber,
334 description => undef,
335 amountoutstanding => $new_outstanding,
336 accounttype => $self->accounttype,
338 itemnumber => $self->itemnumber,
342 ) if ( $update_type eq 'overdue_update' );
352 my $bool = $line->is_credit;
359 return ( $self->amount < 0 );
364 my $bool = $line->is_debit;
371 return !$self->is_credit;
374 =head2 Internal methods
383 return 'Accountline';
390 =head3 $allowed_update
394 our $allowed_update = { 'overdue_update' => { 'OVERDUE' => 'UNRETURNED' } };
398 Kyle M Hall <kyle@bywatersolutions.com >
399 Tomás Cohen Arazi <tomascohen@theke.io>
400 Martin Renvoize <martin.renvoize@ptfs-europe.com>