Bug 21797: Update two-column templates with Bootstrap grid: Acquisitions part 5
[koha.git] / Koha / Account / Line.pm
blob502499a8a72410dc16c1d50183dee8702c6cdaac
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 =head1 NAME
34 Koha::Account::Line - Koha accountline Object class
36 =head1 API
38 =head2 Class methods
40 =cut
42 =head3 item
44 Return the item linked to this account line if exists
46 =cut
48 sub item {
49 my ( $self ) = @_;
50 my $rs = $self->_result->itemnumber;
51 return Koha::Item->_new_from_dbic( $rs );
54 =head3 void
56 $payment_accountline->void();
58 =cut
60 sub void {
61 my ($self) = @_;
63 # Make sure it is a payment we are voiding
64 return unless $self->amount < 0;
66 my @account_offsets =
67 Koha::Account::Offsets->search(
68 { credit_id => $self->id, amount => { '<' => 0 } } );
70 $self->_result->result_source->schema->txn_do(
71 sub {
72 foreach my $account_offset (@account_offsets) {
73 my $fee_paid =
74 Koha::Account::Lines->find( $account_offset->debit_id );
76 next unless $fee_paid;
78 my $amount_paid = $account_offset->amount * -1; # amount paid is stored as a negative amount
79 my $new_amount = $fee_paid->amountoutstanding + $amount_paid;
80 $fee_paid->amountoutstanding($new_amount);
81 $fee_paid->store();
83 Koha::Account::Offset->new(
85 credit_id => $self->id,
86 debit_id => $fee_paid->id,
87 amount => $amount_paid,
88 type => 'Void Payment',
90 )->store();
93 if ( C4::Context->preference("FinesLog") ) {
94 logaction(
95 "FINES", 'VOID',
96 $self->borrowernumber,
97 Dumper(
99 action => 'void_payment',
100 borrowernumber => $self->borrowernumber,
101 amount => $self->amount,
102 amountoutstanding => $self->amountoutstanding,
103 description => $self->description,
104 accounttype => $self->accounttype,
105 payment_type => $self->payment_type,
106 note => $self->note,
107 itemnumber => $self->itemnumber,
108 manager_id => $self->manager_id,
109 offsets =>
110 [ map { $_->unblessed } @account_offsets ],
116 $self->set(
118 accounttype => 'VOID',
119 amountoutstanding => 0,
120 amount => 0,
123 $self->store();
129 =head3 apply
131 my $debits = $account->outstanding_debits;
132 my $outstanding_amount = $credit->apply( { debits => $debits, [ offset_type => $offset_type ] } );
134 Applies the credit to a given debits set.
136 =head4 arguments hashref
138 =over 4
140 =item debits - Koha::Account::Lines object set of debits
142 =item offset_type (optional) - a string indicating the offset type (valid values are those from
143 the 'account_offset_types' table)
145 =back
147 =cut
149 sub apply {
150 my ( $self, $params ) = @_;
152 my $debits = $params->{debits};
153 my $offset_type = $params->{offset_type} // 'Credit Applied';
155 unless ( $self->is_credit ) {
156 Koha::Exceptions::Account::IsNotCredit->throw(
157 error => 'Account line ' . $self->id . ' is not a credit'
161 my $available_credit = $self->amountoutstanding * -1;
163 unless ( $available_credit > 0 ) {
164 Koha::Exceptions::Account::NoAvailableCredit->throw(
165 error => 'Outstanding credit is ' . $available_credit . ' and cannot be applied'
169 my $schema = Koha::Database->new->schema;
171 $schema->txn_do( sub {
172 while ( my $debit = $debits->next ) {
174 unless ( $debit->is_debit ) {
175 Koha::Exceptions::Account::IsNotDebit->throw(
176 error => 'Account line ' . $debit->id . 'is not a debit'
179 my $amount_to_cancel;
180 my $owed = $debit->amountoutstanding;
182 if ( $available_credit >= $owed ) {
183 $amount_to_cancel = $owed;
185 else { # $available_credit < $debit->amountoutstanding
186 $amount_to_cancel = $available_credit;
189 # record the account offset
190 Koha::Account::Offset->new(
191 { credit_id => $self->id,
192 debit_id => $debit->id,
193 amount => $amount_to_cancel * -1,
194 type => $offset_type,
196 )->store();
198 $available_credit -= $amount_to_cancel;
200 $self->amountoutstanding( $available_credit * -1 )->store;
201 $debit->amountoutstanding( $owed - $amount_to_cancel )->store;
205 return $available_credit;
208 =head3 adjust
210 This method allows updating a debit or credit on a patron's account
212 $account_line->adjust(
214 amount => $amount,
215 type => $update_type,
219 $update_type can be any of:
220 - fine_increment
222 Authors Note: The intention here is that this method is only used
223 to adjust accountlines where the final amount is not yet known/fixed.
224 Incrementing fines are the only existing case at the time of writing,
225 all other forms of 'adjustment' should be recorded as distinct credits
226 or debits and applied, via an offset, to the corresponding debit or credit.
228 =cut
230 sub adjust {
231 my ( $self, $params ) = @_;
233 my $amount = $params->{amount};
234 my $update_type = $params->{type};
236 unless ( exists($Koha::Account::Line::offset_type->{$update_type}) ) {
237 Koha::Exceptions::Account::UnrecognisedType->throw(
238 error => 'Update type not recognised'
242 my $account_type = $self->accounttype;
243 unless ( $Koha::Account::Line::allowed_update->{$update_type} eq $account_type ) {
244 Koha::Exceptions::Account::UnrecognisedType->throw(
245 error => 'Update type not allowed on this accounttype'
249 my $schema = Koha::Database->new->schema;
251 $schema->txn_do(
252 sub {
254 my $amount_before = $self->amount;
255 my $amount_outstanding_before = $self->amountoutstanding;
256 my $difference = $amount - $amount_before;
257 my $new_outstanding = $amount_outstanding_before + $difference;
259 # Catch cases that require patron refunds
260 if ( $new_outstanding < 0 ) {
261 my $account =
262 Koha::Patrons->find( $self->borrowernumber )->account;
263 my $credit = $account->add_credit(
265 amount => $new_outstanding * -1,
266 description => 'Overpayment refund',
267 type => 'credit',
268 ( $update_type eq 'fine_increment' ? ( item_id => $self->itemnumber ) : ()),
271 $new_outstanding = 0;
274 # Update the account line
275 $self->set(
277 date => \'NOW()',
278 amount => $amount,
279 amountoutstanding => $new_outstanding,
280 ( $update_type eq 'fine_increment' ? ( lastincrement => $difference ) : ()),
282 )->store();
284 # Record the account offset
285 my $account_offset = Koha::Account::Offset->new(
287 debit_id => $self->id,
288 type => $Koha::Account::Line::offset_type->{$update_type},
289 amount => $difference
291 )->store();
293 if ( C4::Context->preference("FinesLog") ) {
294 logaction(
295 "FINES", 'UPDATE', #undef becomes UPDATE in UpdateFine
296 $self->borrowernumber,
297 Dumper(
298 { action => $update_type,
299 borrowernumber => $self->borrowernumber,
300 accountno => $self->accountno,
301 amount => $amount,
302 description => undef,
303 amountoutstanding => $new_outstanding,
304 accounttype => $self->accounttype,
305 note => undef,
306 itemnumber => $self->itemnumber,
307 manager_id => undef,
310 ) if ( $update_type eq 'fine_increment' );
315 return $self;
318 =head3 is_credit
320 my $bool = $line->is_credit;
322 =cut
324 sub is_credit {
325 my ($self) = @_;
327 return ( $self->amount < 0 );
330 =head3 is_debit
332 my $bool = $line->is_debit;
334 =cut
336 sub is_debit {
337 my ($self) = @_;
339 return !$self->is_credit;
342 =head2 Internal methods
344 =cut
346 =head3 _type
348 =cut
350 sub _type {
351 return 'Accountline';
356 =head2 Name mappings
358 =head3 $offset_type
360 =cut
362 our $offset_type = { 'fine_increment' => 'Fine Update', };
364 =head3 $allowed_update
366 =cut
368 our $allowed_update = { 'fine_increment' => 'FU', };
370 =head1 AUTHORS
372 Kyle M Hall <kyle@bywatersolutions.com >
373 Tomás Cohen Arazi <tomascohen@theke.io>
374 Martin Renvoize <martin.renvoize@ptfs-europe.com>
376 =cut