Skip to content

Commit

Permalink
fix: Savings account accrual in zero when overdraft
Browse files Browse the repository at this point in the history
  • Loading branch information
Jose Alberto Hernandez authored and alberto-art3ch committed Jun 27, 2024
1 parent 8737f56 commit 5afc83b
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
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.core.service.MathUtil;
import org.apache.fineract.infrastructure.event.business.domain.savings.transaction.SavingsDepositBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.savings.transaction.SavingsWithdrawalBusinessEvent;
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
Expand Down Expand Up @@ -339,7 +340,7 @@ public void postInterest(SavingsAccount account, final MathContext mc, final Loc
final List<PostingPeriod> postingPeriods = account.calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer,
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill,
postReversals);
log.info("postInterest {}", postingPeriods.size());
log.debug("postInterest {}", postingPeriods.size());

MonetaryCurrency currency = account.getCurrency();
Money interestPostedToDate = Money.zero(currency);
Expand All @@ -359,11 +360,11 @@ public void postInterest(SavingsAccount account, final MathContext mc, final Loc
}

for (final PostingPeriod interestPostingPeriod : postingPeriods) {
log.info(" period: {}", interestPostingPeriod.dateOfPostingTransaction());
log.debug(" period: {}", interestPostingPeriod.dateOfPostingTransaction());

final LocalDate interestPostingTransactionDate = interestPostingPeriod.dateOfPostingTransaction();
final Money interestEarnedToBePostedForPeriod = interestPostingPeriod.getInterestEarned();
log.info(" interestEarnedToBePostedForPeriod: {}", interestEarnedToBePostedForPeriod.toString());
log.debug(" interestEarnedToBePostedForPeriod: {}", interestEarnedToBePostedForPeriod.toString());

if (!interestPostingTransactionDate.isAfter(interestPostingUpToDate)) {
interestPostedToDate = interestPostedToDate.plus(interestEarnedToBePostedForPeriod);
Expand Down Expand Up @@ -394,13 +395,17 @@ public void postInterest(SavingsAccount account, final MathContext mc, final Loc
account.addTransaction(newPostingTransaction);
}
if (account.savingsProduct().isAccrualBasedAccountingEnabled()) {
SavingsAccountTransaction accrualTransaction = SavingsAccountTransaction.accrual(account, account.office(),
interestPostingTransactionDate, interestEarnedToBePostedForPeriod,
interestPostingPeriod.isUserPosting());
if (backdatedTxnsAllowedTill) {
account.addTransactionToExisting(accrualTransaction);
if (MathUtil.isGreaterThanZero(interestEarnedToBePostedForPeriod)) {
SavingsAccountTransaction accrualTransaction = SavingsAccountTransaction.accrual(account, account.office(),
interestPostingTransactionDate, interestEarnedToBePostedForPeriod,
interestPostingPeriod.isUserPosting());
if (backdatedTxnsAllowedTill) {
account.addTransactionToExisting(accrualTransaction);
} else {
account.addTransaction(accrualTransaction);
}
} else {
account.addTransaction(accrualTransaction);
log.info("Accrual for Overdraft interest");
}
}
if (applyWithHoldTax) {
Expand All @@ -416,7 +421,7 @@ public void postInterest(SavingsAccount account, final MathContext mc, final Loc
} else {
correctionRequired = postingTransaction.hasNotAmount(interestEarnedToBePostedForPeriod.negated());
}
log.info(" correctionRequired {}", correctionRequired);
log.debug(" correctionRequired {}", correctionRequired);
if (correctionRequired) {
boolean applyWithHoldTaxForOldTransaction = false;
postingTransaction.reverse();
Expand Down Expand Up @@ -451,7 +456,8 @@ public void postInterest(SavingsAccount account, final MathContext mc, final Loc
account.addTransaction(reversal);
}
}
if (account.savingsProduct().isAccrualBasedAccountingEnabled()) {
if (account.savingsProduct().isAccrualBasedAccountingEnabled() && MathUtil.isGreaterThanZero(interestEarnedToBePostedForPeriod)) {
log.info("TX2: {}", interestEarnedToBePostedForPeriod.getAmount());
SavingsAccountTransaction accrualTransaction = SavingsAccountTransaction.accrual(account, account.office(),
interestPostingTransactionDate, interestEarnedToBePostedForPeriod,
interestPostingPeriod.isUserPosting());
Expand All @@ -460,6 +466,8 @@ public void postInterest(SavingsAccount account, final MathContext mc, final Loc
} else {
account.addTransaction(accrualTransaction);
}
} else {
log.info("Accrual for Overdraft2 interest");
}
if (applyWithHoldTaxForOldTransaction) {
account.createWithHoldTransaction(interestEarnedToBePostedForPeriod.getAmount(), interestPostingTransactionDate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,19 +168,16 @@ private void postInterest(List<SavingsAccountData> savingsAccounts, int threadPo
}

while (queue.size() <= QUEUE_SIZE) {
log.debug("Fetching while threads are running!..:: this is not supposed to run........");
savingsAccounts = Collections.synchronizedList(this.savingAccountReadPlatformService
.retrieveAllSavingsDataForInterestPosting(backdatedTxnsAllowedTill, pageSize, ACTIVE.getValue(), maxId));
if (savingsAccounts.isEmpty()) {
break;
}
maxId = savingsAccounts.get(savingsAccounts.size() - 1).getId();
log.debug("Add to the Queue");
queue.add(savingsAccounts);
}

checkCompletion(responses);
log.debug("Queue size {}", queue.size());
}

private <T> List<T> safeSubList(List<T> list, int fromIndex, int toIndex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ public List<SavingsAccountData> retrieveAllSavingsDataForInterestPosting(final b
new Object[] { maxSavingsId, status, pageSize, yesterday });
for (SavingsAccountData savingsAccountData : savingsAccountDataList) {
this.savingAccountAssembler.assembleSavings(savingsAccountData);
log.info(" to process {} as {}", savingsAccountData.getAccountNo(), savingsAccountData.getDepositType().getValue());
log.debug(" to process {} as {}", savingsAccountData.getAccountNo(), savingsAccountData.getDepositType().getValue());
}
return savingsAccountDataList;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,18 @@ private void addAccrualTransactions(SavingsAccount savingsAccount, final LocalDa
.map(transaction -> transaction.getTransactionDate()).toList();

LocalDate accruedTillDate = fromDate;
final boolean accountInOverdraft = (savingsAccount.getSummary().getAccountBalance().compareTo(BigDecimal.ZERO) < 0);
log.info("ACT {} : {} {}", savingsAccount.getAccountNumber(), savingsAccount.getSummary().getAccountBalance(), accountInOverdraft);
for (PostingPeriod period : allPostingPeriods) {
period.calculateInterest(compoundInterestValues);
log.debug(" period {} {} : {} {}", period.getPeriodInterval().startDate(), period.getPeriodInterval().endDate(),
period.getInterestEarned());
if (!accrualTransactionDates.contains(period.getPeriodInterval().endDate())) {
SavingsAccountTransaction savingsAccountTransaction = SavingsAccountTransaction.accrual(savingsAccount,
savingsAccount.office(), period.getPeriodInterval().endDate(), period.getInterestEarned(), false);
savingsAccount.addTransaction(savingsAccountTransaction);
if (!accountInOverdraft) {
period.calculateInterest(compoundInterestValues);
log.info(" period {} {} : {}", period.getPeriodInterval().startDate(), period.getPeriodInterval().endDate(),
period.getInterestEarned());
if (!accrualTransactionDates.contains(period.getPeriodInterval().endDate())) {
SavingsAccountTransaction savingsAccountTransaction = SavingsAccountTransaction.accrual(savingsAccount,
savingsAccount.office(), period.getPeriodInterval().endDate(), period.getInterestEarned(), false);
savingsAccount.addTransaction(savingsAccountTransaction);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public class SavingsProductDataValidator {
nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName,
SavingsApiConstants.minRequiredBalanceParamName, SavingsApiConstants.enforceMinRequiredBalanceParamName,
SavingsApiConstants.maxAllowedLienLimitParamName, SavingsApiConstants.lienAllowedParamName,
minBalanceForInterestCalculationParamName, withHoldTaxParamName, taxGroupIdParamName));
minBalanceForInterestCalculationParamName, withHoldTaxParamName, taxGroupIdParamName, SavingsApiConstants.accrualChargesParamName));

public void validateForCreate(final String json) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final Lo
boolean isInterestTransfer, final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth,
final LocalDate postInterestOnDate, final boolean backdatedTxnsAllowedTill, final boolean postReversals) {

log.info(" calculateInterestUsing: {} {} {}", upToInterestCalculationDate, isInterestTransfer, postInterestOnDate);
log.debug(" calculateInterestUsing: {} {} {}", upToInterestCalculationDate, isInterestTransfer, postInterestOnDate);
// no openingBalance concept supported yet but probably will to allow for migrations.
// Check global configurations and 'pivot' date is null
Money openingAccountBalance = backdatedTxnsAllowedTill ? Money.of(this.currency, this.summary.getRunningBalanceOnPivotDate())
Expand Down Expand Up @@ -715,14 +715,14 @@ public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final Lo
if (postInterestOnDate != null) {
postedAsOnDates.add(postInterestOnDate);
}
log.info(" postedAsOnDates: {}", postedAsOnDates.size());
log.debug(" postedAsOnDates: {}", postedAsOnDates.size());
final List<LocalDateInterval> postingPeriodIntervals = this.savingsHelper.determineInterestPostingPeriods(
getStartInterestCalculationDate(), upToInterestCalculationDate, postingPeriodType, financialYearBeginningMonth,
postedAsOnDates);
log.info(" postingPeriodIntervals: {}", postingPeriodIntervals.size());
log.debug(" postingPeriodIntervals: {}", postingPeriodIntervals.size());

Money periodStartingBalance;
log.info(" startInterestCalculationDate: {}", this.startInterestCalculationDate);
log.debug(" startInterestCalculationDate: {}", this.startInterestCalculationDate);
if (this.startInterestCalculationDate != null && !this.getStartInterestCalculationDate().equals(this.getActivationDate())) {
LocalDate startInterestCalculationDate = this.startInterestCalculationDate;
SavingsAccountTransaction transaction = null;
Expand All @@ -740,7 +740,7 @@ public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final Lo
} else {
periodStartingBalance = Money.zero(this.currency);
}
log.info(" periodStartingBalance: {}", periodStartingBalance);
log.debug(" periodStartingBalance: {}", periodStartingBalance);

final SavingsInterestCalculationType interestCalculationType = SavingsInterestCalculationType
.fromInt(this.interestCalculationType);
Expand All @@ -751,7 +751,7 @@ public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final Lo
final Money minOverdraftForInterestCalculation = Money.of(getCurrency(), this.minOverdraftForInterestCalculation);

for (final LocalDateInterval periodInterval : postingPeriodIntervals) {
log.info(" periodInterval: {} {}", periodInterval.startDate(), periodInterval.endDate());
log.debug(" periodInterval: {} {}", periodInterval.startDate(), periodInterval.endDate());

boolean isUserPosting = false;
if (postedAsOnDates.contains(periodInterval.endDate().plusDays(1))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.accounting.journalentry.domain.JournalEntryType;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
Expand Down Expand Up @@ -70,8 +70,6 @@ public void postInterest() throws JobExecutionException {
boolean postInterestAsOn = false;
LocalDate transactionDate = null;
try {
log.info(" account: {} {} {} {}", savingsAccountData.getAccountNo(), postInterestAsOn, transactionDate,
backdatedTxnsAllowedTill);
SavingsAccountData savingsAccountDataRet = savingsAccountWritePlatformService.postInterest(savingsAccountData,
postInterestAsOn, transactionDate, backdatedTxnsAllowedTill);
savingsAccountDataList.add(savingsAccountDataRet);
Expand Down Expand Up @@ -186,9 +184,9 @@ private void batchUpdate(final List<SavingsAccountData> savingsAccountDataList)
List<SavingsAccountTransactionData> savingsAccountTransactionDataList = savingsAccountData.getSavingsAccountTransactionData();
for (SavingsAccountTransactionData savingsAccountTransactionData : savingsAccountTransactionDataList) {
if (savingsAccountTransactionData.getId() == null) {
UUID uuid = UUID.randomUUID();
savingsAccountTransactionData.setRefNo(uuid.toString());
transRefNo.add(uuid.toString());
final ExternalId externalId = ExternalId.generate();
savingsAccountTransactionData.setRefNo(externalId.toString());
transRefNo.add(externalId.toString());
paramsForTransactionInsertion.add(new Object[] { savingsAccountData.getId(), savingsAccountData.getOfficeId(),
savingsAccountTransactionData.isReversed(), savingsAccountTransactionData.getTransactionType().getId(),
savingsAccountTransactionData.getTransactionDate(), savingsAccountTransactionData.getAmount(),
Expand Down

0 comments on commit 5afc83b

Please sign in to comment.