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

(-)a/Koha/Account/Line.pm (-14 / +74 lines)
Lines 210-216 sub debits { Link Here
210
210
211
=head3 void
211
=head3 void
212
212
213
  $payment_accountline->void();
213
  $payment_accountline->void({
214
      interface => $interface,
215
      [ staff_id => $staff_id, branch => $branchcode ]
216
  });
214
217
215
Used to 'void' (or reverse) a payment/credit. It will roll back any offsets
218
Used to 'void' (or reverse) a payment/credit. It will roll back any offsets
216
created by the application of this credit upon any debits and mark the credit
219
created by the application of this credit upon any debits and mark the credit
Lines 219-235 as 'void' by updating it's status to "VOID". Link Here
219
=cut
222
=cut
220
223
221
sub void {
224
sub void {
222
    my ($self) = @_;
225
    my ($self, $params) = @_;
226
227
    # Make sure it is a credit we are voiding
228
    unless ( $self->is_credit ) {
229
        Koha::Exceptions::Account::IsNotCredit->throw(
230
            error => 'Account line ' . $self->id . 'is not a credit' );
231
    }
223
232
224
    # Make sure it is a payment we are voiding
233
    # Make sure it is not already voided
225
    return unless $self->amount < 0;
234
    if ( $self->status && $self->status eq 'VOID' ) {
235
        Koha::Exceptions::Account->throw(
236
            error => 'Account line ' . $self->id . 'is already void' );
237
    }
238
239
    # Check for mandatory parameters
240
    my @mandatory = ( 'interface' );
241
    for my $param (@mandatory) {
242
        unless ( defined( $params->{$param} ) ) {
243
            Koha::Exceptions::MissingParameter->throw(
244
                error => "The $param parameter is mandatory" );
245
        }
246
    }
247
248
    # More mandatory parameters
249
    if ( $params->{interface} eq 'intranet' ) {
250
        my @optional = ( 'staff_id', 'branch' );
251
        for my $param (@optional) {
252
            unless ( defined( $params->{$param} ) ) {
253
                Koha::Exceptions::MissingParameter->throw( error =>
254
"The $param parameter is mandatory when interface is set to 'intranet'"
255
                );
256
            }
257
        }
258
    }
226
259
260
    # Find any applied offsets for the credit so we may reverse them
227
    my @account_offsets =
261
    my @account_offsets =
228
      Koha::Account::Offsets->search(
262
      Koha::Account::Offsets->search(
229
        { credit_id => $self->id, amount => { '<' => 0 }  } );
263
        { credit_id => $self->id, amount => { '<' => 0 }  } );
230
264
265
    my $void;
231
    $self->_result->result_source->schema->txn_do(
266
    $self->_result->result_source->schema->txn_do(
232
        sub {
267
        sub {
268
269
            # A 'void' is a 'debit'
270
            $void = Koha::Account::Line->new(
271
                {
272
                    borrowernumber    => $self->borrowernumber,
273
                    date              => \'NOW()',
274
                    debit_type_code   => 'VOID',
275
                    amount            => $self->amount * -1,
276
                    amountoutstanding => $self->amount * -1,
277
                    manager_id        => $params->{staff_id},
278
                    interface         => $params->{interface},
279
                    branchcode        => $params->{branch},
280
                }
281
            )->store();
282
283
            # Record the creation offset
284
            Koha::Account::Offset->new(
285
                {
286
                    debit_id => $void->id,
287
                    type     => 'VOID',
288
                    amount   => $self->amount * -1
289
                }
290
            )->store();
291
292
            # Reverse any applied payments
233
            foreach my $account_offset (@account_offsets) {
293
            foreach my $account_offset (@account_offsets) {
234
                my $fee_paid =
294
                my $fee_paid =
235
                  Koha::Account::Lines->find( $account_offset->debit_id );
295
                  Koha::Account::Lines->find( $account_offset->debit_id );
Lines 246-256 sub void { Link Here
246
                        credit_id => $self->id,
306
                        credit_id => $self->id,
247
                        debit_id  => $fee_paid->id,
307
                        debit_id  => $fee_paid->id,
248
                        amount    => $amount_paid,
308
                        amount    => $amount_paid,
249
                        type      => 'Void Payment',
309
                        type      => 'VOID',
250
                    }
310
                    }
251
                )->store();
311
                )->store();
252
            }
312
            }
253
313
314
            # Link void to payment
315
            $self->set({
316
                amountoutstanding => $self->amount,
317
                status => 'VOID'
318
            })->store();
319
            $self->apply({ debits => [$void]});
320
254
            if ( C4::Context->preference("FinesLog") ) {
321
            if ( C4::Context->preference("FinesLog") ) {
255
                logaction(
322
                logaction(
256
                    "FINES", 'VOID',
323
                    "FINES", 'VOID',
Lines 273-290 sub void { Link Here
273
                    )
340
                    )
274
                );
341
                );
275
            }
342
            }
276
277
            $self->set(
278
                {
279
                    status            => 'VOID',
280
                    amountoutstanding => 0,
281
                    amount            => 0,
282
                }
283
            );
284
            $self->store();
285
        }
343
        }
286
    );
