Bug 15897 - Use Koha::Account::pay internally for recordpayment_selectaccts
[koha-equinox.git] / Koha / Account.pm
1 package Koha::Account;
2
3 # Copyright 2016 ByWater Solutions
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20 use Modern::Perl;
21
22 use Carp;
23 use Data::Dumper;
24
25 use C4::Log qw( logaction );
26 use C4::Stats qw( UpdateStats );
27
28 use Koha::Account::Line;
29 use Koha::Account::Lines;
30 use Koha::DateUtils qw( dt_from_string );
31
32 =head1 NAME
33
34 Koha::Accounts - Module for managing payments and fees for patrons
35
36 =cut
37
38 sub new {
39     my ( $class, $params ) = @_;
40
41     Carp::croak("No patron id passed in!") unless $params->{patron_id};
42
43     return bless( $params, $class );
44 }
45
46 =head2 pay
47
48 This method allows payments to be made against fees/fines
49
50 Koha::Account->new( { patron_id => $borrowernumber } )->pay(
51     {
52         amount     => $amount,
53         sip        => $sipmode,
54         note       => $note,
55         accountlines_id => $accountlines_id,
56         library_id => $branchcode,
57         lines      => $lines, # Arrayref of Koha::Account::Line objects to pay
58     }
59 );
60
61 =cut
62
63 sub pay {
64     my ( $self, $params ) = @_;
65
66     my $amount          = $params->{amount};
67     my $sip             = $params->{sip};
68     my $note            = $params->{note} || q{};
69     my $library_id      = $params->{library_id};
70     my $lines           = $params->{lines},
71
72     my $userenv = C4::Context->userenv;
73
74     # We should remove accountno, it is no longer needed
75     my $last = Koha::Account::Lines->search(
76         {
77             borrowernumber => $self->{patron_id}
78         },
79         {
80             order_by => 'accountno'
81         }
82     )->next();
83     my $accountno = $last ? $last->accountno + 1 : 1;
84
85     my $manager_id = $userenv ? $userenv->{number} : 0;
86
87     my @fines_paid; # List of account lines paid on with this payment
88
89     my $balance_remaining = $amount; # Set it now so we can adjust the amount if necessary
90     $balance_remaining ||= 0;
91
92     # We were passed a specific line to pay
93     foreach my $fine ( @$lines ) {
94         my $amount_to_pay =
95             $fine->amountoutstanding > $balance_remaining
96           ? $balance_remaining
97           : $fine->amountoutstanding;
98
99         my $old_amountoutstanding = $fine->amountoutstanding;
100         my $new_amountoutstanding = $old_amountoutstanding - $amount_to_pay;
101         $fine->amountoutstanding($new_amountoutstanding)->store();
102         $balance_remaining = $balance_remaining - $amount_to_pay;
103
104         if ( $fine->accounttype && ( $fine->accounttype eq 'Rep' || $fine->accounttype eq 'L' ) )
105         {
106             C4::Circulation::ReturnLostItem( $self->{patron_id}, $fine->itemnumber );
107         }
108
109         if ( C4::Context->preference("FinesLog") ) {
110             logaction(
111                 "FINES", 'MODIFY',
112                 $self->{patron_id},
113                 Dumper(
114                     {
115                         action                => 'fee_payment',
116                         borrowernumber        => $fine->borrowernumber,
117                         old_amountoutstanding => $old_amountoutstanding,
118                         new_amountoutstanding => 0,
119                         amount_paid           => $old_amountoutstanding,
120                         accountlines_id       => $fine->id,
121                         accountno             => $fine->accountno,
122                         manager_id            => $manager_id,
123                         note                  => $note,
124                     }
125                 )
126             );
127             push( @fines_paid, $fine->id );
128         }
129     }
130
131     # Were not passed a specific line to pay, or the payment was for more
132     # than the what was owed on the given line. In that case pay down other
133     # lines with remaining balance.
134     my @outstanding_fines;
135     @outstanding_fines = Koha::Account::Lines->search(
136         {
137             borrowernumber    => $self->{patron_id},
138             amountoutstanding => { '>' => 0 },
139         }
140     ) if $balance_remaining > 0;
141
142     foreach my $fine (@outstanding_fines) {
143         my $amount_to_pay =
144             $fine->amountoutstanding > $balance_remaining
145           ? $balance_remaining
146           : $fine->amountoutstanding;
147
148         my $old_amountoutstanding = $fine->amountoutstanding;
149         $fine->amountoutstanding( $old_amountoutstanding - $amount_to_pay );
150         $fine->store();
151
152         if ( C4::Context->preference("FinesLog") ) {
153             logaction(
154                 "FINES", 'MODIFY',
155                 $self->{patron_id},
156                 Dumper(
157                     {
158                         action                => 'fee_payment',
159                         borrowernumber        => $fine->borrowernumber,
160                         old_amountoutstanding => $old_amountoutstanding,
161                         new_amountoutstanding => $fine->amountoutstanding,
162                         amount_paid           => $amount_to_pay,
163                         accountlines_id       => $fine->id,
164                         accountno             => $fine->accountno,
165                         manager_id            => $manager_id,
166                         note                  => $note,
167                     }
168                 )
169             );
170             push( @fines_paid, $fine->id );
171         }
172
173         $balance_remaining = $balance_remaining - $amount_to_pay;
174         last unless $balance_remaining > 0;
175     }
176
177     my $account_type = defined($sip) ? "Pay$sip" : 'Pay';
178
179     my $payment = Koha::Account::Line->new(
180         {
181             borrowernumber    => $self->{patron_id},
182             accountno         => $accountno,
183             date              => dt_from_string(),
184             amount            => 0 - $amount,
185             description       => q{},
186             accounttype       => $account_type,
187             amountoutstanding => 0 - $balance_remaining,
188             manager_id        => $manager_id,
189             note              => $note,
190         }
191     )->store();
192
193     $library_id ||= $userenv ? $userenv->{'branch'} : undef;
194
195     UpdateStats(
196         {
197             branch         => $library_id,
198             type           => 'payment',
199             amount         => $amount,
200             borrowernumber => $self->{patron_id},
201             accountno      => $accountno,
202         }
203     );
204
205     if ( C4::Context->preference("FinesLog") ) {
206         logaction(
207             "FINES", 'CREATE',
208             $self->{patron_id},
209             Dumper(
210                 {
211                     action            => 'create_payment',
212                     borrowernumber    => $self->{patron_id},
213                     accountno         => $accountno,
214                     amount            => 0 - $amount,
215                     amountoutstanding => 0 - $balance_remaining,
216                     accounttype       => 'Pay',
217                     accountlines_paid => \@fines_paid,
218                     manager_id        => $manager_id,
219                 }
220             )
221         );
222     }
223
224     return $payment->id;
225 }
226
227 =head3 balance
228
229 my $balance = $self->balance
230
231 Return the balance (sum of amountoutstanding columns)
232
233 =cut
234
235 sub balance {
236     my ($self) = @_;
237     my $fines = Koha::Account::Lines->search(
238         {
239             borrowernumber => $self->{patron_id},
240         },
241         {
242             select => [ { sum => 'amountoutstanding' } ],
243             as => ['total_amountoutstanding'],
244         }
245     );
246     return $fines->count
247       ? $fines->next->get_column('total_amountoutstanding')
248       : 0;
249 }
250
251 1;
252
253 =head1 AUTHOR
254
255 Kyle M Hall <kyle.m.hall@gmail.com>
256
257 =cut