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 $payment_accountline->void();
66 # Make sure it is a payment we are voiding
67 return unless $self->amount < 0;
70 Koha::Account::Offsets->search(
71 { credit_id => $self->id, amount => { '<' => 0 } } );
73 $self->_result->result_source->schema->txn_do(
75 foreach my $account_offset (@account_offsets) {
77 Koha::Account::Lines->find( $account_offset->debit_id );
79 next unless $fee_paid;
81 my $amount_paid = $account_offset->amount * -1; # amount paid is stored as a negative amount
82 my $new_amount = $fee_paid->amountoutstanding + $amount_paid;
83 $fee_paid->amountoutstanding($new_amount);
86 Koha::Account::Offset->new(
88 credit_id => $self->id,
89 debit_id => $fee_paid->id,
90 amount => $amount_paid,
91 type => 'Void Payment',
96 if ( C4::Context->preference("FinesLog") ) {
99 $self->borrowernumber,
102 action => 'void_payment',
103 borrowernumber => $self->borrowernumber,
104 amount => $self->amount,
105 amountoutstanding => $self->amountoutstanding,
106 description => $self->description,
107 accounttype => $self->accounttype,
108 payment_type => $self->payment_type,
110 itemnumber => $self->itemnumber,
111 manager_id => $self->manager_id,
113 [ map { $_->unblessed } @account_offsets ],
121 accounttype => 'VOID',
122 amountoutstanding => 0,
134 my $debits = $account->outstanding_debits;
135 my $outstanding_amount = $credit->apply( { debits => $debits, [ offset_type => $offset_type ] } );
137 Applies the credit to a given debits set.
139 =head4 arguments hashref
143 =item debits - Koha::Account::Lines object set of debits
145 =item offset_type (optional) - a string indicating the offset type (valid values are those from
146 the 'account_offset_types' table)
153 my ( $self, $params ) = @_;
155 my $debits = $params->{debits};
156 my $offset_type = $params->{offset_type} // 'Credit Applied';
158 unless ( $self->is_credit ) {
159 Koha::Exceptions::Account::IsNotCredit->throw(
160 error => 'Account line ' . $self->id . ' is not a credit'
164 my $available_credit = $self->amountoutstanding * -1;
166 unless ( $available_credit > 0 ) {
167 Koha::Exceptions::Account::NoAvailableCredit->throw(
168 error => 'Outstanding credit is ' . $available_credit . ' and cannot be applied'
172 my $schema = Koha::Database->new->schema;
174 $schema->txn_do( sub {
175 while ( my $debit = $debits->next ) {
177 unless ( $debit->is_debit ) {
178 Koha::Exceptions::Account::IsNotDebit->throw(
179 error => 'Account line ' . $debit->id . 'is not a debit'
182 my $amount_to_cancel;
183 my $owed = $debit->amountoutstanding;
185 if ( $available_credit >= $owed ) {
186 $amount_to_cancel = $owed;
188 else { # $available_credit < $debit->amountoutstanding
189 $amount_to_cancel = $available_credit;
192 # record the account offset
193 Koha::Account::Offset->new(
194 { credit_id => $self->id,
195 debit_id => $debit->id,
196 amount => $amount_to_cancel * -1,
197 type => $offset_type,
201 $available_credit -= $amount_to_cancel;
203 $self->amountoutstanding( $available_credit * -1 )->store;
204 $debit->amountoutstanding( $owed - $amount_to_cancel )->store;
208 return $available_credit;
213 This method allows updating a debit or credit on a patron's account
215 $account_line->adjust(
218 type => $update_type,
222 $update_type can be any of:
225 Authors Note: The intention here is that this method is only used
226 to adjust accountlines where the final amount is not yet known/fixed.
227 Incrementing fines are the only existing case at the time of writing,
228 all other forms of 'adjustment' should be recorded as distinct credits
229 or debits and applied, via an offset, to the corresponding debit or credit.
234 my ( $self, $params ) = @_;
236 my $amount = $params->{amount};
237 my $update_type = $params->{type};
239 unless ( exists($Koha::Account::Line::allowed_update->{$update_type}) ) {
240 Koha::Exceptions::Account::UnrecognisedType->throw(
241 error => 'Update type not recognised'
245 my $account_type = $self->accounttype;
246 unless ( $Koha::Account::Line::allowed_update->{$update_type} eq $account_type ) {
247 Koha::Exceptions::Account::UnrecognisedType->throw(
248 error => 'Update type not allowed on this accounttype'
252 my $schema = Koha::Database->new->schema;
257 my $amount_before = $self->amount;
258 my $amount_outstanding_before = $self->amountoutstanding;
259 my $difference = $amount - $amount_before;
260 my $new_outstanding = $amount_outstanding_before + $difference;
262 my $offset_type = substr( $update_type, 0, index( $update_type, '_' ) );
263 $offset_type .= ( $difference > 0 ) ? "_increase" : "_decrease";
265 # Catch cases that require patron refunds
266 if ( $new_outstanding < 0 ) {
268 Koha::Patrons->find( $self->borrowernumber )->account;
269 my $credit = $account->add_credit(
271 amount => $new_outstanding * -1,
272 description => 'Overpayment refund',
274 ( $update_type eq 'fine_update' ? ( item_id => $self->itemnumber ) : ()),
277 $new_outstanding = 0;
280 # Update the account line
285 amountoutstanding => $new_outstanding,
286 ( $update_type eq 'fine_update' ? ( lastincrement => $difference ) : ()),
290 # Record the account offset
291 my $account_offset = Koha::Account::Offset->new(
293 debit_id => $self->id,
294 type => $offset_type,
295 amount => $difference
299 if ( C4::Context->preference("FinesLog") ) {
301 "FINES", 'UPDATE', #undef becomes UPDATE in UpdateFine
302 $self->borrowernumber,
304 { action => $update_type,
305 borrowernumber => $self->borrowernumber,
306 accountno => $self->accountno,
308 description => undef,
309 amountoutstanding => $new_outstanding,
310 accounttype => $self->accounttype,
312 itemnumber => $self->itemnumber,
316 ) if ( $update_type eq 'fine_update' );
326 my $bool = $line->is_credit;
333 return ( $self->amount < 0 );
338 my $bool = $line->is_debit;
345 return !$self->is_credit;
348 =head2 Internal methods
357 return 'Accountline';
364 =head3 $allowed_update
368 our $allowed_update = { 'fine_update' => 'FU', };
372 Kyle M Hall <kyle@bywatersolutions.com >
373 Tomás Cohen Arazi <tomascohen@theke.io>
374 Martin Renvoize <martin.renvoize@ptfs-europe.com>