From 0587dd95e36a70e31c1fc1306e2adfbfd37a723e Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Tue, 24 Dec 2024 15:06:20 +0400 Subject: [PATCH 01/24] [MODEXPS-273] Improve logging for job launching process --- .../dew/service/JobCommandsReceiverService.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/folio/dew/service/JobCommandsReceiverService.java b/src/main/java/org/folio/dew/service/JobCommandsReceiverService.java index fbc8fe0c1..240f9c53d 100644 --- a/src/main/java/org/folio/dew/service/JobCommandsReceiverService.java +++ b/src/main/java/org/folio/dew/service/JobCommandsReceiverService.java @@ -113,12 +113,16 @@ public void receiveStartJobCommand(@Payload JobCommand jobCommand, @Headers Map< } } - var jobLaunchRequest = - new JobLaunchRequest( - jobMap.get(resolveJobKey(jobCommand)), - jobCommand.getJobParameters()); - - exportJobManagerSync.launchJob(jobLaunchRequest); + var jobKey = resolveJobKey(jobCommand); + log.info("receiveStartJobCommand:: Resolving job with key: '{}' for command: '{}'", jobKey, jobCommand.getId()); + var job = jobMap.get(jobKey); + + if (job != null) { + log.info("receiveStartJobCommand:: Job resolved: '{}', launching...", job.getName()); + exportJobManagerSync.launchJob(new JobLaunchRequest(job, jobCommand.getJobParameters())); + } else { + log.error("Job with key '{}' not found for command: '{}'", jobKey, jobCommand.getId()); + } } catch (Exception e) { log.error(e.toString(), e); From 563994cd94afb3077839d541bbfb1e3c1a6ab088 Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Tue, 24 Dec 2024 15:55:21 +0400 Subject: [PATCH 02/24] [MODEXPS-273] Improve validation logic for acq export configs --- .../jobs/MapToEdifactClaimsTasklet.java | 25 ++++++++++++++++--- .../jobs/MapToEdifactOrdersTasklet.java | 15 ++++++++++- .../edifact/jobs/MapToEdifactTasklet.java | 11 +------- .../edifact/utils/ExportConfigFields.java | 21 ++++++++++++++++ .../edifact/utils/ExportUtils.java | 7 ++++++ 5 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportConfigFields.java diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java index 23c87ad54..1fce227f4 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java @@ -1,9 +1,18 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.CLAIM_PIECE_IDS; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.FILE_FORMAT; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.INTEGRATION_TYPE; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.LIB_EDI_TYPE; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.TRANSMISSION_METHOD; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.VENDOR_EDI_TYPE; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportUtils.validateField; import static org.folio.dew.utils.QueryUtils.convertIdsToCqlQuery; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; import org.apache.commons.collections4.CollectionUtils; import org.folio.dew.batch.acquisitions.edifact.mapper.ExportResourceMapper; @@ -22,7 +31,6 @@ @StepScope public class MapToEdifactClaimsTasklet extends MapToEdifactTasklet { - public static final String CLAIM_PIECE_IDS = "claimPieceIds"; private final ExportResourceMapper edifactMapper; private final ExportResourceMapper csvMapper; @@ -43,9 +51,18 @@ protected ExportResourceMapper getExportResourceMapper(VendorEdiOrdersExportConf @Override protected List getExportConfigMissingFields(VendorEdiOrdersExportConfig ediOrdersExportConfig) { - return CollectionUtils.isEmpty(ediOrdersExportConfig.getClaimPieceIds()) - ? List.of(CLAIM_PIECE_IDS) - : List.of(); + List missingFields = new ArrayList<>(); + validateField(INTEGRATION_TYPE.getName(), ediOrdersExportConfig.getIntegrationType(), Objects::nonNull, missingFields); + validateField(TRANSMISSION_METHOD.getName(), ediOrdersExportConfig.getTransmissionMethod(), Objects::nonNull, missingFields); + validateField(FILE_FORMAT.getName(), ediOrdersExportConfig.getFileFormat(), Objects::nonNull, missingFields); + validateField(CLAIM_PIECE_IDS.getName(), ediOrdersExportConfig.getClaimPieceIds(), CollectionUtils::isNotEmpty, missingFields); + + if (ediOrdersExportConfig.getFileFormat() == VendorEdiOrdersExportConfig.FileFormatEnum.EDI) { + var ediConfig = ediOrdersExportConfig.getEdiConfig(); + validateField(LIB_EDI_TYPE.getName(), ediConfig.getLibEdiType(), Objects::nonNull, missingFields); + validateField(VENDOR_EDI_TYPE.getName(), ediConfig.getVendorEdiType(), Objects::nonNull, missingFields); + } + return missingFields; } @Override diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java index 0aee36e78..84377398f 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java @@ -1,10 +1,16 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.LIB_EDI_CODE; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.LIB_EDI_TYPE; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.VENDOR_EDI_CODE; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.VENDOR_EDI_TYPE; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportUtils.validateField; import static org.folio.dew.utils.QueryUtils.combineCqlExpressions; import static org.folio.dew.utils.QueryUtils.convertFieldListToEnclosedCqlQuery; import static org.folio.dew.utils.QueryUtils.getCqlExpressionForFieldNullValue; import static org.folio.dew.utils.QueryUtils.negateQuery; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -13,6 +19,7 @@ import java.util.stream.Collectors; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.folio.dew.batch.acquisitions.edifact.mapper.ExportResourceMapper; import org.folio.dew.batch.acquisitions.edifact.services.OrdersService; import org.folio.dew.client.DataExportSpringClient; @@ -46,7 +53,13 @@ public MapToEdifactOrdersTasklet(ObjectMapper ediObjectMapper, OrdersService ord @Override protected List getExportConfigMissingFields(VendorEdiOrdersExportConfig ediOrdersExportConfig) { - return List.of(); + List missingFields = new ArrayList<>(); + var ediConfig = ediOrdersExportConfig.getEdiConfig(); + validateField(LIB_EDI_TYPE.getName(), ediConfig.getLibEdiType(), Objects::nonNull, missingFields); + validateField(LIB_EDI_CODE.getName(), ediConfig.getLibEdiCode(), StringUtils::isNotBlank, missingFields); + validateField(VENDOR_EDI_TYPE.getName(), ediConfig.getVendorEdiType(), Objects::nonNull, missingFields); + validateField(VENDOR_EDI_CODE.getName(), ediConfig.getVendorEdiCode(), StringUtils::isNotBlank, missingFields); + return missingFields; } @Override diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java index 7f956074f..9f6b08b73 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java @@ -61,18 +61,9 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon } private void validateEdiExportConfig(VendorEdiOrdersExportConfig ediExportConfig) { - var ediConfig = ediExportConfig.getEdiConfig(); - Optional port = Optional.ofNullable(ediExportConfig.getEdiFtp().getFtpPort()); - - if (StringUtils.isEmpty(ediConfig.getLibEdiCode()) || ediConfig.getLibEdiType() == null - || StringUtils.isEmpty(ediConfig.getVendorEdiCode()) || ediConfig.getVendorEdiType() == null) { - throw new EdifactException("Export configuration is incomplete, missing library EDI code/Vendor EDI code"); - } - - if (port.isEmpty()) { + if (ediExportConfig.getEdiFtp().getFtpPort() == null) { throw new EdifactException("Export configuration is incomplete, missing FTP/SFTP Port"); } - var missingFields = getExportConfigMissingFields(ediExportConfig); if (!missingFields.isEmpty()) { throw new EdifactException("Export configuration is incomplete, missing required fields: %s".formatted(missingFields)); diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportConfigFields.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportConfigFields.java new file mode 100644 index 000000000..b80ee9415 --- /dev/null +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportConfigFields.java @@ -0,0 +1,21 @@ +package org.folio.dew.batch.acquisitions.edifact.utils; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum ExportConfigFields { + + LIB_EDI_TYPE("libEdiType"), + LIB_EDI_CODE("libEdiCode"), + VENDOR_EDI_TYPE("vendorEdiType"), + VENDOR_EDI_CODE("vendorEdiCode"), + INTEGRATION_TYPE("integrationType"), + TRANSMISSION_METHOD("transmissionMethod"), + FILE_FORMAT("fileFormat"), + CLAIM_PIECE_IDS("claimPieceIds"); + + private final String name; + +} diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportUtils.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportUtils.java index 03b05d55d..881d62378 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportUtils.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportUtils.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.function.Predicate; import org.folio.dew.domain.dto.CompositePoLine; import org.folio.dew.domain.dto.ReferenceNumberItem; @@ -39,4 +40,10 @@ public static String getVendorAccountNumber(CompositePoLine poLine) { .orElse(null); } + public static void validateField(String field, T value, Predicate validator, List missingFields) { + if (!validator.test(value)) { + missingFields.add(field); + } + } + } From 965be52fb773d5890aa3838e70d97aa072e7b0c7 Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Tue, 24 Dec 2024 16:05:34 +0400 Subject: [PATCH 03/24] [MODEXPS-273] Fix failing test --- .../jobs/MapToEdifactOrderTaskletTest.java | 16 ++++++++++++++++ .../jobs/MapToEdifactTaskletAbstractTest.java | 12 ------------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrderTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrderTaskletTest.java index 0e94b744b..4b003b4c7 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrderTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrderTaskletTest.java @@ -1,6 +1,8 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; +import static org.assertj.core.api.Assertions.assertThat; import static org.folio.dew.utils.TestUtils.getMockData; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyString; @@ -8,6 +10,7 @@ import static org.mockito.Mockito.verify; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import org.assertj.core.api.Assertions; @@ -18,6 +21,7 @@ import org.folio.dew.domain.dto.PurchaseOrderCollection; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; @@ -31,6 +35,7 @@ class MapToEdifactOrderTaskletTest extends MapToEdifactTaskletAbstractTest { private static final String DATA_EXPORT_CONFIGS_PATH = "edifact/dataExportConfigs.json"; + private static final String SAMPLE_EDI_ORDERS_EXPORT_MISSING_FIELDS = "edifact/edifactOrdersExportWithoutRequiredFields.json"; @Autowired Job edifactOrdersExportJob; @@ -121,6 +126,17 @@ void testEdifactOrdersExportDefaultConfigWithTwoExportConfigs() throws Exception verify(ordersService).getPurchaseOrdersByIds(anyList()); } + @Test + void testEdifactOrdersExportMissingRequiredFields() throws Exception { + JobLauncherTestUtils testLauncher = createTestLauncher(edifactExportJob); + JobExecution jobExecution = testLauncher.launchStep(MAP_TO_EDIFACT_STEP, getJobParameters(getEdifactExportConfig(SAMPLE_EDI_ORDERS_EXPORT_MISSING_FIELDS))); + var status = new ArrayList<>(jobExecution.getStepExecutions()).get(0).getStatus(); + + assertEquals(BatchStatus.FAILED, status); + assertThat(jobExecution.getExitStatus().getExitCode()).isEqualTo(ExitStatus.FAILED.getExitCode()); + assertThat(jobExecution.getExitStatus().getExitDescription()).contains("Export configuration is incomplete, missing required fields: [libEdiCode, vendorEdiType]"); + } + protected ObjectNode getEdifactExportConfig(String path, boolean isDefaultConfig) throws IOException { return getEdifactExportConfig(path).put("isDefaultConfig", isDefaultConfig); } diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java index 530d1c74d..fe79fc0d9 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java @@ -39,7 +39,6 @@ abstract class MapToEdifactTaskletAbstractTest extends BaseBatchTest { protected static final String MAP_TO_EDIFACT_STEP = "mapToEdifactStep"; protected static final String SAMPLE_EDI_ORDERS_EXPORT = "edifact/edifactOrdersExport.json"; - private static final String SAMPLE_EDI_ORDERS_EXPORT_MISSING_FIELDS = "edifact/edifactOrdersExportWithoutRequiredFields.json"; private static final String SAMPLE_EDI_ORDERS_EXPORT_MISSING_PORT = "edifact/edifactOrdersExportWithoutPort.json"; @MockBean @@ -53,17 +52,6 @@ abstract class MapToEdifactTaskletAbstractTest extends BaseBatchTest { protected ObjectMapper objectMapper; protected Job edifactExportJob; - @Test - void testEdifactExportMissingRequiredFields() throws Exception { - JobLauncherTestUtils testLauncher = createTestLauncher(edifactExportJob); - JobExecution jobExecution = testLauncher.launchStep(MAP_TO_EDIFACT_STEP, getJobParameters(getEdifactExportConfig(SAMPLE_EDI_ORDERS_EXPORT_MISSING_FIELDS))); - var status = new ArrayList<>(jobExecution.getStepExecutions()).get(0).getStatus(); - - assertEquals(BatchStatus.FAILED, status); - assertThat(jobExecution.getExitStatus().getExitCode()).isEqualTo(ExitStatus.FAILED.getExitCode()); - assertThat(jobExecution.getExitStatus().getExitDescription()).contains("Export configuration is incomplete, missing library EDI code/Vendor EDI code"); - } - @Test void testEdifactExportMissingFtpPort() throws Exception { JobLauncherTestUtils testLauncher = createTestLauncher(edifactExportJob); From 538c0744024dccad8a14168eebd32143873d36ab Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Tue, 24 Dec 2024 16:05:34 +0400 Subject: [PATCH 04/24] [MODEXPS-273] Fix failing test --- .../jobs/MapToEdifactClaimsTaskletTest.java | 10 +++++++++- .../jobs/MapToEdifactOrderTaskletTest.java | 16 ++++++++++++++++ .../jobs/MapToEdifactTaskletAbstractTest.java | 12 ------------ 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java index 7fcc88db0..5c46c9b69 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java @@ -1,6 +1,11 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; import static org.assertj.core.api.Assertions.assertThat; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.CLAIM_PIECE_IDS; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.INTEGRATION_TYPE; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.TRANSMISSION_METHOD; +import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.CLAIMING; +import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FTP; import static org.folio.dew.utils.QueryUtils.convertIdsToCqlQuery; import static org.folio.dew.utils.TestUtils.getMockData; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -20,6 +25,7 @@ import org.folio.dew.domain.dto.PoLineCollection; import org.folio.dew.domain.dto.PurchaseOrder; import org.folio.dew.domain.dto.PurchaseOrderCollection; +import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; @@ -110,7 +116,9 @@ protected ObjectNode getEdifactExportConfig(String path) throws IOException { protected ObjectNode getEdifactExportConfig(String path, List pieceIds) throws IOException { var exportConfig = super.getEdifactExportConfig(path); - var arr = exportConfig.putArray("claimPieceIds"); + exportConfig.put(INTEGRATION_TYPE.getName(), CLAIMING.getValue()); + exportConfig.put(TRANSMISSION_METHOD.getName(), FTP.getValue()); + var arr = exportConfig.putArray(CLAIM_PIECE_IDS.getName()); pieceIds.forEach(arr::add); return exportConfig; } diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrderTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrderTaskletTest.java index 0e94b744b..4b003b4c7 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrderTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrderTaskletTest.java @@ -1,6 +1,8 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; +import static org.assertj.core.api.Assertions.assertThat; import static org.folio.dew.utils.TestUtils.getMockData; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyString; @@ -8,6 +10,7 @@ import static org.mockito.Mockito.verify; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import org.assertj.core.api.Assertions; @@ -18,6 +21,7 @@ import org.folio.dew.domain.dto.PurchaseOrderCollection; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; @@ -31,6 +35,7 @@ class MapToEdifactOrderTaskletTest extends MapToEdifactTaskletAbstractTest { private static final String DATA_EXPORT_CONFIGS_PATH = "edifact/dataExportConfigs.json"; + private static final String SAMPLE_EDI_ORDERS_EXPORT_MISSING_FIELDS = "edifact/edifactOrdersExportWithoutRequiredFields.json"; @Autowired Job edifactOrdersExportJob; @@ -121,6 +126,17 @@ void testEdifactOrdersExportDefaultConfigWithTwoExportConfigs() throws Exception verify(ordersService).getPurchaseOrdersByIds(anyList()); } + @Test + void testEdifactOrdersExportMissingRequiredFields() throws Exception { + JobLauncherTestUtils testLauncher = createTestLauncher(edifactExportJob); + JobExecution jobExecution = testLauncher.launchStep(MAP_TO_EDIFACT_STEP, getJobParameters(getEdifactExportConfig(SAMPLE_EDI_ORDERS_EXPORT_MISSING_FIELDS))); + var status = new ArrayList<>(jobExecution.getStepExecutions()).get(0).getStatus(); + + assertEquals(BatchStatus.FAILED, status); + assertThat(jobExecution.getExitStatus().getExitCode()).isEqualTo(ExitStatus.FAILED.getExitCode()); + assertThat(jobExecution.getExitStatus().getExitDescription()).contains("Export configuration is incomplete, missing required fields: [libEdiCode, vendorEdiType]"); + } + protected ObjectNode getEdifactExportConfig(String path, boolean isDefaultConfig) throws IOException { return getEdifactExportConfig(path).put("isDefaultConfig", isDefaultConfig); } diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java index 530d1c74d..fe79fc0d9 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java @@ -39,7 +39,6 @@ abstract class MapToEdifactTaskletAbstractTest extends BaseBatchTest { protected static final String MAP_TO_EDIFACT_STEP = "mapToEdifactStep"; protected static final String SAMPLE_EDI_ORDERS_EXPORT = "edifact/edifactOrdersExport.json"; - private static final String SAMPLE_EDI_ORDERS_EXPORT_MISSING_FIELDS = "edifact/edifactOrdersExportWithoutRequiredFields.json"; private static final String SAMPLE_EDI_ORDERS_EXPORT_MISSING_PORT = "edifact/edifactOrdersExportWithoutPort.json"; @MockBean @@ -53,17 +52,6 @@ abstract class MapToEdifactTaskletAbstractTest extends BaseBatchTest { protected ObjectMapper objectMapper; protected Job edifactExportJob; - @Test - void testEdifactExportMissingRequiredFields() throws Exception { - JobLauncherTestUtils testLauncher = createTestLauncher(edifactExportJob); - JobExecution jobExecution = testLauncher.launchStep(MAP_TO_EDIFACT_STEP, getJobParameters(getEdifactExportConfig(SAMPLE_EDI_ORDERS_EXPORT_MISSING_FIELDS))); - var status = new ArrayList<>(jobExecution.getStepExecutions()).get(0).getStatus(); - - assertEquals(BatchStatus.FAILED, status); - assertThat(jobExecution.getExitStatus().getExitCode()).isEqualTo(ExitStatus.FAILED.getExitCode()); - assertThat(jobExecution.getExitStatus().getExitDescription()).contains("Export configuration is incomplete, missing library EDI code/Vendor EDI code"); - } - @Test void testEdifactExportMissingFtpPort() throws Exception { JobLauncherTestUtils testLauncher = createTestLauncher(edifactExportJob); From 79dcdbebdca9532dc7c2453711e6324f3b4cdcc8 Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Tue, 24 Dec 2024 17:05:02 +0400 Subject: [PATCH 05/24] [MODEXPS-273] Remove unused imports and fix ftp validation --- .../edifact/jobs/MapToEdifactTasklet.java | 16 ++++++++++++---- .../edifact/utils/ExportConfigFields.java | 8 +++++--- .../dew/service/JobCommandsReceiverService.java | 7 ------- .../jobs/MapToEdifactClaimsTaskletTest.java | 1 - 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java index 9f6b08b73..342826002 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java @@ -3,11 +3,15 @@ import static java.util.Objects.requireNonNullElse; import static java.util.stream.Collectors.groupingBy; import static org.folio.dew.batch.acquisitions.edifact.jobs.EdifactExportJobConfig.POL_MEM_KEY; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.FTP_PORT; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.SERVER_ADDRESS; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportUtils.validateField; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; +import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FTP; import java.util.List; import java.util.Map; -import java.util.Optional; +import java.util.Objects; import org.apache.commons.lang3.StringUtils; import org.folio.dew.batch.ExecutionContextUtils; @@ -61,10 +65,14 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon } private void validateEdiExportConfig(VendorEdiOrdersExportConfig ediExportConfig) { - if (ediExportConfig.getEdiFtp().getFtpPort() == null) { - throw new EdifactException("Export configuration is incomplete, missing FTP/SFTP Port"); - } var missingFields = getExportConfigMissingFields(ediExportConfig); + + if (ediExportConfig.getTransmissionMethod() == FTP) { + var ftpConfig = ediExportConfig.getEdiFtp(); + validateField(FTP_PORT.getName(), ftpConfig.getFtpPort(), Objects::nonNull, missingFields); + validateField(SERVER_ADDRESS.getName(), ftpConfig.getServerAddress(), StringUtils::isNotEmpty, missingFields); + } + if (!missingFields.isEmpty()) { throw new EdifactException("Export configuration is incomplete, missing required fields: %s".formatted(missingFields)); } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportConfigFields.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportConfigFields.java index b80ee9415..fdd10676e 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportConfigFields.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportConfigFields.java @@ -7,13 +7,15 @@ @Getter public enum ExportConfigFields { + INTEGRATION_TYPE("integrationType"), + TRANSMISSION_METHOD("transmissionMethod"), + FILE_FORMAT("fileFormat"), + FTP_PORT("ftpPort"), + SERVER_ADDRESS("serverAddress"), LIB_EDI_TYPE("libEdiType"), LIB_EDI_CODE("libEdiCode"), VENDOR_EDI_TYPE("vendorEdiType"), VENDOR_EDI_CODE("vendorEdiCode"), - INTEGRATION_TYPE("integrationType"), - TRANSMISSION_METHOD("transmissionMethod"), - FILE_FORMAT("fileFormat"), CLAIM_PIECE_IDS("claimPieceIds"); private final String name; diff --git a/src/main/java/org/folio/dew/service/JobCommandsReceiverService.java b/src/main/java/org/folio/dew/service/JobCommandsReceiverService.java index 240f9c53d..5bb283dff 100644 --- a/src/main/java/org/folio/dew/service/JobCommandsReceiverService.java +++ b/src/main/java/org/folio/dew/service/JobCommandsReceiverService.java @@ -1,16 +1,12 @@ package org.folio.dew.service; -import static java.util.Objects.nonNull; import static org.folio.dew.domain.dto.ExportType.BULK_EDIT_IDENTIFIERS; import static org.folio.dew.domain.dto.ExportType.BULK_EDIT_QUERY; import static org.folio.dew.domain.dto.ExportType.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.utils.Constants.BULKEDIT_DIR_NAME; -import static org.folio.dew.utils.Constants.CSV_EXTENSION; -import static org.folio.dew.utils.Constants.FILE_NAME; import static org.folio.dew.utils.Constants.getWorkingDirectory; import jakarta.annotation.PostConstruct; -import java.io.FileOutputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; @@ -23,7 +19,6 @@ import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; -import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import org.folio.de.entity.JobCommand; import org.folio.de.entity.JobCommandType; @@ -32,7 +27,6 @@ import org.folio.dew.client.SearchClient; import org.folio.dew.config.kafka.KafkaService; import org.folio.dew.domain.dto.JobParameterNames; -import org.folio.dew.error.FileOperationException; import org.folio.dew.repository.JobCommandRepository; import org.folio.dew.repository.LocalFilesStorage; import org.folio.dew.repository.RemoteFilesStorage; @@ -43,7 +37,6 @@ import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.integration.launch.JobLaunchRequest; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.io.InputStreamResource; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.messaging.handler.annotation.Headers; import org.springframework.messaging.handler.annotation.Payload; diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java index 5c46c9b69..7347cb515 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java @@ -25,7 +25,6 @@ import org.folio.dew.domain.dto.PoLineCollection; import org.folio.dew.domain.dto.PurchaseOrder; import org.folio.dew.domain.dto.PurchaseOrderCollection; -import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; From caace7bb9e8c61a4d9b148d10c1dab693e0f74cb Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Tue, 24 Dec 2024 17:26:44 +0400 Subject: [PATCH 06/24] [MODEXPS-273] Improve validation --- .../edifact/jobs/MapToEdifactClaimsTasklet.java | 9 ++------- .../acquisitions/edifact/jobs/MapToEdifactTasklet.java | 6 ++++++ .../edifact/jobs/MapToEdifactTaskletAbstractTest.java | 2 +- src/test/resources/edifact/edifactFTPOrdersExport.json | 3 +++ src/test/resources/edifact/edifactOrdersExport.json | 2 ++ .../edifact/edifactOrdersExportWithoutPort.json | 4 +++- .../edifactOrdersExportWithoutRequiredFields.json | 3 +++ 7 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java index 1fce227f4..67b9f45b2 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java @@ -1,12 +1,10 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.CLAIM_PIECE_IDS; -import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.FILE_FORMAT; -import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.INTEGRATION_TYPE; import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.LIB_EDI_TYPE; -import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.TRANSMISSION_METHOD; import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.VENDOR_EDI_TYPE; import static org.folio.dew.batch.acquisitions.edifact.utils.ExportUtils.validateField; +import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.FileFormatEnum.EDI; import static org.folio.dew.utils.QueryUtils.convertIdsToCqlQuery; import java.util.ArrayList; @@ -52,12 +50,9 @@ protected ExportResourceMapper getExportResourceMapper(VendorEdiOrdersExportConf @Override protected List getExportConfigMissingFields(VendorEdiOrdersExportConfig ediOrdersExportConfig) { List missingFields = new ArrayList<>(); - validateField(INTEGRATION_TYPE.getName(), ediOrdersExportConfig.getIntegrationType(), Objects::nonNull, missingFields); - validateField(TRANSMISSION_METHOD.getName(), ediOrdersExportConfig.getTransmissionMethod(), Objects::nonNull, missingFields); - validateField(FILE_FORMAT.getName(), ediOrdersExportConfig.getFileFormat(), Objects::nonNull, missingFields); validateField(CLAIM_PIECE_IDS.getName(), ediOrdersExportConfig.getClaimPieceIds(), CollectionUtils::isNotEmpty, missingFields); - if (ediOrdersExportConfig.getFileFormat() == VendorEdiOrdersExportConfig.FileFormatEnum.EDI) { + if (ediOrdersExportConfig.getFileFormat() == EDI) { var ediConfig = ediOrdersExportConfig.getEdiConfig(); validateField(LIB_EDI_TYPE.getName(), ediConfig.getLibEdiType(), Objects::nonNull, missingFields); validateField(VENDOR_EDI_TYPE.getName(), ediConfig.getVendorEdiType(), Objects::nonNull, missingFields); diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java index 342826002..26cc53696 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java @@ -3,8 +3,11 @@ import static java.util.Objects.requireNonNullElse; import static java.util.stream.Collectors.groupingBy; import static org.folio.dew.batch.acquisitions.edifact.jobs.EdifactExportJobConfig.POL_MEM_KEY; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.FILE_FORMAT; import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.FTP_PORT; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.INTEGRATION_TYPE; import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.SERVER_ADDRESS; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.TRANSMISSION_METHOD; import static org.folio.dew.batch.acquisitions.edifact.utils.ExportUtils.validateField; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FTP; @@ -66,6 +69,9 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon private void validateEdiExportConfig(VendorEdiOrdersExportConfig ediExportConfig) { var missingFields = getExportConfigMissingFields(ediExportConfig); + validateField(INTEGRATION_TYPE.getName(), ediExportConfig.getIntegrationType(), Objects::nonNull, missingFields); + validateField(TRANSMISSION_METHOD.getName(), ediExportConfig.getTransmissionMethod(), Objects::nonNull, missingFields); + validateField(FILE_FORMAT.getName(), ediExportConfig.getFileFormat(), Objects::nonNull, missingFields); if (ediExportConfig.getTransmissionMethod() == FTP) { var ftpConfig = ediExportConfig.getEdiFtp(); diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java index fe79fc0d9..515388600 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java @@ -60,7 +60,7 @@ void testEdifactExportMissingFtpPort() throws Exception { assertEquals(BatchStatus.FAILED, status); assertThat(jobExecution.getExitStatus().getExitCode()).isEqualTo(ExitStatus.FAILED.getExitCode()); - assertThat(jobExecution.getExitStatus().getExitDescription()).contains("Export configuration is incomplete, missing FTP/SFTP Port"); + assertThat(jobExecution.getExitStatus().getExitDescription()).contains("Export configuration is incomplete, missing required fields: [ftpPort, serverAddress]"); } @Test diff --git a/src/test/resources/edifact/edifactFTPOrdersExport.json b/src/test/resources/edifact/edifactFTPOrdersExport.json index 49ed96244..4b51c2943 100644 --- a/src/test/resources/edifact/edifactFTPOrdersExport.json +++ b/src/test/resources/edifact/edifactFTPOrdersExport.json @@ -2,6 +2,9 @@ "vendorId": "e54f0eb5-36c6-43c8-a219-dabbafb0176c", "configName": "EDIFACT 2", "configDescription": "EDI configuration for testing export", + "integrationType": "Ordering", + "transmissionMethod": "FTP", + "fileFormat": "EDI", "ediConfig": { "accountNoList": [ "BRXXXXX-01" diff --git a/src/test/resources/edifact/edifactOrdersExport.json b/src/test/resources/edifact/edifactOrdersExport.json index 4ac93e09c..70aaf2352 100644 --- a/src/test/resources/edifact/edifactOrdersExport.json +++ b/src/test/resources/edifact/edifactOrdersExport.json @@ -2,6 +2,8 @@ "vendorId": "d0fb5aa0-cdf1-11e8-a8d5-f2801f1b9fd1", "configName": "EDIFACT 1", "configDescription": "EDI configuration for testing export", + "integrationType": "Ordering", + "transmissionMethod": "FTP", "fileFormat": "EDI", "ediConfig": { "accountNoList": [ diff --git a/src/test/resources/edifact/edifactOrdersExportWithoutPort.json b/src/test/resources/edifact/edifactOrdersExportWithoutPort.json index 583f0b4ad..b76445191 100644 --- a/src/test/resources/edifact/edifactOrdersExportWithoutPort.json +++ b/src/test/resources/edifact/edifactOrdersExportWithoutPort.json @@ -2,6 +2,9 @@ "vendorId": "d0fb5aa0-cdf1-11e8-a8d5-f2801f1b9fd1", "configName": "EDIFACT 1", "configDescription": "EDI configuration for testing export", + "integrationType": "Ordering", + "transmissionMethod": "FTP", + "fileFormat": "EDI", "ediConfig": { "accountNoList": [ "BRXXXXX-01" @@ -27,7 +30,6 @@ "notes": "separate directories for EOCRs and cat records", "orderDirectory": "/uploads", "password": "12345", - "serverAddress": "sftp://random-address.com", "username": "user" }, "isDefaultConfig": false diff --git a/src/test/resources/edifact/edifactOrdersExportWithoutRequiredFields.json b/src/test/resources/edifact/edifactOrdersExportWithoutRequiredFields.json index 5df693a5b..91a10b38d 100644 --- a/src/test/resources/edifact/edifactOrdersExportWithoutRequiredFields.json +++ b/src/test/resources/edifact/edifactOrdersExportWithoutRequiredFields.json @@ -2,6 +2,9 @@ "vendorId": "d0fb5aa0-cdf1-11e8-a8d5-f2801f1b9fd1", "configName": "EDIFACT 1", "configDescription": "EDI configuration for testing export", + "integrationType": "Ordering", + "transmissionMethod": "FTP", + "fileFormat": "EDI", "ediConfig": { "accountNoList": [ "BRXXXXX-01" From 8d8611e11dc3269f9ecfbf6939d72708a708f5c7 Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Tue, 24 Dec 2024 18:27:53 +0400 Subject: [PATCH 07/24] [MODEXPS-273] Add job name param for claims export too --- .../org/folio/dew/service/JobCommandsReceiverService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/folio/dew/service/JobCommandsReceiverService.java b/src/main/java/org/folio/dew/service/JobCommandsReceiverService.java index 5bb283dff..7ad94ca38 100644 --- a/src/main/java/org/folio/dew/service/JobCommandsReceiverService.java +++ b/src/main/java/org/folio/dew/service/JobCommandsReceiverService.java @@ -2,6 +2,7 @@ import static org.folio.dew.domain.dto.ExportType.BULK_EDIT_IDENTIFIERS; import static org.folio.dew.domain.dto.ExportType.BULK_EDIT_QUERY; +import static org.folio.dew.domain.dto.ExportType.CLAIMS; import static org.folio.dew.domain.dto.ExportType.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.utils.Constants.BULKEDIT_DIR_NAME; import static org.folio.dew.utils.Constants.getWorkingDirectory; @@ -13,6 +14,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.UUID; @@ -145,7 +147,7 @@ private void prepareJobParameters(JobCommand jobCommand) { } private void addOrderExportSpecificParameters(JobCommand jobCommand, JobParametersBuilder paramsBuilder) { - if (jobCommand.getExportType().equals(EDIFACT_ORDERS_EXPORT)) { + if (jobCommand.getExportType() == EDIFACT_ORDERS_EXPORT || jobCommand.getExportType() == CLAIMS) { paramsBuilder.addString(JobParameterNames.JOB_NAME, jobCommand.getName(), JOB_PARAMETER_DEFAULT_IDENTIFYING_VALUE); } } From 04c1790b5a6bc96a32b712d85f3dfc6a56d7fbb6 Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Wed, 25 Dec 2024 14:44:04 +0400 Subject: [PATCH 08/24] [MODEXPS-273] Fetch pieces with Claim Sent status instead of Late --- .../acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java index 67b9f45b2..4799fde41 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java @@ -62,7 +62,7 @@ protected List getExportConfigMissingFields(VendorEdiOrdersExportConfig @Override protected ExportHolder buildEdifactExportHolder(ChunkContext chunkContext, VendorEdiOrdersExportConfig ediExportConfig, Map jobParameters) { - var pieces = ordersService.getPiecesByIdsAndReceivingStatus(ediExportConfig.getClaimPieceIds(), Piece.ReceivingStatusEnum.LATE); + var pieces = ordersService.getPiecesByIdsAndReceivingStatus(ediExportConfig.getClaimPieceIds(), Piece.ReceivingStatusEnum.CLAIM_SENT); if (pieces.isEmpty()) { throw new NotFoundException(Piece.class); } From 5bd434f8c28a36e45306d31add355dcc0c8ca92f Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Wed, 25 Dec 2024 14:54:05 +0400 Subject: [PATCH 09/24] [MODEXPS-273] Fix failing test --- .../edifact/jobs/MapToEdifactClaimsTaskletTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java index 7347cb515..63ad27f89 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java @@ -61,7 +61,7 @@ protected void setUp() { pieces = objectMapper.readValue(getMockData(SAMPLE_PIECES_PATH), PieceCollection.class).getPieces(); pieceIds = pieces.stream().map(Piece::getId).toList(); - doReturn(pieces).when(ordersService).getPiecesByIdsAndReceivingStatus(pieceIds, Piece.ReceivingStatusEnum.LATE); + doReturn(pieces).when(ordersService).getPiecesByIdsAndReceivingStatus(pieceIds, Piece.ReceivingStatusEnum.CLAIM_SENT); } @Test @@ -77,7 +77,7 @@ void testEdifactClaimsExport() throws Exception { JobExecution jobExecution = testLauncher.launchStep(MAP_TO_EDIFACT_STEP, getJobParameters(exportConfig)); assertThat(jobExecution.getExitStatus()).isEqualTo(ExitStatus.COMPLETED); - verify(ordersService).getPiecesByIdsAndReceivingStatus(pieceIds, Piece.ReceivingStatusEnum.LATE); + verify(ordersService).getPiecesByIdsAndReceivingStatus(pieceIds, Piece.ReceivingStatusEnum.CLAIM_SENT); verify(ordersService).getPoLinesByQuery(poLineQuery); verify(ordersService).getPurchaseOrdersByIds(anyList()); } @@ -85,14 +85,14 @@ void testEdifactClaimsExport() throws Exception { @Test void testEdifactClaimsExportNoPiecesFound() throws Exception { JobLauncherTestUtils testLauncher = createTestLauncher(edifactExportJob); - doReturn(List.of()).when(ordersService).getPiecesByIdsAndReceivingStatus(pieceIds, Piece.ReceivingStatusEnum.LATE); + doReturn(List.of()).when(ordersService).getPiecesByIdsAndReceivingStatus(pieceIds, Piece.ReceivingStatusEnum.CLAIM_SENT); var exportConfig = getEdifactExportConfig(SAMPLE_EDI_ORDERS_EXPORT, pieceIds); JobExecution jobExecution = testLauncher.launchStep(MAP_TO_EDIFACT_STEP, getJobParameters(exportConfig)); assertThat(jobExecution.getExitStatus().getExitCode()).isEqualTo(ExitStatus.FAILED.getExitCode()); assertThat(jobExecution.getExitStatus().getExitDescription()).contains("Entities not found: Piece"); - verify(ordersService).getPiecesByIdsAndReceivingStatus(pieceIds, Piece.ReceivingStatusEnum.LATE); + verify(ordersService).getPiecesByIdsAndReceivingStatus(pieceIds, Piece.ReceivingStatusEnum.CLAIM_SENT); } @Test From 9093da59aa7f450978794a51f94e6d3f0c21dc84 Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Wed, 25 Dec 2024 15:22:31 +0400 Subject: [PATCH 10/24] [MODEXPS-273] Skip FTP/Download step conditionally --- .../edifact/jobs/SaveToFileStorageTasklet.java | 10 ++++++++-- .../acquisitions/edifact/jobs/SaveToMinioTasklet.java | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java index 0e419b227..a0eddafe2 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java @@ -2,6 +2,7 @@ import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.JobParameterNames.UPLOADED_FILE_PATH; +import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FTP; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; @@ -40,9 +41,14 @@ public class SaveToFileStorageTasklet implements Tasklet { @Override @SneakyThrows public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) { - var stepExecution = chunkContext.getStepContext().getStepExecution(); var jobParameters = chunkContext.getStepContext().getJobParameters(); - var ediExportConfig = ediObjectMapper.readValue((String)jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); + var ediExportConfig = ediObjectMapper.readValue((String) jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); + if (ediExportConfig.getTransmissionMethod() != FTP) { + log.info("execute:: Transmission method is not FTP, skipping the step"); + return RepeatStatus.FINISHED; + } + + var stepExecution = chunkContext.getStepContext().getStepExecution(); var uploadedFilePath = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, UPLOADED_FILE_PATH); String host = ediExportConfig.getEdiFtp().getServerAddress().replace(SFTP_PROTOCOL, ""); diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java index 936457584..3bd1410c1 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java @@ -4,6 +4,7 @@ import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.JobParameterNames.OUTPUT_FILES_IN_STORAGE; import static org.folio.dew.domain.dto.JobParameterNames.UPLOADED_FILE_PATH; +import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FILE_DOWNLOAD; import static org.folio.dew.utils.Constants.EDIFACT_EXPORT_DIR_NAME; import static org.folio.dew.utils.Constants.getWorkingDirectory; @@ -52,9 +53,14 @@ public class SaveToMinioTasklet implements Tasklet { @SneakyThrows public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) { // retrieve parameters from job context - var stepExecution = chunkContext.getStepContext().getStepExecution(); var jobParameters = chunkContext.getStepContext().getJobParameters(); - var ediExportConfig = ediObjectMapper.readValue((String)jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); + var ediExportConfig = ediObjectMapper.readValue((String) jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); + if (ediExportConfig.getTransmissionMethod() != FILE_DOWNLOAD) { + log.info("execute:: Transmission method is not File Download, skipping the step"); + return RepeatStatus.FINISHED; + } + + var stepExecution = chunkContext.getStepContext().getStepExecution(); var edifactOrderAsString = (String) ExecutionContextUtils.getExecutionVariable(stepExecution,"edifactOrderAsString"); var fullFilePath = buildFullFilePath(ediExportConfig); From 195f41a2b524dd377296f6fe04f908f2a793696a Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Wed, 25 Dec 2024 16:24:20 +0400 Subject: [PATCH 11/24] [MODEXPS-273] Decouple ftp and file download steps --- .../jobs/MapToEdifactClaimsTasklet.java | 5 ++- .../jobs/MapToEdifactOrdersTasklet.java | 5 ++- .../edifact/jobs/MapToEdifactTasklet.java | 24 ++++++++--- .../jobs/SaveToFileStorageTasklet.java | 27 ++++++------ .../edifact/jobs/SaveToMinioTasklet.java | 43 ++++++------------- .../edifact/utils/ExportUtils.java | 11 +++++ .../dew/domain/dto/JobParameterNames.java | 1 + .../jobs/ExportHistoryTaskletTest.java | 13 +++--- .../jobs/MapToEdifactTaskletAbstractTest.java | 9 ++-- .../jobs/SaveToFileStorageTaskletTest.java | 10 +++-- .../jobs/SaveToMinioTaskletFailTest.java | 10 +++-- .../edifact/jobs/SaveToMinioTaskletTest.java | 12 +++--- 12 files changed, 95 insertions(+), 75 deletions(-) diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java index 4799fde41..6189b985c 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java @@ -15,6 +15,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.folio.dew.batch.acquisitions.edifact.mapper.ExportResourceMapper; import org.folio.dew.batch.acquisitions.edifact.services.OrdersService; +import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; import org.folio.dew.domain.dto.Piece; import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; import org.folio.dew.domain.dto.acquisitions.edifact.ExportHolder; @@ -32,9 +33,9 @@ public class MapToEdifactClaimsTasklet extends MapToEdifactTasklet { private final ExportResourceMapper edifactMapper; private final ExportResourceMapper csvMapper; - public MapToEdifactClaimsTasklet(ObjectMapper ediObjectMapper, OrdersService ordersService, + public MapToEdifactClaimsTasklet(ObjectMapper ediObjectMapper, OrganizationsService organizationsService, OrdersService ordersService, ExportResourceMapper edifactMapper, ExportResourceMapper csvMapper) { - super(ediObjectMapper, ordersService); + super(ediObjectMapper, organizationsService, ordersService); this.edifactMapper = edifactMapper; this.csvMapper = csvMapper; } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java index 84377398f..ac0d54c26 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java @@ -22,6 +22,7 @@ import org.apache.commons.lang3.StringUtils; import org.folio.dew.batch.acquisitions.edifact.mapper.ExportResourceMapper; import org.folio.dew.batch.acquisitions.edifact.services.OrdersService; +import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; import org.folio.dew.client.DataExportSpringClient; import org.folio.dew.domain.dto.ExportConfigCollection; import org.folio.dew.domain.dto.ExportType; @@ -43,10 +44,10 @@ public class MapToEdifactOrdersTasklet extends MapToEdifactTasklet { private final DataExportSpringClient dataExportSpringClient; private final ExportResourceMapper edifactMapper; - public MapToEdifactOrdersTasklet(ObjectMapper ediObjectMapper, OrdersService ordersService, + public MapToEdifactOrdersTasklet(ObjectMapper ediObjectMapper, OrganizationsService organizationsService, OrdersService ordersService, DataExportSpringClient dataExportSpringClient, ExportResourceMapper edifactMapper) { - super(ediObjectMapper, ordersService); + super(ediObjectMapper, organizationsService, ordersService); this.edifactMapper = edifactMapper; this.dataExportSpringClient = dataExportSpringClient; } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java index 26cc53696..f8ed22cf7 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java @@ -8,7 +8,10 @@ import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.INTEGRATION_TYPE; import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.SERVER_ADDRESS; import static org.folio.dew.batch.acquisitions.edifact.utils.ExportConfigFields.TRANSMISSION_METHOD; +import static org.folio.dew.batch.acquisitions.edifact.utils.ExportUtils.generateFileName; import static org.folio.dew.batch.acquisitions.edifact.utils.ExportUtils.validateField; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; +import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FTP; @@ -22,6 +25,7 @@ import org.folio.dew.batch.acquisitions.edifact.exceptions.EdifactException; import org.folio.dew.batch.acquisitions.edifact.mapper.ExportResourceMapper; import org.folio.dew.batch.acquisitions.edifact.services.OrdersService; +import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; import org.folio.dew.domain.dto.CompositePoLine; import org.folio.dew.domain.dto.CompositePurchaseOrder; import org.folio.dew.domain.dto.JobParameterNames; @@ -47,13 +51,14 @@ public abstract class MapToEdifactTasklet implements Tasklet { private final ObjectMapper ediObjectMapper; + private final OrganizationsService organizationsService; protected final OrdersService ordersService; @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { log.info("execute:: Executing MapToEdifactTasklet with job: {}", chunkContext.getStepContext().getJobName()); var jobParameters = chunkContext.getStepContext().getJobParameters(); - var ediExportConfig = ediObjectMapper.readValue((String)jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); + var ediExportConfig = ediObjectMapper.readValue((String) jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); validateEdiExportConfig(ediExportConfig); var holder = buildEdifactExportHolder(chunkContext, ediExportConfig, jobParameters); @@ -62,8 +67,10 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon String jobName = jobParameters.get(JobParameterNames.JOB_NAME).toString(); var edifactStringResult = getExportResourceMapper(ediExportConfig).convertForExport(holder.orders(), holder.pieces(), ediExportConfig, jobName); - // save edifact file content in memory - ExecutionContextUtils.addToJobExecutionContext(chunkContext.getStepContext().getStepExecution(), "edifactOrderAsString", edifactStringResult, ""); + // save edifact file content and name in memory + var stepExecution = chunkContext.getStepContext().getStepExecution(); + ExecutionContextUtils.addToJobExecutionContext(stepExecution, ACQ_EXPORT_FILE, edifactStringResult, ""); + ExecutionContextUtils.addToJobExecutionContext(stepExecution, EDIFACT_FILE_NAME, getFileName(ediExportConfig), ""); return RepeatStatus.FINISHED; } @@ -84,7 +91,7 @@ private void validateEdiExportConfig(VendorEdiOrdersExportConfig ediExportConfig } } -protected List getCompositeOrders(String poLineQuery) { + protected List getCompositeOrders(String poLineQuery) { var poLines = ordersService.getPoLinesByQuery(poLineQuery); var orderIds = poLines.stream() .map(PoLine::getPurchaseOrderId) @@ -104,7 +111,7 @@ protected void persistPoLineIds(ChunkContext chunkContext, List ord.getCompositePoLines().stream()) .map(CompositePoLine::getId) .toList(); - ExecutionContextUtils.addToJobExecutionContext(chunkContext.getStepContext().getStepExecution(), POL_MEM_KEY, ediObjectMapper.writeValueAsString(poLineIds),""); + ExecutionContextUtils.addToJobExecutionContext(chunkContext.getStepContext().getStepExecution(), POL_MEM_KEY, ediObjectMapper.writeValueAsString(poLineIds), ""); } private List assembleCompositeOrders(List orders, List poLines) { @@ -118,6 +125,13 @@ private List assembleCompositeOrders(List .toList(); } + private String getFileName(VendorEdiOrdersExportConfig ediExportConfig) { + var vendorName = organizationsService.getOrganizationById(ediExportConfig.getVendorId().toString()).get("code").asText(); + var configName = ediExportConfig.getConfigName(); + var fileFormat = ediExportConfig.getFileFormat(); + return generateFileName(vendorName, configName, fileFormat); + } + private T convertTo(Object value, Class c) { try { return ediObjectMapper.readValue(ediObjectMapper.writeValueAsString(value), c); diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java index a0eddafe2..bc71f6627 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java @@ -1,21 +1,21 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; +import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; -import static org.folio.dew.domain.dto.JobParameterNames.UPLOADED_FILE_PATH; import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FTP; -import org.apache.commons.io.FilenameUtils; +import java.nio.charset.StandardCharsets; + import org.apache.commons.lang3.StringUtils; import org.folio.dew.batch.ExecutionContextUtils; import org.folio.dew.batch.acquisitions.edifact.services.FTPStorageService; import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; -import org.folio.dew.repository.RemoteFilesStorage; import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; @@ -29,14 +29,11 @@ @StepScope @Log4j2 public class SaveToFileStorageTasklet implements Tasklet { - private final ObjectMapper ediObjectMapper; - private final FTPStorageService ftpStorageService; - - private final RemoteFilesStorage remoteFilesStorage; private static final String SFTP_PROTOCOL = "sftp://"; - @Value("#{jobParameters['edifactFileName']}") - private String edifactFileName; + + private final ObjectMapper ediObjectMapper; + private final FTPStorageService ftpStorageService; @Override @SneakyThrows @@ -48,16 +45,16 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon return RepeatStatus.FINISHED; } - var stepExecution = chunkContext.getStepContext().getStepExecution(); - var uploadedFilePath = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, UPLOADED_FILE_PATH); - String host = ediExportConfig.getEdiFtp().getServerAddress().replace(SFTP_PROTOCOL, ""); // skip ftp upload if address not specified if (StringUtils.isEmpty(host)) { return RepeatStatus.FINISHED; } - byte[] fileContent = remoteFilesStorage.readAllBytes(uploadedFilePath); - ftpStorageService.uploadToFtp(ediExportConfig, fileContent, FilenameUtils.getName(uploadedFilePath)); + + var stepExecution = chunkContext.getStepContext().getStepExecution(); + var fileName = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, EDIFACT_FILE_NAME); + var edifactOrderAsString = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, ACQ_EXPORT_FILE); + ftpStorageService.uploadToFtp(ediExportConfig, edifactOrderAsString.getBytes(StandardCharsets.UTF_8), fileName); return RepeatStatus.FINISHED; } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java index 3bd1410c1..a9dd569d8 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java @@ -1,26 +1,22 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.JobParameterNames.OUTPUT_FILES_IN_STORAGE; -import static org.folio.dew.domain.dto.JobParameterNames.UPLOADED_FILE_PATH; import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FILE_DOWNLOAD; import static org.folio.dew.utils.Constants.EDIFACT_EXPORT_DIR_NAME; import static org.folio.dew.utils.Constants.getWorkingDirectory; import java.nio.charset.StandardCharsets; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import org.apache.commons.io.FilenameUtils; import org.folio.dew.batch.ExecutionContextUtils; import org.folio.dew.batch.acquisitions.edifact.exceptions.EdifactException; -import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; import org.folio.dew.repository.RemoteFilesStorage; import org.folio.spring.FolioExecutionContext; import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.step.tasklet.Tasklet; @@ -39,12 +35,13 @@ @StepScope @Log4j2 public class SaveToMinioTasklet implements Tasklet { + + private static final String REMOTE_STORAGE_ERROR_MESSAGE = "Failed to save edifact file to remote storage"; + private static final String UPLOADED_PATH_TEMPLATE = "%s%s/%s"; + private final RemoteFilesStorage remoteFilesStorage; - private final OrganizationsService organizationsService; private final FolioExecutionContext folioExecutionContext; private final ObjectMapper ediObjectMapper; - private final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); - private static final String REMOTE_STORAGE_ERROR_MESSAGE = "Failed to save edifact file to remote storage"; @Value("${spring.application.name}") protected String springApplicationName; @@ -61,39 +58,25 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon } var stepExecution = chunkContext.getStepContext().getStepExecution(); - var edifactOrderAsString = (String) ExecutionContextUtils.getExecutionVariable(stepExecution,"edifactOrderAsString"); - - var fullFilePath = buildFullFilePath(ediExportConfig); - String edifactFileName = FilenameUtils.getName(fullFilePath); + var edifactOrderAsString = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, ACQ_EXPORT_FILE); + var fullFilePath = buildFullFilePath(stepExecution); String uploadedFilePath; try { uploadedFilePath = remoteFilesStorage.write(fullFilePath, edifactOrderAsString.getBytes(StandardCharsets.UTF_8)); - } - catch (Exception e) { + } catch (Exception e) { log.error(REMOTE_STORAGE_ERROR_MESSAGE, e); throw new EdifactException(REMOTE_STORAGE_ERROR_MESSAGE); } - ExecutionContextUtils.addToJobExecutionContext(contribution.getStepExecution(), UPLOADED_FILE_PATH, fullFilePath, ""); - ExecutionContextUtils.addToJobExecutionContext(contribution.getStepExecution(), EDIFACT_FILE_NAME, edifactFileName, ""); ExecutionContextUtils.addToJobExecutionContext(contribution.getStepExecution(), OUTPUT_FILES_IN_STORAGE, uploadedFilePath, ";"); return RepeatStatus.FINISHED; } - private String generateFileName(VendorEdiOrdersExportConfig ediExportConfig) { - var vendorId = ediExportConfig.getVendorId().toString(); - var vendor = organizationsService.getOrganizationById(vendorId); - var vendorName = vendor.get("code").asText(); - var fileDate = dateFormat.format(new Date()); - // exclude restricted symbols after implementing naming convention feature - return vendorName + "_" + ediExportConfig.getConfigName() + "_" + fileDate + ".edi"; - } - - private String buildFullFilePath(VendorEdiOrdersExportConfig ediExportConfig) { + private String buildFullFilePath(StepExecution stepExecution) { var workDir = getWorkingDirectory(springApplicationName, EDIFACT_EXPORT_DIR_NAME); var tenantName = folioExecutionContext.getTenantId(); - var filename = generateFileName(ediExportConfig); - - return String.format("%s%s/%s", workDir, tenantName, filename); + var fileName = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, EDIFACT_FILE_NAME); + return UPLOADED_PATH_TEMPLATE.formatted(workDir, tenantName, fileName); } + } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportUtils.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportUtils.java index 881d62378..5df6ad760 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportUtils.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportUtils.java @@ -2,7 +2,10 @@ import static org.folio.dew.domain.dto.ReferenceNumberItem.RefNumberTypeEnum.ORDER_REFERENCE_NUMBER; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Optional; import java.util.function.Predicate; @@ -10,9 +13,13 @@ import org.folio.dew.domain.dto.CompositePoLine; import org.folio.dew.domain.dto.ReferenceNumberItem; import org.folio.dew.domain.dto.VendorDetail; +import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.FileFormatEnum; public class ExportUtils { + private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); + private static final String FILE_NAME_FORMAT = "%s_%s_%s.%s"; + private ExportUtils() { } public static List getVendorReferenceNumbers(CompositePoLine poLine) { @@ -46,4 +53,8 @@ public static void validateField(String field, T value, Predicate validat } } + public static String generateFileName(String vendorName, String configName, FileFormatEnum fileFormat) { + return FILE_NAME_FORMAT.formatted(vendorName, configName, DATE_FORMAT.format(new Date()), fileFormat.getValue().toLowerCase()); // Enum being EDI or CSV + } + } diff --git a/src/main/java/org/folio/dew/domain/dto/JobParameterNames.java b/src/main/java/org/folio/dew/domain/dto/JobParameterNames.java index d07803595..d3c41b8ad 100644 --- a/src/main/java/org/folio/dew/domain/dto/JobParameterNames.java +++ b/src/main/java/org/folio/dew/domain/dto/JobParameterNames.java @@ -17,6 +17,7 @@ public class JobParameterNames { public static final String PREVIEW_FILE_NAME = "previewFileName"; public static final String UPLOADED_FILE_PATH = "uploadedFilePath"; public static final String EDIFACT_FILE_NAME = "edifactFileName"; + public static final String ACQ_EXPORT_FILE = "acqExportFile"; public static final String E_HOLDINGS_FILE_NAME = "eHoldingsFileName"; public static final String CIRCULATION_LOG_FILE_NAME = "circulationLogFileName"; public static final String AUTHORITY_CONTROL_FILE_NAME = "authorityControlFileName"; diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTaskletTest.java index db9a1e071..51dcf13db 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTaskletTest.java @@ -20,6 +20,10 @@ import java.util.ArrayList; import java.util.UUID; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; +import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; +import static org.folio.dew.domain.dto.JobParameterNames.JOB_ID; +import static org.folio.dew.domain.dto.JobParameterNames.JOB_NAME; import static org.folio.dew.utils.TestUtils.getMockData; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.anyString; @@ -72,11 +76,10 @@ protected ExecutionContext getExecutionContext() { private JobParameters getJobParameters() throws IOException { JobParametersBuilder paramsBuilder = new JobParametersBuilder(); - paramsBuilder.addString("edifactOrdersExport", getMockData("edifact/edifactOrdersExport.json")); - paramsBuilder.addString("edifactOrderAsString", RandomStringUtils.random(100, true, true)); - paramsBuilder.addString("jobName", "TestJob00123"); - var jobId = UUID.randomUUID().toString(); - paramsBuilder.addString("jobId", jobId); + paramsBuilder.addString(EDIFACT_ORDERS_EXPORT, getMockData("edifact/edifactOrdersExport.json")); + paramsBuilder.addString(ACQ_EXPORT_FILE, RandomStringUtils.random(100, true, true)); + paramsBuilder.addString(JOB_NAME, "TestJob00123"); + paramsBuilder.addString(JOB_ID, UUID.randomUUID().toString()); return paramsBuilder.toJobParameters(); } diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java index 515388600..e3f575258 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java @@ -1,5 +1,8 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; +import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; +import static org.folio.dew.domain.dto.JobParameterNames.JOB_ID; +import static org.folio.dew.domain.dto.JobParameterNames.JOB_NAME; import static org.folio.dew.utils.TestUtils.getMockData; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -82,9 +85,9 @@ protected ObjectNode getEdifactExportConfig(String path) throws IOException { protected JobParameters getJobParameters(ObjectNode edifactExport) { return new JobParametersBuilder() - .addString("jobId", UUID.randomUUID().toString()) - .addString("edifactOrdersExport", edifactExport.toString()) - .addString("jobName", "000015") + .addString(JOB_ID, UUID.randomUUID().toString()) + .addString(JOB_NAME, "000015") + .addString(EDIFACT_ORDERS_EXPORT, edifactExport.toString()) .toJobParameters(); } diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTaskletTest.java index 1bd2fcbeb..ee92a8997 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTaskletTest.java @@ -1,6 +1,8 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; import static org.assertj.core.api.Assertions.assertThat; +import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; +import static org.folio.dew.domain.dto.JobParameterNames.JOB_ID; import static org.folio.dew.domain.dto.JobParameterNames.UPLOADED_FILE_PATH; import static org.folio.dew.utils.Constants.EDIFACT_EXPORT_DIR_NAME; import static org.folio.dew.utils.Constants.getWorkingDirectory; @@ -83,8 +85,8 @@ void ftpUploadSuccessful() throws Exception { private JobParameters getSFTPJobParameters() throws IOException { JobParametersBuilder paramsBuilder = new JobParametersBuilder(); - paramsBuilder.addString("edifactOrdersExport", getMockData("edifact/edifactOrdersExport.json")); - paramsBuilder.addString("jobId", UUID.randomUUID().toString()); + paramsBuilder.addString(EDIFACT_ORDERS_EXPORT, getMockData("edifact/edifactOrdersExport.json")); + paramsBuilder.addString(JOB_ID, UUID.randomUUID().toString()); String workDir = getWorkingDirectory(springApplicationName, EDIFACT_EXPORT_DIR_NAME); @@ -100,8 +102,8 @@ private JobParameters getSFTPJobParameters() throws IOException { private JobParameters getFTPJobParameters() throws IOException { JobParametersBuilder paramsBuilder = new JobParametersBuilder(); - paramsBuilder.addString("edifactOrdersExport", getMockData("edifact/edifactFTPOrdersExport.json")); - paramsBuilder.addString("jobId", UUID.randomUUID().toString()); + paramsBuilder.addString(EDIFACT_ORDERS_EXPORT, getMockData("edifact/edifactFTPOrdersExport.json")); + paramsBuilder.addString(JOB_ID, UUID.randomUUID().toString()); return paramsBuilder.toJobParameters(); } diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletFailTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletFailTest.java index 281569784..c89fcc445 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletFailTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletFailTest.java @@ -1,5 +1,8 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; +import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; +import static org.folio.dew.domain.dto.JobParameterNames.JOB_ID; import static org.folio.dew.utils.TestUtils.getMockData; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; @@ -60,16 +63,15 @@ void minioSaveToRemoteStorageFailed() private JobParameters getJobParameters() throws IOException { JobParametersBuilder paramsBuilder = new JobParametersBuilder(); - paramsBuilder.addString("edifactOrdersExport", getMockData("edifact/edifactOrdersExport.json")); - var jobId = UUID.randomUUID().toString(); - paramsBuilder.addString("jobId", jobId); + paramsBuilder.addString(EDIFACT_ORDERS_EXPORT, getMockData("edifact/edifactOrdersExport.json")); + paramsBuilder.addString(JOB_ID, UUID.randomUUID().toString()); return paramsBuilder.toJobParameters(); } private ExecutionContext getExecutionContext() { ExecutionContext executionContext = new ExecutionContext(); - executionContext.put("edifactOrderAsString", RandomStringUtils.random(100, true, true)); + executionContext.put(ACQ_EXPORT_FILE, RandomStringUtils.random(100, true, true)); return executionContext; } diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java index daa6111ef..16269d16a 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java @@ -1,5 +1,8 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; +import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; +import static org.folio.dew.domain.dto.JobParameterNames.JOB_ID; import static org.folio.dew.utils.TestUtils.getMockData; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.anyString; @@ -50,17 +53,16 @@ void minioUploadSuccessful() throws IOException { private JobParameters getJobParameters() throws IOException { JobParametersBuilder paramsBuilder = new JobParametersBuilder(); - paramsBuilder.addString("edifactOrdersExport", getMockData("edifact/edifactOrdersExport.json")); - paramsBuilder.addString("edifactOrderAsString", RandomStringUtils.random(100, true, true)); - var jobId = UUID.randomUUID().toString(); - paramsBuilder.addString("jobId", jobId); + paramsBuilder.addString(EDIFACT_ORDERS_EXPORT, getMockData("edifact/edifactOrdersExport.json")); + paramsBuilder.addString(ACQ_EXPORT_FILE, RandomStringUtils.random(100, true, true)); + paramsBuilder.addString(JOB_ID, UUID.randomUUID().toString()); return paramsBuilder.toJobParameters(); } private ExecutionContext getExecutionContext() { ExecutionContext executionContext = new ExecutionContext(); - executionContext.put("edifactOrderAsString", RandomStringUtils.random(100, true, true)); + executionContext.put(ACQ_EXPORT_FILE, RandomStringUtils.random(100, true, true)); return executionContext; } From 63c49194a91f9e53e4be28c1d9638156242c25a9 Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Wed, 25 Dec 2024 16:59:26 +0400 Subject: [PATCH 12/24] [MODEXPS-273] Fix failing tests --- .../jobs/MapToEdifactClaimsTaskletTest.java | 1 + .../jobs/MapToEdifactOrderTaskletTest.java | 2 + .../jobs/MapToEdifactTaskletAbstractTest.java | 3 + .../jobs/SaveToFileStorageTaskletTest.java | 78 +++++++------------ 4 files changed, 33 insertions(+), 51 deletions(-) diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java index 63ad27f89..6a455a925 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTaskletTest.java @@ -62,6 +62,7 @@ protected void setUp() { pieceIds = pieces.stream().map(Piece::getId).toList(); doReturn(pieces).when(ordersService).getPiecesByIdsAndReceivingStatus(pieceIds, Piece.ReceivingStatusEnum.CLAIM_SENT); + doReturn(objectMapper.readTree("{\"code\": \"GOBI\"}")).when(organizationsService).getOrganizationById(anyString()); } @Test diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrderTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrderTaskletTest.java index 4b003b4c7..53900e4bd 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrderTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrderTaskletTest.java @@ -51,6 +51,8 @@ protected void setUp() { edifactExportJob = edifactOrdersExportJob; orders = objectMapper.readValue(getMockData(SAMPLE_PURCHASE_ORDERS_PATH), PurchaseOrderCollection.class).getPurchaseOrders(); poLines = objectMapper.readValue(getMockData(SAMPLE_PO_LINES_PATH), PoLineCollection.class).getPoLines(); + + doReturn(objectMapper.readTree("{\"code\": \"GOBI\"}")).when(organizationsService).getOrganizationById(anyString()); } @Test diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java index e3f575258..2333c54cb 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTaskletAbstractTest.java @@ -19,6 +19,7 @@ import org.folio.dew.BaseBatchTest; import org.folio.dew.batch.acquisitions.edifact.mapper.ExportResourceMapper; import org.folio.dew.batch.acquisitions.edifact.services.OrdersService; +import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; import org.folio.dew.client.DataExportSpringClient; import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; @@ -47,6 +48,8 @@ abstract class MapToEdifactTaskletAbstractTest extends BaseBatchTest { @MockBean protected OrdersService ordersService; @MockBean + protected OrganizationsService organizationsService; + @MockBean protected DataExportSpringClient dataExportSpringClient; @MockBean @Qualifier("edifactMapper") diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTaskletTest.java index ee92a8997..c5cc5cb23 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTaskletTest.java @@ -1,11 +1,10 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; import static org.assertj.core.api.Assertions.assertThat; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; +import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.JobParameterNames.JOB_ID; -import static org.folio.dew.domain.dto.JobParameterNames.UPLOADED_FILE_PATH; -import static org.folio.dew.utils.Constants.EDIFACT_EXPORT_DIR_NAME; -import static org.folio.dew.utils.Constants.getWorkingDirectory; import static org.folio.dew.utils.TestUtils.getMockData; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -14,7 +13,6 @@ import static org.mockito.Mockito.doReturn; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.util.UUID; import org.apache.commons.lang3.RandomStringUtils; @@ -22,7 +20,9 @@ import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; import org.folio.dew.repository.FTPObjectStorageRepository; import org.folio.dew.repository.SFTPObjectStorageRepository; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; @@ -35,9 +35,10 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.annotation.DirtiesContext; -import com.fasterxml.jackson.databind.JsonNode; +import lombok.SneakyThrows; class SaveToFileStorageTaskletTest extends BaseBatchTest { + @Autowired @Qualifier("edifactOrdersExportJob") private Job edifactExportJob; @@ -48,69 +49,43 @@ class SaveToFileStorageTaskletTest extends BaseBatchTest { @MockBean private OrganizationsService organizationsService; - @Test - @DirtiesContext - void sftpUploadSuccessful() throws Exception { - JobLauncherTestUtils testLauncher = createTestLauncher(edifactExportJob); + @Override + @SneakyThrows + @BeforeEach + protected void setUp() { + super.setUp(); + doReturn(objectMapper.readTree("{\"code\": \"GOBI\"}")).when(organizationsService).getOrganizationById(anyString()); doReturn(true).when(sftpObjectStorageRepository).upload(anyString(), anyString(), anyString(), anyInt(), anyString(), anyString(), any()); - JsonNode vendorJson = objectMapper.readTree("{\"code\": \"GOBI\"}"); - doReturn(vendorJson).when(organizationsService).getOrganizationById(anyString()); - - JobParameters jobParameters = getSFTPJobParameters(); - ExecutionContext executionContext = getExecutionContext(jobParameters.getString(UPLOADED_FILE_PATH)); - - JobExecution jobExecution = testLauncher.launchStep("saveToFTPStep", getSFTPJobParameters(), executionContext); - - assertThat(jobExecution.getExitStatus()).isEqualTo(ExitStatus.COMPLETED); - + doNothing().when(ftpObjectStorageRepository).upload(anyString(), anyString(), anyString(), anyString(), anyString(), any()); } - @Test + @ParameterizedTest(name = "{0}") + @CsvSource(value = {"SFTP Upload,edifact/edifactOrdersExport.json", "FTP Upload,edifact/edifactFTPOrdersExport.json"}, delimiter = ',') @DirtiesContext - void ftpUploadSuccessful() throws Exception { + void testUploadSuccessful(String testName, String edifactOrdersExport) throws Exception { JobLauncherTestUtils testLauncher = createTestLauncher(edifactExportJob); - JsonNode vendorJson = objectMapper.readTree("{\"code\": \"GOBI\"}"); - doReturn(vendorJson).when(organizationsService).getOrganizationById(anyString()); - doNothing().when(ftpObjectStorageRepository).upload(anyString(),anyString(),anyString(), anyString(), anyString(), any()); - - JobParameters jobParameters = getSFTPJobParameters(); - ExecutionContext executionContext = getExecutionContext(jobParameters.getString(UPLOADED_FILE_PATH)); - JobExecution jobExecution = testLauncher.launchStep("saveToFTPStep", getFTPJobParameters(), executionContext); + var jobParameters = getJobParameters(edifactOrdersExport); + ExecutionContext executionContext = getExecutionContext(); + JobExecution jobExecution = testLauncher.launchStep("saveToFTPStep", jobParameters, executionContext); assertThat(jobExecution.getExitStatus()).isEqualTo(ExitStatus.COMPLETED); - } - private JobParameters getSFTPJobParameters() throws IOException { - JobParametersBuilder paramsBuilder = new JobParametersBuilder(); - - paramsBuilder.addString(EDIFACT_ORDERS_EXPORT, getMockData("edifact/edifactOrdersExport.json")); - paramsBuilder.addString(JOB_ID, UUID.randomUUID().toString()); - - String workDir = getWorkingDirectory(springApplicationName, EDIFACT_EXPORT_DIR_NAME); - - // prepare local file copy - var filename = "testEdiFile.edi"; - var fileContent = RandomStringUtils.random(100); - var uploadedFilePath = remoteFilesStorage.write(workDir + filename, fileContent.getBytes(StandardCharsets.UTF_8)); - paramsBuilder.addString(UPLOADED_FILE_PATH, uploadedFilePath); - - return paramsBuilder.toJobParameters(); } - private JobParameters getFTPJobParameters() throws IOException { + private JobParameters getJobParameters(String edifactOrdersExport) throws IOException { JobParametersBuilder paramsBuilder = new JobParametersBuilder(); - - paramsBuilder.addString(EDIFACT_ORDERS_EXPORT, getMockData("edifact/edifactFTPOrdersExport.json")); + paramsBuilder.addString(EDIFACT_ORDERS_EXPORT, getMockData(edifactOrdersExport)); paramsBuilder.addString(JOB_ID, UUID.randomUUID().toString()); - return paramsBuilder.toJobParameters(); } - private ExecutionContext getExecutionContext(String uploadedFilePath) { + private ExecutionContext getExecutionContext() { + // Prepare file name and content ExecutionContext executionContext = new ExecutionContext(); - executionContext.put(UPLOADED_FILE_PATH, uploadedFilePath); + executionContext.put(EDIFACT_FILE_NAME, "testEdiFile.edi"); + executionContext.put(ACQ_EXPORT_FILE, RandomStringUtils.random(100)); return executionContext; } @@ -121,4 +96,5 @@ protected JobLauncherTestUtils createTestLauncher(Job job) { testLauncher.setJobRepository(jobRepository); return testLauncher; } + } From d4f64d2172ce1cc662cac569103d1b551464cc44 Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Wed, 25 Dec 2024 17:10:11 +0400 Subject: [PATCH 13/24] [MODEXPS-273] Fix failing test --- .../jobs/SaveToMinioTaskletFailTest.java | 85 ------------------- .../edifact/jobs/SaveToMinioTaskletTest.java | 30 ++++++- 2 files changed, 27 insertions(+), 88 deletions(-) delete mode 100644 src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletFailTest.java diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletFailTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletFailTest.java deleted file mode 100644 index c89fcc445..000000000 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletFailTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.folio.dew.batch.acquisitions.edifact.jobs; - -import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; -import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; -import static org.folio.dew.domain.dto.JobParameterNames.JOB_ID; -import static org.folio.dew.utils.TestUtils.getMockData; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; - -import java.io.IOException; -import java.util.UUID; - -import org.apache.commons.lang3.RandomStringUtils; -import org.folio.dew.BaseBatchTest; -import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; -import org.folio.dew.repository.RemoteFilesStorage; -import org.junit.jupiter.api.Test; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.test.JobLauncherTestUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.annotation.DirtiesContext; - -import com.fasterxml.jackson.databind.JsonNode; - -class SaveToMinioTaskletFailTest extends BaseBatchTest { - @Autowired - @Qualifier("edifactOrdersExportJob") - private Job edifactExportJob; - @MockBean - private OrganizationsService organizationsService; - - @MockBean - private RemoteFilesStorage remoteFilesStorage; - - private static final String NULL_POINTER_ERROR_TEXT = "Test null pointer exception message"; - - @Test - @DirtiesContext - void minioSaveToRemoteStorageFailed() - throws IOException { - JobLauncherTestUtils testLauncher = createTestLauncher(edifactExportJob); - - JsonNode vendorJson = objectMapper.readTree("{\"code\": \"GOBI\"}"); - doReturn(vendorJson).when(organizationsService).getOrganizationById(anyString()); - - doThrow(new NullPointerException(NULL_POINTER_ERROR_TEXT)).when(remoteFilesStorage).write(anyString(), any(byte[].class)); - - JobExecution jobExecution = testLauncher.launchStep("saveToMinIOStep", getJobParameters(), getExecutionContext()); - - assertEquals(ExitStatus.FAILED.getExitCode(), jobExecution.getExitStatus().getExitCode()); - } - - private JobParameters getJobParameters() throws IOException { - JobParametersBuilder paramsBuilder = new JobParametersBuilder(); - - paramsBuilder.addString(EDIFACT_ORDERS_EXPORT, getMockData("edifact/edifactOrdersExport.json")); - paramsBuilder.addString(JOB_ID, UUID.randomUUID().toString()); - - return paramsBuilder.toJobParameters(); - } - - private ExecutionContext getExecutionContext() { - ExecutionContext executionContext = new ExecutionContext(); - executionContext.put(ACQ_EXPORT_FILE, RandomStringUtils.random(100, true, true)); - return executionContext; - } - - protected JobLauncherTestUtils createTestLauncher(Job job) { - JobLauncherTestUtils testLauncher = new JobLauncherTestUtils(); - testLauncher.setJob(job); - testLauncher.setJobLauncher(jobLauncher); - testLauncher.setJobRepository(jobRepository); - return testLauncher; - } -} diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java index 16269d16a..18a6ba88f 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java @@ -5,8 +5,10 @@ import static org.folio.dew.domain.dto.JobParameterNames.JOB_ID; import static org.folio.dew.utils.TestUtils.getMockData; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; import java.io.IOException; import java.util.UUID; @@ -14,6 +16,7 @@ import org.apache.commons.lang3.RandomStringUtils; import org.folio.dew.BaseBatchTest; import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.Job; @@ -29,6 +32,8 @@ import com.fasterxml.jackson.databind.JsonNode; +import lombok.SneakyThrows; + class SaveToMinioTaskletTest extends BaseBatchTest { @Autowired @Qualifier("edifactOrdersExportJob") @@ -36,19 +41,38 @@ class SaveToMinioTaskletTest extends BaseBatchTest { @MockBean private OrganizationsService organizationsService; + @Override + @SneakyThrows + @BeforeEach + protected void setUp() { + super.setUp(); + + JsonNode vendorJson = objectMapper.readTree("{\"code\": \"GOBI\"}"); + doReturn(vendorJson).when(organizationsService).getOrganizationById(anyString()); + } + @Test @DirtiesContext void minioUploadSuccessful() throws IOException { JobLauncherTestUtils testLauncher = createTestLauncher(edifactExportJob); - JsonNode vendorJson = objectMapper.readTree("{\"code\": \"GOBI\"}"); - doReturn(vendorJson).when(organizationsService).getOrganizationById(anyString()); - JobExecution jobExecution = testLauncher.launchStep("saveToMinIOStep", getJobParameters(), getExecutionContext()); assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); } + @Test + @DirtiesContext + void minioUploadFails() + throws IOException { + JobLauncherTestUtils testLauncher = createTestLauncher(edifactExportJob); + doThrow(new NullPointerException()).when(remoteFilesStorage).write(anyString(), any(byte[].class)); + + JobExecution jobExecution = testLauncher.launchStep("saveToMinIOStep", getJobParameters(), getExecutionContext()); + + assertEquals(ExitStatus.FAILED.getExitCode(), jobExecution.getExitStatus().getExitCode()); + } + private JobParameters getJobParameters() throws IOException { JobParametersBuilder paramsBuilder = new JobParametersBuilder(); From c5eb9fec24adb32913b396cb719c932e31c2ba0b Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Wed, 25 Dec 2024 17:23:20 +0400 Subject: [PATCH 14/24] [MODEXPS-273] Fix failing test --- .../batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java index 18a6ba88f..1072d8e23 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java @@ -9,6 +9,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.spy; import java.io.IOException; import java.util.UUID; @@ -46,6 +47,7 @@ class SaveToMinioTaskletTest extends BaseBatchTest { @BeforeEach protected void setUp() { super.setUp(); + remoteFilesStorage = spy(remoteFilesStorage); JsonNode vendorJson = objectMapper.readTree("{\"code\": \"GOBI\"}"); doReturn(vendorJson).when(organizationsService).getOrganizationById(anyString()); From 75a6e665d20706c69e5ac868144964a2b3410680 Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Wed, 25 Dec 2024 20:18:47 +0400 Subject: [PATCH 15/24] [MODEXPS-273] Fix step conditional logic --- .../acquisitions/edifact/jobs/SaveToFileStorageTasklet.java | 3 ++- .../batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java | 3 ++- .../acquisitions/edifact/jobs/SaveToMinioTaskletTest.java | 5 ++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java index bc71f6627..a9c994c41 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java @@ -3,6 +3,7 @@ import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; +import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.ORDERING; import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FTP; import java.nio.charset.StandardCharsets; @@ -40,7 +41,7 @@ public class SaveToFileStorageTasklet implements Tasklet { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) { var jobParameters = chunkContext.getStepContext().getJobParameters(); var ediExportConfig = ediObjectMapper.readValue((String) jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); - if (ediExportConfig.getTransmissionMethod() != FTP) { + if (ediExportConfig.getIntegrationType() != ORDERING && ediExportConfig.getTransmissionMethod() != FTP) { log.info("execute:: Transmission method is not FTP, skipping the step"); return RepeatStatus.FINISHED; } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java index a9dd569d8..5077329b2 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java @@ -4,6 +4,7 @@ import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.JobParameterNames.OUTPUT_FILES_IN_STORAGE; +import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.ORDERING; import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FILE_DOWNLOAD; import static org.folio.dew.utils.Constants.EDIFACT_EXPORT_DIR_NAME; import static org.folio.dew.utils.Constants.getWorkingDirectory; @@ -52,7 +53,7 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon // retrieve parameters from job context var jobParameters = chunkContext.getStepContext().getJobParameters(); var ediExportConfig = ediObjectMapper.readValue((String) jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); - if (ediExportConfig.getTransmissionMethod() != FILE_DOWNLOAD) { + if (ediExportConfig.getIntegrationType() != ORDERING && ediExportConfig.getTransmissionMethod() != FILE_DOWNLOAD) { log.info("execute:: Transmission method is not File Download, skipping the step"); return RepeatStatus.FINISHED; } diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java index 1072d8e23..2186f1d6d 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java @@ -17,6 +17,7 @@ import org.apache.commons.lang3.RandomStringUtils; import org.folio.dew.BaseBatchTest; import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; +import org.folio.dew.repository.RemoteFilesStorage; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.batch.core.ExitStatus; @@ -29,6 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.test.annotation.DirtiesContext; import com.fasterxml.jackson.databind.JsonNode; @@ -41,13 +43,14 @@ class SaveToMinioTaskletTest extends BaseBatchTest { private Job edifactExportJob; @MockBean private OrganizationsService organizationsService; + @SpyBean + private RemoteFilesStorage remoteFilesStorage; @Override @SneakyThrows @BeforeEach protected void setUp() { super.setUp(); - remoteFilesStorage = spy(remoteFilesStorage); JsonNode vendorJson = objectMapper.readTree("{\"code\": \"GOBI\"}"); doReturn(vendorJson).when(organizationsService).getOrganizationById(anyString()); From 6fa8951c52211fb7d069b8152e721859bbc2441a Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Wed, 25 Dec 2024 20:48:41 +0400 Subject: [PATCH 16/24] [MODEXPS-273] Fix sonar issues --- .../dew/batch/acquisitions/edifact/utils/ExportUtils.java | 7 ++++--- .../acquisitions/edifact/jobs/SaveToMinioTaskletTest.java | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportUtils.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportUtils.java index 5df6ad760..7dd0d0157 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportUtils.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/utils/ExportUtils.java @@ -2,7 +2,6 @@ import static org.folio.dew.domain.dto.ReferenceNumberItem.RefNumberTypeEnum.ORDER_REFERENCE_NUMBER; -import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -17,7 +16,6 @@ public class ExportUtils { - private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); private static final String FILE_NAME_FORMAT = "%s_%s_%s.%s"; private ExportUtils() { } @@ -54,7 +52,10 @@ public static void validateField(String field, T value, Predicate validat } public static String generateFileName(String vendorName, String configName, FileFormatEnum fileFormat) { - return FILE_NAME_FORMAT.formatted(vendorName, configName, DATE_FORMAT.format(new Date()), fileFormat.getValue().toLowerCase()); // Enum being EDI or CSV + return FILE_NAME_FORMAT.formatted(vendorName, + configName, + new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new Date()), + fileFormat.getValue().toLowerCase()); // Enum being EDI or CSV } } diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java index 2186f1d6d..b01e59fa7 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTaskletTest.java @@ -9,7 +9,6 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.spy; import java.io.IOException; import java.util.UUID; From 06df10dff02be5679f036206be4be2269cd5e3a1 Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Thu, 26 Dec 2024 17:14:45 +0400 Subject: [PATCH 17/24] [MODEXPS-273] Remove export history step for claims --- .../edifact/jobs/EdifactExportJobConfig.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java index ba5367604..1edad4a88 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java @@ -4,6 +4,7 @@ import lombok.extern.log4j.Log4j2; import org.folio.dew.domain.dto.ExportType; import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecutionListener; import org.springframework.batch.core.Step; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.launch.support.RunIdIncrementer; @@ -21,18 +22,16 @@ public class EdifactExportJobConfig { public static final String POL_MEM_KEY = "poLineIds"; private Job constructEdifactExportJob(JobBuilder jobBuilder, - EdiExportJobCompletionListener ediExportJobCompletionListener, - Step mapToEdifactOrdersStep, - Step saveToFTPStep, - Step saveToMinIOStep, - Step createExportHistoryRecordsStep) { - return jobBuilder.incrementer(new RunIdIncrementer()) - .listener(ediExportJobCompletionListener) - .start(mapToEdifactOrdersStep) - .next(saveToMinIOStep) - .next(saveToFTPStep) - .next(createExportHistoryRecordsStep) - .build(); + JobExecutionListener listener, + Step... steps) { + var builder = jobBuilder + .incrementer(new RunIdIncrementer()) + .listener(listener) + .start(steps[0]); + for (int i = 1; i < steps.length; i++) { + builder = builder.next(steps[i]); + } + return builder.build(); } @Bean @@ -44,9 +43,9 @@ public Job edifactOrdersExportJob(EdiExportJobCompletionListener ediExportJobCom @Bean public Job edifactClaimsExportJob(EdiExportJobCompletionListener ediExportJobCompletionListener, JobRepository jobRepository, - Step mapToEdifactClaimsStep, Step saveToFTPStep, Step saveToMinIOStep, Step createExportHistoryRecordsStep) { + Step mapToEdifactClaimsStep, Step saveToFTPStep, Step saveToMinIOStep) { return constructEdifactExportJob(new JobBuilder(ExportType.CLAIMS.getValue(), jobRepository), - ediExportJobCompletionListener, mapToEdifactClaimsStep, saveToFTPStep, saveToMinIOStep, createExportHistoryRecordsStep); + ediExportJobCompletionListener, mapToEdifactClaimsStep, saveToFTPStep, saveToMinIOStep); } @Bean From 24ca809264493ec16fa8dfe8b27193b270b0f158 Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Thu, 26 Dec 2024 17:52:05 +0400 Subject: [PATCH 18/24] [MODEXPS-273] Improve exception message when configuration is not found --- .../edifact/services/ConfigurationService.java | 8 +++++++- src/main/java/org/folio/dew/error/NotFoundException.java | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/services/ConfigurationService.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/services/ConfigurationService.java index 17ba800fc..3888f84a6 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/services/ConfigurationService.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/services/ConfigurationService.java @@ -11,6 +11,7 @@ import org.apache.logging.log4j.Logger; import org.folio.dew.client.ConfigurationClient; import org.folio.dew.domain.dto.ModelConfiguration; +import org.folio.dew.error.NotFoundException; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -24,7 +25,12 @@ public class ConfigurationService { private final ObjectMapper objectMapper; private ModelConfiguration getConfigById(String configId) { - return configurationClient.getConfigById(configId); + try { + return configurationClient.getConfigById(configId); + } catch (NotFoundException e) { + logger.error("getConfigById:: Couldn't fetch configuration entry by id: '{}'", configId, e); + throw new NotFoundException("Configuration entry not found for id: " + configId, e); + } } @Cacheable(cacheNames = "addressConfiguration") diff --git a/src/main/java/org/folio/dew/error/NotFoundException.java b/src/main/java/org/folio/dew/error/NotFoundException.java index 8317c2648..5edc96a31 100644 --- a/src/main/java/org/folio/dew/error/NotFoundException.java +++ b/src/main/java/org/folio/dew/error/NotFoundException.java @@ -12,4 +12,8 @@ public NotFoundException(String message) { super(message); } + public NotFoundException(String message, Throwable cause) { + super(message, cause); + } + } From 12886be71f662732b3a813188fbcf9504a4caa2c Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Mon, 30 Dec 2024 13:41:30 +0400 Subject: [PATCH 19/24] [MODEXPS-273] Change export file name key --- .../edifact/jobs/EdiExportJobCompletionListener.java | 4 ++-- .../batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java | 4 ++-- .../batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java | 4 ++-- .../acquisitions/edifact/jobs/SaveToFileStorageTasklet.java | 4 ++-- .../batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java | 4 ++-- src/main/java/org/folio/dew/domain/dto/JobParameterNames.java | 2 +- .../edifact/jobs/SaveToFileStorageTaskletTest.java | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdiExportJobCompletionListener.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdiExportJobCompletionListener.java index 493299a39..15b9a1cd4 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdiExportJobCompletionListener.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdiExportJobCompletionListener.java @@ -1,6 +1,6 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; -import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_FILE_NAME; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.OUTPUT_FILES_IN_STORAGE; import static org.folio.dew.utils.BulkEditProcessorHelper.convertToDate; @@ -74,7 +74,7 @@ private Job createJobExecutionUpdate(String jobId, JobExecution jobExecution) { result.setFiles(Arrays.asList(outputFilesInStorage.split(PATHS_DELIMITER))); } - String ftpUploadedFile = ExecutionContextUtils.getFromJobExecutionContext(jobExecution, EDIFACT_FILE_NAME); + String ftpUploadedFile = ExecutionContextUtils.getFromJobExecutionContext(jobExecution, ACQ_EXPORT_FILE_NAME); if (StringUtils.isNotBlank(ftpUploadedFile)) { result.setFileNames(List.of(ftpUploadedFile)); } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java index 2035f2bd6..6f9b01c91 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java @@ -1,7 +1,7 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; import static org.folio.dew.batch.acquisitions.edifact.jobs.EdifactExportJobConfig.POL_MEM_KEY; -import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_FILE_NAME; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import java.util.Collections; @@ -60,7 +60,7 @@ ExportHistory buildExportHistory(ChunkContext chunkContext) { var vendorName = vendor.get("code").asText(); var stepExecutionContext = chunkContext.getStepContext().getStepExecution(); var poLineIds = getPoLineIdsFromExecutionContext(stepExecutionContext); - var fileName = ExecutionContextUtils.getExecutionVariable(stepExecutionContext, EDIFACT_FILE_NAME).toString(); + var fileName = ExecutionContextUtils.getExecutionVariable(stepExecutionContext, ACQ_EXPORT_FILE_NAME).toString(); var jobName = jobParameters.get(JobParameterNames.JOB_NAME).toString(); return new ExportHistory() diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java index f8ed22cf7..84447b39c 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java @@ -11,7 +11,7 @@ import static org.folio.dew.batch.acquisitions.edifact.utils.ExportUtils.generateFileName; import static org.folio.dew.batch.acquisitions.edifact.utils.ExportUtils.validateField; import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; -import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_FILE_NAME; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FTP; @@ -70,7 +70,7 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon // save edifact file content and name in memory var stepExecution = chunkContext.getStepContext().getStepExecution(); ExecutionContextUtils.addToJobExecutionContext(stepExecution, ACQ_EXPORT_FILE, edifactStringResult, ""); - ExecutionContextUtils.addToJobExecutionContext(stepExecution, EDIFACT_FILE_NAME, getFileName(ediExportConfig), ""); + ExecutionContextUtils.addToJobExecutionContext(stepExecution, ACQ_EXPORT_FILE_NAME, getFileName(ediExportConfig), ""); return RepeatStatus.FINISHED; } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java index a9c994c41..dee395862 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java @@ -1,7 +1,7 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; -import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_FILE_NAME; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.ORDERING; import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FTP; @@ -53,7 +53,7 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon } var stepExecution = chunkContext.getStepContext().getStepExecution(); - var fileName = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, EDIFACT_FILE_NAME); + var fileName = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, ACQ_EXPORT_FILE_NAME); var edifactOrderAsString = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, ACQ_EXPORT_FILE); ftpStorageService.uploadToFtp(ediExportConfig, edifactOrderAsString.getBytes(StandardCharsets.UTF_8), fileName); diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java index 5077329b2..93ec4d2e2 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java @@ -1,7 +1,7 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; -import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_FILE_NAME; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.JobParameterNames.OUTPUT_FILES_IN_STORAGE; import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.ORDERING; @@ -76,7 +76,7 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon private String buildFullFilePath(StepExecution stepExecution) { var workDir = getWorkingDirectory(springApplicationName, EDIFACT_EXPORT_DIR_NAME); var tenantName = folioExecutionContext.getTenantId(); - var fileName = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, EDIFACT_FILE_NAME); + var fileName = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, ACQ_EXPORT_FILE_NAME); return UPLOADED_PATH_TEMPLATE.formatted(workDir, tenantName, fileName); } diff --git a/src/main/java/org/folio/dew/domain/dto/JobParameterNames.java b/src/main/java/org/folio/dew/domain/dto/JobParameterNames.java index d3c41b8ad..19c587e85 100644 --- a/src/main/java/org/folio/dew/domain/dto/JobParameterNames.java +++ b/src/main/java/org/folio/dew/domain/dto/JobParameterNames.java @@ -16,8 +16,8 @@ public class JobParameterNames { public static final String UPDATED_FILE_NAME = "updatedFileName"; public static final String PREVIEW_FILE_NAME = "previewFileName"; public static final String UPLOADED_FILE_PATH = "uploadedFilePath"; - public static final String EDIFACT_FILE_NAME = "edifactFileName"; public static final String ACQ_EXPORT_FILE = "acqExportFile"; + public static final String ACQ_EXPORT_FILE_NAME = "acqExportFileName"; public static final String E_HOLDINGS_FILE_NAME = "eHoldingsFileName"; public static final String CIRCULATION_LOG_FILE_NAME = "circulationLogFileName"; public static final String AUTHORITY_CONTROL_FILE_NAME = "authorityControlFileName"; diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTaskletTest.java index c5cc5cb23..e36f463ed 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTaskletTest.java @@ -2,7 +2,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; -import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_FILE_NAME; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.JobParameterNames.JOB_ID; import static org.folio.dew.utils.TestUtils.getMockData; @@ -84,7 +84,7 @@ private JobParameters getJobParameters(String edifactOrdersExport) throws IOExce private ExecutionContext getExecutionContext() { // Prepare file name and content ExecutionContext executionContext = new ExecutionContext(); - executionContext.put(EDIFACT_FILE_NAME, "testEdiFile.edi"); + executionContext.put(ACQ_EXPORT_FILE_NAME, "testEdiFile.edi"); executionContext.put(ACQ_EXPORT_FILE, RandomStringUtils.random(100)); return executionContext; } From 39a787ab74dfba879baa5f7ed9a315d0d6bc15bf Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Mon, 30 Dec 2024 14:35:38 +0400 Subject: [PATCH 20/24] [MODEXPS-273] Improve step execution conditions --- .../edifact/jobs/EdifactExportJobConfig.java | 27 ++++----- .../edifact/jobs/ExportHistoryTasklet.java | 16 ++++-- .../edifact/jobs/FilterableTasklet.java | 56 +++++++++++++++++++ .../jobs/MapToEdifactClaimsTasklet.java | 15 +---- .../jobs/MapToEdifactOrdersTasklet.java | 17 +----- .../edifact/jobs/MapToEdifactTasklet.java | 15 +++-- .../jobs/SaveToFileStorageTasklet.java | 31 +++++----- .../edifact/jobs/SaveToMinioTasklet.java | 22 ++------ 8 files changed, 114 insertions(+), 85 deletions(-) create mode 100644 src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/FilterableTasklet.java diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java index 1edad4a88..406491b3f 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java @@ -4,7 +4,6 @@ import lombok.extern.log4j.Log4j2; import org.folio.dew.domain.dto.ExportType; import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecutionListener; import org.springframework.batch.core.Step; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.launch.support.RunIdIncrementer; @@ -22,16 +21,18 @@ public class EdifactExportJobConfig { public static final String POL_MEM_KEY = "poLineIds"; private Job constructEdifactExportJob(JobBuilder jobBuilder, - JobExecutionListener listener, - Step... steps) { - var builder = jobBuilder - .incrementer(new RunIdIncrementer()) - .listener(listener) - .start(steps[0]); - for (int i = 1; i < steps.length; i++) { - builder = builder.next(steps[i]); - } - return builder.build(); + EdiExportJobCompletionListener ediExportJobCompletionListener, + Step mapToFileStep, + Step saveToMinIOStep, + Step saveToFTPStep, + Step createExportHistoryRecordsStep) { + return jobBuilder.incrementer(new RunIdIncrementer()) + .listener(ediExportJobCompletionListener) + .start(mapToFileStep) + .next(saveToMinIOStep) + .next(saveToFTPStep) + .next(createExportHistoryRecordsStep) + .build(); } @Bean @@ -43,9 +44,9 @@ public Job edifactOrdersExportJob(EdiExportJobCompletionListener ediExportJobCom @Bean public Job edifactClaimsExportJob(EdiExportJobCompletionListener ediExportJobCompletionListener, JobRepository jobRepository, - Step mapToEdifactClaimsStep, Step saveToFTPStep, Step saveToMinIOStep) { + Step mapToEdifactClaimsStep, Step saveToFTPStep, Step saveToMinIOStep, Step createExportHistoryRecordsStep) { return constructEdifactExportJob(new JobBuilder(ExportType.CLAIMS.getValue(), jobRepository), - ediExportJobCompletionListener, mapToEdifactClaimsStep, saveToFTPStep, saveToMinIOStep); + ediExportJobCompletionListener, mapToEdifactClaimsStep, saveToFTPStep, saveToMinIOStep, createExportHistoryRecordsStep); } @Bean diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java index 6f9b01c91..33f6a35f4 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java @@ -3,6 +3,7 @@ import static org.folio.dew.batch.acquisitions.edifact.jobs.EdifactExportJobConfig.POL_MEM_KEY; import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; +import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.ORDERING; import java.util.Collections; import java.util.Date; @@ -22,19 +23,18 @@ import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import lombok.RequiredArgsConstructor; +import lombok.experimental.SuperBuilder; import lombok.extern.log4j.Log4j2; -@RequiredArgsConstructor +@SuperBuilder @Component @StepScope @Log4j2 -public class ExportHistoryTasklet implements Tasklet { +public class ExportHistoryTasklet extends FilterableTasklet { private final KafkaService kafkaService; private final ObjectMapper ediObjectMapper; @@ -43,7 +43,7 @@ public class ExportHistoryTasklet implements Tasklet { @Value("#{jobParameters['jobId']}") private String jobId; @Override - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) { + public RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) { var exportHistory = buildExportHistory(chunkContext); kafkaService.send(KafkaService.Topic.EXPORT_HISTORY_CREATE, null, exportHistory); @@ -83,4 +83,10 @@ List getPoLineIdsFromExecutionContext(StepExecution stepExecutionContext return Collections.emptyList(); } } + + @Override + protected boolean shouldExecute(VendorEdiOrdersExportConfig exportConfig) { + return exportConfig.getIntegrationType() == ORDERING; + } + } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/FilterableTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/FilterableTasklet.java new file mode 100644 index 000000000..7f4b69a4b --- /dev/null +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/FilterableTasklet.java @@ -0,0 +1,56 @@ +package org.folio.dew.batch.acquisitions.edifact.jobs; + +import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; + +import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; +import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.core.step.tasklet.Tasklet; +import org.springframework.batch.repeat.RepeatStatus; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.RequiredArgsConstructor; +import lombok.experimental.SuperBuilder; +import lombok.extern.log4j.Log4j2; + +@RequiredArgsConstructor +@Log4j2 +@SuperBuilder +public abstract class FilterableTasklet implements Tasklet { + + private final ObjectMapper objectMapper; + + @Override + public final RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + var ediExportConfig = objectMapper.readValue((String) chunkContext.getStepContext().getJobParameters().get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); + if (shouldExecute(ediExportConfig)) { + return execute(ediExportConfig, contribution, chunkContext); + } + return RepeatStatus.FINISHED; + } + + /** + * Check if the tasklet should be executed, by default always returns true. + * Override this method to provide custom logic. + * + * @param exportConfig the export configuration + * @return true if the tasklet should be executed + */ + protected boolean shouldExecute(VendorEdiOrdersExportConfig exportConfig) { + return true; + } + + + /** + * This method should be overridden to provide the tasklet logic with predefined filtering. + * + * @param exportConfig the export configuration + * @param contribution the step contribution + * @param chunkContext the chunk context + * @return the repeat status + * @throws Exception if an error occurs + */ + protected abstract RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) throws Exception; + +} diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java index 6189b985c..ff445b534 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java @@ -14,18 +14,16 @@ import org.apache.commons.collections4.CollectionUtils; import org.folio.dew.batch.acquisitions.edifact.mapper.ExportResourceMapper; -import org.folio.dew.batch.acquisitions.edifact.services.OrdersService; -import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; import org.folio.dew.domain.dto.Piece; import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; import org.folio.dew.domain.dto.acquisitions.edifact.ExportHolder; import org.folio.dew.error.NotFoundException; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.stereotype.Component; -import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.experimental.SuperBuilder; +@SuperBuilder @Component @StepScope public class MapToEdifactClaimsTasklet extends MapToEdifactTasklet { @@ -33,13 +31,6 @@ public class MapToEdifactClaimsTasklet extends MapToEdifactTasklet { private final ExportResourceMapper edifactMapper; private final ExportResourceMapper csvMapper; - public MapToEdifactClaimsTasklet(ObjectMapper ediObjectMapper, OrganizationsService organizationsService, OrdersService ordersService, - ExportResourceMapper edifactMapper, ExportResourceMapper csvMapper) { - super(ediObjectMapper, organizationsService, ordersService); - this.edifactMapper = edifactMapper; - this.csvMapper = csvMapper; - } - @Override protected ExportResourceMapper getExportResourceMapper(VendorEdiOrdersExportConfig ediOrdersExportConfig) { return switch (ediOrdersExportConfig.getFileFormat()) { @@ -62,7 +53,7 @@ protected List getExportConfigMissingFields(VendorEdiOrdersExportConfig } @Override - protected ExportHolder buildEdifactExportHolder(ChunkContext chunkContext, VendorEdiOrdersExportConfig ediExportConfig, Map jobParameters) { + protected ExportHolder buildEdifactExportHolder(VendorEdiOrdersExportConfig ediExportConfig, Map jobParameters) { var pieces = ordersService.getPiecesByIdsAndReceivingStatus(ediExportConfig.getClaimPieceIds(), Piece.ReceivingStatusEnum.CLAIM_SENT); if (pieces.isEmpty()) { throw new NotFoundException(Piece.class); diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java index ac0d54c26..24f905be7 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java @@ -21,21 +21,18 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.folio.dew.batch.acquisitions.edifact.mapper.ExportResourceMapper; -import org.folio.dew.batch.acquisitions.edifact.services.OrdersService; -import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; import org.folio.dew.client.DataExportSpringClient; import org.folio.dew.domain.dto.ExportConfigCollection; import org.folio.dew.domain.dto.ExportType; import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; import org.folio.dew.domain.dto.acquisitions.edifact.ExportHolder; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.stereotype.Component; -import com.fasterxml.jackson.databind.ObjectMapper; - +import lombok.experimental.SuperBuilder; import lombok.extern.log4j.Log4j2; +@SuperBuilder @Component @StepScope @Log4j2 @@ -44,14 +41,6 @@ public class MapToEdifactOrdersTasklet extends MapToEdifactTasklet { private final DataExportSpringClient dataExportSpringClient; private final ExportResourceMapper edifactMapper; - public MapToEdifactOrdersTasklet(ObjectMapper ediObjectMapper, OrganizationsService organizationsService, OrdersService ordersService, - DataExportSpringClient dataExportSpringClient, - ExportResourceMapper edifactMapper) { - super(ediObjectMapper, organizationsService, ordersService); - this.edifactMapper = edifactMapper; - this.dataExportSpringClient = dataExportSpringClient; - } - @Override protected List getExportConfigMissingFields(VendorEdiOrdersExportConfig ediOrdersExportConfig) { List missingFields = new ArrayList<>(); @@ -64,7 +53,7 @@ protected List getExportConfigMissingFields(VendorEdiOrdersExportConfig } @Override - protected ExportHolder buildEdifactExportHolder(ChunkContext chunkContext, VendorEdiOrdersExportConfig ediExportConfig, Map jobParameters) { + protected ExportHolder buildEdifactExportHolder(VendorEdiOrdersExportConfig ediExportConfig, Map jobParameters) { var poLineQuery = getPoLineQuery(ediExportConfig); var compOrders = getCompositeOrders(poLineQuery); return new ExportHolder(compOrders, List.of()); diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java index 84447b39c..1a831ec40 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java @@ -36,32 +36,31 @@ import org.folio.dew.error.NotFoundException; import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.xlate.edi.stream.EDIStreamException; -import lombok.RequiredArgsConstructor; +import lombok.experimental.SuperBuilder; import lombok.extern.log4j.Log4j2; -@RequiredArgsConstructor +@SuperBuilder @Log4j2 -public abstract class MapToEdifactTasklet implements Tasklet { +public abstract class MapToEdifactTasklet extends FilterableTasklet { private final ObjectMapper ediObjectMapper; private final OrganizationsService organizationsService; protected final OrdersService ordersService; @Override - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + public RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) throws Exception { log.info("execute:: Executing MapToEdifactTasklet with job: {}", chunkContext.getStepContext().getJobName()); var jobParameters = chunkContext.getStepContext().getJobParameters(); var ediExportConfig = ediObjectMapper.readValue((String) jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); validateEdiExportConfig(ediExportConfig); - var holder = buildEdifactExportHolder(chunkContext, ediExportConfig, jobParameters); + var holder = buildEdifactExportHolder(ediExportConfig, jobParameters); persistPoLineIds(chunkContext, holder.orders()); String jobName = jobParameters.get(JobParameterNames.JOB_NAME).toString(); @@ -144,7 +143,7 @@ private T convertTo(Object value, Class c) { protected abstract List getExportConfigMissingFields(VendorEdiOrdersExportConfig ediOrdersExportConfig); - protected abstract ExportHolder buildEdifactExportHolder(ChunkContext chunkContext, VendorEdiOrdersExportConfig ediExportConfig, - Map jobParameters) throws JsonProcessingException, EDIStreamException; + protected abstract ExportHolder buildEdifactExportHolder(VendorEdiOrdersExportConfig ediExportConfig, Map jobParameters) + throws JsonProcessingException, EDIStreamException; } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java index dee395862..bce1c7678 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java @@ -2,7 +2,6 @@ import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME; -import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.ORDERING; import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FTP; @@ -15,21 +14,20 @@ import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; +import lombok.experimental.SuperBuilder; import lombok.extern.log4j.Log4j2; -@RequiredArgsConstructor +@SuperBuilder @Component @StepScope @Log4j2 -public class SaveToFileStorageTasklet implements Tasklet { +public class SaveToFileStorageTasklet extends FilterableTasklet { private static final String SFTP_PROTOCOL = "sftp://"; @@ -38,15 +36,8 @@ public class SaveToFileStorageTasklet implements Tasklet { @Override @SneakyThrows - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) { - var jobParameters = chunkContext.getStepContext().getJobParameters(); - var ediExportConfig = ediObjectMapper.readValue((String) jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); - if (ediExportConfig.getIntegrationType() != ORDERING && ediExportConfig.getTransmissionMethod() != FTP) { - log.info("execute:: Transmission method is not FTP, skipping the step"); - return RepeatStatus.FINISHED; - } - - String host = ediExportConfig.getEdiFtp().getServerAddress().replace(SFTP_PROTOCOL, ""); + public RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) { + String host = exportConfig.getEdiFtp().getServerAddress().replace(SFTP_PROTOCOL, ""); // skip ftp upload if address not specified if (StringUtils.isEmpty(host)) { return RepeatStatus.FINISHED; @@ -55,9 +46,19 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon var stepExecution = chunkContext.getStepContext().getStepExecution(); var fileName = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, ACQ_EXPORT_FILE_NAME); var edifactOrderAsString = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, ACQ_EXPORT_FILE); - ftpStorageService.uploadToFtp(ediExportConfig, edifactOrderAsString.getBytes(StandardCharsets.UTF_8), fileName); + ftpStorageService.uploadToFtp(exportConfig, edifactOrderAsString.getBytes(StandardCharsets.UTF_8), fileName); return RepeatStatus.FINISHED; } + @Override + protected boolean shouldExecute(VendorEdiOrdersExportConfig exportConfig) { + // Always execute if the integration type is not ORDERING, or execute for other integration types if the transmission method is FTP + if (exportConfig.getIntegrationType() == ORDERING || exportConfig.getTransmissionMethod() == FTP) { + return true; + } + log.info("execute:: Transmission method is not FTP, skipping the step"); + return false; + } + } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java index 93ec4d2e2..6bf34ba58 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java @@ -2,10 +2,7 @@ import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME; -import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.JobParameterNames.OUTPUT_FILES_IN_STORAGE; -import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.ORDERING; -import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FILE_DOWNLOAD; import static org.folio.dew.utils.Constants.EDIFACT_EXPORT_DIR_NAME; import static org.folio.dew.utils.Constants.getWorkingDirectory; @@ -20,44 +17,33 @@ import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import com.fasterxml.jackson.databind.ObjectMapper; - -import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; +import lombok.experimental.SuperBuilder; import lombok.extern.log4j.Log4j2; -@RequiredArgsConstructor +@SuperBuilder @Component @StepScope @Log4j2 -public class SaveToMinioTasklet implements Tasklet { +public class SaveToMinioTasklet extends FilterableTasklet { private static final String REMOTE_STORAGE_ERROR_MESSAGE = "Failed to save edifact file to remote storage"; private static final String UPLOADED_PATH_TEMPLATE = "%s%s/%s"; private final RemoteFilesStorage remoteFilesStorage; private final FolioExecutionContext folioExecutionContext; - private final ObjectMapper ediObjectMapper; @Value("${spring.application.name}") protected String springApplicationName; @Override @SneakyThrows - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) { + public RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) { // retrieve parameters from job context - var jobParameters = chunkContext.getStepContext().getJobParameters(); - var ediExportConfig = ediObjectMapper.readValue((String) jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); - if (ediExportConfig.getIntegrationType() != ORDERING && ediExportConfig.getTransmissionMethod() != FILE_DOWNLOAD) { - log.info("execute:: Transmission method is not File Download, skipping the step"); - return RepeatStatus.FINISHED; - } - var stepExecution = chunkContext.getStepContext().getStepExecution(); var edifactOrderAsString = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, ACQ_EXPORT_FILE); var fullFilePath = buildFullFilePath(stepExecution); From 78f5693a672058316f6ad61593f30afb49bcfe4a Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Mon, 30 Dec 2024 17:01:49 +0400 Subject: [PATCH 21/24] [MODEXPS-273] Use Job Deciders for conditional logic --- .../edifact/jobs/EdifactExportJobConfig.java | 37 +++++++++--- .../edifact/jobs/ExportHistoryTasklet.java | 11 +--- .../edifact/jobs/FilterableTasklet.java | 56 ------------------- .../edifact/jobs/MapToEdifactTasklet.java | 5 +- .../jobs/SaveToFileStorageTasklet.java | 19 ++----- .../edifact/jobs/SaveToMinioTasklet.java | 6 +- .../decider/ExportHistoryTaskletDecider.java | 30 ++++++++++ .../jobs/decider/ExportStepDecider.java | 39 +++++++++++++ .../jobs/decider/ExportStepDecision.java | 15 +++++ .../SaveToFileStorageTaskletDecider.java | 31 ++++++++++ 10 files changed, 158 insertions(+), 91 deletions(-) delete mode 100644 src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/FilterableTasklet.java create mode 100644 src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportHistoryTaskletDecider.java create mode 100644 src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportStepDecider.java create mode 100644 src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportStepDecision.java create mode 100644 src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/SaveToFileStorageTaskletDecider.java diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java index 406491b3f..19d3ddaa6 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java @@ -1,11 +1,18 @@ package org.folio.dew.batch.acquisitions.edifact.jobs; +import java.util.Map; + import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; + +import org.folio.dew.batch.acquisitions.edifact.jobs.decider.ExportHistoryTaskletDecider; +import org.folio.dew.batch.acquisitions.edifact.jobs.decider.ExportStepDecision; +import org.folio.dew.batch.acquisitions.edifact.jobs.decider.SaveToFileStorageTaskletDecider; import org.folio.dew.domain.dto.ExportType; 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.job.flow.JobExecutionDecider; import org.springframework.batch.core.launch.support.RunIdIncrementer; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -25,28 +32,33 @@ private Job constructEdifactExportJob(JobBuilder jobBuilder, Step mapToFileStep, Step saveToMinIOStep, Step saveToFTPStep, - Step createExportHistoryRecordsStep) { + Step createExportHistoryRecordsStep, + Map optionalStepDeciders) { return jobBuilder.incrementer(new RunIdIncrementer()) .listener(ediExportJobCompletionListener) .start(mapToFileStep) .next(saveToMinIOStep) - .next(saveToFTPStep) - .next(createExportHistoryRecordsStep) - .build(); + .next(optionalStepDeciders.get(saveToFTPStep)) + .on(ExportStepDecision.PROCESS.getStatus()).to(saveToFTPStep) + .next(optionalStepDeciders.get(createExportHistoryRecordsStep)) + .on(ExportStepDecision.PROCESS.getStatus()).to(createExportHistoryRecordsStep) + .end().build(); } @Bean public Job edifactOrdersExportJob(EdiExportJobCompletionListener ediExportJobCompletionListener, JobRepository jobRepository, - Step mapToEdifactOrdersStep, Step saveToFTPStep, Step saveToMinIOStep, Step createExportHistoryRecordsStep) { + Step mapToEdifactOrdersStep, Step saveToFTPStep, Step saveToMinIOStep, Step createExportHistoryRecordsStep, + Map deciders) { return constructEdifactExportJob(new JobBuilder(ExportType.EDIFACT_ORDERS_EXPORT.getValue(), jobRepository), - ediExportJobCompletionListener, mapToEdifactOrdersStep, saveToFTPStep, saveToMinIOStep, createExportHistoryRecordsStep); + ediExportJobCompletionListener, mapToEdifactOrdersStep, saveToFTPStep, saveToMinIOStep, createExportHistoryRecordsStep, deciders); } @Bean public Job edifactClaimsExportJob(EdiExportJobCompletionListener ediExportJobCompletionListener, JobRepository jobRepository, - Step mapToEdifactClaimsStep, Step saveToFTPStep, Step saveToMinIOStep, Step createExportHistoryRecordsStep) { + Step mapToEdifactClaimsStep, Step saveToFTPStep, Step saveToMinIOStep, Step createExportHistoryRecordsStep, + Map deciders) { return constructEdifactExportJob(new JobBuilder(ExportType.CLAIMS.getValue(), jobRepository), - ediExportJobCompletionListener, mapToEdifactClaimsStep, saveToFTPStep, saveToMinIOStep, createExportHistoryRecordsStep); + ediExportJobCompletionListener, mapToEdifactClaimsStep, saveToFTPStep, saveToMinIOStep, createExportHistoryRecordsStep, deciders); } @Bean @@ -89,4 +101,13 @@ public Step createExportHistoryRecordsStep(ExportHistoryTasklet exportHistoryTas .build(); } + @Bean + public Map optionalStepDeciders(Step saveToFTPStep, SaveToFileStorageTaskletDecider saveToFileStorageTaskletDecider, + Step createExportHistoryRecordsStep, ExportHistoryTaskletDecider exportHistoryTaskletDecider) { + return Map.of( + saveToFTPStep, saveToFileStorageTaskletDecider, + createExportHistoryRecordsStep, exportHistoryTaskletDecider + ); + } + } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java index 33f6a35f4..3627131a1 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java @@ -3,7 +3,6 @@ import static org.folio.dew.batch.acquisitions.edifact.jobs.EdifactExportJobConfig.POL_MEM_KEY; import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; -import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.ORDERING; import java.util.Collections; import java.util.Date; @@ -23,6 +22,7 @@ import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -34,7 +34,7 @@ @Component @StepScope @Log4j2 -public class ExportHistoryTasklet extends FilterableTasklet { +public class ExportHistoryTasklet implements Tasklet { private final KafkaService kafkaService; private final ObjectMapper ediObjectMapper; @@ -43,7 +43,7 @@ public class ExportHistoryTasklet extends FilterableTasklet { @Value("#{jobParameters['jobId']}") private String jobId; @Override - public RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) { + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) { var exportHistory = buildExportHistory(chunkContext); kafkaService.send(KafkaService.Topic.EXPORT_HISTORY_CREATE, null, exportHistory); @@ -84,9 +84,4 @@ List getPoLineIdsFromExecutionContext(StepExecution stepExecutionContext } } - @Override - protected boolean shouldExecute(VendorEdiOrdersExportConfig exportConfig) { - return exportConfig.getIntegrationType() == ORDERING; - } - } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/FilterableTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/FilterableTasklet.java deleted file mode 100644 index 7f4b69a4b..000000000 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/FilterableTasklet.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.folio.dew.batch.acquisitions.edifact.jobs; - -import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; - -import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.core.step.tasklet.Tasklet; -import org.springframework.batch.repeat.RepeatStatus; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import lombok.RequiredArgsConstructor; -import lombok.experimental.SuperBuilder; -import lombok.extern.log4j.Log4j2; - -@RequiredArgsConstructor -@Log4j2 -@SuperBuilder -public abstract class FilterableTasklet implements Tasklet { - - private final ObjectMapper objectMapper; - - @Override - public final RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { - var ediExportConfig = objectMapper.readValue((String) chunkContext.getStepContext().getJobParameters().get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); - if (shouldExecute(ediExportConfig)) { - return execute(ediExportConfig, contribution, chunkContext); - } - return RepeatStatus.FINISHED; - } - - /** - * Check if the tasklet should be executed, by default always returns true. - * Override this method to provide custom logic. - * - * @param exportConfig the export configuration - * @return true if the tasklet should be executed - */ - protected boolean shouldExecute(VendorEdiOrdersExportConfig exportConfig) { - return true; - } - - - /** - * This method should be overridden to provide the tasklet logic with predefined filtering. - * - * @param exportConfig the export configuration - * @param contribution the step contribution - * @param chunkContext the chunk context - * @return the repeat status - * @throws Exception if an error occurs - */ - protected abstract RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) throws Exception; - -} diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java index 1a831ec40..4118d030e 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java @@ -36,6 +36,7 @@ import org.folio.dew.error.NotFoundException; import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; import com.fasterxml.jackson.core.JsonProcessingException; @@ -47,14 +48,14 @@ @SuperBuilder @Log4j2 -public abstract class MapToEdifactTasklet extends FilterableTasklet { +public abstract class MapToEdifactTasklet implements Tasklet { private final ObjectMapper ediObjectMapper; private final OrganizationsService organizationsService; protected final OrdersService ordersService; @Override - public RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) throws Exception { + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { log.info("execute:: Executing MapToEdifactTasklet with job: {}", chunkContext.getStepContext().getJobName()); var jobParameters = chunkContext.getStepContext().getJobParameters(); var ediExportConfig = ediObjectMapper.readValue((String) jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java index bce1c7678..7ecbd27a9 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java @@ -2,8 +2,7 @@ import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME; -import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.ORDERING; -import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FTP; +import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import java.nio.charset.StandardCharsets; @@ -14,6 +13,7 @@ import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; import org.springframework.stereotype.Component; @@ -27,7 +27,7 @@ @Component @StepScope @Log4j2 -public class SaveToFileStorageTasklet extends FilterableTasklet { +public class SaveToFileStorageTasklet implements Tasklet { private static final String SFTP_PROTOCOL = "sftp://"; @@ -36,7 +36,8 @@ public class SaveToFileStorageTasklet extends FilterableTasklet { @Override @SneakyThrows - public RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) { + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) { + var exportConfig = ediObjectMapper.readValue((String) chunkContext.getStepContext().getJobParameters().get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); String host = exportConfig.getEdiFtp().getServerAddress().replace(SFTP_PROTOCOL, ""); // skip ftp upload if address not specified if (StringUtils.isEmpty(host)) { @@ -51,14 +52,4 @@ public RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContri return RepeatStatus.FINISHED; } - @Override - protected boolean shouldExecute(VendorEdiOrdersExportConfig exportConfig) { - // Always execute if the integration type is not ORDERING, or execute for other integration types if the transmission method is FTP - if (exportConfig.getIntegrationType() == ORDERING || exportConfig.getTransmissionMethod() == FTP) { - return true; - } - log.info("execute:: Transmission method is not FTP, skipping the step"); - return false; - } - } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java index 6bf34ba58..891e1d359 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java @@ -10,13 +10,13 @@ import org.folio.dew.batch.ExecutionContextUtils; import org.folio.dew.batch.acquisitions.edifact.exceptions.EdifactException; -import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; import org.folio.dew.repository.RemoteFilesStorage; import org.folio.spring.FolioExecutionContext; import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -29,7 +29,7 @@ @Component @StepScope @Log4j2 -public class SaveToMinioTasklet extends FilterableTasklet { +public class SaveToMinioTasklet implements Tasklet { private static final String REMOTE_STORAGE_ERROR_MESSAGE = "Failed to save edifact file to remote storage"; private static final String UPLOADED_PATH_TEMPLATE = "%s%s/%s"; @@ -42,7 +42,7 @@ public class SaveToMinioTasklet extends FilterableTasklet { @Override @SneakyThrows - public RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) { + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) { // retrieve parameters from job context var stepExecution = chunkContext.getStepContext().getStepExecution(); var edifactOrderAsString = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, ACQ_EXPORT_FILE); diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportHistoryTaskletDecider.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportHistoryTaskletDecider.java new file mode 100644 index 000000000..f6e8f9799 --- /dev/null +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportHistoryTaskletDecider.java @@ -0,0 +1,30 @@ +package org.folio.dew.batch.acquisitions.edifact.jobs.decider; + +import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.ORDERING; + +import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.stereotype.Component; + +import lombok.experimental.SuperBuilder; +import lombok.extern.log4j.Log4j2; + +@SuperBuilder +@Component +@StepScope +@Log4j2 +public class ExportHistoryTaskletDecider extends ExportStepDecider { + + @Override + public ExportStepDecision decide(VendorEdiOrdersExportConfig exportConfig, JobExecution jobExecution, StepExecution stepExecution) { + // Always execute if the integration type is not ORDERING, or execute for other integration types if the transmission method is FTP + if (exportConfig.getIntegrationType() == ORDERING) { + return ExportStepDecision.PROCESS; + } + log.info("decide:: Integration type is not ORDERING, skipping the step: {}", stepExecution.getStepName()); + return ExportStepDecision.SKIP; + } + +} diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportStepDecider.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportStepDecider.java new file mode 100644 index 000000000..0d7b4df99 --- /dev/null +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportStepDecider.java @@ -0,0 +1,39 @@ +package org.folio.dew.batch.acquisitions.edifact.jobs.decider; + +import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; + +import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; +import org.springframework.batch.core.job.flow.JobExecutionDecider; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.SneakyThrows; +import lombok.experimental.SuperBuilder; + +@SuperBuilder +public abstract class ExportStepDecider implements JobExecutionDecider { + + private final ObjectMapper objectMapper; + + @Override + @SneakyThrows + public final FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) { + var exportConfig = objectMapper.readValue(jobExecution.getJobParameters().getString(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class); + return new FlowExecutionStatus(decide(exportConfig, jobExecution, stepExecution).getStatus()); + } + + /** + * Evaluate the decision to execute the step or not using the provided export configuration, job execution and step + * + * @param exportConfig export configuration + * @param jobExecution job execution + * @param stepExecution step execution + * @return the decision to execute the step or not + * @throws Exception if an error occurs during the decision process + */ + protected abstract ExportStepDecision decide(VendorEdiOrdersExportConfig exportConfig, JobExecution jobExecution, StepExecution stepExecution) throws Exception; + +} diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportStepDecision.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportStepDecision.java new file mode 100644 index 000000000..1eae413b5 --- /dev/null +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportStepDecision.java @@ -0,0 +1,15 @@ +package org.folio.dew.batch.acquisitions.edifact.jobs.decider; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public enum ExportStepDecision { + + PROCESS("PROCESS"), + SKIP("SKIP"); + + private final String status; + +} diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/SaveToFileStorageTaskletDecider.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/SaveToFileStorageTaskletDecider.java new file mode 100644 index 000000000..948301a8c --- /dev/null +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/SaveToFileStorageTaskletDecider.java @@ -0,0 +1,31 @@ +package org.folio.dew.batch.acquisitions.edifact.jobs.decider; + +import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.ORDERING; +import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FTP; + +import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.stereotype.Component; + +import lombok.experimental.SuperBuilder; +import lombok.extern.log4j.Log4j2; + +@SuperBuilder +@Component +@StepScope +@Log4j2 +public class SaveToFileStorageTaskletDecider extends ExportStepDecider { + + @Override + public ExportStepDecision decide(VendorEdiOrdersExportConfig exportConfig, JobExecution jobExecution, StepExecution stepExecution) { + // Always execute if the integration type is ORDERING, or other integration type if the transmission method is FTP + if (exportConfig.getIntegrationType() == ORDERING || exportConfig.getTransmissionMethod() == FTP) { + return ExportStepDecision.PROCESS; + } + log.info("decide:: Transmission method is not FTP, skipping the step: {}", stepExecution.getStepName()); + return ExportStepDecision.SKIP; + } + +} From 2d8aeed875be29b79832bd1c8047f672ec0fba1a Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Mon, 30 Dec 2024 17:49:19 +0400 Subject: [PATCH 22/24] [MODEXPS-273] Remove @SuperBuilder --- .../edifact/jobs/EdifactExportJobConfig.java | 25 ++++++++++--------- .../edifact/jobs/ExportHistoryTasklet.java | 5 ++-- .../jobs/MapToEdifactClaimsTasklet.java | 12 +++++++-- .../jobs/MapToEdifactOrdersTasklet.java | 13 ++++++++-- .../edifact/jobs/MapToEdifactTasklet.java | 4 +-- .../jobs/SaveToFileStorageTasklet.java | 4 +-- .../edifact/jobs/SaveToMinioTasklet.java | 4 +-- .../decider/ExportHistoryTaskletDecider.java | 12 ++++----- .../jobs/decider/ExportStepDecider.java | 4 +-- .../SaveToFileStorageTaskletDecider.java | 12 ++++----- 10 files changed, 57 insertions(+), 38 deletions(-) diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java index 19d3ddaa6..b16386984 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/EdifactExportJobConfig.java @@ -20,6 +20,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; +import com.fasterxml.jackson.databind.ObjectMapper; + @Configuration @Log4j2 @RequiredArgsConstructor @@ -30,25 +32,25 @@ public class EdifactExportJobConfig { private Job constructEdifactExportJob(JobBuilder jobBuilder, EdiExportJobCompletionListener ediExportJobCompletionListener, Step mapToFileStep, - Step saveToMinIOStep, Step saveToFTPStep, + Step saveToMinIOStep, Step createExportHistoryRecordsStep, - Map optionalStepDeciders) { + Map optionalStepDeciders) { return jobBuilder.incrementer(new RunIdIncrementer()) .listener(ediExportJobCompletionListener) .start(mapToFileStep) .next(saveToMinIOStep) - .next(optionalStepDeciders.get(saveToFTPStep)) - .on(ExportStepDecision.PROCESS.getStatus()).to(saveToFTPStep) - .next(optionalStepDeciders.get(createExportHistoryRecordsStep)) - .on(ExportStepDecision.PROCESS.getStatus()).to(createExportHistoryRecordsStep) + .next(optionalStepDeciders.get(saveToFTPStep.getName())) + .on(ExportStepDecision.PROCESS.getStatus()).to(saveToFTPStep) + .next(optionalStepDeciders.get(createExportHistoryRecordsStep.getName())) + .on(ExportStepDecision.PROCESS.getStatus()).to(createExportHistoryRecordsStep) .end().build(); } @Bean public Job edifactOrdersExportJob(EdiExportJobCompletionListener ediExportJobCompletionListener, JobRepository jobRepository, Step mapToEdifactOrdersStep, Step saveToFTPStep, Step saveToMinIOStep, Step createExportHistoryRecordsStep, - Map deciders) { + Map deciders) { return constructEdifactExportJob(new JobBuilder(ExportType.EDIFACT_ORDERS_EXPORT.getValue(), jobRepository), ediExportJobCompletionListener, mapToEdifactOrdersStep, saveToFTPStep, saveToMinIOStep, createExportHistoryRecordsStep, deciders); } @@ -56,7 +58,7 @@ public Job edifactOrdersExportJob(EdiExportJobCompletionListener ediExportJobCom @Bean public Job edifactClaimsExportJob(EdiExportJobCompletionListener ediExportJobCompletionListener, JobRepository jobRepository, Step mapToEdifactClaimsStep, Step saveToFTPStep, Step saveToMinIOStep, Step createExportHistoryRecordsStep, - Map deciders) { + Map deciders) { return constructEdifactExportJob(new JobBuilder(ExportType.CLAIMS.getValue(), jobRepository), ediExportJobCompletionListener, mapToEdifactClaimsStep, saveToFTPStep, saveToMinIOStep, createExportHistoryRecordsStep, deciders); } @@ -102,11 +104,10 @@ public Step createExportHistoryRecordsStep(ExportHistoryTasklet exportHistoryTas } @Bean - public Map optionalStepDeciders(Step saveToFTPStep, SaveToFileStorageTaskletDecider saveToFileStorageTaskletDecider, - Step createExportHistoryRecordsStep, ExportHistoryTaskletDecider exportHistoryTaskletDecider) { + public Map optionalStepDeciders(Step saveToFTPStep, Step createExportHistoryRecordsStep, ObjectMapper objectMapper) { return Map.of( - saveToFTPStep, saveToFileStorageTaskletDecider, - createExportHistoryRecordsStep, exportHistoryTaskletDecider + saveToFTPStep.getName(), new SaveToFileStorageTaskletDecider(objectMapper), + createExportHistoryRecordsStep.getName(), new ExportHistoryTaskletDecider(objectMapper) ); } diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java index 3627131a1..0d50701c1 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTasklet.java @@ -11,6 +11,8 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import org.folio.dew.batch.ExecutionContextUtils; import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; @@ -27,10 +29,9 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import lombok.experimental.SuperBuilder; import lombok.extern.log4j.Log4j2; -@SuperBuilder +@RequiredArgsConstructor @Component @StepScope @Log4j2 diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java index ff445b534..0d0753063 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactClaimsTasklet.java @@ -14,6 +14,8 @@ import org.apache.commons.collections4.CollectionUtils; import org.folio.dew.batch.acquisitions.edifact.mapper.ExportResourceMapper; +import org.folio.dew.batch.acquisitions.edifact.services.OrdersService; +import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; import org.folio.dew.domain.dto.Piece; import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; import org.folio.dew.domain.dto.acquisitions.edifact.ExportHolder; @@ -21,9 +23,8 @@ import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.stereotype.Component; -import lombok.experimental.SuperBuilder; +import com.fasterxml.jackson.databind.ObjectMapper; -@SuperBuilder @Component @StepScope public class MapToEdifactClaimsTasklet extends MapToEdifactTasklet { @@ -31,6 +32,13 @@ public class MapToEdifactClaimsTasklet extends MapToEdifactTasklet { private final ExportResourceMapper edifactMapper; private final ExportResourceMapper csvMapper; + public MapToEdifactClaimsTasklet(ObjectMapper ediObjectMapper, OrganizationsService organizationsService, OrdersService ordersService, + ExportResourceMapper edifactMapper, ExportResourceMapper csvMapper) { + super(ediObjectMapper, organizationsService, ordersService); + this.edifactMapper = edifactMapper; + this.csvMapper = csvMapper; + } + @Override protected ExportResourceMapper getExportResourceMapper(VendorEdiOrdersExportConfig ediOrdersExportConfig) { return switch (ediOrdersExportConfig.getFileFormat()) { diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java index 24f905be7..d468ed54c 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactOrdersTasklet.java @@ -21,6 +21,8 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.folio.dew.batch.acquisitions.edifact.mapper.ExportResourceMapper; +import org.folio.dew.batch.acquisitions.edifact.services.OrdersService; +import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService; import org.folio.dew.client.DataExportSpringClient; import org.folio.dew.domain.dto.ExportConfigCollection; import org.folio.dew.domain.dto.ExportType; @@ -29,10 +31,10 @@ import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.stereotype.Component; -import lombok.experimental.SuperBuilder; +import com.fasterxml.jackson.databind.ObjectMapper; + import lombok.extern.log4j.Log4j2; -@SuperBuilder @Component @StepScope @Log4j2 @@ -41,6 +43,13 @@ public class MapToEdifactOrdersTasklet extends MapToEdifactTasklet { private final DataExportSpringClient dataExportSpringClient; private final ExportResourceMapper edifactMapper; + public MapToEdifactOrdersTasklet(ObjectMapper ediObjectMapper, OrganizationsService organizationsService, OrdersService ordersService, + DataExportSpringClient dataExportSpringClient, ExportResourceMapper edifactMapper) { + super(ediObjectMapper, organizationsService, ordersService); + this.dataExportSpringClient = dataExportSpringClient; + this.edifactMapper = edifactMapper; + } + @Override protected List getExportConfigMissingFields(VendorEdiOrdersExportConfig ediOrdersExportConfig) { List missingFields = new ArrayList<>(); diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java index 4118d030e..2402cb8b7 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/MapToEdifactTasklet.java @@ -43,10 +43,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.xlate.edi.stream.EDIStreamException; -import lombok.experimental.SuperBuilder; +import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; -@SuperBuilder +@RequiredArgsConstructor @Log4j2 public abstract class MapToEdifactTasklet implements Tasklet { diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java index 7ecbd27a9..8570ad675 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToFileStorageTasklet.java @@ -19,11 +19,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; -import lombok.experimental.SuperBuilder; import lombok.extern.log4j.Log4j2; -@SuperBuilder +@RequiredArgsConstructor @Component @StepScope @Log4j2 diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java index 891e1d359..a5af973bf 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/SaveToMinioTasklet.java @@ -21,11 +21,11 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; -import lombok.experimental.SuperBuilder; import lombok.extern.log4j.Log4j2; -@SuperBuilder +@RequiredArgsConstructor @Component @StepScope @Log4j2 diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportHistoryTaskletDecider.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportHistoryTaskletDecider.java index f6e8f9799..f0bd655bd 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportHistoryTaskletDecider.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportHistoryTaskletDecider.java @@ -5,18 +5,18 @@ import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.stereotype.Component; -import lombok.experimental.SuperBuilder; +import com.fasterxml.jackson.databind.ObjectMapper; + import lombok.extern.log4j.Log4j2; -@SuperBuilder -@Component -@StepScope @Log4j2 public class ExportHistoryTaskletDecider extends ExportStepDecider { + public ExportHistoryTaskletDecider(ObjectMapper objectMapper) { + super(objectMapper); + } + @Override public ExportStepDecision decide(VendorEdiOrdersExportConfig exportConfig, JobExecution jobExecution, StepExecution stepExecution) { // Always execute if the integration type is not ORDERING, or execute for other integration types if the transmission method is FTP diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportStepDecider.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportStepDecider.java index 0d7b4df99..fdb4f7ed4 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportStepDecider.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportStepDecider.java @@ -10,10 +10,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; -import lombok.experimental.SuperBuilder; -@SuperBuilder +@RequiredArgsConstructor public abstract class ExportStepDecider implements JobExecutionDecider { private final ObjectMapper objectMapper; diff --git a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/SaveToFileStorageTaskletDecider.java b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/SaveToFileStorageTaskletDecider.java index 948301a8c..1d1e5c0e8 100644 --- a/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/SaveToFileStorageTaskletDecider.java +++ b/src/main/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/SaveToFileStorageTaskletDecider.java @@ -6,18 +6,18 @@ import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.stereotype.Component; -import lombok.experimental.SuperBuilder; +import com.fasterxml.jackson.databind.ObjectMapper; + import lombok.extern.log4j.Log4j2; -@SuperBuilder -@Component -@StepScope @Log4j2 public class SaveToFileStorageTaskletDecider extends ExportStepDecider { + public SaveToFileStorageTaskletDecider(ObjectMapper objectMapper) { + super(objectMapper); + } + @Override public ExportStepDecision decide(VendorEdiOrdersExportConfig exportConfig, JobExecution jobExecution, StepExecution stepExecution) { // Always execute if the integration type is ORDERING, or other integration type if the transmission method is FTP From c7d2f6696b06f3f201d00a33e76cd7058b3077ec Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Mon, 30 Dec 2024 18:07:01 +0400 Subject: [PATCH 23/24] [MODEXPS-273] Fix failing test --- .../acquisitions/edifact/jobs/ExportHistoryTaskletTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTaskletTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTaskletTest.java index 51dcf13db..a798d4e8a 100644 --- a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTaskletTest.java +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/ExportHistoryTaskletTest.java @@ -21,6 +21,7 @@ import java.util.UUID; import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE; +import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME; import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT; import static org.folio.dew.domain.dto.JobParameterNames.JOB_ID; import static org.folio.dew.domain.dto.JobParameterNames.JOB_NAME; @@ -68,8 +69,7 @@ void testCreateExportHistoryWithCompleteStatus() throws IOException { protected ExecutionContext getExecutionContext() { ExecutionContext result = new ExecutionContext(); - result.put("edifactFileName", "test_file"); - + result.put(ACQ_EXPORT_FILE_NAME, "test_file"); return result; } From 3daefa74a55dd22b7f48ce2ff17efd26b8985084 Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Mon, 30 Dec 2024 18:26:54 +0400 Subject: [PATCH 24/24] [MODEXPS-273] Add tests for deciders --- .../java/org/folio/dew/CopilotGenerated.java | 26 ++++++++ .../ExportHistoryTaskletDeciderTest.java | 50 +++++++++++++++ .../SaveToFileStorageTaskletDeciderTest.java | 64 +++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 src/test/java/org/folio/dew/CopilotGenerated.java create mode 100644 src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportHistoryTaskletDeciderTest.java create mode 100644 src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/SaveToFileStorageTaskletDeciderTest.java diff --git a/src/test/java/org/folio/dew/CopilotGenerated.java b/src/test/java/org/folio/dew/CopilotGenerated.java new file mode 100644 index 000000000..c272ab7bb --- /dev/null +++ b/src/test/java/org/folio/dew/CopilotGenerated.java @@ -0,0 +1,26 @@ +package org.folio.dew; + +import org.springframework.core.annotation.AliasFor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to indicate that test(s) in the class are generated by GitHub Copilot. + *

+ * Set value or partiallyGenerated attribute to true + * if the generated test(s) were significantly modified/altered by the developer. + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.SOURCE) +public @interface CopilotGenerated { + + @AliasFor("partiallyGenerated") + boolean value() default false; + + @AliasFor("value") + boolean partiallyGenerated() default false; + +} diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportHistoryTaskletDeciderTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportHistoryTaskletDeciderTest.java new file mode 100644 index 000000000..9164c0401 --- /dev/null +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/ExportHistoryTaskletDeciderTest.java @@ -0,0 +1,50 @@ +package org.folio.dew.batch.acquisitions.edifact.jobs.decider; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; + +import org.folio.dew.CopilotGenerated; +import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; +import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; + +import com.fasterxml.jackson.databind.ObjectMapper; + +@CopilotGenerated +class ExportHistoryTaskletDeciderTest { + + private ExportHistoryTaskletDecider decider; + + @BeforeEach + void setUp() { + decider = new ExportHistoryTaskletDecider(new ObjectMapper()); + } + + @Test + void decide_shouldProcess_whenIntegrationTypeIsOrdering() { + VendorEdiOrdersExportConfig config = new VendorEdiOrdersExportConfig(); + config.setIntegrationType(IntegrationTypeEnum.ORDERING); + JobExecution jobExecution = mock(JobExecution.class); + StepExecution stepExecution = mock(StepExecution.class); + + ExportStepDecision decision = decider.decide(config, jobExecution, stepExecution); + + assertEquals(ExportStepDecision.PROCESS, decision); + } + + @Test + void decide_shouldSkip_whenIntegrationTypeIsNotOrdering() { + VendorEdiOrdersExportConfig config = new VendorEdiOrdersExportConfig(); + config.setIntegrationType(IntegrationTypeEnum.CLAIMING); + JobExecution jobExecution = mock(JobExecution.class); + StepExecution stepExecution = mock(StepExecution.class); + + ExportStepDecision decision = decider.decide(config, jobExecution, stepExecution); + + assertEquals(ExportStepDecision.SKIP, decision); + } + +} diff --git a/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/SaveToFileStorageTaskletDeciderTest.java b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/SaveToFileStorageTaskletDeciderTest.java new file mode 100644 index 000000000..73624e599 --- /dev/null +++ b/src/test/java/org/folio/dew/batch/acquisitions/edifact/jobs/decider/SaveToFileStorageTaskletDeciderTest.java @@ -0,0 +1,64 @@ +package org.folio.dew.batch.acquisitions.edifact.jobs.decider; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; + +import org.folio.dew.CopilotGenerated; +import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig; +import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum; +import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; + +import com.fasterxml.jackson.databind.ObjectMapper; + +@CopilotGenerated +class SaveToFileStorageTaskletDeciderTest { + + private SaveToFileStorageTaskletDecider decider; + + @BeforeEach + void setUp() { + decider = new SaveToFileStorageTaskletDecider(new ObjectMapper()); + } + + @Test + void decide_shouldProcess_whenIntegrationTypeIsOrdering() { + VendorEdiOrdersExportConfig config = new VendorEdiOrdersExportConfig(); + config.setIntegrationType(IntegrationTypeEnum.ORDERING); + JobExecution jobExecution = mock(JobExecution.class); + StepExecution stepExecution = mock(StepExecution.class); + + ExportStepDecision decision = decider.decide(config, jobExecution, stepExecution); + + assertEquals(ExportStepDecision.PROCESS, decision); + } + + @Test + void decide_shouldProcess_whenTransmissionMethodIsFtp() { + VendorEdiOrdersExportConfig config = new VendorEdiOrdersExportConfig(); + config.setIntegrationType(IntegrationTypeEnum.CLAIMING); + config.setTransmissionMethod(TransmissionMethodEnum.FTP); + JobExecution jobExecution = mock(JobExecution.class); + StepExecution stepExecution = mock(StepExecution.class); + + ExportStepDecision decision = decider.decide(config, jobExecution, stepExecution); + + assertEquals(ExportStepDecision.PROCESS, decision); + } + + @Test + void decide_shouldSkip_whenIntegrationTypeIsNotOrderingAndTransmissionMethodIsNotFtp() { + VendorEdiOrdersExportConfig config = new VendorEdiOrdersExportConfig(); + config.setIntegrationType(IntegrationTypeEnum.CLAIMING); + config.setTransmissionMethod(TransmissionMethodEnum.FILE_DOWNLOAD); + JobExecution jobExecution = mock(JobExecution.class); + StepExecution stepExecution = mock(StepExecution.class); + + ExportStepDecision decision = decider.decide(config, jobExecution, stepExecution); + + assertEquals(ExportStepDecision.SKIP, decision); + } +}