From 55ef6628c1de79f60e400fb9f1121264c53b3adb Mon Sep 17 00:00:00 2001 From: Pramod Nuthakki Date: Mon, 30 Jun 2014 23:54:48 +0530 Subject: [PATCH] MIFOSX-1392 : changes for minBalanceForInterestCalculation --- api-docs/apiLive.htm | 6 +- ...d_min_balance_for_interest_calculation.sql | 6 + .../ClientSavingsIntegrationTest.java | 83 +++++++-- .../common/savings/SavingsProductHelper.java | 7 + .../savings/DepositsApiConstants.java | 23 +-- .../savings/SavingsApiConstants.java | 29 ++-- .../savings/data/DepositAccountData.java | 17 +- .../savings/data/DepositProductData.java | 26 ++- .../data/DepositProductDataValidator.java | 15 ++ .../savings/data/FixedDepositAccountData.java | 135 ++++++++------- .../savings/data/FixedDepositProductData.java | 57 ++++--- .../data/RecurringDepositAccountData.java | 158 +++++++++--------- .../data/RecurringDepositProductData.java | 77 +++++---- .../savings/data/SavingsAccountData.java | 22 ++- .../savings/data/SavingsProductData.java | 26 ++- .../data/SavingsProductDataValidator.java | 21 ++- .../domain/DepositProductAssembler.java | 24 ++- .../savings/domain/FixedDepositAccount.java | 8 +- .../savings/domain/FixedDepositProduct.java | 10 +- .../domain/RecurringDepositAccount.java | 3 +- .../domain/RecurringDepositProduct.java | 12 +- .../savings/domain/SavingsAccount.java | 46 +++-- .../savings/domain/SavingsProduct.java | 28 +++- .../domain/SavingsProductAssembler.java | 15 +- .../interest/AnnualCompoundingPeriod.java | 46 +++-- .../interest/BiAnnualCompoundingPeriod.java | 46 +++-- .../domain/interest/CompoundingPeriod.java | 4 +- .../interest/DailyCompoundingPeriod.java | 19 +-- .../domain/interest/EndOfDayBalance.java | 30 ++-- .../interest/MonthlyCompoundingPeriod.java | 37 ++-- .../domain/interest/PostingPeriod.java | 21 ++- .../interest/QuarterlyCompoundingPeriod.java | 64 ++++--- ...DepositAccountReadPlatformServiceImpl.java | 16 +- ...DepositProductReadPlatformServiceImpl.java | 6 +- ...SavingsAccountReadPlatformServiceImpl.java | 18 +- ...SavingsProductReadPlatformServiceImpl.java | 5 +- 36 files changed, 685 insertions(+), 481 deletions(-) create mode 100755 mifosng-db/migrations/core_db/V183__added_min_balance_for_interest_calculation.sql diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index 4a8d3c6a4..74252fa5b 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -15060,6 +15060,9 @@ Content-Type: application/json overdraftLimit Optional: If provided, sets the maximum allowed overdraft amount for a savings account e.g. 5,000 else set the limit as zero + minBalanceForInterestCalculation + Optional: If provided, balance must be greater than provided value for calculation of interest e.g. 5,000 + @@ -15631,7 +15634,7 @@ Content-Type: application/json
- +
Optional Fields
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, paymentChannelToFundSourceMappings, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, charges, allowOverdraft, overdraftLimit
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, paymentChannelToFundSourceMappings, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, charges, allowOverdraft, overdraftLimit, minBalanceForInterestCalculation
@@ -15680,6 +15683,7 @@ Request Body: "minRequiredOpeningBalance": "50", "allowOverdraft":true, "overdraftLimit":5000, + "minBalanceForInterestCalculation":5000, "lockinPeriodFrequency": "4", "lockinPeriodFrequencyType": "1", "withdrawalFeeForTransfers":false, diff --git a/mifosng-db/migrations/core_db/V183__added_min_balance_for_interest_calculation.sql b/mifosng-db/migrations/core_db/V183__added_min_balance_for_interest_calculation.sql new file mode 100755 index 000000000..eaaadb89c --- /dev/null +++ b/mifosng-db/migrations/core_db/V183__added_min_balance_for_interest_calculation.sql @@ -0,0 +1,6 @@ +ALTER TABLE `m_savings_product` + ADD COLUMN `min_balance_for_interest_calculation` DECIMAL(19,6) NULL DEFAULT NULL AFTER `allow_overdraft_min_balance`; + +ALTER TABLE `m_savings_account` + ADD COLUMN `min_balance_for_interest_calculation` DECIMAL(19,6) NULL DEFAULT NULL AFTER `allow_overdraft_min_balance`; + \ No newline at end of file diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientSavingsIntegrationTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientSavingsIntegrationTest.java index 02827481c..11326896d 100755 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientSavingsIntegrationTest.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientSavingsIntegrationTest.java @@ -57,8 +57,9 @@ public class ClientSavingsIntegrationTest { final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); Assert.assertNotNull(clientID); - - final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE); + final String minBalanceForInterestCalculation = null; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation); Assert.assertNotNull(savingsProductID); final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL); @@ -91,14 +92,56 @@ public class ClientSavingsIntegrationTest { } + @Test + public void testSavingsAccountWithMinBalanceForInterestCalculation() { + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientID); + final String minBalanceForInterestCalculation = "5000"; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation); + Assert.assertNotNull(savingsProductID); + + final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL); + Assert.assertNotNull(savingsProductID); + + HashMap modifications = this.savingsAccountHelper.updateSavingsAccount(clientID, savingsProductID, savingsId, + ACCOUNT_TYPE_INDIVIDUAL); + Assert.assertTrue(modifications.containsKey("submittedOnDate")); + + HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId); + SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap); + + savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId); + SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap); + + savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsId); + SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap); + + final HashMap summaryBefore = this.savingsAccountHelper.getSavingsSummary(savingsId); + this.savingsAccountHelper.calculateInterestForSavings(savingsId); + HashMap summary = this.savingsAccountHelper.getSavingsSummary(savingsId); + assertEquals(summaryBefore, summary); + + this.savingsAccountHelper.postInterestForSavings(savingsId); + summary = this.savingsAccountHelper.getSavingsSummary(savingsId); + assertEquals(summaryBefore, summary); + + final Object savingsInterest = this.savingsAccountHelper.getSavingsInterest(savingsId); + Assert.assertNull(savingsInterest); + + } + @Test public void testSavingsAccount_CLOSE_APPLICATION() { this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); Assert.assertNotNull(clientID); + final String minBalanceForInterestCalculation = null; - final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, null); + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, null, minBalanceForInterestCalculation); Assert.assertNotNull(savingsProductID); final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL); @@ -127,8 +170,8 @@ public class ClientSavingsIntegrationTest { final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); Assert.assertNotNull(clientID); - - final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, null); + final String minBalanceForInterestCalculation = null; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, null, minBalanceForInterestCalculation); Assert.assertNotNull(savingsProductID); final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL); @@ -166,8 +209,9 @@ public class ClientSavingsIntegrationTest { final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); Assert.assertNotNull(clientID); - - final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE); + final String minBalanceForInterestCalculation = null; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation); Assert.assertNotNull(savingsProductID); final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL); @@ -207,8 +251,9 @@ public class ClientSavingsIntegrationTest { final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); Assert.assertNotNull(clientID); - - final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE); + final String minBalanceForInterestCalculation = null; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation); Assert.assertNotNull(savingsProductID); final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL); @@ -231,8 +276,9 @@ public class ClientSavingsIntegrationTest { final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); Assert.assertNotNull(clientID); - - final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE); + final String minBalanceForInterestCalculation = null; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation); Assert.assertNotNull(savingsProductID); final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL); @@ -325,8 +371,9 @@ public class ClientSavingsIntegrationTest { final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); Assert.assertNotNull(clientID); - - final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE); + final String minBalanceForInterestCalculation = null; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation); Assert.assertNotNull(savingsProductID); final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL); @@ -400,10 +447,11 @@ public class ClientSavingsIntegrationTest { BigDecimal totalWaiveAmount = BigDecimal.valueOf(Double.valueOf((Float) savingsChargeForWaive.get("amount"))); totalWaiveAmount = totalWaiveAmount.add(totalWaiveAmount); assertEquals(totalWaiveAmount.floatValue(), waiveCharge.get("amountWaived")); - - final Integer weeklyFeeId = ChargesHelper.createCharges(this.requestSpec, this.responseSpec, ChargesHelper.getSavingsWeeklyFeeJSON()); + + final Integer weeklyFeeId = ChargesHelper.createCharges(this.requestSpec, this.responseSpec, + ChargesHelper.getSavingsWeeklyFeeJSON()); Assert.assertNotNull(weeklyFeeId); - + this.savingsAccountHelper.addChargesForSavings(savingsId, weeklyFeeId); charges = this.savingsAccountHelper.getSavingsCharges(savingsId); Assert.assertEquals(3, charges.size()); @@ -432,13 +480,14 @@ public class ClientSavingsIntegrationTest { } private Integer createSavingsProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, - final String minOpenningBalance) { + final String minOpenningBalance, String minBalanceForInterestCalculation) { System.out.println("------------------------------CREATING NEW SAVINGS PRODUCT ---------------------------------------"); SavingsProductHelper savingsProductHelper = new SavingsProductHelper(); final String savingsProductJSON = savingsProductHelper // .withInterestCompoundingPeriodTypeAsDaily() // .withInterestPostingPeriodTypeAsMonthly() // .withInterestCalculationPeriodTypeAsDailyBalance() // + .withMinBalanceForInterestCalculation(minBalanceForInterestCalculation)// .withMinimumOpenningBalance(minOpenningBalance).build(); return SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec); } diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/savings/SavingsProductHelper.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/savings/SavingsProductHelper.java index ddb7d0910..6a85d49f9 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/savings/SavingsProductHelper.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/savings/SavingsProductHelper.java @@ -63,6 +63,7 @@ public class SavingsProductHelper { private final String currencyCode = USD; private final String interestCalculationDaysInYearType = DAYS_365; private Account[] accountList = null; + private String minBalanceForInterestCalculation = null; public String build() { final HashMap map = new HashMap<>(); @@ -93,6 +94,7 @@ public class SavingsProductHelper { map.put("lockinPeriodFrequency", this.lockinPeriodFrequency); map.put("lockinPeriodFrequencyType", this.lockingPeriodFrequencyType); map.put("withdrawalFeeForTransfers", this.withdrawalFeeForTransfers); + map.put("minBalanceForInterestCalculation", minBalanceForInterestCalculation); if (this.accountingRule.equals(CASH_BASED)) { map.putAll(getAccountMappingForCashBased()); @@ -126,6 +128,11 @@ public class SavingsProductHelper { this.interestPostingPeriodType = MONTHLY; return this; } + + public SavingsProductHelper withMinBalanceForInterestCalculation(final String amount) { + this.minBalanceForInterestCalculation = amount; + return this; + } public SavingsProductHelper withInterestPostingPeriodTypeAsQuarterly() { this.interestPostingPeriodType = QUARTERLY; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/DepositsApiConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/DepositsApiConstants.java index ec7ce330a..eebd01b9f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/DepositsApiConstants.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/DepositsApiConstants.java @@ -183,8 +183,7 @@ public class DepositsApiConstants { public static final String chartTemplate = "chartTemplate"; // allowed column names for sorting the query result - public final static Set supportedOrderByValues = new HashSet<>(Arrays.asList("id", "accountNumbr", "officeId", - "officeName")); + public final static Set supportedOrderByValues = new HashSet<>(Arrays.asList("id", "accountNumbr", "officeId", "officeName")); /** * Deposit Product Parameters @@ -203,11 +202,11 @@ public class DepositsApiConstants { SAVINGS_PRODUCT_ACCOUNTING_PARAMS.FEE_INCOME_ACCOUNT_MAPPING.getValue(), SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PENALTY_INCOME_ACCOUNT_MAPPING.getValue(), chartsParamName)); - private static final Set PRECLOSURE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList( - preClosurePenalApplicableParamName, preClosurePenalInterestParamName, preClosurePenalInterestOnTypeIdParamName)); + private static final Set PRECLOSURE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(preClosurePenalApplicableParamName, + preClosurePenalInterestParamName, preClosurePenalInterestOnTypeIdParamName)); - private static final Set PRECLOSURE_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList( - preClosurePenalApplicableParamName, preClosurePenalInterestParamName, preClosurePenalInterestOnType)); + private static final Set PRECLOSURE_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(preClosurePenalApplicableParamName, + preClosurePenalInterestParamName, preClosurePenalInterestOnType)); private static final Set DEPOSIT_TERM_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(minDepositTermParamName, maxDepositTermParamName, minDepositTermTypeIdParamName, maxDepositTermTypeIdParamName, inMultiplesOfDepositTermParamName, @@ -258,6 +257,7 @@ public class DepositsApiConstants { recurringDepositRequestData.addAll(PRECLOSURE_REQUEST_DATA_PARAMETERS); recurringDepositRequestData.addAll(DEPOSIT_TERM_REQUEST_DATA_PARAMETERS); recurringDepositRequestData.addAll(RECURRING_DETAILS_REQUEST_DATA_PARAMETERS); + recurringDepositRequestData.add(SavingsApiConstants.minBalanceForInterestCalculationParamName); return recurringDepositRequestData; } @@ -267,6 +267,7 @@ public class DepositsApiConstants { recurringDepositRequestData.addAll(PRECLOSURE_RESPONSE_DATA_PARAMETERS); recurringDepositRequestData.addAll(DEPOSIT_TERM_RESPONSE_DATA_PARAMETERS); recurringDepositRequestData.addAll(RECURRING_DETAILS_RESPONSE_DATA_PARAMETERS); + recurringDepositRequestData.add(SavingsApiConstants.minBalanceForInterestCalculationParamName); return recurringDepositRequestData; } @@ -326,8 +327,8 @@ public class DepositsApiConstants { return recurringDepositResponseData; } - public static final Set DEPOSIT_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList( - localeParamName, dateFormatParamName, transactionDateParamName, transactionAmountParamName, paymentTypeIdParamName, + public static final Set DEPOSIT_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName, + dateFormatParamName, transactionDateParamName, transactionAmountParamName, paymentTypeIdParamName, transactionAccountNumberParamName, checkNumberParamName, routingCodeParamName, receiptNumberParamName, bankNumberParamName)); public static final Set FIXED_DEPOSIT_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(idParamName, @@ -355,9 +356,9 @@ public class DepositsApiConstants { amountWaivedParamName, amountWrittenOffParamName, amountOutstandingParamName, amountOrPercentageParamName, amountParamName, amountPaidParamName, chargeOptionsParamName)); - public static final Set SAVINGS_ACCOUNT_CHARGES_ADD_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList( - chargeIdParamName, amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName, feeOnMonthDayParamName, - monthDayFormatParamName, feeIntervalParamName)); + public static final Set SAVINGS_ACCOUNT_CHARGES_ADD_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(chargeIdParamName, + amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName, feeOnMonthDayParamName, monthDayFormatParamName, + feeIntervalParamName)); public static final Set SAVINGS_ACCOUNT_CHARGES_PAY_CHARGE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList( amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName)); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsApiConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsApiConstants.java index d040d2ffc..162c1f86c 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsApiConstants.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsApiConstants.java @@ -97,6 +97,7 @@ public class SavingsApiConstants { public static final String overdraftLimitParamName = "overdraftLimit"; public static final String minRequiredBalanceParamName = "minRequiredBalance"; public static final String allowOverdraftMinBalanceParamName = "allowOverdraftMinBalance"; + public static final String minBalanceForInterestCalculationParamName = "minBalanceForInterestCalculation"; // transaction parameters public static final String transactionDateParamName = "transactionDate"; @@ -152,15 +153,15 @@ public class SavingsApiConstants { SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(), allowOverdraftParamName, overdraftLimitParamName, - minRequiredBalanceParamName, allowOverdraftMinBalanceParamName)); + minRequiredBalanceParamName, allowOverdraftMinBalanceParamName, minBalanceForInterestCalculationParamName)); /** * These parameters will match the class level parameters of * {@link SavingsProductData}. Where possible, we try to get response * parameters to match those of request parameters. */ - public static final Set SAVINGS_PRODUCT_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(idParamName, - nameParamName, shortNameParamName, descriptionParamName, "currency", digitsAfterDecimalParamName, inMultiplesOfParamName, + public static final Set SAVINGS_PRODUCT_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(idParamName, nameParamName, + shortNameParamName, descriptionParamName, "currency", digitsAfterDecimalParamName, inMultiplesOfParamName, nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, @@ -183,9 +184,9 @@ public class SavingsApiConstants { * {@link SavingsAccountData}. Where possible, we try to get response * parameters to match those of request parameters. */ - public static final Set SAVINGS_ACCOUNT_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(idParamName, - accountNoParamName, externalIdParamName, statusParamName, activatedOnDateParamName, clientIdParamName, "clientName", - groupIdParamName, "groupName", "savingsProductId", "savingsProductName", "currency", nominalAnnualInterestRateParamName, + public static final Set SAVINGS_ACCOUNT_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(idParamName, accountNoParamName, + externalIdParamName, statusParamName, activatedOnDateParamName, clientIdParamName, "clientName", groupIdParamName, "groupName", + "savingsProductId", "savingsProductName", "currency", nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, withdrawalFeeForTransfersParamName, feeAmountParamName, @@ -193,13 +194,13 @@ public class SavingsApiConstants { "interestPostingPeriodTypeOptions", "interestCalculationTypeOptions", "interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions", "withdrawalFee", "annualFee")); - public static final Set SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList( - localeParamName, dateFormatParamName, transactionDateParamName, transactionAmountParamName, paymentTypeIdParamName, + public static final Set SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName, + dateFormatParamName, transactionDateParamName, transactionAmountParamName, paymentTypeIdParamName, transactionAccountNumberParamName, checkNumberParamName, routingCodeParamName, receiptNumberParamName, bankNumberParamName)); - public static final Set SAVINGS_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(idParamName, - "accountId", accountNoParamName, "currency", "amount", dateParamName, paymentDetailDataParamName, runningBalanceParamName, - reversedParamName)); + public static final Set SAVINGS_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet<>( + Arrays.asList(idParamName, "accountId", accountNoParamName, "currency", "amount", dateParamName, paymentDetailDataParamName, + runningBalanceParamName, reversedParamName)); public static final Set SAVINGS_ACCOUNT_ACTIVATION_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName, dateFormatParamName, activatedOnDateParamName)); @@ -213,9 +214,9 @@ public class SavingsApiConstants { amountWaivedParamName, amountWrittenOffParamName, amountOutstandingParamName, amountOrPercentageParamName, amountParamName, amountPaidParamName, chargeOptionsParamName)); - public static final Set SAVINGS_ACCOUNT_CHARGES_ADD_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList( - chargeIdParamName, amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName, feeOnMonthDayParamName, - monthDayFormatParamName, feeIntervalParamName)); + public static final Set SAVINGS_ACCOUNT_CHARGES_ADD_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(chargeIdParamName, + amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName, feeOnMonthDayParamName, monthDayFormatParamName, + feeIntervalParamName)); public static final Set SAVINGS_ACCOUNT_CHARGES_PAY_CHARGE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList( amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName)); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/DepositAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/DepositAccountData.java index 0301717bb..1efc2eab1 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/DepositAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/DepositAccountData.java @@ -17,8 +17,8 @@ import org.mifosplatform.organisation.staff.data.StaffData; import org.mifosplatform.portfolio.charge.data.ChargeData; /** - * Immutable data object representing abstract for Fixed and Recurring Deposit Accounts - * Accounts. + * Immutable data object representing abstract for Fixed and Recurring Deposit + * Accounts Accounts. */ public class DepositAccountData { @@ -46,6 +46,7 @@ public class DepositAccountData { protected final EnumOptionData lockinPeriodFrequencyType; protected final boolean withdrawalFeeForTransfers; protected final EnumOptionData depositType; + protected final BigDecimal minBalanceForInterestCalculation; // associations protected final SavingsAccountSummaryData summary; @@ -78,7 +79,7 @@ public class DepositAccountData { final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers, - final SavingsAccountSummaryData summary, final EnumOptionData depositType) { + final SavingsAccountSummaryData summary, final EnumOptionData depositType, final BigDecimal minBalanceForInterestCalculation) { final Collection productOptions = null; final Collection fieldOfficerOptions = null; @@ -101,7 +102,8 @@ public class DepositAccountData { lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, - withdrawalFeeTypeOptions, charges, chargeOptions, accountChart, chartTemplate, depositType); + withdrawalFeeTypeOptions, charges, chargeOptions, accountChart, chartTemplate, depositType, + minBalanceForInterestCalculation); } public static DepositAccountData lookup(final Long id, final String accountNo, final EnumOptionData depositType) { @@ -142,6 +144,7 @@ public class DepositAccountData { final Collection chargeOptions = null; final DepositAccountInterestRateChartData accountChart = null; final DepositAccountInterestRateChartData chartTemplate = null; + final BigDecimal minBalanceForInterestCalculation = null; return new DepositAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, interestRate, interestCompoundingPeriodType, @@ -149,7 +152,8 @@ public class DepositAccountData { lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, - withdrawalFeeTypeOptions, charges, chargeOptions, accountChart, chartTemplate, depositType); + withdrawalFeeTypeOptions, charges, chargeOptions, accountChart, chartTemplate, depositType, + minBalanceForInterestCalculation); } protected DepositAccountData(final Long id, final String accountNo, final String externalId, final Long groupId, @@ -169,7 +173,7 @@ public class DepositAccountData { final Collection lockinPeriodFrequencyTypeOptions, final Collection withdrawalFeeTypeOptions, final Collection charges, final Collection chargeOptions, final DepositAccountInterestRateChartData accountChart, final DepositAccountInterestRateChartData chartTemplate, - final EnumOptionData depositType) { + final EnumOptionData depositType, final BigDecimal minBalanceForInterestCalculation) { this.id = id; this.accountNo = accountNo; this.externalId = externalId; @@ -215,6 +219,7 @@ public class DepositAccountData { this.accountChart = accountChart; this.chartTemplate = chartTemplate; this.depositType = depositType; + this.minBalanceForInterestCalculation = minBalanceForInterestCalculation; } private SavingsAccountChargeData getWithdrawalFee() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/DepositProductData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/DepositProductData.java index b658ecdde..00c8ddbc5 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/DepositProductData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/DepositProductData.java @@ -39,6 +39,7 @@ public class DepositProductData { protected final Integer lockinPeriodFrequency; protected final EnumOptionData lockinPeriodFrequencyType; // protected final boolean withdrawalFeeForTransfers; + protected final BigDecimal minBalanceForInterestCalculation; // accounting protected final EnumOptionData accountingRule; @@ -88,6 +89,7 @@ public class DepositProductData { final BigDecimal nominalAnnualInterestRate = null; final Integer lockinPeriodFrequency = null; final EnumOptionData lockinPeriodFrequencyType = null; + final BigDecimal minBalanceForInterestCalculation = null; final Map accountingMappings = null; final Collection paymentChannelToFundSourceMappings = null; final Collection charges = null; @@ -101,7 +103,7 @@ public class DepositProductData { interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, - penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate); + penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate, minBalanceForInterestCalculation); } public static DepositProductData withCharges(final DepositProductData existingProduct, final Collection charges) { @@ -116,7 +118,8 @@ public class DepositProductData { existingProduct.lockinPeriodFrequencyTypeOptions, existingProduct.withdrawalFeeTypeOptions, existingProduct.paymentTypeOptions, existingProduct.accountingRuleOptions, existingProduct.accountingMappingOptions, charges, existingProduct.chargeOptions, existingProduct.penaltyOptions, existingProduct.feeToIncomeAccountMappings, - existingProduct.penaltyToIncomeAccountMappings, existingProduct.interestRateCharts, existingProduct.chartTemplate); + existingProduct.penaltyToIncomeAccountMappings, existingProduct.interestRateCharts, existingProduct.chartTemplate, + existingProduct.minBalanceForInterestCalculation); } /** @@ -143,7 +146,7 @@ public class DepositProductData { lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, existingProduct.feeToIncomeAccountMappings, existingProduct.penaltyToIncomeAccountMappings, - existingProduct.interestRateCharts, chartTemplate); + existingProduct.interestRateCharts, chartTemplate, existingProduct.minBalanceForInterestCalculation); } public static DepositProductData withAccountingDetails(final DepositProductData existingProduct, @@ -174,14 +177,16 @@ public class DepositProductData { interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, - penaltyToIncomeAccountMappings, existingProduct.interestRateCharts, existingProduct.chartTemplate); + penaltyToIncomeAccountMappings, existingProduct.interestRateCharts, existingProduct.chartTemplate, + existingProduct.minBalanceForInterestCalculation); } public static DepositProductData instance(final Long id, final String name, final String shortName, final String description, final CurrencyData currency, final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType, final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType, final Integer lockinPeriodFrequency, - final EnumOptionData lockinPeriodFrequencyType, final EnumOptionData accountingType) { + final EnumOptionData lockinPeriodFrequencyType, final EnumOptionData accountingType, + final BigDecimal minBalanceForInterestCalculation) { final Map accountingMappings = null; final Collection paymentChannelToFundSourceMappings = null; @@ -210,7 +215,7 @@ public class DepositProductData { interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, - penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate); + penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate, minBalanceForInterestCalculation); } public static DepositProductData lookup(final Long id, final String name) { @@ -225,6 +230,7 @@ public class DepositProductData { final EnumOptionData interestCalculationDaysInYearType = null; final Integer lockinPeriodFrequency = null; final EnumOptionData lockinPeriodFrequencyType = null; + final BigDecimal minBalanceForInterestCalculation = null; final EnumOptionData accountingType = null; final Map accountingMappings = null; @@ -254,7 +260,7 @@ public class DepositProductData { interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, - penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate); + penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate, minBalanceForInterestCalculation); } public static DepositProductData withInterestChart(final DepositProductData existingProduct, @@ -271,7 +277,7 @@ public class DepositProductData { existingProduct.paymentTypeOptions, existingProduct.accountingRuleOptions, existingProduct.accountingMappingOptions, existingProduct.charges, existingProduct.chargeOptions, existingProduct.penaltyOptions, existingProduct.feeToIncomeAccountMappings, existingProduct.penaltyToIncomeAccountMappings, interestRateCharts, - existingProduct.chartTemplate); + existingProduct.chartTemplate, existingProduct.minBalanceForInterestCalculation); } protected DepositProductData(final Long id, final String name, final String shortName, final String description, @@ -291,7 +297,8 @@ public class DepositProductData { final Collection chargeOptions, final Collection penaltyOptions, final Collection feeToIncomeAccountMappings, final Collection penaltyToIncomeAccountMappings, - final Collection interestRateCharts, final InterestRateChartData chartTemplate) { + final Collection interestRateCharts, final InterestRateChartData chartTemplate, + final BigDecimal minBalanceForInterestCalculation) { this.id = id; this.name = name; @@ -336,6 +343,7 @@ public class DepositProductData { this.interestRateCharts = interestRateCharts; this.activeChart = activeChart(this.interestRateCharts); this.chartTemplate = chartTemplate; + this.minBalanceForInterestCalculation = minBalanceForInterestCalculation; } public static InterestRateChartData activeChart(Collection interestRateCharts) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/DepositProductDataValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/DepositProductDataValidator.java index 592eb6270..de5bfa910 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/DepositProductDataValidator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/DepositProductDataValidator.java @@ -38,6 +38,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCo import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minBalanceForInterestCalculationParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName; @@ -273,6 +274,13 @@ public class DepositProductDataValidator { } } + if (this.fromApiJsonHelper.parameterExists(minBalanceForInterestCalculationParamName, element)) { + final BigDecimal minBalanceForInterestCalculation = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed( + minBalanceForInterestCalculationParamName, element); + baseDataValidator.reset().parameter(minBalanceForInterestCalculationParamName).value(minBalanceForInterestCalculation) + .ignoreIfNull().zeroOrPositiveAmount(); + } + // accounting related data validation final Integer accountingRuleType = fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault()); baseDataValidator.reset().parameter("accountingRule").value(accountingRuleType).notNull().inMinMaxRange(1, 3); @@ -479,6 +487,13 @@ public class DepositProductDataValidator { baseDataValidator.reset().parameter(feeOnMonthDayParamName).value(monthDayOfAnnualFee).ignoreIfNull(); } + if (this.fromApiJsonHelper.parameterExists(minBalanceForInterestCalculationParamName, element)) { + final BigDecimal minBalanceForInterestCalculation = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed( + minBalanceForInterestCalculationParamName, element); + baseDataValidator.reset().parameter(minBalanceForInterestCalculationParamName).value(minBalanceForInterestCalculation) + .ignoreIfNull().zeroOrPositiveAmount(); + } + final Long savingsControlAccountId = fromApiJsonHelper.extractLongNamed( SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(), element); baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue()).value(savingsControlAccountId) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/FixedDepositAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/FixedDepositAccountData.java index 8c2e7a98d..2ff007b15 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/FixedDepositAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/FixedDepositAccountData.java @@ -78,16 +78,16 @@ public class FixedDepositAccountData extends DepositAccountData { depositAccountData.interestPostingPeriodType, depositAccountData.interestCalculationType, depositAccountData.interestCalculationDaysInYearType, depositAccountData.minRequiredOpeningBalance, depositAccountData.lockinPeriodFrequency, depositAccountData.lockinPeriodFrequencyType, - depositAccountData.withdrawalFeeForTransfers, depositAccountData.summary, depositAccountData.transactions, - depositAccountData.productOptions, depositAccountData.fieldOfficerOptions, - depositAccountData.interestCompoundingPeriodTypeOptions, depositAccountData.interestPostingPeriodTypeOptions, - depositAccountData.interestCalculationTypeOptions, depositAccountData.interestCalculationDaysInYearTypeOptions, - depositAccountData.lockinPeriodFrequencyTypeOptions, depositAccountData.withdrawalFeeTypeOptions, - depositAccountData.charges, depositAccountData.chargeOptions, depositAccountData.accountChart, - depositAccountData.chartTemplate, preClosurePenalApplicable, preClosurePenalInterest, preClosurePenalInterestOnType, - preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType, - inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, depositPeriod, - depositPeriodFrequency, periodFrequencyTypeOptions, depositType, onAccountClosure, onAccountClosureOptions, + depositAccountData.withdrawalFeeForTransfers, depositAccountData.minBalanceForInterestCalculation, + depositAccountData.summary, depositAccountData.transactions, depositAccountData.productOptions, + depositAccountData.fieldOfficerOptions, depositAccountData.interestCompoundingPeriodTypeOptions, + depositAccountData.interestPostingPeriodTypeOptions, depositAccountData.interestCalculationTypeOptions, + depositAccountData.interestCalculationDaysInYearTypeOptions, depositAccountData.lockinPeriodFrequencyTypeOptions, + depositAccountData.withdrawalFeeTypeOptions, depositAccountData.charges, depositAccountData.chargeOptions, + depositAccountData.accountChart, depositAccountData.chartTemplate, preClosurePenalApplicable, preClosurePenalInterest, + preClosurePenalInterestOnType, preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, + maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, + depositPeriod, depositPeriodFrequency, periodFrequencyTypeOptions, depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, linkedAccount, transferInterestToSavings); } @@ -98,17 +98,18 @@ public class FixedDepositAccountData extends DepositAccountData { account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance, account.lockinPeriodFrequency, - account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary, account.transactions, - account.productOptions, account.fieldOfficerOptions, account.interestCompoundingPeriodTypeOptions, - account.interestPostingPeriodTypeOptions, account.interestCalculationTypeOptions, - account.interestCalculationDaysInYearTypeOptions, account.lockinPeriodFrequencyTypeOptions, - account.withdrawalFeeTypeOptions, account.charges, account.chargeOptions, accountChart, account.chartTemplate, - account.preClosurePenalApplicable, account.preClosurePenalInterest, account.preClosurePenalInterestOnType, - account.preClosurePenalInterestOnTypeOptions, account.minDepositTerm, account.maxDepositTerm, account.minDepositTermType, - account.maxDepositTermType, account.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, - account.maturityAmount, account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, - account.periodFrequencyTypeOptions, account.depositType, account.onAccountClosure, account.onAccountClosureOptions, - account.paymentTypeOptions, account.savingsAccounts, account.linkedAccount, account.transferInterestToSavings); + account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.minBalanceForInterestCalculation, + account.summary, account.transactions, account.productOptions, account.fieldOfficerOptions, + account.interestCompoundingPeriodTypeOptions, account.interestPostingPeriodTypeOptions, + account.interestCalculationTypeOptions, account.interestCalculationDaysInYearTypeOptions, + account.lockinPeriodFrequencyTypeOptions, account.withdrawalFeeTypeOptions, account.charges, account.chargeOptions, + accountChart, account.chartTemplate, account.preClosurePenalApplicable, account.preClosurePenalInterest, + account.preClosurePenalInterestOnType, account.preClosurePenalInterestOnTypeOptions, account.minDepositTerm, + account.maxDepositTerm, account.minDepositTermType, account.maxDepositTermType, account.inMultiplesOfDepositTerm, + account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount, account.maturityDate, + account.depositPeriod, account.depositPeriodFrequency, account.periodFrequencyTypeOptions, account.depositType, + account.onAccountClosure, account.onAccountClosureOptions, account.paymentTypeOptions, account.savingsAccounts, + account.linkedAccount, account.transferInterestToSavings); } public static FixedDepositAccountData associationsAndTemplate(final FixedDepositAccountData account, FixedDepositAccountData template, @@ -124,17 +125,18 @@ public class FixedDepositAccountData extends DepositAccountData { account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance, account.lockinPeriodFrequency, - account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary, transactions, - template.productOptions, template.fieldOfficerOptions, template.interestCompoundingPeriodTypeOptions, - template.interestPostingPeriodTypeOptions, template.interestCalculationTypeOptions, - template.interestCalculationDaysInYearTypeOptions, template.lockinPeriodFrequencyTypeOptions, - template.withdrawalFeeTypeOptions, charges, template.chargeOptions, account.accountChart, account.chartTemplate, - account.preClosurePenalApplicable, account.preClosurePenalInterest, account.preClosurePenalInterestOnType, - template.preClosurePenalInterestOnTypeOptions, account.minDepositTerm, account.maxDepositTerm, account.minDepositTermType, - account.maxDepositTermType, account.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, - account.maturityAmount, account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, - template.periodFrequencyTypeOptions, account.depositType, account.onAccountClosure, account.onAccountClosureOptions, - account.paymentTypeOptions, template.savingsAccounts, linkedAccount, account.transferInterestToSavings); + account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.minBalanceForInterestCalculation, + account.summary, transactions, template.productOptions, template.fieldOfficerOptions, + template.interestCompoundingPeriodTypeOptions, template.interestPostingPeriodTypeOptions, + template.interestCalculationTypeOptions, template.interestCalculationDaysInYearTypeOptions, + template.lockinPeriodFrequencyTypeOptions, template.withdrawalFeeTypeOptions, charges, template.chargeOptions, + account.accountChart, account.chartTemplate, account.preClosurePenalApplicable, account.preClosurePenalInterest, + account.preClosurePenalInterestOnType, template.preClosurePenalInterestOnTypeOptions, account.minDepositTerm, + account.maxDepositTerm, account.minDepositTermType, account.maxDepositTermType, account.inMultiplesOfDepositTerm, + account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount, account.maturityDate, + account.depositPeriod, account.depositPeriodFrequency, template.periodFrequencyTypeOptions, account.depositType, + account.onAccountClosure, account.onAccountClosureOptions, account.paymentTypeOptions, template.savingsAccounts, + linkedAccount, account.transferInterestToSavings); } public static FixedDepositAccountData withTemplateOptions(final FixedDepositAccountData account, @@ -148,22 +150,22 @@ public class FixedDepositAccountData extends DepositAccountData { final Collection chargeOptions, final Collection preClosurePenalInterestOnTypeOptions, final Collection periodFrequencyTypeOptions, final Collection savingsAccounts) { - return new FixedDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName, account.clientId, account.clientName, account.depositProductId, account.depositProductName, account.fieldOfficerId, account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance, account.lockinPeriodFrequency, - account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary, transactions, productOptions, - fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, - interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, - withdrawalFeeTypeOptions, charges, chargeOptions, account.accountChart, account.chartTemplate, - account.preClosurePenalApplicable, account.preClosurePenalInterest, account.preClosurePenalInterestOnType, - preClosurePenalInterestOnTypeOptions, account.minDepositTerm, account.maxDepositTerm, account.minDepositTermType, - account.maxDepositTermType, account.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, - account.maturityAmount, account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, - periodFrequencyTypeOptions, account.depositType, account.onAccountClosure, account.onAccountClosureOptions, - account.paymentTypeOptions, savingsAccounts, account.linkedAccount, account.transferInterestToSavings); + account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.minBalanceForInterestCalculation, + account.summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, + interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, + lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, account.accountChart, + account.chartTemplate, account.preClosurePenalApplicable, account.preClosurePenalInterest, + account.preClosurePenalInterestOnType, preClosurePenalInterestOnTypeOptions, account.minDepositTerm, + account.maxDepositTerm, account.minDepositTermType, account.maxDepositTermType, account.inMultiplesOfDepositTerm, + account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount, account.maturityDate, + account.depositPeriod, account.depositPeriodFrequency, periodFrequencyTypeOptions, account.depositType, + account.onAccountClosure, account.onAccountClosureOptions, account.paymentTypeOptions, savingsAccounts, + account.linkedAccount, account.transferInterestToSavings); } public static FixedDepositAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId, @@ -188,6 +190,7 @@ public class FixedDepositAccountData extends DepositAccountData { final Integer lockinPeriodFrequency = null; final EnumOptionData lockinPeriodFrequencyType = null; final boolean withdrawalFeeForTransfers = false; + final BigDecimal minBalanceForInterestCalculation = null; final SavingsAccountSummaryData summary = null; final Collection transactions = null; @@ -233,14 +236,15 @@ public class FixedDepositAccountData extends DepositAccountData { return new FixedDepositAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, - lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions, - fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, + lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, minBalanceForInterestCalculation, summary, + transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, accountChart, chartTemplate, preClosurePenalApplicable, preClosurePenalInterest, preClosurePenalInterestOnType, preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, depositPeriod, depositPeriodFrequency, periodFrequencyTypeOptions, - depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, linkedAccount, transferInterestToSavings); + depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, linkedAccount, + transferInterestToSavings); } public static FixedDepositAccountData preClosureDetails(final Long accountId, BigDecimal maturityAmount, @@ -269,6 +273,7 @@ public class FixedDepositAccountData extends DepositAccountData { final Integer lockinPeriodFrequency = null; final EnumOptionData lockinPeriodFrequencyType = null; final boolean withdrawalFeeForTransfers = false; + final BigDecimal minBalanceForInterestCalculation = null; final SavingsAccountSummaryData summary = null; final Collection transactions = null; final Collection productOptions = null; @@ -310,14 +315,15 @@ public class FixedDepositAccountData extends DepositAccountData { return new FixedDepositAccountData(accountId, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, - lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions, - fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, + lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, minBalanceForInterestCalculation, summary, + transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, accountChart, chartTemplate, preClosurePenalApplicable, preClosurePenalInterest, preClosurePenalInterestOnType, preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, depositPeriod, depositPeriodFrequency, periodFrequencyTypeOptions, - depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, linkedAccount, transferInterestToSavings); + depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, linkedAccount, + transferInterestToSavings); } public static FixedDepositAccountData withClosureTemplateDetails(final FixedDepositAccountData account, @@ -329,17 +335,18 @@ public class FixedDepositAccountData extends DepositAccountData { account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance, account.lockinPeriodFrequency, - account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary, account.transactions, - account.productOptions, account.fieldOfficerOptions, account.interestCompoundingPeriodTypeOptions, - account.interestPostingPeriodTypeOptions, account.interestCalculationTypeOptions, - account.interestCalculationDaysInYearTypeOptions, account.lockinPeriodFrequencyTypeOptions, - account.withdrawalFeeTypeOptions, account.charges, account.chargeOptions, account.accountChart, account.chartTemplate, - account.preClosurePenalApplicable, account.preClosurePenalInterest, account.preClosurePenalInterestOnType, - account.preClosurePenalInterestOnTypeOptions, account.minDepositTerm, account.maxDepositTerm, account.minDepositTermType, - account.maxDepositTermType, account.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, - account.maturityAmount, account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, - account.periodFrequencyTypeOptions, account.depositType, account.onAccountClosure, onAccountClosureOptions, - paymentTypeOptions, savingsAccountDatas, account.linkedAccount, account.transferInterestToSavings); + account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.minBalanceForInterestCalculation, + account.summary, account.transactions, account.productOptions, account.fieldOfficerOptions, + account.interestCompoundingPeriodTypeOptions, account.interestPostingPeriodTypeOptions, + account.interestCalculationTypeOptions, account.interestCalculationDaysInYearTypeOptions, + account.lockinPeriodFrequencyTypeOptions, account.withdrawalFeeTypeOptions, account.charges, account.chargeOptions, + account.accountChart, account.chartTemplate, account.preClosurePenalApplicable, account.preClosurePenalInterest, + account.preClosurePenalInterestOnType, account.preClosurePenalInterestOnTypeOptions, account.minDepositTerm, + account.maxDepositTerm, account.minDepositTermType, account.maxDepositTermType, account.inMultiplesOfDepositTerm, + account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount, account.maturityDate, + account.depositPeriod, account.depositPeriodFrequency, account.periodFrequencyTypeOptions, account.depositType, + account.onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, account.linkedAccount, + account.transferInterestToSavings); } @@ -351,9 +358,9 @@ public class FixedDepositAccountData extends DepositAccountData { final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers, - final SavingsAccountSummaryData summary, final Collection transactions, - final Collection productOptions, final Collection fieldOfficerOptions, - final Collection interestCompoundingPeriodTypeOptions, + final BigDecimal minBalanceForInterestCalculation, final SavingsAccountSummaryData summary, + final Collection transactions, final Collection productOptions, + final Collection fieldOfficerOptions, final Collection interestCompoundingPeriodTypeOptions, final Collection interestPostingPeriodTypeOptions, final Collection interestCalculationTypeOptions, final Collection interestCalculationDaysInYearTypeOptions, @@ -377,7 +384,7 @@ public class FixedDepositAccountData extends DepositAccountData { lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, - chargeOptions, accountChart, chartTemplate, depositType); + chargeOptions, accountChart, chartTemplate, depositType, minBalanceForInterestCalculation); this.preClosurePenalApplicable = preClosurePenalApplicable; this.preClosurePenalInterest = preClosurePenalInterest; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/FixedDepositProductData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/FixedDepositProductData.java index 6dfe81446..de3498615 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/FixedDepositProductData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/FixedDepositProductData.java @@ -62,6 +62,7 @@ public class FixedDepositProductData extends DepositProductData { final BigDecimal nominalAnnualInterestRate = null; final Integer lockinPeriodFrequency = null; final EnumOptionData lockinPeriodFrequencyType = null; + final BigDecimal minBalanceForInterestCalculation = null; final Map accountingMappings = null; final Collection paymentChannelToFundSourceMappings = null; final Collection charges = null; @@ -84,10 +85,11 @@ public class FixedDepositProductData extends DepositProductData { return new FixedDepositProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, - lockinPeriodFrequency, lockinPeriodFrequencyType, accountingRule, accountingMappings, paymentChannelToFundSourceMappings, - currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, - interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, - accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, + lockinPeriodFrequency, lockinPeriodFrequencyType, minBalanceForInterestCalculation, accountingRule, accountingMappings, + paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, + interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, + lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, + accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate, preClosurePenalApplicable, preClosurePenalInterest, preClosurePenalInterestOnType, preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, minDepositAmount, depositAmount, @@ -99,8 +101,9 @@ public class FixedDepositProductData extends DepositProductData { existingProduct.description, existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType, existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType, existingProduct.interestCalculationDaysInYearType, - existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, existingProduct.accountingRule, - existingProduct.accountingMappings, existingProduct.paymentChannelToFundSourceMappings, existingProduct.currencyOptions, + existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, + existingProduct.minBalanceForInterestCalculation, existingProduct.accountingRule, existingProduct.accountingMappings, + existingProduct.paymentChannelToFundSourceMappings, existingProduct.currencyOptions, existingProduct.interestCompoundingPeriodTypeOptions, existingProduct.interestPostingPeriodTypeOptions, existingProduct.interestCalculationTypeOptions, existingProduct.interestCalculationDaysInYearTypeOptions, existingProduct.lockinPeriodFrequencyTypeOptions, existingProduct.withdrawalFeeTypeOptions, @@ -136,11 +139,12 @@ public class FixedDepositProductData extends DepositProductData { existingProduct.description, existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType, existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType, existingProduct.interestCalculationDaysInYearType, - existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, existingProduct.accountingRule, - existingProduct.accountingMappings, existingProduct.paymentChannelToFundSourceMappings, currencyOptions, - interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, - interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, - accountingRuleOptions, accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, + existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, + existingProduct.minBalanceForInterestCalculation, existingProduct.accountingRule, existingProduct.accountingMappings, + existingProduct.paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, + interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, + lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, + accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, existingProduct.feeToIncomeAccountMappings, existingProduct.penaltyToIncomeAccountMappings, existingProduct.interestRateCharts, chartTemplate, existingProduct.preClosurePenalApplicable, existingProduct.preClosurePenalInterest, existingProduct.preClosurePenalInterestOnType, @@ -173,8 +177,9 @@ public class FixedDepositProductData extends DepositProductData { existingProduct.description, existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType, existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType, existingProduct.interestCalculationDaysInYearType, - existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, existingProduct.accountingRule, - accountingMappings, paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, + existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, + existingProduct.minBalanceForInterestCalculation, existingProduct.accountingRule, accountingMappings, + paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, @@ -220,8 +225,9 @@ public class FixedDepositProductData extends DepositProductData { depositProductData.description, depositProductData.currency, depositProductData.nominalAnnualInterestRate, depositProductData.interestCompoundingPeriodType, depositProductData.interestPostingPeriodType, depositProductData.interestCalculationType, depositProductData.interestCalculationDaysInYearType, - depositProductData.lockinPeriodFrequency, depositProductData.lockinPeriodFrequencyType, depositProductData.accountingRule, - accountingMappings, paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, + depositProductData.lockinPeriodFrequency, depositProductData.lockinPeriodFrequencyType, + depositProductData.minBalanceForInterestCalculation, depositProductData.accountingRule, accountingMappings, + paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, @@ -243,6 +249,7 @@ public class FixedDepositProductData extends DepositProductData { final EnumOptionData interestCalculationDaysInYearType = null; final Integer lockinPeriodFrequency = null; final EnumOptionData lockinPeriodFrequencyType = null; + final BigDecimal minBalanceForInterestCalculation = null; final EnumOptionData accountingType = null; final Map accountingMappings = null; final Collection paymentChannelToFundSourceMappings = null; @@ -281,10 +288,11 @@ public class FixedDepositProductData extends DepositProductData { return new FixedDepositProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, - lockinPeriodFrequency, lockinPeriodFrequencyType, accountingType, accountingMappings, paymentChannelToFundSourceMappings, - currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, - interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, - accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, + lockinPeriodFrequency, lockinPeriodFrequencyType, minBalanceForInterestCalculation, accountingType, accountingMappings, + paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, + interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, + lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, + accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate, preClosurePenalApplicable, preClosurePenalInterest, preClosurePenalInterestOnType, preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, minDepositAmount, depositAmount, @@ -297,8 +305,9 @@ public class FixedDepositProductData extends DepositProductData { existingProduct.description, existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType, existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType, existingProduct.interestCalculationDaysInYearType, - existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, existingProduct.accountingRule, - existingProduct.accountingMappings, existingProduct.paymentChannelToFundSourceMappings, existingProduct.currencyOptions, + existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, + existingProduct.minBalanceForInterestCalculation, existingProduct.accountingRule, existingProduct.accountingMappings, + existingProduct.paymentChannelToFundSourceMappings, existingProduct.currencyOptions, existingProduct.interestCompoundingPeriodTypeOptions, existingProduct.interestPostingPeriodTypeOptions, existingProduct.interestCalculationTypeOptions, existingProduct.interestCalculationDaysInYearTypeOptions, existingProduct.lockinPeriodFrequencyTypeOptions, existingProduct.withdrawalFeeTypeOptions, @@ -318,8 +327,8 @@ public class FixedDepositProductData extends DepositProductData { final CurrencyData currency, final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType, final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType, final Integer lockinPeriodFrequency, - final EnumOptionData lockinPeriodFrequencyType, final EnumOptionData accountingType, - final Map accountingMappings, + final EnumOptionData lockinPeriodFrequencyType, final BigDecimal minBalanceForInterestCalculation, + final EnumOptionData accountingType, final Map accountingMappings, final Collection paymentChannelToFundSourceMappings, final Collection currencyOptions, final Collection interestCompoundingPeriodTypeOptions, final Collection interestPostingPeriodTypeOptions, @@ -345,7 +354,7 @@ public class FixedDepositProductData extends DepositProductData { interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, - penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate); + penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate, minBalanceForInterestCalculation); // fixed deposit additional fields this.preClosurePenalApplicable = preClosurePenalApplicable; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/RecurringDepositAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/RecurringDepositAccountData.java index 771341746..1e56c8b3b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/RecurringDepositAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/RecurringDepositAccountData.java @@ -69,7 +69,8 @@ public class RecurringDepositAccountData extends DepositAccountData { final LocalDate maturityDate, final Integer depositPeriod, final EnumOptionData depositPeriodFrequency, final BigDecimal mandatoryRecommendedDepositAmount, final EnumOptionData onAccountClosure, final LocalDate expectedFirstDepositOnDate, final BigDecimal totalOverdueAmount, final Integer noOfOverdueInstallments, - final boolean isMandatoryDeposit, final boolean allowWithdrawal, final boolean adjustAdvanceTowardsFuturePayments, final boolean isCalendarInherited) { + final boolean isMandatoryDeposit, final boolean allowWithdrawal, final boolean adjustAdvanceTowardsFuturePayments, + final boolean isCalendarInherited) { final Collection preClosurePenalInterestOnTypeOptions = null; final Collection periodFrequencyTypeOptions = null; @@ -89,41 +90,43 @@ public class RecurringDepositAccountData extends DepositAccountData { depositAccountData.interestPostingPeriodType, depositAccountData.interestCalculationType, depositAccountData.interestCalculationDaysInYearType, depositAccountData.minRequiredOpeningBalance, depositAccountData.lockinPeriodFrequency, depositAccountData.lockinPeriodFrequencyType, - depositAccountData.withdrawalFeeForTransfers, depositAccountData.summary, depositAccountData.transactions, - depositAccountData.productOptions, depositAccountData.fieldOfficerOptions, - depositAccountData.interestCompoundingPeriodTypeOptions, depositAccountData.interestPostingPeriodTypeOptions, - depositAccountData.interestCalculationTypeOptions, depositAccountData.interestCalculationDaysInYearTypeOptions, - depositAccountData.lockinPeriodFrequencyTypeOptions, depositAccountData.withdrawalFeeTypeOptions, - depositAccountData.charges, depositAccountData.chargeOptions, depositAccountData.accountChart, - depositAccountData.chartTemplate, preClosurePenalApplicable, preClosurePenalInterest, preClosurePenalInterestOnType, - preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType, - inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, depositPeriod, - depositPeriodFrequency, mandatoryRecommendedDepositAmount, periodFrequencyTypeOptions, depositType, onAccountClosure, - onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, expectedFirstDepositOnDate, totalOverdueAmount, - noOfOverdueInstallments, isMandatoryDeposit, allowWithdrawal, adjustAdvanceTowardsFuturePayments, isCalendarInherited, recurringFrequency, recurringFrequencyType); + depositAccountData.withdrawalFeeForTransfers, depositAccountData.minBalanceForInterestCalculation, + depositAccountData.summary, depositAccountData.transactions, depositAccountData.productOptions, + depositAccountData.fieldOfficerOptions, depositAccountData.interestCompoundingPeriodTypeOptions, + depositAccountData.interestPostingPeriodTypeOptions, depositAccountData.interestCalculationTypeOptions, + depositAccountData.interestCalculationDaysInYearTypeOptions, depositAccountData.lockinPeriodFrequencyTypeOptions, + depositAccountData.withdrawalFeeTypeOptions, depositAccountData.charges, depositAccountData.chargeOptions, + depositAccountData.accountChart, depositAccountData.chartTemplate, preClosurePenalApplicable, preClosurePenalInterest, + preClosurePenalInterestOnType, preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, + maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, + depositPeriod, depositPeriodFrequency, mandatoryRecommendedDepositAmount, periodFrequencyTypeOptions, depositType, + onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, expectedFirstDepositOnDate, + totalOverdueAmount, noOfOverdueInstallments, isMandatoryDeposit, allowWithdrawal, adjustAdvanceTowardsFuturePayments, + isCalendarInherited, recurringFrequency, recurringFrequencyType); } public static RecurringDepositAccountData withInterestChartAndRecurringDetails(final RecurringDepositAccountData account, - final DepositAccountInterestRateChartData accountChart, final Integer recurringFrequency, final EnumOptionData recurringFrequencyType) { + final DepositAccountInterestRateChartData accountChart, final Integer recurringFrequency, + final EnumOptionData recurringFrequencyType) { return new RecurringDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName, account.clientId, account.clientName, account.depositProductId, account.depositProductName, account.fieldOfficerId, account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance, account.lockinPeriodFrequency, - account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary, account.transactions, - account.productOptions, account.fieldOfficerOptions, account.interestCompoundingPeriodTypeOptions, - account.interestPostingPeriodTypeOptions, account.interestCalculationTypeOptions, - account.interestCalculationDaysInYearTypeOptions, account.lockinPeriodFrequencyTypeOptions, - account.withdrawalFeeTypeOptions, account.charges, account.chargeOptions, accountChart, account.chartTemplate, - account.preClosurePenalApplicable, account.preClosurePenalInterest, account.preClosurePenalInterestOnType, - account.preClosurePenalInterestOnTypeOptions, account.minDepositTerm, account.maxDepositTerm, account.minDepositTermType, - account.maxDepositTermType, account.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, - account.maturityAmount, account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, - account.mandatoryRecommendedDepositAmount, account.periodFrequencyTypeOptions, account.depositType, - account.onAccountClosure, account.onAccountClosureOptions, account.paymentTypeOptions, account.savingsAccounts, - account.expectedFirstDepositOnDate, account.totalOverdueAmount, account.noOfOverdueInstallments, - account.isMandatoryDeposit, account.allowWithdrawal, account.adjustAdvanceTowardsFuturePayments, - account.isCalendarInherited, recurringFrequency, recurringFrequencyType); + account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.minBalanceForInterestCalculation, + account.summary, account.transactions, account.productOptions, account.fieldOfficerOptions, + account.interestCompoundingPeriodTypeOptions, account.interestPostingPeriodTypeOptions, + account.interestCalculationTypeOptions, account.interestCalculationDaysInYearTypeOptions, + account.lockinPeriodFrequencyTypeOptions, account.withdrawalFeeTypeOptions, account.charges, account.chargeOptions, + accountChart, account.chartTemplate, account.preClosurePenalApplicable, account.preClosurePenalInterest, + account.preClosurePenalInterestOnType, account.preClosurePenalInterestOnTypeOptions, account.minDepositTerm, + account.maxDepositTerm, account.minDepositTermType, account.maxDepositTermType, account.inMultiplesOfDepositTerm, + account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount, account.maturityDate, + account.depositPeriod, account.depositPeriodFrequency, account.mandatoryRecommendedDepositAmount, + account.periodFrequencyTypeOptions, account.depositType, account.onAccountClosure, account.onAccountClosureOptions, + account.paymentTypeOptions, account.savingsAccounts, account.expectedFirstDepositOnDate, account.totalOverdueAmount, + account.noOfOverdueInstallments, account.isMandatoryDeposit, account.allowWithdrawal, + account.adjustAdvanceTowardsFuturePayments, account.isCalendarInherited, recurringFrequency, recurringFrequencyType); } public static RecurringDepositAccountData withTemplateOptions(final RecurringDepositAccountData account, @@ -155,20 +158,21 @@ public class RecurringDepositAccountData extends DepositAccountData { account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance, account.lockinPeriodFrequency, - account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary, transactions, - template.productOptions, template.fieldOfficerOptions, template.interestCompoundingPeriodTypeOptions, - template.interestPostingPeriodTypeOptions, template.interestCalculationTypeOptions, - template.interestCalculationDaysInYearTypeOptions, template.lockinPeriodFrequencyTypeOptions, - template.withdrawalFeeTypeOptions, charges, template.chargeOptions, account.accountChart, account.chartTemplate, - account.preClosurePenalApplicable, account.preClosurePenalInterest, account.preClosurePenalInterestOnType, - template.preClosurePenalInterestOnTypeOptions, account.minDepositTerm, account.maxDepositTerm, account.minDepositTermType, - account.maxDepositTermType, account.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, - account.maturityAmount, account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, - account.mandatoryRecommendedDepositAmount, template.periodFrequencyTypeOptions, account.depositType, - account.onAccountClosure, account.onAccountClosureOptions, account.paymentTypeOptions, account.savingsAccounts, - account.expectedFirstDepositOnDate, account.totalOverdueAmount, account.noOfOverdueInstallments, - account.isMandatoryDeposit, account.allowWithdrawal, account.adjustAdvanceTowardsFuturePayments, - account.isCalendarInherited, account.recurringFrequency, account.recurringFrequencyType); + account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.minBalanceForInterestCalculation, + account.summary, transactions, template.productOptions, template.fieldOfficerOptions, + template.interestCompoundingPeriodTypeOptions, template.interestPostingPeriodTypeOptions, + template.interestCalculationTypeOptions, template.interestCalculationDaysInYearTypeOptions, + template.lockinPeriodFrequencyTypeOptions, template.withdrawalFeeTypeOptions, charges, template.chargeOptions, + account.accountChart, account.chartTemplate, account.preClosurePenalApplicable, account.preClosurePenalInterest, + account.preClosurePenalInterestOnType, template.preClosurePenalInterestOnTypeOptions, account.minDepositTerm, + account.maxDepositTerm, account.minDepositTermType, account.maxDepositTermType, account.inMultiplesOfDepositTerm, + account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount, account.maturityDate, + account.depositPeriod, account.depositPeriodFrequency, account.mandatoryRecommendedDepositAmount, + template.periodFrequencyTypeOptions, account.depositType, account.onAccountClosure, account.onAccountClosureOptions, + account.paymentTypeOptions, account.savingsAccounts, account.expectedFirstDepositOnDate, account.totalOverdueAmount, + account.noOfOverdueInstallments, account.isMandatoryDeposit, account.allowWithdrawal, + account.adjustAdvanceTowardsFuturePayments, account.isCalendarInherited, account.recurringFrequency, + account.recurringFrequencyType); } @@ -188,17 +192,18 @@ public class RecurringDepositAccountData extends DepositAccountData { account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance, account.lockinPeriodFrequency, - account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary, transactions, productOptions, - fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, - interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, - withdrawalFeeTypeOptions, charges, chargeOptions, account.accountChart, account.chartTemplate, - account.preClosurePenalApplicable, account.preClosurePenalInterest, account.preClosurePenalInterestOnType, - preClosurePenalInterestOnTypeOptions, account.minDepositTerm, account.maxDepositTerm, account.minDepositTermType, - account.maxDepositTermType, account.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, - account.maturityAmount, account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, - account.mandatoryRecommendedDepositAmount, periodFrequencyTypeOptions, account.depositType, account.onAccountClosure, - account.onAccountClosureOptions, account.paymentTypeOptions, account.savingsAccounts, account.expectedFirstDepositOnDate, - account.totalOverdueAmount, account.noOfOverdueInstallments, account.isMandatoryDeposit, account.allowWithdrawal, + account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.minBalanceForInterestCalculation, + account.summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, + interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, + lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, account.accountChart, + account.chartTemplate, account.preClosurePenalApplicable, account.preClosurePenalInterest, + account.preClosurePenalInterestOnType, preClosurePenalInterestOnTypeOptions, account.minDepositTerm, + account.maxDepositTerm, account.minDepositTermType, account.maxDepositTermType, account.inMultiplesOfDepositTerm, + account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount, account.maturityDate, + account.depositPeriod, account.depositPeriodFrequency, account.mandatoryRecommendedDepositAmount, + periodFrequencyTypeOptions, account.depositType, account.onAccountClosure, account.onAccountClosureOptions, + account.paymentTypeOptions, account.savingsAccounts, account.expectedFirstDepositOnDate, account.totalOverdueAmount, + account.noOfOverdueInstallments, account.isMandatoryDeposit, account.allowWithdrawal, account.adjustAdvanceTowardsFuturePayments, account.isCalendarInherited, account.recurringFrequency, account.recurringFrequencyType); } @@ -225,6 +230,7 @@ public class RecurringDepositAccountData extends DepositAccountData { final Integer lockinPeriodFrequency = null; final EnumOptionData lockinPeriodFrequencyType = null; final boolean withdrawalFeeForTransfers = false; + final BigDecimal minBalanceForInterestCalculation = null; final SavingsAccountSummaryData summary = null; final Collection transactions = null; @@ -281,8 +287,8 @@ public class RecurringDepositAccountData extends DepositAccountData { return new RecurringDepositAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, - lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions, - fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, + lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, minBalanceForInterestCalculation, summary, + transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, accountChart, chartTemplate, preClosurePenalApplicable, preClosurePenalInterest, preClosurePenalInterestOnType, preClosurePenalInterestOnTypeOptions, minDepositTerm, @@ -315,6 +321,7 @@ public class RecurringDepositAccountData extends DepositAccountData { final Integer lockinPeriodFrequency = null; final EnumOptionData lockinPeriodFrequencyType = null; final boolean withdrawalFeeForTransfers = false; + final BigDecimal minBalanceForInterestCalculation = null; final SavingsAccountSummaryData summary = null; final Collection transactions = null; @@ -369,8 +376,8 @@ public class RecurringDepositAccountData extends DepositAccountData { return new RecurringDepositAccountData(accountId, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, - lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions, - fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, + lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, minBalanceForInterestCalculation, summary, + transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, accountChart, chartTemplate, preClosurePenalApplicable, preClosurePenalInterest, preClosurePenalInterestOnType, preClosurePenalInterestOnTypeOptions, minDepositTerm, @@ -390,20 +397,21 @@ public class RecurringDepositAccountData extends DepositAccountData { account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance, account.lockinPeriodFrequency, - account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary, account.transactions, - account.productOptions, account.fieldOfficerOptions, account.interestCompoundingPeriodTypeOptions, - account.interestPostingPeriodTypeOptions, account.interestCalculationTypeOptions, - account.interestCalculationDaysInYearTypeOptions, account.lockinPeriodFrequencyTypeOptions, - account.withdrawalFeeTypeOptions, account.charges, account.chargeOptions, account.accountChart, account.chartTemplate, - account.preClosurePenalApplicable, account.preClosurePenalInterest, account.preClosurePenalInterestOnType, - account.preClosurePenalInterestOnTypeOptions, account.minDepositTerm, account.maxDepositTerm, account.minDepositTermType, - account.maxDepositTermType, account.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, - account.maturityAmount, account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, - account.mandatoryRecommendedDepositAmount, account.periodFrequencyTypeOptions, account.depositType, - account.onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, - account.expectedFirstDepositOnDate, account.totalOverdueAmount, account.noOfOverdueInstallments, - account.isMandatoryDeposit, account.allowWithdrawal, account.adjustAdvanceTowardsFuturePayments, - account.isCalendarInherited, account.recurringFrequency, account.recurringFrequencyType); + account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.minBalanceForInterestCalculation, + account.summary, account.transactions, account.productOptions, account.fieldOfficerOptions, + account.interestCompoundingPeriodTypeOptions, account.interestPostingPeriodTypeOptions, + account.interestCalculationTypeOptions, account.interestCalculationDaysInYearTypeOptions, + account.lockinPeriodFrequencyTypeOptions, account.withdrawalFeeTypeOptions, account.charges, account.chargeOptions, + account.accountChart, account.chartTemplate, account.preClosurePenalApplicable, account.preClosurePenalInterest, + account.preClosurePenalInterestOnType, account.preClosurePenalInterestOnTypeOptions, account.minDepositTerm, + account.maxDepositTerm, account.minDepositTermType, account.maxDepositTermType, account.inMultiplesOfDepositTerm, + account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount, account.maturityDate, + account.depositPeriod, account.depositPeriodFrequency, account.mandatoryRecommendedDepositAmount, + account.periodFrequencyTypeOptions, account.depositType, account.onAccountClosure, onAccountClosureOptions, + paymentTypeOptions, savingsAccountDatas, account.expectedFirstDepositOnDate, account.totalOverdueAmount, + account.noOfOverdueInstallments, account.isMandatoryDeposit, account.allowWithdrawal, + account.adjustAdvanceTowardsFuturePayments, account.isCalendarInherited, account.recurringFrequency, + account.recurringFrequencyType); } private RecurringDepositAccountData(final Long id, final String accountNo, final String externalId, final Long groupId, @@ -414,9 +422,9 @@ public class RecurringDepositAccountData extends DepositAccountData { final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers, - final SavingsAccountSummaryData summary, final Collection transactions, - final Collection productOptions, final Collection fieldOfficerOptions, - final Collection interestCompoundingPeriodTypeOptions, + final BigDecimal minBalanceForInterestCalculation, final SavingsAccountSummaryData summary, + final Collection transactions, final Collection productOptions, + final Collection fieldOfficerOptions, final Collection interestCompoundingPeriodTypeOptions, final Collection interestPostingPeriodTypeOptions, final Collection interestCalculationTypeOptions, final Collection interestCalculationDaysInYearTypeOptions, @@ -443,7 +451,7 @@ public class RecurringDepositAccountData extends DepositAccountData { lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, - chargeOptions, accountChart, chartTemplate, depositType); + chargeOptions, accountChart, chartTemplate, depositType, minBalanceForInterestCalculation); this.preClosurePenalApplicable = preClosurePenalApplicable; this.preClosurePenalInterest = preClosurePenalInterest; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/RecurringDepositProductData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/RecurringDepositProductData.java index 4faebc17f..d86122ded 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/RecurringDepositProductData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/RecurringDepositProductData.java @@ -65,6 +65,7 @@ public class RecurringDepositProductData extends DepositProductData { final Integer lockinPeriodFrequency = null; final EnumOptionData lockinPeriodFrequencyType = null; + final BigDecimal minBalanceForInterestCalculation = null; final Map accountingMappings = null; final Collection paymentChannelToFundSourceMappings = null; @@ -90,10 +91,11 @@ public class RecurringDepositProductData extends DepositProductData { return new RecurringDepositProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, - lockinPeriodFrequency, lockinPeriodFrequencyType, accountingRule, accountingMappings, paymentChannelToFundSourceMappings, - currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, - interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, - accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, + lockinPeriodFrequency, lockinPeriodFrequencyType, minBalanceForInterestCalculation, accountingRule, accountingMappings, + paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, + interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, + lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, + accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate, preClosurePenalApplicable, preClosurePenalInterest, preClosurePenalInterestOnType, preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, isMandatoryDeposit, allowWithdrawal, @@ -106,8 +108,9 @@ public class RecurringDepositProductData extends DepositProductData { existingProduct.description, existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType, existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType, existingProduct.interestCalculationDaysInYearType, - existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, existingProduct.accountingRule, - existingProduct.accountingMappings, existingProduct.paymentChannelToFundSourceMappings, existingProduct.currencyOptions, + existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, + existingProduct.minBalanceForInterestCalculation, existingProduct.accountingRule, existingProduct.accountingMappings, + existingProduct.paymentChannelToFundSourceMappings, existingProduct.currencyOptions, existingProduct.interestCompoundingPeriodTypeOptions, existingProduct.interestPostingPeriodTypeOptions, existingProduct.interestCalculationTypeOptions, existingProduct.interestCalculationDaysInYearTypeOptions, existingProduct.lockinPeriodFrequencyTypeOptions, existingProduct.withdrawalFeeTypeOptions, @@ -144,11 +147,12 @@ public class RecurringDepositProductData extends DepositProductData { existingProduct.description, existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType, existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType, existingProduct.interestCalculationDaysInYearType, - existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, existingProduct.accountingRule, - existingProduct.accountingMappings, existingProduct.paymentChannelToFundSourceMappings, currencyOptions, - interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, - interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, - accountingRuleOptions, accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, + existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, + existingProduct.minBalanceForInterestCalculation, existingProduct.accountingRule, existingProduct.accountingMappings, + existingProduct.paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, + interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, + lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, + accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, existingProduct.feeToIncomeAccountMappings, existingProduct.penaltyToIncomeAccountMappings, existingProduct.interestRateCharts, chartTemplate, existingProduct.preClosurePenalApplicable, existingProduct.preClosurePenalInterest, existingProduct.preClosurePenalInterestOnType, @@ -183,8 +187,9 @@ public class RecurringDepositProductData extends DepositProductData { existingProduct.description, existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType, existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType, existingProduct.interestCalculationDaysInYearType, - existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, existingProduct.accountingRule, - accountingMappings, paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, + existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, + existingProduct.minBalanceForInterestCalculation, existingProduct.accountingRule, accountingMappings, + paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, @@ -233,8 +238,9 @@ public class RecurringDepositProductData extends DepositProductData { depositProductData.description, depositProductData.currency, depositProductData.nominalAnnualInterestRate, depositProductData.interestCompoundingPeriodType, depositProductData.interestPostingPeriodType, depositProductData.interestCalculationType, depositProductData.interestCalculationDaysInYearType, - depositProductData.lockinPeriodFrequency, depositProductData.lockinPeriodFrequencyType, depositProductData.accountingRule, - accountingMappings, paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, + depositProductData.lockinPeriodFrequency, depositProductData.lockinPeriodFrequencyType, + depositProductData.minBalanceForInterestCalculation, depositProductData.accountingRule, accountingMappings, + paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, @@ -257,6 +263,7 @@ public class RecurringDepositProductData extends DepositProductData { final Integer lockinPeriodFrequency = null; final EnumOptionData lockinPeriodFrequencyType = null; + final BigDecimal minBalanceForInterestCalculation = null; final EnumOptionData accountingType = null; final Map accountingMappings = null; @@ -299,10 +306,11 @@ public class RecurringDepositProductData extends DepositProductData { return new RecurringDepositProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, - lockinPeriodFrequency, lockinPeriodFrequencyType, accountingType, accountingMappings, paymentChannelToFundSourceMappings, - currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, - interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, - accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, + lockinPeriodFrequency, lockinPeriodFrequencyType, minBalanceForInterestCalculation, accountingType, accountingMappings, + paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, + interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, + lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, + accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate, preClosurePenalApplicable, preClosurePenalInterest, preClosurePenalInterestOnType, preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, isMandatoryDeposit, allowWithdrawal, @@ -314,18 +322,19 @@ public class RecurringDepositProductData extends DepositProductData { return new RecurringDepositProductData(product.id, product.name, product.shortName, product.description, product.currency, product.nominalAnnualInterestRate, product.interestCompoundingPeriodType, product.interestPostingPeriodType, product.interestCalculationType, product.interestCalculationDaysInYearType, product.lockinPeriodFrequency, - product.lockinPeriodFrequencyType, product.accountingRule, product.accountingMappings, - product.paymentChannelToFundSourceMappings, product.currencyOptions, product.interestCompoundingPeriodTypeOptions, - product.interestPostingPeriodTypeOptions, product.interestCalculationTypeOptions, - product.interestCalculationDaysInYearTypeOptions, product.lockinPeriodFrequencyTypeOptions, - product.withdrawalFeeTypeOptions, product.paymentTypeOptions, product.accountingRuleOptions, - product.accountingMappingOptions, product.charges, product.chargeOptions, product.penaltyOptions, - product.feeToIncomeAccountMappings, product.penaltyToIncomeAccountMappings, interestRateCharts, product.chartTemplate, - product.preClosurePenalApplicable, product.preClosurePenalInterest, product.preClosurePenalInterestOnType, - product.preClosurePenalInterestOnTypeOptions, product.minDepositTerm, product.maxDepositTerm, product.minDepositTermType, - product.maxDepositTermType, product.inMultiplesOfDepositTerm, product.inMultiplesOfDepositTermType, - product.isMandatoryDeposit, product.allowWithdrawal, product.adjustAdvanceTowardsFuturePayments, - product.periodFrequencyTypeOptions, product.minDepositAmount, product.depositAmount, product.maxDepositAmount); + product.lockinPeriodFrequencyType, product.minBalanceForInterestCalculation, product.accountingRule, + product.accountingMappings, product.paymentChannelToFundSourceMappings, product.currencyOptions, + product.interestCompoundingPeriodTypeOptions, product.interestPostingPeriodTypeOptions, + product.interestCalculationTypeOptions, product.interestCalculationDaysInYearTypeOptions, + product.lockinPeriodFrequencyTypeOptions, product.withdrawalFeeTypeOptions, product.paymentTypeOptions, + product.accountingRuleOptions, product.accountingMappingOptions, product.charges, product.chargeOptions, + product.penaltyOptions, product.feeToIncomeAccountMappings, product.penaltyToIncomeAccountMappings, interestRateCharts, + product.chartTemplate, product.preClosurePenalApplicable, product.preClosurePenalInterest, + product.preClosurePenalInterestOnType, product.preClosurePenalInterestOnTypeOptions, product.minDepositTerm, + product.maxDepositTerm, product.minDepositTermType, product.maxDepositTermType, product.inMultiplesOfDepositTerm, + product.inMultiplesOfDepositTermType, product.isMandatoryDeposit, product.allowWithdrawal, + product.adjustAdvanceTowardsFuturePayments, product.periodFrequencyTypeOptions, product.minDepositAmount, + product.depositAmount, product.maxDepositAmount); } @@ -333,8 +342,8 @@ public class RecurringDepositProductData extends DepositProductData { final CurrencyData currency, final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType, final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType, final Integer lockinPeriodFrequency, - final EnumOptionData lockinPeriodFrequencyType, final EnumOptionData accountingType, - final Map accountingMappings, + final EnumOptionData lockinPeriodFrequencyType, final BigDecimal minBalanceForInterestCalculation, + final EnumOptionData accountingType, final Map accountingMappings, final Collection paymentChannelToFundSourceMappings, final Collection currencyOptions, final Collection interestCompoundingPeriodTypeOptions, final Collection interestPostingPeriodTypeOptions, @@ -361,7 +370,7 @@ public class RecurringDepositProductData extends DepositProductData { interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, - penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate); + penaltyToIncomeAccountMappings, interestRateCharts, chartTemplate, minBalanceForInterestCalculation); this.preClosurePenalApplicable = preClosurePenalApplicable; this.preClosurePenalInterest = preClosurePenalInterest; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountData.java index 564bee17a..0e2f24938 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountData.java @@ -49,6 +49,7 @@ public class SavingsAccountData { private final BigDecimal overdraftLimit; private final BigDecimal minRequiredBalance; private final boolean allowOverdraftMinBalance; + private final BigDecimal minBalanceForInterestCalculation; // associations private final SavingsAccountSummaryData summary; @@ -82,7 +83,7 @@ public class SavingsAccountData { final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers, final SavingsAccountSummaryData summary, final boolean allowOverdraft, final BigDecimal overdraftLimit, - final BigDecimal minRequiredBalance, final boolean allowOverdraftMinBalance) { + final BigDecimal minRequiredBalance, final boolean allowOverdraftMinBalance, final BigDecimal minBalanceForInterestCalculation) { final Collection productOptions = null; final Collection fieldOfficerOptions = null; @@ -104,7 +105,7 @@ public class SavingsAccountData { fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance, - allowOverdraftMinBalance); + allowOverdraftMinBalance, minBalanceForInterestCalculation); } public static SavingsAccountData lookup(final Long accountId, final String accountNo, final EnumOptionData depositType) { @@ -139,6 +140,7 @@ public class SavingsAccountData { final BigDecimal overdraftLimit = null; final BigDecimal minRequiredBalance = null; final boolean allowOverdraftMinBalance = false; + final BigDecimal minBalanceForInterestCalculation = null; final SavingsAccountSummaryData summary = null; final Collection transactions = null; @@ -162,7 +164,7 @@ public class SavingsAccountData { fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance, - allowOverdraftMinBalance); + allowOverdraftMinBalance, minBalanceForInterestCalculation); } public static SavingsAccountData lookupWithProductDetails(final Long accountId, final String accountNo, @@ -195,6 +197,7 @@ public class SavingsAccountData { final BigDecimal overdraftLimit = null; final BigDecimal minRequiredBalance = null; final boolean allowOverdraftMinBalance = false; + final BigDecimal minBalanceForInterestCalculation = null; final SavingsAccountSummaryData summary = null; final Collection transactions = null; @@ -218,7 +221,7 @@ public class SavingsAccountData { fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance, - allowOverdraftMinBalance); + allowOverdraftMinBalance, minBalanceForInterestCalculation); } public static SavingsAccountData withTemplateOptions(final SavingsAccountData account, final SavingsAccountData template, @@ -250,7 +253,7 @@ public class SavingsAccountData { template.interestPostingPeriodTypeOptions, template.interestCalculationTypeOptions, template.interestCalculationDaysInYearTypeOptions, template.lockinPeriodFrequencyTypeOptions, template.withdrawalFeeTypeOptions, charges, template.chargeOptions, account.allowOverdraft, account.overdraftLimit, - account.minRequiredBalance, account.allowOverdraftMinBalance); + account.minRequiredBalance, account.allowOverdraftMinBalance, account.minBalanceForInterestCalculation); } public static SavingsAccountData withTemplateOptions(final SavingsAccountData account, @@ -272,7 +275,7 @@ public class SavingsAccountData { transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, account.allowOverdraft, account.overdraftLimit, - account.minRequiredBalance, account.allowOverdraftMinBalance); + account.minRequiredBalance, account.allowOverdraftMinBalance, account.minBalanceForInterestCalculation); } public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId, @@ -307,6 +310,7 @@ public class SavingsAccountData { final BigDecimal overdraftLimit = null; final BigDecimal minRequiredBalance = null; final boolean allowOverdraftMinBalance = false; + final BigDecimal minBalanceForInterestCalculation = null; final SavingsAccountSummaryData summary = null; final Collection transactions = null; @@ -330,7 +334,7 @@ public class SavingsAccountData { fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance, - allowOverdraftMinBalance); + allowOverdraftMinBalance, minBalanceForInterestCalculation); } private SavingsAccountData(final Long id, final String accountNo, final EnumOptionData depositType, final String externalId, @@ -349,7 +353,8 @@ public class SavingsAccountData { final Collection interestCalculationDaysInYearTypeOptions, final Collection lockinPeriodFrequencyTypeOptions, final Collection withdrawalFeeTypeOptions, final Collection charges, final Collection chargeOptions, final boolean allowOverdraft, - final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance, final boolean allowOverdraftMinBalance) { + final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance, final boolean allowOverdraftMinBalance, + final BigDecimal minBalanceForInterestCalculation) { this.id = id; this.accountNo = accountNo; this.depositType = depositType; @@ -403,6 +408,7 @@ public class SavingsAccountData { this.overdraftLimit = overdraftLimit; this.minRequiredBalance = minRequiredBalance; this.allowOverdraftMinBalance = allowOverdraftMinBalance; + this.minBalanceForInterestCalculation = minBalanceForInterestCalculation; } private SavingsAccountChargeData getWithdrawalFee() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductData.java index edd0827b3..3d34f5c1c 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductData.java @@ -42,6 +42,7 @@ public class SavingsProductData { private final BigDecimal overdraftLimit; private final BigDecimal minRequiredBalance; private final boolean allowOverdraftMinBalance; + private final BigDecimal minBalanceForInterestCalculation; // accounting private final EnumOptionData accountingRule; @@ -97,6 +98,7 @@ public class SavingsProductData { final BigDecimal overdraftLimit = null; final BigDecimal minRequiredBalance = null; final boolean allowOverdraftMinBalance = false; + final BigDecimal minBalanceForInterestCalculation = null; return new SavingsProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, @@ -105,7 +107,8 @@ public class SavingsProductData { interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, - penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance); + penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance, + minBalanceForInterestCalculation); } public static SavingsProductData withCharges(final SavingsProductData product, final Collection charges) { @@ -119,7 +122,7 @@ public class SavingsProductData { product.lockinPeriodFrequencyTypeOptions, product.withdrawalFeeTypeOptions, product.paymentTypeOptions, product.accountingRuleOptions, product.accountingMappingOptions, charges, product.chargeOptions, product.penaltyOptions, product.feeToIncomeAccountMappings, product.penaltyToIncomeAccountMappings, product.allowOverdraft, product.overdraftLimit, - product.minRequiredBalance, product.allowOverdraftMinBalance); + product.minRequiredBalance, product.allowOverdraftMinBalance, product.minBalanceForInterestCalculation); } /** @@ -147,7 +150,8 @@ public class SavingsProductData { lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, existingProduct.feeToIncomeAccountMappings, existingProduct.penaltyToIncomeAccountMappings, existingProduct.allowOverdraft, - existingProduct.overdraftLimit, existingProduct.minRequiredBalance, existingProduct.allowOverdraftMinBalance); + existingProduct.overdraftLimit, existingProduct.minRequiredBalance, existingProduct.allowOverdraftMinBalance, + existingProduct.minBalanceForInterestCalculation); } public static SavingsProductData withAccountingDetails(final SavingsProductData existingProduct, @@ -180,7 +184,8 @@ public class SavingsProductData { lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, existingProduct.allowOverdraft, existingProduct.overdraftLimit, - existingProduct.minRequiredBalance, existingProduct.allowOverdraftMinBalance); + existingProduct.minRequiredBalance, existingProduct.allowOverdraftMinBalance, + existingProduct.minBalanceForInterestCalculation); } public static SavingsProductData instance(final Long id, final String name, final String shortName, final String description, @@ -189,7 +194,7 @@ public class SavingsProductData { final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers, final EnumOptionData accountingType, final boolean allowOverdraft, final BigDecimal overdraftLimit, - final BigDecimal minRequiredBalance, final boolean allowOverdraftMinBalance) { + final BigDecimal minRequiredBalance, final boolean allowOverdraftMinBalance, final BigDecimal minBalanceForInterestCalculation) { final Map accountingMappings = null; final Collection paymentChannelToFundSourceMappings = null; @@ -217,7 +222,8 @@ public class SavingsProductData { interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, - penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance); + penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance, + minBalanceForInterestCalculation); } public static SavingsProductData lookup(final Long id, final String name) { @@ -241,6 +247,7 @@ public class SavingsProductData { final BigDecimal overdraftLimit = null; final BigDecimal minRequiredBalance = null; final boolean allowOverdraftMinBalance = false; + final BigDecimal minBalanceForInterestCalculation = null; final Collection currencyOptions = null; final Collection interestCompoundingPeriodTypeOptions = null; @@ -265,7 +272,8 @@ public class SavingsProductData { interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, - penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance); + penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance, + minBalanceForInterestCalculation); } private SavingsProductData(final Long id, final String name, final String shortName, final String description, @@ -285,7 +293,8 @@ public class SavingsProductData { final Collection chargeOptions, final Collection penaltyOptions, final Collection feeToIncomeAccountMappings, final Collection penaltyToIncomeAccountMappings, final boolean allowOverdraft, - final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance, final boolean allowOverdraftMinBalance) { + final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance, final boolean allowOverdraftMinBalance, + final BigDecimal minBalanceForInterestCalculation) { this.id = id; this.name = name; this.shortName = shortName; @@ -332,6 +341,7 @@ public class SavingsProductData { this.overdraftLimit = overdraftLimit; this.minRequiredBalance = minRequiredBalance; this.allowOverdraftMinBalance = allowOverdraftMinBalance; + this.minBalanceForInterestCalculation = minBalanceForInterestCalculation; } public boolean hasAccountingEnabled() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductDataValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductDataValidator.java index 9189cdbb5..4f89d547f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductDataValidator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductDataValidator.java @@ -8,11 +8,11 @@ package org.mifosplatform.portfolio.savings.data; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_RESOURCE_NAME; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftParamName; -import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeAmountParamName; -import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeOnMonthDayParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.currencyCodeParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.descriptionParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.digitsAfterDecimalParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeAmountParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeOnMonthDayParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.inMultiplesOfParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCalculationDaysInYearTypeParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCalculationTypeParamName; @@ -20,12 +20,13 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCo import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minBalanceForInterestCalculationParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.overdraftLimitParamName; -import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.shortNameParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName; import java.lang.reflect.Type; import java.math.BigDecimal; @@ -272,6 +273,13 @@ public class SavingsProductDataValidator { validateOverdraftParams(baseDataValidator, element); + if (this.fromApiJsonHelper.parameterExists(minBalanceForInterestCalculationParamName, element)) { + final BigDecimal minBalanceForInterestCalculation = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed( + minBalanceForInterestCalculationParamName, element); + baseDataValidator.reset().parameter(minBalanceForInterestCalculationParamName).value(minBalanceForInterestCalculation) + .ignoreIfNull().zeroOrPositiveAmount(); + } + throwExceptionIfValidationWarningsExist(dataValidationErrors); } @@ -430,6 +438,13 @@ public class SavingsProductDataValidator { validateChargeToIncomeAccountMappings(baseDataValidator, element); validateOverdraftParams(baseDataValidator, element); + if (this.fromApiJsonHelper.parameterExists(minBalanceForInterestCalculationParamName, element)) { + final BigDecimal minBalanceForInterestCalculation = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed( + minBalanceForInterestCalculationParamName, element); + baseDataValidator.reset().parameter(minBalanceForInterestCalculationParamName).value(minBalanceForInterestCalculation) + .ignoreIfNull().zeroOrPositiveAmount(); + } + throwExceptionIfValidationWarningsExist(dataValidationErrors); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/DepositProductAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/DepositProductAssembler.java index d04d875b5..6d8887257 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/DepositProductAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/DepositProductAssembler.java @@ -33,6 +33,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCo import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minBalanceForInterestCalculationParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.shortNameParamName; @@ -119,6 +120,9 @@ public class DepositProductAssembler { lockinPeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue); } + final BigDecimal minBalanceForInterestCalculation = command + .bigDecimalValueOfParameterNamedDefaultToNullIfZero(minBalanceForInterestCalculationParamName); + final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingRule")); final DepositPreClosureDetail preClosureDetail = this.assemblePreClosureDetail(command); @@ -136,7 +140,8 @@ public class DepositProductAssembler { } FixedDepositProduct fixedDepositProduct = FixedDepositProduct.createNew(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, - lockinPeriodFrequency, lockinPeriodFrequencyType, accountingRuleType, charges, productTermAndPreClosure, charts); + lockinPeriodFrequency, lockinPeriodFrequencyType, accountingRuleType, charges, productTermAndPreClosure, charts, + minBalanceForInterestCalculation); // update product reference productTermAndPreClosure.updateProductReference(fixedDepositProduct); @@ -191,6 +196,9 @@ public class DepositProductAssembler { lockinPeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue); } + final BigDecimal minBalanceForInterestCalculation = command + .bigDecimalValueOfParameterNamedDefaultToNullIfZero(minBalanceForInterestCalculationParamName); + final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingRule")); final DepositPreClosureDetail preClosureDetail = this.assemblePreClosureDetail(command); @@ -213,7 +221,7 @@ public class DepositProductAssembler { RecurringDepositProduct recurringDepositProduct = RecurringDepositProduct.createNew(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, lockinPeriodFrequency, lockinPeriodFrequencyType, accountingRuleType, charges, - productTermAndPreClosure, productRecurringDetail, charts); + productTermAndPreClosure, productRecurringDetail, charts, minBalanceForInterestCalculation); // update product reference productTermAndPreClosure.updateProductReference(recurringDepositProduct); @@ -314,25 +322,25 @@ public class DepositProductAssembler { if (command.parameterExists(minDepositTermParamName)) { minDepositTerm = command.integerValueOfParameterNamed(minDepositTermParamName); - } else if(prodDepositTermDetail != null){ + } else if (prodDepositTermDetail != null) { minDepositTerm = prodDepositTermDetail.minDepositTerm(); } if (command.parameterExists(maxDepositTermParamName)) { maxDepositTerm = command.integerValueOfParameterNamed(maxDepositTermParamName); - } else if(prodDepositTermDetail != null){ + } else if (prodDepositTermDetail != null) { maxDepositTerm = prodDepositTermDetail.maxDepositTerm(); } if (command.parameterExists(minDepositTermTypeIdParamName)) { minDepositTermTypeId = command.integerValueOfParameterNamed(minDepositTermTypeIdParamName); - } else if(prodDepositTermDetail != null){ + } else if (prodDepositTermDetail != null) { minDepositTermTypeId = prodDepositTermDetail.minDepositTermType(); } if (command.parameterExists(maxDepositTermTypeIdParamName)) { maxDepositTermTypeId = command.integerValueOfParameterNamed(maxDepositTermTypeIdParamName); - } else if(prodDepositTermDetail != null){ + } else if (prodDepositTermDetail != null) { maxDepositTermTypeId = prodDepositTermDetail.maxDepositTermType(); } @@ -344,13 +352,13 @@ public class DepositProductAssembler { if (command.parameterExists(inMultiplesOfDepositTermParamName)) { inMultiplesOfDepositTerm = command.integerValueOfParameterNamed(inMultiplesOfDepositTermParamName); - } else if(prodDepositTermDetail != null){ + } else if (prodDepositTermDetail != null) { inMultiplesOfDepositTerm = prodDepositTermDetail.inMultiplesOfDepositTerm(); } if (command.parameterExists(preClosurePenalApplicableParamName)) { inMultiplesOfDepositTermTypeId = command.integerValueOfParameterNamed(inMultiplesOfDepositTermTypeIdParamName); - } else if(prodDepositTermDetail != null){ + } else if (prodDepositTermDetail != null) { inMultiplesOfDepositTermTypeId = prodDepositTermDetail.inMultiplesOfDepositTermType(); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/FixedDepositAccount.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/FixedDepositAccount.java index 44d1abbec..8b0b72e34 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/FixedDepositAccount.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/FixedDepositAccount.java @@ -279,11 +279,12 @@ public class FixedDepositAccount extends SavingsAccount { final BigDecimal interestRateAsFraction = getEffectiveInterestRateAsFraction(mc, maturityDate, isPreMatureClosure); final Collection interestPostTransactions = this.savingsHelper.fetchPostInterestTransactionIds(getId()); boolean isInterestTransfer = false; + final Money minBalanceForInterestCalculation = Money.of(getCurrency(), minBalanceForInterestCalculation()); for (final LocalDateInterval periodInterval : postingPeriodIntervals) { final PostingPeriod postingPeriod = PostingPeriod.createFrom(periodInterval, periodStartingBalance, transactions, this.currency, compoundingPeriodType, interestCalculationType, interestRateAsFraction, daysInYearType.getValue(), - maturityDate, interestPostTransactions, isInterestTransfer); + maturityDate, interestPostTransactions, isInterestTransfer, minBalanceForInterestCalculation); periodStartingBalance = postingPeriod.closingBalance(); @@ -767,4 +768,9 @@ public class FixedDepositAccount extends SavingsAccount { private boolean isAccountMatured() { return SavingsAccountStatusType.fromInt(status).isMatured(); } + + @Override + public BigDecimal minBalanceForInterestCalculation() { + return null; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/FixedDepositProduct.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/FixedDepositProduct.java index 36033beae..07a3f75ce 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/FixedDepositProduct.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/FixedDepositProduct.java @@ -75,7 +75,7 @@ public class FixedDepositProduct extends SavingsProduct { final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType, final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final AccountingRuleType accountingRuleType, - final Set charges, final DepositProductTermAndPreClosure productTermAndPreClosure, final Set charts) { + final Set charges, final DepositProductTermAndPreClosure productTermAndPreClosure, final Set charts, BigDecimal minBalanceForInterestCalculation) { final BigDecimal minRequiredOpeningBalance = null; final boolean withdrawalFeeApplicableForTransfer = false; @@ -85,7 +85,7 @@ public class FixedDepositProduct extends SavingsProduct { return new FixedDepositProduct(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, - productTermAndPreClosure, charts, allowOverdraft, overdraftLimit); + productTermAndPreClosure, charts, allowOverdraft, overdraftLimit, minBalanceForInterestCalculation); } protected FixedDepositProduct(final String name, final String shortName, final String description, final MonetaryCurrency currency, @@ -95,12 +95,12 @@ public class FixedDepositProduct extends SavingsProduct { final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set charges, final DepositProductTermAndPreClosure productTermAndPreClosure, final Set charts, - final boolean allowOverdraft, final BigDecimal overdraftLimit) { + final boolean allowOverdraft, final BigDecimal overdraftLimit, final BigDecimal minBalanceForInterestCalculation) { super(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, - lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, allowOverdraft, - overdraftLimit); + lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, allowOverdraft, overdraftLimit, + minBalanceForInterestCalculation); if (charts != null) { this.charts = charts; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/RecurringDepositAccount.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/RecurringDepositAccount.java index b131637e4..7a988d52f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/RecurringDepositAccount.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/RecurringDepositAccount.java @@ -294,10 +294,11 @@ public class RecurringDepositAccount extends SavingsAccount { final BigDecimal interestRateAsFraction = getEffectiveInterestRateAsFraction(mc, maturityDate, isPreMatureClosure); final Collection interestPostTransactions = this.savingsHelper.fetchPostInterestTransactionIds(getId()); boolean isInterestTransfer = false; + final Money minBalanceForInterestCalculation = Money.of(getCurrency(), minBalanceForInterestCalculation()); for (final LocalDateInterval periodInterval : postingPeriodIntervals) { final PostingPeriod postingPeriod = PostingPeriod.createFrom(periodInterval, periodStartingBalance, transactions, this.currency, compoundingPeriodType, interestCalculationType, interestRateAsFraction, daysInYearType.getValue(), - maturityDate, interestPostTransactions, isInterestTransfer); + maturityDate, interestPostTransactions, isInterestTransfer, minBalanceForInterestCalculation); periodStartingBalance = postingPeriod.closingBalance(); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/RecurringDepositProduct.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/RecurringDepositProduct.java index c5ea40bb7..e24b06cb3 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/RecurringDepositProduct.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/RecurringDepositProduct.java @@ -53,7 +53,8 @@ public class RecurringDepositProduct extends FixedDepositProduct { final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final AccountingRuleType accountingRuleType, final Set charges, final DepositProductTermAndPreClosure productTermAndPreClosure, - final DepositProductRecurringDetail recurringDetail, final Set charts) { + final DepositProductRecurringDetail recurringDetail, final Set charts, + BigDecimal minBalanceForInterestCalculation) { final BigDecimal minRequiredOpeningBalance = null; final boolean withdrawalFeeApplicableForTransfer = false; @@ -63,7 +64,7 @@ public class RecurringDepositProduct extends FixedDepositProduct { return new RecurringDepositProduct(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, - productTermAndPreClosure, recurringDetail, charts, allowOverdraft, overdraftLimit); + productTermAndPreClosure, recurringDetail, charts, allowOverdraft, overdraftLimit, minBalanceForInterestCalculation); } protected RecurringDepositProduct(final String name, final String shortName, final String description, final MonetaryCurrency currency, @@ -73,12 +74,13 @@ public class RecurringDepositProduct extends FixedDepositProduct { final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set charges, final DepositProductTermAndPreClosure productTermAndPreClosure, final DepositProductRecurringDetail recurringDetail, - final Set charts, final boolean allowOverdraft, final BigDecimal overdraftLimit) { + final Set charts, final boolean allowOverdraft, final BigDecimal overdraftLimit, + final BigDecimal minBalanceForInterestCalculation) { super(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, productTermAndPreClosure, - charts, allowOverdraft, overdraftLimit); + charts, allowOverdraft, overdraftLimit, minBalanceForInterestCalculation); this.recurringDetail = recurringDetail; } @@ -147,7 +149,7 @@ public class RecurringDepositProduct extends FixedDepositProduct { baseDataValidator.reset().parameter(DepositsApiConstants.nominalAnnualInterestRateParamName).value(nominalAnnualInterestRate) .failWithCodeNoParameterAddedToErrorCode("interest.chart.or.nominal.interest.rate.required"); } - + this.validateInterestPostingAndCompoundingPeriodTypes(baseDataValidator); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java index 0c0a6a88d..af3a08925 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java @@ -6,15 +6,15 @@ package org.mifosplatform.portfolio.savings.domain; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftMinBalanceParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.dueAsOfDateParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.localeParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.overdraftLimitParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName; -import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName; -import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftMinBalanceParamName; import java.math.BigDecimal; import java.math.MathContext; @@ -269,6 +269,9 @@ public class SavingsAccount extends AbstractPersistable { @Column(name = "deposit_type_enum", insertable = false, updatable = false) private Integer depositType; + @Column(name = "min_balance_for_interest_calculation", scale = 6, precision = 19, nullable = true) + private BigDecimal minBalanceForInterestCalculation; + protected SavingsAccount() { // } @@ -293,16 +296,16 @@ public class SavingsAccount extends AbstractPersistable { } protected SavingsAccount(final Client client, final Group group, final SavingsProduct product, final Staff fieldOfficer, - final String accountNo, final String externalId, final SavingsAccountStatusType status, final AccountType accountType, - final LocalDate submittedOnDate, final AppUser submittedBy, final BigDecimal nominalAnnualInterestRate, - final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType, - final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType, - final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, - final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, - final boolean withdrawalFeeApplicableForTransfer, final Set savingsAccountCharges, - final boolean allowOverdraft, final BigDecimal overdraftLimit) { - this(client, group, product, fieldOfficer, accountNo, externalId, status, accountType, submittedOnDate, - submittedBy, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, + final String accountNo, final String externalId, final SavingsAccountStatusType status, final AccountType accountType, + final LocalDate submittedOnDate, final AppUser submittedBy, final BigDecimal nominalAnnualInterestRate, + final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType, + final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType, + final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, + final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, + final boolean withdrawalFeeApplicableForTransfer, final Set savingsAccountCharges, + final boolean allowOverdraft, final BigDecimal overdraftLimit) { + this(client, group, product, fieldOfficer, accountNo, externalId, status, accountType, submittedOnDate, submittedBy, + nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, savingsAccountCharges, allowOverdraft, overdraftLimit, false, null); } @@ -356,6 +359,7 @@ public class SavingsAccount extends AbstractPersistable { this.allowOverdraftMinBalance = allowOverdraftMinBalance; this.minRequiredBalance = minRequiredBalance; + this.minBalanceForInterestCalculation = product.minBalanceForInterestCalculation(); } /** @@ -516,12 +520,14 @@ public class SavingsAccount extends AbstractPersistable { final SavingsInterestCalculationType interestCalculationType = SavingsInterestCalculationType.fromInt(this.interestCalculationType); final BigDecimal interestRateAsFraction = getEffectiveInterestRateAsFraction(mc, upToInterestCalculationDate); final Collection interestPostTransactions = this.savingsHelper.fetchPostInterestTransactionIds(getId()); + final Money minBalanceForInterestCalculation = Money.of(getCurrency(), minBalanceForInterestCalculation()); + for (final LocalDateInterval periodInterval : postingPeriodIntervals) { final PostingPeriod postingPeriod = PostingPeriod.createFrom(periodInterval, periodStartingBalance, retreiveOrderedNonInterestPostingTransactions(), this.currency, compoundingPeriodType, interestCalculationType, interestRateAsFraction, daysInYearType.getValue(), upToInterestCalculationDate, interestPostTransactions, - isInterestTransfer); + isInterestTransfer,minBalanceForInterestCalculation); periodStartingBalance = postingPeriod.closingBalance(); @@ -796,12 +802,11 @@ public class SavingsAccount extends AbstractPersistable { } final BigDecimal withdrawalFee = null; - // deal with potential minRequiredBalance and allowOverdraftMinBalance + // deal with potential minRequiredBalance and + // allowOverdraftMinBalance if (this.minRequiredBalance != null && !this.allowOverdraftMinBalance) { - if (runningBalance.minus(this.minRequiredBalance).isLessThanZero()) { - throw new InsufficientAccountBalanceException("transactionAmount", - getAccountBalance(), withdrawalFee, transactionAmount); - } + if (runningBalance.minus(this.minRequiredBalance).isLessThanZero()) { throw new InsufficientAccountBalanceException( + "transactionAmount", getAccountBalance(), withdrawalFee, transactionAmount); } } if (runningBalance.isLessThanZero()) { @@ -1139,6 +1144,7 @@ public class SavingsAccount extends AbstractPersistable { public void update(final SavingsProduct product) { this.product = product; + this.minBalanceForInterestCalculation = product.minBalanceForInterestCalculation(); } public void update(final Staff fieldOfficer) { @@ -2176,4 +2182,8 @@ public class SavingsAccount extends AbstractPersistable { public boolean isTransactionsAllowed() { return isActive(); } + + public BigDecimal minBalanceForInterestCalculation() { + return this.minBalanceForInterestCalculation; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProduct.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProduct.java index fc280275c..cde4e87ab 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProduct.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProduct.java @@ -21,6 +21,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestPo import static org.mifosplatform.portfolio.savings.SavingsApiConstants.localeParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minBalanceForInterestCalculationParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName; @@ -155,6 +156,9 @@ public class SavingsProduct extends AbstractPersistable { @Column(name = "min_required_balance", scale = 6, precision = 19, nullable = true) private BigDecimal minRequiredBalance; + @Column(name = "min_balance_for_interest_calculation", scale = 6, precision = 19, nullable = true) + private BigDecimal minBalanceForInterestCalculation; + public static SavingsProduct createNew(final String name, final String shortName, final String description, final MonetaryCurrency currency, final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType, @@ -163,12 +167,12 @@ public class SavingsProduct extends AbstractPersistable { final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set charges, final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean allowOverdraftMinBalance, - final BigDecimal minRequiredBalance) { + final BigDecimal minRequiredBalance, final BigDecimal minBalanceForInterestCalculation) { return new SavingsProduct(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, - allowOverdraft, overdraftLimit, allowOverdraftMinBalance, minRequiredBalance); + allowOverdraft, overdraftLimit, allowOverdraftMinBalance, minRequiredBalance, minBalanceForInterestCalculation); } protected SavingsProduct() { @@ -182,11 +186,11 @@ public class SavingsProduct extends AbstractPersistable { final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set charges, - final boolean allowOverdraft, final BigDecimal overdraftLimit) { + final boolean allowOverdraft, final BigDecimal overdraftLimit, BigDecimal minBalanceForInterestCalculation) { this(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, allowOverdraft, overdraftLimit, - false, null); + false, null, minBalanceForInterestCalculation); } protected SavingsProduct(final String name, final String shortName, final String description, final MonetaryCurrency currency, @@ -196,7 +200,7 @@ public class SavingsProduct extends AbstractPersistable { final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set charges, final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean allowOverdraftMinBalance, - final BigDecimal minRequiredBalance) { + final BigDecimal minRequiredBalance, BigDecimal minBalanceForInterestCalculation) { this.name = name; this.shortName = shortName; @@ -234,6 +238,7 @@ public class SavingsProduct extends AbstractPersistable { this.allowOverdraftMinBalance = allowOverdraftMinBalance; this.minRequiredBalance = minRequiredBalance; + this.minBalanceForInterestCalculation = minBalanceForInterestCalculation; } public MonetaryCurrency currency() { @@ -433,6 +438,15 @@ public class SavingsProduct extends AbstractPersistable { this.minRequiredBalance = newValue; } + if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(minBalanceForInterestCalculationParamName, + this.minBalanceForInterestCalculation)) { + final BigDecimal newValue = command + .bigDecimalValueOfParameterNamedDefaultToNullIfZero(minBalanceForInterestCalculationParamName); + actualChanges.put(minBalanceForInterestCalculationParamName, newValue); + actualChanges.put(localeParamName, localeAsInput); + this.minBalanceForInterestCalculation = newValue; + } + if (!this.allowOverdraftMinBalance) { this.minRequiredBalance = null; } @@ -539,4 +553,8 @@ public class SavingsProduct extends AbstractPersistable { return null; } + public BigDecimal minBalanceForInterestCalculation() { + return this.minBalanceForInterestCalculation; + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProductAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProductAssembler.java index ac16582fc..0a27824f5 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProductAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProductAssembler.java @@ -5,6 +5,8 @@ */ package org.mifosplatform.portfolio.savings.domain; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftMinBalanceParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargesParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.currencyCodeParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.descriptionParamName; @@ -17,15 +19,14 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCo import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minBalanceForInterestCalculationParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName; -import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName; -import static org.mifosplatform.portfolio.savings.SavingsApiConstants.shortNameParamName; -import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.overdraftLimitParamName; -import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName; -import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftMinBalanceParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.shortNameParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName; import java.math.BigDecimal; import java.util.HashSet; @@ -130,11 +131,13 @@ public class SavingsProductAssembler { } final BigDecimal minRequiredBalance = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minRequiredBalanceParamName); + final BigDecimal minBalanceForInterestCalculation = command + .bigDecimalValueOfParameterNamedDefaultToNullIfZero(minBalanceForInterestCalculationParamName); return SavingsProduct.createNew(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, accountingRuleType, charges, - allowOverdraft, overdraftLimit, allowOverdraftMinBalance, minRequiredBalance); + allowOverdraft, overdraftLimit, allowOverdraftMinBalance, minRequiredBalance, minBalanceForInterestCalculation); } public Set assembleListOfSavingsProductCharges(final JsonCommand command, final String savingsProductCurrencyCode) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/AnnualCompoundingPeriod.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/AnnualCompoundingPeriod.java index 9967fd856..06df7d5c9 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/AnnualCompoundingPeriod.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/AnnualCompoundingPeriod.java @@ -26,34 +26,21 @@ public class AnnualCompoundingPeriod implements CompoundingPeriod { return new AnnualCompoundingPeriod(periodInterval, endOfDayBalancesWithinPeriod); } - @Override - public BigDecimal calculateInterest(final BigDecimal interestRateAsFraction, final long daysInYear) { - - BigDecimal interestEarned = BigDecimal.ZERO; - - for (final EndOfDayBalance balance : this.endOfDayBalances) { - final BigDecimal interestOnBalanceUnrounded = balance.calculateInterestOnBalance(BigDecimal.ZERO, interestRateAsFraction, - daysInYear); - interestEarned = interestEarned.add(interestOnBalanceUnrounded); - } - - return interestEarned; - } - @Override public BigDecimal calculateInterest(final SavingsCompoundingInterestPeriodType compoundingInterestPeriodType, final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestToCompound, - final BigDecimal interestRateAsFraction, final long daysInYear) { + final BigDecimal interestRateAsFraction, final long daysInYear, final BigDecimal minBalanceForInterestCalculation) { BigDecimal interestEarned = BigDecimal.ZERO; switch (interestCalculationType) { case DAILY_BALANCE: interestEarned = calculateUsingDailyBalanceMethod(compoundingInterestPeriodType, interestToCompound, - interestRateAsFraction, daysInYear); + interestRateAsFraction, daysInYear, minBalanceForInterestCalculation); break; case AVERAGE_DAILY_BALANCE: - interestEarned = calculateUsingAverageDailyBalanceMethod(interestToCompound, interestRateAsFraction, daysInYear); + interestEarned = calculateUsingAverageDailyBalanceMethod(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; case INVALID: break; @@ -63,7 +50,7 @@ public class AnnualCompoundingPeriod implements CompoundingPeriod { } private BigDecimal calculateUsingAverageDailyBalanceMethod(final BigDecimal interestToCompound, - final BigDecimal interestRateAsFraction, final long daysInYear) { + final BigDecimal interestRateAsFraction, final long daysInYear, final BigDecimal minBalanceForInterestCalculation) { BigDecimal cumulativeBalance = BigDecimal.ZERO; Integer numberOfDays = Integer.valueOf(0); @@ -84,15 +71,18 @@ public class AnnualCompoundingPeriod implements CompoundingPeriod { final BigDecimal multiplicand = BigDecimal.ONE.divide(BigDecimal.valueOf(daysInYear), MathContext.DECIMAL64); final BigDecimal dailyInterestRate = interestRateAsFraction.multiply(multiplicand, MathContext.DECIMAL64); final BigDecimal periodicInterestRate = dailyInterestRate.multiply(BigDecimal.valueOf(numberOfDays), MathContext.DECIMAL64); - - interestEarned = averageDailyBalance.multiply(periodicInterestRate, MathContext.DECIMAL64).setScale(9, RoundingMode.HALF_EVEN); + if (averageDailyBalance.compareTo(minBalanceForInterestCalculation) >= 0) { + interestEarned = averageDailyBalance.multiply(periodicInterestRate, MathContext.DECIMAL64).setScale(9, + RoundingMode.HALF_EVEN); + } } return interestEarned; } private BigDecimal calculateUsingDailyBalanceMethod(final SavingsCompoundingInterestPeriodType compoundingInterestPeriodType, - final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction, final long daysInYear) { + final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction, final long daysInYear, + final BigDecimal minBalanceForInterestCalculation) { BigDecimal interestEarned = BigDecimal.ZERO; BigDecimal interestOnBalanceUnrounded = BigDecimal.ZERO; @@ -101,23 +91,27 @@ public class AnnualCompoundingPeriod implements CompoundingPeriod { switch (compoundingInterestPeriodType) { case DAILY: interestOnBalanceUnrounded = balance.calculateInterestOnBalanceAndInterest(interestToCompound, interestRateAsFraction, - daysInYear); + daysInYear, minBalanceForInterestCalculation); break; case MONTHLY: - interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear); + interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; case QUATERLY: - interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear); + interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; // case WEEKLY: // break; // case BIWEEKLY: // break; case BI_ANNUAL: - interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear); + interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; case ANNUAL: - interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear); + interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; // case NO_COMPOUNDING_SIMPLE_INTEREST: // break; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/BiAnnualCompoundingPeriod.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/BiAnnualCompoundingPeriod.java index 1147ebb63..07a0ebb2f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/BiAnnualCompoundingPeriod.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/BiAnnualCompoundingPeriod.java @@ -26,34 +26,21 @@ public class BiAnnualCompoundingPeriod implements CompoundingPeriod { return new BiAnnualCompoundingPeriod(periodInterval, endOfDayBalancesWithinPeriod); } - @Override - public BigDecimal calculateInterest(final BigDecimal interestRateAsFraction, final long daysInYear) { - - BigDecimal interestEarned = BigDecimal.ZERO; - - for (final EndOfDayBalance balance : this.endOfDayBalances) { - final BigDecimal interestOnBalanceUnrounded = balance.calculateInterestOnBalance(BigDecimal.ZERO, interestRateAsFraction, - daysInYear); - interestEarned = interestEarned.add(interestOnBalanceUnrounded); - } - - return interestEarned; - } - @Override public BigDecimal calculateInterest(final SavingsCompoundingInterestPeriodType compoundingInterestPeriodType, final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestToCompound, - final BigDecimal interestRateAsFraction, final long daysInYear) { + final BigDecimal interestRateAsFraction, final long daysInYear, final BigDecimal minBalanceForInterestCalculation) { BigDecimal interestEarned = BigDecimal.ZERO; switch (interestCalculationType) { case DAILY_BALANCE: interestEarned = calculateUsingDailyBalanceMethod(compoundingInterestPeriodType, interestToCompound, - interestRateAsFraction, daysInYear); + interestRateAsFraction, daysInYear, minBalanceForInterestCalculation); break; case AVERAGE_DAILY_BALANCE: - interestEarned = calculateUsingAverageDailyBalanceMethod(interestToCompound, interestRateAsFraction, daysInYear); + interestEarned = calculateUsingAverageDailyBalanceMethod(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; case INVALID: break; @@ -63,7 +50,7 @@ public class BiAnnualCompoundingPeriod implements CompoundingPeriod { } private BigDecimal calculateUsingAverageDailyBalanceMethod(final BigDecimal interestToCompound, - final BigDecimal interestRateAsFraction, final long daysInYear) { + final BigDecimal interestRateAsFraction, final long daysInYear, final BigDecimal minBalanceForInterestCalculation) { BigDecimal cumulativeBalance = BigDecimal.ZERO; Integer numberOfDays = Integer.valueOf(0); @@ -84,15 +71,18 @@ public class BiAnnualCompoundingPeriod implements CompoundingPeriod { final BigDecimal multiplicand = BigDecimal.ONE.divide(BigDecimal.valueOf(daysInYear), MathContext.DECIMAL64); final BigDecimal dailyInterestRate = interestRateAsFraction.multiply(multiplicand, MathContext.DECIMAL64); final BigDecimal periodicInterestRate = dailyInterestRate.multiply(BigDecimal.valueOf(numberOfDays), MathContext.DECIMAL64); - - interestEarned = averageDailyBalance.multiply(periodicInterestRate, MathContext.DECIMAL64).setScale(9, RoundingMode.HALF_EVEN); + if (averageDailyBalance.compareTo(minBalanceForInterestCalculation) >= 0) { + interestEarned = averageDailyBalance.multiply(periodicInterestRate, MathContext.DECIMAL64).setScale(9, + RoundingMode.HALF_EVEN); + } } return interestEarned; } private BigDecimal calculateUsingDailyBalanceMethod(final SavingsCompoundingInterestPeriodType compoundingInterestPeriodType, - final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction, final long daysInYear) { + final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction, final long daysInYear, + final BigDecimal minBalanceForInterestCalculation) { BigDecimal interestEarned = BigDecimal.ZERO; BigDecimal interestOnBalanceUnrounded = BigDecimal.ZERO; @@ -101,23 +91,27 @@ public class BiAnnualCompoundingPeriod implements CompoundingPeriod { switch (compoundingInterestPeriodType) { case DAILY: interestOnBalanceUnrounded = balance.calculateInterestOnBalanceAndInterest(interestToCompound, interestRateAsFraction, - daysInYear); + daysInYear, minBalanceForInterestCalculation); break; case MONTHLY: - interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear); + interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; case QUATERLY: - interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear); + interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; // case WEEKLY: // break; // case BIWEEKLY: // break; case BI_ANNUAL: - interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear); + interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; case ANNUAL: - interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear); + interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; // case NO_COMPOUNDING_SIMPLE_INTEREST: // break; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/CompoundingPeriod.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/CompoundingPeriod.java index a14bba075..e277efdce 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/CompoundingPeriod.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/CompoundingPeriod.java @@ -7,9 +7,7 @@ import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType; public interface CompoundingPeriod { - BigDecimal calculateInterest(BigDecimal interestRateAsFraction, long daysInYear); - BigDecimal calculateInterest(SavingsCompoundingInterestPeriodType compoundingInterestPeriodType, SavingsInterestCalculationType interestCalculationType, BigDecimal interestFromPreviousPostingPeriod, - BigDecimal interestRateAsFraction, long daysInYear); + BigDecimal interestRateAsFraction, long daysInYear, BigDecimal minBalanceForInterestCalculation); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/DailyCompoundingPeriod.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/DailyCompoundingPeriod.java index 83913c09e..42f9db4b6 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/DailyCompoundingPeriod.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/DailyCompoundingPeriod.java @@ -57,25 +57,12 @@ public class DailyCompoundingPeriod implements CompoundingPeriod { this.endOfDayBalances = endOfDayBalances; } - @Override - public BigDecimal calculateInterest(final BigDecimal interestRateAsFraction, final long daysInYear) { - - BigDecimal interestEarned = BigDecimal.ZERO; - - for (final EndOfDayBalance balance : this.endOfDayBalances) { - final BigDecimal interestOnBalanceUnrounded = balance.calculateInterestOnBalance(BigDecimal.ZERO, interestRateAsFraction, - daysInYear); - interestEarned = interestEarned.add(interestOnBalanceUnrounded); - } - - return interestEarned; - } - @Override public BigDecimal calculateInterest( @SuppressWarnings("unused") final SavingsCompoundingInterestPeriodType compoundingInterestPeriodType, @SuppressWarnings("unused") final SavingsInterestCalculationType interestCalculationType, - final BigDecimal interestFromPreviousPostingPeriod, final BigDecimal interestRateAsFraction, final long daysInYear) { + final BigDecimal interestFromPreviousPostingPeriod, final BigDecimal interestRateAsFraction, final long daysInYear, + final BigDecimal minBalanceForInterestCalculation) { BigDecimal interestEarned = BigDecimal.ZERO; // for daily compounding - each interest calculated from previous daily @@ -83,7 +70,7 @@ public class DailyCompoundingPeriod implements CompoundingPeriod { BigDecimal interestToCompound = interestFromPreviousPostingPeriod; for (final EndOfDayBalance balance : this.endOfDayBalances) { final BigDecimal interestOnBalanceUnrounded = balance.calculateInterestOnBalanceAndInterest(interestToCompound, - interestRateAsFraction, daysInYear); + interestRateAsFraction, daysInYear, minBalanceForInterestCalculation); interestToCompound = interestToCompound.add(interestOnBalanceUnrounded, MathContext.DECIMAL64).setScale(9); interestEarned = interestEarned.add(interestOnBalanceUnrounded); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/EndOfDayBalance.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/EndOfDayBalance.java index cd2e53b54..68accd427 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/EndOfDayBalance.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/EndOfDayBalance.java @@ -41,15 +41,19 @@ public class EndOfDayBalance { } public BigDecimal calculateInterestOnBalance(final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction, - final long daysInYear) { + final long daysInYear, final BigDecimal minBalanceForInterestCalculation) { final BigDecimal multiplicand = BigDecimal.ONE.divide(BigDecimal.valueOf(daysInYear), MathContext.DECIMAL64); final BigDecimal dailyInterestRate = interestRateAsFraction.multiply(multiplicand, MathContext.DECIMAL64); final BigDecimal periodicInterestRate = dailyInterestRate.multiply(BigDecimal.valueOf(this.numberOfDays), MathContext.DECIMAL64); final BigDecimal realBalanceForInterestCalculation = this.endOfDayBalance.getAmount().add(interestToCompound); - - return realBalanceForInterestCalculation.multiply(periodicInterestRate, MathContext.DECIMAL64).setScale(9, RoundingMode.HALF_EVEN); + BigDecimal interest = BigDecimal.ZERO.setScale(9, RoundingMode.HALF_EVEN); + if (realBalanceForInterestCalculation.compareTo(minBalanceForInterestCalculation) >= 0) { + interest = realBalanceForInterestCalculation.multiply(periodicInterestRate, MathContext.DECIMAL64).setScale(9, + RoundingMode.HALF_EVEN); + } + return interest; } /** @@ -60,7 +64,7 @@ public class EndOfDayBalance { * 1/365 n = number of periods rate is compounded */ public BigDecimal calculateInterestOnBalanceAndInterest(final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction, - final long daysInYear) { + final long daysInYear, final BigDecimal minBalanceForInterestCalculation) { final BigDecimal multiplicand = BigDecimal.ONE.divide(BigDecimal.valueOf(daysInYear), MathContext.DECIMAL64); final BigDecimal presentValue = this.endOfDayBalance.getAmount().add(interestToCompound); @@ -71,27 +75,29 @@ public class EndOfDayBalance { final double interestRateForCompoundingPeriodPowered = Math.pow(interestRateForCompoundingPeriodPlusOne.doubleValue(), Integer .valueOf(this.numberOfDays).doubleValue()); - - final BigDecimal futureValue = presentValue.multiply(BigDecimal.valueOf(interestRateForCompoundingPeriodPowered), - MathContext.DECIMAL64).setScale(9, RoundingMode.HALF_EVEN); + BigDecimal futureValue = presentValue.setScale(9, RoundingMode.HALF_EVEN); + if (presentValue.compareTo(minBalanceForInterestCalculation) >= 0) { + futureValue = presentValue.multiply(BigDecimal.valueOf(interestRateForCompoundingPeriodPowered), MathContext.DECIMAL64) + .setScale(9, RoundingMode.HALF_EVEN); + } return futureValue.subtract(presentValue); } /** * @param compoundingPeriodInterval * @param upToInterestCalculationDate - * : For calculating maturity details in advance upToInterestCalculationDate - * will be maturity date else it will be - * DateUtils.getLocalDateOfTenant(). + * : For calculating maturity details in advance + * upToInterestCalculationDate will be maturity date else it will + * be DateUtils.getLocalDateOfTenant(). * @return */ public EndOfDayBalance upTo(final LocalDateInterval compoundingPeriodInterval, final LocalDate upToInterestCalculationDate) { Money startingBalance = this.openingBalance; LocalDate balanceStartDate = this.date; - + LocalDate oldBalanceEndDate = this.date.plusDays(this.numberOfDays - 1); - + int daysOfBalance = this.numberOfDays; if (this.date.isBefore(compoundingPeriodInterval.startDate())) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/MonthlyCompoundingPeriod.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/MonthlyCompoundingPeriod.java index 4af42b4d9..ea82b5886 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/MonthlyCompoundingPeriod.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/MonthlyCompoundingPeriod.java @@ -26,34 +26,21 @@ public class MonthlyCompoundingPeriod implements CompoundingPeriod { return new MonthlyCompoundingPeriod(periodInterval, endOfDayBalancesWithinPeriod); } - @Override - public BigDecimal calculateInterest(final BigDecimal interestRateAsFraction, final long daysInYear) { - - BigDecimal interestEarned = BigDecimal.ZERO; - - for (final EndOfDayBalance balance : this.endOfDayBalances) { - final BigDecimal interestOnBalanceUnrounded = balance.calculateInterestOnBalance(BigDecimal.ZERO, interestRateAsFraction, - daysInYear); - interestEarned = interestEarned.add(interestOnBalanceUnrounded); - } - - return interestEarned; - } - @Override public BigDecimal calculateInterest(final SavingsCompoundingInterestPeriodType compoundingInterestPeriodType, final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestToCompound, - final BigDecimal interestRateAsFraction, final long daysInYear) { + final BigDecimal interestRateAsFraction, final long daysInYear, final BigDecimal minBalanceForInterestCalculation) { BigDecimal interestEarned = BigDecimal.ZERO; switch (interestCalculationType) { case DAILY_BALANCE: interestEarned = calculateUsingDailyBalanceMethod(compoundingInterestPeriodType, interestToCompound, - interestRateAsFraction, daysInYear); + interestRateAsFraction, daysInYear, minBalanceForInterestCalculation); break; case AVERAGE_DAILY_BALANCE: - interestEarned = calculateUsingAverageDailyBalanceMethod(interestToCompound, interestRateAsFraction, daysInYear); + interestEarned = calculateUsingAverageDailyBalanceMethod(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; case INVALID: break; @@ -63,7 +50,7 @@ public class MonthlyCompoundingPeriod implements CompoundingPeriod { } private BigDecimal calculateUsingAverageDailyBalanceMethod(final BigDecimal interestToCompound, - final BigDecimal interestRateAsFraction, final long daysInYear) { + final BigDecimal interestRateAsFraction, final long daysInYear, final BigDecimal minBalanceForInterestCalculation) { BigDecimal cumulativeBalance = BigDecimal.ZERO; Integer numberOfDays = Integer.valueOf(0); @@ -84,15 +71,18 @@ public class MonthlyCompoundingPeriod implements CompoundingPeriod { final BigDecimal multiplicand = BigDecimal.ONE.divide(BigDecimal.valueOf(daysInYear), MathContext.DECIMAL64); final BigDecimal dailyInterestRate = interestRateAsFraction.multiply(multiplicand, MathContext.DECIMAL64); final BigDecimal periodicInterestRate = dailyInterestRate.multiply(BigDecimal.valueOf(numberOfDays), MathContext.DECIMAL64); - - interestEarned = averageDailyBalance.multiply(periodicInterestRate, MathContext.DECIMAL64).setScale(9, RoundingMode.HALF_EVEN); + if (averageDailyBalance.compareTo(minBalanceForInterestCalculation) >= 0) { + interestEarned = averageDailyBalance.multiply(periodicInterestRate, MathContext.DECIMAL64).setScale(9, + RoundingMode.HALF_EVEN); + } } return interestEarned; } private BigDecimal calculateUsingDailyBalanceMethod(final SavingsCompoundingInterestPeriodType compoundingInterestPeriodType, - final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction, final long daysInYear) { + final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction, final long daysInYear, + final BigDecimal minBalanceForInterestCalculation) { BigDecimal interestEarned = BigDecimal.ZERO; BigDecimal interestOnBalanceUnrounded = BigDecimal.ZERO; @@ -101,10 +91,11 @@ public class MonthlyCompoundingPeriod implements CompoundingPeriod { switch (compoundingInterestPeriodType) { case DAILY: interestOnBalanceUnrounded = balance.calculateInterestOnBalanceAndInterest(interestToCompound, interestRateAsFraction, - daysInYear); + daysInYear, minBalanceForInterestCalculation); break; case MONTHLY: - interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear); + interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; // case QUATERLY: // break; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/PostingPeriod.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/PostingPeriod.java index 789cbf5d8..8b18b235b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/PostingPeriod.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/PostingPeriod.java @@ -37,12 +37,17 @@ public class PostingPeriod { // include in compounding interest private boolean interestTransfered = false; - // isInterestTransfer boolean is to identify newly created transaction is interest transfer + // minimum balance for interest calculation + private final Money minBalanceForInterestCalculation; + + // isInterestTransfer boolean is to identify newly created transaction is + // interest transfer public static PostingPeriod createFrom(final LocalDateInterval periodInterval, final Money periodStartingBalance, final List orderedListOfTransactions, final MonetaryCurrency currency, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType, final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestRateAsFraction, final long daysInYear, - final LocalDate upToInterestCalculationDate, Collection interestPostTransactions, boolean isInterestTransfer) { + final LocalDate upToInterestCalculationDate, Collection interestPostTransactions, boolean isInterestTransfer, + final Money minBalanceForInterestCalculation) { final List accountEndOfDayBalances = new ArrayList<>(); boolean interestTransfered = false; @@ -66,7 +71,8 @@ public class PostingPeriod { openingDayBalance = closeOfDayBalance; } - // this check is to make sure to add interest if withdrawal is happened for already + // this check is to make sure to add interest if withdrawal is + // happened for already if (transaction.occursOn(periodInterval.endDate().plusDays(1))) { if (transaction.getId() == null) { interestTransfered = isInterestTransfer; @@ -101,13 +107,14 @@ public class PostingPeriod { accountEndOfDayBalances, upToInterestCalculationDate); return new PostingPeriod(periodInterval, currency, periodStartingBalance, openingDayBalance, interestCompoundingPeriodType, - interestCalculationType, interestRateAsFraction, daysInYear, compoundingPeriods, interestTransfered); + interestCalculationType, interestRateAsFraction, daysInYear, compoundingPeriods, interestTransfered, + minBalanceForInterestCalculation); } private PostingPeriod(final LocalDateInterval periodInterval, final MonetaryCurrency currency, final Money openingBalance, final Money closingBalance, final SavingsCompoundingInterestPeriodType interestCompoundingType, final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestRateAsFraction, final long daysInYear, - final List compoundingPeriods, boolean interestTransfered) { + final List compoundingPeriods, boolean interestTransfered, final Money minBalanceForInterestCalculation) { this.periodInterval = periodInterval; this.currency = currency; this.openingBalance = openingBalance; @@ -120,6 +127,7 @@ public class PostingPeriod { this.dateOfPostingTransaction = periodInterval.endDate().plusDays(1); this.interestTransfered = interestTransfered; + this.minBalanceForInterestCalculation = minBalanceForInterestCalculation; } public Money interest() { @@ -147,7 +155,8 @@ public class PostingPeriod { for (final CompoundingPeriod compoundingPeriod : this.compoundingPeriods) { final BigDecimal interestUnrounded = compoundingPeriod.calculateInterest(this.interestCompoundingType, - this.interestCalculationType, interestCompounded, this.interestRateAsFraction, this.daysInYear); + this.interestCalculationType, interestCompounded, this.interestRateAsFraction, this.daysInYear, + this.minBalanceForInterestCalculation.getAmount()); interestCompounded = interestCompounded.add(interestUnrounded); interestEarned = interestEarned.add(interestUnrounded); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/QuarterlyCompoundingPeriod.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/QuarterlyCompoundingPeriod.java index 903393aff..e596808aa 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/QuarterlyCompoundingPeriod.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/interest/QuarterlyCompoundingPeriod.java @@ -17,41 +17,30 @@ public class QuarterlyCompoundingPeriod implements CompoundingPeriod { private final LocalDateInterval periodInterval; private final List endOfDayBalances; - public static QuarterlyCompoundingPeriod create(final LocalDateInterval periodInterval, final List allEndOfDayBalances, final LocalDate upToInterestCalculationDate) { + public static QuarterlyCompoundingPeriod create(final LocalDateInterval periodInterval, + final List allEndOfDayBalances, final LocalDate upToInterestCalculationDate) { - final List endOfDayBalancesWithinPeriod = endOfDayBalancesWithinPeriodInterval(periodInterval, allEndOfDayBalances, upToInterestCalculationDate); + final List endOfDayBalancesWithinPeriod = endOfDayBalancesWithinPeriodInterval(periodInterval, + allEndOfDayBalances, upToInterestCalculationDate); return new QuarterlyCompoundingPeriod(periodInterval, endOfDayBalancesWithinPeriod); } - @Override - public BigDecimal calculateInterest(final BigDecimal interestRateAsFraction, final long daysInYear) { - - BigDecimal interestEarned = BigDecimal.ZERO; - - for (final EndOfDayBalance balance : this.endOfDayBalances) { - final BigDecimal interestOnBalanceUnrounded = balance.calculateInterestOnBalance(BigDecimal.ZERO, interestRateAsFraction, - daysInYear); - interestEarned = interestEarned.add(interestOnBalanceUnrounded); - } - - return interestEarned; - } - @Override public BigDecimal calculateInterest(final SavingsCompoundingInterestPeriodType compoundingInterestPeriodType, final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestToCompound, - final BigDecimal interestRateAsFraction, final long daysInYear) { + final BigDecimal interestRateAsFraction, final long daysInYear, final BigDecimal minBalanceForInterestCalculation) { BigDecimal interestEarned = BigDecimal.ZERO; switch (interestCalculationType) { case DAILY_BALANCE: interestEarned = calculateUsingDailyBalanceMethod(compoundingInterestPeriodType, interestToCompound, - interestRateAsFraction, daysInYear); + interestRateAsFraction, daysInYear, minBalanceForInterestCalculation); break; case AVERAGE_DAILY_BALANCE: - interestEarned = calculateUsingAverageDailyBalanceMethod(interestToCompound, interestRateAsFraction, daysInYear); + interestEarned = calculateUsingAverageDailyBalanceMethod(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; case INVALID: break; @@ -61,7 +50,7 @@ public class QuarterlyCompoundingPeriod implements CompoundingPeriod { } private BigDecimal calculateUsingAverageDailyBalanceMethod(final BigDecimal interestToCompound, - final BigDecimal interestRateAsFraction, final long daysInYear) { + final BigDecimal interestRateAsFraction, final long daysInYear, final BigDecimal minBalanceForInterestCalculation) { BigDecimal cumulativeBalance = BigDecimal.ZERO; Integer numberOfDays = Integer.valueOf(0); @@ -82,15 +71,18 @@ public class QuarterlyCompoundingPeriod implements CompoundingPeriod { final BigDecimal multiplicand = BigDecimal.ONE.divide(BigDecimal.valueOf(daysInYear), MathContext.DECIMAL64); final BigDecimal dailyInterestRate = interestRateAsFraction.multiply(multiplicand, MathContext.DECIMAL64); final BigDecimal periodicInterestRate = dailyInterestRate.multiply(BigDecimal.valueOf(numberOfDays), MathContext.DECIMAL64); - - interestEarned = averageDailyBalance.multiply(periodicInterestRate, MathContext.DECIMAL64).setScale(9, RoundingMode.HALF_EVEN); + if (averageDailyBalance.compareTo(minBalanceForInterestCalculation) >= 0) { + interestEarned = averageDailyBalance.multiply(periodicInterestRate, MathContext.DECIMAL64).setScale(9, + RoundingMode.HALF_EVEN); + } } return interestEarned; } private BigDecimal calculateUsingDailyBalanceMethod(final SavingsCompoundingInterestPeriodType compoundingInterestPeriodType, - final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction, final long daysInYear) { + final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction, final long daysInYear, + final BigDecimal minBalanceForInterestCalculation) { BigDecimal interestEarned = BigDecimal.ZERO; BigDecimal interestOnBalanceUnrounded = BigDecimal.ZERO; @@ -99,24 +91,28 @@ public class QuarterlyCompoundingPeriod implements CompoundingPeriod { switch (compoundingInterestPeriodType) { case DAILY: interestOnBalanceUnrounded = balance.calculateInterestOnBalanceAndInterest(interestToCompound, interestRateAsFraction, - daysInYear); + daysInYear, minBalanceForInterestCalculation); break; case MONTHLY: - interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear); + interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); + break; + case QUATERLY: + interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); break; - case QUATERLY: - interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear); - break; // case WEEKLY: // break; // case BIWEEKLY: // break; - case BI_ANNUAL: - interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear); - break; - case ANNUAL: - interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear); - break; + case BI_ANNUAL: + interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); + break; + case ANNUAL: + interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear, + minBalanceForInterestCalculation); + break; // case NO_COMPOUNDING_SIMPLE_INTEREST: // break; case INVALID: diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java index ee570f64f..043ab054d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java @@ -540,7 +540,8 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead selectFieldsSqlBuilder.append("sa.account_balance_derived as accountBalance, "); selectFieldsSqlBuilder.append("sa.total_fees_charge_derived as totalFeeCharge, "); selectFieldsSqlBuilder.append("sa.total_penalty_charge_derived as totalPenaltyCharge, "); - selectFieldsSqlBuilder.append("sa.deposit_type_enum as depositTypeId "); + selectFieldsSqlBuilder.append("sa.deposit_type_enum as depositTypeId, "); + selectFieldsSqlBuilder.append("sa.min_balance_for_interest_calculation as minBalanceForInterestCalculation "); this.selectFieldsSql = selectFieldsSqlBuilder.toString(); @@ -668,6 +669,8 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead } final boolean withdrawalFeeForTransfers = rs.getBoolean("withdrawalFeeForTransfers"); + final BigDecimal minBalanceForInterestCalculation = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, + "minBalanceForInterestCalculation"); final BigDecimal totalDeposits = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalDeposits"); final BigDecimal totalWithdrawals = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalWithdrawals"); @@ -687,7 +690,8 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead return DepositAccountData.instance(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, - lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, depositType); + lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, depositType, + minBalanceForInterestCalculation); } } @@ -1022,7 +1026,8 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead selectFieldsSqlBuilder.append("sa.lockin_period_frequency as lockinPeriodFrequency,"); selectFieldsSqlBuilder.append("sa.lockin_period_frequency_enum as lockinPeriodFrequencyType, "); selectFieldsSqlBuilder.append("sa.withdrawal_fee_for_transfer as withdrawalFeeForTransfers, "); - selectFieldsSqlBuilder.append("sa.deposit_type_enum as depositTypeId "); + selectFieldsSqlBuilder.append("sa.deposit_type_enum as depositTypeId, "); + selectFieldsSqlBuilder.append("sa.min_balance_for_interest_calculation as minBalanceForInterestCalculation "); this.selectFieldsSql = selectFieldsSqlBuilder.toString(); @@ -1090,6 +1095,8 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead } final boolean withdrawalFeeForTransfers = rs.getBoolean("withdrawalFeeForTransfers"); + final BigDecimal minBalanceForInterestCalculation = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, + "minBalanceForInterestCalculation"); Long clientId = null; String clientName = null; @@ -1114,7 +1121,8 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead return DepositAccountData.instance(null, null, null, groupId, groupName, clientId, clientName, productId, productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualIterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, - lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, depositType); + lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, depositType, + minBalanceForInterestCalculation); } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/DepositProductReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/DepositProductReadPlatformServiceImpl.java index 202bee84d..85fde30f4 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/DepositProductReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/DepositProductReadPlatformServiceImpl.java @@ -130,7 +130,8 @@ public class DepositProductReadPlatformServiceImpl implements DepositProductRead sqlBuilder.append("sp.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, "); sqlBuilder.append("sp.lockin_period_frequency as lockinPeriodFrequency,"); sqlBuilder.append("sp.lockin_period_frequency_enum as lockinPeriodFrequencyType, "); - sqlBuilder.append("sp.accounting_type as accountingType "); + sqlBuilder.append("sp.accounting_type as accountingType, "); + sqlBuilder.append("sp.min_balance_for_interest_calculation as minBalanceForInterestCalculation "); this.schemaSql = sqlBuilder.toString(); } @@ -181,10 +182,11 @@ public class DepositProductReadPlatformServiceImpl implements DepositProductRead if (lockinPeriodFrequencyTypeValue != null) { lockinPeriodFrequencyType = SavingsEnumerations.lockinPeriodFrequencyType(lockinPeriodFrequencyTypeValue); } + final BigDecimal minBalanceForInterestCalculation = rs.getBigDecimal("minBalanceForInterestCalculation"); return DepositProductData.instance(id, name, shortName, description, currency, nominalAnnualInterestRate, compoundingInterestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, - lockinPeriodFrequency, lockinPeriodFrequencyType, accountingRuleType); + lockinPeriodFrequency, lockinPeriodFrequencyType, accountingRuleType, minBalanceForInterestCalculation); } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java index 20c758a36..6b81b59a1 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java @@ -250,8 +250,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead sqlBuilder.append("sa.account_balance_derived as accountBalance, "); sqlBuilder.append("sa.total_fees_charge_derived as totalFeeCharge, "); sqlBuilder.append("sa.total_penalty_charge_derived as totalPenaltyCharge, "); - sqlBuilder.append("sp.min_required_balance as minRequiredBalance, "); - sqlBuilder.append("sp.allow_overdraft_min_balance as allowOverdraftMinBalance "); + sqlBuilder.append("sa.min_balance_for_interest_calculation as minBalanceForInterestCalculation,"); + sqlBuilder.append("sa.min_required_balance as minRequiredBalance, "); + sqlBuilder.append("sa.allow_overdraft_min_balance as allowOverdraftMinBalance "); sqlBuilder.append("from m_savings_account sa "); sqlBuilder.append("join m_savings_product sp ON sa.product_id = sp.id "); sqlBuilder.append("join m_currency curr on curr.code = sa.currency_code "); @@ -411,6 +412,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead final BigDecimal accountBalance = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "accountBalance"); final BigDecimal totalFeeCharge = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalFeeCharge"); final BigDecimal totalPenaltyCharge = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalPenaltyCharge"); + final BigDecimal minBalanceForInterestCalculation = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, + "minBalanceForInterestCalculation"); final SavingsAccountSummaryData summary = new SavingsAccountSummaryData(currency, totalDeposits, totalWithdrawals, totalWithdrawalFees, totalAnnualFees, totalInterestEarned, totalInterestPosted, accountBalance, totalFeeCharge, @@ -420,7 +423,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, - allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance); + allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance, minBalanceForInterestCalculation); } } @@ -811,8 +814,11 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead // sqlBuilder.append("sp.withdrawal_fee_amount as withdrawalFeeAmount,"); // sqlBuilder.append("sp.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, "); sqlBuilder.append("sp.withdrawal_fee_for_transfer as withdrawalFeeForTransfers, "); + sqlBuilder.append("sp.min_balance_for_interest_calculation as minBalanceForInterestCalculation, "); sqlBuilder.append("sp.allow_overdraft as allowOverdraft, "); - sqlBuilder.append("sp.overdraft_limit as overdraftLimit "); + sqlBuilder.append("sp.overdraft_limit as overdraftLimit, "); + sqlBuilder.append("sp.min_required_balance as minRequiredBalance, "); + sqlBuilder.append("sp.allow_overdraft_min_balance as allowOverdraftMinBalance "); // sqlBuilder.append("sp.annual_fee_amount as annualFeeAmount,"); // sqlBuilder.append("sp.annual_fee_on_month as annualFeeOnMonth, "); // sqlBuilder.append("sp.annual_fee_on_day as annualFeeOnDay "); @@ -884,6 +890,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead final BigDecimal minRequiredBalance = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "minRequiredBalance"); final boolean allowOverdraftMinBalance = rs.getBoolean("allowOverdraftMinBalance"); + final BigDecimal minBalanceForInterestCalculation = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, + "minBalanceForInterestCalculation"); // final BigDecimal annualFeeAmount = // JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, @@ -924,7 +932,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualIterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, - allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance); + allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance, minBalanceForInterestCalculation); } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java index 06e874841..4810749b9 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java @@ -94,6 +94,7 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead sqlBuilder.append("sp.overdraft_limit as overdraftLimit, "); sqlBuilder.append("sp.min_required_balance as minRequiredBalance, "); sqlBuilder.append("sp.allow_overdraft_min_balance as allowOverdraftMinBalance, "); + sqlBuilder.append("sp.min_balance_for_interest_calculation as minBalanceForInterestCalculation,"); sqlBuilder.append("sp.accounting_type as accountingType "); sqlBuilder.append("from m_savings_product sp "); sqlBuilder.append("join m_currency curr on curr.code = sp.currency_code "); @@ -158,11 +159,13 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead final BigDecimal minRequiredBalance = rs.getBigDecimal("minRequiredBalance"); final boolean allowOverdraftMinBalance = rs.getBoolean("allowOverdraftMinBalance"); + final BigDecimal minBalanceForInterestCalculation = rs.getBigDecimal("minBalanceForInterestCalculation"); return SavingsProductData.instance(id, name, shortName, description, currency, nominalAnnualInterestRate, compoundingInterestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, - accountingRuleType, allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance); + accountingRuleType, allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance, + minBalanceForInterestCalculation); } }