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

(-)a/Koha/Account/Line.pm (-33 / +104 lines)
Lines 172-178 sub debit_offsets { Link Here
172
172
173
Return the credits linked to this account line if some exist.
173
Return the credits linked to this account line if some exist.
174
Search conditions and attributes may be passed if you wish to filter
174
Search conditions and attributes may be passed if you wish to filter
175
the resultant resultant resultset.
175
the resultant resultset.
176
176
177
=cut
177
=cut
178
178
Lines 200-206 sub credits { Link Here
200
200
201
Return the debits linked to this account line if some exist.
201
Return the debits linked to this account line if some exist.
202
Search conditions and attributes may be passed if you wish to filter
202
Search conditions and attributes may be passed if you wish to filter
203
the resultant resultant resultset.
203
the resultant resultset.
204
204
205
=cut
205
=cut
206
206
Lines 362-374 sub void { Link Here
362
362
363
=head3 cancel
363
=head3 cancel
364
364
365
  $debit_accountline->cancel({ cancellation_type => $type });
365
  $debit_accountline->cancel();
366
366
367
Cancel a charge. It will mark the debit as 'cancelled' by updating its
367
Cancel a charge. It will mark the debit as 'cancelled' by updating its
368
status to 'CANCELLED'.
368
status to 'CANCELLED'.
369
369
370
Charges that have been fully or partially paid will be refunded upto
370
Charges that have been fully or partially offset will be refunded upto
371
the amount paid excluding discounts, writeoffs and refunds.
371
the amount paid excluding discounts, writeoffs and prior refunds.
372
372
373
Returns the cancellation accountline.
373
Returns the cancellation accountline.
374
374
Lines 393-414 sub cancel { Link Here
393
            error => 'Account line ' . $self->id . 'is already cancelled' );
393
            error => 'Account line ' . $self->id . 'is already cancelled' );
394
    }
394
    }
395
395
396
    my $cancellation_type = $params->{cancellation_type} // 'CANCELLATION';
396
    my $cancellation_amount = $self->amount;
397
397
    my @applied_offsets;
398
    my $cancellation_amount = $self->amountoutstanding;
399
    if ( $self->amount != $self->amountoutstanding ) {
398
    if ( $self->amount != $self->amountoutstanding ) {
400
        my $credit_offsets = Koha::Account::Offsets->search(
399
        # Reductions are 'Writeoff', 'Refund' or 'Discount' lines applied against the debt already.
400
        # We can ignore 'VOID' status as it will be accounted for in the offsets total
401
        my $reduction_offsets = Koha::Account::Offsets->search(
401
            {
402
            {
402
                debit_id  => $self->id,
403
                debit_id                  => $self->id,
403
                credit_id => { '!=' => undef },    # not the debt itself
404
                credit_id                 => { '!=' => undef },
404
                type      => { '!=' => [ 'Writeoff', 'REFUND', 'DISCOUNT' ] }
405
                'credit.credit_type_code' =>
405
                ,    # Don't refund writeoffs, refunds or discounts
406
                  [ 'WRITEOFF', 'REFUND', 'DISCOUNT' ],
406
                amount => { '<' => 0 }    # credits are negative on the DB
407
            },
408
            {
409
                join => 'credit'
407
            }
410
            }
408
        );
411
        );
409
412
410
        $cancellation_amount +=
413
        $cancellation_amount +=
411
          $credit_offsets->count > 0 ? $credit_offsets->total * -1 : 0;
414
          $reduction_offsets->count > 0 ? $reduction_offsets->total : 0;
415
416
        # Payments are any credits applied (and not subsequently voided) that are 
417
        # not 'Writeoff', 'Refund' or 'Discount'
418
        @applied_offsets = Koha::Account::Offsets->search(
419
            {
420
                debit_id                  => $self->id,
421
                credit_id                 => { '!=' => undef },
422
                'credit.credit_type_code' => [
423
                    '-and' => { '!=' => 'WRITEOFF' },
424
                    { '!=' => 'REFUND' }, { '!=' => 'DISCOUNT' }
425
                ],
426
                'credit.status' => [ { '!=' => 'VOID' }, undef ],
427
                'me.amount'     => { '<' => 0 }
428
            },
429
            {
430
                join => 'credit'
431
            }
432
        );
412
    }
433
    }
