diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index 27a3e0400..43fddb5f1 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -1506,6 +1506,10 @@ loans/{loanId}/transactions/template Retrieve Loan Transaction Template + + charges/template + Retrieve Charge Template + offices/template Retrieve Office Template @@ -10980,388 +10984,413 @@ Request Body: -   -
-
-

Charges

-

- Its typical for MFIs to add extra costs for their financial - products. There are typically Fees or Penalties. -

-

Charges is what we use to model both fees and penalties. - For now charges can only be associated with loan products / loans.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +  +
+
+

Charges

+

+ Its typical for MFIs to add extra costs for their financial + products. These are typically Fees or Penalties. +

+

A Charge on mifos platform is what we use to model both Fees and Penalties.

+

At present we support defining charges for use in both loan and saving products.

+
Field Descriptions
name
Name associated with this charge.
active
Boolean flag determines if the Charge is currently active.
penalty
Boolean flag determines if the Charge is a penalty.
currency
Details of the currency associated with this charge. - Refer Charges Template for additional details
amount
Field holds the details of the actual amount to be collected - in the case of "Flat Charges" or the percentage amount to be collected in - case of "Percentage Amount Charges". Refer Charges Template - for details of the Available Charge Types
chargeTimeType
The time at which the charge becomes Due. - Refer Charges Template for additional details
- 1 = Disbursement : Applicable for loans and deducted at the time of loan disbursement.
- 2 = Specified Due Date : Adhoc charge can be applied for loans and savings on a specified due date.
- 3 = Savings Activation : This charge is applicable for savings account and charged at the time of account activation. This charge will be autodeducted once the account is activated with sufficient opening balance.
- 5 = Withdrawal fee : Charge applied to every withdrawal of savings account.
- 6 = Annual Fee : Recurring charge applied annually for savings on a specified Month and day.
- 7 = Monthly Fee : Recurring charge applied on regular interval of months for savings. -
chargeAppliesTo
The Entity for which the charge can be applied (Loans, Savings etc). - Refer Charges Template for additional details
chargeCalculationType
Rules for calculating the amount for a particular Charge. - Refer Charges Template for additional details
feeOnMonthDay
Used along with monthDayFormat to indicate the recurring charge due date starting on a given day of the month and follow specified feeInterval. e.g. fee due date starting on 10 May with feeInterval of two (2) months then a recurring fee on 10th of every two months is applied to savings account. monthDayFormat indicates day and month formatting used e.g. "dd MMM" for 10 May
- This field is mandatory if chargeTimeType is of type Monthly Fee -
feeInterval
Fee to be applied on a specified interval (number of months).
- This field is mandatory if chargeTimeType is of type Monthly Fee -
minCap
minimum cap: a 2% fee with a minimum cap of 500
- In case of a 5000 loan, the 2% is 100, and therefore automatically 500 is used as the value of the charge.
- This field is optional and can be used along when ChargeCalculationType equals (2) PERCENT_OF_AMOUNT -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field Descriptions
name
Name associated with this charge.
chargeAppliesTo
Enumeration for indicating whether charge is to be applicable for loans or savings.
+ 1=Loans, + 2=Savings +

Once a charge definiton has been created, this attribute cannot be changed at any point.

+
active
Boolean flag determines if the charge is currently active.
penalty
Boolean flag determines if the charge is a penalty. If false the charge is considered a Fee
currencyCode
A three letter ISO code of currency.
chargeCalculationType
Enumeration for indicating whether charge amount is flat or percentage based:
+ 1=Flat, + 2=% of Amount +

Used in combination with amount parameter e.g 1 % of Amount or 3.50 Flat

+

For loans, % of Amount refers to the loan principal disbursed.

+

For savings, % of Amount can be used with 'withrawal fees' and refers to the amount withdrawn.

+
amount
The charge amount. Used in combination with chargeCalculationType parameter. e.g 1 % of Amount or 3.50 Flat
minCap
Optional: Can be used when a '% of Amount' value is used for chargeCalculationType. +

Used to enforce a minimum charge amount in cases where the calculated amount is less than the minimum amount provided.

+

e.g. A 2% fee with a minimum cap of 500:
+ In case of a 5000 loan, the 2% is 100, and therefore automatically 500 is used as the value of the charge. +

