update api docs around codes, update validation from JSON API request.
This commit is contained in:
+152
-3
@@ -213,9 +213,24 @@ function getBaseURL(docURL)
|
|||||||
<td><a href="#configs_global">GLOBAL CONFIGURATION</a></td><td>configurations</td>
|
<td><a href="#configs_global">GLOBAL CONFIGURATION</a></td><td>configurations</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><a href="#configs_globalconfig_retrieve">Retrieve Global Configuration</a></td>
|
<td><a href="#configs_globalconfig_retrieve">Retrieve Global Configuration</a></td>
|
||||||
<td><a href="#configs_globalconfig_currencyupdate">Update Global Configuration</a></td>
|
<td><a href="#configs_globalconfig_update">Update Global Configuration</a></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr class="alt">
|
||||||
|
<td><a href="#configs_codes">CODES</a></td><td>codes</td>
|
||||||
|
<td><a href="#configs_codes_create">Create a Code</a></td>
|
||||||
|
<td><a href="#configs_codes_retrieve">List Codes</a></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="alt">
|
||||||
|
<td></td>
|
||||||
|
<td>codes/{codeId}</td>
|
||||||
|
<td></td>
|
||||||
|
<td><a href="#configs_code_retrieve">Retrieve a Code</a></td>
|
||||||
|
<td><a href="#configs_code_update">Update a Code</a></td>
|
||||||
|
<td><a href="#configs_code_delete">Delete a Code</a></td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -2315,7 +2330,7 @@ Request Body:
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a id="configs_globalconfig_currencyupdate" name="configs_globalconfig_currencyupdate" class="old-syle-anchor"> </a>
|
<a id="configs_globalconfig_update" name="configs_globalconfig_update" class="old-syle-anchor"> </a>
|
||||||
<div class="method-section">
|
<div class="method-section">
|
||||||
<div class="method-description">
|
<div class="method-description">
|
||||||
<h4>Update Global Configuration</h4>
|
<h4>Update Global Configuration</h4>
|
||||||
@@ -2336,6 +2351,125 @@ Request Body:
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a id="configs_codes" name="configs_codes" class="old-syle-anchor"> </a>
|
||||||
|
<div class="method-section">
|
||||||
|
<div class="method-description">
|
||||||
|
<h3>Codes</h3>
|
||||||
|
<p>Code and code values: Codes represent a specific category of data, their code values are a specific instance of that category.</p>
|
||||||
|
<p>Codes are mostly <b>system defined</b> which means the code itself comes out of the box and cannot be modifed however its code values can be. e.g. 'Customer Identifier', it defaults to a code value of 'Passport' but could be 'Drivers License, National Id' etc<p/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a id="configs_codes_create" name="configs_codes_create" class="old-syle-anchor"> </a>
|
||||||
|
<div class="method-section">
|
||||||
|
<div class="method-description">
|
||||||
|
<h4>Create a Code</h4>
|
||||||
|
<p>Creates a code. Codes created through api are always 'user defined' and so system defined is marked as false.</p>
|
||||||
|
</div>
|
||||||
|
<div class="method-example">
|
||||||
|
<code class="method-declaration">POST https://Domain Name/api/v1/codes</code>
|
||||||
|
<code class="method-request">POST codes
|
||||||
|
Content-Type: application/json
|
||||||
|
Request Body:
|
||||||
|
{
|
||||||
|
"name": "MyNewCode"
|
||||||
|
}
|
||||||
|
</code>
|
||||||
|
<code class="method-response">{
|
||||||
|
"resourceId": 2
|
||||||
|
}
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a id="configs_codes_retrieve" name="configs_codes_retrieve" class="old-syle-anchor"> </a>
|
||||||
|
<div class="method-section">
|
||||||
|
<div class="method-description">
|
||||||
|
<h4>Retrieve Codes</h4>
|
||||||
|
<p>Returns the list of codes.</p>
|
||||||
|
<p>Example Requests: </p>
|
||||||
|
<div class=apiClick>codes</div>
|
||||||
|
</div>
|
||||||
|
<div class="method-example">
|
||||||
|
<code class="method-declaration">GET https://Domain Name/api/v1/codes</code>
|
||||||
|
<code class="method-response">[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Customer Identifier",
|
||||||
|
"systemDefined": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "MyNewCode",
|
||||||
|
"systemDefined": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a id="configs_code_retrieve" name="configs_code_retrieve" class="old-syle-anchor"> </a>
|
||||||
|
<div class="method-section">
|
||||||
|
<div class="method-description">
|
||||||
|
<h4>Retrieve a Code</h4>
|
||||||
|
<p>Returns the details of a Code.</p>
|
||||||
|
<p>Example Requests: </p>
|
||||||
|
<div class=apiClick>codes/1</div>
|
||||||
|
</div>
|
||||||
|
<div class="method-example">
|
||||||
|
<code class="method-declaration">GET https://Domain Name/api/v1/codes/1</code>
|
||||||
|
<code class="method-response">{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Customer Identifier",
|
||||||
|
"systemDefined": true
|
||||||
|
}
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a id="configs_code_update" name="configs_codes_update" class="old-syle-anchor"> </a>
|
||||||
|
<div class="method-section">
|
||||||
|
<div class="method-description">
|
||||||
|
<h4>Update a Code</h4>
|
||||||
|
<p>Updates the details of a code if it is not system defined.</p>
|
||||||
|
</div>
|
||||||
|
<div class="method-example">
|
||||||
|
<code class="method-declaration">PUT https://Domain Name/api/v1/codes/2</code>
|
||||||
|
<code class="method-request">PUT codes/2
|
||||||
|
Content-Type: application/json
|
||||||
|
Request Body:
|
||||||
|
{
|
||||||
|
"name": "MyNewCode(changed)"
|
||||||
|
}
|
||||||
|
</code>
|
||||||
|
<code class="method-response">{
|
||||||
|
"resourceId": 2,
|
||||||
|
"changes": {
|
||||||
|
"name": "MyNewCode(changed)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a id="configs_code_delete" name="configs_code_delete" class="old-syle-anchor"> </a>
|
||||||
|
<div class="method-section">
|
||||||
|
<div class="method-description">
|
||||||
|
<h4>Delete a Code</h4>
|
||||||
|
<p>Deletes a code if it is not system defined.</p>
|
||||||
|
</div>
|
||||||
|
<div class="method-example">
|
||||||
|
<code class="method-declaration">DELETE https://Domain Name/api/v1/codes/2</code>
|
||||||
|
<code class="method-request">DELETE codes/2
|
||||||
|
Content-Type: application/json
|
||||||
|
</code>
|
||||||
|
<code class="method-response">{
|
||||||
|
"resourceId": 2
|
||||||
|
}
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- start of datatables api docs -->
|
<!-- start of datatables api docs -->
|
||||||
<a id="datatables" name="datatables" class="old-syle-anchor"> </a>
|
<a id="datatables" name="datatables" class="old-syle-anchor"> </a>
|
||||||
<div class="method-section">
|
<div class="method-section">
|
||||||
@@ -3424,9 +3558,24 @@ Request body:
|
|||||||
<td><a href="#configs_global">GLOBAL CONFIGURATION</a></td><td>configurations</td>
|
<td><a href="#configs_global">GLOBAL CONFIGURATION</a></td><td>configurations</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><a href="#configs_globalconfig_retrieve">Retrieve Global Configuration</a></td>
|
<td><a href="#configs_globalconfig_retrieve">Retrieve Global Configuration</a></td>
|
||||||
<td><a href="#configs_globalconfig_currencyupdate">Update Global Configuration</a></td>
|
<td><a href="#configs_globalconfig_update">Update Global Configuration</a></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr class="alt">
|
||||||
|
<td><a href="#configs_codes">CODES</a></td><td>codes</td>
|
||||||
|
<td><a href="#configs_codes_create">Create a Code</a></td>
|
||||||
|
<td><a href="#configs_codes_retrieve">List Codes</a></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="alt">
|
||||||
|
<td></td>
|
||||||
|
<td>codes/{codeId}</td>
|
||||||
|
<td></td>
|
||||||
|
<td><a href="#configs_code_retrieve">Retrieve a Code</a></td>
|
||||||
|
<td><a href="#configs_code_update">Update a Code</a></td>
|
||||||
|
<td><a href="#configs_code_delete">Delete a Code</a></td>
|
||||||
|
</tr>
|
||||||
<tr><td><a href="#datatables">DATA TABLE</a></td><td>datatables</td><td></td><td><a href="#datatables_list">List Data Tables</a></td><td></td><td></td></tr>
|
<tr><td><a href="#datatables">DATA TABLE</a></td><td>datatables</td><td></td><td><a href="#datatables_list">List Data Tables</a></td><td></td><td></td></tr>
|
||||||
<tr class="alt"><td></td><td>datatables/register/{datatable}/{apptable}</td><td><a href="#datatables_register">Register Data Table</a></td><td></td><td></td><td></td></tr>
|
<tr class="alt"><td></td><td>datatables/register/{datatable}/{apptable}</td><td><a href="#datatables_register">Register Data Table</a></td><td></td><td></td><td></td></tr>
|
||||||
<tr><td></td><td>datatables/deregister/{datatable}</td><td><a href="#datatables_deregister">Deregister Data Table</a></td><td></td><td></td><td></td></tr>
|
<tr><td></td><td>datatables/deregister/{datatable}</td><td><a href="#datatables_deregister">Deregister Data Table</a></td><td></td><td></td><td></td></tr>
|
||||||
|
|||||||
-42
@@ -1,42 +0,0 @@
|
|||||||
package org.mifosplatform.infrastructure.codes.command;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
|
||||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Immutable command for creating or updating details of a code.</p>
|
|
||||||
*/
|
|
||||||
public class CodeCommand {
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
public CodeCommand(final String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void validateForCreate() {
|
|
||||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
|
||||||
|
|
||||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("code");
|
|
||||||
baseDataValidator.reset().parameter("name").value(this.name).notBlank();
|
|
||||||
|
|
||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
|
||||||
"Validation errors exist.", dataValidationErrors); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void validateForUpdate() {
|
|
||||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
|
||||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("code");
|
|
||||||
|
|
||||||
baseDataValidator.reset().parameter("name").value(this.name).notBlank();
|
|
||||||
|
|
||||||
baseDataValidator.reset().anyOfNotNull(this.name);
|
|
||||||
|
|
||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
|
||||||
"Validation errors exist.", dataValidationErrors); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+39
-11
@@ -1,16 +1,18 @@
|
|||||||
package org.mifosplatform.infrastructure.codes.serialization;
|
package org.mifosplatform.infrastructure.codes.serialization;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.mifosplatform.infrastructure.codes.command.CodeCommand;
|
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||||
import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
|
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer;
|
|
||||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -19,10 +21,10 @@ import com.google.gson.JsonElement;
|
|||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link FromApiJsonDeserializer} for {@link CodeCommand}'s.
|
* Deserializer for code JSON to validate API request.
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public final class CodeCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer<CodeCommand> {
|
public final class CodeCommandFromApiJsonDeserializer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parameters supported for this command.
|
* The parameters supported for this command.
|
||||||
@@ -35,17 +37,43 @@ public final class CodeCommandFromApiJsonDeserializer extends AbstractFromApiJso
|
|||||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void validateForCreate(final String json) {
|
||||||
public CodeCommand commandFromApiJson(final String json) {
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||||
|
|
||||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||||
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
|
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
|
||||||
|
|
||||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
final String name = fromApiJsonHelper.extractStringNamed("name", element);
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("code");
|
||||||
|
|
||||||
return new CodeCommand(name);
|
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||||
|
|
||||||
|
final String name = fromApiJsonHelper.extractStringNamed("name", element);
|
||||||
|
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100);
|
||||||
|
|
||||||
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validateForUpdate(final String json) {
|
||||||
|
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||||
|
|
||||||
|
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||||
|
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
|
||||||
|
|
||||||
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("code");
|
||||||
|
|
||||||
|
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||||
|
if (fromApiJsonHelper.parameterExists("name", element)) {
|
||||||
|
final String name = fromApiJsonHelper.extractStringNamed("name", element);
|
||||||
|
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||||
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||||
|
"Validation errors exist.", dataValidationErrors); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+9
-7
@@ -2,7 +2,6 @@ package org.mifosplatform.infrastructure.codes.service;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.mifosplatform.infrastructure.codes.command.CodeCommand;
|
|
||||||
import org.mifosplatform.infrastructure.codes.domain.Code;
|
import org.mifosplatform.infrastructure.codes.domain.Code;
|
||||||
import org.mifosplatform.infrastructure.codes.domain.CodeRepository;
|
import org.mifosplatform.infrastructure.codes.domain.CodeRepository;
|
||||||
import org.mifosplatform.infrastructure.codes.exception.CodeNotFoundException;
|
import org.mifosplatform.infrastructure.codes.exception.CodeNotFoundException;
|
||||||
@@ -44,8 +43,7 @@ public class CodeWritePlatformServiceJpaRepositoryImpl implements CodeWritePlatf
|
|||||||
try {
|
try {
|
||||||
context.authenticatedUser();
|
context.authenticatedUser();
|
||||||
|
|
||||||
final CodeCommand codeCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json());
|
this.fromApiJsonDeserializer.validateForCreate(command.json());
|
||||||
codeCommand.validateForCreate();
|
|
||||||
|
|
||||||
final Code code = Code.fromJson(command);
|
final Code code = Code.fromJson(command);
|
||||||
this.codeRepository.save(code);
|
this.codeRepository.save(code);
|
||||||
@@ -62,17 +60,21 @@ public class CodeWritePlatformServiceJpaRepositoryImpl implements CodeWritePlatf
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
context.authenticatedUser();
|
context.authenticatedUser();
|
||||||
final CodeCommand codeCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json());
|
|
||||||
codeCommand.validateForUpdate();
|
this.fromApiJsonDeserializer.validateForUpdate(command.json());
|
||||||
|
|
||||||
final Code code = retrieveCodeBy(codeId);
|
final Code code = retrieveCodeBy(codeId);
|
||||||
Map<String, Object> changes = code.update(command);
|
final Map<String, Object> changes = code.update(command);
|
||||||
|
|
||||||
if (!changes.isEmpty()) {
|
if (!changes.isEmpty()) {
|
||||||
this.codeRepository.save(code);
|
this.codeRepository.save(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(codeId).with(changes).build();
|
return new CommandProcessingResultBuilder() //
|
||||||
|
.withCommandId(command.commandId()) //
|
||||||
|
.withEntityId(codeId) //
|
||||||
|
.with(changes) //
|
||||||
|
.build();
|
||||||
} catch (DataIntegrityViolationException dve) {
|
} catch (DataIntegrityViolationException dve) {
|
||||||
handleCodeDataIntegrityIssues(command, dve);
|
handleCodeDataIntegrityIssues(command, dve);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user