413
434
414
    my $cancellation;
435
    my $cancellation;
Lines 416-430 sub cancel { Link Here
416
        sub {
437
        sub {
417
438
418
            # A 'cancellation' is a 'credit'
439
            # A 'cancellation' is a 'credit'
419
            $cancellation = $self->reduce(
440
            $cancellation = Koha::Account::Line->new(
441
                {
442
                    date              => \'NOW()',
443
                    amount            => 0 - $cancellation_amount,
444
                    credit_type_code  => 'CANCELLATION',
445
                    status            => 'ADDED',
446
                    amountoutstanding => 0 - $cancellation_amount,
447
                    manager_id        => $params->{staff_id},
448
                    borrowernumber    => $self->borrowernumber,
449
                    interface         => 'intranet',
450
                    branchcode        => $params->{branch},
451
                }
452
            )->store();
453
454
            Koha::Account::Offset->new(
420
                {
455
                {
421
                    reduction_type => $cancellation_type,
456
                    credit_id => $cancellation->accountlines_id,
422
                    amount         => $cancellation_amount,
457
                    type      => 'CREATE',
423
                    staff_id       => $params->{staff_id},
458
                    amount    => $cancellation_amount
424
                    interface      => $params->{interface},
425
                    branch         => $params->{branch}
426
                }
459
                }
427
            );
460
            )->store();
461
462
            # Link cancellation to charge
463
            $self->set(
464
                {
465
                    amountoutstanding => $cancellation_amount,
466
                    status            => 'CANCELLED'
467
                }
468
            )->store();
469
            $cancellation->apply( { debits => [$self] } );
470
471
            # Reverse any applied payments
472
            for my $applied_offset ( @applied_offsets ) {
473
                my $credit = $applied_offset->credit;
474
                $credit->amountoutstanding(
475
                    $credit->amountoutstanding - $applied_offset->amount )
476
                  ->store();
477
                
478
                Koha::Account::Offset->new(
479
                    {
480
                        credit_id => $applied_offset->credit_id,
481
                        debit_id  => $self->id,
482
                        amount    => $applied_offset->amount * -1,
483
                        type      => 'VOID',
484
                    }
485
                )->store();
486
            }
428
        }
487
        }
429
    );
488
    );
430
489
Lines 454-460 Reduction type may be one of: Link Here
454
513
455
* REFUND
514
* REFUND
456
* DISCOUNT
515
* DISCOUNT
457
* CANCELLATION
458
516
459
Returns the reduction accountline (which will be a credit)
517
Returns the reduction accountline (which will be a credit)
460
518
Lines 482-487 sub reduce { Link Here
482
        }
540
        }
483
    }
541
    }
484
542
543
    # Amount should always be passed as positive
544
    Koha::Exceptions::Account::AmountNotPositive->throw(
545
        error => 'Reduce amount passed is not positive' )
546
      unless ( $params->{amount} > 0 );
547
485
    # More mandatory parameters
548
    # More mandatory parameters
