FINERACT-2376: Unable to re-invest maturity amount or principal for fixed deposit at closing
This commit is contained in:
+4
-1
@@ -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);
|
||||
|
||||
+3
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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);
|
||||
|
||||
+4
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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()) {
|
||||
|
||||
+3
-2
@@ -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());
|
||||
|
||||
+166
@@ -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);
|
||||
|
||||
+86
@@ -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<>();
|
||||
|
||||
+11
@@ -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)
|
||||
|
||||
+44
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user