From 340aa20120d08e33eb2f536c3a84aabb317896e6 Mon Sep 17 00:00:00 2001 From: Vishwas Babu A J Date: Thu, 20 Aug 2015 01:43:38 +0530 Subject: [PATCH] client fees : adding client transaction api's --- .../portfolio/charge/data/ChargeData.java | 41 ++++++---- .../portfolio/charge/domain/Charge.java | 56 +++++++++---- .../charge/domain/ChargeAppliesTo.java | 12 ++- .../charge/domain/ChargeCalculationType.java | 8 ++ .../charge/domain/ChargeTimeType.java | 24 ++++-- ...initionCommandFromApiJsonDeserializer.java | 22 ++++- .../ChargeDropdownReadPlatformService.java | 4 + ...ChargeDropdownReadPlatformServiceImpl.java | 10 +++ .../charge/service/ChargeEnumerations.java | 13 +-- .../service/ChargeReadPlatformService.java | 9 +- .../ChargeReadPlatformServiceImpl.java | 82 ++++++++++--------- .../client/api/ClientChargesApiResource.java | 9 +- .../client/data/ClientChargeData.java | 22 +++++ .../data/ClientChargeDataValidator.java | 2 - .../portfolio/client/domain/ClientCharge.java | 18 ++-- .../domain/ClientChargeRepositoryWrapper.java | 2 + .../ClientChargeReadPlatformServiceImpl.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 9 +- ...entTransactionReadPlatformServiceImpl.java | 2 + .../LoanChargeReadPlatformServiceImpl.java | 57 +++++++------ ...sAccountChargeReadPlatformServiceImpl.java | 23 ++---- .../migrations/core_db/V266__client_fees.sql | 76 +++++++++++++++++ 22 files changed, 357 insertions(+), 146 deletions(-) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/data/ChargeData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/data/ChargeData.java index fb9ff8d27..5776a2758 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/data/ChargeData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/data/ChargeData.java @@ -49,6 +49,8 @@ public class ChargeData implements Comparable, Serializable { private final List loanChargeTimeTypeOptions; private final List savingsChargeCalculationTypeOptions; private final List savingsChargeTimeTypeOptions; + private final List clientChargeCalculationTypeOptions; + private final List clientChargeTimeTypeOptions; private final List feeFrequencyOptions; public static ChargeData template(final Collection currencyOptions, @@ -56,12 +58,13 @@ public class ChargeData implements Comparable, Serializable { final List chargeTimeTypeOptions, final List chargePaymentModeOptions, final List loansChargeCalculationTypeOptions, final List loansChargeTimeTypeOptions, final List savingsChargeCalculationTypeOptions, final List savingsChargeTimeTypeOptions, + final List clientChargeCalculationTypeOptions, final List clientChargeTimeTypeOptions, final List feeFrequencyOptions) { return new ChargeData(null, null, null, null, null, null, null, null, false, false, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, chargePaymentModeOptions, loansChargeCalculationTypeOptions, - loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, null, null, null, null, - null, feeFrequencyOptions); + loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, + clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, null, null, null, null, null, feeFrequencyOptions); } public static ChargeData withTemplate(final ChargeData charge, final ChargeData template) { @@ -69,8 +72,9 @@ public class ChargeData implements Comparable, Serializable { charge.chargeCalculationType, charge.chargePaymentMode, charge.penalty, charge.active, template.currencyOptions, template.chargeCalculationTypeOptions, template.chargeAppliesToOptions, template.chargeTimeTypeOptions, template.chargePaymetModeOptions, template.loanChargeCalculationTypeOptions, template.loanChargeTimeTypeOptions, - template.savingsChargeCalculationTypeOptions, template.savingsChargeTimeTypeOptions, charge.feeOnMonthDay, - charge.feeInterval, charge.minCap, charge.maxCap, charge.feeFrequency, template.feeFrequencyOptions); + template.savingsChargeCalculationTypeOptions, template.savingsChargeTimeTypeOptions, + 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, @@ -88,12 +92,14 @@ public class ChargeData implements Comparable, Serializable { final List savingsChargeCalculationTypeOptions = null; final List savingsChargeTimeTypeOptions = null; final List feeFrequencyOptions = null; + final List clientChargeCalculationTypeOptions = null; + final List clientChargeTimeTypeOptions = null; return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode, penalty, active, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, - savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, - feeFrequency, feeFrequencyOptions); + savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, + clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions); } public static ChargeData lookup(final Long id, final String name, final boolean isPenalty) { @@ -118,14 +124,16 @@ public class ChargeData implements Comparable, Serializable { final List loansChargeTimeTypeOptions = null; final List savingsChargeCalculationTypeOptions = null; final List savingsChargeTimeTypeOptions = null; + final List clientChargeCalculationTypeOptions = null; + final List clientChargeTimeTypeOptions = null; final EnumOptionData feeFrequency = null; final List feeFrequencyOptions = null; return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode, penalty, active, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, - savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, - feeFrequency, feeFrequencyOptions); + savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, + clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions); } private ChargeData(final Long id, final String name, final BigDecimal amount, final CurrencyData currency, @@ -135,7 +143,8 @@ public class ChargeData implements Comparable, Serializable { final List chargeAppliesToOptions, final List chargeTimeTypeOptions, final List chargePaymentModeOptions, final List loansChargeCalculationTypeOptions, final List loansChargeTimeTypeOptions, final List savingsChargeCalculationTypeOptions, - final List savingsChargeTimeTypeOptions, final MonthDay feeOnMonthDay, final Integer feeInterval, + final List savingsChargeTimeTypeOptions, final List clientChargeCalculationTypeOptions, + final List clientChargeTimeTypeOptions, final MonthDay feeOnMonthDay, final Integer feeInterval, final BigDecimal minCap, final BigDecimal maxCap, final EnumOptionData feeFrequency, final List feeFrequencyOptions) { this.id = id; @@ -159,6 +168,8 @@ public class ChargeData implements Comparable, Serializable { this.chargePaymetModeOptions = chargePaymentModeOptions; this.savingsChargeCalculationTypeOptions = savingsChargeCalculationTypeOptions; this.savingsChargeTimeTypeOptions = savingsChargeTimeTypeOptions; + this.clientChargeCalculationTypeOptions = clientChargeCalculationTypeOptions; + this.clientChargeTimeTypeOptions = clientChargeTimeTypeOptions; this.loanChargeCalculationTypeOptions = loansChargeCalculationTypeOptions; this.loanChargeTimeTypeOptions = loansChargeTimeTypeOptions; this.feeFrequency = feeFrequency; @@ -210,18 +221,18 @@ public class ChargeData implements Comparable, Serializable { 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); + amountPaid, amountWaived, amountWrittenOff, amountOutstanding, this.chargeTimeType, dueAsOfDate, this.chargeCalculationType, + percentage, amountPercentageAppliedTo, chargeOptions, this.penalty, this.feeOnMonthDay, this.feeInterval, isActive, + inactivationDate); } public boolean isPenalty() { return this.penalty; } - - public boolean isOverdueInstallmentCharge(){ + + public boolean isOverdueInstallmentCharge() { boolean isOverdueInstallmentCharge = false; - if(this.chargeTimeType != null){ + if (this.chargeTimeType != null) { isOverdueInstallmentCharge = ChargeTimeType.fromInt(this.chargeTimeType.getId().intValue()).isOverdueInstallment(); } return isOverdueInstallmentCharge; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/Charge.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/Charge.java index f079079d6..d2311a746 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/Charge.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/Charge.java @@ -93,8 +93,8 @@ public class Charge extends AbstractPersistable { final ChargeAppliesTo chargeAppliesTo = ChargeAppliesTo.fromInt(command.integerValueOfParameterNamed("chargeAppliesTo")); final ChargeTimeType chargeTimeType = ChargeTimeType.fromInt(command.integerValueOfParameterNamed("chargeTimeType")); - final ChargeCalculationType chargeCalculationType = ChargeCalculationType.fromInt(command - .integerValueOfParameterNamed("chargeCalculationType")); + final ChargeCalculationType chargeCalculationType = ChargeCalculationType + .fromInt(command.integerValueOfParameterNamed("chargeCalculationType")); final Integer chargePaymentMode = command.integerValueOfParameterNamed("chargePaymentMode"); final ChargePaymentMode paymentMode = chargePaymentMode == null ? null : ChargePaymentMode.fromInt(chargePaymentMode); @@ -116,9 +116,9 @@ public class Charge extends AbstractPersistable { } 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 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) { this.name = name; this.amount = amount; this.currencyCode = currencyCode; @@ -140,12 +140,14 @@ public class Charge extends AbstractPersistable { this.feeFrequency = feeFrequency; if (isSavingsCharge()) { - + // TODO vishwas, this validation seems unnecessary as identical + // validation is performed in the write service if (!isAllowedSavingsChargeTime()) { baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTime) .failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.savings"); } - + // TODO vishwas, this validation seems unnecessary as identical + // validation is performed in the writeservice if (!isAllowedSavingsChargeCalculationType()) { baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation) .failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.savings"); @@ -161,6 +163,8 @@ public class Charge extends AbstractPersistable { if (penalty && chargeTime.isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException(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()) { baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTime) .failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.loan"); @@ -232,10 +236,18 @@ public class Charge extends AbstractPersistable { return ChargeTimeType.fromInt(this.chargeTime).isAllowedLoanChargeTime(); } + public boolean isAllowedClientChargeTime() { + return ChargeTimeType.fromInt(this.chargeTime).isAllowedClientChargeTime(); + } + public boolean isSavingsCharge() { return ChargeAppliesTo.fromInt(this.chargeAppliesTo).isSavingsCharge(); } + public boolean isClientCharge() { + return ChargeAppliesTo.fromInt(this.chargeAppliesTo).isClientCharge(); + } + public boolean isAllowedSavingsChargeTime() { return ChargeTimeType.fromInt(this.chargeTime).isAllowedSavingsChargeTime(); } @@ -244,6 +256,10 @@ public class Charge extends AbstractPersistable { return ChargeCalculationType.fromInt(this.chargeCalculation).isAllowedSavingsChargeCalculationType(); } + public boolean isAllowedClientChargeCalculationType() { + return ChargeCalculationType.fromInt(this.chargeCalculation).isAllowedClientChargeCalculationType(); + } + public boolean isPercentageOfAmount() { return ChargeCalculationType.fromInt(this.chargeCalculation).isPercentageOfAmount(); } @@ -313,6 +329,11 @@ public class Charge extends AbstractPersistable { baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTime) .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 { baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation) .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 { actualChanges.put("locale", localeAsInput); this.feeInterval = newValue; } - + final String feeFrequency = "feeFrequency"; if (command.isChangeInIntegerParameterNamed(feeFrequency, this.feeFrequency)) { final Integer newValue = command.integerValueOfParameterNamed(feeFrequency); @@ -395,8 +421,8 @@ public class Charge extends AbstractPersistable { actualChanges.put("locale", localeAsInput); this.feeFrequency = newValue; } - - if(this.feeFrequency != null){ + + if (this.feeFrequency != null) { baseDataValidator.reset().parameter("feeInterval").value(this.feeInterval).notNull(); } @@ -431,8 +457,8 @@ public class Charge extends AbstractPersistable { } } - if (this.penalty && ChargeTimeType.fromInt(this.chargeTime).isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException( - this.name); } + if (this.penalty && ChargeTimeType.fromInt(this.chargeTime) + .isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException(this.name); } if (!penalty && ChargeTimeType.fromInt(this.chargeTime).isOverdueInstallment()) { throw new ChargeMustBePenaltyException(name); } if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } @@ -467,9 +493,9 @@ public class Charge extends AbstractPersistable { public Integer getChargePaymentMode() { return this.chargePaymentMode; } - - public Integer getFeeInterval(){ - return this.feeInterval; + + public Integer getFeeInterval() { + return this.feeInterval; } public boolean isMonthlyFee() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeAppliesTo.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeAppliesTo.java index ec243dd7e..fc8bead16 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeAppliesTo.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeAppliesTo.java @@ -9,7 +9,8 @@ public enum ChargeAppliesTo { INVALID(0, "chargeAppliesTo.invalid"), // LOAN(1, "chargeAppliesTo.loan"), // - SAVINGS(2, "chargeAppliesTo.savings"); + SAVINGS(2, "chargeAppliesTo.savings"), // + CLIENT(3, "chargeAppliesTo.client"); private final Integer value; private final String code; @@ -38,6 +39,9 @@ public enum ChargeAppliesTo { case 2: chargeAppliesToType = SAVINGS; break; + case 3: + chargeAppliesToType = CLIENT; + break; default: chargeAppliesToType = INVALID; break; @@ -55,7 +59,11 @@ public enum ChargeAppliesTo { return this.value.equals(ChargeAppliesTo.SAVINGS.getValue()); } + public boolean isClientCharge() { + return this.value.equals(ChargeAppliesTo.CLIENT.getValue()); + } + 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() }; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeCalculationType.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeCalculationType.java index 525d110f3..f5b619fe1 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeCalculationType.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeCalculationType.java @@ -38,6 +38,10 @@ public enum ChargeCalculationType { 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) { ChargeCalculationType chargeCalculationType = ChargeCalculationType.INVALID; switch (chargeCalculation) { @@ -77,6 +81,10 @@ public enum ChargeCalculationType { return isFlat() || isPercentageOfAmount(); } + public boolean isAllowedClientChargeCalculationType() { + return isFlat(); + } + public boolean isPercentageBased() { return isPercentageOfAmount() || isPercentageOfAmountAndInterest() || isPercentageOfInterest(); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeTimeType.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeTimeType.java index d0fefd749..8e24cea61 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeTimeType.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeTimeType.java @@ -20,7 +20,7 @@ public enum ChargeTimeType { INSTALMENT_FEE(8, "chargeTimeType.instalmentFee"), // only for loan charges OVERDUE_INSTALLMENT(9, "chargeTimeType.overdueInstallment"), // only for // 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 private final Integer value; @@ -43,10 +43,10 @@ public enum ChargeTimeType { return new Integer[] { ChargeTimeType.DISBURSEMENT.getValue(), ChargeTimeType.SPECIFIED_DUE_DATE.getValue(), ChargeTimeType.INSTALMENT_FEE.getValue(), ChargeTimeType.OVERDUE_INSTALLMENT.getValue() }; } - + public static Object[] validLoanChargeValues() { return new Integer[] { ChargeTimeType.DISBURSEMENT.getValue(), ChargeTimeType.SPECIFIED_DUE_DATE.getValue(), - ChargeTimeType.INSTALMENT_FEE.getValue()}; + ChargeTimeType.INSTALMENT_FEE.getValue() }; } public static Object[] validSavingsValues() { @@ -55,6 +55,10 @@ public enum ChargeTimeType { 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) { ChargeTimeType chargeTimeType = ChargeTimeType.INVALID; if (chargeTime != null) { @@ -127,11 +131,11 @@ public enum ChargeTimeType { public boolean isMonthlyFee() { return this.value.equals(ChargeTimeType.MONTHLY_FEE.getValue()); } - + public boolean isWeeklyFee() { - return this.value.equals(ChargeTimeType.WEEKLY_FEE.getValue()); + return this.value.equals(ChargeTimeType.WEEKLY_FEE.getValue()); } - + public boolean isInstalmentFee() { return this.value.equals(ChargeTimeType.INSTALMENT_FEE.getValue()); } @@ -144,9 +148,13 @@ public enum ChargeTimeType { return isTimeOfDisbursement() || isOnSpecifiedDueDate() || isInstalmentFee() || isOverdueInstallment(); } + public boolean isAllowedClientChargeTime() { + return isOnSpecifiedDueDate(); + } + public boolean isAllowedSavingsChargeTime() { - return isOnSpecifiedDueDate() || isSavingsActivation() || isSavingsClosure() || isWithdrawalFee() || isAnnualFee() - || isMonthlyFee() || isWeeklyFee() || isOverdraftFee(); + return isOnSpecifiedDueDate() || isSavingsActivation() || isSavingsClosure() || isWithdrawalFee() || isAnnualFee() || isMonthlyFee() + || isWeeklyFee() || isOverdraftFee(); } public boolean isOverdraftFee() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java index 324602ae8..efdd90b99 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java @@ -116,8 +116,8 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer { if (ctt.isWeeklyFee()) { final String monthDay = this.fromApiJsonHelper.extractStringNamed("feeOnMonthDay", element); - baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay) - .mustBeBlankWhenParameterProvidedIs("chargeTimeType", chargeTimeType); + baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).mustBeBlankWhenParameterProvidedIs("chargeTimeType", + chargeTimeType); } if (ctt.isMonthlyFee()) { @@ -132,6 +132,22 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer { 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) { baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType) .isOneOfTheseValues(ChargeCalculationType.validValuesForSavings()); @@ -217,9 +233,11 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer { final Collection validLoanValues = Arrays.asList(ChargeTimeType.validLoanValues()); final Collection validSavingsValues = Arrays.asList(ChargeTimeType.validSavingsValues()); + final Collection validClientValues = Arrays.asList(ChargeTimeType.validClientValues()); final Collection allValidValues = new ArrayList<>(validLoanValues); allValidValues.addAll(validSavingsValues); + allValidValues.addAll(validClientValues); baseDataValidator.reset().parameter("chargeTimeType").value(chargeTimeType).notNull() .isOneOfTheseValues(allValidValues.toArray(new Object[allValidValues.size()])); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeDropdownReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeDropdownReadPlatformService.java index aa9a76cfc..de6370fd0 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeDropdownReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeDropdownReadPlatformService.java @@ -27,4 +27,8 @@ public interface ChargeDropdownReadPlatformService { List retrieveSavingsCollectionTimeTypes(); + List retrieveClientCalculationTypes(); + + List retrieveClientCollectionTimeTypes(); + } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeDropdownReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeDropdownReadPlatformServiceImpl.java index 907000762..1ee92d0f7 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeDropdownReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeDropdownReadPlatformServiceImpl.java @@ -87,4 +87,14 @@ public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownRead chargeTimeType(ChargeTimeType.MONTHLY_FEE), chargeTimeType(ChargeTimeType.WEEKLY_FEE), chargeTimeType(ChargeTimeType.OVERDRAFT_FEE)); } + + @Override + public List retrieveClientCalculationTypes() { + return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT)); + } + + @Override + public List retrieveClientCollectionTimeTypes() { + return Arrays.asList(chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE)); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeEnumerations.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeEnumerations.java index e589e810d..6ed44fc4d 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeEnumerations.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeEnumerations.java @@ -49,9 +49,9 @@ public class ChargeEnumerations { "Monthly Fee"); break; case WEEKLY_FEE: - optionData = new EnumOptionData(ChargeTimeType.WEEKLY_FEE.getValue().longValue(), ChargeTimeType.WEEKLY_FEE.getCode(), - "Weekly Fee"); - break; + optionData = new EnumOptionData(ChargeTimeType.WEEKLY_FEE.getValue().longValue(), ChargeTimeType.WEEKLY_FEE.getCode(), + "Weekly Fee"); + break; case INSTALMENT_FEE: optionData = new EnumOptionData(ChargeTimeType.INSTALMENT_FEE.getValue().longValue(), ChargeTimeType.INSTALMENT_FEE.getCode(), "Installment Fee"); @@ -61,8 +61,8 @@ public class ChargeEnumerations { ChargeTimeType.OVERDUE_INSTALLMENT.getCode(), "Overdue Fees"); break; case OVERDRAFT_FEE: - optionData = new EnumOptionData(ChargeTimeType.OVERDRAFT_FEE.getValue().longValue(), - ChargeTimeType.OVERDRAFT_FEE.getCode(), "Overdraft Fee"); + optionData = new EnumOptionData(ChargeTimeType.OVERDRAFT_FEE.getValue().longValue(), ChargeTimeType.OVERDRAFT_FEE.getCode(), + "Overdraft Fee"); break; default: 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(), "Savings"); break; + case CLIENT: + optionData = new EnumOptionData(ChargeAppliesTo.CLIENT.getValue().longValue(), ChargeAppliesTo.CLIENT.getCode(), "Client"); + break; default: optionData = new EnumOptionData(ChargeAppliesTo.INVALID.getValue().longValue(), ChargeAppliesTo.INVALID.getCode(), "Invalid"); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformService.java index 6247d750c..9b002c94c 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformService.java @@ -20,6 +20,13 @@ public interface ChargeReadPlatformService { ChargeData retrieveNewChargeDetails(); + /** + * Returns all charges that can be applied to Cients + * + * @return + */ + Collection retrieveAllChargesApplicableToClients(); + /** * Returns all Fees (excluding penalties) applicable for loans * @@ -93,7 +100,7 @@ public interface ChargeReadPlatformService { * @return */ Collection retrieveSavingsProductCharges(Long savingsProductId); - + /** Retrieve savings account charges **/ Collection retrieveSavingsAccountApplicableCharges(Long savingsId); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformServiceImpl.java index ada5b668d..0d4a9245a 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformServiceImpl.java @@ -45,12 +45,11 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService private final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService; private final DropdownReadPlatformService dropdownReadPlatformService; private final MifosEntityAccessUtil mifosEntityAccessUtil; - + @Autowired public ChargeReadPlatformServiceImpl(final CurrencyReadPlatformService currencyReadPlatformService, final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService, final RoutingDataSource dataSource, - final DropdownReadPlatformService dropdownReadPlatformService, - final MifosEntityAccessUtil mifosEntityAccessUtil) { + final DropdownReadPlatformService dropdownReadPlatformService, final MifosEntityAccessUtil mifosEntityAccessUtil) { this.chargeDropdownReadPlatformService = chargeDropdownReadPlatformService; this.jdbcTemplate = new JdbcTemplate(dataSource); this.currencyReadPlatformService = currencyReadPlatformService; @@ -64,10 +63,10 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService final ChargeMapper rm = new ChargeMapper(); String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 "; - + sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled(); - - sql += " order by c.name "; + + sql += " order by c.name "; return this.jdbcTemplate.query(sql, rm, new Object[] {}); } @@ -76,12 +75,11 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService public Collection retrieveAllChargesForCurrency(String currencyCode) { 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 += " order by c.name "; + + sql += " order by c.name "; return this.jdbcTemplate.query(sql, rm, new Object[] {}); } @@ -92,9 +90,9 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService final ChargeMapper rm = new ChargeMapper(); String sql = "select " + rm.chargeSchema() + " where c.id = ? and c.is_deleted=0 "; - + sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled(); - + return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { chargeId }); } catch (final EmptyResultDataAccessException e) { throw new ChargeNotFoundException(chargeId); @@ -116,11 +114,15 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService .retrieveSavingsCalculationTypes(); final List savingsChargeTimeTypeOptions = this.chargeDropdownReadPlatformService .retrieveSavingsCollectionTimeTypes(); + final List clientChargeCalculationTypeOptions = this.chargeDropdownReadPlatformService + .retrieveClientCalculationTypes(); + final List clientChargeTimeTypeOptions = this.chargeDropdownReadPlatformService.retrieveClientCollectionTimeTypes(); final List feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions(); return ChargeData.template(currencyOptions, allowedChargeCalculationTypeOptions, allowedChargeAppliesToOptions, allowedChargeTimeOptions, chargePaymentOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, - savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, feeFrequencyOptions); + savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, + clientChargeTimeTypeOptions, feeFrequencyOptions); } @Override @@ -128,7 +130,7 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService 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=? "; - + sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled(); 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 + " "; sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled(); sql += " order by c.name "; - return this.jdbcTemplate.query(sql, rm, params); } @@ -219,20 +220,19 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService sql += " order by c.name "; return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.LOAN.getValue() }); } - - private String addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled () { - - String sql = ""; - - // Check if branch specific products are enabled. If yes, fetch only charges mapped to current user's office - String inClause = mifosEntityAccessUtil. - getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled( - MifosEntityType.CHARGE); - if ( (inClause != null) && (!(inClause.trim().isEmpty())) ) { - sql += " and c.id in ( " + inClause + " ) "; - } - - return sql; + + private String addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled() { + + String sql = ""; + + // Check if branch specific products are enabled. If yes, fetch only + // charges mapped to current user's office + String inClause = mifosEntityAccessUtil.getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(MifosEntityType.CHARGE); + if ((inClause != null) && (!(inClause.trim().isEmpty()))) { + sql += " and c.id in ( " + inClause + " ) "; + } + + return sql; } private static final class ChargeMapper implements RowMapper { @@ -312,8 +312,7 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService public Collection retrieveSavingsProductApplicableCharges(final boolean feeChargesOnly) { 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=? "; + String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=? "; if (feeChargesOnly) { 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=? "; @@ -339,13 +338,12 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService public Collection retrieveSavingsProductCharges(final Long savingsProductId) { final ChargeMapper rm = new ChargeMapper(); - String sql = "select " + rm.savingsProductChargeSchema() - + " where c.is_deleted=0 and c.is_active=1 and spc.savings_product_id=? "; + String sql = "select " + rm.savingsProductChargeSchema() + " where c.is_deleted=0 and c.is_active=1 and spc.savings_product_id=? "; sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled(); return this.jdbcTemplate.query(sql, rm, new Object[] { savingsProductId }); } - + @Override public Collection 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" + " where c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=? " + " and sa.account_no = ?"; sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled(); - + return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.SAVINGS.getValue(), savingsAccountId }); - } + } + + @Override + public Collection 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() }); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientChargesApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientChargesApiResource.java index a2f9c5bde..9c3b98bee 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientChargesApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientChargesApiResource.java @@ -25,6 +25,7 @@ import org.mifosplatform.infrastructure.core.exception.UnrecognizedQueryParamExc import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer; 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.client.data.ClientChargeData; import org.mifosplatform.portfolio.client.service.ClientChargeReadPlatformService; @@ -82,11 +83,15 @@ public class ClientChargesApiResource { @Path("template") @Consumes({ 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); - return null; + final Collection 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); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientChargeData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientChargeData.java index 5c72333b3..b77f19180 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientChargeData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientChargeData.java @@ -54,6 +54,28 @@ public class ClientChargeData { amountPaid, amountWaived, amountWrittenOff, amountOutstanding, penalty, isActive, inactivationDate, chargeOptions); } + public static ClientChargeData template(final Collection 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, EnumOptionData chargeCalculationType, CurrencyData currency, BigDecimal amount, BigDecimal amountPaid, BigDecimal amountWaived, BigDecimal amountWrittenOff, BigDecimal amountOutstanding, boolean penalty, Boolean isActive, LocalDate inactivationDate, diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientChargeDataValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientChargeDataValidator.java index 55c8daea8..53b71f95f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientChargeDataValidator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientChargeDataValidator.java @@ -42,8 +42,6 @@ public class ClientChargeDataValidator { .resource(ClientApiConstants.CLIENT_CHARGES_RESOURCE_NAME); 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); baseDataValidator.reset().parameter(ClientApiConstants.amountParamName).value(amount).notNull().positiveAmount(); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientCharge.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientCharge.java index d8cd52479..80a8f900f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientCharge.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientCharge.java @@ -1,12 +1,7 @@ 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.util.ArrayList; import java.util.Date; -import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; @@ -15,14 +10,10 @@ import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; +import javax.persistence.Transient; import org.joda.time.LocalDate; -import org.joda.time.format.DateTimeFormatter; 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.Money; 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.ChargeTimeType; 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; @Entity @@ -87,7 +76,12 @@ public class ClientCharge extends AbstractPersistable { @Column(name = "inactivated_on_date") private Date inactivationDate; + @Transient private OrganisationCurrency currency; + + protected ClientCharge() { + // + } public static ClientCharge createNew(final Client client, final Charge charge, final JsonCommand command) { BigDecimal amount = command.bigDecimalValueOfParameterNamed(ClientApiConstants.amountParamName); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientChargeRepositoryWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientChargeRepositoryWrapper.java index 78441088a..c67dede9d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientChargeRepositoryWrapper.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/ClientChargeRepositoryWrapper.java @@ -3,7 +3,9 @@ package org.mifosplatform.portfolio.client.domain; import org.mifosplatform.organisation.office.domain.OrganisationCurrencyRepositoryWrapper; import org.mifosplatform.portfolio.charge.exception.ChargeNotFoundException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; +@Repository public class ClientChargeRepositoryWrapper { private final ClientChargeRepository repository; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientChargeReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientChargeReadPlatformServiceImpl.java index 1bd8be483..b77c74e41 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientChargeReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientChargeReadPlatformServiceImpl.java @@ -118,7 +118,7 @@ public class ClientChargeReadPlatformServiceImpl implements ClientChargeReadPlat 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 }); } catch (final EmptyResultDataAccessException e) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientChargeWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientChargeWritePlatformServiceJpaRepositoryImpl.java index 211d0991b..61b2d2e31 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientChargeWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientChargeWritePlatformServiceJpaRepositoryImpl.java @@ -24,6 +24,7 @@ import org.mifosplatform.organisation.monetary.domain.Money; import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWrapper; import org.mifosplatform.portfolio.charge.domain.Charge; 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.data.ClientChargeDataValidator; import org.mifosplatform.portfolio.client.domain.Client; @@ -82,6 +83,12 @@ public class ClientChargeWritePlatformServiceJpaRepositoryImpl implements Client final Long chargeDefinitionId = command.longValueOfParameterNamed(ClientApiConstants.chargeIdParamName); 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 DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()); @@ -98,7 +105,7 @@ public class ClientChargeWritePlatformServiceJpaRepositoryImpl implements Client @Override 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); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientTransactionReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientTransactionReadPlatformServiceImpl.java index a905e77fc..399733b10 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientTransactionReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientTransactionReadPlatformServiceImpl.java @@ -18,7 +18,9 @@ import org.mifosplatform.portfolio.paymenttype.data.PaymentTypeData; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Service; +@Service public class ClientTransactionReadPlatformServiceImpl implements ClientTransactionReadPlatformService { private final JdbcTemplate jdbcTemplate; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java index f176dd5d5..dee038e86 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java @@ -54,22 +54,14 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform private static final class LoanChargeMapper implements RowMapper { public String schema() { - 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_waived_derived as amountWaived, " - + "lc.amount_writtenoff_derived as amountWrittenOff, " + 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_waived_derived as amountWaived, " + "lc.amount_writtenoff_derived as amountWrittenOff, " + "lc.amount_outstanding_derived as amountOutstanding, " + "lc.calculation_percentage as percentageOf, lc.calculation_on_amount as amountPercentageAppliedTo, " - + "lc.charge_time_enum as chargeTime, " - + "lc.is_penalty as penalty, " - + "lc.due_for_collection_as_of_date as dueAsOfDate, " - + "lc.charge_calculation_enum as chargeCalculation, " - + "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, " + + "lc.charge_time_enum as chargeTime, " + "lc.is_penalty as penalty, " + + "lc.due_for_collection_as_of_date as dueAsOfDate, " + "lc.charge_calculation_enum as chargeCalculation, " + + "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, " + "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 " @@ -119,8 +111,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform final BigDecimal amountOrPercentage = rs.getBigDecimal("amountOrPercentage"); return new LoanChargeData(id, chargeId, name, currency, amount, amountPaid, amountWaived, amountWrittenOff, amountOutstanding, - chargeTimeType, dueAsOfDate, chargeCalculationType, percentageOf, amountPercentageAppliedTo, penalty, paymentMode, - paid, waived, null, minCap, maxCap, amountOrPercentage, null); + chargeTimeType, dueAsOfDate, chargeCalculationType, percentageOf, amountPercentageAppliedTo, penalty, paymentMode, paid, + waived, null, minCap, maxCap, amountOrPercentage, null); } } @@ -137,11 +129,14 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform .retrieveSavingsCalculationTypes(); final List savingsChargeTimeTypeOptions = this.chargeDropdownReadPlatformService .retrieveSavingsCollectionTimeTypes(); + final List clientChargeCalculationTypeOptions = null; + final List clientChargeTimeTypeOptions = null; + final List feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions(); return ChargeData.template(null, allowedChargeCalculationTypeOptions, null, allowedChargeTimeOptions, null, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions, - savingsChargeTimeTypeOptions, feeFrequencyOptions); + savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, feeFrequencyOptions); } @Override @@ -170,8 +165,7 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform @Override public Collection retrieveLoanChargesForFeePayment(final Integer paymentMode, final Integer loanStatus) { final LoanChargeMapperWithLoanId rm = new LoanChargeMapperWithLoanId(); - final String sql = "select " - + rm.schema() + final String sql = "select " + 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"; 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 { public String schema() { - return "lc.id as id, lc.due_for_collection_as_of_date as dueAsOfDate, " - + "lc.amount_outstanding_derived as amountOutstanding, " + "lc.charge_time_enum as chargeTime, " + "loan.id as loanId " - + "from m_loan_charge lc " + "join m_loan loan on loan.id = lc.loan_id "; + return "lc.id as id, lc.due_for_collection_as_of_date as dueAsOfDate, " + "lc.amount_outstanding_derived as amountOutstanding, " + + "lc.charge_time_enum as chargeTime, " + "loan.id as loanId " + "from m_loan_charge lc " + + "join m_loan loan on loan.id = lc.loan_id "; } @Override @@ -265,8 +259,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform charges.removeAll(removeCharges); for (LoanChargeData loanChargeData : removeCharges) { if (loanChargeData.isInstallmentFee()) { - Collection installmentChargeDatas = retrieveInstallmentLoanChargesForAccrual(loanChargeData - .getId()); + Collection installmentChargeDatas = retrieveInstallmentLoanChargesForAccrual( + loanChargeData.getId()); LoanChargeData modifiedChargeData = new LoanChargeData(loanChargeData, installmentChargeDatas); charges.add(modifiedChargeData); } @@ -292,7 +286,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform sb.append("left join ("); sb.append("select lcp.loan_charge_id, lcp.amount"); 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 "); schemaSql = sb.toString(); @@ -321,7 +316,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform } } - private Collection updateLoanChargesWithUnrecognizedIncome(final Long loanId, Collection loanChargeDatas) { + private Collection updateLoanChargesWithUnrecognizedIncome(final Long loanId, + Collection loanChargeDatas) { final LoanChargeUnRecognizedIncomeMapper rm = new LoanChargeUnRecognizedIncomeMapper(loanChargeDatas); @@ -350,7 +346,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform sb.append("left join ("); sb.append("select cpb.loan_charge_id, lt.unrecognized_income_portion"); 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 "); schemaSql = sb.toString(); @@ -406,7 +403,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform sb.append("left join ("); 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("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 "); schemaSql = sb.toString(); } @@ -449,7 +447,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform sb.append(" cpb.installment_number as installmentNumber, "); sb.append(" sum(lt.unrecognized_income_portion) as amountUnrecognized "); 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(); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountChargeReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountChargeReadPlatformServiceImpl.java index 0d6d880bc..5e27b508c 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountChargeReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountChargeReadPlatformServiceImpl.java @@ -58,18 +58,12 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou private static final class SavingsAccountChargeMapper implements RowMapper { public String schema() { - 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_paid_derived as amountPaid, " - + "sc.amount_waived_derived as amountWaived, " - + "sc.amount_writtenoff_derived as amountWrittenOff, " - + "sc.amount_outstanding_derived as amountOutstanding, " + 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_paid_derived as amountPaid, " + "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.charge_time_enum as chargeTime, " - + "sc.is_penalty as penalty, " - + "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_time_enum as chargeTime, " + "sc.is_penalty as penalty, " + "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.is_active as isActive, sc.inactivated_on_date as inactivationDate, " + "c.currency_code as currencyCode, oc.name as currencyName, " @@ -144,13 +138,15 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou .retrieveSavingsCalculationTypes(); final List savingsChargeTimeTypeOptions = this.chargeDropdownReadPlatformService .retrieveSavingsCollectionTimeTypes(); + final List clientChargeCalculationTypeOptions = null; + final List clientChargeTimeTypeOptions = null; final List feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions(); // TODO AA : revisit for merge conflict - Not sure method signature return ChargeData.template(null, allowedChargeCalculationTypeOptions, null, allowedChargeTimeOptions, null, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions, - savingsChargeTimeTypeOptions, feeFrequencyOptions); + savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, feeFrequencyOptions); } @Override @@ -227,8 +223,7 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou @Override public Collection retrieveChargesWithDue() { - final String sql = "select " - + this.chargeDueMapper.schema() + final String sql = "select " + 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 = " + SavingsAccountStatusType.ACTIVE.getValue() + " order by sac.charge_due_date "; diff --git a/mifosng-provider/src/main/resources/sql/migrations/core_db/V266__client_fees.sql b/mifosng-provider/src/main/resources/sql/migrations/core_db/V266__client_fees.sql index 1eef3622c..5fa72546b 100644 --- a/mifosng-provider/src/main/resources/sql/migrations/core_db/V266__client_fees.sql +++ b/mifosng-provider/src/main/resources/sql/migrations/core_db/V266__client_fees.sql @@ -1,5 +1,6 @@ -- 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', '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); @@ -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', '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 +; +