This is an automated email from the ASF dual-hosted git repository.
manojvm pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new d388a3aa3 fix for 1665 and 1666 (#2441)
d388a3aa3 is described below
commit d388a3aa35da925b5479509ce99c8f6263f6d19f
Author: logoutdhaval <[email protected]>
AuthorDate: Sun Jul 24 01:19:54 2022 +0530
fix for 1665 and 1666 (#2441)
Co-authored-by: Dhaval Maniyar <[email protected]>
---
.../savings/data/SavingsAccountSummaryData.java | 8 +-
.../savings/domain/RecurringDepositAccount.java | 8 +-
.../portfolio/savings/domain/SavingsAccount.java | 112 ++++++++++----
.../savings/domain/SavingsAccountAssembler.java | 22 ++-
.../domain/SavingsAccountDomainServiceJpa.java | 16 +-
.../domain/SavingsAccountRepositoryWrapper.java | 5 +
.../savings/domain/SavingsAccountSummary.java | 25 ++-
.../SavingsAccountTransactionRepository.java | 5 +
...countWritePlatformServiceJpaRepositoryImpl.java | 6 +-
...countWritePlatformServiceJpaRepositoryImpl.java | 6 +-
.../ClientSavingsIntegrationTest.java | 167 ++++++++++++++++++++-
11 files changed, 293 insertions(+), 87 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountSummaryData.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountSummaryData.java
index 145f3e19f..2af8f1484 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountSummaryData.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountSummaryData.java
@@ -256,7 +256,6 @@ public class SavingsAccountSummaryData implements
Serializable {
final SavingsAccountTransactionData savingsAccountTransaction =
savingsAccountTransactions.get(i);
if (savingsAccountTransaction.isInterestPostingAndNotReversed() &&
!savingsAccountTransaction.isReversalTransaction()
&& !isUpdated) {
-
setRunningBalanceOnPivotDate(savingsAccountTransaction.getRunningBalance(currency).getAmount());
setInterestPostedTillDate(savingsAccountTransaction.getTransactionDate());
isUpdated = true;
if (!backdatedTxnsAllowedTill) {
@@ -265,7 +264,6 @@ public class SavingsAccountSummaryData implements
Serializable {
}
if (savingsAccountTransaction.isOverdraftInterestAndNotReversed()
&& !savingsAccountTransaction.isReversalTransaction()
&& !isUpdated) {
-
setRunningBalanceOnPivotDate(savingsAccountTransaction.getRunningBalance(currency).getAmount());
setInterestPostedTillDate(savingsAccountTransaction.getTransactionDate());
isUpdated = true;
if (!backdatedTxnsAllowedTill) {
@@ -273,13 +271,13 @@ public class SavingsAccountSummaryData implements
Serializable {
}
}
if (backdatedTxnsAllowedTill) {
- if
(savingsAccountTransaction.isInterestPostingAndNotReversed()) {
+ if
(savingsAccountTransaction.isInterestPostingAndNotReversed() &&
!savingsAccountTransaction.isReversalTransaction()) {
interestTotal =
interestTotal.plus(savingsAccountTransaction.getAmount());
}
- if
(savingsAccountTransaction.isOverdraftInterestAndNotReversed()) {
+ if
(savingsAccountTransaction.isOverdraftInterestAndNotReversed() &&
!savingsAccountTransaction.isReversalTransaction()) {
overdraftInterestTotal =
overdraftInterestTotal.plus(savingsAccountTransaction.getAmount());
}
- if (savingsAccountTransaction.isWithHoldTaxAndNotReversed()) {
+ if (savingsAccountTransaction.isWithHoldTaxAndNotReversed() &&
!savingsAccountTransaction.isReversalTransaction()) {
withHoldTaxTotal =
withHoldTaxTotal.plus(savingsAccountTransaction.getAmount());
}
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
index 5a6027829..98e1a4823 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
@@ -541,10 +541,11 @@ public class RecurringDepositAccount extends
SavingsAccount {
final Money minRequiredOpeningBalance = Money.of(this.currency,
this.minRequiredOpeningBalance);
final boolean backdatedTxnsAllowedTill = false;
String refNo = null;
+ final Long relaxingDaysConfigForPivotDate =
this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
if (minRequiredOpeningBalance.isGreaterThanZero()) {
final SavingsAccountTransactionDTO transactionDTO = new
SavingsAccountTransactionDTO(fmt, getActivationLocalDate(),
minRequiredOpeningBalance.getAmount(), null,
DateUtils.getLocalDateTimeOfSystem(), user, accountType);
- deposit(transactionDTO, backdatedTxnsAllowedTill, refNo);
+ deposit(transactionDTO, backdatedTxnsAllowedTill,
relaxingDaysConfigForPivotDate, refNo);
// update existing transactions so derived balance fields are
// correct.
@@ -842,7 +843,7 @@ public class RecurringDepositAccount extends SavingsAccount
{
@Override
public SavingsAccountTransaction deposit(final
SavingsAccountTransactionDTO transactionDTO, final boolean
backdatedTxnsAllowedTill,
- final String refNo) {
+ final Long relaxingDaysConfigForPivotDate, final String refNo) {
if (isAccountMatured()) {
final String defaultUserMessage = "Transaction is not allowed.
Account is matured.";
@@ -880,7 +881,8 @@ public class RecurringDepositAccount extends SavingsAccount
{
throw new PlatformApiDataValidationException(dataValidationErrors);
}
- final SavingsAccountTransaction transaction =
super.deposit(transactionDTO, backdatedTxnsAllowedTill, refNo);
+ final SavingsAccountTransaction transaction =
super.deposit(transactionDTO, backdatedTxnsAllowedTill,
+ relaxingDaysConfigForPivotDate, refNo);
return transaction;
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
index 928531625..938666668 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
@@ -72,6 +72,7 @@ import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;
import org.apache.commons.lang3.StringUtils;
+import
org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
@@ -337,6 +338,8 @@ public class SavingsAccount extends
AbstractPersistableCustom {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "account", orphanRemoval
= true, fetch = FetchType.LAZY)
protected List<InteropIdentifier> identifiers = new ArrayList<>();
+ public transient ConfigurationDomainService configurationDomainService;
+
protected SavingsAccount() {
//
}
@@ -529,7 +532,12 @@ public class SavingsAccount extends
AbstractPersistableCustom {
if
(!interestPostingTransactionDate.isAfter(interestPostingUpToDate)) {
interestPostedToDate =
interestPostedToDate.plus(interestEarnedToBePostedForPeriod);
- final SavingsAccountTransaction postingTransaction =
findInterestPostingTransactionFor(interestPostingTransactionDate);
+ SavingsAccountTransaction postingTransaction = null;
+ if (backdatedTxnsAllowedTill) {
+ postingTransaction =
findInterestPostingSavingsTransactionWithPivotConfig(interestPostingTransactionDate);
+ } else {
+ postingTransaction =
findInterestPostingTransactionFor(interestPostingTransactionDate);
+ }
if (postingTransaction == null) {
SavingsAccountTransaction newPostingTransaction;
if
(interestEarnedToBePostedForPeriod.isGreaterThanOrEqualTo(Money.zero(currency)))
{
@@ -741,7 +749,7 @@ public class SavingsAccount extends
AbstractPersistableCustom {
SavingsAccountTransaction savingsTransaction = null;
List<SavingsAccountTransaction> trans = getTransactions();
for (final SavingsAccountTransaction transaction : trans) {
- if (transaction.isNotReversed() && transaction.occursOn(date)) {
+ if (transaction.isNotReversed() &&
!transaction.isReversalTransaction() && transaction.occursOn(date)) {
savingsTransaction = transaction;
break;
}
@@ -754,7 +762,7 @@ public class SavingsAccount extends
AbstractPersistableCustom {
SavingsAccountTransaction savingsTransaction = null;
List<SavingsAccountTransaction> trans =
getSavingsAccountTransactionsWithPivotConfig();
for (final SavingsAccountTransaction transaction : trans) {
- if (transaction.isNotReversed() && transaction.occursOn(date)) {
+ if (transaction.isNotReversed() &&
!transaction.isReversalTransaction() && transaction.occursOn(date)) {
savingsTransaction = transaction;
break;
}
@@ -765,7 +773,7 @@ public class SavingsAccount extends
AbstractPersistableCustom {
public List<LocalDate> getManualPostingDates() {
List<LocalDate> transactions = new ArrayList<>();
for (SavingsAccountTransaction trans : this.transactions) {
- if (trans.isInterestPosting() && trans.isNotReversed() &&
trans.isManualTransaction()) {
+ if (trans.isInterestPosting() && trans.isNotReversed() &&
!trans.isReversalTransaction() && trans.isManualTransaction()) {
transactions.add(trans.getTransactionLocalDate());
}
}
@@ -829,7 +837,12 @@ public class SavingsAccount extends
AbstractPersistableCustom {
final SavingsInterestCalculationDaysInYearType daysInYearType =
SavingsInterestCalculationDaysInYearType
.fromInt(this.interestCalculationDaysInYearType);
- List<LocalDate> postedAsOnDates = getManualPostingDates();
+ List<LocalDate> postedAsOnDates = null;
+ if (backdatedTxnsAllowedTill) {
+ postedAsOnDates = getManualPostingDatesWithPivotConfig();
+ } else {
+ postedAsOnDates = getManualPostingDates();
+ }
if (postInterestOnDate != null) {
postedAsOnDates.add(postInterestOnDate);
}
@@ -840,26 +853,20 @@ public class SavingsAccount extends
AbstractPersistableCustom {
final List<PostingPeriod> allPostingPeriods = new ArrayList<>();
Money periodStartingBalance;
- if (this.startInterestCalculationDate != null) {
+ if (this.startInterestCalculationDate != null &&
!this.getStartInterestCalculationDate().equals(this.getActivationLocalDate())) {
LocalDate startInterestCalculationDate =
this.startInterestCalculationDate;
- final SavingsAccountTransaction transaction =
findLastTransaction(startInterestCalculationDate);
+ SavingsAccountTransaction transaction = null;
+ if (backdatedTxnsAllowedTill) {
+ transaction =
findLastFilteredTransactionWithPivotConfig(startInterestCalculationDate);
+ } else {
+ transaction =
findLastTransaction(startInterestCalculationDate);
+ }
if (transaction == null) {
- final String defaultUserMessage = "No transactions were found
on the specified date "
- + getStartInterestCalculationDate().toString() + " for
account number " + this.accountNumber.toString()
- + " and resource id " + getId();
-
- final ApiParameterError error =
ApiParameterError.parameterError(
-
"error.msg.savingsaccount.transaction.incorrect.start.interest.calculation.date",
defaultUserMessage,
- "transactionDate",
getStartInterestCalculationDate().toString());
-
- final List<ApiParameterError> dataValidationErrors = new
ArrayList<>();
- dataValidationErrors.add(error);
-
- throw new
PlatformApiDataValidationException(dataValidationErrors);
+ periodStartingBalance = Money.zero(this.currency);
+ } else {
+ periodStartingBalance = Money.of(this.currency,
this.summary.getRunningBalanceOnPivotDate());
}
-
- periodStartingBalance =
transaction.getRunningBalance(this.currency);
} else {
periodStartingBalance = Money.zero(this.currency);
}
@@ -878,11 +885,19 @@ public class SavingsAccount extends
AbstractPersistableCustom {
isUserPosting = true;
}
- final PostingPeriod postingPeriod =
PostingPeriod.createFrom(periodInterval, periodStartingBalance,
- retreiveOrderedNonInterestPostingTransactions(),
this.currency, compoundingPeriodType, interestCalculationType,
- interestRateAsFraction, daysInYearType.getValue(),
upToInterestCalculationDate, interestPostTransactions,
- isInterestTransfer, minBalanceForInterestCalculation,
isSavingsInterestPostingAtCurrentPeriodEnd,
- overdraftInterestRateAsFraction,
minOverdraftForInterestCalculation, isUserPosting, financialYearBeginningMonth);
+ PostingPeriod postingPeriod = null;
+ List<SavingsAccountTransaction>
orderedNonInterestPostingTransactions = null;
+ if (backdatedTxnsAllowedTill) {
+ orderedNonInterestPostingTransactions =
retreiveOrderedNonInterestPostingSavingsTransactionsWithPivotConfig();
+ } else {
+ orderedNonInterestPostingTransactions =
retreiveOrderedNonInterestPostingTransactions();
+ }
+
+ postingPeriod = PostingPeriod.createFrom(periodInterval,
periodStartingBalance, orderedNonInterestPostingTransactions,
+ this.currency, compoundingPeriodType,
interestCalculationType, interestRateAsFraction, daysInYearType.getValue(),
+ upToInterestCalculationDate, interestPostTransactions,
isInterestTransfer, minBalanceForInterestCalculation,
+ isSavingsInterestPostingAtCurrentPeriodEnd,
overdraftInterestRateAsFraction, minOverdraftForInterestCalculation,
+ isUserPosting, financialYearBeginningMonth);
periodStartingBalance = postingPeriod.closingBalance();
@@ -1023,7 +1038,7 @@ public class SavingsAccount extends
AbstractPersistableCustom {
if (overdraftAmount.isGreaterThanZero()) {
accountTransaction.updateOverdraftAmount(overdraftAmount.getAmount());
}
- // accountTransaction.updateRunningBalance(runningBalance);
+ accountTransaction.updateRunningBalance(runningBalance);
if (backdatedTxnsAllowedTill) {
addTransactionToExisting(accountTransaction);
if (reversal != null) {
@@ -1068,18 +1083,21 @@ public class SavingsAccount extends
AbstractPersistableCustom {
}
public SavingsAccountTransaction deposit(final
SavingsAccountTransactionDTO transactionDTO, final boolean
backdatedTxnsAllowedTill,
- final String refNo) {
- return deposit(transactionDTO, SavingsAccountTransactionType.DEPOSIT,
backdatedTxnsAllowedTill, refNo);
+ final Long relaxingDaysConfigForPivotDate, final String refNo) {
+ return deposit(transactionDTO, SavingsAccountTransactionType.DEPOSIT,
backdatedTxnsAllowedTill, relaxingDaysConfigForPivotDate,
+ refNo);
}
public SavingsAccountTransaction dividendPayout(final
SavingsAccountTransactionDTO transactionDTO,
- final boolean backdatedTxnsAllowedTill) {
+ final boolean backdatedTxnsAllowedTill, final Long
relaxingDaysConfigForPivotDate) {
String refNo = null;
- return deposit(transactionDTO,
SavingsAccountTransactionType.DIVIDEND_PAYOUT, backdatedTxnsAllowedTill, refNo);
+ return deposit(transactionDTO,
SavingsAccountTransactionType.DIVIDEND_PAYOUT, backdatedTxnsAllowedTill,
+ relaxingDaysConfigForPivotDate, refNo);
}
public SavingsAccountTransaction deposit(final
SavingsAccountTransactionDTO transactionDTO,
- final SavingsAccountTransactionType savingsAccountTransactionType,
final boolean backdatedTxnsAllowedTill, final String refNo) {
+ final SavingsAccountTransactionType savingsAccountTransactionType,
final boolean backdatedTxnsAllowedTill,
+ final Long relaxingDaysConfigForPivotDate, final String refNo) {
final String resourceTypeName = depositAccountType().resourceName();
if (isNotActive()) {
final String defaultUserMessage = "Transaction is not allowed.
Account is not active.";
@@ -1117,6 +1135,9 @@ public class SavingsAccount extends
AbstractPersistableCustom {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
+ validatePivotDateTransaction(transactionDTO.getTransactionDate(),
backdatedTxnsAllowedTill, relaxingDaysConfigForPivotDate,
+ resourceTypeName);
+
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_DEPOSIT,
transactionDTO.getTransactionDate());
final Money amount = Money.of(this.currency,
transactionDTO.getTransactionAmount());
@@ -1144,6 +1165,25 @@ public class SavingsAccount extends
AbstractPersistableCustom {
return transaction;
}
+ public void validatePivotDateTransaction(LocalDate transactionDate, final
boolean backdatedTxnsAllowedTill,
+ final Long relaxingDaysConfigForPivotDate, final String
resourceTypeName) {
+ if (backdatedTxnsAllowedTill) {
+ if (this.getSummary().getLastInterestCalculationDate() != null &&
transactionDate
+
.isBefore(this.getSummary().getLastInterestCalculationDate().minusDays(relaxingDaysConfigForPivotDate)))
{
+ final Object[] defaultUserArgs =
Arrays.asList(transactionDate, getActivationLocalDate()).toArray();
+ final String defaultUserMessage = "Transaction date cannot be
before transactions pivot date.";
+ final ApiParameterError error =
ApiParameterError.parameterError(
+ "error.msg." + resourceTypeName +
".transaction.before.pivot.date", defaultUserMessage, "transactionDate",
+ defaultUserArgs);
+
+ final List<ApiParameterError> dataValidationErrors = new
ArrayList<>();
+ dataValidationErrors.add(error);
+
+ throw new
PlatformApiDataValidationException(dataValidationErrors);
+ }
+ }
+ }
+
public LocalDate getActivationLocalDate() {
return this.activatedOnDate;
}
@@ -1172,8 +1212,12 @@ public class SavingsAccount extends
AbstractPersistableCustom {
return startInterestCalculationLocalDate;
}
+ public void setStartInterestCalculationDate(LocalDate
startInterestCalculationDate) {
+ this.startInterestCalculationDate = startInterestCalculationDate;
+ }
+
public SavingsAccountTransaction withdraw(final
SavingsAccountTransactionDTO transactionDTO, final boolean applyWithdrawFee,
- final boolean backdatedTxnsAllowedTill, String refNo) {
+ final boolean backdatedTxnsAllowedTill, final Long
relaxingDaysConfigForPivotDate, String refNo) {
if (!isTransactionsAllowed()) {
@@ -1224,6 +1268,8 @@ public class SavingsAccount extends
AbstractPersistableCustom {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
+ validatePivotDateTransaction(transactionDTO.getTransactionDate(),
backdatedTxnsAllowedTill, relaxingDaysConfigForPivotDate,
+ "savingsaccount");
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_WITHDRAWAL,
transactionDTO.getTransactionDate());
if (applyWithdrawFee) {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java
index d3e34cbbb..fa234fcaa 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java
@@ -349,6 +349,16 @@ public class SavingsAccountAssembler {
LocalDate interestPostedTillDate =
account.getSummary().getInterestPostedTillDate();
savingsAccountTransactions =
this.savingsAccountRepository.findTransactionsAfterPivotDate(account,
interestPostedTillDate.minusDays(relaxingDaysForPivotDate));
+
+ savingsAccountTransactions.get(0).getSavingsAccount()
+
.setStartInterestCalculationDate(interestPostedTillDate.minusDays(relaxingDaysForPivotDate));
+ List<SavingsAccountTransaction> pivotDateTransaction =
this.savingsAccountRepository
+
.findTransactionRunningBalanceBeforePivotDate(account,
+
interestPostedTillDate.minusDays(relaxingDaysForPivotDate + 1));
+ if (pivotDateTransaction != null &&
!pivotDateTransaction.isEmpty()) {
+
account.getSummary().setRunningBalanceOnPivotDate(pivotDateTransaction.get(pivotDateTransaction.size()
- 1)
+
.getRunningBalance(account.getCurrency()).getAmount());
+ }
} else {
savingsAccountTransactions =
this.savingsAccountRepository.findTransactionsAfterPivotDate(account,
account.getSummary().getInterestPostedTillDate());
@@ -358,24 +368,12 @@ public class SavingsAccountAssembler {
// Update transient variable
account.setSavingsAccountTransactions(savingsAccountTransactions);
}
- // Update last running balance on account level
- if (savingsAccountTransactions != null &&
!savingsAccountTransactions.isEmpty()) {
-
account.getSummary().setRunningBalanceOnPivotDate(savingsAccountTransactions.get(savingsAccountTransactions.size()
- 1)
-
.getRunningBalance(account.getCurrency()).getAmount());
- }
} else {
savingsAccountTransactions =
this.savingsAccountRepository.findAllTransactions(account);
account.setSavingsAccountTransactions(savingsAccountTransactions);
}
}
- // Update last running balance on account level
- // if (savingsAccountTransactions != null &&
!savingsAccountTransactions.isEmpty()) {
- //
account.getSummary().setRunningBalanceOnPivotDate(savingsAccountTransactions.get(savingsAccountTransactions.size()
- // - 1)
- // .getRunningBalance(account.getCurrency()).getAmount());
- // }
-
account.setHelpers(this.savingsAccountTransactionSummaryWrapper,
this.savingsHelper);
return account;
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java
index 4806d5e91..555585145 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java
@@ -91,6 +91,7 @@ public class SavingsAccountDomainServiceJpa implements
SavingsAccountDomainServi
account.validateForDebitBlock();
final boolean isSavingsInterestPostingAtCurrentPeriodEnd =
this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
+ final Long relaxingDaysConfigForPivotDate =
this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
final Integer financialYearBeginningMonth =
this.configurationDomainService.retrieveFinancialYearBeginningMonth();
if (transactionBooleanValues.isRegularTransaction() &&
!account.allowWithdrawal()) {
throw new
DepositAccountTransactionNotAllowedException(account.getId(), "withdraw",
account.depositAccountType());
@@ -110,7 +111,7 @@ public class SavingsAccountDomainServiceJpa implements
SavingsAccountDomainServi
paymentDetail, DateUtils.getLocalDateTimeOfSystem(), user,
accountType);
UUID refNo = UUID.randomUUID();
final SavingsAccountTransaction withdrawal =
account.withdraw(transactionDTO, transactionBooleanValues.isApplyWithdrawFee(),
- backdatedTxnsAllowedTill, refNo.toString());
+ backdatedTxnsAllowedTill, relaxingDaysConfigForPivotDate,
refNo.toString());
final MathContext mc = MathContext.DECIMAL64;
final LocalDate today = DateUtils.getBusinessLocalDate();
@@ -134,7 +135,10 @@ public class SavingsAccountDomainServiceJpa implements
SavingsAccountDomainServi
depositAccountOnHoldTransactions, backdatedTxnsAllowedTill);
saveTransactionToGenerateTransactionId(withdrawal);
-
+ if (backdatedTxnsAllowedTill) {
+ // Update transactions separately
+
saveUpdatedTransactionsOfSavingsAccount(account.getSavingsAccountTransactionsWithPivotConfig());
+ }
this.savingsAccountRepository.save(account);
postJournalEntries(account, existingTransactionIds,
existingReversedTransactionIds, transactionBooleanValues.isAccountTransfer(),
@@ -174,7 +178,7 @@ public class SavingsAccountDomainServiceJpa implements
SavingsAccountDomainServi
final boolean isSavingsInterestPostingAtCurrentPeriodEnd =
this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth =
this.configurationDomainService.retrieveFinancialYearBeginningMonth();
-
+ final Long relaxingDaysConfigForPivotDate =
this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
if (isRegularTransaction && !account.allowDeposit()) {
throw new
DepositAccountTransactionNotAllowedException(account.getId(), "deposit",
account.depositAccountType());
}
@@ -193,7 +197,7 @@ public class SavingsAccountDomainServiceJpa implements
SavingsAccountDomainServi
paymentDetail, DateUtils.getLocalDateTimeOfSystem(), user,
accountType);
UUID refNo = UUID.randomUUID();
final SavingsAccountTransaction deposit =
account.deposit(transactionDTO, savingsAccountTransactionType,
backdatedTxnsAllowedTill,
- refNo.toString());
+ relaxingDaysConfigForPivotDate, refNo.toString());
final LocalDate postInterestOnDate = null;
final MathContext mc = MathContext.DECIMAL64;
@@ -292,6 +296,7 @@ public class SavingsAccountDomainServiceJpa implements
SavingsAccountDomainServi
final boolean isSavingsInterestPostingAtCurrentPeriodEnd =
this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth =
this.configurationDomainService.retrieveFinancialYearBeginningMonth();
+ final Long relaxingDaysConfigForPivotDate =
this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
final Set<Long> existingTransactionIds = new HashSet<>();
final Set<Long> existingReversedTransactionIds = new HashSet<>();
@@ -327,7 +332,8 @@ public class SavingsAccountDomainServiceJpa implements
SavingsAccountDomainServi
account.calculateInterestUsing(mc, today, isInterestTransfer,
isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth, postInterestOnDate,
backdatedTxnsAllowedTill, postReversals);
}
-
+
account.validatePivotDateTransaction(savingsAccountTransaction.getLastTransactionDate(),
backdatedTxnsAllowedTill,
+ relaxingDaysConfigForPivotDate, "savingsaccount");
account.validateAccountBalanceDoesNotBecomeNegativeMinimal(savingsAccountTransaction.getAmount(),
false);
account.activateAccountBasedOnBalance();
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepositoryWrapper.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepositoryWrapper.java
index 0746b5ea7..7b7c23869 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepositoryWrapper.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepositoryWrapper.java
@@ -134,6 +134,11 @@ public class SavingsAccountRepositoryWrapper {
return
this.savingsAccountTransactionRepository.findTransactionsAfterPivotDate(savingsAccount,
transactionDate);
}
+ public List<SavingsAccountTransaction>
findTransactionRunningBalanceBeforePivotDate(
+ @Param("savingsAccount") SavingsAccount savingsAccount,
@Param("date") LocalDate date) {
+ return
this.savingsAccountTransactionRepository.findTransactionRunningBalanceBeforePivotDate(savingsAccount,
date);
+ }
+
@Transactional
public List<SavingsAccountTransaction>
findAllTransactions(@Param("savingsAccount") SavingsAccount savingsAccount) {
return
this.savingsAccountTransactionRepository.findBySavingsAccount(savingsAccount);
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountSummary.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountSummary.java
index a44dbcf03..90a49ced9 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountSummary.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountSummary.java
@@ -117,7 +117,10 @@ public final class SavingsAccountSummary {
public void updateSummaryWithPivotConfig(final MonetaryCurrency currency,
final SavingsAccountTransactionSummaryWrapper wrapper,
final SavingsAccountTransaction transaction, final
List<SavingsAccountTransaction> savingsAccountTransactions) {
- if (transaction != null && !transaction.isReversalTransaction()) {
+ if (transaction != null) {
+ if (transaction.isReversalTransaction()) {
+ return;
+ }
Money transactionAmount = Money.of(currency,
transaction.getAmount());
switch
(SavingsAccountTransactionType.fromInt(transaction.getTypeOf())) {
case DEPOSIT:
@@ -188,12 +191,7 @@ public final class SavingsAccountSummary {
Money overdraftInterestTotal = Money.zero(currency);
this.totalDeposits = wrapper.calculateTotalDeposits(currency,
savingsAccountTransactions);
this.totalWithdrawals =
wrapper.calculateTotalWithdrawals(currency, savingsAccountTransactions);
- this.totalWithdrawalFees =
wrapper.calculateTotalWithdrawalFees(currency, savingsAccountTransactions);
- this.totalAnnualFees = wrapper.calculateTotalAnnualFees(currency,
savingsAccountTransactions);
- this.totalFeeCharge = wrapper.calculateTotalFeesCharge(currency,
savingsAccountTransactions);
- this.totalPenaltyCharge =
wrapper.calculateTotalPenaltyCharge(currency, savingsAccountTransactions);
- this.totalFeeChargesWaived =
wrapper.calculateTotalFeesChargeWaived(currency, savingsAccountTransactions);
- this.totalPenaltyChargesWaived =
wrapper.calculateTotalPenaltyChargeWaived(currency, savingsAccountTransactions);
+
final HashMap<String, Money> map =
updateRunningBalanceAndPivotDate(true, savingsAccountTransactions,
interestTotal,
overdraftInterestTotal, withHoldTaxTotal, currency);
interestTotal = map.get("interestTotal");
@@ -202,12 +200,11 @@ public final class SavingsAccountSummary {
this.totalInterestPosted =
interestTotal.getAmountDefaultedToNullIfZero();
this.totalOverdraftInterestDerived =
overdraftInterestTotal.getAmountDefaultedToNullIfZero();
this.totalWithholdTax =
withHoldTaxTotal.getAmountDefaultedToNullIfZero();
- this.accountBalance = Money.of(currency,
this.totalDeposits).plus(this.totalInterestPosted).minus(this.totalWithdrawals)
-
.minus(this.totalWithdrawalFees).minus(this.totalAnnualFees).minus(this.totalFeeCharge).minus(this.totalPenaltyCharge)
-
.minus(this.totalOverdraftInterestDerived).minus(totalWithholdTax).getAmount();
- // this.accountBalance = Money.of(currency,
- //
this.accountBalance).plus(this.totalInterestPosted).minus(this.totalWithholdTax)
- // .getAmount();
+
+ this.accountBalance = getRunningBalanceOnPivotDate();
+ this.accountBalance = Money.of(currency,
this.accountBalance).plus(Money.of(currency, this.totalDeposits))
+
.plus(this.totalInterestPosted).minus(this.totalWithdrawals).minus(this.totalWithholdTax)
+ .minus(this.totalOverdraftInterestDerived).getAmount();
}
}
@@ -221,7 +218,6 @@ public final class SavingsAccountSummary {
final SavingsAccountTransaction savingsAccountTransaction =
savingsAccountTransactions.get(i);
if (savingsAccountTransaction.isInterestPostingAndNotReversed() &&
!savingsAccountTransaction.isReversalTransaction()
&& !isUpdated) {
-
setRunningBalanceOnPivotDate(savingsAccountTransaction.getRunningBalance(currency).getAmount());
setInterestPostedTillDate(savingsAccountTransaction.getLastTransactionDate());
isUpdated = true;
if (!backdatedTxnsAllowedTill) {
@@ -230,7 +226,6 @@ public final class SavingsAccountSummary {
}
if (savingsAccountTransaction.isOverdraftInterestAndNotReversed()
&& !savingsAccountTransaction.isReversalTransaction()
&& !isUpdated) {
-
setRunningBalanceOnPivotDate(savingsAccountTransaction.getRunningBalance(currency).getAmount());
setInterestPostedTillDate(savingsAccountTransaction.getLastTransactionDate());
isUpdated = true;
if (!backdatedTxnsAllowedTill) {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionRepository.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionRepository.java
index c40bf9d89..6d2db4080 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionRepository.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionRepository.java
@@ -39,6 +39,11 @@ public interface SavingsAccountTransactionRepository
List<SavingsAccountTransaction>
findTransactionsAfterPivotDate(@Param("savingsAccount") SavingsAccount
savingsAccount,
@Param("transactionDate") LocalDate transactionDate);
+ @Lock(LockModeType.PESSIMISTIC_WRITE)
+ @Query("select st from SavingsAccountTransaction st where
st.savingsAccount = :savingsAccount and st.dateOf = :date and
st.reversalTransaction <> 1 and st.reversed <> 1 order by st.id")
+ List<SavingsAccountTransaction>
findTransactionRunningBalanceBeforePivotDate(@Param("savingsAccount")
SavingsAccount savingsAccount,
+ @Param("date") LocalDate date);
+
@Lock(LockModeType.PESSIMISTIC_WRITE)
List<SavingsAccountTransaction>
findBySavingsAccount(@Param("savingsAccount") SavingsAccount savingsAccount);
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
index aadea8e85..3aab8ef0a 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -703,7 +703,7 @@ public class
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
final boolean isSavingsInterestPostingAtCurrentPeriodEnd =
this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth =
this.configurationDomainService.retrieveFinancialYearBeginningMonth();
-
+ final Long relaxingDaysConfigForPivotDate =
this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
this.depositAccountTransactionDataValidator.validate(command,
DepositAccountType.RECURRING_DEPOSIT);
final SavingsAccountTransaction savingsAccountTransaction =
this.savingsAccountTransactionRepository
@@ -750,11 +750,11 @@ public class
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
if (savingsAccountTransaction.isDeposit()) {
final SavingsAccountTransactionDTO transactionDTO = new
SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
paymentDetail, savingsAccountTransaction.getCreatedDate(),
user, accountType);
- transaction = account.deposit(transactionDTO, false,
refNo.toString());
+ transaction = account.deposit(transactionDTO, false,
relaxingDaysConfigForPivotDate, refNo.toString());
} else {
final SavingsAccountTransactionDTO transactionDTO = new
SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
paymentDetail, savingsAccountTransaction.getCreatedDate(),
user, accountType);
- transaction = account.withdraw(transactionDTO, true, false,
refNo.toString());
+ transaction = account.withdraw(transactionDTO, true, false,
relaxingDaysConfigForPivotDate, refNo.toString());
}
final Long newtransactionId =
saveTransactionToGenerateTransactionId(transaction);
boolean isInterestTransfer = false;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
index 35f567556..648a4bd0d 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -822,7 +822,7 @@ public class
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
final boolean isSavingsInterestPostingAtCurrentPeriodEnd =
this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth =
this.configurationDomainService.retrieveFinancialYearBeginningMonth();
-
+ final Long relaxingDaysConfigForPivotDate =
this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
final SavingsAccountTransaction savingsAccountTransaction =
this.savingsAccountTransactionRepository
.findOneByIdAndSavingsAccountId(transactionId, savingsId);
if (savingsAccountTransaction == null) {
@@ -882,9 +882,9 @@ public class
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
paymentDetail, savingsAccountTransaction.getCreatedDate(),
user, accountType);
UUID refNo = UUID.randomUUID();
if (savingsAccountTransaction.isDeposit()) {
- transaction = account.deposit(transactionDTO, false,
refNo.toString());
+ transaction = account.deposit(transactionDTO, false,
relaxingDaysConfigForPivotDate, refNo.toString());
} else {
- transaction = account.withdraw(transactionDTO, true, false,
refNo.toString());
+ transaction = account.withdraw(transactionDTO, true, false,
relaxingDaysConfigForPivotDate, refNo.toString());
}
final Long newtransactionId =
saveTransactionToGenerateTransactionId(transaction);
final LocalDate postInterestOnDate = null;
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java
index f0512f740..d12abc8a3 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java
@@ -76,6 +76,8 @@ public class ClientSavingsIntegrationTest {
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
private SavingsAccountHelper savingsAccountHelper;
+ private SavingsProductHelper savingsProductHelper;
+ private SchedulerJobHelper scheduleJobHelper;
@BeforeEach
public void setup() {
@@ -2820,9 +2822,7 @@ public class ClientSavingsIntegrationTest {
@Test
public void testAccountBalanceAndTransactionRunningBalanceWithConfigOn() {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec,
this.responseSpec);
-
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec,
this.responseSpec, "38", false);
-
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec,
this.responseSpec, "39", true);
-
GlobalConfigurationHelper.updateValueForGlobalConfiguration(requestSpec,
responseSpec, "39", "5");
+ configurationForBackdatedTransaction();
final Integer clientID = ClientHelper.createClient(this.requestSpec,
this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec,
this.responseSpec, clientID);
@@ -2843,17 +2843,19 @@ public class ClientSavingsIntegrationTest {
savingsStatusHashMap =
this.savingsAccountHelper.activateSavings(savingsId);
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
-
+ LocalDate transactionDate =
LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(5);
+ final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd
MMMM yyyy");
+ String startDate = formatter.format(transactionDate);
// withdrawal transaction 1
- Integer withdrawalTransactionId = (Integer)
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "500",
- SavingsAccountHelper.TRANSACTION_DATE,
CommonConstants.RESPONSE_RESOURCE_ID);
+ Integer withdrawalTransactionId = (Integer)
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "500",
startDate,
+ CommonConstants.RESPONSE_RESOURCE_ID);
HashMap summary =
this.savingsAccountHelper.getSavingsSummary(savingsId);
Float balance = Float.parseFloat("-500.0");
assertEquals(balance, summary.get("accountBalance"), "Verifying
account balance is -500");
// withdrawal transaction 2
- withdrawalTransactionId = (Integer)
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "500",
- SavingsAccountHelper.TRANSACTION_DATE,
CommonConstants.RESPONSE_RESOURCE_ID);
+ withdrawalTransactionId = (Integer)
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "500",
startDate,
+ CommonConstants.RESPONSE_RESOURCE_ID);
summary = this.savingsAccountHelper.getSavingsSummary(savingsId);
balance = Float.parseFloat("-1000.0");
assertEquals(balance, summary.get("accountBalance"), "Verifying
account balance is -1000");
@@ -2866,6 +2868,155 @@ public class ClientSavingsIntegrationTest {
assertEquals(balance.toString(),
requestedTransaction.get("runningBalance").toString(), "Equality check for
Balance");
}
+ @Test
+ public void testRunningBalanceAfterWithdrawalWithBackdateConfigurationOn()
{
+ this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec,
this.responseSpec);
+ this.savingsProductHelper = new SavingsProductHelper();
+ this.scheduleJobHelper = new SchedulerJobHelper(requestSpec);
+ configurationForBackdatedTransaction();
+ LocalDate transactionDate =
LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(5);
+ final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd
MMMM yyyy");
+ String startDate = formatter.format(transactionDate);
+ String secondTrx = formatter.format(transactionDate.plusDays(1));
+ final String jobName = "Post Interest For Savings";
+ final Integer clientID = ClientHelper.createClient(this.requestSpec,
this.responseSpec, startDate);
+ Assertions.assertNotNull(clientID);
+
+ final Integer savingsId =
createSavingsAccountDailyPostingOverdraft(clientID, startDate);
+ this.savingsAccountHelper.depositToSavingsAccount(savingsId, "100",
startDate, CommonConstants.RESPONSE_RESOURCE_ID);
+ this.scheduleJobHelper.executeAndAwaitJob(jobName);
+ this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId,
"200", secondTrx, CommonConstants.RESPONSE_RESOURCE_ID);
+ HashMap<String, Object> summaryObj =
this.savingsAccountHelper.getSavingsSummary(savingsId);
+
+ assertEquals("-100.0822",
summaryObj.get("availableBalance").toString(), "Equality check for Balance");
+ }
+
+ @Test
+ public void testRunningBalanceAfterDepositWithBackdateConfigurationOn() {
+ this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec,
this.responseSpec);
+ this.savingsProductHelper = new SavingsProductHelper();
+ this.scheduleJobHelper = new SchedulerJobHelper(requestSpec);
+ configurationForBackdatedTransaction();
+ LocalDate transactionDate =
LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(5);
+ final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd
MMMM yyyy");
+ String startDate = formatter.format(transactionDate);
+ String secondTrx = formatter.format(transactionDate.plusDays(1));
+ final String jobName = "Post Interest For Savings";
+ final Integer clientID = ClientHelper.createClient(this.requestSpec,
this.responseSpec, startDate);
+ Assertions.assertNotNull(clientID);
+
+ final Integer savingsId =
createSavingsAccountDailyPostingOverdraft(clientID, startDate);
+ this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId,
"100", startDate, CommonConstants.RESPONSE_RESOURCE_ID);
+ this.scheduleJobHelper.executeAndAwaitJob(jobName);
+ this.savingsAccountHelper.depositToSavingsAccount(savingsId, "200",
secondTrx, CommonConstants.RESPONSE_RESOURCE_ID);
+ HashMap<String, Object> summaryObj =
this.savingsAccountHelper.getSavingsSummary(savingsId);
+ assertEquals("100.0822",
summaryObj.get("availableBalance").toString(), "Equality check for Balance");
+ }
+
+ @Test
+ public void
testRunningBalanceAfterWithdrawalReversalWithBackdateConfigurationOn() {
+ this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec,
this.responseSpec);
+ this.savingsProductHelper = new SavingsProductHelper();
+ this.scheduleJobHelper = new SchedulerJobHelper(requestSpec);
+ configurationForBackdatedTransaction();
+ LocalDate transactionDate =
LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(5);
+ final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd
MMMM yyyy");
+ String startDate = formatter.format(transactionDate);
+ String secondTrx = formatter.format(transactionDate.plusDays(1));
+ final String jobName = "Post Interest For Savings";
+ final Integer clientID = ClientHelper.createClient(this.requestSpec,
this.responseSpec, startDate);
+ Assertions.assertNotNull(clientID);
+
+ final Integer savingsId =
createSavingsAccountDailyPostingOverdraft(clientID, startDate);
+ this.savingsAccountHelper.depositToSavingsAccount(savingsId, "100",
startDate, CommonConstants.RESPONSE_RESOURCE_ID);
+ this.scheduleJobHelper.executeAndAwaitJob(jobName);
+
+ Integer withdrawalToReverse = (Integer)
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "200",
secondTrx,
+ CommonConstants.RESPONSE_RESOURCE_ID);
+ this.savingsAccountHelper.reverseSavingsAccountTransaction(savingsId,
withdrawalToReverse);
+ HashMap<String, Object> summaryObj =
this.savingsAccountHelper.getSavingsSummary(savingsId);
+
+ assertEquals("100.137", summaryObj.get("availableBalance").toString(),
"Equality check for Balance");
+ }
+
+ @Test
+ public void
testRunningBalanceAfterDepositReversalWithBackdateConfigurationOn() {
+ this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec,
this.responseSpec);
+ this.savingsProductHelper = new SavingsProductHelper();
+ this.scheduleJobHelper = new SchedulerJobHelper(requestSpec);
+ configurationForBackdatedTransaction();
+ LocalDate transactionDate =
LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(5);
+ final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd
MMMM yyyy");
+ String startDate = formatter.format(transactionDate);
+ String secondTrx = formatter.format(transactionDate.plusDays(1));
+ final String jobName = "Post Interest For Savings";
+ final Integer clientID = ClientHelper.createClient(this.requestSpec,
this.responseSpec, startDate);
+ Assertions.assertNotNull(clientID);
+
+ final Integer savingsId =
createSavingsAccountDailyPostingOverdraft(clientID, startDate);
+ this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId,
"100", startDate, CommonConstants.RESPONSE_RESOURCE_ID);
+ this.scheduleJobHelper.executeAndAwaitJob(jobName);
+ Integer depositToReverse = (Integer)
this.savingsAccountHelper.depositToSavingsAccount(savingsId, "200", secondTrx,
+ CommonConstants.RESPONSE_RESOURCE_ID);
+ this.savingsAccountHelper.reverseSavingsAccountTransaction(savingsId,
depositToReverse);
+
+ HashMap<String, Object> summaryObj =
this.savingsAccountHelper.getSavingsSummary(savingsId);
+ assertEquals("-100.137",
summaryObj.get("availableBalance").toString(), "Equality check for Balance");
+ }
+
+ @Test
+ public void testToPerformTransactionBeforePivotDate() {
+ this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec,
this.responseSpec);
+ this.savingsProductHelper = new SavingsProductHelper();
+ this.scheduleJobHelper = new SchedulerJobHelper(requestSpec);
+
+ configurationForBackdatedTransaction();
+
+ String transactionDate = "1 July 2022";
+
+ final Integer clientID = ClientHelper.createClient(this.requestSpec,
this.responseSpec, transactionDate);
+ Assertions.assertNotNull(clientID);
+
+ final Integer savingsId =
createSavingsAccountDailyPostingOverdraft(clientID, transactionDate);
+ this.savingsAccountHelper.depositToSavingsAccount(savingsId, "200",
transactionDate, CommonConstants.RESPONSE_RESOURCE_ID);
+ final String jobName = "Post Interest For Savings";
+ this.scheduleJobHelper.executeAndAwaitJob(jobName);
+ final ResponseSpecification errorResponse = new
ResponseSpecBuilder().expectStatusCode(403).build();
+ final SavingsAccountHelper validationErrorHelper = new
SavingsAccountHelper(this.requestSpec, errorResponse);
+ List<HashMap> error = (List<HashMap>)
validationErrorHelper.depositToSavingsAccount(savingsId, "3000",
transactionDate,
+ CommonConstants.RESPONSE_ERROR);
+
+ assertEquals("error.msg.savings.transaction.is.not.allowed",
error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+ }
+
+ private Integer createSavingsAccountDailyPostingOverdraft(final Integer
clientID, final String startDate) {
+ final Integer savingsProductID =
createSavingsProductDailyPostingOverdraft();
+ Assertions.assertNotNull(savingsProductID);
+ final Integer savingsId =
this.savingsAccountHelper.applyForSavingsApplicationOnDate(clientID,
savingsProductID,
+ ACCOUNT_TYPE_INDIVIDUAL, startDate);
+ Assertions.assertNotNull(savingsId);
+ HashMap savingsStatusHashMap =
this.savingsAccountHelper.approveSavingsOnDate(savingsId, startDate);
+ SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
+ savingsStatusHashMap =
this.savingsAccountHelper.activateSavingsAccount(savingsId, startDate);
+ SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
+ return savingsId;
+ }
+
+ private Integer createSavingsProductDailyPostingOverdraft() {
+ final String overDraftLimit = "10000.0";
+ final String nominalAnnualInterestRateOverdraft = "10";
+ final String savingsProductJSON =
this.savingsProductHelper.withInterestCompoundingPeriodTypeAsDaily()
+
.withInterestPostingPeriodTypeAsDaily().withInterestCalculationPeriodTypeAsDailyBalance()
+ .withOverDraftRate(overDraftLimit,
nominalAnnualInterestRateOverdraft).build();
+ return SavingsProductHelper.createSavingsProduct(savingsProductJSON,
requestSpec, responseSpec);
+ }
+
+ public void configurationForBackdatedTransaction() {
+
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec,
this.responseSpec, "38", false);
+
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec,
this.responseSpec, "39", true);
+
GlobalConfigurationHelper.updateValueForGlobalConfiguration(requestSpec,
responseSpec, "39", "5");
+ }
+
@AfterEach
public void tearDown() {
GlobalConfigurationHelper.resetAllDefaultGlobalConfigurations(this.requestSpec,
this.responseSpec);