FINERACT-2233: Rework journal entry handling logic in Loan module
This commit is contained in:
committed by
Adam Saghy
parent
942ad0183c
commit
ace59352fa
+4
-4
@@ -39,11 +39,11 @@ import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferLoanMapping
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferLoanMappingRepository;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferRepository;
|
||||
import org.apache.fineract.investor.domain.LoanOwnershipTransferBusinessEvent;
|
||||
import org.apache.fineract.investor.service.AccountingService;
|
||||
import org.apache.fineract.investor.service.DelayedSettlementAttributeService;
|
||||
import org.apache.fineract.investor.service.ExternalAssetOwnerTransferOutstandingInterestCalculation;
|
||||
import org.apache.fineract.investor.service.LoanTransferabilityService;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanJournalEntryPoster;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -61,7 +61,7 @@ public class LoanAccountOwnerTransferBusinessStep implements LoanCOBBusinessStep
|
||||
ExternalTransferStatus.BUYBACK);
|
||||
private final ExternalAssetOwnerTransferRepository externalAssetOwnerTransferRepository;
|
||||
private final ExternalAssetOwnerTransferLoanMappingRepository externalAssetOwnerTransferLoanMappingRepository;
|
||||
private final AccountingService accountingService;
|
||||
private final LoanJournalEntryPoster loanJournalEntryPoster;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final LoanTransferabilityService loanTransferabilityService;
|
||||
private final DelayedSettlementAttributeService delayedSettlementAttributeService;
|
||||
@@ -148,7 +148,7 @@ public class LoanAccountOwnerTransferBusinessStep implements LoanCOBBusinessStep
|
||||
externalAssetOwnerTransferRepository.save(activeExternalAssetOwnerTransfer);
|
||||
buybackExternalAssetOwnerTransfer = externalAssetOwnerTransferRepository.save(buybackExternalAssetOwnerTransfer);
|
||||
externalAssetOwnerTransferLoanMappingRepository.deleteByLoanIdAndOwnerTransfer(loan.getId(), activeExternalAssetOwnerTransfer);
|
||||
accountingService.createJournalEntriesForBuybackAssetTransfer(loan, buybackExternalAssetOwnerTransfer);
|
||||
loanJournalEntryPoster.postJournalEntriesForExternalOwnerTransfer(loan, buybackExternalAssetOwnerTransfer, null);
|
||||
return buybackExternalAssetOwnerTransfer;
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ public class LoanAccountOwnerTransferBusinessStep implements LoanCOBBusinessStep
|
||||
ExternalTransferStatus activeStatus = determineActiveStatus(externalAssetOwnerTransfer);
|
||||
|
||||
ExternalAssetOwnerTransfer newTransfer = activatePendingEntry(settlementDate, externalAssetOwnerTransfer, activeStatus);
|
||||
accountingService.createJournalEntriesForSaleAssetTransfer(loan, newTransfer, previousOwner);
|
||||
loanJournalEntryPoster.postJournalEntriesForExternalOwnerTransfer(loan, newTransfer, previousOwner);
|
||||
return newTransfer;
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -47,6 +47,7 @@ import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferLoanMapping
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferRepository;
|
||||
import org.apache.fineract.investor.domain.LoanOwnershipTransferBusinessEvent;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanJournalEntryPoster;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -60,7 +61,7 @@ public class LoanAccountOwnerTransferServiceImpl implements LoanAccountOwnerTran
|
||||
public static final LocalDate FUTURE_DATE_9999_12_31 = LocalDate.of(9999, 12, 31);
|
||||
private final ExternalAssetOwnerTransferRepository externalAssetOwnerTransferRepository;
|
||||
private final ExternalAssetOwnerTransferLoanMappingRepository externalAssetOwnerTransferLoanMappingRepository;
|
||||
private final AccountingService accountingService;
|
||||
private final LoanJournalEntryPoster loanJournalEntryPoster;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final ExternalAssetOwnerTransferOutstandingInterestCalculation externalAssetOwnerTransferOutstandingInterestCalculation;
|
||||
|
||||
@@ -107,7 +108,7 @@ public class LoanAccountOwnerTransferServiceImpl implements LoanAccountOwnerTran
|
||||
buybackTransfer = updatePendingBuybackTransfer(loan, buybackTransfer);
|
||||
|
||||
externalAssetOwnerTransferLoanMappingRepository.deleteByLoanIdAndOwnerTransfer(loan.getId(), activeTransfer);
|
||||
accountingService.createJournalEntriesForBuybackAssetTransfer(loan, buybackTransfer);
|
||||
loanJournalEntryPoster.postJournalEntriesForExternalOwnerTransfer(loan, buybackTransfer, null);
|
||||
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanOwnershipTransferBusinessEvent(buybackTransfer, loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAccountSnapshotBusinessEvent(loan));
|
||||
|
||||
+15
-15
@@ -56,13 +56,13 @@ import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferLoanMapping
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferLoanMappingRepository;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferRepository;
|
||||
import org.apache.fineract.investor.domain.LoanOwnershipTransferBusinessEvent;
|
||||
import org.apache.fineract.investor.service.AccountingService;
|
||||
import org.apache.fineract.investor.service.DelayedSettlementAttributeService;
|
||||
import org.apache.fineract.investor.service.ExternalAssetOwnerTransferOutstandingInterestCalculation;
|
||||
import org.apache.fineract.investor.service.LoanTransferabilityService;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummary;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanJournalEntryPoster;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
@@ -97,7 +97,7 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
private ExternalAssetOwnerTransferLoanMappingRepository externalAssetOwnerTransferLoanMappingRepository;
|
||||
|
||||
@Mock
|
||||
private AccountingService accountingService;
|
||||
private LoanJournalEntryPoster loanJournalEntryPoster;
|
||||
|
||||
@Mock
|
||||
private BusinessEventNotifierService businessEventNotifierService;
|
||||
@@ -130,7 +130,7 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
ThreadLocalContextUtil.setActionContext(ActionContext.DEFAULT);
|
||||
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, actualDate)));
|
||||
underTest = new LoanAccountOwnerTransferBusinessStep(externalAssetOwnerTransferRepository,
|
||||
externalAssetOwnerTransferLoanMappingRepository, accountingService, businessEventNotifierService,
|
||||
externalAssetOwnerTransferLoanMappingRepository, loanJournalEntryPoster, businessEventNotifierService,
|
||||
loanTransferabilityService, delayedSettlementAttributeService, externalAssetOwnerTransferOutstandingInterestCalculation);
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
final Loan processedLoan = underTest.execute(loanForProcessing);
|
||||
// then
|
||||
verify(externalAssetOwnerTransferRepository, times(1)).findAll(any(Specification.class), eq(Sort.by(Sort.Direction.ASC, "id")));
|
||||
verifyNoInteractions(businessEventNotifierService, loanTransferabilityService, accountingService);
|
||||
verifyNoInteractions(businessEventNotifierService, loanTransferabilityService, loanJournalEntryPoster);
|
||||
assertEquals(processedLoan, loanForProcessing);
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
// then
|
||||
assertEquals("Illegal transfer found. Expected PENDING and BUYBACK, found: PENDING and ACTIVE", exception.getMessage());
|
||||
verify(externalAssetOwnerTransferRepository, times(1)).findAll(any(Specification.class), eq(Sort.by(Sort.Direction.ASC, "id")));
|
||||
verifyNoInteractions(businessEventNotifierService, loanTransferabilityService, accountingService);
|
||||
verifyNoInteractions(businessEventNotifierService, loanTransferabilityService, loanJournalEntryPoster);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -202,7 +202,7 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
// then
|
||||
assertEquals("Delayed Settlement enabled, but found 2 transfers of statuses: PENDING and BUYBACK", exception.getMessage());
|
||||
verify(externalAssetOwnerTransferRepository, times(1)).findAll(any(Specification.class), eq(Sort.by(Sort.Direction.ASC, "id")));
|
||||
verifyNoInteractions(businessEventNotifierService, loanTransferabilityService, accountingService);
|
||||
verifyNoInteractions(businessEventNotifierService, loanTransferabilityService, loanJournalEntryPoster);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -273,7 +273,7 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
|
||||
assertEquals(processedLoan, loanForProcessing);
|
||||
|
||||
verifyNoInteractions(loanTransferabilityService, accountingService);
|
||||
verifyNoInteractions(loanTransferabilityService, loanJournalEntryPoster);
|
||||
|
||||
ArgumentCaptor<BusinessEvent<?>> businessEventArgumentCaptor = verifyBusinessEvents(2);
|
||||
verifyLoanTransferBusinessEvent(businessEventArgumentCaptor, 0, loanForProcessing, secondSaveResult);
|
||||
@@ -316,8 +316,8 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
|
||||
assertEquals(processedLoan, loanForProcessing);
|
||||
|
||||
verify(accountingService).createJournalEntriesForBuybackAssetTransfer(loanForProcessing, firstResponseItem);
|
||||
verifyNoMoreInteractions(accountingService);
|
||||
verify(loanJournalEntryPoster).postJournalEntriesForExternalOwnerTransfer(loanForProcessing, firstResponseItem, null);
|
||||
verifyNoMoreInteractions(loanJournalEntryPoster);
|
||||
|
||||
ArgumentCaptor<BusinessEvent<?>> businessEventArgumentCaptor = verifyBusinessEvents(2);
|
||||
verifyLoanTransferBusinessEvent(businessEventArgumentCaptor, 0, loanForProcessing, firstResponseItem);
|
||||
@@ -387,8 +387,8 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
|
||||
verify(externalAssetOwnerTransferLoanMappingRepository).save(externalAssetOwnerTransferLoanMappingArgumentCaptor.capture());
|
||||
|
||||
verify(accountingService).createJournalEntriesForSaleAssetTransfer(loanForProcessing, savedNewTransfer, null);
|
||||
verifyNoMoreInteractions(accountingService);
|
||||
verify(loanJournalEntryPoster).postJournalEntriesForExternalOwnerTransfer(loanForProcessing, savedNewTransfer, null);
|
||||
verifyNoMoreInteractions(loanJournalEntryPoster);
|
||||
|
||||
ArgumentCaptor<BusinessEvent<?>> businessEventArgumentCaptor = verifyBusinessEvents(2);
|
||||
verifyLoanTransferBusinessEvent(businessEventArgumentCaptor, 0, loanForProcessing, savedNewTransfer);
|
||||
@@ -445,7 +445,7 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
assertEquals(actualDate, capturedActiveTransfer.getEffectiveDateTo());
|
||||
assertEquals(processedLoan, loanForProcessing);
|
||||
|
||||
verifyNoInteractions(accountingService);
|
||||
verifyNoInteractions(loanJournalEntryPoster);
|
||||
|
||||
ArgumentCaptor<BusinessEvent<?>> businessEventArgumentCaptor = verifyBusinessEvents(1);
|
||||
verifyLoanTransferBusinessEvent(businessEventArgumentCaptor, 0, loanForProcessing, savedNewTransfer);
|
||||
@@ -516,8 +516,8 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
assertEquals(savedNewTransfer, externalAssetOwnerTransferLoanMappingArgumentCaptor.getValue().getOwnerTransfer());
|
||||
assertEquals(processedLoan, loanForProcessing);
|
||||
|
||||
verify(accountingService).createJournalEntriesForSaleAssetTransfer(loanForProcessing, savedNewTransfer, previousOwner);
|
||||
verifyNoMoreInteractions(accountingService);
|
||||
verify(loanJournalEntryPoster).postJournalEntriesForExternalOwnerTransfer(loanForProcessing, savedNewTransfer, previousOwner);
|
||||
verifyNoMoreInteractions(loanJournalEntryPoster);
|
||||
|
||||
ArgumentCaptor<BusinessEvent<?>> businessEventArgumentCaptor = verifyBusinessEvents(2);
|
||||
verifyLoanTransferBusinessEvent(businessEventArgumentCaptor, 0, loanForProcessing, savedNewTransfer);
|
||||
@@ -552,7 +552,7 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
||||
|
||||
verify(loanTransferabilityService).isTransferable(loanForProcessing, pendingTransfer);
|
||||
verifyNoMoreInteractions(loanTransferabilityService);
|
||||
verifyNoInteractions(accountingService);
|
||||
verifyNoInteractions(loanJournalEntryPoster);
|
||||
verify(externalAssetOwnerTransferRepository).findAll(any(Specification.class), eq(Sort.by(Sort.Direction.ASC, "id")));
|
||||
verify(externalAssetOwnerTransferRepository).findOne(any(Specification.class));
|
||||
verify(externalAssetOwnerTransferRepository, never()).save(any(ExternalAssetOwnerTransfer.class));
|
||||
|
||||
+3
@@ -50,6 +50,7 @@ import org.apache.fineract.investor.domain.LoanOwnershipTransferBusinessEvent;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummary;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanJournalEntryPoster;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
@@ -82,6 +83,8 @@ public class LoanAccountOwnerTransferServiceTest {
|
||||
private BusinessEventNotifierService businessEventNotifierService;
|
||||
@Mock
|
||||
private ExternalAssetOwnerTransferOutstandingInterestCalculation externalAssetOwnerTransferOutstandingInterestCalculation;
|
||||
@Mock
|
||||
private LoanJournalEntryPoster loanJournalEntryPoster;
|
||||
|
||||
@InjectMocks
|
||||
private LoanAccountOwnerTransferServiceImpl underTest;
|
||||
|
||||
-274
@@ -1,274 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.mapper;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccountingBridgeDataDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccountingBridgeLoanTransactionDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargePaidByDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargePaidBy;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelation;
|
||||
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.loanproduct.service.LoanEnumerations;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class LoanAccountingBridgeMapper {
|
||||
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
|
||||
public List<AccountingBridgeDataDTO> deriveAccountingBridgeDataForChargeOff(final String currencyCode,
|
||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds, final boolean isAccountTransfer,
|
||||
final Loan loan) {
|
||||
final List<AccountingBridgeLoanTransactionDTO> newLoanTransactionsBeforeChargeOff = new ArrayList<>();
|
||||
final List<AccountingBridgeLoanTransactionDTO> newLoanTransactionsAfterChargeOff = new ArrayList<>();
|
||||
|
||||
// split the transactions according charge-off date
|
||||
classifyTransactionsBasedOnChargeOffDate(newLoanTransactionsBeforeChargeOff, newLoanTransactionsAfterChargeOff,
|
||||
existingTransactionIds, existingReversedTransactionIds, currencyCode, loan);
|
||||
|
||||
AccountingBridgeDataDTO beforeChargeOff = new AccountingBridgeDataDTO(loan.getId(), loan.productId(), loan.getOfficeId(),
|
||||
currencyCode, loan.getSummary().getTotalInterestCharged(), loan.isCashBasedAccountingEnabledOnLoanProduct(),
|
||||
loan.isUpfrontAccrualAccountingEnabledOnLoanProduct(), loan.isPeriodicAccrualAccountingEnabledOnLoanProduct(),
|
||||
isAccountTransfer, false, loan.isFraud(), loan.fetchChargeOffReasonId(), loan.isClosedWrittenOff(),
|
||||
newLoanTransactionsBeforeChargeOff, loan.getLoanProductRelatedDetail().isMerchantBuyDownFee());
|
||||
|
||||
AccountingBridgeDataDTO afterChargeOff = new AccountingBridgeDataDTO(loan.getId(), loan.productId(), loan.getOfficeId(),
|
||||
currencyCode, loan.getSummary().getTotalInterestCharged(), loan.isCashBasedAccountingEnabledOnLoanProduct(),
|
||||
loan.isUpfrontAccrualAccountingEnabledOnLoanProduct(), loan.isPeriodicAccrualAccountingEnabledOnLoanProduct(),
|
||||
isAccountTransfer, true, loan.isFraud(), loan.fetchChargeOffReasonId(), loan.isClosedWrittenOff(),
|
||||
newLoanTransactionsAfterChargeOff, loan.getLoanProductRelatedDetail().isMerchantBuyDownFee());
|
||||
|
||||
List<AccountingBridgeDataDTO> result = new ArrayList<>();
|
||||
result.add(beforeChargeOff);
|
||||
result.add(afterChargeOff);
|
||||
return result;
|
||||
}
|
||||
|
||||
public AccountingBridgeDataDTO deriveAccountingBridgeData(final String currencyCode, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, final boolean isAccountTransfer, final Loan loan) {
|
||||
final List<LoanTransaction> transactions = findTransactionsForAccountingBridge(existingTransactionIds,
|
||||
existingReversedTransactionIds, loan);
|
||||
|
||||
final List<AccountingBridgeLoanTransactionDTO> newLoanTransactions = transactions.stream() //
|
||||
.map(transaction -> mapToLoanTransactionData(transaction, currencyCode)) //
|
||||
.toList();
|
||||
|
||||
return new AccountingBridgeDataDTO(loan.getId(), loan.productId(), loan.getOfficeId(), currencyCode,
|
||||
loan.getSummary().getTotalInterestCharged(), loan.isCashBasedAccountingEnabledOnLoanProduct(),
|
||||
loan.isUpfrontAccrualAccountingEnabledOnLoanProduct(), loan.isPeriodicAccrualAccountingEnabledOnLoanProduct(),
|
||||
isAccountTransfer, loan.isChargedOff(), loan.isFraud(), loan.fetchChargeOffReasonId(), loan.isClosedWrittenOff(),
|
||||
newLoanTransactions, loan.getLoanProductRelatedDetail().isMerchantBuyDownFee());
|
||||
}
|
||||
|
||||
public AccountingBridgeLoanTransactionDTO mapToLoanTransactionData(final LoanTransaction transaction, final String currencyCode) {
|
||||
final AccountingBridgeLoanTransactionDTO transactionDTO = new AccountingBridgeLoanTransactionDTO();
|
||||
|
||||
transactionDTO.setId(transaction.getId());
|
||||
transactionDTO.setOfficeId(transaction.getOffice().getId());
|
||||
transactionDTO.setType(LoanEnumerations.transactionType(transaction.getTypeOf()));
|
||||
transactionDTO.setReversed(transaction.isReversed());
|
||||
transactionDTO.setDate(transaction.getTransactionDate());
|
||||
transactionDTO.setCurrencyCode(currencyCode);
|
||||
transactionDTO.setAmount(transaction.getAmount());
|
||||
transactionDTO.setNetDisbursalAmount(transaction.getLoan().getNetDisbursalAmount());
|
||||
|
||||
if (transactionDTO.getType().isChargeback() && (transaction.getLoan().getCreditAllocationRules() == null
|
||||
|| transaction.getLoan().getCreditAllocationRules().isEmpty())) {
|
||||
transactionDTO.setPrincipalPortion(transaction.getAmount());
|
||||
} else {
|
||||
transactionDTO.setPrincipalPortion(transaction.getPrincipalPortion());
|
||||
}
|
||||
|
||||
transactionDTO.setInterestPortion(transaction.getInterestPortion());
|
||||
transactionDTO.setFeeChargesPortion(transaction.getFeeChargesPortion());
|
||||
transactionDTO.setPenaltyChargesPortion(transaction.getPenaltyChargesPortion());
|
||||
transactionDTO.setOverPaymentPortion(transaction.getOverPaymentPortion());
|
||||
|
||||
if (transactionDTO.getType().isChargeRefund()) {
|
||||
transactionDTO.setChargeRefundChargeType(transaction.getChargeRefundChargeType());
|
||||
}
|
||||
|
||||
if (transaction.getPaymentDetail() != null) {
|
||||
transactionDTO.setPaymentTypeId(transaction.getPaymentDetail().getPaymentType().getId());
|
||||
}
|
||||
|
||||
if (!transaction.getLoanChargesPaid().isEmpty()) {
|
||||
List<LoanChargePaidByDTO> loanChargesPaidData = new ArrayList<>();
|
||||
for (final LoanChargePaidBy chargePaidBy : transaction.getLoanChargesPaid()) {
|
||||
final LoanChargePaidByDTO loanChargePaidData = new LoanChargePaidByDTO();
|
||||
loanChargePaidData.setChargeId(chargePaidBy.getLoanCharge().getCharge().getId());
|
||||
loanChargePaidData.setIsPenalty(chargePaidBy.getLoanCharge().isPenaltyCharge());
|
||||
loanChargePaidData.setLoanChargeId(chargePaidBy.getLoanCharge().getId());
|
||||
loanChargePaidData.setAmount(chargePaidBy.getAmount());
|
||||
loanChargePaidData.setInstallmentNumber(chargePaidBy.getInstallmentNumber());
|
||||
|
||||
loanChargesPaidData.add(loanChargePaidData);
|
||||
}
|
||||
transactionDTO.setLoanChargesPaid(loanChargesPaidData);
|
||||
}
|
||||
|
||||
if (transactionDTO.getType().isChargeback() && transaction.getOverPaymentPortion() != null
|
||||
&& transaction.getOverPaymentPortion().compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal principalPaid = transaction.getOverPaymentPortion();
|
||||
BigDecimal feePaid = BigDecimal.ZERO;
|
||||
BigDecimal penaltyPaid = BigDecimal.ZERO;
|
||||
if (!transaction.getLoanTransactionToRepaymentScheduleMappings().isEmpty()) {
|
||||
principalPaid = transaction.getLoanTransactionToRepaymentScheduleMappings().stream()
|
||||
.map(mapping -> Optional.ofNullable(mapping.getPrincipalPortion()).orElse(BigDecimal.ZERO))
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
feePaid = transaction.getLoanTransactionToRepaymentScheduleMappings().stream()
|
||||
.map(mapping -> Optional.ofNullable(mapping.getFeeChargesPortion()).orElse(BigDecimal.ZERO))
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
penaltyPaid = transaction.getLoanTransactionToRepaymentScheduleMappings().stream()
|
||||
.map(mapping -> Optional.ofNullable(mapping.getPenaltyChargesPortion()).orElse(BigDecimal.ZERO))
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
transactionDTO.setPrincipalPaid(principalPaid);
|
||||
transactionDTO.setFeePaid(feePaid);
|
||||
transactionDTO.setPenaltyPaid(penaltyPaid);
|
||||
}
|
||||
|
||||
LoanTransactionRelation loanTransactionRelation = transaction.getLoanTransactionRelations().stream()
|
||||
.filter(e -> LoanTransactionRelationTypeEnum.CHARGE_ADJUSTMENT.equals(e.getRelationType())).findAny().orElse(null);
|
||||
if (loanTransactionRelation != null) {
|
||||
LoanCharge loanCharge = loanTransactionRelation.getToCharge();
|
||||
transactionDTO.setLoanChargeData(loanCharge.toData());
|
||||
}
|
||||
|
||||
transactionDTO.setLoanToLoanTransfer(false);
|
||||
|
||||
return transactionDTO;
|
||||
}
|
||||
|
||||
private void classifyTransactionsBasedOnChargeOffDate(final List<AccountingBridgeLoanTransactionDTO> newLoanTransactionsBeforeChargeOff,
|
||||
final List<AccountingBridgeLoanTransactionDTO> newLoanTransactionsAfterChargeOff, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, final String currencyCode, final Loan loan) {
|
||||
|
||||
final LocalDate chargeOffDate = loan.getChargedOffOnDate();
|
||||
if (chargeOffDate == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Before charge-off
|
||||
final List<LoanTransaction> beforeTransactions = findTransactionsForChargeOffClassification(loan, chargeOffDate, "BEFORE",
|
||||
existingTransactionIds, existingReversedTransactionIds);
|
||||
processTransactionsForChargeOff(beforeTransactions, newLoanTransactionsBeforeChargeOff, newLoanTransactionsAfterChargeOff,
|
||||
currencyCode, loan);
|
||||
|
||||
// On charge-off date
|
||||
final List<LoanTransaction> onTransactions = findTransactionsForChargeOffClassification(loan, chargeOffDate, "EQUAL",
|
||||
existingTransactionIds, existingReversedTransactionIds);
|
||||
processTransactionsForChargeOff(onTransactions, newLoanTransactionsBeforeChargeOff, newLoanTransactionsAfterChargeOff, currencyCode,
|
||||
loan);
|
||||
|
||||
// After charge-off
|
||||
final List<LoanTransaction> afterTransactions = findTransactionsForChargeOffClassification(loan, chargeOffDate, "AFTER",
|
||||
existingTransactionIds, existingReversedTransactionIds);
|
||||
processTransactionsForChargeOff(afterTransactions, newLoanTransactionsBeforeChargeOff, newLoanTransactionsAfterChargeOff,
|
||||
currencyCode, loan);
|
||||
}
|
||||
|
||||
private List<LoanTransaction> findTransactionsForChargeOffClassification(final Loan loan, final LocalDate chargeOffDate,
|
||||
final String dateComparison, final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
||||
|
||||
final boolean hasExistingIds = existingTransactionIds != null && !existingTransactionIds.isEmpty();
|
||||
final boolean hasExistingReversedIds = existingReversedTransactionIds != null && !existingReversedTransactionIds.isEmpty();
|
||||
|
||||
if (hasExistingIds && hasExistingReversedIds) {
|
||||
return loanTransactionRepository.findTransactionsForChargeOffClassification(loan, chargeOffDate, dateComparison,
|
||||
existingTransactionIds, existingReversedTransactionIds);
|
||||
} else if (hasExistingIds) {
|
||||
return loanTransactionRepository.findTransactionsForChargeOffClassification(loan, chargeOffDate, dateComparison,
|
||||
existingTransactionIds);
|
||||
} else {
|
||||
return loanTransactionRepository.findTransactionsForChargeOffClassification(loan, chargeOffDate, dateComparison);
|
||||
}
|
||||
}
|
||||
|
||||
private void processTransactionsForChargeOff(final List<LoanTransaction> transactions,
|
||||
final List<AccountingBridgeLoanTransactionDTO> newLoanTransactionsBeforeChargeOff,
|
||||
final List<AccountingBridgeLoanTransactionDTO> newLoanTransactionsAfterChargeOff, final String currencyCode, final Loan loan) {
|
||||
|
||||
final Optional<LoanTransaction> chargeOffTransactionOptional = findChargeOffTransaction(loan);
|
||||
if (chargeOffTransactionOptional.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final LoanTransaction chargeOffTransaction = chargeOffTransactionOptional.get();
|
||||
final LoanTransaction originalChargeOffTransaction = getOriginalTransactionIfReverseReplayed(chargeOffTransaction);
|
||||
|
||||
transactions.forEach(transaction -> {
|
||||
List<AccountingBridgeLoanTransactionDTO> targetList;
|
||||
|
||||
if (transaction.isReversed()) {
|
||||
final LoanTransaction originalTransaction = getOriginalTransactionIfReverseReplayed(transaction);
|
||||
targetList = originalTransaction.happenedBefore(originalChargeOffTransaction) ? newLoanTransactionsBeforeChargeOff
|
||||
: newLoanTransactionsAfterChargeOff;
|
||||
} else {
|
||||
targetList = transaction.happenedBefore(chargeOffTransaction) ? newLoanTransactionsBeforeChargeOff
|
||||
: newLoanTransactionsAfterChargeOff;
|
||||
}
|
||||
|
||||
targetList.add(mapToLoanTransactionData(transaction, currencyCode));
|
||||
});
|
||||
}
|
||||
|
||||
private Optional<LoanTransaction> findChargeOffTransaction(final Loan loan) {
|
||||
return loanTransactionRepository.findNonReversedByLoanAndType(loan, LoanTransactionType.CHARGE_OFF).stream() //
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
private List<LoanTransaction> findTransactionsForAccountingBridge(final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, final Loan loan) {
|
||||
if (existingTransactionIds == null || existingTransactionIds.isEmpty()) {
|
||||
return loanTransactionRepository.findNonReversedByLoan(loan);
|
||||
} else if (existingReversedTransactionIds == null || existingReversedTransactionIds.isEmpty()) {
|
||||
return loanTransactionRepository.findTransactionsForAccountingBridge(loan, existingTransactionIds);
|
||||
} else {
|
||||
return loanTransactionRepository.findTransactionsForAccountingBridge(loan, existingTransactionIds,
|
||||
existingReversedTransactionIds);
|
||||
}
|
||||
}
|
||||
|
||||
private LoanTransaction getOriginalTransactionIfReverseReplayed(final LoanTransaction loanTransaction) {
|
||||
if (loanTransaction.getLoanTransactionRelations().isEmpty()) {
|
||||
return loanTransaction;
|
||||
}
|
||||
|
||||
return loanTransaction.getLoanTransactionRelations().stream() //
|
||||
.filter(tr -> LoanTransactionRelationTypeEnum.REPLAYED.equals(tr.getRelationType())) //
|
||||
.map(LoanTransactionRelation::getToTransaction) //
|
||||
.min(Comparator.comparingLong(LoanTransaction::getId)) //
|
||||
.orElse(loanTransaction);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -34,13 +34,13 @@ public interface LoanAccrualsProcessingService {
|
||||
|
||||
void addAccruals(@NotNull LocalDate tillDate) throws MultiException;
|
||||
|
||||
void reprocessExistingAccruals(@NotNull Loan loan);
|
||||
void reprocessExistingAccruals(@NotNull Loan loan, boolean addEvent);
|
||||
|
||||
void processAccrualsOnInterestRecalculation(@NotNull Loan loan, boolean isInterestRecalculationEnabled, boolean addJournal);
|
||||
|
||||
void addIncomePostingAndAccruals(Long loanId) throws Exception;
|
||||
|
||||
void processIncomePostingAndAccruals(@NotNull Loan loan);
|
||||
void processIncomePostingAndAccruals(@NotNull Loan loan, boolean addEvent);
|
||||
|
||||
void processAccrualsOnLoanClosure(@NonNull Loan loan, boolean addJournal);
|
||||
|
||||
|
||||
+2
-6
@@ -51,7 +51,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleIns
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTrancheDisbursementCharge;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.SingleLoanChargeRepaymentScheduleProcessingWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
||||
@@ -64,7 +63,6 @@ public class LoanChargeService {
|
||||
private final LoanTransactionProcessingService loanTransactionProcessingService;
|
||||
private final LoanLifecycleStateMachine loanLifecycleStateMachine;
|
||||
private final LoanBalanceService loanBalanceService;
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
|
||||
public void recalculateAllCharges(final Loan loan) {
|
||||
Set<LoanCharge> charges = loan.getActiveCharges();
|
||||
@@ -134,11 +132,9 @@ public class LoanChargeService {
|
||||
}
|
||||
}
|
||||
|
||||
public void makeChargePayment(final Loan loan, final Long chargeId, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, final LoanTransaction paymentTransaction, final Integer installmentNumber) {
|
||||
public void makeChargePayment(final Loan loan, final Long chargeId, final LoanTransaction paymentTransaction,
|
||||
final Integer installmentNumber) {
|
||||
loanChargeValidator.validateChargePaymentNotInFuture(paymentTransaction);
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
LoanCharge charge = null;
|
||||
for (final LoanCharge loanCharge : loan.getCharges()) {
|
||||
if (loanCharge.isActive() && chargeId.equals(loanCharge.getId())) {
|
||||
|
||||
+2
@@ -63,6 +63,7 @@ public class LoanDownPaymentHandlerServiceImpl implements LoanDownPaymentHandler
|
||||
private final LoanLifecycleStateMachine loanLifecycleStateMachine;
|
||||
private final LoanBalanceService loanBalanceService;
|
||||
private final LoanTransactionService loanTransactionService;
|
||||
private final LoanJournalEntryPoster journalEntryPoster;
|
||||
|
||||
@Override
|
||||
public LoanTransaction handleDownPayment(ScheduleGeneratorDTO scheduleGeneratorDTO, JsonCommand command,
|
||||
@@ -71,6 +72,7 @@ public class LoanDownPaymentHandlerServiceImpl implements LoanDownPaymentHandler
|
||||
LoanTransaction downPaymentTransaction = handleDownPayment(loan, disbursementTransaction, command, scheduleGeneratorDTO);
|
||||
if (downPaymentTransaction != null) {
|
||||
downPaymentTransaction = loanTransactionRepository.saveAndFlush(downPaymentTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(downPaymentTransaction, false, false);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanTransactionDownPaymentPostBusinessEvent(downPaymentTransaction));
|
||||
}
|
||||
return downPaymentTransaction;
|
||||
|
||||
+25
-2
@@ -18,10 +18,33 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.service;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
|
||||
public interface LoanJournalEntryPoster {
|
||||
|
||||
void postJournalEntries(Loan loan, List<Long> existingTransactionIds, List<Long> existingReversedTransactionIds);
|
||||
/**
|
||||
* Create journal entries immediately for a single loan transaction This replaces the old 2-step process of
|
||||
* collecting transaction IDs and then creating journal entries
|
||||
*
|
||||
* @param loanTransaction
|
||||
* the loan transaction to create journal entries for
|
||||
* @param isAccountTransfer
|
||||
* whether this is an account transfer transaction
|
||||
* @param isLoanToLoanTransfer
|
||||
* whether this is a loan-to-loan transfer transaction
|
||||
*/
|
||||
void postJournalEntriesForLoanTransaction(LoanTransaction loanTransaction, boolean isAccountTransfer, boolean isLoanToLoanTransfer);
|
||||
|
||||
/**
|
||||
* Create journal entries immediately for an external owner transfer
|
||||
*
|
||||
* @param loan
|
||||
* the loan being transferred
|
||||
* @param externalAssetOwnerTransfer
|
||||
* the external owner transfer details
|
||||
* @param previousOwner
|
||||
* the previous owner (can be null for initial transfers)
|
||||
*/
|
||||
void postJournalEntriesForExternalOwnerTransfer(Loan loan, Object externalAssetOwnerTransfer, Object previousOwner);
|
||||
}
|
||||
|
||||
+3
-19
@@ -19,13 +19,11 @@
|
||||
package org.apache.fineract.portfolio.loanaccount.service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanEvent;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
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.TransactionCtx;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanRefundValidator;
|
||||
@@ -36,13 +34,8 @@ public class LoanRefundService {
|
||||
private final LoanRefundValidator loanRefundValidator;
|
||||
private final LoanTransactionProcessingService loadTransactionProcessingService;
|
||||
private final LoanLifecycleStateMachine loanLifecycleStateMachine;
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
|
||||
public void makeRefund(final Loan loan, final LoanTransaction loanTransaction, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds) {
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
public void makeRefund(final Loan loan, final LoanTransaction loanTransaction) {
|
||||
loanRefundValidator.validateTransferRefund(loan, loanTransaction);
|
||||
|
||||
loanTransaction.updateLoan(loan);
|
||||
@@ -59,21 +52,12 @@ public class LoanRefundService {
|
||||
return loanTransactionDate;
|
||||
}
|
||||
|
||||
public void makeRefundForActiveLoan(final Loan loan, final LoanTransaction loanTransaction, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds) {
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
public void makeRefundForActiveLoan(final Loan loan, final LoanTransaction loanTransaction) {
|
||||
handleRefundTransaction(loan, loanTransaction);
|
||||
}
|
||||
|
||||
public void creditBalanceRefund(final Loan loan, final LoanTransaction newCreditBalanceRefundTransaction,
|
||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
||||
public void creditBalanceRefund(final Loan loan, final LoanTransaction newCreditBalanceRefundTransaction) {
|
||||
loanRefundValidator.validateCreditBalanceRefund(loan, newCreditBalanceRefundTransaction);
|
||||
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
loan.getLoanTransactions().add(newCreditBalanceRefundTransaction);
|
||||
|
||||
loanLifecycleStateMachine.determineAndTransition(loan, newCreditBalanceRefundTransaction.getTransactionDate());
|
||||
|
||||
+1
-2
@@ -69,8 +69,7 @@ public class SingleLoanChargeRepaymentScheduleProcessingWrapperTest {
|
||||
private ArgumentCaptor<Money> penaltyChargesWrittenOff = ArgumentCaptor.forClass(Money.class);
|
||||
|
||||
private final LoanChargeService loanChargeService = new LoanChargeService(mock(LoanChargeValidator.class),
|
||||
mock(LoanTransactionProcessingService.class), mock(LoanLifecycleStateMachine.class), mock(LoanBalanceService.class),
|
||||
mock(LoanTransactionRepository.class));
|
||||
mock(LoanTransactionProcessingService.class), mock(LoanLifecycleStateMachine.class), mock(LoanBalanceService.class));
|
||||
|
||||
@BeforeAll
|
||||
public static void init() {
|
||||
|
||||
+3
-10
@@ -20,9 +20,7 @@ package org.apache.fineract.portfolio.loanaccount.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -77,8 +75,6 @@ public class BuyDownFeeWritePlatformServiceImpl implements BuyDownFeePlatformSer
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
|
||||
// Create payment details
|
||||
@@ -109,8 +105,7 @@ public class BuyDownFeeWritePlatformServiceImpl implements BuyDownFeePlatformSer
|
||||
noteWritePlatformService.createLoanTransactionNote(buyDownFeeTransaction.getId(), noteText);
|
||||
}
|
||||
|
||||
// Post journal entries
|
||||
loanJournalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(buyDownFeeTransaction, false, false);
|
||||
|
||||
// Notify business events
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBuyDownFeeTransactionCreatedBusinessEvent(buyDownFeeTransaction));
|
||||
@@ -131,8 +126,6 @@ public class BuyDownFeeWritePlatformServiceImpl implements BuyDownFeePlatformSer
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
|
||||
// Create payment details
|
||||
@@ -178,8 +171,8 @@ public class BuyDownFeeWritePlatformServiceImpl implements BuyDownFeePlatformSer
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
noteWritePlatformService.createLoanTransactionNote(savedBuyDownFeeAdjustment.getId(), noteText);
|
||||
}
|
||||
// Post journal entries
|
||||
loanJournalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(savedBuyDownFeeAdjustment, false, false);
|
||||
|
||||
// Notify business events
|
||||
businessEventNotifierService
|
||||
|
||||
+4
-10
@@ -20,9 +20,7 @@ package org.apache.fineract.portfolio.loanaccount.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -74,8 +72,6 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
||||
public CommandProcessingResult addCapitalizedIncome(final Long loanId, final JsonCommand command) {
|
||||
loanTransactionValidator.validateCapitalizedIncome(command, loanId);
|
||||
final Loan loan = loanAssembler.assembleFrom(loanId);
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
// Create payment details
|
||||
final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
|
||||
@@ -106,8 +102,8 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
||||
noteWritePlatformService.createLoanTransactionNote(capitalizedIncomeTransaction.getId(), noteText);
|
||||
}
|
||||
|
||||
// Post journal entries
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
// Create journal entries immediately for this transaction
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(capitalizedIncomeTransaction, false, false);
|
||||
|
||||
loanLifecycleStateMachine.determineAndTransition(loan, transactionDate);
|
||||
|
||||
@@ -128,8 +124,6 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
||||
final JsonCommand command) {
|
||||
loanTransactionValidator.validateCapitalizedIncomeAdjustment(command, loanId, capitalizedIncomeTransactionId);
|
||||
final Loan loan = loanAssembler.assembleFrom(loanId);
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
// Create payment details
|
||||
final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
|
||||
@@ -155,8 +149,8 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
||||
if (noteText != null && !noteText.isEmpty()) {
|
||||
noteWritePlatformService.createLoanTransactionNote(savedCapitalizedIncomeAdjustment.getId(), noteText);
|
||||
}
|
||||
// Post journal entries
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
// Create journal entries immediately for this transaction
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(savedCapitalizedIncomeAdjustment, false, false);
|
||||
|
||||
LoanCapitalizedIncomeBalance capitalizedIncomeBalance = capitalizedIncomeBalanceRepository.findByLoanIdAndLoanTransactionId(loanId,
|
||||
capitalizedIncomeTransactionId);
|
||||
|
||||
+29
@@ -24,7 +24,11 @@ import java.util.Map;
|
||||
import org.apache.fineract.accounting.provisioning.domain.ProvisioningEntry;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwner;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransfer;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccountingBridgeDataDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
|
||||
public interface JournalEntryWritePlatformService {
|
||||
|
||||
@@ -50,4 +54,29 @@ public interface JournalEntryWritePlatformService {
|
||||
|
||||
void revertShareAccountJournalEntries(ArrayList<Long> transactionId, LocalDate transactionDate);
|
||||
|
||||
/**
|
||||
* Create journal entries immediately for a single loan transaction
|
||||
*
|
||||
* @param loanTransaction
|
||||
* the loan transaction to create journal entries for
|
||||
* @param isAccountTransfer
|
||||
* whether this is an account transfer transaction
|
||||
* @param isLoanToLoanTransfer
|
||||
* whether this is a loan-to-loan transfer transaction
|
||||
*/
|
||||
void createJournalEntriesForLoanTransaction(LoanTransaction loanTransaction, boolean isAccountTransfer, boolean isLoanToLoanTransfer);
|
||||
|
||||
/**
|
||||
* Create journal entries immediately for an external owner transfer
|
||||
*
|
||||
* @param loan
|
||||
* the loan being transferred
|
||||
* @param externalAssetOwnerTransfer
|
||||
* the external owner transfer details
|
||||
* @param previousOwner
|
||||
* the previous owner (can be null for initial transfers)
|
||||
*/
|
||||
void createJournalEntriesForExternalOwnerTransfer(Loan loan, ExternalAssetOwnerTransfer externalAssetOwnerTransfer,
|
||||
ExternalAssetOwner previousOwner);
|
||||
|
||||
}
|
||||
|
||||
+165
@@ -78,13 +78,24 @@ import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwner;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerRepository;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransfer;
|
||||
import org.apache.fineract.investor.exception.ExternalAssetOwnerNotFoundException;
|
||||
import org.apache.fineract.investor.service.AccountingService;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.OrganisationCurrencyRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.PortfolioProductType;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccountingBridgeDataDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccountingBridgeLoanTransactionDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargePaidByDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargePaidBy;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelation;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum;
|
||||
import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
import org.apache.fineract.portfolio.paymentdetail.service.PaymentDetailWritePlatformService;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
@@ -789,6 +800,160 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
accountingProcessorForClientTransactions.createJournalEntriesForClientTransaction(clientTransactionDTO);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void createJournalEntriesForLoanTransaction(final LoanTransaction loanTransaction, final boolean isAccountTransfer,
|
||||
final boolean isLoanToLoanTransfer) {
|
||||
final Loan loan = loanTransaction.getLoan();
|
||||
|
||||
// Check if accounting is enabled for this loan
|
||||
if (!loan.isCashBasedAccountingEnabledOnLoanProduct() && !loan.isUpfrontAccrualAccountingEnabledOnLoanProduct()
|
||||
&& !loan.isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
|
||||
return; // No accounting enabled, skip journal entry creation
|
||||
}
|
||||
|
||||
final AccountingBridgeDataDTO accountingBridgeData = createAccountingBridgeDataForSingleTransaction(loanTransaction,
|
||||
isAccountTransfer);
|
||||
|
||||
if (isLoanToLoanTransfer) {
|
||||
accountingBridgeData.getNewLoanTransactions().forEach(tx -> tx.setLoanToLoanTransfer(true));
|
||||
}
|
||||
|
||||
this.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void createJournalEntriesForExternalOwnerTransfer(final Loan loan, final ExternalAssetOwnerTransfer externalAssetOwnerTransfer,
|
||||
final ExternalAssetOwner previousOwner) {
|
||||
final boolean isBuyback = externalAssetOwnerTransfer.getStatus().name().contains("BUYBACK");
|
||||
|
||||
if (isBuyback) {
|
||||
this.accountingService.createJournalEntriesForBuybackAssetTransfer(loan, externalAssetOwnerTransfer);
|
||||
} else {
|
||||
this.accountingService.createJournalEntriesForSaleAssetTransfer(loan, externalAssetOwnerTransfer, previousOwner);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create AccountingBridgeDataDTO for a single loan transaction This converts a single LoanTransaction to the format
|
||||
* expected by existing journal entry logic
|
||||
*/
|
||||
private AccountingBridgeDataDTO createAccountingBridgeDataForSingleTransaction(final LoanTransaction loanTransaction,
|
||||
final boolean isAccountTransfer) {
|
||||
final Loan loan = loanTransaction.getLoan();
|
||||
final String currencyCode = loan.getCurrencyCode();
|
||||
|
||||
final AccountingBridgeLoanTransactionDTO transactionDTO = convertToAccountingBridgeTransaction(loanTransaction);
|
||||
|
||||
final List<AccountingBridgeLoanTransactionDTO> transactions = new ArrayList<>();
|
||||
transactions.add(transactionDTO);
|
||||
|
||||
boolean wasChargedOffAtTransactionTime = loan.isChargedOff();
|
||||
if (loan.isChargedOff() && loan.getChargedOffOnDate() != null) {
|
||||
// If transaction date is before charge-off date, treat as non-charged-off
|
||||
if (loanTransaction.getTransactionDate().isBefore(loan.getChargedOffOnDate())) {
|
||||
wasChargedOffAtTransactionTime = false;
|
||||
}
|
||||
}
|
||||
|
||||
return new AccountingBridgeDataDTO(loan.getId(), loan.productId(), loan.getOfficeId(), currencyCode,
|
||||
loan.getSummary().getTotalInterestCharged(), loan.isCashBasedAccountingEnabledOnLoanProduct(),
|
||||
loan.isUpfrontAccrualAccountingEnabledOnLoanProduct(), loan.isPeriodicAccrualAccountingEnabledOnLoanProduct(),
|
||||
isAccountTransfer, wasChargedOffAtTransactionTime, loan.isFraud(), loan.fetchChargeOffReasonId(), loan.isClosedWrittenOff(),
|
||||
transactions, loan.getLoanProductRelatedDetail().isMerchantBuyDownFee());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert LoanTransaction to AccountingBridgeLoanTransactionDTO
|
||||
*/
|
||||
private AccountingBridgeLoanTransactionDTO convertToAccountingBridgeTransaction(LoanTransaction loanTransaction) {
|
||||
final MonetaryCurrency currency = loanTransaction.getLoan().getCurrency();
|
||||
final AccountingBridgeLoanTransactionDTO transactionDTO = new AccountingBridgeLoanTransactionDTO();
|
||||
|
||||
transactionDTO.setId(loanTransaction.getId());
|
||||
transactionDTO.setOfficeId(loanTransaction.getOffice().getId());
|
||||
transactionDTO.setType(LoanEnumerations.transactionType(loanTransaction.getTypeOf()));
|
||||
transactionDTO.setReversed(loanTransaction.isReversed());
|
||||
transactionDTO.setDate(loanTransaction.getTransactionDate());
|
||||
transactionDTO.setCurrencyCode(currency.getCode());
|
||||
transactionDTO.setAmount(loanTransaction.getAmount());
|
||||
transactionDTO.setNetDisbursalAmount(loanTransaction.getLoan().getNetDisbursalAmount());
|
||||
|
||||
// Handle principalPortion for chargeback
|
||||
if (transactionDTO.getType().isChargeback() && (loanTransaction.getLoan().getCreditAllocationRules() == null
|
||||
|| loanTransaction.getLoan().getCreditAllocationRules().isEmpty())) {
|
||||
transactionDTO.setPrincipalPortion(loanTransaction.getAmount());
|
||||
} else {
|
||||
transactionDTO.setPrincipalPortion(loanTransaction.getPrincipalPortion());
|
||||
}
|
||||
|
||||
transactionDTO.setInterestPortion(loanTransaction.getInterestPortion());
|
||||
transactionDTO.setFeeChargesPortion(loanTransaction.getFeeChargesPortion());
|
||||
transactionDTO.setPenaltyChargesPortion(loanTransaction.getPenaltyChargesPortion());
|
||||
transactionDTO.setOverPaymentPortion(loanTransaction.getOverPaymentPortion());
|
||||
|
||||
// Handle ChargeRefund transactions
|
||||
if (transactionDTO.getType().isChargeRefund()) {
|
||||
transactionDTO.setChargeRefundChargeType(loanTransaction.getChargeRefundChargeType());
|
||||
}
|
||||
|
||||
if (loanTransaction.getPaymentDetail() != null) {
|
||||
transactionDTO.setPaymentTypeId(loanTransaction.getPaymentDetail().getPaymentType().getId());
|
||||
}
|
||||
|
||||
// Populate loanChargesPaid from the transaction
|
||||
if (!loanTransaction.getLoanChargesPaid().isEmpty()) {
|
||||
List<LoanChargePaidByDTO> loanChargesPaidData = new ArrayList<>();
|
||||
for (final LoanChargePaidBy chargePaidBy : loanTransaction.getLoanChargesPaid()) {
|
||||
final LoanChargePaidByDTO loanChargePaidData = new LoanChargePaidByDTO();
|
||||
loanChargePaidData.setChargeId(chargePaidBy.getLoanCharge().getCharge().getId());
|
||||
loanChargePaidData.setIsPenalty(chargePaidBy.getLoanCharge().isPenaltyCharge());
|
||||
loanChargePaidData.setLoanChargeId(chargePaidBy.getLoanCharge().getId());
|
||||
loanChargePaidData.setAmount(chargePaidBy.getAmount());
|
||||
loanChargePaidData.setInstallmentNumber(chargePaidBy.getInstallmentNumber());
|
||||
|
||||
loanChargesPaidData.add(loanChargePaidData);
|
||||
}
|
||||
transactionDTO.setLoanChargesPaid(loanChargesPaidData);
|
||||
}
|
||||
|
||||
// Handle chargeback principalPaid/feePaid/penaltyPaid
|
||||
if (transactionDTO.getType().isChargeback() && loanTransaction.getOverPaymentPortion() != null
|
||||
&& loanTransaction.getOverPaymentPortion().compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal principalPaid = loanTransaction.getOverPaymentPortion();
|
||||
BigDecimal feePaid = BigDecimal.ZERO;
|
||||
BigDecimal penaltyPaid = BigDecimal.ZERO;
|
||||
if (!loanTransaction.getLoanTransactionToRepaymentScheduleMappings().isEmpty()) {
|
||||
principalPaid = loanTransaction.getLoanTransactionToRepaymentScheduleMappings().stream()
|
||||
.map(mapping -> Optional.ofNullable(mapping.getPrincipalPortion()).orElse(BigDecimal.ZERO))
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
feePaid = loanTransaction.getLoanTransactionToRepaymentScheduleMappings().stream()
|
||||
.map(mapping -> Optional.ofNullable(mapping.getFeeChargesPortion()).orElse(BigDecimal.ZERO))
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
penaltyPaid = loanTransaction.getLoanTransactionToRepaymentScheduleMappings().stream()
|
||||
.map(mapping -> Optional.ofNullable(mapping.getPenaltyChargesPortion()).orElse(BigDecimal.ZERO))
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
transactionDTO.setPrincipalPaid(principalPaid);
|
||||
transactionDTO.setFeePaid(feePaid);
|
||||
transactionDTO.setPenaltyPaid(penaltyPaid);
|
||||
}
|
||||
|
||||
// Populate loanChargeData for CHARGE_ADJUSTMENT transactions
|
||||
LoanTransactionRelation loanTransactionRelation = loanTransaction.getLoanTransactionRelations().stream()
|
||||
.filter(e -> LoanTransactionRelationTypeEnum.CHARGE_ADJUSTMENT.equals(e.getRelationType())).findAny().orElse(null);
|
||||
if (loanTransactionRelation != null) {
|
||||
LoanCharge loanCharge = loanTransactionRelation.getToCharge();
|
||||
transactionDTO.setLoanChargeData(loanCharge.toData());
|
||||
}
|
||||
|
||||
// Set loanToLoanTransfer
|
||||
transactionDTO.setLoanToLoanTransfer(false);
|
||||
|
||||
return transactionDTO;
|
||||
}
|
||||
|
||||
private static class OfficeCurrencyKey {
|
||||
|
||||
final Office office;
|
||||
|
||||
+27
-104
@@ -31,7 +31,6 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
@@ -88,26 +87,24 @@ import org.apache.fineract.portfolio.delinquency.service.DelinquencyWritePlatfor
|
||||
import org.apache.fineract.portfolio.delinquency.validator.LoanDelinquencyActionData;
|
||||
import org.apache.fineract.portfolio.group.domain.Group;
|
||||
import org.apache.fineract.portfolio.group.exception.GroupNotActiveException;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccountingBridgeDataDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanRefundRequestData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanScheduleDelinquencyData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanAccountingBridgeMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanDownPaymentTransactionValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanForeclosureValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanTransactionValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.InterestRefundService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.InterestRefundServiceDelegate;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualTransactionBusinessEventService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualsProcessingService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanBalanceService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanChargeService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanDownPaymentHandlerService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanJournalEntryPoster;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanRefundService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanScheduleService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionProcessingService;
|
||||
@@ -135,7 +132,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final HolidayRepository holidayRepository;
|
||||
private final WorkingDaysRepositoryWrapper workingDaysRepository;
|
||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||
private final NoteRepository noteRepository;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final LoanUtilService loanUtilService;
|
||||
@@ -145,7 +141,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
private final DelinquencyWritePlatformService delinquencyWritePlatformService;
|
||||
private final LoanLifecycleStateMachine loanLifecycleStateMachine;
|
||||
private final ExternalIdFactory externalIdFactory;
|
||||
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
||||
private final DelinquencyEffectivePauseHelper delinquencyEffectivePauseHelper;
|
||||
private final DelinquencyReadPlatformService delinquencyReadPlatformService;
|
||||
private final LoanAccrualsProcessingService loanAccrualsProcessingService;
|
||||
@@ -160,11 +155,11 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
private final LoanRefundService loanRefundService;
|
||||
private final LoanAccountService loanAccountService;
|
||||
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||
private final LoanAccountingBridgeMapper loanAccountingBridgeMapper;
|
||||
private final LoanTransactionProcessingService loanTransactionProcessingService;
|
||||
private final LoanBalanceService loanBalanceService;
|
||||
private final LoanTransactionService loanTransactionService;
|
||||
private final LoanAccountDomainServiceJpaHelper loanAccountDomainServiceJpaHelper;
|
||||
private final LoanJournalEntryPoster journalEntryPoster;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
@@ -235,9 +230,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
* .validateRepaymentDateWithMeetingDate(transactionDate, calendarInstance); }
|
||||
*/
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
final Money repaymentAmount = Money.of(loan.getCurrency(), transactionAmount);
|
||||
LoanTransaction newRepaymentTransaction;
|
||||
if (isRecoveryRepayment) {
|
||||
@@ -273,11 +265,11 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
loanDownPaymentTransactionValidator.validateRepaymentTypeAccountStatus(loan, newRepaymentTransaction, event);
|
||||
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, event,
|
||||
newRepaymentTransaction.getTransactionDate());
|
||||
makeRepayment(loan, newRepaymentTransaction, existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO);
|
||||
makeRepayment(loan, newRepaymentTransaction, scheduleGeneratorDTO);
|
||||
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
|
||||
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newRepaymentTransaction);
|
||||
@@ -289,12 +281,11 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
}
|
||||
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
true);
|
||||
|
||||
setLoanDelinquencyTag(loan, transactionDate);
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, isLoanToLoanTransfer);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(newRepaymentTransaction, isAccountTransfer, isLoanToLoanTransfer);
|
||||
if (!repaymentTransactionType.isChargeRefund()) {
|
||||
final LoanTransactionBusinessEvent transactionRepaymentEvent = getTransactionRepaymentTypeBusinessEvent(
|
||||
repaymentTransactionType, isRecoveryRepayment, newRepaymentTransaction);
|
||||
@@ -393,7 +384,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
public LoanTransaction makeChargePayment(final Loan loan, final Long chargeId, final LocalDate transactionDate,
|
||||
final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final String noteText, final ExternalId txnExternalId,
|
||||
final Integer transactionType, Integer installmentNumber) {
|
||||
boolean isAccountTransfer = true;
|
||||
checkClientOrGroupActive(loan);
|
||||
if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.transaction.date.cannot.be.earlier.than.charge.off.date", "Loan: "
|
||||
@@ -403,9 +393,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
}
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanChargePaymentPreBusinessEvent(loan));
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
final Money paymentAmout = Money.of(loan.getCurrency(), transactionAmount);
|
||||
final LoanTransactionType loanTransactionType = LoanTransactionType.fromInt(transactionType);
|
||||
|
||||
@@ -413,7 +400,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
transactionDate, txnExternalId, loanTransactionType);
|
||||
|
||||
if (loanTransactionType.isRepaymentAtDisbursement()) {
|
||||
handlePayDisbursementTransaction(loan, chargeId, newPaymentTransaction, existingTransactionIds, existingReversedTransactionIds);
|
||||
handlePayDisbursementTransaction(loan, chargeId, newPaymentTransaction);
|
||||
} else {
|
||||
final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled();
|
||||
final List<Holiday> holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), transactionDate,
|
||||
@@ -433,8 +420,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
LoanEvent.LOAN_CHARGE_PAYMENT);
|
||||
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, LoanEvent.LOAN_CHARGE_PAYMENT,
|
||||
newPaymentTransaction.getTransactionDate());
|
||||
loanChargeService.makeChargePayment(loan, chargeId, existingTransactionIds, existingReversedTransactionIds,
|
||||
newPaymentTransaction, installmentNumber);
|
||||
loanChargeService.makeChargePayment(loan, chargeId, newPaymentTransaction, installmentNumber);
|
||||
}
|
||||
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newPaymentTransaction);
|
||||
loanAccountService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
@@ -445,19 +431,15 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
}
|
||||
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
true);
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(newPaymentTransaction, true, false);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanChargePaymentPostBusinessEvent(newPaymentTransaction));
|
||||
return newPaymentTransaction;
|
||||
}
|
||||
|
||||
private void handlePayDisbursementTransaction(final Loan loan, final Long chargeId, final LoanTransaction chargesPayment,
|
||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
private void handlePayDisbursementTransaction(final Loan loan, final Long chargeId, final LoanTransaction chargesPayment) {
|
||||
LoanCharge charge = null;
|
||||
for (final LoanCharge loanCharge : loan.getCharges()) {
|
||||
if (loanCharge.isActive() && chargeId.equals(loanCharge.getId())) {
|
||||
@@ -474,38 +456,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
charge.markAsFullyPaid();
|
||||
}
|
||||
|
||||
private void postJournalEntries(final Loan loanAccount, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, boolean isAccountTransfer) {
|
||||
postJournalEntries(loanAccount, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, false);
|
||||
}
|
||||
|
||||
private void postJournalEntries(final Loan loanAccount, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, boolean isAccountTransfer, boolean isLoanToLoanTransfer) {
|
||||
|
||||
final MonetaryCurrency currency = loanAccount.getCurrency();
|
||||
|
||||
if (loanAccount.isChargedOff()) {
|
||||
final List<AccountingBridgeDataDTO> accountingBridgeDataList = loanAccountingBridgeMapper
|
||||
.deriveAccountingBridgeDataForChargeOff(currency.getCode(), existingTransactionIds, existingReversedTransactionIds,
|
||||
isAccountTransfer, loanAccount);
|
||||
if (isLoanToLoanTransfer) {
|
||||
accountingBridgeDataList.forEach(dto -> dto.getNewLoanTransactions().forEach(tx -> tx.setLoanToLoanTransfer(true)));
|
||||
}
|
||||
|
||||
for (AccountingBridgeDataDTO accountingBridgeData : accountingBridgeDataList) {
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
} else {
|
||||
final AccountingBridgeDataDTO accountingBridgeData = loanAccountingBridgeMapper.deriveAccountingBridgeData(currency.getCode(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, loanAccount);
|
||||
if (isLoanToLoanTransfer) {
|
||||
accountingBridgeData.getNewLoanTransactions().forEach(tx -> tx.setLoanToLoanTransfer(true));
|
||||
}
|
||||
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkClientOrGroupActive(final Loan loan) {
|
||||
final Client client = loan.client();
|
||||
if (client != null) {
|
||||
@@ -525,7 +475,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
public LoanTransaction makeRefund(final Long accountId, final CommandProcessingResultBuilder builderResult,
|
||||
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final String noteText,
|
||||
final ExternalId txnExternalId) {
|
||||
boolean isAccountTransfer = true;
|
||||
final Loan loan = this.loanAccountAssembler.assembleFrom(accountId);
|
||||
checkClientOrGroupActive(loan);
|
||||
if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) {
|
||||
@@ -535,8 +484,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
loan.getId());
|
||||
}
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanRefundPreBusinessEvent(loan));
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
final Money refundAmount = Money.of(loan.getCurrency(), transactionAmount);
|
||||
final LoanTransaction newRefundTransaction = LoanTransaction.refund(loan.getOffice(), refundAmount, paymentDetail, transactionDate,
|
||||
@@ -552,7 +499,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
loanTransactionValidator.validateRepaymentDateIsOnNonWorkingDay(newRefundTransaction.getTransactionDate(), workingDays,
|
||||
allowTransactionsOnNonWorkingDay);
|
||||
|
||||
loanRefundService.makeRefund(loan, newRefundTransaction, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanRefundService.makeRefund(loan, newRefundTransaction);
|
||||
|
||||
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newRefundTransaction);
|
||||
this.loanRepositoryWrapper.saveAndFlush(loan);
|
||||
@@ -562,8 +509,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(newRefundTransaction, true, false);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanRefundPostBusinessEvent(newRefundTransaction));
|
||||
builderResult.withEntityId(newRefundTransaction.getId()).withOfficeId(loan.getOfficeId()).withClientId(loan.getClientId())
|
||||
@@ -591,9 +537,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
+ " backdated transaction is not allowed. Transaction date cannot be earlier than the charge-off date of the loan",
|
||||
loan.getId());
|
||||
}
|
||||
boolean isAccountTransfer = true;
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
final Money amount = Money.of(loan.getCurrency(), transactionAmount);
|
||||
LoanTransaction disbursementTransaction = LoanTransaction.disbursement(loan, amount, paymentDetail, transactionDate, txnExternalId,
|
||||
loan.getTotalOverpaidAsMoney());
|
||||
@@ -611,7 +554,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, isLoanToLoanTransfer);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(disbursementTransaction, true, isLoanToLoanTransfer);
|
||||
return disbursementTransaction;
|
||||
}
|
||||
|
||||
@@ -676,8 +619,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
}
|
||||
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanCreditBalanceRefundPreBusinessEvent(loan));
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
final Money refundAmount = Money.of(loan.getCurrency(), transactionAmount);
|
||||
LoanTransaction newCreditBalanceRefundTransaction = LoanTransaction.creditBalanceRefund(loan, loan.getOffice(), refundAmount,
|
||||
@@ -686,8 +627,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.LOAN_CREDIT_BALANCE_REFUND);
|
||||
loanTransactionValidator.validateRefundDateIsAfterLastRepayment(loan, newCreditBalanceRefundTransaction.getTransactionDate());
|
||||
|
||||
loanRefundService.creditBalanceRefund(loan, newCreditBalanceRefundTransaction, existingTransactionIds,
|
||||
existingReversedTransactionIds);
|
||||
loanRefundService.creditBalanceRefund(loan, newCreditBalanceRefundTransaction);
|
||||
|
||||
newCreditBalanceRefundTransaction = this.loanTransactionRepository.saveAndFlush(newCreditBalanceRefundTransaction);
|
||||
|
||||
@@ -697,10 +637,9 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
}
|
||||
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
true);
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, false);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(newCreditBalanceRefundTransaction, false, false);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService
|
||||
.notifyPostBusinessEvent(new LoanCreditBalanceRefundPostBusinessEvent(newCreditBalanceRefundTransaction));
|
||||
@@ -714,8 +653,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
final Loan loan = this.loanAccountAssembler.assembleFrom(accountId);
|
||||
checkClientOrGroupActive(loan);
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanRefundPreBusinessEvent(loan));
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
final Money refundAmount = Money.of(loan.getCurrency(), transactionAmount);
|
||||
if (loan.isChargedOff() && DateUtils.isBefore(transactionDate, loan.getChargedOffOnDate())) {
|
||||
@@ -740,7 +677,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
allowTransactionsOnNonWorkingDay);
|
||||
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, LoanEvent.LOAN_REFUND,
|
||||
newRefundTransaction.getTransactionDate());
|
||||
loanRefundService.makeRefundForActiveLoan(loan, newRefundTransaction, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanRefundService.makeRefundForActiveLoan(loan, newRefundTransaction);
|
||||
|
||||
this.loanTransactionRepository.saveAndFlush(newRefundTransaction);
|
||||
|
||||
@@ -750,10 +687,9 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
}
|
||||
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
true);
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, false);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(newRefundTransaction, false, false);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanRefundPostBusinessEvent(newRefundTransaction));
|
||||
|
||||
@@ -777,10 +713,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
MonetaryCurrency currency = loan.getCurrency();
|
||||
List<LoanTransaction> newTransactions = new ArrayList<>();
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = null;
|
||||
final LoanRepaymentScheduleInstallment foreCloseDetail = loanBalanceService.fetchLoanForeclosureDetail(loan, foreClosureDate);
|
||||
|
||||
@@ -809,14 +741,15 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.LOAN_FORECLOSURE);
|
||||
handleForeClosureTransactions(loan, payment, scheduleGeneratorDTO);
|
||||
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
|
||||
for (LoanTransaction newTransaction : newTransactions) {
|
||||
LoanTransaction savedNewTransaction = loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newTransaction);
|
||||
loan.addLoanTransaction(savedNewTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(newTransaction, false, false);
|
||||
transactionIds.add(savedNewTransaction.getId());
|
||||
}
|
||||
changes.put("transactions", transactionIds);
|
||||
@@ -830,8 +763,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, false);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanForeClosurePostBusinessEvent(payment));
|
||||
return payment;
|
||||
@@ -1002,18 +933,13 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
final LocalDate transactionDate = DateUtils.getBusinessLocalDate();
|
||||
final BigDecimal refundAmount = loanRefundRequest.getTotalAmount();
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
final LoanTransaction interestRefundTransaction = LoanTransaction.interestRefund(loan, loan.getOffice(), refundAmount,
|
||||
loanRefundRequest.getPrincipal(), loanRefundRequest.getInterest(), loanRefundRequest.getFeeCharges(),
|
||||
loanRefundRequest.getPenaltyCharges(), paymentDetail, transactionDate, externalIdFactory.create());
|
||||
interestRefundTransaction.updateLoan(loan);
|
||||
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(interestRefundTransaction);
|
||||
loan.addLoanTransaction(interestRefundTransaction);
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, false);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(interestRefundTransaction, false, false);
|
||||
|
||||
return interestRefundTransaction;
|
||||
}
|
||||
@@ -1089,12 +1015,9 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
private void makeRepayment(final Loan loan, final LoanTransaction repaymentTransaction, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
private void makeRepayment(final Loan loan, final LoanTransaction repaymentTransaction,
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
loanChargeValidator.validateRepaymentTypeTransactionNotBeforeAChargeRefund(loan, repaymentTransaction, "created");
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
loanDownPaymentHandlerService.handleRepaymentOrRecoveryOrWaiverTransaction(loan, repaymentTransaction, null, scheduleGeneratorDTO);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -974,7 +974,7 @@ public class LoanScheduleAssembler {
|
||||
final LocalDate recalculateFrom = null;
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, false);
|
||||
|
||||
}
|
||||
|
||||
@@ -1553,7 +1553,7 @@ public class LoanScheduleAssembler {
|
||||
if (actualChanges.containsKey(LoanApiConstants.approvedLoanAmountParameterName)
|
||||
|| actualChanges.containsKey("recalculateLoanSchedule") || actualChanges.containsKey("expectedDisbursementDate")) {
|
||||
loanScheduleService.regenerateRepaymentSchedule(loan, loanUtilService.buildScheduleGeneratorDTO(loan, null));
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ public class LoanScheduleWritePlatformServiceImpl implements LoanScheduleWritePl
|
||||
final LocalDate recalculateFrom = null;
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, false);
|
||||
loanAccountService.saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanScheduleVariationsDeletedBusinessEvent(loan));
|
||||
return new CommandProcessingResultBuilder() //
|
||||
|
||||
+2
-23
@@ -32,7 +32,6 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
|
||||
import org.apache.fineract.infrastructure.codes.domain.CodeValueRepositoryWrapper;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
@@ -47,9 +46,7 @@ import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBalance
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanRescheduledDueAdjustScheduleBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccountingBridgeDataDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
@@ -72,14 +69,12 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanRepayme
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleHistoryWritePlatformService;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanAccountingBridgeMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanTermVariationsMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.RescheduleLoansApiConstants;
|
||||
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.data.LoanRescheduleRequestDataValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest;
|
||||
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequestRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.exception.LoanRescheduleRequestNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualTransactionBusinessEventService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualsProcessingService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanChargeService;
|
||||
@@ -108,20 +103,17 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
||||
private final LoanRescheduleRequestRepository loanRescheduleRequestRepository;
|
||||
private final LoanRepaymentScheduleHistoryRepository loanRepaymentScheduleHistoryRepository;
|
||||
private final LoanScheduleHistoryWritePlatformService loanScheduleHistoryWritePlatformService;
|
||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
||||
private final LoanAssembler loanAssembler;
|
||||
private final LoanUtilService loanUtilService;
|
||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||
private final LoanScheduleGeneratorFactory loanScheduleFactory;
|
||||
private final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository;
|
||||
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final LoanAccrualsProcessingService loanAccrualsProcessingService;
|
||||
private final LoanChargeService loanChargeService;
|
||||
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||
private final LoanTermVariationsMapper loanTermVariationsMapper;
|
||||
private final LoanAccountingBridgeMapper loanAccountingBridgeMapper;
|
||||
private final LoanScheduleComponent loanSchedule;
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
private final LoanLifecycleStateMachine loanLifecycleStateMachine;
|
||||
@@ -355,9 +347,6 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
||||
changes.put("approvedByUserId", appUser.getId());
|
||||
|
||||
Loan loan = loanRescheduleRequest.getLoan();
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(
|
||||
loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan,
|
||||
loanRescheduleRequest.getRescheduleFromDate());
|
||||
@@ -442,7 +431,7 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
||||
} else {
|
||||
loanSchedule.updateLoanSchedule(loan, loanScheduleDTO.getLoanScheduleModel());
|
||||
}
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
loanChargeService.recalculateAllCharges(loan);
|
||||
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||
|
||||
@@ -460,11 +449,9 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
||||
}
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, true, false);
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, true, true);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanRescheduledDueAdjustScheduleBusinessEvent(loan));
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
if (hasInterestRateChange) {
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
}
|
||||
@@ -507,14 +494,6 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
||||
}
|
||||
}
|
||||
|
||||
private void postJournalEntries(Loan loan, List<Long> existingTransactionIds, List<Long> existingReversedTransactionIds) {
|
||||
final MonetaryCurrency currency = loan.getCurrency();
|
||||
boolean isAccountTransfer = false;
|
||||
final AccountingBridgeDataDTO accountingBridgeData = loanAccountingBridgeMapper.deriveAccountingBridgeData(currency.getCode(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, loan);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CommandProcessingResult reject(JsonCommand jsonCommand) {
|
||||
|
||||
+3
@@ -63,6 +63,7 @@ public class LoanAccrualActivityProcessingServiceImpl implements LoanAccrualActi
|
||||
private final LoanAccountService loanAccountService;
|
||||
private final LoanBalanceService loanBalanceService;
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
private final LoanJournalEntryPoster journalEntryPoster;
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@@ -245,6 +246,7 @@ public class LoanAccrualActivityProcessingServiceImpl implements LoanAccrualActi
|
||||
|
||||
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newLoanTransaction);
|
||||
loan.addLoanTransaction(newLoanTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(newLoanTransaction, false, false);
|
||||
|
||||
LoanAdjustTransactionBusinessEvent.Data data = new LoanAdjustTransactionBusinessEvent.Data(loanTransaction);
|
||||
data.setNewTransactionDetail(newLoanTransaction);
|
||||
@@ -277,6 +279,7 @@ public class LoanAccrualActivityProcessingServiceImpl implements LoanAccrualActi
|
||||
if (newAccrualActivityTransaction != null) {
|
||||
LoanTransaction savedNewTransaction = makeAccrualActivityTransaction(loan, newAccrualActivityTransaction);
|
||||
loan.addLoanTransaction(savedNewTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(savedNewTransaction, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ public class LoanAccrualEventService {
|
||||
LoanStatus status = loan.getStatus();
|
||||
if (status.isClosedObligationsMet() || status.isOverpaid()) {
|
||||
log.debug("Loan closure on accrual for loan {}", loan.getId());
|
||||
loanAccrualsProcessingService.processAccrualsOnLoanClosure(loan, false);
|
||||
loanAccrualsProcessingService.processAccrualsOnLoanClosure(loan, true);
|
||||
loanAccrualActivityProcessingService.processAccrualActivityForLoanClosure(loan);
|
||||
}
|
||||
}
|
||||
|
||||
+86
-59
@@ -45,7 +45,6 @@ import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.config.TaskExecutorConstant;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
@@ -55,7 +54,6 @@ import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanAdjustTransactionBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanAccrualAdjustmentTransactionBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanAccrualTransactionCreatedBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionBusinessEvent;
|
||||
@@ -63,8 +61,6 @@ import org.apache.fineract.infrastructure.event.business.service.BusinessEventNo
|
||||
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccountingBridgeDataDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccountingBridgeLoanTransactionDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccrualBalances;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccrualChargeData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccrualPeriodData;
|
||||
@@ -88,7 +84,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanAccountingBridgeMapper;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.InterestRecalculationCompoundingMethod;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
@@ -110,18 +105,16 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
||||
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
private final LoanScheduleGeneratorFactory loanScheduleFactory;
|
||||
|
||||
@Qualifier(TaskExecutorConstant.CONFIGURABLE_TASK_EXECUTOR_BEAN_NAME)
|
||||
private final ThreadPoolTaskExecutor taskExecutor;
|
||||
private final TransactionTemplate transactionTemplate;
|
||||
private final LoanAccountingBridgeMapper loanAccountingBridgeMapper;
|
||||
private final LoanChargeService loanChargeService;
|
||||
private final LoanBalanceService loanBalanceService;
|
||||
private final LoanChargePaidByRepository loanChargePaidByRepository;
|
||||
private final LoanJournalEntryPoster journalEntryPoster;
|
||||
|
||||
/**
|
||||
* method adds accrual for batch job "Add Periodic Accrual Transactions" and add accruals api for Loan
|
||||
@@ -210,13 +203,13 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
* reschedule
|
||||
*/
|
||||
@Override
|
||||
public void reprocessExistingAccruals(@NotNull Loan loan) {
|
||||
public void reprocessExistingAccruals(@NotNull final Loan loan, final boolean addEvent) {
|
||||
List<LoanTransaction> accrualTransactions = retrieveListOfAccrualTransactions(loan);
|
||||
if (!accrualTransactions.isEmpty()) {
|
||||
if (loan.isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
|
||||
reprocessPeriodicAccruals(loan, accrualTransactions);
|
||||
reprocessPeriodicAccruals(loan, accrualTransactions, addEvent);
|
||||
} else if (loan.isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
|
||||
reprocessNonPeriodicAccruals(loan, accrualTransactions);
|
||||
reprocessNonPeriodicAccruals(loan, accrualTransactions, addEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -253,40 +246,37 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
if (isProgressiveAccrual(loan)) {
|
||||
return;
|
||||
}
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
processIncomePostingAndAccruals(loan);
|
||||
processIncomePostingAndAccruals(loan, true);
|
||||
this.loanRepositoryWrapper.saveAndFlush(loan);
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* method calculates accruals for loan with interest recalculation and compounding to be posted as income
|
||||
*/
|
||||
@Override
|
||||
public void processIncomePostingAndAccruals(@NotNull Loan loan) {
|
||||
public void processIncomePostingAndAccruals(@NotNull final Loan loan, final boolean addEvent) {
|
||||
if (isProgressiveAccrual(loan)) {
|
||||
return;
|
||||
}
|
||||
LoanInterestRecalculationDetails recalculationDetails = loan.getLoanInterestRecalculationDetails();
|
||||
final LoanInterestRecalculationDetails recalculationDetails = loan.getLoanInterestRecalculationDetails();
|
||||
if (recalculationDetails == null || !recalculationDetails.isCompoundingToBePostedAsTransaction()) {
|
||||
return;
|
||||
}
|
||||
LocalDate lastCompoundingDate = loan.getDisbursementDate();
|
||||
List<LoanInterestRecalcualtionAdditionalDetails> compoundingDetails = extractInterestRecalculationAdditionalDetails(loan);
|
||||
final List<LoanInterestRecalcualtionAdditionalDetails> compoundingDetails = extractInterestRecalculationAdditionalDetails(loan);
|
||||
for (LoanInterestRecalcualtionAdditionalDetails compoundingDetail : compoundingDetails) {
|
||||
if (!DateUtils.isBeforeBusinessDate(compoundingDetail.getEffectiveDate())) {
|
||||
break;
|
||||
}
|
||||
|
||||
addUpdateIncomeAndAccrualTransaction(loan, compoundingDetail, lastCompoundingDate);
|
||||
addUpdateIncomeAndAccrualTransaction(loan, compoundingDetail, lastCompoundingDate, addEvent);
|
||||
lastCompoundingDate = compoundingDetail.getEffectiveDate();
|
||||
}
|
||||
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||
LoanRepaymentScheduleInstallment lastInstallment = LoanRepaymentScheduleInstallment.getLastNonDownPaymentInstallment(installments);
|
||||
final List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||
final LoanRepaymentScheduleInstallment lastInstallment = LoanRepaymentScheduleInstallment
|
||||
.getLastNonDownPaymentInstallment(installments);
|
||||
|
||||
reverseTransactionsAfter(loan, Set.of(ACCRUAL, ACCRUAL_ADJUSTMENT, INCOME_POSTING), lastInstallment.getDueDate(), false);
|
||||
reverseTransactionsAfter(loan, Set.of(ACCRUAL, ACCRUAL_ADJUSTMENT, INCOME_POSTING), lastInstallment.getDueDate(), addEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -431,22 +421,14 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
loanTransactionRepository.flush();
|
||||
|
||||
if (addJournal) {
|
||||
final List<AccountingBridgeLoanTransactionDTO> newTransactionDTOs = new ArrayList<>();
|
||||
for (LoanTransaction accrualTransaction : accrualTransactions) {
|
||||
final LoanTransactionBusinessEvent businessEvent = accrualTransaction.isAccrual()
|
||||
? new LoanAccrualTransactionCreatedBusinessEvent(accrualTransaction)
|
||||
: new LoanAccrualAdjustmentTransactionBusinessEvent(accrualTransaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(businessEvent);
|
||||
final AccountingBridgeLoanTransactionDTO transactionDTO = loanAccountingBridgeMapper
|
||||
.mapToLoanTransactionData(accrualTransaction, currency.getCode());
|
||||
newTransactionDTOs.add(transactionDTO);
|
||||
// Create journal entries immediately for this transaction
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(accrualTransaction, false, false);
|
||||
}
|
||||
final AccountingBridgeDataDTO accountingBridgeData = new AccountingBridgeDataDTO(loan.getId(), loan.getLoanProduct().getId(),
|
||||
loan.getOfficeId(), loan.getCurrencyCode(), loan.getSummary().getTotalInterestCharged(),
|
||||
loan.isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct(),
|
||||
loan.isUpfrontAccrualAccountingEnabledOnLoanProduct(), loan.isPeriodicAccrualAccountingEnabledOnLoanProduct(), false,
|
||||
false, false, null, false, newTransactionDTOs, loan.getLoanProductRelatedDetail().isMerchantBuyDownFee());
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -749,7 +731,7 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
|
||||
// ReprocessAccruals
|
||||
|
||||
private void reprocessPeriodicAccruals(Loan loan, final List<LoanTransaction> accrualTransactions) {
|
||||
private void reprocessPeriodicAccruals(Loan loan, final List<LoanTransaction> accrualTransactions, final boolean addEvent) {
|
||||
if (loan.isChargedOff()) {
|
||||
return;
|
||||
}
|
||||
@@ -809,14 +791,15 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||
boolean isBasedOnSubmittedOnDate = !isChargeOnDueDate;
|
||||
for (LoanRepaymentScheduleInstallment installment : installments) {
|
||||
checkAndUpdateAccrualsForInstallment(loan, accrualTransactions, installments, isBasedOnSubmittedOnDate, installment);
|
||||
checkAndUpdateAccrualsForInstallment(loan, accrualTransactions, installments, isBasedOnSubmittedOnDate, installment,
|
||||
addEvent);
|
||||
}
|
||||
}
|
||||
// reverse accruals after last installment
|
||||
reverseTransactionsAfter(loan, ACCRUAL_TYPES, lastDueDate, false);
|
||||
reverseTransactionsAfter(loan, ACCRUAL_TYPES, lastDueDate, addEvent);
|
||||
}
|
||||
|
||||
private void reprocessNonPeriodicAccruals(Loan loan, final List<LoanTransaction> accrualTransactions) {
|
||||
private void reprocessNonPeriodicAccruals(Loan loan, final List<LoanTransaction> accrualTransactions, final boolean addEvent) {
|
||||
if (isProgressiveAccrual(loan)) {
|
||||
return;
|
||||
}
|
||||
@@ -828,6 +811,12 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
if (accrualTransaction.getInterestPortion(loan.getCurrency()).isGreaterThanZero()) {
|
||||
if (accrualTransaction.getInterestPortion(loan.getCurrency()).isNotEqualTo(interestApplied)) {
|
||||
accrualTransaction.reverse();
|
||||
if (addEvent) {
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(accrualTransaction, false, false);
|
||||
final LoanTransactionBusinessEvent businessEvent = new LoanAccrualAdjustmentTransactionBusinessEvent(
|
||||
accrualTransaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(businessEvent);
|
||||
}
|
||||
if (isExternalIdAutoGenerationEnabled) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
@@ -835,6 +824,12 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
interestApplied, loan.getDisbursementDate(), externalId);
|
||||
LoanTransaction savedInterestAccrualTransaction = loanTransactionRepository.save(interestAccrualTransaction);
|
||||
loan.addLoanTransaction(savedInterestAccrualTransaction);
|
||||
if (addEvent) {
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(savedInterestAccrualTransaction, false, false);
|
||||
final LoanTransactionBusinessEvent businessEvent = new LoanAccrualTransactionCreatedBusinessEvent(
|
||||
savedInterestAccrualTransaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(businessEvent);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Set<LoanChargePaidBy> chargePaidBies = accrualTransaction.getLoanChargesPaid();
|
||||
@@ -843,7 +838,23 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
Money chargeAmount = loanCharge.getAmount(loan.getCurrency());
|
||||
if (chargeAmount.isNotEqualTo(accrualTransaction.getAmount(loan.getCurrency()))) {
|
||||
accrualTransaction.reverse();
|
||||
loanChargeService.handleChargeAppliedTransaction(loan, loanCharge, accrualTransaction.getTransactionDate());
|
||||
if (addEvent) {
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(accrualTransaction, false, false);
|
||||
final LoanTransactionBusinessEvent businessEvent = new LoanAccrualAdjustmentTransactionBusinessEvent(
|
||||
accrualTransaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(businessEvent);
|
||||
}
|
||||
final LoanTransaction applyLoanChargeTransaction = loanChargeService.handleChargeAppliedTransaction(loan,
|
||||
loanCharge, accrualTransaction.getTransactionDate());
|
||||
if (applyLoanChargeTransaction != null) {
|
||||
LoanTransaction savedApplyLoanChargeTransaction = loanTransactionRepository.save(applyLoanChargeTransaction);
|
||||
if (addEvent) {
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(savedApplyLoanChargeTransaction, false, false);
|
||||
final LoanTransactionBusinessEvent businessEvent = new LoanAccrualTransactionCreatedBusinessEvent(
|
||||
savedApplyLoanChargeTransaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(businessEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -852,7 +863,7 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
|
||||
private void checkAndUpdateAccrualsForInstallment(Loan loan, List<LoanTransaction> accrualTransactions,
|
||||
List<LoanRepaymentScheduleInstallment> installments, boolean isBasedOnSubmittedOnDate,
|
||||
LoanRepaymentScheduleInstallment installment) {
|
||||
LoanRepaymentScheduleInstallment installment, final boolean addEvent) {
|
||||
MonetaryCurrency currency = loan.getCurrency();
|
||||
Money zero = Money.zero(currency);
|
||||
Money interest = zero;
|
||||
@@ -870,6 +881,12 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
fee = fee.minus(accrualTransaction.getFeeChargesPortion(currency));
|
||||
penalty = penalty.minus(accrualTransaction.getPenaltyChargesPortion(currency));
|
||||
accrualTransaction.reverse();
|
||||
if (addEvent) {
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(accrualTransaction, false, false);
|
||||
final LoanTransactionBusinessEvent businessEvent = new LoanAccrualAdjustmentTransactionBusinessEvent(
|
||||
accrualTransaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(businessEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -910,7 +927,7 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
}
|
||||
|
||||
private void addUpdateIncomeAndAccrualTransaction(Loan loan, LoanInterestRecalcualtionAdditionalDetails compoundingDetail,
|
||||
LocalDate lastCompoundingDate) {
|
||||
LocalDate lastCompoundingDate, boolean addEvent) {
|
||||
BigDecimal interest = BigDecimal.ZERO;
|
||||
BigDecimal fee = BigDecimal.ZERO;
|
||||
BigDecimal penalties = BigDecimal.ZERO;
|
||||
@@ -938,7 +955,7 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
}
|
||||
|
||||
createUpdateIncomePostingTransaction(loan, compoundingDetail, interest, fee, penalties, externalId);
|
||||
createUpdateAccrualTransaction(loan, compoundingDetail, interest, fee, penalties, feeDetails, externalId);
|
||||
createUpdateAccrualTransaction(loan, compoundingDetail, interest, fee, penalties, feeDetails, externalId, addEvent);
|
||||
loanBalanceService.updateLoanOutstandingBalances(loan);
|
||||
}
|
||||
|
||||
@@ -947,21 +964,25 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
final Optional<LoanTransaction> incomeTransaction = loanTransactionRepository.findNonReversedByLoanAndTypesAndDate(loan,
|
||||
Set.of(INCOME_POSTING), compoundingDetail.getEffectiveDate());
|
||||
if (incomeTransaction.isEmpty()) {
|
||||
LoanTransaction transaction = LoanTransaction.incomePosting(loan, loan.getOffice(), compoundingDetail.getEffectiveDate(),
|
||||
final LoanTransaction transaction = LoanTransaction.incomePosting(loan, loan.getOffice(), compoundingDetail.getEffectiveDate(),
|
||||
compoundingDetail.getAmount(), interest, fee, penalties, externalId);
|
||||
LoanTransaction savedTransaction = loanTransactionRepository.save(transaction);
|
||||
final LoanTransaction savedTransaction = loanTransactionRepository.save(transaction);
|
||||
loan.addLoanTransaction(savedTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(savedTransaction, false, false);
|
||||
} else if (incomeTransaction.get().getAmount(loan.getCurrency()).getAmount().compareTo(compoundingDetail.getAmount()) != 0) {
|
||||
incomeTransaction.get().reverse();
|
||||
LoanTransaction transaction = LoanTransaction.incomePosting(loan, loan.getOffice(), compoundingDetail.getEffectiveDate(),
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(incomeTransaction.get(), false, false);
|
||||
final LoanTransaction transaction = LoanTransaction.incomePosting(loan, loan.getOffice(), compoundingDetail.getEffectiveDate(),
|
||||
compoundingDetail.getAmount(), interest, fee, penalties, externalId);
|
||||
LoanTransaction savedTransaction = loanTransactionRepository.save(transaction);
|
||||
final LoanTransaction savedTransaction = loanTransactionRepository.save(transaction);
|
||||
loan.addLoanTransaction(savedTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(savedTransaction, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void createUpdateAccrualTransaction(Loan loan, LoanInterestRecalcualtionAdditionalDetails compoundingDetail,
|
||||
BigDecimal interest, BigDecimal fee, BigDecimal penalties, HashMap<String, Object> feeDetails, ExternalId externalId) {
|
||||
BigDecimal interest, BigDecimal fee, BigDecimal penalties, HashMap<String, Object> feeDetails, ExternalId externalId,
|
||||
boolean addEvent) {
|
||||
if (configurationDomainService.isExternalIdAutoGenerationEnabled()) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
@@ -971,12 +992,24 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
Set.of(LoanTransactionType.ACCRUAL, LoanTransactionType.ACCRUAL_ADJUSTMENT), compoundingDetail.getEffectiveDate());
|
||||
|
||||
if (accrualTransaction.isEmpty() || !MathUtil.isEqualTo(accrualTransaction.get().getAmount(), compoundingDetail.getAmount())) {
|
||||
accrualTransaction.ifPresent(LoanTransaction::reverse);
|
||||
accrualTransaction.ifPresent(accrualTrans -> {
|
||||
accrualTrans.reverse();
|
||||
if (addEvent) {
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(accrualTrans, false, false);
|
||||
final LoanTransactionBusinessEvent businessEvent = new LoanAccrualAdjustmentTransactionBusinessEvent(accrualTrans);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(businessEvent);
|
||||
}
|
||||
});
|
||||
LoanTransaction accrual = LoanTransaction.accrueTransaction(loan, loan.getOffice(), compoundingDetail.getEffectiveDate(),
|
||||
compoundingDetail.getAmount(), interest, fee, penalties, externalId);
|
||||
updateLoanChargesPaidBy(loan, accrual, feeDetails, null);
|
||||
LoanTransaction savedAccrual = loanTransactionRepository.save(accrual);
|
||||
loan.addLoanTransaction(savedAccrual);
|
||||
if (addEvent) {
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(savedAccrual, false, false);
|
||||
final LoanTransactionBusinessEvent businessEvent = new LoanAccrualTransactionCreatedBusinessEvent(savedAccrual);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(businessEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1039,6 +1072,7 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
interestToPost, feeToPost, penaltyToPost, externalId);
|
||||
LoanTransaction savedFinalIncomeTransaction = loanTransactionRepository.save(finalIncomeTransaction);
|
||||
loan.addLoanTransaction(savedFinalIncomeTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(savedFinalIncomeTransaction, false, false);
|
||||
|
||||
if (loan.isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
|
||||
final LocalDate lastAccruedDate = loanTransactionRepository
|
||||
@@ -1055,6 +1089,7 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
updateLoanChargesPaidBy(loan, finalAccrual, feeDetails, null);
|
||||
LoanTransaction savedFinalAccrual = loanTransactionRepository.save(finalAccrual);
|
||||
loan.addLoanTransaction(savedFinalAccrual);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(savedFinalAccrual, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1120,15 +1155,6 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
}
|
||||
}
|
||||
|
||||
private void postJournalEntries(final Loan loan, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds) {
|
||||
final MonetaryCurrency currency = loan.getCurrency();
|
||||
boolean isAccountTransfer = false;
|
||||
final AccountingBridgeDataDTO accountingBridgeData = loanAccountingBridgeMapper.deriveAccountingBridgeData(currency.getCode(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, loan);
|
||||
journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
|
||||
private void ensureAccrualTransactionMappings(final Loan loan, final boolean chargeOnDueDate) {
|
||||
final List<LoanChargePaidBy> entriesToProcess = loanChargePaidByRepository.findChargePaidByMappingsWithoutInstallmentNumber(loan);
|
||||
|
||||
@@ -1234,14 +1260,15 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
|
||||
private void reverseTransactionsOnOrAfter(final Loan loan, final Set<LoanTransactionType> types, final LocalDate date) {
|
||||
loanTransactionRepository.findNonReversedByLoanAndTypesAndOnOrAfterDate(loan, types, date)
|
||||
.forEach(transaction -> reverseAccrual(transaction, false));
|
||||
.forEach(transaction -> reverseAccrual(transaction, true));
|
||||
}
|
||||
|
||||
private void reverseAccrual(final LoanTransaction transaction, final boolean addEvent) {
|
||||
transaction.reverse();
|
||||
if (addEvent) {
|
||||
final LoanAdjustTransactionBusinessEvent.Data data = new LoanAdjustTransactionBusinessEvent.Data(transaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAdjustTransactionBusinessEvent(data));
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(transaction, false, false);
|
||||
final LoanTransactionBusinessEvent businessEvent = new LoanAccrualAdjustmentTransactionBusinessEvent(transaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(businessEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -625,7 +625,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
LocalDate recalculateFrom = null;
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, false);
|
||||
}
|
||||
|
||||
loan.adjustNetDisbursalAmount(loan.getProposedPrincipal());
|
||||
|
||||
+2
-2
@@ -285,7 +285,7 @@ public class LoanAssemblerImpl implements LoanAssembler {
|
||||
// TODO: review
|
||||
loanChargeService.recalculateAllCharges(loanApplication);
|
||||
topUpLoanConfiguration(element, loanApplication);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loanApplication);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loanApplication, false);
|
||||
return loanApplication;
|
||||
}
|
||||
|
||||
@@ -851,7 +851,7 @@ public class LoanAssemblerImpl implements LoanAssembler {
|
||||
|
||||
final LoanScheduleModel loanScheduleModel = this.calculationPlatformService.calculateLoanSchedule(query, false);
|
||||
loanSchedule.updateLoanSchedule(loan, loanScheduleModel);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, false);
|
||||
loanChargeService.recalculateAllCharges(loan);
|
||||
}
|
||||
|
||||
|
||||
+6
-25
@@ -20,7 +20,6 @@ package org.apache.fineract.portfolio.loanaccount.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -59,9 +58,6 @@ public class LoanBuyDownFeeAmortizationProcessingServiceImpl implements LoanBuyD
|
||||
@Override
|
||||
@Transactional
|
||||
public void processBuyDownFeeAmortizationTillDate(@NonNull Loan loan, @NonNull LocalDate tillDate, boolean addJournal) {
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
|
||||
List<LoanBuyDownFeeBalance> balances = loanBuyDownFeeBalanceRepository.findAllByLoanId(loan.getId());
|
||||
|
||||
LocalDate maturityDate = loan.getMaturityDate() != null ? loan.getMaturityDate()
|
||||
@@ -99,7 +95,7 @@ public class LoanBuyDownFeeAmortizationProcessingServiceImpl implements LoanBuyD
|
||||
loanTransactionRepository.flush();
|
||||
|
||||
if (addJournal) {
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(transaction, false, false);
|
||||
}
|
||||
|
||||
BusinessEvent<?> event = MathUtil.isGreaterThanZero(totalAmortizationAmount)
|
||||
@@ -112,13 +108,6 @@ public class LoanBuyDownFeeAmortizationProcessingServiceImpl implements LoanBuyD
|
||||
@Override
|
||||
@Transactional
|
||||
public void processBuyDownFeeAmortizationOnLoanClosure(@NonNull final Loan loan, final boolean addJournal) {
|
||||
List<Long> existingTransactionIds = Collections.emptyList();
|
||||
List<Long> existingReversedTransactionIds = Collections.emptyList();
|
||||
if (addJournal) {
|
||||
existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
}
|
||||
|
||||
final LocalDate transactionDate = getFinalBuyDownFeeAmortizationTransactionDate(loan);
|
||||
final Optional<LoanTransaction> amortizationTransaction = createBuyDownFeeAmortizationTransaction(loan, transactionDate, false,
|
||||
null);
|
||||
@@ -130,20 +119,16 @@ public class LoanBuyDownFeeAmortizationProcessingServiceImpl implements LoanBuyD
|
||||
businessEventNotifierService
|
||||
.notifyPostBusinessEvent(new LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent(loanTransaction));
|
||||
}
|
||||
if (addJournal) {
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(amortizationTransaction.get(), false, false);
|
||||
}
|
||||
});
|
||||
|
||||
if (addJournal) {
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void processBuyDownFeeAmortizationOnLoanChargeOff(@NonNull final Loan loan,
|
||||
@NonNull final LoanTransaction chargeOffTransaction) {
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
|
||||
LocalDate transactionDate = loan.getChargedOffOnDate();
|
||||
if (transactionDate == null) {
|
||||
transactionDate = DateUtils.getBusinessLocalDate();
|
||||
@@ -152,7 +137,7 @@ public class LoanBuyDownFeeAmortizationProcessingServiceImpl implements LoanBuyD
|
||||
final Optional<LoanTransaction> amortizationTransaction = createBuyDownFeeAmortizationTransaction(loan, transactionDate, true,
|
||||
chargeOffTransaction);
|
||||
if (amortizationTransaction.isPresent()) {
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(amortizationTransaction.get(), false, false);
|
||||
if (amortizationTransaction.get().isBuyDownFeeAmortization()) {
|
||||
businessEventNotifierService.notifyPostBusinessEvent(
|
||||
new LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent(amortizationTransaction.get()));
|
||||
@@ -167,8 +152,6 @@ public class LoanBuyDownFeeAmortizationProcessingServiceImpl implements LoanBuyD
|
||||
@Transactional
|
||||
public void processBuyDownFeeAmortizationOnLoanUndoChargeOff(@NonNull final LoanTransaction loanTransaction) {
|
||||
final Loan loan = loanTransaction.getLoan();
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
|
||||
loan.getLoanTransactions().stream().filter(LoanTransaction::isBuyDownFeeAmortization)
|
||||
.filter(transaction -> transaction.getTransactionDate().equals(loanTransaction.getTransactionDate())
|
||||
@@ -177,17 +160,15 @@ public class LoanBuyDownFeeAmortizationProcessingServiceImpl implements LoanBuyD
|
||||
&& rel.getToTransaction().equals(loanTransaction)))
|
||||
.forEach(transaction -> {
|
||||
transaction.reverse();
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(transaction, false, false);
|
||||
final LoanAdjustTransactionBusinessEvent.Data data = new LoanAdjustTransactionBusinessEvent.Data(transaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAdjustTransactionBusinessEvent(data));
|
||||
|
||||
});
|
||||
|
||||
for (LoanBuyDownFeeBalance balance : loanBuyDownFeeBalanceRepository.findAllByLoanId(loan.getId())) {
|
||||
balance.setUnrecognizedAmount(balance.getChargedOffAmount());
|
||||
balance.setChargedOffAmount(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
}
|
||||
|
||||
private Optional<LoanTransaction> createBuyDownFeeAmortizationTransaction(final Loan loan, final LocalDate transactionDate,
|
||||
|
||||
+6
-25
@@ -20,7 +20,6 @@ package org.apache.fineract.portfolio.loanaccount.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -62,13 +61,6 @@ public class LoanCapitalizedIncomeAmortizationProcessingServiceImpl implements L
|
||||
@Override
|
||||
@Transactional
|
||||
public void processCapitalizedIncomeAmortizationOnLoanClosure(@NotNull final Loan loan, final boolean addJournal) {
|
||||
List<Long> existingTransactionIds = Collections.emptyList();
|
||||
List<Long> existingReversedTransactionIds = Collections.emptyList();
|
||||
if (addJournal) {
|
||||
existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
}
|
||||
|
||||
final LocalDate transactionDate = getFinalCapitalizedIncomeAmortizationTransactionDate(loan);
|
||||
final Optional<LoanTransaction> amortizationTransaction = createCapitalizedIncomeAmortizationTransaction(loan, transactionDate,
|
||||
false, null);
|
||||
@@ -80,20 +72,16 @@ public class LoanCapitalizedIncomeAmortizationProcessingServiceImpl implements L
|
||||
businessEventNotifierService.notifyPostBusinessEvent(
|
||||
new LoanCapitalizedIncomeAmortizationAdjustmentTransactionCreatedBusinessEvent(loanTransaction));
|
||||
}
|
||||
if (addJournal) {
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(amortizationTransaction.get(), false, false);
|
||||
}
|
||||
});
|
||||
|
||||
if (addJournal) {
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void processCapitalizedIncomeAmortizationOnLoanChargeOff(@NotNull final Loan loan,
|
||||
@NonNull final LoanTransaction chargeOffTransaction) {
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
|
||||
LocalDate transactionDate = loan.getChargedOffOnDate();
|
||||
if (transactionDate == null) {
|
||||
transactionDate = DateUtils.getBusinessLocalDate();
|
||||
@@ -102,7 +90,7 @@ public class LoanCapitalizedIncomeAmortizationProcessingServiceImpl implements L
|
||||
final Optional<LoanTransaction> amortizationTransaction = createCapitalizedIncomeAmortizationTransaction(loan, transactionDate,
|
||||
true, chargeOffTransaction);
|
||||
if (amortizationTransaction.isPresent()) {
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(amortizationTransaction.get(), false, false);
|
||||
if (amortizationTransaction.get().isCapitalizedIncomeAmortization()) {
|
||||
businessEventNotifierService.notifyPostBusinessEvent(
|
||||
new LoanCapitalizedIncomeAmortizationTransactionCreatedBusinessEvent(amortizationTransaction.get()));
|
||||
@@ -162,8 +150,6 @@ public class LoanCapitalizedIncomeAmortizationProcessingServiceImpl implements L
|
||||
@Transactional
|
||||
public void processCapitalizedIncomeAmortizationOnLoanUndoChargeOff(@NotNull final LoanTransaction loanTransaction) {
|
||||
final Loan loan = loanTransaction.getLoan();
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
|
||||
loan.getLoanTransactions().stream().filter(LoanTransaction::isCapitalizedIncomeAmortization)
|
||||
.filter(transaction -> transaction.getTransactionDate().equals(loanTransaction.getTransactionDate())
|
||||
@@ -174,24 +160,19 @@ public class LoanCapitalizedIncomeAmortizationProcessingServiceImpl implements L
|
||||
transaction.reverse();
|
||||
final LoanAdjustTransactionBusinessEvent.Data data = new LoanAdjustTransactionBusinessEvent.Data(transaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAdjustTransactionBusinessEvent(data));
|
||||
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(transaction, false, false);
|
||||
});
|
||||
|
||||
for (LoanCapitalizedIncomeBalance balance : loanCapitalizedIncomeBalanceRepository.findAllByLoanId(loan.getId())) {
|
||||
balance.setUnrecognizedAmount(balance.getChargedOffAmount());
|
||||
balance.setChargedOffAmount(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void processCapitalizedIncomeAmortizationTillDate(@NonNull final Loan loan, @NonNull final LocalDate tillDate,
|
||||
final boolean addJournal) {
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
|
||||
List<LoanCapitalizedIncomeBalance> balances = loanCapitalizedIncomeBalanceRepository.findAllByLoanId(loan.getId());
|
||||
|
||||
LocalDate maturityDate = loan.getMaturityDate() != null ? loan.getMaturityDate()
|
||||
@@ -229,7 +210,7 @@ public class LoanCapitalizedIncomeAmortizationProcessingServiceImpl implements L
|
||||
loanTransactionRepository.flush();
|
||||
|
||||
if (addJournal) {
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(transaction, false, false);
|
||||
}
|
||||
|
||||
BusinessEvent<?> event = MathUtil.isGreaterThanZero(totalAmortizationAmount)
|
||||
|
||||
+18
-59
@@ -36,7 +36,6 @@ import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
@@ -90,7 +89,6 @@ import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.group.domain.Group;
|
||||
import org.apache.fineract.portfolio.group.exception.GroupNotActiveException;
|
||||
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccountingBridgeDataDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargePaidByData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
@@ -129,7 +127,6 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.data.OverdueLoanSc
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.ScheduledDateGenerator;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanAccountingBridgeMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeApiJsonValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanDownPaymentTransactionValidator;
|
||||
@@ -156,7 +153,6 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
private final AccountTransfersWritePlatformService accountTransfersWritePlatformService;
|
||||
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||
private final LoanAccountDomainService loanAccountDomainService;
|
||||
private final LoanChargeRepository loanChargeRepository;
|
||||
private final LoanWritePlatformService loanWritePlatformService;
|
||||
@@ -172,7 +168,6 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
private final LoanChargeAssembler loanChargeAssembler;
|
||||
private final PaymentDetailWritePlatformService paymentDetailWritePlatformService;
|
||||
private final NoteRepository noteRepository;
|
||||
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
||||
private final LoanAccrualsProcessingService loanAccrualsProcessingService;
|
||||
private final LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator;
|
||||
private final LoanChargeValidator loanChargeValidator;
|
||||
@@ -180,8 +175,8 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||
private final LoanAccountService loanAccountService;
|
||||
private final LoanAdjustmentService loanAdjustmentService;
|
||||
private final LoanAccountingBridgeMapper loanAccountingBridgeMapper;
|
||||
private final LoanChargeService loanChargeService;
|
||||
private final LoanJournalEntryPoster loanJournalEntryPoster;
|
||||
|
||||
private static boolean isPartOfThisInstallment(LoanCharge loanCharge, LoanRepaymentScheduleInstallment e) {
|
||||
return DateUtils.isAfter(loanCharge.getDueDate(), e.getFromDate()) && !DateUtils.isAfter(loanCharge.getDueDate(), e.getDueDate());
|
||||
@@ -207,8 +202,6 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
// apply this charge
|
||||
validateAddingNewChargeAllowed(loanDisburseDetails);
|
||||
}
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
boolean isAppliedOnBackDate = false;
|
||||
LoanCharge loanCharge = null;
|
||||
@@ -301,14 +294,11 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled() && isAppliedOnBackDate
|
||||
&& loan.isFeeCompoundingEnabledForInterestRecalculation()) {
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, true, false);
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, true, true);
|
||||
}
|
||||
this.loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAddChargeBusinessEvent(loanCharge));
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()) //
|
||||
@@ -546,8 +536,6 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
changes.put(LoanApiConstants.externalIdParameterName, externalId);
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
LocalDate recalculateFrom = null;
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
|
||||
@@ -561,21 +549,21 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
}
|
||||
|
||||
loanChargeValidator.validateLoanIsNotClosed(loan, loanCharge);
|
||||
final LoanTransaction waiveTransaction = waiveLoanCharge(loan, loanCharge, changes, existingTransactionIds,
|
||||
existingReversedTransactionIds, loanInstallmentNumber, scheduleGeneratorDTO, accruedCharge, externalId);
|
||||
final LoanTransaction waiveTransaction = waiveLoanCharge(loan, loanCharge, changes, loanInstallmentNumber, scheduleGeneratorDTO,
|
||||
accruedCharge, externalId);
|
||||
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()
|
||||
&& DateUtils.isBefore(loanCharge.getDueLocalDate(), DateUtils.getBusinessLocalDate())) {
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
|
||||
this.loanTransactionRepository.saveAndFlush(waiveTransaction);
|
||||
this.loanRepositoryWrapper.save(loan);
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(waiveTransaction, false, false);
|
||||
|
||||
this.loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanWaiveChargeBusinessEvent(loanCharge));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
return new CommandProcessingResultBuilder() //
|
||||
@@ -830,8 +818,6 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
if (optPenaltyCharge.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
boolean runInterestRecalculation = false;
|
||||
LocalDate recalculateFrom = DateUtils.getBusinessLocalDate();
|
||||
LocalDate lastChargeDate = null;
|
||||
@@ -881,20 +867,15 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled() && runInterestRecalculation
|
||||
&& loan.isFeeCompoundingEnabledForInterestRecalculation()) {
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, true, false);
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, true, true);
|
||||
}
|
||||
this.loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
}
|
||||
}
|
||||
|
||||
private LoanTransaction applyChargeAdjustment(final Loan loan, final LoanCharge loanCharge, final BigDecimal transactionAmount,
|
||||
final LocalDate transactionDate, final ExternalId txnExternalId, PaymentDetail paymentDetail) {
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanChargeAdjustmentPreBusinessEvent(loan));
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
LoanTransaction loanChargeAdjustmentTransaction = LoanTransaction.chargeAdjustment(loan, transactionAmount, transactionDate,
|
||||
txnExternalId, paymentDetail);
|
||||
@@ -921,11 +902,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
loanLifecycleStateMachine.determineAndTransition(loan, loan.getLastUserTransactionDate());
|
||||
|
||||
loanAccountService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
final AccountingBridgeDataDTO accountingBridgeData = loanAccountingBridgeMapper.deriveAccountingBridgeData(
|
||||
loan.getCurrency().getCode(), existingTransactionIds, existingReversedTransactionIds, false, loan);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(loanChargeAdjustmentTransaction, false, false);
|
||||
loanAccountDomainService.setLoanDelinquencyTag(loan, transactionDate);
|
||||
|
||||
return loanChargeAdjustmentTransaction;
|
||||
@@ -943,8 +920,6 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
|
||||
private void undoInstalmentFee(Map<String, Object> changes, Loan loan, LoanTransaction loanTransaction,
|
||||
LoanChargePaidBy loanChargePaidBy) {
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
LoanCharge loanCharge = loanChargePaidBy.getLoanCharge();
|
||||
final Integer installmentNumber = loanChargePaidBy.getInstallmentNumber();
|
||||
LoanInstallmentCharge chargePerInstallment;
|
||||
@@ -989,7 +964,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
loanCharge.undoWaived();
|
||||
}
|
||||
loan.updateLoanSummaryForUndoWaiveCharge(amountWaived, loanCharge.isPenaltyCharge());
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(loanTransaction, false, false);
|
||||
changes.put(AMOUNT, amountWaived);
|
||||
} else {
|
||||
throw new InstallmentNotFoundException(loanTransaction.getId());
|
||||
@@ -998,9 +973,6 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
|
||||
private void undoSpecifiedDueDateCharge(final Map<String, Object> changes, final Loan loan, final LoanTransaction loanTransaction,
|
||||
final LoanChargePaidBy loanChargePaidBy) {
|
||||
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
LoanCharge loanCharge = loanChargePaidBy.getLoanCharge();
|
||||
BigDecimal amountWaived = loanCharge.getAmountWaived(loan.getCurrency()).getAmount();
|
||||
if (!loanCharge.isWaived() || amountWaived == null) {
|
||||
@@ -1017,7 +989,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
.filter(e -> isPartOfThisInstallment(loanCharge, e)).findFirst().orElseThrow();
|
||||
updateRepaymentInstalmentWithWaivedAmount(loanCharge, installment, amountWaived);
|
||||
loan.updateLoanSummaryForUndoWaiveCharge(amountWaived, loanCharge.isPenaltyCharge());
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(loanTransaction, false, false);
|
||||
changes.put(AMOUNT, amountWaived);
|
||||
}
|
||||
|
||||
@@ -1104,6 +1076,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
final LoanTransaction applyLoanChargeTransaction = loanChargeService.handleChargeAppliedTransaction(loan, loanCharge, null);
|
||||
if (applyLoanChargeTransaction != null) {
|
||||
this.loanTransactionRepository.saveAndFlush(applyLoanChargeTransaction);
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(applyLoanChargeTransaction, false, false);
|
||||
businessEventNotifierService
|
||||
.notifyPostBusinessEvent(new LoanAccrualTransactionCreatedBusinessEvent(applyLoanChargeTransaction));
|
||||
}
|
||||
@@ -1111,6 +1084,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
&& DateUtils.getBusinessLocalDate().isAfter(loan.getMaturityDate())) {
|
||||
final LoanTransaction loanTransaction = loanChargeService.createChargeAppliedTransaction(loan, loanCharge, null);
|
||||
this.loanTransactionRepository.saveAndFlush(loanTransaction);
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(loanTransaction, false, false);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAccrualTransactionCreatedBusinessEvent(loanTransaction));
|
||||
}
|
||||
|
||||
@@ -1212,13 +1186,11 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
|
||||
public Loan runScheduleRecalculation(Loan loan, final LocalDate recalculateFrom) {
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled() && !loan.isChargedOff()) {
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
ScheduleGeneratorDTO generatorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
loanScheduleService.handleRegenerateRepaymentScheduleWithInterestRecalculation(loan, generatorDTO);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
loan = loanAccountService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
}
|
||||
return loan;
|
||||
}
|
||||
@@ -1289,16 +1261,6 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
return refundableAmount;
|
||||
}
|
||||
|
||||
private void postJournalEntries(final Loan loan, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds) {
|
||||
|
||||
final MonetaryCurrency currency = loan.getCurrency();
|
||||
boolean isAccountTransfer = false;
|
||||
final AccountingBridgeDataDTO accountingBridgeData = loanAccountingBridgeMapper.deriveAccountingBridgeData(currency.getCode(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, loan);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
|
||||
private LoanCharge retrieveLoanChargeBy(final Long loanId, final Long loanChargeId) {
|
||||
final LoanCharge loanCharge = this.loanChargeRepository.findById(loanChargeId)
|
||||
.orElseThrow(() -> new LoanChargeNotFoundException(loanChargeId));
|
||||
@@ -1423,8 +1385,8 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
}
|
||||
|
||||
public LoanTransaction waiveLoanCharge(final Loan loan, final LoanCharge loanCharge, final Map<String, Object> changes,
|
||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds, final Integer loanInstallmentNumber,
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO, final Money accruedCharge, final ExternalId externalId) {
|
||||
final Integer loanInstallmentNumber, final ScheduleGeneratorDTO scheduleGeneratorDTO, final Money accruedCharge,
|
||||
final ExternalId externalId) {
|
||||
final Money amountWaived = loanCharge.waive(loan.getCurrency(), loanInstallmentNumber);
|
||||
changes.put("amount", amountWaived.getAmount());
|
||||
|
||||
@@ -1474,9 +1436,6 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
|
||||
loan.updateSummaryWithTotalFeeChargesDueAtDisbursement(loan.deriveSumTotalOfChargesDueAtDisbursement());
|
||||
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
final LoanTransaction waiveLoanChargeTransaction = LoanTransaction.waiveLoanCharge(loan, loan.getOffice(), amountWaived,
|
||||
transactionDate, feeChargesWaived, penaltyChargesWaived, unrecognizedIncome, externalId);
|
||||
final LoanChargePaidBy loanChargePaidBy = new LoanChargePaidBy(waiveLoanChargeTransaction, loanCharge,
|
||||
|
||||
+11
-1
@@ -52,6 +52,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTrancheCharge;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTrancheDisbursementCharge;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanDisbursementValidator;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
@@ -64,6 +65,8 @@ public class LoanDisbursementService {
|
||||
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||
private final LoanChargeService loanChargeService;
|
||||
private final LoanBalanceService loanBalanceService;
|
||||
private final LoanJournalEntryPoster loanJournalEntryPoster;
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
|
||||
public void updateDisbursementDetails(final Loan loan, final JsonCommand jsonCommand, final Map<String, Object> actualChanges) {
|
||||
final List<Long> disbursementList = loan.fetchDisbursementIds();
|
||||
@@ -210,7 +213,12 @@ public class LoanDisbursementService {
|
||||
}
|
||||
} else if (disbursedOn.equals(loan.getActualDisbursementDate())
|
||||
&& loan.isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
|
||||
loanChargeService.handleChargeAppliedTransaction(loan, charge, disbursedOn);
|
||||
final LoanTransaction applyLoanChargeTransaction = loanChargeService.handleChargeAppliedTransaction(loan, charge,
|
||||
disbursedOn);
|
||||
if (applyLoanChargeTransaction != null) {
|
||||
loanTransactionRepository.saveAndFlush(applyLoanChargeTransaction);
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(applyLoanChargeTransaction, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,6 +227,8 @@ public class LoanDisbursementService {
|
||||
chargesPayment.updateComponentsAndTotal(zero, zero, disbursentMoney, zero);
|
||||
chargesPayment.updateLoan(loan);
|
||||
loan.addLoanTransaction(chargesPayment);
|
||||
loanTransactionRepository.saveAndFlush(chargesPayment);
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(chargesPayment, false, false);
|
||||
loanBalanceService.updateLoanOutstandingBalances(loan);
|
||||
}
|
||||
|
||||
|
||||
+15
-21
@@ -18,13 +18,12 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.service;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccountingBridgeDataDTO;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwner;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransfer;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanAccountingBridgeMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@@ -32,25 +31,20 @@ import org.springframework.stereotype.Component;
|
||||
public class LoanJournalEntryPosterImpl implements LoanJournalEntryPoster {
|
||||
|
||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||
private final LoanAccountingBridgeMapper loanAccountingBridgeMapper;
|
||||
|
||||
@Override
|
||||
public void postJournalEntries(final Loan loan, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds) {
|
||||
final MonetaryCurrency currency = loan.getCurrency();
|
||||
boolean isAccountTransfer = false;
|
||||
|
||||
if (loan.isChargedOff()) {
|
||||
List<AccountingBridgeDataDTO> accountingBridgeDataList = loanAccountingBridgeMapper.deriveAccountingBridgeDataForChargeOff(
|
||||
currency.getCode(), existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, loan);
|
||||
for (AccountingBridgeDataDTO accountingBridgeData : accountingBridgeDataList) {
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
} else {
|
||||
AccountingBridgeDataDTO accountingBridgeData = loanAccountingBridgeMapper.deriveAccountingBridgeData(currency.getCode(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, loan);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
}
|
||||
public void postJournalEntriesForLoanTransaction(final LoanTransaction loanTransaction, final boolean isAccountTransfer,
|
||||
final boolean isLoanToLoanTransfer) {
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoanTransaction(loanTransaction, isAccountTransfer,
|
||||
isLoanToLoanTransfer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postJournalEntriesForExternalOwnerTransfer(final Loan loan, final Object externalAssetOwnerTransfer,
|
||||
final Object previousOwner) {
|
||||
// Cast to proper types
|
||||
final ExternalAssetOwnerTransfer transfer = (ExternalAssetOwnerTransfer) externalAssetOwnerTransfer;
|
||||
final ExternalAssetOwner prevOwner = (ExternalAssetOwner) previousOwner;
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForExternalOwnerTransfer(loan, transfer, prevOwner);
|
||||
}
|
||||
}
|
||||
|
||||
+92
-207
@@ -51,7 +51,6 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||
import org.apache.fineract.cob.exceptions.AccountLockCannotBeOverruledException;
|
||||
import org.apache.fineract.cob.service.LoanAccountLockService;
|
||||
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
|
||||
@@ -109,7 +108,6 @@ import org.apache.fineract.infrastructure.security.service.PlatformSecurityConte
|
||||
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
||||
import org.apache.fineract.organisation.holiday.domain.HolidayRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.holiday.service.HolidayUtil;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
import org.apache.fineract.organisation.staff.domain.Staff;
|
||||
@@ -153,7 +151,6 @@ import org.apache.fineract.portfolio.group.domain.Group;
|
||||
import org.apache.fineract.portfolio.group.exception.GroupNotActiveException;
|
||||
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
|
||||
import org.apache.fineract.portfolio.loanaccount.command.LoanUpdateCommand;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccountingBridgeDataDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.GLIMAccountInfoRepository;
|
||||
@@ -200,7 +197,6 @@ import org.apache.fineract.portfolio.loanaccount.guarantor.service.GuarantorDoma
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleHistoryWritePlatformService;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanAccountingBridgeMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanApplicationValidator;
|
||||
@@ -242,7 +238,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
private final LoanTransactionRelationRepository loanTransactionRelationRepository;
|
||||
private final LoanAssembler loanAssembler;
|
||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||
private final CalendarInstanceRepository calendarInstanceRepository;
|
||||
private final PaymentDetailWritePlatformService paymentDetailWritePlatformService;
|
||||
private final HolidayRepositoryWrapper holidayRepository;
|
||||
@@ -287,7 +282,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
private final LoanAccountService loanAccountService;
|
||||
private final LoanJournalEntryPoster journalEntryPoster;
|
||||
private final LoanAdjustmentService loanAdjustmentService;
|
||||
private final LoanAccountingBridgeMapper loanAccountingBridgeMapper;
|
||||
private final LoanMapper loanMapper;
|
||||
private final LoanTransactionProcessingService loanTransactionProcessingService;
|
||||
private final LoanBalanceService loanBalanceService;
|
||||
@@ -356,9 +350,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanDisbursalBusinessEvent(loan));
|
||||
|
||||
List<Long> existingTransactionIds = new ArrayList<>();
|
||||
List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
final AppUser currentUser = getAppUserIfPresent();
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
|
||||
@@ -398,16 +389,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
LoanTransaction disbursementTransaction = null;
|
||||
if (isAccountTransfer) {
|
||||
disburseLoanToSavings(loan, command, amountToDisburse, paymentDetail);
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
} else {
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
disbursementTransaction = LoanTransaction.disbursement(loan, amountToDisburse, paymentDetail, actualDisbursementDate,
|
||||
txnExternalId, loan.getTotalOverpaidAsMoney());
|
||||
disbursementTransaction.updateLoan(loan);
|
||||
loan.addLoanTransaction(disbursementTransaction);
|
||||
loanTransactionRepository.saveAndFlush(disbursementTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(disbursementTransaction, false, false);
|
||||
}
|
||||
if (loan.getRepaymentScheduleInstallments().isEmpty()) {
|
||||
/*
|
||||
@@ -426,12 +414,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
scheduleGeneratorDTO);
|
||||
loan.adjustNetDisbursalAmount(amountToDisburse.getAmount());
|
||||
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
|
||||
LocalDate firstInstallmentDueDate = loan.fetchRepaymentScheduleInstallment(1).getDueDate();
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()
|
||||
&& (DateUtils.isBeforeBusinessDate(firstInstallmentDueDate) || loan.isDisbursementMissed())) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
|
||||
if (loan.isAutoRepaymentForDownPaymentEnabled() && !isWithoutAutoPayment) {
|
||||
@@ -462,9 +450,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
} else {
|
||||
loanDownPaymentHandlerService.handleDownPayment(scheduleGeneratorDTO, command, disbursementTransaction, loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -501,7 +489,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
updateRecurringCalendarDatesForInterestRecalculation(loan);
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
true);
|
||||
this.loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||
|
||||
// Post Dated Checks
|
||||
@@ -525,8 +513,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanDisbursalTransactionBusinessEvent(disbursalTransaction));
|
||||
}
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
@@ -594,6 +580,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final LoanTransaction interestAppliedTransaction = LoanTransaction.accrueInterest(loan.getOffice(), loan, interestApplied,
|
||||
actualDisbursementDate1, externalId);
|
||||
loan.addLoanTransaction(interestAppliedTransaction);
|
||||
loanTransactionRepository.saveAndFlush(interestAppliedTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(interestAppliedTransaction, false, false);
|
||||
}
|
||||
|
||||
if (loan.getLoanProduct().isMultiDisburseLoan() || loan.isProgressiveSchedule()) {
|
||||
@@ -753,9 +741,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
checkClientOrGroupActive(loan);
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanDisbursalBusinessEvent(loan));
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
|
||||
|
||||
// Bulk disbursement should happen on meeting date (mostly from
|
||||
@@ -773,16 +758,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final ExternalId txnExternalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
if (isAccountTransfer) {
|
||||
disburseLoanToSavings(loan, command, disburseAmount, paymentDetail);
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
} else {
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
LoanTransaction disbursementTransaction = LoanTransaction.disbursement(loan, disburseAmount, paymentDetail,
|
||||
actualDisbursementDate, txnExternalId, loan.getTotalOverpaidAsMoney());
|
||||
disbursementTransaction.updateLoan(loan);
|
||||
loan.addLoanTransaction(disbursementTransaction);
|
||||
loanTransactionRepository.saveAndFlush(disbursementTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(disbursementTransaction, false, false);
|
||||
businessEventNotifierService
|
||||
.notifyPostBusinessEvent(new LoanDisbursalTransactionBusinessEvent(disbursementTransaction));
|
||||
}
|
||||
@@ -797,19 +779,17 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
disburseLoan(command, configurationDomainService.isPaymentTypeApplicableForDisbursementCharge(), paymentDetail, loan,
|
||||
currentUser, changes, scheduleGeneratorDTO);
|
||||
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
|
||||
LocalDate firstInstallmentDueDate = loan.fetchRepaymentScheduleInstallment(1).getDueDate();
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()
|
||||
&& (DateUtils.isBeforeBusinessDate(firstInstallmentDueDate) || loan.isDisbursementMissed())) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
}
|
||||
if (!changes.isEmpty()) {
|
||||
createNote(loan, command, changes);
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
}
|
||||
final Set<LoanCharge> loanCharges = loan.getActiveCharges();
|
||||
final Map<Long, BigDecimal> disBuLoanCharges = new HashMap<>();
|
||||
@@ -879,10 +859,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanUndoDisbursalBusinessEvent(loan));
|
||||
removeLoanCycle(loan);
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
//
|
||||
final MonetaryCurrency currency = loan.getCurrency();
|
||||
|
||||
final LocalDate recalculateFrom = null;
|
||||
loan.setActualDisbursementDate(null);
|
||||
@@ -894,10 +870,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.LOAN_DISBURSAL_UNDO);
|
||||
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, LoanEvent.LOAN_DISBURSAL_UNDO,
|
||||
loan.getDisbursementDate());
|
||||
final Map<String, Object> changes = undoDisbursal(loan, scheduleGeneratorDTO, existingTransactionIds,
|
||||
existingReversedTransactionIds);
|
||||
final Map<String, Object> changes = undoDisbursal(loan, scheduleGeneratorDTO);
|
||||
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
if (loan.isTopup() && loan.getClientId() != null) {
|
||||
@@ -912,11 +887,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
this.accountTransfersWritePlatformService.reverseAllTransactions(loanId, PortfolioAccountType.LOAN);
|
||||
createNote(loan, command, changes);
|
||||
boolean isAccountTransfer = false;
|
||||
final AccountingBridgeDataDTO accountingBridgeData = loanAccountingBridgeMapper.deriveAccountingBridgeData(currency.getCode(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, loan);
|
||||
journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanUndoDisbursalBusinessEvent(loan));
|
||||
}
|
||||
|
||||
@@ -1031,8 +1001,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1046,10 +1016,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanTransactionInterestPaymentWaiverPreBusinessEvent(loan));
|
||||
|
||||
// save already existing transaction ids
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
final String noteText = command.stringValueOfParameterNamed("note");
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
|
||||
@@ -1061,13 +1027,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
loanTransactionValidator.validateLoanTransactionInterestPaymentWaiverAfterRecalculation(loan);
|
||||
|
||||
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newInterestPaymentWaiverTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(newInterestPaymentWaiverTransaction, false, false);
|
||||
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
saveNote(noteText, loan, newInterestPaymentWaiverTransaction);
|
||||
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
true);
|
||||
loanAccountDomainService.setLoanDelinquencyTag(loan, newInterestPaymentWaiverTransaction.getTransactionDate());
|
||||
|
||||
// disable all active standing orders linked to this loan if status changes to closed
|
||||
@@ -1079,9 +1046,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
// Finished Notification
|
||||
final LoanTransactionBusinessEvent transactionRepaymentEvent = new LoanTransactionInterestPaymentWaiverPostBusinessEvent(
|
||||
newInterestPaymentWaiverTransaction);
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(transactionRepaymentEvent);
|
||||
|
||||
@@ -1170,7 +1134,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled();
|
||||
for (final SingleRepaymentCommand singleLoanRepaymentCommand : repaymentCommand) {
|
||||
if (singleLoanRepaymentCommand != null) {
|
||||
Loan loan = this.loanRepositoryWrapper.findOneWithNotFoundDetection(singleLoanRepaymentCommand.getLoanId());
|
||||
Loan loan = this.loanAssembler.assembleFrom(singleLoanRepaymentCommand.getLoanId());
|
||||
final List<Holiday> holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(),
|
||||
singleLoanRepaymentCommand.getTransactionDate());
|
||||
final WorkingDays workingDays = this.workingDaysRepository.findOne();
|
||||
@@ -1318,9 +1282,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
checkClientOrGroupActive(loan);
|
||||
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanChargebackTransactionBusinessEvent(loanTransaction));
|
||||
|
||||
final LocalDate transactionDate = DateUtils.getBusinessLocalDate();
|
||||
@@ -1351,6 +1312,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
handleChargebackTransaction(loan, newTransaction);
|
||||
|
||||
newTransaction = this.loanTransactionRepository.saveAndFlush(newTransaction);
|
||||
// Create journal entries immediately for this transaction
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(newTransaction, false, false);
|
||||
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
@@ -1361,9 +1324,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
this.loanAccountDomainService.setLoanDelinquencyTag(loan, transactionDate);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanChargebackTransactionBusinessEvent(newTransaction));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
|
||||
@@ -1412,9 +1373,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
final Money transactionAmountAsMoney = Money.of(loan.getCurrency(), transactionAmount);
|
||||
Money unrecognizedIncome = transactionAmountAsMoney.zero();
|
||||
Money interestComponent = transactionAmountAsMoney;
|
||||
@@ -1439,14 +1397,15 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
LoanEvent.LOAN_REPAYMENT_OR_WAIVER);
|
||||
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
|
||||
waiveInterestTransaction.getTransactionDate());
|
||||
waiveInterest(loan, waiveInterestTransaction, existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO);
|
||||
waiveInterest(loan, waiveInterestTransaction, scheduleGeneratorDTO);
|
||||
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
|
||||
this.loanTransactionRepository.saveAndFlush(waiveInterestTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(waiveInterestTransaction, false, false);
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
final String noteText = command.stringValueOfParameterNamed("note");
|
||||
@@ -1457,11 +1416,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
true);
|
||||
loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanWaiveInterestBusinessEvent(waiveInterestTransaction));
|
||||
return new CommandProcessingResultBuilder() //
|
||||
@@ -1508,10 +1464,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
StatusEnum.WRITE_OFF.getValue(), EntityTables.LOAN.getForeignKeyColumnNameOnDatatable(), loan.productId());
|
||||
|
||||
removeLoanCycle(loan);
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
updateLoanCounters(loan, loan.getDisbursementDate());
|
||||
|
||||
LocalDate recalculateFrom = null;
|
||||
@@ -1533,16 +1485,17 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
.withLoanId(loanId) //
|
||||
.with(changes);
|
||||
|
||||
final Optional<LoanTransaction> loanTransactionOptional = closeAsWrittenOff(loan, command, changes, existingTransactionIds,
|
||||
existingReversedTransactionIds, currentUser, scheduleGeneratorDTO);
|
||||
final Optional<LoanTransaction> loanTransactionOptional = closeAsWrittenOff(loan, command, changes, currentUser,
|
||||
scheduleGeneratorDTO);
|
||||
|
||||
if (loanTransactionOptional.isPresent()) {
|
||||
final LoanTransaction loanTransaction = loanTransactionOptional.get();
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
this.loanTransactionRepository.saveAndFlush(loanTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(loanTransaction, false, false);
|
||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
final String noteText = command.stringValueOfParameterNamed("note");
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
@@ -1551,11 +1504,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan,
|
||||
loan.isInterestBearingAndInterestRecalculationEnabled(), false);
|
||||
loan.isInterestBearingAndInterestRecalculationEnabled(), true);
|
||||
loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanWrittenOffPostBusinessEvent(loanTransaction));
|
||||
|
||||
@@ -1587,9 +1537,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
changes.put("locale", command.locale());
|
||||
changes.put("dateFormat", command.dateFormat());
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
updateLoanCounters(loan, loan.getDisbursementDate());
|
||||
|
||||
LocalDate recalculateFrom = null;
|
||||
@@ -1601,15 +1548,17 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final LocalDate closureDate = command.localDateValueOfParameterNamed(TRANSACTION_DATE);
|
||||
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.LOAN_CLOSED);
|
||||
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, LoanEvent.REPAID_IN_FULL, closureDate);
|
||||
final Optional<LoanTransaction> loanTransactionOptional = close(loan, command, changes, existingTransactionIds,
|
||||
existingReversedTransactionIds, scheduleGeneratorDTO);
|
||||
final Optional<LoanTransaction> loanTransactionOptional = close(loan, command, changes, scheduleGeneratorDTO);
|
||||
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
|
||||
loanTransactionOptional.ifPresent(this.loanTransactionRepository::saveAndFlush);
|
||||
loanTransactionOptional.ifPresent(loanTransaction -> {
|
||||
this.loanTransactionRepository.saveAndFlush(loanTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(loanTransaction, false, false);
|
||||
});
|
||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
final String noteText = command.stringValueOfParameterNamed("note");
|
||||
@@ -1619,9 +1568,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
true);
|
||||
|
||||
loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||
|
||||
@@ -1633,9 +1581,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
// disable all active standing instructions linked to the loan
|
||||
this.loanAccountDomainService.disableStandingInstructionsLinkedToClosedLoan(loan);
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
|
||||
CommandProcessingResult result;
|
||||
if (loanTransactionOptional.isPresent()) {
|
||||
result = new CommandProcessingResultBuilder() //
|
||||
@@ -1756,17 +1701,15 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanInitiateTransferBusinessEvent(loan));
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
ExternalId externalId = externalIdFactory.create();
|
||||
final LoanTransaction newTransferTransaction = LoanTransaction.initiateTransfer(loan.getOffice(), loan, transferDate, externalId);
|
||||
loan.addLoanTransaction(newTransferTransaction);
|
||||
loanLifecycleStateMachine.transition(LoanEvent.LOAN_INITIATE_TRANSFER, loan);
|
||||
|
||||
this.loanTransactionRepository.saveAndFlush(newTransferTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(newTransferTransaction, false, false);
|
||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanInitiateTransferBusinessEvent(loan));
|
||||
return newTransferTransaction;
|
||||
}
|
||||
@@ -1776,8 +1719,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
public LoanTransaction acceptLoanTransfer(final Loan loan, final LocalDate transferDate, final Office acceptedInOffice,
|
||||
final Staff loanOfficer) {
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanAcceptTransferBusinessEvent(loan));
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
ExternalId externalId = externalIdFactory.create();
|
||||
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.approveTransfer(acceptedInOffice, loan, transferDate,
|
||||
externalId);
|
||||
@@ -1792,9 +1733,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
|
||||
this.loanTransactionRepository.saveAndFlush(newTransferAcceptanceTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(newTransferAcceptanceTransaction, false, false);
|
||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAcceptTransferBusinessEvent(loan));
|
||||
|
||||
return newTransferAcceptanceTransaction;
|
||||
@@ -1805,9 +1745,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
public LoanTransaction withdrawLoanTransfer(final Loan loan, final LocalDate transferDate) {
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanWithdrawTransferBusinessEvent(loan));
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
ExternalId externalId = externalIdFactory.create();
|
||||
|
||||
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.withdrawTransfer(loan.getOffice(), loan, transferDate,
|
||||
@@ -1816,9 +1753,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
loanLifecycleStateMachine.transition(LoanEvent.LOAN_WITHDRAW_TRANSFER, loan);
|
||||
|
||||
this.loanTransactionRepository.saveAndFlush(newTransferAcceptanceTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(newTransferAcceptanceTransaction, false, false);
|
||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanWithdrawTransferBusinessEvent(loan));
|
||||
|
||||
return newTransferAcceptanceTransaction;
|
||||
@@ -2019,9 +1955,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
holidays, workingDays, isSkipRepaymentOnFirstMonth, numberOfDays);
|
||||
}
|
||||
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, false);
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, false);
|
||||
}
|
||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanRescheduledDueCalendarChangeBusinessEvent(loan));
|
||||
@@ -2193,8 +2129,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
if (!loan.isClosedWrittenOff()) {
|
||||
throw new PlatformServiceUnavailableException("error.msg.loan.status.not.written.off.update.not.allowed",
|
||||
"Loan :" + loanId + " update not allowed as loan status is not written off", loanId);
|
||||
@@ -2207,20 +2141,19 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanUndoWrittenOffBusinessEvent(writeOffTransaction));
|
||||
|
||||
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.WRITE_OFF_OUTSTANDING_UNDO);
|
||||
undoWrittenOff(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
undoWrittenOff(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
true);
|
||||
|
||||
this.loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(writeOffTransaction, false, false);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanUndoWrittenOffBusinessEvent(writeOffTransaction));
|
||||
|
||||
@@ -2331,8 +2264,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
private CommandProcessingResult processLoanDisbursementDetail(Loan loan, Long loanId, JsonCommand command,
|
||||
LoanDisbursementDetails loanDisbursementDetails) {
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
LocalDate recalculateFrom = null;
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
@@ -2352,9 +2283,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
}
|
||||
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
@@ -2362,12 +2293,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
createLoanScheduleArchive(loan, scheduleGeneratorDTO);
|
||||
}
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
true);
|
||||
this.loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
@@ -2416,18 +2344,15 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
ScheduleGeneratorDTO generatorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||
loanScheduleService.recalculateScheduleFromLastTransaction(loan, generatorDTO, existingTransactionIds,
|
||||
existingReversedTransactionIds);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan,
|
||||
loan.isInterestBearingAndInterestRecalculationEnabled(), false);
|
||||
loan.isInterestBearingAndInterestRecalculationEnabled(), true);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanInterestRecalculationBusinessEvent(loan));
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
} else {
|
||||
loanScheduleService.recalculateScheduleFromLastTransaction(loan, null, existingTransactionIds, existingReversedTransactionIds,
|
||||
true);
|
||||
@@ -2511,10 +2436,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||
}
|
||||
}
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2681,31 +2606,20 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanUndoLastDisbursalBusinessEvent(loan));
|
||||
|
||||
final MonetaryCurrency currency = loan.getCurrency();
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFromDate);
|
||||
|
||||
loanDownPaymentTransactionValidator.validateAccountStatus(loan, LoanEvent.LOAN_DISBURSAL_UNDO_LAST);
|
||||
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, LoanEvent.LOAN_DISBURSAL_UNDO_LAST,
|
||||
loan.getDisbursementDate());
|
||||
final Map<String, Object> changes = undoLastDisbursal(scheduleGeneratorDTO, existingTransactionIds, existingReversedTransactionIds,
|
||||
loan);
|
||||
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
}
|
||||
final Map<String, Object> changes = undoLastDisbursal(scheduleGeneratorDTO, loan);
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
createNote(loan, command, changes);
|
||||
boolean isAccountTransfer = false;
|
||||
final AccountingBridgeDataDTO accountingBridgeData = loanAccountingBridgeMapper.deriveAccountingBridgeData(currency.getCode(),
|
||||
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer, loan);
|
||||
journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanUndoLastDisbursalBusinessEvent(loan));
|
||||
}
|
||||
|
||||
@@ -2813,10 +2727,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
} else {
|
||||
loan.markAsChargedOff(transactionDate, currentUser, null);
|
||||
}
|
||||
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
|
||||
final LoanTransaction chargeOffTransaction = LoanTransaction.chargeOff(loan, transactionDate, txnExternalId);
|
||||
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
@@ -2833,6 +2743,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
loan.addLoanTransaction(chargeOffTransaction);
|
||||
}
|
||||
loanTransactionRepository.saveAndFlush(chargeOffTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(chargeOffTransaction, false, false);
|
||||
|
||||
saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
@@ -2849,13 +2760,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
: DateUtils.isAfter(transaction.getTransactionDate(), transactionDate))
|
||||
.forEach(transaction -> {
|
||||
transaction.reverse();
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(transaction, false, false);
|
||||
final LoanAdjustTransactionBusinessEvent.Data data = new LoanAdjustTransactionBusinessEvent.Data(transaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAdjustTransactionBusinessEvent(data));
|
||||
});
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanChargeOffPostBusinessEvent(chargeOffTransaction));
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(chargeOffTransaction.getId()) //
|
||||
@@ -2873,8 +2783,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.loanTransactionValidator.validateUndoChargeOff(command.json());
|
||||
final Long loanId = command.getLoanId();
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
checkClientOrGroupActive(loan);
|
||||
if (!loan.isOpen()) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.is.not.active",
|
||||
@@ -2906,6 +2814,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
loan.liftChargeOff();
|
||||
loanTransactionRepository.saveAndFlush(chargedOffTransaction);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(chargedOffTransaction, false, false);
|
||||
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, null, null);
|
||||
if (loan.isCumulativeSchedule() && loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
@@ -2917,7 +2826,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||
|
||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanUndoChargeOffBusinessEvent(chargedOffTransaction));
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
@@ -2956,9 +2864,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
|
||||
// Create note
|
||||
createNote(loan, command, changes);
|
||||
// Initial transaction ids for journal entry generation
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
// Create refund transaction(s)
|
||||
final Boolean interestRefundCalculation = command.booleanObjectValueOfParameterNamed("interestRefundCalculation");
|
||||
Pair<LoanTransaction, LoanTransaction> refundTransactions = loanAccountDomainService.makeRefund(loan, scheduleGeneratorDTO,
|
||||
@@ -2967,8 +2872,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
LoanTransaction interestRefundTransaction = refundTransactions.getRight();
|
||||
// Accrual reprocessing
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
@@ -2980,20 +2885,21 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
//// Mark Post Dated Check as paid., Do we need this for refund?
|
||||
loanAccountDomainService.updateAndSavePostDatedChecksForIndividualAccount(loan, refundTransaction);
|
||||
if (interestRefundTransaction != null) {
|
||||
loanAccountDomainService.updateAndSavePostDatedChecksForIndividualAccount(loan, refundTransaction);
|
||||
loanAccountDomainService.updateAndSavePostDatedChecksForIndividualAccount(loan, interestRefundTransaction);
|
||||
}
|
||||
// Collateral management
|
||||
loanAccountDomainService.updateAndSaveLoanCollateralTransactionsForIndividualAccounts(loan, refundTransaction);
|
||||
if (interestRefundTransaction != null) {
|
||||
loanAccountDomainService.updateAndSaveLoanCollateralTransactionsForIndividualAccounts(loan, refundTransaction);
|
||||
loanAccountDomainService.updateAndSaveLoanCollateralTransactionsForIndividualAccounts(loan, interestRefundTransaction);
|
||||
}
|
||||
// Raise business events
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
true);
|
||||
|
||||
// Create journal entries for the new transaction(s)
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(refundTransaction, false, false);
|
||||
if (interestRefundTransaction != null) {
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(interestRefundTransaction, false, false);
|
||||
}
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
|
||||
Long entityId = refundTransaction.getId();
|
||||
@@ -3070,9 +2976,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
createNote(loan, command, changes);
|
||||
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
|
||||
final LoanTransaction interestRefundTxn = loanAccountDomainService.createManualInterestRefundWithAmount(loan, targetTransaction,
|
||||
amount, paymentDetail, txnExternalId);
|
||||
|
||||
@@ -3111,8 +3014,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
// Accrual reprocessing
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
@@ -3123,10 +3026,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
loanAccountDomainService.updateAndSaveLoanCollateralTransactionsForIndividualAccounts(loan, interestRefundTxn);
|
||||
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
true);
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(interestRefundTxn, false, false);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
@@ -3194,13 +3096,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> undoDisbursal(final Loan loan, final ScheduleGeneratorDTO scheduleGeneratorDTO,
|
||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
||||
private Map<String, Object> undoDisbursal(final Loan loan, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>();
|
||||
final LoanStatus currentStatus = loan.getStatus();
|
||||
final LoanStatus statusEnum = this.loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_DISBURSAL_UNDO, loan);
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
if (!statusEnum.hasStateOf(currentStatus)) {
|
||||
this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSAL_UNDO, loan); // tis will update the loan
|
||||
// status
|
||||
@@ -3293,6 +3192,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
for (final LoanTransaction transaction : loan.getLoanTransactions()) {
|
||||
loanChargeValidator.validateRepaymentTypeTransactionNotBeforeAChargeRefund(transaction.getLoan(), transaction, "reversed");
|
||||
transaction.reverse();
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(transaction, false, false);
|
||||
if (transaction.getId() != null) {
|
||||
retainTransactions.add(transaction);
|
||||
}
|
||||
@@ -3301,8 +3201,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
|
||||
private Optional<LoanTransaction> closeAsWrittenOff(final Loan loan, final JsonCommand command, final Map<String, Object> changes,
|
||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds, final AppUser currentUser,
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
final AppUser currentUser, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
closeDisbursements(loan, scheduleGeneratorDTO);
|
||||
|
||||
final LocalDate writtenOffOnLocalDate = command.localDateValueOfParameterNamed(TRANSACTION_DATE);
|
||||
@@ -3315,9 +3214,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull(EXTERNAL_ID);
|
||||
|
||||
ExternalId externalId = ExternalIdFactory.produce(txnExternalId);
|
||||
@@ -3379,11 +3275,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
|
||||
private Optional<LoanTransaction> close(final Loan loan, final JsonCommand command, final Map<String, Object> changes,
|
||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
final LocalDate closureDate = command.localDateValueOfParameterNamed(TRANSACTION_DATE);
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull(EXTERNAL_ID);
|
||||
|
||||
@@ -3489,17 +3381,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||
}
|
||||
|
||||
private Map<String, Object> undoLastDisbursal(final ScheduleGeneratorDTO scheduleGeneratorDTO, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, final Loan loan) {
|
||||
private Map<String, Object> undoLastDisbursal(final ScheduleGeneratorDTO scheduleGeneratorDTO, final Loan loan) {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>();
|
||||
List<LoanTransaction> loanTransactions = loan.retrieveListOfTransactionsByType(LoanTransactionType.DISBURSEMENT);
|
||||
loanTransactions.sort(Comparator.comparing(LoanTransaction::getId));
|
||||
final LoanTransaction lastDisbursalTransaction = loanTransactions.getLast();
|
||||
final LocalDate lastTransactionDate = lastDisbursalTransaction.getTransactionDate();
|
||||
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
loanTransactions = loanTransactionRepository.findNonReversedMonetaryTransactionsByLoan(loan);
|
||||
Collections.reverse(loanTransactions);
|
||||
for (final LoanTransaction previousTransaction : loanTransactions) {
|
||||
@@ -3530,18 +3418,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void waiveInterest(final Loan loan, final LoanTransaction waiveInterestTransaction, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
private void waiveInterest(final Loan loan, final LoanTransaction waiveInterestTransaction,
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
loanDownPaymentHandlerService.handleRepaymentOrRecoveryOrWaiverTransaction(loan, waiveInterestTransaction, null,
|
||||
scheduleGeneratorDTO);
|
||||
}
|
||||
|
||||
private void undoWrittenOff(final Loan loan, final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
private void undoWrittenOff(final Loan loan) {
|
||||
final LoanTransaction writeOffTransaction = loan.findWriteOffTransaction();
|
||||
loanChargeValidator.validateRepaymentTypeTransactionNotBeforeAChargeRefund(writeOffTransaction.getLoan(), writeOffTransaction,
|
||||
"reversed");
|
||||
@@ -3558,7 +3441,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
/**
|
||||
* Reverse only disbursement, accruals, and repayments at disbursal transactions
|
||||
*/
|
||||
public void reverseExistingTransactionsTillLastDisbursal(final Loan loan, final LoanTransaction lastDisbursalTransaction) {
|
||||
public void reverseExistingTransactionsTillLastDisbursal(Loan loan, final LoanTransaction lastDisbursalTransaction) {
|
||||
LoanCharge chargeToDeactivate = null;
|
||||
|
||||
for (final LoanCharge charge : loan.getCharges()) {
|
||||
@@ -3590,6 +3473,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
&& transaction.isAllowTypeTransactionAtTheTimeOfLastUndo()) {
|
||||
loanChargeValidator.validateRepaymentTypeTransactionNotBeforeAChargeRefund(transaction.getLoan(), transaction, "reversed");
|
||||
transaction.reverse();
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(transaction, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3609,9 +3493,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
.max(Comparator.comparing(LoanTransaction::getId));
|
||||
|
||||
// reverse the down-payment transaction
|
||||
downPaymentTransaction.ifPresent(tr -> {
|
||||
loanChargeValidator.validateRepaymentTypeTransactionNotBeforeAChargeRefund(tr.getLoan(), tr, "reversed");
|
||||
tr.reverse();
|
||||
downPaymentTransaction.ifPresent(transaction -> {
|
||||
loanChargeValidator.validateRepaymentTypeTransactionNotBeforeAChargeRefund(transaction.getLoan(), transaction, "reversed");
|
||||
transaction.reverse();
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(transaction, false, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+17
@@ -24,6 +24,10 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanAccrualAdjustmentTransactionBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanAccrualTransactionCreatedBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.interestpauses.service.LoanAccountTransfersService;
|
||||
@@ -56,6 +60,8 @@ public class ReprocessLoanTransactionsServiceImpl implements ReprocessLoanTransa
|
||||
private final LoanBalanceService loanBalanceService;
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
private final LoanTransactionService loanTransactionService;
|
||||
private final LoanJournalEntryPoster loanJournalEntryPoster;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
|
||||
@Override
|
||||
public void reprocessTransactions(final Loan loan) {
|
||||
@@ -191,8 +197,19 @@ public class ReprocessLoanTransactionsServiceImpl implements ReprocessLoanTransa
|
||||
|
||||
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newTransaction);
|
||||
|
||||
// Create journal entries for new transaction
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(newTransaction, false, false);
|
||||
if (oldTransaction == null && (newTransaction.isAccrual() || newTransaction.isAccrualAdjustment())) {
|
||||
final LoanTransactionBusinessEvent businessEvent = newTransaction.isAccrual()
|
||||
? new LoanAccrualTransactionCreatedBusinessEvent(newTransaction)
|
||||
: new LoanAccrualAdjustmentTransactionBusinessEvent(newTransaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(businessEvent);
|
||||
}
|
||||
|
||||
if (oldTransaction != null) {
|
||||
loanAccountTransfersService.updateLoanTransaction(oldTransaction.getId(), newTransaction);
|
||||
// Create reversal journal entries for old transaction if it exists (reverse-replay scenario)
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(oldTransaction, false, false);
|
||||
}
|
||||
}
|
||||
replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail);
|
||||
|
||||
+8
-17
@@ -64,7 +64,6 @@ import org.apache.fineract.portfolio.loanaccount.repository.LoanCapitalizedIncom
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanTransactionValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.BuyDownFeePlatformService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualTransactionBusinessEventService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualsProcessingService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanBalanceService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanDownPaymentHandlerService;
|
||||
@@ -94,7 +93,6 @@ public class LoanAdjustmentServiceImpl implements LoanAdjustmentService {
|
||||
private final LoanUtilService loanUtilService;
|
||||
private final LoanRepaymentScheduleInstallmentRepository loanRepaymentScheduleInstallmentRepository;
|
||||
private final LoanLifecycleStateMachine loanLifecycleStateMachine;
|
||||
private final LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService;
|
||||
private final LoanDownPaymentHandlerService loanDownPaymentHandlerService;
|
||||
private final LoanAccrualsProcessingService loanAccrualsProcessingService;
|
||||
private final LoanChargeValidator loanChargeValidator;
|
||||
@@ -115,9 +113,6 @@ public class LoanAdjustmentServiceImpl implements LoanAdjustmentService {
|
||||
ExternalId reversalTxnExternalId = parameter.getReversalTxnExternalId();
|
||||
String noteText = parameter.getNoteText();
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
final Money transactionAmountAsMoney = Money.of(loan.getCurrency(), transactionAmount);
|
||||
LoanTransaction newTransactionDetail = LoanTransaction.repaymentType(transactionToAdjust.getTypeOf(), loan.getOffice(),
|
||||
transactionAmountAsMoney, paymentDetail, transactionDate, txnExternalId, transactionToAdjust.getChargeRefundChargeType());
|
||||
@@ -220,12 +215,11 @@ public class LoanAdjustmentServiceImpl implements LoanAdjustmentService {
|
||||
loanTransactionValidator.validateRepaymentDateIsOnNonWorkingDay(newTransactionDetail.getTransactionDate(),
|
||||
holidayDetailDTO.getWorkingDays(), holidayDetailDTO.isAllowTransactionsOnNonWorkingDay());
|
||||
|
||||
adjustExistingTransaction(loan, newTransactionDetail, transactionToAdjust, existingTransactionIds, existingReversedTransactionIds,
|
||||
scheduleGeneratorDTO, reversalTxnExternalId);
|
||||
adjustExistingTransaction(loan, newTransactionDetail, transactionToAdjust, scheduleGeneratorDTO, reversalTxnExternalId);
|
||||
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan, true);
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan, true);
|
||||
}
|
||||
|
||||
boolean thereIsNewTransaction = newTransactionDetail.isGreaterThanZero();
|
||||
@@ -234,6 +228,7 @@ public class LoanAdjustmentServiceImpl implements LoanAdjustmentService {
|
||||
this.paymentDetailWritePlatformService.persistPaymentDetail(paymentDetail);
|
||||
}
|
||||
this.loanTransactionRepository.saveAndFlush(newTransactionDetail);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(newTransactionDetail, false, false);
|
||||
}
|
||||
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
@@ -267,7 +262,7 @@ public class LoanAdjustmentServiceImpl implements LoanAdjustmentService {
|
||||
loanLifecycleStateMachine.determineAndTransition(loan, loan.getLastUserTransactionDate());
|
||||
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
true);
|
||||
|
||||
this.loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||
|
||||
@@ -283,8 +278,7 @@ public class LoanAdjustmentServiceImpl implements LoanAdjustmentService {
|
||||
entityExternalId = newTransactionDetail.getExternalId();
|
||||
}
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(transactionToAdjust, false, false);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAdjustTransactionBusinessEvent(eventData));
|
||||
|
||||
@@ -300,12 +294,8 @@ public class LoanAdjustmentServiceImpl implements LoanAdjustmentService {
|
||||
}
|
||||
|
||||
public void adjustExistingTransaction(final Loan loan, final LoanTransaction newTransactionDetail,
|
||||
final LoanTransaction transactionForAdjustment, final List<Long> existingTransactionIds,
|
||||
final List<Long> existingReversedTransactionIds, final ScheduleGeneratorDTO scheduleGeneratorDTO,
|
||||
final LoanTransaction transactionForAdjustment, final ScheduleGeneratorDTO scheduleGeneratorDTO,
|
||||
final ExternalId reversalExternalId) {
|
||||
existingTransactionIds.addAll(loanTransactionRepository.findTransactionIdsByLoan(loan));
|
||||
existingReversedTransactionIds.addAll(loanTransactionRepository.findReversedTransactionIdsByLoan(loan));
|
||||
|
||||
loanTransactionValidator.validateActivityNotBeforeClientOrGroupTransferDate(loan, LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
|
||||
transactionForAdjustment.getTransactionDate());
|
||||
|
||||
@@ -336,6 +326,7 @@ public class LoanAdjustmentServiceImpl implements LoanAdjustmentService {
|
||||
loanTransaction, "reversed");
|
||||
loanTransaction.reverse();
|
||||
loanTransaction.manuallyAdjustedOrReversed();
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(loanTransaction, false, false);
|
||||
LoanAdjustTransactionBusinessEvent.Data eventData = new LoanAdjustTransactionBusinessEvent.Data(loanTransaction);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAdjustTransactionBusinessEvent(eventData));
|
||||
});
|
||||
|
||||
+38
-44
@@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.starter;
|
||||
|
||||
import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||
import org.apache.fineract.cob.service.LoanAccountLockService;
|
||||
import org.apache.fineract.infrastructure.accountnumberformat.domain.AccountNumberFormatRepositoryWrapper;
|
||||
import org.apache.fineract.infrastructure.codes.domain.CodeValueRepositoryWrapper;
|
||||
@@ -83,7 +82,6 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanSchedul
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleAssembler;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleCalculationPlatformService;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleHistoryWritePlatformService;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanAccountingBridgeMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanChargeMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanCollateralManagementMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanMapper;
|
||||
@@ -306,29 +304,27 @@ public class LoanAccountConfiguration {
|
||||
LoanAssembler loanAssembler, ChargeRepositoryWrapper chargeRepository,
|
||||
BusinessEventNotifierService businessEventNotifierService, LoanTransactionRepository loanTransactionRepository,
|
||||
AccountTransfersWritePlatformService accountTransfersWritePlatformService, LoanRepositoryWrapper loanRepositoryWrapper,
|
||||
JournalEntryWritePlatformService journalEntryWritePlatformService, LoanAccountDomainService loanAccountDomainService,
|
||||
LoanChargeRepository loanChargeRepository, LoanWritePlatformService loanWritePlatformService, LoanUtilService loanUtilService,
|
||||
LoanAccountDomainService loanAccountDomainService, LoanChargeRepository loanChargeRepository,
|
||||
LoanWritePlatformService loanWritePlatformService, LoanUtilService loanUtilService,
|
||||
LoanChargeReadPlatformService loanChargeReadPlatformService, LoanLifecycleStateMachine loanLifecycleStateMachine,
|
||||
AccountAssociationsReadPlatformService accountAssociationsReadPlatformService, FromJsonHelper fromApiJsonHelper,
|
||||
ConfigurationDomainService configurationDomainService,
|
||||
LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
|
||||
ExternalIdFactory externalIdFactory, AccountTransferDetailRepository accountTransferDetailRepository,
|
||||
LoanChargeAssembler loanChargeAssembler, PaymentDetailWritePlatformService paymentDetailWritePlatformService,
|
||||
NoteRepository noteRepository, LoanAccrualTransactionBusinessEventService loanAccrualTransactionBusinessEventService,
|
||||
LoanAccrualsProcessingService loanAccrualsProcessingService,
|
||||
NoteRepository noteRepository, LoanAccrualsProcessingService loanAccrualsProcessingService,
|
||||
LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator, LoanChargeValidator loanChargeValidator,
|
||||
LoanScheduleService loanScheduleService, ReprocessLoanTransactionsService reprocessLoanTransactionsService,
|
||||
LoanAccountService loanAccountService, LoanAdjustmentService loanAdjustmentService,
|
||||
LoanAccountingBridgeMapper loanAccountingBridgeMapper, LoanChargeService loanChargeService) {
|
||||
LoanAccountService loanAccountService, LoanAdjustmentService loanAdjustmentService, LoanChargeService loanChargeService,
|
||||
LoanJournalEntryPoster loanJournalEntryPoster) {
|
||||
return new LoanChargeWritePlatformServiceImpl(loanChargeApiJsonValidator, loanAssembler, chargeRepository,
|
||||
businessEventNotifierService, loanTransactionRepository, accountTransfersWritePlatformService, loanRepositoryWrapper,
|
||||
journalEntryWritePlatformService, loanAccountDomainService, loanChargeRepository, loanWritePlatformService, loanUtilService,
|
||||
loanChargeReadPlatformService, loanLifecycleStateMachine, accountAssociationsReadPlatformService, fromApiJsonHelper,
|
||||
configurationDomainService, loanRepaymentScheduleTransactionProcessorFactory, externalIdFactory,
|
||||
accountTransferDetailRepository, loanChargeAssembler, paymentDetailWritePlatformService, noteRepository,
|
||||
loanAccrualTransactionBusinessEventService, loanAccrualsProcessingService, loanDownPaymentTransactionValidator,
|
||||
loanAccountDomainService, loanChargeRepository, loanWritePlatformService, loanUtilService, loanChargeReadPlatformService,
|
||||
loanLifecycleStateMachine, accountAssociationsReadPlatformService, fromApiJsonHelper, configurationDomainService,
|
||||
loanRepaymentScheduleTransactionProcessorFactory, externalIdFactory, accountTransferDetailRepository, loanChargeAssembler,
|
||||
paymentDetailWritePlatformService, noteRepository, loanAccrualsProcessingService, loanDownPaymentTransactionValidator,
|
||||
loanChargeValidator, loanScheduleService, reprocessLoanTransactionsService, loanAccountService, loanAdjustmentService,
|
||||
loanAccountingBridgeMapper, loanChargeService);
|
||||
loanChargeService, loanJournalEntryPoster);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -415,10 +411,10 @@ public class LoanAccountConfiguration {
|
||||
LoanUpdateCommandFromApiJsonDeserializer loanUpdateCommandFromApiJsonDeserializer, LoanRepositoryWrapper loanRepositoryWrapper,
|
||||
LoanAccountDomainService loanAccountDomainService, NoteRepository noteRepository,
|
||||
LoanTransactionRepository loanTransactionRepository, LoanTransactionRelationRepository loanTransactionRelationRepository,
|
||||
LoanAssembler loanAssembler, JournalEntryWritePlatformService journalEntryWritePlatformService,
|
||||
CalendarInstanceRepository calendarInstanceRepository, PaymentDetailWritePlatformService paymentDetailWritePlatformService,
|
||||
HolidayRepositoryWrapper holidayRepository, ConfigurationDomainService configurationDomainService,
|
||||
WorkingDaysRepositoryWrapper workingDaysRepository, AccountTransfersWritePlatformService accountTransfersWritePlatformService,
|
||||
LoanAssembler loanAssembler, CalendarInstanceRepository calendarInstanceRepository,
|
||||
PaymentDetailWritePlatformService paymentDetailWritePlatformService, HolidayRepositoryWrapper holidayRepository,
|
||||
ConfigurationDomainService configurationDomainService, WorkingDaysRepositoryWrapper workingDaysRepository,
|
||||
AccountTransfersWritePlatformService accountTransfersWritePlatformService,
|
||||
AccountTransfersReadPlatformService accountTransfersReadPlatformService,
|
||||
AccountAssociationsReadPlatformService accountAssociationsReadPlatformService, LoanReadPlatformService loanReadPlatformService,
|
||||
FromJsonHelper fromApiJsonHelper, CalendarRepository calendarRepository,
|
||||
@@ -440,25 +436,24 @@ public class LoanAccountConfiguration {
|
||||
LoanDisbursementService loanDisbursementService, LoanScheduleService loanScheduleService,
|
||||
LoanChargeValidator loanChargeValidator, LoanOfficerService loanOfficerService,
|
||||
ReprocessLoanTransactionsService reprocessLoanTransactionsService, LoanAccountService loanAccountService,
|
||||
LoanJournalEntryPoster journalEntryPoster, LoanAdjustmentService loanAdjustmentService,
|
||||
LoanAccountingBridgeMapper loanAccountingBridgeMapper, LoanMapper loanMapper,
|
||||
LoanJournalEntryPoster journalEntryPoster, LoanAdjustmentService loanAdjustmentService, LoanMapper loanMapper,
|
||||
LoanTransactionProcessingService loanTransactionProcessingService, final LoanBalanceService loanBalanceService,
|
||||
LoanTransactionService loanTransactionService) {
|
||||
return new LoanWritePlatformServiceJpaRepositoryImpl(context, loanTransactionValidator, loanUpdateCommandFromApiJsonDeserializer,
|
||||
loanRepositoryWrapper, loanAccountDomainService, noteRepository, loanTransactionRepository,
|
||||
loanTransactionRelationRepository, loanAssembler, journalEntryWritePlatformService, calendarInstanceRepository,
|
||||
paymentDetailWritePlatformService, holidayRepository, configurationDomainService, workingDaysRepository,
|
||||
accountTransfersWritePlatformService, accountTransfersReadPlatformService, accountAssociationsReadPlatformService,
|
||||
loanReadPlatformService, fromApiJsonHelper, calendarRepository, loanScheduleHistoryWritePlatformService,
|
||||
loanApplicationValidator, accountAssociationRepository, accountTransferDetailRepository, businessEventNotifierService,
|
||||
guarantorDomainService, loanUtilService, entityDatatableChecksWritePlatformService, codeValueRepository,
|
||||
cashierTransactionDataValidator, glimRepository, loanRepository, repaymentWithPostDatedChecksAssembler,
|
||||
postDatedChecksRepository, loanRepaymentScheduleInstallmentRepository, loanLifecycleStateMachine, loanAccountLockService,
|
||||
externalIdFactory, loanAccrualTransactionBusinessEventService, errorHandler, loanDownPaymentHandlerService,
|
||||
loanTransactionAssembler, loanAccrualsProcessingService, loanOfficerValidator, loanDownPaymentTransactionValidator,
|
||||
loanDisbursementService, loanScheduleService, loanChargeValidator, loanOfficerService, reprocessLoanTransactionsService,
|
||||
loanAccountService, journalEntryPoster, loanAdjustmentService, loanAccountingBridgeMapper, loanMapper,
|
||||
loanTransactionProcessingService, loanBalanceService, loanTransactionService);
|
||||
loanTransactionRelationRepository, loanAssembler, calendarInstanceRepository, paymentDetailWritePlatformService,
|
||||
holidayRepository, configurationDomainService, workingDaysRepository, accountTransfersWritePlatformService,
|
||||
accountTransfersReadPlatformService, accountAssociationsReadPlatformService, loanReadPlatformService, fromApiJsonHelper,
|
||||
calendarRepository, loanScheduleHistoryWritePlatformService, loanApplicationValidator, accountAssociationRepository,
|
||||
accountTransferDetailRepository, businessEventNotifierService, guarantorDomainService, loanUtilService,
|
||||
entityDatatableChecksWritePlatformService, codeValueRepository, cashierTransactionDataValidator, glimRepository,
|
||||
loanRepository, repaymentWithPostDatedChecksAssembler, postDatedChecksRepository,
|
||||
loanRepaymentScheduleInstallmentRepository, loanLifecycleStateMachine, loanAccountLockService, externalIdFactory,
|
||||
loanAccrualTransactionBusinessEventService, errorHandler, loanDownPaymentHandlerService, loanTransactionAssembler,
|
||||
loanAccrualsProcessingService, loanOfficerValidator, loanDownPaymentTransactionValidator, loanDisbursementService,
|
||||
loanScheduleService, loanChargeValidator, loanOfficerService, reprocessLoanTransactionsService, loanAccountService,
|
||||
journalEntryPoster, loanAdjustmentService, loanMapper, loanTransactionProcessingService, loanBalanceService,
|
||||
loanTransactionService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -476,11 +471,12 @@ public class LoanAccountConfiguration {
|
||||
LoanRefundService loanRefundService, LoanRefundValidator loanRefundValidator,
|
||||
ReprocessLoanTransactionsService reprocessLoanTransactionsService,
|
||||
LoanTransactionProcessingService loanTransactionProcessingService, LoanLifecycleStateMachine loanLifecycleStateMachine,
|
||||
LoanBalanceService loanBalanceService, LoanTransactionService loanTransactionService) {
|
||||
LoanBalanceService loanBalanceService, LoanTransactionService loanTransactionService,
|
||||
LoanJournalEntryPoster journalEntryPoster) {
|
||||
return new LoanDownPaymentHandlerServiceImpl(loanTransactionRepository, businessEventNotifierService,
|
||||
loanDownPaymentTransactionValidator, loanScheduleService, loanRefundService, loanRefundValidator,
|
||||
reprocessLoanTransactionsService, loanTransactionProcessingService, loanLifecycleStateMachine, loanBalanceService,
|
||||
loanTransactionService);
|
||||
loanTransactionService, journalEntryPoster);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -493,19 +489,18 @@ public class LoanAccountConfiguration {
|
||||
@ConditionalOnMissingBean(LoanDisbursementService.class)
|
||||
public LoanDisbursementService loanDisbursementService(LoanChargeValidator loanChargeValidator,
|
||||
LoanDisbursementValidator loanDisbursementValidator, ReprocessLoanTransactionsService reprocessLoanTransactionsService,
|
||||
LoanChargeService loanChargeService, LoanBalanceService loanBalanceService) {
|
||||
LoanChargeService loanChargeService, LoanBalanceService loanBalanceService, LoanJournalEntryPoster journalEntryPoster,
|
||||
LoanTransactionRepository loanTransactionRepository) {
|
||||
return new LoanDisbursementService(loanChargeValidator, loanDisbursementValidator, reprocessLoanTransactionsService,
|
||||
loanChargeService, loanBalanceService);
|
||||
loanChargeService, loanBalanceService, journalEntryPoster, loanTransactionRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(LoanChargeService.class)
|
||||
public LoanChargeService loanChargeService(final LoanChargeValidator loanChargeValidator,
|
||||
final LoanTransactionProcessingService loanTransactionProcessingService,
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanBalanceService loanBalanceService,
|
||||
final LoanTransactionRepository loanTransactionRepository) {
|
||||
return new LoanChargeService(loanChargeValidator, loanTransactionProcessingService, loanLifecycleStateMachine, loanBalanceService,
|
||||
loanTransactionRepository);
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanBalanceService loanBalanceService) {
|
||||
return new LoanChargeService(loanChargeValidator, loanTransactionProcessingService, loanLifecycleStateMachine, loanBalanceService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -528,9 +523,8 @@ public class LoanAccountConfiguration {
|
||||
@ConditionalOnMissingBean(LoanRefundService.class)
|
||||
public LoanRefundService loanRefundService(final LoanRefundValidator loanRefundValidator,
|
||||
final LoanTransactionProcessingService loanTransactionProcessingService,
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransactionRepository loanTransactionRepository) {
|
||||
return new LoanRefundService(loanRefundValidator, loanTransactionProcessingService, loanLifecycleStateMachine,
|
||||
loanTransactionRepository);
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
||||
return new LoanRefundService(loanRefundValidator, loanTransactionProcessingService, loanLifecycleStateMachine);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
+1
-2
@@ -131,8 +131,7 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
|
||||
private AvroDateTimeMapper mapper;
|
||||
|
||||
private final LoanChargeService loanChargeService = new LoanChargeService(mock(LoanChargeValidator.class),
|
||||
mock(LoanTransactionProcessingService.class), mock(LoanLifecycleStateMachine.class), mock(LoanBalanceService.class),
|
||||
mock(LoanTransactionRepository.class));
|
||||
mock(LoanTransactionProcessingService.class), mock(LoanLifecycleStateMachine.class), mock(LoanBalanceService.class));
|
||||
|
||||
private MockedStatic<MoneyHelper> moneyHelper = Mockito.mockStatic(MoneyHelper.class);
|
||||
|
||||
|
||||
+4
-17
@@ -28,9 +28,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -194,6 +192,8 @@ class LoanAdjustmentServiceImplTest {
|
||||
private LoanAccrualsProcessingService loanAccrualsProcessingService;
|
||||
@Mock
|
||||
private LoanChargeValidator loanChargeValidator;
|
||||
@Mock
|
||||
private LoanJournalEntryPoster journalEntryPoster;
|
||||
|
||||
@Test
|
||||
void givenMerchantIssuedRefundTransactionWithRelatedTransactions_whenAdjustExistingTransaction_thenRelatedTransactionsAreReversedAndEventsTriggered() {
|
||||
@@ -204,9 +204,6 @@ class LoanAdjustmentServiceImplTest {
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = mock(ScheduleGeneratorDTO.class);
|
||||
ExternalId reversalExternalId = ExternalId.generate();
|
||||
|
||||
List<Long> existingTransactionIds = new ArrayList<>();
|
||||
List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
// Mock transaction type
|
||||
when(transactionForAdjustment.getTypeOf()).thenReturn(LoanTransactionType.MERCHANT_ISSUED_REFUND);
|
||||
when(transactionForAdjustment.isNotRepaymentLikeType()).thenReturn(false);
|
||||
@@ -233,16 +230,12 @@ class LoanAdjustmentServiceImplTest {
|
||||
List<LoanTransaction> loanTransactions = Arrays.asList(transactionForAdjustment, relatedTransaction);
|
||||
when(loan.getLoanTransactions()).thenReturn(loanTransactions);
|
||||
|
||||
// Mock methods called inside adjustExistingTransaction
|
||||
when(loanTransactionRepository.findTransactionIdsByLoan(loan)).thenReturn(Collections.emptyList());
|
||||
when(loanTransactionRepository.findReversedTransactionIdsByLoan(loan)).thenReturn(Collections.emptyList());
|
||||
doNothing().when(loanTransactionValidator).validateActivityNotBeforeClientOrGroupTransferDate(any(), any(), any());
|
||||
when(loan.isClosedWrittenOff()).thenReturn(false);
|
||||
when(newTransactionDetail.isRepaymentLikeType()).thenReturn(true);
|
||||
|
||||
// Act
|
||||
underTest.adjustExistingTransaction(loan, newTransactionDetail, transactionForAdjustment, existingTransactionIds,
|
||||
existingReversedTransactionIds, scheduleGeneratorDTO, reversalExternalId);
|
||||
underTest.adjustExistingTransaction(loan, newTransactionDetail, transactionForAdjustment, scheduleGeneratorDTO, reversalExternalId);
|
||||
|
||||
// Assert
|
||||
// Verify that related transaction is reversed and event is triggered
|
||||
@@ -265,9 +258,6 @@ class LoanAdjustmentServiceImplTest {
|
||||
ScheduleGeneratorDTO scheduleGeneratorDTO = mock(ScheduleGeneratorDTO.class);
|
||||
ExternalId reversalExternalId = ExternalId.generate();
|
||||
|
||||
List<Long> existingTransactionIds = new ArrayList<>();
|
||||
List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
// Mock transaction type
|
||||
when(transactionForAdjustment.getTypeOf()).thenReturn(LoanTransactionType.REPAYMENT);
|
||||
when(transactionForAdjustment.isNotRepaymentLikeType()).thenReturn(false);
|
||||
@@ -279,15 +269,12 @@ class LoanAdjustmentServiceImplTest {
|
||||
LoanTransaction unrelatedTransaction = mock(LoanTransaction.class);
|
||||
|
||||
// Mock methods called inside adjustExistingTransaction
|
||||
when(loanTransactionRepository.findTransactionIdsByLoan(loan)).thenReturn(Collections.emptyList());
|
||||
when(loanTransactionRepository.findReversedTransactionIdsByLoan(loan)).thenReturn(Collections.emptyList());
|
||||
doNothing().when(loanTransactionValidator).validateActivityNotBeforeClientOrGroupTransferDate(any(), any(), any());
|
||||
when(loan.isClosedWrittenOff()).thenReturn(false);
|
||||
when(newTransactionDetail.isRepaymentLikeType()).thenReturn(true);
|
||||
|
||||
// Act
|
||||
underTest.adjustExistingTransaction(loan, newTransactionDetail, transactionForAdjustment, existingTransactionIds,
|
||||
existingReversedTransactionIds, scheduleGeneratorDTO, reversalExternalId);
|
||||
underTest.adjustExistingTransaction(loan, newTransactionDetail, transactionForAdjustment, scheduleGeneratorDTO, reversalExternalId);
|
||||
|
||||
// Assert
|
||||
// Verify that no related transactions are reversed
|
||||
|
||||
+3
-13
@@ -19,10 +19,7 @@
|
||||
package org.apache.fineract.portfolio.loanaccount.service;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyList;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -35,7 +32,6 @@ import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
@@ -61,7 +57,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.SingleLoanChargeRepaymentScheduleProcessingWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanAccountingBridgeMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeApiJsonValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
|
||||
@@ -155,9 +150,6 @@ class LoanChargeWritePlatformServiceImplTest {
|
||||
@Mock
|
||||
private LoanAccountService loanAccountService;
|
||||
|
||||
@Mock
|
||||
private LoanAccountingBridgeMapper loanAccountingBridgeMapper;
|
||||
|
||||
@Mock
|
||||
private LoanChargeService loanChargeService;
|
||||
|
||||
@@ -170,6 +162,9 @@ class LoanChargeWritePlatformServiceImplTest {
|
||||
@Mock
|
||||
private LoanLifecycleStateMachine loanLifecycleStateMachine;
|
||||
|
||||
@Mock
|
||||
private LoanJournalEntryPoster journalEntryPoster;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
when(loanAssembler.assembleFrom(LOAN_ID)).thenReturn(loan);
|
||||
@@ -190,10 +185,6 @@ class LoanChargeWritePlatformServiceImplTest {
|
||||
when(loan.getCurrency()).thenReturn(monetaryCurrency);
|
||||
when(monetaryCurrency.getCode()).thenReturn(CURRENCY_CODE);
|
||||
when(loanAccountService.saveAndFlushLoanWithDataIntegrityViolationChecks(any())).thenReturn(loan);
|
||||
List<Long> existingTransactionIds = new ArrayList<>();
|
||||
List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
when(loanTransactionRepository.findTransactionIdsByLoan(loan)).thenReturn(existingTransactionIds);
|
||||
when(loanTransactionRepository.findReversedTransactionIdsByLoan(loan)).thenReturn(existingReversedTransactionIds);
|
||||
|
||||
when(loan.getLoanCharges()).thenReturn(new HashSet<>());
|
||||
when(loan.getDisbursementDate()).thenReturn(LocalDate.now(ZoneId.systemDefault()));
|
||||
@@ -209,7 +200,6 @@ class LoanChargeWritePlatformServiceImplTest {
|
||||
when(loan.isCashBasedAccountingEnabledOnLoanProduct()).thenReturn(false);
|
||||
when(loan.isUpfrontAccrualAccountingEnabledOnLoanProduct()).thenReturn(false);
|
||||
|
||||
when(loanAccountingBridgeMapper.deriveAccountingBridgeData(anyString(), anyList(), anyList(), anyBoolean(), any(Loan.class))).thenReturn(new AccountingBridgeDataDTO());
|
||||
doNothing().when(journalEntryWritePlatformService).createJournalEntriesForLoan(any(AccountingBridgeDataDTO.class));
|
||||
doNothing().when(loanChargeService).addLoanCharge(any(Loan.class), any(LoanCharge.class));
|
||||
}
|
||||
|
||||
+4
-1
@@ -117,6 +117,9 @@ public class LoanDownPaymentHandlerServiceImplTest {
|
||||
@Mock
|
||||
private LoanTransactionService loanTransactionService;
|
||||
|
||||
@Mock
|
||||
private LoanJournalEntryPoster loanJournalEntryPoster;
|
||||
|
||||
private LoanDownPaymentHandlerServiceImpl underTest;
|
||||
|
||||
@BeforeEach
|
||||
@@ -124,7 +127,7 @@ public class LoanDownPaymentHandlerServiceImplTest {
|
||||
underTest = new LoanDownPaymentHandlerServiceImpl(loanTransactionRepository, businessEventNotifierService,
|
||||
loanDownPaymentTransactionValidator, loanScheduleService, loanRefundService, loanRefundValidator,
|
||||
reprocessLoanTransactionsService, loanTransactionProcessingService, loanLifecycleStateMachine, loanBalanceService,
|
||||
loanTransactionService);
|
||||
loanTransactionService, loanJournalEntryPoster);
|
||||
moneyHelper.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.UP));
|
||||
moneyHelper.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.UP);
|
||||
tempConfigServiceMock.when(TemporaryConfigurationServiceContainer::isExternalIdAutoGenerationEnabled).thenReturn(true);
|
||||
|
||||
Reference in New Issue
Block a user