[
https://issues.apache.org/jira/browse/FINERACT-2990?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Sonigra Bhavya Hemendrabhai updated FINERACT-2990:
--------------------------------------------------
Description:
h3. Summary
HeavensFamilyLoanRepaymentScheduleTransactionProcessor.handleTransactionThatIsPaymentInAdvanceOfInstallment(),
an early/advance repayment calculates the principal paid on an installment,
but an accidental duplicate call to payPrincipalComponent() immediately
overwrites principalPortion with 0.
As a result, the transaction is saved without any
LoanTransactionToRepaymentScheduleMapping entries, corrupting the link between
the repayment transaction and the installment schedule.
h3. Root Cause
In HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java:
1. Lines 129–130:
{code:java}
if (currentInstallment.isPrincipalNotCompleted(currency)) {
principalPortion =
currentInstallment.payPrincipalComponent(transactionDate,
transactionAmountRemaining);
...
transactionAmountRemaining =
transactionAmountRemaining.minus(principalPortion);
}
{code}
principalPortion is calculated (e.g. $100), and transactionAmountRemaining is
decremented (e.g. to $0).
2. Lines 142–144:
{code:java}
// 1. pay of principal with over payment.
principalPortion = currentInstallment.payPrincipalComponent(transactionDate,
transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion);
{code}
Because transactionAmountRemaining is 0 (and the installment principal was
already paid), currentInstallment.payPrincipalComponent(...) returns 0. This
overwrites principalPortion from $100 to $0.
3. Lines 157–160:
{code:java}
if
(principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero())
{
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(...));
}
{code}
Because principalPortion was clobbered to 0, this condition evaluates to false,
and no LoanTransactionToRepaymentScheduleMapping is created.
Additionally, line 137 calls loanTransaction.updateComponents(...) inside the
if block, and line 156 calls loanTransaction.updateComponents(...) again
unconditionally at the end of the method.
h3. Expected Behavior
* principalPortion should not be overwritten.
* LoanTransactionToRepaymentScheduleMapping should be created linking the
advance repayment transaction to the paid installment with the proper principal
amount.
* loanTransaction.updateComponents(...) should only be called once at the end
of the method.
h3. Proposed Fix
1. Remove lines 142–144 (the duplicate principal payoff lines).
2. Remove line 137 so updateComponents is called only once at the end of the
method (line 156), mirroring the fix in FINERACT-2861.
3. Add a unit test in
HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest verifying that an
in-advance repayment populates repayment.getPrincipalPortion() and creates the
schedule mapping.
was:
h3. Summary
In
HeavensFamilyLoanRepaymentScheduleTransactionProcessor.handleTransactionThatIsPaymentInAdvanceOfInstallment(),
an early/advance repayment calculates the principal paid on an installment,
but an accidental duplicate call to payPrincipalComponent() immediately
overwrites principalPortion with 0.
As a result, the transaction is saved without any
LoanTransactionToRepaymentScheduleMapping entries, corrupting the link between
the repayment transaction and the installment schedule.
h3. Root Cause
In HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java:
1. Lines 129–130:
{code:java}
if (currentInstallment.isPrincipalNotCompleted(currency)) {
principalPortion =
currentInstallment.payPrincipalComponent(transactionDate,
transactionAmountRemaining);
...
transactionAmountRemaining =
transactionAmountRemaining.minus(principalPortion);
}
{code}
principalPortion is calculated (e.g. $100), and transactionAmountRemaining is
decremented (e.g. to $0).
2. Lines 142–144:
{code:java}
// 1. pay of principal with over payment.
principalPortion = currentInstallment.payPrincipalComponent(transactionDate,
transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion);
{code}
Because transactionAmountRemaining is 0 (and the installment principal was
already paid), currentInstallment.payPrincipalComponent(...) returns 0. This
overwrites principalPortion from $100 to $0.
3. Lines 157–160:
{code:java}
if
(principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero())
{
transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(...));
}
{code}
Because principalPortion was clobbered to 0, this condition evaluates to false,
and no LoanTransactionToRepaymentScheduleMapping is created.
Additionally, line 137 calls loanTransaction.updateComponents(...) inside the
if block, and line 156 calls loanTransaction.updateComponents(...) again
unconditionally at the end of the method.
h3. Expected Behavior
* principalPortion should not be overwritten.
* LoanTransactionToRepaymentScheduleMapping should be created linking the
advance repayment transaction to the paid installment with the proper principal
amount.
* loanTransaction.updateComponents(...) should only be called once at the end
of the method.
h3. Proposed Fix
1. Remove lines 142–144 (the duplicate principal payoff lines).
2. Remove line 137 so updateComponents is called only once at the end of the
method (line 156), mirroring the fix in FINERACT-2861.
3. Add a unit test in
HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest verifying that an
in-advance repayment populates repayment.getPrincipalPortion() and creates the
schedule mapping.
> HeavensFamily: Advance repayment clobbers principalPortion and skips schedule
> mapping creation
> ----------------------------------------------------------------------------------------------
>
> Key: FINERACT-2990
> URL: https://issues.apache.org/jira/browse/FINERACT-2990
> Project: Apache Fineract
> Issue Type: Bug
> Components: Loan
> Affects Versions: 1.16.0
> Reporter: Sonigra Bhavya Hemendrabhai
> Assignee: Sonigra Bhavya Hemendrabhai
> Priority: Major
> Labels: loan, repayment
>
> h3. Summary
> HeavensFamilyLoanRepaymentScheduleTransactionProcessor.handleTransactionThatIsPaymentInAdvanceOfInstallment(),
> an early/advance repayment calculates the principal paid on an installment,
> but an accidental duplicate call to payPrincipalComponent() immediately
> overwrites principalPortion with 0.
> As a result, the transaction is saved without any
> LoanTransactionToRepaymentScheduleMapping entries, corrupting the link
> between the repayment transaction and the installment schedule.
> h3. Root Cause
> In HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java:
> 1. Lines 129–130:
> {code:java}
> if (currentInstallment.isPrincipalNotCompleted(currency)) {
> principalPortion =
> currentInstallment.payPrincipalComponent(transactionDate,
> transactionAmountRemaining);
> ...
> transactionAmountRemaining =
> transactionAmountRemaining.minus(principalPortion);
> }
> {code}
> principalPortion is calculated (e.g. $100), and transactionAmountRemaining is
> decremented (e.g. to $0).
> 2. Lines 142–144:
> {code:java}
> // 1. pay of principal with over payment.
> principalPortion = currentInstallment.payPrincipalComponent(transactionDate,
> transactionAmountRemaining);
> transactionAmountRemaining =
> transactionAmountRemaining.minus(principalPortion);
> {code}
> Because transactionAmountRemaining is 0 (and the installment principal was
> already paid), currentInstallment.payPrincipalComponent(...) returns 0. This
> overwrites principalPortion from $100 to $0.
> 3. Lines 157–160:
> {code:java}
> if
> (principalPortion.plus(interestPortion).plus(feeChargesPortion).plus(penaltyChargesPortion).isGreaterThanZero())
> {
>
> transactionMappings.add(LoanTransactionToRepaymentScheduleMapping.createFrom(...));
> }
> {code}
> Because principalPortion was clobbered to 0, this condition evaluates to
> false, and no LoanTransactionToRepaymentScheduleMapping is created.
> Additionally, line 137 calls loanTransaction.updateComponents(...) inside the
> if block, and line 156 calls loanTransaction.updateComponents(...) again
> unconditionally at the end of the method.
> h3. Expected Behavior
> * principalPortion should not be overwritten.
> * LoanTransactionToRepaymentScheduleMapping should be created linking the
> advance repayment transaction to the paid installment with the proper
> principal amount.
> * loanTransaction.updateComponents(...) should only be called once at the
> end of the method.
> h3. Proposed Fix
> 1. Remove lines 142–144 (the duplicate principal payoff lines).
> 2. Remove line 137 so updateComponents is called only once at the end of the
> method (line 156), mirroring the fix in FINERACT-2861.
> 3. Add a unit test in
> HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest verifying that an
> in-advance repayment populates repayment.getPrincipalPortion() and creates
> the schedule mapping.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)