Skip to content

Commit

Permalink
Fix: Savings and Deposit undo transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
Jose Alberto Hernandez authored and alberto-art3ch committed Mar 18, 2024
1 parent 7155537 commit 9982407
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ public final class LoanProductDataValidator {
LoanProductConstants.ENABLE_DOWN_PAYMENT, LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT,
LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT, LoanProductConstants.REPAYMENT_START_DATE_TYPE,
LoanProductConstants.ENABLE_INSTALLMENT_LEVEL_DELINQUENCY, LoanProductConstants.LOAN_SCHEDULE_TYPE,
LoanProductConstants.LOAN_SCHEDULE_PROCESSING_TYPE, LoanProductConstants.FIXED_LENGTH, LoanProductConstants.ALLOW_ACCRUAL_POSTING_IN_ARREARS));
LoanProductConstants.LOAN_SCHEDULE_PROCESSING_TYPE, LoanProductConstants.FIXED_LENGTH,
LoanProductConstants.ALLOW_ACCRUAL_POSTING_IN_ARREARS));

private static final String[] SUPPORTED_LOAN_CONFIGURABLE_ATTRIBUTES = { LoanProductConstants.amortizationTypeParamName,
LoanProductConstants.interestTypeParamName, LoanProductConstants.transactionProcessingStrategyCodeParamName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/
package org.apache.fineract.portfolio.savings.domain;

import static org.apache.fineract.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME;

import java.math.BigDecimal;
import java.math.MathContext;
import java.time.LocalDate;
Expand All @@ -31,7 +33,11 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.exception.PlatformServiceUnavailableException;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.event.business.domain.savings.transaction.SavingsDepositBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.savings.transaction.SavingsWithdrawalBusinessEvent;
Expand All @@ -40,10 +46,16 @@
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.exception.ClientNotActiveException;
import org.apache.fineract.portfolio.group.domain.Group;
import org.apache.fineract.portfolio.group.exception.GroupNotActiveException;
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
import org.apache.fineract.portfolio.savings.SavingsAccountTransactionType;
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
import org.apache.fineract.portfolio.savings.SavingsTransactionBooleanValues;
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionDTO;
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionDataValidator;
import org.apache.fineract.portfolio.savings.domain.interest.PostingPeriod;
import org.apache.fineract.portfolio.savings.exception.DepositAccountTransactionNotAllowedException;
import org.springframework.stereotype.Service;
Expand All @@ -57,6 +69,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
private final PlatformSecurityContext context;
private final SavingsAccountRepositoryWrapper savingsAccountRepository;
private final SavingsAccountTransactionRepository savingsAccountTransactionRepository;
private final SavingsAccountTransactionDataValidator savingsAccountTransactionDataValidator;
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
private final ConfigurationDomainService configurationDomainService;
private final DepositAccountOnHoldTransactionRepository depositAccountOnHoldTransactionRepository;
Expand Down Expand Up @@ -485,14 +498,96 @@ public void postInterest(SavingsAccount account, final MathContext mc, final Loc
}

@Override
public void reverseTransfer(SavingsAccountTransaction savingsTransaction, boolean backdatedTxnsAllowedTill) {
final SavingsAccount account = savingsTransaction.getSavingsAccount();
public void reverseTransfer(SavingsAccountTransaction savingsAccountTransaction, boolean backdatedTxnsAllowedTill) {
final SavingsAccount account = savingsAccountTransaction.getSavingsAccount();
account.setHelpers(savingsAccountTransactionSummaryWrapper, savingsHelper);

List<SavingsAccountTransaction> savingsAccountTransactions = new ArrayList<>();
savingsAccountTransactions.add(savingsTransaction);
undoTransaction(account, savingsAccountTransaction);
}

@Override
public void undoTransaction(SavingsAccount account, SavingsAccountTransaction savingsAccountTransaction) {

final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth();
final Set<Long> existingTransactionIds = new HashSet<>();
final Set<Long> existingReversedTransactionIds = new HashSet<>();
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);

final Long savingsId = account.getId();
final Long transactionId = savingsAccountTransaction.getId();

this.savingsAccountTransactionDataValidator.validateTransactionWithPivotDate(savingsAccountTransaction.getTransactionDate(),
account);

if (!account.allowModify()) {
throw new PlatformServiceUnavailableException("error.msg.saving.account.transaction.update.not.allowed",
"Savings account transaction:" + transactionId + " update not allowed for this savings type", transactionId);
}

final LocalDate today = DateUtils.getBusinessLocalDate();
final MathContext mc = new MathContext(15, MoneyHelper.getRoundingMode());

if (account.isNotActive()) {
throwValidationExceptionForActiveStatus(SavingsApiConstants.undoTransactionAction);
}
account.undoTransaction(transactionId);

// undoing transaction is withdrawal then undo withdrawal fee transaction if any
if (savingsAccountTransaction.isWithdrawal()) {
final SavingsAccountTransaction nextSavingsAccountTransaction = this.savingsAccountTransactionRepository
.findOneByIdAndSavingsAccountId(transactionId + 1, savingsId);
if (nextSavingsAccountTransaction != null && nextSavingsAccountTransaction.isWithdrawalFeeAndNotReversed()) {
account.undoTransaction(transactionId + 1);
}
}
boolean isInterestTransfer = false;
LocalDate postInterestOnDate = null;
boolean postReversals = false;
checkClientOrGroupActive(account);
if (savingsAccountTransaction.isPostInterestCalculationRequired()
&& account.isBeforeLastPostingPeriod(savingsAccountTransaction.getTransactionDate(), false)) {
postInterest(account, mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
postInterestOnDate, false, postReversals);
} else {
account.calculateInterestUsing(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth, postInterestOnDate, false, postReversals);
}
List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions = null;
if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) > 0) {
depositAccountOnHoldTransactions = this.depositAccountOnHoldTransactionRepository
.findBySavingsAccountAndReversedFalseOrderByCreatedDateAsc(account);
}
account.validateAccountBalanceDoesNotBecomeNegative(SavingsApiConstants.undoTransactionAction, depositAccountOnHoldTransactions,
false);
account.activateAccountBasedOnBalance();
savingsAccountRepository.saveAndFlush(account);

postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, false);
}

handleReversal(account, savingsAccountTransactions, backdatedTxnsAllowedTill);
private void throwValidationExceptionForActiveStatus(final String actionName) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(SAVINGS_ACCOUNT_RESOURCE_NAME + actionName);
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("account.is.not.active");
throw new PlatformApiDataValidationException(dataValidationErrors);
}

@Override
public void checkClientOrGroupActive(final SavingsAccount account) {
final Client client = account.getClient();
if (client != null) {
if (client.isNotActive()) {
throw new ClientNotActiveException(client.getId());
}
}
final Group group = account.group();
if (group != null) {
if (group.isNotActive()) {
throw new GroupNotActiveException(group.getId());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ void postInterest(SavingsAccount account, MathContext mc, LocalDate interestPost

void reverseTransfer(SavingsAccountTransaction savingsTransaction, boolean backdatedTxnsAllowedTill);

void undoTransaction(SavingsAccount account, SavingsAccountTransaction savingsAccountTransaction);

void checkClientOrGroupActive(SavingsAccount account);

}

0 comments on commit 9982407

Please sign in to comment.