Bug 28585: (follow-up) Tests for q= supporting date/date-time parameters
[koha.git] / t / db_dependent / api / v1 / patrons_accounts.t
1 #!/usr/bin/perl
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18 use Modern::Perl;
19
20 use Test::More tests => 2;
21
22 use Test::Mojo;
23
24 use t::lib::TestBuilder;
25 use t::lib::Mocks;
26
27 use Koha::Account::Lines;
28
29 my $schema  = Koha::Database->new->schema;
30 my $builder = t::lib::TestBuilder->new;
31
32 t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
33
34 my $t = Test::Mojo->new('Koha::REST::V1');
35
36 subtest 'get_balance() tests' => sub {
37
38     plan tests => 15;
39
40     $schema->storage->txn_begin;
41
42     # Enable AccountAutoReconcile
43     t::lib::Mocks::mock_preference( 'AccountAutoReconcile', 1 );
44
45     my $patron = $builder->build_object({
46         class => 'Koha::Patrons',
47         value => { flags => 1 }
48     });
49     my $password = 'thePassword123';
50     $patron->set_password({ password => $password, skip_validation => 1 });
51     my $userid = $patron->userid;
52
53     my $library   = $builder->build_object({ class => 'Koha::Libraries' });
54     my $patron_id = $patron->id;
55     my $account   = $patron->account;
56
57     $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
58       ->status_is(200)
59       ->json_is(
60         {   balance             => 0.00,
61             outstanding_debits  => { total => 0, lines => [] },
62             outstanding_credits => { total => 0, lines => [] }
63         }
64     );
65
66     my $debit_1 = $account->add_debit(
67         {
68             amount       => 50,
69             description  => "A description",
70             type         => "NEW_CARD",
71             user_id      => $patron->borrowernumber,
72             library_id   => $library->id,
73             interface    => 'test',
74         }
75     )->store();
76     $debit_1->discard_changes;
77
78     my $debit_2 = $account->add_debit(
79         {
80             amount      => 50.01,
81             description => "A description",
82             type        => "NEW_CARD", # New card
83             user_id     => $patron->borrowernumber,
84             library_id  => $library->id,
85             interface   => 'test',
86         }
87     )->store();
88     $debit_2->discard_changes;
89
90     $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
91       ->status_is(200)
92       ->json_is(
93         {   balance            => 100.01,
94             outstanding_debits => {
95                 total => 100.01,
96                 lines => [
97                     $debit_1->to_api,
98                     $debit_2->to_api
99                 ]
100             },
101             outstanding_credits => {
102                 total => 0,
103                 lines => []
104             }
105         }
106     );
107
108     $account->pay(
109         {   amount       => 100.01,
110             note         => 'He paid!',
111             description  => 'Finally!',
112             library_id   => $patron->branchcode,
113             account_type => 'PAYMENT'
114         }
115     );
116
117     $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
118       ->status_is(200)
119       ->json_is(
120         {   balance             => 0,
121             outstanding_debits  => { total => 0, lines => [] },
122             outstanding_credits => { total => 0, lines => [] }
123         }
124     );
125
126     # add a credit
127     my $credit_line = $account->add_credit(
128         { amount => 10, user_id => $patron->id, library_id => $library->id, interface => 'test' } );
129     # re-read from the DB
130     $credit_line->discard_changes;
131
132     $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
133       ->status_is(200)
134       ->json_is(
135         {   balance            => -10,
136             outstanding_debits => {
137                 total => 0,
138                 lines => []
139             },
140             outstanding_credits => {
141                 total => -10,
142                 lines => [ $credit_line->to_api ]
143             }
144         }
145     );
146
147     # Accountline without manager_id (happens with fines.pl cron for example)
148     my $debit_3 = $account->add_debit(
149         {
150             amount      => 50,
151             description => "A description",
152             type        => "NEW_CARD", # New card
153             user_id     => undef,
154             library_id  => $library->id,
155             interface   => 'test',
156         }
157     )->store();
158     $debit_3->discard_changes;
159
160     $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
161       ->status_is(200)
162       ->json_is(
163         {   balance            => 40.00,
164             outstanding_debits => {
165                 total => 50.00,
166                 lines => [
167                     $debit_3->to_api
168                 ]
169             },
170             outstanding_credits => {
171                 total => -10,
172                 lines => [ $credit_line->to_api ]
173             }
174         }
175     );
176
177     $schema->storage->txn_rollback;
178 };
179
180 subtest 'add_credit() tests' => sub {
181
182     plan tests => 18;
183
184     $schema->storage->txn_begin;
185
186     my $patron = $builder->build_object({
187         class => 'Koha::Patrons',
188         value => { flags => 1 }
189     });
190     my $password = 'thePassword123';
191     $patron->set_password({ password => $password, skip_validation => 1 });
192     my $userid = $patron->userid;
193
194     my $library   = $builder->build_object({ class => 'Koha::Libraries' });
195     my $patron_id = $patron->id;
196     my $account   = $patron->account;
197
198     is( $account->outstanding_debits->count,  0, 'No outstanding debits for patron' );
199     is( $account->outstanding_credits->count, 0, 'No outstanding credits for patron' );
200
201     my $credit = { amount => 100 };
202
203     my $ret = $t->post_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit)
204       ->status_is(201)->tx->res->json;
205
206     is_deeply( $ret, Koha::Account::Lines->find( $ret->{account_line_id} )->to_api, 'Line returned correctly' );
207
208     my $outstanding_credits = $account->outstanding_credits;
209     is( $outstanding_credits->count,             1 );
210     is( $outstanding_credits->total_outstanding, -100 );
211
212     my $debit_1 = $account->add_debit(
213         {   amount      => 10,
214             description => "A description",
215             type        => "NEW_CARD",
216             user_id     => $patron->borrowernumber,
217             interface   => 'test',
218         }
219     )->store();
220     my $debit_2 = $account->add_debit(
221         {   amount      => 15,
222             description => "A description",
223             type        => "NEW_CARD",
224             user_id     => $patron->borrowernumber,
225             interface   => 'test',
226         }
227     )->store();
228
229     is( $account->outstanding_debits->total_outstanding, 25 );
230     $credit->{library_id} = $library->id;
231
232     $ret = $t->post_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit)
233       ->status_is(201)
234       ->tx->res->json;
235
236     is_deeply( $ret, Koha::Account::Lines->find( $ret->{account_line_id} )->to_api, 'Line returned correctly' );
237
238     my $account_line_id = $t->tx->res->json->{account_line_id};
239     is( Koha::Account::Lines->find($account_line_id)->branchcode,
240         $library->id, 'Library id is sored correctly' );
241
242     is( $account->outstanding_debits->total_outstanding,
243         0, "Debits have been cancelled automatically" );
244
245     my $debit_3 = $account->add_debit(
246         {   amount      => 100,
247             description => "A description",
248             type        => "NEW_CARD",
249             user_id     => $patron->borrowernumber,
250             interface   => 'test',
251         }
252     )->store();
253
254     $credit = {
255         amount            => 35,
256         account_lines_ids => [ $debit_1->id, $debit_2->id, $debit_3->id ]
257     };
258
259     $ret = $t->post_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit)
260       ->status_is(201)
261       ->tx->res->json;
262
263     is_deeply( $ret, Koha::Account::Lines->find( $ret->{account_line_id} )->to_api, 'Line returned correctly' );
264
265     my $outstanding_debits = $account->outstanding_debits;
266     is( $outstanding_debits->total_outstanding, 65 );
267     is( $outstanding_debits->count,             1 );
268
269     $schema->storage->txn_rollback;
270 };