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

(-)a/Koha/REST/V1/Patrons/Account.pm (-19 / +81 lines)
Lines 44-50 sub get { Link Here
44
    my $patron    = Koha::Patrons->find($patron_id);
44
    my $patron    = Koha::Patrons->find($patron_id);
45
45
46
    unless ($patron) {
46
    unless ($patron) {
47
        return $c->render( status => 404, openapi => { error => "Patron not found." } );
47
        return $c->render(
48
            status  => 404,
49
            openapi => { error => "Patron not found." }
50
        );
48
    }
51
    }
49
52
50
    return try {
53
    return try {
Lines 57-63 sub get { Link Here
57
        return $c->render(
60
        return $c->render(
58
            status  => 200,
61
            status  => 200,
59
            openapi => {
62
            openapi => {
60
                balance => $account->balance,
63
                balance            => $account->balance,
61
                outstanding_debits => {
64
                outstanding_debits => {
62
                    total => $debits->total_outstanding,
65
                    total => $debits->total_outstanding,
63
                    lines => $debits->to_api
66
                    lines => $debits->to_api
Lines 85-98 sub list_credits { Link Here
85
    my $patron    = Koha::Patrons->find($patron_id);
88
    my $patron    = Koha::Patrons->find($patron_id);
86
89
87
    unless ($patron) {
90
    unless ($patron) {
88
        return $c->render( status => 404, openapi => { error => "Patron not found." } );
91
        return $c->render(
92
            status  => 404,
93
            openapi => { error => "Patron not found." }
94
        );
89
    }
95
    }
90
96
91
    return try {
97
    return try {
92
        my $account = $patron->account;
98
        my $account = $patron->account;
93
99
94
        my $credits_set = $account->credits;
100
        my $credits_set = $account->credits;
95
        my $credits = $c->objects->search( $credits_set );
101
        my $credits     = $c->objects->search($credits_set);
96
        return $c->render( status => 200, openapi => $credits );
102
        return $c->render( status => 200, openapi => $credits );
97
    }
103
    }
98
    catch {
104
    catch {
Lines 113-131 sub add_credit { Link Here
113
    my $patron    = Koha::Patrons->find($patron_id);
119
    my $patron    = Koha::Patrons->find($patron_id);
114
    my $user      = $c->stash('koha.user');
120
    my $user      = $c->stash('koha.user');
115
121
116
117
    unless ($patron) {
122
    unless ($patron) {
118
        return $c->render( status => 404, openapi => { error => "Patron not found." } );
123
        return $c->render(
124
            status  => 404,
125
            openapi => { error => "Patron not found." }
126
        );
119
    }
127
    }
120
128
121
    my $account = $patron->account;
129
    my $account = $patron->account;
122
    my $body    = $c->validation->param('body');
130
    my $body    = $c->validation->param('body');
123
131
124
    return try {
132
    return try {
125
        my $credit_type = $body->{credit_type} || 'PAYMENT';    # default to 'PAYMENT'
133
        my $credit_type =
126
        my $amount = $body->{amount};                           # mandatory, validated by openapi
134
          $body->{credit_type} || 'PAYMENT';    # default to 'PAYMENT'
135
        my $amount = $body->{amount};    # mandatory, validated by openapi
127
136
128
        unless ( $amount > 0 ) {  # until we support newer JSON::Validator and thus minimumExclusive
137
        unless ( $amount > 0 )
138
        {    # until we support newer JSON::Validator and thus minimumExclusive
129
            Koha::Exceptions::BadParameter->throw( { parameter => 'amount' } );
139
            Koha::Exceptions::BadParameter->throw( { parameter => 'amount' } );
130
        }
140
        }
131
141
Lines 136-142 sub add_credit { Link Here
136
        my $library_id   = $body->{library_id};
146
        my $library_id   = $body->{library_id};
137
147
138
        my $credit = $account->add_credit(
148
        my $credit = $account->add_credit(
139
            {   amount       => $amount,
149
            {
150
                amount       => $amount,
140
                type         => $credit_type,
151
                type         => $credit_type,
141
                payment_type => $payment_type,
152
                payment_type => $payment_type,
142
                description  => $description,
153
                description  => $description,
Lines 149-170 sub add_credit { Link Here
149
        $credit->discard_changes;
160
        $credit->discard_changes;
150
161
151
        my $date = $body->{date};
162
        my $date = $body->{date};
152
        $credit->date( $date )->store
163
        $credit->date($date)->store
153
            if $date;
164
          if $date;
154
165
155
        my $debits_ids = $body->{account_lines_ids};
166
        my $debits_ids = $body->{account_lines_ids};
156
        my $debits;
167
        my $debits;
157
        $debits = Koha::Account::Lines->search({ accountlines_id => { -in => $debits_ids } })
168
        $debits = Koha::Account::Lines->search(
158
            if $debits_ids;
169
            { accountlines_id => { -in => $debits_ids } } )
170
          if $debits_ids;
159
171
160
        if ($debits) {
172
        if ($debits) {
173
161
            # pay them!
174
            # pay them!
162
            $credit = $credit->apply({ debits => [ $debits->as_list ] });
175
            $credit = $credit->apply( { debits => [ $debits->as_list ] } );
163
        }
176
        }
164
177
165
        if ($credit->amountoutstanding != 0) {
178
        if ( $credit->amountoutstanding != 0 ) {
166
            my $outstanding_debits = $account->outstanding_debits;
179
            my $outstanding_debits = $account->outstanding_debits;
167
            $credit->apply({ debits => [ $outstanding_debits->as_list ] });
180
            $credit->apply( { debits => [ $outstanding_debits->as_list ] } );
168
        }
181
        }
169
182
170
        $credit->discard_changes;
183
        $credit->discard_changes;
Lines 190-203 sub list_debits { Link Here
190
    my $patron    = Koha::Patrons->find($patron_id);
203
    my $patron    = Koha::Patrons->find($patron_id);
191
204
192
    unless ($patron) {
205
    unless ($patron) {
193
        return $c->render( status => 404, openapi => { error => "Patron not found." } );
206
        return $c->render(
207
            status  => 404,
208
            openapi => { error => "Patron not found." }
209
        );
194
    }
210
    }
195
211
196
    return try {
212
    return try {
197
        my $account = $patron->account;
213
        my $account = $patron->account;
198
214
199
        my $debits_set = $account->debits;
215
        my $debits_set = $account->debits;
200
        my $debits = $c->objects->search( $debits_set );
216
        my $debits     = $c->objects->search($debits_set);
201
        return $c->render( status => 200, openapi => $debits );
217
        return $c->render( status => 200, openapi => $debits );
202
    }
218
    }
203
    catch {
219
    catch {
Lines 205-208 sub list_debits { Link Here
205
    };
221
    };
206
}
222
}
207
223
224
=head3 add_debit
225
226
=cut
227
228
sub add_debit {
229
    my $c = shift->openapi->valid_input or return;
230
231
    my $patron_id = $c->validation->param('patron_id');
232
    my $patron    = Koha::Patrons->find($patron_id);
233
234
    unless ($patron) {
235
        return $c->render(
236
            status  => 404,
237
            openapi => { error => "Patron not found." }
238
        );
239
    }
240
241
    return try {
242
        my $data =
243
          Koha::Account::Debit->new_from_api( $c->validation->param('body') )
244
          ->unblessed;
245
246
        $data->{library_id}    = $data->{branchcode};
247
        $data->{cash_register} = $data->{cash_register_id};
248
        $data->{item_id}       = $data->{itemnumber};
249
        $data->{interface}     = 'api'
250
          ; # Should this always be API, or should we allow the API consumer to choose?
251
        $data->{user_id} = $patron->borrowernumber
252
          ; # Should this be API user OR staff the API may be acting on behalf of?
253
254
        my $debit = $patron->account->add_debit($data);
255
256
        $c->res->headers->location(
257
            $c->req->url->to_string . '/' . $debit->id );
258
        $debit->discard_changes;
259
260
        return $c->render(
261
            status  => 201,
262
            openapi => $debit->to_api
263
        );
264
    }
265
    catch {
266
        $c->unhandled_exception($_);
267
    };
268
}
269
208
1;
270
1;
(-)a/api/v1/swagger/definitions/debit.yaml (-1 lines)
Lines 31-37 properties: Link Here
31
    type:
31
    type:
32
      - string
32
      - string
33
      - "null"
33
      - "null"
34
    readOnly: true
35
    description: Account line description
34
    description: Account line description
36
  interface:
35
  interface:
37
    type:
36
    type:
(-)a/api/v1/swagger/paths/patrons_account.yaml (+47 lines)
Lines 177-179 Link Here
177
      permissions:
177
      permissions:
178
        borrowers: edit_borrowers
178
        borrowers: edit_borrowers
179
        updatecharges: remaining_permissions
179
        updatecharges: remaining_permissions
180
  post:
181
    x-mojo-to: Patrons::Account#add_debit
182
    operationId: addPatronDebit
183
    tags:
184
      - patrons
185
    summary: Add debit to a patron's account
186
    parameters:
187
      - $ref: "../swagger.yaml#/parameters/patron_id_pp"
188
      - name: body
189
        in: body
190
        description: A JSON object containing debit information
191
        required: true
192
        schema:
193
          $ref: "../swagger.yaml#/definitions/debit"
194
    produces:
195
      - application/json
196
    responses:
197
      "201":
198
        description: Debit added
199
        schema:
200
          $ref: "../swagger.yaml#/definitions/account_line"
201
      "401":
202
        description: Authentication required
203
        schema:
204
          $ref: "../swagger.yaml#/definitions/error"
205
      "403":
206
        description: Access forbidden
207
        schema:
208
          $ref: "../swagger.yaml#/definitions/error"
209
      "404":
210
        description: Patron not found
211
        schema:
212
          $ref: "../swagger.yaml#/definitions/error"
213
      "500":
214
        description: |
215
          Internal server error. Possible `error_code` attribute values:
216
217
          * `internal_server_error`
218
        schema:
219
          $ref: "../swagger.yaml#/definitions/error"
220
      "503":
221
        description: Under maintenance
222
        schema:
223
          $ref: "../swagger.yaml#/definitions/error"
224
    x-koha-authorization:
225
      permissions:
226
        updatecharges: remaining_permissions
(-)a/t/db_dependent/api/v1/patrons_accounts.t (-67 / +168 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 2;
20
use Test::More tests => 3;
21
21
22
use Test::Mojo;
22
use Test::Mojo;
23
23
Lines 42-76 subtest 'get_balance() tests' => sub { Link Here
42
    # Enable AccountAutoReconcile
42
    # Enable AccountAutoReconcile
43
    t::lib::Mocks::mock_preference( 'AccountAutoReconcile', 1 );
43
    t::lib::Mocks::mock_preference( 'AccountAutoReconcile', 1 );
44
44
45
    my $patron = $builder->build_object({
45
    my $patron = $builder->build_object(
46
        class => 'Koha::Patrons',
46
        {
47
        value => { flags => 1 }
47
            class => 'Koha::Patrons',
48
    });
48
            value => { flags => 1 }
49
        }
50
    );
49
    my $password = 'thePassword123';
51
    my $password = 'thePassword123';
50
    $patron->set_password({ password => $password, skip_validation => 1 });
52
    $patron->set_password( { password => $password, skip_validation => 1 } );
51
    my $userid = $patron->userid;
53
    my $userid = $patron->userid;
52
54
53
    my $library   = $builder->build_object({ class => 'Koha::Libraries' });
55
    my $library   = $builder->build_object( { class => 'Koha::Libraries' } );
54
    my $patron_id = $patron->id;
56
    my $patron_id = $patron->id;
55
    my $account   = $patron->account;
57
    my $account   = $patron->account;
56
58
57
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
59
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
58
      ->status_is(200)
60
      ->status_is(200)->json_is(
59
      ->json_is(
61
        {
60
        {   balance             => 0.00,
62
            balance             => 0.00,
61
            outstanding_debits  => { total => 0, lines => [] },
63
            outstanding_debits  => { total => 0, lines => [] },
62
            outstanding_credits => { total => 0, lines => [] }
64
            outstanding_credits => { total => 0, lines => [] }
63
        }
65
        }
64
    );
66
      );
65
67
66
    my $debit_1 = $account->add_debit(
68
    my $debit_1 = $account->add_debit(
67
        {
69
        {
68
            amount       => 50,
70
            amount      => 50,
69
            description  => "A description",
71
            description => "A description",
70
            type         => "NEW_CARD",
72
            type        => "NEW_CARD",
71
            user_id      => $patron->borrowernumber,
73
            user_id     => $patron->borrowernumber,
72
            library_id   => $library->id,
74
            library_id  => $library->id,
73
            interface    => 'test',
75
            interface   => 'test',
74
        }
76
        }
75
    )->store();
77
    )->store();
76
    $debit_1->discard_changes;
78
    $debit_1->discard_changes;
Lines 79-85 subtest 'get_balance() tests' => sub { Link Here
79
        {
81
        {
80
            amount      => 50.01,
82
            amount      => 50.01,
81
            description => "A description",
83
            description => "A description",
82
            type        => "NEW_CARD", # New card
84
            type        => "NEW_CARD",                # New card
83
            user_id     => $patron->borrowernumber,
85
            user_id     => $patron->borrowernumber,
84
            library_id  => $library->id,
86
            library_id  => $library->id,
85
            interface   => 'test',
87
            interface   => 'test',
Lines 88-112 subtest 'get_balance() tests' => sub { Link Here
88
    $debit_2->discard_changes;
90
    $debit_2->discard_changes;
89
91
90
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
92
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
91
      ->status_is(200)
93
      ->status_is(200)->json_is(
92
      ->json_is(
94
        {
93
        {   balance            => 100.01,
95
            balance            => 100.01,
94
            outstanding_debits => {
96
            outstanding_debits => {
95
                total => 100.01,
97
                total => 100.01,
96
                lines => [
98
                lines => [ $debit_1->to_api, $debit_2->to_api ]
97
                    $debit_1->to_api,
98
                    $debit_2->to_api
99
                ]
100
            },
99
            },
101
            outstanding_credits => {
100
            outstanding_credits => {
102
                total => 0,
101
                total => 0,
103
                lines => []
102
                lines => []
104
            }
103
            }
105
        }
104
        }
106
    );
105
      );
107
106
108
    $account->pay(
107
    $account->pay(
109
        {   amount       => 100.01,
108
        {
109
            amount       => 100.01,
110
            note         => 'He paid!',
110
            note         => 'He paid!',
111
            description  => 'Finally!',
111
            description  => 'Finally!',
112
            library_id   => $patron->branchcode,
112
            library_id   => $patron->branchcode,
Lines 115-138 subtest 'get_balance() tests' => sub { Link Here
115
    );
115
    );
116
116
117
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
117
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
118
      ->status_is(200)
118
      ->status_is(200)->json_is(
119
      ->json_is(
119
        {
120
        {   balance             => 0,
120
            balance             => 0,
121
            outstanding_debits  => { total => 0, lines => [] },
121
            outstanding_debits  => { total => 0, lines => [] },
122
            outstanding_credits => { total => 0, lines => [] }
122
            outstanding_credits => { total => 0, lines => [] }
123
        }
123
        }
124
    );
124
      );
125
125
126
    # add a credit
126
    # add a credit
127
    my $credit_line = $account->add_credit(
127
    my $credit_line = $account->add_credit(
128
        { amount => 10, user_id => $patron->id, library_id => $library->id, interface => 'test' } );
128
        {
129
            amount     => 10,
130
            user_id    => $patron->id,
131
            library_id => $library->id,
132
            interface  => 'test'
133
        }
134
    );
135
129
    # re-read from the DB
136
    # re-read from the DB
130
    $credit_line->discard_changes;
137
    $credit_line->discard_changes;
131
138
132
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
139
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
133
      ->status_is(200)
140
      ->status_is(200)->json_is(
134
      ->json_is(
141
        {
135
        {   balance            => -10,
142
            balance            => -10,
136
            outstanding_debits => {
143
            outstanding_debits => {
137
                total => 0,
144
                total => 0,
138
                lines => []
145
                lines => []
Lines 142-155 subtest 'get_balance() tests' => sub { Link Here
142
                lines => [ $credit_line->to_api ]
149
                lines => [ $credit_line->to_api ]
143
            }
150
            }
144
        }
151
        }
145
    );
152
      );
146
153
147
    # Accountline without manager_id (happens with fines.pl cron for example)
154
    # Accountline without manager_id (happens with fines.pl cron for example)
148
    my $debit_3 = $account->add_debit(
155
    my $debit_3 = $account->add_debit(
149
        {
156
        {
150
            amount      => 50,
157
            amount      => 50,
151
            description => "A description",
158
            description => "A description",
152
            type        => "NEW_CARD", # New card
159
            type        => "NEW_CARD",        # New card
153
            user_id     => undef,
160
            user_id     => undef,
154
            library_id  => $library->id,
161
            library_id  => $library->id,
155
            interface   => 'test',
162
            interface   => 'test',
Lines 158-178 subtest 'get_balance() tests' => sub { Link Here
158
    $debit_3->discard_changes;
165
    $debit_3->discard_changes;
159
166
160
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
167
    $t->get_ok("//$userid:$password@/api/v1/patrons/$patron_id/account")
161
      ->status_is(200)
168
      ->status_is(200)->json_is(
162
      ->json_is(
169
        {
163
        {   balance            => 40.00,
170
            balance            => 40.00,
164
            outstanding_debits => {
171
            outstanding_debits => {
165
                total => 50.00,
172
                total => 50.00,
166
                lines => [
173
                lines => [ $debit_3->to_api ]
167
                    $debit_3->to_api
168
                ]
169
            },
174
            },
170
            outstanding_credits => {
175
            outstanding_credits => {
171
                total => -10,
176
                total => -10,
172
                lines => [ $credit_line->to_api ]
177
                lines => [ $credit_line->to_api ]
173
            }
178
            }
174
        }
179
        }
175
    );
180
      );
176
181
177
    $schema->storage->txn_rollback;
182
    $schema->storage->txn_rollback;
178
};
183
};
Lines 183-216 subtest 'add_credit() tests' => sub { Link Here
183
188
184
    $schema->storage->txn_begin;
189
    $schema->storage->txn_begin;
185
190
186
    my $patron = $builder->build_object({
191
    my $patron = $builder->build_object(
187
        class => 'Koha::Patrons',
192
        {
188
        value => { flags => 1 }
193
            class => 'Koha::Patrons',
189
    });
194
            value => { flags => 1 }
195
        }
196
    );
190
    my $password = 'thePassword123';
197
    my $password = 'thePassword123';
191
    $patron->set_password({ password => $password, skip_validation => 1 });
198
    $patron->set_password( { password => $password, skip_validation => 1 } );
192
    my $userid = $patron->userid;
199
    my $userid = $patron->userid;
193
200
194
    my $library   = $builder->build_object({ class => 'Koha::Libraries' });
201
    my $library   = $builder->build_object( { class => 'Koha::Libraries' } );
195
    my $patron_id = $patron->id;
202
    my $patron_id = $patron->id;
196
    my $account   = $patron->account;
203
    my $account   = $patron->account;
197
204
198
    is( $account->outstanding_debits->count,  0, 'No outstanding debits for patron' );
205
    is( $account->outstanding_debits->count,
199
    is( $account->outstanding_credits->count, 0, 'No outstanding credits for patron' );
206
        0, 'No outstanding debits for patron' );
207
    is( $account->outstanding_credits->count,
208
        0, 'No outstanding credits for patron' );
200
209
201
    my $credit = { amount => 100 };
210
    my $credit = { amount => 100 };
202
211
203
    my $ret = $t->post_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit)
212
    my $ret = $t->post_ok(
204
      ->status_is(201)->tx->res->json;
213
        "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" =>
214
          json => $credit )->status_is(201)->tx->res->json;
205
215
206
    is_deeply( $ret, Koha::Account::Lines->find( $ret->{account_line_id} )->to_api, 'Line returned correctly' );
216
    is_deeply(
217
        $ret,
218
        Koha::Account::Lines->find( $ret->{account_line_id} )->to_api,
219
        'Line returned correctly'
220
    );
207
221
208
    my $outstanding_credits = $account->outstanding_credits;
222
    my $outstanding_credits = $account->outstanding_credits;
209
    is( $outstanding_credits->count,             1 );
223
    is( $outstanding_credits->count,             1 );
210
    is( $outstanding_credits->total_outstanding, -100 );
224
    is( $outstanding_credits->total_outstanding, -100 );
211
225
212
    my $debit_1 = $account->add_debit(
226
    my $debit_1 = $account->add_debit(
213
        {   amount      => 10,
227
        {
228
            amount      => 10,
214
            description => "A description",
229
            description => "A description",
215
            type        => "NEW_CARD",
230
            type        => "NEW_CARD",
216
            user_id     => $patron->borrowernumber,
231
            user_id     => $patron->borrowernumber,
Lines 218-224 subtest 'add_credit() tests' => sub { Link Here
218
        }
233
        }
219
    )->store();
234
    )->store();
220
    my $debit_2 = $account->add_debit(
235
    my $debit_2 = $account->add_debit(
221
        {   amount      => 15,
236
        {
237
            amount      => 15,
222
            description => "A description",
238
            description => "A description",
223
            type        => "NEW_CARD",
239
            type        => "NEW_CARD",
224
            user_id     => $patron->borrowernumber,
240
            user_id     => $patron->borrowernumber,
Lines 229-239 subtest 'add_credit() tests' => sub { Link Here
229
    is( $account->outstanding_debits->total_outstanding, 25 );
245
    is( $account->outstanding_debits->total_outstanding, 25 );
230
    $credit->{library_id} = $library->id;
246
    $credit->{library_id} = $library->id;
231
247
232
    $ret = $t->post_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit)
248
    $ret = $t->post_ok(
233
      ->status_is(201)
249
        "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" =>
234
      ->tx->res->json;
250
          json => $credit )->status_is(201)->tx->res->json;
235
251
236
    is_deeply( $ret, Koha::Account::Lines->find( $ret->{account_line_id} )->to_api, 'Line returned correctly' );
252
    is_deeply(
253
        $ret,
254
        Koha::Account::Lines->find( $ret->{account_line_id} )->to_api,
255
        'Line returned correctly'
256
    );
237
257
238
    my $account_line_id = $t->tx->res->json->{account_line_id};
258
    my $account_line_id = $t->tx->res->json->{account_line_id};
239
    is( Koha::Account::Lines->find($account_line_id)->branchcode,
259
    is( Koha::Account::Lines->find($account_line_id)->branchcode,
Lines 243-249 subtest 'add_credit() tests' => sub { Link Here
243
        0, "Debits have been cancelled automatically" );
263
        0, "Debits have been cancelled automatically" );
244
264
245
    my $debit_3 = $account->add_debit(
265
    my $debit_3 = $account->add_debit(
246
        {   amount      => 100,
266
        {
267
            amount      => 100,
247
            description => "A description",
268
            description => "A description",
248
            type        => "NEW_CARD",
269
            type        => "NEW_CARD",
249
            user_id     => $patron->borrowernumber,
270
            user_id     => $patron->borrowernumber,
Lines 256-266 subtest 'add_credit() tests' => sub { Link Here
256
        account_lines_ids => [ $debit_1->id, $debit_2->id, $debit_3->id ]
277
        account_lines_ids => [ $debit_1->id, $debit_2->id, $debit_3->id ]
257
    };
278
    };
258
279
259
    $ret = $t->post_ok("//$userid:$password@/api/v1/patrons/$patron_id/account/credits" => json => $credit)
280
    $ret = $t->post_ok(
260
      ->status_is(201)
281
        "//$userid:$password@/api/v1/patrons/$patron_id/account/credits" =>
261
      ->tx->res->json;
282
          json => $credit )->status_is(201)->tx->res->json;
262
283
263
    is_deeply( $ret, Koha::Account::Lines->find( $ret->{account_line_id} )->to_api, 'Line returned correctly' );
284
    is_deeply(
285
        $ret,
286
        Koha::Account::Lines->find( $ret->{account_line_id} )->to_api,
287
        'Line returned correctly'
288
    );
264
289
265
    my $outstanding_debits = $account->outstanding_debits;
290
    my $outstanding_debits = $account->outstanding_debits;
266
    is( $outstanding_debits->total_outstanding, 65 );
291
    is( $outstanding_debits->total_outstanding, 65 );
Lines 268-270 subtest 'add_credit() tests' => sub { Link Here
268
293
269
    $schema->storage->txn_rollback;
294
    $schema->storage->txn_rollback;
270
};
295
};
271
- 
296
297
subtest 'add_debit() tests' => sub {
298
299
    plan tests => 13;
300
301
    $schema->storage->txn_begin;
302
303
    my $patron = $builder->build_object(
304
        {
305
            class => 'Koha::Patrons',
306
            value => { flags => 1 }
307
        }
308
    );
309
    my $password = 'thePassword123';
310
    $patron->set_password( { password => $password, skip_validation => 1 } );
311
    my $userid = $patron->userid;
312
313
    my $library   = $builder->build_object( { class => 'Koha::Libraries' } );
314
    my $patron_id = $patron->id;
315
    my $account   = $patron->account;
316
317
    is( $account->outstanding_debits->count,
318
        0, 'No outstanding debits for patron' );
319
    is( $account->outstanding_credits->count,
320
        0, 'No outstanding credits for patron' );
321
322
    my $debit = {
323
        amount      => 100,
324
        description => "A description",
325
        debit_type  => "NEW_CARD",
326
        user_id     => $patron->borrowernumber,
327
        interface   => 'test',
328
        library_id  => $library->id,
329
    };
330
331
    my $ret = $t->post_ok(
332
        "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" =>
333
          json => $debit )->status_is(201)->tx->res->json;
334
    my $account_line = Koha::Account::Lines->find( $ret->{account_line_id} );
335
336
    is_deeply( $ret, $account_line->to_api, 'Line returned correctly' );
337
338
    is( $account_line->branchcode,
339
        $library->id, 'Library id is sored correctly' );
340
341
    my $outstanding_debits = $account->outstanding_debits;
342
    is( $outstanding_debits->count,             1 );
343
    is( $outstanding_debits->total_outstanding, 100 );
344
345
    my $credit_1 = $account->add_credit(
346
        {
347
            amount    => 10,
348
            interface => 'test',
349
        }
350
    )->store()->apply( { debits => [$account_line] } );
351
    my $credit_2 = $account->add_credit(
352
        {
353
            amount    => 15,
354
            interface => 'test'
355
        }
356
    )->store()->apply( { debits => [$account_line] } );
357
358
    is( $account->outstanding_credits->total_outstanding, 0 );
359
    is( $account->outstanding_debits->total_outstanding,
360
        75, "Credits partially cancelled debit" );
361
362
    my $account_line_id = $ret->{account_line_id};
363
364
    $t->post_ok(
365
        "//$userid:$password@/api/v1/patrons/$patron_id/account/debits" =>
366
          json => $debit )->status_is(201);
367
368
    is( $account->outstanding_debits->total_outstanding,
369
        175, "Debit added to total outstanding debits" );
370
371
    $schema->storage->txn_rollback;
372
};

Return to bug 21043