From 7559e90ce235ebc1a2bfdf3cae6e9b88cf9cd163 Mon Sep 17 00:00:00 2001 From: taskain7 Date: Tue, 1 Aug 2023 05:34:14 +0200 Subject: [PATCH] [FINERACT-1678] Configuration for enabling/disabling Loan COB --- .../core/config/FineractProperties.java | 1 + .../core/data/ApiGlobalErrorResponse.java | 11 +++ .../JobIsNotFoundOrNotEnabledException.java | 30 ++++++++ ...IsNotFoundOrNotEnabledExceptionMapper.java | 42 ++++++++++ .../en/chapters/architecture/batch-jobs.adoc | 54 ++++++++++++- .../cob/api/LoanCOBCatchUpApiResource.java | 24 ++++-- .../conditions/LoanCOBEnabledCondition.java | 30 ++++++++ .../conditions/LoanCOBManagerCondition.java | 32 ++++++++ .../conditions/LoanCOBWorkerCondition.java | 32 ++++++++ .../cob/loan/LoanCOBManagerConfiguration.java | 5 +- .../cob/loan/LoanCOBWorkerConfiguration.java | 5 +- .../cob/loan/LoanInlineCOBConfig.java | 3 + .../AsyncLoanCOBExecutorServiceImpl.java | 3 + .../InlineLoanCOBExecutorServiceImpl.java | 3 + .../service/LoanCOBCatchUpServiceImpl.java | 3 + .../core/config/SecurityConfig.java | 13 +++- .../jobs/filter/LoanCOBApiFilter.java | 3 + .../jobs/filter/LoanCOBBatchPreprocessor.java | 3 + .../jobs/filter/LoanCOBFilterHelper.java | 3 + .../jobs/service/InlineJobExecuteHandler.java | 10 ++- .../jobs/service/JobRegisterServiceImpl.java | 13 +++- .../jobs/service/JobSchedulerServiceImpl.java | 7 +- .../src/main/resources/application.properties | 1 + .../LoanCOBEnabledConditionTest.java | 67 ++++++++++++++++ .../LoanCOBManagerConditionTest.java | 77 +++++++++++++++++++ .../LoanCOBWorkerConditionTest.java | 77 +++++++++++++++++++ .../resources/application-test.properties | 1 + 27 files changed, 535 insertions(+), 18 deletions(-) create mode 100644 fineract-core/src/main/java/org/apache/fineract/infrastructure/core/exception/JobIsNotFoundOrNotEnabledException.java create mode 100644 fineract-core/src/main/java/org/apache/fineract/infrastructure/core/exceptionmapper/JobIsNotFoundOrNotEnabledExceptionMapper.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/cob/conditions/LoanCOBEnabledCondition.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/cob/conditions/LoanCOBManagerCondition.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/cob/conditions/LoanCOBWorkerCondition.java create mode 100644 fineract-provider/src/test/java/org/apache/fineract/cob/conditions/LoanCOBEnabledConditionTest.java create mode 100644 fineract-provider/src/test/java/org/apache/fineract/cob/conditions/LoanCOBManagerConditionTest.java create mode 100644 fineract-provider/src/test/java/org/apache/fineract/cob/conditions/LoanCOBWorkerConditionTest.java diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java index f37d27326..eeede352f 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java @@ -380,6 +380,7 @@ public class FineractProperties { public static class FineractJobProperties { private int stuckRetryThreshold; + private boolean loanCobEnabled; } @Getter diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/data/ApiGlobalErrorResponse.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/data/ApiGlobalErrorResponse.java index 521100f44..95a72ab18 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/data/ApiGlobalErrorResponse.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/data/ApiGlobalErrorResponse.java @@ -177,6 +177,17 @@ public class ApiGlobalErrorResponse { return globalErrorResponse; } + public static ApiGlobalErrorResponse jobIsDisabled(final String globalisationMessageCode, final String defaultUserMessage) { + + final ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse(); + globalErrorResponse.setHttpStatusCode(Status.FORBIDDEN.toString()); + globalErrorResponse.setDeveloperMessage(defaultUserMessage); + globalErrorResponse.setUserMessageGlobalisationCode(globalisationMessageCode); + globalErrorResponse.setDefaultUserMessage(defaultUserMessage); + + return globalErrorResponse; + } + public static ApiGlobalErrorResponse badClientRequest(final String globalisationMessageCode, final String defaultUserMessage) { return badClientRequest(globalisationMessageCode, defaultUserMessage, Collections.emptyList()); } diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/exception/JobIsNotFoundOrNotEnabledException.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/exception/JobIsNotFoundOrNotEnabledException.java new file mode 100644 index 000000000..13c7039d9 --- /dev/null +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/exception/JobIsNotFoundOrNotEnabledException.java @@ -0,0 +1,30 @@ +/** + * 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.core.exception; + +public class JobIsNotFoundOrNotEnabledException extends AbstractPlatformException { + + public JobIsNotFoundOrNotEnabledException(Exception e, String jobName) { + super("error.msg.job.disabled", "Job " + jobName + " is not found or it is disabled", e); + } + + public JobIsNotFoundOrNotEnabledException(String jobName) { + super("error.msg.job.disabled", "Job " + jobName + " is not found or it is disabled"); + } +} diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/exceptionmapper/JobIsNotFoundOrNotEnabledExceptionMapper.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/exceptionmapper/JobIsNotFoundOrNotEnabledExceptionMapper.java new file mode 100644 index 000000000..53a570339 --- /dev/null +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/exceptionmapper/JobIsNotFoundOrNotEnabledExceptionMapper.java @@ -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.infrastructure.core.exceptionmapper; + +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import jakarta.ws.rs.ext.Provider; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.infrastructure.core.data.ApiGlobalErrorResponse; +import org.apache.fineract.infrastructure.core.exception.JobIsNotFoundOrNotEnabledException; +import org.springframework.stereotype.Component; + +@Provider +@Component +@Slf4j +public class JobIsNotFoundOrNotEnabledExceptionMapper implements ExceptionMapper { + + @Override + public Response toResponse(JobIsNotFoundOrNotEnabledException exception) { + log.warn("Exception: {}, Message: {}", exception.getClass().getName(), exception.getMessage()); + return Response.status(Response.Status.FORBIDDEN) + .entity(ApiGlobalErrorResponse.jobIsDisabled(exception.getGlobalisationMessageCode(), exception.getDefaultUserMessage())) + .type(MediaType.APPLICATION_JSON).build(); + } +} diff --git a/fineract-doc/src/docs/en/chapters/architecture/batch-jobs.adoc b/fineract-doc/src/docs/en/chapters/architecture/batch-jobs.adoc index a93d671b2..777c87a12 100644 --- a/fineract-doc/src/docs/en/chapters/architecture/batch-jobs.adoc +++ b/fineract-doc/src/docs/en/chapters/architecture/batch-jobs.adoc @@ -253,4 +253,56 @@ PUT /fineract-provider/api/v1/jobs/{jobName}/steps?tenantIdentifier={tenantId} } ---- -The business step configuration for jobs are tracked within the database in the `m_batch_business_steps` table. \ No newline at end of file +The business step configuration for jobs are tracked within the database in the `m_batch_business_steps` table. + +== Inline Jobs + +Some jobs that work with business entities have a corresponding job that can trigger the job with a list of specified entities. +When the Inline job gets triggered then then the corresponding existing job will run in real time with the given entities as a dataset. + +=== List of Inline jobs + +[cols="1,1"] +|=== +|*Inline Job name* +|*Corresponding Job* + +|LOAN_COB +|LOAN_CLOSE_OF_BUSINESS + +|=== + +Triggering the Inline Loan COB Job: + +[source] +---- +POST /fineract-provider/api/v1/jobs/LOAN_COB/inline?tenantIdentifier={tenantId} + +{ + "loanIds": [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 + ] +} +---- +In this case the Loan COB job will work only with the given loan IDs. + +== Global Configuration for enabling/disabling jobs + +Some jobs can be enabled/disabled with global configuration. +If the job is disabled with the global configuration then it cannot be scheduled and cannot be triggered via API. + +=== List of jobs with global configuration + +[cols="1,1,1,1"] +|=== +|*Job name* +|*Application property* +|*Environment variable* +|*Default value* + +|LOAN_CLOSE_OF_BUSINESS +|fineract.job.loan-cob-enabled +|FINERACT_JOB_LOAN_COB_ENABLED +|true + +|=== diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/api/LoanCOBCatchUpApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/cob/api/LoanCOBCatchUpApiResource.java index c30793c6c..b8de555f6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/api/LoanCOBCatchUpApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/api/LoanCOBCatchUpApiResource.java @@ -31,22 +31,27 @@ import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; -import lombok.RequiredArgsConstructor; +import java.util.Objects; import org.apache.fineract.cob.data.IsCatchUpRunningDTO; import org.apache.fineract.cob.data.OldestCOBProcessedLoanDTO; import org.apache.fineract.cob.service.LoanCOBCatchUpService; +import org.apache.fineract.infrastructure.core.exception.JobIsNotFoundOrNotEnabledException; import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer; +import org.apache.fineract.infrastructure.jobs.service.JobName; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Path("/v1/loans") @Component @Tag(name = "Loan COB Catch Up", description = "") -@RequiredArgsConstructor public class LoanCOBCatchUpApiResource { - private final DefaultToApiJsonSerializer oldestCOBProcessedLoanSerializeService; - private final DefaultToApiJsonSerializer isCatchUpRunningSerializer; - private final LoanCOBCatchUpService loanCOBCatchUpService; + @Autowired + private DefaultToApiJsonSerializer oldestCOBProcessedLoanSerializeService; + @Autowired + private DefaultToApiJsonSerializer isCatchUpRunningSerializer; + @Autowired(required = false) + private LoanCOBCatchUpService loanCOBCatchUpService; @GET @Path("oldest-cob-closed") @@ -56,6 +61,9 @@ public class LoanCOBCatchUpApiResource { @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanCOBCatchUpApiResourceSwagger.GetOldestCOBProcessedLoanResponse.class))) }) public String getOldestCOBProcessedLoan() { + if (Objects.isNull(loanCOBCatchUpService)) { + throw new JobIsNotFoundOrNotEnabledException(JobName.LOAN_COB.name()); + } OldestCOBProcessedLoanDTO response = loanCOBCatchUpService.getOldestCOBProcessedLoan(); return oldestCOBProcessedLoanSerializeService.serialize(response); } @@ -69,6 +77,9 @@ public class LoanCOBCatchUpApiResource { @ApiResponse(responseCode = "202", description = "Catch Up has been started"), @ApiResponse(responseCode = "400", description = "Catch Up is already running") }) public Response executeLoanCOBCatchUp() { + if (Objects.isNull(loanCOBCatchUpService)) { + throw new JobIsNotFoundOrNotEnabledException(JobName.LOAN_COB.name()); + } if (loanCOBCatchUpService.isCatchUpRunning().isCatchUpRunning()) { return Response.status(Response.Status.BAD_REQUEST).build(); } @@ -90,6 +101,9 @@ public class LoanCOBCatchUpApiResource { @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanCOBCatchUpApiResourceSwagger.IsCatchUpRunningResponse.class))) }) public String isCatchUpRunning() { + if (Objects.isNull(loanCOBCatchUpService)) { + throw new JobIsNotFoundOrNotEnabledException(JobName.LOAN_COB.name()); + } IsCatchUpRunningDTO response = loanCOBCatchUpService.isCatchUpRunning(); return isCatchUpRunningSerializer.serialize(response); diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/conditions/LoanCOBEnabledCondition.java b/fineract-provider/src/main/java/org/apache/fineract/cob/conditions/LoanCOBEnabledCondition.java new file mode 100644 index 000000000..205a301d8 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/conditions/LoanCOBEnabledCondition.java @@ -0,0 +1,30 @@ +/** + * 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.cob.conditions; + +import org.apache.fineract.infrastructure.core.condition.PropertiesCondition; +import org.apache.fineract.infrastructure.core.config.FineractProperties; + +public class LoanCOBEnabledCondition extends PropertiesCondition { + + @Override + protected boolean matches(FineractProperties properties) { + return properties.getJob().isLoanCobEnabled(); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/conditions/LoanCOBManagerCondition.java b/fineract-provider/src/main/java/org/apache/fineract/cob/conditions/LoanCOBManagerCondition.java new file mode 100644 index 000000000..7c2a6d936 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/conditions/LoanCOBManagerCondition.java @@ -0,0 +1,32 @@ +/** + * 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.cob.conditions; + +import org.apache.fineract.infrastructure.core.condition.PropertiesCondition; +import org.apache.fineract.infrastructure.core.config.FineractProperties; + +public class LoanCOBManagerCondition extends PropertiesCondition { + + @Override + protected boolean matches(FineractProperties properties) { + boolean loanCobEnabled = properties.getJob().isLoanCobEnabled(); + boolean batchManagerEnabled = properties.getMode().isBatchManagerEnabled(); + return loanCobEnabled && batchManagerEnabled; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/conditions/LoanCOBWorkerCondition.java b/fineract-provider/src/main/java/org/apache/fineract/cob/conditions/LoanCOBWorkerCondition.java new file mode 100644 index 000000000..cfb3a2ea7 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/conditions/LoanCOBWorkerCondition.java @@ -0,0 +1,32 @@ +/** + * 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.cob.conditions; + +import org.apache.fineract.infrastructure.core.condition.PropertiesCondition; +import org.apache.fineract.infrastructure.core.config.FineractProperties; + +public class LoanCOBWorkerCondition extends PropertiesCondition { + + @Override + protected boolean matches(FineractProperties properties) { + boolean loanCobEnabled = properties.getJob().isLoanCobEnabled(); + boolean batchWorkerEnabled = properties.getMode().isBatchWorkerEnabled(); + return loanCobEnabled && batchWorkerEnabled; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java index de25ef946..74ffd4224 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java @@ -20,6 +20,7 @@ package org.apache.fineract.cob.loan; import org.apache.fineract.cob.COBBusinessStepService; import org.apache.fineract.cob.common.CustomJobParameterResolver; +import org.apache.fineract.cob.conditions.LoanCOBManagerCondition; import org.apache.fineract.cob.listener.COBExecutionListenerRunner; import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService; import org.apache.fineract.infrastructure.jobs.service.JobName; @@ -37,16 +38,16 @@ import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.integration.config.annotation.EnableBatchIntegration; import org.springframework.batch.integration.partition.RemotePartitioningManagerStepBuilderFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.integration.channel.DirectChannel; import org.springframework.transaction.PlatformTransactionManager; @Configuration @EnableBatchIntegration -@ConditionalOnProperty(value = "fineract.mode.batch-manager-enabled", havingValue = "true") +@Conditional(LoanCOBManagerCondition.class) public class LoanCOBManagerConfiguration { @Autowired diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBWorkerConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBWorkerConfiguration.java index 46c6c9736..abbfeef51 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBWorkerConfiguration.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBWorkerConfiguration.java @@ -22,6 +22,7 @@ import org.apache.fineract.cob.COBBusinessStepService; import org.apache.fineract.cob.common.CustomJobParameterResolver; import org.apache.fineract.cob.common.InitialisationTasklet; import org.apache.fineract.cob.common.ResetContextTasklet; +import org.apache.fineract.cob.conditions.LoanCOBWorkerCondition; import org.apache.fineract.cob.listener.ChunkProcessingLoanItemListener; import org.apache.fineract.infrastructure.core.config.FineractProperties; import org.apache.fineract.infrastructure.jobs.service.JobName; @@ -39,8 +40,8 @@ import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.integration.partition.RemotePartitioningWorkerStepBuilderFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.core.task.SyncTaskExecutor; import org.springframework.core.task.TaskExecutor; @@ -50,7 +51,7 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.support.TransactionTemplate; @Configuration -@ConditionalOnProperty(value = "fineract.mode.batch-worker-enabled", havingValue = "true") +@Conditional(LoanCOBWorkerCondition.class) public class LoanCOBWorkerConfiguration { @Autowired diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanInlineCOBConfig.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanInlineCOBConfig.java index 371b4b4b3..194a4cd79 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanInlineCOBConfig.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanInlineCOBConfig.java @@ -21,6 +21,7 @@ package org.apache.fineract.cob.loan; import org.apache.fineract.cob.COBBusinessStepService; import org.apache.fineract.cob.common.CustomJobParameterResolver; import org.apache.fineract.cob.common.ResetContextTasklet; +import org.apache.fineract.cob.conditions.LoanCOBEnabledCondition; import org.apache.fineract.cob.domain.LoanAccountLockRepository; import org.apache.fineract.cob.listener.InlineCOBLoanItemListener; import org.apache.fineract.infrastructure.jobs.domain.CustomJobParameterRepository; @@ -38,12 +39,14 @@ import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.integration.config.annotation.EnableBatchIntegration; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.support.TransactionTemplate; @Configuration @EnableBatchIntegration +@Conditional(LoanCOBEnabledCondition.class) public class LoanInlineCOBConfig { @Autowired diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/AsyncLoanCOBExecutorServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/AsyncLoanCOBExecutorServiceImpl.java index d92538cc4..fe53d3fd7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/service/AsyncLoanCOBExecutorServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/AsyncLoanCOBExecutorServiceImpl.java @@ -25,6 +25,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import lombok.RequiredArgsConstructor; +import org.apache.fineract.cob.conditions.LoanCOBEnabledCondition; import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate; import org.apache.fineract.cob.loan.LoanCOBConstant; import org.apache.fineract.cob.loan.RetrieveLoanIdService; @@ -45,11 +46,13 @@ import org.springframework.batch.core.launch.NoSuchJobException; import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; import org.springframework.batch.core.repository.JobRestartException; +import org.springframework.context.annotation.Conditional; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor +@Conditional(LoanCOBEnabledCondition.class) public class AsyncLoanCOBExecutorServiceImpl implements AsyncLoanCOBExecutorService { private final JobLocator jobLocator; diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/InlineLoanCOBExecutorServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/InlineLoanCOBExecutorServiceImpl.java index 6c75b2276..271e43a8d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/service/InlineLoanCOBExecutorServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/InlineLoanCOBExecutorServiceImpl.java @@ -35,6 +35,7 @@ import java.util.Set; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.apache.fineract.cob.conditions.LoanCOBEnabledCondition; import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate; import org.apache.fineract.cob.domain.LoanAccountLock; import org.apache.fineract.cob.domain.LoanAccountLockRepository; @@ -68,6 +69,7 @@ import org.springframework.batch.core.configuration.JobLocator; import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.launch.NoSuchJobException; +import org.springframework.context.annotation.Conditional; import org.springframework.stereotype.Service; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Propagation; @@ -78,6 +80,7 @@ import org.springframework.transaction.support.TransactionTemplate; @Service @Slf4j @RequiredArgsConstructor +@Conditional(LoanCOBEnabledCondition.class) public class InlineLoanCOBExecutorServiceImpl implements InlineExecutorService { private static final String JOB_EXECUTION_FAILED_MESSAGE = "Job execution failed for job with name: "; diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/LoanCOBCatchUpServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/LoanCOBCatchUpServiceImpl.java index cc0df3711..07a427fc1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/service/LoanCOBCatchUpServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/LoanCOBCatchUpServiceImpl.java @@ -22,6 +22,7 @@ import com.google.gson.Gson; import java.time.LocalDate; import java.util.List; import lombok.RequiredArgsConstructor; +import org.apache.fineract.cob.conditions.LoanCOBEnabledCondition; import org.apache.fineract.cob.data.IsCatchUpRunningDTO; import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate; import org.apache.fineract.cob.data.OldestCOBProcessedLoanDTO; @@ -34,10 +35,12 @@ import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.jobs.domain.CustomJobParameterRepository; import org.apache.fineract.infrastructure.jobs.domain.JobExecutionRepository; import org.springframework.batch.core.explore.JobExplorer; +import org.springframework.context.annotation.Conditional; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor +@Conditional(LoanCOBEnabledCondition.class) public class LoanCOBCatchUpServiceImpl implements LoanCOBCatchUpService { private final AsyncLoanCOBExecutorService asyncLoanCOBExecutorService; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java index 4fc460085..9a7d45d87 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java @@ -24,6 +24,7 @@ import static org.springframework.security.authorization.AuthorityAuthorizationM import static org.springframework.security.authorization.AuthorizationManagers.allOf; import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher; +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; @@ -107,7 +108,7 @@ public class SecurityConfig { @Autowired private FineractRequestContextHolder fineractRequestContextHolder; - @Autowired + @Autowired(required = false) private LoanCOBFilterHelper loanCOBFilterHelper; @Autowired private PlatformSecurityContext context; @@ -136,9 +137,13 @@ public class SecurityConfig { .addFilterAfter(requestResponseFilter(), ExceptionTranslationFilter.class) // .addFilterAfter(correlationHeaderFilter(), RequestResponseFilter.class) // .addFilterAfter(responseCorsFilter(), CorrelationHeaderFilter.class) // - .addFilterAfter(fineractInstanceModeApiFilter(), ResponseCorsFilter.class) // - .addFilterAfter(loanCOBApiFilter(), FineractInstanceModeApiFilter.class) // - .addFilterAfter(idempotencyStoreFilter(), LoanCOBApiFilter.class); // + .addFilterAfter(fineractInstanceModeApiFilter(), ResponseCorsFilter.class); // + if (!Objects.isNull(loanCOBFilterHelper)) { + http.addFilterAfter(loanCOBApiFilter(), FineractInstanceModeApiFilter.class) // + .addFilterAfter(idempotencyStoreFilter(), LoanCOBApiFilter.class); // + } else { + http.addFilterAfter(idempotencyStoreFilter(), FineractInstanceModeApiFilter.class); // + } if (fineractProperties.getSecurity().getTwoFactor().isEnabled()) { http.addFilterAfter(twoFactorAuthenticationFilter(), ResponseCorsFilter.class); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilter.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilter.java index 58d8db8a0..59e4a0855 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilter.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilter.java @@ -25,13 +25,16 @@ import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; import lombok.RequiredArgsConstructor; +import org.apache.fineract.cob.conditions.LoanCOBEnabledCondition; import org.apache.fineract.infrastructure.core.data.ApiGlobalErrorResponse; import org.apache.fineract.infrastructure.jobs.exception.LoanIdsHardLockedException; import org.apache.fineract.useradministration.exception.UnAuthenticatedUserException; import org.apache.http.HttpStatus; +import org.springframework.context.annotation.Conditional; import org.springframework.web.filter.OncePerRequestFilter; @RequiredArgsConstructor +@Conditional(LoanCOBEnabledCondition.class) public class LoanCOBApiFilter extends OncePerRequestFilter { private final LoanCOBFilterHelper helper; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBBatchPreprocessor.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBBatchPreprocessor.java index 33c7e708d..b4b39bedb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBBatchPreprocessor.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBBatchPreprocessor.java @@ -24,8 +24,10 @@ import io.github.resilience4j.core.functions.Either; import java.util.List; import lombok.RequiredArgsConstructor; import org.apache.fineract.batch.domain.BatchRequest; +import org.apache.fineract.cob.conditions.LoanCOBEnabledCondition; import org.apache.fineract.infrastructure.core.filters.BatchRequestPreprocessor; import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException; +import org.springframework.context.annotation.Conditional; import org.springframework.stereotype.Component; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; @@ -33,6 +35,7 @@ import org.springframework.transaction.support.TransactionTemplate; @Component @RequiredArgsConstructor +@Conditional(LoanCOBEnabledCondition.class) public class LoanCOBBatchPreprocessor implements BatchRequestPreprocessor { private final LoanCOBFilterHelper helper; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBFilterHelper.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBFilterHelper.java index 89173cf6a..9b43a299c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBFilterHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBFilterHelper.java @@ -28,6 +28,7 @@ import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.fineract.cob.conditions.LoanCOBEnabledCondition; import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate; import org.apache.fineract.cob.loan.RetrieveLoanIdService; import org.apache.fineract.cob.service.InlineLoanCOBExecutorServiceImpl; @@ -43,11 +44,13 @@ import org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonit import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequestRepository; +import org.springframework.context.annotation.Conditional; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; @RequiredArgsConstructor @Component +@Conditional(LoanCOBEnabledCondition.class) public class LoanCOBFilterHelper { private final GLIMAccountInfoRepository glimAccountInfoRepository; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/InlineJobExecuteHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/InlineJobExecuteHandler.java index aef62e1c4..c6f9e6647 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/InlineJobExecuteHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/InlineJobExecuteHandler.java @@ -23,6 +23,8 @@ import org.apache.fineract.commands.annotation.CommandType; import org.apache.fineract.commands.handler.NewCommandSourceHandler; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.exception.JobIsNotFoundOrNotEnabledException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; @@ -36,7 +38,11 @@ public class InlineJobExecuteHandler implements NewCommandSourceHandler { @Override public CommandProcessingResult processCommand(JsonCommand command) { InlineJobType inlineJobType = InlineJobType.getInlineJobType(command.getJobName()); - InlineExecutorService inlineJobExecutorService = applicationContext.getBean(inlineJobType.getExecutorServiceClass()); - return inlineJobExecutorService.executeInlineJob(command, inlineJobType.getInlineJobName()); + try { + InlineExecutorService inlineJobExecutorService = applicationContext.getBean(inlineJobType.getExecutorServiceClass()); + return inlineJobExecutorService.executeInlineJob(command, inlineJobType.getInlineJobName()); + } catch (NoSuchBeanDefinitionException e) { + throw new JobIsNotFoundOrNotEnabledException(e, inlineJobType.getInlineJobName()); + } } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobRegisterServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobRegisterServiceImpl.java index 95a5f7a3d..e89f30a97 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobRegisterServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobRegisterServiceImpl.java @@ -29,6 +29,7 @@ import java.util.TimeZone; import lombok.extern.slf4j.Slf4j; import org.apache.fineract.infrastructure.core.config.FineractProperties; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; +import org.apache.fineract.infrastructure.core.exception.JobIsNotFoundOrNotEnabledException; import org.apache.fineract.infrastructure.core.exception.PlatformInternalServerException; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.jobs.data.JobParameterDTO; @@ -48,6 +49,7 @@ import org.quartz.Trigger; import org.quartz.TriggerListener; import org.springframework.batch.core.Job; import org.springframework.batch.core.configuration.JobLocator; +import org.springframework.batch.core.launch.NoSuchJobException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextClosedEvent; @@ -118,6 +120,10 @@ public class JobRegisterServiceImpl implements JobRegisterService, ApplicationLi scheduler.addJob(jobDetail, true); scheduler.triggerJob(jobKey, jobDataMap); } + } catch (JobIsNotFoundOrNotEnabledException e) { + final String msg = "Job is not found or it is disabled with job ID: " + scheduledJobDetail.getId(); + log.error("{}", msg, e); + throw e; } catch (final Exception e) { final String msg = "Job execution failed for job with id:" + scheduledJobDetail.getId(); log.error("{}", msg, e); @@ -327,7 +333,12 @@ public class JobRegisterServiceImpl implements JobRegisterService, ApplicationLi final FineractPlatformTenant tenant = ThreadLocalContextUtil.getTenant(); JobNameData jobName = jobNameService.getJobByHumanReadableName(scheduledJobDetail.getJobName()); - Job job = jobLocator.getJob(jobName.getEnumStyleName()); + Job job; + try { + job = jobLocator.getJob(jobName.getEnumStyleName()); + } catch (NoSuchJobException e) { + throw new JobIsNotFoundOrNotEnabledException(e, jobName.getEnumStyleName()); + } final MethodInvokingJobDetailFactoryBean jobDetailFactoryBean = new MethodInvokingJobDetailFactoryBean(); jobDetailFactoryBean.setName(scheduledJobDetail.getJobName() + "JobDetail" + tenant.getId()); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobSchedulerServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobSchedulerServiceImpl.java index 6d7af7c66..ab5b6ecb4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobSchedulerServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobSchedulerServiceImpl.java @@ -28,6 +28,7 @@ import org.apache.fineract.infrastructure.businessdate.service.BusinessDateReadP import org.apache.fineract.infrastructure.core.config.FineractProperties; import org.apache.fineract.infrastructure.core.domain.ActionContext; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; +import org.apache.fineract.infrastructure.core.exception.JobIsNotFoundOrNotEnabledException; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService; import org.apache.fineract.infrastructure.jobs.domain.ScheduledJobDetail; @@ -63,7 +64,11 @@ public class JobSchedulerServiceImpl implements ApplicationListener scheduledJobDetails = schedularWritePlatformService .retrieveAllJobs(fineractProperties.getNodeId()); for (final ScheduledJobDetail jobDetails : scheduledJobDetails) { - jobRegisterService.scheduleJob(jobDetails); + try { + jobRegisterService.scheduleJob(jobDetails); + } catch (JobIsNotFoundOrNotEnabledException e) { + log.warn("{}", e.getMessage()); + } jobDetails.setTriggerMisfired(false); schedularWritePlatformService.saveOrUpdate(jobDetails); } diff --git a/fineract-provider/src/main/resources/application.properties b/fineract-provider/src/main/resources/application.properties index 77b59ad1a..51325fa3b 100644 --- a/fineract-provider/src/main/resources/application.properties +++ b/fineract-provider/src/main/resources/application.properties @@ -60,6 +60,7 @@ fineract.correlation.enabled=${FINERACT_LOGGING_HTTP_CORRELATION_ID_ENABLED:fals fineract.correlation.header-name=${FINERACT_LOGGING_HTTP_CORRELATION_ID_HEADER_NAME:X-Correlation-ID} fineract.job.stuck-retry-threshold=${FINERACT_JOB_STUCK_RETRY_THRESHOLD:5} +fineract.job.loan-cob-enabled=${FINERACT_JOB_LOAN_COB_ENABLED:true} fineract.partitioned-job.partitioned-job-properties[0].job-name=LOAN_COB fineract.partitioned-job.partitioned-job-properties[0].chunk-size=${LOAN_COB_CHUNK_SIZE:100} diff --git a/fineract-provider/src/test/java/org/apache/fineract/cob/conditions/LoanCOBEnabledConditionTest.java b/fineract-provider/src/test/java/org/apache/fineract/cob/conditions/LoanCOBEnabledConditionTest.java new file mode 100644 index 000000000..6c4004a73 --- /dev/null +++ b/fineract-provider/src/test/java/org/apache/fineract/cob/conditions/LoanCOBEnabledConditionTest.java @@ -0,0 +1,67 @@ +/** + * 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.cob.conditions; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.mock.env.MockEnvironment; + +@ExtendWith(MockitoExtension.class) +class LoanCOBEnabledConditionTest { + + @Mock + private ConditionContext conditionContext; + + @Mock + private AnnotatedTypeMetadata metadata; + + private MockEnvironment environment; + + @InjectMocks + private LoanCOBEnabledCondition testObj = new LoanCOBEnabledCondition(); + + @BeforeEach + public void setUp() { + environment = new MockEnvironment(); + given(conditionContext.getEnvironment()).willReturn(environment); + } + + @Test + public void testMatchesShouldReturnFalseWhenLoanCobIsDisabled() { + environment.withProperty("fineract.job.loan-cob-enabled", "false"); + boolean result = testObj.matches(conditionContext, metadata); + assertThat(result).isFalse(); + } + + @Test + public void testMatchesShouldReturnTrueWhenLoanCobIsEnabled() { + environment.withProperty("fineract.job.loan-cob-enabled", "true"); + boolean result = testObj.matches(conditionContext, metadata); + assertThat(result).isTrue(); + } +} diff --git a/fineract-provider/src/test/java/org/apache/fineract/cob/conditions/LoanCOBManagerConditionTest.java b/fineract-provider/src/test/java/org/apache/fineract/cob/conditions/LoanCOBManagerConditionTest.java new file mode 100644 index 000000000..ec048210e --- /dev/null +++ b/fineract-provider/src/test/java/org/apache/fineract/cob/conditions/LoanCOBManagerConditionTest.java @@ -0,0 +1,77 @@ +/** + * 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.cob.conditions; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.mock.env.MockEnvironment; + +@ExtendWith(MockitoExtension.class) +class LoanCOBManagerConditionTest { + + @Mock + private ConditionContext conditionContext; + + @Mock + private AnnotatedTypeMetadata metadata; + + private MockEnvironment environment; + + @InjectMocks + private LoanCOBManagerCondition testObj = new LoanCOBManagerCondition(); + + @BeforeEach + public void setUp() { + environment = new MockEnvironment(); + given(conditionContext.getEnvironment()).willReturn(environment); + } + + @Test + public void testMatchesShouldReturnFalseWhenLoanCobIsDisabledAndManager() { + environment.withProperty("fineract.job.loan-cob-enabled", "false"); + environment.withProperty("fineract.mode.batch-manager-enabled", "true"); + boolean result = testObj.matches(conditionContext, metadata); + assertThat(result).isFalse(); + } + + @Test + public void testMatchesShouldReturnFalseWhenLoanCobIsEnabledAndNotManager() { + environment.withProperty("fineract.job.loan-cob-enabled", "true"); + environment.withProperty("fineract.mode.batch-manager-enabled", "false"); + boolean result = testObj.matches(conditionContext, metadata); + assertThat(result).isFalse(); + } + + @Test + public void testMatchesShouldReturnTrueWhenLoanCobIsEnabledAndManager() { + environment.withProperty("fineract.job.loan-cob-enabled", "true"); + environment.withProperty("fineract.mode.batch-manager-enabled", "true"); + boolean result = testObj.matches(conditionContext, metadata); + assertThat(result).isTrue(); + } +} diff --git a/fineract-provider/src/test/java/org/apache/fineract/cob/conditions/LoanCOBWorkerConditionTest.java b/fineract-provider/src/test/java/org/apache/fineract/cob/conditions/LoanCOBWorkerConditionTest.java new file mode 100644 index 000000000..1a9385d73 --- /dev/null +++ b/fineract-provider/src/test/java/org/apache/fineract/cob/conditions/LoanCOBWorkerConditionTest.java @@ -0,0 +1,77 @@ +/** + * 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.cob.conditions; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.mock.env.MockEnvironment; + +@ExtendWith(MockitoExtension.class) +class LoanCOBWorkerConditionTest { + + @Mock + private ConditionContext conditionContext; + + @Mock + private AnnotatedTypeMetadata metadata; + + private MockEnvironment environment; + + @InjectMocks + private LoanCOBWorkerCondition testObj = new LoanCOBWorkerCondition(); + + @BeforeEach + public void setUp() { + environment = new MockEnvironment(); + given(conditionContext.getEnvironment()).willReturn(environment); + } + + @Test + public void testMatchesShouldReturnFalseWhenLoanCobIsDisabledAndWorker() { + environment.withProperty("fineract.job.loan-cob-enabled", "false"); + environment.withProperty("fineract.mode.batch-worker-enabled", "true"); + boolean result = testObj.matches(conditionContext, metadata); + assertThat(result).isFalse(); + } + + @Test + public void testMatchesShouldReturnFalseWhenLoanCobIsEnabledAndNotWorker() { + environment.withProperty("fineract.job.loan-cob-enabled", "true"); + environment.withProperty("fineract.mode.batch-worker-enabled", "false"); + boolean result = testObj.matches(conditionContext, metadata); + assertThat(result).isFalse(); + } + + @Test + public void testMatchesShouldReturnTrueWhenLoanCobIsEnabledAndWorker() { + environment.withProperty("fineract.job.loan-cob-enabled", "true"); + environment.withProperty("fineract.mode.batch-worker-enabled", "true"); + boolean result = testObj.matches(conditionContext, metadata); + assertThat(result).isTrue(); + } +} diff --git a/fineract-provider/src/test/resources/application-test.properties b/fineract-provider/src/test/resources/application-test.properties index caa5ff6b4..28e79e287 100644 --- a/fineract-provider/src/test/resources/application-test.properties +++ b/fineract-provider/src/test/resources/application-test.properties @@ -87,6 +87,7 @@ fineract.report.export.s3.enabled=${FINERACT_REPORT_EXPORT_S3_ENABLED:false} fineract.jpa.statementLoggingEnabled=${FINERACT_STATEMENT_LOGGING_ENABLED:false} +fineract.job.loan-cob-enabled=${FINERACT_JOB_LOAN_COB_ENABLED:true} fineract.sampling.enabled=false fineract.sampling.sampledClasses=