From 3ab607ccbf3be41a68df2421756c586e0732d1b7 Mon Sep 17 00:00:00 2001 From: Andrei Isvoran Date: Tue, 2 Apr 2024 08:38:08 +0200 Subject: [PATCH] RED-8776 - Add local redaction when we do a manual change on a non-manual redaction --- .../controller/ManualRedactionController.java | 7 +- .../service/EntityLogMergeService.java | 31 ++- .../ManualRedactionMapper.java | 174 +++++++++--- .../integration/tests/DownloadTest.java | 1 + .../integration/tests/EntityLogMergeTest.java | 69 ++++- .../v1/server/integration/tests/FileTest.java | 14 + .../tests/ManualRedactionTest.java | 248 +++++++++++++++++- 7 files changed, 484 insertions(+), 60 deletions(-) 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/ManualRedactionController.java b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/ManualRedactionController.java index 3e5095fc6..03f71ed61 100644 --- a/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/ManualRedactionController.java +++ b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/ManualRedactionController.java @@ -40,6 +40,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.RemoveRedactionRequest; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ResizeRedactionRequest; import com.iqser.red.service.persistence.service.v1.api.shared.model.audit.AuditRequest; +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.manual.AddCommentRequestModel; import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddRedactionRequestModel; import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.ForceRedactionRequestModel; @@ -238,7 +239,7 @@ public class ManualRedactionController implements ManualRedactionResource { accessControlService.verifyFileIsNotApproved(dossierId, fileId); accessControlService.verifyUserIsMemberOrApprover(dossierId); - List requests = manualRedactionMapper.toForceRedactionRequestList(forceRedactionRequests); + List requests = manualRedactionMapper.toForceRedactionRequestList(dossierId, fileId, forceRedactionRequests); List responseList = manualRedactionService.addForceRedaction(dossierId, fileId, requests); responseList.forEach(response -> auditPersistenceService.audit(AuditRequest.builder() @@ -263,7 +264,7 @@ public class ManualRedactionController implements ManualRedactionResource { accessControlService.verifyFileIsNotApproved(dossierId, fileId); accessControlService.verifyUserIsMemberOrApprover(dossierId); - List requests = manualRedactionMapper.toLegalBasisChangeRequestList(legalBasisChangeRequests); + List requests = manualRedactionMapper.toLegalBasisChangeRequestList(dossierId, fileId, legalBasisChangeRequests); List responseList = manualRedactionService.addLegalBasisChange(dossierId, fileId, requests); @@ -320,7 +321,7 @@ public class ManualRedactionController implements ManualRedactionResource { accessControlService.verifyFileIsNotApproved(dossierId, fileId); accessControlService.verifyUserIsMemberOrApprover(dossierId); - List requests = manualRedactionMapper.toResizeRedactionRequestList(resizeRedactionRequests); + List requests = manualRedactionMapper.toResizeRedactionRequestList(dossierId, fileId, resizeRedactionRequests, includeUnprocessed); List responseList = manualRedactionService.addResizeRedaction(dossierId, fileId, requests, includeUnprocessed); responseList.forEach(response -> auditPersistenceService.audit(AuditRequest.builder() diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogMergeService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogMergeService.java index 9aca20851..671d00485 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogMergeService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/EntityLogMergeService.java @@ -13,7 +13,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -211,7 +210,8 @@ public class EntityLogMergeService { .build()); List changes = new ArrayList<>(); - changes.add(Change.builder().analysisNumber(entityLog.getAnalysisNumber()).dateTime(manualRedactionEntry.getRequestDate()).type(ChangeType.ADDED).build()); + changes.add(Change.builder().analysisNumber(entityLog.getAnalysisNumber()).dateTime(manualRedactionEntry.getRequestDate()).type(ChangeType.ADDED) + .build()); boolean isHint = isHint(manualRedactionEntry.getType(), dossier); @@ -235,7 +235,7 @@ public class EntityLogMergeService { .excluded(false) .changes(changes) .manualChanges(manualChanges) - .engines(Set.of(Engine.MANUAL)) + .engines(new HashSet<>(List.of(Engine.MANUAL))) .reference(new HashSet<>()) .importedRedactionIntersections(new HashSet<>()) .containingNodeId(Collections.emptyList()) @@ -259,7 +259,8 @@ public class EntityLogMergeService { existingEntry.setState(EntryState.REMOVED); List falsePositiveChanges = new ArrayList<>(); - falsePositiveChanges.add(Change.builder().analysisNumber(entityLog.getAnalysisNumber()).dateTime(OffsetDateTime.now()).type(ChangeType.REMOVED).build()); + falsePositiveChanges.add(Change.builder().analysisNumber(entityLog.getAnalysisNumber()).dateTime(OffsetDateTime.now()).type(ChangeType.REMOVED) + .build()); if (existingEntry.getChanges() != null && !existingEntry.getChanges().isEmpty()) { existingEntry.getChanges().addAll(falsePositiveChanges); } else { @@ -302,6 +303,12 @@ public class EntityLogMergeService { manualChange.propertyChanges(Map.of("value", manualResizeRedaction.getValue())); } entityLogEntry.getManualChanges().add(manualChange.build()); + + if ((entityLogEntry.isDictionaryEntry() || entityLogEntry.isDossierDictionaryEntry()) + && !manualResizeRedaction.getUpdateDictionary() + && !manualResizeRedaction.isAddToAllDossiers()) { + entityLogEntry.setState(EntryState.REMOVED); + } } @@ -322,6 +329,9 @@ public class EntityLogMergeService { .userId(manualLegalBasisChange.getUser()) .build()); + if (entityLogEntry.isDictionaryEntry() || entityLogEntry.isDossierDictionaryEntry()) { + entityLogEntry.setState(EntryState.REMOVED); + } } @@ -369,6 +379,10 @@ public class EntityLogMergeService { .userId(recategorization.getUser()) .propertyChanges(getPropertyChanges(recategorization)) .build()); + + if ((entityLogEntry.isDictionaryEntry() || entityLogEntry.isDossierDictionaryEntry()) && !recategorization.isAddToDictionary() && !recategorization.isAddToAllDossiers()) { + entityLogEntry.setState(EntryState.REMOVED); + } } @@ -407,6 +421,9 @@ public class EntityLogMergeService { } entityLogEntry.getManualChanges().add(forceRedactManualChange.build()); + if (entityLogEntry.isDictionaryEntry() || entityLogEntry.isDossierDictionaryEntry()) { + entityLogEntry.setState(EntryState.REMOVED); + } } @@ -423,9 +440,11 @@ public class EntityLogMergeService { private void addChanges(List changes, ChangeType changeType, int analysisNumber, OffsetDateTime offsetDateTime) { if (!changes.isEmpty()) { - changes.add(Change.builder().analysisNumber(analysisNumber + 1).dateTime(offsetDateTime).type(changeType).build()); + changes.add(Change.builder().analysisNumber(analysisNumber + 1).dateTime(offsetDateTime).type(changeType) + .build()); } else { - changes.add(Change.builder().analysisNumber(analysisNumber).dateTime(OffsetDateTime.now()).type(changeType).build()); + changes.add(Change.builder().analysisNumber(analysisNumber).dateTime(OffsetDateTime.now()).type(changeType) + .build()); } } diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/ManualRedactionMapper.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/ManualRedactionMapper.java index c5f8f2606..587688c1f 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/ManualRedactionMapper.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/manualredactions/ManualRedactionMapper.java @@ -2,6 +2,7 @@ package com.iqser.red.service.persistence.management.v1.processor.service.manual import static com.iqser.red.service.persistence.management.v1.processor.utils.TypeIdUtils.toTypeId; +import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -10,18 +11,21 @@ import java.util.Set; import org.springframework.stereotype.Service; -import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException; import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException; import com.iqser.red.service.persistence.management.v1.processor.service.EntityLogService; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Engine; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogEntry; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryType; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Position; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.AddRedactionRequest; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ForceRedactionRequest; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.LegalBasisChangeRequest; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.RecategorizationRequest; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Rectangle; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.RemoveRedactionRequest; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ResizeRedactionRequest; +import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualRedactionEntry; 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.type.DictionaryEntryType; import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddRedactionRequestModel; @@ -43,6 +47,7 @@ import lombok.experimental.FieldDefaults; public class ManualRedactionMapper { EntityLogService entityLogService; + ManualRedactionService manualRedactionService; @Observed(name = "ManualRedactionMapper", contextualName = "to-add-redaction-request-list") @@ -84,7 +89,9 @@ public class ManualRedactionMapper { List requests = new ArrayList<>(); EntityLog entityLog = entityLogService.getEntityLog(dossierId, fileId, Collections.emptyList(), includeUnprocessed); + for (var removeRedactionRequest : removeRedactionRequests) { + EntityLogEntry entityLogEntry = getEntityLogEntry(entityLog, removeRedactionRequest.getAnnotationId()); var removeRedactionRequestBuilder = RemoveRedactionRequest.builder() .annotationId(removeRedactionRequest.getAnnotationId()) @@ -103,36 +110,63 @@ public class ManualRedactionMapper { requests.add(removeRedactionRequestBuilder.build()); } + return requests; } - public List toForceRedactionRequestList(Set forceRedactionRequests) { + public List toForceRedactionRequestList(String dossierId, String fileId, Set forceRedactionRequests) { - return forceRedactionRequests.stream() - .map(forceRedactionRequest -> ForceRedactionRequest.builder() - .annotationId(forceRedactionRequest.getAnnotationId()) - .user(KeycloakSecurity.getUserId()) - .legalBasis(forceRedactionRequest.getLegalBasis()) - .comment(forceRedactionRequest.getComment()) - .build()) - .toList(); + EntityLog entityLog = entityLogService.getEntityLog(dossierId, fileId, Collections.emptyList(), true); + List requests = new ArrayList<>(); + + for (ForceRedactionRequestModel forceRedactionRequestModel : forceRedactionRequests) { + + EntityLogEntry entityLogEntry = getEntityLogEntry(entityLog, forceRedactionRequestModel.getAnnotationId()); + ForceRedactionRequest forceRedactionRequest = ForceRedactionRequest.builder() + .annotationId(forceRedactionRequestModel.getAnnotationId()) + .user(KeycloakSecurity.getUserId()) + .legalBasis(forceRedactionRequestModel.getLegalBasis()) + .comment(forceRedactionRequestModel.getComment()) + .build(); + + if (!entityLogEntry.getEngines().contains(Engine.MANUAL)) { + addManualRedactionEntry(fileId, entityLogEntry); + } + + requests.add(forceRedactionRequest); + } + + return requests; } @Deprecated(forRemoval = true) - public List toLegalBasisChangeRequestList(Set legalBasisChangeRequests) { + public List toLegalBasisChangeRequestList(String dossierId, String fileId, Set legalBasisChangeRequests) { - return legalBasisChangeRequests.stream() - .map(legalBasisChangeRequest -> LegalBasisChangeRequest.builder() - .annotationId(legalBasisChangeRequest.getAnnotationId()) - .user(KeycloakSecurity.getUserId()) - .section(legalBasisChangeRequest.getSection()) - .legalBasis(legalBasisChangeRequest.getLegalBasis()) - .comment(legalBasisChangeRequest.getComment()) - .value(legalBasisChangeRequest.getValue()) - .build()) - .toList(); + EntityLog entityLog = entityLogService.getEntityLog(dossierId, fileId, Collections.emptyList(), true); + List requests = new ArrayList<>(); + + for (LegalBasisChangeRequestModel legalBasisChangeRequest : legalBasisChangeRequests) { + + EntityLogEntry entityLogEntry = getEntityLogEntry(entityLog, legalBasisChangeRequest.getAnnotationId()); + LegalBasisChangeRequest request = LegalBasisChangeRequest.builder() + .annotationId(legalBasisChangeRequest.getAnnotationId()) + .user(KeycloakSecurity.getUserId()) + .section(legalBasisChangeRequest.getSection()) + .legalBasis(legalBasisChangeRequest.getLegalBasis()) + .comment(legalBasisChangeRequest.getComment()) + .value(legalBasisChangeRequest.getValue()) + .build(); + + if (!entityLogEntry.getEngines().contains(Engine.MANUAL)) { + addManualRedactionEntry(fileId, entityLogEntry); + } + + requests.add(request); + } + + return requests; } @@ -144,9 +178,11 @@ public class ManualRedactionMapper { EntityLog entityLog = entityLogService.getEntityLog(dossierId, fileId, Collections.emptyList(), includeUnprocessed); List requests = new ArrayList<>(); + for (RecategorizationRequestModel recategorizationRequest : recategorizationRequests) { + EntityLogEntry entityLogEntry = getEntityLogEntry(entityLog, recategorizationRequest.getAnnotationId()); - RecategorizationRequest build = RecategorizationRequest.builder() + RecategorizationRequest request = RecategorizationRequest.builder() .annotationId(recategorizationRequest.getAnnotationId()) .user(KeycloakSecurity.getUserId()) .dossierTemplateId(dossierTemplateId) @@ -163,26 +199,47 @@ public class ManualRedactionMapper { .section(recategorizationRequest.getSection()) .value(recategorizationRequest.getValue()) .build(); - requests.add(build); + + if (!entityLogEntry.getEngines().contains(Engine.MANUAL) && !recategorizationRequest.isAddToAllDossiers() && !recategorizationRequest.isAddToDictionary()) { + addManualRedactionEntry(fileId, entityLogEntry); + } + + requests.add(request); } return requests; } - public List toResizeRedactionRequestList(Set resizeRedactionRequests) { + public List toResizeRedactionRequestList(String dossierId, + String fileId, + Set resizeRedactionRequests, + boolean includeUnprocessed) { - return resizeRedactionRequests.stream() - .map(resizeRedactionRequest -> ResizeRedactionRequest.builder() - .annotationId(resizeRedactionRequest.getAnnotationId()) - .user(KeycloakSecurity.getUserId()) - .positions(resizeRedactionRequest.getPositions()) - .value(resizeRedactionRequest.getValue() == null ? "" : StringCleaningUtility.cleanString(resizeRedactionRequest.getValue())) - .comment(resizeRedactionRequest.getComment()) - .updateDictionary(resizeRedactionRequest.getUpdateDictionary()) - .addToAllDossiers(resizeRedactionRequest.isAddToAllDossiers()) - .build()) - .toList(); + EntityLog entityLog = entityLogService.getEntityLog(dossierId, fileId, Collections.emptyList(), includeUnprocessed); + List requests = new ArrayList<>(); + + for (ResizeRedactionRequestModel resizeRedactionRequest : resizeRedactionRequests) { + + EntityLogEntry entityLogEntry = getEntityLogEntry(entityLog, resizeRedactionRequest.getAnnotationId()); + ResizeRedactionRequest request = ResizeRedactionRequest.builder() + .annotationId(resizeRedactionRequest.getAnnotationId()) + .user(KeycloakSecurity.getUserId()) + .positions(resizeRedactionRequest.getPositions()) + .value(resizeRedactionRequest.getValue() == null ? "" : StringCleaningUtility.cleanString(resizeRedactionRequest.getValue())) + .comment(resizeRedactionRequest.getComment()) + .updateDictionary(resizeRedactionRequest.getUpdateDictionary()) + .addToAllDossiers(resizeRedactionRequest.isAddToAllDossiers()) + .build(); + + if (!entityLogEntry.getEngines().contains(Engine.MANUAL) && !request.isAddToAllDossiers() && !request.getUpdateDictionary()) { + addManualRedactionEntry(fileId, entityLogEntry); + } + + requests.add(request); + } + + return requests; } @@ -207,4 +264,51 @@ public class ManualRedactionMapper { } } + + private void addManualRedactionEntry(String fileId, EntityLogEntry entityLogEntry) { + + ManualRedactionEntry manualRedactionEntry = ManualRedactionEntry.builder() + .value(entityLogEntry.getValue()) + .reason(entityLogEntry.getReason()) + .section(entityLogEntry.getSection()) + .annotationId(entityLogEntry.getId()) + .type(entityLogEntry.getType()) + .addToDossierDictionary(false) + .addToDictionary(false) + .positions(convertPositions(entityLogEntry.getPositions())) + .rectangle(entityLogEntry.getEntryType() == EntryType.AREA) + .user(KeycloakSecurity.getUserId()) + .legalBasis(entityLogEntry.getLegalBasis()) + .textAfter(entityLogEntry.getTextAfter()) + .textBefore(entityLogEntry.getTextBefore()) + .dictionaryEntryType(convertEntryType(entityLogEntry)) + .fileId(fileId) + .requestDate(OffsetDateTime.now()) + .build(); + + manualRedactionService.addManualRedactionEntries(List.of(manualRedactionEntry), false); + } + + + private List convertPositions(List positions) { + + return positions.stream() + .map(rectangle -> new Rectangle(rectangle.x(), rectangle.y(), rectangle.w(), rectangle.h(), rectangle.getPageNumber())) + .toList(); + } + + + private DictionaryEntryType convertEntryType(EntityLogEntry entityLogEntry) { + + if (entityLogEntry.getEntryType().equals(EntryType.FALSE_POSITIVE)) { + return DictionaryEntryType.FALSE_POSITIVE; + } + + if (entityLogEntry.getEntryType().equals(EntryType.FALSE_RECOMMENDATION)) { + return DictionaryEntryType.FALSE_RECOMMENDATION; + } + + return DictionaryEntryType.ENTRY; + } + } diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/DownloadTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/DownloadTest.java index 42f473d6e..11be42521 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/DownloadTest.java +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/DownloadTest.java @@ -9,6 +9,7 @@ import java.util.Set; import com.iqser.red.service.pdftron.redaction.v1.api.model.RedactionResultDetail; import com.iqser.red.service.pdftron.redaction.v1.api.model.RedactionType; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DownloadRedactionFileStatusRepository; +import com.iqser.red.service.persistence.service.v1.api.shared.model.download.DownloadStatus; import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService; import org.junit.jupiter.api.Disabled; diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogMergeTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogMergeTest.java index c89565ec5..bad993284 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogMergeTest.java +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/EntityLogMergeTest.java @@ -120,7 +120,7 @@ public class EntityLogMergeTest { ManualRedactions manualRedactions = provideManualRedactions(entryToAddId, entryToRemoveId, entryToResizeId, entryLegalBasisId, forceRedactionId, fileId, rectangleToAddId); - var entityLog = provideEntityLog(entryToRemoveId, entryToResizeId, entryLegalBasisId, forceRedactionId); + var entityLog = provideEntityLog(entryToRemoveId, entryToResizeId, entryLegalBasisId, forceRedactionId, false); when(manualRedactionProviderService.getManualRedactions(any(), any())).thenReturn(manualRedactions); when(fileStatusService.getStatus(fileId)).thenReturn(FileModel.builder().excluded(false).dossierStatusId(dossierTemplateId).id(fileId).build()); @@ -237,7 +237,7 @@ public class EntityLogMergeTest { @Test - public void testUnprocessedDictChangesAreDirectlyAfterOriginEntry() { + public void testMergeEntityLogWithManualChangesOnDictRedaction() { String fileId = "fileId"; String dossierId = "dossierId"; @@ -250,6 +250,58 @@ public class EntityLogMergeTest { String entryLegalBasisId = UUID.randomUUID().toString(); String forceRedactionId = UUID.randomUUID().toString(); + ManualRedactions manualRedactions = provideManualRedactions(entryToAddId, entryToRemoveId, entryToResizeId, entryLegalBasisId, forceRedactionId, fileId, rectangleToAddId); + + var entityLog = provideEntityLog(entryToRemoveId, entryToResizeId, entryLegalBasisId, forceRedactionId, true); + + when(manualRedactionProviderService.getManualRedactions(any(), any())).thenReturn(manualRedactions); + when(fileStatusService.getStatus(fileId)).thenReturn(FileModel.builder().excluded(false).dossierStatusId(dossierTemplateId).id(fileId).build()); + when(fileManagementStorageService.getEntityLog(dossierId, fileId)).thenReturn(entityLog); + when(dossierService.getDossierById(dossierId)).thenReturn(DossierEntity.builder().dossierTemplateId(dossierTemplateId).build()); + when(dictionaryPersistenceService.getType(anyString())).thenReturn(TypeEntity.builder().isHint(false).build()); + when(fileStatusPersistenceService.getStatus(fileId)).thenReturn(FileEntity.builder().id(fileId).fileAttributes(Collections.emptyList()).build()); + when(fileStatusService.convertAttributes(any(), anyString())).thenReturn(Collections.emptyList()); + + EntityLog response = entityLogMergeService.mergeEntityLog(manualRedactions, entityLog, DossierEntity.builder().dossierTemplateId(dossierTemplateId).build()); + + assertNotNull(response); + assertFalse(response.getEntityLogEntry().isEmpty()); + + var optionalResizeEntryLogEntry = response.getEntityLogEntry() + .stream() + .filter(entityLogEntry1 -> entityLogEntry1.getId().equals(entryToResizeId)) + .findFirst(); + assertTrue(optionalResizeEntryLogEntry.isPresent()); + assertEquals(optionalResizeEntryLogEntry.get().getEntryType(), EntryType.ENTITY); + + var optionalLegalBasisEntryLogEntry = response.getEntityLogEntry() + .stream() + .filter(entityLogEntry1 -> entityLogEntry1.getId().equals(entryLegalBasisId)) + .findFirst(); + assertTrue(optionalLegalBasisEntryLogEntry.isPresent()); + assertEquals(optionalLegalBasisEntryLogEntry.get().getState(), EntryState.REMOVED); + + var optionalForceRedactionEntryLogEntry = response.getEntityLogEntry() + .stream() + .filter(entityLogEntry1 -> entityLogEntry1.getId().equals(forceRedactionId)) + .findFirst(); + assertTrue(optionalForceRedactionEntryLogEntry.isPresent()); + assertEquals(optionalForceRedactionEntryLogEntry.get().getState(), EntryState.REMOVED); + } + + + @Test + public void testUnprocessedDictChangesAreDirectlyAfterOriginEntry() { + + String fileId = "fileId"; + String dossierId = "dossierId"; + String dossierTemplateId = "dossierTemplateId"; + + String entryToRemoveId = UUID.randomUUID().toString(); + String entryToResizeId = UUID.randomUUID().toString(); + String entryLegalBasisId = UUID.randomUUID().toString(); + String forceRedactionId = UUID.randomUUID().toString(); + ManualRedactions manualRedactions = new ManualRedactions(); List positions = new ArrayList<>(); @@ -265,7 +317,7 @@ public class EntityLogMergeTest { .fileId("file") .build())); - var entityLog = provideEntityLog(entryToRemoveId, entryToResizeId, entryLegalBasisId, forceRedactionId); + var entityLog = provideEntityLog(entryToRemoveId, entryToResizeId, entryLegalBasisId, forceRedactionId, false); when(manualRedactionProviderService.getManualRedactions(any(), any())).thenReturn(manualRedactions); when(fileStatusService.getStatus(fileId)).thenReturn(FileModel.builder().excluded(false).dossierStatusId(dossierTemplateId).id(fileId).build()); @@ -284,7 +336,7 @@ public class EntityLogMergeTest { } - private EntityLog provideEntityLog(String entryToRemoveId, String entryToResizeId, String entryLegalBasisId, String forceRedactionId) { + private EntityLog provideEntityLog(String entryToRemoveId, String entryToResizeId, String entryLegalBasisId, String forceRedactionId, boolean dictEntry) { List positions = new ArrayList<>(); positions.add(new Position(1, 1, 1, 1, 1)); @@ -296,7 +348,7 @@ public class EntityLogMergeTest { .value("Luke Skywalker") .entryType(EntryType.ENTITY) .state(EntryState.APPLIED) - .dictionaryEntry(true) + .dictionaryEntry(dictEntry) .build(), EntityLogEntry.builder() .id(entryToResizeId) @@ -304,7 +356,7 @@ public class EntityLogMergeTest { .value("Darth Vader") .entryType(EntryType.ENTITY) .state(EntryState.APPLIED) - .dictionaryEntry(true) + .dictionaryEntry(dictEntry) .positions(positions) .build(), EntityLogEntry.builder() @@ -313,7 +365,7 @@ public class EntityLogMergeTest { .value("Darth Luke") .entryType(EntryType.ENTITY) .state(EntryState.APPLIED) - .dictionaryEntry(true) + .dictionaryEntry(dictEntry) .positions(positions) .build(), EntityLogEntry.builder() @@ -322,7 +374,7 @@ public class EntityLogMergeTest { .value("Darth Luke") .entryType(EntryType.ENTITY) .state(EntryState.APPLIED) - .dictionaryEntry(true) + .dictionaryEntry(dictEntry) .positions(positions) .build()), Collections.emptyList(), @@ -381,6 +433,7 @@ public class EntityLogMergeTest { .positions(positions) .requestDate(OffsetDateTime.now()) .updateDictionary(false) + .addToAllDossiers(false) .user("User") .fileId("file") .build())) diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/FileTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/FileTest.java index 7ebcf07e7..92100ae45 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/FileTest.java +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/FileTest.java @@ -377,6 +377,20 @@ public class FileTest extends AbstractPersistenceServerServiceTest { .value("value entry") .state(EntryState.APPLIED) .entryType(EntryType.ENTITY) + .build(), + EntityLogEntry.builder() + .id("forceRedactionAnnotation") + .type(type.getType()) + .value("value entry 2") + .state(EntryState.APPLIED) + .entryType(EntryType.ENTITY) + .build(), + EntityLogEntry.builder() + .id("legalBasisChangeAnnotation") + .type(type.getType()) + .value("value entry 3") + .state(EntryState.APPLIED) + .entryType(EntryType.ENTITY) .build()), null, 0, diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/ManualRedactionTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/ManualRedactionTest.java index e4a98d001..e984608d0 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/ManualRedactionTest.java +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/ManualRedactionTest.java @@ -4,6 +4,7 @@ import static com.iqser.red.service.persistence.management.v1.processor.utils.Ty import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -45,10 +46,8 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogEntry; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryState; import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryType; -import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.AddRedactionRequest; -import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions; +import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Position; import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Rectangle; -import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualRedactionEntry; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionaryEntryType; import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddRedactionRequestModel; @@ -808,7 +807,7 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest { @Test - public void MtestEnlargeResizeRedactionInDossierTemplateDictionaryWithAddToAllDossiers() { + public void testEnlargeResizeRedactionInDossierTemplateDictionaryWithAddToAllDossiers() { // preparíng prerequisites var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); @@ -1546,6 +1545,38 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest { var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); var file = fileTesterAndProvider.testAndProvideFile(dossier); + var type = typeProvider.testAndProvideType(dossierTemplate, null, "type", false); + + var entityLog = new EntityLog(1, + 1, + List.of(EntityLogEntry.builder() + .id("forceRedactionAnnotation") + .type(type.getType()) + .value("lukeSkywalker") + .dictionaryEntry(true) + .entryType(EntryType.ENTITY) + .state(EntryState.APPLIED) + .legalBasis("legal basis") + .positions(List.of(new Position(1, 1, 1, 1, 1))) + .build(), + EntityLogEntry.builder() + .id("forceRedactionAnnotation2") + .type(type.getType()) + .value("lukeSkywalker") + .dictionaryEntry(true) + .entryType(EntryType.ENTITY) + .state(EntryState.APPLIED) + .legalBasis("legal basis") + .positions(List.of(new Position(1, 1, 1, 1, 1))) + .build()), + null, + 0, + 0, + 0, + 0); + fileManagementStorageService.storeJSONObject(dossier.getId(), file.getId(), FileType.ENTITY_LOG, entityLog); + when(entityLogService.getEntityLog(Mockito.any(), Mockito.any(), any(), anyBoolean())).thenReturn(entityLog); + manualRedactionClient.forceRedactionBulk(dossier.getId(), file.getId(), Set.of(ForceRedactionRequestModel.builder().annotationId("forceRedactionAnnotation").comment("comment").legalBasis("1").build())); @@ -1766,7 +1797,7 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest { 0); fileManagementStorageService.storeJSONObject(dossier.getId(), file.getId(), FileType.ENTITY_LOG, entityLog); - when(entityLogService.getEntityLog(Mockito.any(), Mockito.any())).thenReturn(entityLog); + when(entityLogService.getEntityLog(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean())).thenReturn(entityLog); manualRedactionClient.legalBasisChangeBulk(dossier.getId(), file.getId(), @@ -1876,7 +1907,7 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest { 0); fileManagementStorageService.storeJSONObject(dossier.getId(), file.getId(), FileType.ENTITY_LOG, entityLog); - when(entityLogService.getEntityLog(Mockito.any(), Mockito.any())).thenReturn(entityLog); + when(entityLogService.getEntityLog(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean())).thenReturn(entityLog); manualRedactionClient.legalBasisChangeBulk(dossier.getId(), file.getId(), @@ -1901,13 +1932,13 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest { .anyMatch(entry -> entry.getLegalBasis().equals("legalBasis"))); var unprocessedManualRedactions = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), true, false); - assertEquals(unprocessedManualRedactions.buildAll().size(), 1); + assertEquals(unprocessedManualRedactions.buildAll().size(), 2); assertTrue(unprocessedManualRedactions.getLegalBasisChanges() .stream() .anyMatch(entry -> entry.getLegalBasis().equals("legalBasis"))); var unprocessedManualRedactionsWithDict = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), true, true); - assertEquals(unprocessedManualRedactionsWithDict.buildAll().size(), 2); + assertEquals(unprocessedManualRedactionsWithDict.buildAll().size(), 3); assertTrue(unprocessedManualRedactionsWithDict.getLegalBasisChanges() .stream() .anyMatch(entry -> entry.getLegalBasis().equals("legalBasis"))); @@ -2076,4 +2107,205 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest { .anyMatch(entry -> entry.getSection().equals("section"))); } + + @Test + public void testManualRecategorizationOnDictionaryRedaction() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + var type = typeProvider.testAndProvideType(dossierTemplate, null, "type", false, 100); + var type2 = typeProvider.testAndProvideType(dossierTemplate, null, "type2", false, 110); + + var entityLogEntry = EntityLogEntry.builder() + .id("annotationId") + .type(type.getType()) + .value("lukeSkywalker") + .dictionaryEntry(true) + .entryType(EntryType.ENTITY) + .state(EntryState.APPLIED) + .legalBasis("legal basis") + .positions(List.of(new Position(1, 1, 1, 1, 1))) + .build(); + var entityLog = new EntityLog(1, + 1, + List.of(entityLogEntry), + null, + 0, + 0, + 0, + 0); + fileManagementStorageService.storeJSONObject(dossier.getId(), file.getId(), FileType.ENTITY_LOG, entityLog); + when(entityLogService.getEntityLog(Mockito.any(), Mockito.any(), any(), anyBoolean())).thenReturn(entityLog); + + var recategorizationRequestModel = RecategorizationRequestModel.builder() + .type(type2.getType()) + .annotationId("annotationId") + .addToDictionary(false) + .addToAllDossiers(false) + .legalBasis("") + .build(); + + manualRedactionClient.recategorizeBulk(dossier.getId(), file.getId(), Set.of(recategorizationRequestModel), false); + + var allManualRedactions = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), false, true); + + assertEquals(allManualRedactions.getRecategorizations().size(), 1); + assertEquals(allManualRedactions.getEntriesToAdd().size(), 1); + var entryToAdd = allManualRedactions.getEntriesToAdd().stream().findFirst().get(); + assertFalse(entryToAdd.isAddToDictionary()); + assertFalse(entryToAdd.isAddToDossierDictionary()); + assertEquals(entryToAdd.getValue(), entityLogEntry.getValue()); + assertEquals(entryToAdd.getType(), entityLogEntry.getType()); + } + + + @Test + public void testManualLegalBasisChangeOnDictionaryRedaction() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + var type = typeProvider.testAndProvideType(dossierTemplate, null, "type", false); + + var entityLogEntry = EntityLogEntry.builder() + .id("annotationId") + .type(type.getType()) + .value("lukeSkywalker") + .dictionaryEntry(true) + .entryType(EntryType.ENTITY) + .state(EntryState.APPLIED) + .legalBasis("legal basis") + .positions(List.of(new Position(1, 1, 1, 1, 1))) + .build(); + var entityLog = new EntityLog(1, + 1, + List.of(entityLogEntry), + null, + 0, + 0, + 0, + 0); + fileManagementStorageService.storeJSONObject(dossier.getId(), file.getId(), FileType.ENTITY_LOG, entityLog); + when(entityLogService.getEntityLog(Mockito.any(), Mockito.any(), any(), anyBoolean())).thenReturn(entityLog); + + var legalBasisChangeRequestModel = LegalBasisChangeRequestModel.builder() + .annotationId("annotationId") + .legalBasis("new legal basis") + .value(entityLogEntry.getValue()) + .build(); + + manualRedactionClient.legalBasisChangeBulk(dossier.getId(), file.getId(), Set.of(legalBasisChangeRequestModel)); + + var allManualRedactions = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), false, true); + + assertEquals(allManualRedactions.getLegalBasisChanges().size(), 1); + assertEquals(allManualRedactions.getEntriesToAdd().size(), 1); + var entryToAdd = allManualRedactions.getEntriesToAdd().stream().findFirst().get(); + assertFalse(entryToAdd.isAddToDictionary()); + assertFalse(entryToAdd.isAddToDossierDictionary()); + assertEquals(entryToAdd.getValue(), entityLogEntry.getValue()); + assertEquals(entryToAdd.getLegalBasis(), entityLogEntry.getLegalBasis()); + } + + + @Test + public void testManualResizeOnDictionaryRedaction() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + var type = typeProvider.testAndProvideType(dossierTemplate, null, "type", false); + + var entityLogEntry = EntityLogEntry.builder() + .id("annotationId") + .type(type.getType()) + .value("lukeSkywalker") + .dictionaryEntry(true) + .entryType(EntryType.ENTITY) + .state(EntryState.APPLIED) + .legalBasis("legal basis") + .positions(List.of(new Position(1, 1, 1, 1, 1))) + .build(); + var entityLog = new EntityLog(1, + 1, + List.of(entityLogEntry), + null, + 0, + 0, + 0, + 0); + fileManagementStorageService.storeJSONObject(dossier.getId(), file.getId(), FileType.ENTITY_LOG, entityLog); + when(entityLogService.getEntityLog(Mockito.any(), Mockito.any(), any(), anyBoolean())).thenReturn(entityLog); + + var resizeRedactionRequestModel = ResizeRedactionRequestModel.builder() + .annotationId("annotationId") + .value("lukeSkywalker resized") + .updateDictionary(false) + .addToAllDossiers(false) + .positions(List.of(Rectangle.builder().page(1).height(1).width(2).topLeftX(1).topLeftY(1).build())) + .build(); + + manualRedactionClient.resizeRedactionBulk(dossier.getId(), file.getId(), Set.of(resizeRedactionRequestModel), false); + + var allManualRedactions = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), false, true); + + assertEquals(allManualRedactions.getResizeRedactions().size(), 1); + assertEquals(allManualRedactions.getEntriesToAdd().size(), 1); + var entryToAdd = allManualRedactions.getEntriesToAdd().stream().findFirst().get(); + assertFalse(entryToAdd.isAddToDictionary()); + assertFalse(entryToAdd.isAddToDossierDictionary()); + assertEquals(entryToAdd.getValue(), entityLogEntry.getValue()); + } + + + @Test + public void testManualForceRedactionOnDictionaryRedaction() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + var file = fileTesterAndProvider.testAndProvideFile(dossier); + + var type = typeProvider.testAndProvideType(dossierTemplate, null, "type", false); + + var entityLogEntry = EntityLogEntry.builder() + .id("annotationId") + .type(type.getType()) + .value("lukeSkywalker") + .dictionaryEntry(true) + .entryType(EntryType.ENTITY) + .state(EntryState.APPLIED) + .legalBasis("legal basis") + .positions(List.of(new Position(1, 1, 1, 1, 1))) + .build(); + var entityLog = new EntityLog(1, + 1, + List.of(entityLogEntry), + null, + 0, + 0, + 0, + 0); + fileManagementStorageService.storeJSONObject(dossier.getId(), file.getId(), FileType.ENTITY_LOG, entityLog); + when(entityLogService.getEntityLog(Mockito.any(), Mockito.any(), any(), anyBoolean())).thenReturn(entityLog); + + var forceRedactionRequestModel = ForceRedactionRequestModel.builder() + .annotationId("annotationId") + .build(); + + manualRedactionClient.forceRedactionBulk(dossier.getId(), file.getId(), Set.of(forceRedactionRequestModel)); + + var allManualRedactions = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), false, true); + + assertEquals(allManualRedactions.getForceRedactions().size(), 1); + assertEquals(allManualRedactions.getEntriesToAdd().size(), 1); + var entryToAdd = allManualRedactions.getEntriesToAdd().stream().findFirst().get(); + assertFalse(entryToAdd.isAddToDictionary()); + assertFalse(entryToAdd.isAddToDossierDictionary()); + assertEquals(entryToAdd.getValue(), entityLogEntry.getValue()); + } + }