FINERACT 2289: New command processing - Working Days

command base test fix
This commit is contained in:
yuwatidora
2026-02-20 21:39:41 +01:00
committed by Aleksandar Vidakovic
parent ce3c9cc297
commit 701cfae60b
16 changed files with 341 additions and 143 deletions
+34
View File
@@ -0,0 +1,34 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
services:
mysql:
container_name: mysql
image: mysql:8
volumes:
- ${PWD}/config/docker/mysql/conf.d/server_collation.cnf:/etc/mysql/conf.d/server_collation.cnf:ro
- ${PWD}/config/docker/mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:Z,ro
restart: always
env_file:
- ${PWD}/config/docker/env/mysql.env
healthcheck:
test: [ "CMD", "healthcheck.sh", "--su-mysql", "--connect", "--innodb_initialized" ]
timeout: 10s
retries: 10
ports:
- "3306:3306"
@@ -21,16 +21,21 @@ package org.apache.fineract.organisation.workingdays.domain;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import java.util.LinkedHashMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import lombok.experimental.FieldNameConstants;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import org.apache.fineract.organisation.workingdays.api.WorkingDaysApiConstants;
@Builder
@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
@Table(name = "m_working_days")
public class WorkingDays extends AbstractPersistableCustom<Long> {
@@ -47,51 +52,4 @@ public class WorkingDays extends AbstractPersistableCustom<Long> {
@Column(name = "extend_term_holiday_repayment", nullable = false)
private Boolean extendTermForRepaymentsOnHolidays;
protected WorkingDays() {
}
public WorkingDays(final String recurrence, final Integer repaymentReschedulingType, final Boolean extendTermForDailyRepayments,
final Boolean extendTermForRepaymentsOnHolidays) {
this.recurrence = recurrence;
this.repaymentReschedulingType = repaymentReschedulingType;
this.extendTermForDailyRepayments = extendTermForDailyRepayments;
this.extendTermForRepaymentsOnHolidays = extendTermForRepaymentsOnHolidays;
}
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();
}
if (command.isChangeInBooleanParameterNamed(WorkingDaysApiConstants.extendTermForDailyRepayments,
this.extendTermForDailyRepayments)) {
final Boolean newValue = command.booleanPrimitiveValueOfParameterNamed(WorkingDaysApiConstants.extendTermForDailyRepayments);
actualChanges.put(WorkingDaysApiConstants.extendTermForDailyRepayments, newValue);
this.extendTermForDailyRepayments = newValue;
}
if (command.isChangeInBooleanParameterNamed(WorkingDaysApiConstants.extendTermForRepaymentsOnHolidays,
this.extendTermForRepaymentsOnHolidays)) {
final Boolean newValue = command
.booleanPrimitiveValueOfParameterNamed(WorkingDaysApiConstants.extendTermForRepaymentsOnHolidays);
actualChanges.put(WorkingDaysApiConstants.extendTermForRepaymentsOnHolidays, newValue);
this.extendTermForRepaymentsOnHolidays = newValue;
}
return actualChanges;
}
}
@@ -41,8 +41,8 @@ public final class WorkingDaysEnumerations {
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");
@@ -52,10 +52,12 @@ public final class WorkingDaysEnumerations {
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;
case MOVE_TO_NEXT_MEETING_DAY:
optionData = new EnumOptionData(RepaymentRescheduleType.MOVE_TO_NEXT_MEETING_DAY.getValue().longValue(),
RepaymentRescheduleType.MOVE_TO_NEXT_MEETING_DAY.getCode(), "move to next meeting day");
@@ -328,6 +328,13 @@ public class SecurityConfig {
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_MIX_REPORT")
.requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/mixreport/*"))
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_MIX_REPORT")
// working days
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/workingdays"))
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_WORKING_DAYS")
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/workingdays/template"))
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_WORKING_DAYS")
.requestMatchers(API_MATCHER.matcher(HttpMethod.PUT, "/api/*/workingdays"))
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_WORKING_DAYS")
.requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/twofactor/validate")).fullyAuthenticated()
.requestMatchers(API_MATCHER.matcher("/api/*/twofactor")).fullyAuthenticated()
@@ -19,26 +19,23 @@
package org.apache.fineract.organisation.workingdays.api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import java.time.Instant;
import java.util.function.Supplier;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.command.core.CommandPipeline;
import org.apache.fineract.organisation.workingdays.command.WorkingDaysUpdateCommand;
import org.apache.fineract.organisation.workingdays.data.WorkingDaysData;
import org.apache.fineract.organisation.workingdays.data.WorkingDaysUpdateRequest;
import org.apache.fineract.organisation.workingdays.data.WorkingDaysUpdateRequestValidator;
import org.apache.fineract.organisation.workingdays.data.WorkingDaysUpdateResponse;
import org.apache.fineract.organisation.workingdays.service.WorkingDaysReadPlatformService;
import org.springframework.stereotype.Component;
@@ -51,17 +48,15 @@ import org.springframework.stereotype.Component;
@RequiredArgsConstructor
public class WorkingDaysApiResource {
private final DefaultToApiJsonSerializer<WorkingDaysData> toApiJsonSerializer;
private final WorkingDaysReadPlatformService workingDaysReadPlatformService;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final PlatformSecurityContext context;
private final WorkingDaysUpdateRequestValidator workingDaysUpdateRequestValidator;
private final CommandPipeline commandPipeline;
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "List Working days", description = "Example Requests:\n" + "\n" + "workingdays")
public WorkingDaysData retrieveAll() {
this.context.authenticatedUser().validateHasReadPermission(WorkingDaysApiConstants.WORKING_DAYS_RESOURCE_NAME);
return this.workingDaysReadPlatformService.retrieve();
}
@@ -70,15 +65,17 @@ public class WorkingDaysApiResource {
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Update a Working Day", description = "Mandatory Fields\n"
+ "recurrence,repaymentRescheduleType,extendTermForDailyRepayments,locale")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = WorkingDaysApiResourceSwagger.PutWorkingDaysRequest.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = WorkingDaysApiResourceSwagger.PutWorkingDaysResponse.class)))
public String update(@Parameter(hidden = true) final String jsonRequestBody) {
public WorkingDaysUpdateResponse update(@Valid WorkingDaysUpdateRequest request) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateWorkingDays().withJson(jsonRequestBody).build();
final var command = new WorkingDaysUpdateCommand();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
command.setCommandId(System.currentTimeMillis());
command.setCreatedAt(Instant.now());
command.setPayload(request);
return this.toApiJsonSerializer.serialize(result);
final Supplier<WorkingDaysUpdateResponse> response = commandPipeline.send(command);
return response.get();
}
@GET
@@ -87,10 +84,7 @@ public class WorkingDaysApiResource {
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Working Days Template", description = "This is a convenience resource. It can be useful when building maintenance user interface screens for working days.\n"
+ "\n" + "Example Request:\n" + "\n" + "workingdays/template")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = WorkingDaysApiResourceSwagger.GetWorkingDaysTemplateResponse.class)))
public WorkingDaysData template() {
this.context.authenticatedUser().validateHasReadPermission(WorkingDaysApiConstants.WORKING_DAYS_RESOURCE_NAME);
return this.workingDaysReadPlatformService.repaymentRescheduleType();
}
@@ -0,0 +1,28 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.organisation.workingdays.command;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.fineract.command.core.Command;
import org.apache.fineract.organisation.workingdays.data.WorkingDaysUpdateRequest;
@Data
@EqualsAndHashCode(callSuper = true)
public class WorkingDaysUpdateCommand extends Command<WorkingDaysUpdateRequest> {}
@@ -37,6 +37,7 @@ import org.apache.fineract.organisation.workingdays.api.WorkingDaysApiConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
//Not used
@Component
public class WorkingDayValidator {
@@ -21,12 +21,18 @@ package org.apache.fineract.organisation.workingdays.data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Collection;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldNameConstants;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
public class WorkingDaysData implements Serializable {
@Serial
@@ -42,37 +48,7 @@ public class WorkingDaysData implements Serializable {
private Boolean extendTermForRepaymentsOnHolidays;
// template date
@SuppressWarnings("unused")
private Collection<EnumOptionData> repaymentRescheduleOptions;
public WorkingDaysData(Long id, String recurrence, EnumOptionData repaymentRescheduleType, Boolean extendTermForDailyRepayments,
Boolean extendTermForRepaymentsOnHolidays) {
this.id = id;
this.recurrence = recurrence;
this.repaymentRescheduleType = repaymentRescheduleType;
this.repaymentRescheduleOptions = null;
this.extendTermForDailyRepayments = extendTermForDailyRepayments;
this.extendTermForRepaymentsOnHolidays = extendTermForRepaymentsOnHolidays;
}
public WorkingDaysData(Long id, String recurrence, EnumOptionData repaymentRescheduleType,
Collection<EnumOptionData> repaymentRescheduleOptions, Boolean extendTermForDailyRepayments,
Boolean extendTermForRepaymentsOnHolidays) {
this.id = id;
this.recurrence = recurrence;
this.repaymentRescheduleType = repaymentRescheduleType;
this.repaymentRescheduleOptions = repaymentRescheduleOptions;
this.extendTermForDailyRepayments = extendTermForDailyRepayments;
this.extendTermForRepaymentsOnHolidays = extendTermForRepaymentsOnHolidays;
}
public WorkingDaysData(WorkingDaysData data, Collection<EnumOptionData> repaymentRescheduleOptions) {
this.id = data.id;
this.recurrence = data.recurrence;
this.repaymentRescheduleType = data.repaymentRescheduleType;
this.repaymentRescheduleOptions = repaymentRescheduleOptions;
this.extendTermForDailyRepayments = data.extendTermForDailyRepayments;
this.extendTermForRepaymentsOnHolidays = data.extendTermForRepaymentsOnHolidays;
}
}
@@ -0,0 +1,47 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.organisation.workingdays.data;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.io.Serial;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class WorkingDaysUpdateRequest implements Serializable {
@Serial
public static final long serialVersionUID = 1L;
private String recurrence;
private Integer repaymentRescheduleType;
private Boolean extendTermForDailyRepayments;
private Boolean extendTermForRepaymentsOnHolidays;
}
@@ -0,0 +1,62 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.organisation.workingdays.data;
import java.util.ArrayList;
import java.util.List;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.organisation.workingdays.api.WorkingDaysApiConstants;
import org.springframework.stereotype.Component;
@Component
public class WorkingDaysUpdateRequestValidator {
public void validateForUpdate(final WorkingDaysUpdateRequest request) {
List<ApiParameterError> validationErrors = new ArrayList<>();
DataValidatorBuilder validator = new DataValidatorBuilder(validationErrors)
.resource(WorkingDaysApiConstants.WORKING_DAYS_RESOURCE_NAME);
// recurrence (mandatory)
String recurrence = request.getRecurrence();
validator.reset().parameter(WorkingDaysApiConstants.recurrence).value(recurrence).notNull();
// repaymentRescheduleType (optional, but must be 1–4 if present)
validator.reset().parameter(WorkingDaysApiConstants.repayment_rescheduling_enum).value(request.getRepaymentRescheduleType())
.ignoreIfNull().inMinMaxRange(1, 4);
// extendTermForDailyRepayments (optional but must be boolean if provided)
validator.reset().parameter(WorkingDaysApiConstants.extendTermForDailyRepayments).value(request.getExtendTermForDailyRepayments())
.ignoreIfNull().validateForBooleanValue();
// extendTermForRepaymentsOnHolidays (optional but must be boolean if provided)
validator.reset().parameter(WorkingDaysApiConstants.extendTermForRepaymentsOnHolidays)
.value(request.getExtendTermForRepaymentsOnHolidays()).ignoreIfNull().validateForBooleanValue();
throwExceptionIfValidationWarningsExist(validationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> validationErrors) {
if (!validationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(validationErrors);
}
}
}
@@ -0,0 +1,43 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.organisation.workingdays.data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class WorkingDaysUpdateResponse implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long resourceId;
private String recurrence;
private Integer repaymentRescheduleType;
private Boolean extendTermForDailyRepayments;
private Boolean extendTermForRepaymentsOnHolidays;
private Map<String, Object> changes;
}
@@ -18,29 +18,38 @@
*/
package org.apache.fineract.organisation.workingdays.handler;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import java.util.Collections;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.command.core.Command;
import org.apache.fineract.command.core.CommandHandler;
import org.apache.fineract.organisation.workingdays.data.WorkingDaysUpdateRequest;
import org.apache.fineract.organisation.workingdays.data.WorkingDaysUpdateResponse;
import org.apache.fineract.organisation.workingdays.service.WorkingDaysWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "WORKINGDAYS", action = "UPDATE")
public class UpdateWorkingDaysCommandHandler implements NewCommandSourceHandler {
@Slf4j
@Component
@RequiredArgsConstructor
public class UpdateWorkingDaysCommandHandler implements CommandHandler<WorkingDaysUpdateRequest, WorkingDaysUpdateResponse> {
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);
public WorkingDaysUpdateResponse handle(Command<WorkingDaysUpdateRequest> command) {
WorkingDaysUpdateRequest request = command.getPayload();
Map<String, Object> changes = this.workingDaysWritePlatformService.updateWorkingDays(request);
if (changes == null) {
changes = Collections.emptyMap();
}
return WorkingDaysUpdateResponse.builder().resourceId((Long) changes.get("resourceId")).changes(changes)
.recurrence(request.getRecurrence()).repaymentRescheduleType(request.getRepaymentRescheduleType())
.extendTermForDailyRepayments(request.getExtendTermForDailyRepayments())
.extendTermForRepaymentsOnHolidays(request.getExtendTermForRepaymentsOnHolidays()).build();
}
}
@@ -65,7 +65,9 @@ public class WorkingDaysReadPlatformServiceImpl implements WorkingDaysReadPlatfo
final Boolean extendTermForDailyRepayments = rs.getBoolean("extendTermForDailyRepayments");
final Boolean extendTermForRepaymentsOnHolidays = rs.getBoolean("extendTermForRepaymentsOnHolidays");
return new WorkingDaysData(id, recurrence, status, extendTermForDailyRepayments, extendTermForRepaymentsOnHolidays);
return WorkingDaysData.builder().id(id).recurrence(recurrence).repaymentRescheduleType(status)
.extendTermForDailyRepayments(extendTermForDailyRepayments)
.extendTermForRepaymentsOnHolidays(extendTermForRepaymentsOnHolidays).build();
}
}
@@ -77,7 +79,11 @@ public class WorkingDaysReadPlatformServiceImpl implements WorkingDaysReadPlatfo
final String sql = " select " + rm.schema();
WorkingDaysData data = this.jdbcTemplate.queryForObject(sql, rm); // NOSONAR
Collection<EnumOptionData> repaymentRescheduleOptions = repaymentRescheduleTypeOptions();
return new WorkingDaysData(data, repaymentRescheduleOptions);
return WorkingDaysData.builder().id(data.getId()).recurrence(data.getRecurrence())
.repaymentRescheduleType(data.getRepaymentRescheduleType())
.extendTermForDailyRepayments(data.getExtendTermForDailyRepayments())
.extendTermForRepaymentsOnHolidays(data.getExtendTermForRepaymentsOnHolidays())
.repaymentRescheduleOptions(repaymentRescheduleOptions).build();
} catch (final EmptyResultDataAccessException e) {
throw new WorkingDaysNotFoundException(e);
}
@@ -86,7 +92,7 @@ public class WorkingDaysReadPlatformServiceImpl implements WorkingDaysReadPlatfo
@Override
public WorkingDaysData repaymentRescheduleType() {
Collection<EnumOptionData> repaymentRescheduleOptions = repaymentRescheduleTypeOptions();
return new WorkingDaysData(null, null, null, repaymentRescheduleOptions, null, null);
return WorkingDaysData.builder().repaymentRescheduleOptions(repaymentRescheduleOptions).build();
}
private Collection<EnumOptionData> repaymentRescheduleTypeOptions() {
@@ -18,10 +18,12 @@
*/
package org.apache.fineract.organisation.workingdays.service;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import java.util.Map;
import org.apache.fineract.organisation.workingdays.data.WorkingDaysUpdateRequest;
import org.springframework.transaction.annotation.Transactional;
public interface WorkingDaysWritePlatformService {
CommandProcessingResult updateWorkingDays(JsonCommand command);
@Transactional
Map<String, Object> updateWorkingDays(WorkingDaysUpdateRequest request);
}
@@ -19,16 +19,15 @@
package org.apache.fineract.organisation.workingdays.service;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import net.fortuna.ical4j.model.property.RRule;
import net.fortuna.ical4j.validate.ValidationException;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
import org.apache.fineract.organisation.workingdays.api.WorkingDaysApiConstants;
import org.apache.fineract.organisation.workingdays.data.WorkingDayValidator;
import org.apache.fineract.organisation.workingdays.data.WorkingDaysUpdateRequest;
import org.apache.fineract.organisation.workingdays.data.WorkingDaysUpdateRequestValidator;
import org.apache.fineract.organisation.workingdays.domain.WorkingDays;
import org.apache.fineract.organisation.workingdays.domain.WorkingDaysRepositoryWrapper;
import org.springframework.transaction.annotation.Transactional;
@@ -37,25 +36,27 @@ import org.springframework.transaction.annotation.Transactional;
public class WorkingDaysWritePlatformServiceJpaRepositoryImpl implements WorkingDaysWritePlatformService {
private final WorkingDaysRepositoryWrapper daysRepositoryWrapper;
private final WorkingDayValidator fromApiJsonDeserializer;
private final WorkingDaysUpdateRequestValidator validator;
@Transactional
@Override
public CommandProcessingResult updateWorkingDays(JsonCommand command) {
public Map<String, Object> updateWorkingDays(WorkingDaysUpdateRequest request) {
String recurrence = "";
RRule rrule = null;
try {
this.fromApiJsonDeserializer.validateForUpdate(command.json());
this.validator.validateForUpdate(request);
final WorkingDays workingDays = this.daysRepositoryWrapper.findOne();
recurrence = command.stringValueOfParameterNamed(WorkingDaysApiConstants.recurrence);
recurrence = request.getRecurrence();
rrule = new RRule(recurrence);
rrule.validate();
Map<String, Object> changes = workingDays.update(command);
Map<String, Object> changes = update(workingDays, request);
// include the current WorkingDays resource id in the changes for response consumption
changes.put("resourceId", workingDays.getId());
this.daysRepositoryWrapper.saveAndFlush(workingDays);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(workingDays.getId()).with(changes)
.build();
return changes;
} catch (final ValidationException e) {
throw new PlatformDataIntegrityException("error.msg.invalid.recurring.rule",
"The Recurring Rule value: " + recurrence + " is not valid.", "recurrence", recurrence, e);
@@ -65,4 +66,32 @@ public class WorkingDaysWritePlatformServiceJpaRepositoryImpl implements Working
}
}
public HashMap<String, Object> update(WorkingDays workingDays, WorkingDaysUpdateRequest request) {
HashMap<String, Object> changes = new HashMap<>();
if (!Objects.equals(request.getRecurrence(), workingDays.getRecurrence())) {
workingDays.setRecurrence(request.getRecurrence());
changes.put("recurrence", request.getRecurrence());
}
Integer repaymentRescheduleType = request.getRepaymentRescheduleType();
if (repaymentRescheduleType != null && !Objects.equals(repaymentRescheduleType, workingDays.getRepaymentReschedulingType())) {
workingDays.setRepaymentReschedulingType(repaymentRescheduleType);
changes.put("repaymentRescheduleType", repaymentRescheduleType);
}
Boolean extendDaily = request.getExtendTermForDailyRepayments();
if (extendDaily != null && !Objects.equals(extendDaily, workingDays.getExtendTermForDailyRepayments())) {
workingDays.setExtendTermForDailyRepayments(extendDaily);
changes.put("extendTermForDailyRepayments", extendDaily);
}
Boolean extendHolidays = request.getExtendTermForRepaymentsOnHolidays();
if (extendHolidays != null && !Objects.equals(extendHolidays, workingDays.getExtendTermForRepaymentsOnHolidays())) {
workingDays.setExtendTermForRepaymentsOnHolidays(extendHolidays);
changes.put("extendTermForRepaymentsOnHolidays", extendHolidays);
}
return changes;
}
}
@@ -18,7 +18,7 @@
*/
package org.apache.fineract.organisation.workingdays.starter;
import org.apache.fineract.organisation.workingdays.data.WorkingDayValidator;
import org.apache.fineract.organisation.workingdays.data.WorkingDaysUpdateRequestValidator;
import org.apache.fineract.organisation.workingdays.domain.WorkingDaysRepositoryWrapper;
import org.apache.fineract.organisation.workingdays.service.WorkingDaysReadPlatformService;
import org.apache.fineract.organisation.workingdays.service.WorkingDaysReadPlatformServiceImpl;
@@ -41,7 +41,7 @@ public class OrganisationWorkingDaysConfiguration {
@Bean
@ConditionalOnMissingBean(WorkingDaysWritePlatformService.class)
public WorkingDaysWritePlatformService workingDaysWritePlatformService(WorkingDaysRepositoryWrapper daysRepositoryWrapper,
WorkingDayValidator fromApiJsonDeserializer) {
return new WorkingDaysWritePlatformServiceJpaRepositoryImpl(daysRepositoryWrapper, fromApiJsonDeserializer);
WorkingDaysUpdateRequestValidator validator) {
return new WorkingDaysWritePlatformServiceJpaRepositoryImpl(daysRepositoryWrapper, validator);
}
}