Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static de.symeda.sormas.api.docgeneneration.RootEntityType.ROOT_EVENT_ACTIONS;
import static de.symeda.sormas.api.docgeneneration.RootEntityType.ROOT_EVENT_PARTICIPANT;
import static de.symeda.sormas.api.docgeneneration.RootEntityType.ROOT_EVENT_PARTICIPANTS;
import static de.symeda.sormas.api.docgeneneration.RootEntityType.ROOT_GENERAL;
import static de.symeda.sormas.api.docgeneneration.RootEntityType.ROOT_PATHOGEN_TEST;
import static de.symeda.sormas.api.docgeneneration.RootEntityType.ROOT_PERSON;
import static de.symeda.sormas.api.docgeneneration.RootEntityType.ROOT_SAMPLE;
Expand Down Expand Up @@ -54,7 +55,8 @@ public enum DocumentWorkflow {
ROOT_USER,
ROOT_SAMPLE,
ROOT_PATHOGEN_TEST,
ROOT_VACCINATION),
ROOT_VACCINATION,
ROOT_GENERAL),
QUARANTINE_ORDER_CONTACT(DocumentWorkflowType.DOCUMENT,
"quarantineContact",
DOCX,
Expand All @@ -64,7 +66,8 @@ public enum DocumentWorkflow {
ROOT_USER,
ROOT_SAMPLE,
ROOT_PATHOGEN_TEST,
ROOT_VACCINATION),
ROOT_VACCINATION,
ROOT_GENERAL),
QUARANTINE_ORDER_EVENT_PARTICIPANT(DocumentWorkflowType.DOCUMENT,
"quarantineEventParticipant",
DOCX,
Expand All @@ -74,14 +77,16 @@ public enum DocumentWorkflow {
ROOT_USER,
ROOT_SAMPLE,
ROOT_PATHOGEN_TEST,
ROOT_VACCINATION),
ROOT_VACCINATION,
ROOT_GENERAL),
QUARANTINE_ORDER_TRAVEL_ENTRY(DocumentWorkflowType.DOCUMENT,
"quarantineTravelEntry",
DOCX,
UserRight.DOCUMENT_TEMPLATE_MANAGEMENT,
ROOT_TRAVEL_ENTRY,
ROOT_PERSON,
ROOT_USER),
ROOT_USER,
ROOT_GENERAL),
EVENT_HANDOUT(DocumentWorkflowType.DOCUMENT,
"eventHandout",
HTML,
Expand Down Expand Up @@ -127,22 +132,15 @@ public enum DocumentWorkflow {
ROOT_TRAVEL_ENTRY,
ROOT_PERSON,
ROOT_USER),
SURVEY_DOCUMENT(DocumentWorkflowType.DOCUMENT,
"survey",
DOCX,
UserRight.SURVEY_EDIT,
ROOT_CASE,
ROOT_PERSON,
ROOT_USER,
ROOT_SAMPLE),
SURVEY_DOCUMENT(DocumentWorkflowType.DOCUMENT, "survey", DOCX, UserRight.SURVEY_EDIT, ROOT_CASE, ROOT_PERSON, ROOT_USER, ROOT_SAMPLE),
SURVEY_EMAIL(DocumentWorkflowType.EMAIL,
Constants.EMAIL_TEMPLATES_FOLDER + "/surveys",
TXT,
UserRight.SURVEY_EDIT,
ROOT_CASE,
ROOT_PERSON,
ROOT_USER,
ROOT_SAMPLE),;
Constants.EMAIL_TEMPLATES_FOLDER + "/surveys",
TXT,
UserRight.SURVEY_EDIT,
ROOT_CASE,
ROOT_PERSON,
ROOT_USER,
ROOT_SAMPLE),;

