MIFOSX-117: integrate andreas work on UGD.
This commit is contained in:
@@ -20,3 +20,4 @@ rebel.xml
|
|||||||
*.DS_Store
|
*.DS_Store
|
||||||
*.ini
|
*.ini
|
||||||
*~
|
*~
|
||||||
|
.metadata
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
DROP TABLE IF EXISTS `m_template`;
|
||||||
|
CREATE TABLE `m_template` (
|
||||||
|
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`text` longtext COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`entity` int(11) DEFAULT NULL,
|
||||||
|
`type` int(11) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `unq_name` (`name`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `m_templatemappers`;
|
||||||
|
CREATE TABLE `m_templatemappers` (
|
||||||
|
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||||
|
`mapperkey` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
|
`mapperorder` int(11) DEFAULT NULL,
|
||||||
|
`mappervalue` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `m_template_m_templatemappers`;
|
||||||
|
CREATE TABLE `m_template_m_templatemappers` (
|
||||||
|
`m_template_id` bigint(20) NOT NULL,
|
||||||
|
`mappers_id` bigint(20) NOT NULL,
|
||||||
|
UNIQUE KEY `mappers_id` (`mappers_id`),
|
||||||
|
KEY (`mappers_id`),
|
||||||
|
KEY (`m_template_id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||||
|
VALUES ('organistion', 'DELETE_TEMPLATE', 'TEMPLATE', 'DELETE', 0),
|
||||||
|
('organistion', 'CREATE_TEMPLATE', 'TEMPLATE', 'CREATE', 0),
|
||||||
|
('organistion', 'UPDATE_TEMPLATE', 'TEMPLATE', 'UPDATE', 0),
|
||||||
|
('organistion', 'READ_TEMPLATE', 'TEMPLATE', 'READ', 0);
|
||||||
@@ -99,6 +99,7 @@ dependencies {
|
|||||||
[group: 'org.springframework', name: 'spring-core', version: springVersion],
|
[group: 'org.springframework', name: 'spring-core', version: springVersion],
|
||||||
[group: 'org.springframework', name: 'spring-aspects', version: springVersion],
|
[group: 'org.springframework', name: 'spring-aspects', version: springVersion],
|
||||||
[group: 'org.springframework', name: 'spring-web', version: springVersion],
|
[group: 'org.springframework', name: 'spring-web', version: springVersion],
|
||||||
|
[group: 'org.springframework', name: 'spring-test', version: springVersion],
|
||||||
[group: 'org.springframework.security', name: 'spring-security-core', version: springSecurityVersion],
|
[group: 'org.springframework.security', name: 'spring-security-core', version: springSecurityVersion],
|
||||||
[group: 'org.springframework.security', name: 'spring-security-web', version: springSecurityVersion],
|
[group: 'org.springframework.security', name: 'spring-security-web', version: springSecurityVersion],
|
||||||
[group: 'org.springframework.security', name: 'spring-security-config', version: springSecurityVersion],
|
[group: 'org.springframework.security', name: 'spring-security-config', version: springSecurityVersion],
|
||||||
@@ -162,8 +163,8 @@ dependencies {
|
|||||||
[group: 'com.googlecode.flyway', name: 'flyway-maven-plugin', version: '2.1.1'],
|
[group: 'com.googlecode.flyway', name: 'flyway-maven-plugin', version: '2.1.1'],
|
||||||
[group: 'org.quartz-scheduler', name: 'quartz', version: '2.1.7'],
|
[group: 'org.quartz-scheduler', name: 'quartz', version: '2.1.7'],
|
||||||
[group: 'com.amazonaws', name: 'aws-java-sdk', version: '1.2.1'],
|
[group: 'com.amazonaws', name: 'aws-java-sdk', version: '1.2.1'],
|
||||||
|
[group: 'net.sf.ehcache', name: 'ehcache', version: '2.7.2'],
|
||||||
[group: 'net.sf.ehcache', name: 'ehcache', version: '2.7.2']
|
[group: 'com.github.spullara.mustache.java', name: 'compiler', version: '0.8.12']
|
||||||
)
|
)
|
||||||
|
|
||||||
testCompile 'junit:junit:4.10',
|
testCompile 'junit:junit:4.10',
|
||||||
|
|||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
package org.mifosplatform.integrationtests;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mifosplatform.integrationtests.common.Utils;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||||
|
import com.jayway.restassured.builder.ResponseSpecBuilder;
|
||||||
|
import com.jayway.restassured.http.ContentType;
|
||||||
|
import com.jayway.restassured.specification.RequestSpecification;
|
||||||
|
import com.jayway.restassured.specification.ResponseSpecification;
|
||||||
|
|
||||||
|
public class TemplateIntegrationTest {
|
||||||
|
|
||||||
|
private final String GET_TEMPLATES_URL = "/mifosng-provider/api/v1/templates?tenantIdentifier=default";
|
||||||
|
private final String GET_TEMPLATE_ID_URL = "/mifosng-provider/api/v1/templates/%s?tenantIdentifier=default";
|
||||||
|
private final String RESPONSE_ATTRIBUTE_NAME = "name";
|
||||||
|
|
||||||
|
private ResponseSpecification responseSpec;
|
||||||
|
private RequestSpecification requestSpec;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
|
||||||
|
Utils.initializeRESTAssured();
|
||||||
|
requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
|
||||||
|
requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
|
||||||
|
responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
|
||||||
|
HashMap<String, String> metadata = new HashMap<String, String>();
|
||||||
|
metadata.put("user", "resource_url");
|
||||||
|
HashMap<String, Object> map = new HashMap<String, Object>();
|
||||||
|
map.put("name", "foo");
|
||||||
|
map.put("text", "Hello {{template}}");
|
||||||
|
map.put("mappers", metadata);
|
||||||
|
|
||||||
|
ArrayList<?> get = Utils.performServerGet(requestSpec, responseSpec, GET_TEMPLATES_URL, "");
|
||||||
|
int entriesBeforeTest = get.size();
|
||||||
|
|
||||||
|
Integer id = Utils.performServerPost(requestSpec, responseSpec, GET_TEMPLATES_URL, new Gson().toJson(map), "resourceId");
|
||||||
|
|
||||||
|
String templateUrlForId = String.format(GET_TEMPLATE_ID_URL, id);
|
||||||
|
|
||||||
|
String getrequest2 = Utils.performServerGet(requestSpec, responseSpec, templateUrlForId, RESPONSE_ATTRIBUTE_NAME);
|
||||||
|
|
||||||
|
Assert.assertTrue(getrequest2.equals("foo"));
|
||||||
|
|
||||||
|
Utils.performServerDelete(requestSpec, responseSpec, templateUrlForId, "");
|
||||||
|
|
||||||
|
get = Utils.performServerGet(requestSpec, responseSpec, GET_TEMPLATES_URL, "");
|
||||||
|
int entriesAfterTest = get.size();
|
||||||
|
|
||||||
|
Assert.assertEquals(entriesBeforeTest, entriesAfterTest);
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-2
@@ -26,6 +26,7 @@ public class CommandWrapper {
|
|||||||
private final String supportedEntityType;
|
private final String supportedEntityType;
|
||||||
private final Long supportedEntityId;
|
private final Long supportedEntityId;
|
||||||
private final Long productId;
|
private final Long productId;
|
||||||
|
private Long templateId;
|
||||||
|
|
||||||
public static CommandWrapper wrap(final String actionName, final String entityName, final Long resourceId, final Long subresourceId) {
|
public static CommandWrapper wrap(final String actionName, final String entityName, final Long resourceId, final Long subresourceId) {
|
||||||
return new CommandWrapper(null, actionName, entityName, resourceId, subresourceId, null, null);
|
return new CommandWrapper(null, actionName, entityName, resourceId, subresourceId, null, null);
|
||||||
@@ -56,13 +57,12 @@ public class CommandWrapper {
|
|||||||
this.json = null;
|
this.json = null;
|
||||||
this.transactionId = null;
|
this.transactionId = null;
|
||||||
this.productId = productId;
|
this.productId = productId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandWrapper(final Long officeId, final Long groupId, final Long clientId, final Long loanId, final Long savingsId,
|
public CommandWrapper(final Long officeId, final Long groupId, final Long clientId, final Long loanId, final Long savingsId,
|
||||||
final String actionName, final String entityName, final Long entityId, final Long subentityId, final Long codeId,
|
final String actionName, final String entityName, final Long entityId, final Long subentityId, final Long codeId,
|
||||||
final String supportedEntityType, final Long supportedEntityId, final String href, final String json,
|
final String supportedEntityType, final Long supportedEntityId, final String href, final String json,
|
||||||
final String transactionId, final Long productId) {
|
final String transactionId, final Long productId, final Long templateId) {
|
||||||
this.commandId = null;
|
this.commandId = null;
|
||||||
this.officeId = officeId;
|
this.officeId = officeId;
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
@@ -81,6 +81,7 @@ public class CommandWrapper {
|
|||||||
this.json = json;
|
this.json = json;
|
||||||
this.transactionId = transactionId;
|
this.transactionId = transactionId;
|
||||||
this.productId = productId;
|
this.productId = productId;
|
||||||
|
this.templateId = templateId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long commandId() {
|
public Long commandId() {
|
||||||
@@ -143,6 +144,10 @@ public class CommandWrapper {
|
|||||||
return this.transactionId;
|
return this.transactionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getTemplateId() {
|
||||||
|
return this.templateId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getEntityName() {
|
public String getEntityName() {
|
||||||
return this.entityName;
|
return this.entityName;
|
||||||
}
|
}
|
||||||
@@ -321,6 +326,10 @@ public class CommandWrapper {
|
|||||||
return this.entityName.equalsIgnoreCase("COLLATERAL");
|
return this.entityName.equalsIgnoreCase("COLLATERAL");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTemplateRessource() {
|
||||||
|
return this.entityName.equalsIgnoreCase("Template");
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isApproveLoanApplication() {
|
public boolean isApproveLoanApplication() {
|
||||||
return this.actionName.equalsIgnoreCase("APPROVE") && this.entityName.equalsIgnoreCase("LOAN");
|
return this.actionName.equalsIgnoreCase("APPROVE") && this.entityName.equalsIgnoreCase("LOAN");
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-1
@@ -26,11 +26,12 @@ public class CommandWrapperBuilder {
|
|||||||
private String supportedEntityType;
|
private String supportedEntityType;
|
||||||
private Long supportedEntityId;
|
private Long supportedEntityId;
|
||||||
private Long productId;
|
private Long productId;
|
||||||
|
private Long templateId;
|
||||||
|
|
||||||
public CommandWrapper build() {
|
public CommandWrapper build() {
|
||||||
return new CommandWrapper(this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, this.actionName,
|
return new CommandWrapper(this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, this.actionName,
|
||||||
this.entityName, this.entityId, this.subentityId, this.codeId, this.supportedEntityType, this.supportedEntityId, this.href,
|
this.entityName, this.entityId, this.subentityId, this.codeId, this.supportedEntityType, this.supportedEntityId, this.href,
|
||||||
this.json, this.transactionId, this.productId);
|
this.json, this.transactionId, this.productId, this.templateId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandWrapperBuilder withLoanId(final Long withLoanId) {
|
public CommandWrapperBuilder withLoanId(final Long withLoanId) {
|
||||||
@@ -1305,6 +1306,33 @@ public class CommandWrapperBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CommandWrapperBuilder createTemplate() {
|
||||||
|
this.actionName = "CREATE";
|
||||||
|
this.entityName = "TEMPLATE";
|
||||||
|
this.entityId = null;
|
||||||
|
this.templateId = null;
|
||||||
|
this.href = "/templates";
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandWrapperBuilder updateTemplate(final Long templateId) {
|
||||||
|
this.actionName = "UPDATE";
|
||||||
|
this.entityName = "TEMPLATE";
|
||||||
|
this.entityId = templateId;
|
||||||
|
this.templateId = templateId;
|
||||||
|
this.href = "/templates/" + templateId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandWrapperBuilder deleteTemplate(final Long templateId) {
|
||||||
|
this.actionName = "DELETE";
|
||||||
|
this.entityName = "TEMPLATE";
|
||||||
|
this.entityId = templateId;
|
||||||
|
this.templateId = templateId;
|
||||||
|
this.href = "/templates/" + templateId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public CommandWrapperBuilder assignClientStaff(final Long clientId) {
|
public CommandWrapperBuilder assignClientStaff(final Long clientId) {
|
||||||
this.actionName = "ASSIGNSTAFF";
|
this.actionName = "ASSIGNSTAFF";
|
||||||
this.entityName = "CLIENT";
|
this.entityName = "CLIENT";
|
||||||
|
|||||||
+23
-8
@@ -144,7 +144,6 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
|||||||
throw new UnsupportedCommandException(wrapper.commandName());
|
throw new UnsupportedCommandException(wrapper.commandName());
|
||||||
}
|
}
|
||||||
} else if (wrapper.isClientIdentifierResource()) {
|
} else if (wrapper.isClientIdentifierResource()) {
|
||||||
|
|
||||||
if (wrapper.isCreate()) {
|
if (wrapper.isCreate()) {
|
||||||
handler = this.applicationContext.getBean("createClientIdentifierCommandHandler", NewCommandSourceHandler.class);
|
handler = this.applicationContext.getBean("createClientIdentifierCommandHandler", NewCommandSourceHandler.class);
|
||||||
} else if (wrapper.isUpdate()) {
|
} else if (wrapper.isUpdate()) {
|
||||||
@@ -501,15 +500,12 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
|||||||
throw new UnsupportedCommandException(wrapper.commandName());
|
throw new UnsupportedCommandException(wrapper.commandName());
|
||||||
}
|
}
|
||||||
} else if (wrapper.isCollectionSheetResource()) {
|
} else if (wrapper.isCollectionSheetResource()) {
|
||||||
|
|
||||||
if (wrapper.isUpdate()) {
|
if (wrapper.isUpdate()) {
|
||||||
handler = this.applicationContext.getBean("updateCollectionSheetCommandHandler", NewCommandSourceHandler.class);
|
handler = this.applicationContext.getBean("updateCollectionSheetCommandHandler", NewCommandSourceHandler.class);
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedCommandException(wrapper.commandName());
|
throw new UnsupportedCommandException(wrapper.commandName());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (wrapper.isReportResource()) {
|
} else if (wrapper.isReportResource()) {
|
||||||
|
|
||||||
if (wrapper.isCreate()) {
|
if (wrapper.isCreate()) {
|
||||||
handler = this.applicationContext.getBean("createReportCommandHandler", NewCommandSourceHandler.class);
|
handler = this.applicationContext.getBean("createReportCommandHandler", NewCommandSourceHandler.class);
|
||||||
} else if (wrapper.isUpdate()) {
|
} else if (wrapper.isUpdate()) {
|
||||||
@@ -519,9 +515,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
|||||||
} else {
|
} else {
|
||||||
throw new UnsupportedCommandException(wrapper.commandName());
|
throw new UnsupportedCommandException(wrapper.commandName());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (wrapper.isAccountingRuleResource()) {
|
} else if (wrapper.isAccountingRuleResource()) {
|
||||||
|
|
||||||
if (wrapper.isCreate()) {
|
if (wrapper.isCreate()) {
|
||||||
handler = this.applicationContext.getBean("createAccountingRuleCommandHandler", NewCommandSourceHandler.class);
|
handler = this.applicationContext.getBean("createAccountingRuleCommandHandler", NewCommandSourceHandler.class);
|
||||||
} else if (wrapper.isUpdate()) {
|
} else if (wrapper.isUpdate()) {
|
||||||
@@ -531,7 +525,6 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
|||||||
} else {
|
} else {
|
||||||
throw new UnsupportedCommandException(wrapper.commandName());
|
throw new UnsupportedCommandException(wrapper.commandName());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (wrapper.isXBRLMappingResource()) {
|
} else if (wrapper.isXBRLMappingResource()) {
|
||||||
if (wrapper.isUpdate()) {
|
if (wrapper.isUpdate()) {
|
||||||
handler = this.applicationContext.getBean("updateTaxonomyMappingCommandHandler", NewCommandSourceHandler.class);
|
handler = this.applicationContext.getBean("updateTaxonomyMappingCommandHandler", NewCommandSourceHandler.class);
|
||||||
@@ -539,7 +532,6 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
|||||||
throw new UnsupportedCommandException(wrapper.commandName());
|
throw new UnsupportedCommandException(wrapper.commandName());
|
||||||
}
|
}
|
||||||
} else if (wrapper.isHolidayResource()) {
|
} else if (wrapper.isHolidayResource()) {
|
||||||
|
|
||||||
if (wrapper.isCreate()) {
|
if (wrapper.isCreate()) {
|
||||||
handler = this.applicationContext.getBean("createHolidayCommandHandler", NewCommandSourceHandler.class);
|
handler = this.applicationContext.getBean("createHolidayCommandHandler", NewCommandSourceHandler.class);
|
||||||
}
|
}
|
||||||
@@ -577,6 +569,29 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
|||||||
} else {
|
} else {
|
||||||
throw new UnsupportedCommandException(wrapper.commandName());
|
throw new UnsupportedCommandException(wrapper.commandName());
|
||||||
}
|
}
|
||||||
|
} else if (wrapper.isTemplateRessource()) {
|
||||||
|
|
||||||
|
if (wrapper.isCreate()) {
|
||||||
|
handler = this.applicationContext.getBean("createTemplateCommandHandler", NewCommandSourceHandler.class);
|
||||||
|
} else if (wrapper.isUpdate()) {
|
||||||
|
handler = this.applicationContext.getBean("updateTemplateCommandHandler", NewCommandSourceHandler.class);
|
||||||
|
} else if (wrapper.isDelete()) {
|
||||||
|
handler = this.applicationContext.getBean("deleteTemplateCommandHandler", NewCommandSourceHandler.class);
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedCommandException(wrapper.commandName());
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (wrapper.isTemplateRessource()) {
|
||||||
|
if (wrapper.isCreate()) {
|
||||||
|
handler = this.applicationContext.getBean("createTemplateCommandHandler", NewCommandSourceHandler.class);
|
||||||
|
} else if (wrapper.isUpdate()) {
|
||||||
|
handler = this.applicationContext.getBean("updateTemplateCommandHandler", NewCommandSourceHandler.class);
|
||||||
|
} else if (wrapper.isDelete()) {
|
||||||
|
handler = this.applicationContext.getBean("deleteTemplateCommandHandler", NewCommandSourceHandler.class);
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedCommandException(wrapper.commandName());
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
throw new UnsupportedCommandException(wrapper.commandName());
|
throw new UnsupportedCommandException(wrapper.commandName());
|
||||||
|
|||||||
+8
@@ -10,6 +10,7 @@ import java.math.BigDecimal;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.lang.ObjectUtils;
|
import org.apache.commons.lang.ObjectUtils;
|
||||||
@@ -23,6 +24,7 @@ import org.mifosplatform.infrastructure.security.service.PlatformPasswordEncoder
|
|||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable representation of a command.
|
* Immutable representation of a command.
|
||||||
@@ -314,6 +316,12 @@ public final class JsonCommand {
|
|||||||
return this.fromApiJsonHelper.extractStringNamed(parameterName, this.parsedCommand);
|
return this.fromApiJsonHelper.extractStringNamed(parameterName, this.parsedCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> mapValueOfParameterNamed(final String json) {
|
||||||
|
final Type typeOfMap = new TypeToken<Map<String, String>>() {}.getType();
|
||||||
|
final Map<String, String> value = this.fromApiJsonHelper.extractDataMap(typeOfMap, json);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isChangeInBigDecimalParameterNamedDefaultingZeroToNull(final String parameterName, final BigDecimal existingValue) {
|
public boolean isChangeInBigDecimalParameterNamedDefaultingZeroToNull(final String parameterName, final BigDecimal existingValue) {
|
||||||
boolean isChanged = false;
|
boolean isChanged = false;
|
||||||
if (parameterExists(parameterName)) {
|
if (parameterExists(parameterName)) {
|
||||||
|
|||||||
+206
@@ -0,0 +1,206 @@
|
|||||||
|
package org.mifosplatform.template.api;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.DefaultValue;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.map.ObjectMapper;
|
||||||
|
import org.mifosplatform.commands.domain.CommandWrapper;
|
||||||
|
import org.mifosplatform.commands.service.CommandWrapperBuilder;
|
||||||
|
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||||
|
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||||
|
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||||
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
|
import org.mifosplatform.template.data.TemplateData;
|
||||||
|
import org.mifosplatform.template.domain.Template;
|
||||||
|
import org.mifosplatform.template.domain.TemplateEntity;
|
||||||
|
import org.mifosplatform.template.domain.TemplateType;
|
||||||
|
import org.mifosplatform.template.service.TemplateDomainService;
|
||||||
|
import org.mifosplatform.template.service.TemplateMergeService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Path("/templates")
|
||||||
|
@Component
|
||||||
|
@Scope("singleton")
|
||||||
|
public class TemplatesApiResource {
|
||||||
|
|
||||||
|
private final Set<String> RESPONSE_TEMPLATES_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id"));
|
||||||
|
private final Set<String> RESPONSE_TEMPLATE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "entities", "types", "template"));
|
||||||
|
private final String RESOURCEN_NAME_FOR_PERMISSION = "template";
|
||||||
|
|
||||||
|
private final PlatformSecurityContext context;
|
||||||
|
private final DefaultToApiJsonSerializer<Template> toApiJsonSerializer;
|
||||||
|
private final DefaultToApiJsonSerializer<TemplateData> templateDataApiJsonSerializer;
|
||||||
|
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||||
|
private final TemplateDomainService templateService;
|
||||||
|
private final TemplateMergeService templateMergeService;
|
||||||
|
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public TemplatesApiResource(final PlatformSecurityContext context, final DefaultToApiJsonSerializer<Template> toApiJsonSerializer,
|
||||||
|
final DefaultToApiJsonSerializer<TemplateData> templateDataApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||||
|
final TemplateDomainService templateService, final TemplateMergeService templateMergeService,
|
||||||
|
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
|
||||||
|
|
||||||
|
this.context = context;
|
||||||
|
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||||
|
this.templateDataApiJsonSerializer = templateDataApiJsonSerializer;
|
||||||
|
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
||||||
|
this.templateService = templateService;
|
||||||
|
this.templateMergeService = templateMergeService;
|
||||||
|
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
public String getTemplates(@DefaultValue("-1") @QueryParam("typeId") final int typeId,
|
||||||
|
@DefaultValue("-1") @QueryParam("entityId") final int entityId, @Context final UriInfo uriInfo) {
|
||||||
|
|
||||||
|
this.context.authenticatedUser().validateHasReadPermission(this.RESOURCEN_NAME_FOR_PERMISSION);
|
||||||
|
|
||||||
|
List<Template> templates = new ArrayList<Template>();
|
||||||
|
|
||||||
|
if (typeId != -1 && entityId != -1) {
|
||||||
|
templates = this.templateService.getAllByEntityAndType(TemplateEntity.values()[entityId], TemplateType.values()[typeId]);
|
||||||
|
} else {
|
||||||
|
templates = this.templateService.getAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||||
|
return this.toApiJsonSerializer.serialize(settings, templates, this.RESPONSE_TEMPLATES_DATA_PARAMETERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("template")
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
public String getTemplatesByTemplate(@Context final UriInfo uriInfo) {
|
||||||
|
|
||||||
|
this.context.authenticatedUser().validateHasReadPermission(this.RESOURCEN_NAME_FOR_PERMISSION);
|
||||||
|
|
||||||
|
final TemplateData templateData = TemplateData.template();
|
||||||
|
|
||||||
|
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||||
|
return this.templateDataApiJsonSerializer.serialize(settings, templateData, this.RESPONSE_TEMPLATES_DATA_PARAMETERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("{templateId}")
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
public String getTemplate(@PathParam("templateId") final Long templateId, @Context final UriInfo uriInfo) {
|
||||||
|
|
||||||
|
this.context.authenticatedUser().validateHasReadPermission(this.RESOURCEN_NAME_FOR_PERMISSION);
|
||||||
|
|
||||||
|
final Template template = this.templateService.getById(templateId);
|
||||||
|
|
||||||
|
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||||
|
return this.toApiJsonSerializer.serialize(settings, template, this.RESPONSE_TEMPLATES_DATA_PARAMETERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("{templateId}/template")
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
public String getTemplateByTemplate(@PathParam("templateId") final Long templateId, @Context final UriInfo uriInfo) {
|
||||||
|
|
||||||
|
this.context.authenticatedUser().validateHasReadPermission(this.RESOURCEN_NAME_FOR_PERMISSION);
|
||||||
|
|
||||||
|
final TemplateData template = TemplateData.template(this.templateService.getById(templateId));
|
||||||
|
|
||||||
|
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||||
|
System.out.println("QUERY_PARAMETER: " + uriInfo.getQueryParameters());
|
||||||
|
System.out.println("SETTINGS: " + settings);
|
||||||
|
System.out.println("FOO: " + this.templateDataApiJsonSerializer.serialize(settings, template, this.RESPONSE_TEMPLATE_DATA_PARAMETERS));
|
||||||
|
|
||||||
|
return this.templateDataApiJsonSerializer.serialize(settings, template, this.RESPONSE_TEMPLATE_DATA_PARAMETERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("{templateId}")
|
||||||
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
public String saveTemplate(@PathParam("templateId") final Long templateId, final String apiRequestBodyAsJson) {
|
||||||
|
|
||||||
|
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateTemplate(templateId).withJson(apiRequestBodyAsJson).build();
|
||||||
|
|
||||||
|
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||||
|
|
||||||
|
return this.toApiJsonSerializer.serialize(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DELETE
|
||||||
|
@Path("{templateId}")
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
public String deleteTemplate(@PathParam("templateId") final Long templateId) {
|
||||||
|
|
||||||
|
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteTemplate(templateId).build();
|
||||||
|
|
||||||
|
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||||
|
|
||||||
|
return this.toApiJsonSerializer.serialize(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
public String createTemplate(final String apiRequestBodyAsJson) {
|
||||||
|
final CommandWrapper commandRequest = new CommandWrapperBuilder().createTemplate().withJson(apiRequestBodyAsJson).build();
|
||||||
|
|
||||||
|
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||||
|
|
||||||
|
return this.toApiJsonSerializer.serialize(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("{templateId}")
|
||||||
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
|
@Produces({ MediaType.TEXT_HTML })
|
||||||
|
public String mergeTemplate(@PathParam("templateId") final Long templateId, @Context final UriInfo uriInfo,
|
||||||
|
final String apiRequestBodyAsJson) throws MalformedURLException, IOException {
|
||||||
|
|
||||||
|
final Template template = this.templateService.getById(templateId);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final
|
||||||
|
HashMap<String, Object> result = new ObjectMapper().readValue(apiRequestBodyAsJson, HashMap.class);
|
||||||
|
|
||||||
|
final MultivaluedMap<String, String> parameters = uriInfo.getQueryParameters();
|
||||||
|
final Map<String, Object> parametersMap = new HashMap<String, Object>();
|
||||||
|
for (final Map.Entry<String, List<String>> entry : parameters.entrySet()) {
|
||||||
|
|
||||||
|
if (entry.getValue().size() == 1) {
|
||||||
|
parametersMap.put(entry.getKey(), entry.getValue().get(0));
|
||||||
|
} else {
|
||||||
|
parametersMap.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parametersMap.put("BASE_URI", uriInfo.getBaseUri());
|
||||||
|
parametersMap.putAll(result);
|
||||||
|
return this.templateMergeService.compile(template, parametersMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package org.mifosplatform.template.data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.mifosplatform.template.domain.Template;
|
||||||
|
import org.mifosplatform.template.domain.TemplateEntity;
|
||||||
|
import org.mifosplatform.template.domain.TemplateType;
|
||||||
|
|
||||||
|
public class TemplateData {
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final List<Map<String, Object>> entities;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final List<Map<String, Object>> types;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final Template template;
|
||||||
|
|
||||||
|
private TemplateData(final Template template) {
|
||||||
|
this.template = template;
|
||||||
|
this.entities = getEntites();
|
||||||
|
this.types = getTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TemplateData template(final Template template) {
|
||||||
|
return new TemplateData(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TemplateData template() {
|
||||||
|
return new TemplateData(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Map<String, Object>> getEntites() {
|
||||||
|
final List<Map<String, Object>> l = new ArrayList<Map<String, Object>>();
|
||||||
|
for (final TemplateEntity e : TemplateEntity.values()) {
|
||||||
|
final Map<String, Object> m = new HashMap<String, Object>();
|
||||||
|
m.put("id", e.getId());
|
||||||
|
m.put("name", e.getName());
|
||||||
|
l.add(m);
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Map<String, Object>> getTypes() {
|
||||||
|
final List<Map<String, Object>> l = new ArrayList<Map<String, Object>>();
|
||||||
|
for (final TemplateType e : TemplateType.values()) {
|
||||||
|
final Map<String, Object> m = new HashMap<String, Object>();
|
||||||
|
m.put("id", e.getId());
|
||||||
|
m.put("name", e.getName());
|
||||||
|
l.add(m);
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package org.mifosplatform.template.domain;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.OrderBy;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "m_template", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unq_name") })
|
||||||
|
public class Template extends AbstractPersistable<Long> {
|
||||||
|
|
||||||
|
@Column(name = "name", nullable = false, unique = true)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Enumerated
|
||||||
|
@JsonSerialize(using = TemplateEntitySerializer.class)
|
||||||
|
private TemplateEntity entity;
|
||||||
|
|
||||||
|
@Enumerated
|
||||||
|
@JsonSerialize(using = TemplateTypeSerializer.class)
|
||||||
|
private TemplateType type;
|
||||||
|
|
||||||
|
@Column(name = "text", columnDefinition = "longtext", nullable = false)
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
@OrderBy(value = "mapperorder")
|
||||||
|
@OneToMany(targetEntity = TemplateMapper.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||||
|
private List<TemplateMapper> mappers;
|
||||||
|
|
||||||
|
public Template(final String name, final String text, final TemplateEntity entity, final TemplateType type, final List<TemplateMapper> mappers) {
|
||||||
|
this.name = name;
|
||||||
|
this.entity = entity;
|
||||||
|
this.type = type;
|
||||||
|
this.text = text;
|
||||||
|
this.mappers = mappers;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Template() {}
|
||||||
|
|
||||||
|
public static Template fromJson(final JsonCommand command) {
|
||||||
|
System.out.println("COMMAND: " + command);
|
||||||
|
final String name = command.stringValueOfParameterNamed("name");
|
||||||
|
final String text = command.stringValueOfParameterNamed("text");
|
||||||
|
final TemplateEntity entity = TemplateEntity.values()[command.integerValueSansLocaleOfParameterNamed("entity")];
|
||||||
|
final TemplateType type = TemplateType.values()[command.integerValueSansLocaleOfParameterNamed("type")];
|
||||||
|
final JsonArray array = command.arrayOfParameterNamed("mappers");
|
||||||
|
final List<TemplateMapper> mappersList = new ArrayList<TemplateMapper>();
|
||||||
|
for (final JsonElement element : array) {
|
||||||
|
mappersList.add(new TemplateMapper(element.getAsJsonObject().get("mappersorder").getAsInt(), element.getAsJsonObject()
|
||||||
|
.get("mapperskey").getAsString(), element.getAsJsonObject().get("mappersvalue").getAsString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Template(name, text, entity, type, mappersList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkedHashMap<String, String> getMappersAsMap() {
|
||||||
|
final LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
|
||||||
|
for (final TemplateMapper mapper : getMappers()) {
|
||||||
|
map.put(mapper.getMapperkey(), mapper.getMappervalue());
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TemplateMapper> getMappers() {
|
||||||
|
return this.mappers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappers(final List<TemplateMapper> mappers) {
|
||||||
|
this.mappers = mappers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemplateEntity getEntity() {
|
||||||
|
return this.entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEntity(final TemplateEntity entity) {
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemplateType getType() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(final TemplateType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return this.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(final String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package org.mifosplatform.template.domain;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
@JsonSerialize(using = TemplateEntitySerializer.class)
|
||||||
|
public enum TemplateEntity {
|
||||||
|
|
||||||
|
@SerializedName("client")
|
||||||
|
CLIENT(0, "client"), @SerializedName("loan")
|
||||||
|
LOAN(1, "loan");
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private TemplateEntity(final int id, final String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package org.mifosplatform.template.domain;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.JsonGenerator;
|
||||||
|
import org.codehaus.jackson.JsonProcessingException;
|
||||||
|
import org.codehaus.jackson.map.JsonSerializer;
|
||||||
|
import org.codehaus.jackson.map.SerializerProvider;
|
||||||
|
|
||||||
|
public class TemplateEntitySerializer extends JsonSerializer<TemplateEntity> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(final TemplateEntity value, final JsonGenerator generator, @SuppressWarnings("unused") final SerializerProvider provider)
|
||||||
|
throws IOException, JsonProcessingException {
|
||||||
|
|
||||||
|
generator.writeStartObject();
|
||||||
|
generator.writeFieldName("id");
|
||||||
|
generator.writeNumber(value.getId());
|
||||||
|
generator.writeFieldName("name");
|
||||||
|
generator.writeString(value.getName());
|
||||||
|
generator.writeEndObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
package org.mifosplatform.template.domain;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class TemplateFunctions {
|
||||||
|
|
||||||
|
public static String now() {
|
||||||
|
final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm");
|
||||||
|
final Date date = new Date();
|
||||||
|
|
||||||
|
return dateFormat.format(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package org.mifosplatform.template.domain;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "m_templatemappers")
|
||||||
|
public class TemplateMapper extends AbstractPersistable<Long> {
|
||||||
|
|
||||||
|
@Column(name = "mapperorder")
|
||||||
|
private int mapperorder;
|
||||||
|
|
||||||
|
@Column(name = "mapperkey")
|
||||||
|
private String mapperkey;
|
||||||
|
|
||||||
|
@Column(name = "mappervalue")
|
||||||
|
private String mappervalue;
|
||||||
|
|
||||||
|
protected TemplateMapper() {}
|
||||||
|
|
||||||
|
public TemplateMapper(final int mapperorder, final String mapperkey, final String mappervalue) {
|
||||||
|
this.mapperorder = mapperorder;
|
||||||
|
this.mapperkey = mapperkey;
|
||||||
|
this.mappervalue = mappervalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMapperkey() {
|
||||||
|
return this.mapperkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMapperorder() {
|
||||||
|
return this.mapperorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMapperorder(final int mapperorder) {
|
||||||
|
this.mapperorder = mapperorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMapperkey(final String mapperkey) {
|
||||||
|
this.mapperkey = mapperkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMappervalue() {
|
||||||
|
return this.mappervalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappervalue(final String mappervalue) {
|
||||||
|
this.mappervalue = mappervalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package org.mifosplatform.template.domain;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface TemplateRepository extends JpaRepository<Template, Long> {
|
||||||
|
|
||||||
|
List<Template> findByEntityAndType(TemplateEntity entity, TemplateType type);
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package org.mifosplatform.template.domain;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
@JsonSerialize(using = TemplateTypeSerializer.class)
|
||||||
|
public enum TemplateType {
|
||||||
|
|
||||||
|
@SerializedName("Document")
|
||||||
|
DOCUMENT(0, "Document");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @SerializedName("E-Mail") EMAIL(1, "E-Mail"),
|
||||||
|
* @SerializedName("SMS") SMS(2, "SMS");
|
||||||
|
*/
|
||||||
|
private int id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private TemplateType(final int id, final String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package org.mifosplatform.template.domain;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.JsonGenerator;
|
||||||
|
import org.codehaus.jackson.JsonProcessingException;
|
||||||
|
import org.codehaus.jackson.map.JsonSerializer;
|
||||||
|
import org.codehaus.jackson.map.SerializerProvider;
|
||||||
|
|
||||||
|
public class TemplateTypeSerializer extends JsonSerializer<TemplateType> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(final TemplateType value, final JsonGenerator generator, @SuppressWarnings("unused") final SerializerProvider provider)
|
||||||
|
throws IOException, JsonProcessingException {
|
||||||
|
|
||||||
|
generator.writeStartObject();
|
||||||
|
generator.writeFieldName("id");
|
||||||
|
generator.writeNumber(value.getId());
|
||||||
|
generator.writeFieldName("name");
|
||||||
|
generator.writeString(value.getName());
|
||||||
|
generator.writeEndObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package org.mifosplatform.template.exception;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||||
|
|
||||||
|
public class TemplateNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||||
|
|
||||||
|
public TemplateNotFoundException(final Long id) {
|
||||||
|
super("error.msg.template.id.invalid", "Template with identifier " + id + " does not exist", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package org.mifosplatform.template.handler;
|
||||||
|
|
||||||
|
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.mifosplatform.template.service.TemplateDomainService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class CreateTemplateCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
|
private final TemplateDomainService templateService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public CreateTemplateCommandHandler(final TemplateDomainService templateService) {
|
||||||
|
|
||||||
|
this.templateService = templateService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
|
return this.templateService.createTemplate(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package org.mifosplatform.template.handler;
|
||||||
|
|
||||||
|
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.mifosplatform.template.service.TemplateDomainService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class DeleteTemplateCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
|
private final TemplateDomainService templateService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public DeleteTemplateCommandHandler(final TemplateDomainService templateService) {
|
||||||
|
|
||||||
|
this.templateService = templateService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
|
return this.templateService.removeTemplate(command.entityId());
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package org.mifosplatform.template.handler;
|
||||||
|
|
||||||
|
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.mifosplatform.template.service.TemplateDomainService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UpdateTemplateCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
|
private final TemplateDomainService templateService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public UpdateTemplateCommandHandler(final TemplateDomainService templateService) {
|
||||||
|
|
||||||
|
this.templateService = templateService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
|
return this.templateService.updateTemplate(command.entityId(), command);
|
||||||
|
}
|
||||||
|
}
|
||||||
+98
@@ -0,0 +1,98 @@
|
|||||||
|
package org.mifosplatform.template.service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||||
|
import org.mifosplatform.template.domain.Template;
|
||||||
|
import org.mifosplatform.template.domain.TemplateEntity;
|
||||||
|
import org.mifosplatform.template.domain.TemplateMapper;
|
||||||
|
import org.mifosplatform.template.domain.TemplateRepository;
|
||||||
|
import org.mifosplatform.template.domain.TemplateType;
|
||||||
|
import org.mifosplatform.template.exception.TemplateNotFoundException;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class JpaTemplateDomainService implements TemplateDomainService {
|
||||||
|
|
||||||
|
private static final String PROPERTY_NAME = "name";
|
||||||
|
private static final String PROPERTY_TEXT = "text";
|
||||||
|
private static final String PROPERTY_MAPPERS = "mappers";
|
||||||
|
private static final String PROPERTY_ENTITY = "entity";
|
||||||
|
private static final String PROPERTY_TYPE = "type";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TemplateRepository templateRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Template> getAll() {
|
||||||
|
return this.templateRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Template getById(final Long id) {
|
||||||
|
final Template template = this.templateRepository.findOne(id);
|
||||||
|
if (template == null) { throw new TemplateNotFoundException(id); }
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult createTemplate(final JsonCommand command) {
|
||||||
|
final Template template = Template.fromJson(command);
|
||||||
|
|
||||||
|
this.templateRepository.saveAndFlush(template);
|
||||||
|
return new CommandProcessingResultBuilder().withEntityId(template.getId()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult updateTemplate(final Long templateId, final JsonCommand command) {
|
||||||
|
final Template template = getById(templateId);
|
||||||
|
System.out.println("COMM: " + command);
|
||||||
|
template.setName(command.stringValueOfParameterNamed(PROPERTY_NAME));
|
||||||
|
template.setText(command.stringValueOfParameterNamed(PROPERTY_TEXT));
|
||||||
|
template.setEntity(TemplateEntity.values()[command.integerValueSansLocaleOfParameterNamed(PROPERTY_ENTITY)]);
|
||||||
|
template.setType(TemplateType.values()[command.integerValueSansLocaleOfParameterNamed(PROPERTY_TYPE)]);
|
||||||
|
|
||||||
|
final JsonArray array = command.arrayOfParameterNamed("mappers");
|
||||||
|
final List<TemplateMapper> mappersList = new ArrayList<TemplateMapper>();
|
||||||
|
for (final JsonElement element : array) {
|
||||||
|
mappersList.add(new TemplateMapper(element.getAsJsonObject().get("mappersorder").getAsInt(), element.getAsJsonObject()
|
||||||
|
.get("mapperskey").getAsString(), element.getAsJsonObject().get("mappersvalue").getAsString()));
|
||||||
|
}
|
||||||
|
template.setMappers(mappersList);
|
||||||
|
|
||||||
|
this.templateRepository.saveAndFlush(template);
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(template.getId()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult removeTemplate(final Long templateId) {
|
||||||
|
final Template template = getById(templateId);
|
||||||
|
|
||||||
|
this.templateRepository.delete(template);
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder().withEntityId(templateId).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Template updateTemplate(final Template template) {
|
||||||
|
return this.templateRepository.saveAndFlush(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Template> getAllByEntityAndType(final TemplateEntity entity, final TemplateType type) {
|
||||||
|
|
||||||
|
return this.templateRepository.findByEntityAndType(entity, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package org.mifosplatform.template.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.mifosplatform.template.domain.Template;
|
||||||
|
import org.mifosplatform.template.domain.TemplateEntity;
|
||||||
|
import org.mifosplatform.template.domain.TemplateType;
|
||||||
|
|
||||||
|
public interface TemplateDomainService {
|
||||||
|
|
||||||
|
List<Template> getAll();
|
||||||
|
|
||||||
|
List<Template> getAllByEntityAndType(TemplateEntity entity, TemplateType type);
|
||||||
|
|
||||||
|
Template getById(Long id);
|
||||||
|
|
||||||
|
Template updateTemplate(Template template);
|
||||||
|
|
||||||
|
CommandProcessingResult createTemplate(final JsonCommand command);
|
||||||
|
|
||||||
|
CommandProcessingResult updateTemplate(final Long templateId, final JsonCommand command);
|
||||||
|
|
||||||
|
CommandProcessingResult removeTemplate(final Long templateId);
|
||||||
|
}
|
||||||
+166
@@ -0,0 +1,166 @@
|
|||||||
|
package org.mifosplatform.template.service;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.net.Authenticator;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.PasswordAuthentication;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.map.ObjectMapper;
|
||||||
|
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||||
|
import org.mifosplatform.template.domain.Template;
|
||||||
|
import org.mifosplatform.template.domain.TemplateFunctions;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.github.mustachejava.DefaultMustacheFactory;
|
||||||
|
import com.github.mustachejava.Mustache;
|
||||||
|
import com.github.mustachejava.MustacheFactory;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TemplateMergeService {
|
||||||
|
|
||||||
|
private final FromJsonHelper fromApiJsonHelper;
|
||||||
|
private Map<String, Object> scopes;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public TemplateMergeService(final FromJsonHelper fromApiJsonHelper) {
|
||||||
|
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String compile(final Template template, final Map<String, Object> scopes) throws MalformedURLException, IOException {
|
||||||
|
|
||||||
|
this.scopes = scopes;
|
||||||
|
this.scopes.put("static", new TemplateFunctions());
|
||||||
|
|
||||||
|
final MustacheFactory mf = new DefaultMustacheFactory();
|
||||||
|
final Mustache mustache = mf.compile(new StringReader(template.getText()), template.getName());
|
||||||
|
|
||||||
|
final Map<String, Object> mappers = getCompiledMapFromMappers(template.getMappersAsMap());
|
||||||
|
this.scopes.putAll(mappers);
|
||||||
|
|
||||||
|
final StringWriter stringWriter = new StringWriter();
|
||||||
|
mustache.execute(stringWriter, this.scopes);
|
||||||
|
|
||||||
|
return stringWriter.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getCompiledMapFromMappers(final Map<String, String> data) {
|
||||||
|
|
||||||
|
final MustacheFactory mf = new DefaultMustacheFactory();
|
||||||
|
|
||||||
|
if (data != null) {
|
||||||
|
for (final Map.Entry<String, String> entry : data.entrySet()) {
|
||||||
|
|
||||||
|
final Mustache mappersMustache = mf.compile(new StringReader(entry.getValue()), "");
|
||||||
|
final StringWriter stringWriter = new StringWriter();
|
||||||
|
|
||||||
|
mappersMustache.execute(stringWriter, this.scopes);
|
||||||
|
String url = stringWriter.toString();
|
||||||
|
if (!url.startsWith("http")) {
|
||||||
|
url = this.scopes.get("BASE_URI") + url;
|
||||||
|
}
|
||||||
|
System.out.println("URL: " + url);
|
||||||
|
try {
|
||||||
|
this.scopes.put(entry.getKey(), getMapFromUrl(url));
|
||||||
|
} catch (final MalformedURLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private Map<String, Object> getMapFromUrl(final String url) throws MalformedURLException, IOException {
|
||||||
|
|
||||||
|
final HttpURLConnection connection = getConnection(url);
|
||||||
|
|
||||||
|
final String response = getStringFromInputStream(connection.getInputStream());
|
||||||
|
HashMap<String, Object> result = new HashMap<String, Object>();
|
||||||
|
System.out.println("CONTENT_TYPE" + connection.getContentType());
|
||||||
|
if (connection.getContentType().equals("text/plain")) {
|
||||||
|
result.put("src", response);
|
||||||
|
} else {
|
||||||
|
result = new ObjectMapper().readValue(response, HashMap.class);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpURLConnection getConnection(final String url) {
|
||||||
|
|
||||||
|
final String name = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||||
|
final String password = SecurityContextHolder.getContext().getAuthentication().getCredentials().toString();
|
||||||
|
|
||||||
|
Authenticator.setDefault(new Authenticator() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PasswordAuthentication getPasswordAuthentication() {
|
||||||
|
return new PasswordAuthentication(name, password.toCharArray());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
HttpURLConnection connection = null;
|
||||||
|
try {
|
||||||
|
connection = (HttpURLConnection) new URL(url).openConnection();
|
||||||
|
TrustModifier.relaxHostChecking(connection);
|
||||||
|
|
||||||
|
connection.setDoInput(true);
|
||||||
|
|
||||||
|
} catch (final MalformedURLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (final KeyManagementException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (final NoSuchAlgorithmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (final KeyStoreException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getStringFromInputStream(final InputStream is) {
|
||||||
|
|
||||||
|
BufferedReader br = null;
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
String line;
|
||||||
|
try {
|
||||||
|
|
||||||
|
br = new BufferedReader(new InputStreamReader(is));
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
sb.append(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (final IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (br != null) {
|
||||||
|
try {
|
||||||
|
br.close();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package org.mifosplatform.template.service;
|
||||||
|
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
|
import javax.net.ssl.HostnameVerifier;
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLSession;
|
||||||
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class TrustModifier {
|
||||||
|
|
||||||
|
private static final TrustingHostnameVerifier TRUSTING_HOSTNAME_VERIFIER = new TrustingHostnameVerifier();
|
||||||
|
private static SSLSocketFactory factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this with any HttpURLConnection, and it will modify the trust
|
||||||
|
* settings if it is an HTTPS connection.
|
||||||
|
*/
|
||||||
|
public static void relaxHostChecking(final HttpURLConnection conn) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
|
||||||
|
|
||||||
|
if (conn instanceof HttpsURLConnection) {
|
||||||
|
final HttpsURLConnection httpsConnection = (HttpsURLConnection) conn;
|
||||||
|
final SSLSocketFactory factory = prepFactory(httpsConnection);
|
||||||
|
httpsConnection.setSSLSocketFactory(factory);
|
||||||
|
httpsConnection.setHostnameVerifier(TRUSTING_HOSTNAME_VERIFIER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static synchronized SSLSocketFactory prepFactory(final HttpsURLConnection httpsConnection) throws NoSuchAlgorithmException,
|
||||||
|
KeyStoreException, KeyManagementException {
|
||||||
|
|
||||||
|
if (factory == null) {
|
||||||
|
final SSLContext ctx = SSLContext.getInstance("TLS");
|
||||||
|
ctx.init(null, new TrustManager[] { new AlwaysTrustManager() }, null);
|
||||||
|
factory = ctx.getSocketFactory();
|
||||||
|
}
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class TrustingHostnameVerifier implements HostnameVerifier {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verify(final String hostname, final SSLSession session) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AlwaysTrustManager implements X509TrustManager {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkClientTrusted(final X509Certificate[] arg0, final String arg1) throws CertificateException {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkServerTrusted(final X509Certificate[] arg0, final String arg1) throws CertificateException {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public X509Certificate[] getAcceptedIssuers() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,10 +14,8 @@
|
|||||||
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
||||||
<properties>
|
<properties>
|
||||||
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
|
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
|
||||||
<!-- <property name="hibernate.hbm2ddl.auto" value="update"/> -->
|
|
||||||
<property name="hibernate.jdbc.batch_size" value="100" />
|
<property name="hibernate.jdbc.batch_size" value="100" />
|
||||||
<property name="hibernate.order_inserts" value="true" />
|
<property name="hibernate.order_inserts" value="true" />
|
||||||
<!-- <property name = "hibernate.show_sql" value = "true" /> -->
|
|
||||||
</properties>
|
</properties>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
</persistence>
|
</persistence>
|
||||||
@@ -36,7 +36,10 @@
|
|||||||
org.mifosplatform.portfolio.savingsaccount.*,
|
org.mifosplatform.portfolio.savingsaccount.*,
|
||||||
org.mifosplatform.portfolio.*,
|
org.mifosplatform.portfolio.*,
|
||||||
org.mifosplatform.useradministration.*,
|
org.mifosplatform.useradministration.*,
|
||||||
org.mifosplatform.mix.*">
|
org.mifosplatform.mix.*,
|
||||||
|
org.mifosplatform.template.*,
|
||||||
|
org.mifosplatform.template.service.*,
|
||||||
|
org.mifosplatform.useradministration.*">
|
||||||
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation" />
|
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation" />
|
||||||
</context:component-scan>
|
</context:component-scan>
|
||||||
|
|
||||||
@@ -51,6 +54,7 @@
|
|||||||
<jpa:repositories base-package="org.mifosplatform.portfolio.*" />
|
<jpa:repositories base-package="org.mifosplatform.portfolio.*" />
|
||||||
<jpa:repositories base-package="org.mifosplatform.mix.domain" />
|
<jpa:repositories base-package="org.mifosplatform.mix.domain" />
|
||||||
<jpa:repositories base-package="org.mifosplatform.scheduledjobs.domain" />
|
<jpa:repositories base-package="org.mifosplatform.scheduledjobs.domain" />
|
||||||
|
<jpa:repositories base-package="org.mifosplatform.template.domain" />
|
||||||
|
|
||||||
<import resource="infrastructure.xml" />
|
<import resource="infrastructure.xml" />
|
||||||
|
|
||||||
|
|||||||
@@ -29,12 +29,6 @@
|
|||||||
<beans:property name="realmName" value="Mifos Platform API" />
|
<beans:property name="realmName" value="Mifos Platform API" />
|
||||||
</beans:bean>
|
</beans:bean>
|
||||||
|
|
||||||
<!--
|
|
||||||
<beans:bean id="basicAuthenticationProcessingFilter" class="org.mifosplatform.infrastructure.security.filter.TenantAwareBasicAuthenticationFilter" depends-on="cacheManager">
|
|
||||||
<beans:constructor-arg ref="authenticationManager" />
|
|
||||||
<beans:constructor-arg ref="basicAuthenticationEntryPoint" />
|
|
||||||
</beans:bean>
|
|
||||||
-->
|
|
||||||
<beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
|
<beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
|
||||||
<beans:constructor-arg value="256"/>
|
<beans:constructor-arg value="256"/>
|
||||||
</beans:bean>
|
</beans:bean>
|
||||||
@@ -49,7 +43,7 @@
|
|||||||
<beans:property name="saltSource" ref="saltSource" />
|
<beans:property name="saltSource" ref="saltSource" />
|
||||||
</beans:bean>
|
</beans:bean>
|
||||||
|
|
||||||
<authentication-manager alias="authenticationManager">
|
<authentication-manager alias="authenticationManager" erase-credentials="false">
|
||||||
<authentication-provider ref="customAuthenticationProvider" />
|
<authentication-provider ref="customAuthenticationProvider" />
|
||||||
</authentication-manager>
|
</authentication-manager>
|
||||||
</beans:beans>
|
</beans:beans>
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package org.mifosplatform.common;
|
||||||
|
|
||||||
|
|
||||||
|
import static com.jayway.restassured.RestAssured.given;
|
||||||
|
import static com.jayway.restassured.path.json.JsonPath.from;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.http.conn.HttpHostConnectException;
|
||||||
|
|
||||||
|
import com.jayway.restassured.RestAssured;
|
||||||
|
import com.jayway.restassured.path.json.JsonPath;
|
||||||
|
import com.jayway.restassured.specification.RequestSpecification;
|
||||||
|
import com.jayway.restassured.specification.ResponseSpecification;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public class Utils {
|
||||||
|
|
||||||
|
private static final String LOGIN_URL = "/mifosng-provider/api/v1/authentication?username=mifos&password=password&tenantIdentifier=default";
|
||||||
|
|
||||||
|
|
||||||
|
public static void initializeRESTAssured() {
|
||||||
|
RestAssured.baseURI ="https://localhost";
|
||||||
|
RestAssured.port = 8443;
|
||||||
|
RestAssured.keystore("../keystore.jks", "openmf");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String loginIntoServerAndGetBase64EncodedAuthenticationKey() {
|
||||||
|
try {
|
||||||
|
System.out.println("-----------------------------------LOGIN-----------------------------------------");
|
||||||
|
String json = RestAssured.post(LOGIN_URL).asString();
|
||||||
|
assertThat("Failed to login into mifosx platform", StringUtils.isBlank(json), is(false));
|
||||||
|
return JsonPath.with(json).get("base64EncodedAuthenticationKey");
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
if (e instanceof HttpHostConnectException) {
|
||||||
|
HttpHostConnectException hh = (HttpHostConnectException) e;
|
||||||
|
fail("Failed to connect to mifosx platform:"+hh.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T performServerGet(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||||
|
final String getURL, final String jsonAttributeToGetBack) {
|
||||||
|
String json = given().spec(requestSpec)
|
||||||
|
.expect().spec(responseSpec).log().ifError()
|
||||||
|
.when().get(getURL).andReturn().asString();
|
||||||
|
return (T) from(json).get(jsonAttributeToGetBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T performServerPost(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||||
|
final String postURL, final String jsonBodyToSend, final String jsonAttributeToGetBack) {
|
||||||
|
String json = given().spec(requestSpec).body(jsonBodyToSend)
|
||||||
|
.expect().spec(responseSpec).log().ifError()
|
||||||
|
.when().post(postURL)
|
||||||
|
.andReturn().asString();
|
||||||
|
return (T) from(json).get(jsonAttributeToGetBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String convertDateToURLFormat(String dateToBeConvert){
|
||||||
|
SimpleDateFormat oldFormat = new SimpleDateFormat("dd MMMMMM yyyy");
|
||||||
|
SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
String reformattedStr="";
|
||||||
|
try {
|
||||||
|
reformattedStr = newFormat.format(oldFormat.parse(dateToBeConvert));
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return reformattedStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String randomStringGenerator(final String prefix, final int len, final String sourceSetString) {
|
||||||
|
int lengthOfSource = sourceSetString.length();
|
||||||
|
Random rnd = new Random();
|
||||||
|
StringBuilder sb = new StringBuilder(len);
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
sb.append((sourceSetString).charAt(rnd.nextInt(lengthOfSource)));
|
||||||
|
return (prefix + (sb.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String randomStringGenerator(final String prefix, final int len) {
|
||||||
|
return randomStringGenerator(prefix, len, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||||
|
}
|
||||||
|
}
|
||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
package org.mifosplatform.template;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||||
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
|
import org.mifosplatform.portfolio.loanaccount.LoanScheduleTestDataHelper;
|
||||||
|
import org.mifosplatform.portfolio.loanaccount.MonetaryCurrencyBuilder;
|
||||||
|
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
|
import org.mifosplatform.template.domain.Template;
|
||||||
|
import org.mifosplatform.template.service.TemplateMergeService;
|
||||||
|
|
||||||
|
public class TemplateMergeServiceTest {
|
||||||
|
|
||||||
|
private Template template;
|
||||||
|
private final static String TEST_FILE = "src/test/resources/template.mustache";
|
||||||
|
private static TemplateMergeService tms;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void init() {
|
||||||
|
tms = new TemplateMergeService(new FromJsonHelper());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void compileHelloTemplate() throws Exception {
|
||||||
|
String name = "TemplateName";
|
||||||
|
String text = "Hello Test for Template {{template.name}}!";
|
||||||
|
|
||||||
|
template = new Template(name, text, null, null, null);
|
||||||
|
|
||||||
|
HashMap<String, Object> scopes = new HashMap<String, Object>();
|
||||||
|
scopes.put("template", template);
|
||||||
|
|
||||||
|
String output ="";
|
||||||
|
output = tms.compile(template, scopes);
|
||||||
|
assertEquals("Hello Test for Template TemplateName!", output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO:ASSERT!!
|
||||||
|
@Test
|
||||||
|
public void compileLoanSummary() throws IOException{
|
||||||
|
|
||||||
|
LocalDate july2nd = new LocalDate(2012, 7, 2);
|
||||||
|
MonetaryCurrency usDollars = new MonetaryCurrencyBuilder().withCode("USD").withDigitsAfterDecimal(2).build();
|
||||||
|
List<LoanRepaymentScheduleInstallment> installments
|
||||||
|
= LoanScheduleTestDataHelper.createSimpleLoanSchedule(july2nd, usDollars);
|
||||||
|
|
||||||
|
File file = new File(TEST_FILE);
|
||||||
|
DataInputStream dis = new DataInputStream(new FileInputStream(file));
|
||||||
|
byte[] bytes = new byte[(int) file.length()];
|
||||||
|
dis.readFully(bytes);
|
||||||
|
String content = new String(bytes, "UTF-8");
|
||||||
|
|
||||||
|
template = new Template("TemplateName", content, null, null, null);
|
||||||
|
|
||||||
|
HashMap<String, Object> scopes = new HashMap<String, Object>();
|
||||||
|
scopes.put("installments", installments);
|
||||||
|
|
||||||
|
String output = tms.compile(template, scopes);
|
||||||
|
|
||||||
|
dis.close();
|
||||||
|
|
||||||
|
System.out.println(output);
|
||||||
|
dis.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:p="http://www.springframework.org/schema/p"
|
||||||
|
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
|
||||||
|
xmlns:context="http://www.springframework.org/schema/context"
|
||||||
|
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||||
|
xmlns:jee="http://www.springframework.org/schema/jee"
|
||||||
|
xsi:schemaLocation="
|
||||||
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||||
|
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
|
||||||
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
|
||||||
|
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
|
||||||
|
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
|
||||||
|
|
||||||
|
<tx:annotation-driven />
|
||||||
|
|
||||||
|
<bean id="dataSource"
|
||||||
|
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
|
||||||
|
p:driverClassName="com.mysql.jdbc.Driver"
|
||||||
|
p:url="jdbc:mysql://localhost:3306/mifosplatform-tenants"
|
||||||
|
p:username="root"
|
||||||
|
p:password="mysql" />
|
||||||
|
|
||||||
|
<bean id="hibernateExceptionTranslator" class="org.springframework.orm.hibernate4.HibernateExceptionTranslator" />
|
||||||
|
|
||||||
|
|
||||||
|
<bean id="entityManagerFactory"
|
||||||
|
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
|
||||||
|
<property name="dataSource" ref="tenantDataSourceJndi"/>
|
||||||
|
<property name="packagesToScan">
|
||||||
|
<list>
|
||||||
|
<value>org.mifosplatform.template</value>
|
||||||
|
<value>org.mifosplatform.commands.domain</value>
|
||||||
|
<value>org.mifosplatform.useradministration.domain</value>
|
||||||
|
<value>org.mifosplatform.organisation.office.domain</value>
|
||||||
|
<value>org.mifosplatform.organisation.staff.domain</value>
|
||||||
|
<value>org.mifosplatform.infrastructure.core.serialization</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="jpaVendorAdapter">
|
||||||
|
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
|
||||||
|
</property>
|
||||||
|
<property name="jpaProperties">
|
||||||
|
<props>
|
||||||
|
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
|
||||||
|
<prop key="hibernate.hbm2ddl.auto">create</prop>
|
||||||
|
</props>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||||
|
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<context:component-scan base-package="org.mifosplatform.accounting.*,
|
||||||
|
org.mifosplatform.commands.handler.*,
|
||||||
|
org.mifosplatform.commands.service.*,
|
||||||
|
org.mifosplatform.commands.*,
|
||||||
|
org.mifosplatform.audit.*,
|
||||||
|
org.mifosplatform.infrastructure.*,
|
||||||
|
org.mifosplatform.scheduledjobs.*,
|
||||||
|
org.mifosplatform.organisation.*,
|
||||||
|
org.mifosplatform.portfolio.loanaccount.*,
|
||||||
|
org.mifosplatform.portfolio.savingsaccount.*,
|
||||||
|
org.mifosplatform.portfolio.*,
|
||||||
|
org.mifosplatform.template.*,
|
||||||
|
org.mifosplatform.template.service.*,
|
||||||
|
org.mifosplatform.useradministration.*" >
|
||||||
|
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation" />
|
||||||
|
</context:component-scan>
|
||||||
|
|
||||||
|
<jpa:repositories base-package="org.mifosplatform.commands.domain" />
|
||||||
|
<jpa:repositories base-package="org.mifosplatform.infrastructure.*.domain" />
|
||||||
|
<jpa:repositories base-package="org.mifosplatform.accounting.*.domain" />
|
||||||
|
<jpa:repositories base-package="org.mifosplatform.useradministration.domain" />
|
||||||
|
<jpa:repositories base-package="org.mifosplatform.organisation.*.domain" />
|
||||||
|
<jpa:repositories base-package="org.mifosplatform.portfolio.*" />
|
||||||
|
<jpa:repositories base-package="org.mifosplatform.template.domain" />
|
||||||
|
|
||||||
|
<jee:jndi-lookup jndi-name="java:comp/env/jdbc/mifosplatform-tenants" id="tenantDataSourceJndi" />
|
||||||
|
|
||||||
|
</beans>
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
<h1><span style="font-size:20px"><strong><span style="color:#0000CD">Sample Loan Summary & Repayment Schedule </span></strong></span></h1>
|
||||||
|
|
||||||
|
<h2><span style="font-size:16px"><span style="color:#0000CD">TABLE 1. LOAN SUMMARY</span> </span></h2>
|
||||||
|
|
||||||
|
<table align="left" border="1" cellpadding="3" cellspacing="0" style="width:650px">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Loan size and currency</td>
|
||||||
|
<td> </td>
|
||||||
|
<td>Total no. of installments </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Interest rate </td>
|
||||||
|
<td> </td>
|
||||||
|
<td>Installment frequency</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Commission fee</td>
|
||||||
|
<td> </td>
|
||||||
|
<td>Disbursement date </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Other fees</td>
|
||||||
|
<td> </td>
|
||||||
|
<td>Mandatory savings</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Purpose of loan</td>
|
||||||
|
<td> </td>
|
||||||
|
<td>Maturity date </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Grace period (if applies)</td>
|
||||||
|
<td> </td>
|
||||||
|
<td>Type of guarantee</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Penalty for late payment</td>
|
||||||
|
<td> </td>
|
||||||
|
<td>Maturity of the loan (in months) </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Penalty for pre-payment</td>
|
||||||
|
<td> </td>
|
||||||
|
<td>Total cost of loan (principle + int.+ fees) </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<h2><span style="font-size:16px"><span style="color:#0000CD">TABLE 2. REPAYMENT SCHEDULE </span></span></h2>
|
||||||
|
|
||||||
|
<table border="1" cellpadding="3" cellspacing="0" style="width:600px">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Date</td>
|
||||||
|
<td>Disbursement Amount</td>
|
||||||
|
<td>
|
||||||
|
<p>Principle Repayment</p>
|
||||||
|
</td>
|
||||||
|
<td> Interest Repayment</td>
|
||||||
|
<td>Commission Payment</td>
|
||||||
|
<td>Fees</td>
|
||||||
|
<td>Tax Payment</td>
|
||||||
|
<td>Total Repayment</td>
|
||||||
|
<td>Total Balance Outstanding</td>
|
||||||
|
</tr>
|
||||||
|
{{#installments}}
|
||||||
|
<tr>
|
||||||
|
<td>{{dueDate}}</td>
|
||||||
|
<td>{{installmentNumber}}</td>
|
||||||
|
<td>{{fromDate}}</td>
|
||||||
|
<td>{{principal}}</td>
|
||||||
|
<td> </td>
|
||||||
|
<td>{{feeChargesCharged}}</td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
{{/installments}}
|
||||||
|
<tr>
|
||||||
|
<td>Total</td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p>Client Signature ___________________________________________________________________ </p>
|
||||||
|
|
||||||
|
<p>Credit Officer Signature _____________________________________________________________ </p>
|
||||||
|
|
||||||
|
<p>Branch Director Signature ___________________________________________________________ </p>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size:12px"><strong>Please contact the<span style="color:#FF0000"> Macro</span><span style="color:#0000CD">Dreams</span> Customer Service Line if you have questions or complaints about our products, </strong></span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size:12px"><strong>services, or staff: 555-555-5555. Open Monday to Saturday 7:00-20:00. All calls are free. </strong></span></p>
|
||||||
Reference in New Issue
Block a user