+
maxCap
Optional: Can be used when a '% of Amount' value is used for chargeCalculationType. +

Used to enforce a maximum charge amount in cases where the calculated amount is greater than the maximum amount provided.

+

e.g. A 2% fee, with a maximum of 2000.:
+ In case of a 150000 loan, the 2% adds up to 3000 charge, and therefore the maximum cap of 2000 will be used. +

+
chargeTimeType
An enumeration indicating the time at which the charge becomes due:
+

+ 1 = Disbursement : Applicable for loans and deducted at the time of loan disbursement.
+ 2 = Specified Due Date : Adhoc charge can be applied for loans and savings on a specified due date.
+ 3 = Savings Activation : This charge is applicable for savings account and charged at the time of account activation. This charge will be autodeducted once the account is activated with sufficient opening balance.
+ 5 = Withdrawal fee : Charge applied to every withdrawal of savings account.
+ 6 = Annual Fee : Recurring charge applied annually for savings on a specified Month and day. see feeOnMonthDay
+ 7 = Monthly Fee : Recurring charge applied on regular interval of months for savings. see feeOnMonthDay and feeInterval +

+
chargePaymentMode
Applicable to loan charges only: Enumeration for indicating whether charge is to be paid through an Account Transfer from savings or through Regular payment mode.
+ 0=Regular, + 1=Account Transfer +
feeOnMonthDay
Used along with monthDayFormat to indicate the recurring charge due date starting on a given day of the month and follow specified feeInterval. e.g. fee due date starting on 10 May with feeInterval of two (2) months then a recurring fee on 10th of every two months is applied to savings account. monthDayFormat indicates day and month formatting used e.g. "dd MMM" for 10 May
+ This field is mandatory if chargeTimeType is of type Monthly Fee +
feeInterval
Fee to be applied on a specified interval (number of months).
+ This field is mandatory if chargeTimeType is of type Monthly Fee +
+
+
- - - maxCap - - - maximum cap: A 2% fee, with a maximum of 2000.
- In case of a 150000 loan, the 2% adds up to 3000 charge, and therefore the maximum cap of 2000 will be used.
- This field is optional and can be used along when ChargeCalculationType equals (2) PERCENT_OF_AMOUNT - - - - - - -   -
-
-

Retrieve Charges Details Template

-

This is a convenience resource. It can be useful when - building maintenance user interface screens for client - applications. The template data returned consists of any or all - of: -

-

-

Example Request:

-
charges/template
-
-
- +   +
+
+

Retrieve Charge Template

+

This is a convenience resource. It can be useful when + building maintenance user interface screens for client + applications. The template data returned consists of any or all + of: +

    +
  • Field Defaults
  • +
  • Allowed Value Lists
  • +
+

+

Example Request:

