diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index aa307502f..1c3ab088e 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -5466,7 +5466,7 @@ Request Body:
-
-
Retrieve a Loan Product
-
Example Requests:
-
loanproducts/1
-
-
-
loanproducts/1?template=true
-
-
-
loanproducts/1?fields=name,description,numberOfRepayments
-
-
-
-GET https://DomainName/api/v1/loanproducts/{productId}
-
-
-{
+ "accountingRule": {
"id": 1,
- "name": "A new loan product for me",
- "currency": {
- "code": "USD",
- "name": "US Dollar",
- "decimalPlaces": 2,
- "displaySymbol": "$",
- "nameCode": "currency.USD",
- "displayLabel": "US Dollar ($)"
- },
- "principal": 100000,
- "numberOfRepayments": 12,
- "loanTermFrequency": 12,
- "repaymentEvery": 1,
- "loanTermFrequencyType": {
- "id": 2,
- "code": "loanTermFrequency.periodFrequencyType.months",
- "value": "Months"
- },
- "repaymentFrequencyType": {
- "id": 2,
- "code": "repaymentFrequency.periodFrequencyType.months",
- "value": "Months"
- },
- "transactionProcessingStrategyId": 1,
- "transactionProcessingStrategyName": "Mifos style",
- "interestRatePerPeriod": 1.75,
- "interestRateFrequencyType": {
- "id": 2,
- "code": "interestRateFrequency.periodFrequencyType.months",
- "value": "Per month"
- },
- "annualInterestRate": 21,
- "amortizationType": {
- "id": 1,
- "code": "amortizationType.equal.installments",
- "value": "Equal installments"
- },
- "interestType": {
- "id": 0,
- "code": "interestType.declining.balance",
- "value": "Declining Balance"
- },
- "interestCalculationPeriodType": {
- "id": 1,
- "code": "interestCalculationPeriodType.same.as.repayment.period",
- "value": "Same as repayment period"
- },
- "accountingRule": 1,
- "charges": []
+ "code": "accountingRuleType.none",
+ "value": "NONE"
+ }
}
@@ -6074,11 +6064,17 @@ GET https://DomainName/api/v1/loanproducts/{productId}
| name, currencyCode, digitsAfterDecimal, principal,
- inArrearsTolerance, repaymentFrequencyType, repaymentEvery,
- numberOfRepayments, interestRatePerPeriod,
- interestRateFrequencyType, amortizationType, interestType,
- interestCalculationPeriodType, accountingRule |
+ numberOfRepayments, repaymentEvery, repaymentFrequencyType,
+ interestRatePerPeriod, interestRateFrequencyType, amortizationType, interestType,
+ interestCalculationPeriodType, transactionProcessingStrategyId, accountingRule
+
+ Optional Fields |
+
+
+ | inArrearsTolerance, charges |
+
+
Additional Mandatory Fields for Cash(2) based accounting |
@@ -6107,7 +6103,7 @@ POST loanproducts
Content-Type: application/json
Request Body:
{
- "name": "A new loan product for me",
+ "name": "LP with Charges but no accounting)",
"currencyCode": "USD",
"locale": "en_GB",
"digitsAfterDecimal": "2",
@@ -6115,12 +6111,14 @@ Request Body:
"numberOfRepayments": "12",
"repaymentEvery": "1",
"repaymentFrequencyType": 2,
- "transactionProcessingStrategyId": 1,
"interestRatePerPeriod": "1.75",
"interestRateFrequencyType": 2,
"amortizationType": 1,
"interestType": 0,
"interestCalculationPeriodType": 1,
+ "inArrearsTolerance": "0",
+ "transactionProcessingStrategyId": 1,
+ "charges":[{"id":"1"},{"id":"1"}],
"accountingRule": 1
}
@@ -6134,7 +6132,7 @@ POST loanproducts
Content-Type: application/json
Request Body:
{
- "name": "A new loan product for me",
+ "name": "LP Cash Accounting",
"currencyCode": "USD",
"locale": "en_GB",
"digitsAfterDecimal": "2",
@@ -6148,13 +6146,13 @@ Request Body:
"amortizationType": 1,
"interestType": 0,
"interestCalculationPeriodType": 1,
- "accountingRule":"3",
- "fundSourceAccountId":"15",
- "loanPortfolioAccountId":"16",
- "interestOnLoanAccountId":"14",
- "incomeFromFeeAccountId":"13",
- "incomeFromPenaltyAccountId":"12",
- "writeOffAccountId":"11"
+ "accountingRule":"2",
+ "fundSourceAccountId":"4",
+ "loanPortfolioAccountId":"8",
+ "interestOnLoanAccountId":"34",
+ "incomeFromFeeAccountId":"37",
+ "incomeFromPenaltyAccountId":"35",
+ "writeOffAccountId":"41"
}
@@ -6167,7 +6165,7 @@ POST loanproducts
Content-Type: application/json
Request Body:
{
- "name": "A new loan product for me",
+ "name": "LP Accrual Accounting",
"currencyCode": "USD",
"locale": "en_GB",
"digitsAfterDecimal": "2",
@@ -6182,15 +6180,15 @@ Request Body:
"interestType": 0,
"interestCalculationPeriodType": 1,
"accountingRule":"3",
- "fundSourceAccountId":"15",
- "loanPortfolioAccountId":"16",
- "receivableInterestAccountId":"10",
- "receivableFeeAccountId":"9",
- "receivablePenaltyAccountId":"8",
- "interestOnLoanAccountId":"14",
- "incomeFromFeeAccountId":"13",
- "incomeFromPenaltyAccountId":"12",
- "writeOffAccountId":"11"
+ "fundSourceAccountId":"4",
+ "loanPortfolioAccountId":"8",
+ "receivableInterestAccountId":"9",
+ "receivableFeeAccountId":"11",
+ "receivablePenaltyAccountId":"10",
+ "interestOnLoanAccountId":"34",
+ "incomeFromFeeAccountId":"37",
+ "incomeFromPenaltyAccountId":"35",
+ "writeOffAccountId":"41"
}
@@ -6823,7 +6821,8 @@ Request Body:
"locale": "en",
"amount": "230.56",
"chargeTimeType": "1",
- "chargeCalculationType": "1"
+ "chargeCalculationType": "1",
+ "active": true
}
{ "resourceId": 1 }
diff --git a/mifosng-db/multi-tenant-demo-backups/default-demo/extra-datatables-and-code-values.sql b/mifosng-db/multi-tenant-demo-backups/default-demo/extra-datatables-and-code-values.sql
index e64491532..4d96df436 100644
--- a/mifosng-db/multi-tenant-demo-backups/default-demo/extra-datatables-and-code-values.sql
+++ b/mifosng-db/multi-tenant-demo-backups/default-demo/extra-datatables-and-code-values.sql
@@ -116,4 +116,106 @@ from x_registered_table r;
insert into m_permission(grouping, `code`, entity_name, action_name)
select 'datatable', concat('DELETE_', r.registered_table_name), r.registered_table_name, 'DELETE'
-from x_registered_table r;
\ No newline at end of file
+from x_registered_table r;
+
+
+
+-- ==== Chart of Accounts =====
+truncate `acc_gl_account`;
+INSERT INTO `acc_gl_account` VALUES
+(1,'Petty Cash Balances',NULL,'11100',0,1,2,1,NULL),
+(2,'Cash in Valut 1',NULL,'11101',0,1,1,1,NULL),
+(3,'Bank Balances',NULL,'11200',0,1,2,1,NULL),
+(4,'Centenary Opening Account',NULL,'11201',0,1,1,1,NULL),
+(5,'Centenary Expense Account',NULL,'11202',0,1,1,1,NULL),
+(6,'Centenary USD Account',NULL,'11203',0,1,1,1,NULL),
+(7,'Loans and Advances',NULL,'13100',0,1,2,1,NULL),
+(8,'Loans to Clients',NULL,'13101',0,1,1,1,NULL),
+(9,'Outstanding Interest',NULL,'13102',0,1,1,1,NULL),
+(10,'Outstanding Late Payment Interest',NULL,'13103',0,1,1,1,NULL),
+(11,'Outstanding Bank Fees to be collected',NULL,'13104',0,1,1,1,NULL),
+(12,'WriteOff Accounts',NULL,'13200',0,1,2,1,NULL),
+(13,'Write-offs (use for funds coming in)',NULL,'13201',0,1,1,1,NULL),
+(14,'Write-offs outstanding principal',NULL,'13202',0,1,1,1,NULL),
+(15,'Write-offs outstanding interest',NULL,'13203',0,1,1,1,NULL),
+(16,'Write-offs collected bank fees',NULL,'13204',0,1,1,1,NULL),
+(17,'Write-offs hardware/furniture',NULL,'13205',0,1,1,1,NULL),
+(18,'Fixed Assets',NULL,'14100',0,1,2,1,NULL),
+(19,'Office Equipment',NULL,'14101',0,1,1,1,NULL),
+(20,'Suspense Items (unidentified deposits)',NULL,'15000',0,1,2,1,NULL),
+(21,'Assets',NULL,'10000',0,1,2,1,NULL),
+(22,'Liabilities',NULL,'20000',0,1,2,2,NULL),
+(23,'Shares Account',NULL,'26100',0,1,2,2,NULL),
+(24,'Shares Captial',NULL,'26101',0,1,1,2,NULL),
+(25,'Donated Equity',NULL,'26300',0,1,2,2,NULL),
+(26,'Donated Equity Ameropa Foundation',NULL,'26301',0,1,1,2,NULL),
+(27,'Donated Equity e.h',NULL,'26302',0,1,1,2,NULL),
+(28,'Overpaid Amounts',NULL,'27000',0,1,2,2,NULL),
+(29,'Loss Provision',NULL,'28000',0,1,2,2,NULL),
+(30,'Provision Outstanding Principal',NULL,'28001',0,1,1,2,NULL),
+(31,'Provision Oustanding Interest',NULL,'28002',0,1,1,2,NULL),(32,'Income',NULL,'30000',0,1,2,4,NULL),
+(33,'Interest Income from Loans',NULL,'31100',0,1,2,4,NULL),
+(34,'Interest on Loans',NULL,'31101',0,1,1,4,NULL),
+(35,'Late Payment Interest',NULL,'31102',0,1,1,4,NULL),
+(36,'Income from Micro credit & Lending Activities',NULL,'31300',0,1,2,4,NULL),
+(37,'Collected Bank Fees Receivable',NULL,'6201',0,1,1,4,NULL),
+(38,'Deposits from Loans Write Off',NULL,'31400',0,1,2,4,NULL),
+(39,'Expenditure',NULL,'40000',0,1,2,5,NULL),
+(40,'Office Expenditure Account',NULL,'42100',0,1,2,5,NULL),
+(41,'Water Charges',NULL,'42102',0,1,1,5,NULL),
+(42,'Electricity Charges',NULL,'42103',0,1,1,5,NULL),
+(43,'Printing and Stationary',NULL,'42105',0,1,1,5,NULL),
+(44,'Office Rent',NULL,'42107',0,1,1,5,NULL),
+(45,'Marketing Expense',NULL,'42109',0,1,1,5,NULL),
+(46,'Office utilities',NULL,'42112',0,1,1,5,'(supplies, toiletries, kitchen)'),
+(47,'Furniture',NULL,'42113',0,1,1,5,NULL),
+(48,'CEDA Meeting Expense',NULL,'42114',0,1,1,5,NULL),
+(49,'Employee Personal Expsense Account',NULL,'42200',0,1,2,5,NULL),
+(50,'Salary Alice',NULL,'42201',0,1,1,5,NULL),
+(51,'Salary Irene',NULL,'42202',0,1,1,5,NULL),
+(52,'Salary Richard',NULL,'42203',0,1,1,5,NULL),
+(53,'Salary Loan Officer TBA',NULL,'42204',0,1,1,5,NULL),
+(54,'Medical Insurance Alice & Family',NULL,'42205',0,1,1,5,NULL),
+(55,'Medical Insurance Irene',NULL,'42206',0,1,1,5,NULL),
+(56,'Medical Insurance Richard',NULL,'42207',0,1,1,5,NULL),
+(57,'Medical Insurance Loan Officer TBA',NULL,'42208',0,1,1,5,NULL),
+(58,'PAYE all employees',NULL,'42209',0,1,1,5,NULL),
+(59,'NSSF all employees',NULL,'42210',0,1,1,5,NULL),
+(60,'Lunch Allowances all employees',NULL,'42211',0,1,1,5,NULL),
+(61,'IT software and maintenance',NULL,'42300',0,1,2,5,NULL),
+(62,'Mifos maintenance contract 12 months',NULL,'42301',0,1,1,5,NULL),
+(63,'VPS Contract 12 months',NULL,'42302',0,1,1,5,NULL),
+(64,'Bulk SMS Service',NULL,'42303',0,1,1,5,NULL),
+(65,'Support Accounting Software',NULL,'42304',0,1,1,5,NULL),
+(66,'Mifos Instance Setup',NULL,'42305',0,1,1,5,NULL),
+(67,'Misc support expense',NULL,'42306',0,1,1,5,NULL),
+(68,'Warid Mobile Line',NULL,'42307',0,1,1,5,NULL),
+(69,'Landline',NULL,'42308',0,1,1,5,NULL),
+(70,'Modem Alice',NULL,'42309',0,1,1,5,NULL),
+(71,'Modem Irene',NULL,'42310',0,1,1,5,NULL),
+(72,'Modem Richard',NULL,'42311',0,1,1,5,NULL),
+(73,'Repairs',NULL,'42312',0,1,1,5,NULL),
+(74,'Airtime Expenses',NULL,'42400',0,1,2,5,NULL),
+(75,'Airtime Alice',NULL,'42401',0,1,1,5,NULL),
+(76,'Airtime Richard',NULL,'42402',0,1,1,5,NULL),
+(77,'Airtime Loan Office TBA',NULL,'42403',0,1,1,5,NULL),
+(78,'Special Airtime Alice',NULL,'42404',0,1,1,5,NULL),
+(79,'Transportation',NULL,'42500',0,1,2,5,NULL),
+(80,'Flat monthly transportation cost',NULL,'42501',0,1,1,5,NULL),
+(81,'Faciliation cost for Richard',NULL,'42502',0,1,1,5,NULL),
+(82,'Faciliation cost for Loan Officer TBA',NULL,'42503',0,1,1,5,NULL),
+(83,'Consultancy Expenses',NULL,'42600',0,1,2,5,NULL),
+(84,'Audit Fees',NULL,'42601',0,1,1,5,NULL),
+(85,'Legal Fees',NULL,'42602',0,1,1,5,NULL),
+(86,'Miscellaneous Expenses Account',NULL,'42700',0,1,2,5,NULL),
+(87,'MFI License',NULL,'42703',0,1,1,5,NULL),
+(88,'Sundy Expenses',NULL,'42704',0,1,1,5,NULL),
+(89,'Bank Fees',NULL,'42800',0,1,2,5,NULL),
+(90,'Bank Charges Operating Account',NULL,'42801',0,1,1,5,NULL),
+(91,'Bank Charges Expense Account',NULL,'42802',0,1,1,5,NULL),
+(92,'E.H Account',NULL,'42900',0,1,2,5,NULL),
+(93,'Airtime',NULL,'42901',0,1,1,5,NULL),
+(94,'Modem',NULL,'42902',0,1,1,5,NULL),
+(95,'Meals',NULL,'42903',0,1,1,5,NULL),
+(96,'Transportation',NULL,'42904',0,1,1,5,NULL),
+(97,'Miscellaneous',NULL,'42905',0,1,1,5,NULL);
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java
index c2ecfb645..3f46cab56 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java
@@ -17,6 +17,7 @@ import org.mifosplatform.infrastructure.security.domain.BasicPasswordEncodablePl
import org.mifosplatform.infrastructure.security.domain.PlatformUser;
import org.mifosplatform.infrastructure.security.service.PlatformPasswordEncoder;
+import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
/**
@@ -39,8 +40,8 @@ public final class JsonCommand {
private final Long apptableId;
private final Long datatableId;
private final Long codeId;
- private String supportedEntityType;
- private Long supportedEntityId;
+ private final String supportedEntityType;
+ private final Long supportedEntityId;
private final String transactionId;
public static JsonCommand from(final String jsonCommand, final JsonElement parsedCommand, final FromJsonHelper fromApiJsonHelper,
@@ -86,6 +87,15 @@ public final class JsonCommand {
return this.parsedCommand;
}
+ public String jsonFragment(final String paramName) {
+ String jsonFragment = null;
+ if (this.parsedCommand.getAsJsonObject().has(paramName)) {
+ JsonElement fragment = this.parsedCommand.getAsJsonObject().get(paramName);
+ jsonFragment = this.fromApiJsonHelper.toJson(fragment);
+ }
+ return jsonFragment;
+ }
+
public Long commandId() {
return this.commandId;
}
@@ -347,6 +357,10 @@ public final class JsonCommand {
return this.fromApiJsonHelper.extractArrayNamed(parameterName, parsedCommand);
}
+ public JsonArray arrayOfParameterNamed(final String parameterName) {
+ return this.fromApiJsonHelper.extractJsonArrayNamed(parameterName, parsedCommand);
+ }
+
public boolean isChangeInPasswordParameterNamed(final String parameterName, final String existingValue,
final PlatformPasswordEncoder platformPasswordEncoder, final Long saltValue) {
boolean isChanged = false;
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/FromJsonHelper.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/FromJsonHelper.java
index 08d3029f0..96991676a 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/FromJsonHelper.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/FromJsonHelper.java
@@ -21,6 +21,7 @@ import org.mifosplatform.infrastructure.core.exception.UnsupportedParameterExcep
import org.springframework.stereotype.Component;
import com.google.gson.Gson;
+import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
@@ -46,7 +47,7 @@ public class FromJsonHelper {
return this.gsonConverter.fromJson(json, typeOfMap);
}
- public
T fromJson(final String json, Class classOfT) {
+ public T fromJson(final String json, final Class classOfT) {
return this.gsonConverter.fromJson(json, classOfT);
}
@@ -93,6 +94,10 @@ public class FromJsonHelper {
return helperDelegator.extractLongNamed(parameterName, element, parametersPassedInRequest);
}
+ public JsonArray extractJsonArrayNamed(final String parameterName, final JsonElement element) {
+ return helperDelegator.extractJsonArrayNamed(parameterName, element);
+ }
+
public String[] extractArrayNamed(final String parameterName, final JsonElement element) {
return helperDelegator.extractArrayNamed(parameterName, element, new HashSet());
}
@@ -109,7 +114,7 @@ public class FromJsonHelper {
return helperDelegator.extractBooleanNamed(parameterName, element, parametersPassedInRequest);
}
- public LocalDate extractLocalDateNamed(final String parameterName, JsonElement element) {
+ public LocalDate extractLocalDateNamed(final String parameterName, final JsonElement element) {
return helperDelegator.extractLocalDateNamed(parameterName, element, new HashSet());
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/JsonParserHelper.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/JsonParserHelper.java
index d1e1b7226..11057429f 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/JsonParserHelper.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/JsonParserHelper.java
@@ -32,7 +32,7 @@ import com.google.gson.JsonPrimitive;
* Helper class to extract values of json named attributes.
*/
public class JsonParserHelper {
-
+
public boolean parameterExists(final String parameterName, final JsonElement element) {
return element.getAsJsonObject().has(parameterName);
}
@@ -137,19 +137,21 @@ public class JsonParserHelper {
}
return value;
}
-
- /** Method used to extract integers from unformatted strings.
- * Ex: "1" , "100002" etc
+
+ /**
+ * Method used to extract integers from unformatted strings. Ex: "1" ,
+ * "100002" etc
*
- * Please note that this method does not support extracting Integers from locale
- * specific formatted strings Ex "1,000" etc
+ * Please note that this method does not support extracting Integers from
+ * locale specific formatted strings Ex "1,000" etc
*
* @param parameterName
* @param element
* @param parametersPassedInRequest
* @return
*/
- public Integer extractIntegerSansLocaleNamed(final String parameterName, final JsonElement element, final Set parametersPassedInRequest) {
+ public Integer extractIntegerSansLocaleNamed(final String parameterName, final JsonElement element,
+ final Set parametersPassedInRequest) {
Integer intValue = null;
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
@@ -211,6 +213,19 @@ public class JsonParserHelper {
return arrayValue;
}
+ public JsonArray extractJsonArrayNamed(final String parameterName, final JsonElement element) {
+ JsonArray jsonArray = null;
+
+ if (element.isJsonObject()) {
+ JsonObject object = element.getAsJsonObject();
+ if (object.has(parameterName)) {
+ jsonArray = object.get(parameterName).getAsJsonArray();
+ }
+ }
+
+ return jsonArray;
+ }
+
/**
* Used with the local date is in array format
*/
@@ -391,8 +406,8 @@ public class JsonParserHelper {
} catch (NumberFormatException e) {
List dataValidationErrors = new ArrayList();
- ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.integer", "The parameter "
- + parameterName + " has value: " + numericalValueFormatted + " which is invalid integer.", parameterName, numericalValueFormatted);
+ ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.integer", "The parameter " + parameterName
+ + " has value: " + numericalValueFormatted + " which is invalid integer.", parameterName, numericalValueFormatted);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
@@ -400,7 +415,6 @@ public class JsonParserHelper {
}
}
-
public BigDecimal convertFrom(final String numericalValueFormatted, final String parameterName, final Locale clientApplicationLocale) {
if (clientApplicationLocale == null) {
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 93ebd0c42..bec4a0be0 100644
--- 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
@@ -11,11 +11,12 @@ import java.util.List;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.organisation.monetary.data.CurrencyData;
+import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData;
/**
* Immutable data object for charge data.
*/
-public class ChargeData {
+public class ChargeData implements Comparable {
private final Long id;
private final String name;
@@ -72,36 +73,8 @@ public class ChargeData {
this.chargeTimeTypeOptions = chargeTimeTypeOptions;
}
- public Long getId() {
- return id;
- }
-
- public String getName() {
- return name;
- }
-
- public boolean isPenalty() {
- return this.penalty;
- }
-
- public BigDecimal getAmount() {
- return amount;
- }
-
- public CurrencyData getCurrency() {
- return currency;
- }
-
- public EnumOptionData getChargeTimeType() {
- return chargeTimeType;
- }
-
- public EnumOptionData getChargeCalculationType() {
- return chargeCalculationType;
- }
-
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
ChargeData chargeData = (ChargeData) obj;
return this.id.equals(chargeData.id);
}
@@ -110,4 +83,16 @@ public class ChargeData {
public int hashCode() {
return this.id.hashCode();
}
+
+ @Override
+ public int compareTo(final ChargeData obj) {
+ if (obj == null) { return -1; }
+
+ return obj.id.compareTo(this.id);
+ }
+
+ public LoanChargeData toLoanChargeData() {
+ return LoanChargeData.newLoanChargeDetails(this.id, this.name, this.currency, this.amount, this.chargeTimeType,
+ this.chargeCalculationType, this.penalty);
+ }
}
\ No newline at end of file
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 a32075762..f9fe209da 100644
--- 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
@@ -14,8 +14,15 @@ import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
+import org.mifosplatform.infrastructure.core.data.EnumOptionData;
+import org.mifosplatform.organisation.monetary.data.CurrencyData;
+import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.charge.exception.ChargeDueAtDisbursementCannotBePenaltyException;
+import org.mifosplatform.portfolio.charge.service.ChargeEnumerations;
+import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@@ -71,7 +78,7 @@ 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, boolean active) {
+ final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculationType, final boolean penalty, final boolean active) {
this.name = name;
this.amount = amount;
this.currencyCode = currencyCode;
@@ -83,6 +90,24 @@ public class Charge extends AbstractPersistable {
if (penalty && chargeTime.isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException(name); }
}
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) { return false; }
+ if (obj == this) { return true; }
+ if (obj.getClass() != getClass()) { return false; }
+ LoanCharge rhs = (LoanCharge) obj;
+ return new EqualsBuilder().appendSuper(super.equals(obj)) //
+ .append(this.getId(), rhs.getId()) //
+ .isEquals();
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder(3, 5) //
+ .append(this.getId()) //
+ .toHashCode();
+ }
+
public String getName() {
return name;
}
@@ -180,8 +205,9 @@ public class Charge extends AbstractPersistable {
actualChanges.put(activeParamName, newValue);
this.active = newValue;
}
-
- if (this.penalty && ChargeTimeType.fromInt(this.chargeTime).isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException(name); }
+
+ if (this.penalty && ChargeTimeType.fromInt(this.chargeTime).isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException(
+ name); }
return actualChanges;
}
@@ -196,4 +222,15 @@ public class Charge extends AbstractPersistable {
this.deleted = true;
this.name = this.getId() + "_" + this.name;
}
+
+ public ChargeData toData() {
+
+ EnumOptionData chargeTimeType = ChargeEnumerations.chargeTimeType(this.chargeTime);
+ EnumOptionData chargeAppliesTo = ChargeEnumerations.chargeAppliesTo(this.chargeAppliesTo);
+ EnumOptionData chargeCalculationType = ChargeEnumerations.chargeCalculationType(this.chargeCalculation);
+
+ CurrencyData currency = new CurrencyData(this.currencyCode, null, 0, null, null);
+ return ChargeData.instance(this.getId(), this.name, this.amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType,
+ penalty, active);
+ }
}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java
index 1ab3acf9c..ad5318c1d 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java
@@ -353,8 +353,7 @@ public class LoanAccountData {
final Collection charges = new ArrayList();
for (ChargeData charge : product.charges()) {
- charges.add(LoanChargeData.newLoanChargeDetails(charge.getId(), charge.getName(), charge.getCurrency(), charge.getAmount(),
- charge.getChargeTimeType(), charge.getChargeCalculationType(), charge.isPenalty()));
+ charges.add(charge.toLoanChargeData());
}
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId,
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/api/LoanProductsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/api/LoanProductsApiResource.java
index e9d381f0d..3d6aa4faf 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/api/LoanProductsApiResource.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/api/LoanProductsApiResource.java
@@ -57,12 +57,13 @@ import org.springframework.stereotype.Component;
public class LoanProductsApiResource {
private final Set LOAN_PRODUCT_DATA_PARAMETERS = new HashSet(Arrays.asList("id", "name", "description", "fundId",
- "fundName", "transactionProcessingStrategyId", "transactionProcessingStrategyName", "principal", "inArrearsTolerance",
- "numberOfRepayments", "repaymentEvery", "interestRatePerPeriod", "annualInterestRate", "repaymentFrequencyType",
- "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType", "charges", "createdOn",
- "lastModifedOn", "currencyOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions",
- "repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "transactionProcessingStrategyOptions",
- "chargeOptions", "accountingOptions", "accountingRule","accountingRuleOptions","accountingMappings","accountingMappingOptions"));
+ "fundName", "currency", "principal", "numberOfRepayments", "repaymentEvery", "repaymentFrequencyType", "interestRatePerPeriod",
+ "interestRateFrequencyType", "annualInterestRate", "amortizationType", "interestType", "interestCalculationPeriodType",
+ "inArrearsTolerance", "transactionProcessingStrategyId", "transactionProcessingStrategyName", "charges", "accountingRule",
+ "accountingMappings", "fundOptions", "currencyOptions", "repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions",
+ "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions",
+ "transactionProcessingStrategyOptions", "chargeOptions", "accountingOptions", "accountingRuleOptions",
+ "accountingMappingOptions"));
private final String resourceNameForPermissions = "LOANPRODUCT";
@@ -129,7 +130,7 @@ public class LoanProductsApiResource {
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
- public String retrieveNewLoanProductDetails(@Context final UriInfo uriInfo) {
+ public String retrieveTemplate(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions);
@@ -154,7 +155,8 @@ public class LoanProductsApiResource {
Map accountingMappings = null;
if (loanProduct.hasAccountingEnabled()) {
- accountingMappings = accountMappingReadPlatformService.fetchAccountMappingDetailsForLoanProduct(productId, loanProduct.accountingRuleType().getId().intValue());
+ accountingMappings = accountMappingReadPlatformService.fetchAccountMappingDetailsForLoanProduct(productId, loanProduct
+ .accountingRuleType().getId().intValue());
loanProduct = LoanProductData.withAccountingMappings(loanProduct, accountingMappings);
}
@@ -182,7 +184,6 @@ public class LoanProductsApiResource {
final boolean feeChargesOnly = true;
Collection chargeOptions = this.chargeReadPlatformService.retrieveLoanApplicableCharges(feeChargesOnly);
- chargeOptions.removeAll(productData.charges());
if (chargeOptions.isEmpty()) {
chargeOptions = null;
}
@@ -192,7 +193,6 @@ public class LoanProductsApiResource {
final List interestTypeOptions = dropdownReadPlatformService.retrieveLoanInterestTypeOptions();
final List interestCalculationPeriodTypeOptions = dropdownReadPlatformService
.retrieveLoanInterestRateCalculatedInPeriodOptions();
- final List loanTermFrequencyTypeOptions = dropdownReadPlatformService.retrieveLoanTermFrequencyTypeOptions();
final List repaymentFrequencyTypeOptions = dropdownReadPlatformService.retrieveRepaymentFrequencyTypeOptions();
final List interestRateFrequencyTypeOptions = dropdownReadPlatformService
.retrieveInterestRateFrequencyTypeOptions();
@@ -204,29 +204,29 @@ public class LoanProductsApiResource {
final Collection transactionProcessingStrategyOptions = this.dropdownReadPlatformService
.retreiveTransactionProcessingStrategies();
- Map> accountOptions= new HashMap>();
+ Map> accountOptions = new HashMap>();
List assetAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.ASSET);
if (assetAccountOptions.isEmpty()) {
assetAccountOptions = null;
}
accountOptions.put("assetAccountOptions", assetAccountOptions);
-
+
List incomeAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.INCOME);
if (incomeAccountOptions.isEmpty()) {
incomeAccountOptions = null;
}
accountOptions.put("incomeAccountOptions", incomeAccountOptions);
-
+
List expenseAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.EXPENSE);
if (expenseAccountOptions.isEmpty()) {
expenseAccountOptions = null;
}
accountOptions.put("expenseAccountOptions", expenseAccountOptions);
-
+
List accountingRuleTypeOptions = dropdownReadPlatformService.retrieveAccountingRuleTypeOptions();
return new LoanProductData(productData, chargeOptions, currencyOptions, amortizationTypeOptions, interestTypeOptions,
- interestCalculationPeriodTypeOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions,
- interestRateFrequencyTypeOptions, fundOptions, transactionProcessingStrategyOptions, accountOptions, accountingRuleTypeOptions,accountingMappings);
+ interestCalculationPeriodTypeOptions, repaymentFrequencyTypeOptions, interestRateFrequencyTypeOptions, fundOptions,
+ transactionProcessingStrategyOptions, accountOptions, accountingRuleTypeOptions, accountingMappings);
}
}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java
index 267581676..990f38113 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java
@@ -33,47 +33,46 @@ public class LoanProductData {
private final String description;
private final Long fundId;
private final String fundName;
+
+ // terms
private final CurrencyData currency;
private final BigDecimal principal;
private final Integer numberOfRepayments;
- private final Integer loanTermFrequency;
private final Integer repaymentEvery;
- private final EnumOptionData loanTermFrequencyType;
private final EnumOptionData repaymentFrequencyType;
- private final Long transactionProcessingStrategyId;
- private final String transactionProcessingStrategyName;
private final BigDecimal interestRatePerPeriod;
private final EnumOptionData interestRateFrequencyType;
private final BigDecimal annualInterestRate;
+
+ // settings
private final EnumOptionData amortizationType;
private final EnumOptionData interestType;
private final EnumOptionData interestCalculationPeriodType;
private final BigDecimal inArrearsTolerance;
+ private final Long transactionProcessingStrategyId;
+ private final String transactionProcessingStrategyName;
- private final EnumOptionData accountingRule;
-
+ // charges
private final Collection charges;
+ // accounting
+ private final EnumOptionData accountingRule;
+ @SuppressWarnings("unused")
+ private final Map accountingMappings;
+
// template related
- private final Collection currencyOptions;
private final Collection fundOptions;
- private final Collection transactionProcessingStrategyOptions;
+ private final Collection currencyOptions;
+ private final List repaymentFrequencyTypeOptions;
+ private final List interestRateFrequencyTypeOptions;
private final List amortizationTypeOptions;
private final List interestTypeOptions;
private final List interestCalculationPeriodTypeOptions;
- private final List repaymentFrequencyTypeOptions;
- private final List interestRateFrequencyTypeOptions;
- private final List loanTermFrequencyTypeOptions;
+ private final Collection transactionProcessingStrategyOptions;
private final Collection chargeOptions;
-
- // accounting related template fields
private final List accountingRuleOptions;
private final Map> accountingMappingOptions;
- // accounting related mapping fields
- @SuppressWarnings("unused")
- private final Map accountingMappings;
-
/**
* Used when returning lookup information about loan product for dropdowns.
*/
@@ -83,11 +82,9 @@ public class LoanProductData {
final BigDecimal principal = null;
final BigDecimal tolerance = null;
final Integer numberOfRepayments = null;
- final Integer loanTermFrequency = null;
final Integer repaymentEvery = null;
final BigDecimal interestRatePerPeriod = null;
final BigDecimal annualInterestRate = null;
- final EnumOptionData loanTermFrequencyType = null;
final EnumOptionData repaymentFrequencyType = null;
final EnumOptionData interestRateFrequencyType = null;
final EnumOptionData amortizationType = null;
@@ -100,10 +97,10 @@ public class LoanProductData {
final Collection charges = null;
final EnumOptionData accountingType = null;
- return new LoanProductData(id, name, description, currency, principal, tolerance, numberOfRepayments, loanTermFrequency,
- repaymentEvery, interestRatePerPeriod, annualInterestRate, loanTermFrequencyType, repaymentFrequencyType,
- interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName,
- transactionProcessingStrategyId, transactionProcessingStrategyName, charges, accountingType);
+ return new LoanProductData(id, name, description, currency, principal, tolerance, numberOfRepayments, repaymentEvery,
+ interestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
+ interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId,
+ transactionProcessingStrategyName, charges, accountingType);
}
public static LoanProductData sensibleDefaultsForNewLoanProductCreation() {
@@ -114,11 +111,9 @@ public class LoanProductData {
final BigDecimal principal = null;
final BigDecimal tolerance = null;
final Integer numberOfRepayments = null;
- final Integer loanTermFrequency = null;
final Integer repaymentEvery = null;
final BigDecimal interestRatePerPeriod = null;
final BigDecimal annualInterestRate = null;
- final EnumOptionData loanTermFrequencyType = LoanEnumerations.loanTermFrequencyType(PeriodFrequencyType.MONTHS);
final EnumOptionData repaymentFrequencyType = LoanEnumerations.repaymentFrequencyType(PeriodFrequencyType.MONTHS);
final EnumOptionData interestRateFrequencyType = LoanEnumerations.interestRateFrequencyType(PeriodFrequencyType.MONTHS);
final EnumOptionData amortizationType = LoanEnumerations.amortizationType(AmortizationMethod.EQUAL_INSTALLMENTS);
@@ -132,25 +127,24 @@ public class LoanProductData {
final Collection charges = null;
final EnumOptionData accountingType = LoanEnumerations.accountingRuleType(AccountingRuleType.NONE);
- return new LoanProductData(id, name, description, currency, principal, tolerance, numberOfRepayments, loanTermFrequency,
- repaymentEvery, interestRatePerPeriod, annualInterestRate, loanTermFrequencyType, repaymentFrequencyType,
- interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName,
- transactionProcessingStrategyId, transactionProcessingStrategyName, charges, accountingType);
+ return new LoanProductData(id, name, description, currency, principal, tolerance, numberOfRepayments, repaymentEvery,
+ interestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
+ interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId,
+ transactionProcessingStrategyName, charges, accountingType);
}
public static LoanProductData withAccountingMappings(final LoanProductData productData, final Map accountingMappings) {
return new LoanProductData(productData, productData.chargeOptions, productData.currencyOptions,
productData.amortizationTypeOptions, productData.interestTypeOptions, productData.interestCalculationPeriodTypeOptions,
- productData.loanTermFrequencyTypeOptions, productData.repaymentFrequencyTypeOptions,
- productData.interestRateFrequencyTypeOptions, productData.fundOptions, productData.transactionProcessingStrategyOptions,
- productData.accountingMappingOptions, productData.accountingRuleOptions, accountingMappings);
+ productData.repaymentFrequencyTypeOptions, productData.interestRateFrequencyTypeOptions, productData.fundOptions,
+ productData.transactionProcessingStrategyOptions, productData.accountingMappingOptions, productData.accountingRuleOptions,
+ accountingMappings);
}
public LoanProductData(final Long id, final String name, final String description, final CurrencyData currency,
- final BigDecimal principal, final BigDecimal tolerance, final Integer numberOfRepayments, final Integer loanTermFrequency,
- final Integer repaymentEvery, final BigDecimal interestRatePerPeriod, final BigDecimal annualInterestRate,
- final EnumOptionData loanTermFrequencyType, final EnumOptionData repaymentFrequencyType,
+ final BigDecimal principal, final BigDecimal tolerance, final Integer numberOfRepayments, final Integer repaymentEvery,
+ final BigDecimal interestRatePerPeriod, final BigDecimal annualInterestRate, final EnumOptionData repaymentFrequencyType,
final EnumOptionData interestRateFrequencyType, final EnumOptionData amortizationType, final EnumOptionData interestType,
final EnumOptionData interestCalculationPeriodType, final Long fundId, final String fundName,
final Long transactionProcessingStrategyId, final String transactionProcessingStrategyName,
@@ -162,11 +156,11 @@ public class LoanProductData {
this.principal = principal;
this.inArrearsTolerance = tolerance;
this.numberOfRepayments = numberOfRepayments;
- this.loanTermFrequency = loanTermFrequency;
+ // this.loanTermFrequency = loanTermFrequency;
this.repaymentEvery = repaymentEvery;
this.interestRatePerPeriod = interestRatePerPeriod;
this.annualInterestRate = annualInterestRate;
- this.loanTermFrequencyType = loanTermFrequencyType;
+ // this.loanTermFrequencyType = loanTermFrequencyType;
this.repaymentFrequencyType = repaymentFrequencyType;
this.interestRateFrequencyType = interestRateFrequencyType;
this.amortizationType = amortizationType;
@@ -186,7 +180,7 @@ public class LoanProductData {
this.amortizationTypeOptions = null;
this.interestTypeOptions = null;
this.interestCalculationPeriodTypeOptions = null;
- this.loanTermFrequencyTypeOptions = null;
+ // this.loanTermFrequencyTypeOptions = null;
this.repaymentFrequencyTypeOptions = null;
this.interestRateFrequencyTypeOptions = null;
@@ -198,31 +192,29 @@ public class LoanProductData {
public LoanProductData(final LoanProductData productData, final Collection chargeOptions,
final Collection currencyOptions, final List amortizationTypeOptions,
final List interestTypeOptions, final List interestCalculationPeriodTypeOptions,
- final List loanTermFrequencyTypeOptions, final List repaymentFrequencyTypeOptions,
- final List interestRateFrequencyTypeOptions, final Collection fundOptions,
- final Collection transactionProcessingStrategyOptions,
+ final List repaymentFrequencyTypeOptions, final List interestRateFrequencyTypeOptions,
+ final Collection fundOptions,
+ final Collection transactionStrategyOptions,
final Map> accountingMappingOptions, final List accountingRuleOptions,
final Map accountingMappings) {
this.id = productData.id;
this.name = productData.name;
this.description = productData.description;
+ this.fundId = productData.fundId;
+ this.fundName = productData.fundName;
+
this.principal = productData.principal;
this.inArrearsTolerance = productData.inArrearsTolerance;
this.numberOfRepayments = productData.numberOfRepayments;
- this.loanTermFrequency = productData.loanTermFrequency;
this.repaymentEvery = productData.repaymentEvery;
this.interestRatePerPeriod = productData.interestRatePerPeriod;
this.annualInterestRate = productData.annualInterestRate;
- this.loanTermFrequencyType = productData.loanTermFrequencyType;
this.repaymentFrequencyType = productData.repaymentFrequencyType;
this.interestRateFrequencyType = productData.interestRateFrequencyType;
this.amortizationType = productData.amortizationType;
this.interestType = productData.interestType;
this.interestCalculationPeriodType = productData.interestCalculationPeriodType;
- this.fundId = productData.fundId;
- this.fundName = productData.fundName;
- this.transactionProcessingStrategyId = productData.transactionProcessingStrategyId;
- this.transactionProcessingStrategyName = productData.transactionProcessingStrategyName;
+
this.charges = nullIfEmpty(productData.charges());
this.accountingRule = productData.accountingRule;
@@ -234,17 +226,32 @@ public class LoanProductData {
this.currency = productData.currency;
}
this.fundOptions = fundOptions;
- this.transactionProcessingStrategyOptions = transactionProcessingStrategyOptions;
+ this.transactionProcessingStrategyOptions = transactionStrategyOptions;
+ if (this.transactionProcessingStrategyOptions != null && this.transactionProcessingStrategyOptions.size() == 1) {
+ final List listOfOptions = new ArrayList(
+ this.transactionProcessingStrategyOptions);
+
+ this.transactionProcessingStrategyId = listOfOptions.get(0).id();
+ this.transactionProcessingStrategyName = listOfOptions.get(0).name();
+ } else {
+ this.transactionProcessingStrategyId = productData.transactionProcessingStrategyId;
+ this.transactionProcessingStrategyName = productData.transactionProcessingStrategyName;
+ }
+
this.amortizationTypeOptions = amortizationTypeOptions;
this.interestTypeOptions = interestTypeOptions;
this.interestCalculationPeriodTypeOptions = interestCalculationPeriodTypeOptions;
- this.loanTermFrequencyTypeOptions = loanTermFrequencyTypeOptions;
this.repaymentFrequencyTypeOptions = repaymentFrequencyTypeOptions;
this.interestRateFrequencyTypeOptions = interestRateFrequencyTypeOptions;
this.accountingMappingOptions = accountingMappingOptions;
this.accountingRuleOptions = accountingRuleOptions;
- this.accountingMappings = accountingMappings;
+
+ if (accountingMappings == null || accountingMappings.isEmpty()) {
+ this.accountingMappings = null;
+ } else {
+ this.accountingMappings = accountingMappings;
+ }
}
private Collection nullIfEmpty(final Collection charges) {
@@ -315,10 +322,6 @@ public class LoanProductData {
return numberOfRepayments;
}
- public Integer getLoanTermFrequency() {
- return loanTermFrequency;
- }
-
public Integer getRepaymentEvery() {
return repaymentEvery;
}
@@ -331,10 +334,6 @@ public class LoanProductData {
return annualInterestRate;
}
- public EnumOptionData getLoanTermFrequencyType() {
- return loanTermFrequencyType;
- }
-
public EnumOptionData getRepaymentFrequencyType() {
return repaymentFrequencyType;
}
@@ -359,10 +358,6 @@ public class LoanProductData {
return fundOptions;
}
- public Collection getTransactionProcessingStrategyOptions() {
- return transactionProcessingStrategyOptions;
- }
-
public List getAmortizationTypeOptions() {
return amortizationTypeOptions;
}
@@ -383,10 +378,6 @@ public class LoanProductData {
return interestRateFrequencyTypeOptions;
}
- public List getLoanTermFrequencyTypeOptions() {
- return loanTermFrequencyTypeOptions;
- }
-
public Collection getChargeOptions() {
return chargeOptions;
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/TransactionProcessingStrategyData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/TransactionProcessingStrategyData.java
index efa27ac55..eed61b0f9 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/TransactionProcessingStrategyData.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/TransactionProcessingStrategyData.java
@@ -5,13 +5,14 @@
*/
package org.mifosplatform.portfolio.loanproduct.data;
+/**
+ * Immutable data object representing a transaction strategy option for a loan.
+ */
public final class TransactionProcessingStrategyData {
- @SuppressWarnings("unused")
private final Long id;
@SuppressWarnings("unused")
private final String code;
- @SuppressWarnings("unused")
private final String name;
public TransactionProcessingStrategyData(final Long id, final String code, final String name) {
@@ -19,4 +20,12 @@ public final class TransactionProcessingStrategyData {
this.code = code;
this.name = name;
}
+
+ public Long id() {
+ return this.id;
+ }
+
+ public String name() {
+ return this.name;
+ }
}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java
index 0fae800ea..8bdcd386b 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java
@@ -6,7 +6,7 @@
package org.mifosplatform.portfolio.loanproduct.domain;
import java.math.BigDecimal;
-import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -29,6 +29,8 @@ import org.mifosplatform.portfolio.fund.domain.Fund;
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator;
import org.springframework.data.jpa.domain.AbstractPersistable;
+import com.google.gson.JsonArray;
+
/**
* Loan products allow for categorisation of an organisations loans into
* something meaningful to them.
@@ -39,7 +41,7 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
* They allow for constraints to be added at product level.
*/
@Entity
-@Table(name = "m_product_loan" , uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unq_name")})
+@Table(name = "m_product_loan", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unq_name") })
public class LoanProduct extends AbstractPersistable {
@ManyToOne
@@ -50,7 +52,7 @@ public class LoanProduct extends AbstractPersistable {
@JoinColumn(name = "loan_transaction_strategy_id", nullable = true)
private LoanTransactionProcessingStrategy transactionProcessingStrategy;
- @Column(name = "name", nullable = false , unique = true)
+ @Column(name = "name", nullable = false, unique = true)
private String name;
@Column(name = "description")
@@ -58,7 +60,7 @@ public class LoanProduct extends AbstractPersistable {
@ManyToMany
@JoinTable(name = "m_product_loan_charge", joinColumns = @JoinColumn(name = "product_loan_id"), inverseJoinColumns = @JoinColumn(name = "charge_id"))
- private Set charges;
+ private List charges;
@Embedded
private final LoanProductRelatedDetail loanProductRelatedDetail;
@@ -67,7 +69,7 @@ public class LoanProduct extends AbstractPersistable {
private Integer accountingRule;
public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy,
- final Set productCharges, final JsonCommand command, final AprCalculator aprCalculator) {
+ final List productCharges, final JsonCommand command, final AprCalculator aprCalculator) {
final String name = command.stringValueOfParameterNamed("name");
final String description = command.stringValueOfParameterNamed("description");
@@ -108,7 +110,7 @@ public class LoanProduct extends AbstractPersistable {
final BigDecimal defaultAnnualNominalInterestRate, final InterestMethod interestMethod,
final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final Integer repayEvery,
final PeriodFrequencyType repaymentFrequencyType, final Integer defaultNumberOfInstallments,
- final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance, final Set charges,
+ final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance, final List charges,
final AccountingRuleType accountingRuleType) {
this.fund = fund;
this.transactionProcessingStrategy = transactionProcessingStrategy;
@@ -136,10 +138,6 @@ public class LoanProduct extends AbstractPersistable {
return this.loanProductRelatedDetail.getCurrency();
}
- public Set getCharges() {
- return charges;
- }
-
public void update(final Fund fund) {
this.fund = fund;
}
@@ -148,8 +146,17 @@ public class LoanProduct extends AbstractPersistable {
this.transactionProcessingStrategy = strategy;
}
- public void update(final Set charges) {
- this.charges = charges;
+ public boolean update(final List newProductCharges) {
+ boolean updated = false;
+ if (this.charges != null) {
+ final Set setOfCharges = new HashSet(this.charges);
+
+ updated = setOfCharges.addAll(newProductCharges);
+ if (updated) {
+ this.charges = newProductCharges;
+ }
+ }
+ return updated;
}
public Integer getAccountingType() {
@@ -202,30 +209,17 @@ public class LoanProduct extends AbstractPersistable {
}
final String chargesParamName = "charges";
- if (command.isChangeInArrayParameterNamed(chargesParamName, getChargesIds())) {
- final String[] newValue = command.arrayValueOfParameterNamed(chargesParamName);
- actualChanges.put(chargesParamName, newValue);
+ if (command.hasParameter(chargesParamName)) {
+ JsonArray jsonArray = command.arrayOfParameterNamed(chargesParamName);
+ if (jsonArray != null) {
+
+ }
+ actualChanges.put(chargesParamName, command.jsonFragment(chargesParamName));
}
return actualChanges;
}
- private String[] getChargesIds() {
- final List chargeIds = new ArrayList();
-
- if (this.charges != null) {
- for (Charge charge : this.charges) {
- chargeIds.add(charge.getId().toString());
- }
- }
-
- return chargeIds.toArray(new String[chargeIds.size()]);
- }
-
- public boolean isAccountingEnabled() {
- return !AccountingRuleType.NONE.getValue().equals(this.accountingRule);
- }
-
public boolean isCashBasedAccountingEnabled() {
return AccountingRuleType.CASH_BASED.getValue().equals(this.accountingRule);
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/serialization/LoanProductCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/serialization/LoanProductCommandFromApiJsonDeserializer.java
index 377c0bcd0..51a571ca8 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/serialization/LoanProductCommandFromApiJsonDeserializer.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/serialization/LoanProductCommandFromApiJsonDeserializer.java
@@ -35,10 +35,10 @@ public final class LoanProductCommandFromApiJsonDeserializer {
/**
* The parameters supported for this command.
*/
- private final Set supportedParameters = new HashSet(Arrays.asList("name", "description", "fundId",
- "transactionProcessingStrategyId", "currencyCode", "digitsAfterDecimal", "principal", "inArrearsTolerance",
- "interestRatePerPeriod", "repaymentEvery", "numberOfRepayments", "repaymentFrequencyType", "interestRateFrequencyType",
- "amortizationType", "interestType", "interestCalculationPeriodType", "charges", "locale", "accountingRule",
+ private final Set supportedParameters = new HashSet(Arrays.asList("locale", "name", "description", "fundId",
+ "currencyCode", "digitsAfterDecimal", "principal", "repaymentEvery", "numberOfRepayments", "repaymentFrequencyType",
+ "interestRatePerPeriod", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType",
+ "inArrearsTolerance", "transactionProcessingStrategyId", "charges", "accountingRule",
LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(),
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(),
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(),
@@ -74,6 +74,7 @@ public final class LoanProductCommandFromApiJsonDeserializer {
baseDataValidator.reset().parameter("fundId").value(fundId).ignoreIfNull().integerGreaterThanZero();
}
+ // terms
final String currencyCode = fromApiJsonHelper.extractStringNamed("currencyCode", element);
baseDataValidator.reset().parameter("currencyCode").value(currencyCode).notBlank().notExceedingLengthOf(3);
@@ -83,12 +84,6 @@ public final class LoanProductCommandFromApiJsonDeserializer {
final BigDecimal principal = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("principal", element);
baseDataValidator.reset().parameter("principal").value(principal).notNull().positiveAmount();
- final BigDecimal inArrearsTolerance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("inArrearsTolerance", element);
- baseDataValidator.reset().parameter("inArrearsTolerance").value(inArrearsTolerance).ignoreIfNull().zeroOrPositiveAmount();
-
- final BigDecimal interestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("interestRatePerPeriod", element);
- baseDataValidator.reset().parameter("interestRatePerPeriod").value(interestRatePerPeriod).notNull().zeroOrPositiveAmount();
-
final Integer numberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed("numberOfRepayments", element);
baseDataValidator.reset().parameter("numberOfRepayments").value(numberOfRepayments).notNull().integerGreaterThanZero();
@@ -99,14 +94,14 @@ public final class LoanProductCommandFromApiJsonDeserializer {
.extractIntegerNamed("repaymentFrequencyType", element, Locale.getDefault());
baseDataValidator.reset().parameter("repaymentFrequencyType").value(repaymentFrequencyType).notNull().inMinMaxRange(0, 3);
- final Long transactionProcessingStrategyId = fromApiJsonHelper.extractLongNamed("transactionProcessingStrategyId", element);
- baseDataValidator.reset().parameter("transactionProcessingStrategyId").value(transactionProcessingStrategyId).notNull()
- .integerGreaterThanZero();
+ final BigDecimal interestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("interestRatePerPeriod", element);
+ baseDataValidator.reset().parameter("interestRatePerPeriod").value(interestRatePerPeriod).notNull().zeroOrPositiveAmount();
final Integer interestRateFrequencyType = fromApiJsonHelper.extractIntegerNamed("interestRateFrequencyType", element,
Locale.getDefault());
baseDataValidator.reset().parameter("interestRateFrequencyType").value(interestRateFrequencyType).notNull().inMinMaxRange(0, 3);
+ // settings
final Integer amortizationType = fromApiJsonHelper.extractIntegerNamed("amortizationType", element, Locale.getDefault());
baseDataValidator.reset().parameter("amortizationType").value(amortizationType).notNull().inMinMaxRange(0, 1);
@@ -118,6 +113,13 @@ public final class LoanProductCommandFromApiJsonDeserializer {
baseDataValidator.reset().parameter("interestCalculationPeriodType").value(interestCalculationPeriodType).notNull()
.inMinMaxRange(0, 1);
+ final BigDecimal inArrearsTolerance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("inArrearsTolerance", element);
+ baseDataValidator.reset().parameter("inArrearsTolerance").value(inArrearsTolerance).ignoreIfNull().zeroOrPositiveAmount();
+
+ final Long transactionProcessingStrategyId = fromApiJsonHelper.extractLongNamed("transactionProcessingStrategyId", element);
+ baseDataValidator.reset().parameter("transactionProcessingStrategyId").value(transactionProcessingStrategyId).notNull()
+ .integerGreaterThanZero();
+
// accounting related data validation
final Integer accountingRuleType = fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault());
baseDataValidator.reset().parameter("accountingRule").value(accountingRuleType).notNull().inMinMaxRange(1, 3);
@@ -176,7 +178,7 @@ public final class LoanProductCommandFromApiJsonDeserializer {
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
- public void validateForUpdate(String json) {
+ public void validateForUpdate(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken