FINERACT-2190: Avoid recreation of loan repayment schedule periods

This commit is contained in:
Jose Alberto Hernandez
2025-04-04 14:29:10 +02:00
committed by Adam Saghy
parent b9cfa470ff
commit 52c41b1471
13 changed files with 229 additions and 117 deletions
@@ -79,6 +79,7 @@ import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
import org.apache.fineract.portfolio.loanaccount.service.LoanChargeService;
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
import org.apache.fineract.portfolio.loanaccount.service.ReprocessLoanTransactionsService;
import org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
import org.apache.fineract.useradministration.domain.AppUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -115,6 +116,7 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
private final LoanAccrualsProcessingService loanAccrualsProcessingService;
private final LoanChargeService loanChargeService;
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
private final LoanScheduleComponent loanSchedule;
/**
* create a new instance of the LoanRescheduleRequest object from the JsonCommand object and persist
@@ -423,14 +425,14 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
loanApplicationTerms.getInterestMethod());
final LoanLifecycleStateMachine loanLifecycleStateMachine = null;
loan.setHelpers(loanLifecycleStateMachine);
final LoanScheduleDTO loanSchedule = loanScheduleGenerator.rescheduleNextInstallments(mathContext, loanApplicationTerms, loan,
final LoanScheduleDTO loanScheduleDTO = loanScheduleGenerator.rescheduleNextInstallments(mathContext, loanApplicationTerms, loan,
loanApplicationTerms.getHolidayDetailDTO(), loanRepaymentScheduleTransactionProcessor, rescheduleFromDate);
// Either the installments got recalculated or the model
if (loanSchedule.getInstallments() != null) {
loan.updateLoanSchedule(loanSchedule.getInstallments());
if (loanScheduleDTO.getInstallments() != null) {
loanSchedule.updateLoanSchedule(loan, loanScheduleDTO.getInstallments());
} else {
loan.updateLoanSchedule(loanSchedule.getLoanScheduleModel());
loanSchedule.updateLoanSchedule(loan, loanScheduleDTO.getLoanScheduleModel());
}
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
loanChargeService.recalculateAllCharges(loan);
@@ -93,6 +93,7 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanSchedu
import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleCalculationPlatformService;
import org.apache.fineract.portfolio.loanaccount.mapper.LoanChargeMapper;
import org.apache.fineract.portfolio.loanaccount.mapper.LoanCollateralManagementMapper;
import org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
@@ -137,6 +138,7 @@ public class LoanAssemblerImpl implements LoanAssembler {
private final LoanDisbursementService loanDisbursementService;
private final LoanChargeService loanChargeService;
private final LoanOfficerService loanOfficerService;
private final LoanScheduleComponent loanSchedule;
@Override
public Loan assembleFrom(final Long accountId) {
@@ -293,6 +295,8 @@ public class LoanAssemblerImpl implements LoanAssembler {
throw new IllegalStateException("No loan application exists for either a client or group (or both).");
}
loanSchedule.updateLoanSchedule(loanApplication, loanScheduleModel);
copyAdvancedPaymentRulesIfApplicable(transactionProcessingStrategyCode, loanProduct, loanApplication);
loanApplication.setHelpers(defaultLoanLifecycleStateMachine);
// TODO: review
@@ -858,8 +862,8 @@ public class LoanAssemblerImpl implements LoanAssembler {
final JsonElement parsedQuery = this.fromApiJsonHelper.parse(command.json());
final JsonQuery query = JsonQuery.from(command.json(), parsedQuery, this.fromApiJsonHelper);
final LoanScheduleModel loanSchedule = this.calculationPlatformService.calculateLoanSchedule(query, false);
loan.updateLoanSchedule(loanSchedule);
final LoanScheduleModel loanScheduleModel = this.calculationPlatformService.calculateLoanSchedule(query, false);
loanSchedule.updateLoanSchedule(loan, loanScheduleModel);
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
loanChargeService.recalculateAllCharges(loan);
}
@@ -34,6 +34,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.imp
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor;
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.RBILoanRepaymentScheduleTransactionProcessor;
import org.apache.fineract.portfolio.loanaccount.service.ProgressiveLoanInterestRefundServiceImpl;
import org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
@@ -118,8 +119,9 @@ public class LoanAccountAutoStarter {
@Conditional(AdvancedPaymentScheduleTransactionProcessorCondition.class)
public AdvancedPaymentScheduleTransactionProcessor advancedPaymentScheduleTransactionProcessor(EMICalculator emiCalculator,
LoanRepositoryWrapper loanRepositoryWrapper,
@Lazy ProgressiveLoanInterestRefundServiceImpl progressiveLoanInterestRefundService, ExternalIdFactory externalIdFactory) {
@Lazy ProgressiveLoanInterestRefundServiceImpl progressiveLoanInterestRefundService, ExternalIdFactory externalIdFactory,
LoanScheduleComponent loanSchedule) {
return new AdvancedPaymentScheduleTransactionProcessor(emiCalculator, loanRepositoryWrapper, progressiveLoanInterestRefundService,
externalIdFactory);
externalIdFactory, loanSchedule);
}
}
@@ -146,6 +146,7 @@ import org.apache.fineract.portfolio.loanaccount.service.ReplayedTransactionBusi
import org.apache.fineract.portfolio.loanaccount.service.ReplayedTransactionBusinessEventServiceImpl;
import org.apache.fineract.portfolio.loanaccount.service.ReprocessLoanTransactionsService;
import org.apache.fineract.portfolio.loanaccount.service.adjustment.LoanAdjustmentService;
import org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
import org.apache.fineract.portfolio.loanproduct.service.LoanDropdownReadPlatformService;
import org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService;
@@ -240,14 +241,15 @@ public class LoanAccountConfiguration {
LoanCollateralAssembler loanCollateralAssembler, LoanScheduleCalculationPlatformService calculationPlatformService,
LoanDisbursementDetailsAssembler loanDisbursementDetailsAssembler, LoanChargeMapper loanChargeMapper,
LoanCollateralManagementMapper loanCollateralManagementMapper, LoanAccrualsProcessingService loanAccrualsProcessingService,
LoanDisbursementService loanDisbursementService, LoanChargeService loanChargeService, LoanOfficerService loanOfficerService) {
LoanDisbursementService loanDisbursementService, LoanChargeService loanChargeService, LoanOfficerService loanOfficerService,
LoanScheduleComponent loanSchedule) {
return new LoanAssemblerImpl(fromApiJsonHelper, loanRepository, loanProductRepository, clientRepository, groupRepository,
fundRepository, staffRepository, codeValueRepository, loanScheduleAssembler, loanChargeAssembler, collateralAssembler,
loanRepaymentScheduleTransactionProcessorFactory, holidayRepository, configurationDomainService, workingDaysRepository,
rateAssembler, defaultLoanLifecycleStateMachine, externalIdFactory, accountNumberFormatRepository, glimRepository,
accountNumberGenerator, glimAccountInfoWritePlatformService, loanCollateralAssembler, calculationPlatformService,
loanDisbursementDetailsAssembler, loanChargeMapper, loanCollateralManagementMapper, loanAccrualsProcessingService,
loanDisbursementService, loanChargeService, loanOfficerService);
loanDisbursementService, loanChargeService, loanOfficerService, loanSchedule);
}
@Bean
@@ -461,8 +463,8 @@ public class LoanAccountConfiguration {
@ConditionalOnMissingBean(LoanScheduleService.class)
public LoanScheduleService loanScheduleService(LoanChargeService loanChargeService,
ReprocessLoanTransactionsService reprocessLoanTransactionsService,
LoanTransactionProcessingService loanTransactionProcessingService) {
return new LoanScheduleService(loanChargeService, reprocessLoanTransactionsService, loanTransactionProcessingService);
LoanTransactionProcessingService loanTransactionProcessingService, LoanScheduleComponent loanSchedule) {
return new LoanScheduleService(loanChargeService, reprocessLoanTransactionsService, loanTransactionProcessingService, loanSchedule);
}
@Bean