FINERACT-2238: New command processing - Business Date Management (org.apache.fineract.infrastructure.businessdate)

This commit is contained in:
viktorpavlenko
2025-06-26 00:49:05 +02:00
committed by Aleksandar Vidakovic
parent d5958f36c7
commit bb46397daa
81 changed files with 1385 additions and 1099 deletions
@@ -28,8 +28,6 @@ import static org.springframework.security.web.util.matcher.AntPathRequestMatche
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.apache.fineract.commands.domain.CommandSourceRepository;
import org.apache.fineract.commands.service.CommandSourceService;
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateReadPlatformService;
import org.apache.fineract.infrastructure.cache.service.CacheWritePlatformService;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
@@ -48,7 +46,6 @@ import org.apache.fineract.infrastructure.security.filter.InsecureTwoFactorAuthe
import org.apache.fineract.infrastructure.security.filter.TenantAwareBasicAuthenticationFilter;
import org.apache.fineract.infrastructure.security.filter.TwoFactorAuthenticationFilter;
import org.apache.fineract.infrastructure.security.service.BasicAuthTenantDetailsService;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.TenantAwareJpaPlatformUserDetailsService;
import org.apache.fineract.infrastructure.security.service.TwoFactorService;
import org.apache.fineract.notification.service.UserNotificationService;
@@ -111,17 +108,11 @@ public class SecurityConfig {
@Autowired
private MDCWrapper mdcWrapper;
@Autowired
private CommandSourceRepository commandSourceRepository;
@Autowired
private CommandSourceService commandSourceService;
@Autowired
private FineractRequestContextHolder fineractRequestContextHolder;
@Autowired(required = false)
private LoanCOBFilterHelper loanCOBFilterHelper;
@Autowired
private PlatformSecurityContext context;
@Autowired
private IdempotencyStoreHelper idempotencyStoreHelper;
@Bean
@@ -141,6 +132,12 @@ public class SecurityConfig {
.requestMatchers(antMatcher(HttpMethod.POST, "/api/*/echo")).permitAll() //
.requestMatchers(antMatcher(HttpMethod.POST, "/api/*/authentication")).permitAll() //
.requestMatchers(antMatcher(HttpMethod.PUT, "/api/*/instance-mode")).permitAll() //
// businessdate
.requestMatchers(antMatcher(HttpMethod.GET, "/api/*/businessdate/*"))
.hasAnyAuthority("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", "READ_BUSINESS_DATE") //
.requestMatchers(antMatcher(HttpMethod.POST, "/api/*/businessdate"))
.hasAnyAuthority("ALL_FUNCTIONS", "ALL_FUNCTIONS_WRITE", "UPDATE_BUSINESS_DATE") //
//
.requestMatchers(antMatcher(HttpMethod.POST, "/api/*/twofactor/validate")).fullyAuthenticated() //
.requestMatchers(antMatcher("/api/*/twofactor")).fullyAuthenticated() //
.requestMatchers(antMatcher("/api/**"))
@@ -46,6 +46,7 @@ public class JerseyConfig extends ResourceConfig {
bind(PageableParamProvider.class).to(ValueParamProvider.class).in(Singleton.class);
}
});
register(org.glassfish.jersey.server.validation.ValidationFeature.class);
property(ServerProperties.WADL_FEATURE_DISABLE, true);
}
@@ -1,26 +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.jobs.service.increasedateby1day;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
public interface IncreaseDateBy1DayService {
void increaseDateByTypeByOneDay(BusinessDateType businessDateType);
}
@@ -1,67 +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.jobs.service.increasedateby1day;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateData;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDate;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateRepository;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateWritePlatformService;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.springframework.stereotype.Service;
@Service
@Slf4j
@RequiredArgsConstructor
public class IncreaseDateBy1DayServiceImpl implements IncreaseDateBy1DayService {
private final BusinessDateRepository businessDateRepository;
private final BusinessDateWritePlatformService businessDateWritePlatformService;
@Override
public void increaseDateByTypeByOneDay(BusinessDateType businessDateType) {
Map<String, Object> changes = new HashMap<>();
Optional<BusinessDate> businessDateEntity = businessDateRepository.findByType(businessDateType);
LocalDate businessDate = businessDateEntity.map(BusinessDate::getDate).orElse(DateUtils.getLocalDateOfTenant());
businessDate = businessDate.plusDays(1);
try {
BusinessDateData businessDateData = BusinessDateData.instance(businessDateType, businessDate);
businessDateWritePlatformService.adjustDate(businessDateData, changes);
} catch (final PlatformApiDataValidationException e) {
final List<ApiParameterError> errors = e.getErrors();
for (final ApiParameterError error : errors) {
log.error("Increasing {} by 1 day failed due to: {}", businessDateType.getDescription(), error.getDeveloperMessage());
}
} catch (final AbstractPlatformDomainRuleException e) {
log.error("Increasing {} by 1 day failed due to: {}", businessDateType.getDescription(), e.getDefaultUserMessage());
} catch (Exception e) {
log.error("Increasing {} by 1 day failed due to: {}", businessDateType.getDescription(), e.getMessage());
}
}
}
@@ -18,16 +18,14 @@
*/
package org.apache.fineract.infrastructure.jobs.service.increasedateby1day.increasebusinessdateby1day;
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateWritePlatformService;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.apache.fineract.infrastructure.jobs.service.increasedateby1day.IncreaseDateBy1DayService;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
@@ -35,29 +33,17 @@ import org.springframework.transaction.PlatformTransactionManager;
@Configuration
public class IncreaseBusinessDateBy1DayConfig {
@Autowired
private JobRepository jobRepository;
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private IncreaseDateBy1DayService increaseDateBy1DayService;
@Autowired
private ConfigurationDomainService configurationDomainService;
@Bean
protected Step increaseBusinessDateBy1DayStep() {
return new StepBuilder(JobName.INCREASE_BUSINESS_DATE_BY_1_DAY.name(), jobRepository)
.tasklet(increaseBusinessDateBy1DayTasklet(), transactionManager).build();
public IncreaseBusinessDateBy1DayTasklet increaseBusinessDateBy1DayTasklet(
BusinessDateWritePlatformService businessDateWritePlatformService, ConfigurationDomainService configurationDomainService) {
return new IncreaseBusinessDateBy1DayTasklet(businessDateWritePlatformService, configurationDomainService);
}
@Bean
public Job increaseBusinessDateBy1DayJob() {
return new JobBuilder(JobName.INCREASE_BUSINESS_DATE_BY_1_DAY.name(), jobRepository).start(increaseBusinessDateBy1DayStep())
public Job increaseBusinessDateBy1DayJob(PlatformTransactionManager transactionManager, JobRepository jobRepository,
IncreaseBusinessDateBy1DayTasklet tasklet) {
return new JobBuilder(JobName.INCREASE_BUSINESS_DATE_BY_1_DAY.name(), jobRepository).start(
new StepBuilder(JobName.INCREASE_BUSINESS_DATE_BY_1_DAY.name(), jobRepository).tasklet(tasklet, transactionManager).build())
.incrementer(new RunIdIncrementer()).build();
}
@Bean
public IncreaseBusinessDateBy1DayTasklet increaseBusinessDateBy1DayTasklet() {
return new IncreaseBusinessDateBy1DayTasklet(increaseDateBy1DayService, configurationDomainService);
}
}
@@ -21,8 +21,8 @@ package org.apache.fineract.infrastructure.jobs.service.increasedateby1day.incre
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateWritePlatformService;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.jobs.service.increasedateby1day.IncreaseDateBy1DayService;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
@@ -33,13 +33,13 @@ import org.springframework.batch.repeat.RepeatStatus;
@RequiredArgsConstructor
public class IncreaseBusinessDateBy1DayTasklet implements Tasklet {
private final IncreaseDateBy1DayService increaseDateBy1DayService;
private final BusinessDateWritePlatformService businessDateWritePlatformService;
private final ConfigurationDomainService configurationDomainService;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
if (configurationDomainService.isBusinessDateEnabled()) {
increaseDateBy1DayService.increaseDateByTypeByOneDay(BusinessDateType.BUSINESS_DATE);
businessDateWritePlatformService.increaseDateByTypeByOneDay(BusinessDateType.BUSINESS_DATE);
} else {
contribution.setExitStatus(ExitStatus.NOOP);
}
@@ -18,31 +18,28 @@
*/
package org.apache.fineract.infrastructure.jobs.service.increasedateby1day.increasecobdateby1day;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateWritePlatformService;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.apache.fineract.infrastructure.jobs.service.increasedateby1day.IncreaseDateBy1DayService;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
@RequiredArgsConstructor
public class IncreaseCobDateBy1DayConfig {
@Autowired
private JobRepository jobRepository;
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private IncreaseDateBy1DayService increaseDateBy1DayService;
@Autowired
private ConfigurationDomainService configurationDomainService;
private final JobRepository jobRepository;
private final PlatformTransactionManager transactionManager;
private final BusinessDateWritePlatformService businessDateWritePlatformService;
private final ConfigurationDomainService configurationDomainService;
@Bean
protected Step increaseCobDateBy1DayStep() {
@@ -58,6 +55,6 @@ public class IncreaseCobDateBy1DayConfig {
@Bean
public IncreaseCobDateBy1DayTasklet increaseCobDateBy1DayTasklet() {
return new IncreaseCobDateBy1DayTasklet(increaseDateBy1DayService, configurationDomainService);
return new IncreaseCobDateBy1DayTasklet(businessDateWritePlatformService, configurationDomainService);
}
}
@@ -21,8 +21,8 @@ package org.apache.fineract.infrastructure.jobs.service.increasedateby1day.incre
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateWritePlatformService;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.jobs.service.increasedateby1day.IncreaseDateBy1DayService;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
@@ -33,13 +33,13 @@ import org.springframework.batch.repeat.RepeatStatus;
@RequiredArgsConstructor
public class IncreaseCobDateBy1DayTasklet implements Tasklet {
private final IncreaseDateBy1DayService increaseDateBy1DayService;
private final BusinessDateWritePlatformService businessDateWritePlatformService;
private final ConfigurationDomainService configurationDomainService;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
if (configurationDomainService.isBusinessDateEnabled()) {
increaseDateBy1DayService.increaseDateByTypeByOneDay(BusinessDateType.COB_DATE);
businessDateWritePlatformService.increaseDateByTypeByOneDay(BusinessDateType.COB_DATE);
} else {
contribution.setExitStatus(ExitStatus.NOOP);
}
@@ -1,141 +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.api;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import java.util.List;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateData;
import org.apache.fineract.infrastructure.businessdate.data.request.BusinessDateRequest;
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateReadPlatformService;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.security.exception.NoAuthorizationException;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.useradministration.domain.AppUser;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class BusinessDateApiTest {
@Mock
private BusinessDateReadPlatformService readPlatformService;
@Mock
private PlatformSecurityContext securityContext;
@Mock
private DefaultToApiJsonSerializer<BusinessDateData> jsonSerializer;
@Mock
private PortfolioCommandSourceWritePlatformService commandWritePlatformService;
@InjectMocks
private BusinessDateApiResource underTest;
@Test
void getBusinessDatesAPIHasPermission() {
AppUser appUser = Mockito.mock(AppUser.class);
List<BusinessDateData> response = Mockito.mock(List.class);
given(readPlatformService.findAll()).willReturn(response);
// given
Mockito.doNothing().when(appUser).validateHasReadPermission("BUSINESS_DATE");
given(securityContext.authenticatedUser()).willReturn(appUser);
// when
underTest.getBusinessDates();
// then
verify(readPlatformService, Mockito.times(1)).findAll();
}
@Test
void getBusinessDatesAPIHasNoPermission() {
AppUser appUser = Mockito.mock(AppUser.class);
// given
Mockito.doThrow(NoAuthorizationException.class).when(appUser).validateHasReadPermission("BUSINESS_DATE");
given(securityContext.authenticatedUser()).willReturn(appUser);
// when
assertThatThrownBy(() -> underTest.getBusinessDates()).isInstanceOf(NoAuthorizationException.class);
// then
verifyNoInteractions(readPlatformService);
}
@Test
void getBusinessDateByTypeAPIHasPermission() {
AppUser appUser = Mockito.mock(AppUser.class);
BusinessDateData response = Mockito.mock(BusinessDateData.class);
given(readPlatformService.findByType("type")).willReturn(response);
// given
Mockito.doNothing().when(appUser).validateHasReadPermission("BUSINESS_DATE");
given(securityContext.authenticatedUser()).willReturn(appUser);
// when
underTest.getBusinessDate("type");
// then
verify(readPlatformService, Mockito.times(1)).findByType("type");
}
@Test
void getBusinessDateByTypeAPIHasNoPermission() {
AppUser appUser = Mockito.mock(AppUser.class);
// given
Mockito.doThrow(NoAuthorizationException.class).when(appUser).validateHasReadPermission("BUSINESS_DATE");
given(securityContext.authenticatedUser()).willReturn(appUser);
// when
assertThatThrownBy(() -> underTest.getBusinessDate("type")).isInstanceOf(NoAuthorizationException.class);
// then
verifyNoInteractions(readPlatformService);
}
@Test
void postBusinessDateAPIHasPermission() {
AppUser appUser = Mockito.mock(AppUser.class);
CommandProcessingResult response = Mockito.mock(CommandProcessingResult.class);
// given
Mockito.doNothing().when(appUser).validateHasUpdatePermission("BUSINESS_DATE");
given(securityContext.authenticatedUser()).willReturn(appUser);
given(commandWritePlatformService.logCommandSource(Mockito.any())).willReturn(response);
// when
underTest.updateBusinessDate(BusinessDateRequest.ofNull());
// then
verify(commandWritePlatformService, Mockito.times(1)).logCommandSource(Mockito.any());
}
@Test
void postBusinessDateAPIHasNoPermission() {
AppUser appUser = Mockito.mock(AppUser.class);
// given
Mockito.doThrow(NoAuthorizationException.class).when(appUser).validateHasUpdatePermission("BUSINESS_DATE");
given(securityContext.authenticatedUser()).willReturn(appUser);
// when
assertThatThrownBy(() -> underTest.updateBusinessDate(BusinessDateRequest.ofNull())).isInstanceOf(NoAuthorizationException.class);
// then
verifyNoInteractions(readPlatformService);
}
}
@@ -1,60 +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.data;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.LocalDate;
import java.time.ZoneId;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.core.serialization.CommandProcessingResultJsonSerializer;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.core.serialization.ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson;
import org.apache.fineract.infrastructure.core.serialization.GoogleGsonSerializerHelper;
import org.junit.jupiter.api.Test;
public class BusinessDataSerialized {
@Test
public void serializeBusinessDateData() {
DefaultToApiJsonSerializer<BusinessDateData> jsonSerializer = new DefaultToApiJsonSerializer<>(
new ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson(), new CommandProcessingResultJsonSerializer(),
new GoogleGsonSerializerHelper());
LocalDate now = LocalDate.now(ZoneId.systemDefault());
BusinessDateData businessDateData = BusinessDateData.instance(BusinessDateType.BUSINESS_DATE, now);
String result = jsonSerializer.serialize(businessDateData);
assertEquals("{\"description\":\"Business Date\",\"type\":\"BUSINESS_DATE\",\"date\":[" + now.getYear() + "," + now.getMonthValue()
+ "," + now.getDayOfMonth() + "]}", result);
}
@Test
public void serializeBusinessDateData_COB() {
DefaultToApiJsonSerializer<BusinessDateData> jsonSerializer = new DefaultToApiJsonSerializer<>(
new ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson(), new CommandProcessingResultJsonSerializer(),
new GoogleGsonSerializerHelper());
LocalDate now = LocalDate.now(ZoneId.systemDefault());
BusinessDateData businessDateData = BusinessDateData.instance(BusinessDateType.COB_DATE, now);
String result = jsonSerializer.serialize(businessDateData);
assertEquals("{\"description\":\"Close of Business Date\",\"type\":\"COB_DATE\",\"date\":[" + now.getYear() + ","
+ now.getMonthValue() + "," + now.getDayOfMonth() + "]}", result);
}
}
@@ -23,11 +23,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.junit.jupiter.api.Test;
public class BusinessDataTypeTest {
class BusinessDataTypeTest {
@Test
public void typoCheck() {
for (BusinessDateType businessDateType : BusinessDateType.values()) {
void typoCheck() {
for (var businessDateType : BusinessDateType.values()) {
switch (businessDateType) {
case BUSINESS_DATE -> assertEquals("Business Date", businessDateType.getDescription());
case COB_DATE -> assertEquals("Close of Business Date", businessDateType.getDescription());
@@ -0,0 +1,60 @@
/**
* 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;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.time.LocalDate;
import java.time.ZoneId;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.junit.jupiter.api.Test;
class BusinessDateSerializationTest {
private final ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule())
.setSerializationInclusion(JsonInclude.Include.NON_NULL);
@Test
void serializeBusinessDateData() throws JsonProcessingException {
var now = LocalDate.now(ZoneId.systemDefault());
var businessDateResponse = BusinessDateResponse.builder().type(BusinessDateType.BUSINESS_DATE)
.description(BusinessDateType.BUSINESS_DATE.getDescription()).date(now).build();
var result = mapper.writeValueAsString(businessDateResponse);
assertEquals("{\"description\":\"Business Date\",\"type\":\"BUSINESS_DATE\",\"date\":[" + now.getYear() + "," + now.getMonthValue()
+ "," + now.getDayOfMonth() + "]}", result);
}
@Test
void serializeBusinessDateData_COB() throws JsonProcessingException {
var now = LocalDate.now(ZoneId.systemDefault());
var businessDateResponse = BusinessDateResponse.builder().type(BusinessDateType.COB_DATE)
.description(BusinessDateType.COB_DATE.getDescription()).date(now).build();
var result = mapper.writeValueAsString(businessDateResponse);
assertEquals("{\"description\":\"Close of Business Date\",\"type\":\"COB_DATE\",\"date\":[" + now.getYear() + ","
+ now.getMonthValue() + "," + now.getDayOfMonth() + "]}", result);
}
}
@@ -23,34 +23,32 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Collections;
import java.util.List;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateData;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDate;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;
public class BusinessDateMapperTest {
class BusinessDateUpdateRequestMapperTest {
private BusinessDateMapper businessDateMapper = Mappers.getMapper(BusinessDateMapper.class);
private final BusinessDateMapper businessDateMapper = Mappers.getMapper(BusinessDateMapper.class);
@Test
public void testMapping() {
LocalDate now = LocalDate.now(ZoneId.systemDefault());
BusinessDate businessDate = BusinessDate.instance(BusinessDateType.BUSINESS_DATE, now);
BusinessDateData businessDateData = businessDateMapper.map(businessDate);
assertEquals(businessDate.getDate(), businessDateData.getDate());
assertEquals(businessDate.getType().getDescription(), businessDateData.getDescription());
assertEquals(businessDate.getType().getName(), businessDateData.getType());
void testMapping() {
var now = LocalDate.now(ZoneId.systemDefault());
var businessDate = BusinessDate.instance(BusinessDateType.BUSINESS_DATE, now);
var businessDateResponse = businessDateMapper.map(businessDate);
assertEquals(businessDate.getDate(), businessDateResponse.getDate());
assertEquals(businessDate.getType().getDescription(), businessDateResponse.getDescription());
assertEquals(businessDate.getType(), businessDateResponse.getType());
}
@Test
public void testMappingList() {
LocalDate now = LocalDate.now(ZoneId.systemDefault());
BusinessDate businessDate = BusinessDate.instance(BusinessDateType.BUSINESS_DATE, now);
List<BusinessDateData> businessDateData = businessDateMapper.map(Collections.singletonList(businessDate));
void testMappingList() {
var now = LocalDate.now(ZoneId.systemDefault());
var businessDate = BusinessDate.instance(BusinessDateType.BUSINESS_DATE, now);
var businessDateData = businessDateMapper.map(Collections.singletonList(businessDate));
assertEquals(businessDate.getDate(), businessDateData.get(0).getDate());
assertEquals(businessDate.getType().getDescription(), businessDateData.get(0).getDescription());
assertEquals(businessDate.getType().getName(), businessDateData.get(0).getType());
assertEquals(businessDate.getType(), businessDateData.get(0).getType());
}
}
@@ -51,7 +51,7 @@ public class BusinessDateReadPlatformServiceTest {
private BusinessDateRepository repository;
@Mock
private BusinessDateMapper mapper;
private BusinessDateMapper businessDateMapper;
@Test
public void notFoundByTypeNonexistentType() {
@@ -73,7 +73,7 @@ public class BusinessDateReadPlatformServiceTest {
given(repository.findAll()).willReturn(resultList);
businessDateReadPlatformService.findAll();
verify(repository, times(1)).findAll();
verify(mapper, times(1)).map(resultList);
verify(businessDateMapper, times(1)).map(resultList);
}
@Test
@@ -82,7 +82,7 @@ public class BusinessDateReadPlatformServiceTest {
given(repository.findByType(BusinessDateType.COB_DATE)).willReturn(result);
businessDateReadPlatformService.findByType("COB_DATE");
verify(repository, times(1)).findByType(BusinessDateType.COB_DATE);
verify(mapper, times(1)).map(result.get());
verify(businessDateMapper, times(1)).map(result.get());
}
@Test
@@ -91,6 +91,6 @@ public class BusinessDateReadPlatformServiceTest {
given(repository.findByType(BusinessDateType.BUSINESS_DATE)).willReturn(result);
businessDateReadPlatformService.findByType("BUSINESS_DATE");
verify(repository, times(1)).findByType(BusinessDateType.BUSINESS_DATE);
verify(mapper, times(1)).map(result.get());
verify(businessDateMapper, times(1)).map(result.get());
}
}
@@ -18,6 +18,8 @@
*/
package org.apache.fineract.infrastructure.businessdate.service;
import static org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType.BUSINESS_DATE;
import static org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType.COB_DATE;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -27,17 +29,17 @@ import static org.mockito.Mockito.verify;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateData;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateResponse;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateUpdateRequest;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDate;
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.validator.BusinessDateDataParserAndValidator;
import org.apache.fineract.infrastructure.businessdate.mapper.BusinessDateUpdateRequestMapper;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
@@ -64,7 +66,7 @@ public class BusinessDateWritePlatformServiceTest {
private BusinessDateWritePlatformServiceImpl underTest;
@Mock
private BusinessDateDataParserAndValidator businessDateDataParserAndValidator;
private BusinessDateUpdateRequestMapper updateBusinessDateMapper;
@Mock
private BusinessDateRepository businessDateRepository;
@@ -87,163 +89,180 @@ public class BusinessDateWritePlatformServiceTest {
@Test
public void businessDateIsNotEnabled() {
JsonCommand command = JsonCommand.from("");
BusinessDateData businessDateData = BusinessDateData.instance(BusinessDateType.BUSINESS_DATE,
LocalDate.now(ZoneId.systemDefault()));
BusinessDateUpdateRequest businessDateUpdateRequest = new BusinessDateUpdateRequest();
given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.FALSE);
given(businessDateDataParserAndValidator.validateAndParseUpdate(command)).willReturn(businessDateData);
BusinessDateActionException exception = assertThrows(BusinessDateActionException.class,
() -> underTest.updateBusinessDate(command));
() -> underTest.updateBusinessDate(businessDateUpdateRequest));
assertEquals("Business date functionality is not enabled", exception.getDefaultUserMessage());
}
@Test
public void businessDateSetNew() {
JsonCommand command = JsonCommand.from("");
BusinessDateData businessDateData = BusinessDateData.instance(BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 6, 13));
BusinessDateUpdateRequest businessDateUpdateRequest = new BusinessDateUpdateRequest();
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.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE);
given(businessDateDataParserAndValidator.validateAndParseUpdate(command)).willReturn(businessDateData);
given(updateBusinessDateMapper.map(businessDateUpdateRequest)).willReturn(businessDateRes);
Optional<BusinessDate> newEntity = Optional.empty();
given(businessDateRepository.findByType(BusinessDateType.BUSINESS_DATE)).willReturn(newEntity);
CommandProcessingResult result = underTest.updateBusinessDate(command);
LocalDate resultData = (LocalDate) result.getChanges().get("BUSINESS_DATE");
assertEquals(LocalDate.of(2022, 6, 13), resultData);
given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity);
BusinessDateResponse result = underTest.updateBusinessDate(businessDateUpdateRequest);
final LocalDate resultDate = result.getChanges().get(BUSINESS_DATE);
assertEquals(LocalDate.of(2022, 6, 13), resultDate);
verify(configurationDomainService, times(1)).isBusinessDateEnabled();
verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled();
verify(businessDateRepository, times(1)).findByType(BusinessDateType.BUSINESS_DATE);
verify(businessDateRepository, times(1)).findByType(BUSINESS_DATE);
verify(businessDateRepository, times(1)).save(businessDateArgumentCaptor.capture());
assertEquals(LocalDate.of(2022, 6, 13), businessDateArgumentCaptor.getValue().getDate());
assertEquals(BusinessDateType.BUSINESS_DATE, businessDateArgumentCaptor.getValue().getType());
assertEquals(BUSINESS_DATE, businessDateArgumentCaptor.getValue().getType());
}
@Test
public void cobDateSetNew() {
JsonCommand command = JsonCommand.from("");
BusinessDateData businessDateData = BusinessDateData.instance(BusinessDateType.COB_DATE, LocalDate.of(2022, 6, 13));
BusinessDateUpdateRequest businessDateUpdateRequest = new BusinessDateUpdateRequest();
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.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE);
given(businessDateDataParserAndValidator.validateAndParseUpdate(command)).willReturn(businessDateData);
given(updateBusinessDateMapper.map(businessDateUpdateRequest)).willReturn(response);
Optional<BusinessDate> newEntity = Optional.empty();
given(businessDateRepository.findByType(BusinessDateType.COB_DATE)).willReturn(newEntity);
CommandProcessingResult result = underTest.updateBusinessDate(command);
LocalDate resultData = (LocalDate) result.getChanges().get("COB_DATE");
given(businessDateRepository.findByType(COB_DATE)).willReturn(newEntity);
BusinessDateResponse result = underTest.updateBusinessDate(businessDateUpdateRequest);
LocalDate resultData = result.getChanges().get(COB_DATE);
assertEquals(LocalDate.of(2022, 6, 13), resultData);
verify(configurationDomainService, times(1)).isBusinessDateEnabled();
verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled();
verify(businessDateRepository, times(1)).findByType(BusinessDateType.COB_DATE);
verify(businessDateRepository, times(1)).findByType(COB_DATE);
verify(businessDateRepository, times(1)).save(businessDateArgumentCaptor.capture());
assertEquals(LocalDate.of(2022, 6, 13), businessDateArgumentCaptor.getValue().getDate());
assertEquals(BusinessDateType.COB_DATE, businessDateArgumentCaptor.getValue().getType());
assertEquals(COB_DATE, businessDateArgumentCaptor.getValue().getType());
}
@Test
public void businessDateSetModifyExistingWhenItWasAfter() {
JsonCommand command = JsonCommand.from("");
BusinessDateData businessDateData = BusinessDateData.instance(BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 6, 11));
BusinessDateUpdateRequest businessDateUpdateRequest = new BusinessDateUpdateRequest();
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.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE);
given(businessDateDataParserAndValidator.validateAndParseUpdate(command)).willReturn(businessDateData);
Optional<BusinessDate> newEntity = Optional.of(BusinessDate.instance(BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 6, 12)));
given(businessDateRepository.findByType(BusinessDateType.BUSINESS_DATE)).willReturn(newEntity);
CommandProcessingResult result = underTest.updateBusinessDate(command);
LocalDate resultData = (LocalDate) result.getChanges().get("BUSINESS_DATE");
given(updateBusinessDateMapper.map(businessDateUpdateRequest)).willReturn(response);
Optional<BusinessDate> newEntity = Optional.of(BusinessDate.instance(BUSINESS_DATE, LocalDate.of(2022, 6, 12)));
given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity);
BusinessDateResponse result = underTest.updateBusinessDate(businessDateUpdateRequest);
LocalDate resultData = result.getChanges().get(BUSINESS_DATE);
assertEquals(LocalDate.of(2022, 6, 11), resultData);
verify(configurationDomainService, times(1)).isBusinessDateEnabled();
verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled();
verify(businessDateRepository, times(1)).findByType(BusinessDateType.BUSINESS_DATE);
verify(businessDateRepository, times(1)).findByType(BUSINESS_DATE);
verify(businessDateRepository, times(1)).save(businessDateArgumentCaptor.capture());
assertEquals(LocalDate.of(2022, 6, 11), businessDateArgumentCaptor.getValue().getDate());
assertEquals(BusinessDateType.BUSINESS_DATE, businessDateArgumentCaptor.getValue().getType());
assertEquals(BUSINESS_DATE, businessDateArgumentCaptor.getValue().getType());
}
@Test
public void businessDateSetModifyExistingWhenItWasBefore() {
JsonCommand command = JsonCommand.from("");
BusinessDateData businessDateData = BusinessDateData.instance(BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 6, 13));
BusinessDateUpdateRequest businessDateUpdateRequest = new BusinessDateUpdateRequest();
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.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE);
given(businessDateDataParserAndValidator.validateAndParseUpdate(command)).willReturn(businessDateData);
Optional<BusinessDate> newEntity = Optional.of(BusinessDate.instance(BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 6, 12)));
given(businessDateRepository.findByType(BusinessDateType.BUSINESS_DATE)).willReturn(newEntity);
CommandProcessingResult result = underTest.updateBusinessDate(command);
LocalDate resultData = (LocalDate) result.getChanges().get("BUSINESS_DATE");
given(updateBusinessDateMapper.map(businessDateUpdateRequest)).willReturn(response);
Optional<BusinessDate> newEntity = Optional.of(BusinessDate.instance(BUSINESS_DATE, LocalDate.of(2022, 6, 12)));
given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity);
BusinessDateResponse result = underTest.updateBusinessDate(businessDateUpdateRequest);
LocalDate resultData = result.getChanges().get(BUSINESS_DATE);
assertEquals(LocalDate.of(2022, 6, 13), resultData);
verify(configurationDomainService, times(1)).isBusinessDateEnabled();
verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled();
verify(businessDateRepository, times(1)).findByType(BusinessDateType.BUSINESS_DATE);
verify(businessDateRepository, times(1)).findByType(BUSINESS_DATE);
verify(businessDateRepository, times(1)).save(businessDateArgumentCaptor.capture());
assertEquals(LocalDate.of(2022, 6, 13), businessDateArgumentCaptor.getValue().getDate());
assertEquals(BusinessDateType.BUSINESS_DATE, businessDateArgumentCaptor.getValue().getType());
assertEquals(BUSINESS_DATE, businessDateArgumentCaptor.getValue().getType());
}
@Test
public void businessDateSetModifyExistingButNoChanges() {
JsonCommand command = JsonCommand.from("");
BusinessDateData businessDateData = BusinessDateData.instance(BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 6, 13));
BusinessDateUpdateRequest businessDateUpdateRequest = new BusinessDateUpdateRequest();
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.isCOBDateAdjustmentEnabled()).willReturn(Boolean.FALSE);
given(businessDateDataParserAndValidator.validateAndParseUpdate(command)).willReturn(businessDateData);
Optional<BusinessDate> newEntity = Optional.of(BusinessDate.instance(BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 6, 13)));
given(businessDateRepository.findByType(BusinessDateType.BUSINESS_DATE)).willReturn(newEntity);
CommandProcessingResult result = underTest.updateBusinessDate(command);
given(updateBusinessDateMapper.map(businessDateUpdateRequest)).willReturn(response);
Optional<BusinessDate> newEntity = Optional.of(BusinessDate.instance(BUSINESS_DATE, LocalDate.of(2022, 6, 13)));
given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity);
BusinessDateResponse result = underTest.updateBusinessDate(businessDateUpdateRequest);
assertNull(result.getChanges());
verify(configurationDomainService, times(1)).isBusinessDateEnabled();
verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled();
verify(businessDateRepository, times(1)).findByType(BusinessDateType.BUSINESS_DATE);
verify(businessDateRepository, times(1)).findByType(BUSINESS_DATE);
verify(businessDateRepository, times(0)).save(businessDateArgumentCaptor.capture());
}
@Test
public void cobDateSetNewAutomatically() {
JsonCommand command = JsonCommand.from("");
BusinessDateData businessDateData = BusinessDateData.instance(BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 6, 13));
BusinessDateUpdateRequest request = new BusinessDateUpdateRequest();
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.isCOBDateAdjustmentEnabled()).willReturn(Boolean.TRUE);
given(businessDateDataParserAndValidator.validateAndParseUpdate(command)).willReturn(businessDateData);
given(updateBusinessDateMapper.map(request)).willReturn(response);
Optional<BusinessDate> newEntity = Optional.empty();
given(businessDateRepository.findByType(BusinessDateType.BUSINESS_DATE)).willReturn(newEntity);
CommandProcessingResult result = underTest.updateBusinessDate(command);
LocalDate businessDate = (LocalDate) result.getChanges().get("BUSINESS_DATE");
given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity);
BusinessDateResponse result = underTest.updateBusinessDate(request);
LocalDate businessDate = result.getChanges().get(BUSINESS_DATE);
assertEquals(LocalDate.of(2022, 6, 13), businessDate);
LocalDate cobDate = (LocalDate) result.getChanges().get("COB_DATE");
LocalDate cobDate = result.getChanges().get(COB_DATE);
assertEquals(LocalDate.of(2022, 6, 12), cobDate);
verify(configurationDomainService, times(1)).isBusinessDateEnabled();
verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled();
verify(businessDateRepository, times(1)).findByType(BusinessDateType.BUSINESS_DATE);
verify(businessDateRepository, times(1)).findByType(BusinessDateType.COB_DATE);
verify(businessDateRepository, times(1)).findByType(BUSINESS_DATE);
verify(businessDateRepository, times(1)).findByType(COB_DATE);
verify(businessDateRepository, times(2)).save(businessDateArgumentCaptor.capture());
assertEquals(LocalDate.of(2022, 6, 13), businessDateArgumentCaptor.getAllValues().get(0).getDate());
assertEquals(BusinessDateType.BUSINESS_DATE, businessDateArgumentCaptor.getAllValues().get(0).getType());
assertEquals(BUSINESS_DATE, businessDateArgumentCaptor.getAllValues().get(0).getType());
assertEquals(LocalDate.of(2022, 6, 12), businessDateArgumentCaptor.getAllValues().get(1).getDate());
assertEquals(BusinessDateType.COB_DATE, businessDateArgumentCaptor.getAllValues().get(1).getType());
assertEquals(COB_DATE, businessDateArgumentCaptor.getAllValues().get(1).getType());
}
@Test
public void businessDateAndCobDateSetModifyExistingButNoChanges() {
JsonCommand command = JsonCommand.from("");
BusinessDateData businessDateData = BusinessDateData.instance(BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 6, 13));
BusinessDateUpdateRequest request = new BusinessDateUpdateRequest();
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.isCOBDateAdjustmentEnabled()).willReturn(Boolean.TRUE);
given(businessDateDataParserAndValidator.validateAndParseUpdate(command)).willReturn(businessDateData);
Optional<BusinessDate> newBusinessEntity = Optional
.of(BusinessDate.instance(BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 6, 13)));
Optional<BusinessDate> newCOBEntity = Optional.of(BusinessDate.instance(BusinessDateType.COB_DATE, LocalDate.of(2022, 6, 12)));
given(businessDateRepository.findByType(BusinessDateType.BUSINESS_DATE)).willReturn(newBusinessEntity);
given(businessDateRepository.findByType(BusinessDateType.COB_DATE)).willReturn(newCOBEntity);
CommandProcessingResult result = underTest.updateBusinessDate(command);
given(updateBusinessDateMapper.map(request)).willReturn(response);
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)));
given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newBusinessEntity);
given(businessDateRepository.findByType(COB_DATE)).willReturn(newCOBEntity);
BusinessDateResponse result = underTest.updateBusinessDate(request);
assertNull(result.getChanges());
verify(configurationDomainService, times(1)).isBusinessDateEnabled();
verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled();
verify(businessDateRepository, times(1)).findByType(BusinessDateType.BUSINESS_DATE);
verify(businessDateRepository, times(1)).findByType(BusinessDateType.COB_DATE);
verify(businessDateRepository, times(1)).findByType(BUSINESS_DATE);
verify(businessDateRepository, times(1)).findByType(COB_DATE);
verify(businessDateRepository, times(0)).save(Mockito.any());
}
@Test
public void businessDateIsNotEnabledTriggeredByJob() {
given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.FALSE);
assertThrows(JobExecutionException.class, () -> underTest.increaseBusinessDateByOneDay());
assertThrows(JobExecutionException.class, () -> underTest.increaseDateByTypeByOneDay(BUSINESS_DATE));
}
@Test
@@ -253,25 +272,25 @@ public class BusinessDateWritePlatformServiceTest {
given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE);
given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.TRUE);
Optional<BusinessDate> newEntity = Optional.empty();
given(businessDateRepository.findByType(BusinessDateType.BUSINESS_DATE)).willReturn(newEntity);
underTest.increaseBusinessDateByOneDay();
given(businessDateRepository.findByType(BUSINESS_DATE)).willReturn(newEntity);
underTest.increaseDateByTypeByOneDay(BUSINESS_DATE);
verify(configurationDomainService, times(1)).isBusinessDateEnabled();
verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled();
verify(businessDateRepository, times(2)).save(businessDateArgumentCaptor.capture());
assertEquals(localDatePlus1, businessDateArgumentCaptor.getAllValues().get(0).getDate());
assertEquals(BusinessDateType.BUSINESS_DATE, businessDateArgumentCaptor.getAllValues().get(0).getType());
assertEquals(BUSINESS_DATE, businessDateArgumentCaptor.getAllValues().get(0).getType());
assertEquals(localDate, businessDateArgumentCaptor.getAllValues().get(1).getDate());
assertEquals(BusinessDateType.COB_DATE, businessDateArgumentCaptor.getAllValues().get(1).getType());
assertEquals(COB_DATE, businessDateArgumentCaptor.getAllValues().get(1).getType());
}
@Test
public void cobDateModifyExistingTriggeredByJob() throws JobExecutionException {
Optional<BusinessDate> newCOBEntity = Optional.of(BusinessDate.instance(BusinessDateType.COB_DATE, LocalDate.of(2022, 6, 12)));
given(businessDateRepository.findByType(BusinessDateType.COB_DATE)).willReturn(newCOBEntity);
Optional<BusinessDate> newCOBEntity = Optional.of(BusinessDate.instance(COB_DATE, LocalDate.of(2022, 6, 12)));
given(businessDateRepository.findByType(COB_DATE)).willReturn(newCOBEntity);
LocalDate localDate = LocalDate.of(2022, 6, 12).plusDays(1);
given(configurationDomainService.isBusinessDateEnabled()).willReturn(Boolean.TRUE);
given(configurationDomainService.isCOBDateAdjustmentEnabled()).willReturn(Boolean.TRUE);
underTest.increaseCOBDateByOneDay();
underTest.increaseDateByTypeByOneDay(COB_DATE);
verify(configurationDomainService, times(1)).isBusinessDateEnabled();
verify(configurationDomainService, times(1)).isCOBDateAdjustmentEnabled();
verify(businessDateRepository, times(1)).save(businessDateArgumentCaptor.capture());
@@ -0,0 +1,88 @@
/**
* 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.validation;
import static org.assertj.core.api.Assertions.assertThat;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateUpdateRequest;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.validation.config.ValidationConfig;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.validation.Validator;
@Slf4j
@SpringBootTest
@ContextConfiguration(classes = { ValidationConfig.class })
class BusinessDateValidationTest {
@Autowired
private Validator validator;
@Test
void invalidAllBlank() {
var request = BusinessDateUpdateRequest.builder().dateFormat("").type(null).date(" ").locale(null).build();
var errors = validator.validateObject(request);
assertThat(errors.getFieldErrorCount()).isEqualTo(5);
assertThat(errors.getFieldErrors()).anyMatch(e -> e.getField().equals("date"));
assertThat(errors.getFieldErrors()).anyMatch(e -> e.getField().equals("dateFormat"));
assertThat(errors.getFieldErrors()).anyMatch(e -> e.getField().equals("locale"));
assertThat(errors.getFieldErrors()).anyMatch(e -> e.getField().equals("type"));
}
@Test
void invalidLocale() {
var request = BusinessDateUpdateRequest.builder().dateFormat("dd-MM-yyyy").type(BusinessDateType.BUSINESS_DATE).date("12-05-2025")
.locale("EN").build();
var errors = validator.validateObject(request);
assertThat(errors.getFieldErrorCount()).isEqualTo(1);
assertThat(errors.getFieldErrors()).anyMatch(e -> e.getField().equals("locale"));
}
@Test
void invalidDateFormat() {
var request = BusinessDateUpdateRequest.builder().dateFormat("dd/MM/yyyy").type(BusinessDateType.BUSINESS_DATE).date("12-05-2025")
.locale("en").build();
var errors = validator.validateObject(request);
assertThat(errors.getErrorCount()).isEqualTo(1);
assertThat(errors.getAllErrors()).anyMatch(e -> "Wrong local date fields.".equals(e.getDefaultMessage()));
}
@Test
void valid() {
var request = BusinessDateUpdateRequest.builder().dateFormat("dd-MM-yyyy").type(BusinessDateType.BUSINESS_DATE).date("12-05-2025")
.locale("en").build();
var errors = validator.validateObject(request);
assertThat(errors.getFieldErrorCount()).isEqualTo(0);
}
}
@@ -1,120 +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.validator;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.time.LocalDate;
import org.apache.fineract.infrastructure.businessdate.data.BusinessDateData;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.junit.jupiter.api.Test;
public class BusinessDateValidatorTest {
private BusinessDateDataParserAndValidator businessDateDataParserAndValidator = new BusinessDateDataParserAndValidator(
new FromJsonHelper());
@Test
public void validateAndParseUpdateWithEmptyRequest() {
String json = "{}";
JsonCommand command = JsonCommand.from(json);
PlatformApiDataValidationException exception = assertThrows(PlatformApiDataValidationException.class,
() -> businessDateDataParserAndValidator.validateAndParseUpdate(command));
assertEquals(
"PlatformApiDataValidationException{errors=[The parameter `type` is mandatory., The parameter `locale` is mandatory., The parameter `dateFormat` is mandatory., The parameter `date` is mandatory.]}",
exception.toString());
}
@Test
public void validateAndParseUpdateWithBlankFieldsInRequest() {
String json = "{\"type\":\"\", \"locale\":\"\",\"dateFormat\":\"\",\"date\":\"\"}";
JsonCommand command = JsonCommand.from(json);
PlatformApiDataValidationException exception = assertThrows(PlatformApiDataValidationException.class,
() -> businessDateDataParserAndValidator.validateAndParseUpdate(command));
assertEquals(
"PlatformApiDataValidationException{errors=[The parameter `type` is mandatory., The parameter `locale` is mandatory., The parameter `dateFormat` is mandatory., The parameter `date` is mandatory.]}",
exception.toString());
}
@Test
public void validateAndParseUpdateWithInvalidLocale() {
String json = "{\"type\":\"BUSINESS_DATE\", \"locale\":\"invalid\",\"dateFormat\":\"yyyy-MM-dd\",\"date\":\"2022-06-11\"}";
JsonCommand command = JsonCommand.from(json);
PlatformApiDataValidationException exception = assertThrows(PlatformApiDataValidationException.class,
() -> businessDateDataParserAndValidator.validateAndParseUpdate(command));
assertEquals("PlatformApiDataValidationException{errors=[The parameter `locale` has an invalid language value invalid .]}",
exception.toString());
}
@Test
public void validateAndParseUpdateWithInvalidBusinessType() {
String json = "{\"type\":\"invalid\", \"locale\":\"hu\",\"dateFormat\":\"yyyy-MM-dd\",\"date\":\"2022-06-11\"}";
JsonCommand command = JsonCommand.from(json);
PlatformApiDataValidationException exception = assertThrows(PlatformApiDataValidationException.class,
() -> businessDateDataParserAndValidator.validateAndParseUpdate(command));
assertEquals("PlatformApiDataValidationException{errors=[Failed data validation due to: Invalid Business Type value: `invalid`.]}",
exception.toString());
}
@Test
public void validateAndParseUpdateWithInvalidDateFormat() {
String json = "{\"type\":\"BUSINESS_DATE\", \"locale\":\"hu\",\"dateFormat\":\"y2yyy-MM-dd\",\"date\":\"2022-06-11\"}";
JsonCommand command = JsonCommand.from(json);
PlatformApiDataValidationException exception = assertThrows(PlatformApiDataValidationException.class,
() -> businessDateDataParserAndValidator.validateAndParseUpdate(command));
assertEquals(
"PlatformApiDataValidationException{errors=[The parameter `date` is invalid based on the dateFormat: `y2yyy-MM-dd` and locale: `hu` provided:]}",
exception.toString());
}
@Test
public void validateAndParseUpdateWithInvalidDate() {
String json = "{\"type\":\"BUSINESS_DATE\", \"locale\":\"hu\",\"dateFormat\":\"yyyy-MM-dd\",\"date\":\"2y22-06-11\"}";
JsonCommand command = JsonCommand.from(json);
PlatformApiDataValidationException exception = assertThrows(PlatformApiDataValidationException.class,
() -> businessDateDataParserAndValidator.validateAndParseUpdate(command));
assertEquals(
"PlatformApiDataValidationException{errors=[The parameter `date` is invalid based on the dateFormat: `yyyy-MM-dd` and locale: `hu` provided:]}",
exception.toString());
}
@Test
public void validateAndParseUpdateWithWrongDate() {
String json = "{\"type\":\"BUSINESS_DATE\", \"locale\":\"hu\",\"dateFormat\":\"yyyy-MM-dd\",\"date\":\"11-06-2022\"}";
JsonCommand command = JsonCommand.from(json);
PlatformApiDataValidationException exception = assertThrows(PlatformApiDataValidationException.class,
() -> businessDateDataParserAndValidator.validateAndParseUpdate(command));
assertEquals(
"PlatformApiDataValidationException{errors=[The parameter `date` is invalid based on the dateFormat: `yyyy-MM-dd` and locale: `hu` provided:]}",
exception.toString());
}
@Test
public void validateAndParseUpdateWithRightDate() {
String json = "{\"type\":\"COB_DATE\", \"locale\":\"hu\",\"dateFormat\":\"yyyy-MM-dd\",\"date\":\"2022-06-11\"}";
JsonCommand command = JsonCommand.from(json);
BusinessDateData result = businessDateDataParserAndValidator.validateAndParseUpdate(command);
assertEquals("COB_DATE", result.getType());
assertEquals("Close of Business Date", result.getDescription());
assertEquals(LocalDate.of(2022, 6, 11), result.getDate());
}
}
@@ -24,8 +24,8 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateWritePlatformService;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.jobs.service.increasedateby1day.IncreaseDateBy1DayService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -52,7 +52,7 @@ class IncreaseBusinessDateBy1DayTaskletTest {
private ConfigurationDomainService configurationDomainService;
@Mock
private IncreaseDateBy1DayService increaseDateBy1DayService;
private BusinessDateWritePlatformService businessDateWritePlatformService;
@InjectMocks
private IncreaseBusinessDateBy1DayTasklet underTest;
@@ -73,7 +73,7 @@ class IncreaseBusinessDateBy1DayTaskletTest {
RepeatStatus repeatStatus = underTest.execute(stepContribution, chunkContext);
verify(increaseDateBy1DayService, times(1)).increaseDateByTypeByOneDay(BusinessDateType.BUSINESS_DATE);
verify(businessDateWritePlatformService, times(1)).increaseDateByTypeByOneDay(BusinessDateType.BUSINESS_DATE);
assertEquals(RepeatStatus.FINISHED, repeatStatus);
}
@@ -24,8 +24,8 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateWritePlatformService;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.jobs.service.increasedateby1day.IncreaseDateBy1DayService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -52,7 +52,7 @@ class IncreaseCobDateBy1DayTaskletTest {
private ConfigurationDomainService configurationDomainService;
@Mock
private IncreaseDateBy1DayService increaseDateBy1DayService;
private BusinessDateWritePlatformService businessDateWritePlatformService;
@InjectMocks
private IncreaseCobDateBy1DayTasklet underTest;
@@ -73,7 +73,7 @@ class IncreaseCobDateBy1DayTaskletTest {
RepeatStatus repeatStatus = underTest.execute(stepContribution, chunkContext);
verify(increaseDateBy1DayService, times(1)).increaseDateByTypeByOneDay(BusinessDateType.COB_DATE);
verify(businessDateWritePlatformService, times(1)).increaseDateByTypeByOneDay(BusinessDateType.COB_DATE);
assertEquals(RepeatStatus.FINISHED, repeatStatus);
}