Transformations Microservice

Note

Available in the Enterprise version only.

An optional ecos-transformations microservice for generating documents from templates, which can be loaded with a project or added through administrator tools.

Connecting the Microservice

Transformations Microservice (ecos-transformations) is a standalone microservice that does not require deploying additional databases (all templates are stored in the ecos-model database). The following are required for it to function:

  • ecos-model:2.13.0

Connection Parameters via docker-compose.yml

    #=== TRANSFORMATIONS ===#

transformations-app-dev:
  container_name: transformations-app-dev
  image: nexus.citeck.ru/ecos-transformations:1.0.0
  ports:
    - 8087:8087
  environment:
    - _JAVA_OPTIONS=-Xmx256m -Xms256m
    - SPRING_PROFILES_ACTIVE=dev,swagger
    - ECOS_INTEGRATIONS_ONLYOFFICE_HOST=only-office-app
    - ECOS_WEBAPP_RABBITMQ_HOST=rabbitmq-dev
    - EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://admin:$${jhipster.registry.password}@ecos-registry:8761/eureka
    - SPRING_CLOUD_CONFIG_URI=http://admin:$${jhipster.registry.password}@ecos-registry:8761/config
    - ECOS_INIT_DELAY=0
  depends_on:
    - ecos-registry

Creating a New Template

To work with new document templates in Citeck, there is a journal “Document Templates” (Workspace “Admin Section” - Transformations):

../../_images/trans_1.png

There are 2 ways to create document templates in the system:

  1. By placing them in the project in a specific directory.

  2. By uploading them through the Add action in the Document Templates journal.

Creating a Document Template in a Project

To successfully add your template to the system, there are several things to keep in mind:

  • Along with the template itself, a meta.yml file must be stored to hold the template’s meta-information.

    File naming convention:

    If there is a single template file, the meta-file is named according to the pattern ${Full_file_name_with_extension}.meta.yml

    Example:

    If there are multiple template files as a result of splitting them by locale, the meta-file is named according to the following pattern ${File_name_before_locale_specification}.meta.yml

    Example:

    Meta-file Structure

    The meta-file must contain the following fields in its structure:

    Field

    Description

    id

    Unique identifier of the template in the system
    id: test-template
    

    engine

    The name of the engine that will handle template filling
    Available engines:
    - freemarker — для формирования документов в формате docx, txt с обработкой Freemarker.
    - ecos-table — для формирования xlsx таблиц, которые поддерживают обработку Freemarker
    - none — для обработки шаблонов без какой-либо трансформации. Возвращается шаблон как есть.
    engine: freemarker
    

    name

    Template name
    name: TestTemplate
    

    mimeType

    Template file type
    mimeType: application/vnd.openxmlformats-officedocument.wordprocessingml.document
    

    model

    Represents a key-value map where the key is an attribute from the template and the value is an attribute taken from the record.
    model:
      regNumber: registrationNumber
      regDate: registrationDate|fmt('dd.MM.yyyy')
      initiator: initiator.firstName
    
    The values support all attribute access capabilities through Records API

    computedAttributes

    Computed model attributes.
    Defined as a list of attributes.
    Before template generation, transforms the received model attributes according to the transformation type.
    computedAttributes:
      - id: docInvestigationInfo
        type: html-to-text
    

    tags

    A list of auxiliary labels for convenient search
    tags:
      - Template
      - Test
      - Example
    

    Example:

      ---
    id: test-docx-template
    engine: freemarker
    name: TestDocxTemplate
    mimeType: application/vnd.openxmlformats-officedocument.wordprocessingml.document
    model:
      modelValue: ?disp
    
  • Files must be placed in the project at a specific path.

    The file path follows this pattern:

    In the microservice: ${home_dir}/src/main/resources/eapps/artifacts/transformation/template/

    In legacy projects: ${module_name}/src/main/resources/alfresco/module/${module_name}/transformation/template/

    You can create an internal folder structure within these directories. Template artifact lookup is performed recursively through subfolders, but starts from these directories.

Creating a Template via the Journal

To create a document template, navigate to the “Document Templates” journal (Workspace “Admin Section” - Transformations) and create a new record.

../../_images/trans_4.png

../../_images/trans_5.png

The following fields must be filled in:

Field

Description

ID

Unique identifier of the template in the system

Name

Template name

Engine

