FINERACT-2234: Replace in-memory transaction loops with repository queries
This commit is contained in:
committed by
Adam Saghy
parent
dd4ca4d3e2
commit
cb6a15c3d2
+4
-7
@@ -58,6 +58,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@@ -77,6 +78,7 @@ public class DelinquencyReadPlatformServiceImpl implements DelinquencyReadPlatfo
|
|||||||
private final LoanDelinquencyActionRepository loanDelinquencyActionRepository;
|
private final LoanDelinquencyActionRepository loanDelinquencyActionRepository;
|
||||||
private final DelinquencyEffectivePauseHelper delinquencyEffectivePauseHelper;
|
private final DelinquencyEffectivePauseHelper delinquencyEffectivePauseHelper;
|
||||||
private final ConfigurationDomainService configurationDomainService;
|
private final ConfigurationDomainService configurationDomainService;
|
||||||
|
private final LoanTransactionRepository loanTransactionRepository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DelinquencyRangeData> retrieveAllDelinquencyRanges() {
|
public List<DelinquencyRangeData> retrieveAllDelinquencyRanges() {
|
||||||
@@ -174,7 +176,7 @@ public class DelinquencyReadPlatformServiceImpl implements DelinquencyReadPlatfo
|
|||||||
private void addInstallmentLevelDelinquencyData(CollectionData collectionData, Long loanId) {
|
private void addInstallmentLevelDelinquencyData(CollectionData collectionData, Long loanId) {
|
||||||
Collection<LoanInstallmentDelinquencyTagData> loanInstallmentDelinquencyTagData = retrieveLoanInstallmentsCurrentDelinquencyTag(
|
Collection<LoanInstallmentDelinquencyTagData> loanInstallmentDelinquencyTagData = retrieveLoanInstallmentsCurrentDelinquencyTag(
|
||||||
loanId);
|
loanId);
|
||||||
if (loanInstallmentDelinquencyTagData != null && loanInstallmentDelinquencyTagData.size() > 0) {
|
if (loanInstallmentDelinquencyTagData != null && !loanInstallmentDelinquencyTagData.isEmpty()) {
|
||||||
|
|
||||||
// installment level delinquency grouped by rangeId, and summed up the delinquent amount
|
// installment level delinquency grouped by rangeId, and summed up the delinquent amount
|
||||||
Collection<InstallmentLevelDelinquency> installmentLevelDelinquencies = loanInstallmentDelinquencyTagData.stream()
|
Collection<InstallmentLevelDelinquency> installmentLevelDelinquencies = loanInstallmentDelinquencyTagData.stream()
|
||||||
@@ -254,12 +256,7 @@ public class DelinquencyReadPlatformServiceImpl implements DelinquencyReadPlatfo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalDate lastTransactionDate = null;
|
final LocalDate lastTransactionDate = loanTransactionRepository.findLastRepaymentLikeTransactionDate(loan).orElse(null);
|
||||||
for (final LoanTransaction transaction : loan.getLoanTransactions()) {
|
|
||||||
if (transaction.isRepaymentLikeType() && transaction.isGreaterThanZero()) {
|
|
||||||
lastTransactionDate = transaction.getTransactionDate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalDate possibleNextRepaymentDate = earliestUnpaidInstallmentDate;
|
LocalDate possibleNextRepaymentDate = earliestUnpaidInstallmentDate;
|
||||||
if (DateUtils.isAfter(lastTransactionDate, earliestUnpaidInstallmentDate)) {
|
if (DateUtils.isAfter(lastTransactionDate, earliestUnpaidInstallmentDate)) {
|
||||||
|
|||||||
+4
-2
@@ -42,6 +42,7 @@ import org.apache.fineract.portfolio.delinquency.validator.DelinquencyBucketPars
|
|||||||
import org.apache.fineract.portfolio.delinquency.validator.DelinquencyRangeParseAndValidator;
|
import org.apache.fineract.portfolio.delinquency.validator.DelinquencyRangeParseAndValidator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionReadService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionReadService;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
|
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
@@ -60,11 +61,12 @@ public class DelinquencyConfiguration {
|
|||||||
LoanDelinquencyDomainService loanDelinquencyDomainService,
|
LoanDelinquencyDomainService loanDelinquencyDomainService,
|
||||||
LoanInstallmentDelinquencyTagRepository repositoryLoanInstallmentDelinquencyTag,
|
LoanInstallmentDelinquencyTagRepository repositoryLoanInstallmentDelinquencyTag,
|
||||||
LoanDelinquencyActionRepository loanDelinquencyActionRepository,
|
LoanDelinquencyActionRepository loanDelinquencyActionRepository,
|
||||||
DelinquencyEffectivePauseHelper delinquencyEffectivePauseHelper, ConfigurationDomainService configurationDomainService) {
|
DelinquencyEffectivePauseHelper delinquencyEffectivePauseHelper, ConfigurationDomainService configurationDomainService,
|
||||||
|
LoanTransactionRepository loanTransactionRepository) {
|
||||||
return new DelinquencyReadPlatformServiceImpl(repositoryRange, repositoryBucket, repositoryLoanDelinquencyTagHistory, mapperRange,
|
return new DelinquencyReadPlatformServiceImpl(repositoryRange, repositoryBucket, repositoryLoanDelinquencyTagHistory, mapperRange,
|
||||||
mapperBucket, mapperLoanDelinquencyTagHistory, loanRepository, loanDelinquencyDomainService,
|
mapperBucket, mapperLoanDelinquencyTagHistory, loanRepository, loanDelinquencyDomainService,
|
||||||
repositoryLoanInstallmentDelinquencyTag, loanDelinquencyActionRepository, delinquencyEffectivePauseHelper,
|
repositoryLoanInstallmentDelinquencyTag, loanDelinquencyActionRepository, delinquencyEffectivePauseHelper,
|
||||||
configurationDomainService);
|
configurationDomainService, loanTransactionRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|||||||
+15
-85
@@ -59,7 +59,6 @@ import org.apache.fineract.infrastructure.codes.domain.CodeValue;
|
|||||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
|
||||||
import org.apache.fineract.infrastructure.security.service.RandomPasswordGenerator;
|
import org.apache.fineract.infrastructure.security.service.RandomPasswordGenerator;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
@@ -74,7 +73,6 @@ import org.apache.fineract.portfolio.fund.domain.Fund;
|
|||||||
import org.apache.fineract.portfolio.group.domain.Group;
|
import org.apache.fineract.portfolio.group.domain.Group;
|
||||||
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.domain.LoanApplicationTerms;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
|
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
|
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanSupportedInterestRefundTypes;
|
import org.apache.fineract.portfolio.loanproduct.domain.LoanSupportedInterestRefundTypes;
|
||||||
@@ -433,13 +431,13 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
|
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
|
||||||
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
||||||
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
||||||
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final LoanScheduleModel loanScheduleModel,
|
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final Boolean enableInstallmentLevelDelinquency,
|
||||||
final Boolean enableInstallmentLevelDelinquency, final LocalDate submittedOnDate) {
|
final LocalDate submittedOnDate) {
|
||||||
return new Loan(accountNo, client, null, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
return new Loan(accountNo, client, null, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
||||||
loanRepaymentScheduleDetail, null, loanCharges, collateral, null, fixedEmiAmount, disbursementDetails,
|
loanRepaymentScheduleDetail, null, loanCharges, collateral, null, fixedEmiAmount, disbursementDetails,
|
||||||
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
||||||
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, loanScheduleModel,
|
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, enableInstallmentLevelDelinquency,
|
||||||
enableInstallmentLevelDelinquency, submittedOnDate);
|
submittedOnDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Loan newGroupLoanApplication(final String accountNo, final Group group, final AccountType loanType,
|
public static Loan newGroupLoanApplication(final String accountNo, final Group group, final AccountType loanType,
|
||||||
@@ -450,13 +448,13 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
|
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
|
||||||
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
||||||
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
||||||
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final LoanScheduleModel loanScheduleModel,
|
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final Boolean enableInstallmentLevelDelinquency,
|
||||||
final Boolean enableInstallmentLevelDelinquency, final LocalDate submittedOnDate) {
|
final LocalDate submittedOnDate) {
|
||||||
return new Loan(accountNo, null, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
return new Loan(accountNo, null, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
||||||
loanRepaymentScheduleDetail, null, loanCharges, null, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails,
|
loanRepaymentScheduleDetail, null, loanCharges, null, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails,
|
||||||
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
||||||
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, loanScheduleModel,
|
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, enableInstallmentLevelDelinquency,
|
||||||
enableInstallmentLevelDelinquency, submittedOnDate);
|
submittedOnDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Loan newIndividualLoanApplicationFromGroup(final String accountNo, final Client client, final Group group,
|
public static Loan newIndividualLoanApplicationFromGroup(final String accountNo, final Client client, final Group group,
|
||||||
@@ -467,13 +465,13 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
|
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
|
||||||
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
||||||
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
||||||
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final LoanScheduleModel loanScheduleModel,
|
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final Boolean enableInstallmentLevelDelinquency,
|
||||||
final Boolean enableInstallmentLevelDelinquency, final LocalDate submittedOnDate) {
|
final LocalDate submittedOnDate) {
|
||||||
return new Loan(accountNo, client, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
return new Loan(accountNo, client, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
||||||
loanRepaymentScheduleDetail, null, loanCharges, null, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails,
|
loanRepaymentScheduleDetail, null, loanCharges, null, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails,
|
||||||
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
||||||
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, loanScheduleModel,
|
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, enableInstallmentLevelDelinquency,
|
||||||
enableInstallmentLevelDelinquency, submittedOnDate);
|
submittedOnDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Loan() {
|
protected Loan() {
|
||||||
@@ -488,8 +486,8 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
|
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
|
||||||
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
||||||
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
||||||
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final LoanScheduleModel loanScheduleModel,
|
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final Boolean enableInstallmentLevelDelinquency,
|
||||||
final Boolean enableInstallmentLevelDelinquency, final LocalDate submittedOnDate) {
|
final LocalDate submittedOnDate) {
|
||||||
this.loanRepaymentScheduleDetail = loanRepaymentScheduleDetail;
|
this.loanRepaymentScheduleDetail = loanRepaymentScheduleDetail;
|
||||||
|
|
||||||
this.isFloatingInterestRate = isFloatingInterestRate;
|
this.isFloatingInterestRate = isFloatingInterestRate;
|
||||||
@@ -850,17 +848,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
this.postDatedChecks = new ArrayList<>();
|
this.postDatedChecks = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<LoanTransaction> retrieveListOfTransactionsExcludeAccruals() {
|
|
||||||
final List<LoanTransaction> repaymentsOrWaivers = new ArrayList<>();
|
|
||||||
for (final LoanTransaction transaction : this.loanTransactions) {
|
|
||||||
if (transaction.isNotReversed() && !transaction.isNonMonetaryTransaction()) {
|
|
||||||
repaymentsOrWaivers.add(transaction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
repaymentsOrWaivers.sort(LoanTransactionComparator.INSTANCE);
|
|
||||||
return repaymentsOrWaivers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<LoanTransaction> retrieveListOfTransactionsByType(final LoanTransactionType transactionType) {
|
public List<LoanTransaction> retrieveListOfTransactionsByType(final LoanTransactionType transactionType) {
|
||||||
return this.loanTransactions.stream()
|
return this.loanTransactions.stream()
|
||||||
.filter(transaction -> transaction.isNotReversed() && transaction.getTypeOf().equals(transactionType))
|
.filter(transaction -> transaction.isNotReversed() && transaction.getTypeOf().equals(transactionType))
|
||||||
@@ -880,11 +867,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Money calculateTotalRecoveredPayments() {
|
|
||||||
// in case logic for reversing recovered payment is implemented handle subtraction from totalRecoveredPayments
|
|
||||||
return getTotalRecoveredPayments();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MonetaryCurrency loanCurrency() {
|
public MonetaryCurrency loanCurrency() {
|
||||||
return this.loanRepaymentScheduleDetail.getCurrency();
|
return this.loanRepaymentScheduleDetail.getCurrency();
|
||||||
}
|
}
|
||||||
@@ -1033,17 +1015,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
return cumulativePaid;
|
return cumulativePaid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Money getTotalRecoveredPayments() {
|
|
||||||
Money cumulativePaid = Money.zero(getCurrency());
|
|
||||||
|
|
||||||
for (final LoanTransaction recoveredPayment : this.loanTransactions) {
|
|
||||||
if (recoveredPayment.isRecoveryRepayment()) {
|
|
||||||
cumulativePaid = cumulativePaid.plus(recoveredPayment.getAmount(getCurrency()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cumulativePaid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Money getTotalPrincipalOutstandingUntil(LocalDate date) {
|
public Money getTotalPrincipalOutstandingUntil(LocalDate date) {
|
||||||
return getRepaymentScheduleInstallments().stream()
|
return getRepaymentScheduleInstallments().stream()
|
||||||
.filter(installment -> installment.getDueDate().isBefore(date) || installment.getDueDate().isEqual(date))
|
.filter(installment -> installment.getDueDate().isBefore(date) || installment.getDueDate().isEqual(date))
|
||||||
@@ -1236,7 +1207,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
.filter(date -> DateUtils.isBefore(getDisbursementDate(), date)).max(LocalDate::compareTo).orElse(getDisbursementDate());
|
.filter(date -> DateUtils.isBefore(getDisbursementDate(), date)).max(LocalDate::compareTo).orElse(getDisbursementDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isUserTransaction(LoanTransaction transaction) {
|
public boolean isUserTransaction(LoanTransaction transaction) {
|
||||||
return !(transaction.isReversed() || transaction.isAccrualRelated() || transaction.isIncomePosting());
|
return !(transaction.isReversed() || transaction.isAccrualRelated() || transaction.isIncomePosting());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1391,47 +1362,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
return recalculatedOn;
|
return recalculatedOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLoanOutstandingBalances() {
|
|
||||||
Money outstanding = Money.zero(getCurrency());
|
|
||||||
List<LoanTransaction> loanTransactions = retrieveListOfTransactionsExcludeAccruals();
|
|
||||||
for (LoanTransaction loanTransaction : loanTransactions) {
|
|
||||||
if (loanTransaction.isDisbursement() || loanTransaction.isIncomePosting() || loanTransaction.isCapitalizedIncome()) {
|
|
||||||
outstanding = outstanding.plus(loanTransaction.getAmount(getCurrency()))
|
|
||||||
.minus(loanTransaction.getOverPaymentPortion(getCurrency()));
|
|
||||||
loanTransaction.updateOutstandingLoanBalance(MathUtil.negativeToZero(outstanding.getAmount()));
|
|
||||||
} else if (loanTransaction.isChargeback() || loanTransaction.isCreditBalanceRefund()) {
|
|
||||||
Money transactionOutstanding = loanTransaction.getPrincipalPortion(getCurrency());
|
|
||||||
if (loanTransaction.isOverPaid()) {
|
|
||||||
// in case of advanced payment strategy and creditAllocations the full amount is recognized first
|
|
||||||
if (this.getCreditAllocationRules() != null && !this.getCreditAllocationRules().isEmpty()) {
|
|
||||||
Money payedPrincipal = loanTransaction.getLoanTransactionToRepaymentScheduleMappings().stream() //
|
|
||||||
.map(mapping -> mapping.getPrincipalPortion(getCurrency())) //
|
|
||||||
.reduce(Money.zero(getCurrency()), Money::plus);
|
|
||||||
transactionOutstanding = loanTransaction.getPrincipalPortion(getCurrency()).minus(payedPrincipal);
|
|
||||||
} else {
|
|
||||||
// in case legacy payment strategy
|
|
||||||
transactionOutstanding = loanTransaction.getAmount(getCurrency())
|
|
||||||
.minus(loanTransaction.getOverPaymentPortion(getCurrency()));
|
|
||||||
}
|
|
||||||
if (transactionOutstanding.isLessThanZero()) {
|
|
||||||
transactionOutstanding = Money.zero(getCurrency());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
outstanding = outstanding.plus(transactionOutstanding);
|
|
||||||
loanTransaction.updateOutstandingLoanBalance(MathUtil.negativeToZero(outstanding.getAmount()));
|
|
||||||
} else if (!loanTransaction.isAccrualActivity()) {
|
|
||||||
if (this.loanInterestRecalculationDetails != null
|
|
||||||
&& this.loanInterestRecalculationDetails.isCompoundingToBePostedAsTransaction()
|
|
||||||
&& !loanTransaction.isRepaymentAtDisbursement()) {
|
|
||||||
outstanding = outstanding.minus(loanTransaction.getAmount(getCurrency()));
|
|
||||||
} else {
|
|
||||||
outstanding = outstanding.minus(loanTransaction.getPrincipalPortion(getCurrency()));
|
|
||||||
}
|
|
||||||
loanTransaction.updateOutstandingLoanBalance(MathUtil.negativeToZero(outstanding.getAmount()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String transactionProcessingStrategy() {
|
public String transactionProcessingStrategy() {
|
||||||
return this.transactionProcessingStrategyCode;
|
return this.transactionProcessingStrategyCode;
|
||||||
}
|
}
|
||||||
|
|||||||
-4
@@ -911,10 +911,6 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
|||||||
|| this.isIncomePosting());
|
|| this.isIncomePosting());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasLoanTransactionRelations() {
|
|
||||||
return !loanTransactionRelations.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<LoanTransactionRelation> getLoanTransactionRelations(Predicate<LoanTransactionRelation> predicate) {
|
public List<LoanTransactionRelation> getLoanTransactionRelations(Predicate<LoanTransactionRelation> predicate) {
|
||||||
return loanTransactionRelations.stream().filter(predicate).toList();
|
return loanTransactionRelations.stream().filter(predicate).toList();
|
||||||
}
|
}
|
||||||
|
|||||||
+96
-6
@@ -127,7 +127,8 @@ public interface LoanTransactionRepository extends JpaRepository<LoanTransaction
|
|||||||
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.INITIATE_TRANSFER,
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.INITIATE_TRANSFER,
|
||||||
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.REJECT_TRANSFER,
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.REJECT_TRANSFER,
|
||||||
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.WITHDRAW_TRANSFER,
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.WITHDRAW_TRANSFER,
|
||||||
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CAPITALIZED_INCOME_AMORTIZATION
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CAPITALIZED_INCOME_AMORTIZATION,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CAPITALIZED_INCOME_AMORTIZATION_ADJUSTMENT
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
Optional<LocalDate> findLastTransactionDateForReprocessing(@Param("loan") Loan loan);
|
Optional<LocalDate> findLastTransactionDateForReprocessing(@Param("loan") Loan loan);
|
||||||
@@ -174,7 +175,7 @@ public interface LoanTransactionRepository extends JpaRepository<LoanTransaction
|
|||||||
AND lt.typeOf IN :types
|
AND lt.typeOf IN :types
|
||||||
AND lt.dateOf = :transactionDate
|
AND lt.dateOf = :transactionDate
|
||||||
""")
|
""")
|
||||||
Optional<LoanTransaction> findNonReversedByLoanAndTypesAndDate(@Param("loan") Loan loan, @Param("type") Set<LoanTransactionType> types,
|
Optional<LoanTransaction> findNonReversedByLoanAndTypesAndDate(@Param("loan") Loan loan, @Param("types") Set<LoanTransactionType> types,
|
||||||
@Param("transactionDate") LocalDate transactionDate);
|
@Param("transactionDate") LocalDate transactionDate);
|
||||||
|
|
||||||
@Query("""
|
@Query("""
|
||||||
@@ -184,7 +185,7 @@ public interface LoanTransactionRepository extends JpaRepository<LoanTransaction
|
|||||||
AND lt.reversed = false
|
AND lt.reversed = false
|
||||||
AND lt.typeOf IN :types
|
AND lt.typeOf IN :types
|
||||||
AND lt.dateOf > :transactionDate
|
AND lt.dateOf > :transactionDate
|
||||||
ORDER BY lt.dateOf
|
ORDER BY lt.dateOf, lt.createdDate, lt.id
|
||||||
""")
|
""")
|
||||||
List<LoanTransaction> findNonReversedByLoanAndTypesAndAfterDate(@Param("loan") Loan loan,
|
List<LoanTransaction> findNonReversedByLoanAndTypesAndAfterDate(@Param("loan") Loan loan,
|
||||||
@Param("types") Set<LoanTransactionType> types, @Param("transactionDate") LocalDate transactionDate);
|
@Param("types") Set<LoanTransactionType> types, @Param("transactionDate") LocalDate transactionDate);
|
||||||
@@ -196,7 +197,7 @@ public interface LoanTransactionRepository extends JpaRepository<LoanTransaction
|
|||||||
AND lt.reversed = false
|
AND lt.reversed = false
|
||||||
AND lt.typeOf = :type
|
AND lt.typeOf = :type
|
||||||
AND lt.dateOf > :transactionDate
|
AND lt.dateOf > :transactionDate
|
||||||
ORDER BY lt.dateOf
|
ORDER BY lt.dateOf, lt.createdDate, lt.id
|
||||||
""")
|
""")
|
||||||
List<LoanTransaction> findNonReversedByLoanAndTypeAndAfterDate(@Param("loan") Loan loan, @Param("type") LoanTransactionType type,
|
List<LoanTransaction> findNonReversedByLoanAndTypeAndAfterDate(@Param("loan") Loan loan, @Param("type") LoanTransactionType type,
|
||||||
@Param("transactionDate") LocalDate transactionDate);
|
@Param("transactionDate") LocalDate transactionDate);
|
||||||
@@ -219,6 +220,7 @@ public interface LoanTransactionRepository extends JpaRepository<LoanTransaction
|
|||||||
AND lt.reversed = false
|
AND lt.reversed = false
|
||||||
AND lt.typeOf IN :types
|
AND lt.typeOf IN :types
|
||||||
AND lt.id NOT IN :existingTransactionIds
|
AND lt.id NOT IN :existingTransactionIds
|
||||||
|
ORDER BY lt.dateOf, lt.createdDate, lt.id
|
||||||
""")
|
""")
|
||||||
List<LoanTransaction> findNonReversedByLoanAndTypesAndNotInIds(@Param("loan") Loan loan, @Param("types") Set<LoanTransactionType> types,
|
List<LoanTransaction> findNonReversedByLoanAndTypesAndNotInIds(@Param("loan") Loan loan, @Param("types") Set<LoanTransactionType> types,
|
||||||
@Param("existingTransactionIds") List<Long> existingTransactionIds);
|
@Param("existingTransactionIds") List<Long> existingTransactionIds);
|
||||||
@@ -229,6 +231,7 @@ public interface LoanTransactionRepository extends JpaRepository<LoanTransaction
|
|||||||
WHERE lt.loan = :loan
|
WHERE lt.loan = :loan
|
||||||
AND lt.reversed = false
|
AND lt.reversed = false
|
||||||
AND lt.typeOf IN :types
|
AND lt.typeOf IN :types
|
||||||
|
ORDER BY lt.dateOf, lt.createdDate, lt.id
|
||||||
""")
|
""")
|
||||||
List<LoanTransaction> findNonReversedByLoanAndTypes(@Param("loan") Loan loan, @Param("types") Set<LoanTransactionType> types);
|
List<LoanTransaction> findNonReversedByLoanAndTypes(@Param("loan") Loan loan, @Param("types") Set<LoanTransactionType> types);
|
||||||
|
|
||||||
@@ -238,6 +241,7 @@ public interface LoanTransactionRepository extends JpaRepository<LoanTransaction
|
|||||||
WHERE lt.loan = :loan
|
WHERE lt.loan = :loan
|
||||||
AND lt.reversed = false
|
AND lt.reversed = false
|
||||||
AND lt.typeOf = :type
|
AND lt.typeOf = :type
|
||||||
|
ORDER BY lt.dateOf, lt.createdDate, lt.id
|
||||||
""")
|
""")
|
||||||
List<LoanTransaction> findNonReversedByLoanAndType(@Param("loan") Loan loan, @Param("type") LoanTransactionType type);
|
List<LoanTransaction> findNonReversedByLoanAndType(@Param("loan") Loan loan, @Param("type") LoanTransactionType type);
|
||||||
|
|
||||||
@@ -248,7 +252,7 @@ public interface LoanTransactionRepository extends JpaRepository<LoanTransaction
|
|||||||
AND lt.reversed = false
|
AND lt.reversed = false
|
||||||
AND lt.dateOf >= :date
|
AND lt.dateOf >= :date
|
||||||
AND lt.typeOf IN :types
|
AND lt.typeOf IN :types
|
||||||
ORDER BY lt.dateOf
|
ORDER BY lt.dateOf, lt.createdDate, lt.id
|
||||||
""")
|
""")
|
||||||
List<LoanTransaction> findNonReversedByLoanAndTypesAndOnOrAfterDate(@Param("loan") Loan loan,
|
List<LoanTransaction> findNonReversedByLoanAndTypesAndOnOrAfterDate(@Param("loan") Loan loan,
|
||||||
@Param("types") Set<LoanTransactionType> types, @Param("date") LocalDate date);
|
@Param("types") Set<LoanTransactionType> types, @Param("date") LocalDate date);
|
||||||
@@ -333,7 +337,7 @@ public interface LoanTransactionRepository extends JpaRepository<LoanTransaction
|
|||||||
AND lt.reversed = false
|
AND lt.reversed = false
|
||||||
AND lt.typeOf = :type
|
AND lt.typeOf = :type
|
||||||
AND lt.dateOf IN :transactionDates
|
AND lt.dateOf IN :transactionDates
|
||||||
ORDER BY lt.id
|
ORDER BY lt.dateOf, lt.createdDate, lt.id
|
||||||
""")
|
""")
|
||||||
List<LoanTransaction> findNonReversedLoanAndTypeAndDates(@Param("loan") Loan loan, @Param("type") LoanTransactionType type,
|
List<LoanTransaction> findNonReversedLoanAndTypeAndDates(@Param("loan") Loan loan, @Param("type") LoanTransactionType type,
|
||||||
@Param("transactionDates") Set<LocalDate> transactionDates);
|
@Param("transactionDates") Set<LocalDate> transactionDates);
|
||||||
@@ -367,4 +371,90 @@ public interface LoanTransactionRepository extends JpaRepository<LoanTransaction
|
|||||||
AND ltr.relationType = org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum.ADJUSTMENT
|
AND ltr.relationType = org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum.ADJUSTMENT
|
||||||
""")
|
""")
|
||||||
List<LoanTransaction> findAdjustmentsForCapitalizedIncome(@Param("capitalizedIncome") LoanTransaction capitalizedIncome);
|
List<LoanTransaction> findAdjustmentsForCapitalizedIncome(@Param("capitalizedIncome") LoanTransaction capitalizedIncome);
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT lt FROM LoanTransaction lt
|
||||||
|
WHERE lt.loan = :loan
|
||||||
|
AND lt.reversed = false
|
||||||
|
AND lt.typeOf NOT IN (
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CONTRA,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.MARKED_FOR_RESCHEDULING,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.ACCRUAL,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.ACCRUAL_ADJUSTMENT,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.APPROVE_TRANSFER,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.INITIATE_TRANSFER,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.REJECT_TRANSFER,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.WITHDRAW_TRANSFER,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CAPITALIZED_INCOME_AMORTIZATION,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CAPITALIZED_INCOME_AMORTIZATION_ADJUSTMENT
|
||||||
|
)
|
||||||
|
ORDER BY lt.dateOf, lt.createdDate, lt.id
|
||||||
|
""")
|
||||||
|
List<LoanTransaction> findNonReversedTransactionsForReprocessingByLoan(@Param("loan") Loan loan);
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT MAX(lt.dateOf) FROM LoanTransaction lt
|
||||||
|
WHERE lt.loan = :loan
|
||||||
|
AND lt.reversed = false
|
||||||
|
AND lt.amount > 0
|
||||||
|
AND lt.typeOf IN (
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.REPAYMENT,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.MERCHANT_ISSUED_REFUND,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.PAYOUT_REFUND,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.GOODWILL_CREDIT,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CHARGE_REFUND,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CHARGE_ADJUSTMENT,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.DOWN_PAYMENT,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.INTEREST_PAYMENT_WAIVER,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.INTEREST_REFUND,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CAPITALIZED_INCOME_ADJUSTMENT
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
Optional<LocalDate> findLastRepaymentLikeTransactionDate(@Param("loan") Loan loan);
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT CASE WHEN COUNT(lt) > 0 THEN true ELSE false END
|
||||||
|
FROM LoanTransaction lt
|
||||||
|
WHERE lt.loan = :loan
|
||||||
|
AND lt.reversed = false
|
||||||
|
AND lt.typeOf = :type
|
||||||
|
AND lt.dateOf > :transactionDate
|
||||||
|
""")
|
||||||
|
boolean existsNonReversedByLoanAndTypeAndAfterDate(@Param("loan") Loan loan, @Param("type") LoanTransactionType type,
|
||||||
|
@Param("transactionDate") LocalDate transactionDate);
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT lt FROM LoanTransaction lt
|
||||||
|
WHERE lt.loan = :loan
|
||||||
|
AND lt.reversed = false
|
||||||
|
AND lt.typeOf NOT IN (
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CONTRA,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.MARKED_FOR_RESCHEDULING,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.ACCRUAL,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.ACCRUAL_ADJUSTMENT,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.ACCRUAL_ACTIVITY,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.APPROVE_TRANSFER,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.INITIATE_TRANSFER,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.REJECT_TRANSFER,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.WITHDRAW_TRANSFER,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CHARGE_OFF,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.REAMORTIZE,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.REAGE,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CAPITALIZED_INCOME_AMORTIZATION,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CONTRACT_TERMINATION,
|
||||||
|
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.CAPITALIZED_INCOME_AMORTIZATION_ADJUSTMENT
|
||||||
|
)
|
||||||
|
ORDER BY lt.dateOf, lt.createdDate, lt.id
|
||||||
|
""")
|
||||||
|
List<LoanTransaction> findNonReversedMonetaryTransactionsByLoan(@Param("loan") Loan loan);
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT COALESCE(SUM(lt.amount), 0)
|
||||||
|
FROM LoanTransaction lt
|
||||||
|
WHERE lt.loan = :loan
|
||||||
|
AND lt.reversed = false
|
||||||
|
AND lt.typeOf = org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.RECOVERY_REPAYMENT
|
||||||
|
""")
|
||||||
|
BigDecimal calculateTotalRecoveryPaymentAmount(@Param("loan") Loan loan);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -37,7 +37,6 @@ public class SingleLoanChargeRepaymentScheduleProcessingWrapper {
|
|||||||
|
|
||||||
public void reprocess(final MonetaryCurrency currency, final LocalDate disbursementDate,
|
public void reprocess(final MonetaryCurrency currency, final LocalDate disbursementDate,
|
||||||
final List<LoanRepaymentScheduleInstallment> installments, LoanCharge loanCharge) {
|
final List<LoanRepaymentScheduleInstallment> installments, LoanCharge loanCharge) {
|
||||||
Loan loan = loanCharge.getLoan();
|
|
||||||
Money zero = Money.zero(currency);
|
Money zero = Money.zero(currency);
|
||||||
Money totalInterest = zero;
|
Money totalInterest = zero;
|
||||||
Money totalPrincipal = zero;
|
Money totalPrincipal = zero;
|
||||||
|
|||||||
+11
-14
@@ -217,11 +217,9 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
loanTransaction.resetDerivedComponents();
|
loanTransaction.resetDerivedComponents();
|
||||||
handleRefund(loanTransaction, currency, installments, charges);
|
handleRefund(loanTransaction, currency, installments, charges);
|
||||||
} else if (loanTransaction.isCreditBalanceRefund()) {
|
} else if (loanTransaction.isCreditBalanceRefund()) {
|
||||||
recalculateCreditTransaction(changedTransactionDetail, loanTransaction, currency, installments, transactionsToBeProcessed,
|
recalculateCreditTransaction(changedTransactionDetail, loanTransaction, currency, installments, overpaymentHolder);
|
||||||
overpaymentHolder);
|
|
||||||
} else if (loanTransaction.isChargeback()) {
|
} else if (loanTransaction.isChargeback()) {
|
||||||
recalculateCreditTransaction(changedTransactionDetail, loanTransaction, currency, installments, transactionsToBeProcessed,
|
recalculateCreditTransaction(changedTransactionDetail, loanTransaction, currency, installments, overpaymentHolder);
|
||||||
overpaymentHolder);
|
|
||||||
reprocessChargebackTransactionRelation(changedTransactionDetail, transactionsToBeProcessed);
|
reprocessChargebackTransactionRelation(changedTransactionDetail, transactionsToBeProcessed);
|
||||||
} else if (loanTransaction.isChargeOff()) {
|
} else if (loanTransaction.isChargeOff()) {
|
||||||
recalculateChargeOffTransaction(changedTransactionDetail, loanTransaction, currency, installments);
|
recalculateChargeOffTransaction(changedTransactionDetail, loanTransaction, currency, installments);
|
||||||
@@ -475,7 +473,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
|
|
||||||
protected void reprocessInstallments(LocalDate disbursementDate, List<LoanTransaction> transactions,
|
protected void reprocessInstallments(LocalDate disbursementDate, List<LoanTransaction> transactions,
|
||||||
List<LoanRepaymentScheduleInstallment> installments, MonetaryCurrency currency) {
|
List<LoanRepaymentScheduleInstallment> installments, MonetaryCurrency currency) {
|
||||||
LoanRepaymentScheduleInstallment lastInstallment = installments.get(installments.size() - 1);
|
LoanRepaymentScheduleInstallment lastInstallment = installments.getLast();
|
||||||
if (lastInstallment.isAdditional() && lastInstallment.getDue(currency).isZero()) {
|
if (lastInstallment.isAdditional() && lastInstallment.getDue(currency).isZero()) {
|
||||||
installments.remove(lastInstallment);
|
installments.remove(lastInstallment);
|
||||||
}
|
}
|
||||||
@@ -519,8 +517,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void recalculateCreditTransaction(ChangedTransactionDetail changedTransactionDetail, LoanTransaction loanTransaction,
|
private void recalculateCreditTransaction(ChangedTransactionDetail changedTransactionDetail, LoanTransaction loanTransaction,
|
||||||
MonetaryCurrency currency, List<LoanRepaymentScheduleInstallment> installments, List<LoanTransaction> transactionsToBeProcessed,
|
MonetaryCurrency currency, List<LoanRepaymentScheduleInstallment> installments, MoneyHolder overpaymentHolder) {
|
||||||
MoneyHolder overpaymentHolder) {
|
|
||||||
// pass through for new transactions
|
// pass through for new transactions
|
||||||
if (loanTransaction.getId() == null) {
|
if (loanTransaction.getId() == null) {
|
||||||
return;
|
return;
|
||||||
@@ -606,7 +603,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
// New installment will be added (N+1 scenario)
|
// New installment will be added (N+1 scenario)
|
||||||
if (!loanTransactionMapped) {
|
if (!loanTransactionMapped) {
|
||||||
if (loanTransaction.getTransactionDate().equals(pastDueDate)) {
|
if (loanTransaction.getTransactionDate().equals(pastDueDate)) {
|
||||||
LoanRepaymentScheduleInstallment currentInstallment = installmentToBeProcessed.get(installmentToBeProcessed.size() - 1);
|
LoanRepaymentScheduleInstallment currentInstallment = installmentToBeProcessed.getLast();
|
||||||
currentInstallment.addToCreditedPrincipal(transactionAmount.getAmount());
|
currentInstallment.addToCreditedPrincipal(transactionAmount.getAmount());
|
||||||
currentInstallment.addToPrincipal(transactionDate, transactionAmount);
|
currentInstallment.addToPrincipal(transactionDate, transactionAmount);
|
||||||
if (repaidAmount.isGreaterThanZero()) {
|
if (repaidAmount.isGreaterThanZero()) {
|
||||||
@@ -647,7 +644,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
final Set<LoanCharge> loanPenalties = extractPenaltyCharges(charges);
|
final Set<LoanCharge> loanPenalties = extractPenaltyCharges(charges);
|
||||||
Integer installmentNumber = null;
|
Integer installmentNumber = null;
|
||||||
if (loanTransaction.isChargePayment() && installments.size() == 1) {
|
if (loanTransaction.isChargePayment() && installments.size() == 1) {
|
||||||
installmentNumber = installments.get(0).getInstallmentNumber();
|
installmentNumber = installments.getFirst().getInstallmentNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loanTransaction.isNotWaiver() && !loanTransaction.isAccrual() && !loanTransaction.isAccrualActivity()) {
|
if (loanTransaction.isNotWaiver() && !loanTransaction.isAccrual() && !loanTransaction.isAccrualActivity()) {
|
||||||
@@ -944,12 +941,12 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
LoanCharge latestCharge = null;
|
LoanCharge latestCharge = null;
|
||||||
List<LoanCharge> chargesWithSpecificDueDate = new ArrayList<>();
|
final List<LoanCharge> chargesWithSpecificDueDate = new ArrayList<>(
|
||||||
chargesWithSpecificDueDate.addAll(charges.stream().filter(charge -> charge.isSpecifiedDueDate()).toList());
|
charges.stream().filter(LoanCharge::isSpecifiedDueDate).toList());
|
||||||
if (!CollectionUtils.isEmpty(chargesWithSpecificDueDate)) {
|
if (!CollectionUtils.isEmpty(chargesWithSpecificDueDate)) {
|
||||||
Collections.sort(chargesWithSpecificDueDate,
|
chargesWithSpecificDueDate
|
||||||
(charge1, charge2) -> DateUtils.compare(charge1.getEffectiveDueDate(), charge2.getEffectiveDueDate()));
|
.sort((charge1, charge2) -> DateUtils.compare(charge1.getEffectiveDueDate(), charge2.getEffectiveDueDate()));
|
||||||
latestCharge = chargesWithSpecificDueDate.get(chargesWithSpecificDueDate.size() - 1);
|
latestCharge = chargesWithSpecificDueDate.getLast();
|
||||||
}
|
}
|
||||||
return latestCharge;
|
return latestCharge;
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-22
@@ -56,6 +56,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
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.data.LoanScheduleModelDownPaymentPeriod;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleModelDownPaymentPeriod;
|
||||||
@@ -63,13 +64,12 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleP
|
|||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.exception.MultiDisbursementEmiAmountException;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.exception.MultiDisbursementEmiAmountException;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.exception.MultiDisbursementOutstandingAmoutException;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.exception.MultiDisbursementOutstandingAmoutException;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.exception.ScheduleDateException;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.exception.ScheduleDateException;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionService;
|
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.RepaymentStartDateType;
|
import org.apache.fineract.portfolio.loanproduct.domain.RepaymentStartDateType;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanScheduleGenerator {
|
public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanScheduleGenerator {
|
||||||
|
|
||||||
private final LoanTransactionService loanTransactionService;
|
private final LoanTransactionRepository loanTransactionRepository;
|
||||||
private final CurrencyMapper currencyMapper;
|
private final CurrencyMapper currencyMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -404,7 +404,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
|
|||||||
// this condition is to add the interest from grace period if not
|
// this condition is to add the interest from grace period if not
|
||||||
// already applied.
|
// already applied.
|
||||||
if (scheduleParams.getTotalOutstandingInterestPaymentDueToGrace().isGreaterThanZero()) {
|
if (scheduleParams.getTotalOutstandingInterestPaymentDueToGrace().isGreaterThanZero()) {
|
||||||
LoanScheduleModelPeriod installment = periods.get(periods.size() - 1);
|
LoanScheduleModelPeriod installment = periods.getLast();
|
||||||
installment.addInterestAmount(scheduleParams.getTotalOutstandingInterestPaymentDueToGrace());
|
installment.addInterestAmount(scheduleParams.getTotalOutstandingInterestPaymentDueToGrace());
|
||||||
scheduleParams.addTotalRepaymentExpected(scheduleParams.getTotalOutstandingInterestPaymentDueToGrace());
|
scheduleParams.addTotalRepaymentExpected(scheduleParams.getTotalOutstandingInterestPaymentDueToGrace());
|
||||||
scheduleParams.addTotalCumulativeInterest(scheduleParams.getTotalOutstandingInterestPaymentDueToGrace());
|
scheduleParams.addTotalCumulativeInterest(scheduleParams.getTotalOutstandingInterestPaymentDueToGrace());
|
||||||
@@ -421,7 +421,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
|
|||||||
if (scheduleParams.getScheduleTillDate() != null) {
|
if (scheduleParams.getScheduleTillDate() != null) {
|
||||||
currentDate = scheduleParams.getScheduleTillDate();
|
currentDate = scheduleParams.getScheduleTillDate();
|
||||||
}
|
}
|
||||||
if (scheduleParams.applyInterestRecalculation() && scheduleParams.getLatePaymentMap().size() > 0
|
if (scheduleParams.applyInterestRecalculation() && !scheduleParams.getLatePaymentMap().isEmpty()
|
||||||
&& DateUtils.isAfter(currentDate, scheduleParams.getPeriodStartDate())) {
|
&& DateUtils.isAfter(currentDate, scheduleParams.getPeriodStartDate())) {
|
||||||
Money totalInterest = addInterestOnlyRepaymentScheduleForCurrentDate(mc, loanApplicationTerms, holidayDetailDTO,
|
Money totalInterest = addInterestOnlyRepaymentScheduleForCurrentDate(mc, loanApplicationTerms, holidayDetailDTO,
|
||||||
monetaryCurrency, periods, currentDate, loanRepaymentScheduleTransactionProcessor, transactions, loanCharges,
|
monetaryCurrency, periods, currentDate, loanRepaymentScheduleTransactionProcessor, transactions, loanCharges,
|
||||||
@@ -1345,9 +1345,8 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
|
|||||||
return principalToBeScheduled.minus(loanApplicationTerms.getDownPaymentAmount());
|
return principalToBeScheduled.minus(loanApplicationTerms.getDownPaymentAmount());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean updateFixedInstallmentAmount(final MathContext mc, final LoanApplicationTerms loanApplicationTerms, int periodNumber,
|
private void updateFixedInstallmentAmount(final MathContext mc, final LoanApplicationTerms loanApplicationTerms, int periodNumber,
|
||||||
Money outstandingBalance) {
|
Money outstandingBalance) {
|
||||||
boolean isAmountChanged = false;
|
|
||||||
if (loanApplicationTerms.getActualFixedEmiAmount() == null && loanApplicationTerms.getInterestMethod().isDecliningBalance()
|
if (loanApplicationTerms.getActualFixedEmiAmount() == null && loanApplicationTerms.getInterestMethod().isDecliningBalance()
|
||||||
&& loanApplicationTerms.getAmortizationMethod().isEqualInstallment()) {
|
&& loanApplicationTerms.getAmortizationMethod().isEqualInstallment()) {
|
||||||
if (periodNumber < loanApplicationTerms.getPrincipalGrace() + 1) {
|
if (periodNumber < loanApplicationTerms.getPrincipalGrace() + 1) {
|
||||||
@@ -1356,9 +1355,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
|
|||||||
Money emiAmount = loanApplicationTerms.pmtForInstallment(getPaymentPeriodsInOneYearCalculator(), outstandingBalance,
|
Money emiAmount = loanApplicationTerms.pmtForInstallment(getPaymentPeriodsInOneYearCalculator(), outstandingBalance,
|
||||||
periodNumber, mc);
|
periodNumber, mc);
|
||||||
loanApplicationTerms.setFixedEmiAmount(emiAmount.getAmount());
|
loanApplicationTerms.setFixedEmiAmount(emiAmount.getAmount());
|
||||||
isAmountChanged = true;
|
|
||||||
}
|
}
|
||||||
return isAmountChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Money fetchArrears(final LoanApplicationTerms loanApplicationTerms, final MonetaryCurrency currency,
|
private Money fetchArrears(final LoanApplicationTerms loanApplicationTerms, final MonetaryCurrency currency,
|
||||||
@@ -1984,7 +1981,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
|
|||||||
|
|
||||||
// this method relates to multi-disbursement loans
|
// this method relates to multi-disbursement loans
|
||||||
BigDecimal principal = BigDecimal.ZERO;
|
BigDecimal principal = BigDecimal.ZERO;
|
||||||
if (loanApplicationTerms.getDisbursementDatas().size() == 0) {
|
if (loanApplicationTerms.getDisbursementDatas().isEmpty()) {
|
||||||
// non tranche loans have no disbursement data entries in submitted and approved status
|
// non tranche loans have no disbursement data entries in submitted and approved status
|
||||||
// the appropriate approved amount or applied for amount is used to show a proposed schedule
|
// the appropriate approved amount or applied for amount is used to show a proposed schedule
|
||||||
if (loanApplicationTerms.getApprovedPrincipal().getAmount().compareTo(BigDecimal.ZERO) > 0) {
|
if (loanApplicationTerms.getApprovedPrincipal().getAmount().compareTo(BigDecimal.ZERO) > 0) {
|
||||||
@@ -2521,10 +2518,9 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retainedInstallments.size() > 0
|
if (!retainedInstallments.isEmpty() && retainedInstallments.getLast().getRescheduleInterestPortion() != null) {
|
||||||
&& retainedInstallments.get(retainedInstallments.size() - 1).getRescheduleInterestPortion() != null) {
|
|
||||||
loanApplicationTerms.setInterestTobeApproppriated(
|
loanApplicationTerms.setInterestTobeApproppriated(
|
||||||
Money.of(loan.getCurrency(), retainedInstallments.get(retainedInstallments.size() - 1).getRescheduleInterestPortion()));
|
Money.of(loan.getCurrency(), retainedInstallments.getLast().getRescheduleInterestPortion()));
|
||||||
}
|
}
|
||||||
LoanScheduleModel loanScheduleModel = generate(mc, loanApplicationTerms, loan.getActiveCharges(), holidayDetailDTO,
|
LoanScheduleModel loanScheduleModel = generate(mc, loanApplicationTerms, loan.getActiveCharges(), holidayDetailDTO,
|
||||||
loanScheduleParams);
|
loanScheduleParams);
|
||||||
@@ -2723,19 +2719,18 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
|
|||||||
return principalPortionCalculated;
|
return principalPortionCalculated;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LoanRepaymentScheduleInstallment addLoanRepaymentScheduleInstallment(final List<LoanRepaymentScheduleInstallment> installments,
|
private void addLoanRepaymentScheduleInstallment(final List<LoanRepaymentScheduleInstallment> installments,
|
||||||
final LoanScheduleModelPeriod scheduledLoanInstallment) {
|
final LoanScheduleModelPeriod scheduledLoanInstallment) {
|
||||||
LoanRepaymentScheduleInstallment installment = null;
|
|
||||||
if (scheduledLoanInstallment.isRepaymentPeriod() || scheduledLoanInstallment.isDownPaymentPeriod()) {
|
if (scheduledLoanInstallment.isRepaymentPeriod() || scheduledLoanInstallment.isDownPaymentPeriod()) {
|
||||||
installment = new LoanRepaymentScheduleInstallment(null, scheduledLoanInstallment.periodNumber(),
|
final LoanRepaymentScheduleInstallment installment = new LoanRepaymentScheduleInstallment(null,
|
||||||
scheduledLoanInstallment.periodFromDate(), scheduledLoanInstallment.periodDueDate(),
|
scheduledLoanInstallment.periodNumber(), scheduledLoanInstallment.periodFromDate(),
|
||||||
scheduledLoanInstallment.principalDue(), scheduledLoanInstallment.interestDue(),
|
scheduledLoanInstallment.periodDueDate(), scheduledLoanInstallment.principalDue(),
|
||||||
scheduledLoanInstallment.feeChargesDue(), scheduledLoanInstallment.penaltyChargesDue(),
|
scheduledLoanInstallment.interestDue(), scheduledLoanInstallment.feeChargesDue(),
|
||||||
scheduledLoanInstallment.isRecalculatedInterestComponent(), scheduledLoanInstallment.getLoanCompoundingDetails(),
|
scheduledLoanInstallment.penaltyChargesDue(), scheduledLoanInstallment.isRecalculatedInterestComponent(),
|
||||||
scheduledLoanInstallment.rescheduleInterestPortion(), scheduledLoanInstallment.isDownPaymentPeriod());
|
scheduledLoanInstallment.getLoanCompoundingDetails(), scheduledLoanInstallment.rescheduleInterestPortion(),
|
||||||
|
scheduledLoanInstallment.isDownPaymentPeriod());
|
||||||
installments.add(installment);
|
installments.add(installment);
|
||||||
}
|
}
|
||||||
return installment;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LoanScheduleModelPeriod createLoanScheduleModelDownPaymentPeriod(final LoanRepaymentScheduleInstallment installment,
|
private LoanScheduleModelPeriod createLoanScheduleModelDownPaymentPeriod(final LoanRepaymentScheduleInstallment installment,
|
||||||
@@ -2804,7 +2799,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
|
|||||||
|
|
||||||
LoanScheduleDTO loanScheduleDTO = rescheduleNextInstallments(mc, loanApplicationTerms, loan, holidayDetailDTO,
|
LoanScheduleDTO loanScheduleDTO = rescheduleNextInstallments(mc, loanApplicationTerms, loan, holidayDetailDTO,
|
||||||
loanRepaymentScheduleTransactionProcessor, onDate, calculateTill);
|
loanRepaymentScheduleTransactionProcessor, onDate, calculateTill);
|
||||||
final List<LoanTransaction> loanTransactions = loanTransactionService.retrieveListOfTransactionsForReprocessing(loan);
|
final List<LoanTransaction> loanTransactions = loanTransactionRepository.findNonReversedTransactionsForReprocessingByLoan(loan);
|
||||||
|
|
||||||
loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(loanApplicationTerms.getExpectedDisbursementDate(),
|
loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(loanApplicationTerms.getExpectedDisbursementDate(),
|
||||||
loanTransactions, currency, loanScheduleDTO.getInstallments(), loan.getActiveCharges());
|
loanTransactions, currency, loanScheduleDTO.getInstallments(), loan.getActiveCharges());
|
||||||
|
|||||||
+4
-4
@@ -29,7 +29,7 @@ import org.apache.fineract.infrastructure.core.service.DateUtils;
|
|||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
import org.apache.fineract.organisation.monetary.mapper.CurrencyMapper;
|
import org.apache.fineract.organisation.monetary.mapper.CurrencyMapper;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionService;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
|
import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -63,9 +63,9 @@ public class CumulativeDecliningBalanceInterestLoanScheduleGenerator extends Abs
|
|||||||
private final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator;
|
private final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator;
|
||||||
|
|
||||||
public CumulativeDecliningBalanceInterestLoanScheduleGenerator(final ScheduledDateGenerator scheduledDateGenerator,
|
public CumulativeDecliningBalanceInterestLoanScheduleGenerator(final ScheduledDateGenerator scheduledDateGenerator,
|
||||||
final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator, final LoanTransactionService loanTransactionService,
|
final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator,
|
||||||
final CurrencyMapper currencyMapper) {
|
final LoanTransactionRepository loanTransactionRepository, final CurrencyMapper currencyMapper) {
|
||||||
super(loanTransactionService, currencyMapper);
|
super(loanTransactionRepository, currencyMapper);
|
||||||
this.scheduledDateGenerator = scheduledDateGenerator;
|
this.scheduledDateGenerator = scheduledDateGenerator;
|
||||||
this.paymentPeriodsInOneYearCalculator = paymentPeriodsInOneYearCalculator;
|
this.paymentPeriodsInOneYearCalculator = paymentPeriodsInOneYearCalculator;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -27,7 +27,7 @@ import java.util.TreeMap;
|
|||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
import org.apache.fineract.organisation.monetary.mapper.CurrencyMapper;
|
import org.apache.fineract.organisation.monetary.mapper.CurrencyMapper;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionService;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -37,9 +37,9 @@ public class CumulativeFlatInterestLoanScheduleGenerator extends AbstractCumulat
|
|||||||
private final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator;
|
private final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator;
|
||||||
|
|
||||||
public CumulativeFlatInterestLoanScheduleGenerator(final ScheduledDateGenerator scheduledDateGenerator,
|
public CumulativeFlatInterestLoanScheduleGenerator(final ScheduledDateGenerator scheduledDateGenerator,
|
||||||
final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator, final LoanTransactionService loanTransactionService,
|
final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator,
|
||||||
final CurrencyMapper currencyMapper) {
|
final LoanTransactionRepository loanTransactionRepository, final CurrencyMapper currencyMapper) {
|
||||||
super(loanTransactionService, currencyMapper);
|
super(loanTransactionRepository, currencyMapper);
|
||||||
this.scheduledDateGenerator = scheduledDateGenerator;
|
this.scheduledDateGenerator = scheduledDateGenerator;
|
||||||
this.paymentPeriodsInOneYearCalculator = paymentPeriodsInOneYearCalculator;
|
this.paymentPeriodsInOneYearCalculator = paymentPeriodsInOneYearCalculator;
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-7
@@ -19,18 +19,24 @@
|
|||||||
package org.apache.fineract.portfolio.loanaccount.serialization;
|
package org.apache.fineract.portfolio.loanaccount.serialization;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeAddedException;
|
import org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeAddedException;
|
||||||
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.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||||
import org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanStateTransitionException;
|
import org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanStateTransitionException;
|
||||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanChargeRefundException;
|
import org.apache.fineract.portfolio.loanaccount.exception.LoanChargeRefundException;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
public final class LoanChargeValidator {
|
public final class LoanChargeValidator {
|
||||||
|
|
||||||
|
private final LoanTransactionRepository loanTransactionRepository;
|
||||||
|
|
||||||
public void validateLoanIsNotClosed(final Loan loan, final LoanCharge loanCharge) {
|
public void validateLoanIsNotClosed(final Loan loan, final LoanCharge loanCharge) {
|
||||||
if (loan.isClosed()) {
|
if (loan.isClosed()) {
|
||||||
final String defaultUserMessage = "This charge cannot be added as the loan is already closed.";
|
final String defaultUserMessage = "This charge cannot be added as the loan is already closed.";
|
||||||
@@ -80,13 +86,13 @@ public final class LoanChargeValidator {
|
|||||||
public void validateRepaymentTypeTransactionNotBeforeAChargeRefund(final Loan loan, final LoanTransaction repaymentTransaction,
|
public void validateRepaymentTypeTransactionNotBeforeAChargeRefund(final Loan loan, final LoanTransaction repaymentTransaction,
|
||||||
final String reversedOrCreated) {
|
final String reversedOrCreated) {
|
||||||
if (repaymentTransaction.isRepaymentLikeType() && !repaymentTransaction.isChargeRefund()) {
|
if (repaymentTransaction.isRepaymentLikeType() && !repaymentTransaction.isChargeRefund()) {
|
||||||
for (LoanTransaction txn : loan.getLoanTransactions()) {
|
final boolean existsChargeRefund = loanTransactionRepository.existsNonReversedByLoanAndTypeAndAfterDate(loan,
|
||||||
if (txn.isChargeRefund() && DateUtils.isBefore(repaymentTransaction.getTransactionDate(), txn.getTransactionDate())) {
|
LoanTransactionType.CHARGE_REFUND, repaymentTransaction.getTransactionDate());
|
||||||
final String errorMessage = "loan.transaction.cant.be." + reversedOrCreated + ".because.later.charge.refund.exists";
|
if (existsChargeRefund) {
|
||||||
final String details = "Loan Transaction: " + loan.getId() + " Can't be " + reversedOrCreated
|
final String errorMessage = "loan.transaction.cant.be." + reversedOrCreated + ".because.later.charge.refund.exists";
|
||||||
+ " because a Later Charge Refund Exists.";
|
final String details = "Loan Transaction: " + loan.getId() + " Can't be " + reversedOrCreated
|
||||||
throw new LoanChargeRefundException(errorMessage, details);
|
+ " because a Later Charge Refund Exists.";
|
||||||
}
|
throw new LoanChargeRefundException(errorMessage, details);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+61
-2
@@ -21,10 +21,12 @@ package org.apache.fineract.portfolio.loanaccount.service;
|
|||||||
import jakarta.persistence.FlushModeType;
|
import jakarta.persistence.FlushModeType;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.fineract.infrastructure.core.persistence.FlushModeHandler;
|
import org.apache.fineract.infrastructure.core.persistence.FlushModeHandler;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
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.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
@@ -34,6 +36,8 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanInstallmentCharge;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionComparator;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.CreditAllocationTransactionType;
|
import org.apache.fineract.portfolio.loanproduct.domain.CreditAllocationTransactionType;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -43,6 +47,7 @@ public class LoanBalanceService {
|
|||||||
|
|
||||||
private final CapitalizedIncomeBalanceService capitalizedIncomeBalanceService;
|
private final CapitalizedIncomeBalanceService capitalizedIncomeBalanceService;
|
||||||
private final FlushModeHandler flushModeHandler;
|
private final FlushModeHandler flushModeHandler;
|
||||||
|
private final LoanTransactionRepository loanTransactionRepository;
|
||||||
|
|
||||||
public Money calculateTotalOverpayment(final Loan loan) {
|
public Money calculateTotalOverpayment(final Loan loan) {
|
||||||
Money totalPaidInRepayments = loan.getTotalPaidInRepayments();
|
Money totalPaidInRepayments = loan.getTotalPaidInRepayments();
|
||||||
@@ -107,7 +112,7 @@ public class LoanBalanceService {
|
|||||||
loan.setTotalOverpaid(overpaidBy.getAmountDefaultedToNullIfZero());
|
loan.setTotalOverpaid(overpaidBy.getAmountDefaultedToNullIfZero());
|
||||||
}
|
}
|
||||||
|
|
||||||
final Money recoveredAmount = loan.calculateTotalRecoveredPayments();
|
final Money recoveredAmount = calculateTotalRecoveredPayments(loan);
|
||||||
loan.setTotalRecovered(recoveredAmount.getAmountDefaultedToNullIfZero());
|
loan.setTotalRecovered(recoveredAmount.getAmountDefaultedToNullIfZero());
|
||||||
|
|
||||||
final Money principal = loan.getLoanRepaymentScheduleDetail().getPrincipal();
|
final Money principal = loan.getLoanRepaymentScheduleDetail().getPrincipal();
|
||||||
@@ -115,7 +120,61 @@ public class LoanBalanceService {
|
|||||||
final Money capitalizedIncomeAdjustment = capitalizedIncomeBalanceService.calculateCapitalizedIncomeAdjustment(loan);
|
final Money capitalizedIncomeAdjustment = capitalizedIncomeBalanceService.calculateCapitalizedIncomeAdjustment(loan);
|
||||||
loan.getSummary().updateSummary(loan.getCurrency(), principal, loan.getRepaymentScheduleInstallments(), loan.getLoanCharges(),
|
loan.getSummary().updateSummary(loan.getCurrency(), principal, loan.getRepaymentScheduleInstallments(), loan.getLoanCharges(),
|
||||||
capitalizedIncome, capitalizedIncomeAdjustment);
|
capitalizedIncome, capitalizedIncomeAdjustment);
|
||||||
loan.updateLoanOutstandingBalances();
|
updateLoanOutstandingBalances(loan);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Money calculateTotalRecoveredPayments(Loan loan) {
|
||||||
|
// in case logic for reversing recovered payment is implemented handle subtraction from totalRecoveredPayments
|
||||||
|
final BigDecimal totalRecoveryAmount = loanTransactionRepository.calculateTotalRecoveryPaymentAmount(loan);
|
||||||
|
return Money.of(loan.getCurrency(), totalRecoveryAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateLoanOutstandingBalances(Loan loan) {
|
||||||
|
Money outstanding = Money.zero(loan.getCurrency());
|
||||||
|
final List<LoanTransaction> loanTransactions = new ArrayList<>();
|
||||||
|
for (final LoanTransaction transaction : loan.getLoanTransactions()) {
|
||||||
|
if (transaction.isNotReversed() && !transaction.isNonMonetaryTransaction()) {
|
||||||
|
loanTransactions.add(transaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loanTransactions.sort(LoanTransactionComparator.INSTANCE);
|
||||||
|
|
||||||
|
for (LoanTransaction loanTransaction : loanTransactions) {
|
||||||
|
if (loanTransaction.isDisbursement() || loanTransaction.isIncomePosting() || loanTransaction.isCapitalizedIncome()) {
|
||||||
|
outstanding = outstanding.plus(loanTransaction.getAmount(loan.getCurrency()))
|
||||||
|
.minus(loanTransaction.getOverPaymentPortion(loan.getCurrency()));
|
||||||
|
loanTransaction.updateOutstandingLoanBalance(MathUtil.negativeToZero(outstanding.getAmount()));
|
||||||
|
} else if (loanTransaction.isChargeback() || loanTransaction.isCreditBalanceRefund()) {
|
||||||
|
Money transactionOutstanding = loanTransaction.getPrincipalPortion(loan.getCurrency());
|
||||||
|
if (loanTransaction.isOverPaid()) {
|
||||||
|
// in case of advanced payment strategy and creditAllocations the full amount is recognized first
|
||||||
|
if (loan.getCreditAllocationRules() != null && !loan.getCreditAllocationRules().isEmpty()) {
|
||||||
|
Money payedPrincipal = loanTransaction.getLoanTransactionToRepaymentScheduleMappings().stream() //
|
||||||
|
.map(mapping -> mapping.getPrincipalPortion(loan.getCurrency())) //
|
||||||
|
.reduce(Money.zero(loan.getCurrency()), Money::plus);
|
||||||
|
transactionOutstanding = loanTransaction.getPrincipalPortion(loan.getCurrency()).minus(payedPrincipal);
|
||||||
|
} else {
|
||||||
|
// in case legacy payment strategy
|
||||||
|
transactionOutstanding = loanTransaction.getAmount(loan.getCurrency())
|
||||||
|
.minus(loanTransaction.getOverPaymentPortion(loan.getCurrency()));
|
||||||
|
}
|
||||||
|
if (transactionOutstanding.isLessThanZero()) {
|
||||||
|
transactionOutstanding = Money.zero(loan.getCurrency());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outstanding = outstanding.plus(transactionOutstanding);
|
||||||
|
loanTransaction.updateOutstandingLoanBalance(MathUtil.negativeToZero(outstanding.getAmount()));
|
||||||
|
} else if (!loanTransaction.isAccrualActivity()) {
|
||||||
|
if (loan.getLoanInterestRecalculationDetails() != null
|
||||||
|
&& loan.getLoanInterestRecalculationDetails().isCompoundingToBePostedAsTransaction()
|
||||||
|
&& !loanTransaction.isRepaymentAtDisbursement()) {
|
||||||
|
outstanding = outstanding.minus(loanTransaction.getAmount(loan.getCurrency()));
|
||||||
|
} else {
|
||||||
|
outstanding = outstanding.minus(loanTransaction.getPrincipalPortion(loan.getCurrency()));
|
||||||
|
}
|
||||||
|
loanTransaction.updateOutstandingLoanBalance(MathUtil.negativeToZero(outstanding.getAmount()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLoanToLastDisbursalState(final Loan loan, final LoanDisbursementDetails disbursementDetail) {
|
public void updateLoanToLastDisbursalState(final Loan loan, final LoanDisbursementDetails disbursementDetail) {
|
||||||
|
|||||||
+10
-12
@@ -84,6 +84,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionComparator;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionComparator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelation;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelation;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
|
||||||
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.transactionprocessor.AbstractLoanRepaymentScheduleTransactionProcessor;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.AbstractLoanRepaymentScheduleTransactionProcessor;
|
||||||
@@ -93,7 +94,6 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanSchedul
|
|||||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.InterestRefundService;
|
import org.apache.fineract.portfolio.loanaccount.service.InterestRefundService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanBalanceService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanBalanceService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionService;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
|
import org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
|
||||||
import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
|
import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
|
||||||
import org.apache.fineract.portfolio.loanproduct.calc.data.PeriodDueDetails;
|
import org.apache.fineract.portfolio.loanproduct.calc.data.PeriodDueDetails;
|
||||||
@@ -121,17 +121,17 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
||||||
private final InterestRefundService interestRefundService;
|
private final InterestRefundService interestRefundService;
|
||||||
private final LoanScheduleComponent loanSchedule;
|
private final LoanScheduleComponent loanSchedule;
|
||||||
private final LoanTransactionService loanTransactionService;
|
private final LoanTransactionRepository loanTransactionRepository;
|
||||||
|
|
||||||
public AdvancedPaymentScheduleTransactionProcessor(final EMICalculator emiCalculator, final LoanRepositoryWrapper loanRepositoryWrapper,
|
public AdvancedPaymentScheduleTransactionProcessor(final EMICalculator emiCalculator, final LoanRepositoryWrapper loanRepositoryWrapper,
|
||||||
final InterestRefundService interestRefundService, final ExternalIdFactory externalIdFactory,
|
final InterestRefundService interestRefundService, final ExternalIdFactory externalIdFactory,
|
||||||
final LoanScheduleComponent loanSchedule, final LoanTransactionService loanTransactionRepository,
|
final LoanScheduleComponent loanSchedule, final LoanTransactionRepository loanTransactionRepository,
|
||||||
final LoanChargeValidator loanChargeValidator, final LoanBalanceService loanBalanceService) {
|
final LoanChargeValidator loanChargeValidator, final LoanBalanceService loanBalanceService) {
|
||||||
super(externalIdFactory, loanChargeValidator, loanBalanceService);
|
super(externalIdFactory, loanChargeValidator, loanBalanceService);
|
||||||
this.emiCalculator = emiCalculator;
|
this.emiCalculator = emiCalculator;
|
||||||
this.loanRepositoryWrapper = loanRepositoryWrapper;
|
this.loanRepositoryWrapper = loanRepositoryWrapper;
|
||||||
this.interestRefundService = interestRefundService;
|
this.interestRefundService = interestRefundService;
|
||||||
this.loanTransactionService = loanTransactionRepository;
|
this.loanTransactionRepository = loanTransactionRepository;
|
||||||
this.loanSchedule = loanSchedule;
|
this.loanSchedule = loanSchedule;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +212,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
}
|
}
|
||||||
|
|
||||||
MoneyHolder overpaymentHolder = new MoneyHolder(Money.zero(currency));
|
MoneyHolder overpaymentHolder = new MoneyHolder(Money.zero(currency));
|
||||||
final Loan loan = loanTransactions.get(0).getLoan();
|
final Loan loan = loanTransactions.getFirst().getLoan();
|
||||||
List<LoanTermVariationsData> loanTermVariations = loan.getActiveLoanTermVariations().stream().map(LoanTermVariations::toData)
|
List<LoanTermVariationsData> loanTermVariations = loan.getActiveLoanTermVariations().stream().map(LoanTermVariations::toData)
|
||||||
.collect(Collectors.toCollection(ArrayList::new));
|
.collect(Collectors.toCollection(ArrayList::new));
|
||||||
final Integer installmentAmountInMultiplesOf = loan.getLoanProductRelatedDetail().getInstallmentAmountInMultiplesOf();
|
final Integer installmentAmountInMultiplesOf = loan.getLoanProductRelatedDetail().getInstallmentAmountInMultiplesOf();
|
||||||
@@ -276,7 +276,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
|
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
|
||||||
public ProgressiveLoanInterestScheduleModel calculateInterestScheduleModel(@NotNull Long loanId, LocalDate targetDate) {
|
public ProgressiveLoanInterestScheduleModel calculateInterestScheduleModel(@NotNull Long loanId, LocalDate targetDate) {
|
||||||
Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
|
Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
|
||||||
final List<LoanTransaction> transactions = loanTransactionService.retrieveListOfTransactionsForReprocessing(loan);
|
final List<LoanTransaction> transactions = loanTransactionRepository.findNonReversedTransactionsForReprocessingByLoan(loan);
|
||||||
MonetaryCurrency currency = loan.getLoanRepaymentScheduleDetail().getCurrency();
|
MonetaryCurrency currency = loan.getLoanRepaymentScheduleDetail().getCurrency();
|
||||||
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||||
Set<LoanCharge> charges = loan.getActiveCharges();
|
Set<LoanCharge> charges = loan.getActiveCharges();
|
||||||
@@ -552,8 +552,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
if (!loanTransactionMapped) {
|
if (!loanTransactionMapped) {
|
||||||
if (transactionDate.equals(pastDueDate)) {
|
if (transactionDate.equals(pastDueDate)) {
|
||||||
// Transaction is on Maturity date, no additional installment is needed
|
// Transaction is on Maturity date, no additional installment is needed
|
||||||
LoanRepaymentScheduleInstallment currentInstallment = installmentToBeProcessed
|
LoanRepaymentScheduleInstallment currentInstallment = installmentToBeProcessed.getLast();
|
||||||
.get(installmentToBeProcessed.size() - 1);
|
|
||||||
|
|
||||||
emiCalculator.creditPrincipal(model, transactionDate, transactionAmount);
|
emiCalculator.creditPrincipal(model, transactionDate, transactionAmount);
|
||||||
updateRepaymentPeriods(loanTransaction, progressiveTransactionCtx);
|
updateRepaymentPeriods(loanTransaction, progressiveTransactionCtx);
|
||||||
@@ -827,7 +826,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
// New installment will be added (N+1 scenario)
|
// New installment will be added (N+1 scenario)
|
||||||
if (!loanTransactionMapped) {
|
if (!loanTransactionMapped) {
|
||||||
if (loanTransaction.getTransactionDate().equals(pastDueDate)) {
|
if (loanTransaction.getTransactionDate().equals(pastDueDate)) {
|
||||||
LoanRepaymentScheduleInstallment currentInstallment = ctx.getInstallments().get(ctx.getInstallments().size() - 1);
|
LoanRepaymentScheduleInstallment currentInstallment = ctx.getInstallments().getLast();
|
||||||
recognizeAmountsAfterChargeback(ctx, transactionDate, currentInstallment, chargebackAllocation);
|
recognizeAmountsAfterChargeback(ctx, transactionDate, currentInstallment, chargebackAllocation);
|
||||||
} else {
|
} else {
|
||||||
Loan loan = loanTransaction.getLoan();
|
Loan loan = loanTransaction.getLoan();
|
||||||
@@ -1450,7 +1449,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
|
|
||||||
public void recalculateInterestForDate(LocalDate targetDate, ProgressiveTransactionCtx ctx) {
|
public void recalculateInterestForDate(LocalDate targetDate, ProgressiveTransactionCtx ctx) {
|
||||||
if (ctx.getInstallments() != null && !ctx.getInstallments().isEmpty()) {
|
if (ctx.getInstallments() != null && !ctx.getInstallments().isEmpty()) {
|
||||||
Loan loan = ctx.getInstallments().get(0).getLoan();
|
Loan loan = ctx.getInstallments().getFirst().getLoan();
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled() && !loan.isNpa() && !ctx.isChargedOff()
|
if (loan.isInterestBearingAndInterestRecalculationEnabled() && !loan.isNpa() && !ctx.isChargedOff()
|
||||||
&& !ctx.isContractTerminated()) {
|
&& !ctx.isContractTerminated()) {
|
||||||
|
|
||||||
@@ -1761,8 +1760,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
.max(LocalDate::compareTo);
|
.max(LocalDate::compareTo);
|
||||||
|
|
||||||
if (latestDueDate.isPresent()) {
|
if (latestDueDate.isPresent()) {
|
||||||
final LoanRepaymentScheduleInstallment lastInstallment = installmentsUpToTransactionDate
|
final LoanRepaymentScheduleInstallment lastInstallment = installmentsUpToTransactionDate.getLast();
|
||||||
.get(installmentsUpToTransactionDate.size() - 1);
|
|
||||||
|
|
||||||
final LoanRepaymentScheduleInstallment installmentForCharges = new LoanRepaymentScheduleInstallment(loan,
|
final LoanRepaymentScheduleInstallment installmentForCharges = new LoanRepaymentScheduleInstallment(loan,
|
||||||
lastInstallment.getInstallmentNumber() + 1, currentInstallment.getDueDate(), latestDueDate.get(),
|
lastInstallment.getInstallmentNumber() + 1, currentInstallment.getDueDate(), latestDueDate.get(),
|
||||||
|
|||||||
+1
-1
@@ -148,7 +148,7 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
|||||||
LoanTransaction savedCapitalizedIncomeAdjustment = loanTransactionRepository.saveAndFlush(capitalizedIncomeAdjustment);
|
LoanTransaction savedCapitalizedIncomeAdjustment = loanTransactionRepository.saveAndFlush(capitalizedIncomeAdjustment);
|
||||||
|
|
||||||
// Update outstanding loan balances
|
// Update outstanding loan balances
|
||||||
loan.updateLoanOutstandingBalances();
|
loanBalanceService.updateLoanOutstandingBalances(loan);
|
||||||
|
|
||||||
// Create a note if provided
|
// Create a note if provided
|
||||||
final String noteText = command.stringValueOfParameterNamed("note");
|
final String noteText = command.stringValueOfParameterNamed("note");
|
||||||
|
|||||||
+4
-3
@@ -40,6 +40,7 @@ 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.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;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
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.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
|
import org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
@@ -56,9 +57,8 @@ public class InternalProgressiveLoanApiResource implements InitializingBean {
|
|||||||
|
|
||||||
private final LoanRepositoryWrapper loanRepository;
|
private final LoanRepositoryWrapper loanRepository;
|
||||||
private final AdvancedPaymentScheduleTransactionProcessor advancedPaymentScheduleTransactionProcessor;
|
private final AdvancedPaymentScheduleTransactionProcessor advancedPaymentScheduleTransactionProcessor;
|
||||||
private final ProgressiveLoanInterestScheduleModelParserService progressiveLoanInterestScheduleModelParserService;
|
|
||||||
private final InterestScheduleModelRepositoryWrapper writePlatformService;
|
private final InterestScheduleModelRepositoryWrapper writePlatformService;
|
||||||
private final LoanTransactionService loanTransactionService;
|
private final LoanTransactionRepository loanTransactionRepository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
|
@SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
|
||||||
@@ -87,7 +87,8 @@ public class InternalProgressiveLoanApiResource implements InitializingBean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ProgressiveLoanInterestScheduleModel reprocessTransactionsAndGetModel(final Loan loan) {
|
private ProgressiveLoanInterestScheduleModel reprocessTransactionsAndGetModel(final Loan loan) {
|
||||||
final List<LoanTransaction> transactionsToReprocess = loanTransactionService.retrieveListOfTransactionsForReprocessing(loan);
|
final List<LoanTransaction> transactionsToReprocess = loanTransactionRepository
|
||||||
|
.findNonReversedTransactionsForReprocessingByLoan(loan);
|
||||||
final LocalDate businessDate = ThreadLocalContextUtil.getBusinessDate();
|
final LocalDate businessDate = ThreadLocalContextUtil.getBusinessDate();
|
||||||
final Pair<ChangedTransactionDetail, ProgressiveLoanInterestScheduleModel> changedTransactionDetailProgressiveLoanInterestScheduleModelPair = advancedPaymentScheduleTransactionProcessor
|
final Pair<ChangedTransactionDetail, ProgressiveLoanInterestScheduleModel> changedTransactionDetailProgressiveLoanInterestScheduleModelPair = advancedPaymentScheduleTransactionProcessor
|
||||||
.reprocessProgressiveLoanTransactionsTransactional(loan.getDisbursementDate(), businessDate, transactionsToReprocess,
|
.reprocessProgressiveLoanTransactionsTransactional(loan.getDisbursementDate(), businessDate, transactionsToReprocess,
|
||||||
|
|||||||
+2
-2
@@ -67,6 +67,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelation;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelation;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum;
|
||||||
|
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.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;
|
||||||
@@ -74,7 +75,6 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanSchedul
|
|||||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.InterestRefundService;
|
import org.apache.fineract.portfolio.loanaccount.service.InterestRefundService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanBalanceService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanBalanceService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionService;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
|
import org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
|
||||||
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;
|
||||||
@@ -120,7 +120,7 @@ class AdvancedPaymentScheduleTransactionProcessorTest {
|
|||||||
public void setUp() {
|
public void setUp() {
|
||||||
underTest = new AdvancedPaymentScheduleTransactionProcessor(emiCalculator, Mockito.mock(LoanRepositoryWrapper.class),
|
underTest = new AdvancedPaymentScheduleTransactionProcessor(emiCalculator, Mockito.mock(LoanRepositoryWrapper.class),
|
||||||
Mockito.mock(InterestRefundService.class), Mockito.mock(ExternalIdFactory.class), Mockito.mock(LoanScheduleComponent.class),
|
Mockito.mock(InterestRefundService.class), Mockito.mock(ExternalIdFactory.class), Mockito.mock(LoanScheduleComponent.class),
|
||||||
Mockito.mock(LoanTransactionService.class), Mockito.mock(LoanChargeValidator.class),
|
Mockito.mock(LoanTransactionRepository.class), Mockito.mock(LoanChargeValidator.class),
|
||||||
Mockito.mock(LoanBalanceService.class));
|
Mockito.mock(LoanBalanceService.class));
|
||||||
|
|
||||||
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
|
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
|
||||||
|
|||||||
+1
-2
@@ -134,7 +134,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
private final ConfigurationDomainService configurationDomainService;
|
private final ConfigurationDomainService configurationDomainService;
|
||||||
private final HolidayRepository holidayRepository;
|
private final HolidayRepository holidayRepository;
|
||||||
private final WorkingDaysRepositoryWrapper workingDaysRepository;
|
private final WorkingDaysRepositoryWrapper workingDaysRepository;
|
||||||
|
|
||||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||||
private final NoteRepository noteRepository;
|
private final NoteRepository noteRepository;
|
||||||
private final BusinessEventNotifierService businessEventNotifierService;
|
private final BusinessEventNotifierService businessEventNotifierService;
|
||||||
@@ -464,7 +463,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
chargesPayment.updateComponents(zero, zero, charge.getAmount(loan.getCurrency()), zero);
|
chargesPayment.updateComponents(zero, zero, charge.getAmount(loan.getCurrency()), zero);
|
||||||
chargesPayment.updateLoan(loan);
|
chargesPayment.updateLoan(loan);
|
||||||
loan.addLoanTransaction(chargesPayment);
|
loan.addLoanTransaction(chargesPayment);
|
||||||
loan.updateLoanOutstandingBalances();
|
loanBalanceService.updateLoanOutstandingBalances(loan);
|
||||||
charge.markAsFullyPaid();
|
charge.markAsFullyPaid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -931,7 +931,7 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
|||||||
|
|
||||||
createUpdateIncomePostingTransaction(loan, compoundingDetail, interest, fee, penalties, externalId);
|
createUpdateIncomePostingTransaction(loan, compoundingDetail, interest, fee, penalties, externalId);
|
||||||
createUpdateAccrualTransaction(loan, compoundingDetail, interest, fee, penalties, feeDetails, externalId);
|
createUpdateAccrualTransaction(loan, compoundingDetail, interest, fee, penalties, feeDetails, externalId);
|
||||||
loan.updateLoanOutstandingBalances();
|
loanBalanceService.updateLoanOutstandingBalances(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createUpdateIncomePostingTransaction(Loan loan, LoanInterestRecalcualtionAdditionalDetails compoundingDetail,
|
private void createUpdateIncomePostingTransaction(Loan loan, LoanInterestRecalcualtionAdditionalDetails compoundingDetail,
|
||||||
@@ -1000,7 +1000,7 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
|||||||
|
|
||||||
createIncomePostingAndAccrualTransactionOnLoanClosure(loan, closedDate, interestToPost, feeToPost, penaltyToPost, amountToPost);
|
createIncomePostingAndAccrualTransactionOnLoanClosure(loan, closedDate, interestToPost, feeToPost, penaltyToPost, amountToPost);
|
||||||
}
|
}
|
||||||
loan.updateLoanOutstandingBalances();
|
loanBalanceService.updateLoanOutstandingBalances(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void determineCumulativeIncomeFromInstallments(final Loan loan,
|
private void determineCumulativeIncomeFromInstallments(final Loan loan,
|
||||||
|
|||||||
+4
-4
@@ -261,20 +261,20 @@ public class LoanAssemblerImpl implements LoanAssembler {
|
|||||||
loanOfficer, loanPurpose, transactionProcessingStrategy, loanProductRelatedDetail, loanCharges,
|
loanOfficer, loanPurpose, transactionProcessingStrategy, loanProductRelatedDetail, loanCharges,
|
||||||
syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance,
|
syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance,
|
||||||
createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
||||||
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, loanScheduleModel,
|
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, isEnableInstallmentLevelDelinquency,
|
||||||
isEnableInstallmentLevelDelinquency, submittedOnDate);
|
submittedOnDate);
|
||||||
} else if (group != null) {
|
} else if (group != null) {
|
||||||
loanApplication = Loan.newGroupLoanApplication(accountNo, group, loanAccountType, loanProduct, fund, loanOfficer, loanPurpose,
|
loanApplication = Loan.newGroupLoanApplication(accountNo, group, loanAccountType, loanProduct, fund, loanOfficer, loanPurpose,
|
||||||
transactionProcessingStrategy, loanProductRelatedDetail, loanCharges, syncDisbursementWithMeeting, fixedEmiAmount,
|
transactionProcessingStrategy, loanProductRelatedDetail, loanCharges, syncDisbursementWithMeeting, fixedEmiAmount,
|
||||||
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate,
|
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate,
|
||||||
interestRateDifferential, rates, fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms,
|
interestRateDifferential, rates, fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms,
|
||||||
loanScheduleModel, isEnableInstallmentLevelDelinquency, submittedOnDate);
|
isEnableInstallmentLevelDelinquency, submittedOnDate);
|
||||||
} else if (client != null) {
|
} else if (client != null) {
|
||||||
loanApplication = Loan.newIndividualLoanApplication(accountNo, client, loanAccountType, loanProduct, fund, loanOfficer,
|
loanApplication = Loan.newIndividualLoanApplication(accountNo, client, loanAccountType, loanProduct, fund, loanOfficer,
|
||||||
loanPurpose, transactionProcessingStrategy, loanProductRelatedDetail, loanCharges, collateral, fixedEmiAmount,
|
loanPurpose, transactionProcessingStrategy, loanProductRelatedDetail, loanCharges, collateral, fixedEmiAmount,
|
||||||
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate,
|
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate,
|
||||||
interestRateDifferential, rates, fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms,
|
interestRateDifferential, rates, fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms,
|
||||||
loanScheduleModel, isEnableInstallmentLevelDelinquency, submittedOnDate);
|
isEnableInstallmentLevelDelinquency, submittedOnDate);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("No loan application exists for either a client or group (or both).");
|
throw new IllegalStateException("No loan application exists for either a client or group (or both).");
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -63,6 +63,7 @@ public class LoanDisbursementService {
|
|||||||
private final LoanDisbursementValidator loanDisbursementValidator;
|
private final LoanDisbursementValidator loanDisbursementValidator;
|
||||||
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
private final LoanChargeService loanChargeService;
|
private final LoanChargeService loanChargeService;
|
||||||
|
private final LoanBalanceService loanBalanceService;
|
||||||
|
|
||||||
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();
|
||||||
@@ -217,7 +218,7 @@ public class LoanDisbursementService {
|
|||||||
chargesPayment.updateComponentsAndTotal(zero, zero, disbursentMoney, zero);
|
chargesPayment.updateComponentsAndTotal(zero, zero, disbursentMoney, zero);
|
||||||
chargesPayment.updateLoan(loan);
|
chargesPayment.updateLoan(loan);
|
||||||
loan.addLoanTransaction(chargesPayment);
|
loan.addLoanTransaction(chargesPayment);
|
||||||
loan.updateLoanOutstandingBalances();
|
loanBalanceService.updateLoanOutstandingBalances(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
final LocalDate expectedDate = loan.getExpectedFirstRepaymentOnDate();
|
final LocalDate expectedDate = loan.getExpectedFirstRepaymentOnDate();
|
||||||
|
|||||||
+1
-1
@@ -61,8 +61,8 @@ public class LoanTransactionProcessingServiceImpl implements LoanTransactionProc
|
|||||||
private final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessorFactory;
|
private final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessorFactory;
|
||||||
private final LoanTermVariationsMapper loanMapper;
|
private final LoanTermVariationsMapper loanMapper;
|
||||||
private final InterestScheduleModelRepositoryWrapper modelRepository;
|
private final InterestScheduleModelRepositoryWrapper modelRepository;
|
||||||
private final LoanTransactionService loanTransactionService;
|
|
||||||
private final LoanBalanceService loanBalanceService;
|
private final LoanBalanceService loanBalanceService;
|
||||||
|
private final LoanTransactionService loanTransactionService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canProcessLatestTransactionOnly(Loan loan, LoanTransaction loanTransaction,
|
public boolean canProcessLatestTransactionOnly(Loan loan, LoanTransaction loanTransaction,
|
||||||
|
|||||||
+7
-7
@@ -594,8 +594,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (loan.getLoanProduct().isMultiDisburseLoan() || loan.isProgressiveSchedule()) {
|
if (loan.getLoanProduct().isMultiDisburseLoan() || loan.isProgressiveSchedule()) {
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = loanTransactionService
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = loanTransactionRepository
|
||||||
.retrieveListOfTransactionsForReprocessing(loan);
|
.findNonReversedTransactionsForReprocessingByLoan(loan);
|
||||||
if (!allNonContraTransactionsPostDisbursement.isEmpty()) {
|
if (!allNonContraTransactionsPostDisbursement.isEmpty()) {
|
||||||
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||||
}
|
}
|
||||||
@@ -2246,7 +2246,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
throw new MultiDisbursementDataNotAllowedException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
throw new MultiDisbursementDataNotAllowedException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (disbursementDataArray == null || disbursementDataArray.size() == 0) {
|
if (disbursementDataArray == null || disbursementDataArray.isEmpty()) {
|
||||||
final String errorMessage = "For this loan product, disbursement details must be provided";
|
final String errorMessage = "For this loan product, disbursement details must be provided";
|
||||||
throw new MultiDisbursementDataRequiredException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
throw new MultiDisbursementDataRequiredException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||||
}
|
}
|
||||||
@@ -2821,7 +2821,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, null, null);
|
final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, null, null);
|
||||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||||
}
|
}
|
||||||
final List<LoanTransaction> loanTransactions = loanTransactionService.retrieveListOfTransactionsForReprocessing(loan);
|
final List<LoanTransaction> loanTransactions = loanTransactionRepository.findNonReversedTransactionsForReprocessingByLoan(loan);
|
||||||
loanTransactions.add(chargeOffTransaction);
|
loanTransactions.add(chargeOffTransaction);
|
||||||
reprocessLoanTransactionsService.reprocessParticularTransactions(loan, loanTransactions);
|
reprocessLoanTransactionsService.reprocessParticularTransactions(loan, loanTransactions);
|
||||||
loan.addLoanTransaction(chargeOffTransaction);
|
loan.addLoanTransaction(chargeOffTransaction);
|
||||||
@@ -3031,7 +3031,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final String errorMessage = "loan.product.does.not.support.multiple.disbursals.cannot.undo.last.disbursal";
|
final String errorMessage = "loan.product.does.not.support.multiple.disbursals.cannot.undo.last.disbursal";
|
||||||
throw new LoanMultiDisbursementException(errorMessage);
|
throw new LoanMultiDisbursementException(errorMessage);
|
||||||
}
|
}
|
||||||
Integer trancheDisbursedCount = 0;
|
int trancheDisbursedCount = 0;
|
||||||
for (LoanDisbursementDetails disbursementDetails : loan.getDisbursementDetails()) {
|
for (LoanDisbursementDetails disbursementDetails : loan.getDisbursementDetails()) {
|
||||||
if (disbursementDetails.actualDisbursementDate() != null) {
|
if (disbursementDetails.actualDisbursementDate() != null) {
|
||||||
trancheDisbursedCount++;
|
trancheDisbursedCount++;
|
||||||
@@ -3361,13 +3361,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final Map<String, Object> actualChanges = new LinkedHashMap<>();
|
final Map<String, Object> actualChanges = new LinkedHashMap<>();
|
||||||
List<LoanTransaction> loanTransactions = loan.retrieveListOfTransactionsByType(LoanTransactionType.DISBURSEMENT);
|
List<LoanTransaction> loanTransactions = loan.retrieveListOfTransactionsByType(LoanTransactionType.DISBURSEMENT);
|
||||||
loanTransactions.sort(Comparator.comparing(LoanTransaction::getId));
|
loanTransactions.sort(Comparator.comparing(LoanTransaction::getId));
|
||||||
final LoanTransaction lastDisbursalTransaction = loanTransactions.get(loanTransactions.size() - 1);
|
final LoanTransaction lastDisbursalTransaction = loanTransactions.getLast();
|
||||||
final LocalDate lastTransactionDate = lastDisbursalTransaction.getTransactionDate();
|
final LocalDate lastTransactionDate = lastDisbursalTransaction.getTransactionDate();
|
||||||
|
|
||||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||||
|
|
||||||
loanTransactions = loan.retrieveListOfTransactionsExcludeAccruals();
|
loanTransactions = loanTransactionRepository.findNonReversedMonetaryTransactionsByLoan(loan);
|
||||||
Collections.reverse(loanTransactions);
|
Collections.reverse(loanTransactions);
|
||||||
for (final LoanTransaction previousTransaction : loanTransactions) {
|
for (final LoanTransaction previousTransaction : loanTransactions) {
|
||||||
if (DateUtils.isBefore(lastTransactionDate, previousTransaction.getTransactionDate())
|
if (DateUtils.isBefore(lastTransactionDate, previousTransaction.getTransactionDate())
|
||||||
|
|||||||
+4
-3
@@ -36,6 +36,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
|||||||
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;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
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.data.LoanScheduleData;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
|
||||||
@@ -53,7 +54,7 @@ public class ProgressiveLoanSummaryDataProvider extends CommonLoanSummaryDataPro
|
|||||||
private final AdvancedPaymentScheduleTransactionProcessor advancedPaymentScheduleTransactionProcessor;
|
private final AdvancedPaymentScheduleTransactionProcessor advancedPaymentScheduleTransactionProcessor;
|
||||||
private final EMICalculator emiCalculator;
|
private final EMICalculator emiCalculator;
|
||||||
private final LoanRepositoryWrapper loanRepository;
|
private final LoanRepositoryWrapper loanRepository;
|
||||||
private final LoanTransactionService loanTransactionService;
|
private final LoanTransactionRepository loanTransactionRepository;
|
||||||
private final InterestScheduleModelRepositoryWrapper modelRepository;
|
private final InterestScheduleModelRepositoryWrapper modelRepository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -81,8 +82,8 @@ public class ProgressiveLoanSummaryDataProvider extends CommonLoanSummaryDataPro
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ProgressiveLoanInterestScheduleModel calculateModel(Loan loan, LocalDate businessDate) {
|
private ProgressiveLoanInterestScheduleModel calculateModel(Loan loan, LocalDate businessDate) {
|
||||||
final List<LoanTransaction> transactionsToReprocess = loanTransactionService.retrieveListOfTransactionsForReprocessing(loan)
|
final List<LoanTransaction> transactionsToReprocess = loanTransactionRepository
|
||||||
.stream().filter(t -> !t.isAccrualActivity()).toList();
|
.findNonReversedTransactionsForReprocessingByLoan(loan).stream().filter(t -> !t.isAccrualActivity()).toList();
|
||||||
Pair<ChangedTransactionDetail, ProgressiveLoanInterestScheduleModel> changedTransactionDetailProgressiveLoanInterestScheduleModelPair = advancedPaymentScheduleTransactionProcessor
|
Pair<ChangedTransactionDetail, ProgressiveLoanInterestScheduleModel> changedTransactionDetailProgressiveLoanInterestScheduleModelPair = advancedPaymentScheduleTransactionProcessor
|
||||||
.reprocessProgressiveLoanTransactions(loan.getDisbursementDate(), businessDate, transactionsToReprocess, loan.getCurrency(),
|
.reprocessProgressiveLoanTransactions(loan.getDisbursementDate(), businessDate, transactionsToReprocess, loan.getCurrency(),
|
||||||
loan.getRepaymentScheduleInstallments(), loan.getActiveCharges());
|
loan.getRepaymentScheduleInstallments(), loan.getActiveCharges());
|
||||||
|
|||||||
+5
-16
@@ -22,8 +22,6 @@ import java.time.LocalDate;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
@@ -37,7 +35,6 @@ 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.LoanRepaymentScheduleProcessingWrapper;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionComparator;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
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;
|
||||||
@@ -55,26 +52,18 @@ public class ReprocessLoanTransactionsServiceImpl implements ReprocessLoanTransa
|
|||||||
private final InterestScheduleModelRepositoryWrapper interestScheduleModelRepositoryWrapper;
|
private final InterestScheduleModelRepositoryWrapper interestScheduleModelRepositoryWrapper;
|
||||||
private final LoanBalanceService loanBalanceService;
|
private final LoanBalanceService loanBalanceService;
|
||||||
private final LoanTransactionRepository loanTransactionRepository;
|
private final LoanTransactionRepository loanTransactionRepository;
|
||||||
|
private final LoanTransactionService loanTransactionService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reprocessTransactions(final Loan loan) {
|
public void reprocessTransactions(final Loan loan) {
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing(loan);
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = loanTransactionService
|
||||||
|
.retrieveListOfTransactionsForReprocessing(loan);
|
||||||
|
|
||||||
final ChangedTransactionDetail changedTransactionDetail = reprocessTransactionsAndFetchChangedTransactions(loan,
|
final ChangedTransactionDetail changedTransactionDetail = reprocessTransactionsAndFetchChangedTransactions(loan,
|
||||||
allNonContraTransactionsPostDisbursement);
|
allNonContraTransactionsPostDisbursement);
|
||||||
handleChangedDetail(changedTransactionDetail);
|
handleChangedDetail(changedTransactionDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<LoanTransaction> retrieveListOfTransactionsForReprocessing(final Loan loan) {
|
|
||||||
return loan.getLoanTransactions().stream().filter(loanTransactionForReprocessingPredicate())
|
|
||||||
.sorted(LoanTransactionComparator.INSTANCE).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Predicate<LoanTransaction> loanTransactionForReprocessingPredicate() {
|
|
||||||
return transaction -> transaction.isNotReversed()
|
|
||||||
&& (transaction.isChargeOff() || transaction.isReAge() || transaction.isAccrualActivity() || transaction.isReAmortize()
|
|
||||||
|| !transaction.isNonMonetaryTransaction() || transaction.isContractTermination());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reprocessParticularTransactions(final Loan loan, final List<LoanTransaction> loanTransactions) {
|
public void reprocessParticularTransactions(final Loan loan, final List<LoanTransaction> loanTransactions) {
|
||||||
final ChangedTransactionDetail changedTransactionDetail = reprocessTransactionsAndFetchChangedTransactions(loan, loanTransactions);
|
final ChangedTransactionDetail changedTransactionDetail = reprocessTransactionsAndFetchChangedTransactions(loan, loanTransactions);
|
||||||
@@ -83,7 +72,7 @@ public class ReprocessLoanTransactionsServiceImpl implements ReprocessLoanTransa
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reprocessTransactionsWithPostTransactionChecks(final Loan loan, final LocalDate transactionDate) {
|
public void reprocessTransactionsWithPostTransactionChecks(final Loan loan, final LocalDate transactionDate) {
|
||||||
final List<LoanTransaction> transactions = retrieveListOfTransactionsForReprocessing(loan);
|
final List<LoanTransaction> transactions = loanTransactionRepository.findNonReversedTransactionsForReprocessingByLoan(loan);
|
||||||
final ChangedTransactionDetail changedTransactionDetail = reprocessTransactionsAndFetchChangedTransactions(loan, transactions);
|
final ChangedTransactionDetail changedTransactionDetail = reprocessTransactionsAndFetchChangedTransactions(loan, transactions);
|
||||||
handleChangedDetail(changedTransactionDetail);
|
handleChangedDetail(changedTransactionDetail);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -70,10 +70,10 @@ public class LoanContractTerminationServiceImpl {
|
|||||||
private final LoanUtilService loanUtilService;
|
private final LoanUtilService loanUtilService;
|
||||||
private final ExternalIdFactory externalIdFactory;
|
private final ExternalIdFactory externalIdFactory;
|
||||||
private final BusinessEventNotifierService businessEventNotifierService;
|
private final BusinessEventNotifierService businessEventNotifierService;
|
||||||
private final LoanTransactionService loanTransactionService;
|
|
||||||
private final LoanScheduleService loanScheduleService;
|
private final LoanScheduleService loanScheduleService;
|
||||||
private final LoanChargeValidator loanChargeValidator;
|
private final LoanChargeValidator loanChargeValidator;
|
||||||
private final ProgressiveLoanTransactionValidator loanTransactionValidator;
|
private final ProgressiveLoanTransactionValidator loanTransactionValidator;
|
||||||
|
private final LoanTransactionService loanTransactionService;
|
||||||
|
|
||||||
public CommandProcessingResult applyContractTermination(final JsonCommand command) {
|
public CommandProcessingResult applyContractTermination(final JsonCommand command) {
|
||||||
final Loan loan = loanAssembler.assembleFrom(command.getLoanId());
|
final Loan loan = loanAssembler.assembleFrom(command.getLoanId());
|
||||||
|
|||||||
+3
-3
@@ -22,6 +22,7 @@ import java.util.List;
|
|||||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
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.domain.transactionprocessor.impl.CreocoreLoanRepaymentScheduleTransactionProcessor;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.CreocoreLoanRepaymentScheduleTransactionProcessor;
|
||||||
@@ -35,7 +36,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.imp
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.RBILoanRepaymentScheduleTransactionProcessor;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.RBILoanRepaymentScheduleTransactionProcessor;
|
||||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanBalanceService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanBalanceService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionService;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.ProgressiveLoanInterestRefundServiceImpl;
|
import org.apache.fineract.portfolio.loanaccount.service.ProgressiveLoanInterestRefundServiceImpl;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
|
import org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
|
||||||
import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
|
import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
|
||||||
@@ -138,9 +138,9 @@ public class LoanAccountAutoStarter {
|
|||||||
final LoanRepositoryWrapper loanRepositoryWrapper,
|
final LoanRepositoryWrapper loanRepositoryWrapper,
|
||||||
final @Lazy ProgressiveLoanInterestRefundServiceImpl progressiveLoanInterestRefundService,
|
final @Lazy ProgressiveLoanInterestRefundServiceImpl progressiveLoanInterestRefundService,
|
||||||
final ExternalIdFactory externalIdFactory, final LoanScheduleComponent loanSchedule,
|
final ExternalIdFactory externalIdFactory, final LoanScheduleComponent loanSchedule,
|
||||||
final LoanTransactionService loanTransactionService, final LoanChargeValidator loanChargeValidator,
|
final LoanTransactionRepository loanTransactionRepository, final LoanChargeValidator loanChargeValidator,
|
||||||
final LoanBalanceService loanBalanceService) {
|
final LoanBalanceService loanBalanceService) {
|
||||||
return new AdvancedPaymentScheduleTransactionProcessor(emiCalculator, loanRepositoryWrapper, progressiveLoanInterestRefundService,
|
return new AdvancedPaymentScheduleTransactionProcessor(emiCalculator, loanRepositoryWrapper, progressiveLoanInterestRefundService,
|
||||||
externalIdFactory, loanSchedule, loanTransactionService, loanChargeValidator, loanBalanceService);
|
externalIdFactory, loanSchedule, loanTransactionRepository, loanChargeValidator, loanBalanceService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -457,9 +457,9 @@ public class LoanAccountConfiguration {
|
|||||||
@ConditionalOnMissingBean(LoanDisbursementService.class)
|
@ConditionalOnMissingBean(LoanDisbursementService.class)
|
||||||
public LoanDisbursementService loanDisbursementService(LoanChargeValidator loanChargeValidator,
|
public LoanDisbursementService loanDisbursementService(LoanChargeValidator loanChargeValidator,
|
||||||
LoanDisbursementValidator loanDisbursementValidator, ReprocessLoanTransactionsService reprocessLoanTransactionsService,
|
LoanDisbursementValidator loanDisbursementValidator, ReprocessLoanTransactionsService reprocessLoanTransactionsService,
|
||||||
LoanChargeService loanChargeService) {
|
LoanChargeService loanChargeService, LoanBalanceService loanBalanceService) {
|
||||||
return new LoanDisbursementService(loanChargeValidator, loanDisbursementValidator, reprocessLoanTransactionsService,
|
return new LoanDisbursementService(loanChargeValidator, loanDisbursementValidator, reprocessLoanTransactionsService,
|
||||||
loanChargeService);
|
loanChargeService, loanBalanceService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|||||||
+1
-1
@@ -363,7 +363,7 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
|
|||||||
DelinquencyReadPlatformService delinquencyReadPlatformService = new DelinquencyReadPlatformServiceImpl(repositoryRange,
|
DelinquencyReadPlatformService delinquencyReadPlatformService = new DelinquencyReadPlatformServiceImpl(repositoryRange,
|
||||||
repositoryBucket, repositoryLoanDelinquencyTagHistory, mapperRange, mapperBucket, mapperLoanDelinquencyTagHistory,
|
repositoryBucket, repositoryLoanDelinquencyTagHistory, mapperRange, mapperBucket, mapperLoanDelinquencyTagHistory,
|
||||||
loanRepository, loanDelinquencyDomainService, repositoryLoanInstallmentDelinquencyTag, loanDelinquencyActionRepository,
|
loanRepository, loanDelinquencyDomainService, repositoryLoanInstallmentDelinquencyTag, loanDelinquencyActionRepository,
|
||||||
delinquencyEffectivePauseHelper, configurationDomainService);
|
delinquencyEffectivePauseHelper, configurationDomainService, Mockito.mock(LoanTransactionRepository.class));
|
||||||
|
|
||||||
LoanProduct loanProduct = Mockito.mock(LoanProduct.class);
|
LoanProduct loanProduct = Mockito.mock(LoanProduct.class);
|
||||||
when(loanProduct.isMultiDisburseLoan()).thenReturn(false);
|
when(loanProduct.isMultiDisburseLoan()).thenReturn(false);
|
||||||
|
|||||||
+2
-9
@@ -40,7 +40,6 @@ import org.apache.fineract.portfolio.group.domain.Group;
|
|||||||
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.InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanBalanceService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanBalanceService;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||||
@@ -80,7 +79,6 @@ public class LoanBuilder {
|
|||||||
private BigDecimal fixedPrincipalPercentagePerInstallment;
|
private BigDecimal fixedPrincipalPercentagePerInstallment;
|
||||||
private ExternalId externalId = ExternalId.empty();
|
private ExternalId externalId = ExternalId.empty();
|
||||||
private LoanApplicationTerms loanApplicationTerms = mock(LoanApplicationTerms.class);
|
private LoanApplicationTerms loanApplicationTerms = mock(LoanApplicationTerms.class);
|
||||||
private LoanScheduleModel loanScheduleModel = mock(LoanScheduleModel.class);
|
|
||||||
private Boolean enableInstallmentLevelDelinquency = false;
|
private Boolean enableInstallmentLevelDelinquency = false;
|
||||||
private LocalDate submittedOnDate = LocalDate.now(ZoneId.systemDefault());
|
private LocalDate submittedOnDate = LocalDate.now(ZoneId.systemDefault());
|
||||||
private LocalDate approvedOnDate;
|
private LocalDate approvedOnDate;
|
||||||
@@ -116,8 +114,8 @@ public class LoanBuilder {
|
|||||||
Loan loan = Loan.newIndividualLoanApplication(accountNo, client, loanType, loanProduct, fund, loanOfficer, loanPurpose,
|
Loan loan = Loan.newIndividualLoanApplication(accountNo, client, loanType, loanProduct, fund, loanOfficer, loanPurpose,
|
||||||
transactionProcessor, loanRepaymentScheduleDetail, charges, collateral, fixedEmiAmount, disbursementDetails,
|
transactionProcessor, loanRepaymentScheduleDetail, charges, collateral, fixedEmiAmount, disbursementDetails,
|
||||||
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential,
|
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential,
|
||||||
rates, fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, loanScheduleModel,
|
rates, fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, enableInstallmentLevelDelinquency,
|
||||||
enableInstallmentLevelDelinquency, submittedOnDate);
|
submittedOnDate);
|
||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
loan.setId(id);
|
loan.setId(id);
|
||||||
@@ -335,11 +333,6 @@ public class LoanBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoanBuilder withLoanScheduleModel(LoanScheduleModel loanScheduleModel) {
|
|
||||||
this.loanScheduleModel = loanScheduleModel;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LoanBuilder withEnableInstallmentLevelDelinquency(Boolean enableInstallmentLevelDelinquency) {
|
public LoanBuilder withEnableInstallmentLevelDelinquency(Boolean enableInstallmentLevelDelinquency) {
|
||||||
this.enableInstallmentLevelDelinquency = enableInstallmentLevelDelinquency;
|
this.enableInstallmentLevelDelinquency = enableInstallmentLevelDelinquency;
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
Reference in New Issue
Block a user