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