diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index 224f6296a..8bbd794dc 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -26947,7 +26947,9 @@ No Request Body:
Column type. Must be one of the following:
+ - Boolean
- Date
+ - DateTime
- Decimal
- Dropdown
- Number
@@ -27257,7 +27259,9 @@ GET https://DomainName/api/v1/datatables/{datatable}
Column type. Must be one of the following:
+ - Boolean
- Date
+ - DateTime
- Decimal
- Dropdown
- Number
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/DatatableCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/DatatableCommandFromApiJsonDeserializer.java
index fbe8adeaa..dd4b0fddb 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/DatatableCommandFromApiJsonDeserializer.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/DatatableCommandFromApiJsonDeserializer.java
@@ -45,7 +45,7 @@ public class DatatableCommandFromApiJsonDeserializer {
private final Set supportedParametersForChangeColumns = new HashSet<>(Arrays.asList("name", "newName", "length",
"mandatory", "after", "code", "newCode"));
private final Set supportedParametersForDropColumns = new HashSet<>(Arrays.asList("name"));
- private final Object[] supportedColumnTypes = { "string", "number", "decimal", "date", "text", "dropdown" };
+ private final Object[] supportedColumnTypes = { "string", "number", "boolean", "decimal", "date", "datetime", "text", "dropdown" };
private final Object[] supportedApptableNames = { "m_loan", "m_savings_account", "m_client", "m_group", "m_center", "m_office",
"m_savings_product", "m_product_loan" };
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 32bc4b9fc..a20168185 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
@@ -18,6 +18,7 @@ import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
import org.joda.time.MonthDay;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
@@ -144,10 +145,10 @@ public class JsonParserHelper {
/**
* 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
- *
+ *
* @param parameterName
* @param element
* @param parametersPassedInRequest
@@ -354,6 +355,36 @@ public class JsonParserHelper {
public static LocalDate convertFrom(final String dateAsString, final String parameterName, final String dateFormat,
final Locale clientApplicationLocale) {
+ return convertDateTimeFrom(dateAsString, parameterName,
+ dateFormat, clientApplicationLocale).toLocalDate();
+ }
+
+ public static LocalDateTime convertDateTimeFrom(final String dateTimeAsString, final String parameterName,
+ final String dateTimeFormat, final Locale clientApplicationLocale) {
+
+ validateDateFormatAndLocale(parameterName, dateTimeFormat, clientApplicationLocale);
+ LocalDateTime eventLocalDateTime = null;
+ if (StringUtils.isNotBlank(dateTimeAsString)) {
+ try {
+ eventLocalDateTime = DateTimeFormat.forPattern(dateTimeFormat).withLocale(clientApplicationLocale)
+ .parseLocalDateTime(dateTimeAsString.toLowerCase(clientApplicationLocale));
+ } catch (final IllegalArgumentException e) {
+ final List dataValidationErrors = new ArrayList<>();
+ final ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.dateFormat.format", "The parameter "
+ + parameterName + " is invalid based on the dateFormat: '" + dateTimeFormat + "' and locale: '"
+ + clientApplicationLocale + "' provided:", parameterName, eventLocalDateTime, dateTimeFormat);
+ dataValidationErrors.add(error);
+
+ throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
+ dataValidationErrors);
+ }
+ }
+
+ return eventLocalDateTime;
+ }
+
+ private static void validateDateFormatAndLocale(final String parameterName, final String dateFormat,
+ final Locale clientApplicationLocale) {
if (StringUtils.isBlank(dateFormat) || clientApplicationLocale == null) {
final List dataValidationErrors = new ArrayList<>();
@@ -375,25 +406,6 @@ public class JsonParserHelper {
dataValidationErrors);
}
- LocalDate eventLocalDate = null;
- if (StringUtils.isNotBlank(dateAsString)) {
- try {
- // Locale locale = LocaleContextHolder.getLocale();
- eventLocalDate = DateTimeFormat.forPattern(dateFormat).withLocale(clientApplicationLocale)
- .parseLocalDate(dateAsString.toLowerCase(clientApplicationLocale));
- } catch (final IllegalArgumentException e) {
- final List dataValidationErrors = new ArrayList<>();
- final ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.date.format", "The parameter "
- + parameterName + " is invalid based on the dateFormat: '" + dateFormat + "' and locale: '"
- + clientApplicationLocale + "' provided:", parameterName, dateAsString, dateFormat);
- dataValidationErrors.add(error);
-
- throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
- dataValidationErrors);
- }
- }
-
- return eventLocalDate;
}
public Integer convertToInteger(final String numericalValueFormatted, final String parameterName, final Locale clientApplicationLocale) {
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/data/ResultsetColumnHeaderData.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/data/ResultsetColumnHeaderData.java
index 68ff31154..cb933a22c 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/data/ResultsetColumnHeaderData.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/data/ResultsetColumnHeaderData.java
@@ -69,6 +69,8 @@ public final class ResultsetColumnHeaderData {
displayType = "DECIMAL";
} else if (isAnyText()) {
displayType = "TEXT";
+ } else if(isBit()) {
+ displayType = "BOOLEAN";
} else {
throw new PlatformDataIntegrityException("error.msg.invalid.lookup.type", "Invalid Lookup Type:" + this.columnType
+ " - Column Name: " + this.columnName);
@@ -137,7 +139,7 @@ public final class ResultsetColumnHeaderData {
}
private boolean isAnyInteger() {
- return isInt() || isSmallInt() || isTinyInt() || isMediumInt() || isBigInt() || isBit();
+ return isInt() || isSmallInt() || isTinyInt() || isMediumInt() || isBigInt();
}
private boolean isInt() {
@@ -184,6 +186,10 @@ public final class ResultsetColumnHeaderData {
return "DATE".equalsIgnoreCase(this.columnDisplayType);
}
+ public boolean isDateTimeDisplayType() {
+ return "DATETIME".equalsIgnoreCase(this.columnDisplayType);
+ }
+
public boolean isIntegerDisplayType() {
return "INTEGER".equalsIgnoreCase(this.columnDisplayType);
}
@@ -192,6 +198,10 @@ public final class ResultsetColumnHeaderData {
return "DECIMAL".equalsIgnoreCase(this.columnDisplayType);
}
+ public boolean isBooleanDisplayType() {
+ return "BOOLEAN".equalsIgnoreCase(this.columnDisplayType);
+ }
+
public boolean isCodeValueDisplayType() {
return "CODEVALUE".equalsIgnoreCase(this.columnDisplayType);
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/GenericDataServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/GenericDataServiceImpl.java
index fe5fbec67..b347f1cdc 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/GenericDataServiceImpl.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/GenericDataServiceImpl.java
@@ -11,6 +11,7 @@ import java.util.List;
import javax.sql.DataSource;
import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
@@ -147,8 +148,13 @@ public class GenericDataServiceImpl implements GenericDataService {
final LocalDate localDate = new LocalDate(currVal);
writer.append("[" + localDate.getYear() + ", " + localDate.getMonthOfYear() + ", " + localDate.getDayOfMonth()
+ "]");
+ } else if (currColType.equals("DATETIME")) {
+ final LocalDateTime localDateTime = new LocalDateTime(currVal);
+ writer.append("[" + localDateTime.getYear() + ", " + localDateTime.getMonthOfYear() + ", "
+ + localDateTime.getDayOfMonth() + " " + localDateTime.getHourOfDay() + ", "
+ + localDateTime.getMinuteOfHour() + ", " + localDateTime.getSecondOfMinute() + ", "
+ + localDateTime.getMillisOfSecond() + "]");
} else {
-
writer.append(doubleQuote + replace(currVal, doubleQuote, slashDoubleQuote) + doubleQuote);
}
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
index 45e41516d..467dd8968 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
@@ -17,11 +17,13 @@ import java.util.Set;
import javax.sql.DataSource;
+import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.exception.GenericJDBCException;
import org.hibernate.exception.SQLGrammarException;
import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
import org.mifosplatform.infrastructure.codes.service.CodeReadPlatformService;
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
@@ -76,8 +78,10 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
{
put("string", "VARCHAR");
put("number", "INT");
+ put("boolean", "BIT");
put("decimal", "DECIMAL");
put("date", "DATE");
+ put("datetime", "DATETIME");
put("text", "TEXT");
put("dropdown", "INT");
}
@@ -514,7 +518,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
/***
* In cases of tables storing hierarchical entities (like m_group),
* different entities would end up being stored in the same table.
- *
+ *
* Ex: Centers are a specific type of group, add abstractions for
* the same
***/
@@ -777,7 +781,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
/**
* Update data table, set column value to empty string where current value
* is NULL. Run update SQL only if the "mandatory" property is set to true
- *
+ *
* @param datatableName
* Name of data table
* @param column
@@ -1028,7 +1032,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
if (datatableId != null) {
pkValue = datatableId;
}
- final String sql = getUpdateSql(dataTableName, pkName, pkValue, changes);
+ final String sql = getUpdateSql(grs.getColumnHeaders(), dataTableName, pkName, pkValue, changes);
logger.info("Update sql: " + sql);
if (StringUtils.isNotBlank(sql)) {
this.jdbcTemplate.update(sql);
@@ -1312,18 +1316,24 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
String selectColumns = "";
String columnName = "";
String pValue = null;
- for (final String key : affectedColumns.keySet()) {
- pValue = affectedColumns.get(key);
-
- if (StringUtils.isEmpty(pValue)) {
- pValueWrite = "null";
- } else {
- pValueWrite = singleQuote + this.genericDataService.replace(pValue, singleQuote, singleQuote + singleQuote) + singleQuote;
+ for(final ResultsetColumnHeaderData pColumnHeader : columnHeaders) {
+ final String key = pColumnHeader.getColumnName();
+ if(affectedColumns.containsKey(key)) {
+ pValue = affectedColumns.get(key);
+ if (StringUtils.isEmpty(pValue)) {
+ pValueWrite = "null";
+ } else {
+ if ("bit".equalsIgnoreCase(pColumnHeader.getColumnType())) {
+ pValueWrite = BooleanUtils.toString(BooleanUtils.toBooleanObject(pValue), "1", "0", "null");
+ } else {
+ pValueWrite = singleQuote + this.genericDataService.replace(pValue, singleQuote, singleQuote + singleQuote) + singleQuote;
+ }
+ }
+ columnName = "`" + key + "`";
+ insertColumns += ", " + columnName;
+ selectColumns += "," + pValueWrite + " as " + columnName;
}
- columnName = "`" + key + "`";
- insertColumns += ", " + columnName;
- selectColumns += "," + pValueWrite + " as " + columnName;
}
addSql = "insert into `" + datatable + "` (`" + fkName + "` " + insertColumns + ")" + " select " + appTableId + " as id"
@@ -1337,7 +1347,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
/**
* This method is used special for ppi cases Where the score need to be
* computed
- *
+ *
* @param columnHeaders
* @param datatable
* @param fkName
@@ -1385,8 +1395,9 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
return vaddSql;
}
- private String getUpdateSql(final String datatable, final String keyFieldName, final Long keyFieldValue,
- final Map changedColumns) {
+ private String getUpdateSql(List columnHeaders, final String datatable,
+ final String keyFieldName, final Long keyFieldValue,
+ final Map changedColumns) {
// just updating fields that have changed since pre-update read - though
// its possible these values are different from the page the user was
@@ -1402,22 +1413,28 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
final String singleQuote = "'";
boolean firstColumn = true;
String sql = "update `" + datatable + "` ";
+ for (final ResultsetColumnHeaderData pColumnHeader : columnHeaders) {
+ final String key = pColumnHeader.getColumnName();
+ if(changedColumns.containsKey(key)) {
+ if (firstColumn) {
+ sql += " set ";
+ firstColumn = false;
+ } else {
+ sql += ", ";
+ }
- for (final String key : changedColumns.keySet()) {
- if (firstColumn) {
- sql += " set ";
- firstColumn = false;
- } else {
- sql += ", ";
+ pValue = (String) changedColumns.get(key);
+ if (StringUtils.isEmpty(pValue)) {
+ pValueWrite = "null";
+ } else {
+ if ("bit".equalsIgnoreCase(pColumnHeader.getColumnType())) {
+ pValueWrite = BooleanUtils.toString(BooleanUtils.toBooleanObject(pValue), "1", "0", "null");
+ } else {
+ pValueWrite = singleQuote + this.genericDataService.replace(pValue, singleQuote, singleQuote + singleQuote) + singleQuote;
+ }
+ }
+ sql += "`" + key + "` = " + pValueWrite;
}
-
- pValue = (String) changedColumns.get(key);
- if (StringUtils.isEmpty(pValue)) {
- pValueWrite = "null";
- } else {
- pValueWrite = singleQuote + this.genericDataService.replace(pValue, singleQuote, singleQuote + singleQuote) + singleQuote;
- }
- sql += "`" + key + "` = " + pValueWrite;
}
sql += " where " + keyFieldName + " = " + keyFieldValue;
@@ -1511,7 +1528,8 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
final Locale clientApplicationLocale) {
String paramValue = pValue;
- if (columnHeader.isDateDisplayType() || columnHeader.isIntegerDisplayType() || columnHeader.isDecimalDisplayType()) {
+ if (columnHeader.isDateDisplayType() || columnHeader.isDateTimeDisplayType()
+ || columnHeader.isIntegerDisplayType() || columnHeader.isDecimalDisplayType() || columnHeader.isBooleanDisplayType()) {
// only trim if string is not empty and is not null.
// throws a NULL pointer exception if the check below is not applied
paramValue = StringUtils.isNotEmpty(paramValue) ? paramValue.trim() : paramValue;
@@ -1569,6 +1587,14 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
} else {
paramValue = tmpDate.toString();
}
+ } else if (columnHeader.isDateTimeDisplayType()) {
+ final LocalDateTime tmpDateTime = JsonParserHelper.convertDateTimeFrom(paramValue,
+ columnHeader.getColumnName(), dateFormat, clientApplicationLocale);
+ if (tmpDateTime == null) {
+ paramValue = null;
+ } else {
+ paramValue = tmpDateTime.toString();
+ }
} else if (columnHeader.isIntegerDisplayType()) {
final Integer tmpInt = this.helper.convertToInteger(paramValue, columnHeader.getColumnName(), clientApplicationLocale);
if (tmpInt == null) {
@@ -1583,6 +1609,20 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
} else {
paramValue = tmpDecimal.toString();
}
+ } else if (columnHeader.isBooleanDisplayType()) {
+
+ final Boolean tmpBoolean = BooleanUtils.toBooleanObject(paramValue);
+ if (tmpBoolean == null) {
+ final ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.boolean.format", "The parameter "
+ + columnHeader.getColumnName() + " has value: " + paramValue + " which is invalid boolean value.",
+ columnHeader.getColumnName(), paramValue);
+ final List dataValidationErrors = new ArrayList<>();
+ dataValidationErrors.add(error);
+ throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
+ dataValidationErrors);
+ } else {
+ paramValue = tmpBoolean.toString();
+ }
} else if (columnHeader.isString()) {
if (paramValue.length() > columnHeader.getColumnLength()) {
final ApiParameterError error = ApiParameterError.parameterError(
| |