Pull request #311: RED-3594 - archived dossier can be unarchived, when using trash

Merge in RED/persistence-service from bugfix/RED-3594 to master

* commit '9fa238f817505086a4949f158ec7fa6a7d1d063f':
  RED-3594 - archived dossier can be unarchived, when using trash
This commit is contained in:
Corina Olariu 2022-03-21 11:42:22 +01:00 committed by Timo Bejan
commit 9f414b2d0b
13 changed files with 66 additions and 57 deletions

View File

@ -22,7 +22,6 @@ public class Dossier {
private String dossierName;
private OffsetDateTime date;
private String description;
private DossierStatus status;
private String ownerId;
private Set<String> memberIds = new HashSet<>();
private Set<String> approverIds = new HashSet<>();

View File

@ -5,7 +5,6 @@ import com.iqser.red.service.persistence.management.v1.processor.entity.configur
import com.iqser.red.service.persistence.management.v1.processor.utils.JSONDownloadFileTypeConverter;
import com.iqser.red.service.persistence.management.v1.processor.utils.JSONStringSetConverter;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.DownloadFileType;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierStatus;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierVisibility;
import lombok.*;
import org.hibernate.annotations.Fetch;
@ -42,10 +41,6 @@ public class DossierEntity {
@Column(length = 4000)
private String description;
@Column(name = "dossier_status")
@Enumerated(EnumType.STRING)
private DossierStatus status;
@Column
private String ownerId;

View File

@ -9,7 +9,6 @@ import com.iqser.red.service.persistence.management.v1.processor.service.persist
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.ReportTemplateRepository;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.CreateOrUpdateDossierRequest;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierChange;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierStatus;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@ -42,7 +41,6 @@ public class DossierPersistenceService {
DossierEntity dossier = new DossierEntity();
BeanUtils.copyProperties(createOrUpdateDossierRequest, dossier);
dossier.setId(UUID.randomUUID().toString());
dossier.setStatus(DossierStatus.ACTIVE);
dossier.setDate(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
dossier.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
dossier.setDossierTemplate(dossierTemplateRepository.getOne(createOrUpdateDossierRequest.getDossierTemplateId()));
@ -95,7 +93,8 @@ public class DossierPersistenceService {
public DossierEntity getAndValidateDossier(String dossierId) {
// check whether the dossierId exists and is not deleted
var dossier = findByDossierId(dossierId);
if (dossier == null || dossier.getStatus().equals(DossierStatus.DELETED) || dossier.getStatus().equals(DossierStatus.ARCHIVED)) {
if (dossier == null || dossier.getSoftDeletedTime() != null || dossier.getHardDeletedTime() != null
|| dossier.getArchivedTime() != null) {
throw new DossierNotFoundException(String.format(DOSSIER_NOT_FOUND_MESSAGE, dossierId));
}
return dossier;
@ -115,13 +114,13 @@ public class DossierPersistenceService {
@Transactional
public void hardDelete(String dossierId) {
dossierRepository.hardDelete(dossierId, DossierStatus.DELETED, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
dossierRepository.hardDelete(dossierId, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
}
@Transactional
public void undelete(String dossierId) {
int updateCount = dossierRepository.undelete(dossierId, DossierStatus.ACTIVE, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
int updateCount = dossierRepository.undelete(dossierId, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
if (updateCount == 0) {
throw new BadRequestException("Cannot undelete a hard-deleted dossier!");
}
@ -130,7 +129,7 @@ public class DossierPersistenceService {
@Transactional
public void markDossierAsDeleted(String dossierId, OffsetDateTime softDeletedTime) {
dossierRepository.markDossierAsDeleted(dossierId, DossierStatus.DELETED, softDeletedTime, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
dossierRepository.markDossierAsDeleted(dossierId, softDeletedTime, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
}
public Set<DossierChange> hasChangesSince(OffsetDateTime since) {
@ -156,13 +155,13 @@ public class DossierPersistenceService {
@Transactional
public void archiveDossier(String dossierId) {
dossierRepository.archiveDossier(dossierId, DossierStatus.ARCHIVED, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
dossierRepository.archiveDossier(dossierId, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
}
@Transactional
public void unarchiveDossier(String dossierId) {
int updateCount = dossierRepository.unarchiveDossier(dossierId, DossierStatus.ACTIVE, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
int updateCount = dossierRepository.unarchiveDossier(dossierId, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
if (updateCount == 0) {
throw new BadRequestException("Cannot unarchive dossier!");
}

View File

@ -16,41 +16,29 @@ public interface DossierRepository extends JpaRepository<DossierEntity, String>
List<String> findDossierChangeByLastUpdatedIsAfter(OffsetDateTime since);
@Modifying
@Query("update DossierEntity d set d.status = :dossierStatus, d.softDeletedTime = null, d.lastUpdated = :lastUpdated where d.id = :dossierId" +
@Query("update DossierEntity d set d.softDeletedTime = null, d.lastUpdated = :lastUpdated where d.id = :dossierId" +
" and d.hardDeletedTime is null")
int undelete(String dossierId, DossierStatus dossierStatus, OffsetDateTime lastUpdated);
int undelete(String dossierId, OffsetDateTime lastUpdated);
@Modifying
@Query("update DossierEntity d set d.status = :dossierStatus, d.softDeletedTime = :softDeletedTime, d.lastUpdated = :lastUpdated where d.id = :dossierId")
void markDossierAsDeleted(String dossierId, DossierStatus dossierStatus, OffsetDateTime softDeletedTime, OffsetDateTime lastUpdated);
@Query("update DossierEntity d set d.softDeletedTime = :softDeletedTime, d.lastUpdated = :lastUpdated where d.id = :dossierId")
void markDossierAsDeleted(String dossierId, OffsetDateTime softDeletedTime, OffsetDateTime lastUpdated);
@Modifying
@Query("update DossierEntity d set d.status = :dossierStatus, d.hardDeletedTime = :hardDeletedTime, d.lastUpdated = :lastUpdated, " +
@Query("update DossierEntity d set d.hardDeletedTime = :hardDeletedTime, d.lastUpdated = :lastUpdated, " +
"d.softDeletedTime = " +
"case " +
"when d.softDeletedTime is null then :hardDeletedTime " +
"else d.softDeletedTime " +
"end " +
"where d.id = :dossierId")
void hardDelete(String dossierId, DossierStatus dossierStatus, OffsetDateTime hardDeletedTime, OffsetDateTime lastUpdated);
void hardDelete(String dossierId, OffsetDateTime hardDeletedTime, OffsetDateTime lastUpdated);
@Modifying
@Query("update DossierEntity d set d.archivedTime = :archiveTime, d.lastUpdated = :archiveTime, " +
"d.status = " +
"case " +
"when d.softDeletedTime is null then :dossierStatus " +
"else d.status " +
"end " +
"where d.id = :dossierId")
void archiveDossier(String dossierId, DossierStatus dossierStatus, OffsetDateTime archiveTime);
@Query("update DossierEntity d set d.archivedTime = :archiveTime, d.lastUpdated = :archiveTime where d.id = :dossierId ")
void archiveDossier(String dossierId, OffsetDateTime archiveTime);
@Modifying
@Query("update DossierEntity d set d.lastUpdated = :lastUpdated, d.archivedTime = null, " +
"d.status = " +
"case " +
"when d.softDeletedTime is null then :dossierStatus " +
"else d.status " +
"end " +
"where d.id = :dossierId")
int unarchiveDossier(String dossierId, DossierStatus dossierStatus, OffsetDateTime lastUpdated);
@Query("update DossierEntity d set d.lastUpdated = :lastUpdated, d.archivedTime = null where d.id = :dossierId")
int unarchiveDossier(String dossierId, OffsetDateTime lastUpdated);
}

View File

@ -141,7 +141,7 @@ public interface FileRepository extends JpaRepository<FileEntity, String> {
@Query("select f from FileEntity f join DossierEntity d on d.id = f.dossierId where f.workflowStatus <> 'APPROVED' and f.excludedFromAutomaticAnalysis = false " +
"and ( f.processingStatus = 'PROCESSED' or f.processingStatus = 'UNPROCESSED' or f.processingStatus = 'DELETED' or f.processingStatus = 'ERROR' )" +
"and d.softDeletedTime is null and d.hardDeletedTime is null and d.status = 'ACTIVE' " )
"and d.softDeletedTime is null and d.hardDeletedTime is null and d.archivedTime is null " )
List<FileEntity> getAllRelevantStatusesForReanalysisScheduler();
@Modifying(clearAutomatically = true)

View File

@ -6,7 +6,6 @@ import com.iqser.red.service.peristence.v1.server.service.FileStatusService;
import com.iqser.red.service.peristence.v1.server.service.IndexingService;
import com.iqser.red.service.peristence.v1.server.utils.DossierMapper;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity;
import com.iqser.red.service.persistence.management.v1.processor.exception.DossierNotFoundException;
import com.iqser.red.service.persistence.service.v1.api.model.common.JSONPrimitive;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.*;
@ -71,7 +70,7 @@ public class DossierController implements DossierResource {
OffsetDateTime now = OffsetDateTime.now();
DossierEntity dossier = dossierService.getDossierById(dossierId);
if (dossier.getStatus().equals(DossierStatus.DELETED)) {
if (dossier.getSoftDeletedTime() != null /*|| dossier.getHardDeletedTime() != null*/) {
throw new DossierNotFoundException(String.format(DOSSIER_NOT_FOUND_MESSAGE, dossierId));
}
@ -97,7 +96,7 @@ public class DossierController implements DossierResource {
return convert(dossierService.getAllDossiers()
.stream()
.filter(p -> p.getStatus().equals(DossierStatus.ACTIVE) || includeDeleted && p.getStatus().equals(DossierStatus.DELETED) || includeArchived && p.getStatus().equals(DossierStatus.ARCHIVED))
.filter(p -> p.getSoftDeletedTime() == null && p.getArchivedTime() == null || includeDeleted && p.getSoftDeletedTime() != null || includeArchived && p.getArchivedTime() != null)
.collect(Collectors.toList()), Dossier.class, new DossierMapper());
}
@ -128,10 +127,10 @@ public class DossierController implements DossierResource {
@RequestParam(name = INCLUDE_DELETED_PARAM, defaultValue = "false", required = false) boolean includeDeleted) {
DossierEntity dossier = dossierService.getDossierById(dossierId);
if (dossier.getStatus().equals(DossierStatus.ARCHIVED) && !includeArchived) {
if (dossier.getArchivedTime() != null && !includeArchived) {
throw new DossierNotFoundException(String.format(DOSSIER_NOT_FOUND_MESSAGE, dossierId));
}
if (dossier.getStatus().equals(DossierStatus.DELETED) && !includeDeleted) {
if (dossier.getSoftDeletedTime() != null && !includeDeleted) {
throw new DossierNotFoundException(String.format(DOSSIER_NOT_FOUND_MESSAGE, dossierId));
}
return convert(dossier, Dossier.class, new DossierMapper());
@ -144,7 +143,7 @@ public class DossierController implements DossierResource {
var archivedDossiers = convert(dossierService.getAllDossiers()
.stream()
.filter(p -> p.getStatus().equals(DossierStatus.ARCHIVED) && p.getHardDeletedTime() == null)
.filter(p -> p.getArchivedTime() != null && p.getHardDeletedTime() == null)
.collect(Collectors.toList()), Dossier.class, new DossierMapper());
archivedDossiers.sort((dossier1, dossier2) -> dossier2.getArchivedTime().compareTo(dossier1.getArchivedTime()));
@ -158,7 +157,7 @@ public class DossierController implements DossierResource {
var softDeletedDossiers = convert(dossierService.getAllDossiers()
.stream()
.filter(p -> p.getStatus().equals(DossierStatus.DELETED) && p.getHardDeletedTime() == null)
.filter(p -> p.getSoftDeletedTime() != null && p.getHardDeletedTime() == null)
.collect(Collectors.toList()), Dossier.class, new DossierMapper());
softDeletedDossiers.sort((dossier1, dossier2) -> dossier2.getSoftDeletedTime().compareTo(dossier1.getSoftDeletedTime()));

View File

@ -10,11 +10,9 @@ import com.iqser.red.service.peristence.v1.server.service.FileManagementStorageS
import com.iqser.red.service.peristence.v1.server.service.FileService;
import com.iqser.red.service.peristence.v1.server.service.FileStatusService;
import com.iqser.red.service.persistence.management.v1.processor.client.PDFTronRedactionClient;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity;
import com.iqser.red.service.persistence.management.v1.processor.exception.DossierNotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.service.v1.api.model.common.JSONPrimitive;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierStatus;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.BinaryFileRequest;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.BinaryFileResult;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileModel;
@ -59,7 +57,7 @@ public class UploadController implements UploadResource {
public void deleteFile(@PathVariable(DOSSIER_ID_PARAM) String dossierId, @PathVariable(FILE_ID) String fileId) {
var dossier = dossierService.getDossierById(dossierId);
if (dossier.getStatus().equals(DossierStatus.DELETED)) {
if (dossier.getSoftDeletedTime() != null) {
throw new DossierNotFoundException(String.format(DOSSIER_NOT_FOUND_MESSAGE, dossierId));
}
@ -72,7 +70,7 @@ public class UploadController implements UploadResource {
public void hardDeleteFiles(@PathVariable(DOSSIER_ID_PARAM) String dossierId, @RequestBody Set<String> fileIds) {
var dossier = dossierService.getDossierById(dossierId);
if (dossier.getStatus().equals(DossierStatus.DELETED)) {
if (dossier.getSoftDeletedTime() != null) {
throw new DossierNotFoundException(String.format(DOSSIER_NOT_FOUND_MESSAGE, dossierId));
}
@ -86,7 +84,7 @@ public class UploadController implements UploadResource {
@Override
public void undeleteFiles(@PathVariable(DOSSIER_ID_PARAM) String dossierId, @RequestBody Set<String> fileIds) {
var dossier = dossierService.getDossierById(dossierId);
if (dossier.getStatus().equals(DossierStatus.DELETED)) {
if (dossier.getSoftDeletedTime() != null) {
throw new DossierNotFoundException(String.format(DOSSIER_NOT_FOUND_MESSAGE, dossierId));
}

View File

@ -41,13 +41,13 @@ public class IndexingService {
if (dossierId == null) {
List<DossierEntity> dossiers = dossierService.getAllDossiers();
for (DossierEntity dossier : dossiers) {
if (dossier.getStatus().equals(DossierStatus.ACTIVE) || dossier.getStatus().equals(DossierStatus.ARCHIVED)) {
if (dossier.getSoftDeletedTime() == null || dossier.getArchivedTime() != null) {
reindexDossierIds.add(new ImmutablePair<>(dossier.getDossierTemplateId(), dossier.getId()));
}
}
} else {
DossierEntity dossier = dossierService.getDossierById(dossierId);
if (dossier.getStatus().equals(DossierStatus.ACTIVE) || dossier.getStatus().equals(DossierStatus.ARCHIVED)) {
if (dossier.getSoftDeletedTime() == null || dossier.getArchivedTime() != null) {
reindexDossierIds.add(new ImmutablePair<>(dossier.getDossierTemplateId(), dossier.getId()));
}
}

View File

@ -4,7 +4,6 @@ import com.iqser.red.service.peristence.v1.server.service.DossierService;
import com.iqser.red.service.peristence.v1.server.settings.FileManagementServiceSettings;
import com.iqser.red.service.persistence.management.v1.processor.entity.download.DownloadStatusEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DownloadStatusPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierStatus;
import com.iqser.red.storage.commons.service.StorageService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -49,7 +48,7 @@ public class DownloadCleanupService {
.getDownloadCleanupNotDownloadFilesHours(), downloadStatus.getCreationDate()
.plusHours(settings.getDownloadCleanupNotDownloadFilesHours()), now);
deleteDownload(downloadStatus);
} else if (dossierService.getDossierById(dossier.getId()).getStatus() == DossierStatus.DELETED) {
} else if (dossierService.getDossierById(dossier.getId()).getSoftDeletedTime() != null) {
log.info("3. Deleting download {}, because dossier does not exist", downloadStatus.getStorageId());
deleteDownload(downloadStatus);
}

View File

@ -0,0 +1,9 @@
databaseChangeLog:
- changeSet:
id: dossier-remove-dossier-state-column
author: corina
changes:
- removeColumn:
columns:
- name: dossier_status
tableName: dossier

View File

@ -35,3 +35,7 @@ databaseChangeLog:
file: db/changelog/release-3.2.0/1-add-index-on-dictionary-entry.changelog.yaml
- include:
file: db/changelog/14-add-redaction-source-id.changelog.yaml
- include:
file: db/changelog/15-dossier-remove-dossier-state.changelog.yaml

View File

@ -2,6 +2,7 @@ package com.iqser.red.service.peristence.v1.server.integration.tests;
import com.google.common.collect.Sets;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierStatusClient;
import com.iqser.red.service.peristence.v1.server.integration.client.ReportTemplateClient;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTemplateTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTesterAndProvider;
@ -10,6 +11,7 @@ import com.iqser.red.service.persistence.service.v1.api.model.common.JSONPrimiti
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.ReportTemplate;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.ReportTemplateUploadRequest;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.CreateOrUpdateDossierRequest;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.CreateOrUpdateDossierStatusRequest;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.Dossier;
import feign.FeignException;
import org.junit.Test;
@ -37,6 +39,9 @@ public class DossierTest extends AbstractPersistenceServerServiceTest {
@Autowired
private ReportTemplateClient reportTemplateClient;
@Autowired
private DossierStatusClient dossierStatusClient;
@Test
public void testDossier() {
@ -58,10 +63,26 @@ public class DossierTest extends AbstractPersistenceServerServiceTest {
BeanUtils.copyProperties(dossier, cru);
cru.setDossierName("Dossier 1 Update");
cru.setWatermarkPreviewEnabled(true);
// Create dossier status
CreateOrUpdateDossierStatusRequest crudsr = new CreateOrUpdateDossierStatusRequest();
crudsr.setName("name1");
crudsr.setDescription("description1");
crudsr.setDossierTemplateId(dossier.getDossierTemplateId());
var loadedDossierStatus = dossierStatusClient.createOrUpdateDossierStatus(crudsr);
assertThat(loadedDossierStatus).isNotNull();
cru.setDossierStatusId(loadedDossierStatus.getId());
var updated = dossierClient.updateDossier(cru, dossier.getId());
assertThat(updated.getDossierName()).isEqualTo("Dossier 1 Update");
assertThat(updated.isWatermarkPreviewEnabled()).isEqualTo(true);
assertThat(updated.getDossierStatusId()).isEqualTo(loadedDossierStatus.getId());
// put dossier status to null
cru.setDossierStatusId(null);
updated = dossierClient.updateDossier(cru, dossier.getId());
assertThat(updated.getDossierStatusId()).isNull();
var loadedTemplate = dossierClient.getDossierById(updated.getId(), false, false);
@ -158,10 +179,10 @@ public class DossierTest extends AbstractPersistenceServerServiceTest {
dossierClient.delete(dossier1.getId());
dossierClient.archiveDossiers(Set.of(dossier1.getId(), dossier2.getId()));
assertThat(dossierClient.getAllDossiers(false, false)).hasSize(0);
assertThat(dossierClient.getAllDossiers(true, false)).hasSize(1);
assertThat(dossierClient.getAllDossiers(true, false)).hasSize(2);
assertThat(dossierClient.getAllDossiers(false, true)).hasSize(1);
assertThat(dossierClient.getAllDossiers(true, true)).hasSize(2);
assertThat(dossierClient.getArchivedDossiers()).hasSize(1);
assertThat(dossierClient.getArchivedDossiers()).hasSize(2);
assertThat(dossierClient.getSoftDeletedDossiers()).hasSize(1);
dossierInformation = dossierClient.getDossierInformation();

View File

@ -9,7 +9,6 @@ import com.iqser.red.service.persistence.management.v1.processor.entity.configur
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.*;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.DownloadFileType;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.Dossier;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierStatus;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileAttributeType;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.ProcessingStatus;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.WorkflowStatus;
@ -122,7 +121,6 @@ public class FilePerformanceTest extends AbstractPersistenceServerServiceTest {
d.setDossierName("Dossier " + i);
d.setDossierTemplate(dte);
d.setDueDate(OffsetDateTime.now());
d.setStatus(DossierStatus.ACTIVE);
d.setDescription("Lorem Ipsum");
d.setWatermarkEnabled(true);
d.setStartDate(OffsetDateTime.now());