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

(-)a/Koha/Account.pm (+89 lines)
Lines 485-490 sub add_credit { Link Here
485
    return $line;
485
    return $line;
486
}
486
}
487
487
488
=head3 payin_amount
489
490
    my $credit = $account->payin_amount(
491
        {
492
            amount          => $amount,
493
            credit_type     => $credit_type,
494
            payment_type    => $payment_type,
495
            cash_register   => $register_id,
496
            interface       => $interface,
497
            library_id      => $branchcode,
498
            user_id         => $staff_id,
499
            debits          => $debit_lines,
500
            description     => $description,
501
            note            => $note
502
        }
503
    );
504
505
This method allows an amount to be paid into a patrons account and immediately applied against debts.
506
507
You can optionally pass a debts parameter which consists of an arrayref of Koha::Account::Line debit lines.
508
509
$credit_type can be any of:
510
  - 'PAYMENT'
511
  - 'WRITEOFF'
512
  - 'FORGIVEN'
513
514
=cut
515
516
sub payin_amount {
517
    my ( $self, $params ) = @_;
518
519
    # check for mandatory params
520
    my @mandatory = ( 'interface', 'amount', 'type' );
521
    for my $param (@mandatory) {
522
        unless ( defined( $params->{$param} ) ) {
523
            Koha::Exceptions::MissingParameter->throw(
524
                error => "The $param parameter is mandatory" );
525
        }
526
    }
527
528
    # Check for mandatory register
529
    Koha::Exceptions::Account::RegisterRequired->throw()
530
      if ( C4::Context->preference("UseCashRegisters")
531
        && defined( $params->{payment_type} )
532
        && ( $params->{payment_type} eq 'CASH' )
533
        && !defined($params->{cash_register}) );
534
535
    # amount should always be passed as a positive value
536
    my $amount = $params->{amount};
537
    unless ( $amount > 0 ) {
538
        Koha::Exceptions::Account::AmountNotPositive->throw(
539
            error => 'Payin amount passed is not positive' );
540
    }
541
542
    my $credit;
543
    my $schema = Koha::Database->new->schema;
544
    $schema->txn_do(
545
        sub {
546
547
            # Add payin credit
548
            $credit = $self->add_credit($params);
549
550
            # Offset debts passed first
551
            if ( exists( $params->{debits} ) ) {
552
                $credit = $credit->apply(
553
                    {
554
                        debits      => $params->{debits},
555
                        offset_type => $params->{type}
556
                    }
557
                );
558
            }
559
560
            # Offset against remaining balance if AutoReconcile
561
            if ( C4::Context->preference("AccountAutoReconcile")
562
                && $credit->amountoutstanding != 0 )
563
            {
564
                $credit = $credit->apply(
565
                    {
566
                        debits      => [ $self->outstanding_debits->as_list ],
567
                        offset_type => $params->{type}
568
                    }
569
                );
570
            }
571
        }
572
    );
573
574
    return $credit;
575
}
576
488
=head3 add_debit
577
=head3 add_debit
489
578
490
This method allows adding debits to a patron's account
579
This method allows adding debits to a patron's account
(-)a/t/db_dependent/Koha/Account.t (-2 / +128 lines)
Lines 19-25 Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::More tests => 14;
22
use Test::More tests => 15;
23
use Test::MockModule;
23
use Test::MockModule;
24
use Test::Exception;
24
use Test::Exception;
25
25
Lines 1303-1305 subtest 'Koha::Account::payout_amount() tests' => sub { Link Here
1303
1303
1304
    $schema->storage->txn_rollback;
1304
    $schema->storage->txn_rollback;
1305
};
1305
};
1306
- 
1306
1307
subtest 'Koha::Account::payin_amount() tests' => sub {
1308
    plan tests => 36;
1309
1310
    $schema->storage->txn_begin;
1311
1312
    # delete logs and statistics
1313
    my $action_logs = $schema->resultset('ActionLog')->search()->count;
1314
    my $statistics  = $schema->resultset('Statistic')->search()->count;
1315
1316
    my $staff = $builder->build_object( { class => 'Koha::Patrons' } );
1317
    my $library = $builder->build_object( { class => 'Koha::Libraries' } );
1318
    my $register =
1319
      $builder->build_object( { class => 'Koha::Cash::Registers' } );
1320
    my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
1321
    my $account =
1322
      Koha::Account->new( { patron_id => $patron->borrowernumber } );
1323
1324
    is( $account->balance, 0, 'Test patron has no balance' );
1325
1326
    my $payin_params = {
1327
        type  => 'PAYMENT',
1328
        payment_type => 'CASH',
1329
        branch       => $library->id,
1330
        register_id  => $register->id,
1331
        staff_id     => $staff->id,
1332
        interface    => 'intranet',
1333
        amount       => -10,
1334
    };
1335
1336
    my @required_fields =
1337
      ( 'interface', 'amount', 'type' );
1338
    for my $required_field (@required_fields) {
1339
        my $this_payin = { %{$payin_params} };
1340
        delete $this_payin->{$required_field};
1341
1342
        throws_ok {
1343
            $account->payin_amount($this_payin);
1344
        }
1345
        'Koha::Exceptions::MissingParameter',
1346
          "Exception thrown if $required_field parameter missing";
1347
    }
1348
1349
    throws_ok {
1350
        $account->payin_amount($payin_params);
1351
    }
1352
    'Koha::Exceptions::Account::AmountNotPositive',
1353
      'Expected validation exception thrown (amount not positive)';
1354
1355
    $payin_params->{amount} = 10;
1356
1357
    # Enable cash registers
1358
    t::lib::Mocks::mock_preference( 'UseCashRegisters', 1 );
1359
    throws_ok {
1360
        $account->payin_amount($payin_params);
1361
    }
1362
    'Koha::Exceptions::Account::RegisterRequired',
1363
'Exception thrown for UseCashRegisters:1 + payment_type:CASH + cash_register:undef';
1364
1365
    # Disable cash registers
1366
    t::lib::Mocks::mock_preference( 'UseCashRegisters', 0 );
1367
1368
    # Enable AccountAutoReconcile
1369
    t::lib::Mocks::mock_preference( 'AccountAutoReconcile', 1 );
1370
1371
    # Add some outstanding debits
1372
    my $debit_1 = $account->add_debit( { amount => 2,  interface => 'commandline', type => 'OVERDUE' } );
1373
    my $debit_2 = $account->add_debit( { amount => 3,  interface => 'commandline', type => 'OVERDUE' } );
1374
    my $debit_3 = $account->add_debit( { amount => 5,  interface => 'commandline', type => 'OVERDUE' } );
1375
    my $debit_4 = $account->add_debit( { amount => 10, interface => 'commandline', type => 'OVERDUE' } );
1376
    my $debits = $account->outstanding_debits();
1377
    is( $debits->count, 4, "Found 4 debits with outstanding amounts" );
1378
    is( $debits->total_outstanding + 0, 20, "Total 20 outstanding debit" );
1379
1380
    my $payin = $account->payin_amount($payin_params);
1381
    is(ref($payin), 'Koha::Account::Line', 'Return the Koha::Account::Line object for the payin');
1382
    is($payin->amount + 0, -10, "Payin amount recorded correctly");
1383
    is($payin->amountoutstanding + 0, 0, "Full amount was used to pay debts");
1384
    $debits = $account->outstanding_debits();
1385
    is($debits->count, 1, "Payin was applied against oldest outstanding debits first");
1386
    is($debits->total_outstanding + 0, 10, "Total of 10 outstanding debit remaining");
1387
1388
    my $offsets = Koha::Account::Offsets->search( { credit_id => $payin->id } );
1389
    is( $offsets->count, 4, 'Four offsets generated' );
1390
    my $offset = $offsets->next;
1391
    is( $offset->type, 'Payment', 'Payment offset added for payin line' );
1392
    is( $offset->amount * 1, -10, 'Correct offset amount recorded' );
1393
    $offset = $offsets->next;
1394
    is( $offset->debit_id, $debit_1->id, "Offset added against debit_1");
1395
    is( $offset->type,       'PAYMENT', "Payment used for offset_type" );
1396
    is( $offset->amount * 1, -2,      'Correct amount offset against debit_1' );
1397
    $offset = $offsets->next;
1398
    is( $offset->debit_id, $debit_2->id, "Offset added against debit_2");
1399
    is( $offset->type,       'PAYMENT', "Payment used for offset_type" );
1400
    is( $offset->amount * 1, -3,      'Correct amount offset against debit_2' );
1401
    $offset = $offsets->next;
1402
    is( $offset->debit_id, $debit_3->id, "Offset added against debit_3");
1403
    is( $offset->type,       'PAYMENT', "Payment used for offset_type" );
1404
    is( $offset->amount * 1, -5,      'Correct amount offset against debit_3' );
1405
1406
    my $debit_5 = $account->add_debit( { amount => 5, interface => 'commandline', type => 'OVERDUE' } );
1407
    $debits = $account->outstanding_debits();
1408
    is($debits->count, 2, "New debit added");
1409
    $payin_params->{amount} = 2.50;
1410
    $payin_params->{debits} = [$debit_5];
1411
    $payin = $account->payin_amount($payin_params);
1412
1413
    $debits = $account->outstanding_debits();
1414
    is($debits->count, 2, "Second debit not fully paid off");
1415
    is($debits->total_outstanding + 0, 12.50, "12.50 outstanding debit remaining");
1416
    $debit_4->discard_changes;
1417
    $debit_5->discard_changes;
1418
    is($debit_4->amountoutstanding + 0, 10, "Debit 4 unaffected when debit_5 was passed to payin_amount");
1419
    is($debit_5->amountoutstanding + 0, 2.50, "Debit 5 correctly reduced when payin_amount called with debit_5 passed");
1420
1421
    $offsets = Koha::Account::Offsets->search( { credit_id => $payin->id } );
1422
    is( $offsets->count, 2, 'Two offsets generated' );
1423
    $offset = $offsets->next;
1424
    is( $offset->type, 'Payment', 'Payment offset added for payin line' );
1425
    is( $offset->amount * 1, -2.50, 'Correct offset amount recorded' );
1426
    $offset = $offsets->next;
1427
    is( $offset->debit_id, $debit_5->id, "Offset added against debit_5");
1428
    is( $offset->type,       'PAYMENT', "PAYMENT used for offset_type" );
1429
    is( $offset->amount * 1, -2.50,      'Correct amount offset against debit_5' );
1430
1431
    $schema->storage->txn_rollback;
1432
};

Return to bug 27636