Bug 26384: Fix executable flags
[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 use Test::Warn;
24
25 use t::lib::TestBuilder;
26 use t::lib::Mocks;
27
28 use C4::Auth;
29 use Koha::Account::Line;
30
31 my $schema  = Koha::Database->new->schema;
32 my $builder = t::lib::TestBuilder->new;
33
34 # FIXME: sessionStorage defaults to mysql, but it seems to break transaction handling
35 # this affects the other REST api tests
36 t::lib::Mocks::mock_preference( 'SessionStorage', 'tmp' );
37
38 my $remote_address = '127.0.0.1';
39 my $t              = Test::Mojo->new('Koha::REST::V1');
40
41 subtest 'get_balance() tests' => sub {
42
43     plan tests => 15;
44
45     $schema->storage->txn_begin;
46
47     my ( $patron, $session_id ) = create_user_and_session({ authorized => 1 });
48     my $library   = $builder->build_object({ class => 'Koha::Libraries' });
49     my $patron_id = $patron->id;
50     my $account   = $patron->account;
51
52     my $tx = $t->ua->build_tx(GET => "/api/v1/patrons/$patron_id/account");
53     $tx->req->cookies({ name => 'CGISESSID', value => $session_id });
54     $tx->req->env({ REMOTE_ADDR => '127.0.0.1' });
55     $t->request_ok($tx)->status_is(200)->json_is(
56         {   balance             => 0.00,
57             outstanding_debits  => { total => 0, lines => [] },
58             outstanding_credits => { total => 0, lines => [] }
59         }
60     );
61
62     my $account_line_1 = Koha::Account::Line->new(
63         {
64             borrowernumber    => $patron->borrowernumber,
65             date              => \'NOW()',
66             amount            => 50,
67             description       => "A description",
68             debit_type_code   => "NEW_CARD", # New card
69             amountoutstanding => 50,
70             manager_id        => $patron->borrowernumber,
71             branchcode        => $library->id,
72             interface         => 'test',
73         }
74     )->store();
75     $account_line_1->discard_changes;
76
77     my $account_line_2 = Koha::Account::Line->new(
78         {
79             borrowernumber    => $patron->borrowernumber,
80             date              => \'NOW()',
81             amount            => 50.01,
82             description       => "A description",
83             debit_type_code   => "NEW_CARD", # New card
84             amountoutstanding => 50.01,
85             manager_id        => $patron->borrowernumber,
86             branchcode        => $library->id,
87             interface         => 'test',
88         }
89     )->store();
90     $account_line_2->discard_changes;
91
92     $tx = $t->ua->build_tx( GET => "/api/v1/patrons/$patron_id/account" );
93     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
94     $tx->req->env( { REMOTE_ADDR => '127.0.0.1' } );
95     $t->request_ok($tx)->status_is(200)->json_is(
96         {   balance            => 100.01,
97             outstanding_debits => {
98                 total => 100.01,
99                 lines => [
100                     $account_line_1->to_api,
101                     $account_line_2->to_api
102                 ]
103             },
104             outstanding_credits => {
105                 total => 0,
106                 lines => []
107             }
108         }
109     );
110
111     $account->pay(
112         {   amount       => 100.01,
113             note         => 'He paid!',
114             description  => 'Finally!',
115             library_id   => $patron->branchcode,
116             account_type => 'PAYMENT',
117             offset_type  => 'Payment'
118         }
119     );
120
121     $tx = $t->ua->build_tx( GET => "/api/v1/patrons/$patron_id/account" );
122     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
123     $tx->req->env( { REMOTE_ADDR => '127.0.0.1' } );
124     $t->request_ok($tx)->status_is(200)->json_is(
125         {   balance             => 0,
126             outstanding_debits  => { total => 0, lines => [] },
127             outstanding_credits => { total => 0, lines => [] }
128         }
129     );
130
131     # add a credit
132     my $credit_line = $account->add_credit(
133         { amount => 10, user_id => $patron->id, library_id => $library->id, interface => 'test' } );
134     # re-read from the DB
135     $credit_line->discard_changes;
136     $tx = $t->ua->build_tx( GET => "/api/v1/patrons/$patron_id/account" );
137     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
138     $tx->req->env( { REMOTE_ADDR => '127.0.0.1' } );
139     $t->request_ok($tx)->status_is(200)->json_is(
140         {   balance            => -10,
141             outstanding_debits => {
142                 total => 0,
143                 lines => []
144             },
145             outstanding_credits => {
146                 total => -10,
147                 lines => [ $credit_line->to_api ]
148             }
149         }
150     );
151
152     # Accountline without manager_id (happens with fines.pl cron for example)
153     my $account_line_3 = Koha::Account::Line->new(
154         {
155             borrowernumber    => $patron->borrowernumber,
156             date              => \'NOW()',
157             amount            => 50,
158             description       => "A description",
159             debit_type_code   => "NEW_CARD", # New card
160             amountoutstanding => 50,
161             manager_id        => undef,
162             branchcode        => $library->id,
163             interface         => 'test',
164         }
165     )->store();
166     $account_line_3->discard_changes;
167
168     $tx = $t->ua->build_tx( GET => "/api/v1/patrons/$patron_id/account" );
169     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
170     $tx->req->env( { REMOTE_ADDR => '127.0.0.1' } );
171     $t->request_ok($tx)->status_is(200)->json_is(
172         {   balance            => 40.00,
173             outstanding_debits => {
174                 total => 50.00,
175                 lines => [
176                     $account_line_3->to_api
177                 ]
178             },
179             outstanding_credits => {
180                 total => -10,
181                 lines => [ $credit_line->to_api ]
182             }
183         }
184     );
185
186     $schema->storage->txn_rollback;
187 };
188
189 subtest 'add_credit() tests' => sub {
190
191     plan tests => 18;
192
193     $schema->storage->txn_begin;
194
195     my ( $patron, $session_id ) = create_user_and_session( { authorized => 1 } );
196     my $library   = $builder->build_object({ class => 'Koha::Libraries' });
197     my $patron_id = $patron->id;
198     my $account   = $patron->account;
199
200     is( $account->outstanding_debits->count,  0, 'No outstanding debits for patron' );
201     is( $account->outstanding_credits->count, 0, 'No outstanding credits for patron' );
202
203     my $credit = { amount => 100 };
204
205     my $tx = $t->ua->build_tx(
206         POST => "/api/v1/patrons/$patron_id/account/credits" => json => $credit );
207     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
208     $tx->req->env( { REMOTE_ADDR => '127.0.0.1' } );
209     $t->request_ok($tx)->status_is(200)->json_has('/account_line_id');
210
211     my $outstanding_credits = $account->outstanding_credits;
212     is( $outstanding_credits->count,             1 );
213     is( $outstanding_credits->total_outstanding, -100 );
214
215     my $debit_1 = Koha::Account::Line->new(
216         {   borrowernumber    => $patron->borrowernumber,
217             date              => \'NOW()',
218             amount            => 10,
219             description       => "A description",
220             debit_type_code   => "NEW_CARD",                       # New card
221             amountoutstanding => 10,
222             manager_id        => $patron->borrowernumber,
223             interface         => 'test',
224         }
225     )->store();
226     my $debit_2 = Koha::Account::Line->new(
227         {   borrowernumber    => $patron->borrowernumber,
228             date              => \'NOW()',
229             amount            => 15,
230             description       => "A description",
231             debit_type_code   => "NEW_CARD",                       # New card
232             amountoutstanding => 15,
233             manager_id        => $patron->borrowernumber,
234             interface         => 'test',
235         }
236     )->store();
237
238     is( $account->outstanding_debits->total_outstanding, 25 );
239     $credit->{library_id} = $library->id;
240     $tx = $t->ua->build_tx(
241         POST => "/api/v1/patrons/$patron_id/account/credits" => json => $credit );
242     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
243     $tx->req->env( { REMOTE_ADDR => '127.0.0.1' } );
244     $t->request_ok($tx)->status_is(200)->json_has('/account_line_id');
245
246     my $account_line_id = $tx->res->json->{account_line_id};
247     is( Koha::Account::Lines->find($account_line_id)->branchcode,
248         $library->id, 'Library id is sored correctly' );
249
250     is( $account->outstanding_debits->total_outstanding,
251         0, "Debits have been cancelled automatically" );
252
253     my $debit_3 = Koha::Account::Line->new(
254         {   borrowernumber    => $patron->borrowernumber,
255             date              => \'NOW()',
256             amount            => 100,
257             description       => "A description",
258             debit_type_code   => "NEW_CARD",                       # New card
259             amountoutstanding => 100,
260             manager_id        => $patron->borrowernumber,
261             interface         => 'test',
262         }
263     )->store();
264
265     $credit = {
266         amount            => 35,
267         account_lines_ids => [ $debit_1->id, $debit_2->id, $debit_3->id ]
268     };
269
270     $tx = $t->ua->build_tx(
271         POST => "/api/v1/patrons/$patron_id/account/credits" => json => $credit );
272     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
273     $tx->req->env( { REMOTE_ADDR => '127.0.0.1' } );
274     $t->request_ok($tx)->status_is(200)->json_has('/account_line_id');
275
276     my $outstanding_debits = $account->outstanding_debits;
277     is( $outstanding_debits->total_outstanding, 65 );
278     is( $outstanding_debits->count,             1 );
279
280     $schema->storage->txn_rollback;
281 };
282
283 sub create_user_and_session {
284
285     my $args  = shift;
286     my $flags = ( $args->{authorized} ) ? 1 : 0;
287
288     my $patron = $builder->build_object(
289         {
290             class => 'Koha::Patrons',
291             value  => {
292                 flags         => $flags
293             }
294         }
295     );
296
297     # Create a session for the authorized user
298     my $session = C4::Auth::get_session('');
299     $session->param( 'number',   $patron->id );
300     $session->param( 'id',       $patron->userid );
301     $session->param( 'ip',       '127.0.0.1' );
302     $session->param( 'lasttime', time() );
303     $session->flush;
304
305     return ( $patron, $session->id );
306 }