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( |