View | Details | Raw Unified | Return to bug 15895
Collapse All | Expand All

(-)a/C4/Accounts.pm (-89 / +3 lines)
Lines 25-30 use C4::Stats; Link Here
25
use C4::Members;
25
use C4::Members;
26
use C4::Circulation qw(ReturnLostItem);
26
use C4::Circulation qw(ReturnLostItem);
27
use C4::Log qw(logaction);
27
use C4::Log qw(logaction);
28
use Koha::Account;
28
29
29
use Data::Dumper qw(Dumper);
30
use Data::Dumper qw(Dumper);
30
31
Lines 91-186 sub recordpayment { Link Here
91
92
92
    #here we update the account lines
93
    #here we update the account lines
93
    my ( $borrowernumber, $data, $sip_paytype, $payment_note ) = @_;
94
    my ( $borrowernumber, $data, $sip_paytype, $payment_note ) = @_;
94
    my $dbh        = C4::Context->dbh;
95
    my $newamtos   = 0;
96
    my $accdata    = "";
97
    my $branch     = C4::Context->userenv->{'branch'};
98
    my $amountleft = $data;
99
    my $manager_id = 0;
100
    $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
101
102
    $payment_note //= "";
103
104
    # begin transaction
105
    my $nextaccntno = getnextacctno($borrowernumber);
106
107
    # get lines with outstanding amounts to offset
108
    my $sth = $dbh->prepare(
109
        "SELECT * FROM accountlines
110
  WHERE (borrowernumber = ?) AND (amountoutstanding<>0)
111
  ORDER BY date"
112
    );
113
    $sth->execute($borrowernumber);
114
115
    # offset transactions
116
    my @ids;
117
    while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) {
118
        if ( $accdata->{'amountoutstanding'} < $amountleft ) {
119
            $newamtos = 0;
120
            $amountleft -= $accdata->{'amountoutstanding'};
121
        }
122
        else {
123
            $newamtos   = $accdata->{'amountoutstanding'} - $amountleft;
124
            $amountleft = 0;
125
        }
126
        my $thisacct = $accdata->{accountlines_id};
127
        my $usth     = $dbh->prepare(
128
            "UPDATE accountlines SET amountoutstanding= ?
129
     WHERE (accountlines_id = ?)"
130
        );
131
        $usth->execute( $newamtos, $thisacct );
132
133
        if ( C4::Context->preference("FinesLog") ) {
134
            $accdata->{'amountoutstanding_new'} = $newamtos;
135
            logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
136
                action                => 'fee_payment',
137
                borrowernumber        => $accdata->{'borrowernumber'},
138
                old_amountoutstanding => $accdata->{'amountoutstanding'},
139
                new_amountoutstanding => $newamtos,
140
                amount_paid           => $accdata->{'amountoutstanding'} - $newamtos,
141
                accountlines_id       => $accdata->{'accountlines_id'},
142
                accountno             => $accdata->{'accountno'},
143
                manager_id            => $manager_id,
144
                note                  => $payment_note,
145
            }));
146
            push( @ids, $accdata->{'accountlines_id'} );
147
        }
148
    }
149
150
    # create new line
151
    my $usth = $dbh->prepare(
152
        "INSERT INTO accountlines
153
  (borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id, note)
154
  VALUES (?,?,now(),?,'',?,?,?,?)"
155
    );
156
157
    my $paytype = "Pay";
158
    $paytype .= $sip_paytype if defined $sip_paytype;
159
    $usth->execute( $borrowernumber, $nextaccntno, 0 - $data, $paytype, 0 - $amountleft, $manager_id, $payment_note );
160
    $usth->finish;
161
162
    UpdateStats({
163
                branch => $branch,
164
                type =>'payment',
165
                amount => $data,
166
                borrowernumber => $borrowernumber,
167
                accountno => $nextaccntno }
168
    );
169
170
    if ( C4::Context->preference("FinesLog") ) {
171
        $accdata->{'amountoutstanding_new'} = $newamtos;
172
        logaction("FINES", 'CREATE',$borrowernumber,Dumper({
173
            action            => 'create_payment',
174
            borrowernumber    => $borrowernumber,
175
            accountno         => $nextaccntno,
176
            amount            => $data * -1,
177
            amountoutstanding => $amountleft * -1,
178
            accounttype       => 'Pay',
179
            accountlines_paid => \@ids,
180
            manager_id        => $manager_id,
181
        }));
182
    }
183
95
96
    return Koha::Account->new( { patron_id => $borrowernumber } )
97
      ->pay( { amount => $data, sip => $sip_paytype, note => $payment_note } );
