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 89-184 sub recordpayment { Link Here
89
90
90
    #here we update the account lines
91
    #here we update the account lines
91
    my ( $borrowernumber, $data, $sip_paytype, $payment_note ) = @_;
92
    my ( $borrowernumber, $data, $sip_paytype, $payment_note ) = @_;
92
    my $dbh        = C4::Context->dbh;
93
    my $newamtos   = 0;
94
    my $accdata    = "";
95
    my $branch     = C4::Context->userenv->{'branch'};
96
    my $amountleft = $data;
97
    my $manager_id = 0;
98
    $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
99
100
    $payment_note //= "";
101
102
    # begin transaction
103
    my $nextaccntno = getnextacctno($borrowernumber);
104
105
    # get lines with outstanding amounts to offset
106
    my $sth = $dbh->prepare(
107
        "SELECT * FROM accountlines
108
  WHERE (borrowernumber = ?) AND (amountoutstanding<>0)
109
  ORDER BY date"
110
    );
111
    $sth->execute($borrowernumber);
112
113
    # offset transactions
114
    my @ids;
115
    while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) {
116
        if ( $accdata->{'amountoutstanding'} < $amountleft ) {
117
            $newamtos = 0;
118
            $amountleft -= $accdata->{'amountoutstanding'};
119
        }
120
        else {
121
            $newamtos   = $accdata->{'amountoutstanding'} - $amountleft;
122
            $amountleft = 0;
123
        }
124
        my $thisacct = $accdata->{accountlines_id};
125
        my $usth     = $dbh->prepare(
126
            "UPDATE accountlines SET amountoutstanding= ?
127
     WHERE (accountlines_id = ?)"
128
        );
129
        $usth->execute( $newamtos, $thisacct );
130
131
        if ( C4::Context->preference("FinesLog") ) {
132
            $accdata->{'amountoutstanding_new'} = $newamtos;
133
            logaction("FINES", 'MODIFY', $borrowernumber, Dumper({
134
                action                => 'fee_payment',
135
                borrowernumber        => $accdata->{'borrowernumber'},
136
                old_amountoutstanding => $accdata->{'amountoutstanding'},
137
                new_amountoutstanding => $newamtos,
138
                amount_paid           => $accdata->{'amountoutstanding'} - $newamtos,
139
                accountlines_id       => $accdata->{'accountlines_id'},
140
                accountno             => $accdata->{'accountno'},
141
                manager_id            => $manager_id,
142
                note                  => $payment_note,
143
            }));
144
            push( @ids, $accdata->{'accountlines_id'} );
145
        }
146
    }
147
148
    # create new line
149
    my $usth = $dbh->prepare(
150
        "INSERT INTO accountlines
151
  (borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id, note)
152
  VALUES (?,?,now(),?,'',?,?,?,?)"
153
    );
154
155
    my $paytype = "Pay";
156
    $paytype .= $sip_paytype if defined $sip_paytype;
157
    $usth->execute( $borrowernumber, $nextaccntno, 0 - $data, $paytype, 0 - $amountleft, $manager_id, $payment_note );
158
    $usth->finish;
159
160
    UpdateStats({
161
                branch => $branch,
162
                type =>'payment',
163
                amount => $data,
164
                borrowernumber => $borrowernumber,
165
                accountno => $nextaccntno }
166
    );
167
168
    if ( C4::Context->preference("FinesLog") ) {
169
        $accdata->{'amountoutstanding_new'} = $newamtos;
170
        logaction("FINES", 'CREATE',$borrowernumber,Dumper({
171
            action            => 'create_payment',
172
            borrowernumber    => $borrowernumber,
173
            accountno         => $nextaccntno,
174
            amount            => $data * -1,
175
            amountoutstanding => $amountleft * -1,
176
            accounttype       => 'Pay',
177
            accountlines_paid => \@ids,
178
            manager_id        => $manager_id,
179
        }));
180
    }
181
93
94
    return Koha::Account->new( { patron_id => $borrowernumber } )
95
      ->pay( { amount => $data, sip => $sip_paytype, note => $payment_note } );
