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

(-)a/Koha/REST/V1/Patrons/Account.pm (+87 lines)
Lines 19-24 use Modern::Perl; Link Here
19
19
20
use Mojo::Base 'Mojolicious::Controller';
20
use Mojo::Base 'Mojolicious::Controller';
21
21
22
use Koha::Patrons;
23
24
use Scalar::Util qw(blessed);
22
use Try::Tiny;
25
use Try::Tiny;
23
26
24
=head1 NAME
27
=head1 NAME
Lines 69-74 sub get { Link Here
69
    return $c->render( status => 200, openapi => $balance );
72
    return $c->render( status => 200, openapi => $balance );
70
}
73
}
71
74
75
=head3 add_credit
76
77
Controller function that handles adding a credit to a patron's account
78
79
=cut
80
81
sub add_credit {
82
    my $c = shift->openapi->valid_input or return;
83
84
    my $patron_id = $c->validation->param('patron_id');
85
    my $patron    = Koha::Patrons->find($patron_id);
86
    my $user      = $c->stash('koha.user');
87
88
89
    unless ($patron) {
90
        return $c->render( status => 404, openapi => { error => "Patron not found." } );
91
    }
92
93
    my $account = $patron->account;
94
    my $body    = $c->validation->param('body');
95
96
    return try {
97
        my $credit_type = $body->{credit_type} || 'payment';    # default to 'payment'
98
        my $amount = $body->{amount};                           # mandatory, validated by openapi
99
100
        unless ( $amount > 0 ) {  # until we support newer JSON::Validator and thus minimumExclusive
101
            Koha::Exceptions::BadParameter->throw( { parameter => 'amount' } );
102
        }
103
104
        # read the rest of the params
105
        my $payment_type = $body->{payment_type};
106
        my $description  = $body->{description};
107
        my $note         = $body->{note};
108
109
        my $credit = $account->add_credit(
110
            {   amount       => $amount,
111
                credit_type  => $credit_type,
112
                payment_type => $payment_type,
113
                description  => $description,
114
                note         => $note,
115
                user_id      => $user->id
116
            }
117
        );
118
        $credit->discard_changes;
119
120
        my $date = $body->{date};
121
        $credit->date( $date )->store
122
            if $date;
123
124
        my $debits_ids = $body->{account_lines_ids};
125
        my $debits = Koha::Account::Lines->search({ accountlines_id => { -in => $debits_ids } })
126
            if $debits_ids;
127
128
        my $outstanding_credit = $credit->amountoutstanding;
129
        if ($debits) {
130
            # pay them!
131
            $outstanding_credit = $credit->apply({ debits => $debits, offset_type => 'payment' });
132
        }
133
134
        if ($outstanding_credit) {
135
            my $outstanding_debits = $account->outstanding_debits;
136
            $credit->apply({ debits => $outstanding_debits, offset_type => 'payment' });
137
        }
138
139
        return $c->render( status => 200, openapi => { account_line_id => $credit->id } );
140
    }
141
    catch {
142
        if ( blessed $_ && $_->can('rethrow') ) {
143
            return $c->render(
144
                status  => 400,
145
                openapi => { error => "$_" }
146
            );
147
        }
148
        else {
149
            # Exception, rely on the stringified exception
150
            return $c->render(
151
                status  => 500,
152
                openapi => { error => "Something went wrong, check the logs" }
153
            );
154
        }
155
    };
156
}
157
158
72
=head3 _to_api
159
=head3 _to_api
73
160
74
Helper function that maps unblessed Koha::Account::Line objects
161
Helper function that maps unblessed Koha::Account::Line objects
(-)a/t/db_dependent/api/v1/patrons_accounts.t (-16 / +95 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 1;
20
use Test::More tests => 2;
21
21
22
use Test::Mojo;
22
use Test::Mojo;
23
use Test::Warn;
23
use Test::Warn;
Lines 45-52 subtest 'get_balance() tests' => sub { Link Here
45
45
46
    $schema->storage->txn_begin;
46
    $schema->storage->txn_begin;
47
47
48
    my ( $patron_id, $session_id ) = create_user_and_session({ authorized => 0 });
48
    my ( $patron, $session_id ) = create_user_and_session({ authorized => 0 });
49
    my $patron  = Koha::Patrons->find($patron_id);
49
    my $patron_id  = $patron->id;
50
    my $account = $patron->account;
50
    my $account = $patron->account;
51
51
52
    my $tx = $t->ua->build_tx(GET => "/api/v1/patrons/$patron_id/account");
52
    my $tx = $t->ua->build_tx(GET => "/api/v1/patrons/$patron_id/account");
Lines 147-178 subtest 'get_balance() tests' => sub { Link Here
147
    $schema->storage->txn_rollback;
147
    $schema->storage->txn_rollback;
148
};
148
};
149
149
150
subtest 'add_credit() tests' => sub {
151
152
    plan tests => 17;
153
154
    $schema->storage->txn_begin;
155
156
    my ( $patron, $session_id ) = create_user_and_session( { authorized => 1 } );
157
    my $patron_id = $patron->id;
158
    my $account   = $patron->account;
159
160
    is( $account->outstanding_debits->count,  0, 'No outstanding debits for patron' );
161
    is( $account->outstanding_credits->count, 0, 'No outstanding credits for patron' );
162
163
    my $credit = { amount => 100 };
164
165
    my $tx = $t->ua->build_tx(
166
        POST => "/api/v1/patrons/$patron_id/account/credits" => json => $credit );
167
    $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
168
    $tx->req->env( { REMOTE_ADDR => '127.0.0.1' } );
169
    $t->request_ok($tx)->status_is(200)->json_has('/account_line_id');
170
171
    my $outstanding_credits = $account->outstanding_credits;
172
    is( $outstanding_credits->count,             1 );
173
    is( $outstanding_credits->total_outstanding, -100 );
174
175
    my $debit_1 = Koha::Account::Line->new(
176
        {   borrowernumber    => $patron->borrowernumber,
177
            date              => \'NOW()',
178
            amount            => 10,
179
            description       => "A description",
180
            accounttype       => "N",                       # New card
181
            amountoutstanding => 10,
182
            manager_id        => $patron->borrowernumber,
183
        }
184
    )->store();
185
    my $debit_2 = Koha::Account::Line->new(
186
        {   borrowernumber    => $patron->borrowernumber,
187
            date              => \'NOW()',
188
            amount            => 15,
189
            description       => "A description",
190
            accounttype       => "N",                       # New card
191
            amountoutstanding => 15,
192
            manager_id        => $patron->borrowernumber,
193
        }
194
    )->store();
195
196
    is( $account->outstanding_debits->total_outstanding, 25 );
197
    $tx = $t->ua->build_tx(
198
        POST => "/api/v1/patrons/$patron_id/account/credits" => json => $credit );
199
    $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
200
    $tx->req->env( { REMOTE_ADDR => '127.0.0.1' } );
201
    $t->request_ok($tx)->status_is(200)->json_has('/account_line_id');
202
203
    is( $account->outstanding_debits->total_outstanding,
204
        0, "Debits have been cancelled automatically" );
205
206
    my $debit_3 = Koha::Account::Line->new(
207
        {   borrowernumber    => $patron->borrowernumber,
208
            date              => \'NOW()',
209
            amount            => 100,
210
            description       => "A description",
211
            accounttype       => "N",                       # New card
212
            amountoutstanding => 100,
213
            manager_id        => $patron->borrowernumber,
214
        }
215
    )->store();
216
217
    $credit = {
218
        amount            => 35,
219
        account_lines_ids => [ $debit_1->id, $debit_2->id, $debit_3->id ]
220
    };
221
222
    $tx = $t->ua->build_tx(
223
        POST => "/api/v1/patrons/$patron_id/account/credits" => json => $credit );
224
    $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
225
    $tx->req->env( { REMOTE_ADDR => '127.0.0.1' } );
226
    $t->request_ok($tx)->status_is(200)->json_has('/account_line_id');
227
228
    my $outstanding_debits = $account->outstanding_debits;
229
    is( $outstanding_debits->total_outstanding, 65 );
230
    is( $outstanding_debits->count,             1 );
231
232
    $schema->storage->txn_rollback;
233
};
234
150
sub create_user_and_session {
235
sub create_user_and_session {
151
236
152
    my $args  = shift;
237
    my $args  = shift;
153
    my $flags = ( $args->{authorized} ) ? 16 : 0;
238
    my $flags = ( $args->{authorized} ) ? 2**10 : 0;
154
239
155
    my $user = $builder->build(
240
    my $patron = $builder->build_object(
156
        {
241
        {
157
            source => 'Borrower',
242
            class => 'Koha::Patrons',
158
            value  => {
243
            value  => {
159
                flags => $flags,
244
                flags         => $flags
160
                gonenoaddress => 0,
161
                lost => 0,
162
                email => 'nobody@example.com',
163
                emailpro => 'nobody@example.com',
164
                B_email => 'nobody@example.com'
165
            }
245
            }
166
        }
246
        }
167
    );
247
    );
168
248
169
    # Create a session for the authorized user
249
    # Create a session for the authorized user
170
    my $session = C4::Auth::get_session('');
250
    my $session = C4::Auth::get_session('');
171
    $session->param( 'number',   $user->{borrowernumber} );
251
    $session->param( 'number',   $patron->id );
172
    $session->param( 'id',       $user->{userid} );
252
    $session->param( 'id',       $patron->userid );
173
    $session->param( 'ip',       '127.0.0.1' );
253
    $session->param( 'ip',       '127.0.0.1' );
174
    $session->param( 'lasttime', time() );
254
    $session->param( 'lasttime', time() );
175
    $session->flush;
255
    $session->flush;
176
256
177
    return ( $user->{borrowernumber}, $session->id );
257
    return ( $patron, $session->id );
178
}
258
}
179
- 

Return to bug 20944