184
}
98
}
185
99
186
=head2 makepayment
100
=head2 makepayment
(-)a/Koha/Account.pm (+171 lines)
Line 0 Link Here
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 feees
49
50
=cut
51
52
sub pay {
53
    my ( $self, $params ) = @_;
54
55
    my $amount = $params->{amount};
56
    my $sip    = $params->{sip};
57
    my $note   = $params->{note} || q{};
58
59
    my $userenv = C4::Context->userenv;
60
61
    # We should remove accountno, it is no longer needed
62
    my $last = Koha::Account::Lines->search(
63
        {
64
            borrowernumber => $self->{patron_id}
65
        },
66
        {
67
            order_by => 'accountno'
68
        }
69
    )->next();
70
    my $accountno = $last ? $last->accountno + 1 : 1;
71
72
    my $manager_id = $userenv ? $userenv->{number} : 0;
73
74
    my @outstanding_fines = Koha::Account::Lines->search(
75
        {
76
            borrowernumber    => $self->{patron_id},
77
            amountoutstanding => { '>' => 0 },
78
        }
79
    );
80
81
    my $balance_remaining = $amount;
82
    my @fines_paid;
83
    foreach my $fine (@outstanding_fines) {
84
        my $amount_to_pay =
85
            $fine->amountoutstanding > $balance_remaining
86
          ? $balance_remaining
87
          : $fine->amountoutstanding;
88
89
        my $old_amountoutstanding = $fine->amountoutstanding;
90
        $fine->amountoutstanding( $old_amountoutstanding - $amount_to_pay );
91
        $fine->store();
92
93
        if ( C4::Context->preference("FinesLog") ) {
94
            logaction(
95
                "FINES", 'MODIFY',
96
                $self->{patron_id},
97
                Dumper(
98
                    {
99
                        action                => 'fee_payment',
100
                        borrowernumber        => $fine->borrowernumber,
101
                        old_amountoutstanding => $old_amountoutstanding,
102
                        new_amountoutstanding => $fine->amountoutstanding,
103
                        amount_paid           => $amount_to_pay,
104
                        accountlines_id       => $fine->id,
105
                        accountno             => $fine->accountno,
106
                        manager_id            => $manager_id,
107
                        note                  => $note,
108
                    }
109
                )
110
            );
111
            push( @fines_paid, $fine->id );
112
        }
113
114
        $balance_remaining = $balance_remaining - $amount_to_pay;
115
        last unless $balance_remaining > 0;
116
    }
117
118
    my $account_type = defined($sip) ? "Pay$sip" : 'Pay';
119
120
    my $payment = Koha::Account::Line->new(
121
        {
122
            borrowernumber    => $self->{patron_id},
123
            accountno         => $accountno,
124
            date              => dt_from_string(),
125
            amount            => 0 - $amount,
126
            description       => q{},
127
            accounttype       => $account_type,
128
            amountoutstanding => 0 - $balance_remaining,
129
            manager_id        => $manager_id,
130
            note              => $note,
131
        }
132
    )->store();
133
134
    my $branch = $userenv ? $userenv->{'branch'} : undef;
135
    UpdateStats(
136
        {
137
            branch         => $branch,
138
            type           => 'payment',
139
            amount         => $amount,
140
            borrowernumber => $self->{patron_id},
141
            accountno      => $accountno,
142
        }
143
    );
144
145
    if ( C4::Context->preference("FinesLog") ) {
146
        logaction(
147
            "FINES", 'CREATE',
148
            $self->{patron_id},
149
            Dumper(
150
                {
151
                    action            => 'create_payment',
152
                    borrowernumber    => $self->{patron_id},
153
                    accountno         => $accountno,
154
                    amount            => 0 - $amount,
155
                    amountoutstanding => 0 - $balance_remaining,
156
                    accounttype       => 'Pay',
157
                    accountlines_paid => \@fines_paid,
158
                    manager_id        => $manager_id,
159
                }
160
            )
161
        );
162
    }
163
}
164
165
1;
166
167
=head1 AUTHOR
168
169
Kyle M Hall <kyle.m.hall@gmail.com>
170
171
=cut
(-)a/t/db_dependent/Accounts.t (-15 / +13 lines)
Lines 24-29 use Test::Warn; Link Here
24
24
25
use t::lib::TestBuilder;
25
use t::lib::TestBuilder;
26
26
27
use Koha::Account::Lines;
28
use Koha::Account::Line;
29
27
BEGIN {
30
BEGIN {
28
    use_ok('C4::Accounts');
31
    use_ok('C4::Accounts');
29
    use_ok('Koha::Object');
32
    use_ok('Koha::Object');
Lines 153-171 subtest "recordpayment() tests" => sub { Link Here
153
    $borrower->branchcode( $branchcode );
156
    $borrower->branchcode( $branchcode );
154
    $borrower->store;
157
    $borrower->store;
155
158
156
    my $sth = $dbh->prepare(
159
    my $line1 = Koha::Account::Line->new({ borrowernumber => $borrower->borrowernumber, amountoutstanding => 100 })->store();
157
        "INSERT INTO accountlines (
160
    my $line2 = Koha::Account::Line->new({ borrowernumber => $borrower->borrowernumber, amountoutstanding => 200 })->store();
158
            borrowernumber,
161
    $line1->_result->discard_changes;
159
            amountoutstanding )
162
    $line2->_result->discard_changes;
160
        VALUES ( ?, ? )"
161
    );
162
    $sth->execute($borrower->borrowernumber, '100');
163
    $sth->execute($borrower->borrowernumber, '200');
164
163
165
    $sth = $dbh->prepare("SELECT count(*) FROM accountlines");
164
    $sth = $dbh->prepare("SELECT count(*) FROM accountlines");
166
    $sth->execute;
165
    $sth->execute;
167
    my $count = $sth->fetchrow_array;
166
    my $count = $sth->fetchrow_array;
168
    is ($count, 2, 'There is 2 lines as expected');
167
    is($count, 2, 'There is 2 lines as expected');
169
168
170
    # Testing recordpayment -------------------------
169
    # Testing recordpayment -------------------------
171
    # There is $100 in the account
170
    # There is $100 in the account
Lines 175-181 subtest "recordpayment() tests" => sub { Link Here
175
    for my $line ( @$amountoutstanding ) {
174
    for my $line ( @$amountoutstanding ) {
176
        $amountleft += $line;
175
        $amountleft += $line;
177
    }
176
    }
178
    ok($amountleft == 300, 'The account has 300$ as expected' );
177
    is($amountleft, 300, 'The account has 300$ as expected' );
179
178
180
    # We make a $20 payment
179
    # We make a $20 payment
181
    my $borrowernumber = $borrower->borrowernumber;
180
    my $borrowernumber = $borrower->borrowernumber;
Lines 190-196 subtest "recordpayment() tests" => sub { Link Here
190
    for my $line ( @$amountoutstanding ) {
189
    for my $line ( @$amountoutstanding ) {
191
        $amountleft += $line;
190
        $amountleft += $line;
192
    }
191
    }
193
    ok($amountleft == 280, 'The account has $280 as expected' );
192
    is($amountleft, 280, 'The account has $280 as expected' );
194
    # Is the payment note well registered
193
    # Is the payment note well registered
195
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
194
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
196
    $sth->execute($borrower->borrowernumber);
195
    $sth->execute($borrower->borrowernumber);
Lines 208-214 subtest "recordpayment() tests" => sub { Link Here
208
    for my $line ( @$amountoutstanding ) {
207
    for my $line ( @$amountoutstanding ) {
209
        $amountleft += $line;
208
        $amountleft += $line;
210
    }
209
    }
211
    ok($amountleft == 310, 'The account has $310 as expected' );
210
    is($amountleft, 310, 'The account has $310 as expected' );
212
    # Is the payment note well registered
211
    # Is the payment note well registered
213
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
212
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
214
    $sth->execute($borrower->borrowernumber);
213
    $sth->execute($borrower->borrowernumber);
Lines 226-232 subtest "recordpayment() tests" => sub { Link Here
226
    for my $line ( @$amountoutstanding ) {
225
    for my $line ( @$amountoutstanding ) {
227
        $amountleft += $line;
226
        $amountleft += $line;
228
    }
227
    }
229
    ok($amountleft == 160, 'The account has $160 as expected' );
228
    is($amountleft, 160, 'The account has $160 as expected' );
230
    # Is the payment note well registered
229
    # Is the payment note well registered
231
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
230
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
232
    $sth->execute($borrower->borrowernumber);
231
    $sth->execute($borrower->borrowernumber);
Lines 244-250 subtest "recordpayment() tests" => sub { Link Here
244
    for my $line ( @$amountoutstanding ) {
243
    for my $line ( @$amountoutstanding ) {
245
        $amountleft += $line;
244
        $amountleft += $line;
246
    }
245
    }
247
    ok($amountleft == -40, 'The account has -$40 as expected, (credit situation)' );
246
    is($amountleft, -40, 'The account has -$40 as expected, (credit situation)' );
248
    # Is the payment note well registered
247
    # Is the payment note well registered
249
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
248
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
250
    $sth->execute($borrower->borrowernumber);
249
    $sth->execute($borrower->borrowernumber);
251
- 

Return to bug 15895