Перенос печатных форм между ландшафтами#

Для защиты контролируемых ландшафтов, например QAS, STG и PRD, от переноса непроверенных печатных форм используется следующая схема работы:

  1. Перенос через код (DataInstall). Системные и проектные печатные формы поставляются в составе прикладных модулей из репозитория Git.

  2. Блокировка ручных изменений. На целевых ландшафтах можно запретить ручной импорт, изменение и удаление печатных форм, поставляемых через код. Попытки выполнения запрещённых действий блокируются и регистрируются в журнале переносов.

Способы переноса печатных форм#

Объект печатной формы Rpt_Report содержит обязательный атрибут Способ переноса (idTransferType). Атрибут ссылается на справочник способов переноса Rpt_TransferType и имеет следующие значения:

  • Поставка с модулем (ModuleDelivery) — печатная форма автоматически регистрируется через DataInstall при установке или обновлении прикладного модуля. При включённом запрете ручного переноса ручные операции с такой печатной формой блокируются.

  • Ручной перенос (Manual) — печатная форма переносится через импорт и экспорт XML- или JSON-файлов либо путём ручного создания версий.

Значение атрибута определяется настройками модуля RPT и способом регистрации печатной формы:

  • Способ переноса печатной формы по умолчанию (Rpt_DefaultTransferType) определяет значение, которое устанавливается при интерактивном создании печатной формы.

  • При выполнении DataInstall для печатных форм, регистрируемых из ресурсов модуля, принудительно устанавливается значение Поставка с модулем (ModuleDelivery), а для существующих печатных форм при миграции — Ручной перенос (Manual).

Автоматическая регистрация из ресурсов модуля#

Для установки печатных форм при обновлении релиза используется автоматическая регистрация из ресурсов прикладного модуля через DataInstall.

Правила именования каталогов и отчёта

  • Имя отчёта (системное имя): должно точно совпадать с именем корневого каталога печатной формы в ресурсах модуля с учётом регистра. Например, ресурсы отчёта MyReport должны находиться в каталоге reports/MyReport/.

  • Каталог отчёта: структура каталогов в ресурсах прикладного модуля должна соответствовать шаблону src/main/resources/reports/<СистемноеИмяОтчёта>/<ИмяВерсии>/.

  • Имя версии: значение, переданное в метод .version("<ИмяВерсии>"), должно точно совпадать с именем подкаталога версии в ресурсах с учётом регистра.

Пример каталога версии 1.0 печатной формы MyReport:

src/main/resources/reports/MyReport/1.0/

Для регистрации печатной формы в API-классе прикладного модуля используется билдер Rpt_ReportApi.registerFromResource:

Rpt_ReportApi().registerFromResource("MyReportSystemName")
  .module("rpt")
  .version("1.0")
    .templateType("Jasper")
    .formats(Seq(ReportFormat.pdf, ReportFormat.xlsx))
  .register()

Методы билдера печатной формы

  • module(value: NString) — обязательный метод. Задаёт прикладной модуль, к которому относится печатная форма. Если метод не вызван, регистрация завершается ошибкой.

  • version(value: String) — обязательный метод. Начинает настройку версии печатной формы. В цепочке методов должна быть настроена хотя бы одна версия.

Методы билдера версии печатной формы

  • templateType(value: NString) — обязательный метод. Задаёт тип шаблона по его мнемокоду, например Jasper, Doc, Xls или Xlsx. Если тип шаблона не указан, регистрация завершается ошибкой.

  • date(value: NDate) — необязательный метод. Задаёт начальную дату действия версии печатной формы. Если метод не вызван, используется текущее системное время NDate.now().

  • formats(value: Seq[ReportFormat.Value]) — необязательный метод. Задаёт перечень доступных выходных форматов.

  • register() — обязательный метод. Запускает обработку ресурсов, проверку параметров, синхронизацию форматов, упаковку шаблонов и сохранение изменений в базе данных. Возвращает идентификатор печатной формы типа NLong.

Регистрация нескольких версий

Для регистрации нескольких версий метод version() вызывается несколько раз в одной цепочке. При каждом вызове билдер переключается на настройку указанной версии:

