FINERACT-1374:Withdrawal-Fee-Scheme
This commit is contained in:
+51
-26
@@ -30,6 +30,7 @@ import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountChargeData;
|
||||
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
||||
@@ -43,6 +44,10 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
private final String name;
|
||||
private final boolean active;
|
||||
private final boolean penalty;
|
||||
private final boolean freeWithdrawal;
|
||||
private final Integer freeWithdrawalChargeFrequency;
|
||||
private final Integer restartFrequency;
|
||||
private final Integer restartFrequencyEnum;
|
||||
private final CurrencyData currency;
|
||||
private final BigDecimal amount;
|
||||
private final EnumOptionData chargeTimeType;
|
||||
@@ -94,8 +99,8 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
final GLAccountData account = null;
|
||||
final TaxGroupData taxGroupData = null;
|
||||
|
||||
return new ChargeData(null, null, null, null, null, null, null, null, false, false, taxGroupData, currencyOptions,
|
||||
chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, chargePaymentModeOptions,
|
||||
return new ChargeData(null, null, null, null, null, null, null, null, false, false, false, null, null, null, taxGroupData,
|
||||
currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, chargePaymentModeOptions,
|
||||
loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions,
|
||||
savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, null, null, null, null, null,
|
||||
feeFrequencyOptions, account, incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions,
|
||||
@@ -104,7 +109,8 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
|
||||
public static ChargeData withTemplate(final ChargeData charge, final ChargeData template) {
|
||||
return new ChargeData(charge.id, charge.name, charge.amount, charge.currency, charge.chargeTimeType, charge.chargeAppliesTo,
|
||||
charge.chargeCalculationType, charge.chargePaymentMode, charge.penalty, charge.active, charge.taxGroup,
|
||||
charge.chargeCalculationType, charge.chargePaymentMode, charge.penalty, charge.active, charge.freeWithdrawal,
|
||||
charge.freeWithdrawalChargeFrequency, charge.restartFrequency, charge.restartFrequencyEnum, charge.taxGroup,
|
||||
template.currencyOptions, template.chargeCalculationTypeOptions, template.chargeAppliesToOptions,
|
||||
template.chargeTimeTypeOptions, template.chargePaymetModeOptions, template.loanChargeCalculationTypeOptions,
|
||||
template.loanChargeTimeTypeOptions, template.savingsChargeCalculationTypeOptions, template.savingsChargeTimeTypeOptions,
|
||||
@@ -118,7 +124,8 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
public static ChargeData instance(final Long id, final String name, final BigDecimal amount, final CurrencyData currency,
|
||||
final EnumOptionData chargeTimeType, final EnumOptionData chargeAppliesTo, final EnumOptionData chargeCalculationType,
|
||||
final EnumOptionData chargePaymentMode, final MonthDay feeOnMonthDay, final Integer feeInterval, final boolean penalty,
|
||||
final boolean active, final BigDecimal minCap, final BigDecimal maxCap, final EnumOptionData feeFrequency,
|
||||
final boolean active, final boolean freeWithdrawal, final Integer freeWithdrawalChargeFrequency, final Integer restartFrequency,
|
||||
final Integer restartFrequencyEnum, final BigDecimal minCap, final BigDecimal maxCap, final EnumOptionData feeFrequency,
|
||||
final GLAccountData accountData, TaxGroupData taxGroupData) {
|
||||
|
||||
final Collection<CurrencyData> currencyOptions = null;
|
||||
@@ -141,12 +148,13 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
final List<GLAccountData> expenseAccountOptions = null;
|
||||
final List<GLAccountData> assetAccountOptions = null;
|
||||
return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode,
|
||||
penalty, active, taxGroupData, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions,
|
||||
chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
|
||||
savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
|
||||
clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions, accountData,
|
||||
incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions,
|
||||
accountMappingForChargeConfig, expenseAccountOptions, assetAccountOptions);
|
||||
penalty, active, freeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency, restartFrequencyEnum, taxGroupData,
|
||||
currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, chargePaymentModeOptions,
|
||||
loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions,
|
||||
savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval,
|
||||
minCap, maxCap, feeFrequency, feeFrequencyOptions, accountData, incomeOrLiabilityAccountOptions, taxGroupOptions,
|
||||
shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions, accountMappingForChargeConfig, expenseAccountOptions,
|
||||
assetAccountOptions);
|
||||
}
|
||||
|
||||
public static ChargeData lookup(final Long id, final String name, final boolean isPenalty) {
|
||||
@@ -160,6 +168,12 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
final Integer feeInterval = null;
|
||||
final Boolean penalty = isPenalty;
|
||||
final Boolean active = false;
|
||||
final Boolean freeWithdrawal = false;
|
||||
final Integer freeWithdrawalChargeFrequency = null;
|
||||
final Integer restartFrequency = null;
|
||||
final Integer restartFrequencyEnum = null;
|
||||
final Boolean isPaymentType = false;
|
||||
final PaymentTypeData paymentTypeOptions = null;
|
||||
final BigDecimal minCap = null;
|
||||
final BigDecimal maxCap = null;
|
||||
final Collection<CurrencyData> currencyOptions = null;
|
||||
@@ -186,25 +200,27 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
final List<GLAccountData> assetAccountOptions = null;
|
||||
|
||||
return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode,
|
||||
penalty, active, taxGroupData, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions,
|
||||
chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
|
||||
savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
|
||||
clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions, account,
|
||||
incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions,
|
||||
accountMappingForChargeConfig, expenseAccountOptions, assetAccountOptions);
|
||||
penalty, active, freeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency, restartFrequencyEnum, taxGroupData,
|
||||
currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, chargePaymentModeOptions,
|
||||
loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions,
|
||||
savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval,
|
||||
minCap, maxCap, feeFrequency, feeFrequencyOptions, account, incomeOrLiabilityAccountOptions, taxGroupOptions,
|
||||
shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions, accountMappingForChargeConfig, expenseAccountOptions,
|
||||
assetAccountOptions);
|
||||
}
|
||||
|
||||
private ChargeData(final Long id, final String name, final BigDecimal amount, final CurrencyData currency,
|
||||
final EnumOptionData chargeTimeType, final EnumOptionData chargeAppliesTo, final EnumOptionData chargeCalculationType,
|
||||
final EnumOptionData chargePaymentMode, final boolean penalty, final boolean active, final TaxGroupData taxGroupData,
|
||||
final Collection<CurrencyData> currencyOptions, final List<EnumOptionData> chargeCalculationTypeOptions,
|
||||
final List<EnumOptionData> chargeAppliesToOptions, final List<EnumOptionData> chargeTimeTypeOptions,
|
||||
final List<EnumOptionData> chargePaymentModeOptions, final List<EnumOptionData> loansChargeCalculationTypeOptions,
|
||||
final List<EnumOptionData> loansChargeTimeTypeOptions, final List<EnumOptionData> savingsChargeCalculationTypeOptions,
|
||||
final List<EnumOptionData> savingsChargeTimeTypeOptions, final List<EnumOptionData> clientChargeCalculationTypeOptions,
|
||||
final List<EnumOptionData> clientChargeTimeTypeOptions, final MonthDay feeOnMonthDay, final Integer feeInterval,
|
||||
final BigDecimal minCap, final BigDecimal maxCap, final EnumOptionData feeFrequency,
|
||||
final List<EnumOptionData> feeFrequencyOptions, final GLAccountData account,
|
||||
final EnumOptionData chargePaymentMode, final boolean penalty, final boolean active, final boolean freeWithdrawal,
|
||||
final Integer freeWithdrawalChargeFrequency, final Integer restartFrequency, final Integer restartFrequencyEnum,
|
||||
final TaxGroupData taxGroupData, final Collection<CurrencyData> currencyOptions,
|
||||
final List<EnumOptionData> chargeCalculationTypeOptions, final List<EnumOptionData> chargeAppliesToOptions,
|
||||
final List<EnumOptionData> chargeTimeTypeOptions, final List<EnumOptionData> chargePaymentModeOptions,
|
||||
final List<EnumOptionData> loansChargeCalculationTypeOptions, final List<EnumOptionData> loansChargeTimeTypeOptions,
|
||||
final List<EnumOptionData> savingsChargeCalculationTypeOptions, final List<EnumOptionData> savingsChargeTimeTypeOptions,
|
||||
final List<EnumOptionData> clientChargeCalculationTypeOptions, final List<EnumOptionData> clientChargeTimeTypeOptions,
|
||||
final MonthDay feeOnMonthDay, final Integer feeInterval, final BigDecimal minCap, final BigDecimal maxCap,
|
||||
final EnumOptionData feeFrequency, final List<EnumOptionData> feeFrequencyOptions, final GLAccountData account,
|
||||
final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions, final Collection<TaxGroupData> taxGroupOptions,
|
||||
final List<EnumOptionData> shareChargeCalculationTypeOptions, final List<EnumOptionData> shareChargeTimeTypeOptions,
|
||||
final String accountMappingForChargeConfig, final List<GLAccountData> expenseAccountOptions,
|
||||
@@ -221,6 +237,10 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
this.feeOnMonthDay = feeOnMonthDay;
|
||||
this.penalty = penalty;
|
||||
this.active = active;
|
||||
this.freeWithdrawal = freeWithdrawal;
|
||||
this.freeWithdrawalChargeFrequency = freeWithdrawalChargeFrequency;
|
||||
this.restartFrequency = restartFrequency;
|
||||
this.restartFrequencyEnum = restartFrequencyEnum;
|
||||
this.minCap = minCap;
|
||||
this.maxCap = maxCap;
|
||||
this.currencyOptions = currencyOptions;
|
||||
@@ -294,12 +314,17 @@ public final class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
final Collection<ChargeData> chargeOptions = null;
|
||||
final LocalDate dueAsOfDate = null;
|
||||
final Boolean isActive = null;
|
||||
final Boolean isFreeWithdrawal = null;
|
||||
final Integer freeWithdrawalChargeFrequency = null;
|
||||
final Integer restartFrequency = null;
|
||||
final Integer restartFrequencyEnum = null;
|
||||
|
||||
final LocalDate inactivationDate = null;
|
||||
|
||||
return SavingsAccountChargeData.instance(savingsChargeId, this.id, savingsAccountId, this.name, this.currency, this.amount,
|
||||
amountPaid, amountWaived, amountWrittenOff, amountOutstanding, this.chargeTimeType, dueAsOfDate, this.chargeCalculationType,
|
||||
percentage, amountPercentageAppliedTo, chargeOptions, this.penalty, this.feeOnMonthDay, this.feeInterval, isActive,
|
||||
inactivationDate);
|
||||
isFreeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency, restartFrequencyEnum, inactivationDate);
|
||||
}
|
||||
|
||||
public ShareAccountChargeData toShareAccountChargeData() {
|
||||
|
||||
+89
-4
@@ -48,6 +48,7 @@ import org.apache.fineract.portfolio.charge.exception.ChargeDueAtDisbursementCan
|
||||
import org.apache.fineract.portfolio.charge.exception.ChargeMustBePenaltyException;
|
||||
import org.apache.fineract.portfolio.charge.exception.ChargeParameterUpdateNotSupportedException;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeEnumerations;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
||||
import org.apache.fineract.portfolio.tax.domain.TaxGroup;
|
||||
|
||||
@@ -103,6 +104,18 @@ public class Charge extends AbstractPersistableCustom {
|
||||
@Column(name = "fee_frequency", nullable = true)
|
||||
private Integer feeFrequency;
|
||||
|
||||
@Column(name = "is_free_withdrawal", nullable = false)
|
||||
private boolean enableFreeWithdrawal;
|
||||
|
||||
@Column(name = "free_withdrawal_charge_frequency", nullable = true)
|
||||
private Integer freeWithdrawalFrequency;
|
||||
|
||||
@Column(name = "restart_frequency", nullable = true)
|
||||
private Integer restartFrequency;
|
||||
|
||||
@Column(name = "restart_frequency_enum", nullable = true)
|
||||
private Integer restartFrequencyEnum;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "income_or_liability_account_id")
|
||||
private GLAccount account;
|
||||
@@ -112,6 +125,7 @@ public class Charge extends AbstractPersistableCustom {
|
||||
private TaxGroup taxGroup;
|
||||
|
||||
public static Charge fromJson(final JsonCommand command, final GLAccount account, final TaxGroup taxGroup) {
|
||||
|
||||
final String name = command.stringValueOfParameterNamed("name");
|
||||
final BigDecimal amount = command.bigDecimalValueOfParameterNamed("amount");
|
||||
final String currencyCode = command.stringValueOfParameterNamed("currencyCode");
|
||||
@@ -132,8 +146,23 @@ public class Charge extends AbstractPersistableCustom {
|
||||
final BigDecimal maxCap = command.bigDecimalValueOfParameterNamed("maxCap");
|
||||
final Integer feeFrequency = command.integerValueOfParameterNamed("feeFrequency");
|
||||
|
||||
boolean enableFreeWithdrawalCharge = false;
|
||||
enableFreeWithdrawalCharge = command.booleanPrimitiveValueOfParameterNamed("enableFreeWithdrawalCharge");
|
||||
|
||||
Integer freeWithdrawalFrequency = null;
|
||||
Integer restartCountFrequency = null;
|
||||
PeriodFrequencyType countFrequencyType = null;
|
||||
|
||||
if (enableFreeWithdrawalCharge) {
|
||||
freeWithdrawalFrequency = command.integerValueOfParameterNamed("freeWithdrawalFrequency");
|
||||
restartCountFrequency = command.integerValueOfParameterNamed("restartCountFrequency");
|
||||
|
||||
countFrequencyType = PeriodFrequencyType.fromInt(command.integerValueOfParameterNamed("countFrequencyType"));
|
||||
}
|
||||
|
||||
return new Charge(name, amount, currencyCode, chargeAppliesTo, chargeTimeType, chargeCalculationType, penalty, active, paymentMode,
|
||||
feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, account, taxGroup);
|
||||
feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, enableFreeWithdrawalCharge, freeWithdrawalFrequency,
|
||||
restartCountFrequency, countFrequencyType, account, taxGroup);
|
||||
}
|
||||
|
||||
protected Charge() {}
|
||||
@@ -141,7 +170,9 @@ public class Charge extends AbstractPersistableCustom {
|
||||
private Charge(final String name, final BigDecimal amount, final String currencyCode, final ChargeAppliesTo chargeAppliesTo,
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculationType, final boolean penalty, final boolean active,
|
||||
final ChargePaymentMode paymentMode, final MonthDay feeOnMonthDay, final Integer feeInterval, final BigDecimal minCap,
|
||||
final BigDecimal maxCap, final Integer feeFrequency, final GLAccount account, final TaxGroup taxGroup) {
|
||||
final BigDecimal maxCap, final Integer feeFrequency, final boolean enableFreeWithdrawalCharge,
|
||||
final Integer freeWithdrawalFrequency, final Integer restartFrequency, final PeriodFrequencyType restartFrequencyEnum,
|
||||
final GLAccount account, final TaxGroup taxGroup) {
|
||||
this.name = name;
|
||||
this.amount = amount;
|
||||
this.currencyCode = currencyCode;
|
||||
@@ -186,6 +217,13 @@ public class Charge extends AbstractPersistableCustom {
|
||||
"savings.charge.calculation.type.percentage.allowed.only.for.withdrawal.or.NoActivity");
|
||||
}
|
||||
|
||||
if (enableFreeWithdrawalCharge) {
|
||||
this.enableFreeWithdrawal = enableFreeWithdrawalCharge;
|
||||
this.freeWithdrawalFrequency = freeWithdrawalFrequency;
|
||||
this.restartFrequency = restartFrequency;
|
||||
this.restartFrequencyEnum = restartFrequencyEnum.getValue();
|
||||
}
|
||||
|
||||
} else if (isLoanCharge()) {
|
||||
|
||||
if (penalty && (chargeTime.isTimeOfDisbursement() || chargeTime.isTrancheDisbursement())) {
|
||||
@@ -201,6 +239,7 @@ public class Charge extends AbstractPersistableCustom {
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.loan");
|
||||
}
|
||||
}
|
||||
|
||||
if (isPercentageOfApprovedAmount()) {
|
||||
this.minCap = minCap;
|
||||
this.maxCap = maxCap;
|
||||
@@ -291,6 +330,22 @@ public class Charge extends AbstractPersistableCustom {
|
||||
return this.maxCap;
|
||||
}
|
||||
|
||||
public boolean isEnableFreeWithdrawal() {
|
||||
return this.enableFreeWithdrawal;
|
||||
}
|
||||
|
||||
public Integer getFrequencyFreeWithdrawalCharge() {
|
||||
return this.freeWithdrawalFrequency;
|
||||
}
|
||||
|
||||
public Integer getRestartFrequency() {
|
||||
return this.restartFrequency;
|
||||
}
|
||||
|
||||
public Integer getRestartFrequencyEnum() {
|
||||
return this.restartFrequencyEnum;
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
|
||||
|
||||
@@ -355,6 +410,35 @@ public class Charge extends AbstractPersistableCustom {
|
||||
}
|
||||
}
|
||||
|
||||
final String freeWithdrawalFrequencyParamName = "freeWithdrawalFrequency";
|
||||
if (command.isChangeInIntegerParameterNamed(freeWithdrawalFrequencyParamName, this.freeWithdrawalFrequency)) {
|
||||
final Integer enableFreeWithdrawalChargeNewValue = command.integerValueOfParameterNamed(freeWithdrawalFrequencyParamName);
|
||||
actualChanges.put(freeWithdrawalFrequencyParamName, enableFreeWithdrawalChargeNewValue);
|
||||
this.freeWithdrawalFrequency = enableFreeWithdrawalChargeNewValue;
|
||||
}
|
||||
|
||||
final String restartCountFrequencyParamName = "restartCountFrequency";
|
||||
if (command.isChangeInIntegerParameterNamed(restartCountFrequencyParamName, this.restartFrequency)) {
|
||||
final Integer restartCountFrequencyNewValue = command.integerValueOfParameterNamed(restartCountFrequencyParamName);
|
||||
actualChanges.put(restartCountFrequencyParamName, restartCountFrequencyNewValue);
|
||||
this.restartFrequency = restartCountFrequencyNewValue;
|
||||
}
|
||||
|
||||
final String countFrequencyTypeParamName = "countFrequencyType";
|
||||
if (command.isChangeInIntegerParameterNamed(countFrequencyTypeParamName, this.restartFrequencyEnum)) {
|
||||
final Integer countFrequencyTypeNewValue = command.integerValueOfParameterNamed(countFrequencyTypeParamName);
|
||||
actualChanges.put(countFrequencyTypeParamName, countFrequencyTypeNewValue);
|
||||
this.restartFrequencyEnum = ChargeTimeType.fromInt(countFrequencyTypeNewValue).getValue();
|
||||
}
|
||||
|
||||
final String enableFreeWithdrawalChargeParamName = "enableFreeWithdrawalCharge";
|
||||
if (command.isChangeInBooleanParameterNamed(enableFreeWithdrawalChargeParamName, this.enableFreeWithdrawal)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(enableFreeWithdrawalChargeParamName);
|
||||
actualChanges.put(enableFreeWithdrawalChargeParamName, newValue);
|
||||
this.enableFreeWithdrawal = newValue;
|
||||
|
||||
}
|
||||
|
||||
final String chargeAppliesToParamName = "chargeAppliesTo";
|
||||
if (command.isChangeInIntegerParameterNamed(chargeAppliesToParamName, this.chargeAppliesTo)) {
|
||||
/*
|
||||
@@ -531,8 +615,9 @@ public class Charge extends AbstractPersistableCustom {
|
||||
|
||||
final CurrencyData currency = new CurrencyData(this.currencyCode, null, 0, 0, null, null);
|
||||
return ChargeData.instance(getId(), this.name, this.amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType,
|
||||
chargePaymentmode, getFeeOnMonthDay(), this.feeInterval, this.penalty, this.active, this.minCap, this.maxCap,
|
||||
feeFrequencyType, accountData, taxGroupData);
|
||||
chargePaymentmode, getFeeOnMonthDay(), this.feeInterval, this.penalty, this.active, this.enableFreeWithdrawal,
|
||||
this.freeWithdrawalFrequency, this.restartFrequency, this.restartFrequencyEnum, this.minCap, this.maxCap, feeFrequencyType,
|
||||
accountData, taxGroupData);
|
||||
}
|
||||
|
||||
public Integer getChargePaymentMode() {
|
||||
|
||||
+57
@@ -54,6 +54,7 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
||||
private final Set<String> supportedParameters = new HashSet<>(Arrays.asList("name", "amount", "locale", "currencyCode",
|
||||
"currencyOptions", "chargeAppliesTo", "chargeTimeType", "chargeCalculationType", "chargeCalculationTypeOptions", "penalty",
|
||||
"active", "chargePaymentMode", "feeOnMonthDay", "feeInterval", "monthDayFormat", "minCap", "maxCap", "feeFrequency",
|
||||
"enableFreeWithdrawalCharge", "freeWithdrawalFrequency", "restartCountFrequency", "countFrequencyType",
|
||||
ChargesApiConstants.glAccountIdParamName, ChargesApiConstants.taxGroupIdParamName));
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
@@ -91,6 +92,28 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
||||
final Integer feeFrequency = this.fromApiJsonHelper.extractIntegerNamed("feeFrequency", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("feeFrequency").value(feeFrequency).inMinMaxRange(0, 3);
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists("enableFreeWithdrawalCharge", element)) {
|
||||
|
||||
final Boolean enableFreeWithdrawalCharge = this.fromApiJsonHelper.extractBooleanNamed("enableFreeWithdrawalCharge", element);
|
||||
baseDataValidator.reset().parameter("enableFreeWithdrawalCharge").value(enableFreeWithdrawalCharge).notNull();
|
||||
|
||||
if (enableFreeWithdrawalCharge) {
|
||||
|
||||
final Integer freeWithdrawalFrequency = this.fromApiJsonHelper.extractIntegerNamed("freeWithdrawalFrequency", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("freeWithdrawalFrequency").value(freeWithdrawalFrequency).integerGreaterThanZero();
|
||||
|
||||
final Integer restartCountFrequency = this.fromApiJsonHelper.extractIntegerNamed("restartCountFrequency", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("restartCountFrequency").value(restartCountFrequency).integerGreaterThanZero();
|
||||
|
||||
final Integer countFrequencyType = this.fromApiJsonHelper.extractIntegerNamed("countFrequencyType", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("countFrequencyType").value(countFrequencyType);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (feeFrequency != null) {
|
||||
baseDataValidator.reset().parameter("feeInterval").value(feeInterval).notNull();
|
||||
}
|
||||
@@ -155,6 +178,7 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType)
|
||||
.isOneOfTheseValues(ChargeCalculationType.validValuesForSavings());
|
||||
}
|
||||
|
||||
} else if (appliesTo.isClientCharge()) {
|
||||
// client applicable validation
|
||||
final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeTimeType", element);
|
||||
@@ -277,6 +301,39 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
||||
.isOneOfTheseValues(ChargeAppliesTo.validValues());
|
||||
}
|
||||
|
||||
Boolean enableFreeWithdrawalCharge = false;
|
||||
if (this.fromApiJsonHelper.parameterExists("enableFreeWithdrawalCharge", element)) {
|
||||
enableFreeWithdrawalCharge = this.fromApiJsonHelper.extractBooleanNamed("enableFreeWithdrawalCharge", element);
|
||||
baseDataValidator.reset().parameter("enableFreeWithdrawalCharge").value(enableFreeWithdrawalCharge).notNull();
|
||||
|
||||
if (enableFreeWithdrawalCharge) {
|
||||
|
||||
final Integer freeWithdrawalFrequency = this.fromApiJsonHelper.extractIntegerNamed("freeWithdrawalFrequency", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("freeWithdrawalFrequency").value(freeWithdrawalFrequency).integerGreaterThanZero();
|
||||
|
||||
final Integer restartCountFrequency = this.fromApiJsonHelper.extractIntegerNamed("restartCountFrequency", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("restartCountFrequency").value(restartCountFrequency).integerGreaterThanZero();
|
||||
|
||||
final Integer countFrequencyType = this.fromApiJsonHelper.extractIntegerNamed("countFrequencyType", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("countFrequencyType").value(countFrequencyType);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists("chargeAppliesTo", element)) {
|
||||
final Integer chargeAppliesTo = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeAppliesTo", element);
|
||||
baseDataValidator.reset().parameter("chargeAppliesTo").value(chargeAppliesTo).notNull()
|
||||
.isOneOfTheseValues(ChargeAppliesTo.validValues());
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists("chargeAppliesTo", element)) {
|
||||
final Integer chargeAppliesTo = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeAppliesTo", element);
|
||||
baseDataValidator.reset().parameter("chargeAppliesTo").value(chargeAppliesTo).notNull()
|
||||
.isOneOfTheseValues(ChargeAppliesTo.validValues());
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists("chargeTimeType", element)) {
|
||||
|
||||
final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeTimeType", element);
|
||||
|
||||
+9
-3
@@ -287,7 +287,8 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
|
||||
+ "c.charge_applies_to_enum as chargeAppliesTo, c.charge_time_enum as chargeTime, "
|
||||
+ "c.charge_payment_mode_enum as chargePaymentMode, "
|
||||
+ "c.charge_calculation_enum as chargeCalculation, c.is_penalty as penalty, "
|
||||
+ "c.is_active as active, oc.name as currencyName, oc.decimal_places as currencyDecimalPlaces, "
|
||||
+ "c.is_active as active, c.is_free_withdrawal as isFreeWithdrawal, c.free_withdrawal_charge_frequency as freeWithdrawalChargeFrequency, c.restart_frequency as restartFrequency, c.restart_frequency_enum as restartFrequencyEnum,"
|
||||
+ "oc.name as currencyName, oc.decimal_places as currencyDecimalPlaces, "
|
||||
+ "oc.currency_multiplesof as inMultiplesOf, oc.display_symbol as currencyDisplaySymbol, "
|
||||
+ "oc.internationalized_name_code as currencyNameCode, c.fee_on_day as feeOnDay, c.fee_on_month as feeOnMonth, "
|
||||
+ "c.fee_interval as feeInterval, c.fee_frequency as feeFrequency,c.min_cap as minCap,c.max_cap as maxCap, "
|
||||
@@ -372,9 +373,14 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
|
||||
taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName);
|
||||
}
|
||||
|
||||
final boolean isFreeWithdrawal = rs.getBoolean("isFreeWithdrawal");
|
||||
final int freeWithdrawalChargeFrequency = rs.getInt("freeWithdrawalChargeFrequency");
|
||||
final int restartFrequency = rs.getInt("restartFrequency");
|
||||
final int restartFrequencyEnum = rs.getInt("restartFrequencyEnum");
|
||||
|
||||
return ChargeData.instance(id, name, amount, currency, chargeTimeType, chargeAppliesToType, chargeCalculationType,
|
||||
chargePaymentMode, feeOnMonthDay, feeInterval, penalty, active, minCap, maxCap, feeFrequencyType, glAccountData,
|
||||
taxGroupData);
|
||||
chargePaymentMode, feeOnMonthDay, feeInterval, penalty, active, isFreeWithdrawal, freeWithdrawalChargeFrequency,
|
||||
restartFrequency, restartFrequencyEnum, minCap, maxCap, feeFrequencyType, glAccountData, taxGroupData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -42,6 +42,7 @@ import org.apache.fineract.portfolio.charge.exception.ChargeNotFoundException;
|
||||
import org.apache.fineract.portfolio.charge.serialization.ChargeDefinitionCommandFromApiJsonDeserializer;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
|
||||
import org.apache.fineract.portfolio.paymenttype.domain.PaymentTypeRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.tax.domain.TaxGroup;
|
||||
import org.apache.fineract.portfolio.tax.domain.TaxGroupRepositoryWrapper;
|
||||
import org.slf4j.Logger;
|
||||
@@ -67,13 +68,14 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl implements ChargeWriteP
|
||||
private final FineractEntityAccessUtil fineractEntityAccessUtil;
|
||||
private final GLAccountRepositoryWrapper glAccountRepository;
|
||||
private final TaxGroupRepositoryWrapper taxGroupRepository;
|
||||
private final PaymentTypeRepositoryWrapper paymentTyperepositoryWrapper;
|
||||
|
||||
@Autowired
|
||||
public ChargeWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
final ChargeDefinitionCommandFromApiJsonDeserializer fromApiJsonDeserializer, final ChargeRepository chargeRepository,
|
||||
final LoanProductRepository loanProductRepository, final RoutingDataSource dataSource,
|
||||
final FineractEntityAccessUtil fineractEntityAccessUtil, final GLAccountRepositoryWrapper glAccountRepository,
|
||||
final TaxGroupRepositoryWrapper taxGroupRepository) {
|
||||
final TaxGroupRepositoryWrapper taxGroupRepository, final PaymentTypeRepositoryWrapper paymentTyperepositoryWrapper) {
|
||||
this.context = context;
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
this.dataSource = dataSource;
|
||||
@@ -83,6 +85,7 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl implements ChargeWriteP
|
||||
this.fineractEntityAccessUtil = fineractEntityAccessUtil;
|
||||
this.glAccountRepository = glAccountRepository;
|
||||
this.taxGroupRepository = taxGroupRepository;
|
||||
this.paymentTyperepositoryWrapper = paymentTyperepositoryWrapper;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
+31
-4
@@ -74,6 +74,14 @@ public class SavingsAccountChargeData implements Serializable {
|
||||
|
||||
private final Boolean isActive;
|
||||
|
||||
private final Boolean isFreeWithdrawal;
|
||||
|
||||
private final Integer freeWithdrawalChargeFrequency;
|
||||
|
||||
private final Integer restartFrequency;
|
||||
|
||||
private final Integer restartFrequencyEnum;
|
||||
|
||||
private final LocalDate inactivationDate;
|
||||
|
||||
private final Collection<ChargeData> chargeOptions;
|
||||
@@ -101,6 +109,10 @@ public class SavingsAccountChargeData implements Serializable {
|
||||
this.isActive = null;
|
||||
this.inactivationDate = null;
|
||||
this.chargeOptions = null;
|
||||
this.isFreeWithdrawal = null;
|
||||
this.freeWithdrawalChargeFrequency = null;
|
||||
this.restartFrequency = null;
|
||||
this.restartFrequencyEnum = null;
|
||||
}
|
||||
|
||||
public static SavingsAccountChargeData template(final Collection<ChargeData> chargeOptions) {
|
||||
@@ -123,11 +135,17 @@ public class SavingsAccountChargeData implements Serializable {
|
||||
final MonthDay feeOnMonthDay = null;
|
||||
final Integer feeInterval = null;
|
||||
final Boolean isActive = null;
|
||||
final Boolean isFreeWithdrawal = null;
|
||||
final Integer freeWithdrawalChargeFrequency = null;
|
||||
final Integer restartFrequency = null;
|
||||
final Integer restartFrequencyEnum = null;
|
||||
|
||||
final LocalDate inactivationDate = null;
|
||||
|
||||
return new SavingsAccountChargeData(id, chargeId, accountId, name, chargeTimeType, dueAsOfDate, chargeCalculationType, percentage,
|
||||
amountPercentageAppliedTo, currency, amount, amountPaid, amountWaived, amountWrittenOff, amountOutstanding, chargeOptions,
|
||||
penalty, feeOnMonthDay, feeInterval, isActive, inactivationDate);
|
||||
penalty, feeOnMonthDay, feeInterval, isActive, isFreeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency,
|
||||
restartFrequencyEnum, inactivationDate);
|
||||
}
|
||||
|
||||
public static SavingsAccountChargeData instance(final Long id, final Long chargeId, final Long accountId, final String name,
|
||||
@@ -135,11 +153,14 @@ public class SavingsAccountChargeData implements Serializable {
|
||||
final BigDecimal amountWrittenOff, final BigDecimal amountOutstanding, final EnumOptionData chargeTimeType,
|
||||
final LocalDate dueAsOfDate, final EnumOptionData chargeCalculationType, final BigDecimal percentage,
|
||||
final BigDecimal amountPercentageAppliedTo, final Collection<ChargeData> chargeOptions, final boolean penalty,
|
||||
final MonthDay feeOnMonthDay, final Integer feeInterval, final Boolean isActive, final LocalDate inactivationDate) {
|
||||
final MonthDay feeOnMonthDay, final Integer feeInterval, final Boolean isActive, final Boolean isFreeWithdrawal,
|
||||
final Integer freeWithdrawalChargeFrequency, final Integer restartFrequency, final Integer restartFrequencyEnum,
|
||||
final LocalDate inactivationDate) {
|
||||
|
||||
return new SavingsAccountChargeData(id, chargeId, accountId, name, chargeTimeType, dueAsOfDate, chargeCalculationType, percentage,
|
||||
amountPercentageAppliedTo, currency, amount, amountPaid, amountWaived, amountWrittenOff, amountOutstanding, chargeOptions,
|
||||
penalty, feeOnMonthDay, feeInterval, isActive, inactivationDate);
|
||||
penalty, feeOnMonthDay, feeInterval, isActive, isFreeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency,
|
||||
restartFrequencyEnum, inactivationDate);
|
||||
}
|
||||
|
||||
private SavingsAccountChargeData(final Long id, final Long chargeId, final Long accountId, final String name,
|
||||
@@ -147,7 +168,9 @@ public class SavingsAccountChargeData implements Serializable {
|
||||
final BigDecimal percentage, final BigDecimal amountPercentageAppliedTo, final CurrencyData currency, final BigDecimal amount,
|
||||
final BigDecimal amountPaid, final BigDecimal amountWaived, final BigDecimal amountWrittenOff,
|
||||
final BigDecimal amountOutstanding, final Collection<ChargeData> chargeOptions, final boolean penalty,
|
||||
final MonthDay feeOnMonthDay, final Integer feeInterval, final Boolean isActive, final LocalDate inactivationDate) {
|
||||
final MonthDay feeOnMonthDay, final Integer feeInterval, final Boolean isActive, final Boolean isFreeWithdrawal,
|
||||
final Integer freeWithdrawalChargeFrequency, final Integer restartFrequency, final Integer restartFrequencyEnum,
|
||||
final LocalDate inactivationDate) {
|
||||
this.id = id;
|
||||
this.chargeId = chargeId;
|
||||
this.accountId = accountId;
|
||||
@@ -170,6 +193,10 @@ public class SavingsAccountChargeData implements Serializable {
|
||||
this.feeInterval = feeInterval;
|
||||
this.isActive = isActive;
|
||||
this.inactivationDate = inactivationDate;
|
||||
this.isFreeWithdrawal = isFreeWithdrawal;
|
||||
this.freeWithdrawalChargeFrequency = freeWithdrawalChargeFrequency;
|
||||
this.restartFrequency = restartFrequency;
|
||||
this.restartFrequencyEnum = restartFrequencyEnum;
|
||||
}
|
||||
|
||||
private BigDecimal getAmountOrPercentage() {
|
||||
|
||||
+92
-4
@@ -36,6 +36,7 @@ import com.google.gson.JsonArray;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.time.LocalDate;
|
||||
import java.time.YearMonth;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
@@ -50,6 +51,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
@@ -92,6 +94,7 @@ import org.apache.fineract.portfolio.charge.exception.SavingsAccountChargeNotFou
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.group.domain.Group;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsAccountTransactionType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
|
||||
@@ -1038,7 +1041,8 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
|
||||
if (applyWithdrawFee) {
|
||||
// auto pay withdrawal fee
|
||||
payWithdrawalFee(transactionDTO.getTransactionAmount(), transactionDTO.getTransactionDate(), transactionDTO.getAppUser());
|
||||
payWithdrawalFee(transactionDTO.getTransactionAmount(), transactionDTO.getTransactionDate(), transactionDTO.getAppUser(),
|
||||
transactionDTO.getPaymentDetail());
|
||||
}
|
||||
|
||||
final Money transactionAmountMoney = Money.of(this.currency, transactionDTO.getTransactionAmount());
|
||||
@@ -1066,15 +1070,99 @@ public class SavingsAccount extends AbstractPersistableCustom {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void payWithdrawalFee(final BigDecimal transactionAmount, final LocalDate transactionDate, final AppUser user) {
|
||||
private void payWithdrawalFee(final BigDecimal transactionAmount, final LocalDate transactionDate, final AppUser user,
|
||||
final PaymentDetail paymentDetail) {
|
||||
|
||||
for (SavingsAccountCharge charge : this.charges()) {
|
||||
|
||||
if (charge.isWithdrawalFee() && charge.isActive()) {
|
||||
charge.updateWithdralFeeAmount(transactionAmount);
|
||||
this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, user);
|
||||
if (charge.getFreeWithdrawalCount() == null) {
|
||||
charge.setFreeWithdrawalCount(0);
|
||||
}
|
||||
|
||||
if (charge.isEnableFreeWithdrawal()) {
|
||||
resetFreeChargeDaysCount(charge, transactionAmount, transactionDate, user);
|
||||
|
||||
} else {
|
||||
charge.updateWithdralFeeAmount(transactionAmount);
|
||||
this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, user);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void resetFreeChargeDaysCount(SavingsAccountCharge charge, final BigDecimal transactionAmount, final LocalDate transactionDate,
|
||||
final AppUser user) {
|
||||
Date resetDate = charge.getResetChargeDate();
|
||||
|
||||
Integer restartPeriod = charge.getRestartFrequency();
|
||||
if (charge.getRestartFrequencyEnum() == 2) { // calculation for months
|
||||
Date currentDate = new Date();
|
||||
LocalDate localDate = currentDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
Integer currentMonth = localDate.getMonthValue();
|
||||
|
||||
LocalDate resetLocalDate = null;
|
||||
if (resetDate == null) {
|
||||
resetLocalDate = this.activatedOnDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
} else {
|
||||
resetLocalDate = resetDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
}
|
||||
Integer resetMonth = resetLocalDate.getMonthValue();
|
||||
|
||||
LocalDate gapIntervalMonth = resetLocalDate.plusMonths(restartPeriod);
|
||||
Integer gapMonth = gapIntervalMonth.getMonthValue();
|
||||
|
||||
Integer resetYear = resetLocalDate.getYear();
|
||||
Integer currentYear = localDate.getYear();
|
||||
|
||||
YearMonth gapYearMonth = YearMonth.from(gapIntervalMonth);
|
||||
YearMonth localYearMonth = YearMonth.from(localDate);
|
||||
if (localYearMonth.isBefore(gapYearMonth)) {
|
||||
countValidation(charge, transactionAmount, transactionDate, user);
|
||||
} else {
|
||||
discountCharge(1, charge);
|
||||
}
|
||||
} else { // calculation for days
|
||||
Long completedDays = null;
|
||||
Long days = null;
|
||||
|
||||
if (resetDate == null) {
|
||||
completedDays = DateUtils.getDateOfTenant().getTime() - this.activatedOnDate.getTime();
|
||||
days = TimeUnit.DAYS.convert(completedDays, TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
completedDays = DateUtils.getDateOfTenant().getTime() - resetDate.getTime();
|
||||
days = TimeUnit.DAYS.convert(completedDays, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
Integer totalDays = days.intValue();
|
||||
|
||||
if (totalDays < restartPeriod) {
|
||||
countValidation(charge, transactionAmount, transactionDate, user);
|
||||
} else {
|
||||
discountCharge(1, charge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void countValidation(SavingsAccountCharge charge, final BigDecimal transactionAmount, final LocalDate transactionDate,
|
||||
final AppUser user) {
|
||||
if (charge.getFreeWithdrawalCount() < charge.getFrequencyFreeWithdrawalCharge()) {
|
||||
final Integer count = charge.getFreeWithdrawalCount() + 1;
|
||||
charge.setFreeWithdrawalCount(count);
|
||||
charge.updateNoWithdrawalFee();
|
||||
} else {
|
||||
charge.updateWithdralFeeAmount(transactionAmount);
|
||||
this.payCharge(charge, charge.getAmountOutstanding(this.getCurrency()), transactionDate, user);
|
||||
}
|
||||
}
|
||||
|
||||
private void discountCharge(Integer freeWithdrawalCount, SavingsAccountCharge charge) {
|
||||
charge.setFreeWithdrawalCount(freeWithdrawalCount);
|
||||
charge.setDiscountDueDate(DateUtils.getDateOfTenant());
|
||||
charge.updateNoWithdrawalFee();
|
||||
}
|
||||
|
||||
public boolean isBeforeLastPostingPeriod(final LocalDate transactionDate) {
|
||||
|
||||
boolean transactionBeforeLastInterestPosting = false;
|
||||
|
||||
+43
@@ -94,6 +94,13 @@ public class SavingsAccountCharge extends AbstractPersistableCustom {
|
||||
@Column(name = "charge_calculation_enum")
|
||||
private Integer chargeCalculation;
|
||||
|
||||
@Column(name = "free_withdrawal_count", nullable = true)
|
||||
private Integer freeWithdrawalCount;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "charge_reset_date", nullable = true)
|
||||
private Date chargeResetDate;
|
||||
|
||||
@Column(name = "calculation_percentage", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal percentage;
|
||||
|
||||
@@ -666,6 +673,38 @@ public class SavingsAccountCharge extends AbstractPersistableCustom {
|
||||
return this.charge;
|
||||
}
|
||||
|
||||
public boolean isEnableFreeWithdrawal() {
|
||||
return charge.isEnableFreeWithdrawal();
|
||||
}
|
||||
|
||||
public Integer getFrequencyFreeWithdrawalCharge() { // number of times free withdrawal allowed
|
||||
return charge.getFrequencyFreeWithdrawalCharge();
|
||||
}
|
||||
|
||||
public Integer getRestartFrequency() { // numeric value of which numeric-period, count should restart
|
||||
return charge.getRestartFrequency();
|
||||
}
|
||||
|
||||
public Integer getRestartFrequencyEnum() { // enum day/week/month for restarting the count.
|
||||
return charge.getRestartFrequencyEnum();
|
||||
}
|
||||
|
||||
public Integer getFreeWithdrawalCount() {
|
||||
return freeWithdrawalCount;
|
||||
}
|
||||
|
||||
public void setFreeWithdrawalCount(Integer freeWithdrawalCount) {
|
||||
this.freeWithdrawalCount = freeWithdrawalCount;
|
||||
}
|
||||
|
||||
public Date getResetChargeDate() {
|
||||
return chargeResetDate;
|
||||
}
|
||||
|
||||
public void setDiscountDueDate(final Date date) {
|
||||
this.chargeResetDate = date;
|
||||
}
|
||||
|
||||
public SavingsAccount savingsAccount() {
|
||||
return this.savingsAccount;
|
||||
}
|
||||
@@ -758,6 +797,10 @@ public class SavingsAccountCharge extends AbstractPersistableCustom {
|
||||
return amountOutstanding = calculateWithdralFeeAmount(transactionAmount);
|
||||
}
|
||||
|
||||
public BigDecimal updateNoWithdrawalFee() {
|
||||
return amountOutstanding = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
public void updateToNextDueDateFrom(final LocalDate startingDate) {
|
||||
if (isAnnualFee() || isMonthlyFee() || isWeeklyFee()) {
|
||||
this.dueDate = Date.from(getNextDueDateFrom(startingDate).atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
|
||||
+8
-1
@@ -82,6 +82,7 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou
|
||||
+ "sc.fee_on_month as feeOnMonth, " + "sc.fee_on_day as feeOnDay, sc.fee_interval as feeInterval, "
|
||||
+ "sc.charge_calculation_enum as chargeCalculation, "
|
||||
+ "sc.is_active as isActive, sc.inactivated_on_date as inactivationDate, "
|
||||
+ "c.is_free_withdrawal as isFreeWithdrawal, c.free_withdrawal_charge_frequency as freeWithdrawalChargeFrequency, c.restart_frequency as restartFrequency, c.restart_frequency_enum as restartFrequencyEnum, "
|
||||
+ "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.internationalized_name_code as currencyNameCode from m_charge c "
|
||||
@@ -133,11 +134,17 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou
|
||||
final Boolean isActive = rs.getBoolean("isActive");
|
||||
final LocalDate inactivationDate = JdbcSupport.getLocalDate(rs, "inactivationDate");
|
||||
|
||||
final Boolean isFreeWithdrawal = rs.getBoolean("isFreeWithdrawal");
|
||||
final Integer freeWithdrawalChargeFrequency = JdbcSupport.getInteger(rs, "freeWithdrawalChargeFrequency");
|
||||
final Integer restartFrequency = JdbcSupport.getInteger(rs, "restartFrequency");
|
||||
final Integer restartFrequencyEnum = JdbcSupport.getInteger(rs, "restartFrequencyEnum");
|
||||
|
||||
final Collection<ChargeData> chargeOptions = null;
|
||||
|
||||
return SavingsAccountChargeData.instance(id, chargeId, accountId, name, currency, amount, amountPaid, amountWaived,
|
||||
amountWrittenOff, amountOutstanding, chargeTimeType, dueAsOfDate, chargeCalculationType, percentageOf,
|
||||
amountPercentageAppliedTo, chargeOptions, penalty, feeOnMonthDay, feeInterval, isActive, inactivationDate);
|
||||
amountPercentageAppliedTo, chargeOptions, penalty, feeOnMonthDay, feeInterval, isActive, isFreeWithdrawal,
|
||||
freeWithdrawalChargeFrequency, restartFrequency, restartFrequencyEnum, inactivationDate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -1025,6 +1025,10 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
}
|
||||
final SavingsAccountCharge savingsAccountCharge = SavingsAccountCharge.createNewFromJson(savingsAccount, chargeDefinition, command);
|
||||
|
||||
if (chargeDefinition.isEnableFreeWithdrawal()) {
|
||||
savingsAccountCharge.setFreeWithdrawalCount(0);
|
||||
}
|
||||
|
||||
if (savingsAccountCharge.getDueLocalDate() != null) {
|
||||
// transaction date should not be on a holiday or non working day
|
||||
if (!this.configurationDomainService.allowTransactionsOnHolidayEnabled()
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
--
|
||||
-- Licensed to the Apache Software Foundation (ASF) under one
|
||||
-- or more contributor license agreements. See the NOTICE file
|
||||
-- distributed with this work for additional information
|
||||
-- regarding copyright ownership. The ASF licenses this file
|
||||
-- to you under the Apache License, Version 2.0 (the
|
||||
-- "License"); you may not use this file except in compliance
|
||||
-- with the License. You may obtain a copy of the License at
|
||||
--
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
--
|
||||
-- Unless required by applicable law or agreed to in writing,
|
||||
-- software distributed under the License is distributed on an
|
||||
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
-- KIND, either express or implied. See the License for the
|
||||
-- specific language governing permissions and limitations
|
||||
-- under the License.
|
||||
--
|
||||
|
||||
|
||||
ALTER TABLE `m_charge` ADD COLUMN `is_free_withdrawal` INT NOT NULL DEFAULT '0' AFTER `fee_frequency`;
|
||||
|
||||
|
||||
ALTER TABLE `m_charge`
|
||||
ADD COLUMN `free_withdrawal_charge_frequency` INT NULL DEFAULT '0' AFTER `is_free_withdrawal`;
|
||||
|
||||
|
||||
ALTER TABLE `m_charge`
|
||||
ADD COLUMN `restart_frequency` INT NULL DEFAULT '0' AFTER `free_withdrawal_charge_frequency`;
|
||||
|
||||
|
||||
ALTER TABLE `m_charge`
|
||||
ADD COLUMN `restart_frequency_enum` INT NULL DEFAULT '0' AFTER `restart_frequency`;
|
||||
|
||||
|
||||
ALTER TABLE `m_savings_account_charge`
|
||||
ADD COLUMN `free_withdrawal_count` INT NULL DEFAULT '0' AFTER `fee_interval`;
|
||||
|
||||
ALTER TABLE `m_savings_account_charge`
|
||||
ADD COLUMN `charge_reset_date` DATE NULL DEFAULT NULL AFTER `free_withdrawal_count`;
|
||||
Reference in New Issue
Block a user