FINERACT-2326: Rework business date validation and dto handling

This commit is contained in:
Adam Saghy
2025-08-19 13:18:40 +02:00
parent f41d986b2a
commit 942ad0183c
24 changed files with 296 additions and 168 deletions
@@ -36,8 +36,10 @@ import java.util.function.Supplier;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.fineract.command.core.CommandPipeline; import org.apache.fineract.command.core.CommandPipeline;
import org.apache.fineract.infrastructure.businessdate.command.BusinessDateUpdateCommand; import org.apache.fineract.infrastructure.businessdate.command.BusinessDateUpdateCommand;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateResponse; import org.apache.fineract.infrastructure.businessdate.data.api.BusinessDateResponse;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateUpdateRequest; import org.apache.fineract.infrastructure.businessdate.data.api.BusinessDateUpdateRequest;
import org.apache.fineract.infrastructure.businessdate.data.api.BusinessDateUpdateResponse;
import org.apache.fineract.infrastructure.businessdate.mapper.BusinessDateMapper;
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateReadPlatformService; import org.apache.fineract.infrastructure.businessdate.service.BusinessDateReadPlatformService;
import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -50,13 +52,14 @@ public class BusinessDateApiResource {
private final BusinessDateReadPlatformService readPlatformService; private final BusinessDateReadPlatformService readPlatformService;
private final CommandPipeline commandPipeline; private final CommandPipeline commandPipeline;
private final BusinessDateMapper businessDateMapper;
@GET @GET
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON }) @Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "List all business dates", description = "") @Operation(summary = "List all business dates", description = "")
public List<BusinessDateResponse> getBusinessDates() { public List<BusinessDateResponse> getBusinessDates() {
return this.readPlatformService.findAll(); return businessDateMapper.mapFetchResponse(this.readPlatformService.findAll());
} }
@GET @GET
@@ -65,24 +68,24 @@ public class BusinessDateApiResource {
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Retrieve a specific Business date", description = "") @Operation(summary = "Retrieve a specific Business date", description = "")
public BusinessDateResponse getBusinessDate(@PathParam("type") @Parameter(description = "type") final String type) { public BusinessDateResponse getBusinessDate(@PathParam("type") @Parameter(description = "type") final String type) {
return this.readPlatformService.findByType(type); return businessDateMapper.mapFetchResponse(this.readPlatformService.findByType(type));
} }
@POST @POST
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Update Business Date", description = "") @Operation(summary = "Update Business Date", description = "")
public BusinessDateResponse updateBusinessDate(@HeaderParam("Idempotency-Key") String idempotencyKey, public BusinessDateUpdateResponse updateBusinessDate(@HeaderParam("Idempotency-Key") String idempotencyKey,
@Valid BusinessDateUpdateRequest request) { @Valid BusinessDateUpdateRequest request) {
final var command = new BusinessDateUpdateCommand(); final BusinessDateUpdateCommand command = new BusinessDateUpdateCommand();
command.setId(UUID.randomUUID()); command.setId(UUID.randomUUID());
command.setIdempotencyKey(idempotencyKey); command.setIdempotencyKey(idempotencyKey);
command.setCreatedAt(DateUtils.getAuditOffsetDateTime()); command.setCreatedAt(DateUtils.getAuditOffsetDateTime());
command.setPayload(request); command.setPayload(request);
final Supplier<BusinessDateResponse> response = commandPipeline.send(command); final Supplier<BusinessDateUpdateResponse> response = commandPipeline.send(command);
return response.get(); return response.get();
} }
@@ -21,7 +21,7 @@ package org.apache.fineract.infrastructure.businessdate.command;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.apache.fineract.command.core.Command; import org.apache.fineract.command.core.Command;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateUpdateRequest; import org.apache.fineract.infrastructure.businessdate.data.api.BusinessDateUpdateRequest;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@@ -0,0 +1,44 @@
/**
* 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.infrastructure.businessdate.data.api;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.core.jersey.serializer.legacy.JsonLocalDateArrayFormat;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonLocalDateArrayFormat
public class BusinessDateResponse implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String description;
private BusinessDateType type;
private LocalDate date;
}
@@ -16,8 +16,9 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.fineract.infrastructure.businessdate.data; package org.apache.fineract.infrastructure.businessdate.data.api;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import java.io.Serial; import java.io.Serial;
@@ -27,6 +28,7 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.validation.constraints.EnumValue;
import org.apache.fineract.validation.constraints.LocalDate; import org.apache.fineract.validation.constraints.LocalDate;
import org.apache.fineract.validation.constraints.Locale; import org.apache.fineract.validation.constraints.Locale;
@@ -42,8 +44,10 @@ public class BusinessDateUpdateRequest implements Serializable {
@NotBlank(message = "{org.apache.fineract.businessdate.date-format.not-blank}") @NotBlank(message = "{org.apache.fineract.businessdate.date-format.not-blank}")
private String dateFormat; private String dateFormat;
@NotNull(message = "{org.apache.fineract.businessdate.type.not-null}") @Schema(description = "Type of business date", example = "BUSINESS_DATE", allowableValues = { "BUSINESS_DATE", "COB_DATE" })
private BusinessDateType type; @EnumValue(enumClass = BusinessDateType.class, message = "{org.apache.fineract.businessdate.type.invalid}")
@NotNull(message = "{org.apache.fineract.businessdate.type.not-blank}")
private String type;
@NotBlank(message = "{org.apache.fineract.businessdate.date.not-blank}") @NotBlank(message = "{org.apache.fineract.businessdate.date.not-blank}")
private String date; private String date;
@NotBlank(message = "{org.apache.fineract.businessdate.locale.not-blank}") @NotBlank(message = "{org.apache.fineract.businessdate.locale.not-blank}")
@@ -0,0 +1,46 @@
/**
* 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.infrastructure.businessdate.data.api;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.core.jersey.serializer.legacy.JsonLocalDateArrayFormat;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonLocalDateArrayFormat
public class BusinessDateUpdateResponse implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String description;
private BusinessDateType type;
private LocalDate date;
private Map<BusinessDateType, LocalDate> changes;
}
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.fineract.infrastructure.businessdate.data; package org.apache.fineract.infrastructure.businessdate.data.service;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
@@ -33,7 +33,7 @@ import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class BusinessDateResponse implements Serializable { public class BusinessDateDTO implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@@ -22,8 +22,10 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.command.core.Command; import org.apache.fineract.command.core.Command;
import org.apache.fineract.command.core.CommandHandler; import org.apache.fineract.command.core.CommandHandler;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateResponse; import org.apache.fineract.infrastructure.businessdate.data.api.BusinessDateUpdateRequest;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateUpdateRequest; import org.apache.fineract.infrastructure.businessdate.data.api.BusinessDateUpdateResponse;
import org.apache.fineract.infrastructure.businessdate.data.service.BusinessDateDTO;
import org.apache.fineract.infrastructure.businessdate.mapper.BusinessDateMapper;
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateWritePlatformService; import org.apache.fineract.infrastructure.businessdate.service.BusinessDateWritePlatformService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -31,13 +33,16 @@ import org.springframework.transaction.annotation.Transactional;
@Slf4j @Slf4j
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class BusinessDateUpdateHandler implements CommandHandler<BusinessDateUpdateRequest, BusinessDateResponse> { public class BusinessDateUpdateHandler implements CommandHandler<BusinessDateUpdateRequest, BusinessDateUpdateResponse> {
private final BusinessDateWritePlatformService businessDateWritePlatformService; private final BusinessDateWritePlatformService businessDateWritePlatformService;
private final BusinessDateMapper businessDateMapper;
@Transactional @Transactional
@Override @Override
public BusinessDateResponse handle(Command<BusinessDateUpdateRequest> command) { public BusinessDateUpdateResponse handle(Command<BusinessDateUpdateRequest> command) {
return businessDateWritePlatformService.updateBusinessDate(command.getPayload()); BusinessDateDTO businessDateDto = businessDateMapper.mapUpdateRequest(command.getPayload());
businessDateDto = businessDateWritePlatformService.updateBusinessDate(businessDateDto);
return businessDateMapper.mapUpdateResponse(businessDateDto);
} }
} }
@@ -19,7 +19,10 @@
package org.apache.fineract.infrastructure.businessdate.mapper; package org.apache.fineract.infrastructure.businessdate.mapper;
import java.util.List; import java.util.List;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateResponse; import org.apache.fineract.infrastructure.businessdate.data.api.BusinessDateResponse;
import org.apache.fineract.infrastructure.businessdate.data.api.BusinessDateUpdateRequest;
import org.apache.fineract.infrastructure.businessdate.data.api.BusinessDateUpdateResponse;
import org.apache.fineract.infrastructure.businessdate.data.service.BusinessDateDTO;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDate; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDate;
import org.apache.fineract.infrastructure.core.config.MapstructMapperConfig; import org.apache.fineract.infrastructure.core.config.MapstructMapperConfig;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
@@ -29,8 +32,20 @@ import org.mapstruct.Mappings;
@Mapper(config = MapstructMapperConfig.class) @Mapper(config = MapstructMapperConfig.class)
public interface BusinessDateMapper { public interface BusinessDateMapper {
@Mappings({ @Mapping(target = "description", source = "source.type.description"), @Mapping(target = "changes", ignore = true) }) @Mappings({ @Mapping(target = "description", source = "type.description"), @Mapping(target = "changes", ignore = true) })
BusinessDateResponse map(BusinessDate source); BusinessDateDTO mapEntity(BusinessDate source);
List<BusinessDateResponse> map(List<BusinessDate> sources); List<BusinessDateDTO> mapEntity(List<BusinessDate> sources);
@Mapping(target = "description", expression = "java(org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType.valueOf(source.getType()).getDescription())")
@Mapping(target = "type", expression = "java(org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType.valueOf(source.getType()))")
@Mapping(target = "date", expression = "java(org.apache.fineract.infrastructure.core.service.DateUtils.toLocalDate(source.getLocale(), source.getDate(), source.getDateFormat()))")
@Mapping(target = "changes", ignore = true)
BusinessDateDTO mapUpdateRequest(BusinessDateUpdateRequest source);
List<BusinessDateResponse> mapFetchResponse(List<BusinessDateDTO> sources);
BusinessDateResponse mapFetchResponse(BusinessDateDTO source);
BusinessDateUpdateResponse mapUpdateResponse(BusinessDateDTO source);
} }
@@ -1,35 +0,0 @@
/**
* 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.infrastructure.businessdate.mapper;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateResponse;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateUpdateRequest;
import org.apache.fineract.infrastructure.core.config.MapstructMapperConfig;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(config = MapstructMapperConfig.class)
public interface BusinessDateUpdateRequestMapper {
@Mapping(target = "description", expression = "java(source.getType().getDescription())")
@Mapping(source = "type", target = "type")
@Mapping(target = "date", expression = "java(org.apache.fineract.infrastructure.core.service.DateUtils.toLocalDate(source.getLocale(), source.getDate(), source.getDateFormat()))")
@Mapping(target = "changes", ignore = true)
BusinessDateResponse map(BusinessDateUpdateRequest source);
}
@@ -21,14 +21,14 @@ package org.apache.fineract.infrastructure.businessdate.service;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateResponse; import org.apache.fineract.infrastructure.businessdate.data.service.BusinessDateDTO;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
public interface BusinessDateReadPlatformService { public interface BusinessDateReadPlatformService {
List<BusinessDateResponse> findAll(); List<BusinessDateDTO> findAll();
BusinessDateResponse findByType(String type); BusinessDateDTO findByType(String type);
HashMap<BusinessDateType, LocalDate> getBusinessDates(); HashMap<BusinessDateType, LocalDate> getBusinessDates();
} }
@@ -24,7 +24,7 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateResponse; import org.apache.fineract.infrastructure.businessdate.data.service.BusinessDateDTO;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDate; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDate;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateRepository; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateRepository;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
@@ -40,17 +40,17 @@ import org.springframework.stereotype.Service;
public class BusinessDateReadPlatformServiceImpl implements BusinessDateReadPlatformService { public class BusinessDateReadPlatformServiceImpl implements BusinessDateReadPlatformService {
private final BusinessDateRepository repository; private final BusinessDateRepository repository;
private final BusinessDateMapper businessDatemapper; private final BusinessDateMapper businessDateMapper;
private final ConfigurationDomainService configurationDomainService; private final ConfigurationDomainService configurationDomainService;
@Override @Override
public List<BusinessDateResponse> findAll() { public List<BusinessDateDTO> findAll() {
List<BusinessDate> businessDateList = repository.findAll(); List<BusinessDate> businessDateList = repository.findAll();
return businessDatemapper.map(businessDateList); return businessDateMapper.mapEntity(businessDateList);
} }
@Override @Override
public BusinessDateResponse findByType(String type) { public BusinessDateDTO findByType(String type) {
BusinessDateType businessDateType; BusinessDateType businessDateType;
try { try {
businessDateType = BusinessDateType.valueOf(type); businessDateType = BusinessDateType.valueOf(type);
@@ -63,7 +63,7 @@ public class BusinessDateReadPlatformServiceImpl implements BusinessDateReadPlat
log.error("Business date with the provided type cannot be found {}", type); log.error("Business date with the provided type cannot be found {}", type);
throw BusinessDateNotFoundException.notFound(type); throw BusinessDateNotFoundException.notFound(type);
} }
return businessDatemapper.map(businessDate.get()); return businessDateMapper.mapEntity(businessDate.get());
} }
@Override @Override
@@ -73,8 +73,8 @@ public class BusinessDateReadPlatformServiceImpl implements BusinessDateReadPlat
businessDateMap.put(BusinessDateType.BUSINESS_DATE, tenantDate); businessDateMap.put(BusinessDateType.BUSINESS_DATE, tenantDate);
businessDateMap.put(BusinessDateType.COB_DATE, tenantDate); businessDateMap.put(BusinessDateType.COB_DATE, tenantDate);
if (configurationDomainService.isBusinessDateEnabled()) { if (configurationDomainService.isBusinessDateEnabled()) {
final List<BusinessDateResponse> businessDateResponseList = this.findAll(); final List<BusinessDateDTO> businessDateResponseList = this.findAll();
for (BusinessDateResponse businessDateResponse : businessDateResponseList) { for (BusinessDateDTO businessDateResponse : businessDateResponseList) {
businessDateMap.put(businessDateResponse.getType(), businessDateResponse.getDate()); businessDateMap.put(businessDateResponse.getType(), businessDateResponse.getDate());
} }
} }
@@ -18,14 +18,13 @@
*/ */
package org.apache.fineract.infrastructure.businessdate.service; package org.apache.fineract.infrastructure.businessdate.service;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateResponse; import org.apache.fineract.infrastructure.businessdate.data.service.BusinessDateDTO;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateUpdateRequest;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException; import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
public interface BusinessDateWritePlatformService { public interface BusinessDateWritePlatformService {
BusinessDateResponse updateBusinessDate(BusinessDateUpdateRequest request); BusinessDateDTO updateBusinessDate(BusinessDateDTO businessDateDTO);
void increaseDateByTypeByOneDay(BusinessDateType businessDateType) throws JobExecutionException; void increaseDateByTypeByOneDay(BusinessDateType businessDateType) throws JobExecutionException;
} }
@@ -24,13 +24,11 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateResponse; import org.apache.fineract.infrastructure.businessdate.data.service.BusinessDateDTO;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateUpdateRequest;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDate; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDate;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateRepository; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateRepository;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.businessdate.exception.BusinessDateActionException; import org.apache.fineract.infrastructure.businessdate.exception.BusinessDateActionException;
import org.apache.fineract.infrastructure.businessdate.mapper.BusinessDateUpdateRequestMapper;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService; import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.core.data.ApiParameterError; import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException; import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
@@ -46,14 +44,10 @@ public class BusinessDateWritePlatformServiceImpl implements BusinessDateWritePl
private final BusinessDateRepository repository; private final BusinessDateRepository repository;
private final ConfigurationDomainService configurationDomainService; private final ConfigurationDomainService configurationDomainService;
private final BusinessDateUpdateRequestMapper updateRequestMapper;
@Override @Override
public BusinessDateResponse updateBusinessDate(BusinessDateUpdateRequest request) { public BusinessDateDTO updateBusinessDate(BusinessDateDTO businessDateDto) {
BusinessDateResponse businessDateDto = updateRequestMapper.map(request);
adjustDate(businessDateDto); adjustDate(businessDateDto);
return businessDateDto; return businessDateDto;
} }
@@ -65,8 +59,8 @@ public class BusinessDateWritePlatformServiceImpl implements BusinessDateWritePl
LocalDate businessDate = businessDateEntity.map(BusinessDate::getDate).orElse(DateUtils.getLocalDateOfTenant()); LocalDate businessDate = businessDateEntity.map(BusinessDate::getDate).orElse(DateUtils.getLocalDateOfTenant());
businessDate = businessDate.plusDays(1); businessDate = businessDate.plusDays(1);
try { try {
BusinessDateResponse response = BusinessDateResponse.builder().type(businessDateType) BusinessDateDTO response = BusinessDateDTO.builder().type(businessDateType).description(businessDateType.getDescription())
.description(businessDateType.getDescription()).date(businessDate).build(); .date(businessDate).build();
adjustDate(response); adjustDate(response);
} catch (final PlatformApiDataValidationException e) { } catch (final PlatformApiDataValidationException e) {
final List<ApiParameterError> errors = e.getErrors(); final List<ApiParameterError> errors = e.getErrors();
@@ -86,7 +80,7 @@ public class BusinessDateWritePlatformServiceImpl implements BusinessDateWritePl
} }
} }
private void adjustDate(BusinessDateResponse response) { private void adjustDate(BusinessDateDTO businessDateDto) {
boolean isCOBDateAdjustmentEnabled = configurationDomainService.isCOBDateAdjustmentEnabled(); boolean isCOBDateAdjustmentEnabled = configurationDomainService.isCOBDateAdjustmentEnabled();
boolean isBusinessDateEnabled = configurationDomainService.isBusinessDateEnabled(); boolean isBusinessDateEnabled = configurationDomainService.isBusinessDateEnabled();
@@ -94,16 +88,16 @@ public class BusinessDateWritePlatformServiceImpl implements BusinessDateWritePl
log.error("Business date functionality is not enabled!"); log.error("Business date functionality is not enabled!");
throw new BusinessDateActionException("business.date.is.not.enabled", "Business date functionality is not enabled"); throw new BusinessDateActionException("business.date.is.not.enabled", "Business date functionality is not enabled");
} }
updateOrCreateBusinessDate(response); updateOrCreateBusinessDate(businessDateDto);
if (isCOBDateAdjustmentEnabled && BusinessDateType.BUSINESS_DATE.equals(response.getType())) { if (isCOBDateAdjustmentEnabled && BusinessDateType.BUSINESS_DATE.equals(businessDateDto.getType())) {
BusinessDateResponse res = BusinessDateResponse.builder().type(BusinessDateType.COB_DATE) BusinessDateDTO res = BusinessDateDTO.builder().type(BusinessDateType.COB_DATE)
.description(BusinessDateType.COB_DATE.getDescription()).date(response.getDate().minusDays(1)).build(); .description(BusinessDateType.COB_DATE.getDescription()).date(businessDateDto.getDate().minusDays(1)).build();
updateOrCreateBusinessDate(res); updateOrCreateBusinessDate(res);
response.addAllChanges(res.getChanges()); businessDateDto.addAllChanges(res.getChanges());
} }
} }
private void updateOrCreateBusinessDate(BusinessDateResponse businessDateDto) { private void updateOrCreateBusinessDate(BusinessDateDTO businessDateDto) {
BusinessDateType businessDateType = businessDateDto.getType(); BusinessDateType businessDateType = businessDateDto.getType();
Optional<BusinessDate> businessDate = repository.findByType(businessDateType); Optional<BusinessDate> businessDate = repository.findByType(businessDateType);
@@ -116,7 +110,7 @@ public class BusinessDateWritePlatformServiceImpl implements BusinessDateWritePl
} }
} }
private void updateBusinessDate(BusinessDate businessDate, BusinessDateResponse businessDateDto) { private void updateBusinessDate(BusinessDate businessDate, BusinessDateDTO businessDateDto) {
if (DateUtils.isEqual(businessDate.getDate(), businessDateDto.getDate())) { if (DateUtils.isEqual(businessDate.getDate(), businessDateDto.getDate())) {
return; return;
} }
@@ -21,8 +21,8 @@ package org.apache.fineract.test.helper;
import java.io.IOException; import java.io.IOException;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.fineract.client.models.BusinessDateResponse;
import org.apache.fineract.client.models.BusinessDateUpdateRequest; import org.apache.fineract.client.models.BusinessDateUpdateRequest;
import org.apache.fineract.client.models.BusinessDateUpdateResponse;
import org.apache.fineract.client.services.BusinessDateManagementApi; import org.apache.fineract.client.services.BusinessDateManagementApi;
import org.apache.fineract.test.support.TestContext; import org.apache.fineract.test.support.TestContext;
import org.apache.fineract.test.support.TestContextKey; import org.apache.fineract.test.support.TestContextKey;
@@ -43,8 +43,8 @@ public class BusinessDateHelper {
public void setBusinessDate(String businessDate) throws IOException { public void setBusinessDate(String businessDate) throws IOException {
BusinessDateUpdateRequest businessDateRequest = defaultBusinessDateRequest().date(businessDate); BusinessDateUpdateRequest businessDateRequest = defaultBusinessDateRequest().date(businessDate);
Response<BusinessDateResponse> businessDateRequestResponse = businessDateManagementApi.updateBusinessDate(null, businessDateRequest) Response<BusinessDateUpdateResponse> businessDateRequestResponse = businessDateManagementApi
.execute(); .updateBusinessDate(null, businessDateRequest).execute();
ErrorHelper.checkSuccessfulApiCall(businessDateRequestResponse); ErrorHelper.checkSuccessfulApiCall(businessDateRequestResponse);
TestContext.INSTANCE.set(TestContextKey.BUSINESS_DATE_RESPONSE, businessDateRequestResponse); TestContext.INSTANCE.set(TestContextKey.BUSINESS_DATE_RESPONSE, businessDateRequestResponse);
} }
@@ -30,6 +30,7 @@ import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
import org.apache.fineract.client.models.BusinessDateResponse; import org.apache.fineract.client.models.BusinessDateResponse;
import org.apache.fineract.client.models.BusinessDateUpdateRequest; import org.apache.fineract.client.models.BusinessDateUpdateRequest;
import org.apache.fineract.client.models.BusinessDateUpdateResponse;
import org.apache.fineract.client.services.BusinessDateManagementApi; import org.apache.fineract.client.services.BusinessDateManagementApi;
import org.apache.fineract.client.util.JSON; import org.apache.fineract.client.util.JSON;
import org.apache.fineract.test.helper.BusinessDateHelper; import org.apache.fineract.test.helper.BusinessDateHelper;
@@ -75,8 +76,8 @@ public class BusinessDateStepDef extends AbstractStepDef {
public void setIncorrectBusinessDateFailure(String businessDate) throws IOException { public void setIncorrectBusinessDateFailure(String businessDate) throws IOException {
BusinessDateUpdateRequest businessDateRequest = businessDateHelper.defaultBusinessDateRequest().date(businessDate); BusinessDateUpdateRequest businessDateRequest = businessDateHelper.defaultBusinessDateRequest().date(businessDate);
Response<BusinessDateResponse> businessDateRequestResponse = businessDateManagementApi.updateBusinessDate(null, businessDateRequest) Response<BusinessDateUpdateResponse> businessDateRequestResponse = businessDateManagementApi
.execute(); .updateBusinessDate(null, businessDateRequest).execute();
final ErrorResponse errorDetails = ErrorResponse.from(businessDateRequestResponse); final ErrorResponse errorDetails = ErrorResponse.from(businessDateRequestResponse);
assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.setIncorrectBusinessDateFailure()).isEqualTo(400); assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.setIncorrectBusinessDateFailure()).isEqualTo(400);
assertThat(errorDetails.getSingleError().getDeveloperMessage()).isEqualTo(ErrorMessageHelper.setIncorrectBusinessDateFailure()); assertThat(errorDetails.getSingleError().getDeveloperMessage()).isEqualTo(ErrorMessageHelper.setIncorrectBusinessDateFailure());
@@ -90,8 +91,8 @@ public class BusinessDateStepDef extends AbstractStepDef {
} else { } else {
businessDateRequest.date(businessDate); businessDateRequest.date(businessDate);
} }
Response<BusinessDateResponse> businessDateRequestResponse = businessDateManagementApi.updateBusinessDate(null, businessDateRequest) Response<BusinessDateUpdateResponse> businessDateRequestResponse = businessDateManagementApi
.execute(); .updateBusinessDate(null, businessDateRequest).execute();
Integer httpStatusCodeExpected = 400; Integer httpStatusCodeExpected = 400;
String errorBody = businessDateRequestResponse.errorBody().string(); String errorBody = businessDateRequestResponse.errorBody().string();
@@ -26,6 +26,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.ZoneId; import java.time.ZoneId;
import org.apache.fineract.infrastructure.businessdate.data.api.BusinessDateResponse;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -36,7 +36,7 @@ class BusinessDateUpdateRequestMapperTest {
void testMapping() { void testMapping() {
var now = LocalDate.now(ZoneId.systemDefault()); var now = LocalDate.now(ZoneId.systemDefault());
var businessDate = BusinessDate.instance(BusinessDateType.BUSINESS_DATE, now); var businessDate = BusinessDate.instance(BusinessDateType.BUSINESS_DATE, now);
var businessDateResponse = businessDateMapper.map(businessDate); var businessDateResponse = businessDateMapper.mapEntity(businessDate);
assertEquals(businessDate.getDate(), businessDateResponse.getDate()); assertEquals(businessDate.getDate(), businessDateResponse.getDate());
assertEquals(businessDate.getType().getDescription(), businessDateResponse.getDescription()); assertEquals(businessDate.getType().getDescription(), businessDateResponse.getDescription());
assertEquals(businessDate.getType(), businessDateResponse.getType()); assertEquals(businessDate.getType(), businessDateResponse.getType());
@@ -46,7 +46,7 @@ class BusinessDateUpdateRequestMapperTest {
void testMappingList() { void testMappingList() {
var now = LocalDate.now(ZoneId.systemDefault()); var now = LocalDate.now(ZoneId.systemDefault());
var businessDate = BusinessDate.instance(BusinessDateType.BUSINESS_DATE, now); var businessDate = BusinessDate.instance(BusinessDateType.BUSINESS_DATE, now);
var businessDateData = businessDateMapper.map(Collections.singletonList(businessDate)); var businessDateData = businessDateMapper.mapEntity(Collections.singletonList(businessDate));
assertEquals(businessDate.getDate(), businessDateData.get(0).getDate()); assertEquals(businessDate.getDate(), businessDateData.get(0).getDate());
assertEquals(businessDate.getType().getDescription(), businessDateData.get(0).getDescription()); assertEquals(businessDate.getType().getDescription(), businessDateData.get(0).getDescription());
assertEquals(businessDate.getType(), businessDateData.get(0).getType()); assertEquals(businessDate.getType(), businessDateData.get(0).getType());
@@ -73,7 +73,7 @@ public class BusinessDateReadPlatformServiceTest {
given(repository.findAll()).willReturn(resultList); given(repository.findAll()).willReturn(resultList);
businessDateReadPlatformService.findAll(); businessDateReadPlatformService.findAll();
verify(repository, times(1)).findAll(); verify(repository, times(1)).findAll();
verify(businessDateMapper, times(1)).map(resultList); verify(businessDateMapper, times(1)).mapEntity(resultList);
} }
@Test @Test
@@ -82,7 +82,7 @@ public class BusinessDateReadPlatformServiceTest {
given(repository.findByType(BusinessDateType.COB_DATE)).willReturn(result); given(repository.findByType(BusinessDateType.COB_DATE)).willReturn(result);
businessDateReadPlatformService.findByType("COB_DATE"); businessDateReadPlatformService.findByType("COB_DATE");
verify(repository, times(1)).findByType(BusinessDateType.COB_DATE); verify(repository, times(1)).findByType(BusinessDateType.COB_DATE);
verify(businessDateMapper, times(1)).map(result.get()); verify(businessDateMapper, times(1)).mapEntity(result.get());
} }
@Test @Test
@@ -91,6 +91,6 @@ public class BusinessDateReadPlatformServiceTest {
given(repository.findByType(BusinessDateType.BUSINESS_DATE)).willReturn(result); given(repository.findByType(BusinessDateType.BUSINESS_DATE)).willReturn(result);
businessDateReadPlatformService.findByType("BUSINESS_DATE"); businessDateReadPlatformService.findByType("BUSINESS_DATE");
verify(repository, times(1)).findByType(BusinessDateType.BUSINESS_DATE); verify(repository, times(1)).findByType(BusinessDateType.BUSINESS_DATE);
verify(businessDateMapper, times(1)).map(result.get()); verify(businessDateMapper, times(1)).mapEntity(result.get());
} }
} }
@@ -29,16 +29,12 @@ import static org.mockito.Mockito.verify;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateResponse; import org.apache.fineract.infrastructure.businessdate.data.service.BusinessDateDTO;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateUpdateRequest;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDate; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDate;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateRepository; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateRepository;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.businessdate.exception.BusinessDateActionException; import org.apache.fineract.infrastructure.businessdate.exception.BusinessDateActionException;
import org.apache.fineract.infrastructure.businessdate.mapper.BusinessDateUpdateRequestMapper; import org.apache.fineract.infrastructure.businessdate.mapper.BusinessDateMapper;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService; import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.DateUtils;
@@ -66,7 +62,7 @@ public class BusinessDateWritePlatformServiceTest {
private BusinessDateWritePlatformServiceImpl underTest; private BusinessDateWritePlatformServiceImpl underTest;
@Mock @Mock
private BusinessDateUpdateRequestMapper updateBusinessDateMapper; private BusinessDateMapper businessDateMapper;
@Mock @Mock
private BusinessDateRepository businessDateRepository; private BusinessDateRepository businessDateRepository;
@@ -89,27 +85,22 @@ public class BusinessDateWritePlatformServiceTest {
@Test @Test
public void businessDateIsNotEnabled() { public void businessDateIsNotEnabled() {
BusinessDateUpdateRequest businessDateUpdateRequest = new BusinessDateUpdateRequest(); BusinessDateDTO businessDateDTO = new BusinessDateDTO();
given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.FALSE); given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.FALSE);
BusinessDateActionException exception = assertThrows(BusinessDateActionException.class, BusinessDateActionException exception = assertThrows(BusinessDateActionException.class,
() -> underTest.updateBusinessDate(businessDateUpdateRequest)); () -> underTest.updateBusinessDate(businessDateDTO));
assertEquals("Business date functionality is not enabled", exception.getDefaultUserMessage()); assertEquals("Business date functionality is not enabled", exception.getDefaultUserMessage());
} }
@Test @Test
public void businessDateSetNew() { public void businessDateSetNew() {
BusinessDateUpdateRequest businessDateUpdateRequest = new BusinessDateUpdateRequest(); BusinessDateDTO businessDateDTO = BusinessDateDTO.builder().date(LocalDate.of(2022, 6, 13)).type(BUSINESS_DATE).build();
final LocalDate localDate = LocalDate.of(2022, 6, 13);
final Map<BusinessDateType, LocalDate> changes = new HashMap<>(Map.of(BUSINESS_DATE, localDate));
BusinessDateResponse businessDateRes = BusinessDateResponse.builder().type(BUSINESS_DATE)
.description(BUSINESS_DATE.getDescription()).date(localDate).changes(changes).build();
given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE); given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE);
given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE); given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE);
given(updateBusinessDateMapper.map(businessDateUpdateRequest)).willReturn(businessDateRes);
Optional<BusinessDate> newEntity = Optional.empty(); Optional<BusinessDate> newEntity = Optional.empty();
given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity); given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity);
BusinessDateResponse result = underTest.updateBusinessDate(businessDateUpdateRequest); BusinessDateDTO result = underTest.updateBusinessDate(businessDateDTO);
final LocalDate resultDate = result.getChanges().get(BUSINESS_DATE); final LocalDate resultDate = result.getChanges().get(BUSINESS_DATE);
assertEquals(LocalDate.of(2022, 6, 13), resultDate); assertEquals(LocalDate.of(2022, 6, 13), resultDate);
verify(configurationDomainService, times(1)).isBusinessDateEnabled(); verify(configurationDomainService, times(1)).isBusinessDateEnabled();
@@ -122,40 +113,30 @@ public class BusinessDateWritePlatformServiceTest {
@Test @Test
public void cobDateSetNew() { public void cobDateSetNew() {
BusinessDateUpdateRequest businessDateUpdateRequest = new BusinessDateUpdateRequest(); BusinessDateDTO businessDateDTO = BusinessDateDTO.builder().date(LocalDate.of(2022, 6, 14)).type(COB_DATE).build();
final LocalDate localDate = LocalDate.of(2022, 6, 13);
final Map<BusinessDateType, LocalDate> changes = new HashMap<>(Map.of(COB_DATE, localDate));
BusinessDateResponse response = BusinessDateResponse.builder().type(COB_DATE).description(COB_DATE.getDescription()).date(localDate)
.changes(changes).build();
given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE); given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE);
given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE); given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE);
given(updateBusinessDateMapper.map(businessDateUpdateRequest)).willReturn(response);
Optional<BusinessDate> newEntity = Optional.empty(); Optional<BusinessDate> newEntity = Optional.empty();
given(businessDateRepository.findByType(COB_DATE)).willReturn(newEntity); given(businessDateRepository.findByType(COB_DATE)).willReturn(newEntity);
BusinessDateResponse result = underTest.updateBusinessDate(businessDateUpdateRequest); BusinessDateDTO result = underTest.updateBusinessDate(businessDateDTO);
LocalDate resultData = result.getChanges().get(COB_DATE); LocalDate resultData = result.getChanges().get(COB_DATE);
assertEquals(LocalDate.of(2022, 6, 13), resultData); assertEquals(LocalDate.of(2022, 6, 14), resultData);
verify(configurationDomainService, times(1)).isBusinessDateEnabled(); verify(configurationDomainService, times(1)).isBusinessDateEnabled();
verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled(); verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled();
verify(businessDateRepository, times(1)).findByType(COB_DATE); verify(businessDateRepository, times(1)).findByType(COB_DATE);
verify(businessDateRepository, times(1)).save(businessDateArgumentCaptor.capture()); verify(businessDateRepository, times(1)).save(businessDateArgumentCaptor.capture());
assertEquals(LocalDate.of(2022, 6, 13), businessDateArgumentCaptor.getValue().getDate()); assertEquals(LocalDate.of(2022, 6, 14), businessDateArgumentCaptor.getValue().getDate());
assertEquals(COB_DATE, businessDateArgumentCaptor.getValue().getType()); assertEquals(COB_DATE, businessDateArgumentCaptor.getValue().getType());
} }
@Test @Test
public void businessDateSetModifyExistingWhenItWasAfter() { public void businessDateSetModifyExistingWhenItWasAfter() {
BusinessDateUpdateRequest businessDateUpdateRequest = new BusinessDateUpdateRequest(); BusinessDateDTO businessDateDTO = BusinessDateDTO.builder().date(LocalDate.of(2022, 6, 11)).type(BUSINESS_DATE).build();
final LocalDate localDate = LocalDate.of(2022, 6, 11);
final Map<BusinessDateType, LocalDate> changes = new HashMap<>(Map.of(COB_DATE, localDate));
BusinessDateResponse response = BusinessDateResponse.builder().type(BUSINESS_DATE).description(BUSINESS_DATE.getDescription())
.date(localDate).changes(changes).build();
given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE); given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE);
given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE); given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE);
given(updateBusinessDateMapper.map(businessDateUpdateRequest)).willReturn(response);
Optional<BusinessDate> newEntity = Optional.of(BusinessDate.instance(BUSINESS_DATE, LocalDate.of(2022, 6, 12))); Optional<BusinessDate> newEntity = Optional.of(BusinessDate.instance(BUSINESS_DATE, LocalDate.of(2022, 6, 12)));
given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity); given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity);
BusinessDateResponse result = underTest.updateBusinessDate(businessDateUpdateRequest); BusinessDateDTO result = underTest.updateBusinessDate(businessDateDTO);
LocalDate resultData = result.getChanges().get(BUSINESS_DATE); LocalDate resultData = result.getChanges().get(BUSINESS_DATE);
assertEquals(LocalDate.of(2022, 6, 11), resultData); assertEquals(LocalDate.of(2022, 6, 11), resultData);
verify(configurationDomainService, times(1)).isBusinessDateEnabled(); verify(configurationDomainService, times(1)).isBusinessDateEnabled();
@@ -168,17 +149,12 @@ public class BusinessDateWritePlatformServiceTest {
@Test @Test
public void businessDateSetModifyExistingWhenItWasBefore() { public void businessDateSetModifyExistingWhenItWasBefore() {
BusinessDateUpdateRequest businessDateUpdateRequest = new BusinessDateUpdateRequest(); BusinessDateDTO businessDateDTO = BusinessDateDTO.builder().date(LocalDate.of(2022, 6, 13)).type(BUSINESS_DATE).build();
final LocalDate localDate = LocalDate.of(2022, 6, 13);
final Map<BusinessDateType, LocalDate> changes = new HashMap<>(Map.of(BUSINESS_DATE, localDate));
BusinessDateResponse response = BusinessDateResponse.builder().type(BUSINESS_DATE).description(BUSINESS_DATE.getDescription())
.date(localDate).changes(changes).build();
given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE); given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE);
given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE); given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE);
given(updateBusinessDateMapper.map(businessDateUpdateRequest)).willReturn(response);
Optional<BusinessDate> newEntity = Optional.of(BusinessDate.instance(BUSINESS_DATE, LocalDate.of(2022, 6, 12))); Optional<BusinessDate> newEntity = Optional.of(BusinessDate.instance(BUSINESS_DATE, LocalDate.of(2022, 6, 12)));
given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity); given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity);
BusinessDateResponse result = underTest.updateBusinessDate(businessDateUpdateRequest); BusinessDateDTO result = underTest.updateBusinessDate(businessDateDTO);
LocalDate resultData = result.getChanges().get(BUSINESS_DATE); LocalDate resultData = result.getChanges().get(BUSINESS_DATE);
assertEquals(LocalDate.of(2022, 6, 13), resultData); assertEquals(LocalDate.of(2022, 6, 13), resultData);
verify(configurationDomainService, times(1)).isBusinessDateEnabled(); verify(configurationDomainService, times(1)).isBusinessDateEnabled();
@@ -191,17 +167,13 @@ public class BusinessDateWritePlatformServiceTest {
@Test @Test
public void businessDateSetModifyExistingButNoChanges() { public void businessDateSetModifyExistingButNoChanges() {
BusinessDateUpdateRequest businessDateUpdateRequest = new BusinessDateUpdateRequest(); BusinessDateDTO businessDateDTO = BusinessDateDTO.builder().date(LocalDate.of(2022, 6, 13)).type(BUSINESS_DATE).build();
final LocalDate localDate = LocalDate.of(2022, 6, 13);
BusinessDateResponse response = BusinessDateResponse.builder().type(BUSINESS_DATE).description(BUSINESS_DATE.getDescription())
.date(localDate).build();
given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE); given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE);
given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE); given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE);
given(updateBusinessDateMapper.map(businessDateUpdateRequest)).willReturn(response);
Optional<BusinessDate> newEntity = Optional.of(BusinessDate.instance(BUSINESS_DATE, LocalDate.of(2022, 6, 13))); Optional<BusinessDate> newEntity = Optional.of(BusinessDate.instance(BUSINESS_DATE, LocalDate.of(2022, 6, 13)));
given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity); given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity);
BusinessDateResponse result = underTest.updateBusinessDate(businessDateUpdateRequest); BusinessDateDTO result = underTest.updateBusinessDate(businessDateDTO);
assertNull(result.getChanges()); assertNull(result.getChanges());
verify(configurationDomainService, times(1)).isBusinessDateEnabled(); verify(configurationDomainService, times(1)).isBusinessDateEnabled();
verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled(); verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled();
@@ -211,17 +183,13 @@ public class BusinessDateWritePlatformServiceTest {
@Test @Test
public void cobDateSetNewAutomatically() { public void cobDateSetNewAutomatically() {
BusinessDateUpdateRequest request = new BusinessDateUpdateRequest(); BusinessDateDTO request = BusinessDateDTO.builder().date(LocalDate.of(2022, 6, 13)).type(BUSINESS_DATE).build();
final LocalDate localDate = LocalDate.of(2022, 6, 13);
final Map<BusinessDateType, LocalDate> changes = new HashMap<>(Map.of(BUSINESS_DATE, localDate));
BusinessDateResponse response = BusinessDateResponse.builder().type(BUSINESS_DATE).description(BUSINESS_DATE.getDescription())
.date(localDate).changes(changes).build();
given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE); given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE);
given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.TRUE); given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.TRUE);
given(updateBusinessDateMapper.map(request)).willReturn(response);
Optional<BusinessDate> newEntity = Optional.empty(); Optional<BusinessDate> newEntity = Optional.empty();
given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity); given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity);
BusinessDateResponse result = underTest.updateBusinessDate(request); BusinessDateDTO result = underTest.updateBusinessDate(request);
LocalDate businessDate = result.getChanges().get(BUSINESS_DATE); LocalDate businessDate = result.getChanges().get(BUSINESS_DATE);
assertEquals(LocalDate.of(2022, 6, 13), businessDate); assertEquals(LocalDate.of(2022, 6, 13), businessDate);
LocalDate cobDate = result.getChanges().get(COB_DATE); LocalDate cobDate = result.getChanges().get(COB_DATE);
@@ -239,18 +207,15 @@ public class BusinessDateWritePlatformServiceTest {
@Test @Test
public void businessDateAndCobDateSetModifyExistingButNoChanges() { public void businessDateAndCobDateSetModifyExistingButNoChanges() {
BusinessDateUpdateRequest request = new BusinessDateUpdateRequest(); BusinessDateDTO request = BusinessDateDTO.builder().date(LocalDate.of(2022, 6, 13)).type(BUSINESS_DATE).build();
BusinessDateResponse response = BusinessDateResponse.builder().type(BUSINESS_DATE).description(BUSINESS_DATE.getDescription())
.date(LocalDate.of(2022, 6, 13)).build();
given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE); given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE);
given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.TRUE); given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.TRUE);
given(updateBusinessDateMapper.map(request)).willReturn(response);
Optional<BusinessDate> newBusinessEntity = Optional.of(BusinessDate.instance(BUSINESS_DATE, LocalDate.of(2022, 6, 13))); Optional<BusinessDate> newBusinessEntity = Optional.of(BusinessDate.instance(BUSINESS_DATE, LocalDate.of(2022, 6, 13)));
Optional<BusinessDate> newCOBEntity = Optional.of(BusinessDate.instance(COB_DATE, LocalDate.of(2022, 6, 12))); Optional<BusinessDate> newCOBEntity = Optional.of(BusinessDate.instance(COB_DATE, LocalDate.of(2022, 6, 12)));
given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newBusinessEntity); given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newBusinessEntity);
given(businessDateRepository.findByType(COB_DATE)).willReturn(newCOBEntity); given(businessDateRepository.findByType(COB_DATE)).willReturn(newCOBEntity);
BusinessDateResponse result = underTest.updateBusinessDate(request); BusinessDateDTO result = underTest.updateBusinessDate(request);
assertNull(result.getChanges()); assertNull(result.getChanges());
verify(configurationDomainService, times(1)).isBusinessDateEnabled(); verify(configurationDomainService, times(1)).isBusinessDateEnabled();
verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled(); verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled();
@@ -23,7 +23,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import jakarta.validation.Validation; import jakarta.validation.Validation;
import jakarta.validation.Validator; import jakarta.validation.Validator;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateUpdateRequest; import org.apache.fineract.infrastructure.businessdate.data.api.BusinessDateUpdateRequest;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.hibernate.validator.HibernateValidator; import org.hibernate.validator.HibernateValidator;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -59,7 +59,7 @@ class BusinessDateValidationTest {
var errors = validator.validate(request); var errors = validator.validate(request);
assertThat(errors).hasSize(6); assertThat(errors).hasSize(7);
assertThat(errors).anyMatch(e -> e.getPropertyPath().toString().equals("date")); assertThat(errors).anyMatch(e -> e.getPropertyPath().toString().equals("date"));
assertThat(errors).anyMatch(e -> e.getPropertyPath().toString().equals("dateFormat")); assertThat(errors).anyMatch(e -> e.getPropertyPath().toString().equals("dateFormat"));
@@ -69,8 +69,8 @@ class BusinessDateValidationTest {
@Test @Test
void invalidLocale() { void invalidLocale() {
var request = BusinessDateUpdateRequest.builder().dateFormat("dd-MM-yyyy").type(BusinessDateType.BUSINESS_DATE).date("12-05-2025") var request = BusinessDateUpdateRequest.builder().dateFormat("dd-MM-yyyy").type(BusinessDateType.BUSINESS_DATE.name())
.locale("INVALID").build(); .date("12-05-2025").locale("INVALID").build();
var errors = validator.validate(request); var errors = validator.validate(request);
@@ -81,8 +81,8 @@ class BusinessDateValidationTest {
@Test @Test
void invalidDateFormat() { void invalidDateFormat() {
var request = BusinessDateUpdateRequest.builder().dateFormat("dd/MM/yyyy").type(BusinessDateType.BUSINESS_DATE).date("12-05-2025") var request = BusinessDateUpdateRequest.builder().dateFormat("dd/MM/yyyy").type(BusinessDateType.BUSINESS_DATE.name())
.locale("en").build(); .date("12-05-2025").locale("en").build();
var errors = validator.validate(request); var errors = validator.validate(request);
@@ -93,8 +93,8 @@ class BusinessDateValidationTest {
@Test @Test
void valid() { void valid() {
var request = BusinessDateUpdateRequest.builder().dateFormat("dd-MM-yyyy").type(BusinessDateType.BUSINESS_DATE).date("12-05-2025") var request = BusinessDateUpdateRequest.builder().dateFormat("dd-MM-yyyy").type(BusinessDateType.BUSINESS_DATE.name())
.locale("en").build(); .date("12-05-2025").locale("en").build();
var errors = validator.validate(request); var errors = validator.validate(request);
@@ -0,0 +1,42 @@
/**
* 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.validation.constraints;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Constraint(validatedBy = EnumValueValidator.class)
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface EnumValue {
String message() default "{org.apache.fineract.validation.enum}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
Class<? extends Enum<?>> enumClass();
}
@@ -0,0 +1,41 @@
/**
* 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.validation.constraints;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
public class EnumValueValidator implements ConstraintValidator<EnumValue, String> {
private Set<String> acceptedValues;
@Override
public void initialize(EnumValue annotation) {
acceptedValues = Arrays.stream(annotation.enumClass().getEnumConstants()).map(e -> e.name().toLowerCase())
.collect(Collectors.toSet());
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return value != null && acceptedValues.contains(value.toLowerCase());
}
}
@@ -21,11 +21,13 @@
org.apache.fineract.validation.local-date=Wrong local date fields. org.apache.fineract.validation.local-date=Wrong local date fields.
org.apache.fineract.validation.locale=The parameter `locale` has an invalid language value: `${validatedValue}`. org.apache.fineract.validation.locale=The parameter `locale` has an invalid language value: `${validatedValue}`.
org.apache.fineract.validation.enum=The parameter has an invalid enum value: `${validatedValue}`.
## Business Date ## Business Date
org.apache.fineract.businessdate.date-format.not-blank=The parameter 'dateFormat' is mandatory. org.apache.fineract.businessdate.date-format.not-blank=The parameter 'dateFormat' is mandatory.
org.apache.fineract.businessdate.type.not-null=The parameter 'type' is mandatory. org.apache.fineract.businessdate.type.not-blank=The parameter 'type' is mandatory.
org.apache.fineract.businessdate.type.invalid=The parameter 'type' must be valid BusinessDateType value. Provided value: '${validatedValue}'.
org.apache.fineract.businessdate.date.not-blank=The parameter 'date' is mandatory. org.apache.fineract.businessdate.date.not-blank=The parameter 'date' is mandatory.
org.apache.fineract.businessdate.locale.not-blank=The parameter 'locale' is mandatory. org.apache.fineract.businessdate.locale.not-blank=The parameter 'locale' is mandatory.
@@ -27,6 +27,7 @@ import java.util.List;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.client.models.BusinessDateResponse; import org.apache.fineract.client.models.BusinessDateResponse;
import org.apache.fineract.client.models.BusinessDateUpdateRequest; import org.apache.fineract.client.models.BusinessDateUpdateRequest;
import org.apache.fineract.client.models.BusinessDateUpdateResponse;
import org.apache.fineract.client.models.PutGlobalConfigurationsRequest; import org.apache.fineract.client.models.PutGlobalConfigurationsRequest;
import org.apache.fineract.client.util.Calls; import org.apache.fineract.client.util.Calls;
import org.apache.fineract.client.util.JSON; import org.apache.fineract.client.util.JSON;
@@ -53,7 +54,7 @@ public final class BusinessDateHelper {
return Utils.performServerPost(requestSpec, responseSpec, BUSINESS_DATE_API, buildBusinessDateRequest(type, date), "changes"); return Utils.performServerPost(requestSpec, responseSpec, BUSINESS_DATE_API, buildBusinessDateRequest(type, date), "changes");
} }
public static BusinessDateResponse updateBusinessDate(final BusinessDateUpdateRequest request) { public static BusinessDateUpdateResponse updateBusinessDate(final BusinessDateUpdateRequest request) {
log.info("------------------UPDATE BUSINESS DATE----------------------"); log.info("------------------UPDATE BUSINESS DATE----------------------");
log.info("------------------Type: {}, date: {}----------------------", request.getType(), request.getDate()); log.info("------------------Type: {}, date: {}----------------------", request.getType(), request.getDate());
return Calls.ok(FineractClientHelper.getFineractClient().businessDateManagement.updateBusinessDate(null, request)); return Calls.ok(FineractClientHelper.getFineractClient().businessDateManagement.updateBusinessDate(null, request));