MIFOSX-237: ensure big decimal entries are compared correctly and only transactions with changes are audited.

This commit is contained in:
Keith Woodlock
2013-03-13 01:49:28 +00:00
parent 509daca905
commit 5ca8d6801d
8 changed files with 102 additions and 55 deletions
+14 -10
View File
@@ -8435,10 +8435,7 @@ Request Body:
<div class="method-description">
<h4>Delete Entry(s) in Data Table</h4>
<p>
Deletes the entry (if it exists) for data tables that are one to
one with the application table. <br> Deletes the entries (if
they exist) for data tables that are one to many with the
application table.
Deletes the entry (if it exists) for data tables that are one-to-one with the application table. <br> Deletes the entries (if they exist) for data tables that are one-to-many with the application table.
</p>
</div>
<div class="method-example">
@@ -8446,14 +8443,17 @@ Request Body:
DELETE https://DomainName/api/v1/datatables/{datatable}/{apptableId}
</code>
<code class="method-request">
DELETE datatables/Additional Client Fields Data/1
DELETE datatables/extra_client_details/1
Content-Type: application/json
Request Body:
{}
</code>
<code class="method-response">{ "resourceId": 1 } </code>
<code class="method-response">
{
"resourceId": 1
}
</code>
</div>
</div>
@@ -8461,7 +8461,7 @@ Request Body:
class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Delete Entry in Data Table (One to Many)</h4>
<h4>Delete Entry in Datatable (One to Many)</h4>
<p>Deletes the entry (if it exists) for data tables that are
one to many with the application table.</p>
</div>
@@ -8470,13 +8470,17 @@ Request Body:
DELETE https://DomainName/api/v1/datatables/{datatable}/{apptableId}/{datatableId}
</code>
<code class="method-request">
DELETE datatables/Extra Family Details Data/1/2
DELETE datatables/extra_family_details/1/2
Content-Type: application/json
Request Body:
{}
</code>
<code class="method-response">{ "resourceId": 1 } </code>
<code class="method-response">
{
"resourceId": 1
}
</code>
</div>
</div>
<!-- end of datatables api docs -->
@@ -23,8 +23,8 @@ public class CommandWrapper {
private final Long datatableId;
private final Long codeId;
private final String transactionId;
private String supportedEntityType;
private Long supportedEntityId;
private final String supportedEntityType;
private final Long supportedEntityId;
public static CommandWrapper wrap(final String actionName, final String enityName, final Long resourceId) {
return new CommandWrapper(null, actionName, enityName, resourceId);
@@ -163,7 +163,7 @@ public class CommandWrapper {
|| (isUpdateOperation() && this.entityId != null);
}
private boolean isUpdateOperation() {
public boolean isUpdateOperation() {
return this.actionName.equalsIgnoreCase("UPDATE");
}
@@ -77,7 +77,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
commandSourceResult.updateJsonTo(changesOnlyJson);
}
if (!result.hasChanges() && wrapper.isUpdate()) {
if (!result.hasChanges() && wrapper.isUpdateOperation()) {
commandSourceResult.updateJsonTo(null);
}
@@ -79,7 +79,6 @@ public class DatatablesApiResource {
this.readWriteNonCoreDataService.registerDatatable(datatable, apptable);
final CommandProcessingResult result = new CommandProcessingResultBuilder().withResourceIdAsString(datatable).build();
return this.toApiJsonSerializer.serialize(result);
}
@@ -151,8 +150,10 @@ public class DatatablesApiResource {
public String createDatatableEntry(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId,
final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createDatatable(datatable, apptableId, null)
.withJson(apiRequestBodyAsJson).build();
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.createDatatable(datatable, apptableId, null) //
.withJson(apiRequestBodyAsJson) //
.build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
@@ -166,8 +167,10 @@ public class DatatablesApiResource {
public String updateDatatableEntryOnetoOne(@PathParam("datatable") final String datatable,
@PathParam("apptableId") final Long apptableId, final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateDatatable(datatable, apptableId, null)
.withJson(apiRequestBodyAsJson).build();
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.updateDatatable(datatable, apptableId, null) //
.withJson(apiRequestBodyAsJson) //
.build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
@@ -182,8 +185,10 @@ public class DatatablesApiResource {
@PathParam("apptableId") final Long apptableId, @PathParam("datatableId") final Long datatableId,
final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateDatatable(datatable, apptableId, datatableId)
.withJson(apiRequestBodyAsJson).build();
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.updateDatatable(datatable, apptableId, datatableId) //
.withJson(apiRequestBodyAsJson) //
.build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
@@ -196,7 +201,9 @@ public class DatatablesApiResource {
@Produces({ MediaType.APPLICATION_JSON })
public String deleteDatatableEntries(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteDatatable(datatable, apptableId, null).build();
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.deleteDatatable(datatable, apptableId, null) //
.build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
@@ -210,7 +217,9 @@ public class DatatablesApiResource {
public String deleteDatatableEntries(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId,
@PathParam("datatableId") final Long datatableId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteDatatable(datatable, apptableId, datatableId).build();
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.deleteDatatable(datatable, apptableId, datatableId) //
.build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
@@ -11,7 +11,7 @@ import java.util.List;
/**
* Immutable data object for generic resultset data.
*/
public class GenericResultsetData {
public final class GenericResultsetData {
private final List<ResultsetColumnHeaderData> columnHeaders;
private final List<ResultsetRowData> data;
@@ -28,4 +28,28 @@ public class GenericResultsetData {
public List<ResultsetRowData> getData() {
return data;
}
public String getColTypeOfColumnNamed(final String columnName) {
String colType = null;
for (ResultsetColumnHeaderData columnHeader : this.columnHeaders) {
if (columnHeader.isNamed(columnName)) {
colType = columnHeader.getColumnType();
}
}
return colType;
}
public boolean hasNoEntries() {
return this.data.isEmpty();
}
public boolean hasEntries() {
return !hasNoEntries();
}
public boolean hasMoreThanOneEntry() {
return this.data.size() > 1;
}
}
@@ -80,6 +80,10 @@ public final class ResultsetColumnHeaderData {
this.columnDisplayType = displayType;
}
public boolean isNamed(final String columnName) {
return this.columnName.equalsIgnoreCase(columnName);
}
private boolean isAnyText() {
return isText() || isTinyText() || isMediumText() || isLongText();
}
@@ -30,6 +30,9 @@ public class DeleteOneToOneDatatableEntryCommandHandler implements NewCommandSou
this.writePlatformService.deleteDatatableEntries(command.entityName(), command.getApptableId());
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(command.getApptableId()).build();
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(command.getApptableId()) //
.build();
}
}
@@ -242,29 +242,26 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
@Override
public Map<String, Object> updateDatatableEntryOneToOne(final String datatable, final Long appTableId, final JsonCommand command) {
GenericResultsetData grs = retrieveDataTableGenericResultSet(datatable, appTableId, null, null);
final GenericResultsetData grs = retrieveDataTableGenericResultSet(datatable, appTableId, null, null);
if (grs.getData().size() == 0) throw new DatatableNotFoundException(datatable, appTableId);
if (grs.hasNoEntries()) { throw new DatatableNotFoundException(datatable, appTableId); }
if (grs.getData().size() > 1)
throw new PlatformDataIntegrityException("error.msg.attempting.multiple.update", "Application Table: " + datatable
+ " Foreign Key Id: " + appTableId);
if (grs.hasMoreThanOneEntry()) { throw new PlatformDataIntegrityException("error.msg.attempting.multiple.update",
"Application table: " + datatable + " Foreign key id: " + appTableId); }
String fkName = getFKField(queryForApplicationTableName(datatable));
final String fkName = getFKField(queryForApplicationTableName(datatable));
final Type typeOfMap = new TypeToken<Map<String, String>>() {}.getType();
Map<String, String> dataParams = this.fromJsonHelper.extractDataMap(typeOfMap, command.json());
final Map<String, Object> changes = getAffectedAndChangedColumns(grs, dataParams, fkName);
if (changes.size() == 0) return changes;
if (!changes.isEmpty()) {
final String updateOneToOneDatatableSql = getUpdateSql(datatable, fkName, appTableId, changes);
final String sql = getUpdateSql(datatable, fkName, appTableId, changes);
if (StringUtils.isNotBlank(sql)) {
this.jdbcTemplate.update(sql);
} else {
logger.info("No Changes");
if (StringUtils.isNotBlank(updateOneToOneDatatableSql)) {
this.jdbcTemplate.update(updateOneToOneDatatableSql);
}
}
return changes;
@@ -301,9 +298,10 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
final String appTable = getWithinScopeApplicationTableName(datatable, appTableId);
final String sql = getDeleteEntriesSql(datatable, getFKField(appTable), appTableId);
final String deleteOneToOneEntrySql = getDeleteEntriesSql(datatable, getFKField(appTable), appTableId);
this.jdbcTemplate.update(sql);
int rowsDeleted = this.jdbcTemplate.update(deleteOneToOneEntrySql);
if (rowsDeleted < 1) { throw new DatatableNotFoundException(datatable, appTableId); }
}
@Override
@@ -334,9 +332,11 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
sql = sql + "select * from `" + datatable + "` where id = " + id;
}
if (order != null) sql = sql + " order by " + order;
if (order != null) {
sql = sql + " order by " + order;
}
List<ResultsetRowData> result = fillDatatableResultSetDataRows(sql);
final List<ResultsetRowData> result = fillDatatableResultSetDataRows(sql);
return new GenericResultsetData(columnHeaders, result);
}
@@ -513,13 +513,13 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
private Map<String, Object> getAffectedAndChangedColumns(final GenericResultsetData grs, final Map<String, String> queryParams,
final String fkName) {
Map<String, String> affectedColumns = getAffectedColumns(grs.getColumnHeaders(), queryParams, fkName);
Map<String, Object> affectedAndChangedColumns = new HashMap<String, Object>();
String columnValue;
final Map<String, String> affectedColumns = getAffectedColumns(grs.getColumnHeaders(), queryParams, fkName);
final Map<String, Object> affectedAndChangedColumns = new HashMap<String, Object>();
for (String key : affectedColumns.keySet()) {
columnValue = affectedColumns.get(key);
if (columnChanged(key, columnValue, grs)) {
for (final String key : affectedColumns.keySet()) {
final String columnValue = affectedColumns.get(key);
final String colType = grs.getColTypeOfColumnNamed(key);
if (columnChanged(key, columnValue, colType, grs)) {
affectedAndChangedColumns.put(key, columnValue);
}
}
@@ -527,7 +527,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
return affectedAndChangedColumns;
}
private boolean columnChanged(final String key, final String keyValue, final GenericResultsetData grs) {
private boolean columnChanged(final String key, final String keyValue, final String colType, final GenericResultsetData grs) {
List<String> columnValues = grs.getData().get(0).getRow();
@@ -537,12 +537,8 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
if (key.equals(grs.getColumnHeaders().get(i).getColumnName())) {
columnValue = columnValues.get(i);
if (notTheSame(columnValue, keyValue)) {
// logger.info("Difference - Column: " + key +
// "- Current Value: " + columnValue + " New Value: " +
// keyValue);
if (notTheSame(columnValue, keyValue, colType)) {
return true;
}
return false;
}
@@ -691,13 +687,20 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
}
private boolean notTheSame(final String currValue, final String pValue) {
private boolean notTheSame(final String currValue, final String pValue, final String colType) {
if (StringUtils.isEmpty(currValue) && StringUtils.isEmpty(pValue)) return false;
if (StringUtils.isEmpty(currValue)) return true;
if (StringUtils.isEmpty(pValue)) return true;
if ("DECIMAL".equalsIgnoreCase(colType)) {
final BigDecimal currentDecimal = BigDecimal.valueOf(Double.valueOf(currValue));
final BigDecimal newDecimal = BigDecimal.valueOf(Double.valueOf(pValue));
return currentDecimal.compareTo(newDecimal) != 0;
}
if (currValue.equals(pValue)) return false;
return true;