+
charges/template
+
+
+ GET https://DomainName/api/v1/charges/template - - + + { - "active": false, - "penalty": false, - "currencyOptions": - [ - { - "code": "USD", - "name": "US Dollar", - "decimalPlaces": 2, - "displaySymbol": "$", - "nameCode": "currency.USD", - "displayLabel": "US Dollar ($)" - } - ], - "chargeCalculationTypeOptions": - [ - { - "id": 1, - "code": "chargeCalculationType.flat", - "value": "Flat" - }, - { - "id": 2, - "code": "chargeCalculationType.percent.of.amount", - "value": "% Amount" - } - ], - "chargeAppliesToOptions": - [ - { - "id": 1, - "code": "chargeAppliesTo.loan", - "value": "Loan" - }, - { - "id": 2, - "code": "chargeAppliesTo.savings", - "value": "Savings" - } - ], - "chargeTimeTypeOptions": - [ - { - "id": 1, - "code": "chargeTimeType.disbursement", - "value": "Disbursement" - }, - { - "id": 2, - "code": "chargeTimeType.specifiedDueDate", - "value": "Specified due date" - }, - { - "id": 3, - "code": "chargeTimeType.savingsActivation", - "value": "Savings Activation" - }, - { - "id": 5, - "code": "chargeTimeType.withdrawalFee", - "value": "Withdrawal Fee" - }, - { - "id": 6, - "code": "chargeTimeType.annualFee", - "value": "Annual Fee" - }, - { - "id": 7, - "code": "chargeTimeType.monthlyFee", - "value": "Monthly Fee" - } - ], - "chargePaymetModeOptions": - [ - { - "id":0, - "code":"chargepaymentmode.regular", - "value":"chargepaymentmode.regular" - }, - { - "id":1, - "code":"chargepaymentmode.accounttransfer", - "value":"chargepaymentmode.accounttransfer" - } - ], - "loanChargeCalculationTypeOptions" : [ { "code" : "chargeCalculationType.flat", - "id" : 1, - "value" : "Flat" - }, - { "code" : "chargeCalculationType.percent.of.amount", - "id" : 2, - "value" : "% Amount" - } - ], - "loanChargeTimeTypeOptions" : [ { "code" : "chargeTimeType.disbursement", - "id" : 1, - "value" : "Disbursement" - }, - { "code" : "chargeTimeType.specifiedDueDate", - "id" : 2, - "value" : "Specified due date" - } - ], - "savingsChargeCalculationTypeOptions" : [ { "code" : "chargeCalculationType.flat", - "id" : 1, - "value" : "Flat" - }, - { "code" : "chargeCalculationType.percent.of.amount", - "id" : 2, - "value" : "% Amount" - } - ], - "savingsChargeTimeTypeOptions" : [ { "code" : "chargeTimeType.specifiedDueDate", - "id" : 2, - "value" : "Specified due date" - }, - { "code" : "chargeTimeType.savingsActivation", - "id" : 3, - "value" : "Savings Activation" - }, - { "code" : "chargeTimeType.withdrawalFee", - "id" : 5, - "value" : "Withdrawal Fee" - }, - { "code" : "chargeTimeType.annualFee", - "id" : 6, - "value" : "Annual Fee" - }, - { "code" : "chargeTimeType.monthlyFee", - "id" : 7, - "value" : "Monthly Fee" - } - ] + "active": false, + "penalty": false, + "currencyOptions": [ + { + "code": "USD", + "name": "US Dollar", + "decimalPlaces": 2, + "displaySymbol": "$", + "nameCode": "currency.USD", + "displayLabel": "US Dollar ($)" + } + ], + "chargeCalculationTypeOptions": [ + { + "id": 1, + "code": "chargeCalculationType.flat", + "value": "Flat" + }, + { + "id": 2, + "code": "chargeCalculationType.percent.of.amount", + "value": "% Amount" + } + ], + "chargeAppliesToOptions": [ + { + "id": 1, + "code": "chargeAppliesTo.loan", + "value": "Loan" + }, + { + "id": 2, + "code": "chargeAppliesTo.savings", + "value": "Savings" + } + ], + "chargeTimeTypeOptions": [ + { + "id": 1, + "code": "chargeTimeType.disbursement", + "value": "Disbursement" + }, + { + "id": 2, + "code": "chargeTimeType.specifiedDueDate", + "value": "Specified due date" + }, + { + "id": 3, + "code": "chargeTimeType.savingsActivation", + "value": "Savings Activation" + }, + { + "id": 5, + "code": "chargeTimeType.withdrawalFee", + "value": "Withdrawal Fee" + }, + { + "id": 6, + "code": "chargeTimeType.annualFee", + "value": "Annual Fee" + }, + { + "id": 7, + "code": "chargeTimeType.monthlyFee", + "value": "Monthly Fee" + } + ], + "chargePaymetModeOptions": [ + { + "id": 0, + "code": "chargepaymentmode.regular", + "value": "Regular" + }, + { + "id": 1, + "code": "chargepaymentmode.accounttransfer", + "value": "Account transfer" + } + ], + "loanChargeCalculationTypeOptions": [ + { + "id": 1, + "code": "chargeCalculationType.flat", + "value": "Flat" + }, + { + "id": 2, + "code": "chargeCalculationType.percent.of.amount", + "value": "% Amount" + } + ], + "loanChargeTimeTypeOptions": [ + { + "id": 1, + "code": "chargeTimeType.disbursement", + "value": "Disbursement" + }, + { + "id": 2, + "code": "chargeTimeType.specifiedDueDate", + "value": "Specified due date" + } + ], + "savingsChargeCalculationTypeOptions": [ + { + "id": 1, + "code": "chargeCalculationType.flat", + "value": "Flat" + }, + { + "id": 2, + "code": "chargeCalculationType.percent.of.amount", + "value": "% Amount" + } + ], + "savingsChargeTimeTypeOptions": [ + { + "id": 2, + "code": "chargeTimeType.specifiedDueDate", + "value": "Specified due date" + }, + { + "id": 3, + "code": "chargeTimeType.savingsActivation", + "value": "Savings Activation" + }, + { + "id": 5, + "code": "chargeTimeType.withdrawalFee", + "value": "Withdrawal Fee" + }, + { + "id": 6, + "code": "chargeTimeType.annualFee", + "value": "Annual Fee" + }, + { + "id": 7, + "code": "chargeTimeType.monthlyFee", + "value": "Monthly Fee" + } + ] } - -
-
+
+
+
-   -
-
-

