MIFOSX-1877 ability to edit working days by clients and added license text to ConcurrencyIntegrationTest file

This commit is contained in:
andrew-dzak
2015-03-12 14:08:41 +01:00
parent f440f294ad
commit fdd84097ea
20 changed files with 853 additions and 5 deletions
+137 -1
View File
@@ -1846,11 +1846,17 @@
</tr>
<tr>
<td><a href="#workingdays">Working days</a></td>
<td>workingdays</td>
<td><a href="#workingdays_list">List workingdays</a></td>
<td><a href="#workingdays_template">Working days template</a></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>workingdays/{workingdaysId}</td>
<td></td>
<td></td>
<td><a href="#workingdays_update">Update a workingdays</a></td>
</tr>
<tr>
<td><a href="#templates">User Generated Documents</a></td>
@@ -13737,6 +13743,31 @@ Request Body:
<p>
Allow transactions on non-working days is configurable by enabling/disbaling the allow-transactions-on-non_workingday parameter in <a href="#configs_global">Global configurations</a>.
</p>
<table class=matrixHeading>
<tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Mandotory Field Descriptions</div></td>
</tr>
<tr class=alt>
<td>recurrence</td>
</tr>
<tr>
<td class=fielddesc>Recurrence pattern</td>
</tr>
<tr class=alt>
<td>repaymentRescheduleType</td>
</tr>
<tr>
<td class=fielddesc>repayment reschedule type .Options listed on the schedule for repayments on non-working days
</td>
</tr>
<tr class=alt>
<td>locale</td>
</tr>
<tr>
<td class=fielddesc>locale must be provided.</td>
</tr>
</table>
<table id="nw_repayment_schedule_rule" class=matrixHeading>
<tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Schedule for repayments on non-working day</div></td>
@@ -13772,6 +13803,111 @@ Request Body:
</table>
</div>
</div>
<a id="workingdays_template" name="workingdays_template"
class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Working Days Template</h4>
<p>This is a convenience resource. It can be useful when
building maintenance user interface screens for working days.
</p>
<p>Example Request:</p>
<div class=apiClick>workingdays/template</div>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/api/v1/workingdays/template
</code>
<code class="method-response">
{
"repaymentRescheduleOptions": [
{
"id": 1,
"code": "RepaymentRescheduleType.same.day",
"value": "same day"
},
{
"id": 4,
"code": "RepaymentRescheduleType.move.to.previous.working.day",
"value": "move to previous working day"
},
{
"id": 3,
"code": "RepaymentRescheduleType.move.to.next.repayment.meeting.day",
"value": "move to next repayment meeting day"
},
{
"id": 2,
"code": "RepaymentRescheduleType.move.to.next.working.day",
"value": "move to next working day"
}
]
}
</code>
</div>
</div>
<a id="workingdays_list" name="workingdays_list" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>List Working days</h4>
<p>Example Requests:</p>
<div class=apiClick>workingdays</div>
<br>
<br>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/api/v1/workingdays
</code>
<code class="method-response">
[
{
"id": 1,
"recurrence": "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR",
"repaymentRescheduleType": {
"id": 4,
"code": "RepaymentRescheduleType.move.to.next.working.day",
"value": "move to next working day"
}
}
]
</code>
</div>
</div>
<a id="workingdays_update" name="workingdays_update" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Update a Working Day</h4>
<table class=matrixHeading>
<tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Mandatory Fields</div></td>
</tr>
<tr class=alt>
<td>recurrence,repaymentRescheduleType,locale</td>
</tr>
</table>
</div>
<div class="method-example">
<code class="method-declaration">
PUT https://DomainName/api/v1/Workingdays/1
</code>
<code class="method-request">
PUT holidays
Content-Type: application/json
Request Body:
{
"recurrence": "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,SU",
"locale": "en",
"repaymentsRescheduledType": 4
}
</code>
<code class="method-response">
{
"resourceId": 1
}
</code>
</div>
</div>
<!-- end of workingdays api docs -->
@@ -1,3 +1,8 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.integrationtests;
import java.text.DateFormat;
@@ -0,0 +1,55 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.integrationtests;
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;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mifosplatform.integrationtests.common.CommonConstants;
import org.mifosplatform.integrationtests.common.Utils;
import org.mifosplatform.integrationtests.common.WorkingDaysHelper;
import java.util.HashMap;
import java.util.List;
import static org.junit.Assert.assertEquals;
@SuppressWarnings({ "rawtypes", "unchecked" })
public class WorkingDaysTest {
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
private ResponseSpecification generalResponseSpec;
@Before
public void setUp(){
Utils.initializeRESTAssured();
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
this.generalResponseSpec = new ResponseSpecBuilder().build();
}
@Test
public void updateWorkingDays(){
HashMap response = (HashMap)WorkingDaysHelper.updateWorkingDays(requestSpec, responseSpec);
Assert.assertNotNull(response.get("resourceId"));
}
@Test
public void updateWorkingDaysWithWrongRecurrencePattern(){
final List<HashMap> error = (List) WorkingDaysHelper.updateWorkingDaysWithWrongRecurrence(requestSpec, generalResponseSpec, CommonConstants.RESPONSE_ERROR);
assertEquals("Verify wrong recurrence pattern error", "error.msg.recurring.rule.parsing.error", error.get(0).get("userMessageGlobalisationCode"));
}
}
@@ -0,0 +1,78 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.integrationtests.common;
import com.google.gson.Gson;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
public class WorkingDaysHelper {
private static final String WORKINGDAYS_URL = "/mifosng-provider/api/v1/workingdays";
private static final String CREATE_HOLIDAY_URL = WORKINGDAYS_URL + "?" + Utils.TENANT_IDENTIFIER;
public static Object updateWorkingDays(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
final String UPDATE_WORKINGDAYS_URL = WORKINGDAYS_URL +"/" +workingDaysId(requestSpec,responseSpec) + "?" + Utils.TENANT_IDENTIFIER;
System.out.println("---------------------------------UPDATE WORKINGDAY---------------------------------------------");
return Utils.performServerPut(requestSpec, responseSpec,UPDATE_WORKINGDAYS_URL, updateWorkingDaysAsJson(), "");
}
public static Object updateWorkingDaysWithWrongRecurrence(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,String jsonAttributeToGetback){
final String UPDATE_WORKINGDAYS_URL = WORKINGDAYS_URL +"/" +workingDaysId(requestSpec,responseSpec) + "?" + Utils.TENANT_IDENTIFIER;
System.out.println("---------------------------------UPDATE WORKINGDAY WITH WRONG RECURRENCE-----------------------------------------");
return Utils.performServerPut(requestSpec, responseSpec,UPDATE_WORKINGDAYS_URL, updateWorkingDayWithWrongRecur(), jsonAttributeToGetback);
}
public static String updateWorkingDaysAsJson(){
final HashMap<String, Object> map = new HashMap<>();
map.put("recurrence", "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH");
map.put("locale", "en");
map.put("repaymentRescheduleType", randomInt(1,4));
System.out.println("map : " + map);
return new Gson().toJson(map);
}
public static String updateWorkingDayWithWrongRecur(){
final HashMap<String, Object> map = new HashMap<>();
map.put("recurrence", "FREQ=WEEKLY;INTERVAL=1;BYDAY=MP,TI,TE,TH");
map.put("locale", "en");
map.put("repaymentRescheduleType", randomInt(1,4));
System.out.println("map : " + map);
return new Gson().toJson(map);
}
public static int randomInt(int low, int high){
int i = new Random().nextInt(high) + low;
return i;
}
public static int workingDaysId(final RequestSpecification requestSpec,final ResponseSpecification responseSpec){
List<HashMap<String, Object>> workingDaysId = getAllWorkingDays(requestSpec,responseSpec);
final HashMap<String, Object> workingDay = workingDaysId.get(0);
return (int) workingDay.get("id");
}
public static ArrayList<HashMap<String, Object>> getAllWorkingDays(
final RequestSpecification requestSpec,
final ResponseSpecification responseSpec) {
return Utils.performServerGet(requestSpec, responseSpec, WORKINGDAYS_URL + "?"
+ Utils.TENANT_IDENTIFIER, "");
}
}
@@ -1012,8 +1012,13 @@ public class CommandWrapper {
public boolean isEnableOperation() {
return this.actionName.equalsIgnoreCase("ENABLE");
}
public boolean isEntityMappingResource() {
return this.entityName.equalsIgnoreCase("ENTITYMAPPING");
}
public boolean isWorkingDaysResource() {
return this.entityName.equalsIgnoreCase("WORKINGDAYS");
}
}
@@ -2353,4 +2353,12 @@ public class CommandWrapperBuilder {
this.href = "/entitytoentitymapping/" + mapId;
return this;
}
public CommandWrapperBuilder updateWorkingDays(final Long workingDaysId) {
this.actionName = "UPDATE";
this.entityName = "WORKINGDAYS";
this.entityId = workingDaysId;
this.href = "/workingdays/" + workingDaysId;
return this;
}
}
@@ -923,6 +923,12 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if(wrapper.isWorkingDaysResource()) {
if(wrapper.isUpdate()){
handler = this.applicationContext.getBean("updateWorkingDaysCommandHandler",NewCommandSourceHandler.class);
}else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else {
throw new UnsupportedCommandException(wrapper.commandName());
@@ -0,0 +1,36 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.organisation.workingdays.api;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class WorkingDaysApiConstants {
public static final String WORKING_DAYS_RESOURCE_NAME = "workingdays";
// request parameters
public static final String recurrence = "recurrence";
public static final String repayment_rescheduling_enum = "repaymentRescheduleType";
public static final String idParamName = "id";
public static final String rescheduleRepaymentTemplate = "rescheduleRepaymentTemplate";
public static final String localeParamName = "locale";
public static final Set<String> WORKING_DAYS_CREATE_OR_UPDATE_REQUEST_DATA_PARAMETERS =new HashSet<>(Arrays.asList(
recurrence,repayment_rescheduling_enum,localeParamName
));
public static final Set<String> WORKING_DAYS_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(idParamName,
recurrence,repayment_rescheduling_enum
));
public static final Set<String> WORKING_DAYS_TEMPLATE_PARAMETERS = new HashSet<>(Arrays.asList(rescheduleRepaymentTemplate));
}
@@ -0,0 +1,109 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.organisation.workingdays.api;
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.organisation.workingdays.data.WorkingDaysData;
import org.mifosplatform.organisation.workingdays.service.WorkingDaysReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import java.util.Collection;
@Path("/workingdays")
@Component
@Scope("singleton")
public class WorkingDaysApiResource {
private final DefaultToApiJsonSerializer<WorkingDaysData> toApiJsonSerializer;
private final WorkingDaysReadPlatformService workingDaysReadPlatformService;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final PlatformSecurityContext context;
private final ApiRequestParameterHelper apiRequestParameterHelper;
@Autowired
public WorkingDaysApiResource(DefaultToApiJsonSerializer<WorkingDaysData> toApiJsonSerializer, WorkingDaysReadPlatformService workingDaysReadPlatformService, PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, PlatformSecurityContext context, ApiRequestParameterHelper apiRequestParameterHelper) {
this.toApiJsonSerializer = toApiJsonSerializer;
this.workingDaysReadPlatformService = workingDaysReadPlatformService;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.context = context;
this.apiRequestParameterHelper = apiRequestParameterHelper;
}
@GET
@Path("{workingdaysId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveOne(@PathParam("workingdaysId") final Long workingDaysId, @Context final UriInfo uriInfo){
this.context.authenticatedUser().validateHasReadPermission(WorkingDaysApiConstants.WORKING_DAYS_RESOURCE_NAME);
final WorkingDaysData workingDaysData = this.workingDaysReadPlatformService.retrieveOne(workingDaysId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings,workingDaysData);
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAll(@Context final UriInfo uriInfo){
this.context.authenticatedUser().validateHasReadPermission(WorkingDaysApiConstants.WORKING_DAYS_RESOURCE_NAME);
final Collection<WorkingDaysData> workingDaysData = this.workingDaysReadPlatformService.retrieveAll();
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings,workingDaysData);
}
@PUT
@Path("{workingdaysId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String update(@PathParam("workingdaysId") final Long workingDaysId,final String jsonRequestBody, @Context final UriInfo uriInfo){
this.context.authenticatedUser().validateHasReadPermission(WorkingDaysApiConstants.WORKING_DAYS_RESOURCE_NAME);
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateWorkingDays(workingDaysId).withJson(jsonRequestBody).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
@GET
@Path("/template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String template(@Context final UriInfo uriInfo){
this.context.authenticatedUser().validateHasReadPermission(WorkingDaysApiConstants.WORKING_DAYS_RESOURCE_NAME);
final WorkingDaysData repaymentRescheduleOptions = this.workingDaysReadPlatformService.repaymentRescheduleType();
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings,repaymentRescheduleOptions,WorkingDaysApiConstants.WORKING_DAYS_TEMPLATE_PARAMETERS);
}
}
@@ -0,0 +1,70 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.organisation.workingdays.data;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.lang.StringUtils;
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.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.organisation.workingdays.api.WorkingDaysApiConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Component
public class WorkingDayValidator {
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public WorkingDayValidator(FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
public void validateForUpdate(final String json){
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json,
WorkingDaysApiConstants.WORKING_DAYS_CREATE_OR_UPDATE_REQUEST_DATA_PARAMETERS);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource( WorkingDaysApiConstants.WORKING_DAYS_RESOURCE_NAME);
final String recurrence = this.fromApiJsonHelper.extractStringNamed(WorkingDaysApiConstants.recurrence, element);
baseDataValidator.reset().parameter(WorkingDaysApiConstants.recurrence).value(recurrence).notNull();
final Integer repaymentRescheduleType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("repaymentRescheduleType", element);
baseDataValidator.reset().parameter("repaymentRescheduleType").value(repaymentRescheduleType).ignoreIfNull().inMinMaxRange(1,4);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) {
//
throw new PlatformApiDataValidationException(dataValidationErrors);
}
}
}
@@ -0,0 +1,39 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.organisation.workingdays.data;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import java.util.Collection;
public class WorkingDaysData {
@SuppressWarnings("unused")
private final Long id;
@SuppressWarnings("unused")
private final String recurrence;
@SuppressWarnings("unused")
private final EnumOptionData repaymentRescheduleType;
//template date
private final Collection<EnumOptionData> repaymentRescheduleOptions;
public WorkingDaysData(Long id, String recurrence, EnumOptionData repaymentRescheduleType) {
this.id = id;
this.recurrence = recurrence;
this.repaymentRescheduleType = repaymentRescheduleType;
this.repaymentRescheduleOptions = null;
}
public WorkingDaysData(Long id, String recurrence, EnumOptionData repaymentRescheduleType, Collection<EnumOptionData> repaymentRescheduleOptions) {
this.id = null;
this.recurrence = null;
this.repaymentRescheduleType = null;
this.repaymentRescheduleOptions = repaymentRescheduleOptions;
}
}
@@ -6,11 +6,14 @@
package org.mifosplatform.organisation.workingdays.domain;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.springframework.data.jpa.domain.AbstractPersistable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.springframework.data.jpa.domain.AbstractPersistable;
import java.util.LinkedHashMap;
import java.util.Map;
@Entity
@Table(name = "m_working_days")
@@ -45,4 +48,24 @@ public class WorkingDays extends AbstractPersistable<Long> {
return this.repaymentReschedulingType;
}
public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
final String recurrenceParamName = "recurrence";
if (command.isChangeInStringParameterNamed(recurrenceParamName, this.recurrence)) {
final String newValue = command.stringValueOfParameterNamed(recurrenceParamName);
actualChanges.put(recurrenceParamName, newValue);
this.recurrence = newValue;
}
final String repaymentRescheduleTypeParamName = "repaymentRescheduleType";
if (command.isChangeInIntegerParameterNamed(repaymentRescheduleTypeParamName, this.repaymentReschedulingType)) {
final Integer newValue =command.integerValueOfParameterNamed(repaymentRescheduleTypeParamName);
actualChanges.put(repaymentRescheduleTypeParamName, WorkingDaysEnumerations.workingDaysStatusType(newValue));
this.repaymentReschedulingType = RepaymentRescheduleType.fromInt(newValue).getValue();
}
return actualChanges;
}
}
@@ -0,0 +1,47 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.organisation.workingdays.domain;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
public class WorkingDaysEnumerations {
public static EnumOptionData workingDaysStatusType(final int id) {
return repaymentRescheduleType(RepaymentRescheduleType.fromInt(id));
}
public static EnumOptionData repaymentRescheduleType(final RepaymentRescheduleType type){
EnumOptionData optionData = null;
switch(type){
case INVALID:
optionData = new EnumOptionData(RepaymentRescheduleType.INVALID.getValue().longValue(),RepaymentRescheduleType.INVALID.getCode(),
"invalid");
break;
case SAME_DAY:
optionData = new EnumOptionData(RepaymentRescheduleType.SAME_DAY.getValue().longValue(),RepaymentRescheduleType.SAME_DAY.getCode(),
"same day");
break;
case MOVE_TO_NEXT_WORKING_DAY:
optionData = new EnumOptionData(RepaymentRescheduleType.MOVE_TO_NEXT_WORKING_DAY.getValue().longValue(),RepaymentRescheduleType.MOVE_TO_NEXT_WORKING_DAY.getCode(),
"move to next working day");
break;
case MOVE_TO_NEXT_REPAYMENT_MEETING_DAY:
optionData = new EnumOptionData(RepaymentRescheduleType.MOVE_TO_NEXT_REPAYMENT_MEETING_DAY.getValue().longValue(),RepaymentRescheduleType.MOVE_TO_NEXT_REPAYMENT_MEETING_DAY.getCode(),
"move to next repayment meeting day");
break;
case MOVE_TO_PREVIOUS_WORKING_DAY:
optionData = new EnumOptionData(RepaymentRescheduleType.MOVE_TO_PREVIOUS_WORKING_DAY.getValue().longValue(),RepaymentRescheduleType.MOVE_TO_PREVIOUS_WORKING_DAY.getCode(),
"move to previous working day");
break;
}
return optionData;
}
}
@@ -15,4 +15,8 @@ public class WorkingDaysNotFoundException extends AbstractPlatformResourceNotFou
public WorkingDaysNotFoundException() {
super("error.msg.working.days.not.configured", "Must configure the Working days for the organisation.");
}
public WorkingDaysNotFoundException(Long id){
super("error.msg.workingdays.id.invalid", "Working day with identifier " + id + " does not exist", id);
}
}
@@ -0,0 +1,31 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.organisation.workingdays.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.organisation.workingdays.service.WorkingDaysWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UpdateWorkingDaysCommandHandler implements NewCommandSourceHandler {
private final WorkingDaysWritePlatformService workingDaysWritePlatformService;
@Autowired
public UpdateWorkingDaysCommandHandler(final WorkingDaysWritePlatformService workingDaysWritePlatformService) {
this.workingDaysWritePlatformService = workingDaysWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.workingDaysWritePlatformService.updateWorkingDays(command);
}
}
@@ -0,0 +1,19 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.organisation.workingdays.service;
import org.mifosplatform.organisation.workingdays.data.WorkingDaysData;
import java.util.Collection;
public interface WorkingDaysReadPlatformService {
Collection<WorkingDaysData> retrieveAll();
WorkingDaysData retrieveOne(Long id);
WorkingDaysData repaymentRescheduleType();
}
@@ -0,0 +1,96 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.organisation.workingdays.service;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.workingdays.data.WorkingDaysData;
import org.mifosplatform.organisation.workingdays.domain.RepaymentRescheduleType;
import org.mifosplatform.organisation.workingdays.domain.WorkingDaysEnumerations;
import org.mifosplatform.organisation.workingdays.exception.WorkingDaysNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
@Service
public class WorkingDaysReadPlatformServiceImpl implements WorkingDaysReadPlatformService{
private final PlatformSecurityContext context;
private final JdbcTemplate jdbcTemplate;
@Autowired
public WorkingDaysReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
private static final class WorkingDaysMapper implements RowMapper<WorkingDaysData> {
private final String schema;
public WorkingDaysMapper() {
final StringBuilder sqlBuilder = new StringBuilder(100);
sqlBuilder.append("w.id as id,w.recurrence as recurrence,w.repayment_rescheduling_enum as status_enum ");
sqlBuilder.append("from m_working_days w");
this.schema = sqlBuilder.toString();
}
public String schema() {
return this.schema;
}
@Override
public WorkingDaysData mapRow(ResultSet rs, int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final String recurrence = rs.getString("recurrence");
final Integer statusEnum = JdbcSupport.getInteger(rs, "status_enum");
final EnumOptionData status = WorkingDaysEnumerations.workingDaysStatusType(statusEnum);
return new WorkingDaysData(id,recurrence,status);
}
}
@Override
public Collection<WorkingDaysData> retrieveAll() {
final WorkingDaysMapper rm = new WorkingDaysMapper();
final String sql = " select " + rm.schema() ;
return this.jdbcTemplate.query(sql, rm, new Object[] {});
}
@Override
public WorkingDaysData retrieveOne(final Long id) {
try {
final WorkingDaysMapper rm = new WorkingDaysMapper();
final String sql = " select " + rm.schema() + " where w.id = ?";
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { id });
} catch (final EmptyResultDataAccessException e) {
throw new WorkingDaysNotFoundException(id);
}
}
@Override
public WorkingDaysData repaymentRescheduleType() {
Collection<EnumOptionData> repaymentRescheduleOptions = Arrays.asList(WorkingDaysEnumerations.repaymentRescheduleType(RepaymentRescheduleType.SAME_DAY),
WorkingDaysEnumerations.repaymentRescheduleType(RepaymentRescheduleType.MOVE_TO_NEXT_WORKING_DAY),
WorkingDaysEnumerations.repaymentRescheduleType(RepaymentRescheduleType.MOVE_TO_NEXT_REPAYMENT_MEETING_DAY),
WorkingDaysEnumerations.repaymentRescheduleType(RepaymentRescheduleType.MOVE_TO_PREVIOUS_WORKING_DAY)
);
return new WorkingDaysData(null,null,null,repaymentRescheduleOptions);
}
}
@@ -6,10 +6,14 @@
package org.mifosplatform.organisation.workingdays.service;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
public interface WorkingDaysWritePlatformService {
boolean isWorkingDay(LocalDate transactionDate);
boolean isTransactionAllowedOnNonWorkingDay();
CommandProcessingResult updateWorkingDays(JsonCommand command);
}
@@ -5,24 +5,39 @@
*/
package org.mifosplatform.organisation.workingdays.service;
import net.fortuna.ical4j.model.ValidationException;
import net.fortuna.ical4j.model.property.RRule;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.organisation.workingdays.api.WorkingDaysApiConstants;
import org.mifosplatform.organisation.workingdays.data.WorkingDayValidator;
import org.mifosplatform.organisation.workingdays.domain.WorkingDays;
import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.ParseException;
import java.util.Map;
@Service
public class WorkingDaysWritePlatformServiceJpaRepositoryImpl implements WorkingDaysWritePlatformService {
private final WorkingDaysRepositoryWrapper daysRepositoryWrapper;
private final ConfigurationDomainService configurationDomainService;
private final WorkingDayValidator fromApiJsonDeserializer;
@Autowired
public WorkingDaysWritePlatformServiceJpaRepositoryImpl(final WorkingDaysRepositoryWrapper daysRepositoryWrapper,
final ConfigurationDomainService configurationDomainService) {
final ConfigurationDomainService configurationDomainService,
final WorkingDayValidator fromApiJsonDeserializer) {
this.daysRepositoryWrapper = daysRepositoryWrapper;
this.configurationDomainService = configurationDomainService;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
}
@Override
@@ -36,4 +51,30 @@ public class WorkingDaysWritePlatformServiceJpaRepositoryImpl implements Working
return this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled();
}
@Transactional
@Override
public CommandProcessingResult updateWorkingDays(JsonCommand command) {
String recurrence = "";
RRule rrule = null;
try{
this.fromApiJsonDeserializer.validateForUpdate(command.json());
final WorkingDays workingDays = this.daysRepositoryWrapper.findOne();
recurrence = command.stringValueOfParameterNamed(WorkingDaysApiConstants.recurrence);
rrule = new RRule(recurrence);
rrule.validate();
Map<String, Object> changes = workingDays.update(command);
this.daysRepositoryWrapper.saveAndFlush(workingDays);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(workingDays.getId()).build();
}catch (final ValidationException e) {
throw new PlatformDataIntegrityException("error.msg.invalid.recurring.rule", "The Recurring Rule value: " + recurrence
+ " is not valid.", "recurrence", recurrence);
} catch (final IllegalArgumentException|ParseException e) {
throw new PlatformDataIntegrityException("error.msg.recurring.rule.parsing.error",
"Error in passing the Recurring Rule value: " + recurrence, "recurrence", e.getMessage());
}
}
}
@@ -0,0 +1,36 @@
INSERT INTO `m_permission` (
`grouping` ,
`code` ,
`entity_name` ,
`action_name` ,
`can_maker_checker`
)
VALUES (
'organisation', 'READ_WORKINGDAYS', 'WORKINGDAYS', 'READ', '0'
);
INSERT INTO `m_permission` (
`grouping` ,
`code` ,
`entity_name` ,
`action_name` ,
`can_maker_checker`
)
VALUES (
'organisation', 'UPDATE_WORKINGDAYS', 'WORKINGDAYS', 'UPDATE', '0'
);
INSERT INTO `m_permission` (
`grouping` ,
`code` ,
`entity_name` ,
`action_name` ,
`can_maker_checker`
)
VALUES (
'organisation', 'UPDATE_WORKINGDAYS_CHECKER', 'WORKINGDAYS', 'UPDATE_CHECKER', '0'
);