Bug 21637: Fixed upercase letter in EasyAnalyticalRecords syspref
[koha.git] / Koha / Account / Line.pm
blob529b625d02e5b8c816ce35d157e068c545b3dd4c
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
8 # version.
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.
18 use Modern::Perl;
20 use Carp;
21 use Data::Dumper;
23 use C4::Log qw(logaction);
25 use Koha::Account::Offsets;
26 use Koha::Database;
27 use Koha::Exceptions::Account;
28 use Koha::Items;
30 use base qw(Koha::Object);
32 =encoding utf8
34 =head1 NAME
36 Koha::Account::Line - Koha accountline Object class
38 =head1 API
40 =head2 Class methods
42 =cut
44 =head3 item
46 Return the item linked to this account line if exists
48 =cut
50 sub item {
51 my ( $self ) = @_;
52 my $rs = $self->_result->itemnumber;
53 return Koha::Item->_new_from_dbic( $rs );
56 =head3 void
58 $payment_accountline->void();
60 =cut
62 sub void {
63 my ($self) = @_;
65 # Make sure it is a payment we are voiding
66 return unless $self->amount < 0;
68 my @account_offsets =
69 Koha::Account::Offsets->search(
70 { credit_id => $self->id, amount => { '<' => 0 } } );
72 $self->_result->result_source->schema->txn_do(
73 sub {
74 foreach my $account_offset (@account_offsets) {
75 my $fee_paid =
76 Koha::Account::Lines->find( $account_offset->debit_id );
78 next unless $fee_paid;
80 my $amount_paid = $account_offset->amount * -1; # amount paid is stored as a negative amount
81 my $new_amount = $fee_paid->amountoutstanding + $amount_paid;
82 $fee_paid->amountoutstanding($new_amount);
83 $fee_paid->store();
85 Koha::Account::Offset->new(
87 credit_id => $self->id,
88 debit_id => $fee_paid->id,
89 amount => $amount_paid,
90 type => 'Void Payment',
92 )->store();
95 if ( C4::Context->preference("FinesLog") ) {
96 logaction(
97 "FINES", 'VOID',
98 $self->borrowernumber,
99 Dumper(
101 action => 'void_payment',
102 borrowernumber => $self->borrowernumber,
103 amount => $self->amount,
104 amountoutstanding => $self->amountoutstanding,
105 description => $self->description,
106 accounttype => $self->accounttype,
107 payment_type => $self->payment_type,
108 note => $self->note,
109 itemnumber => $self->itemnumber,
110 manager_id => $self->manager_id,
111 offsets =>
112 [ map { $_->unblessed } @account_offsets ],
118 $self->set(
120 accounttype => 'VOID',
121 amountoutstanding => 0,
122 amount => 0,
125 $self->store();
131 =head3 apply
133 my $debits = $account->outstanding_debits;
134 my $outstanding_amount = $credit->apply( { debits => $debits, [ offset_type => $offset_type ] } );
136 Applies the credit to a given debits set.
138 =head4 arguments hashref
140 =over 4
142 =item debits - Koha::Account::Lines object set of debits
144 =item offset_type (optional) - a string indicating the offset type (valid values are those from
145 the 'account_offset_types' table)
147 =back
149 =cut
151 sub apply {
152 my ( $self, $params ) = @_;
154 my $debits = $params->{debits};
155 my $offset_type = $params->{offset_type} // 'Credit Applied';
157 unless ( $self->is_credit ) {
158 Koha::Exceptions::Account::IsNotCredit->throw(
159 error => 'Account line ' . $self->id . ' is not a credit'
163 my $available_credit = $self->amountoutstanding * -1;
165 unless ( $available_credit > 0 ) {
166 Koha::Exceptions::Account::NoAvailableCredit->throw(
167 error => 'Outstanding credit is ' . $available_credit . ' and cannot be applied'
171 my $schema = Koha::Database->new->schema;
173 $schema->txn_do( sub {
174 while ( my $debit = $debits->next ) {
176 unless ( $debit->is_debit ) {
177 Koha::Exceptions::Account::IsNotDebit->throw(
178 error => 'Account line ' . $debit->id . 'is not a debit'
181 my $amount_to_cancel;
182 my $owed = $debit->amountoutstanding;
184 if ( $available_credit >= $owed ) {
185 $amount_to_cancel = $owed;
187 else { # $available_credit < $debit->amountoutstanding
188 $amount_to_cancel = $available_credit;
191 # record the account offset
192 Koha::Account::Offset->new(
193 { credit_id => $self->id,
194 debit_id => $debit->id,
195 amount => $amount_to_cancel * -1,
196 type => $offset_type,
198 )->store();
200 $available_credit -= $amount_to_cancel;
202 $self->amountoutstanding( $available_credit * -1 )->store;
203 $debit->amountoutstanding( $owed - $amount_to_cancel )->store;
207 return $available_credit;
210 =head3 adjust
212 This method allows updating a debit or credit on a patron's account
214 $account_line->adjust(
216 amount => $amount,
217 type => $update_type,
221 $update_type can be any of:
222 - fine_increment
224 Authors Note: The intention here is that this method is only used
225 to adjust accountlines where the final amount is not yet known/fixed.
226 Incrementing fines are the only existing case at the time of writing,
227 all other forms of 'adjustment' should be recorded as distinct credits
228 or debits and applied, via an offset, to the corresponding debit or credit.
230 =cut
232 sub adjust {
233 my ( $self, $params ) = @_;
235 my $amount = $params->{amount};
236 my $update_type = $params->{type};
238 unless ( exists($Koha::Account::Line::offset_type->{$update_type}) ) {
239 Koha::Exceptions::Account::UnrecognisedType->throw(
240 error => 'Update type not recognised'
244 my $account_type = $self->accounttype;
245 unless ( $Koha::Account::Line::allowed_update->{$update_type} eq $account_type ) {
246 Koha::Exceptions::Account::UnrecognisedType->throw(
247 error => 'Update type not allowed on this accounttype'
251 my $schema = Koha::Database->new->schema;
253 $schema->txn_do(
254 sub {
256 my $amount_before = $self->amount;
257 my $amount_outstanding_before = $self->amountoutstanding;
258 my $difference = $amount - $amount_before;
259 my $new_outstanding = $amount_outstanding_before + $difference;
261 # Catch cases that require patron refunds
262 if ( $new_outstanding < 0 ) {
263 my $account =
264 Koha::Patrons->find( $self->borrowernumber )->account;
265 my $credit = $account->add_credit(
267 amount => $new_outstanding * -1,
268 description => 'Overpayment refund',
269 type => 'credit',
270 ( $update_type eq 'fine_increment' ? ( item_id => $self->itemnumber ) : ()),
273 $new_outstanding = 0;
276 # Update the account line
277 $self->set(
279 date => \'NOW()',
280 amount => $amount,
281 amountoutstanding => $new_outstanding,
282 ( $update_type eq 'fine_increment' ? ( lastincrement => $difference ) : ()),
284 )->store();
286 # Record the account offset
287 my $account_offset = Koha::Account::Offset->new(
289 debit_id => $self->id,
290 type => $Koha::Account::Line::offset_type->{$update_type},
291 amount => $difference
293 )->store();
295 if ( C4::Context->preference("FinesLog") ) {
296 logaction(
297 "FINES", 'UPDATE', #undef becomes UPDATE in UpdateFine
298 $self->borrowernumber,
299 Dumper(
300 { action => $update_type,
301 borrowernumber => $self->borrowernumber,
302 accountno => $self->accountno,
303 amount => $amount,
304 description => undef,
305 amountoutstanding => $new_outstanding,
306 accounttype => $self->accounttype,
307 note => undef,
308 itemnumber => $self->itemnumber,
309 manager_id => undef,
312 ) if ( $update_type eq 'fine_increment' );
317 return $self;
320 =head3 is_credit
322 my $bool = $line->is_credit;
324 =cut
326 sub is_credit {
327 my ($self) = @_;
329 return ( $self->amount < 0 );
332 =head3 is_debit
334 my $bool = $line->is_debit;
336 =cut
338 sub is_debit {
339 my ($self) = @_;
341 return !$self->is_credit;
344 =head2 Internal methods
346 =cut
348 =head3 _type
350 =cut
352 sub _type {
353 return 'Accountline';
358 =head2 Name mappings
360 =head3 $offset_type
362 =cut
364 our $offset_type = { 'fine_increment' => 'Fine Update', };
366 =head3 $allowed_update
368 =cut
370 our $allowed_update = { 'fine_increment' => 'FU', };
372 =head1 AUTHORS
374 Kyle M Hall <kyle@bywatersolutions.com >
375 Tomás Cohen Arazi <tomascohen@theke.io>
376 Martin Renvoize <martin.renvoize@ptfs-europe.com>
378 =cut