private final DocumentWorkflowType type;
private final String templateDirectory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public enum RootEntityType {
ROOT_EVENT_ACTIONS("eventActions"),
ROOT_EVENT_PARTICIPANTS("eventParticipants"),
ROOT_TRAVEL_ENTRY("travelEntry"),
ROOT_VACCINATION("vaccination");
ROOT_VACCINATION("vaccination"),
ROOT_GENERAL("general");

private final String entityName;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
Expand Down Expand Up @@ -229,6 +233,12 @@ private Properties prepareProperties(
continue;
}

// check if the entity is from a general.
// General entities are used for common and dynamic data that can be referenced across different entities.
if (rootEntityType == RootEntityType.ROOT_GENERAL) {
fillGeneralValues(documentVariables, properties, propertyKey);
}

Object entity = entities.getEntity(rootEntityType);
if (entity instanceof HasUuid) {
if (documentWorkflow.isDocx() || propertyKey.contains(propertySeparator)) {
Expand Down Expand Up @@ -284,6 +294,49 @@ private Properties prepareProperties(
return properties;
}

/**
* Fills general values into the properties based on the provided document variables and properties.
*
* @param documentVariables
* The document variables to use for filling general values.
* @param properties
* The properties to fill with general values.
* @param propertyKey
* The property key to use for general value retrieval.
*/
private void fillGeneralValues(DocumentVariables documentVariables, Properties properties, String propertyKey) {
// finding the general property key. Based on the type, formatStyle is deciding.
// general properties are allowed only doc-formatted files.
Optional<String> generalPropertyOpt = documentVariables.getVariables()
.stream()
.filter(e -> e.startsWith(RootEntityType.ROOT_GENERAL.getEntityName() + "."))
.filter(e -> e.equals(propertyKey))
.findAny();

if (generalPropertyOpt.isPresent()) {
String generalProperty = generalPropertyOpt.get();
String dateType = generalProperty.substring(generalProperty.lastIndexOf('.') + 1);
FormatStyle formatStyle;
switch (dateType) {
case "long":
formatStyle = FormatStyle.LONG;
break;
case "full":
formatStyle = FormatStyle.FULL;
break;
case "medium":
formatStyle = FormatStyle.MEDIUM;
break;
case "short":
default:
formatStyle = FormatStyle.SHORT;
}
Comment thread
KarnaiahPesula marked this conversation as resolved.
String propertyValue =
LocalDate.now().format(DateTimeFormatter.ofLocalizedDate(formatStyle).withLocale(I18nProperties.getUserLanguage().getLocale()));
properties.setProperty(generalProperty, propertyValue);
Comment on lines +307 to +336

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate the full general placeholder, not just its last segment.

The rest of this class gets here via case-insensitive root matching, but this helper only accepts lowercase general. and then treats any general.* key as “current date in some style” by looking only at the final token. That means $General.currentDate.short stays unresolved, while typos like $general.curentDate.full still render today’s date. Parse propertyKey directly, compare the expected segments case-insensitively, and return for unknown names / formats instead of defaulting them to SHORT.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@sormas-backend/src/main/java/de/symeda/sormas/backend/docgeneration/DocumentTemplateFacadeEjb.java`
around lines 307 - 336, fillGeneralValues currently treats any key ending in
".{style}" as a general date and only checks the last token; change it to parse
propertyKey (split on '.') and validate all segments: confirm the first segment
equals RootEntityType.ROOT_GENERAL.getEntityName() case-insensitively, confirm
the second segment equals "currentDate" case-insensitively, and confirm a third
segment exists and is one of "long","full","medium","short" (map to FormatStyle
accordingly). If any of these checks fail, return without setting properties;
only then format the date with
DateTimeFormatter.ofLocalizedDate(...).withLocale(I18nProperties.getUserLanguage().getLocale())
and call properties.setProperty(generalProperty, propertyValue). Use the
existing method name fillGeneralValues and the DocumentVariables/propertyKey
inputs to locate the change.

}
}

private byte[] generateDocumentDocx(File templateFile, Properties properties) throws DocumentTemplateException {
return templateEngine.generateDocumentDocx(properties, templateFile);
}
Expand Down
Loading