Skip to content

Commit 744fd08

Browse files
committed
None Interest Test on Fixed Deposit
1 parent 6e6666f commit 744fd08

File tree

4 files changed

+526
-14
lines changed

4 files changed

+526
-14
lines changed

integration-tests/src/test/java/org/apache/fineract/integrationtests/FixedDepositTest.java

Lines changed: 265 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,24 @@
4242
import java.util.ArrayList;
4343
import java.util.Arrays;
4444
import java.util.Calendar;
45+
import java.util.Map;
4546
import java.util.HashMap;
4647
import java.util.List;
4748
import java.util.Locale;
4849
import java.util.TimeZone;
4950
import lombok.extern.slf4j.Slf4j;
5051
import org.apache.fineract.accounting.common.AccountingConstants.FinancialActivity;
5152
import org.apache.fineract.infrastructure.core.api.JsonQuery;
53+
import org.apache.fineract.client.models.PutGlobalConfigurationsRequest;
54+
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
55+
import org.apache.fineract.infrastructure.configuration.api.GlobalConfigurationConstants;
5256
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
5357
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
5458
import org.apache.fineract.integrationtests.client.IntegrationTest;
5559
import org.apache.fineract.integrationtests.common.ClientHelper;
60+
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
5661
import org.apache.fineract.integrationtests.common.CommonConstants;
62+
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
5763
import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
5864
import org.apache.fineract.integrationtests.common.TaxComponentHelper;
5965
import org.apache.fineract.integrationtests.common.TaxGroupHelper;
@@ -71,6 +77,7 @@
7177
import org.apache.fineract.integrationtests.common.savings.SavingsProductHelper;
7278
import org.apache.fineract.integrationtests.common.savings.SavingsStatusChecker;
7379
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
80+
import org.apache.fineract.portfolio.savings.SavingsAccountTransactionType;
7481
import org.apache.fineract.portfolio.savings.data.DepositAccountDataValidator;
7582
import org.apache.fineract.portfolio.savings.service.FixedDepositAccountInterestCalculationServiceImpl;
7683
import org.junit.jupiter.api.AfterEach;
@@ -92,7 +99,8 @@ public class FixedDepositTest extends IntegrationTest {
9299
private SavingsAccountHelper savingsAccountHelper;
93100
private JournalEntryHelper journalEntryHelper;
94101
private FinancialActivityAccountHelper financialActivityAccountHelper;
95-
102+
private GlobalConfigurationHelper globalConfigurationHelper;
103+
private SchedulerJobHelper schedulerJobHelper;
96104
private FixedDepositAccountInterestCalculationServiceImpl fixedDepositAccountInterestCalculationServiceImpl;
97105

98106
public static final String WHOLE_TERM = "1";
@@ -138,8 +146,11 @@ public void setup() {
138146
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
139147
this.requestSpec.header("Fineract-Platform-TenantId", "default");
140148
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
149+
this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec);
150+
this.schedulerJobHelper = new SchedulerJobHelper(this.requestSpec);
141151
this.journalEntryHelper = new JournalEntryHelper(this.requestSpec, this.responseSpec);
142152
this.financialActivityAccountHelper = new FinancialActivityAccountHelper(this.requestSpec);
153+
this.globalConfigurationHelper = new GlobalConfigurationHelper();
143154
TimeZone.setDefault(TimeZone.getTimeZone(Utils.TENANT_TIME_ZONE));
144155
}
145156

@@ -2598,6 +2609,249 @@ public void testFixedDepositAccountWithRolloverPrincipal() {
25982609
FixedDepositAccountStatusChecker.verifyFixedDepositIsActive(fixedDepositAccountStatusHashMap);
25992610
}
26002611

