Move withdrawal and annual fee charges to charges workflow
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
ALTER TABLE `m_savings_account_charge`
|
||||
ADD COLUMN `is_active` TINYINT(1) NOT NULL DEFAULT '1' AFTER `waived`;
|
||||
|
||||
ALTER TABLE `m_savings_account`
|
||||
DROP COLUMN `withdrawal_fee_amount`,
|
||||
DROP COLUMN `withdrawal_fee_type_enum`;
|
||||
|
||||
ALTER TABLE `m_savings_account_charge`
|
||||
ADD COLUMN `fee_on_month` SMALLINT(5) NULL DEFAULT NULL AFTER `due_for_collection_as_of_date`,
|
||||
ADD COLUMN `fee_on_day` SMALLINT(5) NULL DEFAULT NULL AFTER `fee_on_month`;
|
||||
|
||||
ALTER TABLE `m_savings_account_charge`
|
||||
CHANGE COLUMN `due_for_collection_as_of_date` `charge_due_date` DATE NULL DEFAULT NULL AFTER `charge_time_enum`;
|
||||
|
||||
|
||||
ALTER TABLE `m_savings_account`
|
||||
DROP COLUMN `annual_fee_amount`,
|
||||
DROP COLUMN `annual_fee_on_month`,
|
||||
DROP COLUMN `annual_fee_on_day`,
|
||||
DROP COLUMN `annual_fee_next_due_date`;
|
||||
|
||||
ALTER TABLE `m_savings_product`
|
||||
DROP COLUMN `annual_fee_amount`,
|
||||
DROP COLUMN `annual_fee_on_month`,
|
||||
DROP COLUMN `annual_fee_on_day`;
|
||||
+2
-2
@@ -419,9 +419,9 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
handler = this.applicationContext.getBean("calculateInterestSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isSavingsAccountInterestPosting()) {
|
||||
handler = this.applicationContext.getBean("postInterestSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isSavingsAccountApplyAnnualFee()) {
|
||||
} /*else if (wrapper.isSavingsAccountApplyAnnualFee()) {
|
||||
handler = this.applicationContext.getBean("applyAnnualFeeSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isSavingsAccountUndoTransaction()) {
|
||||
} */else if (wrapper.isSavingsAccountUndoTransaction()) {
|
||||
handler = this.applicationContext.getBean("undoTransactionSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isAdjustSavingsAccountTransaction()) {
|
||||
handler = this.applicationContext.getBean("savingsTransactionAdjustmentCommandHandler", NewCommandSourceHandler.class);
|
||||
|
||||
+9
@@ -149,6 +149,11 @@ public class FromJsonHelper {
|
||||
public MonthDay extractMonthDayNamed(final String parameterName, final JsonElement element) {
|
||||
return this.helperDelegator.extractMonthDayNamed(parameterName, element);
|
||||
}
|
||||
|
||||
public MonthDay extractMonthDayNamed(final String parameterName, final JsonObject object, final String dateFormat,
|
||||
final Locale clientApplicationLocale) {
|
||||
return this.helperDelegator.extractMonthDayNamed(parameterName, object, dateFormat, clientApplicationLocale);
|
||||
}
|
||||
|
||||
public LocalDate extractLocalDateNamed(final String parameterName, final JsonElement element) {
|
||||
return this.helperDelegator.extractLocalDateNamed(parameterName, element, new HashSet<String>());
|
||||
@@ -216,4 +221,8 @@ public class FromJsonHelper {
|
||||
public String extractDateFormatParameter(final JsonObject element) {
|
||||
return this.helperDelegator.extractDateFormatParameter(element);
|
||||
}
|
||||
|
||||
public String extractMonthDayFormatParameter(final JsonObject element) {
|
||||
return this.helperDelegator.extractMonthDayFormatParameter(element);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -64,7 +64,7 @@ public class DateUtils {
|
||||
return formattedSqlDate;
|
||||
}
|
||||
|
||||
public static boolean isInFuture(final LocalDate date){
|
||||
return date.isAfter(getLocalDateOfTenant());
|
||||
public static boolean isDateInTheFuture(final LocalDate localDate){
|
||||
return localDate.isAfter(getLocalDateOfTenant());
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -11,6 +11,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData;
|
||||
@@ -176,9 +177,10 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
final BigDecimal amountPercentageAppliedTo = BigDecimal.ZERO;
|
||||
final Collection<ChargeData> chargeOptions = null;
|
||||
final LocalDate dueAsOfDate = null;
|
||||
final MonthDay feeOnMonthDay = null;
|
||||
|
||||
return SavingsAccountChargeData.instance(savingsChargeId, this.id, this.name, this.currency, this.amount, amountPaid, amountWaived,
|
||||
amountWrittenOff, amountOutstanding, this.chargeTimeType, dueAsOfDate, this.chargeCalculationType, percentage,
|
||||
amountPercentageAppliedTo, chargeOptions, this.penalty);
|
||||
amountPercentageAppliedTo, chargeOptions, this.penalty, feeOnMonthDay);
|
||||
}
|
||||
}
|
||||
@@ -114,6 +114,11 @@ public class Charge extends AbstractPersistable<Long> {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.savings");
|
||||
}
|
||||
|
||||
if (!ChargeTimeType.fromInt(getChargeTime()).isWithdrawalFee() && ChargeCalculationType.fromInt(getChargeCalculation()).isPercentageOfAmount()) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode("charge.calculation.type.percentage.allowed.only.for.withdrawal");
|
||||
}
|
||||
|
||||
} else if (isLoanCharge()) {
|
||||
|
||||
@@ -277,6 +282,11 @@ public class Charge extends AbstractPersistable<Long> {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.savings");
|
||||
}
|
||||
|
||||
if (!ChargeTimeType.fromInt(getChargeTime()).isWithdrawalFee() && ChargeCalculationType.fromInt(getChargeCalculation()).isPercentageOfAmount()) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode("charge.calculation.type.percentage.allowed.only.for.withdrawal");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -57,6 +57,6 @@ public enum ChargeCalculationType {
|
||||
}
|
||||
|
||||
public boolean isAllowedSavingsChargeCalculationType() {
|
||||
return isFlat();
|
||||
return isFlat() || isPercentageOfAmount();
|
||||
}
|
||||
}
|
||||
+32
-10
@@ -8,8 +8,12 @@ package org.mifosplatform.portfolio.charge.domain;
|
||||
public enum ChargeTimeType {
|
||||
|
||||
INVALID(0, "chargeTimeType.invalid"), //
|
||||
DISBURSEMENT(1, "chargeTimeType.disbursement"), //
|
||||
SPECIFIED_DUE_DATE(2, "chargeTimeType.specifiedDueDate"), MONTHLY(3, "chargeTimeType.monthly"), YEARLY(4, "chargeTimeType.yearly");
|
||||
DISBURSEMENT(1, "chargeTimeType.disbursement"), //only for loan charges
|
||||
SPECIFIED_DUE_DATE(2, "chargeTimeType.specifiedDueDate"), // for loan and savings charges
|
||||
SAVINGS_ACTIVATION(3, "chargeTimeType.savingsActivation"), // only for savings
|
||||
SAVINGS_CLOSURE(4, "chargeTimeType.savingsClosure"), // only for savings
|
||||
WITHDRAWAL_FEE(5, "chargeTimeType.withdrawalFee"), // only for savings
|
||||
ANNUAL_FEE(6, "chargeTimeType.annualFee"); // only for savings
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
@@ -32,7 +36,11 @@ public enum ChargeTimeType {
|
||||
}
|
||||
|
||||
public static int maxValue() {
|
||||
return 4;
|
||||
int max = 1;// Default it to one (1)
|
||||
for (ChargeTimeType chargeTimeType : ChargeTimeType.values()) {
|
||||
max = (chargeTimeType.getValue() > max) ? chargeTimeType.getValue() : max;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
public static ChargeTimeType fromInt(final Integer chargeTime) {
|
||||
@@ -45,10 +53,16 @@ public enum ChargeTimeType {
|
||||
chargeTimeType = SPECIFIED_DUE_DATE;
|
||||
break;
|
||||
case 3:
|
||||
chargeTimeType = MONTHLY;
|
||||
chargeTimeType = SAVINGS_ACTIVATION;
|
||||
break;
|
||||
case 4:
|
||||
chargeTimeType = YEARLY;
|
||||
chargeTimeType = SAVINGS_CLOSURE;
|
||||
break;
|
||||
case 5:
|
||||
chargeTimeType = WITHDRAWAL_FEE;
|
||||
break;
|
||||
case 6:
|
||||
chargeTimeType = ANNUAL_FEE;
|
||||
break;
|
||||
default:
|
||||
chargeTimeType = INVALID;
|
||||
@@ -65,12 +79,20 @@ public enum ChargeTimeType {
|
||||
return this.value.equals(ChargeTimeType.SPECIFIED_DUE_DATE.getValue());
|
||||
}
|
||||
|
||||
public boolean isMonthly() {
|
||||
return this.value.equals(ChargeTimeType.MONTHLY.getValue());
|
||||
public boolean isSavingsActivation() {
|
||||
return this.value.equals(ChargeTimeType.SAVINGS_ACTIVATION.getValue());
|
||||
}
|
||||
|
||||
public boolean isYearly() {
|
||||
return this.value.equals(ChargeTimeType.YEARLY.getValue());
|
||||
public boolean isSavingsClosure() {
|
||||
return this.value.equals(ChargeTimeType.SAVINGS_CLOSURE.getValue());
|
||||
}
|
||||
|
||||
public boolean isWithdrawalFee() {
|
||||
return this.value.equals(ChargeTimeType.WITHDRAWAL_FEE.getValue());
|
||||
}
|
||||
|
||||
public boolean isAnnualFee() {
|
||||
return this.value.equals(ChargeTimeType.ANNUAL_FEE.getValue());
|
||||
}
|
||||
|
||||
public boolean isAllowedLoanChargeTime() {
|
||||
@@ -78,6 +100,6 @@ public enum ChargeTimeType {
|
||||
}
|
||||
|
||||
public boolean isAllowedSavingsChargeTime() {
|
||||
return isOnSpecifiedDueDate() || isMonthly() || isYearly();
|
||||
return isOnSpecifiedDueDate() || isSavingsActivation() || isSavingsClosure() || isWithdrawalFee() || isAnnualFee();
|
||||
}
|
||||
}
|
||||
+6
-17
@@ -49,15 +49,7 @@ public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownRead
|
||||
public List<EnumOptionData> retrieveCollectionTimeTypes() {
|
||||
final List<EnumOptionData> chargeTimeTypes = new ArrayList<EnumOptionData>();
|
||||
for (final ChargeTimeType chargeTimeType : ChargeTimeType.values()) {
|
||||
if (ChargeTimeType.INVALID.equals(chargeTimeType) || ChargeTimeType.MONTHLY.equals(chargeTimeType) // To
|
||||
// be
|
||||
// implemented
|
||||
// for
|
||||
// Savings
|
||||
|| ChargeTimeType.YEARLY.equals(chargeTimeType)) {
|
||||
// implemented
|
||||
// for
|
||||
// Savings
|
||||
if (ChargeTimeType.INVALID.equals(chargeTimeType)) {
|
||||
continue;
|
||||
}
|
||||
chargeTimeTypes.add(ChargeEnumerations.chargeTimeType(chargeTimeType));
|
||||
@@ -82,17 +74,14 @@ public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownRead
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveSavingsCalculationTypes() {
|
||||
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT)
|
||||
//Enable when percentage of amount is supported for savings charges
|
||||
//, chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT)
|
||||
);
|
||||
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT),
|
||||
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveSavingsCollectionTimeTypes() {
|
||||
return Arrays.asList(chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE)
|
||||
//enable when support is added for recurring Monthly and yearly charges
|
||||
//, chargeTimeType(ChargeTimeType.MONTHLY), chargeTimeType(ChargeTimeType.YEARLY)
|
||||
);
|
||||
return Arrays.asList(chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE), chargeTimeType(ChargeTimeType.SAVINGS_ACTIVATION),
|
||||
chargeTimeType(ChargeTimeType.SAVINGS_CLOSURE), chargeTimeType(ChargeTimeType.WITHDRAWAL_FEE),
|
||||
chargeTimeType(ChargeTimeType.ANNUAL_FEE));
|
||||
}
|
||||
}
|
||||
+10
-4
@@ -28,11 +28,17 @@ public class ChargeEnumerations {
|
||||
optionData = new EnumOptionData(ChargeTimeType.SPECIFIED_DUE_DATE.getValue().longValue(),
|
||||
ChargeTimeType.SPECIFIED_DUE_DATE.getCode(), "Specified due date");
|
||||
break;
|
||||
case MONTHLY:
|
||||
optionData = new EnumOptionData(ChargeTimeType.MONTHLY.getValue().longValue(), ChargeTimeType.MONTHLY.getCode(), "Monthly");
|
||||
case SAVINGS_ACTIVATION:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SAVINGS_ACTIVATION.getValue().longValue(), ChargeTimeType.SAVINGS_ACTIVATION.getCode(), "Savings Activation");
|
||||
break;
|
||||
case YEARLY:
|
||||
optionData = new EnumOptionData(ChargeTimeType.YEARLY.getValue().longValue(), ChargeTimeType.YEARLY.getCode(), "Yearly");
|
||||
case SAVINGS_CLOSURE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SAVINGS_CLOSURE.getValue().longValue(), ChargeTimeType.SAVINGS_CLOSURE.getCode(), "Savings Closure");
|
||||
break;
|
||||
case WITHDRAWAL_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.WITHDRAWAL_FEE.getValue().longValue(), ChargeTimeType.WITHDRAWAL_FEE.getCode(), "Withdrawal Fee");
|
||||
break;
|
||||
case ANNUAL_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.ANNUAL_FEE.getValue().longValue(), ChargeTimeType.ANNUAL_FEE.getCode(), "Annual Fee");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(ChargeTimeType.INVALID.getValue().longValue(), ChargeTimeType.INVALID.getCode(), "Invalid");
|
||||
|
||||
+6
-2
@@ -105,9 +105,13 @@ public enum SavingsAccountTransactionType {
|
||||
return this.value.equals(SavingsAccountTransactionType.ANNUAL_FEE.getValue());
|
||||
}
|
||||
|
||||
public boolean isCharge() {
|
||||
public boolean isPayCharge() {
|
||||
return this.value.equals(SavingsAccountTransactionType.PAY_CHARGE.getValue());
|
||||
}
|
||||
|
||||
public boolean isChargeTransaction(){
|
||||
return isPayCharge() || isWithdrawalFee() || isAnnualFee();
|
||||
}
|
||||
|
||||
public boolean isWaiveCharge() {
|
||||
return this.value.equals(SavingsAccountTransactionType.WAIVE_CHARGES.getValue());
|
||||
@@ -130,7 +134,7 @@ public enum SavingsAccountTransactionType {
|
||||
}
|
||||
|
||||
public boolean isDebit() {
|
||||
return isWithdrawal() || isWithdrawalFee() || isAnnualFee() || isCharge();
|
||||
return isWithdrawal() || isWithdrawalFee() || isAnnualFee() || isPayCharge();
|
||||
}
|
||||
|
||||
public boolean isCredit() {
|
||||
|
||||
+19
-11
@@ -81,8 +81,8 @@ public class SavingsApiConstants {
|
||||
public static final String withdrawalFeeAmountParamName = "withdrawalFeeAmount";
|
||||
public static final String withdrawalFeeTypeParamName = "withdrawalFeeType";
|
||||
public static final String withdrawalFeeForTransfersParamName = "withdrawalFeeForTransfers";
|
||||
public static final String annualFeeAmountParamName = "annualFeeAmount";
|
||||
public static final String annualFeeOnMonthDayParamName = "annualFeeOnMonthDay";
|
||||
public static final String feeAmountParamName = "feeAmount";//to be deleted
|
||||
public static final String feeOnMonthDayParamName = "feeOnMonthDay";
|
||||
public static final String accountingRuleParamName = "accountingRule";
|
||||
public static final String paymentTypeIdParamName = "paymentTypeId";
|
||||
public static final String transactionAccountNumberParamName = "accountNumber";
|
||||
@@ -118,16 +118,22 @@ public class SavingsApiConstants {
|
||||
public static final String amountParamName = "amount";
|
||||
public static final String amountPaidParamName = "amountPaid";
|
||||
public static final String chargeOptionsParamName = "chargeOptions";
|
||||
public static final String chargePaymentModeParamName = "chargePaymentMode";
|
||||
|
||||
public static final String noteParamName = "note";
|
||||
|
||||
//Savings account associations
|
||||
public static final String transactions = "transactions";
|
||||
public static final String charges = "charges";
|
||||
|
||||
|
||||
public static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||
monthDayFormatParamName, nameParamName, descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName,
|
||||
inMultiplesOfParamName, nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName,
|
||||
interestPostingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
|
||||
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
|
||||
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, withdrawalFeeForTransfersParamName, annualFeeAmountParamName,
|
||||
annualFeeOnMonthDayParamName, accountingRuleParamName, chargesParamName,
|
||||
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, withdrawalFeeForTransfersParamName, feeAmountParamName,
|
||||
feeOnMonthDayParamName, accountingRuleParamName, chargesParamName,
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(),
|
||||
@@ -147,7 +153,7 @@ public class SavingsApiConstants {
|
||||
nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName,
|
||||
interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName,
|
||||
lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName,
|
||||
withdrawalFeeForTransfersParamName, annualFeeAmountParamName, annualFeeOnMonthDayParamName, "currencyOptions",
|
||||
withdrawalFeeForTransfersParamName, feeAmountParamName, feeOnMonthDayParamName, "currencyOptions",
|
||||
"interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions", "interestCalculationTypeOptions",
|
||||
"interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions"));
|
||||
|
||||
@@ -156,8 +162,10 @@ public class SavingsApiConstants {
|
||||
productIdParamName, fieldOfficerIdParamName, submittedOnDateParamName, nominalAnnualInterestRateParamName,
|
||||
interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
|
||||
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
|
||||
lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName,
|
||||
withdrawalFeeForTransfersParamName, annualFeeAmountParamName, annualFeeOnMonthDayParamName, chargesParamName));
|
||||
lockinPeriodFrequencyTypeParamName,
|
||||
//withdrawalFeeAmountParamName, withdrawalFeeTypeParamName,
|
||||
//withdrawalFeeForTransfersParamName,
|
||||
feeAmountParamName, feeOnMonthDayParamName, chargesParamName));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of
|
||||
@@ -169,10 +177,10 @@ public class SavingsApiConstants {
|
||||
groupIdParamName, "groupName", "savingsProductId", "savingsProductName", "currency", nominalAnnualInterestRateParamName,
|
||||
interestCompoundingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
|
||||
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
|
||||
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, withdrawalFeeForTransfersParamName, annualFeeAmountParamName,
|
||||
annualFeeOnMonthDayParamName, "summary", "transactions", "productOptions", "interestCompoundingPeriodTypeOptions",
|
||||
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, withdrawalFeeForTransfersParamName, feeAmountParamName,
|
||||
feeOnMonthDayParamName, "summary", "transactions", "productOptions", "interestCompoundingPeriodTypeOptions",
|
||||
"interestPostingPeriodTypeOptions", "interestCalculationTypeOptions", "interestCalculationDaysInYearTypeOptions",
|
||||
"lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions"));
|
||||
"lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions", "withdrawalFee", "annualFee"));
|
||||
|
||||
public static final Set<String> SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(
|
||||
localeParamName, dateFormatParamName, transactionDateParamName, transactionAmountParamName, paymentTypeIdParamName,
|
||||
@@ -195,7 +203,7 @@ public class SavingsApiConstants {
|
||||
amountPaidParamName, chargeOptionsParamName));
|
||||
|
||||
public static final Set<String> SAVINGS_ACCOUNT_CHARGES_ADD_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(
|
||||
chargeIdParamName, amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName));
|
||||
chargeIdParamName, amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName, feeOnMonthDayParamName, monthDayFormatParamName));
|
||||
|
||||
public static final Set<String> SAVINGS_ACCOUNT_CHARGES_PAY_CHARGE_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(
|
||||
amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName));
|
||||
|
||||
+5
-5
@@ -154,11 +154,11 @@ public class SavingsAccountsApiResource {
|
||||
if (!associationParameters.isEmpty()) {
|
||||
|
||||
if (associationParameters.contains("all")) {
|
||||
associationParameters.addAll(Arrays.asList("transactions", "charges"));
|
||||
associationParameters.addAll(Arrays.asList(SavingsApiConstants.transactions, SavingsApiConstants.charges));
|
||||
}
|
||||
|
||||
if (associationParameters.contains("transactions")) {
|
||||
mandatoryResponseParameters.add("transactions");
|
||||
if (associationParameters.contains(SavingsApiConstants.transactions)) {
|
||||
mandatoryResponseParameters.add(SavingsApiConstants.transactions);
|
||||
final Collection<SavingsAccountTransactionData> currentTransactions = this.savingsAccountReadPlatformService
|
||||
.retrieveAllTransactions(accountId);
|
||||
if (!CollectionUtils.isEmpty(currentTransactions)) {
|
||||
@@ -166,8 +166,8 @@ public class SavingsAccountsApiResource {
|
||||
}
|
||||
}
|
||||
|
||||
if (associationParameters.contains("charges")) {
|
||||
mandatoryResponseParameters.add("charges");
|
||||
if (associationParameters.contains(SavingsApiConstants.charges)) {
|
||||
mandatoryResponseParameters.add(SavingsApiConstants.charges);
|
||||
final Collection<SavingsAccountChargeData> currentCharges = this.savingsAccountChargeReadPlatformService
|
||||
.retrieveSavingsAccountCharges(accountId);
|
||||
if (!CollectionUtils.isEmpty(currentCharges)) {
|
||||
|
||||
+19
-5
@@ -9,9 +9,11 @@ import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.portfolio.charge.data.ChargeData;
|
||||
import org.mifosplatform.portfolio.charge.domain.ChargeTimeType;
|
||||
|
||||
/**
|
||||
* Immutable data object for Savings Account charge data.
|
||||
@@ -27,12 +29,14 @@ public class SavingsAccountChargeData {
|
||||
@SuppressWarnings("unused")
|
||||
private final String name;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final EnumOptionData chargeTimeType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final LocalDate dueDate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final MonthDay feeOnMonthDay;
|
||||
|
||||
private final EnumOptionData chargeCalculationType;
|
||||
|
||||
private final BigDecimal percentage;
|
||||
@@ -82,28 +86,30 @@ public class SavingsAccountChargeData {
|
||||
final BigDecimal percentage = BigDecimal.ZERO;
|
||||
final boolean penalty = false;
|
||||
final LocalDate dueAsOfDate = null;
|
||||
final MonthDay feeOnMonthDay = null;
|
||||
|
||||
|
||||
return new SavingsAccountChargeData(id, chargeId, name, chargeTimeType, dueAsOfDate, chargeCalculationType, percentage,
|
||||
amountPercentageAppliedTo, currency, amount, amountPaid, amountWaived, amountWrittenOff, amountOutstanding, chargeOptions,
|
||||
penalty);
|
||||
penalty, feeOnMonthDay);
|
||||
}
|
||||
|
||||
public static SavingsAccountChargeData instance(final Long id, final Long chargeId, final String name, final CurrencyData currency,
|
||||
final BigDecimal amount, final BigDecimal amountPaid, final BigDecimal amountWaived, final BigDecimal amountWrittenOff,
|
||||
final BigDecimal amountOutstanding, final EnumOptionData chargeTimeType, final LocalDate dueAsOfDate,
|
||||
final EnumOptionData chargeCalculationType, final BigDecimal percentage, final BigDecimal amountPercentageAppliedTo,
|
||||
final Collection<ChargeData> chargeOptions, final boolean penalty) {
|
||||
final Collection<ChargeData> chargeOptions, final boolean penalty, final MonthDay feeOnMonthDay) {
|
||||
|
||||
return new SavingsAccountChargeData(id, chargeId, name, chargeTimeType, dueAsOfDate, chargeCalculationType, percentage,
|
||||
amountPercentageAppliedTo, currency, amount, amountPaid, amountWaived, amountWrittenOff, amountOutstanding, chargeOptions,
|
||||
penalty);
|
||||
penalty, feeOnMonthDay);
|
||||
}
|
||||
|
||||
private SavingsAccountChargeData(final Long id, final Long chargeId, final String name, final EnumOptionData chargeTimeType,
|
||||
final LocalDate dueAsOfDate, final EnumOptionData chargeCalculationType, final BigDecimal percentage,
|
||||
final BigDecimal amountPercentageAppliedTo, final CurrencyData currency, final BigDecimal amount, final BigDecimal amountPaid,
|
||||
final BigDecimal amountWaived, final BigDecimal amountWrittenOff, final BigDecimal amountOutstanding,
|
||||
final Collection<ChargeData> chargeOptions, final boolean penalty) {
|
||||
final Collection<ChargeData> chargeOptions, final boolean penalty, final MonthDay feeOnMonthDay) {
|
||||
this.id = id;
|
||||
this.chargeId = chargeId;
|
||||
this.name = name;
|
||||
@@ -121,10 +127,18 @@ public class SavingsAccountChargeData {
|
||||
this.amountOrPercentage = getAmountOrPercentage();
|
||||
this.chargeOptions = chargeOptions;
|
||||
this.penalty = penalty;
|
||||
this.feeOnMonthDay = feeOnMonthDay;
|
||||
}
|
||||
|
||||
private BigDecimal getAmountOrPercentage() {
|
||||
return (this.chargeCalculationType != null) && (this.chargeCalculationType.getId().intValue() > 1) ? this.percentage : this.amount;
|
||||
}
|
||||
|
||||
public boolean isWithdrawalFee(){
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType.getId().intValue()).isWithdrawalFee();
|
||||
}
|
||||
|
||||
public boolean isAnnualFee(){
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType.getId().intValue()).isAnnualFee();
|
||||
}
|
||||
}
|
||||
+8
-1
@@ -11,6 +11,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_AC
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.amountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargeIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.dueAsOfDateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeOnMonthDayParamName;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
@@ -20,6 +21,7 @@ import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||
@@ -62,7 +64,12 @@ public class SavingsAccountChargeDataValidator {
|
||||
final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed(dueAsOfDateParamName, element);
|
||||
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(transactionDate).notNull();
|
||||
}
|
||||
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(feeOnMonthDayParamName, element)) {
|
||||
final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed(feeOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(feeOnMonthDayParamName).value(monthDay).notNull();
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
|
||||
+95
-50
@@ -7,11 +7,10 @@ package org.mifosplatform.portfolio.savings.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.organisation.staff.data.StaffData;
|
||||
@@ -44,18 +43,13 @@ public class SavingsAccountData {
|
||||
private final BigDecimal minRequiredOpeningBalance;
|
||||
private final Integer lockinPeriodFrequency;
|
||||
private final EnumOptionData lockinPeriodFrequencyType;
|
||||
private final BigDecimal withdrawalFeeAmount;
|
||||
private final EnumOptionData withdrawalFeeType;
|
||||
private final boolean withdrawalFeeForTransfers;
|
||||
private final BigDecimal annualFeeAmount;
|
||||
private final MonthDay annualFeeOnMonthDay;
|
||||
private final LocalDate annualFeeNextDueDate;
|
||||
|
||||
// associations
|
||||
private final SavingsAccountSummaryData summary;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<SavingsAccountTransactionData> transactions;
|
||||
@SuppressWarnings("unused")
|
||||
|
||||
private final Collection<SavingsAccountChargeData> charges;
|
||||
|
||||
// template
|
||||
@@ -69,6 +63,11 @@ public class SavingsAccountData {
|
||||
private final Collection<EnumOptionData> withdrawalFeeTypeOptions;
|
||||
private final Collection<ChargeData> chargeOptions;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final SavingsAccountChargeData withdrawalFee;
|
||||
@SuppressWarnings("unused")
|
||||
private final SavingsAccountChargeData annualFee;
|
||||
|
||||
public static SavingsAccountData instance(final Long id, final String accountNo, 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 SavingsAccountStatusEnumData status,
|
||||
@@ -76,9 +75,7 @@ public class SavingsAccountData {
|
||||
final EnumOptionData interestCompoundingPeriodType, final EnumOptionData interestPostingPeriodType,
|
||||
final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
|
||||
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
|
||||
final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount, final EnumOptionData withdrawalFeeType,
|
||||
final boolean withdrawalFeeForTransfers, final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay,
|
||||
final LocalDate annualFeeNextDueDate, final SavingsAccountSummaryData summary) {
|
||||
final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers, final SavingsAccountSummaryData summary) {
|
||||
|
||||
final Collection<SavingsProductData> productOptions = null;
|
||||
final Collection<StaffData> fieldOfficerOptions = null;
|
||||
@@ -96,15 +93,44 @@ public class SavingsAccountData {
|
||||
return new SavingsAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, status, timeline, currency, interestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, withdrawalFeeForTransfers,
|
||||
annualFeeAmount, annualFeeOnMonthDay, annualFeeNextDueDate, summary, transactions, productOptions, fieldOfficerOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges,
|
||||
chargeOptions);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions,
|
||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions);
|
||||
}
|
||||
|
||||
public static SavingsAccountData lookup(final Long accountId, final String accountNo) {
|
||||
|
||||
final String externalId = null;
|
||||
final Long productId = null;
|
||||
final Long groupId = null;
|
||||
final Long clientId = null;
|
||||
final String clientName = null;
|
||||
final String groupName = null;
|
||||
final String productName = null;
|
||||
final Long fieldOfficerId = null;
|
||||
final String fieldOfficerName = null;
|
||||
final SavingsAccountStatusEnumData status = null;
|
||||
final SavingsAccountApplicationTimelineData timeline = null;
|
||||
final CurrencyData currency = null;
|
||||
final BigDecimal nominalAnnualInterestRate = null;
|
||||
final EnumOptionData interestPeriodType = null;
|
||||
final EnumOptionData interestPostingPeriodType = null;
|
||||
final EnumOptionData interestCalculationType = null;
|
||||
final EnumOptionData interestCalculationDaysInYearType = null;
|
||||
final BigDecimal minRequiredOpeningBalance = null;
|
||||
final Integer lockinPeriodFrequency = null;
|
||||
final EnumOptionData lockinPeriodFrequencyType = null;
|
||||
// final BigDecimal withdrawalFeeAmount = null;
|
||||
// final EnumOptionData withdrawalFeeType = null;
|
||||
final boolean withdrawalFeeForTransfers = false;
|
||||
// final BigDecimal annualFeeAmount = null;
|
||||
// final MonthDay annualFeeOnMonthDay = null;
|
||||
// final LocalDate annualFeeNextDueDate = null;
|
||||
|
||||
final SavingsAccountSummaryData summary = null;
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
|
||||
final Collection<SavingsProductData> productOptions = null;
|
||||
final Collection<StaffData> fieldOfficerOptions = null;
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||
@@ -114,12 +140,13 @@ public class SavingsAccountData {
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
|
||||
final Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
|
||||
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
final Collection<SavingsAccountChargeData> charges = null;
|
||||
final Collection<ChargeData> chargeOptions = null;
|
||||
|
||||
return new SavingsAccountData(accountId, accountNo, null, null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, false, null, null, null, null, transactions, productOptions,
|
||||
return new SavingsAccountData(accountId, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId , fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions,
|
||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions);
|
||||
@@ -149,12 +176,11 @@ public class SavingsAccountData {
|
||||
account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate,
|
||||
account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType,
|
||||
account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance, account.lockinPeriodFrequency,
|
||||
account.lockinPeriodFrequencyType, account.withdrawalFeeAmount, account.withdrawalFeeType,
|
||||
account.withdrawalFeeForTransfers, account.annualFeeAmount, account.annualFeeOnMonthDay, account.annualFeeNextDueDate,
|
||||
account.summary, transactions, template.productOptions, template.fieldOfficerOptions,
|
||||
template.interestCompoundingPeriodTypeOptions, template.interestPostingPeriodTypeOptions,
|
||||
template.interestCalculationTypeOptions, template.interestCalculationDaysInYearTypeOptions,
|
||||
template.lockinPeriodFrequencyTypeOptions, template.withdrawalFeeTypeOptions, charges, template.chargeOptions);
|
||||
account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary, transactions,
|
||||
template.productOptions, template.fieldOfficerOptions, template.interestCompoundingPeriodTypeOptions,
|
||||
template.interestPostingPeriodTypeOptions, template.interestCalculationTypeOptions,
|
||||
template.interestCalculationDaysInYearTypeOptions, template.lockinPeriodFrequencyTypeOptions,
|
||||
template.withdrawalFeeTypeOptions, charges, template.chargeOptions);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
||||
@@ -172,11 +198,10 @@ public class SavingsAccountData {
|
||||
account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate,
|
||||
account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType,
|
||||
account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance, account.lockinPeriodFrequency,
|
||||
account.lockinPeriodFrequencyType, account.withdrawalFeeAmount, account.withdrawalFeeType,
|
||||
account.withdrawalFeeForTransfers, account.annualFeeAmount, account.annualFeeOnMonthDay, account.annualFeeNextDueDate,
|
||||
account.summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions);
|
||||
account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary, transactions, productOptions,
|
||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
||||
@@ -200,12 +225,12 @@ public class SavingsAccountData {
|
||||
final BigDecimal minRequiredOpeningBalance = null;
|
||||
final Integer lockinPeriodFrequency = null;
|
||||
final EnumOptionData lockinPeriodFrequencyType = null;
|
||||
final BigDecimal withdrawalFeeAmount = null;
|
||||
final EnumOptionData withdrawalFeeType = null;
|
||||
// final BigDecimal withdrawalFeeAmount = null;
|
||||
// final EnumOptionData withdrawalFeeType = null;
|
||||
final boolean withdrawalFeeForTransfers = false;
|
||||
final BigDecimal annualFeeAmount = null;
|
||||
final MonthDay annualFeeOnMonthDay = null;
|
||||
final LocalDate annualFeeNextDueDate = null;
|
||||
// final BigDecimal annualFeeAmount = null;
|
||||
// final MonthDay annualFeeOnMonthDay = null;
|
||||
// final LocalDate annualFeeNextDueDate = null;
|
||||
|
||||
final SavingsAccountSummaryData summary = null;
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
@@ -225,11 +250,10 @@ public class SavingsAccountData {
|
||||
return new SavingsAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, withdrawalFeeForTransfers,
|
||||
annualFeeAmount, annualFeeOnMonthDay, annualFeeNextDueDate, summary, transactions, productOptions, fieldOfficerOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges,
|
||||
chargeOptions);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions,
|
||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions);
|
||||
}
|
||||
|
||||
private SavingsAccountData(final Long id, final String accountNo, final String externalId, final Long groupId, final String groupName,
|
||||
@@ -238,11 +262,10 @@ public class SavingsAccountData {
|
||||
final CurrencyData currency, final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestPeriodType,
|
||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount,
|
||||
final EnumOptionData withdrawalFeeType, final boolean withdrawalFeeForTransfers, final BigDecimal annualFeeAmount,
|
||||
final MonthDay annualFeeOnMonthDay, final LocalDate annualFeeNextDueDate, final SavingsAccountSummaryData summary,
|
||||
final Collection<SavingsAccountTransactionData> transactions, final Collection<SavingsProductData> productOptions,
|
||||
final Collection<StaffData> fieldOfficerOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers,
|
||||
final SavingsAccountSummaryData summary, final Collection<SavingsAccountTransactionData> transactions,
|
||||
final Collection<SavingsProductData> productOptions, final Collection<StaffData> fieldOfficerOptions,
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
||||
@@ -270,12 +293,12 @@ public class SavingsAccountData {
|
||||
this.minRequiredOpeningBalance = minRequiredOpeningBalance;
|
||||
this.lockinPeriodFrequency = lockinPeriodFrequency;
|
||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType;
|
||||
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||
this.withdrawalFeeType = withdrawalFeeType;
|
||||
// this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||
// this.withdrawalFeeType = withdrawalFeeType;
|
||||
this.withdrawalFeeForTransfers = withdrawalFeeForTransfers;
|
||||
this.annualFeeAmount = annualFeeAmount;
|
||||
this.annualFeeOnMonthDay = annualFeeOnMonthDay;
|
||||
this.annualFeeNextDueDate = annualFeeNextDueDate;
|
||||
// this.annualFeeAmount = annualFeeAmount;
|
||||
// this.annualFeeOnMonthDay = annualFeeOnMonthDay;
|
||||
// this.annualFeeNextDueDate = annualFeeNextDueDate;
|
||||
|
||||
this.summary = summary;
|
||||
this.transactions = transactions;
|
||||
@@ -292,8 +315,26 @@ public class SavingsAccountData {
|
||||
this.charges = charges;// charges associated with Savings account
|
||||
// charges available for adding to Savings account
|
||||
this.chargeOptions = chargeOptions;
|
||||
|
||||
this.withdrawalFee = getWithdrawalFee();
|
||||
|
||||
this.annualFee = getAnnualFee();
|
||||
}
|
||||
|
||||
private SavingsAccountChargeData getWithdrawalFee() {
|
||||
for (SavingsAccountChargeData charge : this.charges()) {
|
||||
if (charge.isWithdrawalFee()) return charge;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private SavingsAccountChargeData getAnnualFee() {
|
||||
for (SavingsAccountChargeData charge : this.charges()) {
|
||||
if (charge.isAnnualFee()) return charge;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long id() {
|
||||
return this.id;
|
||||
}
|
||||
@@ -328,4 +369,8 @@ public class SavingsAccountData {
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37).append(this.id).append(this.accountNo).toHashCode();
|
||||
}
|
||||
|
||||
public Collection<SavingsAccountChargeData> charges() {
|
||||
return (this.charges == null) ? new HashSet<SavingsAccountChargeData>() : this.charges;
|
||||
}
|
||||
}
|
||||
+39
-70
@@ -6,10 +6,13 @@
|
||||
package org.mifosplatform.portfolio.savings.data;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.accountNoParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.amountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargeIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargesParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.clientIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.externalIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.fieldOfficerIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.groupIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
||||
@@ -22,14 +25,13 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequire
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.productIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.submittedOnDateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
@@ -45,11 +47,12 @@ import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsWithdrawalFeesType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
@Component
|
||||
@@ -176,32 +179,6 @@ public class SavingsAccountDataValidator {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {
|
||||
|
||||
final BigDecimal withdrawalFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).zeroOrPositiveAmount();
|
||||
|
||||
if (withdrawalFeeAmount != null) {
|
||||
final Integer withdrawalFeeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType)
|
||||
.isOneOfTheseValues(SavingsWithdrawalFeesType.integerValues());
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
||||
final Integer withdrawalFeeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).ignoreIfNull()
|
||||
.isOneOfTheseValues(1, 2);
|
||||
|
||||
if (withdrawalFeeType != null) {
|
||||
final BigDecimal withdrawalFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
withdrawalFeeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).notNull()
|
||||
.zeroOrPositiveAmount();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeForTransfersParamName, element)) {
|
||||
final Boolean isWithdrawalFeeApplicableForTransfers = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
withdrawalFeeForTransfersParamName, element);
|
||||
@@ -209,29 +186,34 @@ public class SavingsAccountDataValidator {
|
||||
.ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
||||
final BigDecimal annualFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).zeroOrPositiveAmount();
|
||||
|
||||
if (annualFeeAmount != null) {
|
||||
final MonthDay monthDayOfAnnualFee = this.fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeOnMonthDayParamName).value(monthDayOfAnnualFee).notNull();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeOnMonthDayParamName, element)) {
|
||||
|
||||
final MonthDay monthDayOfAnnualFee = this.fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||
if (monthDayOfAnnualFee != null) {
|
||||
final BigDecimal annualFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).notNull().zeroOrPositiveAmount();
|
||||
}
|
||||
}
|
||||
|
||||
validateSavingsCharges(element, baseDataValidator);
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
private void validateSavingsCharges(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
|
||||
|
||||
if (element.isJsonObject()) {
|
||||
final JsonObject topLevelJsonElement = element.getAsJsonObject();
|
||||
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
|
||||
if (topLevelJsonElement.has(chargesParamName) && topLevelJsonElement.get(chargesParamName).isJsonArray()) {
|
||||
final JsonArray array = topLevelJsonElement.get(chargesParamName).getAsJsonArray();
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
|
||||
final JsonObject savingsChargeElement = array.get(i).getAsJsonObject();
|
||||
|
||||
//final Long id = this.fromApiJsonHelper.extractLongNamed(idParamName, savingsChargeElement);
|
||||
|
||||
final Long chargeId = this.fromApiJsonHelper.extractLongNamed(chargeIdParamName, savingsChargeElement);
|
||||
baseDataValidator.reset().parameter(chargeIdParamName).value(chargeId).longGreaterThanZero();
|
||||
|
||||
final BigDecimal amount = this.fromApiJsonHelper.extractBigDecimalNamed(amountParamName, savingsChargeElement, locale);
|
||||
baseDataValidator.reset().parameter(amountParamName).value(amount).notNull().positiveAmount();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void validateForUpdate(final String json) {
|
||||
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
@@ -359,19 +341,6 @@ public class SavingsAccountDataValidator {
|
||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).inMinMaxRange(0, 3);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {
|
||||
final BigDecimal withdrawalFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).ignoreIfNull()
|
||||
.zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
||||
final Integer withdrawalFeeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).ignoreIfNull()
|
||||
.isOneOfTheseValues(SavingsWithdrawalFeesType.integerValues());
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeForTransfersParamName, element)) {
|
||||
final Boolean isWithdrawalFeeApplicableForTransfers = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
withdrawalFeeForTransfersParamName, element);
|
||||
@@ -379,14 +348,14 @@ public class SavingsAccountDataValidator {
|
||||
.ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
||||
final BigDecimal annualFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).ignoreIfNull().zeroOrPositiveAmount();
|
||||
if (this.fromApiJsonHelper.parameterExists(feeAmountParamName, element)) {
|
||||
final BigDecimal annualFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(feeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(feeAmountParamName).value(annualFeeAmount).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeOnMonthDayParamName, element)) {
|
||||
final MonthDay monthDayOfAnnualFee = this.fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeOnMonthDayParamName).value(monthDayOfAnnualFee).ignoreIfNull();
|
||||
if (this.fromApiJsonHelper.parameterExists(feeOnMonthDayParamName, element)) {
|
||||
final MonthDay monthDayOfAnnualFee = this.fromApiJsonHelper.extractMonthDayNamed(feeOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(feeOnMonthDayParamName).value(monthDayOfAnnualFee).ignoreIfNull();
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
+26
-48
@@ -10,7 +10,6 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.accounting.common.AccountingRuleType;
|
||||
import org.mifosplatform.accounting.glaccount.data.GLAccountData;
|
||||
import org.mifosplatform.accounting.producttoaccountmapping.data.ChargeToGLAccountMapper;
|
||||
@@ -37,11 +36,7 @@ public class SavingsProductData {
|
||||
private final BigDecimal minRequiredOpeningBalance;
|
||||
private final Integer lockinPeriodFrequency;
|
||||
private final EnumOptionData lockinPeriodFrequencyType;
|
||||
private final BigDecimal withdrawalFeeAmount;
|
||||
private final EnumOptionData withdrawalFeeType;
|
||||
private final boolean withdrawalFeeForTransfers;
|
||||
private final BigDecimal annualFeeAmount;
|
||||
private final MonthDay annualFeeOnMonthDay;
|
||||
|
||||
// accounting
|
||||
private final EnumOptionData accountingRule;
|
||||
@@ -86,11 +81,7 @@ public class SavingsProductData {
|
||||
final BigDecimal minRequiredOpeningBalance = null;
|
||||
final Integer lockinPeriodFrequency = null;
|
||||
final EnumOptionData lockinPeriodFrequencyType = null;
|
||||
final BigDecimal withdrawalFeeAmount = null;
|
||||
final EnumOptionData withdrawalFeeType = null;
|
||||
final boolean withdrawalFeeForTransfers = false;
|
||||
final BigDecimal annualFeeAmount = null;
|
||||
final MonthDay annualFeeMonthDay = null;
|
||||
final Map<String, Object> accountingMappings = null;
|
||||
final Collection<PaymentTypeToGLAccountMapper> paymentChannelToFundSourceMappings = null;
|
||||
final Collection<ChargeData> charges = null;
|
||||
@@ -99,11 +90,11 @@ public class SavingsProductData {
|
||||
|
||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, withdrawalFeeForTransfers,
|
||||
accountingRule, annualFeeAmount, annualFeeMonthDay, accountingMappings, paymentChannelToFundSourceMappings,
|
||||
currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions,
|
||||
accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, accountingRule, accountingMappings,
|
||||
paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions,
|
||||
accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||
penaltyToIncomeAccountMappings);
|
||||
}
|
||||
|
||||
@@ -111,13 +102,12 @@ public class SavingsProductData {
|
||||
return new SavingsProductData(product.id, product.name, product.description, product.currency, product.nominalAnnualInterestRate,
|
||||
product.interestCompoundingPeriodType, product.interestPostingPeriodType, product.interestCalculationType,
|
||||
product.interestCalculationDaysInYearType, product.minRequiredOpeningBalance, product.lockinPeriodFrequency,
|
||||
product.lockinPeriodFrequencyType, product.withdrawalFeeAmount, product.withdrawalFeeType,
|
||||
product.withdrawalFeeForTransfers, product.accountingRule, product.annualFeeAmount, product.annualFeeOnMonthDay,
|
||||
product.accountingMappings, product.paymentChannelToFundSourceMappings, product.currencyOptions,
|
||||
product.interestCompoundingPeriodTypeOptions, product.interestPostingPeriodTypeOptions,
|
||||
product.interestCalculationTypeOptions, product.interestCalculationDaysInYearTypeOptions,
|
||||
product.lockinPeriodFrequencyTypeOptions, product.withdrawalFeeTypeOptions, product.paymentTypeOptions,
|
||||
product.accountingRuleOptions, product.accountingMappingOptions, charges, product.chargeOptions, product.penaltyOptions,
|
||||
product.lockinPeriodFrequencyType, product.withdrawalFeeForTransfers, product.accountingRule, product.accountingMappings,
|
||||
product.paymentChannelToFundSourceMappings, product.currencyOptions, product.interestCompoundingPeriodTypeOptions,
|
||||
product.interestPostingPeriodTypeOptions, product.interestCalculationTypeOptions,
|
||||
product.interestCalculationDaysInYearTypeOptions, product.lockinPeriodFrequencyTypeOptions,
|
||||
product.withdrawalFeeTypeOptions, product.paymentTypeOptions, product.accountingRuleOptions,
|
||||
product.accountingMappingOptions, charges, product.chargeOptions, product.penaltyOptions,
|
||||
product.feeToIncomeAccountMappings, product.penaltyToIncomeAccountMappings);
|
||||
}
|
||||
|
||||
@@ -139,9 +129,8 @@ public class SavingsProductData {
|
||||
existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
|
||||
existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
||||
existingProduct.interestCalculationDaysInYearType, existingProduct.minRequiredOpeningBalance,
|
||||
existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, existingProduct.withdrawalFeeAmount,
|
||||
existingProduct.withdrawalFeeType, existingProduct.withdrawalFeeForTransfers, existingProduct.accountingRule,
|
||||
existingProduct.annualFeeAmount, existingProduct.annualFeeOnMonthDay, existingProduct.accountingMappings,
|
||||
existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType,
|
||||
existingProduct.withdrawalFeeForTransfers, existingProduct.accountingRule, existingProduct.accountingMappings,
|
||||
existingProduct.paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions,
|
||||
@@ -172,9 +161,8 @@ public class SavingsProductData {
|
||||
existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
|
||||
existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
||||
existingProduct.interestCalculationDaysInYearType, existingProduct.minRequiredOpeningBalance,
|
||||
existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, existingProduct.withdrawalFeeAmount,
|
||||
existingProduct.withdrawalFeeType, existingProduct.withdrawalFeeForTransfers, existingProduct.accountingRule,
|
||||
existingProduct.annualFeeAmount, existingProduct.annualFeeOnMonthDay, accountingMappings,
|
||||
existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType,
|
||||
existingProduct.withdrawalFeeForTransfers, existingProduct.accountingRule, accountingMappings,
|
||||
paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions,
|
||||
@@ -186,9 +174,8 @@ public class SavingsProductData {
|
||||
final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType,
|
||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount,
|
||||
final EnumOptionData withdrawalFeeType, final boolean withdrawalFeeForTransfers, final BigDecimal annualFeeAmount,
|
||||
final MonthDay annualFeeOnMonthDay, final EnumOptionData accountingType) {
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers,
|
||||
final EnumOptionData accountingType) {
|
||||
|
||||
final Map<String, Object> accountingMappings = null;
|
||||
final Collection<PaymentTypeToGLAccountMapper> paymentChannelToFundSourceMappings = null;
|
||||
@@ -211,11 +198,11 @@ public class SavingsProductData {
|
||||
|
||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, withdrawalFeeForTransfers,
|
||||
accountingType, annualFeeAmount, annualFeeOnMonthDay, accountingMappings, paymentChannelToFundSourceMappings,
|
||||
currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions,
|
||||
accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, accountingType, accountingMappings,
|
||||
paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions,
|
||||
accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||
penaltyToIncomeAccountMappings);
|
||||
}
|
||||
|
||||
@@ -231,12 +218,8 @@ public class SavingsProductData {
|
||||
final BigDecimal minRequiredOpeningBalance = null;
|
||||
final Integer lockinPeriodFrequency = null;
|
||||
final EnumOptionData lockinPeriodFrequencyType = null;
|
||||
final BigDecimal withdrawalFeeAmount = null;
|
||||
final EnumOptionData withdrawalFeeType = null;
|
||||
final boolean withdrawalFeeForTransfers = false;
|
||||
final EnumOptionData accountingType = null;
|
||||
final BigDecimal annualFeeAmount = null;
|
||||
final MonthDay annualFeeMonthDay = null;
|
||||
final Map<String, Object> accountingMappings = null;
|
||||
final Collection<PaymentTypeToGLAccountMapper> paymentChannelToFundSourceMappings = null;
|
||||
|
||||
@@ -258,8 +241,8 @@ public class SavingsProductData {
|
||||
|
||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, withdrawalFeeForTransfers,
|
||||
accountingType, annualFeeAmount, annualFeeMonthDay, accountingMappings, paymentChannelToFundSourceMappings,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers,
|
||||
accountingType, accountingMappings, paymentChannelToFundSourceMappings,
|
||||
currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions,
|
||||
accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||
@@ -270,9 +253,8 @@ public class SavingsProductData {
|
||||
final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType,
|
||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount,
|
||||
final EnumOptionData withdrawalFeeType, final boolean withdrawalFeeForTransfers, final EnumOptionData accountingType,
|
||||
final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay, final Map<String, Object> accountingMappings,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers,
|
||||
final EnumOptionData accountingType, final Map<String, Object> accountingMappings,
|
||||
final Collection<PaymentTypeToGLAccountMapper> paymentChannelToFundSourceMappings,
|
||||
final Collection<CurrencyData> currencyOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||
@@ -297,11 +279,7 @@ public class SavingsProductData {
|
||||
this.minRequiredOpeningBalance = minRequiredOpeningBalance;
|
||||
this.lockinPeriodFrequency = lockinPeriodFrequency;
|
||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType;
|
||||
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||
this.withdrawalFeeType = withdrawalFeeType;
|
||||
this.withdrawalFeeForTransfers = withdrawalFeeForTransfers;
|
||||
this.annualFeeAmount = annualFeeAmount;
|
||||
this.annualFeeOnMonthDay = annualFeeOnMonthDay;
|
||||
|
||||
this.currencyOptions = currencyOptions;
|
||||
this.interestCompoundingPeriodTypeOptions = interestCompoundingPeriodTypeOptions;
|
||||
|
||||
+19
-35
@@ -7,8 +7,8 @@ package org.mifosplatform.portfolio.savings.data;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_RESOURCE_NAME;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.currencyCodeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.descriptionParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.digitsAfterDecimalParamName;
|
||||
@@ -22,9 +22,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeri
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
@@ -46,7 +44,6 @@ import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsWithdrawalFeesType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -151,7 +148,7 @@ public class SavingsProductDataValidator {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {
|
||||
/*if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {
|
||||
|
||||
final BigDecimal withdrawalFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName,
|
||||
element);
|
||||
@@ -176,7 +173,7 @@ public class SavingsProductDataValidator {
|
||||
.zeroOrPositiveAmount();
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeForTransfersParamName, element)) {
|
||||
final Boolean isWithdrawalFeeApplicableForTransfers = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
withdrawalFeeForTransfersParamName, element);
|
||||
@@ -184,23 +181,23 @@ public class SavingsProductDataValidator {
|
||||
.ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
||||
final BigDecimal annualFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).zeroOrPositiveAmount();
|
||||
if (this.fromApiJsonHelper.parameterExists(feeAmountParamName, element)) {
|
||||
final BigDecimal annualFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(feeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(feeAmountParamName).value(annualFeeAmount).zeroOrPositiveAmount();
|
||||
|
||||
if (annualFeeAmount != null) {
|
||||
final MonthDay monthDayOfAnnualFee = this.fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeOnMonthDayParamName).value(monthDayOfAnnualFee).notNull();
|
||||
final MonthDay monthDayOfAnnualFee = this.fromApiJsonHelper.extractMonthDayNamed(feeOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(feeOnMonthDayParamName).value(monthDayOfAnnualFee).notNull();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeOnMonthDayParamName, element)) {
|
||||
if (this.fromApiJsonHelper.parameterExists(feeOnMonthDayParamName, element)) {
|
||||
|
||||
final MonthDay monthDayOfAnnualFee = this.fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||
final MonthDay monthDayOfAnnualFee = this.fromApiJsonHelper.extractMonthDayNamed(feeOnMonthDayParamName, element);
|
||||
if (monthDayOfAnnualFee != null) {
|
||||
final BigDecimal annualFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName,
|
||||
final BigDecimal annualFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(feeAmountParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).notNull().zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter(feeAmountParamName).value(annualFeeAmount).notNull().zeroOrPositiveAmount();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,19 +328,6 @@ public class SavingsProductDataValidator {
|
||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).inMinMaxRange(0, 3);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {
|
||||
final BigDecimal withdrawalFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).ignoreIfNull()
|
||||
.zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
||||
final Integer withdrawalFeeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).ignoreIfNull()
|
||||
.isOneOfTheseValues(1, 2);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeForTransfersParamName, element)) {
|
||||
final Boolean isWithdrawalFeeApplicableForTransfers = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
withdrawalFeeForTransfersParamName, element);
|
||||
@@ -351,14 +335,14 @@ public class SavingsProductDataValidator {
|
||||
.ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
||||
final BigDecimal annualFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).ignoreIfNull().zeroOrPositiveAmount();
|
||||
if (this.fromApiJsonHelper.parameterExists(feeAmountParamName, element)) {
|
||||
final BigDecimal annualFeeAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(feeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(feeAmountParamName).value(annualFeeAmount).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeOnMonthDayParamName, element)) {
|
||||
final MonthDay monthDayOfAnnualFee = this.fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeOnMonthDayParamName).value(monthDayOfAnnualFee).ignoreIfNull();
|
||||
if (this.fromApiJsonHelper.parameterExists(feeOnMonthDayParamName, element)) {
|
||||
final MonthDay monthDayOfAnnualFee = this.fromApiJsonHelper.extractMonthDayNamed(feeOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(feeOnMonthDayParamName).value(monthDayOfAnnualFee).ignoreIfNull();
|
||||
}
|
||||
|
||||
final Long savingsControlAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||
|
||||
+149
-326
@@ -6,15 +6,10 @@
|
||||
package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.dueAsOfDateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.localeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
@@ -49,7 +44,6 @@ import org.apache.commons.lang.StringUtils;
|
||||
import org.hibernate.annotations.LazyCollection;
|
||||
import org.hibernate.annotations.LazyCollectionOption;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
@@ -76,7 +70,6 @@ import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearT
|
||||
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsWithdrawalFeesType;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionDTO;
|
||||
import org.mifosplatform.portfolio.savings.domain.interest.PostingPeriod;
|
||||
import org.mifosplatform.portfolio.savings.exception.InsufficientAccountBalanceException;
|
||||
@@ -223,28 +216,9 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
@Column(name = "lockedin_until_date_derived", nullable = true)
|
||||
private Date lockedInUntilDate;
|
||||
|
||||
@Column(name = "withdrawal_fee_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal withdrawalFeeAmount;
|
||||
|
||||
@Column(name = "withdrawal_fee_type_enum", nullable = true)
|
||||
private Integer withdrawalFeeType;
|
||||
|
||||
@Column(name = "withdrawal_fee_for_transfer", nullable = true)
|
||||
private boolean withdrawalFeeApplicableForTransfer;
|
||||
|
||||
@Column(name = "annual_fee_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal annualFeeAmount;
|
||||
|
||||
@Column(name = "annual_fee_on_month", nullable = true)
|
||||
private Integer annualFeeOnMonth;
|
||||
|
||||
@Column(name = "annual_fee_on_day", nullable = true)
|
||||
private Integer annualFeeOnDay;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "annual_fee_next_due_date", nullable = true)
|
||||
private Date annualFeeNextDueDate;
|
||||
|
||||
@Embedded
|
||||
private SavingsAccountSummary summary;
|
||||
|
||||
@@ -275,16 +249,13 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay,
|
||||
final Set<SavingsAccountCharge> savingsAccountCharges) {
|
||||
final boolean withdrawalFeeApplicableForTransfer, final Set<SavingsAccountCharge> savingsAccountCharges) {
|
||||
|
||||
final SavingsAccountStatusType status = SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL;
|
||||
return new SavingsAccount(client, group, product, fieldOfficer, accountNo, externalId, status, accountType, submittedOnDate,
|
||||
interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
|
||||
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
|
||||
withdrawalFeeAmount, withdrawalFeeType, withdrawalFeeApplicableForTransfer, annualFeeAmount, annualFeeOnMonthDay,
|
||||
savingsAccountCharges);
|
||||
withdrawalFeeApplicableForTransfer, savingsAccountCharges);
|
||||
}
|
||||
|
||||
private SavingsAccount(final Client client, final Group group, final SavingsProduct product, final Staff fieldOfficer,
|
||||
@@ -294,9 +265,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay,
|
||||
final Set<SavingsAccountCharge> savingsAccountCharges) {
|
||||
final boolean withdrawalFeeApplicableForTransfer, final Set<SavingsAccountCharge> savingsAccountCharges) {
|
||||
this.client = client;
|
||||
this.group = group;
|
||||
this.product = product;
|
||||
@@ -322,18 +291,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
if (lockinPeriodFrequencyType != null) {
|
||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType.getValue();
|
||||
}
|
||||
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||
if (withdrawalFeeType != null) {
|
||||
this.withdrawalFeeType = withdrawalFeeType.getValue();
|
||||
}
|
||||
this.withdrawalFeeApplicableForTransfer = withdrawalFeeApplicableForTransfer;
|
||||
|
||||
this.annualFeeAmount = annualFeeAmount;
|
||||
if (annualFeeOnMonthDay != null) {
|
||||
this.annualFeeOnMonth = annualFeeOnMonthDay.getMonthOfYear();
|
||||
this.annualFeeOnDay = annualFeeOnMonthDay.getDayOfMonth();
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(savingsAccountCharges)) {
|
||||
this.charges = associateChargesWithThisSavingsAccount(savingsAccountCharges);
|
||||
}
|
||||
@@ -616,7 +575,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
private LocalDate getActivationLocalDate() {
|
||||
public LocalDate getActivationLocalDate() {
|
||||
LocalDate activationLocalDate = null;
|
||||
if (this.activatedOnDate != null) {
|
||||
activationLocalDate = new LocalDate(this.activatedOnDate);
|
||||
@@ -682,33 +641,20 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
transactionDTO.getPaymentDetail(), transactionDTO.getTransactionDate(), transactionAmountMoney);
|
||||
this.transactions.add(transaction);
|
||||
|
||||
if (applyWithdrawFee && isAutomaticWithdrawalFee()) {
|
||||
|
||||
SavingsAccountTransaction withdrawalFeeTransaction = null;
|
||||
Money feeAmount = Money.zero(this.currency);
|
||||
switch (SavingsWithdrawalFeesType.fromInt(this.withdrawalFeeType)) {
|
||||
case INVALID:
|
||||
break;
|
||||
case FLAT:
|
||||
feeAmount = Money.of(this.currency, this.withdrawalFeeAmount);
|
||||
withdrawalFeeTransaction = SavingsAccountTransaction
|
||||
.fee(this, office(), transactionDTO.getTransactionDate(), feeAmount);
|
||||
this.transactions.add(withdrawalFeeTransaction);
|
||||
break;
|
||||
case PERCENT_OF_AMOUNT:
|
||||
final BigDecimal feeAmountDecimal = transactionDTO.getTransactionAmount().multiply(this.withdrawalFeeAmount)
|
||||
.divide(BigDecimal.valueOf(100l));
|
||||
feeAmount = Money.of(this.currency, feeAmountDecimal);
|
||||
withdrawalFeeTransaction = SavingsAccountTransaction
|
||||
.fee(this, office(), transactionDTO.getTransactionDate(), feeAmount);
|
||||
this.transactions.add(withdrawalFeeTransaction);
|
||||
break;
|
||||
if (applyWithdrawFee){
|
||||
//auto pay withdrawal fee
|
||||
payWithdrawalFee(transactionDTO.getTransactionAmount(), transactionDTO.getTransactionDate());
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
private void payWithdrawalFee(final BigDecimal transactionAmoount, final LocalDate transactionDate){
|
||||
for (SavingsAccountCharge charge : this.charges()) {
|
||||
if (charge.isWithdrawalFee()){
|
||||
charge.updateWithdralFeeAmount(transactionAmoount);
|
||||
this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate);
|
||||
}
|
||||
}
|
||||
|
||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public boolean isBeforeLastPostingPeriod(final LocalDate transactionDate) {
|
||||
@@ -768,128 +714,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SavingsAccountTransaction addAnnualFee(final MathContext mc, final DateTimeFormatter formatter,
|
||||
final LocalDate annualFeeTransactionDate, final LocalDate today) {
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(SAVINGS_ACCOUNT_RESOURCE_NAME + SavingsApiConstants.applyAnnualFeeTransactionAction);
|
||||
|
||||
if (isNotActive()) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("transaction.invalid.account.is.not.active");
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
final LocalDate nextAnnualFeeDueDate = getNextAnnualFeeDueDate();
|
||||
if (nextAnnualFeeDueDate == null || annualFeeSettingsNotSet()) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("no.annualfee.settings");
|
||||
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
if (nextAnnualFeeDueDate.isBefore(getActivationLocalDate())) {
|
||||
|
||||
baseDataValidator.reset().parameter("annualFeeTransactionDate").value(getActivationLocalDate().toString(formatter))
|
||||
.failWithCodeNoParameterAddedToErrorCode("before.activationDate");
|
||||
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
if (isDateInTheFuture(annualFeeTransactionDate)) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("transaction.in.the.future");
|
||||
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
if (isNotValidAnnualFeeTransactionDate(annualFeeTransactionDate, today)) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("invalid.date");
|
||||
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
Date currentAnnualFeeNextDueDate = findLatestAnnualFeeTransactionDueDate();
|
||||
if (currentAnnualFeeNextDueDate != null && new LocalDate(currentAnnualFeeNextDueDate).isEqual(annualFeeTransactionDate)) {
|
||||
baseDataValidator.reset().parameter("annualFeeTransactionDate").value(annualFeeTransactionDate.toString(formatter))
|
||||
.failWithCodeNoParameterAddedToErrorCode("transaction.exists.on.date");
|
||||
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_PAY_CHARGE, annualFeeTransactionDate);
|
||||
|
||||
final Money annualFee = Money.of(this.currency, this.annualFeeAmount);
|
||||
final SavingsAccountTransaction annualFeeTransaction = SavingsAccountTransaction.annualFee(this, office(),
|
||||
annualFeeTransactionDate, annualFee);
|
||||
this.transactions.add(annualFeeTransaction);
|
||||
|
||||
validateAccountBalanceDoesNotBecomeNegative(SavingsApiConstants.applyAnnualFeeTransactionAction);
|
||||
|
||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||
|
||||
calculateInterestUsing(mc, today);
|
||||
|
||||
currentAnnualFeeNextDueDate = findLatestAnnualFeeTransactionDueDate();
|
||||
if (currentAnnualFeeNextDueDate != null) {
|
||||
final LocalDate newAnnualFeeNextDueDate = new LocalDate(currentAnnualFeeNextDueDate).withMonthOfYear(this.annualFeeOnMonth)
|
||||
.withDayOfMonth(this.annualFeeOnDay).plusYears(1);
|
||||
this.annualFeeNextDueDate = newAnnualFeeNextDueDate.toDate();
|
||||
} else {
|
||||
updateToNextAnnualFeeDueDateFrom(getActivationLocalDate());
|
||||
}
|
||||
|
||||
return annualFeeTransaction;
|
||||
}
|
||||
|
||||
private boolean isNotValidAnnualFeeTransactionDate(final LocalDate annualFeeTransactionDate, final LocalDate today) {
|
||||
return !isValidAnnualFeeTransactionDate(annualFeeTransactionDate, today);
|
||||
}
|
||||
|
||||
private boolean isValidAnnualFeeTransactionDate(final LocalDate annualFeeTransactionDate, final LocalDate today) {
|
||||
|
||||
LocalDate startingDate = getActivationLocalDate();
|
||||
boolean isValid = false;
|
||||
while (!startingDate.isAfter(today) && !isValid) {
|
||||
LocalDate nextDueLocalDate = startingDate.withMonthOfYear(this.annualFeeOnMonth).withDayOfMonth(this.annualFeeOnDay);
|
||||
if (startingDate.isAfter(nextDueLocalDate)) {
|
||||
nextDueLocalDate = nextDueLocalDate.plusYears(1);
|
||||
}
|
||||
isValid = nextDueLocalDate.isEqual(annualFeeTransactionDate);
|
||||
|
||||
startingDate = nextDueLocalDate.plusYears(1);
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
private void updateToNextAnnualFeeDueDateFrom(final LocalDate startingDate) {
|
||||
LocalDate nextDueLocalDate = startingDate.withMonthOfYear(this.annualFeeOnMonth).withDayOfMonth(this.annualFeeOnDay);
|
||||
if (startingDate.isAfter(nextDueLocalDate)) {
|
||||
nextDueLocalDate = nextDueLocalDate.plusYears(1);
|
||||
}
|
||||
this.annualFeeNextDueDate = nextDueLocalDate.toDate();
|
||||
}
|
||||
|
||||
private LocalDate getNextAnnualFeeDueDate() {
|
||||
LocalDate nextAnnualFeeDueDate = null;
|
||||
if (this.annualFeeNextDueDate != null) {
|
||||
nextAnnualFeeDueDate = new LocalDate(this.annualFeeNextDueDate);
|
||||
}
|
||||
return nextAnnualFeeDueDate;
|
||||
}
|
||||
|
||||
private boolean annualFeeSettingsNotSet() {
|
||||
return !annualFeeSettingsSet();
|
||||
}
|
||||
|
||||
private boolean annualFeeSettingsSet() {
|
||||
return this.annualFeeOnDay != null && this.annualFeeOnMonth != null;
|
||||
}
|
||||
|
||||
private boolean isAutomaticWithdrawalFee() {
|
||||
return this.withdrawalFeeType != null;
|
||||
}
|
||||
|
||||
|
||||
private boolean isAccountLocked(final LocalDate transactionDate) {
|
||||
boolean isLocked = false;
|
||||
final boolean accountHasLockedInSetting = this.lockedInUntilDate != null;
|
||||
@@ -1037,55 +862,12 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
this.lockinPeriodFrequencyType = null;
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(withdrawalFeeAmountParamName, this.withdrawalFeeAmount)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(withdrawalFeeAmountParamName);
|
||||
actualChanges.put(withdrawalFeeAmountParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.withdrawalFeeAmount = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamedDefaultingZeroToNull(withdrawalFeeTypeParamName, this.withdrawalFeeType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamedDefaultToNullIfZero(withdrawalFeeTypeParamName);
|
||||
actualChanges.put(withdrawalFeeTypeParamName, newValue);
|
||||
this.withdrawalFeeType = newValue != null ? SavingsWithdrawalFeesType.fromInt(newValue).getValue() : newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(withdrawalFeeForTransfersParamName, this.withdrawalFeeApplicableForTransfer)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(withdrawalFeeForTransfersParamName);
|
||||
actualChanges.put(withdrawalFeeForTransfersParamName, newValue);
|
||||
this.withdrawalFeeApplicableForTransfer = newValue;
|
||||
}
|
||||
|
||||
// set period type to null if frequency is null
|
||||
if (this.withdrawalFeeAmount == null) {
|
||||
this.withdrawalFeeType = null;
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(annualFeeAmountParamName, this.annualFeeAmount)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(annualFeeAmountParamName);
|
||||
actualChanges.put(annualFeeAmountParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.annualFeeAmount = newValue;
|
||||
}
|
||||
|
||||
if (command.hasParameter(annualFeeOnMonthDayParamName)) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed(annualFeeOnMonthDayParamName);
|
||||
final Integer dayOfMonthValue = monthDay.getDayOfMonth();
|
||||
if (this.annualFeeOnDay != dayOfMonthValue) {
|
||||
actualChanges.put(annualFeeOnMonthDayParamName, actualValueEntered);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.annualFeeOnDay = dayOfMonthValue;
|
||||
}
|
||||
|
||||
final Integer monthOfYear = monthDay.getMonthOfYear();
|
||||
if (this.annualFeeOnMonth != monthOfYear) {
|
||||
actualChanges.put(annualFeeOnMonthDayParamName, actualValueEntered);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.annualFeeOnMonth = monthOfYear;
|
||||
}
|
||||
}
|
||||
|
||||
// charges
|
||||
final String chargesParamName = "charges";
|
||||
if (command.hasParameter(chargesParamName)) {
|
||||
@@ -1095,60 +877,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
}
|
||||
}
|
||||
|
||||
// set period type to null if frequency is null
|
||||
if (this.annualFeeAmount == null) {
|
||||
this.annualFeeOnDay = null;
|
||||
this.annualFeeOnMonth = null;
|
||||
}
|
||||
|
||||
validateLockinDetails();
|
||||
validateWithdrawalFeeDetails();
|
||||
validateAnnualFeeDetails();
|
||||
}
|
||||
|
||||
private void validateAnnualFeeDetails() {
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||
|
||||
if (this.annualFeeAmount == null) {
|
||||
|
||||
if (this.annualFeeOnMonth != null || this.annualFeeOnDay != null) {
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(this.annualFeeAmount).notNull();
|
||||
}
|
||||
} else {
|
||||
|
||||
if (this.annualFeeOnMonth == null || this.annualFeeOnDay == null) {
|
||||
baseDataValidator.reset().parameter(annualFeeOnMonthDayParamName).value(this.annualFeeOnMonth).notNull();
|
||||
}
|
||||
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(this.annualFeeAmount).zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
private void validateWithdrawalFeeDetails() {
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||
|
||||
if (this.withdrawalFeeAmount == null) {
|
||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(this.withdrawalFeeType).ignoreIfNull()
|
||||
.isOneOfTheseValues(1, 2);
|
||||
|
||||
if (this.withdrawalFeeType != null) {
|
||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(this.withdrawalFeeAmount).notNull();
|
||||
}
|
||||
} else {
|
||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(this.withdrawalFeeAmount).zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(this.withdrawalFeeType).notNull()
|
||||
.isOneOfTheseValues(1, 2);
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
|
||||
}
|
||||
|
||||
private void validateLockinDetails() {
|
||||
@@ -1311,8 +1041,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
public void validateNewApplicationState(final LocalDate todayDateOfTenant) {
|
||||
|
||||
validateLockinDetails();
|
||||
validateWithdrawalFeeDetails();
|
||||
validateAnnualFeeDetails();
|
||||
//validateWithdrawalFeeDetails();
|
||||
//validateAnnualFeeDetails();
|
||||
|
||||
final LocalDate submittedOn = getSubmittedOnLocalDate();
|
||||
|
||||
@@ -1470,22 +1200,16 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_UNDO_TRANSACTION,
|
||||
transactionToUndo.transactionLocalDate());
|
||||
transactionToUndo.reverse();
|
||||
if (transactionToUndo.isAnnualFee()) {
|
||||
this.annualFeeNextDueDate = findLatestAnnualFeeTransactionDueDate();
|
||||
if (this.annualFeeNextDueDate == null) {
|
||||
updateToNextAnnualFeeDueDateFrom(getActivationLocalDate());
|
||||
} else {
|
||||
final LocalDate newAnnualFeeNextDueDate = new LocalDate(this.annualFeeNextDueDate)
|
||||
.withMonthOfYear(this.annualFeeOnMonth).withDayOfMonth(this.annualFeeOnDay).plusYears(1);
|
||||
this.annualFeeNextDueDate = newAnnualFeeNextDueDate.toDate();
|
||||
}
|
||||
} else if (transactionToUndo.isCharge() || transactionToUndo.isWaiveCharge()) {
|
||||
if (transactionToUndo.isChargeTransaction() || transactionToUndo.isWaiveCharge()) {
|
||||
// undo charge
|
||||
final Set<SavingsAccountChargePaidBy> chargesPaidBy = transactionToUndo.getSavingsAccountChargesPaid();
|
||||
for (final SavingsAccountChargePaidBy savingsAccountChargePaidBy : chargesPaidBy) {
|
||||
final SavingsAccountCharge chargeToUndo = savingsAccountChargePaidBy.getSavingsAccountCharge();
|
||||
if (transactionToUndo.isCharge()) {
|
||||
if (transactionToUndo.isChargeTransaction()) {
|
||||
chargeToUndo.undoPayment(this.getCurrency(), transactionToUndo.getAmount(this.getCurrency()));
|
||||
if(chargeToUndo.isAnnualFee()){
|
||||
chargeToUndo.updateToPreviousAnnualFeeDueDate();
|
||||
}
|
||||
} else if (transactionToUndo.isWaiveCharge()) {
|
||||
chargeToUndo.undoWaiver(this.getCurrency(), transactionToUndo.getAmount(this.getCurrency()));
|
||||
}
|
||||
@@ -1672,10 +1396,10 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
this.activatedBy = currentUser;
|
||||
this.lockedInUntilDate = calculateDateAccountIsLockedUntil(getActivationLocalDate());
|
||||
|
||||
if (annualFeeSettingsSet()) {
|
||||
/*if (annualFeeSettingsSet()) {
|
||||
updateToNextAnnualFeeDueDateFrom(getActivationLocalDate());
|
||||
}
|
||||
|
||||
*/
|
||||
if (this.client != null && this.client.isActivatedAfter(activationDate)) {
|
||||
final DateTimeFormatter formatter = DateTimeFormat.forPattern(command.dateFormat()).withLocale(command.extractLocale());
|
||||
final String dateAsString = formatter.print(this.client.getActivationLocalDate());
|
||||
@@ -1730,9 +1454,27 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
// correct.
|
||||
recalculateDailyBalances(openingAccountBalance);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//update annual fee due date
|
||||
for (SavingsAccountCharge charge : this.charges()) {
|
||||
charge.updateToNextAnnualFeeDueDateFrom(getActivationLocalDate());
|
||||
}
|
||||
|
||||
//auto pay the activation time charges
|
||||
this.payActivationCharges();
|
||||
//TODO : AA add activation charges to actual changes list
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void payActivationCharges() {
|
||||
for (SavingsAccountCharge savingsAccountCharge : this.charges()) {
|
||||
if (savingsAccountCharge.isSavingsActivation()) {
|
||||
payCharge(savingsAccountCharge, savingsAccountCharge.getAmountOutstanding(getCurrency()), getActivationLocalDate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> close(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate) {
|
||||
|
||||
@@ -1918,6 +1660,11 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
|
||||
final SavingsAccountCharge savingsAccountCharge = getCharge(savingsAccountChargeId);
|
||||
|
||||
if (savingsAccountCharge.isWithdrawalFee()){
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("transaction.invalid.waiver.of.withdrawal.fee.not.supported");
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
// validate charge is not already paid or waived
|
||||
if (savingsAccountCharge.isWaived()) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("transaction.invalid.account.charge.is.already.waived");
|
||||
@@ -1963,14 +1710,55 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
if (savingsAccountCharge.isSavingsActivation() && !(isSubmittedAndPendingApproval() || (isApproved() && isNotActive()))) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"not.valid.account.status.cannot.add.activation.time.charge");
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_APPLY_CHARGE, chargeDueDate);
|
||||
|
||||
//Only one withdrawal fee is supported per account
|
||||
if(savingsAccountCharge.isWithdrawalFee()){
|
||||
if(this.isWithDrawalFeeExists()){
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"multiple.withdrawal.fee.per.account.not.supported");
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
//Only one annual fee is supported per account
|
||||
if(savingsAccountCharge.isAnnualFee()){
|
||||
if(this.isAnnualFeeExists()){
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"multiple.annual.fee.per.account.not.supported");
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
//activation charge and withdrawal charges not required this validation
|
||||
if(savingsAccountCharge.isOnSpecifiedDueDate()){
|
||||
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_APPLY_CHARGE, chargeDueDate);
|
||||
}
|
||||
|
||||
// add new charge to savings account
|
||||
getCharges().add(savingsAccountCharge);
|
||||
charges().add(savingsAccountCharge);
|
||||
|
||||
}
|
||||
|
||||
private boolean isWithDrawalFeeExists() {
|
||||
for (SavingsAccountCharge charge : this.charges()) {
|
||||
if(charge.isWithdrawalFee()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isAnnualFeeExists() {
|
||||
for (SavingsAccountCharge charge : this.charges()) {
|
||||
if(charge.isAnnualFee()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void payCharge(final SavingsAccountCharge savingsAccountCharge, final BigDecimal amountPaid, final LocalDate transactionDate,
|
||||
final DateTimeFormatter formatter) {
|
||||
|
||||
@@ -1988,24 +1776,45 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
if (savingsAccountCharge.isOnSpecifiedDueDate()) {
|
||||
if (getActivationLocalDate() != null && transactionDate.isBefore(getActivationLocalDate())) {
|
||||
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getActivationLocalDate().toString(formatter))
|
||||
.failWithCodeNoParameterAddedToErrorCode("transaction.before.activationDate");
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
} else if (getSubmittedOnLocalDate() != null && transactionDate.isBefore(getSubmittedOnLocalDate())) {
|
||||
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getSubmittedOnLocalDate().toString(formatter))
|
||||
.failWithCodeNoParameterAddedToErrorCode("transaction.before.submittedOnDate");
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
if (getActivationLocalDate() != null && transactionDate.isBefore(getActivationLocalDate())) {
|
||||
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getActivationLocalDate().toString(formatter))
|
||||
.failWithCodeNoParameterAddedToErrorCode("transaction.before.activationDate");
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
if (DateUtils.isInFuture(transactionDate)) {
|
||||
if (DateUtils.isDateInTheFuture(transactionDate)) {
|
||||
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getSubmittedOnLocalDate().toString(formatter))
|
||||
.failWithCodeNoParameterAddedToErrorCode("transaction.is.futureDate");
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
if (savingsAccountCharge.isSavingsActivation()) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||
"transaction.not.valid.cannot.pay.activation.time.charge.is.automated");
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
if (savingsAccountCharge.isAnnualFee()){
|
||||
final LocalDate annualFeeDueDate = savingsAccountCharge.getDueLocalDate();
|
||||
if (annualFeeDueDate == null) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("no.annualfee.settings");
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
if (!annualFeeDueDate.equals(transactionDate)) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("invalid.date");
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
Date currentAnnualFeeNextDueDate = findLatestAnnualFeeTransactionDueDate();
|
||||
if (currentAnnualFeeNextDueDate != null && new LocalDate(currentAnnualFeeNextDueDate).isEqual(transactionDate)) {
|
||||
baseDataValidator.reset().parameter("dueDate").value(transactionDate.toString(formatter))
|
||||
.failWithCodeNoParameterAddedToErrorCode("transaction.exists.on.date");
|
||||
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
// validate charge is not already paid or waived
|
||||
if (savingsAccountCharge.isWaived()) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("transaction.invalid.account.charge.is.already.waived");
|
||||
@@ -2015,21 +1824,35 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
final Money amountPaidMoney = Money.of(currency, amountPaid);
|
||||
if (!savingsAccountCharge.getAmountOutstanding(getCurrency()).isGreaterThanOrEqualTo(amountPaidMoney)) {
|
||||
final Money chargePaid = Money.of(currency, amountPaid);
|
||||
if (!savingsAccountCharge.getAmountOutstanding(getCurrency()).isGreaterThanOrEqualTo(chargePaid)) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("transaction.invalid.charge.amount.paid.in.access");
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
savingsAccountCharge.pay(getCurrency(), amountPaidMoney);
|
||||
|
||||
handlePayChargeTransactions(savingsAccountCharge, amountPaidMoney, transactionDate);
|
||||
this.payCharge(savingsAccountCharge, chargePaid, transactionDate);
|
||||
|
||||
//update next annual fee due date
|
||||
savingsAccountCharge.updateToNextAnnualFeeDueDate();
|
||||
}
|
||||
|
||||
public void payCharge(final SavingsAccountCharge savingsAccountCharge, final Money amountPaid, final LocalDate transactionDate) {
|
||||
savingsAccountCharge.pay(getCurrency(), amountPaid);
|
||||
handlePayChargeTransactions(savingsAccountCharge, amountPaid, transactionDate);
|
||||
}
|
||||
|
||||
private void handlePayChargeTransactions(SavingsAccountCharge savingsAccountCharge, Money transactionAmount,
|
||||
final LocalDate transactionDate) {
|
||||
final SavingsAccountTransaction chargeTransaction = SavingsAccountTransaction.charge(this, office(), transactionDate,
|
||||
transactionAmount);
|
||||
SavingsAccountTransaction chargeTransaction = null;
|
||||
|
||||
if (savingsAccountCharge.isWithdrawalFee()){
|
||||
chargeTransaction = SavingsAccountTransaction.withdrawalFee(this, office(), transactionDate, transactionAmount);
|
||||
}else if (savingsAccountCharge.isAnnualFee()){
|
||||
chargeTransaction = SavingsAccountTransaction.annualFee(this, office(), transactionDate, transactionAmount);
|
||||
}else {
|
||||
chargeTransaction = SavingsAccountTransaction.charge(this, office(), transactionDate, transactionAmount);
|
||||
}
|
||||
|
||||
handleChargeTransactions(savingsAccountCharge, chargeTransaction);
|
||||
}
|
||||
|
||||
@@ -2062,7 +1885,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
return charge;
|
||||
}
|
||||
|
||||
private Set<SavingsAccountCharge> getCharges() {
|
||||
public Set<SavingsAccountCharge> charges() {
|
||||
return (this.charges == null) ? new HashSet<SavingsAccountCharge>() : this.charges;
|
||||
}
|
||||
}
|
||||
+1
-39
@@ -6,8 +6,6 @@
|
||||
package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.accountNoParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.clientIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.externalIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.fieldOfficerIdParamName;
|
||||
@@ -22,15 +20,12 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequire
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.productIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.submittedOnDateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||
@@ -50,7 +45,6 @@ import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearT
|
||||
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsWithdrawalFeesType;
|
||||
import org.mifosplatform.portfolio.savings.exception.SavingsProductNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -199,50 +193,18 @@ public class SavingsAccountAssembler {
|
||||
} else {
|
||||
lockinPeriodFrequencyType = product.lockinPeriodFrequencyType();
|
||||
}
|
||||
|
||||
BigDecimal withdrawalFeeAmount = null;
|
||||
if (command.parameterExists(withdrawalFeeAmountParamName)) {
|
||||
withdrawalFeeAmount = command.bigDecimalValueOfParameterNamed(withdrawalFeeAmountParamName);
|
||||
} else {
|
||||
withdrawalFeeAmount = product.withdrawalFeeAmount();
|
||||
}
|
||||
|
||||
SavingsWithdrawalFeesType withdrawalFeeType = null;
|
||||
if (command.parameterExists(withdrawalFeeAmountParamName)) {
|
||||
final Integer withdrawalFeeTypeValue = command.integerValueOfParameterNamed(withdrawalFeeTypeParamName);
|
||||
if (withdrawalFeeTypeValue != null) {
|
||||
withdrawalFeeType = SavingsWithdrawalFeesType.fromInt(withdrawalFeeTypeValue);
|
||||
}
|
||||
} else {
|
||||
withdrawalFeeType = product.withdrawalFeeType();
|
||||
}
|
||||
|
||||
boolean iswithdrawalFeeApplicableForTransfer = false;
|
||||
if (command.parameterExists(withdrawalFeeForTransfersParamName)) {
|
||||
iswithdrawalFeeApplicableForTransfer = command.booleanPrimitiveValueOfParameterNamed(withdrawalFeeForTransfersParamName);
|
||||
}
|
||||
|
||||
BigDecimal annualFeeAmount = null;
|
||||
if (command.parameterExists(annualFeeAmountParamName)) {
|
||||
annualFeeAmount = command.bigDecimalValueOfParameterNamed(annualFeeAmountParamName);
|
||||
} else {
|
||||
annualFeeAmount = product.annualFeeAmount();
|
||||
}
|
||||
|
||||
MonthDay monthDayOfAnnualFee = null;
|
||||
if (command.parameterExists(annualFeeOnMonthDayParamName)) {
|
||||
monthDayOfAnnualFee = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||
} else {
|
||||
monthDayOfAnnualFee = product.monthDayOfAnnualFee();
|
||||
}
|
||||
|
||||
final Set<SavingsAccountCharge> charges = this.savingsAccountChargeAssembler.fromParsedJson(element, product.currency().getCode());
|
||||
|
||||
final SavingsAccount account = SavingsAccount.createNewApplicationForSubmittal(client, group, product, fieldOfficer, accountNo,
|
||||
externalId, accountType, submittedOnDate, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, iswithdrawalFeeApplicableForTransfer, annualFeeAmount,
|
||||
monthDayOfAnnualFee, charges);
|
||||
lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, charges);
|
||||
account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper);
|
||||
|
||||
account.validateNewApplicationState(DateUtils.getLocalDateOfTenant());
|
||||
|
||||
+142
-31
@@ -9,6 +9,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.amountPara
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.dateFormatParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.dueAsOfDateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.localeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeOnMonthDayParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
@@ -28,6 +29,7 @@ import javax.persistence.TemporalType;
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||
@@ -53,15 +55,22 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
private Integer chargeTime;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "due_for_collection_as_of_date")
|
||||
@Column(name = "charge_due_date")
|
||||
private Date dueDate;
|
||||
|
||||
@Column(name = "fee_on_month", nullable = true)
|
||||
private Integer feeOnMonth;
|
||||
|
||||
@Column(name = "fee_on_day", nullable = true)
|
||||
private Integer feeOnDay;
|
||||
|
||||
@Column(name = "charge_calculation_enum")
|
||||
private Integer chargeCalculation;
|
||||
|
||||
@Column(name = "calculation_percentage", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal percentage;
|
||||
|
||||
// TODO AA: This field may not require for savings charges
|
||||
@Column(name = "calculation_on_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal amountPercentageAppliedTo;
|
||||
|
||||
@@ -89,29 +98,38 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
@Column(name = "waived", nullable = false)
|
||||
private boolean waived = false;
|
||||
|
||||
@Column(name = "is_active", nullable = false)
|
||||
private boolean status = true;
|
||||
|
||||
public static SavingsAccountCharge createNewFromJson(final SavingsAccount savingsAccount, final Charge chargeDefinition,
|
||||
final JsonCommand command) {
|
||||
|
||||
final BigDecimal amount = command.bigDecimalValueOfParameterNamed(amountParamName);
|
||||
final LocalDate dueDate = command.localDateValueOfParameterNamed(dueAsOfDateParamName);
|
||||
final MonthDay feeOnMonthDay = command.extractMonthDayNamed(feeOnMonthDayParamName);
|
||||
final ChargeTimeType chargeTime = null;
|
||||
final ChargeCalculationType chargeCalculation = null;
|
||||
final boolean status = true;
|
||||
|
||||
return new SavingsAccountCharge(savingsAccount, chargeDefinition, amount, chargeTime, chargeCalculation, dueDate);
|
||||
return new SavingsAccountCharge(savingsAccount, chargeDefinition, amount, chargeTime, chargeCalculation, dueDate, status,
|
||||
feeOnMonthDay);
|
||||
}
|
||||
|
||||
// TODO AA: refactor method signature
|
||||
public static SavingsAccountCharge createNewWithoutSavingsAccount(final Charge chargeDefinition, final BigDecimal amount,
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate dueDate) {
|
||||
return new SavingsAccountCharge(null, chargeDefinition, amount, chargeTime, chargeCalculation, dueDate);
|
||||
public static SavingsAccountCharge createNewWithoutSavingsAccount(final Charge chargeDefinition, final BigDecimal amountPayable,
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate dueDate, final boolean status,
|
||||
final MonthDay feeOnMonthDay) {
|
||||
return new SavingsAccountCharge(null, chargeDefinition, amountPayable, chargeTime, chargeCalculation, dueDate, status,
|
||||
feeOnMonthDay);
|
||||
}
|
||||
|
||||
protected SavingsAccountCharge() {
|
||||
//
|
||||
}
|
||||
|
||||
public SavingsAccountCharge(final SavingsAccount savingsAccount, final Charge chargeDefinition, final BigDecimal amount,
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate dueDate) {
|
||||
private SavingsAccountCharge(final SavingsAccount savingsAccount, final Charge chargeDefinition, final BigDecimal amount,
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate dueDate, final boolean status,
|
||||
final MonthDay feeOnMonthDay) {
|
||||
|
||||
this.savingsAccount = savingsAccount;
|
||||
this.charge = chargeDefinition;
|
||||
@@ -127,6 +145,16 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
|
||||
}
|
||||
|
||||
if (isAnnualFee()) {
|
||||
if (feeOnMonthDay == null) {
|
||||
final String defaultUserMessage = "Savings Account charge is missing due date.";
|
||||
throw new SavingsAccountChargeWithoutMandatoryFieldException("savingsaccount.charge", dueAsOfDateParamName,
|
||||
defaultUserMessage, chargeDefinition.getId(), chargeDefinition.getName());
|
||||
}
|
||||
this.feeOnMonth = feeOnMonthDay.getMonthOfYear();
|
||||
this.feeOnDay = feeOnMonthDay.getDayOfMonth();
|
||||
}
|
||||
|
||||
this.dueDate = (dueDate == null) ? null : dueDate.toDate();
|
||||
|
||||
this.chargeCalculation = chargeDefinition.getChargeCalculation();
|
||||
@@ -139,13 +167,18 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
chargeAmount = amount;
|
||||
}
|
||||
|
||||
final BigDecimal transactionAmount = new BigDecimal(0);// percentage
|
||||
// based fee is
|
||||
// not yet
|
||||
// supported for
|
||||
// savings
|
||||
final BigDecimal transactionAmount = new BigDecimal(0);
|
||||
|
||||
populateDerivedFields(transactionAmount, chargeAmount);
|
||||
resetOutstandingAmount();// reset only if it's withdrawal or annual fee
|
||||
this.paid = determineIfFullyPaid();
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
private void resetOutstandingAmount() {
|
||||
if (this.isWithdrawalFee()) {
|
||||
this.amountOutstanding = BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
private void populateDerivedFields(final BigDecimal transactionAmount, final BigDecimal chargeAmount) {
|
||||
@@ -219,6 +252,9 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
amountPaid = amountPaid.minus(transactionAmount);
|
||||
this.amountPaid = amountPaid.getAmount();
|
||||
this.amountOutstanding = calculateAmountOutstanding(currency);
|
||||
if (this.isWithdrawalFee()) {
|
||||
this.amountOutstanding = BigDecimal.ZERO;
|
||||
}
|
||||
this.paid = false;
|
||||
}
|
||||
|
||||
@@ -228,7 +264,7 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
this.waived = true;
|
||||
return getAmountWaived(currency);
|
||||
}
|
||||
|
||||
|
||||
public void undoWaiver(final MonetaryCurrency currency, final Money transactionAmount) {
|
||||
Money amountWaived = getAmountWaived(currency);
|
||||
amountWaived = amountWaived.minus(transactionAmount);
|
||||
@@ -257,16 +293,17 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
this.savingsAccount = savingsAccount;
|
||||
}
|
||||
|
||||
public void update(final BigDecimal amount, final LocalDate dueDate) {
|
||||
final BigDecimal transactionAmount = BigDecimal.ZERO;// percentage based
|
||||
// fee calculation
|
||||
// is not yet
|
||||
// supported for
|
||||
// Savings
|
||||
public void update(final BigDecimal amount, final LocalDate dueDate, final MonthDay feeOnMonthDay) {
|
||||
final BigDecimal transactionAmount = BigDecimal.ZERO;
|
||||
if (dueDate != null) {
|
||||
this.dueDate = dueDate.toDate();
|
||||
}
|
||||
|
||||
if (feeOnMonthDay != null) {
|
||||
this.feeOnMonth = feeOnMonthDay.getMonthOfYear();
|
||||
this.feeOnDay = feeOnMonthDay.getDayOfMonth();
|
||||
}
|
||||
|
||||
if (amount != null) {
|
||||
switch (ChargeCalculationType.fromInt(this.chargeCalculation)) {
|
||||
case INVALID:
|
||||
@@ -313,6 +350,24 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
this.dueDate = newValue.toDate();
|
||||
}
|
||||
|
||||
if (command.hasParameter(feeOnMonthDayParamName)) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed(feeOnMonthDayParamName);
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed(feeOnMonthDayParamName);
|
||||
final Integer dayOfMonthValue = monthDay.getDayOfMonth();
|
||||
if (this.feeOnDay != dayOfMonthValue) {
|
||||
actualChanges.put(feeOnMonthDayParamName, actualValueEntered);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.feeOnDay = dayOfMonthValue;
|
||||
}
|
||||
|
||||
final Integer monthOfYear = monthDay.getMonthOfYear();
|
||||
if (this.feeOnMonth != monthOfYear) {
|
||||
actualChanges.put(feeOnMonthDayParamName, actualValueEntered);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.feeOnMonth = monthOfYear;
|
||||
}
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamed(amountParamName, this.amount)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(amountParamName);
|
||||
actualChanges.put(amountParamName, newValue);
|
||||
@@ -322,6 +377,7 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
break;
|
||||
case FLAT:
|
||||
this.amount = newValue;
|
||||
this.amountOutstanding = calculateOutstanding();
|
||||
break;
|
||||
case PERCENT_OF_AMOUNT:
|
||||
this.percentage = newValue;
|
||||
@@ -347,10 +403,6 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public boolean isSpecifiedDueDate() {
|
||||
return ChargeTimeType.fromInt(this.chargeTime).equals(ChargeTimeType.SPECIFIED_DUE_DATE);
|
||||
}
|
||||
|
||||
private boolean isGreaterThanZero(final BigDecimal value) {
|
||||
return value.compareTo(BigDecimal.ZERO) == 1;
|
||||
}
|
||||
@@ -405,8 +457,8 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
public BigDecimal amount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
public BigDecimal amoutOutstanding(){
|
||||
|
||||
public BigDecimal amoutOutstanding() {
|
||||
return this.amountOutstanding;
|
||||
}
|
||||
|
||||
@@ -452,10 +504,10 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
return Money.of(currency, this.amountWrittenOff);
|
||||
}
|
||||
|
||||
public Money getAmountOutstanding(final MonetaryCurrency currency){
|
||||
public Money getAmountOutstanding(final MonetaryCurrency currency) {
|
||||
return Money.of(currency, this.amountOutstanding);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param incrementBy
|
||||
* Amount used to pay off this charge
|
||||
@@ -498,19 +550,35 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
return this.charge;
|
||||
}
|
||||
|
||||
public SavingsAccount savingsAccount() {
|
||||
return this.savingsAccount;
|
||||
}
|
||||
|
||||
public boolean isOnSpecifiedDueDate() {
|
||||
return ChargeTimeType.fromInt(this.chargeTime).isOnSpecifiedDueDate();
|
||||
}
|
||||
|
||||
public SavingsAccount savingsAccount(){
|
||||
return this.savingsAccount;
|
||||
public boolean isSavingsActivation() {
|
||||
return ChargeTimeType.fromInt(this.chargeTime).isSavingsActivation();
|
||||
}
|
||||
|
||||
|
||||
public boolean isSavingsClosure() {
|
||||
return ChargeTimeType.fromInt(this.chargeTime).isSavingsClosure();
|
||||
}
|
||||
|
||||
public boolean isWithdrawalFee() {
|
||||
return ChargeTimeType.fromInt(this.chargeTime).isWithdrawalFee();
|
||||
}
|
||||
|
||||
public boolean isAnnualFee() {
|
||||
return ChargeTimeType.fromInt(this.chargeTime).isAnnualFee();
|
||||
}
|
||||
|
||||
public boolean hasCurrencyCodeOf(final String matchingCurrencyCode) {
|
||||
if (this.currencyCode() == null || matchingCurrencyCode == null) { return false; }
|
||||
return this.currencyCode().equalsIgnoreCase(matchingCurrencyCode);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (obj == null) { return false; }
|
||||
@@ -533,4 +601,47 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
.append(this.amount).append(getDueLocalDate()) //
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
public BigDecimal updateWithdralFeeAmount(final BigDecimal transactionAmount) {
|
||||
BigDecimal amountPaybale = BigDecimal.ZERO;
|
||||
if (ChargeCalculationType.fromInt(this.chargeCalculation).isFlat()) {
|
||||
amountPaybale = this.amount;
|
||||
} else if (ChargeCalculationType.fromInt(this.chargeCalculation).isPercentageOfAmount()) {
|
||||
amountPaybale = transactionAmount.multiply(this.percentage).divide(BigDecimal.valueOf(100l));
|
||||
}
|
||||
this.amountOutstanding = amountPaybale;
|
||||
return amountPaybale;
|
||||
}
|
||||
|
||||
public void updateToNextAnnualFeeDueDateFrom(final LocalDate startingDate) {
|
||||
if (isAnnualFee()) {
|
||||
LocalDate nextDueLocalDate = startingDate.withMonthOfYear(this.feeOnMonth).withDayOfMonth(this.feeOnDay);
|
||||
if (startingDate.isAfter(nextDueLocalDate)) {
|
||||
nextDueLocalDate = nextDueLocalDate.plusYears(1);
|
||||
}
|
||||
this.dueDate = nextDueLocalDate.toDate();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateToNextAnnualFeeDueDate() {
|
||||
if (isAnnualFee()) {
|
||||
LocalDate nextDueLocalDate = new LocalDate(dueDate);
|
||||
this.dueDate = nextDueLocalDate.withMonthOfYear(this.feeOnMonth).withDayOfMonth(this.feeOnDay).plusYears(1).toDate();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateToPreviousAnnualFeeDueDate() {
|
||||
if (isAnnualFee()) {
|
||||
LocalDate previousDueLocalDate = new LocalDate(dueDate);
|
||||
this.dueDate = previousDueLocalDate.withMonthOfYear(this.feeOnMonth).withDayOfMonth(this.feeOnDay).minusYears(1).toDate();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean feeSettingsNotSet() {
|
||||
return !feeSettingsSet();
|
||||
}
|
||||
|
||||
public boolean feeSettingsSet() {
|
||||
return this.feeOnDay != null && this.feeOnMonth != null;
|
||||
}
|
||||
}
|
||||
+28
-5
@@ -12,6 +12,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargeIdPa
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargeTimeTypeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargesParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.dueAsOfDateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.idParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@@ -22,6 +23,7 @@ import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
@@ -61,6 +63,7 @@ public class SavingsAccountChargeAssembler {
|
||||
if (element.isJsonObject()) {
|
||||
final JsonObject topLevelJsonElement = element.getAsJsonObject();
|
||||
final String dateFormat = this.fromApiJsonHelper.extractDateFormatParameter(topLevelJsonElement);
|
||||
final String monthDayFormat = this.fromApiJsonHelper.extractMonthDayFormatParameter(topLevelJsonElement);
|
||||
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
|
||||
if (topLevelJsonElement.has(chargesParamName) && topLevelJsonElement.get(chargesParamName).isJsonArray()) {
|
||||
final JsonArray array = topLevelJsonElement.get(chargesParamName).getAsJsonArray();
|
||||
@@ -78,6 +81,8 @@ public class SavingsAccountChargeAssembler {
|
||||
final LocalDate dueDate = this.fromApiJsonHelper.extractLocalDateNamed(dueAsOfDateParamName, savingsChargeElement,
|
||||
dateFormat, locale);
|
||||
|
||||
final MonthDay feeOnMonthDay = this.fromApiJsonHelper.extractMonthDayNamed(feeOnMonthDayParamName, savingsChargeElement, monthDayFormat, locale);
|
||||
|
||||
if (id == null) {
|
||||
final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(chargeId);
|
||||
|
||||
@@ -95,8 +100,10 @@ public class SavingsAccountChargeAssembler {
|
||||
if (chargeCalculationType != null) {
|
||||
ChargeCalculationType.fromInt(chargeCalculationType);
|
||||
}
|
||||
|
||||
final boolean status = true;
|
||||
final SavingsAccountCharge savingsAccountCharge = SavingsAccountCharge.createNewWithoutSavingsAccount(
|
||||
chargeDefinition, amount, chargeTime, chargeCalculation, dueDate);
|
||||
chargeDefinition, amount, chargeTime, chargeCalculation, dueDate, status, feeOnMonthDay);
|
||||
savingsAccountCharges.add(savingsAccountCharge);
|
||||
} else {
|
||||
final Long savingsAccountChargeId = id;
|
||||
@@ -104,7 +111,7 @@ public class SavingsAccountChargeAssembler {
|
||||
.findOne(savingsAccountChargeId);
|
||||
if (savingsAccountCharge == null) { throw new SavingsAccountChargeNotFoundException(savingsAccountChargeId); }
|
||||
|
||||
savingsAccountCharge.update(amount, dueDate);
|
||||
savingsAccountCharge.update(amount, dueDate, feeOnMonthDay);
|
||||
|
||||
savingsAccountCharges.add(savingsAccountCharge);
|
||||
}
|
||||
@@ -120,11 +127,27 @@ public class SavingsAccountChargeAssembler {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||
for (SavingsAccountCharge savingsAccountCharge : charges) {
|
||||
if(!savingsAccountCharge.hasCurrencyCodeOf(productCurrencyCode)){
|
||||
baseDataValidator.reset().parameter("currency").value(savingsAccountCharge.getCharge().getId())
|
||||
boolean isOneWithdrawalPresent = false;
|
||||
boolean isOneAnnualPresent = false;
|
||||
for (SavingsAccountCharge charge : charges) {
|
||||
if(!charge.hasCurrencyCodeOf(productCurrencyCode)){
|
||||
baseDataValidator.reset().parameter("currency").value(charge.getCharge().getId())
|
||||
.failWithCodeNoParameterAddedToErrorCode("currency.and.charge.currency.not.same");
|
||||
}
|
||||
|
||||
if (charge.isWithdrawalFee()) {
|
||||
if (isOneWithdrawalPresent) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("multiple.withdrawal.fee.per.account.not.supported");
|
||||
}
|
||||
isOneWithdrawalPresent = true;
|
||||
}
|
||||
|
||||
if (charge.isAnnualFee()) {
|
||||
if (isOneAnnualPresent) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("multiple.annual.fee.per.account.not.supported");
|
||||
}
|
||||
isOneAnnualPresent = true;
|
||||
}
|
||||
}
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
+15
-7
@@ -116,7 +116,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
amount, isReversed);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction fee(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
|
||||
public static SavingsAccountTransaction withdrawalFee(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
|
||||
final Money amount) {
|
||||
final boolean isReversed = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue(), date, amount,
|
||||
@@ -211,7 +211,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public boolean isPostInterestCalculationRequired(){
|
||||
return this.isDeposit() || this.isWithdrawal() || this.isCharge();
|
||||
return this.isDeposit() || this.isWithdrawal() || this.isPayCharge();
|
||||
}
|
||||
|
||||
public boolean isInterestPostingAndNotReversed() {
|
||||
@@ -221,6 +221,10 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
public boolean isWithdrawalFeeAndNotReversed() {
|
||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isWithdrawalFee() && isNotReversed();
|
||||
}
|
||||
|
||||
public boolean isWithdrawalFee() {
|
||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isWithdrawalFee();
|
||||
}
|
||||
|
||||
public boolean isAnnualFeeAndNotReversed() {
|
||||
return isAnnualFee() && isNotReversed();
|
||||
@@ -456,11 +460,15 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public boolean isDebit() {
|
||||
return isWithdrawal() || isWithdrawalFeeAndNotReversed() || isAnnualFeeAndNotReversed() || isCharge();
|
||||
return isWithdrawal() || isWithdrawalFeeAndNotReversed() || isAnnualFeeAndNotReversed() || isPayCharge();
|
||||
}
|
||||
|
||||
public boolean isCharge() {
|
||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isCharge();
|
||||
public boolean isPayCharge() {
|
||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isPayCharge();
|
||||
}
|
||||
|
||||
public boolean isChargeTransaction(){
|
||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isChargeTransaction();
|
||||
}
|
||||
|
||||
public boolean isWaiveCharge(){
|
||||
@@ -469,12 +477,12 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
|
||||
public boolean isFeeCharge() {
|
||||
final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy();
|
||||
return (isCharge() && chargePaidBy != null) ? chargePaidBy.isFeeCharge() : false;
|
||||
return (isPayCharge() && chargePaidBy != null) ? chargePaidBy.isFeeCharge() : false;
|
||||
}
|
||||
|
||||
public boolean isPenaltyCharge() {
|
||||
final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy();
|
||||
return (isCharge() && chargePaidBy != null) ? chargePaidBy.isPenaltyCharge() : false;
|
||||
return (isPayCharge() && chargePaidBy != null) ? chargePaidBy.isPenaltyCharge() : false;
|
||||
}
|
||||
|
||||
public boolean isFeeChargeAndNotReversed() {
|
||||
|
||||
+39
-93
@@ -7,8 +7,6 @@ package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_RESOURCE_NAME;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.accountingRuleParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargesParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.currencyCodeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.descriptionParamName;
|
||||
@@ -24,9 +22,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeri
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
@@ -44,7 +40,6 @@ import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.accounting.common.AccountingRuleType;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
@@ -58,7 +53,6 @@ import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearT
|
||||
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsWithdrawalFeesType;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
@@ -123,24 +117,9 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
@Column(name = "accounting_type", nullable = false)
|
||||
private Integer accountingRule;
|
||||
|
||||
@Column(name = "withdrawal_fee_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal withdrawalFeeAmount;
|
||||
|
||||
@Column(name = "withdrawal_fee_type_enum", nullable = true)
|
||||
private Integer withdrawalFeeType;
|
||||
|
||||
@Column(name = "withdrawal_fee_for_transfer")
|
||||
private boolean withdrawalFeeApplicableForTransfer;
|
||||
|
||||
@Column(name = "annual_fee_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal annualFeeAmount;
|
||||
|
||||
@Column(name = "annual_fee_on_month", nullable = true)
|
||||
private Integer annualFeeOnMonth;
|
||||
|
||||
@Column(name = "annual_fee_on_day", nullable = true)
|
||||
private Integer annualFeeOnDay;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(name = "m_savings_product_charge", joinColumns = @JoinColumn(name = "savings_product_id"), inverseJoinColumns = @JoinColumn(name = "charge_id"))
|
||||
private Set<Charge> charges;
|
||||
@@ -150,14 +129,11 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay,
|
||||
final AccountingRuleType accountingRuleType, final Set<Charge> charges) {
|
||||
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set<Charge> charges) {
|
||||
|
||||
return new SavingsProduct(name, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, withdrawalFeeApplicableForTransfer, annualFeeAmount,
|
||||
annualFeeOnMonthDay, accountingRuleType, charges);
|
||||
lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges);
|
||||
}
|
||||
|
||||
protected SavingsProduct() {
|
||||
@@ -170,9 +146,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay,
|
||||
final AccountingRuleType accountingRuleType, final Set<Charge> charges) {
|
||||
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set<Charge> charges) {
|
||||
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
@@ -192,17 +166,13 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
if (lockinPeriodFrequency != null && lockinPeriodFrequencyType != null) {
|
||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType.getValue();
|
||||
}
|
||||
|
||||
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||
if (withdrawalFeeAmount != null && withdrawalFeeType != null) {
|
||||
this.withdrawalFeeType = withdrawalFeeType.getValue();
|
||||
}
|
||||
|
||||
this.withdrawalFeeApplicableForTransfer = withdrawalFeeApplicableForTransfer;
|
||||
this.annualFeeAmount = annualFeeAmount;
|
||||
/* this.annualFeeAmount = annualFeeAmount;
|
||||
if (annualFeeAmount != null && annualFeeOnMonthDay != null) {
|
||||
this.annualFeeOnMonth = annualFeeOnMonthDay.getMonthOfYear();
|
||||
this.annualFeeOnDay = annualFeeOnMonthDay.getDayOfMonth();
|
||||
}
|
||||
}*/
|
||||
|
||||
if (accountingRuleType != null) {
|
||||
this.accountingRule = accountingRuleType.getValue();
|
||||
@@ -213,8 +183,8 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
validateLockinDetails();
|
||||
validateWithdrawalFeeDetails();
|
||||
validateAnnualFeeDetails();
|
||||
//validateWithdrawalFeeDetails();
|
||||
//validateAnnualFeeDetails();
|
||||
}
|
||||
|
||||
public MonetaryCurrency currency() {
|
||||
@@ -257,30 +227,6 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
return type;
|
||||
}
|
||||
|
||||
public BigDecimal withdrawalFeeAmount() {
|
||||
return this.withdrawalFeeAmount;
|
||||
}
|
||||
|
||||
public SavingsWithdrawalFeesType withdrawalFeeType() {
|
||||
SavingsWithdrawalFeesType type = null;
|
||||
if (this.withdrawalFeeType != null) {
|
||||
type = SavingsWithdrawalFeesType.fromInt(this.withdrawalFeeType);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public BigDecimal annualFeeAmount() {
|
||||
return this.annualFeeAmount;
|
||||
}
|
||||
|
||||
public MonthDay monthDayOfAnnualFee() {
|
||||
MonthDay monthDay = null;
|
||||
if (this.annualFeeOnMonth != null && this.annualFeeOnDay != null) {
|
||||
monthDay = new MonthDay(this.annualFeeOnMonth, this.annualFeeOnDay);
|
||||
}
|
||||
return monthDay;
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(10);
|
||||
@@ -382,7 +328,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
if (this.lockinPeriodFrequency == null) {
|
||||
this.lockinPeriodFrequencyType = null;
|
||||
}
|
||||
|
||||
/*
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(withdrawalFeeAmountParamName, this.withdrawalFeeAmount)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(withdrawalFeeAmountParamName);
|
||||
actualChanges.put(withdrawalFeeAmountParamName, newValue);
|
||||
@@ -395,7 +341,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
actualChanges.put(withdrawalFeeTypeParamName, newValue);
|
||||
this.withdrawalFeeType = newValue != null ? SavingsWithdrawalFeesType.fromInt(newValue).getValue() : newValue;
|
||||
}
|
||||
|
||||
*/
|
||||
if (command.isChangeInBooleanParameterNamed(withdrawalFeeForTransfersParamName, this.withdrawalFeeApplicableForTransfer)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(withdrawalFeeForTransfersParamName);
|
||||
actualChanges.put(withdrawalFeeForTransfersParamName, newValue);
|
||||
@@ -403,40 +349,40 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
// set period type to null if frequency is null
|
||||
if (this.withdrawalFeeAmount == null) {
|
||||
this.withdrawalFeeType = null;
|
||||
}
|
||||
// if (this.withdrawalFeeAmount == null) {
|
||||
// this.withdrawalFeeType = null;
|
||||
// }
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(annualFeeAmountParamName, this.annualFeeAmount)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(annualFeeAmountParamName);
|
||||
actualChanges.put(annualFeeAmountParamName, newValue);
|
||||
/* if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(feeAmountParamName, this.annualFeeAmount)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(feeAmountParamName);
|
||||
actualChanges.put(feeAmountParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.annualFeeAmount = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamedDefaultingZeroToNull(annualFeeOnMonthDayParamName, this.annualFeeOnDay)) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed(annualFeeOnMonthDayParamName);
|
||||
if (command.isChangeInIntegerParameterNamedDefaultingZeroToNull(feeOnMonthDayParamName, this.annualFeeOnDay)) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed(feeOnMonthDayParamName);
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed(feeOnMonthDayParamName);
|
||||
final Integer newValue = monthDay != null ? monthDay.getDayOfMonth() : null;
|
||||
actualChanges.put(annualFeeOnMonthDayParamName, actualValueEntered);
|
||||
actualChanges.put(feeOnMonthDayParamName, actualValueEntered);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.annualFeeOnDay = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamedDefaultingZeroToNull(annualFeeOnMonthDayParamName, this.annualFeeOnMonth)) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed(annualFeeOnMonthDayParamName);
|
||||
if (command.isChangeInIntegerParameterNamedDefaultingZeroToNull(feeOnMonthDayParamName, this.annualFeeOnMonth)) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed(feeOnMonthDayParamName);
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed(feeOnMonthDayParamName);
|
||||
final Integer newValue = monthDay != null ? monthDay.getMonthOfYear() : null;
|
||||
actualChanges.put(annualFeeOnMonthDayParamName, actualValueEntered);
|
||||
actualChanges.put(feeOnMonthDayParamName, actualValueEntered);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.annualFeeOnMonth = newValue;
|
||||
}
|
||||
}*/
|
||||
|
||||
// set period type to null if frequency is null
|
||||
if (this.annualFeeAmount == null) {
|
||||
this.annualFeeOnDay = null;
|
||||
this.annualFeeOnMonth = null;
|
||||
}
|
||||
// // set period type to null if frequency is null
|
||||
// if (this.annualFeeAmount == null) {
|
||||
// this.annualFeeOnDay = null;
|
||||
// this.annualFeeOnMonth = null;
|
||||
// }
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(accountingRuleParamName, this.accountingRule)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(accountingRuleParamName);
|
||||
@@ -453,13 +399,13 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
validateLockinDetails();
|
||||
validateWithdrawalFeeDetails();
|
||||
validateAnnualFeeDetails();
|
||||
//validateWithdrawalFeeDetails();
|
||||
//validateAnnualFeeDetails();
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void validateAnnualFeeDetails() {
|
||||
/* private void validateAnnualFeeDetails() {
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
@@ -468,21 +414,21 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
if (this.annualFeeAmount == null) {
|
||||
|
||||
if (this.annualFeeOnMonth != null || this.annualFeeOnDay != null) {
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(this.annualFeeAmount).notNull();
|
||||
baseDataValidator.reset().parameter(feeAmountParamName).value(this.annualFeeAmount).notNull();
|
||||
}
|
||||
} else {
|
||||
|
||||
if (this.annualFeeOnMonth == null || this.annualFeeOnDay == null) {
|
||||
baseDataValidator.reset().parameter(annualFeeOnMonthDayParamName).value(this.annualFeeOnMonth).notNull();
|
||||
baseDataValidator.reset().parameter(feeOnMonthDayParamName).value(this.annualFeeOnMonth).notNull();
|
||||
}
|
||||
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(this.annualFeeAmount).zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter(feeAmountParamName).value(this.annualFeeAmount).zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
private void validateWithdrawalFeeDetails() {
|
||||
*/
|
||||
/* private void validateWithdrawalFeeDetails() {
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
@@ -503,7 +449,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
*/
|
||||
private void validateLockinDetails() {
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
+1
-17
@@ -5,8 +5,6 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargesParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.currencyCodeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.descriptionParamName;
|
||||
@@ -22,15 +20,12 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeri
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.accounting.common.AccountingRuleType;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||
@@ -43,7 +38,6 @@ import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearT
|
||||
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsWithdrawalFeesType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -107,20 +101,11 @@ public class SavingsProductAssembler {
|
||||
lockinPeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
|
||||
}
|
||||
|
||||
final BigDecimal withdrawalFeeAmount = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(withdrawalFeeAmountParamName);
|
||||
SavingsWithdrawalFeesType withdrawalFeeType = null;
|
||||
final Integer withdrawalFeeTypeValue = command.integerValueOfParameterNamed(withdrawalFeeTypeParamName);
|
||||
if (withdrawalFeeTypeValue != null) {
|
||||
withdrawalFeeType = SavingsWithdrawalFeesType.fromInt(withdrawalFeeTypeValue);
|
||||
}
|
||||
|
||||
boolean iswithdrawalFeeApplicableForTransfer = false;
|
||||
if (command.parameterExists(withdrawalFeeForTransfersParamName)) {
|
||||
iswithdrawalFeeApplicableForTransfer = command.booleanPrimitiveValueOfParameterNamed(withdrawalFeeForTransfersParamName);
|
||||
}
|
||||
|
||||
final BigDecimal annualFeeAmount = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(annualFeeAmountParamName);
|
||||
final MonthDay monthDayOfAnnualFee = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingRule"));
|
||||
|
||||
// Savings product charges
|
||||
@@ -128,8 +113,7 @@ public class SavingsProductAssembler {
|
||||
|
||||
return SavingsProduct.createNew(name, description, currency, interestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType,
|
||||
iswithdrawalFeeApplicableForTransfer, annualFeeAmount, monthDayOfAnnualFee, accountingRuleType, charges);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, accountingRuleType, charges);
|
||||
}
|
||||
|
||||
public Set<Charge> assembleListOfSavingsProductCharges(final JsonCommand command, final String savingsProductCurrencyCode) {
|
||||
|
||||
+6
-3
@@ -11,6 +11,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargeIdPa
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargeTimeTypeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargesParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.dueAsOfDateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.idParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@@ -19,6 +20,7 @@ import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.portfolio.charge.domain.Charge;
|
||||
import org.mifosplatform.portfolio.charge.domain.ChargeCalculationType;
|
||||
@@ -70,7 +72,8 @@ public class SavingsProductChargeAssembler {
|
||||
savingsChargeElement, locale);
|
||||
final LocalDate dueDate = this.fromApiJsonHelper.extractLocalDateNamed(dueAsOfDateParamName, savingsChargeElement,
|
||||
dateFormat, locale);
|
||||
|
||||
final MonthDay feeOnMonthDay = this.fromApiJsonHelper.extractMonthDayNamed(feeOnMonthDayParamName, savingsChargeElement);
|
||||
|
||||
if (id == null) {
|
||||
final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(chargeId);
|
||||
final ChargeTimeType chargeTime = null;
|
||||
@@ -82,7 +85,7 @@ public class SavingsProductChargeAssembler {
|
||||
ChargeCalculationType.fromInt(chargeCalculationType);
|
||||
}
|
||||
final SavingsAccountCharge savingsAccountCharge = SavingsAccountCharge.createNewWithoutSavingsAccount(
|
||||
chargeDefinition, amount, chargeTime, chargeCalculation, dueDate);
|
||||
chargeDefinition, amount, chargeTime, chargeCalculation, dueDate, true, feeOnMonthDay);
|
||||
savingsAccountCharges.add(savingsAccountCharge);
|
||||
} else {
|
||||
final Long savingsAccountChargeId = id;
|
||||
@@ -90,7 +93,7 @@ public class SavingsProductChargeAssembler {
|
||||
.findOne(savingsAccountChargeId);
|
||||
if (savingsAccountCharge == null) { throw new SavingsAccountChargeNotFoundException(savingsAccountChargeId); }
|
||||
|
||||
savingsAccountCharge.update(amount, dueDate);
|
||||
savingsAccountCharge.update(amount, dueDate, null);
|
||||
|
||||
savingsAccountCharges.add(savingsAccountCharge);
|
||||
}
|
||||
|
||||
+4
-1
@@ -17,6 +17,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Service
|
||||
public class ApplyAnnualFeeSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final SavingsAccountWritePlatformService writePlatformService;
|
||||
|
||||
@Autowired
|
||||
@@ -28,8 +29,10 @@ public class ApplyAnnualFeeSavingsAccountCommandHandler implements NewCommandSou
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
final LocalDate annualFeeTransactionDate = command.localDateValueOfParameterNamed("annualFeeTransactionDate");
|
||||
|
||||
return this.writePlatformService.applyAnnualFee(command.getSavingsId(), annualFeeTransactionDate);
|
||||
//return this.writePlatformService.applyAnnualFee(command.getSavingsId(), annualFeeTransactionDate);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+13
-4
@@ -12,6 +12,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
|
||||
@@ -55,7 +56,9 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou
|
||||
+ "sc.calculation_percentage as percentageOf, sc.calculation_on_amount as amountPercentageAppliedTo, "
|
||||
+ "sc.charge_time_enum as chargeTime, "
|
||||
+ "sc.is_penalty as penalty, "
|
||||
+ "sc.due_for_collection_as_of_date as dueAsOfDate, "
|
||||
+ "sc.charge_due_date as dueAsOfDate, "
|
||||
+ "sc.fee_on_month as feeOnMonth, "
|
||||
+ "sc.fee_on_day as feeOnDay, "
|
||||
+ "sc.charge_calculation_enum as chargeCalculation, "
|
||||
+ "c.currency_code as currencyCode, oc.name as currencyName, "
|
||||
+ "oc.decimal_places as currencyDecimalPlaces, oc.currency_multiplesof as inMultiplesOf, oc.display_symbol as currencyDisplaySymbol, "
|
||||
@@ -93,7 +96,13 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou
|
||||
final EnumOptionData chargeTimeType = ChargeEnumerations.chargeTimeType(chargeTime);
|
||||
|
||||
final LocalDate dueAsOfDate = JdbcSupport.getLocalDate(rs, "dueAsOfDate");
|
||||
|
||||
MonthDay feeOnMonthDay = null;
|
||||
final Integer feeOnMonth = JdbcSupport.getInteger(rs, "feeOnMonth");
|
||||
final Integer feeOnDay = JdbcSupport.getInteger(rs, "feeOnDay");
|
||||
if (feeOnDay != null) {
|
||||
feeOnMonthDay = new MonthDay(feeOnMonth, feeOnDay);
|
||||
}
|
||||
|
||||
final int chargeCalculation = rs.getInt("chargeCalculation");
|
||||
final EnumOptionData chargeCalculationType = ChargeEnumerations.chargeCalculationType(chargeCalculation);
|
||||
final boolean penalty = rs.getBoolean("penalty");
|
||||
@@ -102,7 +111,7 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou
|
||||
|
||||
return SavingsAccountChargeData.instance(id, chargeId, name, currency, amount, amountPaid, amountWaived, amountWrittenOff,
|
||||
amountOutstanding, chargeTimeType, dueAsOfDate, chargeCalculationType, percentageOf, amountPercentageAppliedTo,
|
||||
chargeOptions, penalty);
|
||||
chargeOptions, penalty, feeOnMonthDay);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +157,7 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou
|
||||
final SavingsAccountChargeMapper rm = new SavingsAccountChargeMapper();
|
||||
|
||||
final String sql = "select " + rm.schema() + " where sc.savings_account_id=? "
|
||||
+ " order by sc.charge_time_enum ASC, sc.due_for_collection_as_of_date ASC, sc.is_penalty ASC";
|
||||
+ " order by sc.charge_time_enum ASC, sc.charge_due_date ASC, sc.is_penalty ASC";
|
||||
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] { loanId });
|
||||
}
|
||||
|
||||
+1
-2
@@ -9,7 +9,6 @@ import java.util.Collection;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.service.Page;
|
||||
import org.mifosplatform.portfolio.group.service.SearchParameters;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountAnnualFeeData;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountData;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionData;
|
||||
|
||||
@@ -27,7 +26,7 @@ public interface SavingsAccountReadPlatformService {
|
||||
|
||||
Collection<SavingsAccountTransactionData> retrieveAllTransactions(Long savingsId);
|
||||
|
||||
Collection<SavingsAccountAnnualFeeData> retrieveAccountsWithAnnualFeeDue();
|
||||
//Collection<SavingsAccountAnnualFeeData> retrieveAccountsWithAnnualFeeDue();
|
||||
|
||||
SavingsAccountTransactionData retrieveSavingsTransaction(Long savingsId, Long transactionId);
|
||||
}
|
||||
+31
-35
@@ -14,7 +14,6 @@ import java.util.Collection;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
@@ -40,7 +39,6 @@ import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearT
|
||||
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountAnnualFeeData;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountApplicationTimelineData;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountChargeData;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountData;
|
||||
@@ -74,7 +72,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
private final SavingsAccountTransactionTemplateMapper transactionTemplateMapper;
|
||||
private final SavingsAccountTransactionsMapper transactionsMapper;
|
||||
private final SavingAccountMapper savingAccountMapper;
|
||||
private final SavingsAccountAnnualFeeMapper annualFeeMapper;
|
||||
//private final SavingsAccountAnnualFeeMapper annualFeeMapper;
|
||||
|
||||
// pagination
|
||||
private final PaginationHelper<SavingsAccountData> paginationHelper = new PaginationHelper<SavingsAccountData>();
|
||||
@@ -95,7 +93,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
this.transactionTemplateMapper = new SavingsAccountTransactionTemplateMapper();
|
||||
this.transactionsMapper = new SavingsAccountTransactionsMapper();
|
||||
this.savingAccountMapper = new SavingAccountMapper();
|
||||
this.annualFeeMapper = new SavingsAccountAnnualFeeMapper();
|
||||
//this.annualFeeMapper = new SavingsAccountAnnualFeeMapper();
|
||||
this.chargeReadPlatformService = chargeReadPlatformService;
|
||||
}
|
||||
|
||||
@@ -222,13 +220,13 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
sqlBuilder.append("sa.min_required_opening_balance as minRequiredOpeningBalance, ");
|
||||
sqlBuilder.append("sa.lockin_period_frequency as lockinPeriodFrequency,");
|
||||
sqlBuilder.append("sa.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
||||
sqlBuilder.append("sa.withdrawal_fee_amount as withdrawalFeeAmount,");
|
||||
sqlBuilder.append("sa.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, ");
|
||||
// sqlBuilder.append("sa.withdrawal_fee_amount as withdrawalFeeAmount,");
|
||||
// sqlBuilder.append("sa.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, ");
|
||||
sqlBuilder.append("sa.withdrawal_fee_for_transfer as withdrawalFeeForTransfers, ");
|
||||
sqlBuilder.append("sa.annual_fee_amount as annualFeeAmount,");
|
||||
sqlBuilder.append("sa.annual_fee_on_month as annualFeeOnMonth, ");
|
||||
sqlBuilder.append("sa.annual_fee_on_day as annualFeeOnDay, ");
|
||||
sqlBuilder.append("sa.annual_fee_next_due_date as annualFeeNextDueDate, ");
|
||||
// sqlBuilder.append("sa.annual_fee_amount as annualFeeAmount,");
|
||||
// sqlBuilder.append("sa.annual_fee_on_month as annualFeeOnMonth, ");
|
||||
// sqlBuilder.append("sa.annual_fee_on_day as annualFeeOnDay, ");
|
||||
// sqlBuilder.append("sa.annual_fee_next_due_date as annualFeeNextDueDate, ");
|
||||
sqlBuilder.append("sa.total_deposits_derived as totalDeposits, ");
|
||||
sqlBuilder.append("sa.total_withdrawals_derived as totalWithdrawals, ");
|
||||
sqlBuilder.append("sa.total_withdrawal_fees_derived as totalWithdrawalFees, ");
|
||||
@@ -351,17 +349,17 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
lockinPeriodFrequencyType = SavingsEnumerations.lockinPeriodFrequencyType(lockinPeriodType);
|
||||
}
|
||||
|
||||
final BigDecimal withdrawalFeeAmount = rs.getBigDecimal("withdrawalFeeAmount");
|
||||
/*final BigDecimal withdrawalFeeAmount = rs.getBigDecimal("withdrawalFeeAmount");
|
||||
|
||||
EnumOptionData withdrawalFeeType = null;
|
||||
final Integer withdrawalFeeTypeValue = JdbcSupport.getInteger(rs, "withdrawalFeeTypeEnum");
|
||||
if (withdrawalFeeTypeValue != null) {
|
||||
withdrawalFeeType = SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue);
|
||||
}
|
||||
}*/
|
||||
|
||||
final boolean withdrawalFeeForTransfers = rs.getBoolean("withdrawalFeeForTransfers");
|
||||
|
||||
final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
/*final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
|
||||
MonthDay annualFeeOnMonthDay = null;
|
||||
final Integer annualFeeOnMonth = JdbcSupport.getInteger(rs, "annualFeeOnMonth");
|
||||
@@ -371,7 +369,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
}
|
||||
|
||||
final LocalDate annualFeeNextDueDate = JdbcSupport.getLocalDate(rs, "annualFeeNextDueDate");
|
||||
|
||||
*/
|
||||
final BigDecimal totalDeposits = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalDeposits");
|
||||
final BigDecimal totalWithdrawals = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalWithdrawals");
|
||||
final BigDecimal totalWithdrawalFees = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalWithdrawalFees");
|
||||
@@ -390,8 +388,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
return SavingsAccountData.instance(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, withdrawalFeeForTransfers,
|
||||
annualFeeAmount, annualFeeOnMonthDay, annualFeeNextDueDate, summary);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -554,13 +551,13 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
return this.jdbcTemplate.queryForObject(sql, this.transactionsMapper, new Object[] { savingsId, transactionId });
|
||||
}
|
||||
|
||||
@Override
|
||||
/*@Override
|
||||
public Collection<SavingsAccountAnnualFeeData> retrieveAccountsWithAnnualFeeDue() {
|
||||
final String sql = "select " + this.annualFeeMapper.schema()
|
||||
+ " where sa.annual_fee_next_due_date is not null and sa.annual_fee_next_due_date <= NOW()";
|
||||
|
||||
return this.jdbcTemplate.query(sql, this.annualFeeMapper, new Object[] {});
|
||||
}
|
||||
}*/
|
||||
|
||||
private static final class SavingsAccountTransactionsMapper implements RowMapper<SavingsAccountTransactionData> {
|
||||
|
||||
@@ -732,12 +729,12 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
sqlBuilder.append("sp.min_required_opening_balance as minRequiredOpeningBalance, ");
|
||||
sqlBuilder.append("sp.lockin_period_frequency as lockinPeriodFrequency,");
|
||||
sqlBuilder.append("sp.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
||||
sqlBuilder.append("sp.withdrawal_fee_amount as withdrawalFeeAmount,");
|
||||
sqlBuilder.append("sp.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, ");
|
||||
sqlBuilder.append("sp.withdrawal_fee_for_transfer as withdrawalFeeForTransfers, ");
|
||||
sqlBuilder.append("sp.annual_fee_amount as annualFeeAmount,");
|
||||
sqlBuilder.append("sp.annual_fee_on_month as annualFeeOnMonth, ");
|
||||
sqlBuilder.append("sp.annual_fee_on_day as annualFeeOnDay ");
|
||||
// sqlBuilder.append("sp.withdrawal_fee_amount as withdrawalFeeAmount,");
|
||||
// sqlBuilder.append("sp.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, ");
|
||||
sqlBuilder.append("sp.withdrawal_fee_for_transfer as withdrawalFeeForTransfers ");
|
||||
// sqlBuilder.append("sp.annual_fee_amount as annualFeeAmount,");
|
||||
// sqlBuilder.append("sp.annual_fee_on_month as annualFeeOnMonth, ");
|
||||
// sqlBuilder.append("sp.annual_fee_on_day as annualFeeOnDay ");
|
||||
sqlBuilder.append("from m_savings_product sp ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = sp.currency_code ");
|
||||
|
||||
@@ -789,24 +786,24 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
lockinPeriodFrequencyType = SavingsEnumerations.lockinPeriodFrequencyType(lockinPeriodType);
|
||||
}
|
||||
|
||||
final BigDecimal withdrawalFeeAmount = rs.getBigDecimal("withdrawalFeeAmount");
|
||||
// final BigDecimal withdrawalFeeAmount = rs.getBigDecimal("withdrawalFeeAmount");
|
||||
|
||||
EnumOptionData withdrawalFeeType = null;
|
||||
/* EnumOptionData withdrawalFeeType = null;
|
||||
final Integer withdrawalFeeTypeValue = JdbcSupport.getInteger(rs, "withdrawalFeeTypeEnum");
|
||||
if (withdrawalFeeTypeValue != null) {
|
||||
withdrawalFeeType = SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue);
|
||||
}
|
||||
|
||||
*/
|
||||
final boolean withdrawalFeeForTransfers = rs.getBoolean("withdrawalFeeForTransfers");
|
||||
|
||||
final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
//final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
|
||||
MonthDay annualFeeOnMonthDay = null;
|
||||
/*MonthDay annualFeeOnMonthDay = null;
|
||||
final Integer annualFeeOnMonth = JdbcSupport.getInteger(rs, "annualFeeOnMonth");
|
||||
final Integer annualFeeOnDay = JdbcSupport.getInteger(rs, "annualFeeOnDay");
|
||||
if (annualFeeAmount != null && annualFeeOnDay != null) {
|
||||
annualFeeOnMonthDay = new MonthDay(annualFeeOnMonth, annualFeeOnDay);
|
||||
}
|
||||
}*/
|
||||
|
||||
Long clientId = null;
|
||||
String clientName = null;
|
||||
@@ -825,7 +822,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
final Long fieldOfficerId = null;
|
||||
final String fieldOfficerName = null;
|
||||
final SavingsAccountStatusEnumData status = null;
|
||||
final LocalDate annualFeeNextDueDate = null;
|
||||
// final LocalDate annualFeeNextDueDate = null;
|
||||
final SavingsAccountSummaryData summary = null;
|
||||
|
||||
final SavingsAccountApplicationTimelineData timeline = SavingsAccountApplicationTimelineData.templateDefault();
|
||||
@@ -833,12 +830,11 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
return SavingsAccountData.instance(null, null, null, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualIterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, withdrawalFeeForTransfers,
|
||||
annualFeeAmount, annualFeeOnMonthDay, annualFeeNextDueDate, summary);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class SavingsAccountAnnualFeeMapper implements RowMapper<SavingsAccountAnnualFeeData> {
|
||||
/*private static final class SavingsAccountAnnualFeeMapper implements RowMapper<SavingsAccountAnnualFeeData> {
|
||||
|
||||
private final String schemaSql;
|
||||
|
||||
@@ -864,5 +860,5 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
|
||||
return SavingsAccountAnnualFeeData.instance(id, accountNo, annualFeeNextDueDate);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
+1
-1
@@ -20,7 +20,7 @@ public interface SavingsAccountWritePlatformService {
|
||||
|
||||
CommandProcessingResult withdrawal(Long savingsId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult applyAnnualFee(Long savingsId, LocalDate annualFeeTransactionDate);
|
||||
/*CommandProcessingResult applyAnnualFee(Long savingsId, LocalDate annualFeeTransactionDate);*/
|
||||
|
||||
CommandProcessingResult calculateInterest(Long savingsId);
|
||||
|
||||
|
||||
+31
-11
@@ -57,6 +57,7 @@ import org.mifosplatform.portfolio.note.domain.Note;
|
||||
import org.mifosplatform.portfolio.note.domain.NoteRepository;
|
||||
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
import org.mifosplatform.portfolio.paymentdetail.service.PaymentDetailWritePlatformService;
|
||||
import org.mifosplatform.portfolio.savings.SavingsAccountTransactionType;
|
||||
import org.mifosplatform.portfolio.savings.SavingsApiConstants;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountChargeDataValidator;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionDTO;
|
||||
@@ -70,7 +71,6 @@ import org.mifosplatform.portfolio.savings.domain.SavingsAccountRepository;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountStatusType;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransactionRepository;
|
||||
import org.mifosplatform.portfolio.savings.exception.InsufficientAccountBalanceException;
|
||||
import org.mifosplatform.portfolio.savings.exception.SavingsAccountClosingNotAllowedException;
|
||||
import org.mifosplatform.portfolio.savings.exception.SavingsAccountTransactionNotFoundException;
|
||||
import org.mifosplatform.portfolio.savings.exception.TransactionUpdateNotAllowedException;
|
||||
@@ -152,6 +152,18 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
|
||||
final Map<String, Object> changes = account.activate(user, command, DateUtils.getLocalDateOfTenant());
|
||||
if (!changes.isEmpty()) {
|
||||
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
if (account.isBeforeLastPostingPeriod(account.getActivationLocalDate())) {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.postInterest(mc, today);
|
||||
} else {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.calculateInterestUsing(mc, today);
|
||||
}
|
||||
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(SavingsAccountTransactionType.PAY_CHARGE.name());
|
||||
|
||||
this.savingAccountRepository.save(account);
|
||||
}
|
||||
|
||||
@@ -236,7 +248,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
.build();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
/*@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult applyAnnualFee(final Long savingsId, final LocalDate annualFeeTransactionDate) {
|
||||
|
||||
@@ -265,7 +277,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
.withGroupId(account.groupId()) //
|
||||
.withSavingsId(savingsId) //
|
||||
.build();
|
||||
}
|
||||
}*/
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
@@ -356,6 +368,17 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
throwValidationForActiveStatus(SavingsApiConstants.undoTransactionAction);
|
||||
}
|
||||
account.undoTransaction(transactionId);
|
||||
|
||||
// undoing transaction is withdrawal then undo withdrawal fee
|
||||
// transaction if any
|
||||
if (savingsAccountTransaction.isWithdrawal()) {
|
||||
final SavingsAccountTransaction nextSavingsAccountTransaction = this.savingsAccountTransactionRepository
|
||||
.findOneByIdAndSavingsAccountId(transactionId + 1, savingsId);
|
||||
if (nextSavingsAccountTransaction != null && nextSavingsAccountTransaction.isWithdrawalFeeAndNotReversed()) {
|
||||
account.undoTransaction(transactionId + 1);
|
||||
}
|
||||
}
|
||||
|
||||
checkClientOrGroupActive(account);
|
||||
if (savingsAccountTransaction.isPostInterestCalculationRequired()
|
||||
&& account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate())) {
|
||||
@@ -604,7 +627,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
checkClientOrGroupActive(savingsAccount);
|
||||
|
||||
final Locale locale = command.extractLocale();
|
||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
||||
final String format = command.dateFormat();
|
||||
final DateTimeFormatter fmt = StringUtils.isNotBlank(format) ? DateTimeFormat.forPattern(format).withLocale(locale) : DateTimeFormat.forPattern("dd MM yyyy");
|
||||
|
||||
final Long chargeDefinitionId = command.longValueOfParameterNamed(chargeIdParamName);
|
||||
final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(chargeDefinitionId);
|
||||
@@ -810,19 +834,15 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
// always use current date as transaction date for batch job
|
||||
final LocalDate transactionDate = DateUtils.getLocalDateOfTenant();
|
||||
final List<SavingsAccountCharge> pendingCharges = this.savingsAccountChargeRepository.findPendingCharges(transactionDate.toDate());
|
||||
// final List<SavingsAccountCharge> paidCharges = new
|
||||
// ArrayList<SavingsAccountCharge>(pendingCharges.size());
|
||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern("dd MM yyyy");
|
||||
for (SavingsAccountCharge savingsAccountCharge : pendingCharges) {
|
||||
try {
|
||||
payCharge(savingsAccountCharge, transactionDate, savingsAccountCharge.amoutOutstanding(), fmt);
|
||||
} catch (InsufficientAccountBalanceException isab) {
|
||||
payCharge(savingsAccountCharge, transactionDate, savingsAccountCharge.amoutOutstanding(), fmt);
|
||||
} catch (Exception exception) {
|
||||
// TODO: AA - provide a meaningful error with failed
|
||||
// transactions list
|
||||
}
|
||||
}
|
||||
|
||||
// this.savingsAccountChargeRepository.save(paidCharges);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -845,7 +865,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
account.calculateInterestUsing(mc, today);
|
||||
}
|
||||
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(amountPaid);
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(SavingsAccountTransactionType.PAY_CHARGE.name());
|
||||
|
||||
this.savingAccountRepository.save(account);
|
||||
|
||||
|
||||
+10
-12
@@ -10,7 +10,6 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.accounting.common.AccountingEnumerations;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
@@ -87,12 +86,12 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
sqlBuilder.append("sp.min_required_opening_balance as minRequiredOpeningBalance, ");
|
||||
sqlBuilder.append("sp.lockin_period_frequency as lockinPeriodFrequency,");
|
||||
sqlBuilder.append("sp.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
||||
sqlBuilder.append("sp.withdrawal_fee_amount as withdrawalFeeAmount,");
|
||||
sqlBuilder.append("sp.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, ");
|
||||
// sqlBuilder.append("sp.withdrawal_fee_amount as withdrawalFeeAmount,");
|
||||
// sqlBuilder.append("sp.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, ");
|
||||
sqlBuilder.append("sp.withdrawal_fee_for_transfer as withdrawalFeeForTransfers, ");
|
||||
sqlBuilder.append("sp.annual_fee_amount as annualFeeAmount,");
|
||||
sqlBuilder.append("sp.annual_fee_on_month as annualFeeOnMonth, ");
|
||||
sqlBuilder.append("sp.annual_fee_on_day as annualFeeOnDay, ");
|
||||
// sqlBuilder.append("sp.annual_fee_amount as annualFeeAmount,");
|
||||
// sqlBuilder.append("sp.annual_fee_on_month as annualFeeOnMonth, ");
|
||||
// sqlBuilder.append("sp.annual_fee_on_day as annualFeeOnDay, ");
|
||||
sqlBuilder.append("sp.accounting_type as accountingType ");
|
||||
sqlBuilder.append("from m_savings_product sp ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = sp.currency_code ");
|
||||
@@ -150,17 +149,17 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
lockinPeriodFrequencyType = SavingsEnumerations.lockinPeriodFrequencyType(lockinPeriodFrequencyTypeValue);
|
||||
}
|
||||
|
||||
final BigDecimal withdrawalFeeAmount = rs.getBigDecimal("withdrawalFeeAmount");
|
||||
/*final BigDecimal withdrawalFeeAmount = rs.getBigDecimal("withdrawalFeeAmount");
|
||||
|
||||
EnumOptionData withdrawalFeeType = null;
|
||||
final Integer withdrawalFeeTypeValue = JdbcSupport.getInteger(rs, "withdrawalFeeTypeEnum");
|
||||
if (withdrawalFeeTypeValue != null) {
|
||||
withdrawalFeeType = SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue);
|
||||
}
|
||||
|
||||
*/
|
||||
final boolean withdrawalFeeForTransfers = rs.getBoolean("withdrawalFeeForTransfers");
|
||||
|
||||
final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
/* final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
|
||||
MonthDay annualFeeOnMonthDay = null;
|
||||
final Integer annualFeeOnMonth = JdbcSupport.getInteger(rs, "annualFeeOnMonth");
|
||||
@@ -168,11 +167,10 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
if (annualFeeAmount != null && annualFeeOnDay != null) {
|
||||
annualFeeOnMonthDay = new MonthDay(annualFeeOnMonth, annualFeeOnDay);
|
||||
}
|
||||
|
||||
*/
|
||||
return SavingsProductData.instance(id, name, description, currency, nominalAnnualInterestRate, compoundingInterestPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, withdrawalFeeForTransfers,
|
||||
annualFeeAmount, annualFeeOnMonthDay, accountingRuleType);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, accountingRuleType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-8
@@ -5,16 +5,10 @@
|
||||
*/
|
||||
package org.mifosplatform.scheduledjobs.service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.infrastructure.core.service.RoutingDataSourceServiceFactory;
|
||||
import org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.mifosplatform.infrastructure.jobs.annotation.CronTarget;
|
||||
import org.mifosplatform.infrastructure.jobs.service.JobName;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountAnnualFeeData;
|
||||
import org.mifosplatform.portfolio.savings.service.SavingsAccountReadPlatformService;
|
||||
import org.mifosplatform.portfolio.savings.service.SavingsAccountWritePlatformService;
|
||||
import org.slf4j.Logger;
|
||||
@@ -30,7 +24,9 @@ public class ScheduledJobRunnerServiceImpl implements ScheduledJobRunnerService
|
||||
private final static Logger logger = LoggerFactory.getLogger(ScheduledJobRunnerServiceImpl.class);
|
||||
|
||||
private final RoutingDataSourceServiceFactory dataSourceServiceFactory;
|
||||
@SuppressWarnings("unused")
|
||||
private final SavingsAccountWritePlatformService savingsAccountWritePlatformService;
|
||||
@SuppressWarnings("unused")
|
||||
private final SavingsAccountReadPlatformService savingsAccountReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
@@ -203,7 +199,7 @@ public class ScheduledJobRunnerServiceImpl implements ScheduledJobRunnerService
|
||||
@CronTarget(jobName = JobName.APPLY_ANNUAL_FEE_FOR_SAVINGS)
|
||||
public void applyAnnualFeeForSavings() {
|
||||
|
||||
final Collection<SavingsAccountAnnualFeeData> annualFeeData = this.savingsAccountReadPlatformService
|
||||
/*final Collection<SavingsAccountAnnualFeeData> annualFeeData = this.savingsAccountReadPlatformService
|
||||
.retrieveAccountsWithAnnualFeeDue();
|
||||
|
||||
for (final SavingsAccountAnnualFeeData savingsAccountReference : annualFeeData) {
|
||||
@@ -219,6 +215,6 @@ public class ScheduledJobRunnerServiceImpl implements ScheduledJobRunnerService
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Savings accounts affected by update: " + annualFeeData.size());
|
||||
logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Savings accounts affected by update: " + annualFeeData.size());*/
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user