From cfda6a8217215b4503f5d89fe168b96f9afe74b7 Mon Sep 17 00:00:00 2001 From: Maverick Studer Date: Mon, 3 Jun 2024 12:36:20 +0200 Subject: [PATCH] RED-9254: Support Controller (Part 1) --- .../impl/controller/SupportController.java | 125 +++++++++++++++++ .../external/resource/SupportResource.java | 101 ++++++++++++++ .../v1/processor/roles/ActionRoles.java | 4 + .../v1/processor/roles/ApplicationRoles.java | 24 +++- .../service/FileStatusManagementService.java | 16 +++ .../processor/service/FileStatusService.java | 24 ++++ .../processor/service/ReanalysisService.java | 89 +++++++++--- .../FileStatusPersistenceService.java | 17 +++ .../integration/client/SupportClient.java | 11 ++ .../tests/SupportControllerTest.java | 131 ++++++++++++++++++ .../v1/api/shared/model/FileStatusFilter.java | 21 +++ 11 files changed, 541 insertions(+), 22 deletions(-) create mode 100644 persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/SupportController.java create mode 100644 persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/SupportResource.java create mode 100644 persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/client/SupportClient.java create mode 100644 persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/SupportControllerTest.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/FileStatusFilter.java diff --git a/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/SupportController.java b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/SupportController.java new file mode 100644 index 000000000..02c884c32 --- /dev/null +++ b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/SupportController.java @@ -0,0 +1,125 @@ +package com.iqser.red.persistence.service.v1.external.api.impl.controller; + +import static com.iqser.red.service.persistence.management.v1.processor.roles.ActionRoles.USE_SUPPORT_CONTROLLER; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.google.common.collect.Sets; +import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusManagementService; +import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusMapper; +import com.iqser.red.service.persistence.management.v1.processor.service.ReanalysisService; +import com.iqser.red.service.persistence.service.v1.api.external.resource.SupportResource; +import com.iqser.red.service.persistence.service.v1.api.shared.model.FileStatus; +import com.iqser.red.service.persistence.service.v1.api.shared.model.FileStatusFilter; +import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileModel; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestController +@RequiredArgsConstructor +@PreAuthorize("hasAuthority('" + USE_SUPPORT_CONTROLLER + "')") +public class SupportController implements SupportResource { + + private final ReanalysisService reanalysisService; + private final FileStatusManagementService fileStatusManagementService; + + + @Override + public void reanalyzeAllErrorFiles(@RequestParam(value = FULL_ANALYSIS_PARAM, required = false, defaultValue = FALSE) boolean fullAnalysis) { + + reanalysisService.reanalyzeAllErrorFiles(fullAnalysis); + } + + + @Override + public void reanalyzeErrorFilesForDossier(@PathVariable(DOSSIER_ID) String dossierId, + @RequestParam(value = FULL_ANALYSIS_PARAM, required = false, defaultValue = FALSE) boolean fullAnalysis) { + + reanalysisService.reanalyzeErrorFilesInDossier(dossierId, fullAnalysis); + } + + + @Override + public void reanalyzeErrorFilesBulkForDossier(@PathVariable(DOSSIER_ID) String dossierId, + @RequestBody List fileIds, + @RequestParam(value = FULL_ANALYSIS_PARAM, required = false, defaultValue = FALSE) boolean fullAnalysis) { + + reanalysisService.reanalyzeGivenErrorFilesInDossier(dossierId, new HashSet<>(fileIds), fullAnalysis); + + } + + + @Override + public void reanalyzeErrorFile(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestParam(value = FULL_ANALYSIS_PARAM, required = false, defaultValue = FALSE) boolean fullAnalysis) { + + reanalysisService.reanalyzeGivenErrorFilesInDossier(dossierId, Sets.newHashSet(fileId), fullAnalysis); + } + + + private static Predicate matchesStatusFilters(FileStatusFilter fileStatusFilter) { + + FileStatusFilter filter = Optional.ofNullable(fileStatusFilter).orElseGet(FileStatusFilter::new); + + if (filter.getProcessingStatusList() == null) { + filter.setProcessingStatusList(new ArrayList<>()); + } + + if (filter.getWorkflowStatusList() == null) { + filter.setWorkflowStatusList(new ArrayList<>()); + } + + return fileStatus -> + (filter.getProcessingStatusList().isEmpty() || filter.getProcessingStatusList().contains(fileStatus.getProcessingStatus())) && + (filter.getWorkflowStatusList().isEmpty() || filter.getWorkflowStatusList().contains(fileStatus.getWorkflowStatus())); + } + + + + @Override + public List getFileStatus(@RequestBody FileStatusFilter fileStatusFilter) { + + return fileStatusManagementService.getAllFileStatuses() + .stream() + .filter(matchesStatusFilters(fileStatusFilter)) + .map(FileStatusMapper::toFileStatus) + .collect(Collectors.toList()); + } + + + @Override + public List getFileStatusForDossierTemplate(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId, @RequestBody FileStatusFilter fileStatusFilter) { + + return fileStatusManagementService.getDossierTemplateStatus(dossierTemplateId) + .stream() + .filter(matchesStatusFilters(fileStatusFilter)) + .map(FileStatusMapper::toFileStatus) + .collect(Collectors.toList()); + } + + + @Override + public List getFileStatusForDossier(@PathVariable(DOSSIER_ID) String dossierId, @RequestBody FileStatusFilter fileStatusFilter) { + + return fileStatusManagementService.getDossierStatus(dossierId) + .stream() + .filter(matchesStatusFilters(fileStatusFilter)) + .map(FileStatusMapper::toFileStatus) + .collect(Collectors.toList()); + } + +} diff --git a/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/SupportResource.java b/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/SupportResource.java new file mode 100644 index 000000000..7b44a3db0 --- /dev/null +++ b/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/SupportResource.java @@ -0,0 +1,101 @@ +package com.iqser.red.service.persistence.service.v1.api.external.resource; + +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +import com.iqser.red.service.persistence.service.v1.api.shared.model.FileStatus; +import com.iqser.red.service.persistence.service.v1.api.shared.model.FileStatusFilter; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +@ResponseStatus(value = HttpStatus.NO_CONTENT) +public interface SupportResource { + + String ERROR_REANALYSIS_REST_PATH = ExternalApi.BASE_PATH + "/error/reanalyze"; + + String STATUS_REST_PATH = ExternalApi.BASE_PATH + "/status/filter"; + + String BULK_REST_PATH = "/bulk"; + + String DOSSIER_TEMPLATE_ID = "dossierTemplateId"; + String DOSSIER_ID = "dossierId"; + String FILE_ID = "fileId"; + + String DOSSIER_ID_PATH_VARIABLE = "/{" + DOSSIER_ID + "}"; + String FILE_ID_PATH_VARIABLE = "/{" + FILE_ID + "}"; + String DOSSIER_TEMPLATE_DOSSIER_TEMPLATE_ID_PATH_VARIABLE = "/dossierTemplate/{" + DOSSIER_TEMPLATE_ID + "}"; + String DOSSIER_DOSSIER_ID_PATH_VARIABLE = "/dossier/{" + DOSSIER_ID + "}"; + + String FALSE = "false"; + + String FULL_ANALYSIS_PARAM = "fullAnalysis"; + + + @PostMapping(value = ERROR_REANALYSIS_REST_PATH) + @Operation(summary = "Reanalyze all files in error state", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK"), @ApiResponse(responseCode = "403", description = "Forbidden")}) + void reanalyzeAllErrorFiles(@RequestParam(value = FULL_ANALYSIS_PARAM, required = false, defaultValue = FALSE) boolean fullAnalysis); + + + @PostMapping(value = ERROR_REANALYSIS_REST_PATH + DOSSIER_ID_PATH_VARIABLE) + @Operation(summary = "Reanalyze all files in error state in a dossier", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found"), @ApiResponse(responseCode = "403", description = "Forbidden")}) + void reanalyzeErrorFilesForDossier(@PathVariable(DOSSIER_ID) String dossierId, + @RequestParam(value = FULL_ANALYSIS_PARAM, required = false, defaultValue = FALSE) boolean fullAnalysis); + + + @PostMapping(value = ERROR_REANALYSIS_REST_PATH + + DOSSIER_ID_PATH_VARIABLE + + BULK_REST_PATH) + @Operation(summary = "Reanalyze multiple files in error state for a dossier", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found"), @ApiResponse(responseCode = "403", description = "Forbidden")}) + void reanalyzeErrorFilesBulkForDossier(@PathVariable(DOSSIER_ID) String dossierId, + @RequestBody List fileIds, + @RequestParam(value = FULL_ANALYSIS_PARAM, required = false, defaultValue = FALSE) boolean fullAnalysis); + + + @PostMapping(value = ERROR_REANALYSIS_REST_PATH + + DOSSIER_ID_PATH_VARIABLE + + FILE_ID_PATH_VARIABLE) + @Operation(summary = "Reanalyze a file in error state", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found"), @ApiResponse(responseCode = "403", description = "Forbidden")}) + void reanalyzeErrorFile(@PathVariable(DOSSIER_ID) String dossierId, + @PathVariable(FILE_ID) String fileId, + @RequestParam(value = FULL_ANALYSIS_PARAM, required = false, defaultValue = FALSE) boolean fullAnalysis); + + + @ResponseStatus(value = HttpStatus.OK) + @ResponseBody + @PostMapping(value = STATUS_REST_PATH, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Get the filtered status for all files in a dossier.", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")}) + List getFileStatus(@RequestBody FileStatusFilter fileStatusFilter); + + + @ResponseStatus(value = HttpStatus.OK) + @ResponseBody + @PostMapping(value = STATUS_REST_PATH + DOSSIER_TEMPLATE_DOSSIER_TEMPLATE_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Get the filtered status for all files in a dossier template.", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")}) + List getFileStatusForDossierTemplate(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId, @RequestBody FileStatusFilter fileStatusFilter); + + + @ResponseStatus(value = HttpStatus.OK) + @ResponseBody + @PostMapping(value = STATUS_REST_PATH + DOSSIER_DOSSIER_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Get the filtered status for all files in a dossier.", description = "None") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")}) + List getFileStatusForDossier(@PathVariable(DOSSIER_ID) String dossierId, @RequestBody FileStatusFilter fileStatusFilter); + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ActionRoles.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ActionRoles.java index 73b62c34f..3b3594033 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ActionRoles.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ActionRoles.java @@ -176,6 +176,10 @@ public final class ActionRoles { public static final String DEPLOYMENT_INFO = "red-deployment-info"; + public static final String USE_SUPPORT_CONTROLLER = "red-use-support-controller"; + + + private ActionRoles() {} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ApplicationRoles.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ApplicationRoles.java index c5ea43146..f53538221 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ApplicationRoles.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ApplicationRoles.java @@ -80,6 +80,7 @@ import static com.iqser.red.service.persistence.management.v1.processor.roles.Ac import static com.iqser.red.service.persistence.management.v1.processor.roles.ActionRoles.UPDATE_NOTIFICATIONS; import static com.iqser.red.service.persistence.management.v1.processor.roles.ActionRoles.UPLOAD_FILE; import static com.iqser.red.service.persistence.management.v1.processor.roles.ActionRoles.UPLOAD_REPORT_TEMPLATE; +import static com.iqser.red.service.persistence.management.v1.processor.roles.ActionRoles.USE_SUPPORT_CONTROLLER; import static com.iqser.red.service.persistence.management.v1.processor.roles.ActionRoles.WRITE_APP_CONFIG; import static com.iqser.red.service.persistence.management.v1.processor.roles.ActionRoles.WRITE_COLORS; import static com.iqser.red.service.persistence.management.v1.processor.roles.ActionRoles.WRITE_DIGITAL_SIGNATURE; @@ -104,12 +105,27 @@ import com.google.common.collect.Sets; public final class ApplicationRoles { + public static final String KNECON_ADMIN_ROLE = "KNECON_ADMIN"; + public static final String KNECON_SUPPORT_ROLE = "KNECON_SUPPORT"; public static final String RED_USER_ROLE = "RED_USER"; public static final String RED_MANAGER_ROLE = "RED_MANAGER"; public static final String RED_ADMIN_ROLE = "RED_ADMIN"; public static final String RED_USER_ADMIN_ROLE = "RED_USER_ADMIN"; - public static final Set UNMAPPED_ACTION_ROLES = Sets.newHashSet(UNARCHIVE_DOSSIER, UPDATE_LICENSE, GET_RSS); + public static final Set UNMAPPED_ACTION_ROLES = Sets.newHashSet(UNARCHIVE_DOSSIER, UPDATE_LICENSE, GET_RSS, USE_SUPPORT_CONTROLLER); + + public static final Set KNECON_ADMIN_ACTION_ROLES = Sets.newHashSet(READ_LICENSE, + UPDATE_LICENSE, + GET_TENANTS, + CREATE_TENANT, + READ_USERS, + READ_ALL_USERS, + WRITE_USERS, + READ_SMTP_CONFIGURATION, + WRITE_SMTP_CONFIGURATION, + UNARCHIVE_DOSSIER, + USE_SUPPORT_CONTROLLER); + public static final Set KNECON_SUPPORT_ACTION_ROLES = Sets.newHashSet(KNECON_ADMIN_ACTION_ROLES); public static final Set RED_USER_ACTION_ROLES = Sets.newHashSet(ADD_COMMENT, READ_LICENSE, @@ -231,7 +247,11 @@ public final class ApplicationRoles { WRITE_USERS, READ_LICENSE); - public static final Map> ROLE_DATA = Map.of(RED_USER_ROLE, + public static final Map> ROLE_DATA = Map.of(KNECON_ADMIN_ROLE, + KNECON_ADMIN_ACTION_ROLES, + KNECON_SUPPORT_ROLE, + KNECON_SUPPORT_ACTION_ROLES, + RED_USER_ROLE, RED_USER_ACTION_ROLES, RED_MANAGER_ROLE, RED_MANAGER_ACTION_ROLES, diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusManagementService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusManagementService.java index 2e9b2f096..49d6728e4 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusManagementService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusManagementService.java @@ -33,6 +33,22 @@ public class FileStatusManagementService { } + public List getAllFileStatuses() { + + return fileStatusService.getAllFiles() + .stream() + .filter(f -> !f.isSoftOrHardDeleted()) + .collect(Collectors.toList()); + } + + public List getDossierTemplateStatus(String dossierTemplateId) { + + return fileStatusService.getDossierTemplateStatus(dossierTemplateId) + .stream() + .filter(f -> !f.isSoftOrHardDeleted()) + .collect(Collectors.toList()); + } + public List getDossierStatus(String dossierId) { return fileStatusService.getDossierStatus(dossierId) diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusService.java index 0440de55f..842997c7b 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusService.java @@ -125,6 +125,30 @@ public class FileStatusService { return reanalysisRequiredStatusService.enhanceFileStatusWithAnalysisRequirements(convertedList); } + @Transactional + public List getDossierTemplateStatus(String dossierTemplateId) { + + var fileEntities = new ArrayList<>(fileStatusPersistenceService.getStatusesForDossierTemplate(dossierTemplateId)); + var convertedList = MagicConverter.convert(fileEntities, FileModel.class, new FileModelMapper()); + return reanalysisRequiredStatusService.enhanceFileStatusWithAnalysisRequirements(convertedList); + } + + @Transactional + public List getAllFiles() { + + var fileEntities = new ArrayList<>(fileStatusPersistenceService.getAllFiles()); + var convertedList = MagicConverter.convert(fileEntities, FileModel.class, new FileModelMapper()); + return reanalysisRequiredStatusService.enhanceFileStatusWithAnalysisRequirements(convertedList); + } + + @Transactional + public List getAllErrorFiles() { + + var fileEntities = new ArrayList<>(fileStatusPersistenceService.getAllErrorFiles()); + var convertedList = MagicConverter.convert(fileEntities, FileModel.class, new FileModelMapper()); + return reanalysisRequiredStatusService.enhanceFileStatusWithAnalysisRequirements(convertedList); + } + public Set getFileIdentifiersWhereAnalysisFlagCalculationIsRequired() { diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/ReanalysisService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/ReanalysisService.java index 32d15de4a..47134587d 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/ReanalysisService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/ReanalysisService.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; +import java.util.function.Predicate; import java.util.stream.Collectors; @Slf4j @@ -40,39 +41,58 @@ public class ReanalysisService { private final PDFTronClient pDFTronRedactionClient; private final FileManagementStorageService fileManagementStorageService; + private final Predicate validFilesFilter = fileStatus -> !fileStatus.isSoftOrHardDeleted() && !fileStatus.getWorkflowStatus().equals(WorkflowStatus.APPROVED); + private final Predicate errorFilesFilter = fileStatus -> fileStatus.getProcessingStatus().equals(ProcessingStatus.ERROR); + + + public void reanalyzeAllErrorFiles(boolean fullAnalysis) { + + var errorFiles = fileStatusService.getAllErrorFiles(); + analyseFiles(fullAnalysis, errorFiles); + } public void reanalyzeDossier(String dossierId, boolean force) { - var relevantFiles = getAllFilesForDossier(dossierId, true); - reanalyseFiles(dossierId, force, relevantFiles); + var relevantFiles = getAllFilesForDossier(dossierId, validFilesFilter); + reanalyseFiles(force, relevantFiles); } - private List getAllFilesForDossier(String dossierId, boolean filterOnlyValidFiles) { + public void reanalyzeErrorFilesInDossier(String dossierId, boolean fullAnalysis) { + + var errorFiles = getAllFilesForDossier(dossierId, errorFilesFilter); + analyseFiles(fullAnalysis, errorFiles); + } + + + private List getAllFilesForDossier(String dossierId, Predicate filter) { var dossier = dossierPersistenceService.getAndValidateDossier(dossierId); - if (filterOnlyValidFiles) { - return fileStatusService.getDossierStatus(dossier.getId()) - .stream() - .filter(fileStatus -> !fileStatus.isSoftOrHardDeleted()) - .filter(fileStatus -> !fileStatus.getWorkflowStatus().equals(WorkflowStatus.APPROVED)) - .collect(Collectors.toList()); - } else { - return fileStatusService.getDossierStatus(dossier.getId()); - } + return fileStatusService.getDossierStatus(dossier.getId()) + .stream() + .filter(filter) + .collect(Collectors.toList()); + + } + + private List getAllFilesForDossier(String dossierId) { + + var dossier = dossierPersistenceService.getAndValidateDossier(dossierId); + + return fileStatusService.getDossierStatus(dossier.getId()); } - private void reanalyseFiles(String dossierId, boolean force, List filesToReanalyse) { + private void reanalyseFiles(boolean force, List filesToReanalyse) { if (force) { filesToReanalyse.forEach(file -> { if (file.isFullAnalysisRequired()) { - fileStatusService.setStatusFullReprocess(dossierId, file.getId(), filesToReanalyse.size() == 1, false); + fileStatusService.setStatusFullReprocess(file.getDossierId(), file.getId(), filesToReanalyse.size() == 1, false); } else { - fileStatusService.setStatusReprocess(dossierId, file.getId(), filesToReanalyse.size() == 1, true); + fileStatusService.setStatusReprocess(file.getDossierId(), file.getId(), filesToReanalyse.size() == 1, true); } }); } else { @@ -80,25 +100,41 @@ public class ReanalysisService { .filter(FileModel::isReanalysisRequired) .forEach(file -> { if (file.isFullAnalysisRequired()) { - fileStatusService.setStatusFullReprocess(dossierId, file.getId(), filesToReanalyse.size() == 1, false); + fileStatusService.setStatusFullReprocess(file.getDossierId(), file.getId(), filesToReanalyse.size() == 1, false); } else { - fileStatusService.setStatusReprocess(dossierId, file.getId(), filesToReanalyse.size() == 1, true); + fileStatusService.setStatusReprocess(file.getDossierId(), file.getId(), filesToReanalyse.size() == 1, true); } }); } } + private void analyseFiles(boolean fullAnalysis, List filesToReanalyse) { + + if (fullAnalysis) { + filesToReanalyse.forEach(file -> fileStatusService.setStatusFullReprocess(file.getDossierId(), file.getId(), filesToReanalyse.size() == 1, false)); + } else { + filesToReanalyse.forEach(file -> fileStatusService.setStatusReprocess(file.getDossierId(), file.getId(), filesToReanalyse.size() == 1, true)); + } + } + + public void reanalyzeFiles(String dossierId, Set fileIds, boolean force) { var relevantFiles = getRelevantFiles(dossierId, fileIds); - reanalyseFiles(dossierId, force, relevantFiles); + reanalyseFiles(force, relevantFiles); + } + + public void reanalyzeGivenErrorFilesInDossier(String dossierId, Set fileIds, boolean fullAnalysis) { + + var errorFiles = getRelevantErrorFiles(dossierId, fileIds); + analyseFiles(fullAnalysis, errorFiles); } private List getRelevantFiles(String dossierId, Collection fileIds) { - var dossierFiles = getAllFilesForDossier(dossierId, false); + var dossierFiles = getAllFilesForDossier(dossierId); var relevantFiles = new ArrayList(); for (var fileId : fileIds) { @@ -124,9 +160,22 @@ public class ReanalysisService { } + + private List getRelevantErrorFiles(String dossierId, Collection fileIds) { + + List relevantFiles = getRelevantFiles(dossierId, fileIds); + relevantFiles.forEach(fileModel -> { + if(!fileModel.getProcessingStatus().equals(ProcessingStatus.ERROR)) { + throw new BadRequestException("Only files in error state are allowed to be analyzed here!"); + } + }); + return relevantFiles; + } + + public void ocrDossier(String dossierId) { - var relevantFiles = getAllFilesForDossier(dossierId, true); + var relevantFiles = getAllFilesForDossier(dossierId, validFilesFilter); relevantFiles.stream() .filter(fileStatus -> fileStatus.getOcrStartTime() == null) diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/FileStatusPersistenceService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/FileStatusPersistenceService.java index 16b45a1c9..10a979939 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/FileStatusPersistenceService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/FileStatusPersistenceService.java @@ -10,6 +10,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; @@ -401,6 +402,13 @@ public class FileStatusPersistenceService { } + public List getStatusesForDossierTemplate(String dossierTemplateId) { + + return dossierService.findAllDossiersForDossierTemplateId(dossierTemplateId) + .stream().map(dossier -> fileRepository.findByDossierId(dossier.getId())).flatMap(List::stream).toList(); + } + + public List getStatusesAddedBefore(OffsetDateTime end) { return fileRepository.findByAddedBefore(end); @@ -416,6 +424,15 @@ public class FileStatusPersistenceService { } + public List getAllErrorFiles() { + + return fileRepository.findAll() + .stream() + .filter(f -> f.getProcessingStatus().equals(ProcessingStatus.ERROR)) + .collect(Collectors.toList()); + } + + public List getAllFiles() { return fileRepository.findAll(); diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/client/SupportClient.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/client/SupportClient.java new file mode 100644 index 000000000..d645957d8 --- /dev/null +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/client/SupportClient.java @@ -0,0 +1,11 @@ +package com.iqser.red.service.peristence.v1.server.integration.client; + +import org.springframework.cloud.openfeign.FeignClient; + +import com.iqser.red.service.persistence.service.v1.api.external.resource.ReanalysisResource; +import com.iqser.red.service.persistence.service.v1.api.external.resource.SupportResource; + +@FeignClient(name = "SupportClient", url = "http://localhost:${server.port}") +public interface SupportClient extends SupportResource { + +} diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/SupportControllerTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/SupportControllerTest.java new file mode 100644 index 000000000..31f7f3a5d --- /dev/null +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/SupportControllerTest.java @@ -0,0 +1,131 @@ +package com.iqser.red.service.peristence.v1.server.integration.tests; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.iqser.red.service.peristence.v1.server.integration.client.FileClient; +import com.iqser.red.service.peristence.v1.server.integration.client.FileProcessingClient; +import com.iqser.red.service.peristence.v1.server.integration.client.SupportClient; +import com.iqser.red.service.peristence.v1.server.integration.service.DossierTesterAndProvider; +import com.iqser.red.service.peristence.v1.server.integration.service.FileTesterAndProvider; +import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest; +import com.iqser.red.service.persistence.service.v1.api.shared.model.FileStatus; +import com.iqser.red.service.persistence.service.v1.api.shared.model.FileStatusFilter; +import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.Dossier; +import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileErrorInfo; +import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.ProcessingStatus; +import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.WorkflowStatus; + +public class SupportControllerTest extends AbstractPersistenceServerServiceTest { + + @Autowired + private FileTesterAndProvider fileTesterAndProvider; + + @Autowired + private DossierTesterAndProvider dossierTesterAndProvider; + + @Autowired + private SupportClient supportClient; + + @Autowired + private FileClient fileClient; + + @Autowired + private FileProcessingClient fileProcessingClient; + + + @Test + public void testReanalysis() { + + var dossier = dossierTesterAndProvider.provideTestDossier(); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + setProcessingStatusToError(dossier, file); + + supportClient.reanalyzeAllErrorFiles(true); + var loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId()); + assertThat(loadedFile.getProcessingStatus()).isEqualTo(ProcessingStatus.FULL_PROCESSING); + + setProcessingStatusToError(dossier, file); + + supportClient.reanalyzeErrorFilesForDossier(dossier.getId(), true); + loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId()); + assertThat(loadedFile.getProcessingStatus()).isEqualTo(ProcessingStatus.FULL_PROCESSING); + + setProcessingStatusToError(dossier, file); + + supportClient.reanalyzeErrorFile(dossier.getId(), file.getFileId(), true); + loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId()); + assertThat(loadedFile.getProcessingStatus()).isEqualTo(ProcessingStatus.FULL_PROCESSING); + + setProcessingStatusToError(dossier, file); + + supportClient.reanalyzeErrorFilesBulkForDossier(dossier.getId(), List.of(file.getFileId()), true); + loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId()); + assertThat(loadedFile.getProcessingStatus()).isEqualTo(ProcessingStatus.FULL_PROCESSING); + + setProcessingStatusToError(dossier, file); + } + + + @Test + public void testFileStatus() { + + var dossier = dossierTesterAndProvider.provideTestDossier(); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + setProcessingStatusToError(dossier, file); + + var fileStatuses = supportClient.getFileStatus(new FileStatusFilter()); + assertThat(fileStatuses.size()).isEqualTo(1); + + List errorProcessingStatusList = List.of(ProcessingStatus.ERROR); + fileStatuses = supportClient.getFileStatus(new FileStatusFilter(errorProcessingStatusList, new ArrayList<>())); + assertThat(fileStatuses.size()).isEqualTo(1); + + List processedProcessingStatusList = List.of(ProcessingStatus.PROCESSED); + fileStatuses = supportClient.getFileStatus(new FileStatusFilter(processedProcessingStatusList, new ArrayList<>())); + assertThat(fileStatuses.size()).isEqualTo(0); + + List newWorkflowStatusList = List.of(WorkflowStatus.NEW); + fileStatuses = supportClient.getFileStatus(new FileStatusFilter(new ArrayList<>(), newWorkflowStatusList)); + assertThat(fileStatuses.size()).isEqualTo(1); + + List approvedWorkflowStatusList = List.of(WorkflowStatus.APPROVED); + fileStatuses = supportClient.getFileStatus(new FileStatusFilter(new ArrayList<>(), approvedWorkflowStatusList)); + assertThat(fileStatuses.size()).isEqualTo(0); + + fileStatuses = supportClient.getFileStatus(new FileStatusFilter(errorProcessingStatusList, approvedWorkflowStatusList)); + assertThat(fileStatuses.size()).isEqualTo(0); + + fileStatuses = supportClient.getFileStatus(new FileStatusFilter(processedProcessingStatusList, newWorkflowStatusList)); + assertThat(fileStatuses.size()).isEqualTo(0); + + fileStatuses = supportClient.getFileStatusForDossier(file.getDossierId(), new FileStatusFilter(errorProcessingStatusList, newWorkflowStatusList)); + assertThat(fileStatuses.size()).isEqualTo(1); + + fileStatuses = supportClient.getFileStatusForDossierTemplate(file.getDossierTemplateId(), new FileStatusFilter(errorProcessingStatusList, newWorkflowStatusList)); + assertThat(fileStatuses.size()).isEqualTo(1); + + fileStatuses = supportClient.getFileStatusForDossierTemplate(file.getDossierTemplateId(), new FileStatusFilter(new ArrayList<>(), new ArrayList<>())); + assertThat(fileStatuses.size()).isEqualTo(1); + + fileStatuses = supportClient.getFileStatusForDossierTemplate(file.getDossierTemplateId(), new FileStatusFilter(null, null)); + assertThat(fileStatuses.size()).isEqualTo(1); + + } + + + private void setProcessingStatusToError(Dossier dossier, FileStatus file) { + + fileProcessingClient.analysisFailed(dossier.getId(), file.getId(), new FileErrorInfo()); + var loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId()); + assertThat(loadedFile.getProcessingStatus()).isEqualTo(ProcessingStatus.ERROR); + } + +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/FileStatusFilter.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/FileStatusFilter.java new file mode 100644 index 000000000..700f2e756 --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/FileStatusFilter.java @@ -0,0 +1,21 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model; + +import java.util.ArrayList; +import java.util.List; + +import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.ProcessingStatus; +import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.WorkflowStatus; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class FileStatusFilter { + + private List processingStatusList = new ArrayList<>(); + private List workflowStatusList = new ArrayList<>(); + +}