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