FINERACT-2326: Improve LoanTransactionData DTO structure

This commit is contained in:
Adam Saghy
2025-09-02 20:20:33 +02:00
committed by Arnold Gálovics
parent d06eb618d0
commit 937bfe529c
6 changed files with 703 additions and 351 deletions
@@ -316,7 +316,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
final List<LoanChargePaidByData> loanChargePaidByDatas = loanChargePaidByReadService
.fetchLoanChargesPaidByDataTransactionId(loanIds);
for (LoanTransactionData loanTransaction : loanTransactionData) {
loanTransaction.setLoanTransactionRelations(loanTransactionRelationDatas.stream().filter(
loanTransaction.setTransactionRelations(loanTransactionRelationDatas.stream().filter(
loanTransactionRelationData -> loanTransactionRelationData.getFromLoanTransaction().equals(loanTransaction.getId()))
.toList());
loanTransaction.setLoanChargePaidByList(loanChargePaidByDatas.stream()
@@ -580,11 +580,13 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
BigDecimal adjustedChargeAmount = adjustPrepayInstallmentCharge(loan, onDate);
BigDecimal totalAdjusted = outstandingAmounts.getTotalOutstanding().getAmount().subtract(adjustedChargeAmount);
return new LoanTransactionData(null, null, null, transactionType, null, currencyData, earliestUnpaidInstallmentDate, totalAdjusted,
loan.getNetDisbursalAmount(), outstandingAmounts.principal().getAmount(), outstandingAmounts.interest().getAmount(),
outstandingAmounts.feeCharges().getAmount().subtract(adjustedChargeAmount), outstandingAmounts.penaltyCharges().getAmount(),
null, unrecognizedIncomePortion, paymentOptions, ExternalId.empty(), null, null, outstandingLoanBalance, false, loanId,
loan.getExternalId());
return LoanTransactionData.builder().type(transactionType).currency(currencyData).date(earliestUnpaidInstallmentDate)
.amount(totalAdjusted).netDisbursalAmount(loan.getNetDisbursalAmount())
.principalPortion(outstandingAmounts.principal().getAmount()).interestPortion(outstandingAmounts.interest().getAmount())
.feeChargesPortion(outstandingAmounts.feeCharges().getAmount().subtract(adjustedChargeAmount))
.penaltyChargesPortion(outstandingAmounts.penaltyCharges().getAmount()).unrecognizedIncomePortion(unrecognizedIncomePortion)
.paymentTypeOptions(paymentOptions).externalId(ExternalId.empty()).outstandingLoanBalance(outstandingLoanBalance)
.manuallyReversed(false).loanId(loanId).externalLoanId(loan.getExternalId()).build();
}
private BigDecimal adjustPrepayInstallmentCharge(Loan loan, final LocalDate onDate) {
@@ -621,9 +623,10 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
final BigDecimal outstandingLoanBalance = null;
final BigDecimal unrecognizedIncomePortion = null;
return new LoanTransactionData(null, null, null, transactionType, null, currencyData, waiveOfInterest.getTransactionDate(), amount,
loan.getNetDisbursalAmount(), null, null, null, null, null, ExternalId.empty(), null, null, outstandingLoanBalance,
unrecognizedIncomePortion, false, loanId, loan.getExternalId());
return LoanTransactionData.builder().type(transactionType).currency(currencyData).date(waiveOfInterest.getTransactionDate())
.amount(amount).netDisbursalAmount(loan.getNetDisbursalAmount()).outstandingLoanBalance(outstandingLoanBalance)
.unrecognizedIncomePortion(unrecognizedIncomePortion).externalId(ExternalId.empty()).manuallyReversed(false).loanId(loanId)
.externalLoanId(loan.getExternalId()).build();
}
@Override
@@ -633,9 +636,9 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
final BigDecimal outstandingLoanBalance = null;
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(LoanTransactionType.WRITEOFF);
final BigDecimal unrecognizedIncomePortion = null;
return new LoanTransactionData(null, null, null, transactionType, null, null, DateUtils.getBusinessLocalDate(), null, null, null,
null, null, null, null, ExternalId.empty(), null, null, outstandingLoanBalance, unrecognizedIncomePortion, false, null,
null);
return LoanTransactionData.builder().type(transactionType).date(DateUtils.getBusinessLocalDate()).externalId(ExternalId.empty())
.outstandingLoanBalance(outstandingLoanBalance).unrecognizedIncomePortion(unrecognizedIncomePortion).manuallyReversed(false)
.build();
}
@@ -695,7 +698,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
final LoanTransactionsMapper rm = new LoanTransactionsMapper(sqlGenerator);
final String sql = "select " + rm.loanPaymentsSchema() + " where l.id = ? and tr.id = ? ";
LoanTransactionData loanTransactionData = this.jdbcTemplate.queryForObject(sql, rm, loanId, transactionId); // NOSONAR
loanTransactionData.setLoanTransactionRelations(
loanTransactionData.setTransactionRelations(
loanTransactionRelationReadService.fetchLoanTransactionRelationDataFrom(loanTransactionData.getId()));
return loanTransactionData;
} catch (final EmptyResultDataAccessException e) {
@@ -1749,10 +1752,14 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
toTransferDescription, toTransferReversed);
}
return new LoanTransactionData(id, officeId, officeName, transactionType, paymentDetailData, currencyData, date, totalAmount,
netDisbursalAmount, principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion, overPaymentPortion,
unrecognizedIncomePortion, externalId, transfer, null, outstandingLoanBalance, submittedOnDate, manuallyReversed,
reversalExternalId, reversedOnDate, loanId, externalLoanId);
return LoanTransactionData.builder().id(id).officeId(officeId).officeName(officeName).type(transactionType)
.paymentDetailData(paymentDetailData).currency(currencyData).date(date).amount(totalAmount)
.netDisbursalAmount(netDisbursalAmount).principalPortion(principalPortion).interestPortion(interestPortion)
.feeChargesPortion(feeChargesPortion).penaltyChargesPortion(penaltyChargesPortion)
.overpaymentPortion(overPaymentPortion).unrecognizedIncomePortion(unrecognizedIncomePortion).externalId(externalId)
.transfer(transfer).outstandingLoanBalance(outstandingLoanBalance).submittedOnDate(submittedOnDate)
.manuallyReversed(manuallyReversed).reversalExternalId(reversalExternalId).reversedOnDate(reversedOnDate).loanId(loanId)
.externalLoanId(externalLoanId).build();
}
}
@@ -2007,9 +2014,10 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
final Collection<PaymentTypeData> paymentOptions = this.paymentTypeReadPlatformService.retrieveAllPaymentTypes();
BigDecimal outstandingLoanBalance = null;
final BigDecimal unrecognizedIncomePortion = null;
return new LoanTransactionData(null, null, null, transactionType, null, null, null, loan.getTotalWrittenOff(),
loan.getNetDisbursalAmount(), null, null, null, null, null, unrecognizedIncomePortion, paymentOptions, ExternalId.empty(),
null, null, outstandingLoanBalance, false, loanId, loan.getExternalId());
return LoanTransactionData.builder().type(transactionType).amount(loan.getTotalWrittenOff())
.netDisbursalAmount(loan.getNetDisbursalAmount()).unrecognizedIncomePortion(unrecognizedIncomePortion)
.paymentTypeOptions(paymentOptions).externalId(ExternalId.empty()).outstandingLoanBalance(outstandingLoanBalance)
.manuallyReversed(false).loanId(loanId).externalLoanId(loan.getExternalId()).build();
}
@@ -2021,10 +2029,10 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
final BigDecimal totalOutstanding = loan.getSummary() != null ? loan.getSummary().getTotalOutstanding() : null;
final List<CodeValueData> writeOffReasonOptions = new ArrayList<>(
this.codeValueReadPlatformService.retrieveCodeValuesByCode(LoanApiConstants.WRITEOFFREASONS));
LoanTransactionData loanTransactionData = new LoanTransactionData(null, null, null, transactionType, null, loan.getCurrency(),
DateUtils.getBusinessLocalDate(), totalOutstanding, loan.getNetDisbursalAmount(), null, null, null, null, null,
ExternalId.empty(), null, null, null, null, false, loanId, loan.getExternalId());
loanTransactionData.setWriteOffReasonOptions(writeOffReasonOptions);
LoanTransactionData loanTransactionData = LoanTransactionData.builder().type(transactionType).currency(loan.getCurrency())
.date(DateUtils.getBusinessLocalDate()).amount(totalOutstanding).netDisbursalAmount(loan.getNetDisbursalAmount())
.externalId(ExternalId.empty()).manuallyReversed(false).loanId(loanId).externalLoanId(loan.getExternalId())
.writeOffReasonOptions(writeOffReasonOptions).build();
return loanTransactionData;
}
@@ -2040,11 +2048,12 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
final BigDecimal totalPenaltyOutstanding = loan.getSummary() != null ? loan.getSummary().getPenaltyChargesOutstanding() : null;
final List<CodeValueData> chargeOffReasonOptions = new ArrayList<>(
this.codeValueReadPlatformService.retrieveCodeValuesByCode(LoanApiConstants.CHARGE_OFF_REASONS));
LoanTransactionData loanTransactionData = new LoanTransactionData(null, null, null, transactionType, null, loan.getCurrency(),
DateUtils.getBusinessLocalDate(), totalOutstanding, loan.getNetDisbursalAmount(), totalPrincipalOutstanding,
totalInterestOutstanding, totalFeeOutstanding, totalPenaltyOutstanding, null, ExternalId.empty(), null, null, null, null,
false, loanId, loan.getExternalId());
loanTransactionData.setChargeOffReasonOptions(chargeOffReasonOptions);
LoanTransactionData loanTransactionData = LoanTransactionData.builder().type(transactionType).currency(loan.getCurrency())
.date(DateUtils.getBusinessLocalDate()).amount(totalOutstanding).netDisbursalAmount(loan.getNetDisbursalAmount())
.principalPortion(totalPrincipalOutstanding).interestPortion(totalInterestOutstanding)
.feeChargesPortion(totalFeeOutstanding).penaltyChargesPortion(totalPenaltyOutstanding).externalId(ExternalId.empty())
.manuallyReversed(false).loanId(loanId).externalLoanId(loan.getExternalId()).chargeOffReasonOptions(chargeOffReasonOptions)
.build();
return loanTransactionData;
}
@@ -2216,9 +2225,9 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
final LocalDate currentDate = LocalDate.now(DateUtils.getDateTimeZoneOfTenant());
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(loanTransactionType);
return new LoanTransactionData(null, null, null, transactionType, null, currencyData, currentDate, transactionAmount, null,
netDisbursal, null, null, null, null, null, paymentOptions, ExternalId.empty(), null, null, null, false, loanId,
externalLoanId);
return LoanTransactionData.builder().type(transactionType).currency(currencyData).date(currentDate).amount(transactionAmount)
.netDisbursalAmount(netDisbursal).paymentTypeOptions(paymentOptions).externalId(ExternalId.empty()).manuallyReversed(false)
.loanId(loanId).externalLoanId(externalLoanId).build();
}
@Override
@@ -2309,14 +2318,15 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
final Money outStandingAmount = loanRepaymentScheduleInstallment.getTotalOutstanding(currency);
return new LoanTransactionData(null, null, null, transactionType, null, currencyData, earliestUnpaidInstallmentDate,
outStandingAmount.getAmount(), loan.getNetDisbursalAmount(),
loanRepaymentScheduleInstallment.getPrincipalOutstanding(currency).getAmount(),
loanRepaymentScheduleInstallment.getInterestOutstanding(currency).getAmount(),
loanRepaymentScheduleInstallment.getFeeChargesOutstanding(currency).getAmount(),
loanRepaymentScheduleInstallment.getPenaltyChargesOutstanding(currency).getAmount(), null, unrecognizedIncomePortion,
paymentTypeOptions, ExternalId.empty(), null, null, outstandingLoanBalance, isManuallyReversed, loanId,
loan.getExternalId());
return LoanTransactionData.builder().type(transactionType).currency(currencyData).date(earliestUnpaidInstallmentDate)
.amount(outStandingAmount.getAmount()).netDisbursalAmount(loan.getNetDisbursalAmount())
.principalPortion(loanRepaymentScheduleInstallment.getPrincipalOutstanding(currency).getAmount())
.interestPortion(loanRepaymentScheduleInstallment.getInterestOutstanding(currency).getAmount())
.feeChargesPortion(loanRepaymentScheduleInstallment.getFeeChargesOutstanding(currency).getAmount())
.penaltyChargesPortion(loanRepaymentScheduleInstallment.getPenaltyChargesOutstanding(currency).getAmount())
.unrecognizedIncomePortion(unrecognizedIncomePortion).paymentTypeOptions(paymentTypeOptions).externalId(ExternalId.empty())
.outstandingLoanBalance(outstandingLoanBalance).manuallyReversed(isManuallyReversed).loanId(loanId)
.externalLoanId(loan.getExternalId()).build();
}
private static final class CurrencyMapper implements RowMapper<CurrencyData> {
@@ -2395,10 +2405,13 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
boolean manuallyReversed = false;
final PaymentDetailData paymentDetailData = null;
final AccountTransferData transfer = null;
final BigDecimal fixedEmiAmount = null;
return new LoanTransactionData(id, officeId, officeName, transactionType, paymentDetailData, currencyData, date, totalDue,
netDisbursalAmount, principalPortion, interestDue, feeDue, penaltyDue, overPaymentPortion, ExternalId.empty(), transfer,
fixedEmiAmount, outstandingLoanBalance, unrecognizedIncomePortion, manuallyReversed, loanId, ExternalId.empty());
return LoanTransactionData.builder().id(id).officeId(officeId).officeName(officeName).type(transactionType)
.paymentDetailData(paymentDetailData).currency(currencyData).date(date).amount(totalDue)
.netDisbursalAmount(netDisbursalAmount).principalPortion(principalPortion).interestPortion(interestDue)
.feeChargesPortion(feeDue).penaltyChargesPortion(penaltyDue).overpaymentPortion(overPaymentPortion)
.externalId(ExternalId.empty()).transfer(transfer).outstandingLoanBalance(outstandingLoanBalance)
.unrecognizedIncomePortion(unrecognizedIncomePortion).manuallyReversed(manuallyReversed).loanId(loanId)
.externalLoanId(ExternalId.empty()).build();
}
}
@@ -137,11 +137,15 @@ public class LoanAdjustTransactionBusinessEventSerializerTest {
String reversedLocalDate = reversedOnDate.format(DateTimeFormatter.ISO_DATE);
LoanAdjustTransactionBusinessEvent businessEvent = new LoanAdjustTransactionBusinessEvent(loanAdjustTransactionBusinessEventData);
LoanTransactionData transactionToAdjustData = new LoanTransactionData(1L, 1L, "", LoanEnumerations.transactionType(2), null, null,
LocalDate.now(ZoneId.systemDefault()), BigDecimal.valueOf(0.0), BigDecimal.valueOf(0.0), BigDecimal.valueOf(0.0),
BigDecimal.valueOf(0.0), BigDecimal.valueOf(0.0), BigDecimal.valueOf(0.0), BigDecimal.valueOf(0.0), BigDecimal.valueOf(0.0),
new ExternalId("testExternalId"), null, null, BigDecimal.valueOf(0.0), LocalDate.now(ZoneId.systemDefault()).minusDays(4),
true, new ExternalId("testReversalExternalId"), reversedOnDate, 1L, new ExternalId("testExternalLoanId"));
LoanTransactionData transactionToAdjustData = LoanTransactionData.builder().id(1L).officeId(1L).officeName("")
.type(LoanEnumerations.transactionType(2)).date(LocalDate.now(ZoneId.systemDefault())).amount(BigDecimal.valueOf(0.0))
.netDisbursalAmount(BigDecimal.valueOf(0.0)).principalPortion(BigDecimal.valueOf(0.0))
.interestPortion(BigDecimal.valueOf(0.0)).feeChargesPortion(BigDecimal.valueOf(0.0))
.penaltyChargesPortion(BigDecimal.valueOf(0.0)).overpaymentPortion(BigDecimal.valueOf(0.0))
.unrecognizedIncomePortion(BigDecimal.valueOf(0.0)).externalId(new ExternalId("testExternalId"))
.outstandingLoanBalance(BigDecimal.valueOf(0.0)).submittedOnDate(LocalDate.now(ZoneId.systemDefault()).minusDays(4))
.manuallyReversed(true).reversalExternalId(new ExternalId("testReversalExternalId")).reversedOnDate(reversedOnDate)
.loanId(1L).externalLoanId(new ExternalId("testExternalLoanId")).build();
when(service.retrieveLoanTransaction(anyLong(), anyLong())).thenReturn(transactionToAdjustData);
when(loanChargePaidByReadService.fetchLoanChargesPaidByDataTransactionId(anyLong())).thenReturn(new ArrayList<>());