RED-9888: DM: Components not restored after file re-upload
This commit is contained in:
parent
dc8abbba58
commit
e4ec187c2f
@ -172,6 +172,18 @@ public class ComponentLogService {
|
||||
|
||||
}
|
||||
|
||||
private void hardDeleteAllOverrides(String dossierId, String fileId) {
|
||||
|
||||
componentLogMongoService.hardDeleteComponentLogEntries(dossierId, fileId);
|
||||
|
||||
}
|
||||
|
||||
private void softDeleteAllOverrides(String dossierId, String fileId) {
|
||||
|
||||
componentLogMongoService.softDeleteComponentLogEntries(dossierId, fileId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void insertOverride(String dossierId, String fileId, ComponentLogEntry componentToAdd) {
|
||||
|
||||
@ -181,7 +193,7 @@ public class ComponentLogService {
|
||||
|
||||
public List<ComponentLogEntry> getOverrides(String dossierId, String fileId) {
|
||||
|
||||
return componentLogMongoService.findOverrides(dossierId, fileId);
|
||||
return componentLogMongoService.findOverrides(dossierId, fileId, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ public class DossierDeletionService {
|
||||
public void undeleteDossier(String dossierId, List<String> relevantFileIds, OffsetDateTime dossierSoftDeleteTime) {
|
||||
|
||||
relevantFileIds.forEach(fileId -> {
|
||||
fileDeletionService.undeleteFile(fileId, dossierSoftDeleteTime);
|
||||
fileDeletionService.undeleteFile(dossierId, fileId, dossierSoftDeleteTime);
|
||||
});
|
||||
|
||||
dossierService.undeleteDossier(dossierId);
|
||||
@ -30,7 +30,7 @@ public class DossierDeletionService {
|
||||
@Transactional
|
||||
public void softDeleteDossier(String dossierId, List<String> relevantFileIds, OffsetDateTime softDeleteTime) {
|
||||
|
||||
fileDeletionService.softDeleteFiles(relevantFileIds, softDeleteTime);
|
||||
fileDeletionService.softDeleteFiles(dossierId, relevantFileIds, softDeleteTime);
|
||||
dossierService.softDeleteDossier(dossierId, softDeleteTime);
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ public class DossierDeletionService {
|
||||
@Transactional
|
||||
public void hardDeleteDossier(String dossierId, List<String> relevantFileIds) {
|
||||
|
||||
fileDeletionService.hardDeleteFiles(relevantFileIds);
|
||||
fileDeletionService.hardDeleteFiles(dossierId, relevantFileIds);
|
||||
dossierService.hardDeleteDossier(dossierId);
|
||||
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ import com.iqser.red.service.persistence.management.v1.processor.service.persist
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.RemoveRedactionPersistenceService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.ResizeRedactionPersistenceService;
|
||||
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.mongo.service.ComponentLogMongoService;
|
||||
import com.iqser.red.service.search.v1.model.IndexMessageType;
|
||||
import jakarta.transaction.Transactional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -38,10 +39,11 @@ public class FileDeletionService {
|
||||
private final FileStatusPersistenceService fileStatusPersistenceService;
|
||||
private final FileManagementStorageService fileManagementStorageService;
|
||||
private final IndexingService indexingService;
|
||||
private final ComponentLogMongoService componentLogMongoService;
|
||||
|
||||
|
||||
@Transactional
|
||||
public void undeleteFile(String fileId, OffsetDateTime softDeletedTime) {
|
||||
public void undeleteFile(String dossierId, String fileId, OffsetDateTime softDeletedTime) {
|
||||
|
||||
// revert comment deletion
|
||||
commentPersistenceService.undeleteByFileId(fileId, softDeletedTime);
|
||||
@ -54,12 +56,15 @@ public class FileDeletionService {
|
||||
legalBasisChangePersistenceService.undeleteByFileId(fileId, softDeletedTime);
|
||||
resizeRedactionPersistenceService.undeleteByFileId(fileId, softDeletedTime);
|
||||
|
||||
//revert override deletion
|
||||
componentLogMongoService.undeleteComponentLogEntries(dossierId, fileId);
|
||||
|
||||
fileStatusPersistenceService.undelete(fileId);
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public void softDeleteFiles(List<String> fileIds, OffsetDateTime softDeleteTime) {
|
||||
public void softDeleteFiles(String dossierId, List<String> fileIds, OffsetDateTime softDeleteTime) {
|
||||
|
||||
// delete all annotations
|
||||
addRedactionPersistenceService.softDeleteByFileIds(fileIds, softDeleteTime);
|
||||
@ -75,6 +80,9 @@ public class FileDeletionService {
|
||||
// delete all viewed pages for all files
|
||||
viewedPagesPersistenceService.deleteForFiles(fileIds);
|
||||
|
||||
//delete all overrides
|
||||
fileIds.forEach(fileId -> componentLogMongoService.softDeleteComponentLogEntries(dossierId, fileId));
|
||||
|
||||
fileStatusPersistenceService.softDeleteFiles(fileIds, softDeleteTime);
|
||||
|
||||
}
|
||||
@ -114,14 +122,14 @@ public class FileDeletionService {
|
||||
|
||||
|
||||
@Transactional
|
||||
public void hardDeleteFile(String fileId) {
|
||||
public void hardDeleteFile(String dossierId, String fileId) {
|
||||
|
||||
this.hardDeleteFiles(List.of(fileId));
|
||||
this.hardDeleteFiles(dossierId, List.of(fileId));
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public void hardDeleteFiles(List<String> fileIds) {
|
||||
public void hardDeleteFiles(String dossierId, List<String> fileIds) {
|
||||
|
||||
// delete all annotations
|
||||
addRedactionPersistenceService.deleteByFileIds(fileIds);
|
||||
@ -137,6 +145,10 @@ public class FileDeletionService {
|
||||
// delete all viewed pages for all files
|
||||
viewedPagesPersistenceService.deleteForFiles(fileIds);
|
||||
|
||||
//delete all overrides
|
||||
fileIds.forEach(fileId -> componentLogMongoService.hardDeleteComponentLogEntries(dossierId, fileId));
|
||||
|
||||
|
||||
fileStatusPersistenceService.hardDeleteFiles(fileIds);
|
||||
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ public class FileService {
|
||||
}
|
||||
|
||||
OffsetDateTime softDeleteTime = OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
fileDeletionService.softDeleteFiles(List.of(fileId), softDeleteTime);
|
||||
fileDeletionService.softDeleteFiles(dossierId, List.of(fileId), softDeleteTime);
|
||||
fileDeletionService.reindexDeletedFiles(dossierId, List.of(fileId));
|
||||
websocketService.sendFileEvent(dossierId, fileId, FileEventType.SOFT_DELETE);
|
||||
}
|
||||
@ -106,7 +106,7 @@ public class FileService {
|
||||
throw new DossierNotFoundException(DOSSIER_NOT_FOUND_MESSAGE);
|
||||
}
|
||||
|
||||
fileDeletionService.hardDeleteFiles(fileIds);
|
||||
fileDeletionService.hardDeleteFiles(dossierId, fileIds);
|
||||
fileDeletionService.hardDeleteFileDataAndIndexUpdates(dossierId, fileIds);
|
||||
fileIds.forEach(fileId -> {
|
||||
websocketService.sendFileEvent(dossierId, fileId, FileEventType.HARD_DELETE);
|
||||
@ -124,7 +124,7 @@ public class FileService {
|
||||
for (String fileId : fileIds) {
|
||||
FileModel fileStatus = fileStatusService.getStatus(fileId);
|
||||
OffsetDateTime softDeletedTime = fileStatus.getDeleted();
|
||||
fileDeletionService.undeleteFile(fileId, softDeletedTime);
|
||||
fileDeletionService.undeleteFile(dossierId, fileId, softDeletedTime);
|
||||
}
|
||||
fileDeletionService.reindexUndeletedFiles(dossier.getDossierTemplateId(), dossierId, fileIds);
|
||||
fileIds.forEach(fileId -> {
|
||||
|
||||
@ -61,7 +61,7 @@ public class DeletedFilesCleanupJob implements Job {
|
||||
if (file.getHardDeletedTime() == null && file.getDeleted() != null && file.getDeleted()
|
||||
.isBefore(now.minusHours(applicationConfigurationEntity.getSoftDeleteCleanupTime()))) {
|
||||
|
||||
fileDeletionService.hardDeleteFile(file.getId());
|
||||
fileDeletionService.hardDeleteFile(file.getDossierId(), file.getId());
|
||||
fileDeletionService.hardDeleteFileDataAndIndexUpdates(dossierEntity.getId(),file.getId());
|
||||
log.info("Hard deleted file with dossier id {} and file id {}", dossierEntity.getId(), file.getId());
|
||||
}
|
||||
|
||||
@ -21,9 +21,11 @@ import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemp
|
||||
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.management.v1.processor.service.FileService;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLogEntry;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.component.ComponentsOverrides;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.component.RevertOverrideRequest;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.AddFileRequest;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
|
||||
import com.iqser.red.service.persistence.service.v2.api.external.model.Component;
|
||||
import com.iqser.red.service.persistence.service.v2.api.external.model.ComponentValue;
|
||||
@ -49,6 +51,9 @@ public class ComponentOverrideTest extends AbstractPersistenceServerServiceTest
|
||||
@Autowired
|
||||
private DossierTemplateClient dossierTemplateClient;
|
||||
|
||||
@Autowired
|
||||
private FileService fileService;
|
||||
|
||||
|
||||
@Test
|
||||
public void testOverrides() throws IOException {
|
||||
@ -199,7 +204,86 @@ public class ComponentOverrideTest extends AbstractPersistenceServerServiceTest
|
||||
.findAny()
|
||||
.get();
|
||||
assertTrue(studyTitle.isOverridden());
|
||||
assertTrue(studyTitle.getComponentValues().stream().anyMatch(componentLogEntryValue -> componentLogEntryValue.getValue().equals(value)));
|
||||
assertTrue(studyTitle.getComponentValues()
|
||||
.stream()
|
||||
.anyMatch(componentLogEntryValue -> componentLogEntryValue.getValue().equals(value)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDeletedFileOverrides() throws IOException {
|
||||
|
||||
var dossier = dossierTesterAndProvider.provideTestDossier();
|
||||
|
||||
var dossierTemplate = dossierTemplateClient.getDossierTemplate(dossier.getDossierTemplateId());
|
||||
|
||||
var file = fileTesterAndProvider.testAndProvideFile(dossier, "filename");
|
||||
|
||||
System.out.println("DOSSIER TEMPLATE ID: " + dossierTemplate.getId());
|
||||
System.out.println("DOSSIER ID: " + dossier.getId());
|
||||
System.out.println("FILE ID: " + file.getId());
|
||||
|
||||
Component componentOverrideModel = Component.builder()
|
||||
.name("Study_Title")
|
||||
.componentValues(List.of(ComponentValue.builder()
|
||||
.value("AAAA Strange Chemical Name And the rest of a title – With a dash and some more text")
|
||||
.originalValue("Strange Chemical Name And the rest of a title – With a dash and some more text")
|
||||
.valueDescription("First found value of type title or else ''")
|
||||
.componentRuleId("StudyTitle.0.0")
|
||||
.entityReferences(List.of(EntityReference.builder()
|
||||
.id("cf7f0d0c4c07918ce7d67b204f5fdb7d")
|
||||
.type("title")
|
||||
.entityRuleId("DOC.6.1")
|
||||
.page(1)
|
||||
.build()))
|
||||
.build()))
|
||||
.build();
|
||||
|
||||
var componentLogJson = new ClassPathResource("files/componentlog/exampleComponentLog.json");
|
||||
|
||||
fileManagementStorageService.storeObject(dossier.getId(), file.getId(), FileType.COMPONENT_LOG, componentLogJson.getInputStream());
|
||||
|
||||
componentClient.addOverride(dossierTemplate.getId(), dossier.getId(), file.getId(), componentOverrideModel);
|
||||
|
||||
var overrides = componentClient.getOverrides(dossierTemplate.getId(), dossier.getId(), file.getId());
|
||||
|
||||
assertFalse(overrides.getComponentOverrides().isEmpty());
|
||||
assertTrue(overrides.getComponentOverrides()
|
||||
.get(0).isOverridden());
|
||||
|
||||
// case 1: delete file, overrides should not be returned anymore
|
||||
fileService.deleteFile(dossier.getId(), file.getFileId());
|
||||
|
||||
overrides = componentClient.getOverrides(dossierTemplate.getId(), dossier.getId(), file.getId());
|
||||
|
||||
assertTrue(overrides.getComponentOverrides().isEmpty());
|
||||
|
||||
// case 2: re-upload file that was deleted before overrides should also not be returned anymore
|
||||
fileTesterAndProvider.testAndProvideFile(dossier, "filename");
|
||||
|
||||
overrides = componentClient.getOverrides(dossierTemplate.getId(), dossier.getId(), file.getId());
|
||||
|
||||
assertTrue(overrides.getComponentOverrides().isEmpty());
|
||||
|
||||
// delete file again
|
||||
fileService.deleteFile(dossier.getId(), file.getFileId());
|
||||
|
||||
// case 3: when undeleting, the overrides should be there again (restored)
|
||||
fileService.undeleteFiles(dossier.getId(), Set.of(file.getFileId()));
|
||||
|
||||
overrides = componentClient.getOverrides(dossierTemplate.getId(), dossier.getId(), file.getId());
|
||||
|
||||
assertFalse(overrides.getComponentOverrides().isEmpty());
|
||||
assertTrue(overrides.getComponentOverrides()
|
||||
.get(0).isOverridden());
|
||||
|
||||
// case 4: on hard delete overrides should also be gone of course
|
||||
fileService.hardDeleteFiles(dossier.getId(), List.of(file.getFileId()));
|
||||
|
||||
overrides = componentClient.getOverrides(dossierTemplate.getId(), dossier.getId(), file.getId());
|
||||
|
||||
assertTrue(overrides.getComponentOverrides().isEmpty());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.iqser.red.service.persistence.service.v1.api.shared.mongo.document;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -37,4 +38,6 @@ public class ComponentDocument {
|
||||
|
||||
boolean overridden;
|
||||
|
||||
OffsetDateTime softDeletedTime;
|
||||
|
||||
}
|
||||
|
||||
@ -15,12 +15,19 @@ public interface ComponentDocumentRepository extends MongoRepository<ComponentDo
|
||||
@Query(value = "{ 'componentLogId' : ?0}", delete = true)
|
||||
void deleteByComponentLogId(String componentLogId);
|
||||
|
||||
|
||||
@Query(value = "{ 'componentLogId': ?0, 'componentName': ?1 }")
|
||||
Optional<ComponentDocument> findComponentDocumentByName(String componentLogId, String componentName);
|
||||
|
||||
|
||||
@Query(value = "{ 'componentLogId': ?0 }")
|
||||
List<ComponentDocument> findByComponentLogId(String componentLogId);
|
||||
|
||||
|
||||
@Query(value = "{ 'componentLogId': ?0, 'softDeletedTime': { $eq: null } }")
|
||||
List<ComponentDocument> findByComponentLogIdExcludeSoftDeleted(String componentLogId);
|
||||
|
||||
|
||||
@Query(value = "{ 'componentLogId': ?0 }", fields = "{ 'overrideValues': 0 }")
|
||||
List<ComponentDocument> findWithoutOverrideValuesByDossierIdAndFileId(String componentLogId);
|
||||
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
package com.iqser.red.service.persistence.service.v1.api.shared.mongo.service;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.ComponentDocument;
|
||||
|
||||
@Service
|
||||
public class ComponentDocumentUpdateService {
|
||||
|
||||
private final MongoTemplate mongoTemplate;
|
||||
|
||||
|
||||
public ComponentDocumentUpdateService(MongoTemplate mongoTemplate) {this.mongoTemplate = mongoTemplate;}
|
||||
|
||||
|
||||
public void setSoftDeletedTime(String componentLogId) {
|
||||
|
||||
Query query = new Query(Criteria.where("componentLogId").is(componentLogId));
|
||||
|
||||
Update update = new Update().set("softDeletedTime", OffsetDateTime.now());
|
||||
mongoTemplate.updateFirst(query, update, ComponentDocument.class);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void unsetSoftDeletedTime(String componentLogId) {
|
||||
|
||||
Query query = new Query(Criteria.where("componentLogId").is(componentLogId));
|
||||
|
||||
Update update = new Update().unset("softDeletedTime");
|
||||
mongoTemplate.updateFirst(query, update, ComponentDocument.class);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -17,24 +17,20 @@ import com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository.
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository.ComponentLogDocumentRepository;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
@Service
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
|
||||
@RequiredArgsConstructor
|
||||
public class ComponentLogMongoService {
|
||||
|
||||
ComponentLogDocumentRepository componentLogDocumentRepository;
|
||||
ComponentDocumentRepository componentDocumentRepository;
|
||||
ComponentDocumentUpdateService componentDocumentUpdateService;
|
||||
ComponentLogDocumentMapper mapper = ComponentLogDocumentMapper.INSTANCE;
|
||||
|
||||
|
||||
public ComponentLogMongoService(ComponentLogDocumentRepository componentLogDocumentRepository, ComponentDocumentRepository componentDocumentRepository) {
|
||||
|
||||
this.componentLogDocumentRepository = componentLogDocumentRepository;
|
||||
this.componentDocumentRepository = componentDocumentRepository;
|
||||
}
|
||||
|
||||
|
||||
public void insertComponentLog(String dossierId, String fileId, ComponentLog componentLog) {
|
||||
|
||||
ComponentLogDocument componentLogDocument = componentLogDocumentRepository.insert(mapper.toComponentLogDocument(dossierId, fileId, componentLog));
|
||||
@ -109,6 +105,30 @@ public class ComponentLogMongoService {
|
||||
}
|
||||
|
||||
|
||||
public void hardDeleteComponentLogEntries(String dossierId, String fileId) {
|
||||
|
||||
String componentLogId = mapper.getComponentLogId(dossierId, fileId);
|
||||
|
||||
componentDocumentRepository.deleteByComponentLogId(componentLogId);
|
||||
}
|
||||
|
||||
|
||||
public void softDeleteComponentLogEntries(String dossierId, String fileId) {
|
||||
|
||||
String componentLogId = mapper.getComponentLogId(dossierId, fileId);
|
||||
|
||||
componentDocumentUpdateService.setSoftDeletedTime(componentLogId);
|
||||
}
|
||||
|
||||
|
||||
public void undeleteComponentLogEntries(String dossierId, String fileId) {
|
||||
|
||||
String componentLogId = mapper.getComponentLogId(dossierId, fileId);
|
||||
|
||||
componentDocumentUpdateService.unsetSoftDeletedTime(componentLogId);
|
||||
}
|
||||
|
||||
|
||||
private ComponentLogDocument getComponentLogDocument(String componentLogId) {
|
||||
|
||||
return componentLogDocumentRepository.findById(componentLogId)
|
||||
@ -170,12 +190,14 @@ public class ComponentLogMongoService {
|
||||
}
|
||||
|
||||
|
||||
public List<ComponentLogEntry> findOverrides(String dossierId, String fileId) {
|
||||
public List<ComponentLogEntry> findOverrides(String dossierId, String fileId, boolean includeSoftDeleted) {
|
||||
|
||||
String componentLogId = mapper.getComponentLogId(dossierId, fileId);
|
||||
|
||||
return componentDocumentRepository.findByComponentLogId(componentLogId)
|
||||
.stream()
|
||||
List<ComponentDocument> componentDocuments = includeSoftDeleted ? //
|
||||
componentDocumentRepository.findByComponentLogId(componentLogId) : componentDocumentRepository.findByComponentLogIdExcludeSoftDeleted(componentLogId);
|
||||
|
||||
return componentDocuments.stream()
|
||||
.map(mapper::fromComponentDocument)
|
||||
.peek(componentLogEntry -> componentLogEntry.setOverridden(true))
|
||||
.toList();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user