FINERACT-2376: Unable to re-invest maturity amount or principal for fixed deposit at closing

This commit is contained in:
sayhaed
2025-10-01 15:31:25 +02:00
committed by Adam Saghy
parent cb7ead208f
commit d782e65fc2
10 changed files with 324 additions and 7 deletions
@@ -212,6 +212,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
final LocalDate closedDate = command.localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName);
Long savingsTransactionId = null;
account.postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
account.setClosedOnDate(closedDate);
final Integer onAccountClosureId = command.integerValueOfParameterNamed(onAccountClosureIdParamName);
final DepositAccountOnClosureType onClosureType = DepositAccountOnClosureType.fromInt(onAccountClosureId);
if (onClosureType.isReinvest()) {
@@ -272,6 +273,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
final MathContext mc = MathContext.DECIMAL64;
Long savingsTransactionId = null;
account.postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
account.setClosedOnDate(closedDate);
final DepositAccountOnClosureType onClosureType = DepositAccountOnClosureType.fromInt(onAccountClosureId);
if (onClosureType.isReinvest()) {
BigDecimal reInvestAmount;
@@ -367,10 +369,11 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
this.calendarInstanceRepository.save(calendarInstance);
final Calendar calendar = calendarInstance.getCalendar();
final PeriodFrequencyType frequencyType = CalendarFrequencyType.from(CalendarUtils.getFrequency(calendar.getRecurrence()));
final Long relaxingDaysConfigForPivotDate = this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
Integer frequency = CalendarUtils.getInterval(calendar.getRecurrence());
frequency = frequency == -1 ? 1 : frequency;
reinvestedDeposit.generateSchedule(frequencyType, frequency, calendar);
reinvestedDeposit.processAccountUponActivation(fmt, postReversals);
reinvestedDeposit.processAccountUponActivation(fmt, postReversals, relaxingDaysConfigForPivotDate);
reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
this.savingsAccountRepository.save(reinvestedDeposit);
@@ -882,4 +882,7 @@ public class FixedDepositAccount extends SavingsAccount {
return SavingsAccountStatusType.MATURED.getValue().equals(this.status);
}
public void setClosedOnDate(final LocalDate closedOnDate) {
this.closedOnDate = closedOnDate;
}
}
@@ -536,11 +536,11 @@ public class RecurringDepositAccount extends SavingsAccount {
return Money.of(this.currency, this.minRequiredOpeningBalance);
}
protected void processAccountUponActivation(final DateTimeFormatter fmt, final boolean postReversals) {
protected void processAccountUponActivation(final DateTimeFormatter fmt, final boolean postReversals,
final Long relaxingDaysConfigForPivotDate) {
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, getActivationDate(),
minRequiredOpeningBalance.getAmount(), null, null, accountType);
@@ -32,6 +32,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.core.domain.LocalDateInterval;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.MathUtil;
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money;
@@ -177,7 +178,9 @@ public class SavingsAccrualWritePlatformServiceImpl implements SavingsAccrualWri
savingsAccount.office(), period.getPeriodInterval().endDate(), period.getInterestEarned().abs(), false, refNo);
savingsAccountTransaction.setRunningBalance(period.getClosingBalance());
savingsAccountTransaction.setOverdraftAmount(period.getInterestEarned());
savingsAccount.addTransaction(savingsAccountTransaction);
if (!MathUtil.isZero(savingsAccountTransaction.getAmount())) {
savingsAccount.addTransaction(savingsAccountTransaction);
}
}
}
@@ -1042,7 +1042,7 @@ public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom<Long>
if (MathUtil.isEmpty(overdraftAmount) && runningBalance.isLessThanZero() && !transaction.isAmountOnHold()) {
overdraftAmount = runningBalance.negated();
}
if (!calculateInterest || transaction.getId() == null) {
if (!calculateInterest || transaction.getId() == null || transaction.getOverdraftAmount(this.currency).isZero()) {
transaction.setOverdraftAmount(overdraftAmount);
} else if (!MathUtil.isEqualTo(overdraftAmount, transaction.getOverdraftAmount(this.currency))
&& !transaction.isAccrual()) {
@@ -36,6 +36,7 @@ import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.accounting.journalentry.domain.JournalEntryType;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.MathUtil;
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
@@ -106,7 +107,7 @@ public class SavingsSchedularInterestPoster {
List<SavingsAccountTransactionData> savingsAccountTransactionDataList = savingsAccountData.getSavingsAccountTransactionData();
for (SavingsAccountTransactionData savingsAccountTransactionData : savingsAccountTransactionDataList) {
if (savingsAccountTransactionData.getId() == null) {
if (savingsAccountTransactionData.getId() == null && !MathUtil.isZero(savingsAccountTransactionData.getAmount())) {
final String key = savingsAccountTransactionData.getRefNo();
final Boolean isOverdraft = savingsAccountTransactionData.getIsOverdraft();
final SavingsAccountTransactionData dataFromFetch = savingsAccountTransactionDataHashMap.get(key);
@@ -183,7 +184,7 @@ public class SavingsSchedularInterestPoster {
auditTime, userId, savingsAccountData.getId() });
List<SavingsAccountTransactionData> savingsAccountTransactionDataList = savingsAccountData.getSavingsAccountTransactionData();
for (SavingsAccountTransactionData savingsAccountTransactionData : savingsAccountTransactionDataList) {
if (savingsAccountTransactionData.getId() == null) {
if (savingsAccountTransactionData.getId() == null && !MathUtil.isZero(savingsAccountTransactionData.getAmount())) {
UUID uuid = UUID.randomUUID();
savingsAccountTransactionData.setRefNo(uuid.toString());
transRefNo.add(uuid.toString());
@@ -48,12 +48,17 @@ import java.util.Locale;
import java.util.TimeZone;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.accounting.common.AccountingConstants.FinancialActivity;
import org.apache.fineract.client.models.PutGlobalConfigurationsRequest;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.configuration.api.GlobalConfigurationConstants;
import org.apache.fineract.infrastructure.core.api.JsonQuery;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.integrationtests.client.IntegrationTest;
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
import org.apache.fineract.integrationtests.common.TaxComponentHelper;
import org.apache.fineract.integrationtests.common.TaxGroupHelper;
@@ -92,6 +97,7 @@ public class FixedDepositTest extends IntegrationTest {
private SavingsAccountHelper savingsAccountHelper;
private JournalEntryHelper journalEntryHelper;
private FinancialActivityAccountHelper financialActivityAccountHelper;
private GlobalConfigurationHelper globalConfigurationHelper;
private FixedDepositAccountInterestCalculationServiceImpl fixedDepositAccountInterestCalculationServiceImpl;
@@ -108,12 +114,14 @@ public class FixedDepositTest extends IntegrationTest {
private static final String NONE = "1";
private static final String CASH_BASED = "2";
private static final String ACCRUAL = "3";
public static final String MINIMUM_OPENING_BALANCE = "1000.0";
public static final String ACCOUNT_TYPE_INDIVIDUAL = "INDIVIDUAL";
public static final String CLOSURE_TYPE_WITHDRAW_DEPOSIT = "100";
public static final String CLOSURE_TYPE_TRANSFER_TO_SAVINGS = "200";
public static final String CLOSURE_TYPE_REINVEST = "300";
public static final String CLOSURE_TYPE_REINVEST_PRINCIPAL_ONLY = "400";
public static final Integer DAILY_COMPOUNDING_INTERVAL = 0;
public static final Integer MONTHLY_INTERVAL = 1;
public static final Integer QUARTERLY_INTERVAL = 3;
@@ -130,6 +138,7 @@ public class FixedDepositTest extends IntegrationTest {
public static final Float THRESHOLD = 1.0f;
private MockedStatic<MoneyHelper> moneyHelperStatic;
private SchedulerJobHelper schedulerJobHelper;
@BeforeEach
public void setup() {
@@ -138,8 +147,11 @@ public class FixedDepositTest extends IntegrationTest {
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.requestSpec.header("Fineract-Platform-TenantId", "default");
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec);
this.schedulerJobHelper = new SchedulerJobHelper(this.requestSpec);
this.journalEntryHelper = new JournalEntryHelper(this.requestSpec, this.responseSpec);
this.financialActivityAccountHelper = new FinancialActivityAccountHelper(this.requestSpec);
this.globalConfigurationHelper = new GlobalConfigurationHelper();
TimeZone.setDefault(TimeZone.getTimeZone(Utils.TENANT_TIME_ZONE));
}
@@ -2598,6 +2610,158 @@ public class FixedDepositTest extends IntegrationTest {
FixedDepositAccountStatusChecker.verifyFixedDepositIsActive(fixedDepositAccountStatusHashMap);
}
@Test
public void testCloseFixedDepositForCLOSURE_TYPE_REINVEST_withConfigurationMaturityInstruction() {
try {
final Account assetAccount = this.accountHelper.createAssetAccount();
final Account liabilityAccount = this.accountHelper.createLiabilityAccount();
final Account incomeAccount = this.accountHelper.createIncomeAccount();
final Account expenseAccount = this.accountHelper.createExpenseAccount();
this.fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec);
this.fixedDepositAccountHelper = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec);
DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US);
DateFormat monthDayFormat = new SimpleDateFormat("dd MMM", Locale.US);
DateFormat currentDateFormat = new SimpleDateFormat("dd");
Calendar todaysDate = Calendar.getInstance();
int currentYear = todaysDate.get(Calendar.YEAR);
todaysDate.set(currentYear, Calendar.JANUARY, 1);
final String VALID_FROM = dateFormat.format(todaysDate.getTime());
todaysDate.set(currentYear + 1, Calendar.MARCH, 1);
final String VALID_TO = dateFormat.format(todaysDate.getTime());
todaysDate = Calendar.getInstance();
Integer currentDate = Integer.valueOf(currentDateFormat.format(todaysDate.getTime()));
todaysDate.set(currentYear, Calendar.JANUARY, 1);
final String SUBMITTED_ON_DATE = dateFormat.format(todaysDate.getTime());
final String APPROVED_ON_DATE = dateFormat.format(todaysDate.getTime());
dateFormat.format(todaysDate.getTime());
monthDayFormat.format(todaysDate.getTime());
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE,
new PutGlobalConfigurationsRequest().enabled(true));
LocalDate marchDate = LocalDate.of(currentYear + 1, 3, 1);
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, marchDate);
log.info("Submitted Date: {}", SUBMITTED_ON_DATE);
final String accountingRule = ACCRUAL;
Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule, assetAccount, liabilityAccount,
incomeAccount, expenseAccount);
Assertions.assertNotNull(fixedDepositProductId);
Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(),
SUBMITTED_ON_DATE, WHOLE_TERM, Integer.valueOf(CLOSURE_TYPE_REINVEST));
Assertions.assertNotNull(fixedDepositAccountId);
this.fixedDepositAccountHelper.approveFixedDeposit(fixedDepositAccountId, APPROVED_ON_DATE);
this.fixedDepositAccountHelper.activateFixedDeposit(fixedDepositAccountId, APPROVED_ON_DATE);
schedulerJobHelper.executeAndAwaitJob("Update Deposit Accounts Maturity details");
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
this.responseSpec, fixedDepositAccountId.toString());
FixedDepositAccountStatusChecker.verifyFixedDepositAccountIsClosed(fixedDepositAccountStatusHashMap);
} finally {
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE,
new PutGlobalConfigurationsRequest().enabled(false));
}
}
@Test
public void testCloseFixedDepositForCLOSURE_TYPE_REINVEST() {
testClosureTypeReinvestVariants(CLOSURE_TYPE_REINVEST);
}
@Test
public void testCloseFixedDepositForCLOSURE_TYPE_REINVEST_PRINCIPAL_ONLY() {
testClosureTypeReinvestVariants(CLOSURE_TYPE_REINVEST_PRINCIPAL_ONLY);
}
public void testClosureTypeReinvestVariants(String reInvest) {
try {
final Account assetAccount = this.accountHelper.createAssetAccount();
final Account liabilityAccount = this.accountHelper.createLiabilityAccount();
final Account incomeAccount = this.accountHelper.createIncomeAccount();
final Account expenseAccount = this.accountHelper.createExpenseAccount();
this.fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec);
this.fixedDepositAccountHelper = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec);
DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US);
DateFormat monthDayFormat = new SimpleDateFormat("dd MMM", Locale.US);
DateFormat currentDateFormat = new SimpleDateFormat("dd");
Calendar todaysDate = Calendar.getInstance();
int currentYear = todaysDate.get(Calendar.YEAR);
todaysDate.set(currentYear, Calendar.JANUARY, 1);
final String VALID_FROM = dateFormat.format(todaysDate.getTime());
todaysDate.set(currentYear + 1, Calendar.JANUARY, 1);
final String VALID_TO = dateFormat.format(todaysDate.getTime());
todaysDate = Calendar.getInstance();
Integer currentDate = Integer.valueOf(currentDateFormat.format(todaysDate.getTime()));
todaysDate.set(currentYear, Calendar.JANUARY, 1);
final String SUBMITTED_ON_DATE = dateFormat.format(todaysDate.getTime());
final String APPROVED_ON_DATE = dateFormat.format(todaysDate.getTime());
dateFormat.format(todaysDate.getTime());
monthDayFormat.format(todaysDate.getTime());
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE,
new PutGlobalConfigurationsRequest().enabled(true));
LocalDate marchDate = LocalDate.of(currentYear + 1, 1, 1);
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, marchDate);
log.info("Submitted Date: {}", SUBMITTED_ON_DATE);
final String accountingRule = ACCRUAL;
Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule, assetAccount, liabilityAccount,
incomeAccount, expenseAccount);
Assertions.assertNotNull(fixedDepositProductId);
Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(),
SUBMITTED_ON_DATE, WHOLE_TERM, "10000", "12");
Assertions.assertNotNull(fixedDepositAccountId);
this.fixedDepositAccountHelper.approveFixedDeposit(fixedDepositAccountId, APPROVED_ON_DATE);
this.fixedDepositAccountHelper.activateFixedDeposit(fixedDepositAccountId, APPROVED_ON_DATE);
schedulerJobHelper.executeAndAwaitJob("Update Deposit Accounts Maturity details");
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
this.responseSpec, fixedDepositAccountId.toString());
FixedDepositAccountStatusChecker.verifyFixedDepositAccountIsMatured(fixedDepositAccountStatusHashMap);
todaysDate.set(currentYear + 1, Calendar.JANUARY, 1);
final String CLOSED_ON_DATE = dateFormat.format(todaysDate.getTime());
Integer prematureClosureTransactionId = (Integer) this.fixedDepositAccountHelper.closeForFixedDeposit(fixedDepositAccountId,
CLOSED_ON_DATE, reInvest, null, CommonConstants.RESPONSE_RESOURCE_ID);
fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
this.responseSpec, fixedDepositAccountId.toString());
FixedDepositAccountStatusChecker.verifyFixedDepositAccountIsClosed(fixedDepositAccountStatusHashMap);
} finally {
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE,
new PutGlobalConfigurationsRequest().enabled(false));
}
}
private Integer createFixedDepositProduct(final String validFrom, final String validTo, final String accountingRule,
Account... accounts) {
log.info("------------------------------CREATING NEW FIXED DEPOSIT PRODUCT ---------------------------------------");
@@ -2606,6 +2770,8 @@ public class FixedDepositTest extends IntegrationTest {
fixedDepositProductHelper = fixedDepositProductHelper.withAccountingRuleAsCashBased(accounts);
} else if (accountingRule.equals(NONE)) {
fixedDepositProductHelper = fixedDepositProductHelper.withAccountingRuleAsNone();
} else if (accountingRule.equals(ACCRUAL)) {
fixedDepositProductHelper = fixedDepositProductHelper.withAccountingRuleAsAccrual(accounts);
}
final String fixedDepositProductJSON = fixedDepositProductHelper.withPeriodRangeChart() //
.build(validFrom, validTo, true);
@@ -340,6 +340,92 @@ public class SavingsInterestPostingTest {
}
}
@Test
public void testPostInterestNotZero() {
try {
final String amountDeposit = "1000";
final String amountWithdrawal = "1000";
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account liabilityAccount = accountHelper.createLiabilityAccount();
final Account interestReceivableAccount = accountHelper.createAssetAccount("interestReceivableAccount");
final Account savingsControlAccount = accountHelper.createLiabilityAccount("Savings Control");
final Account interestPayableAccount = accountHelper.createLiabilityAccount("Interest Payable");
final Integer productId = createSavingsProductWithAccrualAccountingWithOutOverdraftAllowed(
interestPayableAccount.getAccountID().toString(), savingsControlAccount.getAccountID().toString(),
interestReceivableAccount.getAccountID().toString(), assetAccount, incomeAccount, expenseAccount, liabilityAccount);
final Integer clientId = ClientHelper.createClient(requestSpec, responseSpec, "01 January 2025");
final LocalDate startDate = LocalDate.of(LocalDate.now(Utils.getZoneIdOfTenant()).getYear(), 1, 1);
final String startStr = DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.US).format(startDate);
final Integer accountId = savingsAccountHelper.applyForSavingsApplicationOnDate(clientId, productId,
SavingsAccountHelper.ACCOUNT_TYPE_INDIVIDUAL, startStr);
savingsAccountHelper.approveSavingsOnDate(accountId, startStr);
savingsAccountHelper.activateSavings(accountId, startStr);
savingsAccountHelper.depositToSavingsAccount(accountId, amountDeposit, startStr, CommonConstants.RESPONSE_RESOURCE_ID);
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE,
new PutGlobalConfigurationsRequest().enabled(true));
LocalDate februaryDate = LocalDate.of(startDate.getYear(), 2, 1);
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, februaryDate);
schedulerJobHelper.executeAndAwaitJob(POST_INTEREST_JOB_NAME);
List<HashMap> txsFebruary = getInterestTransactions(accountId); // OBTENER EL POSTEO DEL INTEREST
long daysFebruary = ChronoUnit.DAYS.between(startDate, februaryDate);
BigDecimal expectedFebruary = calcInterestPosting(productHelper, amountDeposit, daysFebruary);
Assertions.assertEquals(expectedFebruary, BigDecimal.valueOf(((Double) txsFebruary.get(0).get("amount"))));
final LocalDate withdrawalDate = LocalDate.of(startDate.getYear(), 2, 1);
final String withdrawal = DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.US).format(withdrawalDate);
BigDecimal runningBalance = new BigDecimal(txsFebruary.get(0).get("runningBalance").toString());
String withdrawalRunning = runningBalance.setScale(2, RoundingMode.HALF_UP).toString();
savingsAccountHelper.withdrawalFromSavingsAccount(accountId, withdrawalRunning, withdrawal,
CommonConstants.RESPONSE_RESOURCE_ID);
savingsAccountHelper.withdrawalFromSavingsAccount(accountId, amountWithdrawal, withdrawal,
CommonConstants.RESPONSE_RESOURCE_ID);
LocalDate marchDate = LocalDate.of(startDate.getYear(), 3, 1);
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, marchDate);
schedulerJobHelper.executeAndAwaitJob(POST_INTEREST_JOB_NAME);
List<HashMap> txs = getInterestTransactions(accountId); // CON ESTE DEBEMOS DE VALIDAR QUE EL DIA DE MARZO
// NO SE TENGA POSTEO EN CERO
for (HashMap tx : txs) {
BigDecimal amt = BigDecimal.valueOf(((Double) tx.get("amount")));
@SuppressWarnings("unchecked")
Map<String, Object> typeMap = (Map<String, Object>) tx.get("transactionType");
SavingsAccountTransactionType type = SavingsAccountTransactionType.fromInt(((Double) typeMap.get("id")).intValue());
if (type.isOverDraftInterestPosting()) {
long days = ChronoUnit.DAYS.between(withdrawalDate, marchDate);
BigDecimal decimalsss = new BigDecimal(txsFebruary.get(0).get("runningBalance").toString())
.subtract(runningBalance.setScale(2, RoundingMode.HALF_UP));
BigDecimal withdraw = new BigDecimal(amountWithdrawal);
BigDecimal res = withdraw.subtract(decimalsss);
BigDecimal expected = calcOverdraftPosting(productHelper, res.toString(), days);
Assertions.assertEquals(expected, amt);
}
}
Assertions.assertEquals(0L, countInterestOnDate(accountId, marchDate), "Expected exactly one INTEREST posting on posting date");
Assertions.assertEquals(1L, countOverdraftOnDate(accountId, marchDate),
"Expected exactly one OVERDRAFT posting on posting date");
assertNoAccrualReversals(accountId);
} finally {
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE,
new PutGlobalConfigurationsRequest().enabled(false));
}
}
private List<HashMap> getInterestTransactions(Integer savingsAccountId) {
List<HashMap> all = savingsAccountHelper.getSavingsTransactions(savingsAccountId);
List<HashMap> filtered = new ArrayList<>();
@@ -402,6 +402,17 @@ public class FixedDepositAccountHelper {
getPrematureCloseForFixedDepositAccountAsJSON(closedOnDate, closureType, toSavingsId), jsonAttributeToGetBack);
}
// TODO: Rewrite to use fineract-client instead!
// Example: org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper.disburseLoan(java.lang.Long,
// org.apache.fineract.client.models.PostLoansLoanIdRequest)
@Deprecated(forRemoval = true)
public Object closeForFixedDeposit(final Integer fixedDepositAccountId, final String closedOnDate, final String closureType,
final Integer toSavingsId, final String jsonAttributeToGetBack) {
LOG.info("--------------------- CLOSE FOR FIXED DEPOSIT ----------------------------");
return performFixedDepositActions(createFixedDepositCalculateInterestURL(CLOSE_FIXED_DEPOSIT_COMMAND, fixedDepositAccountId),
getPrematureCloseForFixedDepositAccountAsJSON(closedOnDate, closureType, toSavingsId), jsonAttributeToGetBack);
}
// TODO: Rewrite to use fineract-client instead!
// Example: org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper.disburseLoan(java.lang.Long,
// org.apache.fineract.client.models.PostLoansLoanIdRequest)
@@ -163,6 +163,9 @@ public class FixedDepositProductHelper {
if (this.accountingRule.equals(CASH_BASED)) {
map.putAll(getAccountMappingForCashBased());
}
if (this.accountingRule.equals(ACCRUAL_PERIODIC)) {
map.putAll(getAccountMappingForAccrualBased());
}
String FixedDepositProductCreateJson = new Gson().toJson(map);
LOG.info("{}", FixedDepositProductCreateJson);
@@ -397,6 +400,12 @@ public class FixedDepositProductHelper {
return this;
}
public FixedDepositProductHelper withAccountingRuleAsAccrual(final Account[] account_list) {
this.accountingRule = ACCRUAL_PERIODIC;
this.accountList = account_list;
return this;
}
public FixedDepositProductHelper withPeriodRangeChart() {
this.chartSlabs = constructChartSlabWithPeriodRange();
return this;
@@ -456,6 +465,41 @@ public class FixedDepositProductHelper {
return map;
}
// TODO: Rewrite to use fineract-client instead!
// Example: org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper.disburseLoan(java.lang.Long,
// org.apache.fineract.client.models.PostLoansLoanIdRequest)
@Deprecated(forRemoval = true)
private Map<String, String> getAccountMappingForAccrualBased() {
final Map<String, String> map = new HashMap<>();
if (accountList != null) {
for (int i = 0; i < this.accountList.length; i++) {
if (this.accountList[i].getAccountType().equals(Account.AccountType.ASSET)) {
final String ID = this.accountList[i].getAccountID().toString();
map.put("savingsReferenceAccountId", ID);
map.put("feesReceivableAccountId", ID);
map.put("penaltiesReceivableAccountId", ID);
}
if (this.accountList[i].getAccountType().equals(Account.AccountType.LIABILITY)) {
final String ID = this.accountList[i].getAccountID().toString();
map.put("savingsControlAccountId", ID);
map.put("transfersInSuspenseAccountId", ID);
map.put("interestPayableAccountId", ID);
}
if (this.accountList[i].getAccountType().equals(Account.AccountType.EXPENSE)) {
final String ID = this.accountList[i].getAccountID().toString();
map.put("interestOnSavingsAccountId", ID);
}
if (this.accountList[i].getAccountType().equals(Account.AccountType.INCOME)) {
final String ID = this.accountList[i].getAccountID().toString();
map.put("incomeFromFeeAccountId", ID);
map.put("incomeFromPenaltyAccountId", ID);
}
}
}
return map;
}
// TODO: Rewrite to use fineract-client instead!
// Example: org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper.disburseLoan(java.lang.Long,
// org.apache.fineract.client.models.PostLoansLoanIdRequest)