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
This commit is contained in:
parent
55c6b7419d
commit
552d760ead
@ -56,7 +56,8 @@ public class CommentPersistenceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void softDeleteCommentsForFiles(List<String> fileId, OffsetDateTime softDeletedTime) {
|
public void softDeleteCommentsForFiles(List<String> fileId, OffsetDateTime softDeletedTime) {
|
||||||
commentRepository.softDeleteCommentsByFilesAndAnnotationSoftDeletedTime(fileId, softDeletedTime);
|
|
||||||
|
commentRepository.softDeleteCommentsByFiles(fileId, softDeletedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void undeleteByFileId(String fileId, OffsetDateTime deletionTime) {
|
public void undeleteByFileId(String fileId, OffsetDateTime deletionTime) {
|
||||||
|
|||||||
@ -34,28 +34,38 @@ public interface CommentRepository extends JpaRepository<CommentEntity, Long> {
|
|||||||
int updateSoftDelete(@Param("id") long id, @Param("softDeleteTime") OffsetDateTime softDeleteTime);
|
int updateSoftDelete(@Param("id") long id, @Param("softDeleteTime") OffsetDateTime softDeleteTime);
|
||||||
|
|
||||||
@Modifying
|
@Modifying
|
||||||
@Query("update CommentEntity c set c.softDeletedTime = :softDeleteTime where c.fileId in (:fileIds) and " +
|
@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 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 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 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 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 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)) ")
|
+ "exists (select a from ManualLegalBasisChangeEntity a where a.id.annotationId = c.annotationId and a.softDeletedTime = :softDeleteTime)) ")
|
||||||
void softDeleteCommentsByFilesAndAnnotationSoftDeletedTime(@Param("fileIds") List<String> fileIds, @Param("softDeleteTime") OffsetDateTime softDeleteTime);
|
void softDeleteCommentsByFilesAndAnnotationSoftDeletedTime(@Param("fileIds") List<String> fileIds, @Param("softDeleteTime") OffsetDateTime softDeleteTime);
|
||||||
|
|
||||||
|
@Modifying
|
||||||
|
@Query("update CommentEntity c set c.softDeletedTime = :softDeleteTime where c.fileId in (:fileIds)")
|
||||||
|
void softDeleteCommentsByFiles(@Param("fileIds") List<String> fileIds, @Param("softDeleteTime") OffsetDateTime softDeleteTime);
|
||||||
|
|
||||||
|
|
||||||
@Modifying
|
@Modifying
|
||||||
@Query("delete from CommentEntity c where c.fileId in (:fileIds)")
|
@Query("delete from CommentEntity c where c.fileId in (:fileIds)")
|
||||||
void deleteCommentsByFiles(@Param("fileIds") List<String> fileIds);
|
void deleteCommentsByFiles(@Param("fileIds") List<String> fileIds);
|
||||||
|
|
||||||
|
|
||||||
@Modifying
|
@Modifying
|
||||||
@Query("update CommentEntity c set c.softDeletedTime = null where c.fileId = :fileId and " +
|
@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 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 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 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 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 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)) ")
|
+ "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);
|
void undeleteByFileId(@Param("fileId") String fileId, @Param("deletionTime") OffsetDateTime deletionTime);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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.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.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.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.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.Dossier;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileAttributeConfig;
|
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");
|
var type = typeProvider.testAndProvideType(dossierTemplate, null, "manual");
|
||||||
typeProvider.testAndProvideType(dossierTemplate, null, "new-type", false, 2000);
|
typeProvider.testAndProvideType(dossierTemplate, null, "new-type", false, 2000);
|
||||||
var annotationId = "imagine_this_makes_sense";
|
var annotationId = "imagine_this_makes_sense";
|
||||||
|
var commentId = "commentId";
|
||||||
EntityLog entityLog = new EntityLog(1,
|
EntityLog entityLog = new EntityLog(1,
|
||||||
1,
|
1,
|
||||||
List.of(EntityLogEntry.builder()
|
List.of(EntityLogEntry.builder()
|
||||||
@ -397,6 +399,14 @@ public class FileTest extends AbstractPersistenceServerServiceTest {
|
|||||||
.value("value entry 3")
|
.value("value entry 3")
|
||||||
.state(EntryState.APPLIED)
|
.state(EntryState.APPLIED)
|
||||||
.entryType(EntryType.ENTITY)
|
.entryType(EntryType.ENTITY)
|
||||||
|
.build(),
|
||||||
|
EntityLogEntry.builder()
|
||||||
|
.id(commentId)
|
||||||
|
.type(type.getType())
|
||||||
|
.value("value entry 4")
|
||||||
|
.dictionaryEntry(true)
|
||||||
|
.state(EntryState.APPLIED)
|
||||||
|
.entryType(EntryType.ENTITY)
|
||||||
.build()),
|
.build()),
|
||||||
null,
|
null,
|
||||||
0,
|
0,
|
||||||
@ -445,19 +455,39 @@ public class FileTest extends AbstractPersistenceServerServiceTest {
|
|||||||
.build()),
|
.build()),
|
||||||
false);
|
false);
|
||||||
|
|
||||||
|
manualRedactionClient.addComment(dossierId, fileId, commentId, AddCommentRequestModel.builder().text("comment added via text fileId").build());
|
||||||
|
|
||||||
var loadedFile = fileClient.getFileStatus(dossierId, fileId);
|
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());
|
fileManagementClient.deleteFile(dossier.getId(), file.getId());
|
||||||
var softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId());
|
var softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId());
|
||||||
assertThat(softDeletedFiles).hasSize(1);
|
assertThat(softDeletedFiles).hasSize(1);
|
||||||
var activeFiles = fileClient.getDossierStatus(dossier.getId());
|
var activeFiles = fileClient.getDossierStatus(dossier.getId());
|
||||||
assertThat(activeFiles).isEmpty();
|
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()));
|
fileManagementClient.restoreFiles(dossier.getId(), Sets.newHashSet(file.getId()));
|
||||||
softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId());
|
softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId());
|
||||||
assertThat(softDeletedFiles).isEmpty();
|
assertThat(softDeletedFiles).isEmpty();
|
||||||
activeFiles = fileClient.getDossierStatus(dossier.getId());
|
activeFiles = fileClient.getDossierStatus(dossier.getId());
|
||||||
assertThat(activeFiles).hasSize(1);
|
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()));
|
fileManagementClient.hardDeleteFiles(dossier.getId(), List.of(file.getId()));
|
||||||
softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId());
|
softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId());
|
||||||
@ -697,4 +727,89 @@ public class FileTest extends AbstractPersistenceServerServiceTest {
|
|||||||
assertThrows(FeignException.class, () -> uploadClient.upload(malformedCsvFile, dossier.getId(), false));
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user