Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fineract-1646 and fineract-1638 combined fix #2457

Merged
merged 1 commit into from
Jul 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -366,10 +366,6 @@ public Long getGlAccountIdForInterestOnSavings() {
return this.glAccountIdForInterestOnSavings;
}

public SavingsAccountSummaryData getSavingsAccountSummaryData() {
return this.savingsAccountSummaryData;
}

public List<SavingsAccountTransactionData> getSavingsAccountTransactionData() {
return this.savingsAccountTransactionData;
}
Expand Down Expand Up @@ -417,7 +413,7 @@ public SavingsAccountTransactionData findLastTransaction(final LocalDate date) {
SavingsAccountTransactionData savingsTransaction = null;
List<SavingsAccountTransactionData> trans = getTransactions();
for (final SavingsAccountTransactionData transaction : trans) {
if (transaction.isNotReversed() && transaction.occursOn(date)) {
if (transaction.isNotReversed() && !transaction.isReversalTransaction() && transaction.occursOn(date)) {
savingsTransaction = transaction;
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,10 @@ public BigDecimal getRunningBalanceOnPivotDate() {
public void updateSummaryWithPivotConfig(final CurrencyData currency, final SavingsAccountTransactionSummaryWrapper wrapper,
final SavingsAccountTransaction transaction, final List<SavingsAccountTransactionData> 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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@ public LocalDate getTransactionLocalDate() {
return this.transactionDate;
}

public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, final LocalDateInterval boundedBy) {
public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, final LocalDateInterval boundedBy,
final boolean isAllowOverdraft) {

final MonetaryCurrency currency = openingBalance.getCurrency();
Money endOfDayBalance = openingBalance.copy();
Expand All @@ -263,7 +264,7 @@ public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, fi
if (isDeposit() || isDividendPayoutAndNotReversed()) {
endOfDayBalance = endOfDayBalance.plus(getAmount());
} else if (isWithdrawal() || isChargeTransactionAndNotReversed()) {
if (endOfDayBalance.isGreaterThanZero()) {
if (endOfDayBalance.isGreaterThanZero() || isAllowOverdraft) {
endOfDayBalance = endOfDayBalance.minus(getAmount());
} else {
endOfDayBalance = Money.of(currency, this.runningBalance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1168,8 +1168,8 @@ public SavingsAccountTransaction deposit(final SavingsAccountTransactionDTO tran
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))) {
if (this.getSummary().getInterestPostedTillDate() != null
&& transactionDate.isBefore(this.getSummary().getInterestPostedTillDate().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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public static PostingPeriod createFromDTO(final LocalDateInterval periodInterval
final LocalDate upToInterestCalculationDate, Collection<Long> interestPostTransactions, boolean isInterestTransfer,
final Money minBalanceForInterestCalculation, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
final BigDecimal overdraftInterestRateAsFraction, final Money minOverdraftForInterestCalculation, boolean isUserPosting,
int financialYearBeginningMonth) {
int financialYearBeginningMonth, final boolean isAllowOverdraft) {

final List<EndOfDayBalance> accountEndOfDayBalances = new ArrayList<>();
boolean interestTransfered = false;
Expand All @@ -182,7 +182,8 @@ public static PostingPeriod createFromDTO(final LocalDateInterval periodInterval
openingDayBalance = endOfDayBalance.closingBalance();

} else if (transaction.spansAnyPortionOf(periodInterval)) {
final EndOfDayBalance endOfDayBalance = transaction.toEndOfDayBalanceBoundedBy(openingDayBalance, periodInterval);
final EndOfDayBalance endOfDayBalance = transaction.toEndOfDayBalanceBoundedBy(openingDayBalance, periodInterval,
isAllowOverdraft);
accountEndOfDayBalances.add(endOfDayBalance);

closeOfDayBalance = endOfDayBalance.closingBalance();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.domain.LocalDateInterval;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.portfolio.savings.DepositAccountType;
Expand Down Expand Up @@ -72,7 +70,7 @@ public SavingsAccountData postInterest(final MathContext mc, final LocalDate int
interestPostedToDate = Money.of(savingsAccountData.currency(), savingsAccountData.getSummary().getTotalInterestPosted());
SavingsAccountTransactionData savingsAccountTransactionData = retrieveLastTransactions(savingsAccountData);
LocalDate lastTransactionDate = savingsAccountTransactionData.getLastTransactionDate();
savingsAccountData.setStartInterestCalculationDate(lastTransactionDate);
savingsAccountData.setStartInterestCalculationDate(lastTransactionDate.plusDays(1));
} else {
savingsAccountData.setStartInterestCalculationDate(startInterestDate);
}
Expand Down Expand Up @@ -251,21 +249,12 @@ public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final Lo
final SavingsAccountTransactionData transaction = retrieveLastTransactions(savingsAccountData);

if (transaction == null) {
final String defaultUserMessage = "No transactions were found on the specified date "
+ savingsAccountData.getStartInterestCalculationDate().toString() + " for account number "
+ savingsAccountData.getAccountNo() + " and resource id " + savingsAccountData.getId();

final ApiParameterError error = ApiParameterError.parameterError(
"error.msg.savingsaccount.transaction.incorrect.start.interest.calculation.date", defaultUserMessage,
"transactionDate", savingsAccountData.getStartInterestCalculationDate().toString());

final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
dataValidationErrors.add(error);

throw new PlatformApiDataValidationException(dataValidationErrors);
periodStartingBalance = Money.zero(savingsAccountData.currency());
} else {
periodStartingBalance = Money.of(savingsAccountData.currency(),
savingsAccountData.getSummary().getRunningBalanceOnPivotDate());
}

periodStartingBalance = transaction.getRunningBalance(savingsAccountData.currency());
} else {
periodStartingBalance = Money.zero(savingsAccountData.currency());
}
Expand All @@ -292,7 +281,7 @@ public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final Lo
interestCalculationType, interestRateAsFraction, daysInYearType.getValue(), upToInterestCalculationDate,
interestPostTransactions, isInterestTransfer, minBalanceForInterestCalculation,
isSavingsInterestPostingAtCurrentPeriodEnd, overdraftInterestRateAsFraction, minOverdraftForInterestCalculation,
isUserPosting, financialYearBeginningMonth);
isUserPosting, financialYearBeginningMonth, savingsAccountData.isAllowOverdraft());

periodStartingBalance = postingPeriod.closingBalance();

Expand Down Expand Up @@ -322,7 +311,7 @@ private List<SavingsAccountTransactionData> retreiveOrderedNonInterestPostingTra

for (final SavingsAccountTransactionData transaction : listOfTransactionsSorted) {
if (!(transaction.isInterestPostingAndNotReversed() || transaction.isOverdraftInterestAndNotReversed())
&& transaction.isNotReversed()) {
&& transaction.isNotReversed() && !transaction.isReversalTransaction()) {
orderedNonInterestPostingTransactions.add(transaction);
}
}
Expand All @@ -331,10 +320,6 @@ private List<SavingsAccountTransactionData> retreiveOrderedNonInterestPostingTra
}

private List<SavingsAccountTransactionData> retreiveListOfTransactions(final SavingsAccountData savingsAccountData) {
if (savingsAccountData.getTransactions() != null && savingsAccountData.getTransactions().size() == 1) {
return savingsAccountData.getTransactions();
}

final List<SavingsAccountTransactionData> listOfTransactionsSorted = new ArrayList<>();
listOfTransactionsSorted.addAll(savingsAccountData.getTransactions());

Expand Down Expand Up @@ -405,7 +390,7 @@ public LocalDate getActivationLocalDate(final SavingsAccountData savingsAccountD
public List<LocalDate> getManualPostingDates(final SavingsAccountData savingsAccountData) {
List<LocalDate> transactions = new ArrayList<>();
for (SavingsAccountTransactionData trans : savingsAccountData.getSavingsAccountTransactionData()) {
if (trans.isInterestPosting() && trans.isNotReversed() && trans.isManualTransaction()) {
if (trans.isInterestPosting() && trans.isNotReversed() && !trans.isReversalTransaction() && trans.isManualTransaction()) {
transactions.add(trans.getTransactionLocalDate());
}
}
Expand Down Expand Up @@ -444,7 +429,10 @@ protected void recalculateDailyBalances(final Money openingAccountBalance, final
}

runningBalance = runningBalance.plus(transactionAmount);
transaction.updateRunningBalance(runningBalance);
if (!transaction.getRunningBalance(transactionAmount.getCurrency()).isEqualTo(transactionAmount)) {
transaction.updateRunningBalance(runningBalance);
}
// transaction.updateRunningBalance(runningBalance);
if (overdraftAmount.isZero() && runningBalance.isLessThanZero()) {
overdraftAmount = overdraftAmount.plus(runningBalance.getAmount().negate());
}
Expand Down Expand Up @@ -522,7 +510,7 @@ protected SavingsAccountTransactionData findInterestPostingTransactionFor(final
List<SavingsAccountTransactionData> trans = savingsAccountData.getSavingsAccountTransactionData();
for (final SavingsAccountTransactionData transaction : trans) {
if ((transaction.isInterestPostingAndNotReversed() || transaction.isOverdraftInterestAndNotReversed())
&& transaction.occursOn(postingDate)) {
&& transaction.occursOn(postingDate) && !transaction.isReversalTransaction()) {
postingTransation = transaction;
break;
}
Expand All @@ -536,7 +524,7 @@ protected void resetAccountTransactionsEndOfDayBalances(final List<SavingsAccoun
LocalDate endOfBalanceDate = interestPostingUpToDate;
for (int i = accountTransactionsSorted.size() - 1; i >= 0; i--) {
final SavingsAccountTransactionData transaction = accountTransactionsSorted.get(i);
if (transaction.isNotReversed()
if (transaction.isNotReversed() && !transaction.isReversalTransaction()
&& !(transaction.isInterestPostingAndNotReversed() || transaction.isOverdraftInterestAndNotReversed())) {
transaction.updateCumulativeBalanceAndDates(MonetaryCurrency.fromCurrencyData(savingsAccountData.currency()),
endOfBalanceDate);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ private static final class SavingAccountMapperForInterestPosting implements Resu
sqlBuilder.append("tg.id as taxGroupId, ");
sqlBuilder.append("(select COALESCE(max(sat.transaction_date),sa.activatedon_date) ");
sqlBuilder.append("from m_savings_account_transaction as sat ");
sqlBuilder.append("where sat.is_reversed = false ");
sqlBuilder.append("where sat.is_reversed = false and sat.is_reversal = false ");
sqlBuilder.append("and sat.transaction_type_enum in (1,2) ");
sqlBuilder.append("and sat.savings_account_id = sa.id) as lastActiveTransactionDate, ");
sqlBuilder.append("sp.id as productId, ");
Expand Down Expand Up @@ -825,7 +825,7 @@ private static final class SavingAccountMapper implements RowMapper<SavingsAccou
sqlBuilder.append("tg.id as taxGroupId, tg.name as taxGroupName, ");
sqlBuilder.append("(select COALESCE(max(sat.transaction_date),sa.activatedon_date) ");
sqlBuilder.append("from m_savings_account_transaction as sat ");
sqlBuilder.append("where sat.is_reversed = false ");
sqlBuilder.append("where sat.is_reversed = false and sat.is_reversal = false ");
sqlBuilder.append("and sat.transaction_type_enum in (1,2) ");
sqlBuilder.append("and sat.savings_account_id = sa.id) as lastActiveTransactionDate, ");
sqlBuilder.append("sp.is_dormancy_tracking_active as isDormancyTrackingActive, ");
Expand Down Expand Up @@ -1684,7 +1684,7 @@ public List<Long> retrieveSavingsIdsPendingInactive(LocalDate tenantLocalDate) {
sql.append(" where sa.status_enum = 300 ");
sql.append(" and sa.sub_status_enum = 0 ");
String compareDate = "(select COALESCE(max(sat.transaction_date), sa.activatedon_date) "
+ "from m_savings_account_transaction as sat where sat.is_reversed = false"
+ "from m_savings_account_transaction as sat where sat.is_reversed = false and sat.is_reversal = false"
+ " and sat.transaction_type_enum in (1,2) and sat.savings_account_id = sa.id)";
sql.append(" and ").append(sqlGenerator.dateDiff("?", compareDate)).append(" >= sp.days_to_inactive ");

Expand All @@ -1708,7 +1708,7 @@ public List<Long> retrieveSavingsIdsPendingDormant(LocalDate tenantLocalDate) {
sql.append(" where sa.status_enum = 300 ");
sql.append(" and sa.sub_status_enum = 100 ");
sql.append(" and " + sqlGenerator.dateDiff("?",
"(select COALESCE(max(sat.transaction_date),sa.activatedon_date) from m_savings_account_transaction as sat where sat.is_reversed = false and sat.transaction_type_enum in (1,2) and sat.savings_account_id = sa.id)")
"(select COALESCE(max(sat.transaction_date),sa.activatedon_date) from m_savings_account_transaction as sat where sat.is_reversed = false and sat.is_reversal = false and sat.transaction_type_enum in (1,2) and sat.savings_account_id = sa.id)")
+ " ");
sql.append(" >= sp.days_to_dormancy ");

Expand All @@ -1732,7 +1732,7 @@ public List<Long> retrieveSavingsIdsPendingEscheat(LocalDate tenantLocalDate) {
sql.append(" where sa.status_enum = 300 ");
sql.append(" and sa.sub_status_enum = 200 ");
sql.append(" and " + sqlGenerator.dateDiff("?",
"(select COALESCE(max(sat.transaction_date),sa.activatedon_date) from m_savings_account_transaction as sat where sat.is_reversed = false and sat.transaction_type_enum in (1,2) and sat.savings_account_id = sa.id)")
"(select COALESCE(max(sat.transaction_date),sa.activatedon_date) from m_savings_account_transaction as sat where sat.is_reversed = false and sat.is_reversal = false and sat.transaction_type_enum in (1,2) and sat.savings_account_id = sa.id)")
+ " ");
sql.append(" >= sp.days_to_escheat ");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.math.BigDecimal;
import java.security.SecureRandom;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
Expand Down Expand Up @@ -270,6 +271,7 @@ private void batchUpdate(final List<SavingsAccountData> savingsAccountDataList)
.atStartOfDay(DateUtils.getDateTimeZoneOfTenant()).toInstant()),
savingsAccountData.getId() });
List<SavingsAccountTransactionData> savingsAccountTransactionDataList = savingsAccountData.getSavingsAccountTransactionData();
LocalDateTime currentDate = DateUtils.getLocalDateTimeOfTenant();
for (SavingsAccountTransactionData savingsAccountTransactionData : savingsAccountTransactionDataList) {
Date balanceEndDate = null;
if (savingsAccountTransactionData.getBalanceEndDate() != null) {
Expand All @@ -284,10 +286,9 @@ private void batchUpdate(final List<SavingsAccountData> savingsAccountDataList)
savingsAccountTransactionData.isReversed(), savingsAccountTransactionData.getTransactionType().getId(),
savingsAccountTransactionData.getTransactionDate(), savingsAccountTransactionData.getAmount(), balanceEndDate,
savingsAccountTransactionData.getBalanceNumberOfDays(), savingsAccountTransactionData.getRunningBalance(),
savingsAccountTransactionData.getCumulativeBalance(), savingsAccountTransactionData.getSubmittedOnDate(),
Integer.valueOf(1), savingsAccountTransactionData.isManualTransaction(),
savingsAccountTransactionData.getRefNo(), savingsAccountTransactionData.isReversalTransaction(),
savingsAccountTransactionData.getOverdraftAmount(), });
savingsAccountTransactionData.getCumulativeBalance(), currentDate, Integer.valueOf(1),
savingsAccountTransactionData.isManualTransaction(), savingsAccountTransactionData.getRefNo(),
savingsAccountTransactionData.isReversalTransaction(), savingsAccountTransactionData.getOverdraftAmount(), });
} else {
paramsForTransactionUpdate.add(new Object[] { savingsAccountTransactionData.isReversed(),
savingsAccountTransactionData.getAmount(), savingsAccountTransactionData.getOverdraftAmount(), balanceEndDate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public void postInterestForAccounts(Map<String, String> jobParameters) throws Jo
Long maxSavingsIdInList = 0L;
// initialise the executor service with fetched configurations
final ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
final boolean backdatedTxnsAllowedTill = this.configurationDomainService.retrievePivotDateConfig();
final boolean backdatedTxnsAllowedTill = false;

long start = System.currentTimeMillis();

Expand Down