The name of the engine that will handle template filling
(Currently, only Freemarker is available)

Templates

The template file is uploaded
The template must be added in a zip archive (since this is how templates are stored in the database).
The archive must contain a template file in docx or ftl format. There are no strict naming rules, but it is recommended to follow the general convention and name the file after the template ID.
If there are multiple templates (split by locale), the file names must have suffixes such as _ru, _en, etc. appended at the end.

Model

Represents a key-value mapping where the key is an attribute from the template and the value is an attribute taken from the record.

Computed Attributes

A list of objects containing information about computed attributes.

Tags

A list of auxiliary labels for convenient search

Computed Attributes for Templates

Computed attributes in the template meta-file are intended to perform post-processing on values received in the model, and to update these values in the model or add them under new names.

Record Structure:

Computed attributes are specified starting with the key attribute computedAttributes in the root structure of the meta-file, which contains a list of objects of the following form:

Field

Description

ID

Unique identifier of the attribute. The attribute will be added to the final model under this value.
If the model already contains an attribute with this name, its value in the model will be updated.

type

Specifies the type of value transformation.

config

Represents a key-value map of additional configuration parameters and their values.
config:
  attribute: test1
Has a common parameter for all types — attribute. This parameter accepts the name of the attribute whose value will be used for transformation.
If this parameter is not specified, the value will be taken from the model using the attribute name from the id field of the computed attribute.

Example:

model:
  test1: ecos:text1
  test2: ecos:text2
computedAttributes:
  - id: test3
    type: html-to-text
    config:
      attribute: test1
  - id: test2
    type: html-to-text

Computed Attribute Types

Type

Description

html-to-text

Converts input text from HTML code to plain text by removing unnecessary tags (such as <p>, <br>, <li>).

Generate and Download Document Action

The system provides an action that allows generating a document from a document template based on a record and immediately downloading it. To do this, create a new action (see: actions) of type download-by-template.

For the action to work, the following attributes must be filled in the action configuration:

Attribute

Value

resultName

The name of the resulting document.
resultName: 'test-docx.docx'
If this attribute is absent, the template document name will be used.

templateRef

Reference to the invoked template
templateRef: 'transformations/template@test-template'

How it works:

When the action is invoked from the record’s action menu, the system sends a request to the template, retrieves the model from the template, fills it with the corresponding values, and sends all data to the transformation microservice, where a document is generated based on the model and template and returned to the UI for download.

In TemplateServiceImpl, before passing the data model to the template engine, recursive sanitization of all string values is implemented. Control characters u0000, u0008, u000B, u000C, u000E, u001F are removed from strings. Allowed characters — tab, newline, and carriage return — are preserved.

Sanitization is centralized and covers all template types (DOCX, XLSX, text).

Note: if encrypted fields are used (encrypted in the database and decrypted on the client side), such fields will be passed in decrypted form and will be displayed correctly in the generated document.

Action examples:

---
id: download-by-test-template
type: download-by-template
config:
  templateRef: 'transformations/template@test-template'
---
id: download-by-test-docx-template
type: download-by-template
name:
  ru: Скачать DOCX шаблон
  en: Download DOCX template
config:
  templateRef: 'transformations/template@test-docx-template'
  resultName: 'test-docx.docx'

Template Import/Export

Template import and export makes it easy to transfer document templates between environments. You download the required templates from one environment and import them into another. You can also generate a template archive yourself and import the desired template into an environment in one simple action.

During import/export, you work with a zip archive containing the template’s meta-information and the document template itself:

../../_images/trans_6.png

Import

Templates are imported via the Import Document Template creation option in the Document Templates journal:

../../_images/trans_7.png

To import, attach a zip archive with the following files:

  • A file with the template metadata. The file name must follow the pattern: File_name.meta.yml

  • The template itself (or templates with different localizations).

Important

This is exactly the archive created during template export

Export

Export is performed using the Download action when hovering over the required document template.

../../_images/trans_8.png

After clicking the action, a zip archive containing the template and its metadata will be downloaded.

Automatic Content Generation from a Template

For automatic content generation from a template when creating a record, you need to:

  1. Add the aspect templated-content to the data type

  2. Select a template in the aspect configuration:

../../_images/templated_content.png

Note

If the templated-content aspect is enabled when creating a record but automatic generation needs to be disabled, you can set the templated-content:autoGenerate attribute to false.