Rpt_ReportApi().registerFromResource("MyReportSystemName")
  .module("rpt")
  .version("1.0")
    .templateType("Jasper")
    .formats(Seq(ReportFormat.pdf))
  .version("2.0")
    .templateType("Jasper")
    .formats(Seq(ReportFormat.pdf, ReportFormat.xlsx))
  .register()

Алгоритм поиска и упаковки шаблонов

  1. Поиск файлов. Билдер сканирует каталог reports/<Имя отчета>/<Имя версии>/ в classpath. В файловой системе обрабатывается содержимое каталога, а внутри JAR-файлов — записи JarEntry с помощью JarFileHelper. Исходные файлы шаблонов при этом хранятся в Git и доступны для проверки в GitLab.

  2. Упаковка в ZIP-архив. Перед сохранением шаблона в базе данных файлы упаковываются в ZIP-архив.

    • Для шаблонов Jasper допускается несколько файлов, включая основной шаблон и шаблоны подотчётов. Файлы добавляются в архив с сохранением исходных имён.

    • Для остальных типов шаблонов, допускается один файл. В архиве файл сохраняется под именем template.<расширение>.

  3. Синхронизация доступных форматов. Для коллекции доступных форматов экспорта версии печатной формы вычисляется разность (Set.diff) между форматами, указанными в методе formats(), и форматами, сохранёнными в базе данных. Форматы, отсутствующие в коде, удаляются из коллекции, а новые форматы добавляются. Вызовы session.flush() предотвращают коллизии ключей в кэше EclipseLink.

  4. Проверка форматов. Для каждого формата автоматически проверяется совместимость с типом шаблона. Например, формат xls нельзя указать для шаблона типа Doc. При обнаружении несовместимого формата выполнение DataInstall завершается с ошибкой AppException.

Блокировка и контроль ручного переноса#

Если на ландшафте включена системная настройка Запрет ручного переноса печатных форм (Rpt_BlockManualTransfer), для печатных форм со способом переноса Поставка с модулем (ModuleDelivery) применяются ограничения на ручной импорт, изменение и удаление.

На уровне бизнес-логики

  • Импорт из JSON через метод registerFromJson класса Rpt_ReportApi завершается с ошибкой AppException.

  • Импорт через Менеджер конфигураций с помощью Btk_ConfigManagerImporter завершается с ошибкой AppException.

  • Удаление отчётов через Rpt_ReportApi и их версий через Rpt_ReportVersionApi запрещено.

В пользовательском интерфейсе

  • В карточке печатной формы блокируется операция удаления и скрывается кнопка Загрузить ПФ из json. Описательные текстовые поля остаются доступными для редактирования.

  • Списки версий переводятся в режим только для чтения. Создание и удаление версий блокируются. Кнопки ручной загрузки файлов шаблонов в базу данных и импорта версий из JSON скрываются.

  • Изменение состава доступных форматов версии блокируется.

Журнал переносов печатных форм#

Журнал переносов печатных форм доступен по пути: Настройка системы > Аудит > Журнал переноса печатных форм.

Также журнал можно открыть через поле Выборка, указав Rpt_TransferLogAvi.

В журнале регистрируются:

  • автоматическая регистрация через DataInstall;

  • импорт печатной формы из JSON-файла;

  • импорт через Менеджер конфигураций;

  • заблокированные попытки ручного импорта.

Для каждой операции сохраняются:

  • дата и время операции;

  • пользователь, выполнивший действие;

  • системное имя печатной формы;

  • способ переноса;

  • способ доставки;

  • признак активности запрета ручного переноса;

  • результат выполнения в поле b_success и описание ошибки при неуспешном выполнении.

Сведения о переносах печатных форм сохраняются в таблице аудита aud.rpt_transfer_log. Таблица aud.rpt_transfer_log по умолчанию включена в типовое задание очистки устаревших данных, настроенное в Менеджере заданий. Срок хранения записей журнала составляет 60 дней. Записи старше установленного срока удаляются автоматически при выполнении задания.