.. _features_rendering_documents_from_templates:
Підходи до рендеру документів з темплейтів та json
==================================================
Документ це pdf файл відповідного формату. Частина тексту і форматування є відносно сталими
Даний документ описує і порівнює два розглянуті варіанти.
Рендерінг за допомогою JS сервіса/бібліотеки
--------------------------------------------
Наразі використовуємо підхід, де маємо репозиторій з кодом, який реалізує бібліотеку для генерації pdf документів.
Усі правил генерації документів описані js кодом. Бібліотека приймає дані, які використовуються для наповнення. Також може приймати конфіг, для конфігурації блоків документу або додавання додаткового тексту.
.. image:: img/rendering_documents/overview_jslib.png
У випадку додавання нового темплейту **треба модифікувати вихідний код бібліотеки і робити тестування та реліз**. Тестування правильності генерації треба робити для усіх темплейтів кожного разу.
З таким підходом дуже дорого додати новий темплейт так, щоб точно не внести ніяких потенційних змін до всіх інших.
Рендерінг з html темлейтів
--------------------------
Інший поширений підхід - це `розмічений спеціальним синтаксисом `_ html - файл.
.. image:: img/rendering_documents/overview_html.png
Розмітка визначає правила підстановки даних в темплейт. Темплейт визначає структуру документу і формат.
Таким чином сгенерувавши на початку темплейт документу, нам ми можемо гарантувати його незмінність для всіх документів.
Сам сервіс, що підставляє дані в темплейт і рендерить pdf не буде потребувати змін для підтримки нових темплейтів.
У відкритому доступі є і `аналогічні сервіси `_ і бібліотеки.
Приклад html темплейту з розміткою
.. sourcecode:: html
Hello, {{ name }}!
Please get us:
{% for item in items %}- {{ item.name }}
{% endfor %}
.. sourcecode:: json
{
"name": "Oleg",
"items": [{"name": "bread"}, {"name": "eggs"}, {"name": "spam"}]
}
.. image:: img/rendering_documents/jinja-engine.png
.. warning::
Для генерації на стороні клієнта підхід "друкування html в pdf" може давати відмінні результати, для різних ОС, браузерів, налаштувань. Але якщо генерувати на стороні сервера - то ми будемо отримувати повторювані результати.
Порівняння підходів
-------------------
Зручність
~~~~~~~~~
Наявний підхід з JS біліотекою спрощує роботу, коли і документ і код генерації реалізують ті самі розробники. Виходить нова версія - що підтримує новий документ.
Але якщо темплейтів буде дуже багато такий підхід майже унеможливлює роботу, бо час релізного циклу бібліотеки буде рости пропорційно кіолькості темплейтів.
У випадку з тепелйтами в html не потрібно релізити код/сервіси щоб додати темплейт.
Підтримка
~~~~~~~~~
Для додавання темплейту в js бібілотеку необхідна кваліфікація JS розробника та знання як працює бібліотека. Тобто будь-який JS розробник з ринку має ще витратити час на ознайомлення з кодом бібліотеки, перед тим як почати працювати з нею.
Для додавання html темплейту з розміткою jinja2 не потрібно знань мов програмування - лише знання html та jinja2 , що набагато простіше - відповідно легше/дешевше. Також не потрібно витрачати час на ознайомлення з усіма попередньо створеними темплейтами, бо вони один на одного не впливають як у випадку з бібліотекою.
Тобто ситуація - треба новий темплейт і нікому його зробити. JS бібліотека - шукаєм досвідченого JS розробника, який витратить 5днів на ознайомлення, 2 дні на новий темплейт, ще 2 дні на підготовку деплоя версії. html бібліотека - шукаєм досвідченого html + jinaj2 верстальника, який за 2 дні верстає новий документ.
Надійність
~~~~~~~~~~
JS бібліотека це завжди black box. Немає дожних гарантій що темплейти однакові від версії до версії. В свою чергу обидва рішення з часом можуть трохи відмінні вихідні файли навіть при незмінності наповнення. Це стосується стилей, розміру / типів шрифтів. Тобто один контракт згенерований рік тому і зараз може відрізнятись на якись відступ/піксель і тому мати інший хеш вихідного файла.
Опис технічного рішення (HTML темлейти)
---------------------------------------
Згідно вимог, адміністратор темплейтів ЦЗО може конфігурувати темлейт для типових контрактів.
Конфігурування складається з включення/виключення базових блоків та додавання довільних абзаців.
Далі під час/після підписання контракт можна роздрукувати в pdf використавши даний темплейт і дані електроних полів з ЦБД.
Зберігатися темплейти будуть централізовано в обох підходах. Але у випадку з html тепмлейтами, ми можемо мати git репозиторій базових блоків, щоб посилатися на них при створенні тепелейта контракта.
наприклад маємо git репозиторій з файлами базових блоків
.. sourcecode:: yaml
-contracts/
-2024/
-base.html.jinja2
-header.html.jinja2
-items.html.jinja2
-milestones.html.jinja2
Далі при створенні темлейту в апі передається "структура" темпелйту:
.. sourcecode:: http
POST /api/templates/ HTTP/1.1
Content-Type: application/json
Host: lb-api.prozorro.gov.ua
{
"type": "contract",
"base": "contracts/2024/base.html.jinja2",
"content": [
{
"include": "contracts/2024/header.html.jinja2"
},
{
"include": "contracts/2024/items.html.jinja2"
},
{
"include": "contracts/2024/milestones.html.jinja2"
},
{
"title": "Додаткові умови щодо якості товару",
"text": "У випадку незадовільної якості замовник може застосувати фізичні санкції щодо постачальника."
}
]
}
HTTP/1.1 200 OK
Content-Type: application/json
Location: http://lb-api.prozorro.gov.ua/api/templates/4178f66eebf04c4497d0fb223feeb0fe
{
"id": "4178f66eebf04c4497d0fb223feeb0fe",
"type": "contract",
"base": "contracts/base-2024.html.jinja2",
"content": [
{
"include": "contracts/header-2024.html.jinja2",
},
{
"include": "contracts/items-2024.html.jinja2",
},
{
"include": "contracts/milestones-2024.html.jinja2",
},
{
"title": "Додаткові умови щодо якості товару",
"text": "У випадку незадовільної якості замовник може застосувати фізичні санкції щодо постачальника."
}
],
"documents":[
{
"id":"08682b48035643a39d924df55eb915e0",
"hash":"md5:00000000000000000000000000000000",
"title":"template.html.jinja2",
"format":"text/plain",
"url":"http://public-docs.prozorro.gov.ua/get/1ea9c5fa82c84b2a8206318bc86360df?Signature=x6tzZwzV4d5DGLeiqvD%2Bm0EdAUGgzUmYnoQ4AjImnxjQRU49JnE3aq50UHtPUVvIRfF5JSrLqmyF3tssHOT%2BCA%3D%3D&KeyID=a8968c46",
"datePublished":"2023-10-10T01:00:00+03:00",
"dateModified":"2023-10-10T01:00:00+03:00"
}
]
}
Створення конфігурації теплейта також створює сам файл теплейта, який вже включає всю необхідну структуру на момент створення (з блоків репозиторія).
.. sourcecode:: html
Контракт #{{ contract_number }} {{ signed_date }}
Предмети закупівлі
{% for item in items %}- {{ item.name }}
{% endfor %}
Так звані майлстоуни
{% for milestone in milestones %}- {{ milestone }}
{% endfor %}
Додаткові умови щодо якості товару
У випадку незадовільної якості замовник може застосувати фізичні санкції щодо постачальника.
В цей теплейт тільки треба підставити дані згідно правил jinja2 розмітки.
.. sourcecode:: http
GET /api/contracts/1abf353aa1abf353aa1abf353aa1abf353aa/render/html HTTP/1.1
HTTP/1.1 200 OK
Content-Type: text/html
Контракт #2024-12-12-0000001 2024-12-12 12:30:42
Предмети закупівлі
Так звані майлстоуни
- Доставка вранці
- Оплата ввечері
Додаткові умови щодо якості товару
У випадку незадовільної якості замовник може застосувати фізичні санкції щодо постачальника.
Такий html файл можна відкрити користувачу на перегляд або роздрукутвати в pdf в браузері. Або одразу скачати pdf:
.. sourcecode:: http
GET /api/contracts/1abf353aa1abf353aa1abf353aa1abf353aa/render/pdf HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment;filename=contract.pdf
<>
Вищеописані ендпоінти для наповнення темплейту і генерації pdf можуть бути відносно легко реалізовані в будь-якому іншому сервісі - на порталі, майданчиках etc.
Опис технічного рішення (JS бібліотека)
---------------------------------------
Адміністратор темплейтів ЦЗО має конфігурувати темлейт для типових контрактів.
Конфігурування складається з включення/виключення базових блоків та додавання довільних абзаців.
На відміну від підходу з html блоками які лежать в репозиторії, які блоки може приймати JS код невідомо. Але можна домомвитись внести їх в стандарт, щоб кабінет ЦЗО, апі ЦБД і бібліотека посилались на ті самі назви блоків.
Наприклад:
.. sourcecode:: json
[
{
"id": "header-1",
"description": "Заголовок типового контракту №1"
},
{
"id": "items-1",
"description": "Блок предмітів закупівлі №1"
},
{
"id": "milestones-1",
"description": "Блок доставок / оплат №1"
}
]
Таким чином апі зможе приймати ці блоки від кабінету ЦЗО:
.. sourcecode:: http
POST /api/templates/ HTTP/1.1
Content-Type: application/json
Host: lb-api.prozorro.gov.ua
{
"type": "contract",
"base": "contracts/2024/base.html.jinja2",
"content": [
{
"include": "header-1"
},
{
"include": "items-1"
},
{
"include": "milestones-1"
},
{
"title": "Додаткові умови щодо якості товару",
"text": "У випадку незадовільної якості замовник може застосувати фізичні санкції щодо постачальника."
}
]
}
HTTP/1.1 200 OK
Content-Type: application/json
Location: http://lb-api.prozorro.gov.ua/api/templates/4178f66eebf04c4497d0fb223feeb0fe
{
"id": "4178f66eebf04c4497d0fb223feeb0fe",
"type": "contract",
"content": [
{
"include": "header-1"
},
{
"include": "items-1"
},
{
"include": "milestones-1"
},
{
"title": "Додаткові умови щодо якості товару",
"text": "У випадку незадовільної якості замовник може застосувати фізичні санкції щодо постачальника."
}
]
}
Далі, користуючись бібліотекою: інтерфейси зможуть відмалювати pdf і віддати його користувачу.
У цьому підході і структура і наповнення темплейту відбуваються в момент генерації pdf, відповідно до логіки конкретної версії бібліотеки.