When a record is created, automatic generation is performed synchronously, and the result is written to the _content attribute.

The generated content will be available for download, preview, and version comparison.

Conditional Statement Syntax

The logic from the DocxFreeMarkerProcessor class of the ecos-community-core project has been migrated to the transformation microservice. It is located in the DocxFreemarkerTemplateService class.

Pay attention to the service description, specifically to the syntax of conditional statements:

Expressions that contain opening and closing tags must be wrapped in grouping tags [# #]:

Parameters for Working with Documents in the Built-in OnlyOffice Editor

In the action, in url, specify the config via “&config=JSON”, having first generated it using encodeURIComponent directly in the browser:


In this example, we allow the user to edit only specific fields while removing the ability to download the file.

Editor configuration options are described in the official documentation

To create a document with editable fields, open the source .docx file locally in the OnlyOffice editor and save it in .docxf format

Open it in this format and mark the required fields using the Forms → Text Field tab.

Make sure that “Placeholder” and “Default value” are empty (to avoid layout issues and text color changes after template generation).

After marking the required fields, save the document again in .docx format, open it in Word, fill it with the necessary tags, and save:

Then open it again with OnlyOffice and go to the Protection → Protect Document tab:

Specify a password and “Fill in forms”:

The result is a ready .docx file, which should be fixed before uploading to the system by following the article Temporary Workaround for Template Generation Error with Conditions

Temporary Workaround for Template Generation Error with Conditions

When generating a document from a template that contains a condition (i.e., if, else, or elseif), an error occurs.

because the document.xml file splits the condition into multiple tags:

Workaround for the issue:

  1. Open the docx file as an archive.

  2. In the word folder, open the document.xml file

Find the condition split across tags:

  1. Merge into a single tag:

  2. Save. Upload.

“ECOS table” Engine

This engine in the Citeck system is used to work with document templates in xlsx format. The engine is a combination of an xlsx file processor and a Freemarker processor, providing the following capabilities:

  • use of full Freemarker syntax in cells to fill them with values;

  • use of a special syntax for generating rows in the xlsx file.

General engine operation principle:

  • scans all pages of the template, replacing cell values with model values where necessary, using the Freemarker processor;

  • when rows with a specific syntax are found (for generating new rows), it begins generating new rows, replacing cells with values from objects within the corresponding list in the model. In other words, the model must contain a list of objects from which rows will be generated (the number of rows will match the number of list elements). When generating a row, the values of the corresponding list object will be used.

Outputting Data to a Cell

Cells support full Freemarker processor syntax.

Construction:

Карточка: ${name}

substitutes the value of the name variable at the specified location, taking it from the data model.

More complex constructs supported by the Freemarker processor can also be used.

<#if annotations??><#list annotations as annotation>"${annotation.annotation.ru}"<#sep>, </#list></#if>

Outputting an Arbitrary Number of Rows to the Template

To output an arbitrary number of rows as a table in the template, use the following construction:

At the position where the rows generated from the list of objects are expected, write the following construction in the first cell:

#LIST list_name

where list_name is the name of the variable in the model that contains the list of objects.

The following rows are structured the way we want them to be generated based on objects from the list_name list

For example:

../../_images/xlsx_1.png

In the rows, when filling cells, we use variable names from objects of this list (we can also use variables from the general model; if the variable names from the object and from the general model match, the value from the object will be used).

After the template rows are described, place the following construction in the first cell of a new row:

#END

It indicates that the rows after this point are not template rows and should not be generated.

../../_images/list_1.png

Example

We have a data type with the following attributes:

../../_images/xlsx_2.png

The empls attribute is a list of system users.

For this type, we create a template with the following model:

../../_images/xlsx_3.png

The empls variable stores a list of objects consisting of 3 fields, based on system users.

The xlsx template looks as follows:

../../_images/xlsx_4.png

Where:

  • In cell A2 we want to write the value from the model with the key name

  • In cell A5 we indicate that we want rows based on objects from the list with key empls in the model

  • In cells A6-C6 we specify how cells should be filled in the generated rows

  • In cell A7 we indicate that the template rows for the list with key empls end here (i.e., we can define 2 template rows and 2 rows will be generated for each list entry in the final file)

As a result, for a record with these parameters:

../../_images/xlsx_5.png

The following template will be generated:

../../_images/xlsx_6.png