Create/Define a Charge

-

Define a new charge specific to loan or saving that can later be associated with loan - products, loans Savings product or Savings account.

-
-
- +   +
+
+

Create/Define a Charge

+

Define a new charge that can later be associated with loans and savings through their respective product definitions or directly on each account instance.

+
+
+ POST https://DomainName/api/v1/charges - - + + POST charges Content-Type: application/json Request Body: { - "name": "Loan service fee", - "chargeAppliesTo": 1, - "currencyCode": "USD", - "locale": "en", - "amount": "230.56", - "chargeTimeType": "1", - "chargeCalculationType": "1", - "chargePaymentMode": "1", - "active": true +"name": "Loan service fee", +"chargeAppliesTo": 1, +"currencyCode": "USD", +"locale": "en", +"amount": "230.56", +"chargeTimeType": "1", +"chargeCalculationType": "1", +"chargePaymentMode": "1", +"active": true } - - + + { - "resourceId": 1 +"resourceId": 1 } - - + + POST charges Content-Type: application/json Request Body: { - "locale": "en", - "name": "Default Penalty", - "amount": "2", - "currencyCode": "USD", - "chargeAppliesTo": "1", - "chargeTimeType": "2", - "chargeCalculationType": "2", - "chargePaymentMode": "1", - "active": "true", - "penalty": "true", - "minCap": 50.00, - "maxCap": 100.00 +"locale": "en", +"name": "Default Penalty", +"amount": "2", +"currencyCode": "USD", +"chargeAppliesTo": "1", +"chargeTimeType": "2", +"chargeCalculationType": "2", +"chargePaymentMode": "1", +"active": "true", +"penalty": "true", +"minCap": 50.00, +"maxCap": 100.00 } - - + + { - "resourceId": 4 +"resourceId": 4 } - + - + POST charges Content-Type: application/json Request Body: { - "locale": "en", - "name": "Annuaul Fee", - "amount": "20", - "currencyCode": "USD", - "chargeAppliesTo": "2", - "chargeTimeType": "6", - "chargeCalculationType": "1", - "chargePaymentMode": "1", - "active": "true", - "penalty": "false" +"locale": "en", +"name": "Annuaul Fee", +"amount": "20", +"currencyCode": "USD", +"chargeAppliesTo": "2", +"chargeTimeType": "6", +"chargeCalculationType": "1", +"chargePaymentMode": "1", +"active": "true", +"penalty": "false" } - - + + { - "resourceId": 5 +"resourceId": 5 } - - + + POST charges Content-Type: application/json Request Body: { - "locale": "en", - "name": "Quarterly Fee", - "amount": "5", - "currencyCode": "USD", - "chargeAppliesTo": "2", - "chargeTimeType": "7", - "feeOnMonthDay": "10 May", - "monthDayFormat": "dd MMM", - "feeInterval": "4", - "chargeCalculationType": "1", - "active": "true", - "penalty": "false" +"locale": "en", +"name": "Quarterly Fee", +"amount": "5", +"currencyCode": "USD", +"chargeAppliesTo": "2", +"chargeTimeType": "7", +"feeOnMonthDay": "10 May", +"monthDayFormat": "dd MMM", +"feeInterval": "4", +"chargeCalculationType": "1", +"active": "true", +"penalty": "false" } - - + + { - "resourceId": 6 +"resourceId": 6 } - -
-
+ +
+
 
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 73189df9a..71246b7f4 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 @@ -5,10 +5,12 @@ */ package org.mifosplatform.portfolio.charge.domain; + public enum ChargeAppliesTo { INVALID(0, "chargeAppliesTo.invalid"), // - LOAN(1, "chargeAppliesTo.loan"), SAVINGS(2, "chargeAppliesTo.savings"); + LOAN(1, "chargeAppliesTo.loan"), // + SAVINGS(2, "chargeAppliesTo.savings"); private final Integer value; private final String code; @@ -26,27 +28,23 @@ public enum ChargeAppliesTo { return this.code; } - public static int minValue() { - return 1; - } - - public static int maxValue() { - return 2;// modify whenever a new value added - } - public static ChargeAppliesTo fromInt(final Integer chargeAppliesTo) { ChargeAppliesTo chargeAppliesToType = ChargeAppliesTo.INVALID; - switch (chargeAppliesTo) { - case 1: - chargeAppliesToType = LOAN; - break; - case 2: - chargeAppliesToType = SAVINGS; - break; - default: - chargeAppliesToType = INVALID; - break; + + if (chargeAppliesTo != null) { + switch (chargeAppliesTo) { + case 1: + chargeAppliesToType = LOAN; + break; + case 2: + chargeAppliesToType = SAVINGS; + break; + default: + chargeAppliesToType = INVALID; + break; + } } + return chargeAppliesToType; } @@ -57,4 +55,8 @@ public enum ChargeAppliesTo { public boolean isSavingsCharge() { return this.value.equals(ChargeAppliesTo.SAVINGS.getValue()); } + + public static Object[] validValues() { + return new Object[] {ChargeAppliesTo.LOAN.getValue(), ChargeAppliesTo.SAVINGS.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 7d2689f73..99e607b5b 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 @@ -29,6 +29,10 @@ public enum ChargeCalculationType { return this.code; } + public static Object[] validValues() { + return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() }; + } + public static ChargeCalculationType fromInt(final Integer chargeCalculation) { ChargeCalculationType chargeCalculationType = ChargeCalculationType.INVALID; switch (chargeCalculation) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargePaymentMode.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargePaymentMode.java index e802fbeda..821d61646 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargePaymentMode.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargePaymentMode.java @@ -21,6 +21,10 @@ public enum ChargePaymentMode { return this.code; } + public static Object[] validValues() { + return new Integer[] { ChargePaymentMode.REGULAR.getValue(), ChargePaymentMode.ACCOUNT_TRANSFER.getValue() }; + } + public static ChargePaymentMode fromInt(final Integer paymentMode) { ChargePaymentMode chargeAppliesToType = ChargePaymentMode.REGULAR; switch (paymentMode) { 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 9f86d2f12..97f0d602b 100644 --- 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 @@ -8,9 +8,11 @@ package org.mifosplatform.portfolio.charge.domain; public enum ChargeTimeType { INVALID(0, "chargeTimeType.invalid"), // - DISBURSEMENT(1, "chargeTimeType.disbursement"), //only for loan charges - SPECIFIED_DUE_DATE(2, "chargeTimeType.specifiedDueDate"), // for loan and savings charges - SAVINGS_ACTIVATION(3, "chargeTimeType.savingsActivation"), // only for savings + DISBURSEMENT(1, "chargeTimeType.disbursement"), // only for loan charges + SPECIFIED_DUE_DATE(2, "chargeTimeType.specifiedDueDate"), // for loan and + // savings charges + SAVINGS_ACTIVATION(3, "chargeTimeType.savingsActivation"), // only for + // savings SAVINGS_CLOSURE(4, "chargeTimeType.savingsClosure"), // only for savings WITHDRAWAL_FEE(5, "chargeTimeType.withdrawalFee"), // only for savings ANNUAL_FEE(6, "chargeTimeType.annualFee"), // only for savings @@ -32,45 +34,45 @@ public enum ChargeTimeType { return this.code; } - public static int minValue() { - return 1; + public static Object[] validLoanValues() { + return new Integer[] { ChargeTimeType.DISBURSEMENT.getValue(), ChargeTimeType.SPECIFIED_DUE_DATE.getValue() }; } - public static int maxValue() { - int max = 1;// Default it to one (1) - for (ChargeTimeType chargeTimeType : ChargeTimeType.values()) { - max = (chargeTimeType.getValue() > max) ? chargeTimeType.getValue() : max; - } - return max; + public static Object[] validSavingsValues() { + return new Integer[] { ChargeTimeType.SPECIFIED_DUE_DATE.getValue(), ChargeTimeType.SAVINGS_ACTIVATION.getValue(), + ChargeTimeType.SAVINGS_CLOSURE.getValue(), ChargeTimeType.WITHDRAWAL_FEE.getValue(), ChargeTimeType.ANNUAL_FEE.getValue(), + ChargeTimeType.MONTHLY_FEE.getValue() }; } public static ChargeTimeType fromInt(final Integer chargeTime) { ChargeTimeType chargeTimeType = ChargeTimeType.INVALID; - switch (chargeTime) { - case 1: - chargeTimeType = DISBURSEMENT; - break; - case 2: - chargeTimeType = SPECIFIED_DUE_DATE; - break; - case 3: - chargeTimeType = SAVINGS_ACTIVATION; - break; - case 4: - chargeTimeType = SAVINGS_CLOSURE; - break; - case 5: - chargeTimeType = WITHDRAWAL_FEE; - break; - case 6: - chargeTimeType = ANNUAL_FEE; - break; - case 7: - chargeTimeType = MONTHLY_FEE; - break; - default: - chargeTimeType = INVALID; - break; + if (chargeTime != null) { + switch (chargeTime) { + case 1: + chargeTimeType = DISBURSEMENT; + break; + case 2: + chargeTimeType = SPECIFIED_DUE_DATE; + break; + case 3: + chargeTimeType = SAVINGS_ACTIVATION; + break; + case 4: + chargeTimeType = SAVINGS_CLOSURE; + break; + case 5: + chargeTimeType = WITHDRAWAL_FEE; + break; + case 6: + chargeTimeType = ANNUAL_FEE; + break; + case 7: + chargeTimeType = MONTHLY_FEE; + break; + default: + chargeTimeType = INVALID; + break; + } } return chargeTimeType; } @@ -90,11 +92,11 @@ public enum ChargeTimeType { public boolean isSavingsClosure() { return this.value.equals(ChargeTimeType.SAVINGS_CLOSURE.getValue()); } - + public boolean isWithdrawalFee() { return this.value.equals(ChargeTimeType.WITHDRAWAL_FEE.getValue()); } - + public boolean isAnnualFee() { return this.value.equals(ChargeTimeType.ANNUAL_FEE.getValue()); } @@ -102,7 +104,7 @@ public enum ChargeTimeType { public boolean isMonthlyFee() { return this.value.equals(ChargeTimeType.MONTHLY_FEE.getValue()); } - + public boolean isAllowedLoanChargeTime() { return isTimeOfDisbursement() || isOnSpecifiedDueDate(); } 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 050d4f76f..9a6c84b18 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 @@ -23,6 +23,8 @@ import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.portfolio.charge.domain.ChargeAppliesTo; +import org.mifosplatform.portfolio.charge.domain.ChargeCalculationType; +import org.mifosplatform.portfolio.charge.domain.ChargePaymentMode; import org.mifosplatform.portfolio.charge.domain.ChargeTimeType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -38,7 +40,7 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer { */ private final Set supportedParameters = new HashSet(Arrays.asList("name", "amount", "locale", "currencyCode", "currencyOptions", "chargeAppliesTo", "chargeTimeType", "chargeCalculationType", "chargeCalculationTypeOptions", "penalty", - "active", "chargePaymentMode", "feeOnMonthDay", "feeInterval", "monthDayFormat","minCap","maxCap")); + "active", "chargePaymentMode", "feeOnMonthDay", "feeInterval", "monthDayFormat", "minCap", "maxCap")); private final FromJsonHelper fromApiJsonHelper; @@ -58,6 +60,50 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer { final JsonElement element = this.fromApiJsonHelper.parse(json); + final Integer chargeAppliesTo = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeAppliesTo", element); + baseDataValidator.reset().parameter("chargeAppliesTo").value(chargeAppliesTo).notNull(); + if (chargeAppliesTo != null) { + baseDataValidator.reset().parameter("chargeAppliesTo").value(chargeAppliesTo).isOneOfTheseValues(ChargeAppliesTo.validValues()); + } + + final ChargeAppliesTo appliesTo = ChargeAppliesTo.fromInt(chargeAppliesTo); + if (appliesTo.isLoanCharge()) { + // loan 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.validLoanValues()); + } + + final Integer chargePaymentMode = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargePaymentMode", element); + baseDataValidator.reset().parameter("chargePaymentMode").value(chargePaymentMode).notNull().isOneOfTheseValues(ChargePaymentMode.validValues()); + if (chargePaymentMode != null) { + baseDataValidator.reset().parameter("chargePaymentMode").value(chargePaymentMode).isOneOfTheseValues(ChargePaymentMode.validValues()); + } + + } else if (appliesTo.isSavingsCharge()) { + // savings 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.validSavingsValues()); + } + + final ChargeTimeType ctt = ChargeTimeType.fromInt(chargeTimeType); + if (ctt.isMonthlyFee()) { + final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed("feeOnMonthDay", element); + baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).notNull(); + + final Integer feeInterval = this.fromApiJsonHelper.extractIntegerNamed("feeInterval", element, Locale.getDefault()); + baseDataValidator.reset().parameter("feeInterval").value(feeInterval).notNull().inMinMaxRange(1, 12); + } + + if (ctt.isAnnualFee()) { + final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed("feeOnMonthDay", element); + baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).notNull(); + } + } + final String name = this.fromApiJsonHelper.extractStringNamed("name", element); baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100); @@ -67,24 +113,6 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer { final BigDecimal amount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("amount", element.getAsJsonObject()); baseDataValidator.reset().parameter("amount").value(amount).notNull().positiveAmount(); - final Integer chargeAppliesTo = this.fromApiJsonHelper.extractIntegerNamed("chargeAppliesTo", element, Locale.getDefault()); - baseDataValidator.reset().parameter("chargeAppliesTo").value(chargeAppliesTo).notNull() - .inMinMaxRange(ChargeAppliesTo.minValue(), ChargeAppliesTo.maxValue()); - - final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerNamed("chargeTimeType", element, Locale.getDefault()); - baseDataValidator.reset().parameter("chargeTimeType").value(chargeTimeType).notNull() - .inMinMaxRange(ChargeTimeType.minValue(), ChargeTimeType.maxValue()); - - final Integer chargeCalculationType = this.fromApiJsonHelper.extractIntegerNamed("chargeCalculationType", element, - Locale.getDefault()); - baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).notNull().inMinMaxRange(1, 4); - - ChargeAppliesTo appliesTo = ChargeAppliesTo.fromInt(chargeAppliesTo); - if (appliesTo.isLoanCharge()) { - final Integer chargePaymentMode = this.fromApiJsonHelper.extractIntegerNamed("chargePaymentMode", element, Locale.getDefault()); - baseDataValidator.reset().parameter("chargePaymentMode").value(chargePaymentMode).notNull().inMinMaxRange(0, 1); - } - if (this.fromApiJsonHelper.parameterExists("penalty", element)) { final Boolean penalty = this.fromApiJsonHelper.extractBooleanNamed("penalty", element); baseDataValidator.reset().parameter("penalty").value(penalty).notNull(); @@ -94,26 +122,18 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer { final Boolean active = this.fromApiJsonHelper.extractBooleanNamed("active", element); baseDataValidator.reset().parameter("active").value(active).notNull(); } - - final ChargeTimeType ctt = ChargeTimeType.fromInt(chargeTimeType); - if(ctt.isMonthlyFee()){ - final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed("feeOnMonthDay", element); - baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).notNull(); - - final Integer feeInterval = this.fromApiJsonHelper.extractIntegerNamed("feeInterval", element, Locale.getDefault()); - baseDataValidator.reset().parameter("feeInterval").value(feeInterval).notNull().inMinMaxRange(1, 12); - } - - if(ctt.isAnnualFee()){ - final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed("feeOnMonthDay", element); - baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).notNull(); + + final Integer chargeCalculationType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeCalculationType", element); + baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).notNull(); + if (chargeCalculationType != null) { + baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).isOneOfTheseValues(ChargeCalculationType.validValues()); } - if(this.fromApiJsonHelper.parameterExists("minCap",element)){ + if (this.fromApiJsonHelper.parameterExists("minCap", element)) { final BigDecimal minCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("minCap", element.getAsJsonObject()); baseDataValidator.reset().parameter("minCap").value(minCap).notNull().positiveAmount(); } - if(this.fromApiJsonHelper.parameterExists("maxCap",element)){ + if (this.fromApiJsonHelper.parameterExists("maxCap", element)) { final BigDecimal maxCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("maxCap", element.getAsJsonObject()); baseDataValidator.reset().parameter("maxCap").value(maxCap).notNull().positiveAmount(); } @@ -131,6 +151,7 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer { final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charge"); final JsonElement element = this.fromApiJsonHelper.parse(json); + if (this.fromApiJsonHelper.parameterExists("name", element)) { final String name = this.fromApiJsonHelper.extractStringNamed("name", element); baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100); @@ -146,33 +167,34 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer { baseDataValidator.reset().parameter("amount").value(amount).notNull().positiveAmount(); } - if(this.fromApiJsonHelper.parameterExists("minCap",element)){ + if (this.fromApiJsonHelper.parameterExists("minCap", element)) { final BigDecimal minCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("minCap", element.getAsJsonObject()); baseDataValidator.reset().parameter("minCap").value(minCap).notNull().positiveAmount(); } - if(this.fromApiJsonHelper.parameterExists("maxCap",element)){ + if (this.fromApiJsonHelper.parameterExists("maxCap", element)) { final BigDecimal maxCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("maxCap", element.getAsJsonObject()); baseDataValidator.reset().parameter("maxCap").value(maxCap).notNull().positiveAmount(); } if (this.fromApiJsonHelper.parameterExists("chargeAppliesTo", element)) { - final Integer chargeAppliesTo = this.fromApiJsonHelper.extractIntegerNamed("chargeAppliesTo", element, Locale.getDefault()); + final Integer chargeAppliesTo = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeAppliesTo", element); baseDataValidator.reset().parameter("chargeAppliesTo").value(chargeAppliesTo).notNull() - .inMinMaxRange(ChargeAppliesTo.minValue(), ChargeAppliesTo.maxValue()); + .isOneOfTheseValues(ChargeAppliesTo.validValues()); } if (this.fromApiJsonHelper.parameterExists("chargeTimeType", element)) { - final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerNamed("chargeTimeType", element, Locale.getDefault()); + + final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeTimeType", element); baseDataValidator.reset().parameter("chargeTimeType").value(chargeTimeType).notNull() - .inMinMaxRange(ChargeTimeType.minValue(), ChargeTimeType.maxValue()); + .isOneOfTheseValues(ChargeTimeType.validLoanValues(), ChargeTimeType.validSavingsValues()); } - + if (this.fromApiJsonHelper.parameterExists("feeOnMonthDay", element)) { - final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed("feeOnMonthDay", element); + final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed("feeOnMonthDay", element); baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).notNull(); } - + if (this.fromApiJsonHelper.parameterExists("feeInterval", element)) { final Integer feeInterval = this.fromApiJsonHelper.extractIntegerNamed("feeInterval", element, Locale.getDefault()); baseDataValidator.reset().parameter("feeInterval").value(feeInterval).notNull().inMinMaxRange(1, 12); @@ -198,11 +220,11 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer { final Boolean active = this.fromApiJsonHelper.extractBooleanNamed("active", element); baseDataValidator.reset().parameter("active").value(active).notNull(); } - if(this.fromApiJsonHelper.parameterExists("minCap",element)){ + if (this.fromApiJsonHelper.parameterExists("minCap", element)) { final BigDecimal minCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("minCap", element.getAsJsonObject()); baseDataValidator.reset().parameter("minCap").value(minCap).notNull().positiveAmount(); } - if(this.fromApiJsonHelper.parameterExists("maxCap",element)){ + if (this.fromApiJsonHelper.parameterExists("maxCap", element)) { final BigDecimal maxCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("maxCap", element.getAsJsonObject()); baseDataValidator.reset().parameter("maxCap").value(maxCap).notNull().positiveAmount(); } @@ -211,7 +233,6 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer { } private void throwExceptionIfValidationWarningsExist(final List dataValidationErrors) { - if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", - "Validation errors exist.", dataValidationErrors); } + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } } \ No newline at end of file