FINERACT-2233: Rework journal entry handling logic in Loan module
This commit is contained in:
committed by
Adam Saghy
parent
942ad0183c
commit
ace59352fa
-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());
|
||||
|
||||
Reference in New Issue
Block a user