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

(-)a/Koha/Account/Line.pm (-27 / +29 lines)
Lines 128-141 sub void { Link Here
128
128
129
=head3 apply
129
=head3 apply
130
130
131
    my $outstanding_amount = $credit->apply({ debit =>  $debit, [ offset_type => $offset_type ] });
131
    my $debits = $account->outstanding_debits;
132
    my $outstanding_amount = $credit->apply({ debits =>  $debits, [ offset_type => $offset_type ] });
132
133
133
=cut
134
=cut
134
135
135
sub apply {
136
sub apply {
136
    my ( $self, $params ) = @_;
137
    my ( $self, $params ) = @_;
137
138
138
    my $debit       = $params->{debit};
139
    my $debits      = $params->{debits};
139
    my $offset_type = $params->{offset_type} // 'credit_applied';
140
    my $offset_type = $params->{offset_type} // 'credit_applied';
140
141
141
    unless ( $self->is_credit ) {
142
    unless ( $self->is_credit ) {
Lines 144-155 sub apply { Link Here
144
        );
145
        );
145
    }
146
    }
146
147
147
    unless ( $debit->is_debit ) {
148
        Koha::Exceptions::Account::IsNotDebit->throw(
149
            error => 'Account line ' . $debit->id . 'is not a debit'
150
        );
151
    }
152
153
    my $available_credit = $self->amountoutstanding * -1;
148
    my $available_credit = $self->amountoutstanding * -1;
154
149
155
    unless ( $available_credit > 0 ) {
150
    unless ( $available_credit > 0 ) {
Lines 161-190 sub apply { Link Here
161
    my $schema = Koha::Database->new->schema;
156
    my $schema = Koha::Database->new->schema;
162
157
163
    $schema->txn_do( sub {
158
    $schema->txn_do( sub {
159
        while ( my $debit = $debits->next ) {
164
160
165
        my $amount_to_cancel;
161
            unless ( $debit->is_debit ) {
166
        my $owed = $debit->amountoutstanding;
162
                Koha::Exceptions::Account::IsNotDebit->throw(
167
163
                    error => 'Account line ' . $debit->id . 'is not a debit'
168
        if ( $available_credit >= $owed ) {
164
                );
169
            $amount_to_cancel = $owed;
165
            }
170
        }
166
            my $amount_to_cancel;
171
        else {    # $available_credit < $debit->amountoutstanding
167
            my $owed = $debit->amountoutstanding;
172
            $amount_to_cancel = $available_credit;
173
        }
174
168
175
        # record the account offset
169
            if ( $available_credit >= $owed ) {
176
        Koha::Account::Offset->new(
170
                $amount_to_cancel = $owed;
177
            {   credit_id => $self->id,
171
            }
178
                debit_id  => $debit->id,
172
            else {    # $available_credit < $debit->amountoutstanding
179
                amount    => $amount_to_cancel,
173
                $amount_to_cancel = $available_credit;
180
                type      => $offset_type,
181
            }
174
            }
182
        )->store();
183
175
184
        $available_credit -= $amount_to_cancel;
176
            # record the account offset
177
            Koha::Account::Offset->new(
178
                {   credit_id => $self->id,
179
                    debit_id  => $debit->id,
180
                    amount    => $amount_to_cancel,
181
                    type      => $offset_type,
182
                }
183
            )->store();
184
185
            $available_credit -= $amount_to_cancel;
185
186
186
        $self->amountoutstanding( $available_credit * -1 )->store;
187
            $self->amountoutstanding( $available_credit * -1 )->store;
187
        $debit->amountoutstanding( $owed - $amount_to_cancel )->store;
188
            $debit->amountoutstanding( $owed - $amount_to_cancel )->store;
189
        }
188
    });
190
    });
189
191
190
    return $available_credit;
192
    return $available_credit;
(-)a/t/db_dependent/Koha/Account/Lines.t (-16 / +54 lines)
Lines 19-25 Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::More tests => 3;
22
use Test::More tests => 4;
23
use Test::Exception;
23
use Test::Exception;
24
24
25
use Koha::Account;
25
use Koha::Account;
Lines 161-171 subtest 'is_credit() and is_debit() tests' => sub { Link Here
161
161
162
subtest 'apply() tests' => sub {
162
subtest 'apply() tests' => sub {
163
163
164
    plan tests => 12;
164
    plan tests => 24;
165
165
166
    $schema->storage->txn_begin;
166
    $schema->storage->txn_begin;
167
167
168
    my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
168
    my $patron  = $builder->build_object( { class => 'Koha::Patrons' } );
169
    my $account = $patron->account;
169
    my $account = $patron->account;
170
170
171
    my $credit = $account->add_credit( { amount => 100, user_id => $patron->id } );
171
    my $credit = $account->add_credit( { amount => 100, user_id => $patron->id } );
Lines 189-196 subtest 'apply() tests' => sub { Link Here
189
    $credit->discard_changes;
189
    $credit->discard_changes;
190
    $debit_1->discard_changes;
190
    $debit_1->discard_changes;
191
191
192
    my $remaining_credit = $credit->apply( { debit => $debit_1, offset_type => 'Manual Credit' } );
192
    my $debits = Koha::Account::Lines->search({ accountlines_id => $debit_1->id });
193
    is( $remaining_credit, 90, 'Remaining credit is correctly calculated' );
193
    my $remaining_credit = $credit->apply( { debits => $debits, offset_type => 'Manual Credit' } );
194
    is( $remaining_credit * 1, 90, 'Remaining credit is correctly calculated' );
194
    $credit->discard_changes;
195
    $credit->discard_changes;
195
    is( $credit->amountoutstanding * -1, $remaining_credit, 'Remaining credit correctly stored' );
196
    is( $credit->amountoutstanding * -1, $remaining_credit, 'Remaining credit correctly stored' );
196
197
Lines 200-231 subtest 'apply() tests' => sub { Link Here
200
201
201
    my $offsets = Koha::Account::Offsets->search( { credit_id => $credit->id, debit_id => $debit_1->id } );
202
    my $offsets = Koha::Account::Offsets->search( { credit_id => $credit->id, debit_id => $debit_1->id } );
202
    is( $offsets->count, 1, 'Only one offset is generated' );
203
    is( $offsets->count, 1, 'Only one offset is generated' );
203
    my $THE_offest = $offsets->next;
204
    my $THE_offset = $offsets->next;
204
    is( $THE_offest->amount * 1, 10, 'Amount was calculated correctly (less than the available credit)' );
205
    is( $THE_offset->amount * 1, 10, 'Amount was calculated correctly (less than the available credit)' );
205
    is( $THE_offest->type, 'Manual Credit', 'Passed type stored correctly' );
206
    is( $THE_offset->type, 'Manual Credit', 'Passed type stored correctly' );
206
207
207
    $remaining_credit = $credit->apply( { debit => $debit_2, offset_type => 'Manual Credit' } );
208
    $debits = Koha::Account::Lines->search({ accountlines_id => $debit_2->id });
209
    $remaining_credit = $credit->apply( { debits => $debits } );
208
    is( $remaining_credit, 0, 'No remaining credit left' );
210
    is( $remaining_credit, 0, 'No remaining credit left' );
209
    $credit->discard_changes;
211
    $credit->discard_changes;
210
    is( $credit->amountoutstanding * 1, 0, 'No outstanding credit' );
212
    is( $credit->amountoutstanding * 1, 0, 'No outstanding credit' );
211
    $debit_2->discard_changes;
213
    $debit_2->discard_changes;
212
    is( $debit_2->amountoutstanding * 1, 10, 'Outstanding amount decremented correctly' );
214
    is( $debit_2->amountoutstanding * 1, 10, 'Outstanding amount decremented correctly' );
213
215
216
    $offsets = Koha::Account::Offsets->search( { credit_id => $credit->id, debit_id => $debit_2->id } );
217
    is( $offsets->count, 1, 'Only one offset is generated' );
218
    $THE_offset = $offsets->next;
219
    is( $THE_offset->amount * 1, 90, 'Amount was calculated correctly (less than the available credit)' );
220
    is( $THE_offset->type, 'credit_applied', 'Defaults to credit_applied offset type' );
221
222
    $debits = Koha::Account::Lines->search({ accountlines_id => $debit_1->id });
223
    throws_ok
224
        { $credit->apply({ debits => $debits }); }
225
        'Koha::Exceptions::Account::NoAvailableCredit',
226
        '->apply() can only be used with outstanding credits';
227
228
    $debits = Koha::Account::Lines->search({ accountlines_id => $credit->id });
214
    throws_ok
229
    throws_ok
215
        { $debit_1->apply({ debit => $credit }); }
230
        { $debit_1->apply({ debits => $debits }); }
216
        'Koha::Exceptions::Account::IsNotCredit',
231
        'Koha::Exceptions::Account::IsNotCredit',
217
        '->apply() can only be used with credits';
232
        '->apply() can only be used with credits';
218
233
234
    $debits = Koha::Account::Lines->search({ accountlines_id => $credit->id });
235
    my $credit_3 = $account->add_credit({ amount => 1 });
219
    throws_ok
236
    throws_ok
220
        { $credit->apply({ debit => $credit }); }
237
        { $credit_3->apply({ debits => $debits }); }
221
        'Koha::Exceptions::Account::IsNotDebit',
238
        'Koha::Exceptions::Account::IsNotDebit',
222
        '->apply() can only be applied to credits';
239
        '->apply() can only be applied to credits';
223
240
224
    throws_ok
241
    my $credit_2 = $account->add_credit({ amount => 20 });
225
        { $credit->apply({ debit => $debit_1 }); }
242
    my $debit_3  = Koha::Account::Line->new(
226
        'Koha::Exceptions::Account::NoAvailableCredit',
243
        {   borrowernumber    => $patron->id,
227
        '->apply() can only be used with outstanding credits';
244
            accounttype       => "F",
245
            amount            => 100,
246
            amountoutstanding => 100
247
        }
248
    )->store;
249
250
    $debits = Koha::Account::Lines->search({ accountlines_id => { -in => [ $debit_1->id, $debit_2->id, $debit_3->id, $credit->id ] } });
251
    throws_ok {
252
        $credit_2->apply( { debits => $debits, offset_type => 'Manual Credit' } ); }
253
        'Koha::Exceptions::Account::IsNotDebit',
254
        '->apply() rolls back if any of the passed lines is not a debit';
255
256
    is( $debit_1->discard_changes->amountoutstanding * 1,   0, 'No changes to already cancelled debit' );
257
    is( $debit_2->discard_changes->amountoutstanding * 1,  10, 'Debit cancelled' );
258
    is( $debit_3->discard_changes->amountoutstanding * 1, 100, 'Outstanding amount correctly calculated' );
259
    is( $credit_2->discard_changes->amountoutstanding * -1, 20, 'No changes made' );
260
261
    $debits = Koha::Account::Lines->search({ accountlines_id => { -in => [ $debit_1->id, $debit_2->id, $debit_3->id ] } });
262
    $remaining_credit = $credit_2->apply( { debits => $debits, offset_type => 'Manual Credit' } );
228
263
264
    is( $debit_1->discard_changes->amountoutstanding * 1,  0, 'No changes to already cancelled debit' );
265
    is( $debit_2->discard_changes->amountoutstanding * 1,  0, 'Debit cancelled' );
266
    is( $debit_3->discard_changes->amountoutstanding * 1, 90, 'Outstanding amount correctly calculated' );
267
    is( $credit_2->discard_changes->amountoutstanding * 1, 0, 'No remaining credit' );
229
268
230
    $schema->storage->txn_rollback;
269
    $schema->storage->txn_rollback;
231
};
270
};
232
- 

Return to bug 20997