client fees : adding client transaction api's

This commit is contained in:
Vishwas Babu A J
2015-08-20 01:45:20 +05:30
parent b6626b0b83
commit 340aa20120
22 changed files with 357 additions and 146 deletions
@@ -49,6 +49,8 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
private final List<EnumOptionData> loanChargeTimeTypeOptions; private final List<EnumOptionData> loanChargeTimeTypeOptions;
private final List<EnumOptionData> savingsChargeCalculationTypeOptions; private final List<EnumOptionData> savingsChargeCalculationTypeOptions;
private final List<EnumOptionData> savingsChargeTimeTypeOptions; private final List<EnumOptionData> savingsChargeTimeTypeOptions;
private final List<EnumOptionData> clientChargeCalculationTypeOptions;
private final List<EnumOptionData> clientChargeTimeTypeOptions;
private final List<EnumOptionData> feeFrequencyOptions; private final List<EnumOptionData> feeFrequencyOptions;
public static ChargeData template(final Collection<CurrencyData> currencyOptions, public static ChargeData template(final Collection<CurrencyData> currencyOptions,
@@ -56,12 +58,13 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
final List<EnumOptionData> chargeTimeTypeOptions, final List<EnumOptionData> chargePaymentModeOptions, final List<EnumOptionData> chargeTimeTypeOptions, final List<EnumOptionData> chargePaymentModeOptions,
final List<EnumOptionData> loansChargeCalculationTypeOptions, final List<EnumOptionData> loansChargeTimeTypeOptions, final List<EnumOptionData> loansChargeCalculationTypeOptions, final List<EnumOptionData> loansChargeTimeTypeOptions,
final List<EnumOptionData> savingsChargeCalculationTypeOptions, final List<EnumOptionData> savingsChargeTimeTypeOptions, final List<EnumOptionData> savingsChargeCalculationTypeOptions, final List<EnumOptionData> savingsChargeTimeTypeOptions,
final List<EnumOptionData> clientChargeCalculationTypeOptions, final List<EnumOptionData> clientChargeTimeTypeOptions,
final List<EnumOptionData> feeFrequencyOptions) { final List<EnumOptionData> feeFrequencyOptions) {
return new ChargeData(null, null, null, null, null, null, null, null, false, false, currencyOptions, chargeCalculationTypeOptions, return new ChargeData(null, null, null, null, null, null, null, null, false, false, currencyOptions, chargeCalculationTypeOptions,
chargeAppliesToOptions, chargeTimeTypeOptions, chargePaymentModeOptions, loansChargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, chargePaymentModeOptions, loansChargeCalculationTypeOptions,
loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, null, null, null, null, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions,
null, feeFrequencyOptions); clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, null, null, null, null, null, feeFrequencyOptions);
} }
public static ChargeData withTemplate(final ChargeData charge, final ChargeData template) { public static ChargeData withTemplate(final ChargeData charge, final ChargeData template) {
@@ -69,8 +72,9 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
charge.chargeCalculationType, charge.chargePaymentMode, charge.penalty, charge.active, template.currencyOptions, charge.chargeCalculationType, charge.chargePaymentMode, charge.penalty, charge.active, template.currencyOptions,
template.chargeCalculationTypeOptions, template.chargeAppliesToOptions, template.chargeTimeTypeOptions, template.chargeCalculationTypeOptions, template.chargeAppliesToOptions, template.chargeTimeTypeOptions,
template.chargePaymetModeOptions, template.loanChargeCalculationTypeOptions, template.loanChargeTimeTypeOptions, template.chargePaymetModeOptions, template.loanChargeCalculationTypeOptions, template.loanChargeTimeTypeOptions,
template.savingsChargeCalculationTypeOptions, template.savingsChargeTimeTypeOptions, charge.feeOnMonthDay, template.savingsChargeCalculationTypeOptions, template.savingsChargeTimeTypeOptions,
charge.feeInterval, charge.minCap, charge.maxCap, charge.feeFrequency, template.feeFrequencyOptions); template.clientChargeCalculationTypeOptions, template.clientChargeTimeTypeOptions, charge.feeOnMonthDay, charge.feeInterval,
charge.minCap, charge.maxCap, charge.feeFrequency, template.feeFrequencyOptions);
} }
public static ChargeData instance(final Long id, final String name, final BigDecimal amount, final CurrencyData currency, public static ChargeData instance(final Long id, final String name, final BigDecimal amount, final CurrencyData currency,
@@ -88,12 +92,14 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
final List<EnumOptionData> savingsChargeCalculationTypeOptions = null; final List<EnumOptionData> savingsChargeCalculationTypeOptions = null;
final List<EnumOptionData> savingsChargeTimeTypeOptions = null; final List<EnumOptionData> savingsChargeTimeTypeOptions = null;
final List<EnumOptionData> feeFrequencyOptions = null; final List<EnumOptionData> feeFrequencyOptions = null;
final List<EnumOptionData> clientChargeCalculationTypeOptions = null;
final List<EnumOptionData> clientChargeTimeTypeOptions = null;
return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode, return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode,
penalty, active, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, penalty, active, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions,
chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
feeFrequency, feeFrequencyOptions); clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions);
} }
public static ChargeData lookup(final Long id, final String name, final boolean isPenalty) { public static ChargeData lookup(final Long id, final String name, final boolean isPenalty) {
@@ -118,14 +124,16 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
final List<EnumOptionData> loansChargeTimeTypeOptions = null; final List<EnumOptionData> loansChargeTimeTypeOptions = null;
final List<EnumOptionData> savingsChargeCalculationTypeOptions = null; final List<EnumOptionData> savingsChargeCalculationTypeOptions = null;
final List<EnumOptionData> savingsChargeTimeTypeOptions = null; final List<EnumOptionData> savingsChargeTimeTypeOptions = null;
final List<EnumOptionData> clientChargeCalculationTypeOptions = null;
final List<EnumOptionData> clientChargeTimeTypeOptions = null;
final EnumOptionData feeFrequency = null; final EnumOptionData feeFrequency = null;
final List<EnumOptionData> feeFrequencyOptions = null; final List<EnumOptionData> feeFrequencyOptions = null;
return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode, return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode,
penalty, active, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, penalty, active, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions,
chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
feeFrequency, feeFrequencyOptions); clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions);
} }
private ChargeData(final Long id, final String name, final BigDecimal amount, final CurrencyData currency, private ChargeData(final Long id, final String name, final BigDecimal amount, final CurrencyData currency,
@@ -135,7 +143,8 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
final List<EnumOptionData> chargeAppliesToOptions, final List<EnumOptionData> chargeTimeTypeOptions, final List<EnumOptionData> chargeAppliesToOptions, final List<EnumOptionData> chargeTimeTypeOptions,
final List<EnumOptionData> chargePaymentModeOptions, final List<EnumOptionData> loansChargeCalculationTypeOptions, final List<EnumOptionData> chargePaymentModeOptions, final List<EnumOptionData> loansChargeCalculationTypeOptions,
final List<EnumOptionData> loansChargeTimeTypeOptions, final List<EnumOptionData> savingsChargeCalculationTypeOptions, final List<EnumOptionData> loansChargeTimeTypeOptions, final List<EnumOptionData> savingsChargeCalculationTypeOptions,
final List<EnumOptionData> savingsChargeTimeTypeOptions, final MonthDay feeOnMonthDay, final Integer feeInterval, 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 BigDecimal minCap, final BigDecimal maxCap, final EnumOptionData feeFrequency,
final List<EnumOptionData> feeFrequencyOptions) { final List<EnumOptionData> feeFrequencyOptions) {
this.id = id; this.id = id;
@@ -159,6 +168,8 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
this.chargePaymetModeOptions = chargePaymentModeOptions; this.chargePaymetModeOptions = chargePaymentModeOptions;
this.savingsChargeCalculationTypeOptions = savingsChargeCalculationTypeOptions; this.savingsChargeCalculationTypeOptions = savingsChargeCalculationTypeOptions;
this.savingsChargeTimeTypeOptions = savingsChargeTimeTypeOptions; this.savingsChargeTimeTypeOptions = savingsChargeTimeTypeOptions;
this.clientChargeCalculationTypeOptions = clientChargeCalculationTypeOptions;
this.clientChargeTimeTypeOptions = clientChargeTimeTypeOptions;
this.loanChargeCalculationTypeOptions = loansChargeCalculationTypeOptions; this.loanChargeCalculationTypeOptions = loansChargeCalculationTypeOptions;
this.loanChargeTimeTypeOptions = loansChargeTimeTypeOptions; this.loanChargeTimeTypeOptions = loansChargeTimeTypeOptions;
this.feeFrequency = feeFrequency; this.feeFrequency = feeFrequency;
@@ -210,18 +221,18 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
final LocalDate inactivationDate = null; final LocalDate inactivationDate = null;
return SavingsAccountChargeData.instance(savingsChargeId, this.id, savingsAccountId, this.name, this.currency, this.amount, return SavingsAccountChargeData.instance(savingsChargeId, this.id, savingsAccountId, this.name, this.currency, this.amount,
amountPaid, amountWaived, amountWrittenOff, amountOutstanding, this.chargeTimeType, dueAsOfDate, amountPaid, amountWaived, amountWrittenOff, amountOutstanding, this.chargeTimeType, dueAsOfDate, this.chargeCalculationType,
this.chargeCalculationType, percentage, amountPercentageAppliedTo, chargeOptions, this.penalty, this.feeOnMonthDay, percentage, amountPercentageAppliedTo, chargeOptions, this.penalty, this.feeOnMonthDay, this.feeInterval, isActive,
this.feeInterval, isActive, inactivationDate); inactivationDate);
} }
public boolean isPenalty() { public boolean isPenalty() {
return this.penalty; return this.penalty;
} }
public boolean isOverdueInstallmentCharge(){ public boolean isOverdueInstallmentCharge() {
boolean isOverdueInstallmentCharge = false; boolean isOverdueInstallmentCharge = false;
if(this.chargeTimeType != null){ if (this.chargeTimeType != null) {
isOverdueInstallmentCharge = ChargeTimeType.fromInt(this.chargeTimeType.getId().intValue()).isOverdueInstallment(); isOverdueInstallmentCharge = ChargeTimeType.fromInt(this.chargeTimeType.getId().intValue()).isOverdueInstallment();
} }
return isOverdueInstallmentCharge; return isOverdueInstallmentCharge;
@@ -93,8 +93,8 @@ public class Charge extends AbstractPersistable<Long> {
final ChargeAppliesTo chargeAppliesTo = ChargeAppliesTo.fromInt(command.integerValueOfParameterNamed("chargeAppliesTo")); final ChargeAppliesTo chargeAppliesTo = ChargeAppliesTo.fromInt(command.integerValueOfParameterNamed("chargeAppliesTo"));
final ChargeTimeType chargeTimeType = ChargeTimeType.fromInt(command.integerValueOfParameterNamed("chargeTimeType")); final ChargeTimeType chargeTimeType = ChargeTimeType.fromInt(command.integerValueOfParameterNamed("chargeTimeType"));
final ChargeCalculationType chargeCalculationType = ChargeCalculationType.fromInt(command final ChargeCalculationType chargeCalculationType = ChargeCalculationType
.integerValueOfParameterNamed("chargeCalculationType")); .fromInt(command.integerValueOfParameterNamed("chargeCalculationType"));
final Integer chargePaymentMode = command.integerValueOfParameterNamed("chargePaymentMode"); final Integer chargePaymentMode = command.integerValueOfParameterNamed("chargePaymentMode");
final ChargePaymentMode paymentMode = chargePaymentMode == null ? null : ChargePaymentMode.fromInt(chargePaymentMode); final ChargePaymentMode paymentMode = chargePaymentMode == null ? null : ChargePaymentMode.fromInt(chargePaymentMode);
@@ -116,9 +116,9 @@ public class Charge extends AbstractPersistable<Long> {
} }
private Charge(final String name, final BigDecimal amount, final String currencyCode, final ChargeAppliesTo chargeAppliesTo, private Charge(final String name, final BigDecimal amount, final String currencyCode, final ChargeAppliesTo chargeAppliesTo,
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculationType, final boolean penalty, final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculationType, final boolean penalty, final boolean active,
final boolean active, final ChargePaymentMode paymentMode, final MonthDay feeOnMonthDay, final Integer feeInterval, final ChargePaymentMode paymentMode, final MonthDay feeOnMonthDay, final Integer feeInterval, final BigDecimal minCap,
final BigDecimal minCap, final BigDecimal maxCap, final Integer feeFrequency) { final BigDecimal maxCap, final Integer feeFrequency) {
this.name = name; this.name = name;
this.amount = amount; this.amount = amount;
this.currencyCode = currencyCode; this.currencyCode = currencyCode;
@@ -140,12 +140,14 @@ public class Charge extends AbstractPersistable<Long> {
this.feeFrequency = feeFrequency; this.feeFrequency = feeFrequency;
if (isSavingsCharge()) { if (isSavingsCharge()) {
// TODO vishwas, this validation seems unnecessary as identical
// validation is performed in the write service
if (!isAllowedSavingsChargeTime()) { if (!isAllowedSavingsChargeTime()) {
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTime) baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTime)
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.savings"); .failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.savings");
} }
// TODO vishwas, this validation seems unnecessary as identical
// validation is performed in the writeservice
if (!isAllowedSavingsChargeCalculationType()) { if (!isAllowedSavingsChargeCalculationType()) {
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");
@@ -161,6 +163,8 @@ public class Charge extends AbstractPersistable<Long> {
if (penalty && chargeTime.isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException(name); } if (penalty && chargeTime.isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException(name); }
if (!penalty && chargeTime.isOverdueInstallment()) { throw new ChargeMustBePenaltyException(name); } if (!penalty && chargeTime.isOverdueInstallment()) { throw new ChargeMustBePenaltyException(name); }
// TODO vishwas, this validation seems unnecessary as identical
// validation is performed in the write service
if (!isAllowedLoanChargeTime()) { if (!isAllowedLoanChargeTime()) {
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTime) baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTime)
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.loan"); .failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.loan");
@@ -232,10 +236,18 @@ public class Charge extends AbstractPersistable<Long> {
return ChargeTimeType.fromInt(this.chargeTime).isAllowedLoanChargeTime(); return ChargeTimeType.fromInt(this.chargeTime).isAllowedLoanChargeTime();
} }
public boolean isAllowedClientChargeTime() {
return ChargeTimeType.fromInt(this.chargeTime).isAllowedClientChargeTime();
}
public boolean isSavingsCharge() { public boolean isSavingsCharge() {
return ChargeAppliesTo.fromInt(this.chargeAppliesTo).isSavingsCharge(); return ChargeAppliesTo.fromInt(this.chargeAppliesTo).isSavingsCharge();
} }
public boolean isClientCharge() {
return ChargeAppliesTo.fromInt(this.chargeAppliesTo).isClientCharge();
}
public boolean isAllowedSavingsChargeTime() { public boolean isAllowedSavingsChargeTime() {
return ChargeTimeType.fromInt(this.chargeTime).isAllowedSavingsChargeTime(); return ChargeTimeType.fromInt(this.chargeTime).isAllowedSavingsChargeTime();
} }
@@ -244,6 +256,10 @@ public class Charge extends AbstractPersistable<Long> {
return ChargeCalculationType.fromInt(this.chargeCalculation).isAllowedSavingsChargeCalculationType(); return ChargeCalculationType.fromInt(this.chargeCalculation).isAllowedSavingsChargeCalculationType();
} }
public boolean isAllowedClientChargeCalculationType() {
return ChargeCalculationType.fromInt(this.chargeCalculation).isAllowedClientChargeCalculationType();
}
public boolean isPercentageOfAmount() { public boolean isPercentageOfAmount() {
return ChargeCalculationType.fromInt(this.chargeCalculation).isPercentageOfAmount(); return ChargeCalculationType.fromInt(this.chargeCalculation).isPercentageOfAmount();
} }
@@ -313,6 +329,11 @@ public class Charge extends AbstractPersistable<Long> {
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTime) baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTime)
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.loan"); .failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.loan");
} }
} else if (isClientCharge()) {
if (!isAllowedLoanChargeTime()) {
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTime)
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.client");
}
} }
} }
@@ -349,6 +370,11 @@ public class Charge extends AbstractPersistable<Long> {
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation) baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
.failWithCodeNoParameterAddedToErrorCode("charge.calculation.type.percentage.allowed.only.for.withdrawal"); .failWithCodeNoParameterAddedToErrorCode("charge.calculation.type.percentage.allowed.only.for.withdrawal");
} }
} else if (isClientCharge()) {
if (!isAllowedClientChargeCalculationType()) {
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.client");
}
} }
} }
@@ -387,7 +413,7 @@ public class Charge extends AbstractPersistable<Long> {
actualChanges.put("locale", localeAsInput); actualChanges.put("locale", localeAsInput);
this.feeInterval = newValue; this.feeInterval = newValue;
} }
final String feeFrequency = "feeFrequency"; final String feeFrequency = "feeFrequency";
if (command.isChangeInIntegerParameterNamed(feeFrequency, this.feeFrequency)) { if (command.isChangeInIntegerParameterNamed(feeFrequency, this.feeFrequency)) {
final Integer newValue = command.integerValueOfParameterNamed(feeFrequency); final Integer newValue = command.integerValueOfParameterNamed(feeFrequency);
@@ -395,8 +421,8 @@ public class Charge extends AbstractPersistable<Long> {
actualChanges.put("locale", localeAsInput); actualChanges.put("locale", localeAsInput);
this.feeFrequency = newValue; this.feeFrequency = newValue;
} }
if(this.feeFrequency != null){ if (this.feeFrequency != null) {
baseDataValidator.reset().parameter("feeInterval").value(this.feeInterval).notNull(); baseDataValidator.reset().parameter("feeInterval").value(this.feeInterval).notNull();
} }
@@ -431,8 +457,8 @@ public class Charge extends AbstractPersistable<Long> {
} }
} }
if (this.penalty && ChargeTimeType.fromInt(this.chargeTime).isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException( if (this.penalty && ChargeTimeType.fromInt(this.chargeTime)
this.name); } .isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException(this.name); }
if (!penalty && ChargeTimeType.fromInt(this.chargeTime).isOverdueInstallment()) { throw new ChargeMustBePenaltyException(name); } if (!penalty && ChargeTimeType.fromInt(this.chargeTime).isOverdueInstallment()) { throw new ChargeMustBePenaltyException(name); }
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
@@ -467,9 +493,9 @@ public class Charge extends AbstractPersistable<Long> {
public Integer getChargePaymentMode() { public Integer getChargePaymentMode() {
return this.chargePaymentMode; return this.chargePaymentMode;
} }
public Integer getFeeInterval(){ public Integer getFeeInterval() {
return this.feeInterval; return this.feeInterval;
} }
public boolean isMonthlyFee() { public boolean isMonthlyFee() {
@@ -9,7 +9,8 @@ public enum ChargeAppliesTo {
INVALID(0, "chargeAppliesTo.invalid"), // INVALID(0, "chargeAppliesTo.invalid"), //
LOAN(1, "chargeAppliesTo.loan"), // LOAN(1, "chargeAppliesTo.loan"), //
SAVINGS(2, "chargeAppliesTo.savings"); SAVINGS(2, "chargeAppliesTo.savings"), //
CLIENT(3, "chargeAppliesTo.client");
private final Integer value; private final Integer value;
private final String code; private final String code;
@@ -38,6 +39,9 @@ public enum ChargeAppliesTo {
case 2: case 2:
chargeAppliesToType = SAVINGS; chargeAppliesToType = SAVINGS;
break; break;
case 3:
chargeAppliesToType = CLIENT;
break;
default: default:
chargeAppliesToType = INVALID; chargeAppliesToType = INVALID;
break; break;
@@ -55,7 +59,11 @@ public enum ChargeAppliesTo {
return this.value.equals(ChargeAppliesTo.SAVINGS.getValue()); return this.value.equals(ChargeAppliesTo.SAVINGS.getValue());
} }
public boolean isClientCharge() {
return this.value.equals(ChargeAppliesTo.CLIENT.getValue());
}
public static Object[] validValues() { public static Object[] validValues() {
return new Object[] { ChargeAppliesTo.LOAN.getValue(), ChargeAppliesTo.SAVINGS.getValue() }; return new Object[] { ChargeAppliesTo.LOAN.getValue(), ChargeAppliesTo.SAVINGS.getValue(), ChargeAppliesTo.CLIENT.getValue() };
} }
} }
@@ -38,6 +38,10 @@ public enum ChargeCalculationType {
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() }; return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() };
} }
public static Object[] validValuesForClients() {
return new Integer[] { ChargeCalculationType.FLAT.getValue() };
}
public static ChargeCalculationType fromInt(final Integer chargeCalculation) { public static ChargeCalculationType fromInt(final Integer chargeCalculation) {
ChargeCalculationType chargeCalculationType = ChargeCalculationType.INVALID; ChargeCalculationType chargeCalculationType = ChargeCalculationType.INVALID;
switch (chargeCalculation) { switch (chargeCalculation) {
@@ -77,6 +81,10 @@ public enum ChargeCalculationType {
return isFlat() || isPercentageOfAmount(); return isFlat() || isPercentageOfAmount();
} }
public boolean isAllowedClientChargeCalculationType() {
return isFlat();
}
public boolean isPercentageBased() { public boolean isPercentageBased() {
return isPercentageOfAmount() || isPercentageOfAmountAndInterest() || isPercentageOfInterest(); return isPercentageOfAmount() || isPercentageOfAmountAndInterest() || isPercentageOfInterest();
} }
@@ -20,7 +20,7 @@ public enum ChargeTimeType {
INSTALMENT_FEE(8, "chargeTimeType.instalmentFee"), // only for loan charges INSTALMENT_FEE(8, "chargeTimeType.instalmentFee"), // only for loan charges
OVERDUE_INSTALLMENT(9, "chargeTimeType.overdueInstallment"), // only for OVERDUE_INSTALLMENT(9, "chargeTimeType.overdueInstallment"), // only for
// loan charges // loan charges
OVERDRAFT_FEE(10, "chargeTimeType.overdraftFee"),// only for savings OVERDRAFT_FEE(10, "chargeTimeType.overdraftFee"), // only for savings
WEEKLY_FEE(11, "chargeTimeType.weeklyFee"); // only for savings WEEKLY_FEE(11, "chargeTimeType.weeklyFee"); // only for savings
private final Integer value; private final Integer value;
@@ -43,10 +43,10 @@ public enum ChargeTimeType {
return new Integer[] { ChargeTimeType.DISBURSEMENT.getValue(), ChargeTimeType.SPECIFIED_DUE_DATE.getValue(), return new Integer[] { ChargeTimeType.DISBURSEMENT.getValue(), ChargeTimeType.SPECIFIED_DUE_DATE.getValue(),
ChargeTimeType.INSTALMENT_FEE.getValue(), ChargeTimeType.OVERDUE_INSTALLMENT.getValue() }; ChargeTimeType.INSTALMENT_FEE.getValue(), ChargeTimeType.OVERDUE_INSTALLMENT.getValue() };
} }
public static Object[] validLoanChargeValues() { public static Object[] validLoanChargeValues() {
return new Integer[] { ChargeTimeType.DISBURSEMENT.getValue(), ChargeTimeType.SPECIFIED_DUE_DATE.getValue(), return new Integer[] { ChargeTimeType.DISBURSEMENT.getValue(), ChargeTimeType.SPECIFIED_DUE_DATE.getValue(),
ChargeTimeType.INSTALMENT_FEE.getValue()}; ChargeTimeType.INSTALMENT_FEE.getValue() };
} }
public static Object[] validSavingsValues() { public static Object[] validSavingsValues() {
@@ -55,6 +55,10 @@ public enum ChargeTimeType {
ChargeTimeType.MONTHLY_FEE.getValue(), ChargeTimeType.OVERDRAFT_FEE.getValue(), ChargeTimeType.WEEKLY_FEE.getValue() }; ChargeTimeType.MONTHLY_FEE.getValue(), ChargeTimeType.OVERDRAFT_FEE.getValue(), ChargeTimeType.WEEKLY_FEE.getValue() };
} }
public static Object[] validClientValues() {
return new Integer[] { ChargeTimeType.SPECIFIED_DUE_DATE.getValue() };
}
public static ChargeTimeType fromInt(final Integer chargeTime) { public static ChargeTimeType fromInt(final Integer chargeTime) {
ChargeTimeType chargeTimeType = ChargeTimeType.INVALID; ChargeTimeType chargeTimeType = ChargeTimeType.INVALID;
if (chargeTime != null) { if (chargeTime != null) {
@@ -127,11 +131,11 @@ public enum ChargeTimeType {
public boolean isMonthlyFee() { public boolean isMonthlyFee() {
return this.value.equals(ChargeTimeType.MONTHLY_FEE.getValue()); return this.value.equals(ChargeTimeType.MONTHLY_FEE.getValue());
} }
public boolean isWeeklyFee() { public boolean isWeeklyFee() {
return this.value.equals(ChargeTimeType.WEEKLY_FEE.getValue()); return this.value.equals(ChargeTimeType.WEEKLY_FEE.getValue());
} }
public boolean isInstalmentFee() { public boolean isInstalmentFee() {
return this.value.equals(ChargeTimeType.INSTALMENT_FEE.getValue()); return this.value.equals(ChargeTimeType.INSTALMENT_FEE.getValue());
} }
@@ -144,9 +148,13 @@ public enum ChargeTimeType {
return isTimeOfDisbursement() || isOnSpecifiedDueDate() || isInstalmentFee() || isOverdueInstallment(); return isTimeOfDisbursement() || isOnSpecifiedDueDate() || isInstalmentFee() || isOverdueInstallment();
} }
public boolean isAllowedClientChargeTime() {
return isOnSpecifiedDueDate();
}
public boolean isAllowedSavingsChargeTime() { public boolean isAllowedSavingsChargeTime() {
return isOnSpecifiedDueDate() || isSavingsActivation() || isSavingsClosure() || isWithdrawalFee() || isAnnualFee() return isOnSpecifiedDueDate() || isSavingsActivation() || isSavingsClosure() || isWithdrawalFee() || isAnnualFee() || isMonthlyFee()
|| isMonthlyFee() || isWeeklyFee() || isOverdraftFee(); || isWeeklyFee() || isOverdraftFee();
} }
public boolean isOverdraftFee() { public boolean isOverdraftFee() {
@@ -116,8 +116,8 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
if (ctt.isWeeklyFee()) { if (ctt.isWeeklyFee()) {
final String monthDay = this.fromApiJsonHelper.extractStringNamed("feeOnMonthDay", element); final String monthDay = this.fromApiJsonHelper.extractStringNamed("feeOnMonthDay", element);
baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay) baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).mustBeBlankWhenParameterProvidedIs("chargeTimeType",
.mustBeBlankWhenParameterProvidedIs("chargeTimeType", chargeTimeType); chargeTimeType);
} }
if (ctt.isMonthlyFee()) { if (ctt.isMonthlyFee()) {
@@ -132,6 +132,22 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).notNull(); baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).notNull();
} }
if (chargeCalculationType != null) {
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType)
.isOneOfTheseValues(ChargeCalculationType.validValuesForSavings());
}
} else if (appliesTo.isClientCharge()) {
// client applicable validation
final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeTimeType", element);
baseDataValidator.reset().parameter("chargeTimeType").value(chargeTimeType).notNull();
if (chargeTimeType != null) {
baseDataValidator.reset().parameter("chargeTimeType").value(chargeTimeType)
.isOneOfTheseValues(ChargeTimeType.validClientValues());
}
// final ChargeTimeType ctt =
// ChargeTimeType.fromInt(chargeTimeType);
if (chargeCalculationType != null) { if (chargeCalculationType != null) {
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType) baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType)
.isOneOfTheseValues(ChargeCalculationType.validValuesForSavings()); .isOneOfTheseValues(ChargeCalculationType.validValuesForSavings());
@@ -217,9 +233,11 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
final Collection<Object> validLoanValues = Arrays.asList(ChargeTimeType.validLoanValues()); final Collection<Object> validLoanValues = Arrays.asList(ChargeTimeType.validLoanValues());
final Collection<Object> validSavingsValues = Arrays.asList(ChargeTimeType.validSavingsValues()); final Collection<Object> validSavingsValues = Arrays.asList(ChargeTimeType.validSavingsValues());
final Collection<Object> validClientValues = Arrays.asList(ChargeTimeType.validClientValues());
final Collection<Object> allValidValues = new ArrayList<>(validLoanValues); final Collection<Object> allValidValues = new ArrayList<>(validLoanValues);
allValidValues.addAll(validSavingsValues); allValidValues.addAll(validSavingsValues);
allValidValues.addAll(validClientValues);
baseDataValidator.reset().parameter("chargeTimeType").value(chargeTimeType).notNull() baseDataValidator.reset().parameter("chargeTimeType").value(chargeTimeType).notNull()
.isOneOfTheseValues(allValidValues.toArray(new Object[allValidValues.size()])); .isOneOfTheseValues(allValidValues.toArray(new Object[allValidValues.size()]));
@@ -27,4 +27,8 @@ public interface ChargeDropdownReadPlatformService {
List<EnumOptionData> retrieveSavingsCollectionTimeTypes(); List<EnumOptionData> retrieveSavingsCollectionTimeTypes();
List<EnumOptionData> retrieveClientCalculationTypes();
List<EnumOptionData> retrieveClientCollectionTimeTypes();
} }
@@ -87,4 +87,14 @@ public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownRead
chargeTimeType(ChargeTimeType.MONTHLY_FEE), chargeTimeType(ChargeTimeType.WEEKLY_FEE), chargeTimeType(ChargeTimeType.MONTHLY_FEE), chargeTimeType(ChargeTimeType.WEEKLY_FEE),
chargeTimeType(ChargeTimeType.OVERDRAFT_FEE)); chargeTimeType(ChargeTimeType.OVERDRAFT_FEE));
} }
@Override
public List<EnumOptionData> retrieveClientCalculationTypes() {
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT));
}
@Override
public List<EnumOptionData> retrieveClientCollectionTimeTypes() {
return Arrays.asList(chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE));
}
} }
@@ -49,9 +49,9 @@ public class ChargeEnumerations {
"Monthly Fee"); "Monthly Fee");
break; break;
case WEEKLY_FEE: case WEEKLY_FEE:
optionData = new EnumOptionData(ChargeTimeType.WEEKLY_FEE.getValue().longValue(), ChargeTimeType.WEEKLY_FEE.getCode(), optionData = new EnumOptionData(ChargeTimeType.WEEKLY_FEE.getValue().longValue(), ChargeTimeType.WEEKLY_FEE.getCode(),
"Weekly Fee"); "Weekly Fee");
break; break;
case INSTALMENT_FEE: case INSTALMENT_FEE:
optionData = new EnumOptionData(ChargeTimeType.INSTALMENT_FEE.getValue().longValue(), optionData = new EnumOptionData(ChargeTimeType.INSTALMENT_FEE.getValue().longValue(),
ChargeTimeType.INSTALMENT_FEE.getCode(), "Installment Fee"); ChargeTimeType.INSTALMENT_FEE.getCode(), "Installment Fee");
@@ -61,8 +61,8 @@ public class ChargeEnumerations {
ChargeTimeType.OVERDUE_INSTALLMENT.getCode(), "Overdue Fees"); ChargeTimeType.OVERDUE_INSTALLMENT.getCode(), "Overdue Fees");
break; break;
case OVERDRAFT_FEE: case OVERDRAFT_FEE:
optionData = new EnumOptionData(ChargeTimeType.OVERDRAFT_FEE.getValue().longValue(), optionData = new EnumOptionData(ChargeTimeType.OVERDRAFT_FEE.getValue().longValue(), ChargeTimeType.OVERDRAFT_FEE.getCode(),
ChargeTimeType.OVERDRAFT_FEE.getCode(), "Overdraft Fee"); "Overdraft 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");
@@ -85,6 +85,9 @@ public class ChargeEnumerations {
optionData = new EnumOptionData(ChargeAppliesTo.SAVINGS.getValue().longValue(), ChargeAppliesTo.SAVINGS.getCode(), optionData = new EnumOptionData(ChargeAppliesTo.SAVINGS.getValue().longValue(), ChargeAppliesTo.SAVINGS.getCode(),
"Savings"); "Savings");
break; break;
case CLIENT:
optionData = new EnumOptionData(ChargeAppliesTo.CLIENT.getValue().longValue(), ChargeAppliesTo.CLIENT.getCode(), "Client");
break;
default: default:
optionData = new EnumOptionData(ChargeAppliesTo.INVALID.getValue().longValue(), ChargeAppliesTo.INVALID.getCode(), optionData = new EnumOptionData(ChargeAppliesTo.INVALID.getValue().longValue(), ChargeAppliesTo.INVALID.getCode(),
"Invalid"); "Invalid");
@@ -20,6 +20,13 @@ public interface ChargeReadPlatformService {
ChargeData retrieveNewChargeDetails(); ChargeData retrieveNewChargeDetails();
/**
* Returns all charges that can be applied to Cients
*
* @return
*/
Collection<ChargeData> retrieveAllChargesApplicableToClients();
/** /**
* Returns all Fees (excluding penalties) applicable for loans * Returns all Fees (excluding penalties) applicable for loans
* *
@@ -93,7 +100,7 @@ public interface ChargeReadPlatformService {
* @return * @return
*/ */
Collection<ChargeData> retrieveSavingsProductCharges(Long savingsProductId); Collection<ChargeData> retrieveSavingsProductCharges(Long savingsProductId);
/** Retrieve savings account charges **/ /** Retrieve savings account charges **/
Collection<ChargeData> retrieveSavingsAccountApplicableCharges(Long savingsId); Collection<ChargeData> retrieveSavingsAccountApplicableCharges(Long savingsId);
@@ -45,12 +45,11 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
private final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService; private final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService;
private final DropdownReadPlatformService dropdownReadPlatformService; private final DropdownReadPlatformService dropdownReadPlatformService;
private final MifosEntityAccessUtil mifosEntityAccessUtil; private final MifosEntityAccessUtil mifosEntityAccessUtil;
@Autowired @Autowired
public ChargeReadPlatformServiceImpl(final CurrencyReadPlatformService currencyReadPlatformService, public ChargeReadPlatformServiceImpl(final CurrencyReadPlatformService currencyReadPlatformService,
final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService, final RoutingDataSource dataSource, final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService, final RoutingDataSource dataSource,
final DropdownReadPlatformService dropdownReadPlatformService, final DropdownReadPlatformService dropdownReadPlatformService, final MifosEntityAccessUtil mifosEntityAccessUtil) {
final MifosEntityAccessUtil mifosEntityAccessUtil) {
this.chargeDropdownReadPlatformService = chargeDropdownReadPlatformService; this.chargeDropdownReadPlatformService = chargeDropdownReadPlatformService;
this.jdbcTemplate = new JdbcTemplate(dataSource); this.jdbcTemplate = new JdbcTemplate(dataSource);
this.currencyReadPlatformService = currencyReadPlatformService; this.currencyReadPlatformService = currencyReadPlatformService;
@@ -64,10 +63,10 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 "; String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled(); sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
sql += " order by c.name "; sql += " order by c.name ";
return this.jdbcTemplate.query(sql, rm, new Object[] {}); return this.jdbcTemplate.query(sql, rm, new Object[] {});
} }
@@ -76,12 +75,11 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
public Collection<ChargeData> retrieveAllChargesForCurrency(String currencyCode) { public Collection<ChargeData> retrieveAllChargesForCurrency(String currencyCode) {
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 and c.currency_code='" + currencyCode String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 and c.currency_code='" + currencyCode + "' ";
+ "' ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled(); sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
sql += " order by c.name "; sql += " order by c.name ";
return this.jdbcTemplate.query(sql, rm, new Object[] {}); return this.jdbcTemplate.query(sql, rm, new Object[] {});
} }
@@ -92,9 +90,9 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
String sql = "select " + rm.chargeSchema() + " where c.id = ? and c.is_deleted=0 "; String sql = "select " + rm.chargeSchema() + " where c.id = ? and c.is_deleted=0 ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled(); sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { chargeId }); return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { chargeId });
} catch (final EmptyResultDataAccessException e) { } catch (final EmptyResultDataAccessException e) {
throw new ChargeNotFoundException(chargeId); throw new ChargeNotFoundException(chargeId);
@@ -116,11 +114,15 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
.retrieveSavingsCalculationTypes(); .retrieveSavingsCalculationTypes();
final List<EnumOptionData> savingsChargeTimeTypeOptions = this.chargeDropdownReadPlatformService final List<EnumOptionData> savingsChargeTimeTypeOptions = this.chargeDropdownReadPlatformService
.retrieveSavingsCollectionTimeTypes(); .retrieveSavingsCollectionTimeTypes();
final List<EnumOptionData> clientChargeCalculationTypeOptions = this.chargeDropdownReadPlatformService
.retrieveClientCalculationTypes();
final List<EnumOptionData> clientChargeTimeTypeOptions = this.chargeDropdownReadPlatformService.retrieveClientCollectionTimeTypes();
final List<EnumOptionData> feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions(); final List<EnumOptionData> feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions();
return ChargeData.template(currencyOptions, allowedChargeCalculationTypeOptions, allowedChargeAppliesToOptions, return ChargeData.template(currencyOptions, allowedChargeCalculationTypeOptions, allowedChargeAppliesToOptions,
allowedChargeTimeOptions, chargePaymentOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, allowedChargeTimeOptions, chargePaymentOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, feeFrequencyOptions); savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
clientChargeTimeTypeOptions, feeFrequencyOptions);
} }
@Override @Override
@@ -128,7 +130,7 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
String sql = "select " + rm.loanProductChargeSchema() + " where c.is_deleted=0 and c.is_active=1 and plc.product_loan_id=? "; String sql = "select " + rm.loanProductChargeSchema() + " where c.is_deleted=0 and c.is_active=1 and plc.product_loan_id=? ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled(); sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
return this.jdbcTemplate.query(sql, rm, new Object[] { loanProductId }); return this.jdbcTemplate.query(sql, rm, new Object[] { loanProductId });
@@ -168,7 +170,6 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
+ " and c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=?" + excludeClause + " "; + " and c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=?" + excludeClause + " ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled(); sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
sql += " order by c.name "; sql += " order by c.name ";
return this.jdbcTemplate.query(sql, rm, params); return this.jdbcTemplate.query(sql, rm, params);
} }
@@ -219,20 +220,19 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
sql += " order by c.name "; sql += " order by c.name ";
return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.LOAN.getValue() }); return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.LOAN.getValue() });
} }
private String addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled () { private String addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled() {
String sql = ""; String sql = "";
// Check if branch specific products are enabled. If yes, fetch only charges mapped to current user's office // Check if branch specific products are enabled. If yes, fetch only
String inClause = mifosEntityAccessUtil. // charges mapped to current user's office
getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled( String inClause = mifosEntityAccessUtil.getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(MifosEntityType.CHARGE);
MifosEntityType.CHARGE); if ((inClause != null) && (!(inClause.trim().isEmpty()))) {
if ( (inClause != null) && (!(inClause.trim().isEmpty())) ) { sql += " and c.id in ( " + inClause + " ) ";
sql += " and c.id in ( " + inClause + " ) "; }
}
return sql;
return sql;
} }
private static final class ChargeMapper implements RowMapper<ChargeData> { private static final class ChargeMapper implements RowMapper<ChargeData> {
@@ -312,8 +312,7 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
public Collection<ChargeData> retrieveSavingsProductApplicableCharges(final boolean feeChargesOnly) { public Collection<ChargeData> retrieveSavingsProductApplicableCharges(final boolean feeChargesOnly) {
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
String sql = "select " + rm.chargeSchema() String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=? ";
+ " where c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=? ";
if (feeChargesOnly) { if (feeChargesOnly) {
sql = "select " + rm.chargeSchema() sql = "select " + rm.chargeSchema()
+ " where c.is_deleted=0 and c.is_active=1 and c.is_penalty=0 and c.charge_applies_to_enum=? "; + " where c.is_deleted=0 and c.is_active=1 and c.is_penalty=0 and c.charge_applies_to_enum=? ";
@@ -339,13 +338,12 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
public Collection<ChargeData> retrieveSavingsProductCharges(final Long savingsProductId) { public Collection<ChargeData> retrieveSavingsProductCharges(final Long savingsProductId) {
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
String sql = "select " + rm.savingsProductChargeSchema() String sql = "select " + rm.savingsProductChargeSchema() + " where c.is_deleted=0 and c.is_active=1 and spc.savings_product_id=? ";
+ " where c.is_deleted=0 and c.is_active=1 and spc.savings_product_id=? ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled(); sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
return this.jdbcTemplate.query(sql, rm, new Object[] { savingsProductId }); return this.jdbcTemplate.query(sql, rm, new Object[] { savingsProductId });
} }
@Override @Override
public Collection<ChargeData> retrieveSavingsAccountApplicableCharges(Long savingsAccountId) { public Collection<ChargeData> retrieveSavingsAccountApplicableCharges(Long savingsAccountId) {
@@ -354,9 +352,19 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
String sql = "select " + rm.chargeSchema() + " join m_savings_account sa on sa.currency_code = c.currency_code" String sql = "select " + rm.chargeSchema() + " join m_savings_account sa on sa.currency_code = c.currency_code"
+ " where c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=? " + " and sa.account_no = ?"; + " where c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=? " + " and sa.account_no = ?";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled(); sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.SAVINGS.getValue(), savingsAccountId }); return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.SAVINGS.getValue(), savingsAccountId });
} }
@Override
public Collection<ChargeData> retrieveAllChargesApplicableToClients() {
final ChargeMapper rm = new ChargeMapper();
String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=? ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
sql += " order by c.name ";
return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.CLIENT.getValue() });
}
} }
@@ -25,6 +25,7 @@ import org.mifosplatform.infrastructure.core.exception.UnrecognizedQueryParamExc
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer; import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.charge.service.ChargeReadPlatformService; import org.mifosplatform.portfolio.charge.service.ChargeReadPlatformService;
import org.mifosplatform.portfolio.client.data.ClientChargeData; import org.mifosplatform.portfolio.client.data.ClientChargeData;
import org.mifosplatform.portfolio.client.service.ClientChargeReadPlatformService; import org.mifosplatform.portfolio.client.service.ClientChargeReadPlatformService;
@@ -82,11 +83,15 @@ public class ClientChargesApiResource {
@Path("template") @Path("template")
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
public String retrieveTemplate(@PathParam("savingsAccountId") final Long savingsAccountId, @Context final UriInfo uriInfo) { public String retrieveTemplate(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(ClientApiConstants.CLIENT_CHARGES_RESOURCE_NAME); this.context.authenticatedUser().validateHasReadPermission(ClientApiConstants.CLIENT_CHARGES_RESOURCE_NAME);
return null; final Collection<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveAllChargesApplicableToClients();
final ClientChargeData clientChargeData = ClientChargeData.template(chargeOptions);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, clientChargeData, ClientApiConstants.CLIENT_CHARGES_RESPONSE_DATA_PARAMETERS);
} }
@@ -54,6 +54,28 @@ public class ClientChargeData {
amountPaid, amountWaived, amountWrittenOff, amountOutstanding, penalty, isActive, inactivationDate, chargeOptions); amountPaid, amountWaived, amountWrittenOff, amountOutstanding, penalty, isActive, inactivationDate, chargeOptions);
} }
public static ClientChargeData template(final Collection<ChargeData> chargeOptions) {
final Long id = null;
final Long clientId = null;
final Long chargeId = null;
final String name = null;
final EnumOptionData chargeTimeType = null;
final LocalDate dueDate = null;
final EnumOptionData chargeCalculationType = null;
final CurrencyData currency = null;
final BigDecimal amount = null;
final BigDecimal amountPaid = null;
final BigDecimal amountWaived = null;
final BigDecimal amountWrittenOff = null;
final BigDecimal amountOutstanding = null;
final Boolean penalty = false;
final Boolean isActive = null;
final LocalDate inactivationDate = null;
return new ClientChargeData(id, clientId, chargeId, name, chargeTimeType, dueDate, chargeCalculationType, currency, amount,
amountPaid, amountWaived, amountWrittenOff, amountOutstanding, penalty, isActive, inactivationDate, chargeOptions);
}
private ClientChargeData(Long id, Long clientId, Long chargeId, String name, EnumOptionData chargeTimeType, LocalDate dueDate, private ClientChargeData(Long id, Long clientId, Long chargeId, String name, EnumOptionData chargeTimeType, LocalDate dueDate,
EnumOptionData chargeCalculationType, CurrencyData currency, BigDecimal amount, BigDecimal amountPaid, BigDecimal amountWaived, EnumOptionData chargeCalculationType, CurrencyData currency, BigDecimal amount, BigDecimal amountPaid, BigDecimal amountWaived,
BigDecimal amountWrittenOff, BigDecimal amountOutstanding, boolean penalty, Boolean isActive, LocalDate inactivationDate, BigDecimal amountWrittenOff, BigDecimal amountOutstanding, boolean penalty, Boolean isActive, LocalDate inactivationDate,
@@ -42,8 +42,6 @@ public class ClientChargeDataValidator {
.resource(ClientApiConstants.CLIENT_CHARGES_RESOURCE_NAME); .resource(ClientApiConstants.CLIENT_CHARGES_RESOURCE_NAME);
final JsonElement element = this.fromApiJsonHelper.parse(json); final JsonElement element = this.fromApiJsonHelper.parse(json);
final Long chargeId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.chargeIdParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.chargeIdParamName).value(chargeId).notNull().integerGreaterThanZero();
final BigDecimal amount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(ClientApiConstants.amountParamName, element); final BigDecimal amount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(ClientApiConstants.amountParamName, element);
baseDataValidator.reset().parameter(ClientApiConstants.amountParamName).value(amount).notNull().positiveAmount(); baseDataValidator.reset().parameter(ClientApiConstants.amountParamName).value(amount).notNull().positiveAmount();
@@ -1,12 +1,7 @@
package org.mifosplatform.portfolio.client.domain; package org.mifosplatform.portfolio.client.domain;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.dueAsOfDateParamName;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
@@ -15,14 +10,10 @@ import javax.persistence.ManyToOne;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Temporal; import javax.persistence.Temporal;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import javax.persistence.Transient;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormatter;
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.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.service.DateUtils;
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;
import org.mifosplatform.organisation.office.domain.OrganisationCurrency; import org.mifosplatform.organisation.office.domain.OrganisationCurrency;
@@ -30,8 +21,6 @@ import org.mifosplatform.portfolio.charge.domain.Charge;
import org.mifosplatform.portfolio.charge.domain.ChargeCalculationType; import org.mifosplatform.portfolio.charge.domain.ChargeCalculationType;
import org.mifosplatform.portfolio.charge.domain.ChargeTimeType; import org.mifosplatform.portfolio.charge.domain.ChargeTimeType;
import org.mifosplatform.portfolio.client.api.ClientApiConstants; import org.mifosplatform.portfolio.client.api.ClientApiConstants;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountCharge;
import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.data.jpa.domain.AbstractPersistable; import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity @Entity
@@ -87,7 +76,12 @@ public class ClientCharge extends AbstractPersistable<Long> {
@Column(name = "inactivated_on_date") @Column(name = "inactivated_on_date")
private Date inactivationDate; private Date inactivationDate;
@Transient
private OrganisationCurrency currency; private OrganisationCurrency currency;
protected ClientCharge() {
//
}
public static ClientCharge createNew(final Client client, final Charge charge, final JsonCommand command) { public static ClientCharge createNew(final Client client, final Charge charge, final JsonCommand command) {
BigDecimal amount = command.bigDecimalValueOfParameterNamed(ClientApiConstants.amountParamName); BigDecimal amount = command.bigDecimalValueOfParameterNamed(ClientApiConstants.amountParamName);
@@ -3,7 +3,9 @@ package org.mifosplatform.portfolio.client.domain;
import org.mifosplatform.organisation.office.domain.OrganisationCurrencyRepositoryWrapper; import org.mifosplatform.organisation.office.domain.OrganisationCurrencyRepositoryWrapper;
import org.mifosplatform.portfolio.charge.exception.ChargeNotFoundException; import org.mifosplatform.portfolio.charge.exception.ChargeNotFoundException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class ClientChargeRepositoryWrapper { public class ClientChargeRepositoryWrapper {
private final ClientChargeRepository repository; private final ClientChargeRepository repository;
@@ -118,7 +118,7 @@ public class ClientChargeReadPlatformServiceImpl implements ClientChargeReadPlat
final ClientChargeMapper rm = new ClientChargeMapper(); final ClientChargeMapper rm = new ClientChargeMapper();
final String sql = "select " + rm.schema() + " where sc.client_id=? and sc.id=? "; final String sql = "select " + rm.schema() + " where cc.client_id=? and cc.id=? ";
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { clientId, clientChargeId }); return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { clientId, clientChargeId });
} catch (final EmptyResultDataAccessException e) { } catch (final EmptyResultDataAccessException e) {
@@ -24,6 +24,7 @@ import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWrapper; import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWrapper;
import org.mifosplatform.portfolio.charge.domain.Charge; import org.mifosplatform.portfolio.charge.domain.Charge;
import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper; import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper;
import org.mifosplatform.portfolio.charge.exception.ChargeCannotBeAppliedToException;
import org.mifosplatform.portfolio.client.api.ClientApiConstants; import org.mifosplatform.portfolio.client.api.ClientApiConstants;
import org.mifosplatform.portfolio.client.data.ClientChargeDataValidator; import org.mifosplatform.portfolio.client.data.ClientChargeDataValidator;
import org.mifosplatform.portfolio.client.domain.Client; import org.mifosplatform.portfolio.client.domain.Client;
@@ -82,6 +83,12 @@ public class ClientChargeWritePlatformServiceJpaRepositoryImpl implements Client
final Long chargeDefinitionId = command.longValueOfParameterNamed(ClientApiConstants.chargeIdParamName); final Long chargeDefinitionId = command.longValueOfParameterNamed(ClientApiConstants.chargeIdParamName);
final Charge charge = this.chargeRepository.findOneWithNotFoundDetection(chargeDefinitionId); final Charge charge = this.chargeRepository.findOneWithNotFoundDetection(chargeDefinitionId);
// validate for client charge
if (!charge.isClientCharge()) {
final String errorMessage = "Charge with identifier " + charge.getId() + " cannot be applied to a Client";
throw new ChargeCannotBeAppliedToException("client", errorMessage, charge.getId());
}
final ClientCharge clientCharge = ClientCharge.createNew(client, charge, command); final ClientCharge clientCharge = ClientCharge.createNew(client, charge, command);
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()); final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat());
@@ -98,7 +105,7 @@ public class ClientChargeWritePlatformServiceJpaRepositoryImpl implements Client
@Override @Override
public CommandProcessingResult payCharge(Long clientId, Long clientChargeId, JsonCommand command) { public CommandProcessingResult payCharge(Long clientId, Long clientChargeId, JsonCommand command) {
this.clientChargeDataValidator.validateAdd(command.json()); this.clientChargeDataValidator.validatePayCharge(command.json());
final Client client = this.clientRepository.getActiveClient(clientId); final Client client = this.clientRepository.getActiveClient(clientId);
@@ -18,7 +18,9 @@ import org.mifosplatform.portfolio.paymenttype.data.PaymentTypeData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class ClientTransactionReadPlatformServiceImpl implements ClientTransactionReadPlatformService { public class ClientTransactionReadPlatformServiceImpl implements ClientTransactionReadPlatformService {
private final JdbcTemplate jdbcTemplate; private final JdbcTemplate jdbcTemplate;
@@ -54,22 +54,14 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
private static final class LoanChargeMapper implements RowMapper<LoanChargeData> { private static final class LoanChargeMapper implements RowMapper<LoanChargeData> {
public String schema() { public String schema() {
return "lc.id as id, c.id as chargeId, c.name as name, " return "lc.id as id, c.id as chargeId, c.name as name, " + "lc.amount as amountDue, " + "lc.amount_paid_derived as amountPaid, "
+ "lc.amount as amountDue, " + "lc.amount_waived_derived as amountWaived, " + "lc.amount_writtenoff_derived as amountWrittenOff, "
+ "lc.amount_paid_derived as amountPaid, "
+ "lc.amount_waived_derived as amountWaived, "
+ "lc.amount_writtenoff_derived as amountWrittenOff, "
+ "lc.amount_outstanding_derived as amountOutstanding, " + "lc.amount_outstanding_derived as amountOutstanding, "
+ "lc.calculation_percentage as percentageOf, lc.calculation_on_amount as amountPercentageAppliedTo, " + "lc.calculation_percentage as percentageOf, lc.calculation_on_amount as amountPercentageAppliedTo, "
+ "lc.charge_time_enum as chargeTime, " + "lc.charge_time_enum as chargeTime, " + "lc.is_penalty as penalty, "
+ "lc.is_penalty as penalty, " + "lc.due_for_collection_as_of_date as dueAsOfDate, " + "lc.charge_calculation_enum as chargeCalculation, "
+ "lc.due_for_collection_as_of_date as dueAsOfDate, " + "lc.charge_payment_mode_enum as chargePaymentMode, " + "lc.is_paid_derived as paid, " + "lc.waived as waied, "
+ "lc.charge_calculation_enum as chargeCalculation, " + "lc.min_cap as minCap, lc.max_cap as maxCap, " + "lc.charge_amount_or_percentage as amountOrPercentage, "
+ "lc.charge_payment_mode_enum as chargePaymentMode, "
+ "lc.is_paid_derived as paid, "
+ "lc.waived as waied, "
+ "lc.min_cap as minCap, lc.max_cap as maxCap, "
+ "lc.charge_amount_or_percentage as amountOrPercentage, "
+ "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, "
+ "oc.internationalized_name_code as currencyNameCode from m_charge c " + "oc.internationalized_name_code as currencyNameCode from m_charge c "
@@ -119,8 +111,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
final BigDecimal amountOrPercentage = rs.getBigDecimal("amountOrPercentage"); final BigDecimal amountOrPercentage = rs.getBigDecimal("amountOrPercentage");
return new LoanChargeData(id, chargeId, name, currency, amount, amountPaid, amountWaived, amountWrittenOff, amountOutstanding, return new LoanChargeData(id, chargeId, name, currency, amount, amountPaid, amountWaived, amountWrittenOff, amountOutstanding,
chargeTimeType, dueAsOfDate, chargeCalculationType, percentageOf, amountPercentageAppliedTo, penalty, paymentMode, chargeTimeType, dueAsOfDate, chargeCalculationType, percentageOf, amountPercentageAppliedTo, penalty, paymentMode, paid,
paid, waived, null, minCap, maxCap, amountOrPercentage, null); waived, null, minCap, maxCap, amountOrPercentage, null);
} }
} }
@@ -137,11 +129,14 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
.retrieveSavingsCalculationTypes(); .retrieveSavingsCalculationTypes();
final List<EnumOptionData> savingsChargeTimeTypeOptions = this.chargeDropdownReadPlatformService final List<EnumOptionData> savingsChargeTimeTypeOptions = this.chargeDropdownReadPlatformService
.retrieveSavingsCollectionTimeTypes(); .retrieveSavingsCollectionTimeTypes();
final List<EnumOptionData> clientChargeCalculationTypeOptions = null;
final List<EnumOptionData> clientChargeTimeTypeOptions = null;
final List<EnumOptionData> feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions(); final List<EnumOptionData> feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions();
return ChargeData.template(null, allowedChargeCalculationTypeOptions, null, allowedChargeTimeOptions, null, return ChargeData.template(null, allowedChargeCalculationTypeOptions, null, allowedChargeTimeOptions, null,
loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions,
savingsChargeTimeTypeOptions, feeFrequencyOptions); savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, feeFrequencyOptions);
} }
@Override @Override
@@ -170,8 +165,7 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
@Override @Override
public Collection<LoanChargeData> retrieveLoanChargesForFeePayment(final Integer paymentMode, final Integer loanStatus) { public Collection<LoanChargeData> retrieveLoanChargesForFeePayment(final Integer paymentMode, final Integer loanStatus) {
final LoanChargeMapperWithLoanId rm = new LoanChargeMapperWithLoanId(); final LoanChargeMapperWithLoanId rm = new LoanChargeMapperWithLoanId();
final String sql = "select " final String sql = "select " + rm.schema()
+ rm.schema()
+ "where loan.loan_status_id= ? and lc.charge_payment_mode_enum=? and lc.waived =0 and lc.is_paid_derived=0 and lc.is_active = 1"; + "where loan.loan_status_id= ? and lc.charge_payment_mode_enum=? and lc.waived =0 and lc.is_paid_derived=0 and lc.is_active = 1";
return this.jdbcTemplate.query(sql, rm, new Object[] { loanStatus, paymentMode }); return this.jdbcTemplate.query(sql, rm, new Object[] { loanStatus, paymentMode });
} }
@@ -179,9 +173,9 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
private static final class LoanChargeMapperWithLoanId implements RowMapper<LoanChargeData> { private static final class LoanChargeMapperWithLoanId implements RowMapper<LoanChargeData> {
public String schema() { public String schema() {
return "lc.id as id, lc.due_for_collection_as_of_date as dueAsOfDate, " return "lc.id as id, lc.due_for_collection_as_of_date as dueAsOfDate, " + "lc.amount_outstanding_derived as amountOutstanding, "
+ "lc.amount_outstanding_derived as amountOutstanding, " + "lc.charge_time_enum as chargeTime, " + "loan.id as loanId " + "lc.charge_time_enum as chargeTime, " + "loan.id as loanId " + "from m_loan_charge lc "
+ "from m_loan_charge lc " + "join m_loan loan on loan.id = lc.loan_id "; + "join m_loan loan on loan.id = lc.loan_id ";
} }
@Override @Override
@@ -265,8 +259,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
charges.removeAll(removeCharges); charges.removeAll(removeCharges);
for (LoanChargeData loanChargeData : removeCharges) { for (LoanChargeData loanChargeData : removeCharges) {
if (loanChargeData.isInstallmentFee()) { if (loanChargeData.isInstallmentFee()) {
Collection<LoanInstallmentChargeData> installmentChargeDatas = retrieveInstallmentLoanChargesForAccrual(loanChargeData Collection<LoanInstallmentChargeData> installmentChargeDatas = retrieveInstallmentLoanChargesForAccrual(
.getId()); loanChargeData.getId());
LoanChargeData modifiedChargeData = new LoanChargeData(loanChargeData, installmentChargeDatas); LoanChargeData modifiedChargeData = new LoanChargeData(loanChargeData, installmentChargeDatas);
charges.add(modifiedChargeData); charges.add(modifiedChargeData);
} }
@@ -292,7 +286,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
sb.append("left join ("); sb.append("left join (");
sb.append("select lcp.loan_charge_id, lcp.amount"); sb.append("select lcp.loan_charge_id, lcp.amount");
sb.append(" from m_loan_charge_paid_by lcp "); sb.append(" from m_loan_charge_paid_by lcp ");
sb.append("inner join m_loan_transaction lt on lt.id = lcp.loan_transaction_id and lt.is_reversed = 0 and lt.transaction_type_enum = ?"); sb.append(
"inner join m_loan_transaction lt on lt.id = lcp.loan_transaction_id and lt.is_reversed = 0 and lt.transaction_type_enum = ?");
sb.append(") cp on cp.loan_charge_id= lc.id "); sb.append(") cp on cp.loan_charge_id= lc.id ");
schemaSql = sb.toString(); schemaSql = sb.toString();
@@ -321,7 +316,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
} }
} }
private Collection<LoanChargeData> updateLoanChargesWithUnrecognizedIncome(final Long loanId, Collection<LoanChargeData> loanChargeDatas) { private Collection<LoanChargeData> updateLoanChargesWithUnrecognizedIncome(final Long loanId,
Collection<LoanChargeData> loanChargeDatas) {
final LoanChargeUnRecognizedIncomeMapper rm = new LoanChargeUnRecognizedIncomeMapper(loanChargeDatas); final LoanChargeUnRecognizedIncomeMapper rm = new LoanChargeUnRecognizedIncomeMapper(loanChargeDatas);
@@ -350,7 +346,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
sb.append("left join ("); sb.append("left join (");
sb.append("select cpb.loan_charge_id, lt.unrecognized_income_portion"); sb.append("select cpb.loan_charge_id, lt.unrecognized_income_portion");
sb.append(" from m_loan_charge_paid_by cpb "); sb.append(" from m_loan_charge_paid_by cpb ");
sb.append("inner join m_loan_transaction lt on lt.id = cpb.loan_transaction_id and lt.is_reversed = 0 and lt.transaction_type_enum = ?"); sb.append(
"inner join m_loan_transaction lt on lt.id = cpb.loan_transaction_id and lt.is_reversed = 0 and lt.transaction_type_enum = ?");
sb.append(") wt on wt.loan_charge_id= lc.id "); sb.append(") wt on wt.loan_charge_id= lc.id ");
schemaSql = sb.toString(); schemaSql = sb.toString();
@@ -406,7 +403,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
sb.append("left join ("); sb.append("left join (");
sb.append("select lcp.loan_charge_id, lcp.amount as amount, lcp.installment_number "); sb.append("select lcp.loan_charge_id, lcp.amount as amount, lcp.installment_number ");
sb.append(" from m_loan_charge_paid_by lcp "); sb.append(" from m_loan_charge_paid_by lcp ");
sb.append("inner join m_loan_transaction lt on lt.id = lcp.loan_transaction_id and lt.is_reversed = 0 and lt.transaction_type_enum = ?"); sb.append(
"inner join m_loan_transaction lt on lt.id = lcp.loan_transaction_id and lt.is_reversed = 0 and lt.transaction_type_enum = ?");
sb.append(") cp on cp.loan_charge_id= lic.loan_charge_id and cp.installment_number = lsi.installment "); sb.append(") cp on cp.loan_charge_id= lic.loan_charge_id and cp.installment_number = lsi.installment ");
schemaSql = sb.toString(); schemaSql = sb.toString();
} }
@@ -449,7 +447,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
sb.append(" cpb.installment_number as installmentNumber, "); sb.append(" cpb.installment_number as installmentNumber, ");
sb.append(" sum(lt.unrecognized_income_portion) as amountUnrecognized "); sb.append(" sum(lt.unrecognized_income_portion) as amountUnrecognized ");
sb.append(" from m_loan_charge_paid_by cpb "); sb.append(" from m_loan_charge_paid_by cpb ");
sb.append("inner join m_loan_transaction lt on lt.id = cpb.loan_transaction_id and lt.is_reversed = 0 and lt.transaction_type_enum = ?"); sb.append(
"inner join m_loan_transaction lt on lt.id = cpb.loan_transaction_id and lt.is_reversed = 0 and lt.transaction_type_enum = ?");
schemaSql = sb.toString(); schemaSql = sb.toString();
} }
@@ -58,18 +58,12 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou
private static final class SavingsAccountChargeMapper implements RowMapper<SavingsAccountChargeData> { private static final class SavingsAccountChargeMapper implements RowMapper<SavingsAccountChargeData> {
public String schema() { public String schema() {
return "sc.id as id, c.id as chargeId, sc.savings_account_id as accountId, c.name as name, " return "sc.id as id, c.id as chargeId, sc.savings_account_id as accountId, c.name as name, " + "sc.amount as amountDue, "
+ "sc.amount as amountDue, " + "sc.amount_paid_derived as amountPaid, " + "sc.amount_waived_derived as amountWaived, "
+ "sc.amount_paid_derived as amountPaid, " + "sc.amount_writtenoff_derived as amountWrittenOff, " + "sc.amount_outstanding_derived as amountOutstanding, "
+ "sc.amount_waived_derived as amountWaived, "
+ "sc.amount_writtenoff_derived as amountWrittenOff, "
+ "sc.amount_outstanding_derived as amountOutstanding, "
+ "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.charge_due_date as dueAsOfDate, "
+ "sc.is_penalty as penalty, " + "sc.fee_on_month as feeOnMonth, " + "sc.fee_on_day as feeOnDay, sc.fee_interval as feeInterval, "
+ "sc.charge_due_date as dueAsOfDate, "
+ "sc.fee_on_month as feeOnMonth, "
+ "sc.fee_on_day as feeOnDay, sc.fee_interval as feeInterval, "
+ "sc.charge_calculation_enum as chargeCalculation, " + "sc.charge_calculation_enum as chargeCalculation, "
+ "sc.is_active as isActive, sc.inactivated_on_date as inactivationDate, " + "sc.is_active as isActive, sc.inactivated_on_date as inactivationDate, "
+ "c.currency_code as currencyCode, oc.name as currencyName, " + "c.currency_code as currencyCode, oc.name as currencyName, "
@@ -144,13 +138,15 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou
.retrieveSavingsCalculationTypes(); .retrieveSavingsCalculationTypes();
final List<EnumOptionData> savingsChargeTimeTypeOptions = this.chargeDropdownReadPlatformService final List<EnumOptionData> savingsChargeTimeTypeOptions = this.chargeDropdownReadPlatformService
.retrieveSavingsCollectionTimeTypes(); .retrieveSavingsCollectionTimeTypes();
final List<EnumOptionData> clientChargeCalculationTypeOptions = null;
final List<EnumOptionData> clientChargeTimeTypeOptions = null;
final List<EnumOptionData> feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions(); final List<EnumOptionData> feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions();
// TODO AA : revisit for merge conflict - Not sure method signature // TODO AA : revisit for merge conflict - Not sure method signature
return ChargeData.template(null, allowedChargeCalculationTypeOptions, null, allowedChargeTimeOptions, null, return ChargeData.template(null, allowedChargeCalculationTypeOptions, null, allowedChargeTimeOptions, null,
loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions,
savingsChargeTimeTypeOptions, feeFrequencyOptions); savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, feeFrequencyOptions);
} }
@Override @Override
@@ -227,8 +223,7 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou
@Override @Override
public Collection<SavingsAccountAnnualFeeData> retrieveChargesWithDue() { public Collection<SavingsAccountAnnualFeeData> retrieveChargesWithDue() {
final String sql = "select " final String sql = "select " + this.chargeDueMapper.schema()
+ this.chargeDueMapper.schema()
+ " where sac.charge_due_date is not null and sac.charge_due_date <= NOW() and sac.waived = 0 and sac.is_paid_derived=0 and sac.is_active=1 and sa.status_enum = " + " where sac.charge_due_date is not null and sac.charge_due_date <= NOW() and sac.waived = 0 and sac.is_paid_derived=0 and sac.is_active=1 and sa.status_enum = "
+ SavingsAccountStatusType.ACTIVE.getValue() + " order by sac.charge_due_date "; + SavingsAccountStatusType.ACTIVE.getValue() + " order by sac.charge_due_date ";
@@ -1,5 +1,6 @@
-- add permissions for Client Fees -- add permissions for Client Fees
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'READ_CLIENTCHARGE', 'CLIENTCHARGE', 'READ', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'CREATE_CLIENTCHARGE', 'CLIENTCHARGE', 'CREATE', 0); INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'CREATE_CLIENTCHARGE', 'CLIENTCHARGE', 'CREATE', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'DELETE_CLIENTCHARGE', 'CLIENTCHARGE', 'DELETE', 0); INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'DELETE_CLIENTCHARGE', 'CLIENTCHARGE', 'DELETE', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'WAIVE_CLIENTCHARGE', 'CLIENTCHARGE', 'WAIVE', 0); INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'WAIVE_CLIENTCHARGE', 'CLIENTCHARGE', 'WAIVE', 0);
@@ -7,3 +8,78 @@ INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `c
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'INACTIVATE_CLIENTCHARGE', 'CLIENTCHARGE', 'INACTIVATE', 0); INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'INACTIVATE_CLIENTCHARGE', 'CLIENTCHARGE', 'INACTIVATE', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UPDATE_CLIENTCHARGE', 'CLIENTCHARGE', 'UPDATE', 0); INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UPDATE_CLIENTCHARGE', 'CLIENTCHARGE', 'UPDATE', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'CREATE_CLIENTCHARGE_CHECKER', 'CLIENTCHARGE', 'CREATE_CHECKER', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'DELETE_CLIENTCHARGE_CHECKER', 'CLIENTCHARGE', 'DELETE_CHECKER', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'WAIVE_CLIENTCHARGE_CHECKER', 'CLIENTCHARGE', 'WAIVE_CHECKER', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'PAY_CLIENTCHARGE_CHECKER', 'CLIENTCHARGE', 'PAY_CHECKER', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'INACTIVATE_CLIENTCHARGE_CHECKER', 'CLIENTCHARGE', 'INACTIVATE_CHECKER', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UPDATE_CLIENTCHARGE_CHECKER', 'CLIENTCHARGE', 'UPDATE_CHECKER', 0);
-- new tables
CREATE TABLE `m_client_transaction` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`client_id` BIGINT(20) NOT NULL,
`office_id` BIGINT(20) NOT NULL,
`currency_code` VARCHAR(3) NOT NULL,
`payment_detail_id` BIGINT(20) NULL DEFAULT NULL,
`is_reversed` TINYINT(1) NOT NULL,
`external_id` VARCHAR(50) NULL DEFAULT NULL,
`transaction_date` DATE NOT NULL,
`transaction_type_enum` SMALLINT(5) NOT NULL,
`amount` DECIMAL(19,6) NOT NULL,
`created_date` DATETIME NOT NULL,
`appuser_id` BIGINT(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `external_id` (`external_id`),
INDEX `FK_m_client_transaction_m_client` (`client_id`),
INDEX `FK_m_client_transaction_m_appuser` (`appuser_id`),
CONSTRAINT `FK_m_client_transaction_m_appuser` FOREIGN KEY (`appuser_id`) REFERENCES `m_appuser` (`id`),
CONSTRAINT `FK_m_client_transaction_m_client` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
CREATE TABLE `m_client_charge` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`client_id` BIGINT(20) NOT NULL,
`charge_id` BIGINT(20) NOT NULL,
`is_penalty` TINYINT(1) NOT NULL,
`charge_time_enum` SMALLINT(5) NOT NULL,
`charge_due_date` DATE NULL DEFAULT NULL,
`charge_calculation_enum` SMALLINT(5) NOT NULL,
`amount` DECIMAL(19,6) NOT NULL,
`amount_paid_derived` DECIMAL(19,6) NULL DEFAULT NULL,
`amount_waived_derived` DECIMAL(19,6) NULL DEFAULT NULL,
`amount_writtenoff_derived` DECIMAL(19,6) NULL DEFAULT NULL,
`amount_outstanding_derived` DECIMAL(19,6) NOT NULL,
`is_paid_derived` TINYINT(1) NULL DEFAULT NULL,
`waived` TINYINT(1) NULL DEFAULT NULL,
`is_active` TINYINT(1) NULL DEFAULT NULL,
`inactivated_on_date` DATE NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `FK_m_client_charge_m_client` (`client_id`),
INDEX `FK_m_client_charge_m_charge` (`charge_id`),
CONSTRAINT `FK_m_client_charge_m_charge` FOREIGN KEY (`charge_id`) REFERENCES `m_charge` (`id`),
CONSTRAINT `FK_m_client_charge_m_client` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
CREATE TABLE `m_client_charge_paid_by` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`client_transaction_id` BIGINT(20) NOT NULL,
`client_charge_id` BIGINT(20) NOT NULL,
`amount` DECIMAL(19,6) NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_m_client_charge_paid_by_m_client_transaction` (`client_transaction_id`),
INDEX `FK_m_client_charge_paid_by_m_client_charge` (`client_charge_id`),
CONSTRAINT `FK_m_client_charge_paid_by_m_client_charge` FOREIGN KEY (`client_charge_id`) REFERENCES `m_client_charge` (`id`),
CONSTRAINT `FK_m_client_charge_paid_by_m_client_transaction` FOREIGN KEY (`client_transaction_id`) REFERENCES `m_client_transaction` (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;