From c0199a3aec8d3f21a256beb899186ee91dbf7276 Mon Sep 17 00:00:00 2001 From: Faheem Ahmad Date: Mon, 9 Dec 2024 13:53:55 +0500 Subject: [PATCH] Su 485 (#1357) * SU-485 --- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- ...faultOrCancelInsuranceInstallmentData.java | 10 + .../service/LoanArrearsAgingServiceImpl.java | 56 +++++- .../service/LoanReadPlatformServiceImpl.java | 14 +- ...WritePlatformServiceJpaRepositoryImpl.java | 181 ++++++++++-------- .../starter/LoanAccountConfiguration.java | 5 +- .../db/changelog/tenant/changelog-tenant.xml | 1 + ...43_SU_485_client_death_blocking_reason.xml | 39 ++++ 8 files changed, 220 insertions(+), 88 deletions(-) create mode 100644 fineract-provider/src/main/resources/db/changelog/tenant/parts/20241208121243_SU_485_client_death_blocking_reason.xml diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java index 90d9cf97915..910719b39b7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java @@ -1080,7 +1080,7 @@ public CommandProcessingResult blockClient(final Long clientId, final JsonComman || (incident.isVoluntary() && loanCharge.isVoluntaryInsurance())) { if (loanCharge.getAmountOutstanding(loan.getCurrency()).isGreaterThanZero()) { InsuranceIncidentNoveltyNews insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, - loanCharge, 0, incident, loan.getClosedOnDate(), BigDecimal.ZERO); + loanCharge, 0, incident, blockedOnDate, BigDecimal.ZERO); this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DefaultOrCancelInsuranceInstallmentData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DefaultOrCancelInsuranceInstallmentData.java index 7b854d0ecca..fcd8ea769da 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DefaultOrCancelInsuranceInstallmentData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DefaultOrCancelInsuranceInstallmentData.java @@ -1,5 +1,6 @@ package org.apache.fineract.portfolio.loanaccount.data; +import java.time.LocalDate; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -12,6 +13,7 @@ public class DefaultOrCancelInsuranceInstallmentData { private Long loanId; private Long loanChargeId; private Integer installment; + private LocalDate suspensionDate; public Long loanId() { return loanId; @@ -36,4 +38,12 @@ public Integer installment() { public void setInstallment(Integer installment) { this.installment = installment; } + + public LocalDate suspensionDate() { + return suspensionDate; + } + + public void setSuspensionDate(LocalDate suspensionDate) { + this.suspensionDate = suspensionDate; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanArrearsAgingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanArrearsAgingServiceImpl.java index 85c02cd9b89..9e1bedf542e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanArrearsAgingServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanArrearsAgingServiceImpl.java @@ -88,6 +88,7 @@ public class LoanArrearsAgingServiceImpl implements LoanArrearsAgingService { private final PlatformSecurityContext context; private final InsuranceIncidentRepository insuranceIncidentRepository; private final InsuranceIncidentNoveltyNewsRepository insuranceIncidentNoveltyNewsRepository; + private final LoanReadPlatformService loanReadPlatformService; @PostConstruct public void registerForNotification() { @@ -653,6 +654,18 @@ private void createSuspensionRemovedNews(Loan loan) { daysInArrears = 0; } if (daysInArrears >= 90) { + // In case of transaction rollback, a loan can move again to suspension + LocalDate date = null; + try { + date = this.jdbcTemplate.queryForObject( + "select overdue_since_date_derived aging_days from m_loan_arrears_aging mlaa where mlaa.loan_id =?", + LocalDate.class, loan.getId()); + } catch (final EmptyResultDataAccessException e) { + // not in arrears + } + if (date != null) { + temporarySuspendDefaultInsuranceCharges(loan, date.plusDays(90)); + } return; } final LocalDate currentDate = DateUtils.getBusinessLocalDate(); @@ -670,9 +683,17 @@ private void createSuspensionRemovedNews(Loan loan) { // Do not add suspension news if loan is already in suspension return; } + } else { + // Loan was never in arrears + return; } Collection loanCharges = loan.getInsuranceChargesForNoveltyIncidentReporting(incident.isMandatory(), incident.isVoluntary()); + LocalDate transactionDate = currentDate; + List transactions = loan.retrieveListOfTransactionsPostDisbursementExcludeAccruals(); + if (!transactions.isEmpty()) { + transactionDate = transactions.get(transactions.size() - 1).getTransactionDate(); + } if (loanCharges != null && !loanCharges.isEmpty()) { for (LoanCharge loanCharge : loanCharges) { if (loanCharge.getAmountOutstanding(loan.getCurrency()).isGreaterThanZero()) { @@ -680,7 +701,7 @@ private void createSuspensionRemovedNews(Loan loan) { || (incident.isVoluntary() && loanCharge.isVoluntaryInsurance())) { BigDecimal cumulative = BigDecimal.ZERO; InsuranceIncidentNoveltyNews insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, loanCharge, - null, incident, currentDate, cumulative); + null, incident, transactionDate, cumulative); this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); } @@ -689,4 +710,37 @@ private void createSuspensionRemovedNews(Loan loan) { } } + private void temporarySuspendDefaultInsuranceCharges(Loan loan, LocalDate suspensionDate) { + final LocalDate currentDate = DateUtils.getBusinessLocalDate(); + InsuranceIncident incident = this.insuranceIncidentRepository + .findByIncidentType(InsuranceIncidentType.TEMPORARY_SUSPENSION_DUE_TO_DEFAULT); + InsuranceIncident suspensionRemovedIncident = this.insuranceIncidentRepository + .findByIncidentType(InsuranceIncidentType.SUSPENSION_REMOVED); + if (incident == null || (!incident.isMandatory() && !incident.isVoluntary())) { + throw new InsuranceIncidentNotFoundException(InsuranceIncidentType.TEMPORARY_SUSPENSION_DUE_TO_DEFAULT.name()); + } + + Optional lastSuspensionNewsOptional = this.insuranceIncidentNoveltyNewsRepository + .findLastSuspensionIfPresent(loan.getId(), incident.getId(), suspensionRemovedIncident.getId()); + if (lastSuspensionNewsOptional.isPresent()) { + InsuranceIncidentNoveltyNews news = lastSuspensionNewsOptional.get(); + if (news.getInsuranceIncident().getIncidentType().equals(InsuranceIncidentType.TEMPORARY_SUSPENSION_DUE_TO_DEFAULT)) { + // Do not add suspension news if loan is already in suspension + return; + } + } + for (LoanCharge loanCharge : loan.getCharges()) { + if (loanCharge.getAmountOutstanding(loan.getCurrency()).isGreaterThanZero()) { + if ((incident.isMandatory() && loanCharge.isMandatoryInsurance()) + || (incident.isVoluntary() && loanCharge.isVoluntaryInsurance())) { + BigDecimal cumulative = BigDecimal.ZERO; + InsuranceIncidentNoveltyNews insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, loanCharge, + null, incident, suspensionDate, cumulative); + + this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); + } + } + } + } + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 4a646d6e6cf..e4ef84659fe 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -3341,7 +3341,8 @@ ml.id loanId, min(mlrs.installment) installment, mlc.id loanChargeId public String suspensionSchema() { return """ - distinct ml.id loanId, min(mlrs.installment) installment, mlc.id loanChargeId + distinct ml.id loanId, min(mlrs.installment) installment, mlc.id loanChargeId, mlaa.overdue_since_date_derived overdue_date, + ? suspension_period from m_loan ml join m_loan_arrears_aging mlaa on mlaa.loan_id = ml.id @@ -3360,8 +3361,10 @@ public DefaultOrCancelInsuranceInstallmentData mapRow(@NotNull ResultSet rs, int final Long loanId = JdbcSupport.getLong(rs, "loanId"); final Integer installment = JdbcSupport.getInteger(rs, "installment"); final Long loanChargeId = JdbcSupport.getLong(rs, "loanChargeId"); + final LocalDate overDueDate = JdbcSupport.getLocalDate(rs, "overdue_date"); + final Long suspensionPeriod = JdbcSupport.getLong(rs, "suspension_period"); - return new DefaultOrCancelInsuranceInstallmentData(loanId, loanChargeId, installment); + return new DefaultOrCancelInsuranceInstallmentData(loanId, loanChargeId, installment, overDueDate.plusDays(suspensionPeriod)); } } @@ -3372,7 +3375,7 @@ public List getLoanDataWithDefaultOrCan final DefaultInsuranceMapper rowMapper = new DefaultInsuranceMapper(); String sql = "SELECT " + rowMapper.schema(); Object[] params = null; - sql = sql + " and mc.charge_calculation_enum = " + ChargeCalculationType.FLAT_SEGOVOLUNTARIO.getValue(); + // sql = sql + " and mc.charge_calculation_enum = " + ChargeCalculationType.FLAT_SEGOVOLUNTARIO.getValue(); if (loanId == null && insuranceCode == null) { sql = sql + " and mlrs.duedate < CURRENT_DATE " + " and CURRENT_DATE - mlrs.duedate = 60 "; params = new Object[] {}; @@ -3399,8 +3402,9 @@ public List getLoanDataWithDefaultManda final DefaultInsuranceMapper rowMapper = new DefaultInsuranceMapper(); String sql = "SELECT " + rowMapper.suspensionSchema(); - Object[] params = new Object[] { numberOfDays }; - sql = sql + " and (CURRENT_DATE - mlaa.overdue_since_date_derived) >= ? " + " group by ml.id, mlc.id order by ml.id"; + Object[] params = new Object[] { numberOfDays, numberOfDays }; + sql = sql + " and (CURRENT_DATE - mlaa.overdue_since_date_derived) >= ? " + + " group by ml.id, mlc.id, mlaa.overdue_since_date_derived order by ml.id"; return this.jdbcTemplate.query(sql, rowMapper, params); // NOSONAR } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 7875e7bc100..a0baeedd977 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -1276,18 +1276,7 @@ public CommandProcessingResult makeLoanRepaymentWithChargeRefundChargeType(final } if (loan.getStatus().isClosed()) { - InsuranceIncident incident = this.insuranceIncidentRepository - .findByIncidentType(InsuranceIncidentType.DEFINITIVE_FINAL_CANCELLATION); - if (incident != null) { - BigDecimal cumulative = BigDecimal.ZERO; - List loanCharges = loan.getLoanCharges().stream().filter(lc -> lc.getChargeCalculation().isVoluntaryInsurance()) - .toList(); - for (LoanCharge loanCharge : loanCharges) { - InsuranceIncidentNoveltyNews insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, loanCharge, 0, - incident, loan.getClosedOnDate(), cumulative); - this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); - } - } + createCancellationNoveltyNews(loan, loan.getClosedOnDate()); } return new CommandProcessingResultBuilder().withCommandId(command.commandId()) // @@ -1301,6 +1290,27 @@ public CommandProcessingResult makeLoanRepaymentWithChargeRefundChargeType(final .build(); } + private void createCancellationNoveltyNews(Loan loan, LocalDate writeOffDate) { + InsuranceIncident incident = this.insuranceIncidentRepository + .findByIncidentType(InsuranceIncidentType.DEFINITIVE_FINAL_CANCELLATION); + if (incident == null || (!incident.isMandatory() && !incident.isVoluntary())) { + throw new InsuranceIncidentNotFoundException(InsuranceIncidentType.DEFINITIVE_FINAL_CANCELLATION.name()); + } + + for (LoanCharge loanCharge : loan.getCharges()) { + if (loanCharge.getAmountOutstanding(loan.getCurrency()).isGreaterThanZero()) { + if ((incident.isMandatory() && loanCharge.isMandatoryInsurance()) + || (incident.isVoluntary() && loanCharge.isVoluntaryInsurance())) { + BigDecimal cumulative = BigDecimal.ZERO; + InsuranceIncidentNoveltyNews insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, loanCharge, + null, incident, writeOffDate, cumulative); + + this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); + } + } + } + } + private ChannelData validateRepaymentChannel(final String channelName, final LoanProduct loanProduct) { if (StringUtils.isBlank(channelName)) { throw new GeneralPlatformDomainRuleException("validation.msg.channel.is.blank", "Channel is blank"); @@ -1412,18 +1422,7 @@ public Map makeLoanBulkRepayment(final CollectionSheetBulkRepaym transactionIds.add(loanTransaction.getId()); if (loan.getStatus().isClosed()) { - InsuranceIncident incident = this.insuranceIncidentRepository - .findByIncidentType(InsuranceIncidentType.DEFINITIVE_FINAL_CANCELLATION); - if (incident != null) { - BigDecimal cumulative = BigDecimal.ZERO; - List loanCharges = loan.getLoanCharges().stream() - .filter(lc -> lc.getChargeCalculation().isVoluntaryInsurance()).toList(); - for (LoanCharge loanCharge : loanCharges) { - InsuranceIncidentNoveltyNews insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, - loanCharge, 0, incident, loan.getClosedOnDate(), cumulative); - this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); - } - } + createCancellationNoveltyNews(loan, loan.getClosedOnDate()); } } } @@ -1939,8 +1938,10 @@ public CommandProcessingResult writeOff(final Long loanId, final JsonCommand com loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds); loanAccountDomainService.recalculateAccruals(loan); loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate()); + createWriteOffNoveltyNews(loan, transactionDate); businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan)); businessEventNotifierService.notifyPostBusinessEvent(new LoanWrittenOffPostBusinessEvent(writeOff)); + return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withEntityId(writeOff.getId()) // @@ -1952,6 +1953,27 @@ public CommandProcessingResult writeOff(final Long loanId, final JsonCommand com .with(changes).build(); } + private void createWriteOffNoveltyNews(Loan loan, LocalDate writeOffDate) { + InsuranceIncident incident = this.insuranceIncidentRepository + .findByIncidentType(InsuranceIncidentType.PORTFOLIO_WRITE_OFF_CANCELLATION); + if (incident == null || (!incident.isMandatory() && !incident.isVoluntary())) { + throw new InsuranceIncidentNotFoundException(InsuranceIncidentType.PORTFOLIO_WRITE_OFF_CANCELLATION.name()); + } + + for (LoanCharge loanCharge : loan.getCharges()) { + if (loanCharge.getAmountOutstanding(loan.getCurrency()).isGreaterThanZero()) { + if ((incident.isMandatory() && loanCharge.isMandatoryInsurance()) + || (incident.isVoluntary() && loanCharge.isVoluntaryInsurance())) { + BigDecimal cumulative = BigDecimal.ZERO; + InsuranceIncidentNoveltyNews insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, loanCharge, + null, incident, writeOffDate, cumulative); + + this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); + } + } + } + } + @Transactional @Override public CommandProcessingResult specialWriteOff(final Long loanId, final JsonCommand command) { @@ -3514,27 +3536,23 @@ public CommandProcessingResult forecloseLoan(final Long loanId, final JsonComman this.loanScheduleHistoryWritePlatformService.createAndSaveLoanScheduleArchive(loan.getRepaymentScheduleInstallments(), loan, loanRescheduleRequest); - List cancelInsuranceInstallmentIds = this.loanReadPlatformService - .getLoanDataWithDefaultOrCancelInsurance(loanId, null, transactionDate); - InsuranceIncident incident = this.insuranceIncidentRepository - .findByIncidentType(InsuranceIncidentType.DEFINITIVE_FINAL_CANCELLATION); - if (incident == null) { - throw new InsuranceIncidentNotFoundException(InsuranceIncidentType.DEFINITIVE_FINAL_CANCELLATION.name()); - } - for (DefaultOrCancelInsuranceInstallmentData data : cancelInsuranceInstallmentIds) { - LoanCharge loanCharge = null; - Optional loanChargeOptional = loan.getLoanCharges().stream() - .filter(lc -> Objects.equals(lc.getId(), data.loanChargeId())).findFirst(); - if (loanChargeOptional.isPresent()) { - loanCharge = loanChargeOptional.get(); - } - BigDecimal cumulative = BigDecimal.ZERO; - cumulative = processInsuranceChargeCancellation(cumulative, loan, loanCharge, data, true); - InsuranceIncidentNoveltyNews insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, loanCharge, - data.installment(), incident, transactionDate, cumulative); - - this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); - } + /* + * List cancelInsuranceInstallmentIds = this.loanReadPlatformService + * .getLoanDataWithDefaultOrCancelInsurance(loanId, null, transactionDate); InsuranceIncident incident = + * this.insuranceIncidentRepository .findByIncidentType(InsuranceIncidentType.DEFINITIVE_FINAL_CANCELLATION); if + * (incident == null) { throw new + * InsuranceIncidentNotFoundException(InsuranceIncidentType.DEFINITIVE_FINAL_CANCELLATION.name()); } for + * (DefaultOrCancelInsuranceInstallmentData data : cancelInsuranceInstallmentIds) { LoanCharge loanCharge = + * null; Optional loanChargeOptional = loan.getLoanCharges().stream() .filter(lc -> + * Objects.equals(lc.getId(), data.loanChargeId())).findFirst(); if (loanChargeOptional.isPresent()) { + * loanCharge = loanChargeOptional.get(); } BigDecimal cumulative = BigDecimal.ZERO; cumulative = + * processInsuranceChargeCancellation(cumulative, loan, loanCharge, data, true); InsuranceIncidentNoveltyNews + * insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, loanCharge, data.installment(), + * incident, transactionDate, cumulative); + * + * this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); } + */ + createCancellationNoveltyNews(loan, transactionDate); LoanTransaction foreclosureTransaction = this.loanAccountDomainService.foreCloseLoan(loan, transactionDate, noteText, externalId, changes); @@ -3571,26 +3589,22 @@ public CommandProcessingResult cancelLoan(final Long loanId, final JsonCommand c } } this.loanScheduleHistoryWritePlatformService.createAndSaveLoanScheduleArchive(loan.getRepaymentScheduleInstallments(), loan, null); - List cancelInsuranceInstallmentIds = this.loanReadPlatformService - .getLoanDataWithDefaultOrCancelInsurance(loanId, null, transactionDate); - InsuranceIncident incident = this.insuranceIncidentRepository - .findByIncidentType(InsuranceIncidentType.DEFINITIVE_FINAL_CANCELLATION); - if (incident == null) { - throw new InsuranceIncidentNotFoundException(InsuranceIncidentType.DEFINITIVE_FINAL_CANCELLATION.name()); - } - for (final DefaultOrCancelInsuranceInstallmentData data : cancelInsuranceInstallmentIds) { - LoanCharge loanCharge = null; - Optional loanChargeOptional = loan.getLoanCharges().stream() - .filter(lc -> Objects.equals(lc.getId(), data.loanChargeId())).findFirst(); - if (loanChargeOptional.isPresent()) { - loanCharge = loanChargeOptional.get(); - } - BigDecimal cumulative = BigDecimal.ZERO; - cumulative = processInsuranceChargeCancellation(cumulative, loan, loanCharge, data, true); - InsuranceIncidentNoveltyNews insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, loanCharge, - data.installment(), incident, transactionDate, cumulative); - this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); - } + /* + * List cancelInsuranceInstallmentIds = this.loanReadPlatformService + * .getLoanDataWithDefaultOrCancelInsurance(loanId, null, transactionDate); InsuranceIncident incident = + * this.insuranceIncidentRepository .findByIncidentType(InsuranceIncidentType.DEFINITIVE_FINAL_CANCELLATION); if + * (incident == null) { throw new + * InsuranceIncidentNotFoundException(InsuranceIncidentType.DEFINITIVE_FINAL_CANCELLATION.name()); } for (final + * DefaultOrCancelInsuranceInstallmentData data : cancelInsuranceInstallmentIds) { LoanCharge loanCharge = null; + * Optional loanChargeOptional = loan.getLoanCharges().stream() .filter(lc -> + * Objects.equals(lc.getId(), data.loanChargeId())).findFirst(); if (loanChargeOptional.isPresent()) { + * loanCharge = loanChargeOptional.get(); } BigDecimal cumulative = BigDecimal.ZERO; cumulative = + * processInsuranceChargeCancellation(cumulative, loan, loanCharge, data, true); InsuranceIncidentNoveltyNews + * insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, loanCharge, data.installment(), + * incident, transactionDate, cumulative); + * this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); } + */ + createCancellationNoveltyNews(loan, transactionDate); if (transactionDate.equals(loan.getDisbursementDate())) { loan.setAnulado(true); loan.setAnuladoOnDisbursementDate(true); @@ -3664,12 +3678,15 @@ public CommandProcessingResult chargeOff(JsonCommand command) { .filter(lc -> Objects.equals(lc.getId(), data.loanChargeId())).findFirst(); if (loanChargeOptional.isPresent()) { loanCharge = loanChargeOptional.get(); + if ((incident.isMandatory() && loanCharge.isMandatoryInsurance()) + || (incident.isVoluntary() && loanCharge.isVoluntaryInsurance())) { + BigDecimal cumulative = BigDecimal.ZERO; + cumulative = processInsuranceChargeCancellation(cumulative, loan, loanCharge, data, true); + InsuranceIncidentNoveltyNews insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, loanCharge, + data.installment(), incident, transactionDate, cumulative); + this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); + } } - BigDecimal cumulative = BigDecimal.ZERO; - cumulative = processInsuranceChargeCancellation(cumulative, loan, loanCharge, data, true); - InsuranceIncidentNoveltyNews insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, loanCharge, - data.installment(), incident, transactionDate, cumulative); - this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); } businessEventNotifierService.notifyPreBusinessEvent(new LoanChargeOffPreBusinessEvent(loan)); @@ -4580,14 +4597,17 @@ public void cancelDefaultInsuranceCharges(List Objects.equals(lc.getId(), data.loanChargeId())).findFirst(); if (loanChargeOptional.isPresent()) { loanCharge = loanChargeOptional.get(); - } - BigDecimal cumulative = BigDecimal.ZERO; - cumulative = processInsuranceChargeCancellation(cumulative, loan, loanCharge, data, false); - InsuranceIncidentNoveltyNews insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, loanCharge, - data.installment(), incident, currentDate, cumulative); + if ((incident.isMandatory() && loanCharge.isMandatoryInsurance()) + || (incident.isVoluntary() && loanCharge.isVoluntaryInsurance())) { + BigDecimal cumulative = BigDecimal.ZERO; + cumulative = processInsuranceChargeCancellation(cumulative, loan, loanCharge, data, false); + InsuranceIncidentNoveltyNews insuranceIncidentNoveltyNews = InsuranceIncidentNoveltyNews.instance(loan, loanCharge, + data.installment(), incident, currentDate, cumulative); - this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); - saveAndFlushLoanWithDataIntegrityViolationChecks(loan); + this.insuranceIncidentNoveltyNewsRepository.saveAndFlush(insuranceIncidentNoveltyNews); + saveAndFlushLoanWithDataIntegrityViolationChecks(loan); + } + } } } @@ -4621,8 +4641,8 @@ public void temporarySuspendDefaultInsuranceCharges(List + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/20241208121243_SU_485_client_death_blocking_reason.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/20241208121243_SU_485_client_death_blocking_reason.xml new file mode 100644 index 00000000000..b33d2e66e85 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/20241208121243_SU_485_client_death_blocking_reason.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + +