Skip to content

Commit

Permalink
Merge pull request #13104 from SORMAS-Foundation/feature-13044_Bulk-a…
Browse files Browse the repository at this point in the history
…ction_send-emails_attach_document_template

#13044 - Bulk action - send emails - attach a document template, gene…
  • Loading branch information
sergiupacurariu authored May 27, 2024
2 parents 9a93c99 + ef30f2a commit 9655678
Show file tree
Hide file tree
Showing 19 changed files with 543 additions and 96 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package de.symeda.sormas.api.docgeneneration;

import de.symeda.sormas.api.sample.PathogenTestReferenceDto;
import de.symeda.sormas.api.sample.SampleReferenceDto;
import de.symeda.sormas.api.vaccination.VaccinationReferenceDto;

import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Properties;

public class QuarantineOrderDocumentOptionsDto implements Serializable {

private String templateFile;
private SampleReferenceDto sample;
private PathogenTestReferenceDto pathogenTest;
private VaccinationReferenceDto vaccinationReference;
private Properties extraProperties;
private Boolean shouldUploadGeneratedDoc;
private DocumentWorkflow documentWorkflow;


public String getTemplateFile() {
return templateFile;
}

public void setTemplateFile(String templateFile) {
this.templateFile = templateFile;
}

public SampleReferenceDto getSample() {
return sample;
}

public void setSample(SampleReferenceDto sample) {
this.sample = sample;
}

public PathogenTestReferenceDto getPathogenTest() {
return pathogenTest;
}

public void setPathogenTest(PathogenTestReferenceDto pathogenTest) {
this.pathogenTest = pathogenTest;
}

public VaccinationReferenceDto getVaccinationReference() {
return vaccinationReference;
}

public void setVaccinationReference(VaccinationReferenceDto vaccinationReference) {
this.vaccinationReference = vaccinationReference;
}

public Properties getExtraProperties() {
return extraProperties;
}

public void setExtraProperties(Properties extraProperties) {
this.extraProperties = extraProperties;
}

public Boolean getShouldUploadGeneratedDoc() {
return shouldUploadGeneratedDoc;
}

public void setShouldUploadGeneratedDoc(Boolean shouldUploadGeneratedDoc) {
this.shouldUploadGeneratedDoc = shouldUploadGeneratedDoc;
}

public DocumentWorkflow getDocumentWorkflow() {
return documentWorkflow;
}

public void setDocumentWorkflow(DocumentWorkflow documentWorkflow) {
this.documentWorkflow = documentWorkflow;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public interface ExternalEmailFacade {
List<DocumentReferenceDto> getAttachableDocuments(DocumentWorkflow documentWorkflow, String relatedEntityUuid);

void sendEmail(@Valid ExternalEmailOptionsDto options)
throws DocumentTemplateException, ExternalEmailException, AttachmentException, ValidationException;
throws DocumentTemplateException, ExternalEmailException, AttachmentException, ValidationException, IOException;

List<ProcessedEntity> sendBulkEmail(@Valid ExternalEmailOptionsWithAttachmentsDto options, List<ReferenceDto> rootEntityReferences)
throws IOException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import de.symeda.sormas.api.ReferenceDto;
import de.symeda.sormas.api.audit.AuditedClass;
import de.symeda.sormas.api.docgeneneration.DocumentWorkflow;
import de.symeda.sormas.api.docgeneneration.QuarantineOrderDocumentOptionsDto;
import de.symeda.sormas.api.docgeneneration.RootEntityType;
import de.symeda.sormas.api.document.DocumentReferenceDto;
import de.symeda.sormas.api.i18n.Validations;
Expand Down Expand Up @@ -53,6 +54,8 @@ public class ExternalEmailOptionsDto implements Serializable {
private String recipientEmail;
private Set<DocumentReferenceDto> attachedDocuments;

private QuarantineOrderDocumentOptionsDto quarantineOrderDocumentOptions;

public ExternalEmailOptionsDto(DocumentWorkflow documentWorkflow, RootEntityType rootEntityType, ReferenceDto rootEntityReference) {
this.documentWorkflow = documentWorkflow;
this.rootEntityType = rootEntityType;
Expand Down Expand Up @@ -98,4 +101,12 @@ public Set<DocumentReferenceDto> getAttachedDocuments() {
public void setAttachedDocuments(Set<DocumentReferenceDto> attachedDocuments) {
this.attachedDocuments = attachedDocuments;
}

public QuarantineOrderDocumentOptionsDto getQuarantineOrderDocumentOptions() {
return quarantineOrderDocumentOptions;
}

public void setQuarantineOrderDocumentOptions(QuarantineOrderDocumentOptionsDto quarantineOrderDocumentOptions) {
this.quarantineOrderDocumentOptions = quarantineOrderDocumentOptions;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,17 @@
package de.symeda.sormas.api.externalemail;

import java.io.Serializable;
import java.util.Properties;
import java.util.Set;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import de.symeda.sormas.api.audit.AuditedClass;
import de.symeda.sormas.api.docgeneneration.DocumentWorkflow;
import de.symeda.sormas.api.docgeneneration.EmailAttachementDto;
import de.symeda.sormas.api.docgeneneration.QuarantineOrderDocumentOptionsDto;
import de.symeda.sormas.api.docgeneneration.RootEntityType;
import de.symeda.sormas.api.i18n.Validations;

Expand All @@ -52,6 +55,8 @@ public class ExternalEmailOptionsWithAttachmentsDto implements Serializable {
private String templateName;
private Set<EmailAttachementDto> attachedDocuments;

private QuarantineOrderDocumentOptionsDto quarantineOrderDocumentOptionsDto;

public ExternalEmailOptionsWithAttachmentsDto(DocumentWorkflow documentWorkflow, RootEntityType rootEntityType) {
this.documentWorkflow = documentWorkflow;
this.rootEntityType = rootEntityType;
Expand Down Expand Up @@ -80,4 +85,12 @@ public Set<EmailAttachementDto> getAttachedDocuments() {
public void setAttachedDocuments(Set<EmailAttachementDto> attachedDocuments) {
this.attachedDocuments = attachedDocuments;
}

public QuarantineOrderDocumentOptionsDto getQuarantineOrderDocumentOptionsDto() {
return quarantineOrderDocumentOptionsDto;
}

public void setQuarantineOrderDocumentOptionsDto(QuarantineOrderDocumentOptionsDto quarantineOrderDocumentOptionsDto) {
this.quarantineOrderDocumentOptionsDto = quarantineOrderDocumentOptionsDto;
}
}
4 changes: 2 additions & 2 deletions sormas-api/src/main/resources/captions.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2937,11 +2937,11 @@ environmentSampleDeletedSamples=Deleted environment samples
humanSampleViewType=Human
environmentSampleViewType=Environment
environmentSampleNewSample=New sample
ExternalEmailOptions.templateName=Choose template
ExternalEmailOptions.templateName=Choose email template
ExternalEmailOptions.recipientEmail=Email address
ExternalEmailOptions.attachedDocuments=Attach document(s)
ExternalEmailOptionsWithAttachments.attachedDocuments=Attach document(s)
ExternalEmailOptionsWithAttachments.templateName=Choose template
ExternalEmailOptionsWithAttachments.templateName=Choose email template
externalEmailUsedTemplate=Template
externalEmailSentBy=Sent by
externalEmailSentTo=Sent to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Properties;

import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;

import de.symeda.sormas.api.Disease;
Expand Down Expand Up @@ -69,23 +70,23 @@ public byte[] getGeneratedDocument(
Boolean shouldUploadGeneratedDoc)
throws DocumentTemplateException {

DocumentTemplateEntities entities =
entitiesBuilder.getQuarantineOrderEntities(rootEntityType, rootEntityReference, sampleReference, pathogenTestReference, vaccinationReference);
DocumentTemplateEntities entities = entitiesBuilder
.getQuarantineOrderEntities(rootEntityType, rootEntityReference, sampleReference, pathogenTestReference, vaccinationReference);
byte[] documentToSave = documentTemplateFacade.generateDocumentDocxFromEntities(workflow, templateName, entities, extraProperties);
if (shouldUploadGeneratedDoc) {
uploadDocument(templateName, rootEntityReference, documentToSave);
uploadDocument(helper.getDocumentFileName(rootEntityReference, templateName), rootEntityReference, documentToSave);
}
return documentToSave;
}

private void uploadDocument(String templateName, ReferenceDto rootEntityReference, byte[] documentToSave) throws DocumentTemplateException {
public void uploadDocument(String fileName, ReferenceDto rootEntityReference, byte[] documentToSave) throws DocumentTemplateException {
try {
if (isFileSizeLimitExceeded(documentToSave.length)) {
return;
}

helper.saveDocument(
helper.getDocumentFileName(rootEntityReference, templateName),
fileName,
DocumentDto.MIME_TYPE_DEFAULT,
documentToSave.length,
helper.getDocumentRelatedEntityType(rootEntityReference),
Expand Down Expand Up @@ -129,7 +130,12 @@ public Map<ReferenceDto, byte[]> getGeneratedDocumentsForEventParticipants(
Map<ReferenceDto, DocumentTemplateEntities> quarantineOrderEntities =
entitiesBuilder.getEventParticipantQuarantineOrderEntities(rootEntityReferences, eventDisease);

return getGeneratedDocuments(templateName, DocumentWorkflow.QUARANTINE_ORDER_EVENT_PARTICIPANT, quarantineOrderEntities, extraProperties, shouldUploadGeneratedDoc);
return getGeneratedDocuments(
templateName,
DocumentWorkflow.QUARANTINE_ORDER_EVENT_PARTICIPANT,
quarantineOrderEntities,
extraProperties,
shouldUploadGeneratedDoc);
}

private Map<ReferenceDto, byte[]> getGeneratedDocuments(
Expand All @@ -143,13 +149,10 @@ private Map<ReferenceDto, byte[]> getGeneratedDocuments(
Map<ReferenceDto, byte[]> documents = new HashMap<>(quarantineOrderEntities.size());

for (Map.Entry<ReferenceDto, DocumentTemplateEntities> entities : quarantineOrderEntities.entrySet()) {
byte[] documentContent = documentTemplateFacade.generateDocumentDocxFromEntities(
workflow,
templateName,
entities.getValue(),
extraProperties);
byte[] documentContent =
documentTemplateFacade.generateDocumentDocxFromEntities(workflow, templateName, entities.getValue(), extraProperties);
if (shouldUploadGeneratedDoc) {
uploadDocument(templateName, entities.getKey(), documentContent);
uploadDocument(helper.getDocumentFileName(entities.getKey(), templateName), entities.getKey(), documentContent);
}
documents.put(entities.getKey(), documentContent);
}
Expand All @@ -166,4 +169,9 @@ public List<String> getAvailableTemplates(DocumentWorkflow workflow) {
public DocumentVariables getDocumentVariables(DocumentWorkflow documentWorkflow, String templateName) throws DocumentTemplateException {
return documentTemplateFacade.getDocumentVariables(documentWorkflow, templateName);
}

@LocalBean
@Stateless
public static class QuarantineOrderFacadeEjbLocal extends QuarantineOrderFacadeEjb {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,6 @@ public void deleteDocument(String documentUuid, String relatedEntityUuid, Docume
documentService.markAsDeleted(document);
}
}

@Override
public List<DocumentDto> getDocumentsRelatedToEntity(DocumentRelatedEntityType type, String uuid) {
Pseudonymizer<DocumentDto> pseudonymizer = Pseudonymizer.getDefault(userService);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,13 @@
import java.io.OutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;

import javax.ejb.EJB;
import javax.ejb.LocalBean;
Expand Down Expand Up @@ -84,31 +83,32 @@ public Set<String> getAttachableFileExtensions() {
return Set.of((PDF_FILE_EXTENSION + "," + DOCX_FILE_EXTENSION + "," + IMAGE_FILE_EXTENSTIONS).split(","));
}

public Map<File, String> createEncryptedPdfs(List<de.symeda.sormas.backend.document.Document> sormasDocuments, String password) {
return sormasDocuments.stream().map(d -> {
String fileName = d.getName();
String fileExtension = fileName.substring(fileName.lastIndexOf("."));
public Map<File, String> createEncryptedPdfs(Map<File, String> sormasDocuments, String password) {
Map<File, String> encryptedFiles = new HashMap<>(Collections.emptyMap());

try {
final File encryptedPdf;
File document = documentStorageService.getFile(d.getStorageReference());
if (fileExtension.equals(PDF_FILE_EXTENSION)) {
sormasDocuments.forEach((document, fileName) -> {
String fileExtension = fileName.substring(fileName.lastIndexOf("."));

try {
final File encryptedPdf;
if (fileExtension.equals(PDF_FILE_EXTENSION)) {
encryptedPdf = encryptPdf(document, password);
} else {
PdfConverter converter = getConverter(fileExtension);
fileName = converter.getConvertedFileName(fileName);
File converted = converter.convert(document);
encryptedPdf = encryptPdf(converted, password);
converted.delete();
}

return new AbstractMap.SimpleEntry<>(encryptedPdf, fileName);
} catch (IOException e) {
// not really expected to happen
throw new RuntimeException(e);
}
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
converted.delete();
}
encryptedFiles.put(encryptedPdf, fileName);
} catch (IOException e) {
// not really expected to happen
throw new RuntimeException(e);
}
});

return encryptedFiles;
}

private File encryptPdf(File pdf, String password) throws IOException {
PDDocument pdd = Loader.loadPDF(pdf);
Expand Down
Loading

0 comments on commit 9655678

Please sign in to comment.