344
    );
287
345
346
    $void->discard_changes;
347
    return $void;
288
}
348
}
289
349
290
=head3 cancel
350
=head3 cancel
(-)a/Koha/Item.pm (-1 / +1 lines)
Lines 1056-1062 sub _set_found_trigger { Link Here
1056
1056
1057
                    if ( $refund ) {
1057
                    if ( $refund ) {
1058
                        # Revert the forgive credit
1058
                        # Revert the forgive credit
1059
                        $refund->void();
1059
                        $refund->void({ interface => 'trigger' });
1060
                        $self->{_restored} = 1;
1060
                        $self->{_restored} = 1;
1061
                    }
1061
                    }
1062
1062
(-)a/installer/data/mysql/atomicupdate/bug_27971.perl (+23 lines)
Line 0 Link Here
1
$DBversion = 'XXX'; # will be replaced by the RM
2
if( CheckVersion( $DBversion ) ) {
3
    $dbh->do(
4
        qq{
5
            INSERT IGNORE INTO account_debit_types (
6
              code,
7
              description,
8
              can_be_invoiced,
9
              can_be_sold,
10
              default_amount,
11
              is_system
12
            )
13
            VALUES
14
              ('VOID', 'Credit has been voided', 0, 0, NULL, 1)
15
        }
16
    );
17
18
    $dbh->do(q{
19
        INSERT IGNORE INTO account_offset_types ( type ) VALUES ('VOID');
20
    });
21
22
    NewVersion( $DBversion, 27971, "Add VOID debit type code");
23
}
(-)a/installer/data/mysql/mandatory/account_debit_types.sql (-1 / +2 lines)
Lines 12-15 INSERT INTO account_debit_types ( code, description, can_be_invoiced, can_be_sol Link Here
12
('RENT_RENEW', 'Renewal of rental item', 0, 0, NULL, 1),
12
('RENT_RENEW', 'Renewal of rental item', 0, 0, NULL, 1),
13
('RENT_DAILY_RENEW', 'Renewal of daily rental item', 0, 0, NULL, 1),
13
('RENT_DAILY_RENEW', 'Renewal of daily rental item', 0, 0, NULL, 1),
14
('RESERVE', 'Hold fee', 0, 0, NULL, 1),
14
('RESERVE', 'Hold fee', 0, 0, NULL, 1),
15
('RESERVE_EXPIRED', 'Hold waiting too long', 0, 0, NULL, 1);
15
('RESERVE_EXPIRED', 'Hold waiting too long', 0, 0, NULL, 1),
16
('VOID', 'Credit has been voided', 0, 0, NULL, 1);
(-)a/installer/data/mysql/mandatory/account_offset_types.sql (-1 / +2 lines)
Lines 23-26 INSERT INTO account_offset_types ( type ) VALUES Link Here
23
('PAYOUT'),
23
('PAYOUT'),
24
('DISCOUNT'),
24
('DISCOUNT'),
25
('REFUND'),
25
('REFUND'),
26
('CANCELLATION');
26
('CANCELLATION'),
27
('VOID');
(-)a/members/boraccount.pl (-1 / +7 lines)
Lines 72-78 my $registerid = $input->param('registerid'); Link Here
72
if ( $action eq 'void' ) {
72
if ( $action eq 'void' ) {
73
    my $payment_id = scalar $input->param('accountlines_id');
73
    my $payment_id = scalar $input->param('accountlines_id');
74
    my $payment    = Koha::Account::Lines->find( $payment_id );
74
    my $payment    = Koha::Account::Lines->find( $payment_id );
75
    $payment->void();
75
    $payment->void(
76
        {
77
            branch    => $library_id,
78
            staff_id  => $logged_in_user->id,
79
            interface => 'intranet',
80
        }
81
    );
76
}
82
}
77
83
78
if ( $action eq 'payout' ) {
84
if ( $action eq 'payout' ) {
(-)a/t/db_dependent/Koha/Account/Line.t (-4 / +3 lines)
Lines 744-750 subtest "void() tests" => sub { Link Here
744
    is( $line1->amountoutstanding+0, 0, 'First fee has amount outstanding of 0' );
744
    is( $line1->amountoutstanding+0, 0, 'First fee has amount outstanding of 0' );
745
    is( $line2->amountoutstanding+0, 0, 'Second fee has amount outstanding of 0' );
745
    is( $line2->amountoutstanding+0, 0, 'Second fee has amount outstanding of 0' );
746
746
747
    my $ret = $account_payment->void();
747
    my $ret = $account_payment->void({ interface => 'test' });
748
748
749
    is( ref($ret), 'Koha::Account::Line', 'Void returns the account line' );
749
    is( ref($ret), 'Koha::Account::Line', 'Void returns the account line' );
750
    is( $account->balance(), 30, "Account balance is again 30" );
750
    is( $account->balance(), 30, "Account balance is again 30" );
Lines 755-761 subtest "void() tests" => sub { Link Here
755
755
756
    is( $account_payment->credit_type_code, 'PAYMENT', 'Voided payment credit_type_code is still PAYMENT' );
756
    is( $account_payment->credit_type_code, 'PAYMENT', 'Voided payment credit_type_code is still PAYMENT' );
757
    is( $account_payment->status, 'VOID', 'Voided payment status is VOID' );
757
    is( $account_payment->status, 'VOID', 'Voided payment status is VOID' );
758
    is( $account_payment->amount+0, 0, 'Voided payment amount is 0' );
758
    is( $account_payment->amount+0, -30, 'Voided payment amount is -30' );
759
    is( $account_payment->amountoutstanding+0, 0, 'Voided payment amount outstanding is 0' );
759
    is( $account_payment->amountoutstanding+0, 0, 'Voided payment amount outstanding is 0' );
760
760
761
    is( $line1->amountoutstanding+0, 10, 'First fee again has amount outstanding of 10' );
761
    is( $line1->amountoutstanding+0, 10, 'First fee again has amount outstanding of 10' );
Lines 763-769 subtest "void() tests" => sub { Link Here
763
763
764
    # Accountlines that are not credits should be un-voidable
764
    # Accountlines that are not credits should be un-voidable
765
    my $line1_pre = $line1->unblessed();
765
    my $line1_pre = $line1->unblessed();
766
    $ret = $line1->void();
766
    $ret = $line1->void({ interface => 'test' });
767
    $line1->_result->discard_changes();
767
    $line1->_result->discard_changes();
768
    my $line1_post = $line1->unblessed();
768
    my $line1_post = $line1->unblessed();
769
    is( $ret, undef, 'Attempted void on non-credit returns undef' );
769
    is( $ret, undef, 'Attempted void on non-credit returns undef' );
770
- 

Return to bug 27971