FINERACT-2081: Refactoring for reprocess transactions and regenerate repayment schedule invocations
This commit is contained in:
committed by
Adam Saghy
parent
6bb68051ce
commit
b1384b9cce
+4
-16
@@ -40,15 +40,12 @@ import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
|||||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||||
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariations;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariations;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanTermVariationsRepository;
|
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanTermVariationsRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.ReplayedTransactionBusinessEventService;
|
import org.apache.fineract.portfolio.loanaccount.service.ReprocessLoanTransactionsService;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@@ -58,9 +55,7 @@ public class InterestPauseWritePlatformServiceImpl implements InterestPauseWrite
|
|||||||
private final LoanTermVariationsRepository loanTermVariationsRepository;
|
private final LoanTermVariationsRepository loanTermVariationsRepository;
|
||||||
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
||||||
private final LoanAssembler loanAssembler;
|
private final LoanAssembler loanAssembler;
|
||||||
private final LoanAccountDomainService loanAccountDomainService;
|
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
private final AccountTransfersService accountTransfersService;
|
|
||||||
private final ReplayedTransactionBusinessEventService replayedTransactionBusinessEventService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult createInterestPause(final ExternalId loanExternalId, final String startDateString,
|
public CommandProcessingResult createInterestPause(final ExternalId loanExternalId, final String startDateString,
|
||||||
@@ -151,16 +146,9 @@ public class InterestPauseWritePlatformServiceImpl implements InterestPauseWrite
|
|||||||
loan);
|
loan);
|
||||||
|
|
||||||
final LoanTermVariations savedVariation = loanTermVariationsRepository.saveAndFlush(variation);
|
final LoanTermVariations savedVariation = loanTermVariationsRepository.saveAndFlush(variation);
|
||||||
|
|
||||||
loan.getLoanTermVariations().add(savedVariation);
|
loan.getLoanTermVariations().add(savedVariation);
|
||||||
final ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactions();
|
|
||||||
if (changedTransactionDetail != null) {
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder().withEntityId(savedVariation.getId()).build();
|
return new CommandProcessingResultBuilder().withEntityId(savedVariation.getId()).build();
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ package org.apache.fineract.portfolio.interestpauses.service;
|
|||||||
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
|
|
||||||
public interface AccountTransfersService {
|
public interface LoanAccountTransfersService {
|
||||||
|
|
||||||
void updateLoanTransaction(Long loanTransactionId, LoanTransaction newLoanTransaction);
|
void updateLoanTransaction(Long loanTransactionId, LoanTransaction newLoanTransaction);
|
||||||
|
|
||||||
+27
-52
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.portfolio.loanaccount.domain;
|
package org.apache.fineract.portfolio.loanaccount.domain;
|
||||||
|
|
||||||
|
import static org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType.CUMULATIVE;
|
||||||
import static org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType.PROGRESSIVE;
|
import static org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType.PROGRESSIVE;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
@@ -829,7 +830,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
return lastRepaymentDate;
|
return lastRepaymentDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeLoanCharge(final LoanCharge loanCharge) {
|
public Optional<ChangedTransactionDetail> removeLoanCharge(final LoanCharge loanCharge) {
|
||||||
final boolean removed = loanCharge.isActive();
|
final boolean removed = loanCharge.isActive();
|
||||||
if (removed) {
|
if (removed) {
|
||||||
loanCharge.setActive(false);
|
loanCharge.setActive(false);
|
||||||
@@ -848,10 +849,12 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
* Consider removing this block of code or logically completing it for the future by getting the list of
|
* Consider removing this block of code or logically completing it for the future by getting the list of
|
||||||
* affected Transactions
|
* affected Transactions
|
||||||
*/
|
*/
|
||||||
reprocessTransactions();
|
return Optional.ofNullable(reprocessTransactions());
|
||||||
}
|
}
|
||||||
this.charges.remove(loanCharge);
|
this.charges.remove(loanCharge);
|
||||||
updateLoanSummaryDerivedFields();
|
updateLoanSummaryDerivedFields();
|
||||||
|
|
||||||
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursement(final LoanCharge loanCharge) {
|
private void removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursement(final LoanCharge loanCharge) {
|
||||||
@@ -900,37 +903,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
.anyMatch(loanChargePaidBy -> loanChargePaidBy.getLoanCharge().equals(loanCharge));
|
.anyMatch(loanChargePaidBy -> loanChargePaidBy.getLoanCharge().equals(loanCharge));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> updateLoanCharge(final LoanCharge loanCharge, final JsonCommand command) {
|
|
||||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(3);
|
|
||||||
|
|
||||||
if (getActiveCharges().contains(loanCharge)) {
|
|
||||||
final BigDecimal amount = calculateAmountPercentageAppliedTo(loanCharge);
|
|
||||||
final Map<String, Object> loanChargeChanges = loanCharge.update(command, amount);
|
|
||||||
actualChanges.putAll(loanChargeChanges);
|
|
||||||
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
|
||||||
}
|
|
||||||
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor();
|
|
||||||
if (!loanCharge.isDueAtDisbursement()) {
|
|
||||||
/*
|
|
||||||
* TODO Vishwas Currently we do not allow waiving updating loan charge after a loan is approved (hence there
|
|
||||||
* is no need to adjust any loan transactions).
|
|
||||||
*
|
|
||||||
* Consider removing this block of code or logically completing it for the future by getting the list of
|
|
||||||
* affected Transactions
|
|
||||||
*/
|
|
||||||
reprocessTransactions();
|
|
||||||
} else {
|
|
||||||
// reprocess loan schedule based on charge been waived.
|
|
||||||
final LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper();
|
|
||||||
wrapper.reprocess(getCurrency(), getDisbursementDate(), getRepaymentScheduleInstallments(), getActiveCharges());
|
|
||||||
}
|
|
||||||
|
|
||||||
updateLoanSummaryDerivedFields();
|
|
||||||
|
|
||||||
return actualChanges;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal calculateAmountPercentageAppliedTo(final LoanCharge loanCharge) {
|
public BigDecimal calculateAmountPercentageAppliedTo(final LoanCharge loanCharge) {
|
||||||
if (loanCharge.isOverdueInstallmentCharge()) {
|
if (loanCharge.isOverdueInstallmentCharge()) {
|
||||||
return loanCharge.getAmountPercentageAppliedTo();
|
return loanCharge.getAmountPercentageAppliedTo();
|
||||||
@@ -1881,10 +1853,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
return getStatus().isClosedWrittenOff();
|
return getStatus().isClosedWrittenOff();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isClosedWithOutstandingAmountMarkedForReschedule() {
|
|
||||||
return getStatus().isClosedWithOutsandingAmountMarkedForReschedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCancelled() {
|
public boolean isCancelled() {
|
||||||
return isRejected() || isWithdrawn();
|
return isRejected() || isWithdrawn();
|
||||||
}
|
}
|
||||||
@@ -2696,20 +2664,25 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
/*
|
/*
|
||||||
* Probably this is buggy when a chargeback transaction happens
|
* Probably this is buggy when a chargeback transaction happens
|
||||||
*/
|
*/
|
||||||
public void processPostDisbursementTransactions() {
|
public Optional<ChangedTransactionDetail> processPostDisbursementTransactions() {
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor();
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor();
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
||||||
final List<LoanTransaction> copyTransactions = new ArrayList<>();
|
final List<LoanTransaction> copyTransactions = new ArrayList<>();
|
||||||
if (!allNonContraTransactionsPostDisbursement.isEmpty()) {
|
|
||||||
// TODO: Probably this is not needed and can be eliminated, make sure to double check it
|
|
||||||
for (LoanTransaction loanTransaction : allNonContraTransactionsPostDisbursement) {
|
|
||||||
copyTransactions.add(LoanTransaction.copyTransactionProperties(loanTransaction));
|
|
||||||
}
|
|
||||||
loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(), copyTransactions, getCurrency(),
|
|
||||||
getRepaymentScheduleInstallments(), getActiveCharges());
|
|
||||||
|
|
||||||
updateLoanSummaryDerivedFields();
|
if (allNonContraTransactionsPostDisbursement.isEmpty()) {
|
||||||
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Probably this is not needed and can be eliminated, make sure to double check it
|
||||||
|
for (LoanTransaction loanTransaction : allNonContraTransactionsPostDisbursement) {
|
||||||
|
copyTransactions.add(LoanTransaction.copyTransactionProperties(loanTransaction));
|
||||||
|
}
|
||||||
|
final ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(
|
||||||
|
getDisbursementDate(), copyTransactions, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
|
||||||
|
|
||||||
|
updateLoanSummaryDerivedFields();
|
||||||
|
|
||||||
|
return Optional.of(changedTransactionDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoanScheduleDTO getRecalculatedSchedule(final ScheduleGeneratorDTO generatorDTO) {
|
public LoanScheduleDTO getRecalculatedSchedule(final ScheduleGeneratorDTO generatorDTO) {
|
||||||
@@ -2826,7 +2799,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
Money totalInterest = Money.zero(getCurrency());
|
Money totalInterest = Money.zero(getCurrency());
|
||||||
Money feeCharges = Money.zero(getCurrency());
|
Money feeCharges = Money.zero(getCurrency());
|
||||||
Money penaltyCharges = Money.zero(getCurrency());
|
Money penaltyCharges = Money.zero(getCurrency());
|
||||||
final Set<LoanInterestRecalcualtionAdditionalDetails> compoundingDetails = null;
|
|
||||||
List<LoanRepaymentScheduleInstallment> repaymentSchedule = getRepaymentScheduleInstallments();
|
List<LoanRepaymentScheduleInstallment> repaymentSchedule = getRepaymentScheduleInstallments();
|
||||||
for (final LoanRepaymentScheduleInstallment scheduledRepayment : repaymentSchedule) {
|
for (final LoanRepaymentScheduleInstallment scheduledRepayment : repaymentSchedule) {
|
||||||
totalPrincipal = totalPrincipal.plus(scheduledRepayment.getPrincipalOutstanding(getCurrency()));
|
totalPrincipal = totalPrincipal.plus(scheduledRepayment.getPrincipalOutstanding(getCurrency()));
|
||||||
@@ -3106,11 +3078,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
return this.createStandingInstructionAtDisbursement != null && this.createStandingInstructionAtDisbursement;
|
return this.createStandingInstructionAtDisbursement != null && this.createStandingInstructionAtDisbursement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<LoanCharge> getLoanChargesByDueDate(LocalDate dueDate) {
|
|
||||||
return getLoanCharges(
|
|
||||||
loanCharge -> loanCharge.getDueLocalDate() != null && DateUtils.isEqual(loanCharge.getDueLocalDate(), dueDate));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param predicate
|
* @param predicate
|
||||||
* filter of the charges
|
* filter of the charges
|
||||||
@@ -3591,6 +3558,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
return getLoanProductRelatedDetail().getLoanScheduleType() == PROGRESSIVE;
|
return getLoanProductRelatedDetail().getLoanScheduleType() == PROGRESSIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCumulativeSchedule() {
|
||||||
|
return getLoanProductRelatedDetail().getLoanScheduleType() == CUMULATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isChargeOffOnDate(final LocalDate onDate) {
|
public boolean isChargeOffOnDate(final LocalDate onDate) {
|
||||||
final LoanTransaction chargeOffTransaction = findChargedOffTransaction();
|
final LoanTransaction chargeOffTransaction = findChargedOffTransaction();
|
||||||
return (chargeOffTransaction == null) ? false : (chargeOffTransaction.getDateOf().compareTo(onDate) <= 0);
|
return (chargeOffTransaction == null) ? false : (chargeOffTransaction.getDateOf().compareTo(onDate) <= 0);
|
||||||
@@ -3609,4 +3580,8 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasChargeOffTransaction() {
|
||||||
|
return getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-6
@@ -74,12 +74,6 @@ public interface LoanAccountDomainService {
|
|||||||
boolean isRecoveryRepayment, String chargeRefundChargeType, boolean isAccountTransfer, HolidayDetailDTO holidayDetailDto,
|
boolean isRecoveryRepayment, String chargeRefundChargeType, boolean isAccountTransfer, HolidayDetailDTO holidayDetailDto,
|
||||||
Boolean isHolidayValidationDone, boolean isLoanToLoanTransfer);
|
Boolean isHolidayValidationDone, boolean isLoanToLoanTransfer);
|
||||||
|
|
||||||
LoanTransaction saveLoanTransactionWithDataIntegrityViolationChecks(LoanTransaction newRepaymentTransaction);
|
|
||||||
|
|
||||||
Loan saveAndFlushLoanWithDataIntegrityViolationChecks(Loan loan);
|
|
||||||
|
|
||||||
Loan saveLoanWithDataIntegrityViolationChecks(Loan loan);
|
|
||||||
|
|
||||||
LoanTransaction foreCloseLoan(Loan loan, LocalDate foreClourseDate, String noteText, ExternalId externalId,
|
LoanTransaction foreCloseLoan(Loan loan, LocalDate foreClourseDate, String noteText, ExternalId externalId,
|
||||||
Map<String, Object> changes);
|
Map<String, Object> changes);
|
||||||
|
|
||||||
|
|||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.loanaccount.domain;
|
||||||
|
|
||||||
|
public interface LoanAccountService {
|
||||||
|
|
||||||
|
LoanTransaction saveLoanTransactionWithDataIntegrityViolationChecks(LoanTransaction newRepaymentTransaction);
|
||||||
|
|
||||||
|
Loan saveAndFlushLoanWithDataIntegrityViolationChecks(Loan loan);
|
||||||
|
|
||||||
|
Loan saveLoanWithDataIntegrityViolationChecks(Loan loan);
|
||||||
|
|
||||||
|
}
|
||||||
+1
-2
@@ -20,7 +20,6 @@ package org.apache.fineract.portfolio.loanaccount.service;
|
|||||||
|
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
@@ -30,7 +29,7 @@ public interface LoanDownPaymentHandlerService {
|
|||||||
LoanTransaction handleDownPayment(ScheduleGeneratorDTO scheduleGeneratorDTO, JsonCommand command,
|
LoanTransaction handleDownPayment(ScheduleGeneratorDTO scheduleGeneratorDTO, JsonCommand command,
|
||||||
LoanTransaction disbursementTransaction, Loan loan);
|
LoanTransaction disbursementTransaction, Loan loan);
|
||||||
|
|
||||||
ChangedTransactionDetail handleRepaymentOrRecoveryOrWaiverTransaction(Loan loan, LoanTransaction newTransactionDetail,
|
void handleRepaymentOrRecoveryOrWaiverTransaction(Loan loan, LoanTransaction newTransactionDetail,
|
||||||
LoanLifecycleStateMachine loanLifecycleStateMachine, LoanTransaction transactionForAdjustment,
|
LoanLifecycleStateMachine loanLifecycleStateMachine, LoanTransaction transactionForAdjustment,
|
||||||
ScheduleGeneratorDTO scheduleGeneratorDTO);
|
ScheduleGeneratorDTO scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-13
@@ -36,7 +36,6 @@ import org.apache.fineract.infrastructure.event.business.service.BusinessEventNo
|
|||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
|
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanEvent;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanEvent;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
||||||
@@ -48,7 +47,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.Mon
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
||||||
import org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanStateTransitionException;
|
import org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanStateTransitionException;
|
||||||
import org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanTransactionTypeException;
|
import org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanTransactionTypeException;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanDownPaymentTransactionValidator;
|
import org.apache.fineract.portfolio.loanaccount.serialization.LoanDownPaymentTransactionValidator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanRefundValidator;
|
import org.apache.fineract.portfolio.loanaccount.serialization.LoanRefundValidator;
|
||||||
|
|
||||||
@@ -62,6 +60,7 @@ public class LoanDownPaymentHandlerServiceImpl implements LoanDownPaymentHandler
|
|||||||
private final LoanScheduleService loanScheduleService;
|
private final LoanScheduleService loanScheduleService;
|
||||||
private final LoanRefundService loanRefundService;
|
private final LoanRefundService loanRefundService;
|
||||||
private final LoanRefundValidator loanRefundValidator;
|
private final LoanRefundValidator loanRefundValidator;
|
||||||
|
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanTransaction handleDownPayment(ScheduleGeneratorDTO scheduleGeneratorDTO, JsonCommand command,
|
public LoanTransaction handleDownPayment(ScheduleGeneratorDTO scheduleGeneratorDTO, JsonCommand command,
|
||||||
@@ -77,11 +76,9 @@ public class LoanDownPaymentHandlerServiceImpl implements LoanDownPaymentHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChangedTransactionDetail handleRepaymentOrRecoveryOrWaiverTransaction(final Loan loan, final LoanTransaction loanTransaction,
|
public void handleRepaymentOrRecoveryOrWaiverTransaction(final Loan loan, final LoanTransaction loanTransaction,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction adjustedTransaction,
|
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction adjustedTransaction,
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||||
ChangedTransactionDetail changedTransactionDetail = null;
|
|
||||||
|
|
||||||
if (loanTransaction.isRecoveryRepayment()) {
|
if (loanTransaction.isRecoveryRepayment()) {
|
||||||
loanLifecycleStateMachine.transition(LoanEvent.LOAN_RECOVERY_PAYMENT, loan);
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_RECOVERY_PAYMENT, loan);
|
||||||
}
|
}
|
||||||
@@ -155,15 +152,12 @@ public class LoanDownPaymentHandlerServiceImpl implements LoanDownPaymentHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (reprocess) {
|
if (reprocess) {
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()
|
if (loan.isCumulativeSchedule() && loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
&& !loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)) {
|
|
||||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||||
} else if (loan.getLoanProductRelatedDetail() != null
|
} else if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
&& loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)
|
|
||||||
&& loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff)) {
|
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
changedTransactionDetail = loan.reprocessTransactions();
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
loan.updateLoanSummaryDerivedFields();
|
loan.updateLoanSummaryDerivedFields();
|
||||||
@@ -185,8 +179,6 @@ public class LoanDownPaymentHandlerServiceImpl implements LoanDownPaymentHandler
|
|||||||
throw new InvalidLoanStateTransitionException("transaction", "amount.exceeds.threshold", errorMessage);
|
throw new InvalidLoanStateTransitionException("transaction", "amount.exceeds.threshold", errorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changedTransactionDetail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LoanTransaction handleDownPayment(final Loan loan, final LoanTransaction disbursementTransaction, final JsonCommand command,
|
private LoanTransaction handleDownPayment(final Loan loan, final LoanTransaction disbursementTransaction, final JsonCommand command,
|
||||||
|
|||||||
+5
-11
@@ -65,7 +65,7 @@ public class LoanRefundService {
|
|||||||
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
||||||
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
||||||
|
|
||||||
handleRefundTransaction(loan, loanTransaction, loanLifecycleStateMachine, null);
|
handleRefundTransaction(loan, loanTransaction, loanLifecycleStateMachine);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void creditBalanceRefund(final Loan loan, final LoanTransaction newCreditBalanceRefundTransaction,
|
public void creditBalanceRefund(final Loan loan, final LoanTransaction newCreditBalanceRefundTransaction,
|
||||||
@@ -88,7 +88,7 @@ public class LoanRefundService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleRefundTransaction(final Loan loan, final LoanTransaction loanTransaction,
|
private void handleRefundTransaction(final Loan loan, final LoanTransaction loanTransaction,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction adjustedTransaction) {
|
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
||||||
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REFUND, loan);
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REFUND, loan);
|
||||||
|
|
||||||
loanTransaction.updateLoan(loan);
|
loanTransaction.updateLoan(loan);
|
||||||
@@ -104,18 +104,12 @@ public class LoanRefundService {
|
|||||||
final LocalDate loanTransactionDate = extractTransactionDate(loan, loanTransaction);
|
final LocalDate loanTransactionDate = extractTransactionDate(loan, loanTransaction);
|
||||||
|
|
||||||
loanRefundValidator.validateTransactionDateNotInFuture(loanTransactionDate);
|
loanRefundValidator.validateTransactionDateNotInFuture(loanTransactionDate);
|
||||||
loanRefundValidator.validateTransactionAmountThreshold(loan, adjustedTransaction);
|
loanRefundValidator.validateTransactionAmountThreshold(loan, null);
|
||||||
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor();
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor();
|
||||||
|
|
||||||
// If it's a refund
|
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(loanTransaction, new TransactionCtx(loan.getCurrency(),
|
||||||
if (adjustedTransaction == null) {
|
loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(), new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
||||||
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(loanTransaction,
|
|
||||||
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
|
||||||
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
|
||||||
} else {
|
|
||||||
loan.reprocessTransactions();
|
|
||||||
}
|
|
||||||
|
|
||||||
loan.updateLoanSummaryDerivedFields();
|
loan.updateLoanSummaryDerivedFields();
|
||||||
loan.doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
loan.doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
||||||
|
|||||||
+7
-8
@@ -24,7 +24,6 @@ import java.util.Set;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO;
|
||||||
@@ -35,6 +34,7 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanSchedul
|
|||||||
public class LoanScheduleService {
|
public class LoanScheduleService {
|
||||||
|
|
||||||
private final LoanChargeService loanChargeService;
|
private final LoanChargeService loanChargeService;
|
||||||
|
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ability to regenerate the repayment schedule based on the loans current details/state.
|
* Ability to regenerate the repayment schedule based on the loans current details/state.
|
||||||
@@ -59,10 +59,10 @@ public class LoanScheduleService {
|
|||||||
} else {
|
} else {
|
||||||
regenerateRepaymentSchedule(loan, generatorDTO);
|
regenerateRepaymentSchedule(loan, generatorDTO);
|
||||||
}
|
}
|
||||||
loan.reprocessTransactions();
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChangedTransactionDetail recalculateScheduleFromLastTransaction(final Loan loan, final ScheduleGeneratorDTO generatorDTO,
|
public void recalculateScheduleFromLastTransaction(final Loan loan, final ScheduleGeneratorDTO generatorDTO,
|
||||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
||||||
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
||||||
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
||||||
@@ -73,7 +73,8 @@ public class LoanScheduleService {
|
|||||||
regenerateRepaymentSchedule(loan, generatorDTO);
|
regenerateRepaymentSchedule(loan, generatorDTO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return loan.reprocessTransactions();
|
|
||||||
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void regenerateRepaymentScheduleWithInterestRecalculation(final Loan loan, final ScheduleGeneratorDTO generatorDTO) {
|
public void regenerateRepaymentScheduleWithInterestRecalculation(final Loan loan, final ScheduleGeneratorDTO generatorDTO) {
|
||||||
@@ -106,13 +107,11 @@ public class LoanScheduleService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loan.processPostDisbursementTransactions();
|
loan.processPostDisbursementTransactions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChangedTransactionDetail handleRegenerateRepaymentScheduleWithInterestRecalculation(final Loan loan,
|
public void handleRegenerateRepaymentScheduleWithInterestRecalculation(final Loan loan, final ScheduleGeneratorDTO generatorDTO) {
|
||||||
final ScheduleGeneratorDTO generatorDTO) {
|
|
||||||
regenerateRepaymentScheduleWithInterestRecalculation(loan, generatorDTO);
|
regenerateRepaymentScheduleWithInterestRecalculation(loan, generatorDTO);
|
||||||
return loan.reprocessTransactions();
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.loanaccount.service;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
|
|
||||||
|
public interface ReprocessLoanTransactionsService {
|
||||||
|
|
||||||
|
void reprocessTransactions(Loan loan);
|
||||||
|
|
||||||
|
void reprocessTransactionsWithPostTransactionChecks(Loan loan, LocalDate transactionDate);
|
||||||
|
|
||||||
|
void processPostDisbursementTransactions(Loan loan);
|
||||||
|
|
||||||
|
void removeLoanCharge(Loan loan, LoanCharge loanCharge);
|
||||||
|
|
||||||
|
}
|
||||||
+74
@@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.loanaccount.service;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.fineract.portfolio.interestpauses.service.LoanAccountTransfersService;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountService;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ReprocessLoanTransactionsServiceImpl implements ReprocessLoanTransactionsService {
|
||||||
|
|
||||||
|
private final LoanAccountService loanAccountService;
|
||||||
|
private final LoanAccountTransfersService loanAccountTransfersService;
|
||||||
|
private final ReplayedTransactionBusinessEventService replayedTransactionBusinessEventService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reprocessTransactions(final Loan loan) {
|
||||||
|
final ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactions();
|
||||||
|
if (changedTransactionDetail != null) {
|
||||||
|
handleChangedDetail(changedTransactionDetail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reprocessTransactionsWithPostTransactionChecks(final Loan loan, final LocalDate transactionDate) {
|
||||||
|
final ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactionsWithPostTransactionChecks(transactionDate);
|
||||||
|
if (changedTransactionDetail != null) {
|
||||||
|
handleChangedDetail(changedTransactionDetail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processPostDisbursementTransactions(final Loan loan) {
|
||||||
|
loan.processPostDisbursementTransactions().ifPresent(this::handleChangedDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeLoanCharge(final Loan loan, final LoanCharge loanCharge) {
|
||||||
|
loan.removeLoanCharge(loanCharge).ifPresent(this::handleChangedDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleChangedDetail(final ChangedTransactionDetail changedTransactionDetail) {
|
||||||
|
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
||||||
|
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
||||||
|
loanAccountTransfersService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
||||||
|
}
|
||||||
|
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+1
-2
@@ -24,9 +24,8 @@ import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
|||||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||||
import org.apache.fineract.portfolio.account.data.AccountTransferDTO;
|
import org.apache.fineract.portfolio.account.data.AccountTransferDTO;
|
||||||
import org.apache.fineract.portfolio.account.domain.AccountTransferDetails;
|
import org.apache.fineract.portfolio.account.domain.AccountTransferDetails;
|
||||||
import org.apache.fineract.portfolio.interestpauses.service.AccountTransfersService;
|
|
||||||
|
|
||||||
public interface AccountTransfersWritePlatformService extends AccountTransfersService {
|
public interface AccountTransfersWritePlatformService {
|
||||||
|
|
||||||
CommandProcessingResult create(JsonCommand command);
|
CommandProcessingResult create(JsonCommand command);
|
||||||
|
|
||||||
|
|||||||
-10
@@ -502,16 +502,6 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
|||||||
return accountTransferDetails;
|
return accountTransferDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional
|
|
||||||
public void updateLoanTransaction(final Long loanTransactionId, final LoanTransaction newLoanTransaction) {
|
|
||||||
final AccountTransferTransaction transferTransaction = this.accountTransferRepository.findByToLoanTransactionId(loanTransactionId);
|
|
||||||
if (transferTransaction != null) {
|
|
||||||
transferTransaction.updateToLoanTransaction(newLoanTransaction);
|
|
||||||
this.accountTransferRepository.save(transferTransaction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isLoanToSavingsAccountTransfer(final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType) {
|
private boolean isLoanToSavingsAccountTransfer(final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType) {
|
||||||
return fromAccountType.isLoanAccount() && toAccountType.isSavingsAccount();
|
return fromAccountType.isLoanAccount() && toAccountType.isSavingsAccount();
|
||||||
}
|
}
|
||||||
|
|||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.account.service;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.fineract.portfolio.account.domain.AccountTransferRepository;
|
||||||
|
import org.apache.fineract.portfolio.account.domain.AccountTransferTransaction;
|
||||||
|
import org.apache.fineract.portfolio.interestpauses.service.LoanAccountTransfersService;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class LoanAccountTransfersServiceImpl implements LoanAccountTransfersService {
|
||||||
|
|
||||||
|
private final AccountTransferRepository accountTransferRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void updateLoanTransaction(final Long loanTransactionId, final LoanTransaction newLoanTransaction) {
|
||||||
|
final AccountTransferTransaction transferTransaction = this.accountTransferRepository.findByToLoanTransactionId(loanTransactionId);
|
||||||
|
if (transferTransaction != null) {
|
||||||
|
transferTransaction.updateToLoanTransaction(newLoanTransaction);
|
||||||
|
this.accountTransferRepository.save(transferTransaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+29
-131
@@ -32,13 +32,10 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
|
import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
|
||||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||||
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||||
@@ -77,9 +74,7 @@ import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
|||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
import org.apache.fineract.organisation.workingdays.domain.WorkingDays;
|
import org.apache.fineract.organisation.workingdays.domain.WorkingDays;
|
||||||
import org.apache.fineract.organisation.workingdays.domain.WorkingDaysRepositoryWrapper;
|
import org.apache.fineract.organisation.workingdays.domain.WorkingDaysRepositoryWrapper;
|
||||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRepository;
|
|
||||||
import org.apache.fineract.portfolio.account.domain.AccountTransferStandingInstruction;
|
import org.apache.fineract.portfolio.account.domain.AccountTransferStandingInstruction;
|
||||||
import org.apache.fineract.portfolio.account.domain.AccountTransferTransaction;
|
|
||||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionRepository;
|
import org.apache.fineract.portfolio.account.domain.StandingInstructionRepository;
|
||||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionStatus;
|
import org.apache.fineract.portfolio.account.domain.StandingInstructionStatus;
|
||||||
import org.apache.fineract.portfolio.client.domain.Client;
|
import org.apache.fineract.portfolio.client.domain.Client;
|
||||||
@@ -99,7 +94,6 @@ import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanDownPaymentTransactionValidator;
|
import org.apache.fineract.portfolio.loanaccount.serialization.LoanDownPaymentTransactionValidator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanForeclosureValidator;
|
import org.apache.fineract.portfolio.loanaccount.serialization.LoanForeclosureValidator;
|
||||||
@@ -114,7 +108,7 @@ import org.apache.fineract.portfolio.loanaccount.service.LoanDownPaymentHandlerS
|
|||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanRefundService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanRefundService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanScheduleService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanScheduleService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.ReplayedTransactionBusinessEventService;
|
import org.apache.fineract.portfolio.loanaccount.service.ReprocessLoanTransactionsService;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanSupportedInterestRefundTypes;
|
import org.apache.fineract.portfolio.loanproduct.domain.LoanSupportedInterestRefundTypes;
|
||||||
import org.apache.fineract.portfolio.note.domain.Note;
|
import org.apache.fineract.portfolio.note.domain.Note;
|
||||||
import org.apache.fineract.portfolio.note.domain.NoteRepository;
|
import org.apache.fineract.portfolio.note.domain.NoteRepository;
|
||||||
@@ -122,8 +116,6 @@ import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
|||||||
import org.apache.fineract.portfolio.repaymentwithpostdatedchecks.data.PostDatedChecksStatus;
|
import org.apache.fineract.portfolio.repaymentwithpostdatedchecks.data.PostDatedChecksStatus;
|
||||||
import org.apache.fineract.portfolio.repaymentwithpostdatedchecks.domain.PostDatedChecks;
|
import org.apache.fineract.portfolio.repaymentwithpostdatedchecks.domain.PostDatedChecks;
|
||||||
import org.apache.fineract.portfolio.repaymentwithpostdatedchecks.domain.PostDatedChecksRepository;
|
import org.apache.fineract.portfolio.repaymentwithpostdatedchecks.domain.PostDatedChecksRepository;
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
|
||||||
import org.springframework.orm.jpa.JpaSystemException;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@@ -141,7 +133,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
|
|
||||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||||
private final NoteRepository noteRepository;
|
private final NoteRepository noteRepository;
|
||||||
private final AccountTransferRepository accountTransferRepository;
|
|
||||||
private final BusinessEventNotifierService businessEventNotifierService;
|
private final BusinessEventNotifierService businessEventNotifierService;
|
||||||
private final LoanUtilService loanUtilService;
|
private final LoanUtilService loanUtilService;
|
||||||
private final StandingInstructionRepository standingInstructionRepository;
|
private final StandingInstructionRepository standingInstructionRepository;
|
||||||
@@ -150,7 +141,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
private final DelinquencyWritePlatformService delinquencyWritePlatformService;
|
private final DelinquencyWritePlatformService delinquencyWritePlatformService;
|
||||||
private final LoanLifecycleStateMachine defaultLoanLifecycleStateMachine;
|
private final LoanLifecycleStateMachine defaultLoanLifecycleStateMachine;
|
||||||
private final ExternalIdFactory externalIdFactory;
|
private final ExternalIdFactory externalIdFactory;
|
||||||
private final ReplayedTransactionBusinessEventService replayedTransactionBusinessEventService;
|
|
||||||
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
||||||
private final DelinquencyEffectivePauseHelper delinquencyEffectivePauseHelper;
|
private final DelinquencyEffectivePauseHelper delinquencyEffectivePauseHelper;
|
||||||
private final DelinquencyReadPlatformService delinquencyReadPlatformService;
|
private final DelinquencyReadPlatformService delinquencyReadPlatformService;
|
||||||
@@ -165,6 +155,8 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
private final LoanDownPaymentHandlerService loanDownPaymentHandlerService;
|
private final LoanDownPaymentHandlerService loanDownPaymentHandlerService;
|
||||||
private final LoanChargeValidator loanChargeValidator;
|
private final LoanChargeValidator loanChargeValidator;
|
||||||
private final LoanRefundService loanRefundService;
|
private final LoanRefundService loanRefundService;
|
||||||
|
private final LoanAccountService loanAccountService;
|
||||||
|
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
@@ -264,30 +256,16 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
loanDownPaymentTransactionValidator.validateRepaymentTypeAccountStatus(loan, newRepaymentTransaction, event);
|
loanDownPaymentTransactionValidator.validateRepaymentTypeAccountStatus(loan, newRepaymentTransaction, event);
|
||||||
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, event,
|
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, event,
|
||||||
newRepaymentTransaction.getTransactionDate());
|
newRepaymentTransaction.getTransactionDate());
|
||||||
final ChangedTransactionDetail changedTransactionDetail = makeRepayment(loan, newRepaymentTransaction,
|
makeRepayment(loan, newRepaymentTransaction, defaultLoanLifecycleStateMachine, existingTransactionIds,
|
||||||
defaultLoanLifecycleStateMachine, existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO);
|
existingReversedTransactionIds, scheduleGeneratorDTO);
|
||||||
|
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveLoanTransactionWithDataIntegrityViolationChecks(newRepaymentTransaction);
|
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newRepaymentTransaction);
|
||||||
|
loan = loanAccountService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
/***
|
|
||||||
* TODO Vishwas Batch save is giving me a HibernateOptimisticLockingFailureException, looping and saving for the
|
|
||||||
* time being, not a major issue for now as this loop is entered only in edge cases (when a payment is made
|
|
||||||
* before the latest payment recorded against the loan)
|
|
||||||
***/
|
|
||||||
if (changedTransactionDetail != null) {
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
updateLoanTransferTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(noteText)) {
|
if (StringUtils.isNotBlank(noteText)) {
|
||||||
final Note note = Note.loanTransactionNote(loan, newRepaymentTransaction, noteText);
|
final Note note = Note.loanTransactionNote(loan, newRepaymentTransaction, noteText);
|
||||||
@@ -395,50 +373,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
return repaymentEvent;
|
return repaymentEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public LoanTransaction saveLoanTransactionWithDataIntegrityViolationChecks(LoanTransaction newRepaymentTransaction) {
|
|
||||||
try {
|
|
||||||
return this.loanTransactionRepository.saveAndFlush(newRepaymentTransaction);
|
|
||||||
} catch (final JpaSystemException | DataIntegrityViolationException e) {
|
|
||||||
raiseValidationExceptionForUniqueConstraintViolation(e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Loan saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) {
|
|
||||||
try {
|
|
||||||
return this.loanRepositoryWrapper.saveAndFlush(loan);
|
|
||||||
} catch (final JpaSystemException | DataIntegrityViolationException e) {
|
|
||||||
raiseValidationExceptionForUniqueConstraintViolation(e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Loan saveLoanWithDataIntegrityViolationChecks(final Loan loan) {
|
|
||||||
try {
|
|
||||||
return this.loanRepositoryWrapper.save(loan);
|
|
||||||
} catch (final JpaSystemException | DataIntegrityViolationException e) {
|
|
||||||
raiseValidationExceptionForUniqueConstraintViolation(e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void raiseValidationExceptionForUniqueConstraintViolation(Exception e) {
|
|
||||||
final Throwable realCause = e.getCause();
|
|
||||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
|
||||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.transaction");
|
|
||||||
if (realCause.getMessage().toLowerCase().contains("external_id_unique") || realCause.getMessage()
|
|
||||||
.contains("duplicate key value violates unique constraint \"m_loan_transaction_external_id_key\"")) {
|
|
||||||
baseDataValidator.reset().parameter("externalId").failWithCode("value.must.be.unique");
|
|
||||||
}
|
|
||||||
if (!dataValidationErrors.isEmpty()) {
|
|
||||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
|
||||||
dataValidationErrors, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public LoanTransaction makeChargePayment(final Loan loan, final Long chargeId, final LocalDate transactionDate,
|
public LoanTransaction makeChargePayment(final Loan loan, final Long chargeId, final LocalDate transactionDate,
|
||||||
@@ -487,8 +421,8 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
loanChargeService.makeChargePayment(loan, chargeId, defaultLoanLifecycleStateMachine, existingTransactionIds,
|
loanChargeService.makeChargePayment(loan, chargeId, defaultLoanLifecycleStateMachine, existingTransactionIds,
|
||||||
existingReversedTransactionIds, newPaymentTransaction, installmentNumber);
|
existingReversedTransactionIds, newPaymentTransaction, installmentNumber);
|
||||||
}
|
}
|
||||||
saveLoanTransactionWithDataIntegrityViolationChecks(newPaymentTransaction);
|
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newPaymentTransaction);
|
||||||
saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
loanAccountService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(noteText)) {
|
if (StringUtils.isNotBlank(noteText)) {
|
||||||
final Note note = Note.loanTransactionNote(loan, newPaymentTransaction, noteText);
|
final Note note = Note.loanTransactionNote(loan, newPaymentTransaction, noteText);
|
||||||
@@ -579,7 +513,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
loanRefundService.makeRefund(loan, newRefundTransaction, defaultLoanLifecycleStateMachine, existingTransactionIds,
|
loanRefundService.makeRefund(loan, newRefundTransaction, defaultLoanLifecycleStateMachine, existingTransactionIds,
|
||||||
existingReversedTransactionIds);
|
existingReversedTransactionIds);
|
||||||
|
|
||||||
saveLoanTransactionWithDataIntegrityViolationChecks(newRefundTransaction);
|
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newRefundTransaction);
|
||||||
this.loanRepositoryWrapper.saveAndFlush(loan);
|
this.loanRepositoryWrapper.saveAndFlush(loan);
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(noteText)) {
|
if (StringUtils.isNotBlank(noteText)) {
|
||||||
@@ -628,8 +562,8 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
|
|
||||||
disbursementTransaction.updateLoan(loan);
|
disbursementTransaction.updateLoan(loan);
|
||||||
loan.addLoanTransaction(disbursementTransaction);
|
loan.addLoanTransaction(disbursementTransaction);
|
||||||
saveLoanTransactionWithDataIntegrityViolationChecks(disbursementTransaction);
|
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(disbursementTransaction);
|
||||||
saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
loanAccountService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(noteText)) {
|
if (StringUtils.isNotBlank(noteText)) {
|
||||||
final Note note = Note.loanTransactionNote(loan, disbursementTransaction, noteText);
|
final Note note = Note.loanTransactionNote(loan, disbursementTransaction, noteText);
|
||||||
@@ -651,7 +585,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
}
|
}
|
||||||
loanChargeValidator.validateRepaymentTypeTransactionNotBeforeAChargeRefund(loanTransaction.getLoan(), loanTransaction, "reversed");
|
loanChargeValidator.validateRepaymentTypeTransactionNotBeforeAChargeRefund(loanTransaction.getLoan(), loanTransaction, "reversed");
|
||||||
loanTransaction.reverse();
|
loanTransaction.reverse();
|
||||||
saveLoanTransactionWithDataIntegrityViolationChecks(loanTransaction);
|
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(loanTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -686,14 +620,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLoanTransferTransaction(final Long loanTransactionId, final LoanTransaction newLoanTransaction) {
|
|
||||||
final AccountTransferTransaction transferTransaction = this.accountTransferRepository.findByToLoanTransactionId(loanTransactionId);
|
|
||||||
if (transferTransaction != null) {
|
|
||||||
transferTransaction.updateToLoanTransaction(newLoanTransaction);
|
|
||||||
this.accountTransferRepository.save(transferTransaction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanTransaction creditBalanceRefund(final Loan loan, final LocalDate transactionDate, final BigDecimal transactionAmount,
|
public LoanTransaction creditBalanceRefund(final Loan loan, final LocalDate transactionDate, final BigDecimal transactionAmount,
|
||||||
final String noteText, final ExternalId externalId, PaymentDetail paymentDetail) {
|
final String noteText, final ExternalId externalId, PaymentDetail paymentDetail) {
|
||||||
@@ -841,36 +767,21 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
loanForeclosureValidator.validateForForeclosure(loan, payment.getTransactionDate());
|
loanForeclosureValidator.validateForForeclosure(loan, payment.getTransactionDate());
|
||||||
}
|
}
|
||||||
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.LOAN_FORECLOSURE);
|
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.LOAN_FORECLOSURE);
|
||||||
final ChangedTransactionDetail changedTransactionDetail = handleForeClosureTransactions(loan, payment,
|
handleForeClosureTransactions(loan, payment, defaultLoanLifecycleStateMachine, scheduleGeneratorDTO);
|
||||||
defaultLoanLifecycleStateMachine, scheduleGeneratorDTO);
|
|
||||||
|
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
|
||||||
* TODO Vishwas Batch save is giving me a HibernateOptimisticLockingFailureException, looping and saving for the
|
|
||||||
* time being, not a major issue for now as this loop is entered only in edge cases (when a payment is made
|
|
||||||
* before the latest payment recorded against the loan)
|
|
||||||
***/
|
|
||||||
|
|
||||||
for (LoanTransaction newTransaction : newTransactions) {
|
for (LoanTransaction newTransaction : newTransactions) {
|
||||||
saveLoanTransactionWithDataIntegrityViolationChecks(newTransaction);
|
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newTransaction);
|
||||||
transactionIds.add(newTransaction.getId());
|
transactionIds.add(newTransaction.getId());
|
||||||
}
|
}
|
||||||
changes.put("transactions", transactionIds);
|
changes.put("transactions", transactionIds);
|
||||||
changes.put("eventAmount", payPrincipal.getAmount().negate());
|
changes.put("eventAmount", payPrincipal.getAmount().negate());
|
||||||
|
|
||||||
if (changedTransactionDetail != null) {
|
loan = loanAccountService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
updateLoanTransferTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(noteText)) {
|
if (StringUtils.isNotBlank(noteText)) {
|
||||||
changes.put("note", noteText);
|
changes.put("note", noteText);
|
||||||
@@ -978,36 +889,23 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isCumulativeSchedule() && loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||||
} else if (loan.getLoanProductRelatedDetail() != null
|
} else if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
&& loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)
|
|
||||||
&& loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff)) {
|
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
loan.getLoanTransactions().add(refundTransaction);
|
loan.getLoanTransactions().add(refundTransaction);
|
||||||
if (interestRefundTransaction != null) {
|
if (interestRefundTransaction != null) {
|
||||||
loan.addLoanTransaction(interestRefundTransaction);
|
loan.addLoanTransaction(interestRefundTransaction);
|
||||||
}
|
}
|
||||||
ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactions();
|
|
||||||
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
|
|
||||||
// Store and flush newly created transaction to generate PK
|
// Store and flush newly created transaction to generate PK
|
||||||
saveLoanTransactionWithDataIntegrityViolationChecks(refundTransaction);
|
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(refundTransaction);
|
||||||
if (interestRefundTransaction != null) {
|
if (interestRefundTransaction != null) {
|
||||||
saveLoanTransactionWithDataIntegrityViolationChecks(interestRefundTransaction);
|
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(interestRefundTransaction);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* TODO Vishwas Batch save is giving me a HibernateOptimisticLockingFailureException, looping and saving for
|
|
||||||
* the time being, not a major issue for now as this loop is entered only in edge cases (when a payment is
|
|
||||||
* made before the latest payment recorded against the loan)
|
|
||||||
*/
|
|
||||||
// Apply reprocessed transactions (if applicable)
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
updateLoanTransferTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loan.updateLoanSummaryDerivedFields();
|
loan.updateLoanSummaryDerivedFields();
|
||||||
@@ -1076,7 +974,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
loanRefundRequest.getPrincipal(), loanRefundRequest.getInterest(), loanRefundRequest.getFeeCharges(),
|
loanRefundRequest.getPrincipal(), loanRefundRequest.getInterest(), loanRefundRequest.getFeeCharges(),
|
||||||
loanRefundRequest.getPenaltyCharges(), paymentDetail, transactionDate, externalIdFactory.create());
|
loanRefundRequest.getPenaltyCharges(), paymentDetail, transactionDate, externalIdFactory.create());
|
||||||
interestRefundTransaction.updateLoan(loan);
|
interestRefundTransaction.updateLoan(loan);
|
||||||
saveLoanTransactionWithDataIntegrityViolationChecks(interestRefundTransaction);
|
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(interestRefundTransaction);
|
||||||
loan.addLoanTransaction(interestRefundTransaction);
|
loan.addLoanTransaction(interestRefundTransaction);
|
||||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, false);
|
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, false);
|
||||||
|
|
||||||
@@ -1154,21 +1052,21 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("null")
|
@SuppressWarnings("null")
|
||||||
private ChangedTransactionDetail makeRepayment(final Loan loan, final LoanTransaction repaymentTransaction,
|
private void makeRepayment(final Loan loan, final LoanTransaction repaymentTransaction,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final List<Long> existingTransactionIds,
|
final LoanLifecycleStateMachine loanLifecycleStateMachine, final List<Long> existingTransactionIds,
|
||||||
final List<Long> existingReversedTransactionIds, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
final List<Long> existingReversedTransactionIds, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||||
loanChargeValidator.validateRepaymentTypeTransactionNotBeforeAChargeRefund(loan, repaymentTransaction, "created");
|
loanChargeValidator.validateRepaymentTypeTransactionNotBeforeAChargeRefund(loan, repaymentTransaction, "created");
|
||||||
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
||||||
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
||||||
|
|
||||||
return loanDownPaymentHandlerService.handleRepaymentOrRecoveryOrWaiverTransaction(loan, repaymentTransaction,
|
loanDownPaymentHandlerService.handleRepaymentOrRecoveryOrWaiverTransaction(loan, repaymentTransaction, loanLifecycleStateMachine,
|
||||||
loanLifecycleStateMachine, null, scheduleGeneratorDTO);
|
null, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangedTransactionDetail handleForeClosureTransactions(final Loan loan, final LoanTransaction repaymentTransaction,
|
private void handleForeClosureTransactions(final Loan loan, final LoanTransaction repaymentTransaction,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
final LoanLifecycleStateMachine loanLifecycleStateMachine, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||||
loan.setLoanSubStatus(LoanSubStatus.FORECLOSED.getValue());
|
loan.setLoanSubStatus(LoanSubStatus.FORECLOSED.getValue());
|
||||||
return loanDownPaymentHandlerService.handleRepaymentOrRecoveryOrWaiverTransaction(loan, repaymentTransaction,
|
loanDownPaymentHandlerService.handleRepaymentOrRecoveryOrWaiverTransaction(loan, repaymentTransaction, loanLifecycleStateMachine,
|
||||||
loanLifecycleStateMachine, null, scheduleGeneratorDTO);
|
null, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -33,7 +33,7 @@ import org.apache.fineract.infrastructure.event.business.service.BusinessEventNo
|
|||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariations;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariations;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualsProcessingService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualsProcessingService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||||
@@ -47,13 +47,13 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class LoanScheduleWritePlatformServiceImpl implements LoanScheduleWritePlatformService {
|
public class LoanScheduleWritePlatformServiceImpl implements LoanScheduleWritePlatformService {
|
||||||
|
|
||||||
private final LoanAccountDomainService loanAccountDomainService;
|
|
||||||
private final LoanAssembler loanAssembler;
|
private final LoanAssembler loanAssembler;
|
||||||
private final LoanScheduleAssembler loanScheduleAssembler;
|
private final LoanScheduleAssembler loanScheduleAssembler;
|
||||||
private final LoanUtilService loanUtilService;
|
private final LoanUtilService loanUtilService;
|
||||||
private final BusinessEventNotifierService businessEventNotifierService;
|
private final BusinessEventNotifierService businessEventNotifierService;
|
||||||
private final LoanAccrualsProcessingService loanAccrualsProcessingService;
|
private final LoanAccrualsProcessingService loanAccrualsProcessingService;
|
||||||
private final LoanScheduleService loanScheduleService;
|
private final LoanScheduleService loanScheduleService;
|
||||||
|
private final LoanAccountService loanAccountService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult addLoanScheduleVariations(final Long loanId, final JsonCommand command) {
|
public CommandProcessingResult addLoanScheduleVariations(final Long loanId, final JsonCommand command) {
|
||||||
@@ -64,7 +64,7 @@ public class LoanScheduleWritePlatformServiceImpl implements LoanScheduleWritePl
|
|||||||
}
|
}
|
||||||
loanScheduleAssembler.assempleVariableScheduleFrom(loan, command.json());
|
loanScheduleAssembler.assempleVariableScheduleFrom(loan, command.json());
|
||||||
|
|
||||||
loanAccountDomainService.saveLoanWithDataIntegrityViolationChecks(loan);
|
loanAccountService.saveLoanWithDataIntegrityViolationChecks(loan);
|
||||||
final Map<String, Object> changes = new HashMap<>();
|
final Map<String, Object> changes = new HashMap<>();
|
||||||
List<LoanTermVariationsData> newVariationsData = new ArrayList<>();
|
List<LoanTermVariationsData> newVariationsData = new ArrayList<>();
|
||||||
List<LoanTermVariations> modifiedVariations = loan.getLoanTermVariations();
|
List<LoanTermVariations> modifiedVariations = loan.getLoanTermVariations();
|
||||||
@@ -102,7 +102,7 @@ public class LoanScheduleWritePlatformServiceImpl implements LoanScheduleWritePl
|
|||||||
ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
loanAccountDomainService.saveLoanWithDataIntegrityViolationChecks(loan);
|
loanAccountService.saveLoanWithDataIntegrityViolationChecks(loan);
|
||||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanScheduleVariationsDeletedBusinessEvent(loan));
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanScheduleVariationsDeletedBusinessEvent(loan));
|
||||||
return new CommandProcessingResultBuilder() //
|
return new CommandProcessingResultBuilder() //
|
||||||
.withLoanId(loanId) //
|
.withLoanId(loanId) //
|
||||||
|
|||||||
+4
-23
@@ -47,12 +47,9 @@ import org.apache.fineract.infrastructure.event.business.service.BusinessEventNo
|
|||||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||||
import org.apache.fineract.portfolio.account.service.AccountTransfersWritePlatformService;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallmentRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallmentRepository;
|
||||||
@@ -62,7 +59,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRescheduleRequestToT
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariations;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariations;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator;
|
||||||
@@ -82,7 +78,7 @@ import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualsProcessingS
|
|||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanChargeService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanChargeService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.ReplayedTransactionBusinessEventService;
|
import org.apache.fineract.portfolio.loanaccount.service.ReprocessLoanTransactionsService;
|
||||||
import org.apache.fineract.useradministration.domain.AppUser;
|
import org.apache.fineract.useradministration.domain.AppUser;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -98,6 +94,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanRescheduleRequestWritePlatformService {
|
public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanRescheduleRequestWritePlatformService {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(LoanRescheduleRequestWritePlatformServiceImpl.class);
|
private static final Logger LOG = LoggerFactory.getLogger(LoanRescheduleRequestWritePlatformServiceImpl.class);
|
||||||
|
private static final DefaultScheduledDateGenerator DEFAULT_SCHEDULED_DATE_GENERATOR = new DefaultScheduledDateGenerator();
|
||||||
|
|
||||||
private final CodeValueRepositoryWrapper codeValueRepositoryWrapper;
|
private final CodeValueRepositoryWrapper codeValueRepositoryWrapper;
|
||||||
private final PlatformSecurityContext platformSecurityContext;
|
private final PlatformSecurityContext platformSecurityContext;
|
||||||
@@ -112,15 +109,12 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
|||||||
private final LoanUtilService loanUtilService;
|
private final LoanUtilService loanUtilService;
|
||||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||||
private final LoanScheduleGeneratorFactory loanScheduleFactory;
|
private final LoanScheduleGeneratorFactory loanScheduleFactory;
|
||||||
private final AccountTransfersWritePlatformService accountTransfersWritePlatformService;
|
|
||||||
private static final DefaultScheduledDateGenerator DEFAULT_SCHEDULED_DATE_GENERATOR = new DefaultScheduledDateGenerator();
|
|
||||||
private final LoanAccountDomainService loanAccountDomainService;
|
|
||||||
private final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository;
|
private final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository;
|
||||||
private final ReplayedTransactionBusinessEventService replayedTransactionBusinessEventService;
|
|
||||||
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
||||||
private final BusinessEventNotifierService businessEventNotifierService;
|
private final BusinessEventNotifierService businessEventNotifierService;
|
||||||
private final LoanAccrualsProcessingService loanAccrualsProcessingService;
|
private final LoanAccrualsProcessingService loanAccrualsProcessingService;
|
||||||
private final LoanChargeService loanChargeService;
|
private final LoanChargeService loanChargeService;
|
||||||
|
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create a new instance of the LoanRescheduleRequest object from the JsonCommand object and persist
|
* create a new instance of the LoanRescheduleRequest object from the JsonCommand object and persist
|
||||||
@@ -440,7 +434,7 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
|||||||
}
|
}
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
loanChargeService.recalculateAllCharges(loan);
|
loanChargeService.recalculateAllCharges(loan);
|
||||||
ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactions();
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
|
|
||||||
this.loanRepaymentScheduleHistoryRepository.saveAll(loanRepaymentScheduleHistoryList);
|
this.loanRepaymentScheduleHistoryRepository.saveAll(loanRepaymentScheduleHistoryList);
|
||||||
|
|
||||||
@@ -450,19 +444,6 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
|||||||
// update the status of the request
|
// update the status of the request
|
||||||
loanRescheduleRequest.approve(appUser, approvedOnDate);
|
loanRescheduleRequest.approve(appUser, approvedOnDate);
|
||||||
|
|
||||||
/***
|
|
||||||
* TODO Vishwas Batch save is giving me a HibernateOptimisticLockingFailureException, looping and saving for
|
|
||||||
* the time being, not a major issue for now as this loop is entered only in edge cases (when a adjustment
|
|
||||||
* is made before the latest payment recorded against the loan)
|
|
||||||
***/
|
|
||||||
if (changedTransactionDetail != null) {
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
|
|
||||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, true, false);
|
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, true, false);
|
||||||
|
|||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.loanaccount.service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||||
|
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||||
|
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountService;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
|
import org.springframework.orm.jpa.JpaSystemException;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class LoanAccountServiceImpl implements LoanAccountService {
|
||||||
|
|
||||||
|
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
||||||
|
private final LoanTransactionRepository loanTransactionRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoanTransaction saveLoanTransactionWithDataIntegrityViolationChecks(LoanTransaction newRepaymentTransaction) {
|
||||||
|
try {
|
||||||
|
return this.loanTransactionRepository.saveAndFlush(newRepaymentTransaction);
|
||||||
|
} catch (final JpaSystemException | DataIntegrityViolationException e) {
|
||||||
|
raiseValidationExceptionForUniqueConstraintViolation(e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Loan saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) {
|
||||||
|
try {
|
||||||
|
return this.loanRepositoryWrapper.saveAndFlush(loan);
|
||||||
|
} catch (final JpaSystemException | DataIntegrityViolationException e) {
|
||||||
|
raiseValidationExceptionForUniqueConstraintViolation(e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Loan saveLoanWithDataIntegrityViolationChecks(final Loan loan) {
|
||||||
|
try {
|
||||||
|
return this.loanRepositoryWrapper.save(loan);
|
||||||
|
} catch (final JpaSystemException | DataIntegrityViolationException e) {
|
||||||
|
raiseValidationExceptionForUniqueConstraintViolation(e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void raiseValidationExceptionForUniqueConstraintViolation(Exception e) {
|
||||||
|
final Throwable realCause = e.getCause();
|
||||||
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||||
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.transaction");
|
||||||
|
if (realCause.getMessage().toLowerCase().contains("external_id_unique") || realCause.getMessage()
|
||||||
|
.contains("duplicate key value violates unique constraint \"m_loan_transaction_external_id_key\"")) {
|
||||||
|
baseDataValidator.reset().parameter("externalId").failWithCode("value.must.be.unique");
|
||||||
|
}
|
||||||
|
if (!dataValidationErrors.isEmpty()) {
|
||||||
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||||
|
dataValidationErrors, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+4
-4
@@ -34,7 +34,7 @@ import org.apache.fineract.infrastructure.event.business.domain.loan.transaction
|
|||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionAccrualActivityPreBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionAccrualActivityPreBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
@@ -54,7 +54,7 @@ public class LoanAccrualActivityProcessingServiceImpl implements LoanAccrualActi
|
|||||||
private final ExternalIdFactory externalIdFactory;
|
private final ExternalIdFactory externalIdFactory;
|
||||||
private final BusinessEventNotifierService businessEventNotifierService;
|
private final BusinessEventNotifierService businessEventNotifierService;
|
||||||
private final LoanTransactionAssembler loanTransactionAssembler;
|
private final LoanTransactionAssembler loanTransactionAssembler;
|
||||||
private final LoanAccountDomainService loanAccountDomainService;
|
private final LoanAccountService loanAccountService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||||
@@ -207,7 +207,7 @@ public class LoanAccrualActivityProcessingServiceImpl implements LoanAccrualActi
|
|||||||
newLoanTransaction.copyLoanTransactionRelations(loanTransaction.getLoanTransactionRelations());
|
newLoanTransaction.copyLoanTransactionRelations(loanTransaction.getLoanTransactionRelations());
|
||||||
newLoanTransaction.getLoanTransactionRelations().add(LoanTransactionRelation.linkToTransaction(newLoanTransaction,
|
newLoanTransaction.getLoanTransactionRelations().add(LoanTransactionRelation.linkToTransaction(newLoanTransaction,
|
||||||
loanTransaction, LoanTransactionRelationTypeEnum.REPLAYED));
|
loanTransaction, LoanTransactionRelationTypeEnum.REPLAYED));
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(newLoanTransaction);
|
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newLoanTransaction);
|
||||||
loan.addLoanTransaction(newLoanTransaction);
|
loan.addLoanTransaction(newLoanTransaction);
|
||||||
|
|
||||||
LoanAdjustTransactionBusinessEvent.Data data = new LoanAdjustTransactionBusinessEvent.Data(loanTransaction);
|
LoanAdjustTransactionBusinessEvent.Data data = new LoanAdjustTransactionBusinessEvent.Data(loanTransaction);
|
||||||
@@ -242,7 +242,7 @@ public class LoanAccrualActivityProcessingServiceImpl implements LoanAccrualActi
|
|||||||
|
|
||||||
private LoanTransaction makeAccrualActivityTransaction(@NotNull Loan loan, @NotNull LoanTransaction newAccrualActivityTransaction) {
|
private LoanTransaction makeAccrualActivityTransaction(@NotNull Loan loan, @NotNull LoanTransaction newAccrualActivityTransaction) {
|
||||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanTransactionAccrualActivityPreBusinessEvent(loan));
|
businessEventNotifierService.notifyPreBusinessEvent(new LoanTransactionAccrualActivityPreBusinessEvent(loan));
|
||||||
newAccrualActivityTransaction = loanAccountDomainService
|
newAccrualActivityTransaction = loanAccountService
|
||||||
.saveLoanTransactionWithDataIntegrityViolationChecks(newAccrualActivityTransaction);
|
.saveLoanTransactionWithDataIntegrityViolationChecks(newAccrualActivityTransaction);
|
||||||
|
|
||||||
loan.addLoanTransaction(newAccrualActivityTransaction);
|
loan.addLoanTransaction(newAccrualActivityTransaction);
|
||||||
|
|||||||
+41
-67
@@ -92,9 +92,9 @@ import org.apache.fineract.portfolio.group.exception.GroupNotActiveException;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
|
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargePaidByData;
|
import org.apache.fineract.portfolio.loanaccount.data.LoanChargePaidByData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargePaidBy;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargePaidBy;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeRepository;
|
||||||
@@ -165,7 +165,6 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
|||||||
private final ExternalIdFactory externalIdFactory;
|
private final ExternalIdFactory externalIdFactory;
|
||||||
private final AccountTransferDetailRepository accountTransferDetailRepository;
|
private final AccountTransferDetailRepository accountTransferDetailRepository;
|
||||||
private final LoanChargeAssembler loanChargeAssembler;
|
private final LoanChargeAssembler loanChargeAssembler;
|
||||||
private final ReplayedTransactionBusinessEventService replayedTransactionBusinessEventService;
|
|
||||||
private final PaymentDetailWritePlatformService paymentDetailWritePlatformService;
|
private final PaymentDetailWritePlatformService paymentDetailWritePlatformService;
|
||||||
private final NoteRepository noteRepository;
|
private final NoteRepository noteRepository;
|
||||||
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
||||||
@@ -173,6 +172,8 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
|||||||
private final LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator;
|
private final LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator;
|
||||||
private final LoanChargeValidator loanChargeValidator;
|
private final LoanChargeValidator loanChargeValidator;
|
||||||
private final LoanScheduleService loanScheduleService;
|
private final LoanScheduleService loanScheduleService;
|
||||||
|
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
private final LoanAccountService loanAccountService;
|
||||||
|
|
||||||
private static boolean isPartOfThisInstallment(LoanCharge loanCharge, LoanRepaymentScheduleInstallment e) {
|
private static boolean isPartOfThisInstallment(LoanCharge loanCharge, LoanRepaymentScheduleInstallment e) {
|
||||||
return DateUtils.isAfter(loanCharge.getDueDate(), e.getFromDate()) && !DateUtils.isAfter(loanCharge.getDueDate(), e.getDueDate());
|
return DateUtils.isAfter(loanCharge.getDueDate(), e.getFromDate()) && !DateUtils.isAfter(loanCharge.getDueDate(), e.getDueDate());
|
||||||
@@ -287,25 +288,18 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (reprocessRequired) {
|
if (reprocessRequired) {
|
||||||
if (loan.getLoanProductRelatedDetail() != null
|
if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
&& loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)
|
|
||||||
&& loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff)) {
|
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, null);
|
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, null);
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangedTransactionDetail changedTransactionDetail = overpaidReprocess
|
if (overpaidReprocess) {
|
||||||
? loan.reprocessTransactionsWithPostTransactionChecks(transactionDate)
|
reprocessLoanTransactionsService.reprocessTransactionsWithPostTransactionChecks(loan, transactionDate);
|
||||||
: loan.reprocessTransactions();
|
} else {
|
||||||
if (changedTransactionDetail != null) {
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
}
|
||||||
loan = loanAccountDomainService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
|
||||||
|
loan = loanAccountService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled() && isAppliedOnBackDate
|
if (loan.isInterestBearingAndInterestRecalculationEnabled() && isAppliedOnBackDate
|
||||||
@@ -469,7 +463,23 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
|||||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanUpdateChargeBusinessEvent(loanCharge));
|
businessEventNotifierService.notifyPreBusinessEvent(new LoanUpdateChargeBusinessEvent(loanCharge));
|
||||||
|
|
||||||
loanChargeValidator.validateLoanIsNotClosed(loan, loanCharge);
|
loanChargeValidator.validateLoanIsNotClosed(loan, loanCharge);
|
||||||
final Map<String, Object> changes = loan.updateLoanCharge(loanCharge, command);
|
|
||||||
|
final Map<String, Object> changes = new LinkedHashMap<>(3);
|
||||||
|
if (loan.getActiveCharges().contains(loanCharge)) {
|
||||||
|
final BigDecimal amount = loan.calculateAmountPercentageAppliedTo(loanCharge);
|
||||||
|
final Map<String, Object> loanChargeChanges = loanCharge.update(command, amount);
|
||||||
|
changes.putAll(loanChargeChanges);
|
||||||
|
loan.updateSummaryWithTotalFeeChargesDueAtDisbursement(loan.deriveSumTotalOfChargesDueAtDisbursement());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loanCharge.isDueAtDisbursement()) {
|
||||||
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
|
} else {
|
||||||
|
// reprocess loan schedule based on charge been waived.
|
||||||
|
final LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper();
|
||||||
|
wrapper.reprocess(loan.getCurrency(), loan.getDisbursementDate(), loan.getRepaymentScheduleInstallments(),
|
||||||
|
loan.getActiveCharges());
|
||||||
|
}
|
||||||
|
|
||||||
this.loanRepositoryWrapper.save(loan);
|
this.loanRepositoryWrapper.save(loan);
|
||||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanUpdateChargeBusinessEvent(loanCharge));
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanUpdateChargeBusinessEvent(loanCharge));
|
||||||
@@ -606,7 +616,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
|||||||
|
|
||||||
loanChargeValidator.validateLoanIsNotClosed(loan, loanCharge);
|
loanChargeValidator.validateLoanIsNotClosed(loan, loanCharge);
|
||||||
loanChargeValidator.validateLoanChargeIsNotWaived(loan, loanCharge);
|
loanChargeValidator.validateLoanChargeIsNotWaived(loan, loanCharge);
|
||||||
loan.removeLoanCharge(loanCharge);
|
reprocessLoanTransactionsService.removeLoanCharge(loan, loanCharge);
|
||||||
this.loanRepositoryWrapper.save(loan);
|
this.loanRepositoryWrapper.save(loan);
|
||||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanDeleteChargeBusinessEvent(loanCharge));
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanDeleteChargeBusinessEvent(loanCharge));
|
||||||
return new CommandProcessingResultBuilder() //
|
return new CommandProcessingResultBuilder() //
|
||||||
@@ -820,23 +830,12 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
|||||||
|
|
||||||
if (reprocessRequired) {
|
if (reprocessRequired) {
|
||||||
addInstallmentIfPenaltyAppliedAfterLastDueDate(loan, lastChargeDate);
|
addInstallmentIfPenaltyAppliedAfterLastDueDate(loan, lastChargeDate);
|
||||||
if (loan.getLoanProductRelatedDetail() != null
|
if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
&& loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)
|
|
||||||
&& loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff)) {
|
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, null);
|
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, null);
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactions();
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
if (changedTransactionDetail != null) {
|
loan = loanAccountService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings()
|
|
||||||
.entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
loan = loanAccountDomainService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled() && runInterestRecalculation
|
if (loan.isInterestBearingAndInterestRecalculationEnabled() && runInterestRecalculation
|
||||||
@@ -866,22 +865,20 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
|||||||
.determineProcessor(loan.transactionProcessingStrategy());
|
.determineProcessor(loan.transactionProcessingStrategy());
|
||||||
loan.addLoanTransaction(loanChargeAdjustmentTransaction);
|
loan.addLoanTransaction(loanChargeAdjustmentTransaction);
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
if (loan.getLoanProductRelatedDetail() != null
|
if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
&& loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)
|
|
||||||
&& loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff)) {
|
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, null);
|
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, null);
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
loan.reprocessTransactions();
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
} else {
|
} else {
|
||||||
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(loanChargeAdjustmentTransaction,
|
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(loanChargeAdjustmentTransaction,
|
||||||
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
||||||
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
||||||
}
|
}
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(loanChargeAdjustmentTransaction);
|
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(loanChargeAdjustmentTransaction);
|
||||||
loan.updateLoanSummaryAndStatus();
|
loan.updateLoanSummaryAndStatus();
|
||||||
|
|
||||||
loanAccountDomainService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
loanAccountService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
|
|
||||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(loan.getCurrency().getCode(),
|
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(loan.getCurrency().getCode(),
|
||||||
existingTransactionIds, existingReversedTransactionIds, false);
|
existingTransactionIds, existingReversedTransactionIds, false);
|
||||||
@@ -1176,20 +1173,10 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
|||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled() && !loan.isChargedOff()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled() && !loan.isChargedOff()) {
|
||||||
final List<Long> existingTransactionIds = loan.findExistingTransactionIds();
|
final List<Long> existingTransactionIds = loan.findExistingTransactionIds();
|
||||||
ScheduleGeneratorDTO generatorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
ScheduleGeneratorDTO generatorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||||
ChangedTransactionDetail changedTransactionDetail = loanScheduleService
|
loanScheduleService.handleRegenerateRepaymentScheduleWithInterestRecalculation(loan, generatorDTO);
|
||||||
.handleRegenerateRepaymentScheduleWithInterestRecalculation(loan, generatorDTO);
|
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||||
|
loan = loanAccountService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
if (changedTransactionDetail != null) {
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
loan = loanAccountDomainService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
|
||||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||||
}
|
}
|
||||||
return loan;
|
return loan;
|
||||||
@@ -1456,29 +1443,16 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
|||||||
waiveLoanChargeTransaction.getAmount(loan.getCurrency()).getAmount(), loanInstallmentNumber);
|
waiveLoanChargeTransaction.getAmount(loan.getCurrency()).getAmount(), loanInstallmentNumber);
|
||||||
waiveLoanChargeTransaction.getLoanChargesPaid().add(loanChargePaidBy);
|
waiveLoanChargeTransaction.getLoanChargesPaid().add(loanChargePaidBy);
|
||||||
loan.addLoanTransaction(waiveLoanChargeTransaction);
|
loan.addLoanTransaction(waiveLoanChargeTransaction);
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled() && DateUtils.isBefore(loanCharge.getDueLocalDate(), businessDate)) {
|
if (loan.isCumulativeSchedule() && loan.isInterestBearingAndInterestRecalculationEnabled()
|
||||||
|
&& DateUtils.isBefore(loanCharge.getDueLocalDate(), businessDate)) {
|
||||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||||
} else if (loan.getLoanProductRelatedDetail() != null
|
} else if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
&& loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)
|
|
||||||
&& loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff)) {
|
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
// Waive of charges whose due date falls after latest 'repayment' transaction don't require entire loan schedule
|
// Waive of charges whose due date falls after latest 'repayment' transaction don't require entire loan schedule
|
||||||
// to be reprocessed.
|
// to be reprocessed.
|
||||||
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loan.getCurrency())) {
|
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loan.getCurrency())) {
|
||||||
/*
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
* TODO Vishwas Currently we do not allow waiving fully paid loan charge and waiving partially paid loan
|
|
||||||
* charges only waives the remaining amount.
|
|
||||||
*
|
|
||||||
* Consider removing this block of code or logically completing it for the future by getting the list of
|
|
||||||
* affected Transactions
|
|
||||||
*/
|
|
||||||
if (loan.getLoanProductRelatedDetail() != null
|
|
||||||
&& loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)
|
|
||||||
&& loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff)) {
|
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
|
||||||
}
|
|
||||||
loan.reprocessTransactions();
|
|
||||||
} else {
|
} else {
|
||||||
// reprocess loan schedule based on charge been waived.
|
// reprocess loan schedule based on charge been waived.
|
||||||
final LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper();
|
final LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper();
|
||||||
|
|||||||
+4
-3
@@ -58,6 +58,7 @@ public class LoanDisbursementService {
|
|||||||
|
|
||||||
private final LoanChargeValidator loanChargeValidator;
|
private final LoanChargeValidator loanChargeValidator;
|
||||||
private final LoanDisbursementValidator loanDisbursementValidator;
|
private final LoanDisbursementValidator loanDisbursementValidator;
|
||||||
|
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
|
||||||
public void updateDisbursementDetails(final Loan loan, final JsonCommand jsonCommand, final Map<String, Object> actualChanges) {
|
public void updateDisbursementDetails(final Loan loan, final JsonCommand jsonCommand, final Map<String, Object> actualChanges) {
|
||||||
final List<Long> disbursementList = loan.fetchDisbursementIds();
|
final List<Long> disbursementList = loan.fetchDisbursementIds();
|
||||||
@@ -262,7 +263,7 @@ public class LoanDisbursementService {
|
|||||||
for (LoanCharge loanCharge : tempCharges) {
|
for (LoanCharge loanCharge : tempCharges) {
|
||||||
loanChargeValidator.validateLoanIsNotClosed(loan, loanCharge);
|
loanChargeValidator.validateLoanIsNotClosed(loan, loanCharge);
|
||||||
loanChargeValidator.validateLoanChargeIsNotWaived(loan, loanCharge);
|
loanChargeValidator.validateLoanChargeIsNotWaived(loan, loanCharge);
|
||||||
loan.removeLoanCharge(loanCharge);
|
reprocessLoanTransactionsService.removeLoanCharge(loan, loanCharge);
|
||||||
}
|
}
|
||||||
loan.getTrancheCharges().clear();
|
loan.getTrancheCharges().clear();
|
||||||
} else {
|
} else {
|
||||||
@@ -272,7 +273,7 @@ public class LoanDisbursementService {
|
|||||||
if (loan.getCharges().contains(deleteCharge)) {
|
if (loan.getCharges().contains(deleteCharge)) {
|
||||||
loanChargeValidator.validateLoanIsNotClosed(loan, deleteCharge);
|
loanChargeValidator.validateLoanIsNotClosed(loan, deleteCharge);
|
||||||
loanChargeValidator.validateLoanChargeIsNotWaived(loan, deleteCharge);
|
loanChargeValidator.validateLoanChargeIsNotWaived(loan, deleteCharge);
|
||||||
loan.removeLoanCharge(deleteCharge);
|
reprocessLoanTransactionsService.removeLoanCharge(loan, deleteCharge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,6 +296,6 @@ public class LoanDisbursementService {
|
|||||||
loanChargeValidator.validateLoanChargeIsNotWaived(loan, charge); //
|
loanChargeValidator.validateLoanChargeIsNotWaived(loan, charge); //
|
||||||
return true; //
|
return true; //
|
||||||
}) //
|
}) //
|
||||||
.forEach(loan::removeLoanCharge);
|
.forEach(loanCharge -> reprocessLoanTransactionsService.removeLoanCharge(loan, loanCharge));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+132
-295
@@ -123,9 +123,7 @@ import org.apache.fineract.portfolio.account.domain.AccountAssociationsRepositor
|
|||||||
import org.apache.fineract.portfolio.account.domain.AccountTransferDetailRepository;
|
import org.apache.fineract.portfolio.account.domain.AccountTransferDetailRepository;
|
||||||
import org.apache.fineract.portfolio.account.domain.AccountTransferDetails;
|
import org.apache.fineract.portfolio.account.domain.AccountTransferDetails;
|
||||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRecurrenceType;
|
import org.apache.fineract.portfolio.account.domain.AccountTransferRecurrenceType;
|
||||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRepository;
|
|
||||||
import org.apache.fineract.portfolio.account.domain.AccountTransferStandingInstruction;
|
import org.apache.fineract.portfolio.account.domain.AccountTransferStandingInstruction;
|
||||||
import org.apache.fineract.portfolio.account.domain.AccountTransferTransaction;
|
|
||||||
import org.apache.fineract.portfolio.account.domain.AccountTransferType;
|
import org.apache.fineract.portfolio.account.domain.AccountTransferType;
|
||||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionPriority;
|
import org.apache.fineract.portfolio.account.domain.StandingInstructionPriority;
|
||||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionStatus;
|
import org.apache.fineract.portfolio.account.domain.StandingInstructionStatus;
|
||||||
@@ -153,11 +151,11 @@ import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.command.LoanUpdateCommand;
|
import org.apache.fineract.portfolio.loanaccount.command.LoanUpdateCommand;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
|
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.GLIMAccountInfoRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.GLIMAccountInfoRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonitoringAccount;
|
import org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonitoringAccount;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanEvent;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanEvent;
|
||||||
@@ -267,11 +265,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
private final LoanLifecycleStateMachine loanLifecycleStateMachine;
|
private final LoanLifecycleStateMachine loanLifecycleStateMachine;
|
||||||
private final LoanAccountLockService loanAccountLockService;
|
private final LoanAccountLockService loanAccountLockService;
|
||||||
private final ExternalIdFactory externalIdFactory;
|
private final ExternalIdFactory externalIdFactory;
|
||||||
private final ReplayedTransactionBusinessEventService replayedTransactionBusinessEventService;
|
|
||||||
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
||||||
private final ErrorHandler errorHandler;
|
private final ErrorHandler errorHandler;
|
||||||
private final LoanDownPaymentHandlerService loanDownPaymentHandlerService;
|
private final LoanDownPaymentHandlerService loanDownPaymentHandlerService;
|
||||||
private final AccountTransferRepository accountTransferRepository;
|
|
||||||
private final LoanTransactionAssembler loanTransactionAssembler;
|
private final LoanTransactionAssembler loanTransactionAssembler;
|
||||||
private final LoanAccrualsProcessingService loanAccrualsProcessingService;
|
private final LoanAccrualsProcessingService loanAccrualsProcessingService;
|
||||||
private final LoanOfficerValidator loanOfficerValidator;
|
private final LoanOfficerValidator loanOfficerValidator;
|
||||||
@@ -280,6 +276,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
private final LoanScheduleService loanScheduleService;
|
private final LoanScheduleService loanScheduleService;
|
||||||
private final LoanChargeValidator loanChargeValidator;
|
private final LoanChargeValidator loanChargeValidator;
|
||||||
private final LoanOfficerService loanOfficerService;
|
private final LoanOfficerService loanOfficerService;
|
||||||
|
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
private final LoanAccountService loanAccountService;
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
@@ -429,8 +427,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled() || downPaymentEnabled) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled() || downPaymentEnabled) {
|
||||||
createAndSaveLoanScheduleArchive(loan, scheduleGeneratorDTO);
|
createAndSaveLoanScheduleArchive(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
ChangedTransactionDetail changedTransactionDetail = disburseLoan(command, isPaymentTypeApplicableForDisbursementCharge,
|
disburseLoan(command, isPaymentTypeApplicableForDisbursementCharge, paymentDetail, loan, currentUser, changes,
|
||||||
paymentDetail, loan, currentUser, changes, scheduleGeneratorDTO);
|
scheduleGeneratorDTO);
|
||||||
loan.adjustNetDisbursalAmount(amountToDisburse.getAmount());
|
loan.adjustNetDisbursalAmount(amountToDisburse.getAmount());
|
||||||
|
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
@@ -444,14 +442,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
if (disbursementTransaction != null) {
|
if (disbursementTransaction != null) {
|
||||||
loanTransactionRepository.saveAndFlush(disbursementTransaction);
|
loanTransactionRepository.saveAndFlush(disbursementTransaction);
|
||||||
}
|
}
|
||||||
if (changedTransactionDetail != null) {
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
if (loan.isAutoRepaymentForDownPaymentEnabled() && !isWithoutAutoPayment) {
|
if (loan.isAutoRepaymentForDownPaymentEnabled() && !isWithoutAutoPayment) {
|
||||||
// updating linked savings account for auto down payment transaction for disbursement to savings account
|
// updating linked savings account for auto down payment transaction for disbursement to savings account
|
||||||
if (isAccountTransfer && loan.shouldCreateStandingInstructionAtDisbursement()) {
|
if (isAccountTransfer && loan.shouldCreateStandingInstructionAtDisbursement()) {
|
||||||
@@ -569,9 +560,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangedTransactionDetail disburseLoan(JsonCommand command, boolean isPaymentTypeApplicableForDisbursementCharge,
|
private void disburseLoan(JsonCommand command, boolean isPaymentTypeApplicableForDisbursementCharge, PaymentDetail paymentDetail,
|
||||||
PaymentDetail paymentDetail, Loan loan, AppUser currentUser, Map<String, Object> changes,
|
Loan loan, AppUser currentUser, Map<String, Object> changes, ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||||
ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
|
||||||
final PaymentDetail paymentDetail1 = isPaymentTypeApplicableForDisbursementCharge ? paymentDetail : null;
|
final PaymentDetail paymentDetail1 = isPaymentTypeApplicableForDisbursementCharge ? paymentDetail : null;
|
||||||
final LocalDate actualDisbursementDate1 = command.localDateValueOfParameterNamed(ACTUAL_DISBURSEMENT_DATE);
|
final LocalDate actualDisbursementDate1 = command.localDateValueOfParameterNamed(ACTUAL_DISBURSEMENT_DATE);
|
||||||
|
|
||||||
@@ -584,9 +574,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
|
|
||||||
boolean disbursementMissedParam = loan.isDisbursementMissed();
|
boolean disbursementMissedParam = loan.isDisbursementMissed();
|
||||||
LocalDate firstInstallmentDueDate = loan.fetchRepaymentScheduleInstallment(1).getDueDate();
|
LocalDate firstInstallmentDueDate = loan.fetchRepaymentScheduleInstallment(1).getDueDate();
|
||||||
if ((loan.isInterestBearingAndInterestRecalculationEnabled()
|
if ((loan.isCumulativeSchedule() && loan.isInterestBearingAndInterestRecalculationEnabled()
|
||||||
&& (DateUtils.isBeforeBusinessDate(firstInstallmentDueDate) || disbursementMissedParam))) {
|
&& (DateUtils.isBeforeBusinessDate(firstInstallmentDueDate) || disbursementMissedParam))) {
|
||||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||||
|
} else {
|
||||||
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
loan.updateSummaryWithTotalFeeChargesDueAtDisbursement(loan.deriveSumTotalOfChargesDueAtDisbursement());
|
loan.updateSummaryWithTotalFeeChargesDueAtDisbursement(loan.deriveSumTotalOfChargesDueAtDisbursement());
|
||||||
@@ -612,18 +604,16 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
loan.addLoanTransaction(interestAppliedTransaction);
|
loan.addLoanTransaction(interestAppliedTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangedTransactionDetail changedTransactionDetail = null;
|
if (loan.getLoanProduct().isMultiDisburseLoan() || loan.isProgressiveSchedule()) {
|
||||||
if (loan.getLoanProduct().isMultiDisburseLoan()) {
|
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = loan.retrieveListOfTransactionsForReprocessing();
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = loan.retrieveListOfTransactionsForReprocessing();
|
||||||
if (!allNonContraTransactionsPostDisbursement.isEmpty()) {
|
if (!allNonContraTransactionsPostDisbursement.isEmpty()) {
|
||||||
changedTransactionDetail = loan.reprocessTransactions();
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
}
|
}
|
||||||
loan.updateLoanSummaryDerivedFields();
|
loan.updateLoanSummaryDerivedFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED, loan);
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED, loan);
|
||||||
changes.put(PARAM_STATUS, LoanEnumerations.status(loan.getLoanStatus()));
|
changes.put(PARAM_STATUS, LoanEnumerations.status(loan.getLoanStatus()));
|
||||||
return changedTransactionDetail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePostDatedChecks(Set<PostDatedChecks> postDatedChecks) {
|
private void updatePostDatedChecks(Set<PostDatedChecks> postDatedChecks) {
|
||||||
@@ -784,7 +774,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.LOAN_DISBURSED);
|
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.LOAN_DISBURSED);
|
||||||
updateLoanCounters(loan, actualDisbursementDate);
|
updateLoanCounters(loan, actualDisbursementDate);
|
||||||
boolean canDisburse = loan.canDisburse();
|
boolean canDisburse = loan.canDisburse();
|
||||||
ChangedTransactionDetail changedTransactionDetail = null;
|
|
||||||
if (canDisburse) {
|
if (canDisburse) {
|
||||||
Money amountBeforeAdjust = loan.getPrincipal();
|
Money amountBeforeAdjust = loan.getPrincipal();
|
||||||
Money disburseAmount = loanDisbursementService.adjustDisburseAmount(loan, command, actualDisbursementDate);
|
Money disburseAmount = loanDisbursementService.adjustDisburseAmount(loan, command, actualDisbursementDate);
|
||||||
@@ -813,8 +802,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled() || downPaymentEnabled) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled() || downPaymentEnabled) {
|
||||||
createAndSaveLoanScheduleArchive(loan, scheduleGeneratorDTO);
|
createAndSaveLoanScheduleArchive(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
changedTransactionDetail = disburseLoan(command, configurationDomainService.isPaymentTypeApplicableForDisbursementCharge(),
|
disburseLoan(command, configurationDomainService.isPaymentTypeApplicableForDisbursementCharge(), paymentDetail, loan,
|
||||||
paymentDetail, loan, currentUser, changes, scheduleGeneratorDTO);
|
currentUser, changes, scheduleGeneratorDTO);
|
||||||
|
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
|
|
||||||
@@ -825,17 +814,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!changes.isEmpty()) {
|
if (!changes.isEmpty()) {
|
||||||
|
|
||||||
createNote(loan, command, changes);
|
createNote(loan, command, changes);
|
||||||
if (changedTransactionDetail != null) {
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings()
|
|
||||||
.entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||||
@@ -1049,14 +1028,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
return statusChanged;
|
return statusChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLoanTransferTransaction(final Long loanTransactionId, final LoanTransaction newLoanTransaction) {
|
|
||||||
final AccountTransferTransaction transferTransaction = this.accountTransferRepository.findByToLoanTransactionId(loanTransactionId);
|
|
||||||
if (transferTransaction != null) {
|
|
||||||
transferTransaction.updateToLoanTransaction(newLoanTransaction);
|
|
||||||
this.accountTransferRepository.save(transferTransaction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO check
|
// TODO check
|
||||||
public boolean isChronologicallyTheLatestTransaction(final LoanTransaction loanTransaction,
|
public boolean isChronologicallyTheLatestTransaction(final LoanTransaction loanTransaction,
|
||||||
final List<LoanTransaction> loanTransactions) {
|
final List<LoanTransaction> loanTransactions) {
|
||||||
@@ -1077,8 +1048,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
return isChronologicallyLatestRepaymentOrWaiver;
|
return isChronologicallyLatestRepaymentOrWaiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangedTransactionDetail recalculateLoanWithInterestPaymentWaiverTxn(Loan loan,
|
private void recalculateLoanWithInterestPaymentWaiverTxn(Loan loan, LoanTransaction newInterestPaymentWaiverTransaction) {
|
||||||
LoanTransaction newInterestPaymentWaiverTransaction) {
|
|
||||||
LocalDate recalculateFrom = null;
|
LocalDate recalculateFrom = null;
|
||||||
LocalDate transactionDate = newInterestPaymentWaiverTransaction.getTransactionDate();
|
LocalDate transactionDate = newInterestPaymentWaiverTransaction.getTransactionDate();
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
@@ -1086,7 +1056,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
}
|
}
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom, null);
|
final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom, null);
|
||||||
|
|
||||||
ChangedTransactionDetail changedTransactionDetail = null;
|
|
||||||
newInterestPaymentWaiverTransaction.updateLoan(loan);
|
newInterestPaymentWaiverTransaction.updateLoan(loan);
|
||||||
|
|
||||||
final boolean isTransactionChronologicallyLatest = loan
|
final boolean isTransactionChronologicallyLatest = loan
|
||||||
@@ -1126,37 +1095,27 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (reprocess) {
|
if (reprocess) {
|
||||||
changedTransactionDetail = reprocessChangedLoanTransactions(loan, loanRepaymentScheduleTransactionProcessor,
|
reprocessChangedLoanTransactions(loan, scheduleGeneratorDTO);
|
||||||
scheduleGeneratorDTO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loan.updateLoanSummaryDerivedFields();
|
loan.updateLoanSummaryDerivedFields();
|
||||||
|
|
||||||
doPostLoanTransactionChecks(loan, newInterestPaymentWaiverTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
doPostLoanTransactionChecks(loan, newInterestPaymentWaiverTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
||||||
|
|
||||||
return changedTransactionDetail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangedTransactionDetail reprocessChangedLoanTransactions(Loan loan,
|
private void reprocessChangedLoanTransactions(Loan loan, ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||||
LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor,
|
if (loan.isCumulativeSchedule() && loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
|
||||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||||
|
} else if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
} else if (loan.getLoanProductRelatedDetail() != null
|
|
||||||
&& loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)
|
|
||||||
&& loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff)) {
|
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactions();
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
|
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
return changedTransactionDetail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -1179,14 +1138,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
LoanTransaction newInterestPaymentWaiverTransaction = loanTransactionAssembler.assembleTransactionAndCalculateChanges(loan, command,
|
LoanTransaction newInterestPaymentWaiverTransaction = loanTransactionAssembler.assembleTransactionAndCalculateChanges(loan, command,
|
||||||
changes);
|
changes);
|
||||||
|
|
||||||
ChangedTransactionDetail changedTransactionDetail = recalculateLoanWithInterestPaymentWaiverTxn(loan,
|
recalculateLoanWithInterestPaymentWaiverTxn(loan, newInterestPaymentWaiverTransaction);
|
||||||
newInterestPaymentWaiverTransaction);
|
|
||||||
|
|
||||||
loanTransactionValidator.validateLoanTransactionInterestPaymentWaiverAfterRecalculation(loan);
|
loanTransactionValidator.validateLoanTransactionInterestPaymentWaiverAfterRecalculation(loan);
|
||||||
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(newInterestPaymentWaiverTransaction);
|
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newInterestPaymentWaiverTransaction);
|
||||||
|
|
||||||
saveChangedTransactionDetail(changedTransactionDetail);
|
|
||||||
|
|
||||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
|
|
||||||
@@ -1230,17 +1186,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveChangedTransactionDetail(ChangedTransactionDetail changedTransactionDetail) {
|
|
||||||
if (changedTransactionDetail != null) {
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
updateLoanTransferTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult makeLoanRepaymentWithChargeRefundChargeType(final LoanTransactionType repaymentTransactionType,
|
public CommandProcessingResult makeLoanRepaymentWithChargeRefundChargeType(final LoanTransactionType repaymentTransactionType,
|
||||||
@@ -1451,9 +1396,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
loanTransactionValidator.validateRepaymentDateIsOnNonWorkingDay(newTransactionDetail.getTransactionDate(),
|
loanTransactionValidator.validateRepaymentDateIsOnNonWorkingDay(newTransactionDetail.getTransactionDate(),
|
||||||
holidayDetailDTO.getWorkingDays(), holidayDetailDTO.isAllowTransactionsOnNonWorkingDay());
|
holidayDetailDTO.getWorkingDays(), holidayDetailDTO.isAllowTransactionsOnNonWorkingDay());
|
||||||
|
|
||||||
final ChangedTransactionDetail changedTransactionDetail = adjustExistingTransaction(loan, newTransactionDetail,
|
adjustExistingTransaction(loan, newTransactionDetail, loanLifecycleStateMachine, transactionToAdjust, existingTransactionIds,
|
||||||
loanLifecycleStateMachine, transactionToAdjust, existingTransactionIds, existingReversedTransactionIds,
|
existingReversedTransactionIds, scheduleGeneratorDTO, reversalTxnExternalId);
|
||||||
scheduleGeneratorDTO, reversalTxnExternalId);
|
|
||||||
|
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
@@ -1468,19 +1412,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
this.loanTransactionRepository.saveAndFlush(newTransactionDetail);
|
this.loanTransactionRepository.saveAndFlush(newTransactionDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO Vishwas Batch save is giving me a HibernateOptimisticLockingFailureException, looping and saving for the
|
|
||||||
* time being, not a major issue for now as this loop is entered only in edge cases (when a adjustment is made
|
|
||||||
* before the latest payment recorded against the loan)
|
|
||||||
*/
|
|
||||||
if (changedTransactionDetail != null) {
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
|
|
||||||
final String noteText = command.stringValueOfParameterNamed("note");
|
final String noteText = command.stringValueOfParameterNamed("note");
|
||||||
@@ -1545,13 +1476,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
.with(changes).build();
|
.with(changes).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChangedTransactionDetail adjustExistingTransaction(final Loan loan, final LoanTransaction newTransactionDetail,
|
public void adjustExistingTransaction(final Loan loan, final LoanTransaction newTransactionDetail,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction transactionForAdjustment,
|
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction transactionForAdjustment,
|
||||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
|
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO, final ExternalId reversalExternalId) {
|
final ScheduleGeneratorDTO scheduleGeneratorDTO, final ExternalId reversalExternalId) {
|
||||||
|
|
||||||
ChangedTransactionDetail changedTransactionDetail = null;
|
|
||||||
|
|
||||||
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
||||||
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
||||||
|
|
||||||
@@ -1598,11 +1526,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
loan.updateLoanSummaryAndStatus();
|
loan.updateLoanSummaryAndStatus();
|
||||||
|
|
||||||
if (newTransactionDetail.isRepaymentLikeType() || newTransactionDetail.isInterestWaiver()) {
|
if (newTransactionDetail.isRepaymentLikeType() || newTransactionDetail.isInterestWaiver()) {
|
||||||
changedTransactionDetail = loanDownPaymentHandlerService.handleRepaymentOrRecoveryOrWaiverTransaction(loan,
|
loanDownPaymentHandlerService.handleRepaymentOrRecoveryOrWaiverTransaction(loan, newTransactionDetail,
|
||||||
newTransactionDetail, loanLifecycleStateMachine, transactionForAdjustment, scheduleGeneratorDTO);
|
loanLifecycleStateMachine, transactionForAdjustment, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
return changedTransactionDetail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -1763,8 +1689,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
LoanEvent.LOAN_REPAYMENT_OR_WAIVER);
|
LoanEvent.LOAN_REPAYMENT_OR_WAIVER);
|
||||||
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
|
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
|
||||||
waiveInterestTransaction.getTransactionDate());
|
waiveInterestTransaction.getTransactionDate());
|
||||||
final ChangedTransactionDetail changedTransactionDetail = waiveInterest(loan, waiveInterestTransaction, loanLifecycleStateMachine,
|
waiveInterest(loan, waiveInterestTransaction, loanLifecycleStateMachine, existingTransactionIds, existingReversedTransactionIds,
|
||||||
existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO);
|
scheduleGeneratorDTO);
|
||||||
|
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
@@ -1772,21 +1698,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.loanTransactionRepository.saveAndFlush(waiveInterestTransaction);
|
this.loanTransactionRepository.saveAndFlush(waiveInterestTransaction);
|
||||||
|
|
||||||
/***
|
|
||||||
* TODO Vishwas Batch save is giving me a HibernateOptimisticLockingFailureException, looping and saving for the
|
|
||||||
* time being, not a major issue for now as this loop is entered only in edge cases (when a waiver is made
|
|
||||||
* before the latest payment recorded against the loan)
|
|
||||||
***/
|
|
||||||
|
|
||||||
if (changedTransactionDetail != null) {
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
|
|
||||||
final String noteText = command.stringValueOfParameterNamed("note");
|
final String noteText = command.stringValueOfParameterNamed("note");
|
||||||
@@ -1874,45 +1785,41 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
.withLoanId(loanId) //
|
.withLoanId(loanId) //
|
||||||
.with(changes);
|
.with(changes);
|
||||||
|
|
||||||
final ChangedTransactionDetail changedTransactionDetail = closeAsWrittenOff(loan, command, loanLifecycleStateMachine, changes,
|
final Optional<LoanTransaction> loanTransactionOptional = closeAsWrittenOff(loan, command, loanLifecycleStateMachine, changes,
|
||||||
existingTransactionIds, existingReversedTransactionIds, currentUser, scheduleGeneratorDTO);
|
existingTransactionIds, existingReversedTransactionIds, currentUser, scheduleGeneratorDTO);
|
||||||
|
|
||||||
if (changedTransactionDetail != null) {
|
if (loanTransactionOptional.isPresent()) {
|
||||||
|
final LoanTransaction loanTransaction = loanTransactionOptional.get();
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||||
}
|
}
|
||||||
LoanTransaction writeOff = changedTransactionDetail.getNewTransactionMappings().remove(0L);
|
this.loanTransactionRepository.saveAndFlush(loanTransaction);
|
||||||
this.loanTransactionRepository.saveAndFlush(writeOff);
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
this.loanTransactionRepository.save(mapEntry.getValue());
|
|
||||||
this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||||
final String noteText = command.stringValueOfParameterNamed("note");
|
final String noteText = command.stringValueOfParameterNamed("note");
|
||||||
if (StringUtils.isNotBlank(noteText)) {
|
if (StringUtils.isNotBlank(noteText)) {
|
||||||
changes.put("note", noteText);
|
changes.put("note", noteText);
|
||||||
final Note note = Note.loanTransactionNote(loan, writeOff, noteText);
|
final Note note = Note.loanTransactionNote(loan, loanTransaction, noteText);
|
||||||
this.noteRepository.save(note);
|
this.noteRepository.save(note);
|
||||||
}
|
}
|
||||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan,
|
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan,
|
||||||
loan.isInterestBearingAndInterestRecalculationEnabled(), false);
|
loan.isInterestBearingAndInterestRecalculationEnabled(), false);
|
||||||
loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanWrittenOffPostBusinessEvent(writeOff));
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanWrittenOffPostBusinessEvent(loanTransaction));
|
||||||
|
|
||||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||||
|
|
||||||
builder.withEntityId(writeOff.getId()).withEntityExternalId(writeOff.getExternalId());
|
builder.withEntityId(loanTransaction.getId()).withEntityExternalId(loanTransaction.getExternalId());
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult closeLoan(final Long loanId, final JsonCommand command) {
|
public CommandProcessingResult closeLoan(final Long loanId, final JsonCommand command) {
|
||||||
|
|
||||||
this.loanTransactionValidator.validateTransactionWithNoAmount(command.json());
|
this.loanTransactionValidator.validateTransactionWithNoAmount(command.json());
|
||||||
|
|
||||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||||
@@ -1946,22 +1853,15 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final LocalDate closureDate = command.localDateValueOfParameterNamed(TRANSACTION_DATE);
|
final LocalDate closureDate = command.localDateValueOfParameterNamed(TRANSACTION_DATE);
|
||||||
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.LOAN_CLOSED);
|
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.LOAN_CLOSED);
|
||||||
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, LoanEvent.REPAID_IN_FULL, closureDate);
|
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, LoanEvent.REPAID_IN_FULL, closureDate);
|
||||||
ChangedTransactionDetail changedTransactionDetail = close(loan, command, loanLifecycleStateMachine, changes, existingTransactionIds,
|
final Optional<LoanTransaction> loanTransactionOptional = close(loan, command, loanLifecycleStateMachine, changes,
|
||||||
existingReversedTransactionIds, scheduleGeneratorDTO);
|
existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO);
|
||||||
|
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
final LoanTransaction possibleClosingTransaction = changedTransactionDetail.getNewTransactionMappings().remove(0L);
|
loanTransactionOptional.ifPresent(this.loanTransactionRepository::saveAndFlush);
|
||||||
if (possibleClosingTransaction != null) {
|
|
||||||
this.loanTransactionRepository.saveAndFlush(possibleClosingTransaction);
|
|
||||||
}
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
this.loanTransactionRepository.save(mapEntry.getValue());
|
|
||||||
this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||||
|
|
||||||
final String noteText = command.stringValueOfParameterNamed("note");
|
final String noteText = command.stringValueOfParameterNamed("note");
|
||||||
@@ -1989,12 +1889,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||||
|
|
||||||
CommandProcessingResult result;
|
CommandProcessingResult result;
|
||||||
if (possibleClosingTransaction != null) {
|
if (loanTransactionOptional.isPresent()) {
|
||||||
|
|
||||||
result = new CommandProcessingResultBuilder() //
|
result = new CommandProcessingResultBuilder() //
|
||||||
.withCommandId(command.commandId()) //
|
.withCommandId(command.commandId()) //
|
||||||
.withEntityId(possibleClosingTransaction.getId()) //
|
.withEntityId(loanTransactionOptional.get().getId()) //
|
||||||
.withEntityExternalId(possibleClosingTransaction.getExternalId()) //
|
.withEntityExternalId(loanTransactionOptional.get().getExternalId()) //
|
||||||
.withOfficeId(loan.getOfficeId()) //
|
.withOfficeId(loan.getOfficeId()) //
|
||||||
.withClientId(loan.getClientId()) //
|
.withClientId(loan.getClientId()) //
|
||||||
.withGroupId(loan.getGroupId()) //
|
.withGroupId(loan.getGroupId()) //
|
||||||
@@ -2589,20 +2488,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanUndoWrittenOffBusinessEvent(writeOffTransaction));
|
businessEventNotifierService.notifyPreBusinessEvent(new LoanUndoWrittenOffBusinessEvent(writeOffTransaction));
|
||||||
|
|
||||||
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.WRITE_OFF_OUTSTANDING_UNDO);
|
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.WRITE_OFF_OUTSTANDING_UNDO);
|
||||||
ChangedTransactionDetail changedTransactionDetail = undoWrittenOff(loan, loanLifecycleStateMachine, existingTransactionIds,
|
undoWrittenOff(loan, loanLifecycleStateMachine, existingTransactionIds, existingReversedTransactionIds);
|
||||||
existingReversedTransactionIds);
|
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||||
}
|
}
|
||||||
if (changedTransactionDetail != null) {
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
|
|
||||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||||
@@ -2730,20 +2620,17 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
LocalDate recalculateFrom = null;
|
LocalDate recalculateFrom = null;
|
||||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||||
|
|
||||||
ChangedTransactionDetail changedTransactionDetail = null;
|
|
||||||
|
|
||||||
if (command.entityId() != null) {
|
if (command.entityId() != null) {
|
||||||
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.LOAN_EDIT_MULTI_DISBURSE_DATE);
|
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.LOAN_EDIT_MULTI_DISBURSE_DATE);
|
||||||
changedTransactionDetail = updateDisbursementDateAndAmountForTranche(loan, loanDisbursementDetails, command, changes,
|
updateDisbursementDateAndAmountForTranche(loan, loanDisbursementDetails, command, changes, scheduleGeneratorDTO);
|
||||||
scheduleGeneratorDTO);
|
|
||||||
} else {
|
} else {
|
||||||
loan.repaymentScheduleDetail().setPrincipal(loan.getPrincipalAmountForRepaymentSchedule());
|
loan.repaymentScheduleDetail().setPrincipal(loan.getPrincipalAmountForRepaymentSchedule());
|
||||||
|
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isCumulativeSchedule() && loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||||
} else {
|
} else if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
loan.processPostDisbursementTransactions();
|
reprocessLoanTransactionsService.processPostDisbursementTransactions(loan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2752,14 +2639,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.entityId() != null && changedTransactionDetail != null) {
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
createLoanScheduleArchive(loan, scheduleGeneratorDTO);
|
createLoanScheduleArchive(loan, scheduleGeneratorDTO);
|
||||||
@@ -2817,22 +2696,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
|
|
||||||
ScheduleGeneratorDTO generatorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
ScheduleGeneratorDTO generatorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||||
|
|
||||||
ChangedTransactionDetail changedTransactionDetail = loanScheduleService.recalculateScheduleFromLastTransaction(loan, generatorDTO,
|
loanScheduleService.recalculateScheduleFromLastTransaction(loan, generatorDTO, existingTransactionIds,
|
||||||
existingTransactionIds, existingReversedTransactionIds);
|
existingReversedTransactionIds);
|
||||||
|
|
||||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedTransactionDetail != null) {
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||||
false);
|
false);
|
||||||
@@ -2909,9 +2780,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
|
|
||||||
if (loan.isActualDisbursedOnDateEarlierOrLaterThanExpected(actualDisbursementDate) || recalculateSchedule || isEmiAmountChanged
|
if (loan.isActualDisbursedOnDateEarlierOrLaterThanExpected(actualDisbursementDate) || recalculateSchedule || isEmiAmountChanged
|
||||||
|| rescheduledRepaymentDate != null) {
|
|| rescheduledRepaymentDate != null) {
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isCumulativeSchedule() && loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||||
} else {
|
} else if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3168,7 +3039,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public CommandProcessingResult chargeOff(JsonCommand command) {
|
public CommandProcessingResult chargeOff(JsonCommand command) {
|
||||||
|
|
||||||
loanTransactionValidator.validateChargeOffTransaction(command.json());
|
loanTransactionValidator.validateChargeOffTransaction(command.json());
|
||||||
|
|
||||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||||
@@ -3225,18 +3095,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final LoanTransaction chargeOffTransaction = LoanTransaction.chargeOff(loan, transactionDate, txnExternalId);
|
final LoanTransaction chargeOffTransaction = LoanTransaction.chargeOff(loan, transactionDate, txnExternalId);
|
||||||
|
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, null, null);
|
if (loan.isCumulativeSchedule()) {
|
||||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, null, null);
|
||||||
loan.addLoanTransaction(chargeOffTransaction);
|
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||||
ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactions();
|
|
||||||
if (changedTransactionDetail != null) {
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
// Trigger transaction replayed event
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
}
|
||||||
|
loan.addLoanTransaction(chargeOffTransaction);
|
||||||
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
} else {
|
} else {
|
||||||
loan.addLoanTransaction(chargeOffTransaction);
|
loan.addLoanTransaction(chargeOffTransaction);
|
||||||
loan.getTransactionProcessor().processLatestTransaction(chargeOffTransaction,
|
loan.getTransactionProcessor().processLatestTransaction(chargeOffTransaction,
|
||||||
@@ -3307,30 +3171,20 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
|
|
||||||
loan.liftChargeOff();
|
loan.liftChargeOff();
|
||||||
loanTransactionRepository.saveAndFlush(chargedOffTransaction);
|
loanTransactionRepository.saveAndFlush(chargedOffTransaction);
|
||||||
if (loan.isProgressiveSchedule()) {
|
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, null, null);
|
|
||||||
|
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, null, null);
|
||||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
if (loan.isCumulativeSchedule() && loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
} else {
|
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
} else if (loan.isProgressiveSchedule()) {
|
||||||
}
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
|
|
||||||
ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactions();
|
|
||||||
if (changedTransactionDetail != null) {
|
|
||||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
|
||||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
|
|
||||||
accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
|
|
||||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanUndoChargeOffBusinessEvent(chargedOffTransaction));
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanUndoChargeOffBusinessEvent(chargedOffTransaction));
|
||||||
|
|
||||||
loan.reprocessTransactions();
|
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder() //
|
return new CommandProcessingResultBuilder() //
|
||||||
.withOfficeId(loan.getOfficeId()) //
|
.withOfficeId(loan.getOfficeId()) //
|
||||||
.withClientId(loan.getClientId()) //
|
.withClientId(loan.getClientId()) //
|
||||||
@@ -3577,12 +3431,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
loan.getLoanTransactions().retainAll(retainTransactions);
|
loan.getLoanTransactions().retainAll(retainTransactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangedTransactionDetail closeAsWrittenOff(final Loan loan, final JsonCommand command,
|
private Optional<LoanTransaction> closeAsWrittenOff(final Loan loan, final JsonCommand command,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final Map<String, Object> changes,
|
final LoanLifecycleStateMachine loanLifecycleStateMachine, final Map<String, Object> changes,
|
||||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds, final AppUser currentUser,
|
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds, final AppUser currentUser,
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor();
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor();
|
||||||
ChangedTransactionDetail changedTransactionDetail = closeDisbursements(loan, scheduleGeneratorDTO);
|
closeDisbursements(loan, scheduleGeneratorDTO);
|
||||||
|
|
||||||
final LocalDate writtenOffOnLocalDate = command.localDateValueOfParameterNamed(TRANSACTION_DATE);
|
final LocalDate writtenOffOnLocalDate = command.localDateValueOfParameterNamed(TRANSACTION_DATE);
|
||||||
loan.setClosedOnDate(writtenOffOnLocalDate);
|
loan.setClosedOnDate(writtenOffOnLocalDate);
|
||||||
@@ -3590,82 +3444,74 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
loan.setClosedBy(currentUser);
|
loan.setClosedBy(currentUser);
|
||||||
final LoanStatus statusEnum = loanLifecycleStateMachine.dryTransition(LoanEvent.WRITE_OFF_OUTSTANDING, loan);
|
final LoanStatus statusEnum = loanLifecycleStateMachine.dryTransition(LoanEvent.WRITE_OFF_OUTSTANDING, loan);
|
||||||
|
|
||||||
LoanTransaction loanTransaction = null;
|
if (statusEnum.hasStateOf(loan.getStatus())) {
|
||||||
if (!statusEnum.hasStateOf(loan.getStatus())) {
|
return Optional.empty();
|
||||||
loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING, loan);
|
|
||||||
changes.put(PARAM_STATUS, LoanEnumerations.status(loan.getLoanStatus()));
|
|
||||||
|
|
||||||
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
|
||||||
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
|
||||||
|
|
||||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull(EXTERNAL_ID);
|
|
||||||
|
|
||||||
ExternalId externalId = ExternalIdFactory.produce(txnExternalId);
|
|
||||||
|
|
||||||
if (externalId.isEmpty() && TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
|
|
||||||
externalId = ExternalId.generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
changes.put(CLOSED_ON_DATE, command.stringValueOfParameterNamed(TRANSACTION_DATE));
|
|
||||||
changes.put(WRITTEN_OFF_ON_DATE, command.stringValueOfParameterNamed(TRANSACTION_DATE));
|
|
||||||
changes.put("externalId", externalId);
|
|
||||||
|
|
||||||
if (DateUtils.isBefore(writtenOffOnLocalDate, loan.getDisbursementDate())) {
|
|
||||||
final String errorMessage = "The date on which a loan is written off cannot be before the loan disbursement date: "
|
|
||||||
+ loan.getDisbursementDate().toString();
|
|
||||||
throw new InvalidLoanStateTransitionException("writeoff", "cannot.be.before.submittal.date", errorMessage,
|
|
||||||
writtenOffOnLocalDate, loan.getDisbursementDate());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DateUtils.isDateInTheFuture(writtenOffOnLocalDate)) {
|
|
||||||
final String errorMessage = "The date on which a loan is written off cannot be in the future.";
|
|
||||||
throw new InvalidLoanStateTransitionException("writeoff", "cannot.be.a.future.date", errorMessage, writtenOffOnLocalDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
loanTransaction = LoanTransaction.writeoff(loan, loan.getOffice(), writtenOffOnLocalDate, externalId);
|
|
||||||
LocalDate lastTransactionDate = loan.getLastUserTransactionDate();
|
|
||||||
if (DateUtils.isAfter(lastTransactionDate, writtenOffOnLocalDate)) {
|
|
||||||
final String errorMessage = "The date of the writeoff transaction must occur on or before previous transactions.";
|
|
||||||
throw new InvalidLoanStateTransitionException("writeoff", "must.occur.on.or.after.other.transaction.dates", errorMessage,
|
|
||||||
writtenOffOnLocalDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
loan.addLoanTransaction(loanTransaction);
|
|
||||||
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(loanTransaction,
|
|
||||||
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
|
||||||
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
|
||||||
|
|
||||||
loan.updateLoanSummaryDerivedFields();
|
|
||||||
}
|
}
|
||||||
if (changedTransactionDetail == null) {
|
|
||||||
changedTransactionDetail = new ChangedTransactionDetail();
|
loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING, loan);
|
||||||
|
changes.put(PARAM_STATUS, LoanEnumerations.status(loan.getLoanStatus()));
|
||||||
|
|
||||||
|
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
||||||
|
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
||||||
|
|
||||||
|
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull(EXTERNAL_ID);
|
||||||
|
|
||||||
|
ExternalId externalId = ExternalIdFactory.produce(txnExternalId);
|
||||||
|
|
||||||
|
if (externalId.isEmpty() && TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
|
||||||
|
externalId = ExternalId.generate();
|
||||||
}
|
}
|
||||||
changedTransactionDetail.getNewTransactionMappings().put(0L, loanTransaction);
|
|
||||||
return changedTransactionDetail;
|
changes.put(CLOSED_ON_DATE, command.stringValueOfParameterNamed(TRANSACTION_DATE));
|
||||||
|
changes.put(WRITTEN_OFF_ON_DATE, command.stringValueOfParameterNamed(TRANSACTION_DATE));
|
||||||
|
changes.put("externalId", externalId);
|
||||||
|
|
||||||
|
if (DateUtils.isBefore(writtenOffOnLocalDate, loan.getDisbursementDate())) {
|
||||||
|
final String errorMessage = "The date on which a loan is written off cannot be before the loan disbursement date: "
|
||||||
|
+ loan.getDisbursementDate().toString();
|
||||||
|
throw new InvalidLoanStateTransitionException("writeoff", "cannot.be.before.submittal.date", errorMessage,
|
||||||
|
writtenOffOnLocalDate, loan.getDisbursementDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DateUtils.isDateInTheFuture(writtenOffOnLocalDate)) {
|
||||||
|
final String errorMessage = "The date on which a loan is written off cannot be in the future.";
|
||||||
|
throw new InvalidLoanStateTransitionException("writeoff", "cannot.be.a.future.date", errorMessage, writtenOffOnLocalDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
final LoanTransaction loanTransaction = LoanTransaction.writeoff(loan, loan.getOffice(), writtenOffOnLocalDate, externalId);
|
||||||
|
LocalDate lastTransactionDate = loan.getLastUserTransactionDate();
|
||||||
|
if (DateUtils.isAfter(lastTransactionDate, writtenOffOnLocalDate)) {
|
||||||
|
final String errorMessage = "The date of the writeoff transaction must occur on or before previous transactions.";
|
||||||
|
throw new InvalidLoanStateTransitionException("writeoff", "must.occur.on.or.after.other.transaction.dates", errorMessage,
|
||||||
|
writtenOffOnLocalDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
loan.addLoanTransaction(loanTransaction);
|
||||||
|
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(loanTransaction, new TransactionCtx(loan.getCurrency(),
|
||||||
|
loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(), new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
||||||
|
|
||||||
|
loan.updateLoanSummaryDerivedFields();
|
||||||
|
|
||||||
|
return Optional.of(loanTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangedTransactionDetail closeDisbursements(final Loan loan, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
private void closeDisbursements(final Loan loan, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||||
ChangedTransactionDetail changedTransactionDetail = null;
|
|
||||||
if (loan.isDisbursementAllowed() && loan.atLeastOnceDisbursed()) {
|
if (loan.isDisbursementAllowed() && loan.atLeastOnceDisbursed()) {
|
||||||
loan.getLoanRepaymentScheduleDetail().setPrincipal(loan.getDisbursedAmount());
|
loan.getLoanRepaymentScheduleDetail().setPrincipal(loan.getDisbursedAmount());
|
||||||
loan.removeDisbursementDetail();
|
loan.removeDisbursementDetail();
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isCumulativeSchedule() && loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||||
}
|
} else if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
if (loan.getLoanProductRelatedDetail() != null
|
|
||||||
&& loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)
|
|
||||||
&& loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff)) {
|
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
changedTransactionDetail = loan.reprocessTransactions();
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
LocalDate lastLoanTransactionDate = loan.getLatestTransactionDate();
|
LocalDate lastLoanTransactionDate = loan.getLatestTransactionDate();
|
||||||
loan.doPostLoanTransactionChecks(lastLoanTransactionDate, loanLifecycleStateMachine);
|
loan.doPostLoanTransactionChecks(lastLoanTransactionDate, loanLifecycleStateMachine);
|
||||||
}
|
}
|
||||||
return changedTransactionDetail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangedTransactionDetail close(final Loan loan, final JsonCommand command,
|
private Optional<LoanTransaction> close(final Loan loan, final JsonCommand command,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final Map<String, Object> changes,
|
final LoanLifecycleStateMachine loanLifecycleStateMachine, final Map<String, Object> changes,
|
||||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
|
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||||
@@ -3695,7 +3541,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
throw new InvalidLoanStateTransitionException("close", "cannot.be.a.future.date", errorMessage, closureDate);
|
throw new InvalidLoanStateTransitionException("close", "cannot.be.a.future.date", errorMessage, closureDate);
|
||||||
}
|
}
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor();
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor();
|
||||||
ChangedTransactionDetail changedTransactionDetail = closeDisbursements(loan, scheduleGeneratorDTO);
|
closeDisbursements(loan, scheduleGeneratorDTO);
|
||||||
|
|
||||||
LoanTransaction loanTransaction = null;
|
LoanTransaction loanTransaction = null;
|
||||||
if (loan.isOpen()) {
|
if (loan.isOpen()) {
|
||||||
@@ -3747,16 +3593,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedTransactionDetail == null) {
|
return Optional.ofNullable(loanTransaction);
|
||||||
changedTransactionDetail = new ChangedTransactionDetail();
|
|
||||||
}
|
|
||||||
changedTransactionDetail.getNewTransactionMappings().put(0L, loanTransaction);
|
|
||||||
return changedTransactionDetail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangedTransactionDetail updateDisbursementDateAndAmountForTranche(final Loan loan,
|
private void updateDisbursementDateAndAmountForTranche(final Loan loan, final LoanDisbursementDetails disbursementDetails,
|
||||||
final LoanDisbursementDetails disbursementDetails, final JsonCommand command, final Map<String, Object> actualChanges,
|
final JsonCommand command, final Map<String, Object> actualChanges, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
|
||||||
final Locale locale = command.extractLocale();
|
final Locale locale = command.extractLocale();
|
||||||
final BigDecimal principal = command.bigDecimalValueOfParameterNamed(LoanApiConstants.updatedDisbursementPrincipalParameterName,
|
final BigDecimal principal = command.bigDecimalValueOfParameterNamed(LoanApiConstants.updatedDisbursementPrincipalParameterName,
|
||||||
locale);
|
locale);
|
||||||
@@ -3772,15 +3613,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
|
|
||||||
loan.getLoanRepaymentScheduleDetail().setPrincipal(loan.getPrincipalAmountForRepaymentSchedule());
|
loan.getLoanRepaymentScheduleDetail().setPrincipal(loan.getPrincipalAmountForRepaymentSchedule());
|
||||||
|
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled() && !(loan.getLoanProductRelatedDetail() != null
|
if (loan.isCumulativeSchedule() && loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
&& loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)
|
|
||||||
&& loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff))) {
|
|
||||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||||
} else {
|
} else if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
return loan.reprocessTransactions();
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Object> undoLastDisbursal(final ScheduleGeneratorDTO scheduleGeneratorDTO, final List<Long> existingTransactionIds,
|
private Map<String, Object> undoLastDisbursal(final ScheduleGeneratorDTO scheduleGeneratorDTO, final List<Long> existingTransactionIds,
|
||||||
@@ -3826,17 +3665,17 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
return actualChanges;
|
return actualChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangedTransactionDetail waiveInterest(final Loan loan, final LoanTransaction waiveInterestTransaction,
|
private void waiveInterest(final Loan loan, final LoanTransaction waiveInterestTransaction,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final List<Long> existingTransactionIds,
|
final LoanLifecycleStateMachine loanLifecycleStateMachine, final List<Long> existingTransactionIds,
|
||||||
final List<Long> existingReversedTransactionIds, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
final List<Long> existingReversedTransactionIds, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||||
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
||||||
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
||||||
|
|
||||||
return loanDownPaymentHandlerService.handleRepaymentOrRecoveryOrWaiverTransaction(loan, waiveInterestTransaction,
|
loanDownPaymentHandlerService.handleRepaymentOrRecoveryOrWaiverTransaction(loan, waiveInterestTransaction,
|
||||||
loanLifecycleStateMachine, null, scheduleGeneratorDTO);
|
loanLifecycleStateMachine, null, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangedTransactionDetail undoWrittenOff(final Loan loan, final LoanLifecycleStateMachine loanLifecycleStateMachine,
|
private void undoWrittenOff(final Loan loan, final LoanLifecycleStateMachine loanLifecycleStateMachine,
|
||||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
||||||
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
||||||
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
|
||||||
@@ -3845,13 +3684,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
"reversed");
|
"reversed");
|
||||||
writeOffTransaction.reverse();
|
writeOffTransaction.reverse();
|
||||||
loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING_UNDO, loan);
|
loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING_UNDO, loan);
|
||||||
if (loan.getLoanProductRelatedDetail() != null
|
if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
&& loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)
|
|
||||||
&& loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff)) {
|
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, null);
|
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, null);
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
return loan.reprocessTransactions();
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-4
@@ -41,7 +41,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.starter.AdvancedPaymentScheduleTransactionProcessorCondition;
|
import org.apache.fineract.portfolio.loanaccount.starter.AdvancedPaymentScheduleTransactionProcessorCondition;
|
||||||
import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
|
import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
|
||||||
import org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
|
import org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
|
||||||
@@ -85,9 +84,7 @@ public class ProgressiveLoanInterestRefundServiceImpl implements InterestRefundS
|
|||||||
List<LoanRepaymentScheduleInstallment> installmentsToReprocess = new ArrayList<>(
|
List<LoanRepaymentScheduleInstallment> installmentsToReprocess = new ArrayList<>(
|
||||||
loan.getRepaymentScheduleInstallments().stream().filter(i -> !i.isReAged() && !i.isAdditional()).toList());
|
loan.getRepaymentScheduleInstallments().stream().filter(i -> !i.isReAged() && !i.isAdditional()).toList());
|
||||||
|
|
||||||
if (loan.getLoanProductRelatedDetail() != null
|
if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
&& loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)
|
|
||||||
&& loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff)) {
|
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, null);
|
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, null);
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-7
@@ -47,16 +47,15 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter;
|
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgingParameterRepository;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
||||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionNotFoundException;
|
import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionNotFoundException;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanScheduleService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanScheduleService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.service.ReprocessLoanTransactionsService;
|
||||||
import org.apache.fineract.portfolio.note.domain.Note;
|
import org.apache.fineract.portfolio.note.domain.Note;
|
||||||
import org.apache.fineract.portfolio.note.domain.NoteRepository;
|
import org.apache.fineract.portfolio.note.domain.NoteRepository;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -72,12 +71,12 @@ public class LoanReAgingServiceImpl {
|
|||||||
private final ExternalIdFactory externalIdFactory;
|
private final ExternalIdFactory externalIdFactory;
|
||||||
private final BusinessEventNotifierService businessEventNotifierService;
|
private final BusinessEventNotifierService businessEventNotifierService;
|
||||||
private final LoanTransactionRepository loanTransactionRepository;
|
private final LoanTransactionRepository loanTransactionRepository;
|
||||||
private final LoanReAgingParameterRepository reAgingParameterRepository;
|
|
||||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||||
private final NoteRepository noteRepository;
|
private final NoteRepository noteRepository;
|
||||||
private final LoanChargeValidator loanChargeValidator;
|
private final LoanChargeValidator loanChargeValidator;
|
||||||
private final LoanUtilService loanUtilService;
|
private final LoanUtilService loanUtilService;
|
||||||
private final LoanScheduleService loanScheduleService;
|
private final LoanScheduleService loanScheduleService;
|
||||||
|
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
|
||||||
public CommandProcessingResult reAge(Long loanId, JsonCommand command) {
|
public CommandProcessingResult reAge(Long loanId, JsonCommand command) {
|
||||||
Loan loan = loanAssembler.assembleFrom(loanId);
|
Loan loan = loanAssembler.assembleFrom(loanId);
|
||||||
@@ -129,13 +128,11 @@ public class LoanReAgingServiceImpl {
|
|||||||
}
|
}
|
||||||
reverseReAgeTransaction(reAgeTransaction, command);
|
reverseReAgeTransaction(reAgeTransaction, command);
|
||||||
loanTransactionRepository.saveAndFlush(reAgeTransaction);
|
loanTransactionRepository.saveAndFlush(reAgeTransaction);
|
||||||
if (loan.getLoanProductRelatedDetail() != null
|
if (loan.isProgressiveSchedule() && loan.hasChargeOffTransaction()) {
|
||||||
&& loan.getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE)
|
|
||||||
&& loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isChargeOff)) {
|
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, null);
|
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, null);
|
||||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
loan.reprocessTransactions();
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
loan.updateLoanScheduleDependentDerivedFields();
|
loan.updateLoanScheduleDependentDerivedFields();
|
||||||
persistNote(loan, command, changes);
|
persistNote(loan, command, changes);
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -49,6 +49,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.Mon
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
||||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.service.ReprocessLoanTransactionsService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@@ -64,6 +65,7 @@ public class LoanReAmortizationServiceImpl {
|
|||||||
private final LoanTransactionRepository loanTransactionRepository;
|
private final LoanTransactionRepository loanTransactionRepository;
|
||||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||||
private final LoanChargeValidator loanChargeValidator;
|
private final LoanChargeValidator loanChargeValidator;
|
||||||
|
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
|
||||||
public CommandProcessingResult reAmortize(Long loanId, JsonCommand command) {
|
public CommandProcessingResult reAmortize(Long loanId, JsonCommand command) {
|
||||||
Loan loan = loanAssembler.assembleFrom(loanId);
|
Loan loan = loanAssembler.assembleFrom(loanId);
|
||||||
@@ -132,7 +134,7 @@ public class LoanReAmortizationServiceImpl {
|
|||||||
"reversed");
|
"reversed");
|
||||||
reAmortizeTransaction.reverse(reversalExternalId);
|
reAmortizeTransaction.reverse(reversalExternalId);
|
||||||
reAmortizeTransaction.manuallyAdjustedOrReversed();
|
reAmortizeTransaction.manuallyAdjustedOrReversed();
|
||||||
reAmortizeTransaction.getLoan().reprocessTransactions();
|
reprocessLoanTransactionsService.reprocessTransactions(reAmortizeTransaction.getLoan());
|
||||||
}
|
}
|
||||||
|
|
||||||
private LoanTransaction findLatestNonReversedReAmortizeTransaction(Loan loan) {
|
private LoanTransaction findLatestNonReversedReAmortizeTransaction(Loan loan) {
|
||||||
|
|||||||
+42
-32
@@ -42,7 +42,6 @@ import org.apache.fineract.organisation.teller.data.CashierTransactionDataValida
|
|||||||
import org.apache.fineract.organisation.workingdays.domain.WorkingDaysRepositoryWrapper;
|
import org.apache.fineract.organisation.workingdays.domain.WorkingDaysRepositoryWrapper;
|
||||||
import org.apache.fineract.portfolio.account.domain.AccountAssociationsRepository;
|
import org.apache.fineract.portfolio.account.domain.AccountAssociationsRepository;
|
||||||
import org.apache.fineract.portfolio.account.domain.AccountTransferDetailRepository;
|
import org.apache.fineract.portfolio.account.domain.AccountTransferDetailRepository;
|
||||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRepository;
|
|
||||||
import org.apache.fineract.portfolio.account.service.AccountAssociationsReadPlatformService;
|
import org.apache.fineract.portfolio.account.service.AccountAssociationsReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.account.service.AccountNumberGenerator;
|
import org.apache.fineract.portfolio.account.service.AccountNumberGenerator;
|
||||||
import org.apache.fineract.portfolio.account.service.AccountTransfersReadPlatformService;
|
import org.apache.fineract.portfolio.account.service.AccountTransfersReadPlatformService;
|
||||||
@@ -64,13 +63,13 @@ import org.apache.fineract.portfolio.fund.domain.FundRepository;
|
|||||||
import org.apache.fineract.portfolio.fund.service.FundReadPlatformService;
|
import org.apache.fineract.portfolio.fund.service.FundReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.group.domain.GroupRepositoryWrapper;
|
import org.apache.fineract.portfolio.group.domain.GroupRepositoryWrapper;
|
||||||
import org.apache.fineract.portfolio.group.service.GroupReadPlatformService;
|
import org.apache.fineract.portfolio.group.service.GroupReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.interestpauses.service.AccountTransfersService;
|
|
||||||
import org.apache.fineract.portfolio.interestpauses.service.InterestPauseReadPlatformService;
|
import org.apache.fineract.portfolio.interestpauses.service.InterestPauseReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.interestpauses.service.InterestPauseReadPlatformServiceImpl;
|
import org.apache.fineract.portfolio.interestpauses.service.InterestPauseReadPlatformServiceImpl;
|
||||||
import org.apache.fineract.portfolio.interestpauses.service.InterestPauseWritePlatformService;
|
import org.apache.fineract.portfolio.interestpauses.service.InterestPauseWritePlatformService;
|
||||||
import org.apache.fineract.portfolio.interestpauses.service.InterestPauseWritePlatformServiceImpl;
|
import org.apache.fineract.portfolio.interestpauses.service.InterestPauseWritePlatformServiceImpl;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.GLIMAccountInfoRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.GLIMAccountInfoRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallmentRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallmentRepository;
|
||||||
@@ -104,6 +103,7 @@ import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoReadPlat
|
|||||||
import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoReadPlatformServiceImpl;
|
import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoReadPlatformServiceImpl;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoWritePlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoWritePlatformService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoWritePlatformServiceImpl;
|
import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoWritePlatformServiceImpl;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.service.LoanAccountServiceImpl;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualActivityProcessingService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualActivityProcessingService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualEventService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualEventService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualTransactionBusinessEventService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualTransactionBusinessEventService;
|
||||||
@@ -141,6 +141,7 @@ import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformServic
|
|||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformServiceJpaRepositoryImpl;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformServiceJpaRepositoryImpl;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.ReplayedTransactionBusinessEventService;
|
import org.apache.fineract.portfolio.loanaccount.service.ReplayedTransactionBusinessEventService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.ReplayedTransactionBusinessEventServiceImpl;
|
import org.apache.fineract.portfolio.loanaccount.service.ReplayedTransactionBusinessEventServiceImpl;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.service.ReprocessLoanTransactionsService;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
|
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
|
||||||
import org.apache.fineract.portfolio.loanproduct.service.LoanDropdownReadPlatformService;
|
import org.apache.fineract.portfolio.loanproduct.service.LoanDropdownReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService;
|
import org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService;
|
||||||
@@ -192,13 +193,12 @@ public class LoanAccountConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(LoanApplicationWritePlatformService.class)
|
@ConditionalOnMissingBean(LoanApplicationWritePlatformService.class)
|
||||||
public LoanApplicationWritePlatformService loanApplicationWritePlatformService(PlatformSecurityContext context,
|
public LoanApplicationWritePlatformService loanApplicationWritePlatformService(PlatformSecurityContext context,
|
||||||
FromJsonHelper fromJsonHelper, LoanApplicationTransitionValidator loanApplicationTransitionValidator,
|
LoanApplicationTransitionValidator loanApplicationTransitionValidator, LoanApplicationValidator loanApplicationValidator,
|
||||||
LoanApplicationValidator loanApplicationValidator, LoanRepositoryWrapper loanRepositoryWrapper, NoteRepository noteRepository,
|
LoanRepositoryWrapper loanRepositoryWrapper, NoteRepository noteRepository, LoanAssembler loanAssembler,
|
||||||
LoanAssembler loanAssembler, LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
|
LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
|
||||||
CalendarRepository calendarRepository, CalendarInstanceRepository calendarInstanceRepository,
|
CalendarRepository calendarRepository, CalendarInstanceRepository calendarInstanceRepository,
|
||||||
SavingsAccountRepositoryWrapper savingsAccountRepository, AccountAssociationsRepository accountAssociationsRepository,
|
SavingsAccountRepositoryWrapper savingsAccountRepository, AccountAssociationsRepository accountAssociationsRepository,
|
||||||
LoanReadPlatformService loanReadPlatformService, BusinessEventNotifierService businessEventNotifierService,
|
BusinessEventNotifierService businessEventNotifierService, LoanScheduleAssembler loanScheduleAssembler,
|
||||||
ConfigurationDomainService configurationDomainService, LoanScheduleAssembler loanScheduleAssembler,
|
|
||||||
LoanUtilService loanUtilService, CalendarReadPlatformService calendarReadPlatformService,
|
LoanUtilService loanUtilService, CalendarReadPlatformService calendarReadPlatformService,
|
||||||
EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService, GLIMAccountInfoRepository glimRepository,
|
EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService, GLIMAccountInfoRepository glimRepository,
|
||||||
LoanRepository loanRepository, GSIMReadPlatformService gsimReadPlatformService,
|
LoanRepository loanRepository, GSIMReadPlatformService gsimReadPlatformService,
|
||||||
@@ -291,20 +291,20 @@ public class LoanAccountConfiguration {
|
|||||||
ConfigurationDomainService configurationDomainService,
|
ConfigurationDomainService configurationDomainService,
|
||||||
LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
|
LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
|
||||||
ExternalIdFactory externalIdFactory, AccountTransferDetailRepository accountTransferDetailRepository,
|
ExternalIdFactory externalIdFactory, AccountTransferDetailRepository accountTransferDetailRepository,
|
||||||
LoanChargeAssembler loanChargeAssembler, ReplayedTransactionBusinessEventService replayedTransactionBusinessEventService,
|
LoanChargeAssembler loanChargeAssembler, PaymentDetailWritePlatformService paymentDetailWritePlatformService,
|
||||||
PaymentDetailWritePlatformService paymentDetailWritePlatformService, NoteRepository noteRepository,
|
NoteRepository noteRepository, LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService,
|
||||||
LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService,
|
|
||||||
LoanAccrualsProcessingService loanAccrualsProcessingService,
|
LoanAccrualsProcessingService loanAccrualsProcessingService,
|
||||||
LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator, LoanChargeValidator loanChargeValidator,
|
LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator, LoanChargeValidator loanChargeValidator,
|
||||||
LoanScheduleService loanScheduleService) {
|
LoanScheduleService loanScheduleService, ReprocessLoanTransactionsService reprocessLoanTransactionsService,
|
||||||
|
LoanAccountService loanAccountService) {
|
||||||
return new LoanChargeWritePlatformServiceImpl(loanChargeApiJsonValidator, loanAssembler, chargeRepository,
|
return new LoanChargeWritePlatformServiceImpl(loanChargeApiJsonValidator, loanAssembler, chargeRepository,
|
||||||
businessEventNotifierService, loanTransactionRepository, accountTransfersWritePlatformService, loanRepositoryWrapper,
|
businessEventNotifierService, loanTransactionRepository, accountTransfersWritePlatformService, loanRepositoryWrapper,
|
||||||
journalEntryWritePlatformService, loanAccountDomainService, loanChargeRepository, loanWritePlatformService, loanUtilService,
|
journalEntryWritePlatformService, loanAccountDomainService, loanChargeRepository, loanWritePlatformService, loanUtilService,
|
||||||
loanChargeReadPlatformService, defaultLoanLifecycleStateMachine, accountAssociationsReadPlatformService, fromApiJsonHelper,
|
loanChargeReadPlatformService, defaultLoanLifecycleStateMachine, accountAssociationsReadPlatformService, fromApiJsonHelper,
|
||||||
configurationDomainService, loanRepaymentScheduleTransactionProcessorFactory, externalIdFactory,
|
configurationDomainService, loanRepaymentScheduleTransactionProcessorFactory, externalIdFactory,
|
||||||
accountTransferDetailRepository, loanChargeAssembler, replayedTransactionBusinessEventService,
|
accountTransferDetailRepository, loanChargeAssembler, paymentDetailWritePlatformService, noteRepository,
|
||||||
paymentDetailWritePlatformService, noteRepository, loanAccrualTransactionBusinessEventService,
|
loanAccrualTransactionBusinessEventService, loanAccrualsProcessingService, loanDownPaymentTransactionValidator,
|
||||||
loanAccrualsProcessingService, loanDownPaymentTransactionValidator, loanChargeValidator, loanScheduleService);
|
loanChargeValidator, loanScheduleService, reprocessLoanTransactionsService, loanAccountService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -386,13 +386,13 @@ public class LoanAccountConfiguration {
|
|||||||
PostDatedChecksRepository postDatedChecksRepository,
|
PostDatedChecksRepository postDatedChecksRepository,
|
||||||
LoanRepaymentScheduleInstallmentRepository loanRepaymentScheduleInstallmentRepository,
|
LoanRepaymentScheduleInstallmentRepository loanRepaymentScheduleInstallmentRepository,
|
||||||
LoanLifecycleStateMachine defaultLoanLifecycleStateMachine, LoanAccountLockService loanAccountLockService,
|
LoanLifecycleStateMachine defaultLoanLifecycleStateMachine, LoanAccountLockService loanAccountLockService,
|
||||||
ExternalIdFactory externalIdFactory, ReplayedTransactionBusinessEventService replayedTransactionBusinessEventService,
|
ExternalIdFactory externalIdFactory, LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService,
|
||||||
LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService, ErrorHandler errorHandler,
|
ErrorHandler errorHandler, LoanDownPaymentHandlerService loanDownPaymentHandlerService,
|
||||||
LoanDownPaymentHandlerService loanDownPaymentHandlerService, AccountTransferRepository accountTransferRepository,
|
|
||||||
LoanTransactionAssembler loanTransactionAssembler, LoanAccrualsProcessingService loanAccrualsProcessingService,
|
LoanTransactionAssembler loanTransactionAssembler, LoanAccrualsProcessingService loanAccrualsProcessingService,
|
||||||
LoanOfficerValidator loanOfficerValidator, LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator,
|
LoanOfficerValidator loanOfficerValidator, LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator,
|
||||||
LoanDisbursementService loanDisbursementService, LoanScheduleService loanScheduleService,
|
LoanDisbursementService loanDisbursementService, LoanScheduleService loanScheduleService,
|
||||||
LoanChargeValidator loanChargeValidator, LoanOfficerService loanOfficerService) {
|
LoanChargeValidator loanChargeValidator, LoanOfficerService loanOfficerService,
|
||||||
|
ReprocessLoanTransactionsService reprocessLoanTransactionsService, LoanAccountService loanAccountService) {
|
||||||
return new LoanWritePlatformServiceJpaRepositoryImpl(context, loanTransactionValidator, loanUpdateCommandFromApiJsonDeserializer,
|
return new LoanWritePlatformServiceJpaRepositoryImpl(context, loanTransactionValidator, loanUpdateCommandFromApiJsonDeserializer,
|
||||||
loanRepositoryWrapper, loanAccountDomainService, noteRepository, loanTransactionRepository,
|
loanRepositoryWrapper, loanAccountDomainService, noteRepository, loanTransactionRepository,
|
||||||
loanTransactionRelationRepository, loanAssembler, journalEntryWritePlatformService, calendarInstanceRepository,
|
loanTransactionRelationRepository, loanAssembler, journalEntryWritePlatformService, calendarInstanceRepository,
|
||||||
@@ -403,10 +403,10 @@ public class LoanAccountConfiguration {
|
|||||||
guarantorDomainService, loanUtilService, entityDatatableChecksWritePlatformService, transactionProcessingStrategy,
|
guarantorDomainService, loanUtilService, entityDatatableChecksWritePlatformService, transactionProcessingStrategy,
|
||||||
codeValueRepository, cashierTransactionDataValidator, glimRepository, loanRepository, repaymentWithPostDatedChecksAssembler,
|
codeValueRepository, cashierTransactionDataValidator, glimRepository, loanRepository, repaymentWithPostDatedChecksAssembler,
|
||||||
postDatedChecksRepository, loanRepaymentScheduleInstallmentRepository, defaultLoanLifecycleStateMachine,
|
postDatedChecksRepository, loanRepaymentScheduleInstallmentRepository, defaultLoanLifecycleStateMachine,
|
||||||
loanAccountLockService, externalIdFactory, replayedTransactionBusinessEventService,
|
loanAccountLockService, externalIdFactory, loanAccrualTransactionBusinessEventService, errorHandler,
|
||||||
loanAccrualTransactionBusinessEventService, errorHandler, loanDownPaymentHandlerService, accountTransferRepository,
|
loanDownPaymentHandlerService, loanTransactionAssembler, loanAccrualsProcessingService, loanOfficerValidator,
|
||||||
loanTransactionAssembler, loanAccrualsProcessingService, loanOfficerValidator, loanDownPaymentTransactionValidator,
|
loanDownPaymentTransactionValidator, loanDisbursementService, loanScheduleService, loanChargeValidator, loanOfficerService,
|
||||||
loanDisbursementService, loanScheduleService, loanChargeValidator, loanOfficerService);
|
reprocessLoanTransactionsService, loanAccountService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -421,9 +421,11 @@ public class LoanAccountConfiguration {
|
|||||||
public LoanDownPaymentHandlerService loanDownPaymentHandlerService(LoanTransactionRepository loanTransactionRepository,
|
public LoanDownPaymentHandlerService loanDownPaymentHandlerService(LoanTransactionRepository loanTransactionRepository,
|
||||||
BusinessEventNotifierService businessEventNotifierService,
|
BusinessEventNotifierService businessEventNotifierService,
|
||||||
LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator, LoanScheduleService loanScheduleService,
|
LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator, LoanScheduleService loanScheduleService,
|
||||||
LoanRefundService loanRefundService, LoanRefundValidator loanRefundValidator) {
|
LoanRefundService loanRefundService, LoanRefundValidator loanRefundValidator,
|
||||||
|
ReprocessLoanTransactionsService reprocessLoanTransactionsService) {
|
||||||
return new LoanDownPaymentHandlerServiceImpl(loanTransactionRepository, businessEventNotifierService,
|
return new LoanDownPaymentHandlerServiceImpl(loanTransactionRepository, businessEventNotifierService,
|
||||||
loanDownPaymentTransactionValidator, loanScheduleService, loanRefundService, loanRefundValidator);
|
loanDownPaymentTransactionValidator, loanScheduleService, loanRefundService, loanRefundValidator,
|
||||||
|
reprocessLoanTransactionsService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -435,8 +437,8 @@ public class LoanAccountConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(LoanDisbursementService.class)
|
@ConditionalOnMissingBean(LoanDisbursementService.class)
|
||||||
public LoanDisbursementService loanDisbursementService(LoanChargeValidator loanChargeValidator,
|
public LoanDisbursementService loanDisbursementService(LoanChargeValidator loanChargeValidator,
|
||||||
LoanDisbursementValidator loanDisbursementValidator) {
|
LoanDisbursementValidator loanDisbursementValidator, ReprocessLoanTransactionsService reprocessLoanTransactionsService) {
|
||||||
return new LoanDisbursementService(loanChargeValidator, loanDisbursementValidator);
|
return new LoanDisbursementService(loanChargeValidator, loanDisbursementValidator, reprocessLoanTransactionsService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -447,8 +449,9 @@ public class LoanAccountConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(LoanScheduleService.class)
|
@ConditionalOnMissingBean(LoanScheduleService.class)
|
||||||
public LoanScheduleService loanScheduleService(LoanChargeService loanChargeService) {
|
public LoanScheduleService loanScheduleService(LoanChargeService loanChargeService,
|
||||||
return new LoanScheduleService(loanChargeService);
|
ReprocessLoanTransactionsService reprocessLoanTransactionsService) {
|
||||||
|
return new LoanScheduleService(loanChargeService, reprocessLoanTransactionsService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -472,10 +475,17 @@ public class LoanAccountConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(InterestPauseWritePlatformService.class)
|
@ConditionalOnMissingBean(InterestPauseWritePlatformService.class)
|
||||||
public InterestPauseWritePlatformService interestPauseWritePlatformService(LoanTermVariationsRepository loanTermVariationsRepository,
|
public InterestPauseWritePlatformService interestPauseWritePlatformService(LoanTermVariationsRepository loanTermVariationsRepository,
|
||||||
LoanRepositoryWrapper loanRepositoryWrapper, LoanAssembler loanAssembler, LoanAccountDomainService loanAccountDomainService,
|
LoanRepositoryWrapper loanRepositoryWrapper, LoanAssembler loanAssembler,
|
||||||
AccountTransfersService accountTransfersService,
|
ReprocessLoanTransactionsService reprocessLoanTransactionsService) {
|
||||||
ReplayedTransactionBusinessEventService replayedTransactionBusinessEventService) {
|
|
||||||
return new InterestPauseWritePlatformServiceImpl(loanTermVariationsRepository, loanRepositoryWrapper, loanAssembler,
|
return new InterestPauseWritePlatformServiceImpl(loanTermVariationsRepository, loanRepositoryWrapper, loanAssembler,
|
||||||
loanAccountDomainService, accountTransfersService, replayedTransactionBusinessEventService);
|
reprocessLoanTransactionsService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(LoanAccountService.class)
|
||||||
|
public LoanAccountService loanAccountService(LoanRepositoryWrapper loanRepositoryWrapper,
|
||||||
|
LoanTransactionRepository loanTransactionRepository) {
|
||||||
|
return new LoanAccountServiceImpl(loanRepositoryWrapper, loanTransactionRepository);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -40,6 +40,7 @@ import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode;
|
|||||||
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
|
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||||
@@ -131,6 +132,12 @@ class LoanChargeWritePlatformServiceImplTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
private LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private LoanAccountService loanAccountService;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
when(loanAssembler.assembleFrom(LOAN_ID)).thenReturn(loan);
|
when(loanAssembler.assembleFrom(LOAN_ID)).thenReturn(loan);
|
||||||
@@ -143,7 +150,7 @@ class LoanChargeWritePlatformServiceImplTest {
|
|||||||
when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
|
when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
|
||||||
when(loanChargeRepository.saveAndFlush(any(LoanCharge.class))).thenReturn(loanCharge);
|
when(loanChargeRepository.saveAndFlush(any(LoanCharge.class))).thenReturn(loanCharge);
|
||||||
when(loan.getCurrency()).thenReturn(monetaryCurrency);
|
when(loan.getCurrency()).thenReturn(monetaryCurrency);
|
||||||
when(loanAccountDomainService.saveAndFlushLoanWithDataIntegrityViolationChecks(any())).thenReturn(loan);
|
when(loanAccountService.saveAndFlushLoanWithDataIntegrityViolationChecks(any())).thenReturn(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
|
|||||||
+5
-1
@@ -101,12 +101,16 @@ public class LoanDownPaymentHandlerServiceImplTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private LoanRefundValidator loanRefundValidator;
|
private LoanRefundValidator loanRefundValidator;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
|
||||||
private LoanDownPaymentHandlerServiceImpl underTest;
|
private LoanDownPaymentHandlerServiceImpl underTest;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
underTest = new LoanDownPaymentHandlerServiceImpl(loanTransactionRepository, businessEventNotifierService,
|
underTest = new LoanDownPaymentHandlerServiceImpl(loanTransactionRepository, businessEventNotifierService,
|
||||||
loanDownPaymentTransactionValidator, loanScheduleService, loanRefundService, loanRefundValidator);
|
loanDownPaymentTransactionValidator, loanScheduleService, loanRefundService, loanRefundValidator,
|
||||||
|
reprocessLoanTransactionsService);
|
||||||
moneyHelper.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.UP));
|
moneyHelper.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.UP));
|
||||||
moneyHelper.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.UP);
|
moneyHelper.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.UP);
|
||||||
tempConfigServiceMock.when(TemporaryConfigurationServiceContainer::isExternalIdAutoGenerationEnabled).thenReturn(true);
|
tempConfigServiceMock.when(TemporaryConfigurationServiceContainer::isExternalIdAutoGenerationEnabled).thenReturn(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user