Dormant Savings Feature
This commit is contained in:
+4
-3
@@ -151,7 +151,7 @@ public class AccountingConstants {
|
|||||||
/*** Accounting placeholders for cash based accounting for savings products ***/
|
/*** Accounting placeholders for cash based accounting for savings products ***/
|
||||||
public static enum CASH_ACCOUNTS_FOR_SAVINGS {
|
public static enum CASH_ACCOUNTS_FOR_SAVINGS {
|
||||||
SAVINGS_REFERENCE(1), SAVINGS_CONTROL(2), INTEREST_ON_SAVINGS(3), INCOME_FROM_FEES(4), INCOME_FROM_PENALTIES(5), TRANSFERS_SUSPENSE(
|
SAVINGS_REFERENCE(1), SAVINGS_CONTROL(2), INTEREST_ON_SAVINGS(3), INCOME_FROM_FEES(4), INCOME_FROM_PENALTIES(5), TRANSFERS_SUSPENSE(
|
||||||
10), OVERDRAFT_PORTFOLIO_CONTROL(11), INCOME_FROM_INTEREST(12), LOSSES_WRITTEN_OFF(13);
|
10), OVERDRAFT_PORTFOLIO_CONTROL(11), INCOME_FROM_INTEREST(12), LOSSES_WRITTEN_OFF(13), ESCHEAT_LIABILITY(14);
|
||||||
|
|
||||||
private final Integer value;
|
private final Integer value;
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ public class AccountingConstants {
|
|||||||
"paymentTypeId"), FUND_SOURCE("fundSourceAccountId"), TRANSFERS_SUSPENSE("transfersInSuspenseAccountId"), FEE_INCOME_ACCOUNT_MAPPING(
|
"paymentTypeId"), FUND_SOURCE("fundSourceAccountId"), TRANSFERS_SUSPENSE("transfersInSuspenseAccountId"), FEE_INCOME_ACCOUNT_MAPPING(
|
||||||
"feeToIncomeAccountMappings"), PENALTY_INCOME_ACCOUNT_MAPPING("penaltyToIncomeAccountMappings"), CHARGE_ID("chargeId"), INCOME_ACCOUNT_ID(
|
"feeToIncomeAccountMappings"), PENALTY_INCOME_ACCOUNT_MAPPING("penaltyToIncomeAccountMappings"), CHARGE_ID("chargeId"), INCOME_ACCOUNT_ID(
|
||||||
"incomeAccountId"), OVERDRAFT_PORTFOLIO_CONTROL("overdraftPortfolioControlId"), INCOME_FROM_INTEREST("incomeFromInterestId"), LOSSES_WRITTEN_OFF(
|
"incomeAccountId"), OVERDRAFT_PORTFOLIO_CONTROL("overdraftPortfolioControlId"), INCOME_FROM_INTEREST("incomeFromInterestId"), LOSSES_WRITTEN_OFF(
|
||||||
"writeOffAccountId");
|
"writeOffAccountId"), ESCHEAT_LIABILITY("escheatLiabilityId");
|
||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
||||||
@@ -215,7 +215,8 @@ public class AccountingConstants {
|
|||||||
"incomeFromPenaltyAccount"), INTEREST_ON_SAVINGS("interestOnSavingsAccount"), PAYMENT_TYPE("paymentType"), FUND_SOURCE(
|
"incomeFromPenaltyAccount"), INTEREST_ON_SAVINGS("interestOnSavingsAccount"), PAYMENT_TYPE("paymentType"), FUND_SOURCE(
|
||||||
"fundSourceAccount"), TRANSFERS_SUSPENSE("transfersInSuspenseAccount"), PENALTY_INCOME_ACCOUNT_MAPPING(
|
"fundSourceAccount"), TRANSFERS_SUSPENSE("transfersInSuspenseAccount"), PENALTY_INCOME_ACCOUNT_MAPPING(
|
||||||
"penaltyToIncomeAccountMappings"), CHARGE_ID("charge"), INCOME_ACCOUNT_ID("incomeAccount"), OVERDRAFT_PORTFOLIO_CONTROL(
|
"penaltyToIncomeAccountMappings"), CHARGE_ID("charge"), INCOME_ACCOUNT_ID("incomeAccount"), OVERDRAFT_PORTFOLIO_CONTROL(
|
||||||
"overdraftPortfolioControl"), INCOME_FROM_INTEREST("incomeFromInterest"), LOSSES_WRITTEN_OFF("writeOffAccount");
|
"overdraftPortfolioControl"), INCOME_FROM_INTEREST("incomeFromInterest"), LOSSES_WRITTEN_OFF("writeOffAccount"),
|
||||||
|
ESCHEAT_LIABILITY("escheatLiabilityAccount");
|
||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
||||||
|
|||||||
+5
@@ -143,6 +143,11 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (savingsTransactionDTO.getTransactionType().isEscheat()) {
|
||||||
|
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||||
|
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(), CASH_ACCOUNTS_FOR_SAVINGS.ESCHEAT_LIABILITY.getValue(),
|
||||||
|
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Handle Interest Applications and reversals of Interest
|
* Handle Interest Applications and reversals of Interest
|
||||||
* Applications
|
* Applications
|
||||||
|
|||||||
+9
@@ -20,6 +20,7 @@ package org.apache.fineract.accounting.producttoaccountmapping.serialization;
|
|||||||
|
|
||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_RESOURCE_NAME;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_RESOURCE_NAME;
|
||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountingRuleParamName;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountingRuleParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.isDormancyTrackingActiveParamName;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -207,6 +208,14 @@ public final class ProductToGLAccountMappingFromApiJsonDeserializer {
|
|||||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue())
|
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue())
|
||||||
.value(incomeFromPenaltyId).notNull().integerGreaterThanZero();
|
.value(incomeFromPenaltyId).notNull().integerGreaterThanZero();
|
||||||
|
|
||||||
|
final Boolean isDormancyTrackingActive = this.fromApiJsonHelper.extractBooleanNamed(isDormancyTrackingActiveParamName, element);
|
||||||
|
if(null != isDormancyTrackingActive && isDormancyTrackingActive){
|
||||||
|
final Long escheatLiabilityId = this.fromApiJsonHelper.extractLongNamed(
|
||||||
|
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.ESCHEAT_LIABILITY.getValue(), element);
|
||||||
|
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.ESCHEAT_LIABILITY.getValue())
|
||||||
|
.value(escheatLiabilityId).notNull().integerGreaterThanZero();
|
||||||
|
}
|
||||||
|
|
||||||
if (!accountType.equals(DepositAccountType.RECURRING_DEPOSIT) && !accountType.equals(DepositAccountType.FIXED_DEPOSIT)) {
|
if (!accountType.equals(DepositAccountType.RECURRING_DEPOSIT) && !accountType.equals(DepositAccountType.FIXED_DEPOSIT)) {
|
||||||
final Long overdraftAccount = this.fromApiJsonHelper.extractLongNamed(
|
final Long overdraftAccount = this.fromApiJsonHelper.extractLongNamed(
|
||||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), element);
|
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), element);
|
||||||
|
|||||||
+2
@@ -228,6 +228,8 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
|||||||
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_DATA_PARAMS.LOSSES_WRITTEN_OFF.getValue(), gLAccountData);
|
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_DATA_PARAMS.LOSSES_WRITTEN_OFF.getValue(), gLAccountData);
|
||||||
} else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_INTEREST)) {
|
} else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_INTEREST)) {
|
||||||
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_DATA_PARAMS.INCOME_FROM_INTEREST.getValue(), gLAccountData);
|
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_DATA_PARAMS.INCOME_FROM_INTEREST.getValue(), gLAccountData);
|
||||||
|
} else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.ESCHEAT_LIABILITY)) {
|
||||||
|
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_DATA_PARAMS.ESCHEAT_LIABILITY.getValue(), gLAccountData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
@@ -19,6 +19,7 @@
|
|||||||
package org.apache.fineract.accounting.producttoaccountmapping.service;
|
package org.apache.fineract.accounting.producttoaccountmapping.service;
|
||||||
|
|
||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountingRuleParamName;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountingRuleParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.isDormancyTrackingActiveParamName;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -225,6 +226,13 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
|||||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), savingProductId,
|
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), savingProductId,
|
||||||
CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE.getValue());
|
CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE.getValue());
|
||||||
|
|
||||||
|
final Boolean isDormancyTrackingActive = this.fromApiJsonHelper.extractBooleanNamed(isDormancyTrackingActiveParamName, element);
|
||||||
|
if(null != isDormancyTrackingActive && isDormancyTrackingActive){
|
||||||
|
this.savingsProductToGLAccountMappingHelper.saveSavingsToLiabilityAccountMapping(element,
|
||||||
|
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.ESCHEAT_LIABILITY.getValue(), savingProductId,
|
||||||
|
CASH_ACCOUNTS_FOR_SAVINGS.ESCHEAT_LIABILITY.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
// advanced accounting mappings
|
// advanced accounting mappings
|
||||||
this.savingsProductToGLAccountMappingHelper.savePaymentChannelToFundSourceMappings(command, element, savingProductId, null);
|
this.savingsProductToGLAccountMappingHelper.savePaymentChannelToFundSourceMappings(command, element, savingProductId, null);
|
||||||
this.savingsProductToGLAccountMappingHelper.saveChargesToIncomeAccountMappings(command, element, savingProductId, null);
|
this.savingsProductToGLAccountMappingHelper.saveChargesToIncomeAccountMappings(command, element, savingProductId, null);
|
||||||
|
|||||||
+3
@@ -222,6 +222,9 @@ public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMa
|
|||||||
mergeSavingsToLiabilityAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(),
|
mergeSavingsToLiabilityAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(),
|
||||||
savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE.getValue(),
|
savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE.getValue(),
|
||||||
CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE.toString(), changes);
|
CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE.toString(), changes);
|
||||||
|
mergeSavingsToLiabilityAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.ESCHEAT_LIABILITY.getValue(),
|
||||||
|
savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.ESCHEAT_LIABILITY.getValue(),
|
||||||
|
CASH_ACCOUNTS_FOR_SAVINGS.ESCHEAT_LIABILITY.toString(), changes);
|
||||||
break;
|
break;
|
||||||
case ACCRUAL_PERIODIC:
|
case ACCRUAL_PERIODIC:
|
||||||
break;
|
break;
|
||||||
|
|||||||
+2
-1
@@ -39,7 +39,8 @@ public enum JobName {
|
|||||||
RECALCULATE_INTEREST_FOR_LOAN("Recalculate Interest For Loans"), //
|
RECALCULATE_INTEREST_FOR_LOAN("Recalculate Interest For Loans"), //
|
||||||
GENERATE_RD_SCEHDULE("Generate Mandatory Savings Schedule"), //
|
GENERATE_RD_SCEHDULE("Generate Mandatory Savings Schedule"), //
|
||||||
GENERATE_LOANLOSS_PROVISIONING("Generate Loan Loss Provisioning"), //
|
GENERATE_LOANLOSS_PROVISIONING("Generate Loan Loss Provisioning"), //
|
||||||
POST_DIVIDENTS_FOR_SHARES("Post Dividends For Shares");
|
POST_DIVIDENTS_FOR_SHARES("Post Dividends For Shares"),
|
||||||
|
UPDATE_SAVINGS_DORMANT_ACCOUNTS("Update Savings Dormant Accounts");
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
|||||||
+8
-1
@@ -24,6 +24,8 @@ import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
|||||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountApplicationTimelineData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountApplicationTimelineData;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData;
|
||||||
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountSubStatusEnumData;
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable data object for savings accounts.
|
* Immutable data object for savings accounts.
|
||||||
@@ -43,13 +45,16 @@ public class SavingsAccountSummaryData {
|
|||||||
//differentiate Individual, JLG or Group account
|
//differentiate Individual, JLG or Group account
|
||||||
private final EnumOptionData accountType;
|
private final EnumOptionData accountType;
|
||||||
private final SavingsAccountApplicationTimelineData timeline;
|
private final SavingsAccountApplicationTimelineData timeline;
|
||||||
|
private final SavingsAccountSubStatusEnumData subStatus;
|
||||||
|
private final LocalDate lastActiveTransactionDate;
|
||||||
|
|
||||||
//differentiate deposit accounts Savings, FD and RD accounts
|
//differentiate deposit accounts Savings, FD and RD accounts
|
||||||
private final EnumOptionData depositType;
|
private final EnumOptionData depositType;
|
||||||
|
|
||||||
public SavingsAccountSummaryData(final Long id, final String accountNo, final String externalId, final Long productId,
|
public SavingsAccountSummaryData(final Long id, final String accountNo, final String externalId, final Long productId,
|
||||||
final String productName, final String shortProductName, final SavingsAccountStatusEnumData status, final CurrencyData currency,
|
final String productName, final String shortProductName, final SavingsAccountStatusEnumData status, final CurrencyData currency,
|
||||||
final BigDecimal accountBalance, final EnumOptionData accountType, final SavingsAccountApplicationTimelineData timeline, final EnumOptionData depositType) {
|
final BigDecimal accountBalance, final EnumOptionData accountType, final SavingsAccountApplicationTimelineData timeline, final EnumOptionData depositType,
|
||||||
|
final SavingsAccountSubStatusEnumData subStatus, final LocalDate lastActiveTransactionDate) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.accountNo = accountNo;
|
this.accountNo = accountNo;
|
||||||
this.externalId = externalId;
|
this.externalId = externalId;
|
||||||
@@ -62,5 +67,7 @@ public class SavingsAccountSummaryData {
|
|||||||
this.accountType = accountType;
|
this.accountType = accountType;
|
||||||
this.timeline = timeline;
|
this.timeline = timeline;
|
||||||
this.depositType = depositType;
|
this.depositType = depositType;
|
||||||
|
this.subStatus = subStatus;
|
||||||
|
this.lastActiveTransactionDate = lastActiveTransactionDate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+13
-1
@@ -39,6 +39,7 @@ import org.apache.fineract.portfolio.loanaccount.data.LoanStatusEnumData;
|
|||||||
import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
|
import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountApplicationTimelineData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountApplicationTimelineData;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData;
|
||||||
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountSubStatusEnumData;
|
||||||
import org.apache.fineract.portfolio.savings.service.SavingsEnumerations;
|
import org.apache.fineract.portfolio.savings.service.SavingsEnumerations;
|
||||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountApplicationTimelineData;
|
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountApplicationTimelineData;
|
||||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountStatusEnumData;
|
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountStatusEnumData;
|
||||||
@@ -258,6 +259,13 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
|
|||||||
accountsSummary.append("avbu.username as activatedByUsername,");
|
accountsSummary.append("avbu.username as activatedByUsername,");
|
||||||
accountsSummary.append("avbu.firstname as activatedByFirstname, avbu.lastname as activatedByLastname,");
|
accountsSummary.append("avbu.firstname as activatedByFirstname, avbu.lastname as activatedByLastname,");
|
||||||
|
|
||||||
|
accountsSummary.append("sa.sub_status_enum as subStatusEnum, ");
|
||||||
|
accountsSummary.append("(select IFNULL(max(sat.transaction_date),sa.activatedon_date) ");
|
||||||
|
accountsSummary.append("from m_savings_account_transaction as sat ");
|
||||||
|
accountsSummary.append("where sat.is_reversed = 0 ");
|
||||||
|
accountsSummary.append("and sat.transaction_type_enum in (1,2) ");
|
||||||
|
accountsSummary.append("and sat.savings_account_id = sa.id) as lastActiveTransactionDate, ");
|
||||||
|
|
||||||
accountsSummary.append("sa.closedon_date as closedOnDate,");
|
accountsSummary.append("sa.closedon_date as closedOnDate,");
|
||||||
accountsSummary.append("cbu.username as closedByUsername,");
|
accountsSummary.append("cbu.username as closedByUsername,");
|
||||||
accountsSummary.append("cbu.firstname as closedByFirstname, cbu.lastname as closedByLastname,");
|
accountsSummary.append("cbu.firstname as closedByFirstname, cbu.lastname as closedByLastname,");
|
||||||
@@ -340,6 +348,10 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
|
|||||||
final String closedByUsername = rs.getString("closedByUsername");
|
final String closedByUsername = rs.getString("closedByUsername");
|
||||||
final String closedByFirstname = rs.getString("closedByFirstname");
|
final String closedByFirstname = rs.getString("closedByFirstname");
|
||||||
final String closedByLastname = rs.getString("closedByLastname");
|
final String closedByLastname = rs.getString("closedByLastname");
|
||||||
|
final Integer subStatusEnum = JdbcSupport.getInteger(rs, "subStatusEnum");
|
||||||
|
final SavingsAccountSubStatusEnumData subStatus = SavingsEnumerations.subStatus(subStatusEnum);
|
||||||
|
|
||||||
|
final LocalDate lastActiveTransactionDate = JdbcSupport.getLocalDate(rs, "lastActiveTransactionDate");
|
||||||
|
|
||||||
final SavingsAccountApplicationTimelineData timeline = new SavingsAccountApplicationTimelineData(submittedOnDate,
|
final SavingsAccountApplicationTimelineData timeline = new SavingsAccountApplicationTimelineData(submittedOnDate,
|
||||||
submittedByUsername, submittedByFirstname, submittedByLastname, rejectedOnDate, rejectedByUsername,
|
submittedByUsername, submittedByFirstname, submittedByLastname, rejectedOnDate, rejectedByUsername,
|
||||||
@@ -349,7 +361,7 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
|
|||||||
closedByLastname);
|
closedByLastname);
|
||||||
|
|
||||||
return new SavingsAccountSummaryData(id, accountNo, externalId, productId, productName, shortProductName, status, currency, accountBalance,
|
return new SavingsAccountSummaryData(id, accountNo, externalId, productId, productName, shortProductName, status, currency, accountBalance,
|
||||||
accountTypeData, timeline, depositTypeData);
|
accountTypeData, timeline, depositTypeData, subStatus, lastActiveTransactionDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -184,10 +184,10 @@ public class Charge extends AbstractPersistable<Long> {
|
|||||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.savings");
|
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.savings");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ChargeTimeType.fromInt(getChargeTimeType()).isWithdrawalFee()
|
if (!(ChargeTimeType.fromInt(getChargeTimeType()).isWithdrawalFee() || ChargeTimeType.fromInt(getChargeTimeType()).isSavingsNoActivityFee())
|
||||||
&& ChargeCalculationType.fromInt(getChargeCalculation()).isPercentageOfAmount()) {
|
&& ChargeCalculationType.fromInt(getChargeCalculation()).isPercentageOfAmount()) {
|
||||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||||
.failWithCodeNoParameterAddedToErrorCode("savings.charge.calculation.type.percentage.allowed.only.for.withdrawal");
|
.failWithCodeNoParameterAddedToErrorCode("savings.charge.calculation.type.percentage.allowed.only.for.withdrawal.or.NoActivity");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (isLoanCharge()) {
|
} else if (isLoanCharge()) {
|
||||||
@@ -401,10 +401,10 @@ public class Charge extends AbstractPersistable<Long> {
|
|||||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.savings");
|
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.savings");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ChargeTimeType.fromInt(getChargeTimeType()).isWithdrawalFee()
|
if (!(ChargeTimeType.fromInt(getChargeTimeType()).isWithdrawalFee() || ChargeTimeType.fromInt(getChargeTimeType()).isSavingsNoActivityFee())
|
||||||
&& ChargeCalculationType.fromInt(getChargeCalculation()).isPercentageOfAmount()) {
|
&& ChargeCalculationType.fromInt(getChargeCalculation()).isPercentageOfAmount()) {
|
||||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||||
.failWithCodeNoParameterAddedToErrorCode("charge.calculation.type.percentage.allowed.only.for.withdrawal");
|
.failWithCodeNoParameterAddedToErrorCode("charge.calculation.type.percentage.allowed.only.for.withdrawal.or.noactivity");
|
||||||
}
|
}
|
||||||
} else if (isClientCharge()) {
|
} else if (isClientCharge()) {
|
||||||
if (!isAllowedClientChargeCalculationType()) {
|
if (!isAllowedClientChargeCalculationType()) {
|
||||||
|
|||||||
+13
-3
@@ -35,7 +35,9 @@ public enum ChargeTimeType {
|
|||||||
// loan
|
// loan
|
||||||
SHAREACCOUNT_ACTIVATION(13, "chargeTimeType.activation"), // only for loan
|
SHAREACCOUNT_ACTIVATION(13, "chargeTimeType.activation"), // only for loan
|
||||||
SHARE_PURCHASE(14, "chargeTimeType.sharespurchase"),
|
SHARE_PURCHASE(14, "chargeTimeType.sharespurchase"),
|
||||||
SHARE_REDEEM(15, "chargeTimeType.sharesredeem");
|
SHARE_REDEEM(15, "chargeTimeType.sharesredeem"),
|
||||||
|
|
||||||
|
SAVINGS_NOACTIVITY_FEE(16,"chargeTimeType.savingsNoActivityFee");
|
||||||
|
|
||||||
private final Integer value;
|
private final Integer value;
|
||||||
private final String code;
|
private final String code;
|
||||||
@@ -67,7 +69,8 @@ public enum ChargeTimeType {
|
|||||||
public static Object[] validSavingsValues() {
|
public static Object[] validSavingsValues() {
|
||||||
return new Integer[] { ChargeTimeType.SPECIFIED_DUE_DATE.getValue(), ChargeTimeType.SAVINGS_ACTIVATION.getValue(),
|
return new Integer[] { ChargeTimeType.SPECIFIED_DUE_DATE.getValue(), ChargeTimeType.SAVINGS_ACTIVATION.getValue(),
|
||||||
ChargeTimeType.SAVINGS_CLOSURE.getValue(), ChargeTimeType.WITHDRAWAL_FEE.getValue(), ChargeTimeType.ANNUAL_FEE.getValue(),
|
ChargeTimeType.SAVINGS_CLOSURE.getValue(), ChargeTimeType.WITHDRAWAL_FEE.getValue(), ChargeTimeType.ANNUAL_FEE.getValue(),
|
||||||
ChargeTimeType.MONTHLY_FEE.getValue(), ChargeTimeType.OVERDRAFT_FEE.getValue(), ChargeTimeType.WEEKLY_FEE.getValue() };
|
ChargeTimeType.MONTHLY_FEE.getValue(), ChargeTimeType.OVERDRAFT_FEE.getValue(), ChargeTimeType.WEEKLY_FEE.getValue(),
|
||||||
|
ChargeTimeType.SAVINGS_NOACTIVITY_FEE.getValue()};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object[] validClientValues() {
|
public static Object[] validClientValues() {
|
||||||
@@ -127,6 +130,9 @@ public enum ChargeTimeType {
|
|||||||
case 15:
|
case 15:
|
||||||
chargeTimeType = SHARE_REDEEM;
|
chargeTimeType = SHARE_REDEEM;
|
||||||
break;
|
break;
|
||||||
|
case 16:
|
||||||
|
chargeTimeType = SAVINGS_NOACTIVITY_FEE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
chargeTimeType = INVALID;
|
chargeTimeType = INVALID;
|
||||||
break;
|
break;
|
||||||
@@ -155,6 +161,10 @@ public enum ChargeTimeType {
|
|||||||
return this.value.equals(ChargeTimeType.WITHDRAWAL_FEE.getValue());
|
return this.value.equals(ChargeTimeType.WITHDRAWAL_FEE.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSavingsNoActivityFee() {
|
||||||
|
return this.value.equals(ChargeTimeType.SAVINGS_NOACTIVITY_FEE.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isAnnualFee() {
|
public boolean isAnnualFee() {
|
||||||
return this.value.equals(ChargeTimeType.ANNUAL_FEE.getValue());
|
return this.value.equals(ChargeTimeType.ANNUAL_FEE.getValue());
|
||||||
}
|
}
|
||||||
@@ -185,7 +195,7 @@ public enum ChargeTimeType {
|
|||||||
|
|
||||||
public boolean isAllowedSavingsChargeTime() {
|
public boolean isAllowedSavingsChargeTime() {
|
||||||
return isOnSpecifiedDueDate() || isSavingsActivation() || isSavingsClosure() || isWithdrawalFee() || isAnnualFee()
|
return isOnSpecifiedDueDate() || isSavingsActivation() || isSavingsClosure() || isWithdrawalFee() || isAnnualFee()
|
||||||
|| isMonthlyFee() || isWeeklyFee() || isOverdraftFee();
|
|| isMonthlyFee() || isWeeklyFee() || isOverdraftFee() || isSavingsNoActivityFee();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOverdraftFee() {
|
public boolean isOverdraftFee() {
|
||||||
|
|||||||
+1
-1
@@ -102,7 +102,7 @@ public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownRead
|
|||||||
// chargeTimeType(ChargeTimeType.SAVINGS_CLOSURE),
|
// chargeTimeType(ChargeTimeType.SAVINGS_CLOSURE),
|
||||||
chargeTimeType(ChargeTimeType.WITHDRAWAL_FEE), chargeTimeType(ChargeTimeType.ANNUAL_FEE),
|
chargeTimeType(ChargeTimeType.WITHDRAWAL_FEE), chargeTimeType(ChargeTimeType.ANNUAL_FEE),
|
||||||
chargeTimeType(ChargeTimeType.MONTHLY_FEE), chargeTimeType(ChargeTimeType.WEEKLY_FEE),
|
chargeTimeType(ChargeTimeType.MONTHLY_FEE), chargeTimeType(ChargeTimeType.WEEKLY_FEE),
|
||||||
chargeTimeType(ChargeTimeType.OVERDRAFT_FEE));
|
chargeTimeType(ChargeTimeType.OVERDRAFT_FEE), chargeTimeType(ChargeTimeType.SAVINGS_NOACTIVITY_FEE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+4
@@ -91,6 +91,10 @@ public class ChargeEnumerations {
|
|||||||
case SHARE_REDEEM:
|
case SHARE_REDEEM:
|
||||||
optionData = new EnumOptionData(ChargeTimeType.SHARE_REDEEM.getValue().longValue(), ChargeTimeType.SHARE_REDEEM.getCode(), "Share Redeem") ;
|
optionData = new EnumOptionData(ChargeTimeType.SHARE_REDEEM.getValue().longValue(), ChargeTimeType.SHARE_REDEEM.getCode(), "Share Redeem") ;
|
||||||
break ;
|
break ;
|
||||||
|
case SAVINGS_NOACTIVITY_FEE:
|
||||||
|
optionData = new EnumOptionData(ChargeTimeType.SAVINGS_NOACTIVITY_FEE.getValue().longValue(), ChargeTimeType.SAVINGS_NOACTIVITY_FEE.getCode(),
|
||||||
|
"Saving No Activity Fee");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
optionData = new EnumOptionData(ChargeTimeType.INVALID.getValue().longValue(), ChargeTimeType.INVALID.getCode(), "Invalid");
|
optionData = new EnumOptionData(ChargeTimeType.INVALID.getValue().longValue(), ChargeTimeType.INVALID.getCode(), "Invalid");
|
||||||
break;
|
break;
|
||||||
|
|||||||
+10
-2
@@ -40,7 +40,8 @@ public enum SavingsAccountTransactionType {
|
|||||||
WITHDRAW_TRANSFER(14, "savingsAccountTransactionType.withdrawTransfer"), //
|
WITHDRAW_TRANSFER(14, "savingsAccountTransactionType.withdrawTransfer"), //
|
||||||
REJECT_TRANSFER(15, "savingsAccountTransactionType.rejectTransfer"), WRITTEN_OFF(16, "savingsAccountTransactionType.writtenoff"), //
|
REJECT_TRANSFER(15, "savingsAccountTransactionType.rejectTransfer"), WRITTEN_OFF(16, "savingsAccountTransactionType.writtenoff"), //
|
||||||
OVERDRAFT_INTEREST(17, "savingsAccountTransactionType.overdraftInterest"), //
|
OVERDRAFT_INTEREST(17, "savingsAccountTransactionType.overdraftInterest"), //
|
||||||
WITHHOLD_TAX(18, "savingsAccountTransactionType.withholdTax");
|
WITHHOLD_TAX(18, "savingsAccountTransactionType.withholdTax"),
|
||||||
|
ESCHEAT(19, "savingsAccountTransactionType.escheat");
|
||||||
|
|
||||||
private final Integer value;
|
private final Integer value;
|
||||||
private final String code;
|
private final String code;
|
||||||
@@ -109,6 +110,9 @@ public enum SavingsAccountTransactionType {
|
|||||||
case 18:
|
case 18:
|
||||||
savingsAccountTransactionType = SavingsAccountTransactionType.WITHHOLD_TAX;
|
savingsAccountTransactionType = SavingsAccountTransactionType.WITHHOLD_TAX;
|
||||||
break;
|
break;
|
||||||
|
case 19:
|
||||||
|
savingsAccountTransactionType = SavingsAccountTransactionType.ESCHEAT;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return savingsAccountTransactionType;
|
return savingsAccountTransactionType;
|
||||||
}
|
}
|
||||||
@@ -177,8 +181,12 @@ public enum SavingsAccountTransactionType {
|
|||||||
return this.value.equals(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue());
|
return this.value.equals(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEscheat() {
|
||||||
|
return this.value.equals(SavingsAccountTransactionType.ESCHEAT.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isDebit() {
|
public boolean isDebit() {
|
||||||
return isWithdrawal() || isWithdrawalFee() || isAnnualFee() || isPayCharge() || isIncomeFromInterest() || isWithHoldTax();
|
return isWithdrawal() || isWithdrawalFee() || isAnnualFee() || isPayCharge() || isIncomeFromInterest() || isWithHoldTax() || isEscheat();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCredit() {
|
public boolean isCredit() {
|
||||||
|
|||||||
+13
-2
@@ -161,6 +161,13 @@ public class SavingsApiConstants {
|
|||||||
public static final String onHoldTransactionDateParamName = "transactionDate";
|
public static final String onHoldTransactionDateParamName = "transactionDate";
|
||||||
public static final String onHoldReversedParamName = "reversed";
|
public static final String onHoldReversedParamName = "reversed";
|
||||||
|
|
||||||
|
// Savings Dormancy
|
||||||
|
public static final String isDormancyTrackingActiveParamName = "isDormancyTrackingActive";
|
||||||
|
public static final String daysToInactiveParamName = "daysToInactive";
|
||||||
|
public static final String daysToDormancyParamName = "daysToDormancy";
|
||||||
|
public static final String daysToEscheatParamName = "daysToEscheat";
|
||||||
|
|
||||||
|
|
||||||
public static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
|
public static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
|
||||||
monthDayFormatParamName, nameParamName, shortNameParamName, descriptionParamName, currencyCodeParamName,
|
monthDayFormatParamName, nameParamName, shortNameParamName, descriptionParamName, currencyCodeParamName,
|
||||||
digitsAfterDecimalParamName, inMultiplesOfParamName, nominalAnnualInterestRateParamName,
|
digitsAfterDecimalParamName, inMultiplesOfParamName, nominalAnnualInterestRateParamName,
|
||||||
@@ -178,7 +185,10 @@ public class SavingsApiConstants {
|
|||||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PENALTY_INCOME_ACCOUNT_MAPPING.getValue(),
|
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PENALTY_INCOME_ACCOUNT_MAPPING.getValue(),
|
||||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
|
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
|
||||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),
|
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),
|
||||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(), allowOverdraftParamName, overdraftLimitParamName,
|
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(),
|
||||||
|
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.ESCHEAT_LIABILITY.getValue(),
|
||||||
|
isDormancyTrackingActiveParamName, daysToDormancyParamName, daysToInactiveParamName, daysToEscheatParamName,
|
||||||
|
allowOverdraftParamName, overdraftLimitParamName,
|
||||||
nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName, minRequiredBalanceParamName,
|
nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName, minRequiredBalanceParamName,
|
||||||
enforceMinRequiredBalanceParamName, minBalanceForInterestCalculationParamName, withHoldTaxParamName, taxGroupIdParamName));
|
enforceMinRequiredBalanceParamName, minBalanceForInterestCalculationParamName, withHoldTaxParamName, taxGroupIdParamName));
|
||||||
|
|
||||||
@@ -196,7 +206,8 @@ public class SavingsApiConstants {
|
|||||||
"interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions", "interestCalculationTypeOptions",
|
"interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions", "interestCalculationTypeOptions",
|
||||||
"interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions",
|
"interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions",
|
||||||
nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName, withHoldTaxParamName,
|
nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName, withHoldTaxParamName,
|
||||||
taxGroupIdParamName));
|
taxGroupIdParamName, isDormancyTrackingActiveParamName, daysToInactiveParamName, daysToDormancyParamName,
|
||||||
|
daysToInactiveParamName));
|
||||||
|
|
||||||
public static final Set<String> SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
|
public static final Set<String> SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
|
||||||
dateFormatParamName, monthDayFormatParamName, staffIdParamName, accountNoParamName, externalIdParamName, clientIdParamName,
|
dateFormatParamName, monthDayFormatParamName, staffIdParamName, accountNoParamName, externalIdParamName, clientIdParamName,
|
||||||
|
|||||||
+119
-77
@@ -29,6 +29,7 @@ import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
|||||||
import org.apache.fineract.organisation.staff.data.StaffData;
|
import org.apache.fineract.organisation.staff.data.StaffData;
|
||||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||||
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable data object representing a savings account.
|
* Immutable data object representing a savings account.
|
||||||
@@ -48,6 +49,7 @@ public class SavingsAccountData {
|
|||||||
private final Long fieldOfficerId;
|
private final Long fieldOfficerId;
|
||||||
private final String fieldOfficerName;
|
private final String fieldOfficerName;
|
||||||
private final SavingsAccountStatusEnumData status;
|
private final SavingsAccountStatusEnumData status;
|
||||||
|
private final SavingsAccountSubStatusEnumData subStatus;
|
||||||
private final SavingsAccountApplicationTimelineData timeline;
|
private final SavingsAccountApplicationTimelineData timeline;
|
||||||
private final CurrencyData currency;
|
private final CurrencyData currency;
|
||||||
private final BigDecimal nominalAnnualInterestRate;
|
private final BigDecimal nominalAnnualInterestRate;
|
||||||
@@ -67,6 +69,11 @@ public class SavingsAccountData {
|
|||||||
private final BigDecimal onHoldFunds;
|
private final BigDecimal onHoldFunds;
|
||||||
private final boolean withHoldTax;
|
private final boolean withHoldTax;
|
||||||
private final TaxGroupData taxGroup;
|
private final TaxGroupData taxGroup;
|
||||||
|
private final LocalDate lastActiveTransactionDate;
|
||||||
|
private final boolean isDormancyTrackingActive;
|
||||||
|
private final Integer daysToInactive;
|
||||||
|
private final Integer daysToDormancy;
|
||||||
|
private final Integer daysToEscheat;
|
||||||
|
|
||||||
// associations
|
// associations
|
||||||
private final SavingsAccountSummaryData summary;
|
private final SavingsAccountSummaryData summary;
|
||||||
@@ -96,16 +103,18 @@ public class SavingsAccountData {
|
|||||||
public static SavingsAccountData instance(final Long id, final String accountNo, final EnumOptionData depositType,
|
public static SavingsAccountData instance(final Long id, final String accountNo, final EnumOptionData depositType,
|
||||||
final String externalId, final Long groupId, final String groupName, final Long clientId, final String clientName,
|
final String externalId, final Long groupId, final String groupName, final Long clientId, final String clientName,
|
||||||
final Long productId, final String productName, final Long fieldOfficerId, final String fieldOfficerName,
|
final Long productId, final String productName, final Long fieldOfficerId, final String fieldOfficerName,
|
||||||
final SavingsAccountStatusEnumData status, final SavingsAccountApplicationTimelineData timeline, final CurrencyData currency,
|
final SavingsAccountStatusEnumData status, SavingsAccountSubStatusEnumData subStatus, final SavingsAccountApplicationTimelineData timeline,
|
||||||
final BigDecimal interestRate, final EnumOptionData interestCompoundingPeriodType,
|
final CurrencyData currency, final BigDecimal interestRate,
|
||||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
final EnumOptionData interestCompoundingPeriodType, final EnumOptionData interestPostingPeriodType,
|
||||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
|
||||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers,
|
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType,
|
||||||
final SavingsAccountSummaryData summary, final boolean allowOverdraft, final BigDecimal overdraftLimit,
|
final boolean withdrawalFeeForTransfers, final SavingsAccountSummaryData summary, final boolean allowOverdraft,
|
||||||
final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance,
|
final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance,
|
||||||
final BigDecimal minBalanceForInterestCalculation, final BigDecimal onHoldFunds,
|
final boolean enforceMinRequiredBalance, final BigDecimal minBalanceForInterestCalculation,
|
||||||
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation,
|
final BigDecimal onHoldFunds, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||||
final boolean withHoldTax, final TaxGroupData taxGroup) {
|
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroupData taxGroup,
|
||||||
|
final LocalDate lastActiveTransactionDate, final boolean isDormancyTrackingActive, final Integer daysToInactive,
|
||||||
|
final Integer daysToDormancy, final Integer daysToEscheat) {
|
||||||
|
|
||||||
final Collection<SavingsProductData> productOptions = null;
|
final Collection<SavingsProductData> productOptions = null;
|
||||||
final Collection<StaffData> fieldOfficerOptions = null;
|
final Collection<StaffData> fieldOfficerOptions = null;
|
||||||
@@ -121,14 +130,15 @@ public class SavingsAccountData {
|
|||||||
final Collection<ChargeData> chargeOptions = null;
|
final Collection<ChargeData> chargeOptions = null;
|
||||||
|
|
||||||
return new SavingsAccountData(id, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
return new SavingsAccountData(id, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
||||||
productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, interestRate, interestCompoundingPeriodType,
|
productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline, currency, interestRate,
|
||||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions,
|
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions,
|
||||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions,
|
||||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||||
withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance,
|
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
||||||
enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft,
|
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
||||||
minOverdraftForInterestCalculation, withHoldTax, taxGroup);
|
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
||||||
|
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData lookup(final Long accountId, final String accountNo, final EnumOptionData depositType) {
|
public static SavingsAccountData lookup(final Long accountId, final String accountNo, final EnumOptionData depositType) {
|
||||||
@@ -184,16 +194,23 @@ public class SavingsAccountData {
|
|||||||
final Collection<ChargeData> chargeOptions = null;
|
final Collection<ChargeData> chargeOptions = null;
|
||||||
final boolean withHoldTax = false;
|
final boolean withHoldTax = false;
|
||||||
final TaxGroupData taxGroup = null;
|
final TaxGroupData taxGroup = null;
|
||||||
|
final SavingsAccountSubStatusEnumData subStatus = null;
|
||||||
|
final LocalDate lastActiveTransactionDate = null;
|
||||||
|
final boolean isDormancyTrackingActive = false;
|
||||||
|
final Integer daysToInactive = null;
|
||||||
|
final Integer daysToDormancy = null;
|
||||||
|
final Integer daysToEscheat = null;
|
||||||
|
|
||||||
return new SavingsAccountData(accountId, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
return new SavingsAccountData(accountId, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
||||||
productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType,
|
productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline, currency, nominalAnnualInterestRate,
|
||||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
interestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions,
|
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions,
|
||||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions,
|
||||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||||
withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance,
|
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
||||||
enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft,
|
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
||||||
minOverdraftForInterestCalculation, withHoldTax, taxGroup);
|
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
||||||
|
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData lookupWithProductDetails(final Long accountId, final String accountNo,
|
public static SavingsAccountData lookupWithProductDetails(final Long accountId, final String accountNo,
|
||||||
@@ -247,16 +264,23 @@ public class SavingsAccountData {
|
|||||||
final Collection<ChargeData> chargeOptions = null;
|
final Collection<ChargeData> chargeOptions = null;
|
||||||
final boolean withHoldTax = false;
|
final boolean withHoldTax = false;
|
||||||
final TaxGroupData taxGroup = null;
|
final TaxGroupData taxGroup = null;
|
||||||
|
final SavingsAccountSubStatusEnumData subStatus = null;
|
||||||
|
final LocalDate lastActiveTransactionDate = null;
|
||||||
|
final boolean isDormancyTrackingActive = false;
|
||||||
|
final Integer daysToInactive = null;
|
||||||
|
final Integer daysToDormancy = null;
|
||||||
|
final Integer daysToEscheat = null;
|
||||||
|
|
||||||
return new SavingsAccountData(accountId, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
return new SavingsAccountData(accountId, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
||||||
productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType,
|
productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline, currency, nominalAnnualInterestRate,
|
||||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
interestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions,
|
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions,
|
||||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions,
|
||||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||||
withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance,
|
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
||||||
enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft,
|
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
||||||
minOverdraftForInterestCalculation, withHoldTax, taxGroup);
|
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
||||||
|
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account, final SavingsAccountData template,
|
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account, final SavingsAccountData template,
|
||||||
@@ -280,17 +304,19 @@ public class SavingsAccountData {
|
|||||||
|
|
||||||
return new SavingsAccountData(account.id, account.accountNo, account.depositType, account.externalId, account.groupId,
|
return new SavingsAccountData(account.id, account.accountNo, account.depositType, account.externalId, account.groupId,
|
||||||
account.groupName, account.clientId, account.clientName, account.savingsProductId, account.savingsProductName,
|
account.groupName, account.clientId, account.clientName, account.savingsProductId, account.savingsProductName,
|
||||||
account.fieldOfficerId, account.fieldOfficerName, account.status, account.timeline, account.currency,
|
account.fieldOfficerId, account.fieldOfficerName, account.status, account.subStatus, account.timeline,
|
||||||
account.nominalAnnualInterestRate, account.interestCompoundingPeriodType, account.interestPostingPeriodType,
|
account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType,
|
||||||
account.interestCalculationType, account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance,
|
account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType,
|
||||||
account.lockinPeriodFrequency, account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary,
|
account.minRequiredOpeningBalance, account.lockinPeriodFrequency, account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers,
|
||||||
transactions, template.productOptions, template.fieldOfficerOptions, template.interestCompoundingPeriodTypeOptions,
|
account.summary, transactions, template.productOptions, template.fieldOfficerOptions,
|
||||||
template.interestPostingPeriodTypeOptions, template.interestCalculationTypeOptions,
|
template.interestCompoundingPeriodTypeOptions, template.interestPostingPeriodTypeOptions,
|
||||||
template.interestCalculationDaysInYearTypeOptions, template.lockinPeriodFrequencyTypeOptions,
|
template.interestCalculationTypeOptions, template.interestCalculationDaysInYearTypeOptions,
|
||||||
template.withdrawalFeeTypeOptions, charges, template.chargeOptions, account.allowOverdraft, account.overdraftLimit,
|
template.lockinPeriodFrequencyTypeOptions, template.withdrawalFeeTypeOptions, charges, template.chargeOptions, account.allowOverdraft,
|
||||||
account.minRequiredBalance, account.enforceMinRequiredBalance, account.minBalanceForInterestCalculation,
|
account.overdraftLimit, account.minRequiredBalance, account.enforceMinRequiredBalance,
|
||||||
account.onHoldFunds, account.nominalAnnualInterestRateOverdraft, account.minOverdraftForInterestCalculation,
|
account.minBalanceForInterestCalculation, account.onHoldFunds, account.nominalAnnualInterestRateOverdraft,
|
||||||
account.withHoldTax, account.taxGroup);
|
account.minOverdraftForInterestCalculation, account.withHoldTax, account.taxGroup,
|
||||||
|
account.lastActiveTransactionDate, account.isDormancyTrackingActive, account.daysToInactive,
|
||||||
|
account.daysToDormancy, account.daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
||||||
@@ -305,16 +331,17 @@ public class SavingsAccountData {
|
|||||||
|
|
||||||
return new SavingsAccountData(account.id, account.accountNo, account.depositType, account.externalId, account.groupId,
|
return new SavingsAccountData(account.id, account.accountNo, account.depositType, account.externalId, account.groupId,
|
||||||
account.groupName, account.clientId, account.clientName, account.savingsProductId, account.savingsProductName,
|
account.groupName, account.clientId, account.clientName, account.savingsProductId, account.savingsProductName,
|
||||||
account.fieldOfficerId, account.fieldOfficerName, account.status, account.timeline, account.currency,
|
account.fieldOfficerId, account.fieldOfficerName, account.status, account.subStatus, account.timeline,
|
||||||
account.nominalAnnualInterestRate, account.interestCompoundingPeriodType, account.interestPostingPeriodType,
|
account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType,
|
||||||
account.interestCalculationType, account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance,
|
account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType,
|
||||||
account.lockinPeriodFrequency, account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary,
|
account.minRequiredOpeningBalance, account.lockinPeriodFrequency, account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers,
|
||||||
transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
account.summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions,
|
||||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||||
withdrawalFeeTypeOptions, charges, chargeOptions, account.allowOverdraft, account.overdraftLimit,
|
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, account.allowOverdraft,
|
||||||
account.minRequiredBalance, account.enforceMinRequiredBalance, account.minBalanceForInterestCalculation,
|
account.overdraftLimit, account.minRequiredBalance, account.enforceMinRequiredBalance,
|
||||||
account.onHoldFunds, account.nominalAnnualInterestRateOverdraft, account.minOverdraftForInterestCalculation,
|
account.minBalanceForInterestCalculation, account.onHoldFunds, account.nominalAnnualInterestRateOverdraft,
|
||||||
account.withHoldTax, account.taxGroup);
|
account.minOverdraftForInterestCalculation, account.withHoldTax, account.taxGroup, account.lastActiveTransactionDate,
|
||||||
|
account.isDormancyTrackingActive, account.daysToInactive, account.daysToDormancy, account.daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
||||||
@@ -370,38 +397,47 @@ public class SavingsAccountData {
|
|||||||
|
|
||||||
final Collection<SavingsAccountChargeData> charges = null;
|
final Collection<SavingsAccountChargeData> charges = null;
|
||||||
final Collection<ChargeData> chargeOptions = null;
|
final Collection<ChargeData> chargeOptions = null;
|
||||||
|
final SavingsAccountSubStatusEnumData subStatus = null;
|
||||||
|
final LocalDate lastActiveTransactionDate = null;
|
||||||
|
final boolean isDormancyTrackingActive = false;
|
||||||
|
final Integer daysToInactive = null;
|
||||||
|
final Integer daysToDormancy = null;
|
||||||
|
final Integer daysToEscheat = null;
|
||||||
|
|
||||||
return new SavingsAccountData(id, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
return new SavingsAccountData(id, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
||||||
productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType,
|
productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline, currency, nominalAnnualInterestRate,
|
||||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
interestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions,
|
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions,
|
||||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions,
|
||||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||||
withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance,
|
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit,
|
||||||
enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft,
|
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, onHoldFunds,
|
||||||
minOverdraftForInterestCalculation, withHoldTax, taxGroup);
|
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
||||||
|
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SavingsAccountData(final Long id, final String accountNo, final EnumOptionData depositType, final String externalId,
|
private SavingsAccountData(final Long id, final String accountNo, final EnumOptionData depositType, final String externalId,
|
||||||
final Long groupId, final String groupName, final Long clientId, final String clientName, final Long productId,
|
final Long groupId, final String groupName, final Long clientId, final String clientName, final Long productId,
|
||||||
final String productName, final Long fieldofficerId, final String fieldofficerName, final SavingsAccountStatusEnumData status,
|
final String productName, final Long fieldofficerId, final String fieldofficerName, final SavingsAccountStatusEnumData status,
|
||||||
final SavingsAccountApplicationTimelineData timeline, final CurrencyData currency, final BigDecimal nominalAnnualInterestRate,
|
final SavingsAccountSubStatusEnumData subStatus, final SavingsAccountApplicationTimelineData timeline, final CurrencyData currency,
|
||||||
final EnumOptionData interestPeriodType, final EnumOptionData interestPostingPeriodType,
|
final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestPeriodType,
|
||||||
final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
|
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||||
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
|
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||||
final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers,
|
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType,
|
||||||
final SavingsAccountSummaryData summary, final Collection<SavingsAccountTransactionData> transactions,
|
final boolean withdrawalFeeForTransfers, final SavingsAccountSummaryData summary,
|
||||||
final Collection<SavingsProductData> productOptions, final Collection<StaffData> fieldOfficerOptions,
|
final Collection<SavingsAccountTransactionData> transactions, final Collection<SavingsProductData> productOptions,
|
||||||
|
final Collection<StaffData> fieldOfficerOptions,
|
||||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||||
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
||||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions, final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions,
|
||||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions,
|
final Collection<EnumOptionData> withdrawalFeeTypeOptions, final Collection<SavingsAccountChargeData> charges, final Collection<ChargeData> chargeOptions,
|
||||||
final Collection<SavingsAccountChargeData> charges, final Collection<ChargeData> chargeOptions, final boolean allowOverdraft,
|
final boolean allowOverdraft, final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance,
|
||||||
final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance,
|
final boolean enforceMinRequiredBalance, final BigDecimal minBalanceForInterestCalculation,
|
||||||
final BigDecimal minBalanceForInterestCalculation, final BigDecimal onHoldFunds,
|
final BigDecimal onHoldFunds, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||||
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation,
|
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroupData taxGroup,
|
||||||
final boolean withHoldTax, final TaxGroupData taxGroup) {
|
final LocalDate lastActiveTransactionDate, final boolean isDormancyTrackingActive, final Integer daysToInactive,
|
||||||
|
final Integer daysToDormancy, final Integer daysToEscheat) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.accountNo = accountNo;
|
this.accountNo = accountNo;
|
||||||
this.depositType = depositType;
|
this.depositType = depositType;
|
||||||
@@ -415,6 +451,7 @@ public class SavingsAccountData {
|
|||||||
this.fieldOfficerId = fieldofficerId;
|
this.fieldOfficerId = fieldofficerId;
|
||||||
this.fieldOfficerName = fieldofficerName;
|
this.fieldOfficerName = fieldofficerName;
|
||||||
this.status = status;
|
this.status = status;
|
||||||
|
this.subStatus = subStatus;
|
||||||
this.timeline = timeline;
|
this.timeline = timeline;
|
||||||
this.currency = currency;
|
this.currency = currency;
|
||||||
this.nominalAnnualInterestRate = nominalAnnualInterestRate;
|
this.nominalAnnualInterestRate = nominalAnnualInterestRate;
|
||||||
@@ -461,6 +498,11 @@ public class SavingsAccountData {
|
|||||||
this.onHoldFunds = onHoldFunds;
|
this.onHoldFunds = onHoldFunds;
|
||||||
this.withHoldTax = withHoldTax;
|
this.withHoldTax = withHoldTax;
|
||||||
this.taxGroup = taxGroup;
|
this.taxGroup = taxGroup;
|
||||||
|
this.lastActiveTransactionDate = lastActiveTransactionDate;
|
||||||
|
this.isDormancyTrackingActive = isDormancyTrackingActive;
|
||||||
|
this.daysToInactive = daysToInactive;
|
||||||
|
this.daysToDormancy = daysToDormancy;
|
||||||
|
this.daysToEscheat = daysToEscheat;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SavingsAccountChargeData getWithdrawalFee() {
|
private SavingsAccountChargeData getWithdrawalFee() {
|
||||||
|
|||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.savings.data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immutable data object represent savings account sub-status enumerations.
|
||||||
|
*/
|
||||||
|
public class SavingsAccountSubStatusEnumData {
|
||||||
|
|
||||||
|
private final Long id;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final String code;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final String value;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final boolean none;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final boolean inactive;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final boolean dormant;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final boolean escheat;
|
||||||
|
|
||||||
|
public SavingsAccountSubStatusEnumData(final Long id, final String code, final String value, final boolean none,
|
||||||
|
final boolean inactive, final boolean dormant, final boolean escheat) {
|
||||||
|
this.id = id;
|
||||||
|
this.code = code;
|
||||||
|
this.value = value;
|
||||||
|
this.none = none;
|
||||||
|
this.inactive = inactive;
|
||||||
|
this.dormant = dormant;
|
||||||
|
this.escheat = escheat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long id() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -43,6 +43,7 @@ public class SavingsAccountTransactionEnumData {
|
|||||||
private final boolean writtenoff;
|
private final boolean writtenoff;
|
||||||
private final boolean overdraftFee = true;
|
private final boolean overdraftFee = true;
|
||||||
private final boolean withholdTax;
|
private final boolean withholdTax;
|
||||||
|
private final boolean escheat;
|
||||||
|
|
||||||
public SavingsAccountTransactionEnumData(final Long id, final String code, final String value) {
|
public SavingsAccountTransactionEnumData(final Long id, final String code, final String value) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@@ -62,6 +63,7 @@ public class SavingsAccountTransactionEnumData {
|
|||||||
this.writtenoff = Long.valueOf(SavingsAccountTransactionType.WRITTEN_OFF.getValue()).equals(this.id);
|
this.writtenoff = Long.valueOf(SavingsAccountTransactionType.WRITTEN_OFF.getValue()).equals(this.id);
|
||||||
this.overdraftInterest = Long.valueOf(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue()).equals(this.id);
|
this.overdraftInterest = Long.valueOf(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue()).equals(this.id);
|
||||||
this.withholdTax = Long.valueOf(SavingsAccountTransactionType.WITHHOLD_TAX.getValue()).equals(this.id);
|
this.withholdTax = Long.valueOf(SavingsAccountTransactionType.WITHHOLD_TAX.getValue()).equals(this.id);
|
||||||
|
this.escheat = Long.valueOf(SavingsAccountTransactionType.ESCHEAT.getValue()).equals(this.id);
|
||||||
// this.overdraftFee =
|
// this.overdraftFee =
|
||||||
// Long.valueOf(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue()).equals(this.id);
|
// Long.valueOf(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue()).equals(this.id);
|
||||||
}
|
}
|
||||||
@@ -134,4 +136,8 @@ public class SavingsAccountTransactionEnumData {
|
|||||||
return this.dividendPayout;
|
return this.dividendPayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEscheat() {
|
||||||
|
return this.escheat;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+29
-8
@@ -86,6 +86,10 @@ public class SavingsProductData {
|
|||||||
private final Collection<ChargeData> chargeOptions;
|
private final Collection<ChargeData> chargeOptions;
|
||||||
private final Collection<ChargeData> penaltyOptions;
|
private final Collection<ChargeData> penaltyOptions;
|
||||||
private final Collection<TaxGroupData> taxGroupOptions;
|
private final Collection<TaxGroupData> taxGroupOptions;
|
||||||
|
private final Boolean isDormancyTrackingActive;
|
||||||
|
private final Long daysToInactive;
|
||||||
|
private final Long daysToDormancy;
|
||||||
|
private final Long daysToEscheat;
|
||||||
|
|
||||||
public static SavingsProductData template(final CurrencyData currency, final EnumOptionData interestCompoundingPeriodType,
|
public static SavingsProductData template(final CurrencyData currency, final EnumOptionData interestCompoundingPeriodType,
|
||||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||||
@@ -122,6 +126,10 @@ public class SavingsProductData {
|
|||||||
final BigDecimal minOverdraftForInterestCalculation = null;
|
final BigDecimal minOverdraftForInterestCalculation = null;
|
||||||
final boolean withHoldTax = false;
|
final boolean withHoldTax = false;
|
||||||
final TaxGroupData taxGroup = null;
|
final TaxGroupData taxGroup = null;
|
||||||
|
final Boolean isDormancyTrackingActive = false;
|
||||||
|
final Long daysToInactive = null;
|
||||||
|
final Long daysToDormancy = null;
|
||||||
|
final Long daysToEscheat = null;
|
||||||
|
|
||||||
return new SavingsProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
return new SavingsProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||||
@@ -132,7 +140,7 @@ public class SavingsProductData {
|
|||||||
accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||||
penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
||||||
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
||||||
taxGroup, taxGroupOptions);
|
taxGroup, taxGroupOptions, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsProductData withCharges(final SavingsProductData product, final Collection<ChargeData> charges) {
|
public static SavingsProductData withCharges(final SavingsProductData product, final Collection<ChargeData> charges) {
|
||||||
@@ -148,7 +156,8 @@ public class SavingsProductData {
|
|||||||
product.feeToIncomeAccountMappings, product.penaltyToIncomeAccountMappings, product.allowOverdraft, product.overdraftLimit,
|
product.feeToIncomeAccountMappings, product.penaltyToIncomeAccountMappings, product.allowOverdraft, product.overdraftLimit,
|
||||||
product.minRequiredBalance, product.enforceMinRequiredBalance, product.minBalanceForInterestCalculation,
|
product.minRequiredBalance, product.enforceMinRequiredBalance, product.minBalanceForInterestCalculation,
|
||||||
product.nominalAnnualInterestRateOverdraft, product.minOverdraftForInterestCalculation, product.withHoldTax,
|
product.nominalAnnualInterestRateOverdraft, product.minOverdraftForInterestCalculation, product.withHoldTax,
|
||||||
product.taxGroup, product.taxGroupOptions);
|
product.taxGroup, product.taxGroupOptions, product.isDormancyTrackingActive, product.daysToInactive,
|
||||||
|
product.daysToDormancy, product.daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -181,7 +190,8 @@ public class SavingsProductData {
|
|||||||
existingProduct.feeToIncomeAccountMappings, existingProduct.penaltyToIncomeAccountMappings, existingProduct.allowOverdraft,
|
existingProduct.feeToIncomeAccountMappings, existingProduct.penaltyToIncomeAccountMappings, existingProduct.allowOverdraft,
|
||||||
existingProduct.overdraftLimit, existingProduct.minRequiredBalance, existingProduct.enforceMinRequiredBalance,
|
existingProduct.overdraftLimit, existingProduct.minRequiredBalance, existingProduct.enforceMinRequiredBalance,
|
||||||
existingProduct.minBalanceForInterestCalculation, existingProduct.nominalAnnualInterestRateOverdraft,
|
existingProduct.minBalanceForInterestCalculation, existingProduct.nominalAnnualInterestRateOverdraft,
|
||||||
existingProduct.minOverdraftForInterestCalculation, existingProduct.withHoldTax, existingProduct.taxGroup, taxGroupOptions);
|
existingProduct.minOverdraftForInterestCalculation, existingProduct.withHoldTax, existingProduct.taxGroup, taxGroupOptions,
|
||||||
|
existingProduct.isDormancyTrackingActive, existingProduct.daysToInactive, existingProduct.daysToDormancy, existingProduct.daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsProductData withAccountingDetails(final SavingsProductData existingProduct,
|
public static SavingsProductData withAccountingDetails(final SavingsProductData existingProduct,
|
||||||
@@ -217,7 +227,8 @@ public class SavingsProductData {
|
|||||||
existingProduct.minRequiredBalance, existingProduct.enforceMinRequiredBalance,
|
existingProduct.minRequiredBalance, existingProduct.enforceMinRequiredBalance,
|
||||||
existingProduct.minBalanceForInterestCalculation, existingProduct.nominalAnnualInterestRateOverdraft,
|
existingProduct.minBalanceForInterestCalculation, existingProduct.nominalAnnualInterestRateOverdraft,
|
||||||
existingProduct.minOverdraftForInterestCalculation, existingProduct.withHoldTax, existingProduct.taxGroup,
|
existingProduct.minOverdraftForInterestCalculation, existingProduct.withHoldTax, existingProduct.taxGroup,
|
||||||
existingProduct.taxGroupOptions);
|
existingProduct.taxGroupOptions, existingProduct.isDormancyTrackingActive, existingProduct.daysToInactive,
|
||||||
|
existingProduct.daysToDormancy, existingProduct.daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsProductData instance(final Long id, final String name, final String shortName, final String description,
|
public static SavingsProductData instance(final Long id, final String name, final String shortName, final String description,
|
||||||
@@ -228,7 +239,8 @@ public class SavingsProductData {
|
|||||||
final EnumOptionData accountingType, final boolean allowOverdraft, final BigDecimal overdraftLimit,
|
final EnumOptionData accountingType, final boolean allowOverdraft, final BigDecimal overdraftLimit,
|
||||||
final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance,
|
final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance,
|
||||||
final BigDecimal minBalanceForInterestCalculation, final BigDecimal nominalAnnualInterestRateOverdraft,
|
final BigDecimal minBalanceForInterestCalculation, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||||
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroupData taxGroup) {
|
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroupData taxGroup,
|
||||||
|
final Boolean isDormancyTrackingActive, final Long daysToInactive, final Long daysToDormancy, final Long daysToEscheat) {
|
||||||
|
|
||||||
final Map<String, Object> accountingMappings = null;
|
final Map<String, Object> accountingMappings = null;
|
||||||
final Collection<PaymentTypeToGLAccountMapper> paymentChannelToFundSourceMappings = null;
|
final Collection<PaymentTypeToGLAccountMapper> paymentChannelToFundSourceMappings = null;
|
||||||
@@ -259,7 +271,7 @@ public class SavingsProductData {
|
|||||||
accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||||
penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
||||||
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
||||||
taxGroup, taxGroupOptions);
|
taxGroup, taxGroupOptions, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsProductData lookup(final Long id, final String name) {
|
public static SavingsProductData lookup(final Long id, final String name) {
|
||||||
@@ -305,6 +317,10 @@ public class SavingsProductData {
|
|||||||
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings = null;
|
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings = null;
|
||||||
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = null;
|
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = null;
|
||||||
final Collection<TaxGroupData> taxGroupOptions = null;
|
final Collection<TaxGroupData> taxGroupOptions = null;
|
||||||
|
final Boolean isDormancyTrackingActive = null;
|
||||||
|
final Long daysToInactive = null;
|
||||||
|
final Long daysToDormancy = null;
|
||||||
|
final Long daysToEscheat = null;
|
||||||
|
|
||||||
return new SavingsProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
return new SavingsProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||||
@@ -315,7 +331,7 @@ public class SavingsProductData {
|
|||||||
accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||||
penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
||||||
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
||||||
taxGroup, taxGroupOptions);
|
taxGroup, taxGroupOptions, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SavingsProductData(final Long id, final String name, final String shortName, final String description,
|
private SavingsProductData(final Long id, final String name, final String shortName, final String description,
|
||||||
@@ -338,7 +354,8 @@ public class SavingsProductData {
|
|||||||
final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance,
|
final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance, final boolean enforceMinRequiredBalance,
|
||||||
final BigDecimal minBalanceForInterestCalculation, final BigDecimal nominalAnnualInterestRateOverdraft,
|
final BigDecimal minBalanceForInterestCalculation, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||||
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroupData taxGroup,
|
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroupData taxGroup,
|
||||||
final Collection<TaxGroupData> taxGroupOptions) {
|
final Collection<TaxGroupData> taxGroupOptions, final Boolean isDormancyTrackingActive, final Long daysToInactive,
|
||||||
|
final Long daysToDormancy, final Long daysToEscheat) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.shortName = shortName;
|
this.shortName = shortName;
|
||||||
@@ -391,6 +408,10 @@ public class SavingsProductData {
|
|||||||
this.taxGroup = taxGroup;
|
this.taxGroup = taxGroup;
|
||||||
this.withHoldTax = withHoldTax;
|
this.withHoldTax = withHoldTax;
|
||||||
this.taxGroupOptions = taxGroupOptions;
|
this.taxGroupOptions = taxGroupOptions;
|
||||||
|
this.isDormancyTrackingActive = isDormancyTrackingActive;
|
||||||
|
this.daysToInactive = daysToInactive;
|
||||||
|
this.daysToDormancy = daysToDormancy;
|
||||||
|
this.daysToEscheat = daysToEscheat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasAccountingEnabled() {
|
public boolean hasAccountingEnabled() {
|
||||||
|
|||||||
+70
-1
@@ -44,6 +44,10 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shortNam
|
|||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withHoldTaxParamName;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withHoldTaxParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.taxGroupIdParamName;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.taxGroupIdParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.isDormancyTrackingActiveParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToInactiveParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToDormancyParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToEscheatParamName;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -64,6 +68,7 @@ import org.apache.fineract.portfolio.savings.SavingsCompoundingInterestPeriodTyp
|
|||||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationType;
|
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationType;
|
||||||
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
|
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||||
|
import org.apache.fineract.portfolio.savings.domain.SavingsProduct;
|
||||||
import org.joda.time.MonthDay;
|
import org.joda.time.MonthDay;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -233,6 +238,27 @@ public class SavingsProductDataValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//dormancy
|
||||||
|
final Boolean isDormancyActive = this.fromApiJsonHelper.extractBooleanNamed(isDormancyTrackingActiveParamName, element);
|
||||||
|
|
||||||
|
if(null != isDormancyActive && isDormancyActive){
|
||||||
|
final Long daysToInact = this.fromApiJsonHelper.extractLongNamed(daysToInactiveParamName, element);
|
||||||
|
baseDataValidator.reset().parameter(daysToInactiveParamName).value(daysToInact).notNull().longGreaterThanZero();
|
||||||
|
|
||||||
|
final Long daysToDor = this.fromApiJsonHelper.extractLongNamed(daysToDormancyParamName, element);
|
||||||
|
baseDataValidator.reset().parameter(daysToDormancyParamName).value(daysToDor).notNull().longGreaterThanZero();
|
||||||
|
|
||||||
|
final Long daysToEsc = this.fromApiJsonHelper.extractLongNamed(daysToEscheatParamName, element);
|
||||||
|
baseDataValidator.reset().parameter(daysToEscheatParamName).value(daysToEsc).notNull().longGreaterThanZero();
|
||||||
|
|
||||||
|
if(null != daysToInact
|
||||||
|
&& null != daysToDor
|
||||||
|
&& null != daysToEsc){
|
||||||
|
baseDataValidator.reset().parameter(daysToDormancyParamName).value(daysToDor).longGreaterThanNumber(daysToInact);
|
||||||
|
baseDataValidator.reset().parameter(daysToEscheatParamName).value(daysToEsc).longGreaterThanNumber(daysToDor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// accounting related data validation
|
// accounting related data validation
|
||||||
final Integer accountingRuleType = this.fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault());
|
final Integer accountingRuleType = this.fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault());
|
||||||
baseDataValidator.reset().parameter("accountingRule").value(accountingRuleType).notNull().inMinMaxRange(1, 3);
|
baseDataValidator.reset().parameter("accountingRule").value(accountingRuleType).notNull().inMinMaxRange(1, 3);
|
||||||
@@ -284,6 +310,13 @@ public class SavingsProductDataValidator {
|
|||||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue()).value(writtenoff)
|
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue()).value(writtenoff)
|
||||||
.notNull().integerGreaterThanZero();
|
.notNull().integerGreaterThanZero();
|
||||||
|
|
||||||
|
if(null != isDormancyActive && isDormancyActive){
|
||||||
|
final Long escheatLiabilityAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||||
|
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.ESCHEAT_LIABILITY.getValue(), element);
|
||||||
|
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.ESCHEAT_LIABILITY.getValue())
|
||||||
|
.value(escheatLiabilityAccountId).notNull().integerGreaterThanZero();
|
||||||
|
}
|
||||||
|
|
||||||
validatePaymentChannelFundSourceMappings(baseDataValidator, element);
|
validatePaymentChannelFundSourceMappings(baseDataValidator, element);
|
||||||
validateChargeToIncomeAccountMappings(baseDataValidator, element);
|
validateChargeToIncomeAccountMappings(baseDataValidator, element);
|
||||||
}
|
}
|
||||||
@@ -302,7 +335,7 @@ public class SavingsProductDataValidator {
|
|||||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateForUpdate(final String json) {
|
public void validateForUpdate(final String json, final SavingsProduct product) {
|
||||||
|
|
||||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||||
|
|
||||||
@@ -453,6 +486,42 @@ public class SavingsProductDataValidator {
|
|||||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue()).value(writtenoff)
|
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue()).value(writtenoff)
|
||||||
.ignoreIfNull().integerGreaterThanZero();
|
.ignoreIfNull().integerGreaterThanZero();
|
||||||
|
|
||||||
|
//dormancy
|
||||||
|
final Boolean isDormancyActive = this.fromApiJsonHelper.parameterExists(isDormancyTrackingActiveParamName, element)?
|
||||||
|
this.fromApiJsonHelper.extractBooleanNamed(isDormancyTrackingActiveParamName, element):
|
||||||
|
product.isDormancyTrackingActive();
|
||||||
|
|
||||||
|
if(null != isDormancyActive && isDormancyActive){
|
||||||
|
final Long daysToInact = this.fromApiJsonHelper.parameterExists(daysToInactiveParamName, element)?
|
||||||
|
this.fromApiJsonHelper.extractLongNamed(daysToInactiveParamName, element):
|
||||||
|
product.getDaysToInactive();
|
||||||
|
baseDataValidator.reset().parameter(daysToInactiveParamName).value(daysToInact).notNull().longGreaterThanZero();
|
||||||
|
|
||||||
|
final Long daysToDor = this.fromApiJsonHelper.parameterExists(daysToDormancyParamName, element)?
|
||||||
|
this.fromApiJsonHelper.extractLongNamed(daysToDormancyParamName, element):
|
||||||
|
product.getDaysToDormancy();
|
||||||
|
baseDataValidator.reset().parameter(daysToDormancyParamName).value(daysToDor).notNull().longGreaterThanZero();
|
||||||
|
|
||||||
|
final Long daysToEsc = this.fromApiJsonHelper.parameterExists(daysToEscheatParamName, element)?
|
||||||
|
this.fromApiJsonHelper.extractLongNamed(daysToEscheatParamName, element):
|
||||||
|
product.getDaysToEscheat();
|
||||||
|
baseDataValidator.reset().parameter(daysToEscheatParamName).value(daysToEsc).notNull().longGreaterThanZero();
|
||||||
|
|
||||||
|
if(null != daysToInact
|
||||||
|
&& null != daysToDor
|
||||||
|
&& null != daysToEsc){
|
||||||
|
baseDataValidator.reset().parameter(daysToDormancyParamName).value(daysToDor).longGreaterThanNumber(daysToInact);
|
||||||
|
baseDataValidator.reset().parameter(daysToEscheatParamName).value(daysToEsc).longGreaterThanNumber(daysToDor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.fromApiJsonHelper.parameterExists(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.ESCHEAT_LIABILITY.getValue(), element)){
|
||||||
|
final Long escheatLiabilityAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||||
|
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.ESCHEAT_LIABILITY.getValue(), element);
|
||||||
|
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.ESCHEAT_LIABILITY.getValue())
|
||||||
|
.value(escheatLiabilityAccountId).notNull().integerGreaterThanZero();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
validatePaymentChannelFundSourceMappings(baseDataValidator, element);
|
validatePaymentChannelFundSourceMappings(baseDataValidator, element);
|
||||||
validateChargeToIncomeAccountMappings(baseDataValidator, element);
|
validateChargeToIncomeAccountMappings(baseDataValidator, element);
|
||||||
validateOverdraftParams(baseDataValidator, element);
|
validateOverdraftParams(baseDataValidator, element);
|
||||||
|
|||||||
+46
@@ -114,6 +114,7 @@ import org.joda.time.LocalDate;
|
|||||||
import org.joda.time.format.DateTimeFormat;
|
import org.joda.time.format.DateTimeFormat;
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
@@ -154,6 +155,9 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
@Column(name = "status_enum", nullable = false)
|
@Column(name = "status_enum", nullable = false)
|
||||||
protected Integer status;
|
protected Integer status;
|
||||||
|
|
||||||
|
@Column(name = "sub_status_enum", nullable = false)
|
||||||
|
protected Integer sub_status = 0;
|
||||||
|
|
||||||
@Column(name = "account_type_enum", nullable = false)
|
@Column(name = "account_type_enum", nullable = false)
|
||||||
protected Integer accountType;
|
protected Integer accountType;
|
||||||
|
|
||||||
@@ -902,6 +906,11 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||||
|
|
||||||
|
if(this.sub_status.equals(SavingsAccountSubStatusEnum.INACTIVE.getValue())
|
||||||
|
|| this.sub_status.equals(SavingsAccountSubStatusEnum.DORMANT.getValue())){
|
||||||
|
this.sub_status = SavingsAccountSubStatusEnum.NONE.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -987,6 +996,10 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
// auto pay withdrawal fee
|
// auto pay withdrawal fee
|
||||||
payWithdrawalFee(transactionDTO.getTransactionAmount(), transactionDTO.getTransactionDate(), transactionDTO.getAppUser());
|
payWithdrawalFee(transactionDTO.getTransactionAmount(), transactionDTO.getTransactionDate(), transactionDTO.getAppUser());
|
||||||
}
|
}
|
||||||
|
if(this.sub_status.equals(SavingsAccountSubStatusEnum.INACTIVE.getValue())
|
||||||
|
|| this.sub_status.equals(SavingsAccountSubStatusEnum.DORMANT.getValue())){
|
||||||
|
this.sub_status = SavingsAccountSubStatusEnum.NONE.getValue();
|
||||||
|
}
|
||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2744,4 +2757,37 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
return recalucateDailyBalance;
|
return recalucateDailyBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSubStatusInactive(AppUser appUser) {
|
||||||
|
this.sub_status = SavingsAccountSubStatusEnum.INACTIVE.getValue();
|
||||||
|
LocalDate transactionDate = DateUtils.getLocalDateOfTenant();
|
||||||
|
for (SavingsAccountCharge charge : this.charges()) {
|
||||||
|
if (charge.isSavingsNoActivity() && charge.isActive()) {
|
||||||
|
charge.updateWithdralFeeAmount(this.getAccountBalance());
|
||||||
|
this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, appUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recalculateDailyBalances(Money.zero(this.currency), transactionDate);
|
||||||
|
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setSubStatusDormant() {
|
||||||
|
this.sub_status = SavingsAccountSubStatusEnum.DORMANT.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void escheat(AppUser appUser) {
|
||||||
|
this.status = SavingsAccountStatusType.CLOSED.getValue();
|
||||||
|
this.sub_status = SavingsAccountSubStatusEnum.ESCHEAT.getValue();
|
||||||
|
this.closedOnDate = DateUtils.getDateOfTenant();
|
||||||
|
this.closedBy = appUser;
|
||||||
|
|
||||||
|
LocalDate transactionDate = DateUtils.getLocalDateOfTenant();
|
||||||
|
if(this.getSummary().getAccountBalance(this.getCurrency()).isGreaterThanZero()){
|
||||||
|
SavingsAccountTransaction transaction = SavingsAccountTransaction.escheat(this, transactionDate, appUser);
|
||||||
|
this.transactions.add(transaction);
|
||||||
|
}
|
||||||
|
recalculateDailyBalances(Money.zero(this.currency), transactionDate);
|
||||||
|
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+4
@@ -657,6 +657,10 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
|||||||
return ChargeTimeType.fromInt(this.chargeTime).isSavingsActivation();
|
return ChargeTimeType.fromInt(this.chargeTime).isSavingsActivation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSavingsNoActivity(){
|
||||||
|
return ChargeTimeType.fromInt(this.chargeTime).isSavingsNoActivityFee();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSavingsClosure() {
|
public boolean isSavingsClosure() {
|
||||||
return ChargeTimeType.fromInt(this.chargeTime).isSavingsClosure();
|
return ChargeTimeType.fromInt(this.chargeTime).isSavingsClosure();
|
||||||
}
|
}
|
||||||
|
|||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.savings.domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum representation of {@link SavingsAccount} sub-status states.
|
||||||
|
*/
|
||||||
|
public enum SavingsAccountSubStatusEnum {
|
||||||
|
|
||||||
|
NONE(0, "SavingsAccountSubStatusEnum.none"), //
|
||||||
|
INACTIVE(100, "SavingsAccountSubStatusEnum.inactive"), //
|
||||||
|
DORMANT(200, "SavingsAccountSubStatusEnum.dormant"),
|
||||||
|
ESCHEAT(300,"SavingsAccountSubStatusEnum.escheat");
|
||||||
|
|
||||||
|
private final Integer value;
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
public static SavingsAccountSubStatusEnum fromInt(final Integer type) {
|
||||||
|
|
||||||
|
SavingsAccountSubStatusEnum enumeration = SavingsAccountSubStatusEnum.NONE;
|
||||||
|
if(null != type){
|
||||||
|
switch (type) {
|
||||||
|
case 100:
|
||||||
|
enumeration = SavingsAccountSubStatusEnum.INACTIVE;
|
||||||
|
break;
|
||||||
|
case 200:
|
||||||
|
enumeration = SavingsAccountSubStatusEnum.DORMANT;
|
||||||
|
break;
|
||||||
|
case 300:
|
||||||
|
enumeration = SavingsAccountSubStatusEnum.ESCHEAT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return enumeration;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SavingsAccountSubStatusEnum(final Integer value, final String code) {
|
||||||
|
this.value = value;
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasStateOf(final SavingsAccountSubStatusEnum state) {
|
||||||
|
return this.value.equals(state.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return this.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSubStatusInactive() {
|
||||||
|
return this.value.equals(SavingsAccountSubStatusEnum.INACTIVE.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSubStatusDormant() {
|
||||||
|
return this.value.equals(SavingsAccountSubStatusEnum.DORMANT.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSubStatusNone() {
|
||||||
|
return this.value.equals(SavingsAccountSubStatusEnum.NONE.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSubStatusEscheat() {
|
||||||
|
return this.value.equals(SavingsAccountSubStatusEnum.ESCHEAT.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -228,6 +228,15 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
|||||||
return accountTransaction;
|
return accountTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static SavingsAccountTransaction escheat(final SavingsAccount savingsAccount, final LocalDate date,
|
||||||
|
final AppUser appUser) {
|
||||||
|
final boolean isReversed = false;
|
||||||
|
final PaymentDetail paymentDetail = null;
|
||||||
|
return new SavingsAccountTransaction(savingsAccount, savingsAccount.office(), paymentDetail,
|
||||||
|
SavingsAccountTransactionType.ESCHEAT.getValue(), date, new Date(), savingsAccount.getSummary()
|
||||||
|
.getAccountBalance(), isReversed, appUser);
|
||||||
|
}
|
||||||
|
|
||||||
public static void updateTaxDetails(final Map<TaxComponent, BigDecimal> taxDetails, final SavingsAccountTransaction accountTransaction) {
|
public static void updateTaxDetails(final Map<TaxComponent, BigDecimal> taxDetails, final SavingsAccountTransaction accountTransaction) {
|
||||||
if (taxDetails != null) {
|
if (taxDetails != null) {
|
||||||
for (Map.Entry<TaxComponent, BigDecimal> mapEntry : taxDetails.entrySet()) {
|
for (Map.Entry<TaxComponent, BigDecimal> mapEntry : taxDetails.entrySet()) {
|
||||||
|
|||||||
+74
-4
@@ -46,6 +46,10 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shortNam
|
|||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.taxGroupIdParamName;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.taxGroupIdParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withHoldTaxParamName;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withHoldTaxParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.isDormancyTrackingActiveParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToInactiveParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToDormancyParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToEscheatParamName;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -191,6 +195,18 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
@JoinColumn(name = "tax_group_id")
|
@JoinColumn(name = "tax_group_id")
|
||||||
private TaxGroup taxGroup;
|
private TaxGroup taxGroup;
|
||||||
|
|
||||||
|
@Column(name = "is_dormancy_tracking_active")
|
||||||
|
private Boolean isDormancyTrackingActive;
|
||||||
|
|
||||||
|
@Column(name = "days_to_inactive")
|
||||||
|
private Long daysToInactive;
|
||||||
|
|
||||||
|
@Column(name = "days_to_dormancy")
|
||||||
|
private Long daysToDormancy;
|
||||||
|
|
||||||
|
@Column(name = "days_to_escheat")
|
||||||
|
private Long daysToEscheat;
|
||||||
|
|
||||||
public static SavingsProduct createNew(final String name, final String shortName, final String description,
|
public static SavingsProduct createNew(final String name, final String shortName, final String description,
|
||||||
final MonetaryCurrency currency, final BigDecimal interestRate,
|
final MonetaryCurrency currency, final BigDecimal interestRate,
|
||||||
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
||||||
@@ -201,13 +217,15 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean enforceMinRequiredBalance,
|
final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean enforceMinRequiredBalance,
|
||||||
final BigDecimal minRequiredBalance, final BigDecimal minBalanceForInterestCalculation,
|
final BigDecimal minRequiredBalance, final BigDecimal minBalanceForInterestCalculation,
|
||||||
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation,
|
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation,
|
||||||
boolean withHoldTax, TaxGroup taxGroup) {
|
boolean withHoldTax, TaxGroup taxGroup,
|
||||||
|
final Boolean isDormancyTrackingActive, final Long daysToInactive, final Long daysToDormancy, final Long daysToEscheat) {
|
||||||
|
|
||||||
return new SavingsProduct(name, shortName, description, currency, interestRate, interestCompoundingPeriodType,
|
return new SavingsProduct(name, shortName, description, currency, interestRate, interestCompoundingPeriodType,
|
||||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges,
|
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges,
|
||||||
allowOverdraft, overdraftLimit, enforceMinRequiredBalance, minRequiredBalance, minBalanceForInterestCalculation,
|
allowOverdraft, overdraftLimit, enforceMinRequiredBalance, minRequiredBalance, minBalanceForInterestCalculation,
|
||||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup);
|
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
||||||
|
isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SavingsProduct() {
|
protected SavingsProduct() {
|
||||||
@@ -226,7 +244,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
this(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
this(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||||
lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, allowOverdraft, overdraftLimit,
|
lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, allowOverdraft, overdraftLimit,
|
||||||
false, null, minBalanceForInterestCalculation, null, null, withHoldTax, taxGroup);
|
false, null, minBalanceForInterestCalculation, null, null, withHoldTax, taxGroup, null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SavingsProduct(final String name, final String shortName, final String description, final MonetaryCurrency currency,
|
protected SavingsProduct(final String name, final String shortName, final String description, final MonetaryCurrency currency,
|
||||||
@@ -238,7 +256,8 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean enforceMinRequiredBalance,
|
final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean enforceMinRequiredBalance,
|
||||||
final BigDecimal minRequiredBalance, BigDecimal minBalanceForInterestCalculation,
|
final BigDecimal minRequiredBalance, BigDecimal minBalanceForInterestCalculation,
|
||||||
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation,
|
final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation,
|
||||||
final boolean withHoldTax, final TaxGroup taxGroup) {
|
final boolean withHoldTax, final TaxGroup taxGroup,
|
||||||
|
final Boolean isDormancyTrackingActive, final Long daysToInactive, final Long daysToDormancy, final Long daysToEscheat) {
|
||||||
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.shortName = shortName;
|
this.shortName = shortName;
|
||||||
@@ -283,6 +302,11 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
this.minBalanceForInterestCalculation = minBalanceForInterestCalculation;
|
this.minBalanceForInterestCalculation = minBalanceForInterestCalculation;
|
||||||
this.withHoldTax = withHoldTax;
|
this.withHoldTax = withHoldTax;
|
||||||
this.taxGroup = taxGroup;
|
this.taxGroup = taxGroup;
|
||||||
|
|
||||||
|
this.isDormancyTrackingActive = isDormancyTrackingActive;
|
||||||
|
this.daysToInactive = daysToInactive;
|
||||||
|
this.daysToDormancy = daysToDormancy;
|
||||||
|
this.daysToEscheat = daysToEscheat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -542,6 +566,36 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
this.taxGroup = null;
|
this.taxGroup = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(command.isChangeInBooleanParameterNamed(isDormancyTrackingActiveParamName, this.isDormancyTrackingActive)){
|
||||||
|
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(isDormancyTrackingActiveParamName);
|
||||||
|
actualChanges.put(isDormancyTrackingActiveParamName, newValue);
|
||||||
|
this.isDormancyTrackingActive = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(command.isChangeInLongParameterNamed(daysToInactiveParamName, this.daysToInactive)){
|
||||||
|
final Long newValue = command.longValueOfParameterNamed(daysToInactiveParamName);
|
||||||
|
actualChanges.put(daysToInactiveParamName, newValue);
|
||||||
|
this.daysToInactive = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(command.isChangeInLongParameterNamed(daysToDormancyParamName, this.daysToDormancy)){
|
||||||
|
final Long newValue = command.longValueOfParameterNamed(daysToDormancyParamName);
|
||||||
|
actualChanges.put(daysToDormancyParamName, newValue);
|
||||||
|
this.daysToDormancy = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(command.isChangeInLongParameterNamed(daysToEscheatParamName, this.daysToEscheat)){
|
||||||
|
final Long newValue = command.longValueOfParameterNamed(daysToEscheatParamName);
|
||||||
|
actualChanges.put(daysToEscheatParamName, newValue);
|
||||||
|
this.daysToEscheat = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this.isDormancyTrackingActive){
|
||||||
|
this.daysToInactive = null;
|
||||||
|
this.daysToDormancy = null;
|
||||||
|
this.daysToEscheat = null;
|
||||||
|
}
|
||||||
|
|
||||||
validateLockinDetails();
|
validateLockinDetails();
|
||||||
esnureOverdraftLimitsSetForOverdraftAccounts();
|
esnureOverdraftLimitsSetForOverdraftAccounts();
|
||||||
|
|
||||||
@@ -676,4 +730,20 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
return this.withHoldTax;
|
return this.withHoldTax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDormancyTrackingActive() {
|
||||||
|
return null == this.isDormancyTrackingActive? false: this.isDormancyTrackingActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getDaysToInactive() {
|
||||||
|
return this.daysToInactive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getDaysToDormancy() {
|
||||||
|
return this.daysToDormancy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getDaysToEscheat() {
|
||||||
|
return this.daysToEscheat;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+11
-1
@@ -44,6 +44,10 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.overdraf
|
|||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shortNameParamName;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shortNameParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.taxGroupIdParamName;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.taxGroupIdParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.isDormancyTrackingActiveParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToInactiveParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToDormancyParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToEscheatParamName;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -174,11 +178,17 @@ public class SavingsProductAssembler {
|
|||||||
boolean withHoldTax = command.booleanPrimitiveValueOfParameterNamed(withHoldTaxParamName);
|
boolean withHoldTax = command.booleanPrimitiveValueOfParameterNamed(withHoldTaxParamName);
|
||||||
final TaxGroup taxGroup = assembleTaxGroup(command);
|
final TaxGroup taxGroup = assembleTaxGroup(command);
|
||||||
|
|
||||||
|
final Boolean isDormancyTrackingActive = command.booleanObjectValueOfParameterNamed(isDormancyTrackingActiveParamName);
|
||||||
|
final Long daysToInactive = command.longValueOfParameterNamed(daysToInactiveParamName);
|
||||||
|
final Long daysToDormancy = command.longValueOfParameterNamed(daysToDormancyParamName);
|
||||||
|
final Long daysToEscheat = command.longValueOfParameterNamed(daysToEscheatParamName);
|
||||||
|
|
||||||
return SavingsProduct.createNew(name, shortName, description, currency, interestRate, interestCompoundingPeriodType,
|
return SavingsProduct.createNew(name, shortName, description, currency, interestRate, interestCompoundingPeriodType,
|
||||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||||
lockinPeriodFrequency, lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, accountingRuleType, charges,
|
lockinPeriodFrequency, lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, accountingRuleType, charges,
|
||||||
allowOverdraft, overdraftLimit, enforceMinRequiredBalance, minRequiredBalance, minBalanceForInterestCalculation,
|
allowOverdraft, overdraftLimit, enforceMinRequiredBalance, minRequiredBalance, minBalanceForInterestCalculation,
|
||||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup);
|
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroup,
|
||||||
|
isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Charge> assembleListOfSavingsProductCharges(final JsonCommand command, final String savingsProductCurrencyCode) {
|
public Set<Charge> assembleListOfSavingsProductCharges(final JsonCommand command, final String savingsProductCurrencyCode) {
|
||||||
|
|||||||
+8
@@ -19,12 +19,14 @@
|
|||||||
package org.apache.fineract.portfolio.savings.service;
|
package org.apache.fineract.portfolio.savings.service;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.fineract.infrastructure.core.service.Page;
|
import org.apache.fineract.infrastructure.core.service.Page;
|
||||||
import org.apache.fineract.infrastructure.core.service.SearchParameters;
|
import org.apache.fineract.infrastructure.core.service.SearchParameters;
|
||||||
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
|
||||||
public interface SavingsAccountReadPlatformService {
|
public interface SavingsAccountReadPlatformService {
|
||||||
|
|
||||||
@@ -50,4 +52,10 @@ public interface SavingsAccountReadPlatformService {
|
|||||||
SavingsAccountTransactionData retrieveSavingsTransaction(Long savingsId, Long transactionId, DepositAccountType depositAccountType);
|
SavingsAccountTransactionData retrieveSavingsTransaction(Long savingsId, Long transactionId, DepositAccountType depositAccountType);
|
||||||
|
|
||||||
Collection<SavingsAccountData> retrieveForLookup(Long clientId, Boolean overdraft);
|
Collection<SavingsAccountData> retrieveForLookup(Long clientId, Boolean overdraft);
|
||||||
|
|
||||||
|
List<Long> retrieveSavingsIdsPendingInactive(LocalDate tenantLocalDate);
|
||||||
|
|
||||||
|
List<Long> retrieveSavingsIdsPendingDormant(LocalDate tenantLocalDate);
|
||||||
|
|
||||||
|
List<Long> retrieveSavingsIdsPendingEscheat(LocalDate tenantLocalDate);
|
||||||
}
|
}
|
||||||
+144
-13
@@ -24,6 +24,8 @@ import java.sql.SQLException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||||
@@ -38,6 +40,7 @@ import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
|||||||
import org.apache.fineract.organisation.staff.data.StaffData;
|
import org.apache.fineract.organisation.staff.data.StaffData;
|
||||||
import org.apache.fineract.organisation.staff.service.StaffReadPlatformService;
|
import org.apache.fineract.organisation.staff.service.StaffReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.account.data.AccountTransferData;
|
import org.apache.fineract.portfolio.account.data.AccountTransferData;
|
||||||
|
import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
|
||||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||||
import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
|
import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.client.data.ClientData;
|
import org.apache.fineract.portfolio.client.data.ClientData;
|
||||||
@@ -56,15 +59,22 @@ import org.apache.fineract.portfolio.savings.data.SavingsAccountApplicationTimel
|
|||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData;
|
||||||
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountSubStatusEnumData;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountSummaryData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountSummaryData;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionEnumData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionEnumData;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsProductData;
|
import org.apache.fineract.portfolio.savings.data.SavingsProductData;
|
||||||
|
import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType;
|
||||||
|
import org.apache.fineract.portfolio.savings.domain.SavingsAccountSubStatusEnum;
|
||||||
import org.apache.fineract.portfolio.savings.exception.SavingsAccountNotFoundException;
|
import org.apache.fineract.portfolio.savings.exception.SavingsAccountNotFoundException;
|
||||||
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
||||||
import org.apache.fineract.useradministration.domain.AppUser;
|
import org.apache.fineract.useradministration.domain.AppUser;
|
||||||
|
import org.joda.time.Days;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
import org.joda.time.format.DateTimeFormat;
|
||||||
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.EmptyResultDataAccessException;
|
import org.springframework.dao.EmptyResultDataAccessException;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.jdbc.core.RowMapper;
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
@@ -82,6 +92,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
private final StaffReadPlatformService staffReadPlatformService;
|
private final StaffReadPlatformService staffReadPlatformService;
|
||||||
private final SavingsDropdownReadPlatformService dropdownReadPlatformService;
|
private final SavingsDropdownReadPlatformService dropdownReadPlatformService;
|
||||||
private final ChargeReadPlatformService chargeReadPlatformService;
|
private final ChargeReadPlatformService chargeReadPlatformService;
|
||||||
|
private final DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
|
||||||
|
|
||||||
// mappers
|
// mappers
|
||||||
private final SavingsAccountTransactionTemplateMapper transactionTemplateMapper;
|
private final SavingsAccountTransactionTemplateMapper transactionTemplateMapper;
|
||||||
@@ -217,7 +228,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
sqlBuilder.append("sp.id as productId, sp.name as productName, ");
|
sqlBuilder.append("sp.id as productId, sp.name as productName, ");
|
||||||
sqlBuilder.append("s.id fieldOfficerId, s.display_name as fieldOfficerName, ");
|
sqlBuilder.append("s.id fieldOfficerId, s.display_name as fieldOfficerName, ");
|
||||||
sqlBuilder.append("sa.status_enum as statusEnum, ");
|
sqlBuilder.append("sa.status_enum as statusEnum, ");
|
||||||
|
sqlBuilder.append("sa.sub_status_enum as subStatusEnum, ");
|
||||||
sqlBuilder.append("sa.submittedon_date as submittedOnDate,");
|
sqlBuilder.append("sa.submittedon_date as submittedOnDate,");
|
||||||
sqlBuilder.append("sbu.username as submittedByUsername,");
|
sqlBuilder.append("sbu.username as submittedByUsername,");
|
||||||
sqlBuilder.append("sbu.firstname as submittedByFirstname, sbu.lastname as submittedByLastname,");
|
sqlBuilder.append("sbu.firstname as submittedByFirstname, sbu.lastname as submittedByLastname,");
|
||||||
@@ -282,8 +293,16 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
sqlBuilder.append("sa.on_hold_funds_derived as onHoldFunds, ");
|
sqlBuilder.append("sa.on_hold_funds_derived as onHoldFunds, ");
|
||||||
sqlBuilder.append("sa.withhold_tax as withHoldTax,");
|
sqlBuilder.append("sa.withhold_tax as withHoldTax,");
|
||||||
sqlBuilder.append("sa.total_withhold_tax_derived as totalWithholdTax,");
|
sqlBuilder.append("sa.total_withhold_tax_derived as totalWithholdTax,");
|
||||||
sqlBuilder.append("tg.id as taxGroupId, tg.name as taxGroupName ");
|
sqlBuilder.append("tg.id as taxGroupId, tg.name as taxGroupName, ");
|
||||||
|
sqlBuilder.append("(select IFNULL(max(sat.transaction_date),sa.activatedon_date) ");
|
||||||
|
sqlBuilder.append("from m_savings_account_transaction as sat ");
|
||||||
|
sqlBuilder.append("where sat.is_reversed = 0 ");
|
||||||
|
sqlBuilder.append("and sat.transaction_type_enum in (1,2) ");
|
||||||
|
sqlBuilder.append("and sat.savings_account_id = sa.id) as lastActiveTransactionDate, ");
|
||||||
|
sqlBuilder.append("sp.is_dormancy_tracking_active as isDormancyTrackingActive, ");
|
||||||
|
sqlBuilder.append("sp.days_to_inactive as daysToInactive, ");
|
||||||
|
sqlBuilder.append("sp.days_to_dormancy as daysToDormancy, ");
|
||||||
|
sqlBuilder.append("sp.days_to_escheat as daysToEscheat ");
|
||||||
sqlBuilder.append("from m_savings_account sa ");
|
sqlBuilder.append("from m_savings_account sa ");
|
||||||
sqlBuilder.append("join m_savings_product sp ON sa.product_id = sp.id ");
|
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 ");
|
sqlBuilder.append("join m_currency curr on curr.code = sa.currency_code ");
|
||||||
@@ -328,6 +347,31 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
final Integer statusEnum = JdbcSupport.getInteger(rs, "statusEnum");
|
final Integer statusEnum = JdbcSupport.getInteger(rs, "statusEnum");
|
||||||
final SavingsAccountStatusEnumData status = SavingsEnumerations.status(statusEnum);
|
final SavingsAccountStatusEnumData status = SavingsEnumerations.status(statusEnum);
|
||||||
|
|
||||||
|
final Integer subStatusEnum = JdbcSupport.getInteger(rs, "subStatusEnum");
|
||||||
|
final SavingsAccountSubStatusEnumData subStatus = SavingsEnumerations.subStatus(subStatusEnum);
|
||||||
|
|
||||||
|
final LocalDate lastActiveTransactionDate = JdbcSupport.getLocalDate(rs, "lastActiveTransactionDate");
|
||||||
|
final boolean isDormancyTrackingActive = rs.getBoolean("isDormancyTrackingActive");
|
||||||
|
final Integer numDaysToInactive = JdbcSupport.getInteger(rs, "daysToInactive");
|
||||||
|
final Integer numDaysToDormancy = JdbcSupport.getInteger(rs, "daysToDormancy");
|
||||||
|
final Integer numDaysToEscheat = JdbcSupport.getInteger(rs, "daysToEscheat");
|
||||||
|
Integer daysToInactive = null;
|
||||||
|
Integer daysToDormancy = null;
|
||||||
|
Integer daysToEscheat = null;
|
||||||
|
|
||||||
|
LocalDate localTenantDate = DateUtils.getLocalDateOfTenant();
|
||||||
|
if(isDormancyTrackingActive && statusEnum.equals(SavingsAccountStatusType.ACTIVE.getValue())){
|
||||||
|
if(subStatusEnum < SavingsAccountSubStatusEnum.ESCHEAT.getValue()){
|
||||||
|
daysToEscheat = Days.daysBetween(localTenantDate,lastActiveTransactionDate.plusDays(numDaysToEscheat)).getDays();
|
||||||
|
}
|
||||||
|
if(subStatusEnum < SavingsAccountSubStatusEnum.DORMANT.getValue()){
|
||||||
|
daysToDormancy = Days.daysBetween(localTenantDate,lastActiveTransactionDate.plusDays(numDaysToDormancy)).getDays();
|
||||||
|
}
|
||||||
|
if(subStatusEnum < SavingsAccountSubStatusEnum.INACTIVE.getValue()){
|
||||||
|
daysToInactive = Days.daysBetween(localTenantDate,lastActiveTransactionDate.plusDays(numDaysToInactive)).getDays();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final LocalDate submittedOnDate = JdbcSupport.getLocalDate(rs, "submittedOnDate");
|
final LocalDate submittedOnDate = JdbcSupport.getLocalDate(rs, "submittedOnDate");
|
||||||
final String submittedByUsername = rs.getString("submittedByUsername");
|
final String submittedByUsername = rs.getString("submittedByUsername");
|
||||||
final String submittedByFirstname = rs.getString("submittedByFirstname");
|
final String submittedByFirstname = rs.getString("submittedByFirstname");
|
||||||
@@ -469,11 +513,12 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
}
|
}
|
||||||
|
|
||||||
return SavingsAccountData.instance(id, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
return SavingsAccountData.instance(id, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
|
||||||
productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate,
|
productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline, currency,
|
||||||
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
|
||||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary,
|
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers,
|
||||||
allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation,
|
summary, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
||||||
onHoldFunds, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroupData);
|
minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
||||||
|
taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -997,14 +1042,22 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
final SavingsAccountSummaryData summary = null;
|
final SavingsAccountSummaryData summary = null;
|
||||||
final BigDecimal onHoldFunds = null;
|
final BigDecimal onHoldFunds = null;
|
||||||
|
|
||||||
|
final SavingsAccountSubStatusEnumData subStatus = null;
|
||||||
|
final LocalDate lastActiveTransactionDate = null;
|
||||||
|
final boolean isDormancyTrackingActive = false;
|
||||||
|
final Integer daysToInactive = null;
|
||||||
|
final Integer daysToDormancy = null;
|
||||||
|
final Integer daysToEscheat = null;
|
||||||
|
|
||||||
final SavingsAccountApplicationTimelineData timeline = SavingsAccountApplicationTimelineData.templateDefault();
|
final SavingsAccountApplicationTimelineData timeline = SavingsAccountApplicationTimelineData.templateDefault();
|
||||||
final EnumOptionData depositType = null;
|
final EnumOptionData depositType = null;
|
||||||
return SavingsAccountData.instance(null, null, depositType, null, groupId, groupName, clientId, clientName, productId,
|
return SavingsAccountData.instance(null, null, depositType, null, groupId, groupName, clientId, clientName, productId,
|
||||||
productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualIterestRate,
|
productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline, currency,
|
||||||
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
nominalAnnualIterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
|
||||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary,
|
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers,
|
||||||
allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation,
|
summary, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
||||||
onHoldFunds, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroupData);
|
minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
||||||
|
taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1025,6 +1078,84 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Long> retrieveSavingsIdsPendingInactive(
|
||||||
|
LocalDate tenantLocalDate) {
|
||||||
|
List<Long> ret = null;
|
||||||
|
StringBuilder sql = new StringBuilder("select sa.id ");
|
||||||
|
sql.append(" from m_savings_account as sa ");
|
||||||
|
sql.append(" inner join m_savings_product as sp on (sa.product_id = sp.id and sp.is_dormancy_tracking_active = 1) ");
|
||||||
|
sql.append(" where sa.status_enum = 300 ");
|
||||||
|
sql.append(" and sa.sub_status_enum = 0 ");
|
||||||
|
sql.append(" and DATEDIFF(?,(select IFNULL(max(sat.transaction_date),sa.activatedon_date) ");
|
||||||
|
sql.append(" from m_savings_account_transaction as sat ");
|
||||||
|
sql.append(" where sat.is_reversed = 0 ");
|
||||||
|
sql.append(" and sat.transaction_type_enum in (1,2) ");
|
||||||
|
sql.append(" and sat.savings_account_id = sa.id)) >= sp.days_to_inactive ");
|
||||||
|
|
||||||
|
try {
|
||||||
|
ret = this.jdbcTemplate.queryForList(sql.toString(), Long.class, new Object[] {formatter.print(tenantLocalDate)});
|
||||||
|
} catch (EmptyResultDataAccessException e) {
|
||||||
|
// ignore empty result scenario
|
||||||
|
} catch (DataAccessException e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Long> retrieveSavingsIdsPendingDormant(
|
||||||
|
LocalDate tenantLocalDate) {
|
||||||
|
List<Long> ret = null;
|
||||||
|
StringBuilder sql = new StringBuilder("select sa.id ");
|
||||||
|
sql.append(" from m_savings_account as sa ");
|
||||||
|
sql.append(" inner join m_savings_product as sp on (sa.product_id = sp.id and sp.is_dormancy_tracking_active = 1) ");
|
||||||
|
sql.append(" where sa.status_enum = 300 ");
|
||||||
|
sql.append(" and sa.sub_status_enum = 100 ");
|
||||||
|
sql.append(" and DATEDIFF(?,(select IFNULL(max(sat.transaction_date),sa.activatedon_date) ");
|
||||||
|
sql.append(" from m_savings_account_transaction as sat ");
|
||||||
|
sql.append(" where sat.is_reversed = 0 ");
|
||||||
|
sql.append(" and sat.transaction_type_enum in (1,2) ");
|
||||||
|
sql.append(" and sat.savings_account_id = sa.id)) >= sp.days_to_dormancy ");
|
||||||
|
|
||||||
|
try {
|
||||||
|
ret = this.jdbcTemplate.queryForList(sql.toString(), Long.class, new Object[] {formatter.print(tenantLocalDate)});
|
||||||
|
} catch (EmptyResultDataAccessException e) {
|
||||||
|
// ignore empty result scenario
|
||||||
|
} catch (DataAccessException e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Long> retrieveSavingsIdsPendingEscheat(
|
||||||
|
LocalDate tenantLocalDate) {
|
||||||
|
List<Long> ret = null;
|
||||||
|
StringBuilder sql = new StringBuilder("select sa.id ");
|
||||||
|
sql.append(" from m_savings_account as sa ");
|
||||||
|
sql.append(" inner join m_savings_product as sp on (sa.product_id = sp.id and sp.is_dormancy_tracking_active = 1) ");
|
||||||
|
sql.append(" where sa.status_enum = 300 ");
|
||||||
|
sql.append(" and sa.sub_status_enum = 200 ");
|
||||||
|
sql.append(" and DATEDIFF(?,(select IFNULL(max(sat.transaction_date),sa.activatedon_date) ");
|
||||||
|
sql.append(" from m_savings_account_transaction as sat ");
|
||||||
|
sql.append(" where sat.is_reversed = 0 ");
|
||||||
|
sql.append(" and sat.transaction_type_enum in (1,2) ");
|
||||||
|
sql.append(" and sat.savings_account_id = sa.id)) >= sp.days_to_escheat ");
|
||||||
|
|
||||||
|
try {
|
||||||
|
ret = this.jdbcTemplate.queryForList(sql.toString(), Long.class, new Object[] {formatter.print(tenantLocalDate)});
|
||||||
|
} catch (EmptyResultDataAccessException e) {
|
||||||
|
// ignore empty result scenario
|
||||||
|
} catch (DataAccessException e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* private static final class SavingsAccountAnnualFeeMapper implements
|
* private static final class SavingsAccountAnnualFeeMapper implements
|
||||||
* RowMapper<SavingsAccountAnnualFeeData> {
|
* RowMapper<SavingsAccountAnnualFeeData> {
|
||||||
|
|||||||
+6
@@ -81,4 +81,10 @@ public interface SavingsAccountWritePlatformService {
|
|||||||
void postInterest(SavingsAccount account);
|
void postInterest(SavingsAccount account);
|
||||||
|
|
||||||
CommandProcessingResult modifyWithHoldTax(Long savingsAccountId, JsonCommand command);
|
CommandProcessingResult modifyWithHoldTax(Long savingsAccountId, JsonCommand command);
|
||||||
|
|
||||||
|
void setSubStatusInactive(Long savingsId);
|
||||||
|
|
||||||
|
void setSubStatusDormant(Long savingsId);
|
||||||
|
|
||||||
|
void escheat(Long savingsId);
|
||||||
}
|
}
|
||||||
+38
-2
@@ -78,6 +78,7 @@ import org.apache.fineract.portfolio.savings.exception.SavingsOfficerAssignmentE
|
|||||||
import org.apache.fineract.portfolio.savings.exception.SavingsOfficerUnassignmentException;
|
import org.apache.fineract.portfolio.savings.exception.SavingsOfficerUnassignmentException;
|
||||||
import org.apache.fineract.portfolio.savings.exception.TransactionUpdateNotAllowedException;
|
import org.apache.fineract.portfolio.savings.exception.TransactionUpdateNotAllowedException;
|
||||||
import org.apache.fineract.useradministration.domain.AppUser;
|
import org.apache.fineract.useradministration.domain.AppUser;
|
||||||
|
import org.apache.fineract.useradministration.domain.AppUserRepositoryWrapper;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.joda.time.format.DateTimeFormat;
|
import org.joda.time.format.DateTimeFormat;
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
@@ -130,6 +131,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
private final WorkingDaysRepositoryWrapper workingDaysRepository;
|
private final WorkingDaysRepositoryWrapper workingDaysRepository;
|
||||||
private final ConfigurationDomainService configurationDomainService;
|
private final ConfigurationDomainService configurationDomainService;
|
||||||
private final DepositAccountOnHoldTransactionRepository depositAccountOnHoldTransactionRepository;
|
private final DepositAccountOnHoldTransactionRepository depositAccountOnHoldTransactionRepository;
|
||||||
|
private final AppUserRepositoryWrapper appuserRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public SavingsAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
public SavingsAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||||
@@ -148,7 +150,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
final ChargeRepositoryWrapper chargeRepository, final SavingsAccountChargeRepositoryWrapper savingsAccountChargeRepository,
|
final ChargeRepositoryWrapper chargeRepository, final SavingsAccountChargeRepositoryWrapper savingsAccountChargeRepository,
|
||||||
final SavingsAccountDataValidator fromApiJsonDeserializer, final SavingsAccountRepositoryWrapper savingsRepository,
|
final SavingsAccountDataValidator fromApiJsonDeserializer, final SavingsAccountRepositoryWrapper savingsRepository,
|
||||||
final StaffRepositoryWrapper staffRepository, final ConfigurationDomainService configurationDomainService,
|
final StaffRepositoryWrapper staffRepository, final ConfigurationDomainService configurationDomainService,
|
||||||
final DepositAccountOnHoldTransactionRepository depositAccountOnHoldTransactionRepository) {
|
final DepositAccountOnHoldTransactionRepository depositAccountOnHoldTransactionRepository,
|
||||||
|
final AppUserRepositoryWrapper appuserRepository) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.savingAccountRepository = savingAccountRepository;
|
this.savingAccountRepository = savingAccountRepository;
|
||||||
this.savingsAccountTransactionRepository = savingsAccountTransactionRepository;
|
this.savingsAccountTransactionRepository = savingsAccountTransactionRepository;
|
||||||
@@ -171,6 +174,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
this.staffRepository = staffRepository;
|
this.staffRepository = staffRepository;
|
||||||
this.configurationDomainService = configurationDomainService;
|
this.configurationDomainService = configurationDomainService;
|
||||||
this.depositAccountOnHoldTransactionRepository = depositAccountOnHoldTransactionRepository;
|
this.depositAccountOnHoldTransactionRepository = depositAccountOnHoldTransactionRepository;
|
||||||
|
this.appuserRepository = appuserRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -1223,7 +1227,39 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private AppUser getAppUserIfPresent() {
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void setSubStatusInactive(Long savingsId){
|
||||||
|
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
final Set<Long> existingTransactionIds = new HashSet<>();
|
||||||
|
final Set<Long> existingReversedTransactionIds = new HashSet<>();
|
||||||
|
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
account.setSubStatusInactive(appuserRepository.fetchSystemUser());
|
||||||
|
this.savingAccountRepository.save(account);
|
||||||
|
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void setSubStatusDormant(Long savingsId){
|
||||||
|
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
account.setSubStatusDormant();
|
||||||
|
this.savingAccountRepository.save(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void escheat(Long savingsId){
|
||||||
|
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
final Set<Long> existingTransactionIds = new HashSet<>();
|
||||||
|
final Set<Long> existingReversedTransactionIds = new HashSet<>();
|
||||||
|
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
account.escheat(appuserRepository.fetchSystemUser());
|
||||||
|
this.savingAccountRepository.save(account);
|
||||||
|
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AppUser getAppUserIfPresent() {
|
||||||
AppUser user = null;
|
AppUser user = null;
|
||||||
if (this.context != null) {
|
if (this.context != null) {
|
||||||
user = this.context.getAuthenticatedUserIfPresent();
|
user = this.context.getAuthenticatedUserIfPresent();
|
||||||
|
|||||||
+39
@@ -36,8 +36,10 @@ import org.apache.fineract.portfolio.savings.SavingsPeriodFrequencyType;
|
|||||||
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
|
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||||
import org.apache.fineract.portfolio.savings.SavingsWithdrawalFeesType;
|
import org.apache.fineract.portfolio.savings.SavingsWithdrawalFeesType;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData;
|
||||||
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountSubStatusEnumData;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionEnumData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionEnumData;
|
||||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType;
|
import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType;
|
||||||
|
import org.apache.fineract.portfolio.savings.domain.SavingsAccountSubStatusEnum;
|
||||||
|
|
||||||
public class SavingsEnumerations {
|
public class SavingsEnumerations {
|
||||||
|
|
||||||
@@ -187,6 +189,10 @@ public class SavingsEnumerations {
|
|||||||
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.DIVIDEND_PAYOUT.getValue().longValue(),
|
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.DIVIDEND_PAYOUT.getValue().longValue(),
|
||||||
SavingsAccountTransactionType.DIVIDEND_PAYOUT.getCode(), "Dividend Payout");
|
SavingsAccountTransactionType.DIVIDEND_PAYOUT.getCode(), "Dividend Payout");
|
||||||
break;
|
break;
|
||||||
|
case ESCHEAT:
|
||||||
|
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.ESCHEAT.getValue().longValue(),
|
||||||
|
SavingsAccountTransactionType.ESCHEAT.getCode(), "Escheat");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return optionData;
|
return optionData;
|
||||||
}
|
}
|
||||||
@@ -278,6 +284,39 @@ public class SavingsEnumerations {
|
|||||||
return optionData;
|
return optionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static SavingsAccountSubStatusEnumData subStatus(final Integer subStatusEnum) {
|
||||||
|
return subStatus(SavingsAccountSubStatusEnum.fromInt(subStatusEnum));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SavingsAccountSubStatusEnumData subStatus(final SavingsAccountSubStatusEnum type) {
|
||||||
|
|
||||||
|
final boolean none = type.isSubStatusNone();
|
||||||
|
final boolean inactive = type.isSubStatusInactive();
|
||||||
|
final boolean dormant = type.isSubStatusDormant();
|
||||||
|
final boolean escheat = type.isSubStatusEscheat();
|
||||||
|
|
||||||
|
SavingsAccountSubStatusEnumData optionData = new SavingsAccountSubStatusEnumData(SavingsAccountSubStatusEnum.NONE.getValue().longValue(),
|
||||||
|
SavingsAccountSubStatusEnum.NONE.getCode(), "None", true, inactive, dormant, escheat);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case INACTIVE:
|
||||||
|
optionData = new SavingsAccountSubStatusEnumData(SavingsAccountSubStatusEnum.INACTIVE.getValue().longValue(),
|
||||||
|
SavingsAccountSubStatusEnum.INACTIVE.getCode(), "Inactive", none, inactive, dormant, escheat);
|
||||||
|
break;
|
||||||
|
case DORMANT:
|
||||||
|
optionData = new SavingsAccountSubStatusEnumData(SavingsAccountSubStatusEnum.DORMANT.getValue().longValue(),
|
||||||
|
SavingsAccountSubStatusEnum.DORMANT.getCode(), "Dormant", none, inactive, dormant, escheat);
|
||||||
|
break;
|
||||||
|
case ESCHEAT:
|
||||||
|
optionData = new SavingsAccountSubStatusEnumData(SavingsAccountSubStatusEnum.ESCHEAT.getValue().longValue(),
|
||||||
|
SavingsAccountSubStatusEnum.ESCHEAT.getCode(), "Escheat", none, inactive, dormant, escheat);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return optionData;
|
||||||
|
}
|
||||||
|
|
||||||
public static EnumOptionData interestPostingPeriodType(final Integer type) {
|
public static EnumOptionData interestPostingPeriodType(final Integer type) {
|
||||||
return interestPostingPeriodType(SavingsPostingInterestPeriodType.fromInt(type));
|
return interestPostingPeriodType(SavingsPostingInterestPeriodType.fromInt(type));
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-2
@@ -134,7 +134,11 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
|||||||
sqlBuilder.append("sp.min_balance_for_interest_calculation as minBalanceForInterestCalculation,");
|
sqlBuilder.append("sp.min_balance_for_interest_calculation as minBalanceForInterestCalculation,");
|
||||||
sqlBuilder.append("sp.accounting_type as accountingType, ");
|
sqlBuilder.append("sp.accounting_type as accountingType, ");
|
||||||
sqlBuilder.append("sp.withhold_tax as withHoldTax,");
|
sqlBuilder.append("sp.withhold_tax as withHoldTax,");
|
||||||
sqlBuilder.append("tg.id as taxGroupId, tg.name as taxGroupName ");
|
sqlBuilder.append("tg.id as taxGroupId, tg.name as taxGroupName, ");
|
||||||
|
sqlBuilder.append("sp.is_dormancy_tracking_active as isDormancyTrackingActive,");
|
||||||
|
sqlBuilder.append("sp.days_to_inactive as daysToInactive,");
|
||||||
|
sqlBuilder.append("sp.days_to_dormancy as daysToDormancy,");
|
||||||
|
sqlBuilder.append("sp.days_to_escheat as daysToEscheat ");
|
||||||
sqlBuilder.append("from m_savings_product sp ");
|
sqlBuilder.append("from m_savings_product sp ");
|
||||||
sqlBuilder.append("join m_currency curr on curr.code = sp.currency_code ");
|
sqlBuilder.append("join m_currency curr on curr.code = sp.currency_code ");
|
||||||
sqlBuilder.append("left join m_tax_group tg on tg.id = sp.tax_group_id ");
|
sqlBuilder.append("left join m_tax_group tg on tg.id = sp.tax_group_id ");
|
||||||
@@ -211,12 +215,17 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
|||||||
taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName);
|
taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Boolean isDormancyTrackingActive = rs.getBoolean("isDormancyTrackingActive");
|
||||||
|
final Long daysToInactive = JdbcSupport.getLong(rs, "daysToInactive");
|
||||||
|
final Long daysToDormancy = JdbcSupport.getLong(rs, "daysToDormancy");
|
||||||
|
final Long daysToEscheat = JdbcSupport.getLong(rs, "daysToEscheat");
|
||||||
|
|
||||||
return SavingsProductData.instance(id, name, shortName, description, currency, nominalAnnualInterestRate,
|
return SavingsProductData.instance(id, name, shortName, description, currency, nominalAnnualInterestRate,
|
||||||
compoundingInterestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
compoundingInterestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers,
|
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers,
|
||||||
accountingRuleType, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
accountingRuleType, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
||||||
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
|
||||||
taxGroupData);
|
taxGroupData, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -145,11 +145,11 @@ public class SavingsProductWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
this.context.authenticatedUser();
|
this.context.authenticatedUser();
|
||||||
this.fromApiJsonDataValidator.validateForUpdate(command.json());
|
|
||||||
|
|
||||||
final SavingsProduct product = this.savingProductRepository.findOne(productId);
|
final SavingsProduct product = this.savingProductRepository.findOne(productId);
|
||||||
if (product == null) { throw new SavingsProductNotFoundException(productId); }
|
if (product == null) { throw new SavingsProductNotFoundException(productId); }
|
||||||
|
|
||||||
|
this.fromApiJsonDataValidator.validateForUpdate(command.json(), product);
|
||||||
|
|
||||||
final Map<String, Object> changes = product.update(command);
|
final Map<String, Object> changes = product.update(command);
|
||||||
|
|
||||||
if (changes.containsKey(chargesParamName)) {
|
if (changes.containsKey(chargesParamName)) {
|
||||||
|
|||||||
+2
@@ -25,4 +25,6 @@ public interface SavingsSchedularService {
|
|||||||
|
|
||||||
void postInterestForAccounts() throws JobExecutionException;
|
void postInterestForAccounts() throws JobExecutionException;
|
||||||
|
|
||||||
|
void updateSavingsDormancyStatus() throws JobExecutionException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-1
@@ -20,6 +20,7 @@ package org.apache.fineract.portfolio.savings.service;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.jobs.annotation.CronTarget;
|
import org.apache.fineract.infrastructure.jobs.annotation.CronTarget;
|
||||||
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
|
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
|
||||||
import org.apache.fineract.infrastructure.jobs.service.JobName;
|
import org.apache.fineract.infrastructure.jobs.service.JobName;
|
||||||
@@ -27,6 +28,7 @@ import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
|||||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
|
import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
|
||||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepository;
|
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepository;
|
||||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType;
|
import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType;
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -36,14 +38,17 @@ public class SavingsSchedularServiceImpl implements SavingsSchedularService {
|
|||||||
private final SavingsAccountAssembler savingAccountAssembler;
|
private final SavingsAccountAssembler savingAccountAssembler;
|
||||||
private final SavingsAccountWritePlatformService savingsAccountWritePlatformService;
|
private final SavingsAccountWritePlatformService savingsAccountWritePlatformService;
|
||||||
private final SavingsAccountRepository savingAccountRepository;
|
private final SavingsAccountRepository savingAccountRepository;
|
||||||
|
private final SavingsAccountReadPlatformService savingAccountReadPlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public SavingsSchedularServiceImpl(final SavingsAccountAssembler savingAccountAssembler,
|
public SavingsSchedularServiceImpl(final SavingsAccountAssembler savingAccountAssembler,
|
||||||
final SavingsAccountWritePlatformService savingsAccountWritePlatformService,
|
final SavingsAccountWritePlatformService savingsAccountWritePlatformService,
|
||||||
final SavingsAccountRepository savingAccountRepository) {
|
final SavingsAccountRepository savingAccountRepository,
|
||||||
|
final SavingsAccountReadPlatformService savingAccountReadPlatformService) {
|
||||||
this.savingAccountAssembler = savingAccountAssembler;
|
this.savingAccountAssembler = savingAccountAssembler;
|
||||||
this.savingsAccountWritePlatformService = savingsAccountWritePlatformService;
|
this.savingsAccountWritePlatformService = savingsAccountWritePlatformService;
|
||||||
this.savingAccountRepository = savingAccountRepository;
|
this.savingAccountRepository = savingAccountRepository;
|
||||||
|
this.savingAccountReadPlatformService = savingAccountReadPlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@CronTarget(jobName = JobName.POST_INTEREST_FOR_SAVINGS)
|
@CronTarget(jobName = JobName.POST_INTEREST_FOR_SAVINGS)
|
||||||
@@ -68,4 +73,34 @@ public class SavingsSchedularServiceImpl implements SavingsSchedularService {
|
|||||||
|
|
||||||
if (sb.length() > 0) { throw new JobExecutionException(sb.toString()); }
|
if (sb.length() > 0) { throw new JobExecutionException(sb.toString()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CronTarget(jobName = JobName.UPDATE_SAVINGS_DORMANT_ACCOUNTS)
|
||||||
|
@Override
|
||||||
|
public void updateSavingsDormancyStatus() throws JobExecutionException {
|
||||||
|
final LocalDate tenantLocalDate = DateUtils.getLocalDateOfTenant();
|
||||||
|
|
||||||
|
final List<Long> savingsPendingInactive = this.savingAccountReadPlatformService
|
||||||
|
.retrieveSavingsIdsPendingInactive(tenantLocalDate);
|
||||||
|
if(null != savingsPendingInactive && savingsPendingInactive.size() > 0){
|
||||||
|
for(Long savingsId : savingsPendingInactive){
|
||||||
|
this.savingsAccountWritePlatformService.setSubStatusInactive(savingsId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Long> savingsPendingDormant = this.savingAccountReadPlatformService
|
||||||
|
.retrieveSavingsIdsPendingDormant(tenantLocalDate);
|
||||||
|
if(null != savingsPendingDormant && savingsPendingDormant.size() > 0){
|
||||||
|
for(Long savingsId : savingsPendingDormant){
|
||||||
|
this.savingsAccountWritePlatformService.setSubStatusDormant(savingsId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Long> savingsPendingEscheat = this.savingAccountReadPlatformService
|
||||||
|
.retrieveSavingsIdsPendingEscheat(tenantLocalDate);
|
||||||
|
if(null != savingsPendingEscheat && savingsPendingEscheat.size() > 0){
|
||||||
|
for(Long savingsId : savingsPendingEscheat){
|
||||||
|
this.savingsAccountWritePlatformService.escheat(savingsId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
ALTER TABLE `m_savings_product`
|
||||||
|
ADD COLUMN `is_dormancy_tracking_active` SMALLINT(1) NULL,
|
||||||
|
ADD COLUMN `days_to_inactive` INT(11) NULL,
|
||||||
|
ADD COLUMN `days_to_dormancy` INT(11) NULL,
|
||||||
|
ADD COLUMN `days_to_escheat` INT(11) NULL;
|
||||||
|
|
||||||
|
ALTER TABLE `m_savings_account`
|
||||||
|
ADD COLUMN `sub_status_enum` SMALLINT(5) NOT NULL DEFAULT '0' AFTER `status_enum`;
|
||||||
|
|
||||||
|
INSERT INTO `job` (`name`, `display_name`, `cron_expression`, `create_time`) VALUES ('Update Savings Dormant Accounts', 'Update Savings Dormant Accounts', '0 0 0 1/1 * ? *', now());
|
||||||
|
|
||||||
|
INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_category`, `report_sql`, `description`, `core_report`, `use_report`) VALUES ('Savings Accounts Dormancy Report', 'Table', 'Savings', 'select cl.display_name as \'Client Display Name\',\r\nsa.account_no as \'Account Number\',\r\ncl.mobile_no as \'Mobile Number\',\r\n@lastdate:=(select IFNULL(max(sat.transaction_date),sa.activatedon_date) \r\n from m_savings_account_transaction as sat \r\n where sat.is_reversed = 0 \r\n and sat.transaction_type_enum in (1,2) \r\n and sat.savings_account_id = sa.id) as \'Date of Last Activity\',\r\nDATEDIFF(now(), @lastdate) as \'Days Since Last Activity\'\r\nfrom m_savings_account as sa \r\ninner join m_savings_product as sp on (sa.product_id = sp.id and sp.is_dormancy_tracking_active = 1) \r\nleft join m_client as cl on sa.client_id = cl.id \r\nwhere sa.sub_status_enum = ${subStatus}\r\nand cl.office_id = ${officeId}', NULL, 1, 1);
|
||||||
|
|
||||||
|
INSERT INTO `stretchy_parameter` (`parameter_name`, `parameter_variable`, `parameter_label`, `parameter_displayType`, `parameter_FormatType`, `parameter_default`, `parameter_sql`) VALUES ('SavingsAccountSubStatus', 'subStatus', 'SavingsAccountDormancyStatus', 'select', 'number', '100', 'select * from\r\n(select 100 as id, "Inactive" as name union all\r\nselect 200 as id, "Dormant" as name union all \r\nselect 300 as id, "Escheat" as name) x\r\norder by x.`id`');
|
||||||
|
|
||||||
|
INSERT INTO stretchy_report_parameter (report_id, parameter_id) VALUES ((select sr.id From stretchy_report sr where sr.report_name='Savings Accounts Dormancy Report'),(select sp.id from stretchy_parameter sp where sp.parameter_name='SavingsAccountSubStatus'));
|
||||||
|
|
||||||
|
INSERT INTO stretchy_report_parameter (report_id, parameter_id) VALUES ((select sr.id From stretchy_report sr where sr.report_name='Savings Accounts Dormancy Report'),(select sp.id from stretchy_parameter sp where sp.parameter_name='OfficeIdSelectOne'));
|
||||||
Reference in New Issue
Block a user