Bug 15896 [QA Followup] - Supress warn when running unit tests
[koha.git] / t / db_dependent / Accounts.t
1 #!/usr/bin/perl
2 use Carp::Always;
3
4 # Copyright 2015 BibLibre
5 #
6 # This file is part of Koha.
7 #
8 # Koha is free software; you can redistribute it and/or modify it under the
9 # terms of the GNU General Public License as published by the Free Software
10 # Foundation; either version 3 of the License, or (at your option) any later
11 # version.
12 #
13 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
14 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License along
18 # with Koha; if not, see <http://www.gnu.org/licenses>.
19
20 use Modern::Perl;
21
22 use Test::More tests => 19;
23 use Test::MockModule;
24 use Test::Warn;
25
26 use t::lib::TestBuilder;
27
28 use Koha::Account::Lines;
29 use Koha::Account::Line;
30
31 BEGIN {
32     use_ok('C4::Accounts');
33     use_ok('Koha::Object');
34     use_ok('Koha::Patron');
35     use_ok('Data::Dumper');
36 }
37
38 can_ok( 'C4::Accounts',
39     qw(
40         makepayment
41         getnextacctno
42         chargelostitem
43         manualinvoice
44         getcharges
45         ModNote
46         getcredits
47         getrefunds
48         ReversePayment
49         recordpayment_selectaccts
50         makepartialpayment
51         WriteOffFee
52         purge_zero_balance_fees )
53 );
54
55 my $schema  = Koha::Database->new->schema;
56 $schema->storage->txn_begin;
57 my $dbh = C4::Context->dbh;
58
59 my $builder = t::lib::TestBuilder->new;
60 my $library = $builder->build( { source => 'Branch' } );
61
62 $dbh->do(q|DELETE FROM accountlines|);
63 $dbh->do(q|DELETE FROM issues|);
64 $dbh->do(q|DELETE FROM borrowers|);
65
66 my $branchcode = $library->{branchcode};
67 my $borrower_number;
68
69 my $context = new Test::MockModule('C4::Context');
70 $context->mock( 'userenv', sub {
71     return {
72         flags  => 1,
73         id     => 'my_userid',
74         branch => $branchcode,
75     };
76 });
77
78 # Testing purge_zero_balance_fees
79
80 # The 3rd value in the insert is 'days ago' --
81 # 0 => today
82 # 1 => yesterday
83 # etc.
84
85 my $sth = $dbh->prepare(
86     "INSERT INTO accountlines (
87          borrowernumber,
88          amountoutstanding,
89          date,
90          description
91      )
92      VALUES ( ?, ?, (select date_sub(CURRENT_DATE, INTERVAL ? DAY) ), ? )"
93 );
94
95 my $days = 5;
96
97 my @test_data = (
98     { amount => 0     , days_ago => 0         , description =>'purge_zero_balance_fees should not delete 0 balance fees with date today'                     , delete => 0 } ,
99     { amount => 0     , days_ago => $days - 1 , description =>'purge_zero_balance_fees should not delete 0 balance fees with date before threshold day'      , delete => 0 } ,
100     { amount => 0     , days_ago => $days     , description =>'purge_zero_balance_fees should not delete 0 balance fees with date on threshold day'          , delete => 0 } ,
101     { amount => 0     , days_ago => $days + 1 , description =>'purge_zero_balance_fees should delete 0 balance fees with date after threshold day'           , delete => 1 } ,
102     { amount => undef , days_ago => $days + 1 , description =>'purge_zero_balance_fees should delete NULL balance fees with date after threshold day'        , delete => 1 } ,
103     { amount => 5     , days_ago => $days - 1 , description =>'purge_zero_balance_fees should not delete fees with positive amout owed before threshold day'  , delete => 0 } ,
104     { amount => 5     , days_ago => $days     , description =>'purge_zero_balance_fees should not delete fees with positive amout owed on threshold day'      , delete => 0 } ,
105     { amount => 5     , days_ago => $days + 1 , description =>'purge_zero_balance_fees should not delete fees with positive amout owed after threshold day'   , delete => 0 } ,
106     { amount => -5    , days_ago => $days - 1 , description =>'purge_zero_balance_fees should not delete fees with negative amout owed before threshold day' , delete => 0 } ,
107     { amount => -5    , days_ago => $days     , description =>'purge_zero_balance_fees should not delete fees with negative amout owed on threshold day'     , delete => 0 } ,
108     { amount => -5    , days_ago => $days + 1 , description =>'purge_zero_balance_fees should not delete fees with negative amout owed after threshold day'  , delete => 0 }
109 );
110
111 my $borrower = Koha::Patron->new( { firstname => 'Test', surname => 'Patron', categorycode => 'PT', branchcode => $branchcode } )->store();
112
113 for my $data ( @test_data ) {
114     $sth->execute($borrower->borrowernumber, $data->{amount}, $data->{days_ago}, $data->{description});
115 }
116
117 purge_zero_balance_fees( $days );
118
119 $sth = $dbh->prepare(
120             "select count(*) = 0 as deleted
121              from accountlines
122              where description = ?"
123        );
124
125 #
126 sub is_delete_correct {
127     my $should_delete = shift;
128     my $description = shift;
129     $sth->execute( $description );
130     my $test = $sth->fetchrow_hashref();
131     is( $test->{deleted}, $should_delete, $description )
132 }
133
134 for my $data  (@test_data) {
135     is_delete_correct( $data->{delete}, $data->{description});
136 }
137
138 $dbh->do(q|DELETE FROM accountlines|);
139
140 subtest "Koha::Account::pay tests" => sub {
141
142     plan tests => 12;
143
144     # Create a borrower
145     my $categorycode = $builder->build({ source => 'Category' })->{ categorycode };
146     my $branchcode   = $builder->build({ source => 'Branch' })->{ branchcode };
147
148     my $borrower = Koha::Patron->new( {
149         cardnumber => '1234567890',
150         surname => 'McFly',
151         firstname => 'Marty',
152     } );
153     $borrower->categorycode( $categorycode );
154     $borrower->branchcode( $branchcode );
155     $borrower->store;
156
157     my $account = Koha::Account->new({ patron_id => $borrower->id });
158
159     my $line1 = Koha::Account::Line->new({ borrowernumber => $borrower->borrowernumber, amountoutstanding => 100 })->store();
160     my $line2 = Koha::Account::Line->new({ borrowernumber => $borrower->borrowernumber, amountoutstanding => 200 })->store();
161
162     $sth = $dbh->prepare("SELECT count(*) FROM accountlines");
163     $sth->execute;
164     my $count = $sth->fetchrow_array;
165     is($count, 2, 'There is 2 lines as expected');
166
167     # There is $100 in the account
168     $sth = $dbh->prepare("SELECT amountoutstanding FROM accountlines WHERE borrowernumber=?");
169     my $amountoutstanding = $dbh->selectcol_arrayref($sth, {}, $borrower->borrowernumber);
170     my $amountleft = 0;
171     for my $line ( @$amountoutstanding ) {
172         $amountleft += $line;
173     }
174     is($amountleft, 300, 'The account has 300$ as expected' );
175
176     # We make a $20 payment
177     my $borrowernumber = $borrower->borrowernumber;
178     my $data = '20.00';
179     my $payment_note = '$20.00 payment note';
180     $account->pay( { amount => $data, note => $payment_note } );
181
182     # There is now $280 in the account
183     $sth = $dbh->prepare("SELECT amountoutstanding FROM accountlines WHERE borrowernumber=?");
184     $amountoutstanding = $dbh->selectcol_arrayref($sth, {}, $borrower->borrowernumber);
185     $amountleft = 0;
186     for my $line ( @$amountoutstanding ) {
187         $amountleft += $line;
188     }
189     is($amountleft, 280, 'The account has $280 as expected' );
190
191     # Is the payment note well registered
192     $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
193     $sth->execute($borrower->borrowernumber);
194     my $note = $sth->fetchrow_array;
195     is($note,'$20.00 payment note', '$20.00 payment note is registered');
196
197     # We make a -$30 payment (a NEGATIVE payment)
198     $data = '-30.00';
199     $payment_note = '-$30.00 payment note';
200     $account->pay( { amount => $data, note => $payment_note } );
201
202     # There is now $310 in the account
203     $sth = $dbh->prepare("SELECT amountoutstanding FROM accountlines WHERE borrowernumber=?");
204     $amountoutstanding = $dbh->selectcol_arrayref($sth, {}, $borrower->borrowernumber);
205     $amountleft = 0;
206     for my $line ( @$amountoutstanding ) {
207         $amountleft += $line;
208     }
209     is($amountleft, 310, 'The account has $310 as expected' );
210     # Is the payment note well registered
211     $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
212     $sth->execute($borrower->borrowernumber);
213     $note = $sth->fetchrow_array;
214     is($note,'-$30.00 payment note', '-$30.00 payment note is registered');
215
216     #We make a $150 payment ( > 1stLine )
217     $data = '150.00';
218     $payment_note = '$150.00 payment note';
219     $account->pay( { amount => $data, note => $payment_note } );
220
221     # There is now $160 in the account
222     $sth = $dbh->prepare("SELECT amountoutstanding FROM accountlines WHERE borrowernumber=?");
223     $amountoutstanding = $dbh->selectcol_arrayref($sth, {}, $borrower->borrowernumber);
224     $amountleft = 0;
225     for my $line ( @$amountoutstanding ) {
226         $amountleft += $line;
227     }
228     is($amountleft, 160, 'The account has $160 as expected' );
229
230     # Is the payment note well registered
231     $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
232     $sth->execute($borrower->borrowernumber);
233     $note = $sth->fetchrow_array;
234     is($note,'$150.00 payment note', '$150.00 payment note is registered');
235
236     #We make a $200 payment ( > amountleft )
237     $data = '200.00';
238     $payment_note = '$200.00 payment note';
239     $account->pay( { amount => $data, note => $payment_note } );
240
241     # There is now -$40 in the account
242     $sth = $dbh->prepare("SELECT amountoutstanding FROM accountlines WHERE borrowernumber=?");
243     $amountoutstanding = $dbh->selectcol_arrayref($sth, {}, $borrower->borrowernumber);
244     $amountleft = 0;
245     for my $line ( @$amountoutstanding ) {
246         $amountleft += $line;
247     }
248     is($amountleft, -40, 'The account has -$40 as expected, (credit situation)' );
249
250     # Is the payment note well registered
251     $sth = $dbh->prepare("SELECT note FROM accountlines WHERE borrowernumber=? ORDER BY accountlines_id DESC LIMIT 1");
252     $sth->execute($borrower->borrowernumber);
253     $note = $sth->fetchrow_array;
254     is($note,'$200.00 payment note', '$200.00 payment note is registered');
255
256     my $line3 = Koha::Account::Line->new({ borrowernumber => $borrower->borrowernumber, amountoutstanding => 42, accounttype => 'TEST' })->store();
257     my $payment_id = $account->pay( { accountlines_id => $line3->id, amount => 42 } );
258     my $payment = Koha::Account::Lines->find( $payment_id );
259     is( $payment->amount(), '-42.000000', "Payment paid the specified fine" );
260     $line3 = Koha::Account::Lines->find( $line3->id );
261     is( $line3->amountoutstanding, '0.000000', "Specified fine is paid" );
262 };
263
264 subtest "makepayment() tests" => sub {
265
266     plan tests => 6;
267
268     # Create a borrower
269     my $category   = $builder->build({ source => 'Category' })->{ categorycode };
270     my $branch     = $builder->build({ source => 'Branch' })->{ branchcode };
271     $branchcode = $branch;
272     my $borrowernumber = $builder->build({
273         source => 'Borrower',
274         value  => { categorycode => $category,
275                     branchcode   => $branch }
276     })->{ borrowernumber };
277
278     my $amount = 100;
279     my $accountline = $builder->build({ source => 'Accountline',
280         value  => { borrowernumber => $borrowernumber,
281                     amount => $amount,
282                     amountoutstanding => $amount }
283     });
284
285     my $rs = $schema->resultset('Accountline')->search({
286         borrowernumber => $borrowernumber
287     });
288
289     is( $rs->count(), 1, 'Accountline created' );
290
291     # make the full payment
292     makepayment(
293         $accountline->{ accountlines_id }, $borrowernumber,
294         $accountline->{ accountno },       $amount,
295         $borrowernumber, $branch, 'A payment note' );
296
297     # TODO: someone should write actual tests for makepayment()
298
299     my $stat = $schema->resultset('Statistic')->search({
300         branch  => $branch,
301         type    => 'payment'
302     }, { order_by => { -desc => 'datetime' } })->next();
303
304     ok( defined $stat, "There's a payment log that matches the branch" );
305
306     SKIP: {
307         skip "No statistic logged", 4 unless defined $stat;
308
309         is( $stat->type, 'payment', "Correct statistic type" );
310         is( $stat->branch, $branch, "Correct branch logged to statistics" );
311         is( $stat->borrowernumber, $borrowernumber, "Correct borrowernumber logged to statistics" );
312         is( $stat->value, "$amount" . "\.0000", "Correct amount logged to statistics" );
313     }
314 };
315
316 subtest "makepartialpayment() tests" => sub {
317
318     plan tests => 6;
319
320     # Create a borrower
321     my $category   = $builder->build({ source => 'Category' })->{ categorycode };
322     my $branch     = $builder->build({ source => 'Branch' })->{ branchcode };
323     $branchcode = $branch;
324     my $borrowernumber = $builder->build({
325         source => 'Borrower',
326         value  => { categorycode => $category,
327                     branchcode   => $branch }
328     })->{ borrowernumber };
329
330     my $amount = 100;
331     my $partialamount = 60;
332     my $accountline = $builder->build({ source => 'Accountline',
333         value  => { borrowernumber => $borrowernumber,
334                     amount => $amount,
335                     amountoutstanding => $amount }
336     });
337
338     my $rs = $schema->resultset('Accountline')->search({
339         borrowernumber => $borrowernumber
340     });
341
342     is( $rs->count(), 1, 'Accountline created' );
343
344     # make the full payment
345     makepartialpayment(
346         $accountline->{ accountlines_id }, $borrowernumber,
347         $accountline->{ accountno },       $partialamount,
348         $borrowernumber, $branch, 'A payment note' );
349
350     # TODO: someone should write actual tests for makepartialpayment()
351
352     my $stat = $schema->resultset('Statistic')->search({
353         branch  => $branch,
354         type    => 'payment'
355     }, { order_by => { -desc => 'datetime' } })->next();
356
357     ok( defined $stat, "There's a payment log that matches the branch" );
358
359     SKIP: {
360         skip "No statistic logged", 4 unless defined $stat;
361
362         is( $stat->type, 'payment', "Correct statistic type" );
363         is( $stat->branch, $branch, "Correct branch logged to statistics" );
364         is( $stat->borrowernumber, $borrowernumber, "Correct borrowernumber logged to statistics" );
365         is( $stat->value, "$partialamount" . "\.0000", "Correct amount logged to statistics" );
366     }
367 };
368
369 1;