RED-5049 - Allow reports to be downloaded in all document states

- add new endpoint to prepare the download package with options: the reports list and the download types list
- unapproved files can be present in the package but not in redacted form
- add reports list to download status entity
This commit is contained in:
devplant 2022-11-10 11:44:38 +02:00
parent 3a2905200f
commit c34698c202
11 changed files with 124 additions and 14 deletions

View File

@ -28,5 +28,6 @@ public class DownloadStatus {
private String dossierId;
private List<String> fileIds = new ArrayList<>();
private List<DownloadFileType> downloadFileTypes = new ArrayList<>();
private List<String> reportTemplateIds = new ArrayList<>();
}

View File

@ -0,0 +1,29 @@
package com.iqser.red.service.persistence.service.v1.api.model.download;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.DownloadFileType;
import lombok.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class DownloadWithOptionRequest {
private String userId;
private String dossierId;
@Builder.Default
private List<String> fileIds = new ArrayList<>();
@Builder.Default
private List<String> reportTemplateIds = new ArrayList<>();
@Builder.Default
private Set<DownloadFileType> downloadFileTypes = new HashSet<>();
}

View File

@ -2,6 +2,7 @@ package com.iqser.red.service.persistence.service.v1.api.resources;
import java.util.List;
import com.iqser.red.service.persistence.service.v1.api.model.download.DownloadWithOptionRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
@ -24,6 +25,8 @@ public interface DownloadResource {
@PostMapping(value = REST_PATH + "/prepare", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
JSONPrimitive<String> prepareDownload(@RequestBody DownloadRequest request);
@PostMapping(value = REST_PATH + "/prepare-option", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
JSONPrimitive<String> prepareDownload(@RequestBody DownloadWithOptionRequest request);
@GetMapping(value = REST_PATH + "/status/{" + USER_ID + "}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
List<DownloadStatus> getDownloadStatus(@PathVariable(USER_ID) String userId);

View File

@ -17,6 +17,7 @@ import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.ReportTemplateEntity;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
@ -72,4 +73,8 @@ public class DownloadStatusEntity {
@Convert(converter = JSONDownloadFileTypeConverter.class)
Set<DownloadFileType> downloadFileTypes = new HashSet<>();
@ManyToMany(fetch = FetchType.LAZY)
@Fetch(FetchMode.SUBSELECT)
List<ReportTemplateEntity> reports = new ArrayList<>();
}

View File

@ -9,6 +9,7 @@ import java.util.Set;
import javax.transaction.Transactional;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.ReportTemplateRepository;
import org.springframework.stereotype.Service;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
@ -27,6 +28,7 @@ public class DownloadStatusPersistenceService {
private final DownloadStatusRepository downloadStatusRepository;
private final FileRepository fileRepository;
private final ReportTemplateRepository reportTemplateRepository;
public void createStatus(String userId,
@ -35,7 +37,8 @@ public class DownloadStatusPersistenceService {
String filename,
String mimeType,
List<String> fileIds,
Set<DownloadFileType> downloadFileTypes) {
Set<DownloadFileType> downloadFileTypes,
List<String> reportTemplateIds) {
DownloadStatusEntity downloadStatus = new DownloadStatusEntity();
downloadStatus.setUserId(userId);
@ -46,6 +49,7 @@ public class DownloadStatusPersistenceService {
downloadStatus.setCreationDate(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
downloadStatus.setFiles(fileIds != null ? fileRepository.findAllById(fileIds) : new ArrayList<>());
downloadStatus.setDownloadFileTypes(downloadFileTypes != null ? new HashSet<>(downloadFileTypes) : new HashSet<>());
downloadStatus.setReports(reportTemplateIds != null ? reportTemplateRepository.findAllById(reportTemplateIds) : new ArrayList<>());
downloadStatusRepository.save(downloadStatus);
}
@ -54,7 +58,7 @@ public class DownloadStatusPersistenceService {
// use this to create a status for export dossier template.
public void createStatus(String userId, String storageId, String filename, String mimeType) {
this.createStatus(userId, storageId, null, filename, mimeType, null, null);
this.createStatus(userId, storageId, null, filename, mimeType, null, null, null);
}

View File

@ -6,6 +6,9 @@ import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.ReportTemplateEntity;
import com.iqser.red.service.persistence.service.v1.api.model.download.DownloadWithOptionRequest;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
@ -45,8 +48,6 @@ public class DownloadController implements DownloadResource {
public JSONPrimitive<String> prepareDownload(@RequestBody DownloadRequest request) {
var mimeType = "application/zip";
var existingFileStatuses = fileStatusPersistenceService.getStatusesForDossier(request.getDossierId());
var filesInNotApprovedState = existingFileStatuses.stream()
.filter(f -> request.getFileIds().contains(f.getId()) && !WorkflowStatus.APPROVED.equals(f.getWorkflowStatus()))
@ -54,17 +55,38 @@ public class DownloadController implements DownloadResource {
if (!filesInNotApprovedState.isEmpty()) {
throw new BadRequestException("At least one file is not in Approved state");
}
String downloadFilename = buildName(request.getDossierId(), request.getFileIds(), request.getUserId(), mimeType, existingFileStatuses);
String storageId = StorageIdUtils.getStorageId(request.getUserId(), request.getDossierId(), downloadFilename);
var dossier = dossierPersistenceService.getActiveOrArchivedDossier(request.getDossierId());
downloadStatusPersistenceService.createStatus(request.getUserId(), storageId, dossier, downloadFilename, mimeType, request.getFileIds(), dossier.getDownloadFileTypes());
DownloadWithOptionRequest requestWithOptions = DownloadWithOptionRequest.builder()
.userId(request.getUserId())
.dossierId(request.getDossierId())
.fileIds(request.getFileIds())
.downloadFileTypes(dossier.getDownloadFileTypes())
.reportTemplateIds(dossier.getReportTemplates().stream().map(ReportTemplateEntity::getTemplateId).collect(Collectors.toList()))
.build();
return this.startPrepareDownload(requestWithOptions, dossier, existingFileStatuses);
}
public JSONPrimitive<String> prepareDownload(@RequestBody DownloadWithOptionRequest request) {
var existingFileStatuses = fileStatusPersistenceService.getStatusesForDossier(request.getDossierId());
var dossier = dossierPersistenceService.getActiveOrArchivedDossier(request.getDossierId());
return this.startPrepareDownload(request, dossier, existingFileStatuses);
}
private JSONPrimitive<String> startPrepareDownload(DownloadWithOptionRequest request, DossierEntity dossier, List<FileEntity> existingFileStatuses) {
var mimeType = "application/zip";
String downloadFilename = buildName(request.getDossierId(), request.getFileIds(), request.getUserId(), mimeType, existingFileStatuses);
String storageId = StorageIdUtils.getStorageId(request.getUserId(), request.getDossierId(), downloadFilename);
downloadStatusPersistenceService.createStatus(request.getUserId(), storageId, dossier, downloadFilename, mimeType, request.getFileIds(), request.getDownloadFileTypes(), request.getReportTemplateIds());
addToDownloadQueue(DownloadJob.builder().storageId(storageId).userId(request.getUserId()).build(), 1);
return new JSONPrimitive<>(storageId);
}
public List<DownloadStatus> getDownloadStatus(@PathVariable(USER_ID) String userId) {
return convert(downloadStatusPersistenceService.getStatusesByUser(userId), DownloadStatus.class);

View File

@ -10,6 +10,7 @@ import java.util.stream.Collectors;
import javax.transaction.Transactional;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.WorkflowStatus;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
@ -75,6 +76,7 @@ public class DownloadPreparationService {
.downloadId(reportResultMessage.getDownloadId())
.redactionTypes(toPdfTronRedactionTypes(downloadStatus.getDownloadFileTypes()))
.fileIds(downloadStatus.getFiles().stream().map(FileEntity::getId).collect(Collectors.toList()))
.unapprovedFileIds(downloadStatus.getFiles().stream().filter(f -> !WorkflowStatus.APPROVED.equals(f.getWorkflowStatus())).map(FileEntity::getId).collect(Collectors.toSet()))
.build();
log.info("Sending redaction request for downloadId:{} to pdftron-redaction-queue", message.getDownloadId());
@ -150,20 +152,22 @@ public class DownloadPreparationService {
FileEntity fileStatus = fileStatusPersistenceService.getStatus(fileId);
byte[] original = fileManagementStorageService.getStoredObjectBytes(fileStatus.getDossierId(), fileId, FileType.ORIGIN);
var isFileApproved = WorkflowStatus.APPROVED.equals(fileStatus.getWorkflowStatus());
String filename = isFileApproved ? fileStatus.getFilename() : "UNAPPROVED_" + fileStatus.getFilename();
for (DownloadFileType downloadFileType : downloadStatus.getDownloadFileTypes()) {
if (downloadFileType.name().equals(DownloadFileType.ORIGINAL.name())) {
fileSystemBackedArchiver.addEntry(new FileSystemBackedArchiver.ArchiveModel("Original", fileStatus.getFilename(), original));
fileSystemBackedArchiver.addEntry(new FileSystemBackedArchiver.ArchiveModel("Original", filename, original));
}
if (downloadFileType.name().equals(DownloadFileType.PREVIEW.name())) {
fileSystemBackedArchiver.addEntry(new FileSystemBackedArchiver.ArchiveModel("Preview", addSuffix(fileStatus.getFilename(), "highlighted"), //
fileSystemBackedArchiver.addEntry(new FileSystemBackedArchiver.ArchiveModel("Preview", addSuffix(filename, "highlighted"), //
getPreview(fileId, reportResultMessage.getRedactionResultDetails())));
}
if (downloadFileType.name().equals(DownloadFileType.DELTA_PREVIEW.name())) {
fileSystemBackedArchiver.addEntry(new FileSystemBackedArchiver.ArchiveModel("Delta Preview", addSuffix(fileStatus.getFilename(), "delta_highlighted"), //
fileSystemBackedArchiver.addEntry(new FileSystemBackedArchiver.ArchiveModel("Delta Preview", addSuffix(filename, "delta_highlighted"), //
getDeltaPreview(fileId, reportResultMessage.getRedactionResultDetails())));
}
if (downloadFileType.name().equals(DownloadFileType.REDACTED.name())) {
if (downloadFileType.name().equals(DownloadFileType.REDACTED.name()) && isFileApproved) {
fileSystemBackedArchiver.addEntry(new FileSystemBackedArchiver.ArchiveModel("Redacted", addSuffix(fileStatus.getFilename(), "redacted"), //
getRedacted(fileId, reportResultMessage.getRedactionResultDetails())));
}

View File

@ -53,7 +53,7 @@ public class DownloadProcessorService {
.dossierId(dossier.getId())
.dossierTemplateId(dossierService.getDossierById(dossier.getId()).getDossierTemplateId())
.fileIds(filenameSortedFileIds)
.templateIds(dossier.getReportTemplates().stream().map(ReportTemplateEntity::getTemplateId).collect(Collectors.toSet()))
.templateIds(downloadStatus.getReports().stream().map(ReportTemplateEntity::getTemplateId).collect(Collectors.toSet()))
.build(), 1);
}

View File

@ -105,3 +105,5 @@ databaseChangeLog:
file: db/changelog/tenant/sql/41-update-ocr-file-columns.sql
- include:
file: db/changelog/tenant/sql/42-add-encoding-column-file-attribute-config.sql
- include:
file: db/changelog/tenant/43-add-reports-information-column.changelog.yaml

View File

@ -0,0 +1,40 @@
databaseChangeLog:
- changeSet:
id: add-reports-info-table
author: corinaolariu
changes:
- createTable:
columns:
- column:
constraints:
nullable: false
name: download_status_entity_storage_id
type: VARCHAR(255)
- column:
constraints:
nullable: false
name: reports_template_id
type: VARCHAR(255)
tableName: download_status_reports
- addForeignKeyConstraint:
baseColumnNames: reports_template_id
baseTableName: download_status_reports
constraintName: download_status_reports_to_report_templates
deferrable: false
initiallyDeferred: false
onDelete: NO ACTION
onUpdate: NO ACTION
referencedColumnNames: template_id
referencedTableName: report_template
validate: true
- addForeignKeyConstraint:
baseColumnNames: download_status_entity_storage_id
baseTableName: download_status_reports
constraintName: download_status_reports_to_download_status
deferrable: false
initiallyDeferred: false
onDelete: NO ACTION
onUpdate: NO ACTION
referencedColumnNames: storage_id
referencedTableName: download_status
validate: true

View File

@ -27,7 +27,7 @@
<properties>
<redaction-service.version>3.206.0</redaction-service.version>
<search-service.version>2.39.0</search-service.version>
<pdftron-redaction-service.version>3.140.0</pdftron-redaction-service.version>
<pdftron-redaction-service.version>3.143.0</pdftron-redaction-service.version>
<redaction-report-service.version>3.63.0</redaction-report-service.version>
</properties>