182
}
96
}
183
97
184
=head2 makepayment
98
=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 152-170 subtest "recordpayment() tests" => sub { Link Here
152
    $borrower->branchcode( $branchcode );
155
    $borrower->branchcode( $branchcode );
153
    $borrower->store;
156
    $borrower->store;
154
157
155
    my $sth = $dbh->prepare(
158
    my $line1 = Koha::Account::Line->new({ borrowernumber => $borrower->borrowernumber, amountoutstanding => 100 })->store();
156
        "INSERT INTO accountlines (
159
    my $line2 = Koha::Account::Line->new({ borrowernumber => $borrower->borrowernumber, amountoutstanding => 200 })->store();
157
            borrowernumber,
160
    $line1->_result->discard_changes;
158
            amountoutstanding )
161
    $line2->_result->discard_changes;
159
        VALUES ( ?, ? )"
160
    );
161
    $sth->execute($borrower->borrowernumber, '100');
162
    $sth->execute($borrower->borrowernumber, '200');
163
162
164
    $sth = $dbh->prepare("SELECT count(*) FROM accountlines");
163
    $sth = $dbh->prepare("SELECT count(*) FROM accountlines");
165
    $sth->execute;
164
    $sth->execute;
166
    my $count = $sth->fetchrow_array;
165
    my $count = $sth->fetchrow_array;
167
    is ($count, 2, 'There is 2 lines as expected');
166
    is($count, 2, 'There is 2 lines as expected');
168
167
169
    # Testing recordpayment -------------------------
168
    # Testing recordpayment -------------------------
170
    # There is $100 in the account
169
    # There is $100 in the account
Lines 174-180 subtest "recordpayment() tests" => sub { Link Here
174
    for my $line ( @$amountoutstanding ) {
173
    for my $line ( @$amountoutstanding ) {
175
        $amountleft += $line;
174
        $amountleft += $line;
176
    }
175
    }
177
    ok($amountleft == 300, 'The account has 300$ as expected' );
176
    is($amountleft, 300, 'The account has 300$ as expected' );
178
177
179
    # We make a $20 payment
178
    # We make a $20 payment
180
    my $borrowernumber = $borrower->borrowernumber;
179
    my $borrowernumber = $borrower->borrowernumber;
Lines 189-195 subtest "recordpayment() tests" => sub { Link Here
189
    for my $line ( @$amountoutstanding ) {
188
    for my $line ( @$amountoutstanding ) {
190
        $amountleft += $line;
189
        $amountleft += $line;
191
    }
190
    }
192
    ok($amountleft == 280, 'The account has $280 as expected' );
191
    is($amountleft, 280, 'The account has $280 as expected' );
193
    # Is the payment note well registered
192
    # Is the payment note well registered
194
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
193
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
195
    $sth->execute($borrower->borrowernumber);
194
    $sth->execute($borrower->borrowernumber);
Lines 207-213 subtest "recordpayment() tests" => sub { Link Here
207
    for my $line ( @$amountoutstanding ) {
206
    for my $line ( @$amountoutstanding ) {
208
        $amountleft += $line;
207
        $amountleft += $line;
209
    }
208
    }
210
    ok($amountleft == 310, 'The account has $310 as expected' );
209
    is($amountleft, 310, 'The account has $310 as expected' );
211
    # Is the payment note well registered
210
    # Is the payment note well registered
212
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
211
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
213
    $sth->execute($borrower->borrowernumber);
212
    $sth->execute($borrower->borrowernumber);
Lines 225-231 subtest "recordpayment() tests" => sub { Link Here
225
    for my $line ( @$amountoutstanding ) {
224
    for my $line ( @$amountoutstanding ) {
226
        $amountleft += $line;
225
        $amountleft += $line;
227
    }
226
    }
228
    ok($amountleft == 160, 'The account has $160 as expected' );
227
    is($amountleft, 160, 'The account has $160 as expected' );
229
    # Is the payment note well registered
228
    # Is the payment note well registered
230
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
229
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
231
    $sth->execute($borrower->borrowernumber);
230
    $sth->execute($borrower->borrowernumber);
Lines 243-249 subtest "recordpayment() tests" => sub { Link Here
243
    for my $line ( @$amountoutstanding ) {
242
    for my $line ( @$amountoutstanding ) {
244
        $amountleft += $line;
243
        $amountleft += $line;
245
    }
244
    }
246
    ok($amountleft == -40, 'The account has -$40 as expected, (credit situation)' );
245
    is($amountleft, -40, 'The account has -$40 as expected, (credit situation)' );
247
    # Is the payment note well registered
246
    # Is the payment note well registered
248
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
247
    $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
249
    $sth->execute($borrower->borrowernumber);
248
    $sth->execute($borrower->borrowernumber);
250
- 

Return to bug 15895