Bug 15905 [QA Followup] - Fix bad syntax in pay()
[koha.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         library_id => $branchcode,
56         lines      => $lines, # Arrayref of Koha::Account::Line objects to pay
57     }
58 );
59
60 =cut
61
62 sub pay {
63     my ( $self, $params ) = @_;
64
65     my $amount          = $params->{amount};
66     my $sip             = $params->{sip};
67     my $note            = $params->{note} || q{};
68     my $library_id      = $params->{library_id};
69     my $lines           = $params->{lines};
70
71     my $userenv = C4::Context->userenv;
72
73     # We should remove accountno, it is no longer needed
74     my $last = Koha::Account::Lines->search(
75         {
76             borrowernumber => $self->{patron_id}
77         },
78         {
79             order_by => 'accountno'
80         }
81     )->next();
82     my $accountno = $last ? $last->accountno + 1 : 1;
83
84     my $manager_id = $userenv ? $userenv->{number} : 0;
85
86     my @fines_paid; # List of account lines paid on with this payment
87
88     my $balance_remaining = $amount; # Set it now so we can adjust the amount if necessary
89     $balance_remaining ||= 0;
90
91     # We were passed a specific line to pay
92     foreach my $fine ( @$lines ) {
93         my $amount_to_pay =
94             $fine->amountoutstanding > $balance_remaining
95           ? $balance_remaining
96           : $fine->amountoutstanding;
97
98         my $old_amountoutstanding = $fine->amountoutstanding;
99         my $new_amountoutstanding = $old_amountoutstanding - $amount_to_pay;
100         $fine->amountoutstanding($new_amountoutstanding)->store();
101         $balance_remaining = $balance_remaining - $amount_to_pay;
102
103         if ( $fine->accounttype && ( $fine->accounttype eq 'Rep' || $fine->accounttype eq 'L' ) )
104         {
105             C4::Circulation::ReturnLostItem( $self->{patron_id}, $fine->itemnumber );
106         }
107
108         if ( C4::Context->preference("FinesLog") ) {
109             logaction(
110                 "FINES", 'MODIFY',
111                 $self->{patron_id},
112                 Dumper(
113                     {
114                         action                => 'fee_payment',
115                         borrowernumber        => $fine->borrowernumber,
116                         old_amountoutstanding => $old_amountoutstanding,
117                         new_amountoutstanding => 0,
118                         amount_paid           => $old_amountoutstanding,
119                         accountlines_id       => $fine->id,
120                         accountno             => $fine->accountno,
121                         manager_id            => $manager_id,
122                         note                  => $note,
123                     }
124                 )
125             );
126             push( @fines_paid, $fine->id );
127         }
128     }
129
130     # Were not passed a specific line to pay, or the payment was for more
131     # than the what was owed on the given line. In that case pay down other
132     # lines with remaining balance.
133     my @outstanding_fines;
134     @outstanding_fines = Koha::Account::Lines->search(
135         {
136             borrowernumber    => $self->{patron_id},
137             amountoutstanding => { '>' => 0 },
138         }
139     ) if $balance_remaining > 0;
140
141     foreach my $fine (@outstanding_fines) {
142         my $amount_to_pay =
143             $fine->amountoutstanding > $balance_remaining
144           ? $balance_remaining
145           : $fine->amountoutstanding;
146
147         my $old_amountoutstanding = $fine->amountoutstanding;
148         $fine->amountoutstanding( $old_amountoutstanding - $amount_to_pay );
149         $fine->store();
150
151         if ( C4::Context->preference("FinesLog") ) {
152             logaction(
153                 "FINES", 'MODIFY',
154                 $self->{patron_id},
155                 Dumper(
156                     {
157                         action                => 'fee_payment',
158                         borrowernumber        => $fine->borrowernumber,
159                         old_amountoutstanding => $old_amountoutstanding,
160                         new_amountoutstanding => $fine->amountoutstanding,
161                         amount_paid           => $amount_to_pay,
162                         accountlines_id       => $fine->id,
163                         accountno             => $fine->accountno,
164                         manager_id            => $manager_id,
165                         note                  => $note,
166                     }
167                 )
168             );
169             push( @fines_paid, $fine->id );
170         }
171
172         $balance_remaining = $balance_remaining - $amount_to_pay;
173         last unless $balance_remaining > 0;
174     }
175
176     my $account_type = defined($sip) ? "Pay$sip" : 'Pay';
177
178     my $payment = Koha::Account::Line->new(
179         {
180             borrowernumber    => $self->{patron_id},
181             accountno         => $accountno,
182             date              => dt_from_string(),
183             amount            => 0 - $amount,
184             description       => q{},
185             accounttype       => $account_type,
186             amountoutstanding => 0 - $balance_remaining,
187             manager_id        => $manager_id,
188             note              => $note,
189         }
190     )->store();
191
192     $library_id ||= $userenv ? $userenv->{'branch'} : undef;
193
194     UpdateStats(
195         {
196             branch         => $library_id,
197             type           => 'payment',
198             amount         => $amount,
199             borrowernumber => $self->{patron_id},
200             accountno      => $accountno,
201         }
202     );
203
204     if ( C4::Context->preference("FinesLog") ) {
205         logaction(
206             "FINES", 'CREATE',
207             $self->{patron_id},
208             Dumper(
209                 {
210                     action            => 'create_payment',
211                     borrowernumber    => $self->{patron_id},
212                     accountno         => $accountno,
213                     amount            => 0 - $amount,
214                     amountoutstanding => 0 - $balance_remaining,
215                     accounttype       => 'Pay',
216                     accountlines_paid => \@fines_paid,
217                     manager_id        => $manager_id,
218                 }
219             )
220         );
221     }
222
223     return $payment->id;
224 }
225
226 =head3 balance
227
228 my $balance = $self->balance
229
230 Return the balance (sum of amountoutstanding columns)
231
232 =cut
233
234 sub balance {
235     my ($self) = @_;
236     my $fines = Koha::Account::Lines->search(
237         {
238             borrowernumber => $self->{patron_id},
239         },
240         {
241             select => [ { sum => 'amountoutstanding' } ],
242             as => ['total_amountoutstanding'],
243         }
244     );
245     return $fines->count
246       ? $fines->next->get_column('total_amountoutstanding')
247       : 0;
248 }
249
250 1;
251
252 =head1 AUTHOR
253
254 Kyle M Hall <kyle.m.hall@gmail.com>
255
256 =cut