486
    if ( $params->{interface} eq 'intranet' ) {
549
    if ( $params->{interface} eq 'intranet' ) {
487
        my @optional = ( 'staff_id', 'branch' );
550
        my @optional = ( 'staff_id', 'branch' );
Lines 496-520 sub reduce { Link Here
496
559
497
    # Make sure the reduction isn't more than the original
560
    # Make sure the reduction isn't more than the original
498
    my $original = $self->amount;
561
    my $original = $self->amount;
499
    Koha::Exceptions::Account::AmountNotPositive->throw(
500
        error => 'Reduce amount passed is not positive' )
501
      unless ( $params->{amount} > 0 );
502
    Koha::Exceptions::ParameterTooHigh->throw( error =>
562
    Koha::Exceptions::ParameterTooHigh->throw( error =>
503
"Amount to reduce ($params->{amount}) is higher than original amount ($original)"
563
"Amount to reduce ($params->{amount}) is higher than original amount ($original)"
504
    ) unless ( $original >= $params->{amount} );
564
    ) unless ( $original >= $params->{amount} );
505
    my $reduced =
565
506
      $self->credits( { credit_type_code => [ 'WRITEOFF', 'DISCOUNT', 'REFUND' ] } )->total;
566
    # Make sure combined reduction isn't more than the original
567
    my $reduced = 0;
568
    if ( $self->amount != $self->amountoutstanding ) {
569
        my $reduction_offsets = Koha::Account::Offsets->search(
570
            {
571
                debit_id  => $self->id,
572
                credit_id => { '!=' => undef },    # not the debt itself
573
                type      => { '!=' => [ 'Writeoff', 'REFUND', 'DISCOUNT' ] }
574
                ,    # Don't refund writeoffs, refunds or discounts
575
                amount => { '<' => 0 }    # credits are negative on the DB
576
            }
577
        );
578
579
        $reduced = $reduction_offsets->count > 0 ? $reduction_offsets->total * -1 : 0;
580
    }
581
507
    Koha::Exceptions::ParameterTooHigh->throw( error =>
582
    Koha::Exceptions::ParameterTooHigh->throw( error =>
508
"Combined reduction ($params->{amount} + $reduced) is higher than original amount ("
583
"Combined reduction ($params->{amount} + $reduced) is higher than original amount ("
509
          . abs($original)
584
          . abs($original)
510
          . ")" )
585
          . ")" )
511
      unless ( $original >= ( $params->{amount} + abs($reduced) ) );
586
      unless ( $original >= ( $params->{amount} + abs($reduced) ) );
512
587
513
    my $status = {
588
    my $status = { 'REFUND' => 'REFUNDED', 'DISCOUNT' => 'DISCOUNTED' };
514
        'REFUND'       => 'REFUNDED',
515
        'DISCOUNT'     => 'DISCOUNTED',
516
        'CANCELLATION' => 'CANCELLED'
517
    };
518
589
519
    my $reduction;
590
    my $reduction;
520
    $self->_result->result_source->schema->txn_do(
591
    $self->_result->result_source->schema->txn_do(
(-)a/Koha/Account/Offsets.pm (-1 / +44 lines)
Lines 61-66 sub total { Link Here
61
      : 0;
61
      : 0;
62
}
62
}
63
63
64
65
=head3
66
67
=cut
68
69
sub filter_by_non_reversable {
70
    my ($self) = @_;
71
72
    my $me = $self->_resultset()->current_source_alias . ".";
73
    my $where = {
74
        debit_id                  => { '!=' => undef },
75
        credit_id                 => { '!=' => undef },
76
        'credit.credit_type_code' => [ 'WRITEOFF', 'REFUND', 'DISCOUNT' ],
77
        'credit.status'           => [ { '!=' => 'VOID' }, undef ],
78
        $me.amount                    => { '<' => 0 }
79
    };
80
    my $attr = { join => 'credit' };
81
82
    return $self->search( $where, $attr );
83
}
84
85
=head3
86
87
=cut
88
89
sub filter_by_reversable {
90
    my ($self) = @_;
91
92
    my $me = $self->_resultset()->current_source_alias . ".";
93
    my $where = {
94
        debit_id                  => { '!=' => undef },
95
        credit_id                 => { '!=' => undef },
96
        'credit.credit_type_code' => [
97
            '-and' => { '!=' => 'WRITEOFF' },
98
            { '!=' => 'REFUND' }, { '!=' => 'DISCOUNT' }
99
        ],
100
        'credit.status' => [ { '!=' => 'VOID' }, undef ],
101
        $me.amount          => { '<' => 0 }
102
    };
103
    my $attr = { join => 'credit' };
104
105
    return $self->search( $where, $attr );
106
}
107
64
=head2 Internal methods
108
=head2 Internal methods
65
109
66
=head3 _type
110
=head3 _type
67
- 

Return to bug 28656