From 552d760eadbb69c8d4d8e91a913d5e68787809a8 Mon Sep 17 00:00:00 2001 From: corinaolariu Date: Tue, 16 Jul 2024 13:48:25 +0300 Subject: [PATCH] RED-9608 - Comments not removed after uploading multiple files via ZIP-Archive with "Overwrite and start over" selected - remove (soft-delete) all comments, not just the ones related to the manual redactions at overwrite - restore back all comments (not just the ones related to the manual redactions) when file is restored - unit tests added --- .../CommentPersistenceService.java | 3 +- .../repository/CommentRepository.java | 40 +++--- .../v1/server/integration/tests/FileTest.java | 115 ++++++++++++++++++ 3 files changed, 142 insertions(+), 16 deletions(-) diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/annotations/CommentPersistenceService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/annotations/CommentPersistenceService.java index c905d0db3..535780504 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/annotations/CommentPersistenceService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/annotations/CommentPersistenceService.java @@ -56,7 +56,8 @@ public class CommentPersistenceService { } public void softDeleteCommentsForFiles(List fileId, OffsetDateTime softDeletedTime) { - commentRepository.softDeleteCommentsByFilesAndAnnotationSoftDeletedTime(fileId, softDeletedTime); + + commentRepository.softDeleteCommentsByFiles(fileId, softDeletedTime); } public void undeleteByFileId(String fileId, OffsetDateTime deletionTime) { diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/CommentRepository.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/CommentRepository.java index 75830cbec..8ef2373a3 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/CommentRepository.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/CommentRepository.java @@ -34,29 +34,39 @@ public interface CommentRepository extends JpaRepository { int updateSoftDelete(@Param("id") long id, @Param("softDeleteTime") OffsetDateTime softDeleteTime); @Modifying - @Query("update CommentEntity c set c.softDeletedTime = :softDeleteTime where c.fileId in (:fileIds) and " + - "(exists (select a from ManualForceRedactionEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime = :softDeleteTime) or "+ - "exists (select a from IdRemovalEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime = :softDeleteTime) or "+ - "exists (select a from ManualRedactionEntryEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime = :softDeleteTime) or "+ - "exists (select a from ManualRecategorizationEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime = :softDeleteTime) or "+ - "exists (select a from ManualResizeRedactionEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime = :softDeleteTime) or "+ - "exists (select a from ManualLegalBasisChangeEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime = :softDeleteTime)) ") + @Query("update CommentEntity c set c.softDeletedTime = :softDeleteTime where c.fileId in (:fileIds) and " + + "(exists (select a from ManualForceRedactionEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime = :softDeleteTime) or " + + "exists (select a from IdRemovalEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime = :softDeleteTime) or " + + "exists (select a from ManualRedactionEntryEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime = :softDeleteTime) or " + + "exists (select a from ManualRecategorizationEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime = :softDeleteTime) or " + + "exists (select a from ManualResizeRedactionEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime = :softDeleteTime) or " + + "exists (select a from ManualLegalBasisChangeEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime = :softDeleteTime)) ") void softDeleteCommentsByFilesAndAnnotationSoftDeletedTime(@Param("fileIds") List fileIds, @Param("softDeleteTime") OffsetDateTime softDeleteTime); + @Modifying + @Query("update CommentEntity c set c.softDeletedTime = :softDeleteTime where c.fileId in (:fileIds)") + void softDeleteCommentsByFiles(@Param("fileIds") List fileIds, @Param("softDeleteTime") OffsetDateTime softDeleteTime); + + @Modifying @Query("delete from CommentEntity c where c.fileId in (:fileIds)") void deleteCommentsByFiles(@Param("fileIds") List fileIds); @Modifying - @Query("update CommentEntity c set c.softDeletedTime = null where c.fileId = :fileId and " + - "(exists (select a from ManualForceRedactionEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime >= :deletionTime) or "+ - "exists (select a from IdRemovalEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime >= :deletionTime) or "+ - "exists (select a from ManualRedactionEntryEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime >= :deletionTime) or "+ - "exists (select a from ManualRecategorizationEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime >= :deletionTime) or "+ - "exists (select a from ManualResizeRedactionEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime >= :deletionTime) or "+ - "exists (select a from ManualLegalBasisChangeEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime >= :deletionTime)) ") - void undeleteByFileId(@Param("fileId") String fileId,@Param("deletionTime") OffsetDateTime deletionTime); + @Query("update CommentEntity c set c.softDeletedTime = null where c.fileId = :fileId and " + + "(exists (select a from ManualForceRedactionEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime >= :deletionTime) or " + + "exists (select a from IdRemovalEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime >= :deletionTime) or " + + "exists (select a from ManualRedactionEntryEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime >= :deletionTime) or " + + "exists (select a from ManualRecategorizationEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime >= :deletionTime) or " + + "exists (select a from ManualResizeRedactionEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime >= :deletionTime) or " + + "exists (select a from ManualLegalBasisChangeEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime >= :deletionTime)) ") + void undeleteByFileIdAndAnnotationSoftDeletedTime(@Param("fileId") String fileId, @Param("deletionTime") OffsetDateTime deletionTime); + + + @Modifying + @Query("update CommentEntity c set c.softDeletedTime = null where c.fileId = :fileId and c.softDeletedTime >= :deletionTime") + void undeleteByFileId(@Param("fileId") String fileId, @Param("deletionTime") OffsetDateTime deletionTime); @Modifying 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 4f3012c93..c70b6abba 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 @@ -58,6 +58,7 @@ 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.AnnotationComments; import com.iqser.red.service.persistence.service.v1.api.shared.model.common.JSONPrimitive; 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.FileAttributeConfig; @@ -375,6 +376,7 @@ public class FileTest extends AbstractPersistenceServerServiceTest { var type = typeProvider.testAndProvideType(dossierTemplate, null, "manual"); typeProvider.testAndProvideType(dossierTemplate, null, "new-type", false, 2000); var annotationId = "imagine_this_makes_sense"; + var commentId = "commentId"; EntityLog entityLog = new EntityLog(1, 1, List.of(EntityLogEntry.builder() @@ -397,6 +399,14 @@ public class FileTest extends AbstractPersistenceServerServiceTest { .value("value entry 3") .state(EntryState.APPLIED) .entryType(EntryType.ENTITY) + .build(), + EntityLogEntry.builder() + .id(commentId) + .type(type.getType()) + .value("value entry 4") + .dictionaryEntry(true) + .state(EntryState.APPLIED) + .entryType(EntryType.ENTITY) .build()), null, 0, @@ -445,19 +455,39 @@ public class FileTest extends AbstractPersistenceServerServiceTest { .build()), false); + manualRedactionClient.addComment(dossierId, fileId, commentId, AddCommentRequestModel.builder().text("comment added via text fileId").build()); + var loadedFile = fileClient.getFileStatus(dossierId, fileId); + //check comments are restored + AnnotationComments annotationComments = manualRedactionClient.getComments(dossierId, fileId, commentId); + assertThat(annotationComments.getComments()).hasSize(1); + AnnotationComments annotationCommentsForManualRedactions = manualRedactionClient.getComments(dossierId, fileId, annotationId); + assertThat(annotationCommentsForManualRedactions.getComments()).hasSize(1); + fileManagementClient.deleteFile(dossier.getId(), file.getId()); var softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId()); assertThat(softDeletedFiles).hasSize(1); var activeFiles = fileClient.getDossierStatus(dossier.getId()); assertThat(activeFiles).isEmpty(); + // check the comment added to an annotation that has no manual redaction + Exception exception = Assertions.assertThrows(FeignException.NotFound.class, () -> manualRedactionClient.getComments(dossierId, fileId, commentId)); + + String expectedMessage = "The requested file has been soft deleted on"; + String actualMessage = exception.getMessage(); + assertThat(actualMessage).contains(expectedMessage); + fileManagementClient.restoreFiles(dossier.getId(), Sets.newHashSet(file.getId())); softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId()); assertThat(softDeletedFiles).isEmpty(); activeFiles = fileClient.getDossierStatus(dossier.getId()); assertThat(activeFiles).hasSize(1); + //check comments are restored + annotationComments = manualRedactionClient.getComments(dossierId, fileId, commentId); + assertThat(annotationComments.getComments()).hasSize(1); + annotationCommentsForManualRedactions = manualRedactionClient.getComments(dossierId, fileId, annotationId); + assertThat(annotationCommentsForManualRedactions.getComments()).hasSize(1); fileManagementClient.hardDeleteFiles(dossier.getId(), List.of(file.getId())); softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId()); @@ -697,4 +727,89 @@ public class FileTest extends AbstractPersistenceServerServiceTest { assertThrows(FeignException.class, () -> uploadClient.upload(malformedCsvFile, dossier.getId(), false)); } + + @Test + void testFileWithCommentsAtReupload() { + + var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(); + + var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate); + String dossierId = dossier.getId(); + + var file = fileTesterAndProvider.testAndProvideFile(dossier); + String fileId = file.getId(); + + var type = typeProvider.testAndProvideType(dossierTemplate, null, "manual"); + typeProvider.testAndProvideType(dossierTemplate, null, "new-type", false, 2000); + var annotationId = "imagine_this_makes_sense"; + var annotation2Id = "imagine_this_makes_sense 2"; + EntityLog entityLog = new EntityLog(1, + 1, + List.of(EntityLogEntry.builder() + .id(annotationId) + .type(type.getType()) + .value("value entry") + .state(EntryState.APPLIED) + .entryType(EntryType.ENTITY) + .build(), + EntityLogEntry.builder() + .id(annotation2Id) + .type(type.getType()) + .value("value entry 3") + .state(EntryState.APPLIED) + .entryType(EntryType.ENTITY) + .build()), + null, + 0, + 0, + 0, + 0); + + fileManagementStorageService.saveEntityLog(dossier.getId(), file.getId(), entityLog); + when(entityLogService.getEntityLog(any(), any(), anyBoolean())).thenReturn(entityLog); + + assertThat(fileClient.getDossierStatus(dossier.getId()).size()).isEqualTo(1); + + var recatResponse = manualRedactionClient.recategorizeBulk(dossierId, + fileId, + Set.of(RecategorizationRequestModel.builder() + .annotationId(annotation2Id) + .comment("comment edit via edit dialog") + .type(type.getType()) + .legalBasis("") + .section("section") + .value("value entry 3") + .build()), + false); + + var loadedFile = fileClient.getFileStatus(dossierId, fileId); + + manualRedactionClient.addComment(dossierId, fileId, annotationId, AddCommentRequestModel.builder().text("comment added via text fileId").build()); + + //check comments are restored + AnnotationComments annotationComments = manualRedactionClient.getComments(dossierId, fileId, annotationId); + assertThat(annotationComments.getComments()).hasSize(1); + AnnotationComments annotationCommentsForInitialAnnotation = manualRedactionClient.getComments(dossierId, fileId, annotation2Id); + assertThat(annotationCommentsForInitialAnnotation.getComments()).hasSize(0); + AnnotationComments annotationCommentsForManualRecat = manualRedactionClient.getComments(dossierId, fileId, recatResponse.getManualAddResponses().get(0).getAnnotationId()); + assertThat(annotationCommentsForManualRecat.getComments()).hasSize(1); + + //overwrite the file + var fileUpload = new MockMultipartFile(file.getFilename(), file.getFilename(), "application/pdf", "content".getBytes()); + var uploadResult = uploadClient.upload(fileUpload, dossier.getId(), false); + + loadedFile = fileClient.getFileStatus(dossier.getId(), + uploadResult.getFileIds() + .iterator().next()); + + //check comments are soft deleted + annotationComments = manualRedactionClient.getComments(dossierId, loadedFile.getId(), annotation2Id); + assertThat(annotationComments.getComments()).hasSize(0); + annotationCommentsForInitialAnnotation = manualRedactionClient.getComments(dossierId, fileId, annotation2Id); + assertThat(annotationCommentsForInitialAnnotation.getComments()).hasSize(0); + annotationCommentsForManualRecat = manualRedactionClient.getComments(dossierId, fileId, recatResponse.getManualAddResponses().get(0).getAnnotationId()); + assertThat(annotationCommentsForManualRecat.getComments()).hasSize(0); + + } + }