FINERACT-1885 - Fix Actual Maturity when Loan reopen
- [x] Fix actual maturity date - [x] Added to actual maturity date to the timeline too - [x] Integration test
This commit is contained in:
+5
-4
@@ -470,7 +470,7 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
|
||||
.append(" l.closedon_date as closedOnDate,")
|
||||
.append(" cbu.username as closedByUsername, cbu.firstname as closedByFirstname, cbu.lastname as closedByLastname,")
|
||||
.append(" la.overdue_since_date_derived as overdueSinceDate, ")
|
||||
.append(" l.writtenoffon_date as writtenOffOnDate, l.expected_maturedon_date as expectedMaturityDate, ")
|
||||
.append(" l.writtenoffon_date as writtenOffOnDate, l.maturedon_date as actualMaturityDate, l.expected_maturedon_date as expectedMaturityDate, ")
|
||||
.append(" l.charged_off_on_date as chargedOffOnDate, cobu.username as chargedOffByUsername, ")
|
||||
.append(" cobu.firstname as chargedOffByFirstname, cobu.lastname as chargedOffByLastname ").append(" from m_loan l ")
|
||||
.append("LEFT JOIN m_product_loan AS lp ON lp.id = l.product_id")
|
||||
@@ -541,6 +541,7 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
|
||||
final LocalDate writtenOffOnDate = JdbcSupport.getLocalDate(rs, "writtenOffOnDate");
|
||||
|
||||
final LocalDate expectedMaturityDate = JdbcSupport.getLocalDate(rs, "expectedMaturityDate");
|
||||
final LocalDate actualMaturityDate = JdbcSupport.getLocalDate(rs, "actualMaturityDate");
|
||||
|
||||
final LocalDate overdueSinceDate = JdbcSupport.getLocalDate(rs, "overdueSinceDate");
|
||||
|
||||
@@ -556,8 +557,8 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
|
||||
withdrawnOnDate, withdrawnByUsername, withdrawnByFirstname, withdrawnByLastname, approvedOnDate, approvedByUsername,
|
||||
approvedByFirstname, approvedByLastname, expectedDisbursementDate, actualDisbursementDate, disbursedByUsername,
|
||||
disbursedByFirstname, disbursedByLastname, closedOnDate, closedByUsername, closedByFirstname, closedByLastname,
|
||||
expectedMaturityDate, writtenOffOnDate, closedByUsername, closedByFirstname, closedByLastname, chargedOffOnDate,
|
||||
chargedOffByUsername, chargedOffByFirstname, chargedOffByLastname);
|
||||
actualMaturityDate, expectedMaturityDate, writtenOffOnDate, closedByUsername, closedByFirstname, closedByLastname,
|
||||
chargedOffOnDate, chargedOffByUsername, chargedOffByFirstname, chargedOffByLastname);
|
||||
|
||||
return new LoanAccountSummaryData(id, accountNo, parentAccountNumber, externalId, productId, loanProductName,
|
||||
shortLoanProductName, loanStatus, loanType, loanCycle, timeline, inArrears, originalLoan, loanBalance, amountPaid);
|
||||
@@ -584,7 +585,7 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
|
||||
.append(" l.approvedon_date as approvedOnDate,")
|
||||
.append(" l.expected_disbursedon_date as expectedDisbursementDate, l.disbursedon_date as actualDisbursementDate,")
|
||||
.append(" l.closedon_date as closedOnDate,").append(" la.overdue_since_date_derived as overdueSinceDate,")
|
||||
.append(" l.writtenoffon_date as writtenOffOnDate, l.expected_maturedon_date as expectedMaturityDate,")
|
||||
.append(" l.writtenoffon_date as writtenOffOnDate, l.maturedon_date as actualMaturityDate, l.expected_maturedon_date as expectedMaturityDate,")
|
||||
.append(" g.is_active as isActive,").append(" cv.code_value as relationship,").append(" sa.on_hold_funds_derived")
|
||||
.append(" from m_loan l ").append(" join m_guarantor as g on g.loan_id = l.id ")
|
||||
.append(" join m_client as c on c.id = g.entity_id ").append(" LEFT JOIN m_product_loan AS lp ON lp.id = l.product_id")
|
||||
|
||||
+2
@@ -245,6 +245,8 @@ final class LoansApiResourceSwagger {
|
||||
public String disbursedByLastname;
|
||||
@Schema(example = "[2012, 4, 10]")
|
||||
public LocalDate expectedMaturityDate;
|
||||
@Schema(example = "[2012, 4, 10]")
|
||||
public LocalDate actualMaturityDate;
|
||||
@Schema(example = "[2012, 4, 3]")
|
||||
public LocalDate closedOnDate;
|
||||
@Schema(example = "[2012, 4, 10]")
|
||||
|
||||
+6
-3
@@ -56,6 +56,8 @@ public class LoanApplicationTimelineData {
|
||||
private final String closedByUsername;
|
||||
private final String closedByFirstname;
|
||||
private final String closedByLastname;
|
||||
|
||||
private final LocalDate actualMaturityDate;
|
||||
private final LocalDate expectedMaturityDate;
|
||||
private final LocalDate writeOffOnDate;
|
||||
private final String writeOffByUsername;
|
||||
@@ -102,14 +104,15 @@ public class LoanApplicationTimelineData {
|
||||
final String chargedOffByUsername = null;
|
||||
final String chargedOffByFirstname = null;
|
||||
final String chargedOffByLastname = null;
|
||||
final LocalDate actualMaturityDate = null;
|
||||
|
||||
return new LoanApplicationTimelineData(submittedOnDate, submittedByUsername, submittedByFirstname, submittedByLastname,
|
||||
rejectedOnDate, rejectedByUsername, rejectedByFirstname, rejectedByLastname, withdrawnOnDate, withdrawnByUsername,
|
||||
withdrawnByFirstname, withdrawnByLastname, approvedOnDate, approvedByUsername, approvedByFirstname, approvedByLastname,
|
||||
expectedDisbursementDate, actualDisbursementDate, disbursedByUsername, disbursedByFirstname, disbursedByLastname,
|
||||
closedOnDate, closedByUsername, closedByFirstname, closedByLastname, expectedMaturityDate, writeOffOnDate,
|
||||
writeOffByUsername, writeOffByFirstname, writeOffByLastname, chargedOffOnDate, chargedOffByUsername, chargedOffByFirstname,
|
||||
chargedOffByLastname);
|
||||
closedOnDate, closedByUsername, closedByFirstname, closedByLastname, actualMaturityDate, expectedMaturityDate,
|
||||
writeOffOnDate, writeOffByUsername, writeOffByFirstname, writeOffByLastname, chargedOffOnDate, chargedOffByUsername,
|
||||
chargedOffByFirstname, chargedOffByLastname);
|
||||
}
|
||||
|
||||
public RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData(final CurrencyData currency, final BigDecimal principal,
|
||||
|
||||
+6
@@ -7027,4 +7027,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
return getLoanTransactions().stream().filter(predicate).toList();
|
||||
}
|
||||
|
||||
public void handleMaturityDateActivate() {
|
||||
if (this.expectedMaturityDate != null && this.actualMaturityDate == null) {
|
||||
this.actualMaturityDate = this.expectedMaturityDate;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-3
@@ -616,7 +616,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
+ " l.approvedon_date as approvedOnDate, abu.username as approvedByUsername, abu.firstname as approvedByFirstname, abu.lastname as approvedByLastname,"
|
||||
+ " l.expected_disbursedon_date as expectedDisbursementDate, l.disbursedon_date as actualDisbursementDate, dbu.username as disbursedByUsername, dbu.firstname as disbursedByFirstname, dbu.lastname as disbursedByLastname,"
|
||||
+ " l.closedon_date as closedOnDate, cbu.username as closedByUsername, cbu.firstname as closedByFirstname, cbu.lastname as closedByLastname, l.writtenoffon_date as writtenOffOnDate, "
|
||||
+ " l.expected_firstrepaymenton_date as expectedFirstRepaymentOnDate, l.interest_calculated_from_date as interestChargedFromDate, l.expected_maturedon_date as expectedMaturityDate, "
|
||||
+ " l.expected_firstrepaymenton_date as expectedFirstRepaymentOnDate, l.interest_calculated_from_date as interestChargedFromDate, l.maturedon_date as actualMaturityDate, l.expected_maturedon_date as expectedMaturityDate, "
|
||||
+ " l.principal_amount_proposed as proposedPrincipal, l.principal_amount as principal, l.approved_principal as approvedPrincipal, l.net_disbursal_amount as netDisbursalAmount, l.arrearstolerance_amount as inArrearsTolerance, l.number_of_repayments as numberOfRepayments, l.repay_every as repaymentEvery,"
|
||||
+ " l.grace_on_principal_periods as graceOnPrincipalPayment, l.recurring_moratorium_principal_periods as recurringMoratoriumOnPrincipalPeriods, l.grace_on_interest_periods as graceOnInterestPayment, l.grace_interest_free_periods as graceOnInterestCharged,l.grace_on_arrears_ageing as graceOnArrearsAgeing,"
|
||||
+ " l.nominal_interest_rate_per_period as interestRatePerPeriod, l.annual_nominal_interest_rate as annualInterestRate, "
|
||||
@@ -791,6 +791,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final LocalDate writtenOffOnDate = JdbcSupport.getLocalDate(rs, "writtenOffOnDate");
|
||||
final Long writeoffReasonId = JdbcSupport.getLong(rs, "writeoffReasonId");
|
||||
final String writeoffReason = rs.getString("writeoffReason");
|
||||
final LocalDate actualMaturityDate = JdbcSupport.getLocalDate(rs, "actualMaturityDate");
|
||||
final LocalDate expectedMaturityDate = JdbcSupport.getLocalDate(rs, "expectedMaturityDate");
|
||||
|
||||
final Boolean isvariableInstallmentsAllowed = rs.getBoolean("isvariableInstallmentsAllowed");
|
||||
@@ -810,8 +811,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
withdrawnOnDate, withdrawnByUsername, withdrawnByFirstname, withdrawnByLastname, approvedOnDate, approvedByUsername,
|
||||
approvedByFirstname, approvedByLastname, expectedDisbursementDate, actualDisbursementDate, disbursedByUsername,
|
||||
disbursedByFirstname, disbursedByLastname, closedOnDate, closedByUsername, closedByFirstname, closedByLastname,
|
||||
expectedMaturityDate, writtenOffOnDate, closedByUsername, closedByFirstname, closedByLastname, chargedOffOnDate,
|
||||
chargedOffByUsername, chargedOffByFirstname, chargedOffByLastname);
|
||||
actualMaturityDate, expectedMaturityDate, writtenOffOnDate, closedByUsername, closedByFirstname, closedByLastname,
|
||||
chargedOffOnDate, chargedOffByUsername, chargedOffByFirstname, chargedOffByLastname);
|
||||
|
||||
final BigDecimal principal = rs.getBigDecimal("principal");
|
||||
final BigDecimal approvedPrincipal = rs.getBigDecimal("approvedPrincipal");
|
||||
|
||||
+3
@@ -50,6 +50,9 @@ public class LoanStatusChangePlatformServiceImpl implements LoanStatusChangePlat
|
||||
log.debug("Loan Status {} for loan {}", loan.getStatus().getCode(), loan.getId());
|
||||
loan.applyIncomeAccrualTransaction(loan.getClosedOnDate());
|
||||
}
|
||||
if (loan.isOpen()) {
|
||||
loan.handleMaturityDateActivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+58
@@ -7004,6 +7004,64 @@ public class ClientLoanIntegrationTest {
|
||||
assertEquals("Administrator", loanDetails.getTimeline().getChargedOffByLastname());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseOpenMaturityDate() {
|
||||
GlobalConfigurationHelper.updateIsAutomaticExternalIdGenerationEnabled(this.requestSpec, this.responseSpec, true);
|
||||
final Account assetAccount = this.accountHelper.createAssetAccount();
|
||||
final Account incomeAccount = this.accountHelper.createIncomeAccount();
|
||||
final Account expenseAccount = this.accountHelper.createExpenseAccount();
|
||||
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
|
||||
|
||||
final Integer loanProductID = createLoanProductWithPeriodicAccrualAccountingNoInterest(assetAccount, incomeAccount, expenseAccount,
|
||||
overpaymentAccount);
|
||||
|
||||
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, "01 January 2011");
|
||||
|
||||
final Integer loanID = applyForLoanApplication(clientID, loanProductID);
|
||||
|
||||
HashMap<String, Object> loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
|
||||
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
|
||||
|
||||
loanStatusHashMap = this.loanTransactionHelper.approveLoan("02 September 2022", loanID);
|
||||
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
|
||||
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
|
||||
|
||||
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount("03 September 2022", loanID, "1000");
|
||||
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
|
||||
|
||||
GetLoansLoanIdResponse loanDetails = this.loanTransactionHelper.getLoanDetails((long) loanID);
|
||||
LocalDate expectedMaturityDate = loanDetails.getTimeline().getExpectedMaturityDate();
|
||||
LocalDate actualMaturityDate = loanDetails.getTimeline().getActualMaturityDate();
|
||||
|
||||
assertTrue(expectedMaturityDate.isEqual(actualMaturityDate));
|
||||
|
||||
this.loanTransactionHelper.makeRepayment("04 September 2022", Float.parseFloat("500"), loanID);
|
||||
this.loanTransactionHelper.makeRepayment("05 September 2022", Float.parseFloat("700"), loanID);
|
||||
|
||||
loanDetails = this.loanTransactionHelper.getLoanDetails((long) loanID);
|
||||
|
||||
expectedMaturityDate = loanDetails.getTimeline().getExpectedMaturityDate();
|
||||
actualMaturityDate = loanDetails.getTimeline().getActualMaturityDate();
|
||||
|
||||
assertNotNull(expectedMaturityDate);
|
||||
assertNull(actualMaturityDate);
|
||||
|
||||
this.loanTransactionHelper.reverseLoanTransaction((long) loanID, loanDetails.getTransactions().get(1).getId(),
|
||||
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat("dd MMMM yyyy").transactionDate("04 September 2022")
|
||||
.transactionAmount(0.0).locale("en"));
|
||||
|
||||
loanDetails = this.loanTransactionHelper.getLoanDetails((long) loanID);
|
||||
|
||||
expectedMaturityDate = loanDetails.getTimeline().getExpectedMaturityDate();
|
||||
actualMaturityDate = loanDetails.getTimeline().getActualMaturityDate();
|
||||
|
||||
assertNotNull(expectedMaturityDate);
|
||||
assertNotNull(actualMaturityDate);
|
||||
|
||||
assertTrue(expectedMaturityDate.isEqual(actualMaturityDate));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReverseReplay() {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user