adamsaghy commented on code in PR #4294:
URL: https://github.com/apache/fineract/pull/4294#discussion_r1949788640
##########
fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java:
##########
@@ -413,16 +415,119 @@ protected LoanTransaction
findChargebackOriginalTransaction(LoanTransaction char
Long toId = chargebackId;
// if the original transaction is not in the ctx, then it means that
it has not changed during reverse replay
Optional<LoanTransaction> fromTransaction =
chargebackTransaction.getLoan().getLoanTransactions().stream()
- .filter(tr ->
tr.getLoanTransactionRelations().stream().anyMatch(this.hasMatchingToLoanTransaction(toId,
CHARGEBACK)))
+ .filter(tr ->
tr.getLoanTransactionRelations().stream().anyMatch(this.hasMatchingToLoanTransaction(toId,
CHARGEBACK))
+ || tr.getLoanTransactionRelations().stream()
+
.anyMatch(this.hasMatchingToLoanTransaction(chargebackTransaction, CHARGEBACK)))
.findFirst();
if (fromTransaction.isEmpty()) {
throw new RuntimeException("Chargeback transaction must have an
original transaction");
}
return fromTransaction.get();
}
- protected void processCreditTransaction(LoanTransaction loanTransaction,
TransactionCtx ctx) {
+ private Map<AllocationType, Money>
calculateChargebackAllocationMapPrincipalOnly(Money transactionAmount,
MonetaryCurrency currency) {
+ Map<AllocationType, Money> chargebackAllocation = new HashMap<>();
+ chargebackAllocation.put(PRINCIPAL, transactionAmount);
+ chargebackAllocation.put(INTEREST, Money.zero(currency));
+ chargebackAllocation.put(PENALTY, Money.zero(currency));
+ chargebackAllocation.put(FEE, Money.zero(currency));
+ return chargebackAllocation;
+ }
+
+ protected void processCreditTransactionWithEmiCalculator(LoanTransaction
loanTransaction, ProgressiveTransactionCtx ctx) {
+
+ ProgressiveLoanInterestScheduleModel model = ctx.getModel();
+ MonetaryCurrency currency = ctx.getCurrency();
+ loanTransaction.resetDerivedComponents();
+ Money transactionAmount = loanTransaction.getAmount(currency);
+ Money totalOverpaid = ctx.getOverpaymentHolder().getMoneyObject();
+ loanTransaction.setOverPayments(totalOverpaid);
+ if (!transactionAmount.isGreaterThanZero()) {
+ return;
+ }
+ if (!loanTransaction.isChargeback()) {
+ throw new RuntimeException("Unsupported transaction " +
loanTransaction.getTypeOf().name());
+ }
+ Map<AllocationType, Money> chargebackAllocation;
+
if (hasNoCustomCreditAllocationRule(loanTransaction)) {
+ // whole amount should allocate as principal no need to check
previous chargebacks.
+ chargebackAllocation =
calculateChargebackAllocationMapPrincipalOnly(transactionAmount, currency);
+ } else {
+ chargebackAllocation =
calculateChargebackAllocationMapByCreditAllocationRule(loanTransaction, ctx);
+ }
+
+ loanTransaction.updateComponents(chargebackAllocation.get(PRINCIPAL),
chargebackAllocation.get(INTEREST),
+ chargebackAllocation.get(FEE),
chargebackAllocation.get(PENALTY));
+
+ LocalDate lastInstallmentDueDate = model.getMaturityDate();
+ if
(!loanTransaction.getTransactionDate().isAfter(lastInstallmentDueDate)) {
+ if (chargebackAllocation.get(PRINCIPAL).isGreaterThanZero()) {
+ emiCalculator.chargebackPrincipal(model,
loanTransaction.getTransactionDate(), chargebackAllocation.get(PRINCIPAL));
+ }
+
+ // interest
+ if (chargebackAllocation.get(INTEREST).isGreaterThanZero()) {
+ emiCalculator.chargebackInterest(model,
loanTransaction.getTransactionDate(), chargebackAllocation.get(INTEREST));
+ }
+ // update repayment periods until maturity date, for principal and
interest portions
+ updateRepaymentPeriods(loanTransaction, ctx);
+
+ LoanRepaymentScheduleInstallment instalment =
lastInstallmentDueDate.isEqual(loanTransaction.getDateOf())
+ ? ctx.getInstallments().stream().filter(i ->
i.getDueDate().isEqual(loanTransaction.getDateOf())).findAny()
+ .orElseThrow()
+ : ctx.getInstallments().stream().filter(i ->
!loanTransaction.getTransactionDate().isBefore(i.getFromDate())
+ &&
i.getDueDate().isAfter(loanTransaction.getTransactionDate())).findAny().orElseThrow();
+ // special because principal and interest dues are already updated.
+ recognizeAmountsAfterChargebackWithInterestRecalculation(ctx,
instalment, chargebackAllocation);
+ } else {
+ // N+1
+ LoanRepaymentScheduleInstallment instalment =
ctx.getInstallments().stream()
+
.filter(LoanRepaymentScheduleInstallment::isAdditional).findAny()
+ .or(() -> createAdditionalInstalment(loanTransaction,
ctx)).orElseThrow();
+ // generic
+ recognizeAmountsAfterChargeback(ctx,
loanTransaction.getTransactionDate(), instalment, chargebackAllocation);
+ if
(instalment.getDueDate().isBefore(loanTransaction.getTransactionDate())) {
+ instalment.updateDueDate(loanTransaction.getTransactionDate());
+ }
+ }
+
+ allocateOverpayment(loanTransaction, ctx);
+ }
+
+ private Optional<LoanRepaymentScheduleInstallment>
createAdditionalInstalment(LoanTransaction loanTransaction,
+ ProgressiveTransactionCtx ctx) {
+ LoanRepaymentScheduleInstallment installment = new
LoanRepaymentScheduleInstallment(loanTransaction.getLoan(),
+ (ctx.getInstallments().size() + 1),
ctx.getModel().getMaturityDate(), loanTransaction.getTransactionDate(), ZERO,
ZERO,
+ ZERO, ZERO, false, null);
+ installment.markAsAdditional();
+
loanTransaction.getLoan().addLoanRepaymentScheduleInstallment(installment);
+ return Optional.of(installment);
+ }
+
+ private Map<AllocationType, Money>
calculateChargebackAllocationMapByCreditAllocationRule(LoanTransaction
loanTransaction,
+ ProgressiveTransactionCtx ctx) {
+ MonetaryCurrency currency = ctx.getCurrency();
+ LoanTransaction originalTransaction =
findChargebackOriginalTransaction(loanTransaction, ctx);
+ // get the original allocation from the opriginal transaction
+ Map<AllocationType, Money> originalAllocationNotAdjusted =
getOriginalAllocation(originalTransaction, currency);
+ LoanCreditAllocationRule chargeBackAllocationRule =
getChargebackAllocationRules(loanTransaction);
+
+ // if there were earlier chargebacks then let's calculate the
remaining amounts for each portion
+ Map<AllocationType, Money> originalAllocation =
adjustOriginalAllocationWithFormerChargebacks(originalTransaction,
+ originalAllocationNotAdjusted, loanTransaction, ctx,
chargeBackAllocationRule);
+
+ // calculate the current chargeback allocation
+ return calculateChargebackAllocationMap(originalAllocation,
loanTransaction.getAmount(currency).getAmount(),
+ chargeBackAllocationRule.getAllocationTypes(), currency);
+ }
+
+ protected void processCreditTransaction(LoanTransaction loanTransaction,
TransactionCtx ctx) {
+ // TODO refactor if needed
+ if (loanTransaction.getLoan().isInterestBearing()
Review Comment:
You can use the `isInterestBearingAndInterestRecalculationEnabled` instead
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]