2612+
@Test
2613+
public void FixedDepositNoneInterestAccruals(){
2614+
try{
2615+
final String amount = "10000";
2616+
final Account assetAccount = this.accountHelper.createAssetAccount();
2617+
final Account incomeAccount = this.accountHelper.createIncomeAccount();
2618+
final Account expenseAccount = this.accountHelper.createExpenseAccount();
2619+
final Account liabilityAccount = this.accountHelper.createLiabilityAccount();
2620+
final Account savingsControlAccount = this.accountHelper.createLiabilityAccount("Savings Control");
2621+
2622+
this.fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec);
2623+
this.fixedDepositAccountHelper = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec);
2624+
2625+
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.US);
2626+
DateTimeFormatter monthDayFormat = DateTimeFormatter.ofPattern("dd MMM", Locale.US);
2627+
DateTimeFormatter currentDateFormat = DateTimeFormatter.ofPattern("dd");
2628+
2629+
LocalDate mayDate = LocalDate.of(LocalDate.now().getYear()-1, 5, 1);
2630+
2631+
final String SUBMITTED_ON_DATE = mayDate.format(dateFormat);
2632+
final String APPROVED_ON_DATE = mayDate.format(dateFormat);
2633+
2634+
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE,
2635+
new PutGlobalConfigurationsRequest().enabled(true));
2636+
2637+
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, mayDate);
2638+
2639+
log.info("Submitted Date: {}", SUBMITTED_ON_DATE);
2640+
2641+
2642+
final Integer fixedDepositProductId = createFixedWithAccrualAccountingWithNoneInterest(liabilityAccount, expenseAccount,incomeAccount,assetAccount, savingsControlAccount);
2643+
Assertions.assertNotNull(fixedDepositProductId);
2644+
2645+
Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
2646+
Assertions.assertNotNull(clientId);
2647+
2648+
Integer fixedDepositAccountId = applyForFixedDepositApplication_10000(clientId.toString(), fixedDepositProductId.toString(),
2649+
SUBMITTED_ON_DATE, WHOLE_TERM, Integer.valueOf(CLOSURE_TYPE_REINVEST));
2650+
Assertions.assertNotNull(fixedDepositAccountId);
2651+
2652+
this.fixedDepositAccountHelper.approveFixedDeposit(fixedDepositAccountId, APPROVED_ON_DATE);
2653+
this.fixedDepositAccountHelper.activateFixedDeposit(fixedDepositAccountId, APPROVED_ON_DATE);
2654+
2655+
2656+
final LocalDate endOfMay = LocalDate.of(LocalDate.now().getYear()-1, 6, 1);
2657+
BusinessDateHelper.updateBusinessDate(this.requestSpec, this.responseSpec, BusinessDateType.BUSINESS_DATE, endOfMay);
2658+
log.info("Advancing business date to: {}. Running Accrual Job for May...", endOfMay);
2659+
2660+
this.schedulerJobHelper.executeAndAwaitJob("Add Accrual Transactions For Savings");
2661+
2662+
final LocalDate endOfJune = LocalDate.of(LocalDate.now().getYear()-1, 7, 1);
2663+
BusinessDateHelper.updateBusinessDate(this.requestSpec, this.responseSpec, BusinessDateType.BUSINESS_DATE, endOfJune);
2664+
log.info("Advancing business date to: {}. Running Accrual Job for June...", endOfJune);
2665+
2666+
this.schedulerJobHelper.executeAndAwaitJob("Add Accrual Transactions For Savings");
2667+
2668+
2669+
BigDecimal expectedDailyInterest = new BigDecimal(amount)
2670+
.multiply(new BigDecimal("0.15"))
2671+
.divide(new BigDecimal("360"), 4, RoundingMode.HALF_EVEN);
2672+
2673+
List<HashMap> allTransactions = this.fixedDepositAccountHelper.getFixedDepositTransactions(fixedDepositAccountId);
2674+
Assertions.assertNotNull(allTransactions, "The transaction list should not be null");
2675+
2676+
int juneAccrualsVerified = 0;
2677+
log.info("Verifying accrual transactions for June... Expected daily amount around: {}", expectedDailyInterest);
2678+
2679+
for (HashMap transaction : allTransactions) {
2680+
Map<String, Object> type = (Map<String, Object>) transaction.get("transactionType");
2681+
2682+
if (type != null && Boolean.TRUE.equals(type.get("accrual"))) {
2683+
2684+
List<Number> dateArray = (List<Number>) transaction.get("date");
2685+
LocalDate transactionDate = LocalDate.of(dateArray.get(0).intValue(), dateArray.get(1).intValue(), dateArray.get(2).intValue());
2686+
2687+
if (transactionDate.getMonthValue() == 6 && transactionDate.getYear() == 2024) {
2688+
BigDecimal actualAmount = new BigDecimal(transaction.get("amount").toString()).setScale(4, RoundingMode.HALF_EVEN);
2689+
2690+
Assertions.assertEquals(expectedDailyInterest.doubleValue(), actualAmount.doubleValue(), 0.01,
2691+
"The accrual for June on date " + transactionDate + " is incorrect.");
2692+
2693+
juneAccrualsVerified++;
2694+
}
2695+
}
2696+
}
2697+
2698+
Assertions.assertEquals(30, juneAccrualsVerified, "El número de transacciones de accrual para Junio no es 30.");
2699+
log.info("Successfully verified {} accrual transactions for June.", juneAccrualsVerified);
2700+
2701+
} finally {
2702+
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE,
2703+
new PutGlobalConfigurationsRequest().enabled(false));
2704+
}
2705+
}
2706+
2707+
@Test
2708+
public void FixedDepositNoneInterestPostInterest(){
2709+
try{
2710+
final String amount = "10000";
2711+
final Account assetAccount = this.accountHelper.createAssetAccount();
2712+
final Account incomeAccount = this.accountHelper.createIncomeAccount();
2713+
final Account expenseAccount = this.accountHelper.createExpenseAccount();
2714+
final Account liabilityAccount = this.accountHelper.createLiabilityAccount();
2715+
final Account savingsControlAccount = this.accountHelper.createLiabilityAccount("Savings Control");
2716+
2717+
this.fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec);
2718+
this.fixedDepositAccountHelper = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec);
2719+
2720+
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.US);
2721+
DateTimeFormatter monthDayFormat = DateTimeFormatter.ofPattern("dd MMM", Locale.US);
2722+
DateTimeFormatter currentDateFormat = DateTimeFormatter.ofPattern("dd");
2723+
2724+
LocalDate mayDate = LocalDate.of(LocalDate.now().getYear()-1, 5, 1);
2725+
2726+
final String SUBMITTED_ON_DATE = mayDate.format(dateFormat);
2727+
final String APPROVED_ON_DATE = mayDate.format(dateFormat);
2728+
2729+
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE,
2730+
new PutGlobalConfigurationsRequest().enabled(true));
2731+
2732+
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, mayDate);
2733+
2734+
log.info("Submitted Date: {}", SUBMITTED_ON_DATE);
2735+
2736+
2737+
final Integer fixedDepositProductId = createFixedWithAccrualAccountingWithNoneInterest(liabilityAccount, expenseAccount,incomeAccount,assetAccount, savingsControlAccount);
2738+
Assertions.assertNotNull(fixedDepositProductId);
2739+
2740+
Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
2741+
Assertions.assertNotNull(clientId);
2742+
2743+
Integer fixedDepositAccountId = applyForFixedDepositApplication_10000(clientId.toString(), fixedDepositProductId.toString(),
2744+
SUBMITTED_ON_DATE, WHOLE_TERM, Integer.valueOf(CLOSURE_TYPE_REINVEST));
2745+
Assertions.assertNotNull(fixedDepositAccountId);
2746+
2747+
this.fixedDepositAccountHelper.approveFixedDeposit(fixedDepositAccountId, APPROVED_ON_DATE);
2748+
this.fixedDepositAccountHelper.activateFixedDeposit(fixedDepositAccountId, APPROVED_ON_DATE);
2749+
2750+
2751+
final LocalDate endOfMay = LocalDate.of(LocalDate.now().getYear()-1, 6, 1);
2752+
BusinessDateHelper.updateBusinessDate(this.requestSpec, this.responseSpec, BusinessDateType.BUSINESS_DATE, endOfMay);
2753+
log.info("Advancing business date to: {}. Running Post interest Job for May...", endOfMay);
2754+
2755+
this.schedulerJobHelper.executeAndAwaitJob("Post Interest For Savings");
2756+
2757+
final LocalDate endOfJune = LocalDate.of(LocalDate.now().getYear()-1, 7, 1);
2758+
BusinessDateHelper.updateBusinessDate(this.requestSpec, this.responseSpec, BusinessDateType.BUSINESS_DATE, endOfJune);
2759+
log.info("Advancing business date to: {}. Running Post interest Job for June...", endOfJune);
2760+
2761+
this.schedulerJobHelper.executeAndAwaitJob("Post Interest For Savings");
2762+
2763+
List<HashMap> allTransactions = this.fixedDepositAccountHelper.getFixedDepositTransactions(fixedDepositAccountId);
2764+
Assertions.assertNotNull(allTransactions, "The transaction list should not be null.");
2765+
2766+
BigDecimal newPrincipalAfterMay = new BigDecimal(amount);
2767+
for (HashMap transaction : allTransactions) {
2768+
Map<String, Object> typeMap = (Map<String, Object>) transaction.get("transactionType");
2769+
if (typeMap != null) {
2770+
int typeId = ((Number) typeMap.get("id")).intValue();
2771+
SavingsAccountTransactionType txType = SavingsAccountTransactionType.fromInt(typeId);
2772+
if (txType.isInterestPosting()) {
2773+
List<Number> dateArray = (List<Number>) transaction.get("date");
2774+
LocalDate txDate = LocalDate.of(dateArray.get(0).intValue(), dateArray.get(1).intValue(), dateArray.get(2).intValue());
2775+
if (txDate.equals(endOfMay)) {
2776+
newPrincipalAfterMay = newPrincipalAfterMay.add(new BigDecimal(transaction.get("amount").toString()));
2777+
break;
2778+
}
2779+
}
2780+
}
2781+
}
2782+
2783+
BigDecimal daysInJune = new BigDecimal(30);
2784+
BigDecimal expectedJuneInterest = newPrincipalAfterMay
2785+
.multiply(new BigDecimal("0.15"))
2786+
.divide(new BigDecimal("365"), 8, RoundingMode.HALF_EVEN)
2787+
.multiply(daysInJune)
2788+
.setScale(2, RoundingMode.HALF_EVEN);
2789+
2790+
boolean junePostingVerified = false;
2791+
log.info("Verifying the 'Interest Posting' transaction for June... Expected amount: {}", expectedJuneInterest);
2792+
2793+
for (HashMap transaction : allTransactions) {
2794+
Map<String, Object> typeMap = (Map<String, Object>) transaction.get("transactionType");
2795+
if (typeMap != null) {
2796+
int typeId = ((Number) typeMap.get("id")).intValue();
2797+
SavingsAccountTransactionType txType = SavingsAccountTransactionType.fromInt(typeId);
2798+
2799+
if (txType.isInterestPosting()) {
2800+
List<Number> dateArray = (List<Number>) transaction.get("date");
2801+
LocalDate txDate = LocalDate.of(dateArray.get(0).intValue(), dateArray.get(1).intValue(), dateArray.get(2).intValue());
2802+
2803+
if (txDate.equals(endOfJune)) {
2804+
BigDecimal actualAmount = new BigDecimal(transaction.get("amount").toString());
2805+
log.info("Found 'Interest Posting' transaction on {} with amount: {}", txDate, actualAmount);
2806+
2807+
Assertions.assertEquals(0, expectedJuneInterest.compareTo(actualAmount),
2808+
"The interest posting amount for June (" + actualAmount + ") does not match the expected (" + expectedJuneInterest + ")");
2809+
2810+
junePostingVerified = true;
2811+
break;
2812+
}
2813+
}
2814+
}
2815+
}
2816+
2817+
Assertions.assertTrue(junePostingVerified, "The 'INTEREST_POSTING' transaction for June was not found.");
2818+
log.info("Successfully verified the interest posting transaction for June.");
2819+
2820+
} finally {
2821+
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE,
2822+
new PutGlobalConfigurationsRequest().enabled(false));
2823+
}
2824+
}
2825+
2826+
public Integer createFixedWithAccrualAccountingWithNoneInterest(Account... accounts) {
2827+
this.fixedDepositProductHelper = new FixedDepositProductHelper(null,null).withInterestCompoundingPeriodTypeAsNone()
2828+
.withCurrencyCode("NGN")
2829+
.withDigitsAfterDecimal("2")
2830+
.withInMultiplesOf("")
2831+
.withMinDepositAmount("1")
2832+
.withMaxDepositAmount("1000000000")
2833+
.withInterestPostingPeriodTypeAsMonthly()
2834+
.withInterestCalculationPeriodTypeAsDailyBalance()
2835+
.withLockinPeriodFrequency("")
2836+
.withLockingPeriodFrequencyType("")
2837+
.withInterestCalculationDaysInYearType_360()
2838+
.withMinDepositTerm("1")
2839+
.withMaxDepositTerm("")
2840+
.withInMultiplesOfDepositTerm("")
2841+
.with_minDepositTermTypeIdAsYears()
2842+
.withPreClosurePenalApplicable(false)
2843+
.withAccountingRuleAsAccrualBased(accounts)
2844+
.withInterestPayableAccountId(accounts[0].getAccountID().toString())
2845+
.withSavingsReferenceAccountId(accounts[3].getAccountID().toString())
2846+
.withFixedpenaltiesReceivableAccountId(accounts[3].getAccountID().toString())
2847+
.withInterestPayableAccountId(accounts[1].getAccountID().toString())
2848+
.withInterestOnSavingsAccountId(accounts[2].getAccountID().toString())
2849+
.withSavingsControlAccountId(accounts[4].getAccountID().toString())
2850+
.withPeriodFixed();
2851+
final String fixedProductJSON = this.fixedDepositProductHelper.build("01 January 2024", "01 January 2035", true);
2852+
return FixedDepositProductHelper.createFixedDepositProduct(fixedProductJSON, requestSpec ,responseSpec);
2853+
}
2854+
26012855
private Integer createFixedDepositProduct(final String validFrom, final String validTo, final String accountingRule,
26022856
Account... accounts) {
26032857
log.info("------------------------------CREATING NEW FIXED DEPOSIT PRODUCT ---------------------------------------");
@@ -2691,6 +2945,16 @@ private Integer applyForFixedDepositApplication(final String clientID, final Str
26912945
this.responseSpec);
26922946
}
26932947

2948+
private Integer applyForFixedDepositApplication_10000(final String clientID, final String productID, final String submittedOnDate,
2949+
final String penalInterestType, final Integer maturityInstructionId) {
2950+
log.info("--------------------------------APPLYING FOR FIXED DEPOSIT ACCOUNT --------------------------------");
2951+
final String fixedDepositApplicationJSON = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec) //
2952+
.withSubmittedOnDate(submittedOnDate).withMaturityInstructionId(maturityInstructionId).withDepositAmount("10000")
2953+
.build(clientID, productID, penalInterestType);
2954+
return FixedDepositAccountHelper.applyFixedDepositApplicationGetId(fixedDepositApplicationJSON, this.requestSpec,
2955+
this.responseSpec);
2956+
}
2957+
26942958
private Integer applyForFixedDepositApplication(final String clientID, final String productID, final String submittedOnDate,
26952959
final String penalInterestType, final String depositAmount, final String depositPeriod) {
26962960
log.info("--------------------------------APPLYING FOR FIXED DEPOSIT ACCOUNT --------------------------------");

0 commit comments

Comments
 (0)