В первой и второй частях мы рассматривали общий подход к бизнес-документации на нашем платформенном проекте в компании «Наука». А сейчас подобрались к главному – техническому проекту (ТП). Это – наш основной и наиболее распространенный документ для типовых задач в ERP-области.

Итак – ТП…

Стоит, наверное, отметить, что, как не существует двух одинаковых пирожных тирамису, так и не существует двух одинаковых шаблонов ТП. Все шаблоны ТП должны быть адаптированы под свои классы задач и быть максимально «обезжирены» - содержать только достаточный минимум для разработки.

Мы рассматриваем ТП – как основной документ детального проектирования задачи. В сущности, только он и годится для передачи в разработку (все остальные – Vision, SRS – это всегда вынужденный компромисс, когда в разработку отдается что-то довольн�� сырое с целью поэкспериментировать)

Файловая структура ТП

Начнем с того, что наши ТП имеют в проекте Git следующую структуру, помещаемую в головной функциональный раздел крупного компонента, например «НСИ»:

Подсветим некоторые принципы:

  1. Центральный документ – это файл ТП «*_specification.md» со ссылками на все остальные файлы. О его структуре поговорим чуть позже.

  2. Если в документы нужно внести дополнения, то мы оформляем новый документ типа «*_addonNN», в котором описываем «дельту» изменений с сохранением структуры. В итоге – каждое ТП или ЧТП получают вот такую «гармошку» редакций в стиле Консультант+ - это сделано в том числе для контроля исполнения задач по разработке и привязке задач на исправление багов в трекере задач.

  3. В каждом каталоге лежит файл README.md, который содержит корректный заголовок для сборки в MkDocs и навигационные ссылки.

Разделы ТП на примере

Рассмотрим пример ТП на типовой справочник - например, условий оплаты.

Непосредственно под заголовком документа мы кратко описываем его бизнес-назначение, даем ссылки на заявки Service Desk и задачу для трекинга:

# Технический проект на разработку справочника «Условия оплаты»

Назначение разработки: функционал в составе ядра для предоставления в прикладные решения справочника условий оплаты.

Спроектировано на основании [SD-13862](https://xxxx/index.html?id=13862).

Задача для аналитики [AVRORA_III-1038](https://xxxx.nauka.local/?moduleSign=PROJECTS&route=task/AVRORA_III-1038)

Общие положения, как видно, задают область разработки:

## Общие положения

Разработка ведется в составе ядрового приложения *General Data*

Визуальный интерфейс реализуется для:

1. Стандартной библиотеки просмотра справочника.
2. Модуля ведения справочника.

Порядок разработки

Порядок разработки описывает разрабатываемую сущность как таковую, например:

## Порядок разработки

1. Создать сущности и объекты БД. Структура таблиц сущностей приведена  
   на ![общей ERD-диаграмме](../erd/payment_terms_erd.pgerd.png)
2. Реализовать стандартную библиотеку просмотра «Условия оплаты»
3. Реализовать модуль ведения CRUD-операций для словаря «Условия оплаты»

Необходимо удостовериться в наличии в схеме general_data таблиц, получаемых по подписке:

- `ref_companies` - Организации
- `ref_folders*` - Общесистемн��е папки

Последовательность создания объектов БД с учетом наличия FK и constraints:

[ref_payment_terms](../erd/db_objects/ref_payment_terms.sql)

[ref_payment_terms_langs](../erd/db_objects/ref_payment_terms_langs.sql)

[ref_payment_terms_elements](../erd/db_objects/ref_payment_terms_elements.sql)

*Внимание!* Никакие из приведенных структур данных в ERD-диаграмме не могут быть изменены программистом
в одностороннем порядке без согласования с ответственным аналитиком. SQL-запросы, приведенные в настоящем документе,  
могут быть изменены программистом произвольно и по своему усмотрению при условии неизменности их
бизнес-логики возврата данных.

*Внимание!* Во всех скриптах необходимо применить корректную схему БД (изменить ее при необходимости).

Остановимся здесь несколько подробнее:

  1. Мы почти всегда начинаем описывать доменную область сразу с физической ERD-диаграммы. Такой уж у нас подход: аналитик должен уметь спроектировать взаимосвязь сущностей.

  2. Мы пробовали описывать физические ERD в разных инструментах, но сейчас пришли к самому простому – sql-скриптам с CREATE TABLE внутри, например, таким:

3.	-- Table: analytic_dev.ref_payment_terms

-- DROP TABLE IF EXISTS analytic_dev.ref_payment_terms;

CREATE TABLE IF NOT EXISTS analytic_dev.ref_payment_terms
(
    payment_term_id uuid NOT NULL,
    company_id character varying(10) COLLATE pg_catalog."default" NOT NULL,
    folder_id uuid NOT NULL,
    payment_term_sign character varying COLLATE pg_catalog."default" NOT NULL,
    payment_term_note character varying COLLATE pg_catalog."default",
    payment_term_usage integer,
    date_start date NOT NULL,
    date_end date,
    del_sign boolean NOT NULL DEFAULT false,
    motherland character varying(20) COLLATE pg_catalog."default" NOT NULL DEFAULT 'GD'::character varying,
    CONSTRAINT payment_term_pk PRIMARY KEY (payment_term_id),
    CONSTRAINT payment_term_company_id_fk FOREIGN KEY (company_id)
        REFERENCES analytic_dev.ref_companies (company_id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION,
    CONSTRAINT payment_term_folder_id_fk FOREIGN KEY (folder_id)
        REFERENCES analytic_dev.ref_folders (folder_id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION,
    CONSTRAINT payment_terms_ds_de CHECK (COALESCE(date_end, date_start) >= date_start),
    CONSTRAINT payment_terms_sign_overlap EXCLUDE USING gist (
        company_id WITH =,
        daterange(date_start, COALESCE(date_end, '3000-01-01'::date), '[]'::text) WITH &&,
        payment_term_sign WITH =)

        WHERE (del_sign = false)
)

TABLESPACE pg_default;

ALTER TABLE IF EXISTS analytic_dev.ref_payment_terms
    OWNER to analytic_dev;

COMMENT ON TABLE analytic_dev.ref_payment_terms
    IS 'Словарь условий оплаты';

COMMENT ON COLUMN analytic_dev.ref_payment_terms.payment_term_id
    IS 'Ключ записи';

COMMENT ON COLUMN analytic_dev.ref_payment_terms.company_id
    IS 'Ключ организации';

COMMENT ON COLUMN analytic_dev.ref_payment_terms.folder_id
    IS 'Ключ общесистемной папки';

COMMENT ON COLUMN analytic_dev.ref_payment_terms.payment_term_sign
    IS 'Сигнатура условия оплаты';

COMMENT ON COLUMN analytic_dev.ref_payment_terms.payment_term_note
    IS 'Примечание условия оплаты';

COMMENT ON COLUMN analytic_dev.ref_payment_terms.payment_term_usage
    IS 'Признак использования в документах';

COMMENT ON COLUMN analytic_dev.ref_payment_terms.date_start
    IS 'Дата начала действия записи';

COMMENT ON COLUMN analytic_dev.ref_payment_terms.date_end
    IS 'Дата окончания действия записи';

COMMENT ON COLUMN analytic_dev.ref_payment_terms.del_sign
    IS 'Признак удаления записи';

COMMENT ON COLUMN analytic_dev.ref_payment_terms.motherland
    IS 'Идентификатор системы источника';

Аналитики располагают собственной БД и схемой, в которой они могут с помощью любого удобного им средства (мы используем PGAdmin или DBeaver) создавать таблицы сущностей в мастере или прямо скриптом (кто как умеет).

 Читатель может, конечно, усомниться в целесообразности такого повышения компетенций к аналитику (согласитесь, не каждый напишет такой constraint, как в примере, для контроля пересечения хроникальных данных), но – на самом деле – аналитик должен просто хорошо освоить:

  1. азы нормализации и отношений в БД

  2. базовый синтаксис CREATE TABLE

  3. наш собственный гайд по именованию объектов в БД

  4. базовый английский с переводчиком

  5. как level up – понимать, как написать, например, CONSTRAINT или FK (а если нет, ему это подскажет лид на ревью)

Раньше мы пробовали рисовать ERD-скетчи в draw.io, но всегда находились какие-то недоработки – то признаки обязательности не указаны, то комментариев к полям нет, то аналитик запутался в типах связей.  А скрипт хорош тем, что в нем сущность описана исчерпывающе – аналитик, работая в мастере PGAdmin, фактически следует чеклисту, не пропускает важные данные (размерность и тип полей, обязательность, ограничения, FK).

Обратите внимание, что в нашем понимании только аналитик способен корректно выставить связи таблиц (если речь идет про реляционную БД), типы и размерность данных на основании доступной ему нормативной базы – федерального стандарта, постановления правительства, формата ЭДО ФНС и т.д. Разработчик в этом смысле условно «слеп», он просто не знает, какой должна быть доменная область, а аналитик это выявить обязан в ходе работы с нормативкой и доступными ему доменными экспертами.

Техническая специфика, такая, как проектирование индексов, вынесена из скриптов – ей занимается разработчик на основании метрик производительности из ТП.

Т. о., аналитик полностью описывает скриптами все таблицы сущностей со всеми взаимосвязями, прогоняет в схеме аналитической БД  (создает их в БД) и, в итоге, формирует ERD-диаграмму в ERDTool (это – стандартный инструмент PGAdmin), позволяющий набросать на холст таблицы из схемы и получить ее визуальное представление в виде файла .pgerd. Получается что-то типа такого:

Вообще, конечно, такой подход требует, во-первых, стандартизации подхода к задачам, а во-вторых – некоторой квалификации аналитика на уровне БД – по сути, он работает в рамках единого подхода и в очень редких случаях выходит за него – например, если метрики производительности или объемы данных какие-то нетиповые. Тогда он уже на этапе проектирования ERD зовет техлидов для консультаций и согласует с ними макет ERD, который он подготовил «за основу» с внесением оперативных правок по замечаниям.

Интерфейс приложений

Обычно мы разрабатываем 2 вида интерфейсов. Первый (простейший), это т. н. «библиотека просмотра» - read-only DataGrid, позволяющий вызвать справочник НСИ из другого регистра для выбора записей (выбрать в договоре условие оплаты, выбрать контрагента и т. д.). Второй – полноценный «модуль ведения» - регистр с CRUD+ операциями для наполнения данными и бизнес-логикой. Рассмотрим часть ТП, относящуюся к модулю ведения.

### Модуль ведения

| Показатель               | Значение         |
| ------------------------ |------------------|
| Путь к модулю в лаунчере | НСИ - Финансы    |
| Сигнатура модуля         | GD_PAYMENT_TERMS |
| Наименование модуля      | Условия оплаты   |

Модуль должен содержать тулбар (правый верхний угол) со следующими стандартными кнопками:

- Обновить
- Объекты доступа
- Информация
- "Справка" (с выпадающими пунктами)
    - "Справка" со ссылкой на вложенный в проект модуля [файл руководства пользователя по модулю "Условия оплаты"](../user_instructions/GD_PAYMENT_TERMS_GRID_user_manual_actual.pdf) 
      **Внимание!** Файл руководства должен быть подготовлен техническим писателем после исполнения ТП на ландшафте
      развертывания.
    - "Написать в поддержку" - ссылка на адрес на продуктивный WFB клиента (взять из настройки уровня модуля `feedback.service.path` + `/index_user.html?NewTopic=true`)
    - "Служба поддержки" - ссылка на адрес на продуктивный WFB клиента (взять из настройки уровня модуля `feedback.service.path` + `/index_user.html`)
- Конфигурации экрана
- Пользовательские настройки

**Внимание:** Модуль должен поддерживать стандартную синхронизацию по kafka (прямую и обратную).

#### Мастер грид

##### Общие свойства

| Свойство grid                       | Значение                                                                                                    |
|-------------------------------------|-------------------------------------------------------------------------------------------------------------|
| Техническая сигнатура грида         | GD_PAYMENT_TERMS_GRID                                                                                       |
| Вид грида                           | Плоский.                                                                                                    |
| Заголовок грида                     | Присутствует. =  "Условия оплаты"                                                                           |
| Возможность инлайн-режима           | Отсутствует.                                                                                                |
| Общегридовый поиск                  | Присутствует. (editbox «Найти…»)                                                                            |
| Размещение на табе                  | Табы отсутствуют.                                                                                           |
| Тулбар с кнопками                   | Присутствует. Список кнопок и описание их действий см. ниже                                                 |
| Колоночные фильтры                  | Присутствуют. Под каждым заголовком колонки - поле с фильтром                                               |
| Иконка воронки колоночного фильтра  | Присутствуют у каждого поля.                                                                                |
| Колонка множественного выбора       | Присутствует. Первая колонка грида – колонка с чекбоксами выделения                                         |
| Поле количества строк и пагинация   | Присутствует. Под гридом: поле для выбора количества отражаемых строк на странице и счетчик-пагинатор       |
| Конструктор фильтров                | Отсутствует.                                                                                                |
| Тулбар строки                       | Отсутствует.                                                                                                |
| Контекстное мен��                    | Присутствует. Полностью дублирует тулбар грида                                                              |
| Контекстное меню шапки              | Стандартное. В соответствии с текущей версией ядра.                                                         |
| Наличие зависимых гридов            | Имеет зависимые гриды: "Элементы условия оплаты", "Локализация условия оплаты", "Ссылки на внешние объекты" |

Отображаются только те колонки, которые есть в [макете](../layout/payment_terms_crud_layout.drawio)

![макет](../layout/payment_terms_crud_layout.png)

##### Выборка данных

Запрос для выборки данных приведен в файле [ref_payment_terms_main_crud.sql](../erd/sql_scripts/ref_payment_terms_main_crud.sql).

| Параметр запроса | Описание             | Источник заполнения                               |
|------------------|----------------------|---------------------------------------------------|
| :ondate          | Текущая дата         | Значение сессионной настройки SYS_DATE_PARAM      | 
| :comp_id         | Идентификатор БЕ     | Значение сессионной настройки SYS_COMPANY_PARAM   |
| :lang_id         | Идентификатор языка  | Значение сессионной настройки SYS_LANG_PARAM      |

**Внимание**: grid **отображает** удаленные записи.

##### Действия в гриде

| Действие              | Иконка                                                                             | Тип             | Описание                            | Особенности                                        |
|-----------------------|------------------------------------------------------------------------------------|-----------------|-------------------------------------|----------------------------------------------------|
| Добавить              | ![i](../../../../../../Methodology/UI/Icons/src/svg/plus-solid.svg)                | Независимое     | Добавляет новую строку | Описание [алгоритма](./algs/pt_mod_tbar_add.md)    |
| Исправить             | ![i](../../../../../../Methodology/UI/Icons/src/svg/edit-solid.svg)                | Индивидуальное  | Исправляет строку                   | Описание [алгоритма](./algs/pt_mod_tbar_edit.md)   |
| Удалить               | ![i](../../../../../../Methodology/UI/Icons/src/svg/trash-solid.svg)               | Массовое        | Удаляет строки                      | Описание [алгоритма](./algs/pt_mod_tbar_delete.md) |
| Скрыть колонки        | ![i](../../../../../../Methodology/UI/Icons/src/svg/list-alt-solid.svg)            | Независимое     | Выбор отображаемых колонок          | Стандартное платформенное действие тулбара         |

Реализовать модальные формы для действий с интерфейсом, указанным в макете (см. выше).

После успешных действий обновлять выборку на экране и в подчиненных детейл-гридах при их наличии.

##### Контроль

| Контроль       | Constraints                 | Содержание                                                                                     |
| -------------- |-----------------------------|------------------------------------------------------------------------------------------------|
| Уникальность   | payment_terms_sign_overlap  | Сигнатура должна быть уникальной с учетом признака удаления записи и пересечения дат действия  |
| Хроникальность | payment_terms_ds_de         | Если date_end is not null, то она >= date_start                                                |

Дадим здесь некоторые пояснения:

  1. Интерфейсы модулей для операций с сущностями не проектируются с нуля – у нас написан довольно большой методический документ – «Общая концепция интерфейса», который, подобно Контур.Гайды, вводит понятийный аппарат и описывает основные элементы, их зонирование на экране, правила взаимодействия и ограничения.

  2. Поэтому частные аналитические артефакты (SRS, ТП) свободно ссылаются на такие понятия, как «тулбар модуля», «тулбар грида», «индивидуальное действие», «сессионная настройка» и т.д.

  3. Как видно, аналитик описывает интерфейс с исключительно пользовательских позиций (посмотрите, к примеру, на таблицу с описание мастер- и детейл-гридов), но по стандартному чеклисту.

  4. При этом для отображения данных он обязан написать параметризированный запрос из ранее спроектированных таблиц сущностей и «смапить» его на колонки грида.

По поводу макетов интерфейса у нас случались довольно ожесточенные схватки по части выбора инструмента: на смежных проектах есть опытные любители Figma, кто-то предпочитает «просто draw.io», а кто-то дошел до того, что развернул Budibase и натравливает его прямо на аналитическую БД с данными. Сейчас популярность у нас приобретают AI-инструменты для формирования динамических html экранов – короче, пробуем мы многое, а используем, как правило, самое дешевое и быстрое – draw.io.

По итогу макет выглядит как-то так:

Да – знаем, знаем – не формализованно, не универсально. Но мы действительно честно посмотрели довольно много инструментов описания интерфейсов (как правило - open-source и on-premise) и вот какие выводы сделали:

  1. Нужно экономить и выдавать ТП быстро. А инструменты типа Budibase – крутые, но все же требуют вкладываться в настройку каждой кнопочки, каждого события и т. д. Для нас это - долго!

  2. Figma – все же, не для наших типовых «крудошлепских» задач – ну не нужно нам попиксельно все рисовать и позиционировать красиво на экране! У нас нет дизайна - у нас есть грубая компоновка ��тандартных компонентов на заранее зонированном экране.

  3. AI – рисует красиво, но итоговый макет использует совсем не наши визуальные компоненты (а заставить его перейти именно к нашим стилям – не так-то легко) и это часто путает разработчиков.

Пока у нас наиболее распространенный вариант – вот такой draw.io-скетч. Поэтому в плане дизайна интерфейсов мы сейчас находимся в поиске и вариантов у нас несколько:

  1. Сделать собственный дизайнер экранов для наших типовых компонентов с собственным форматом хранения данных в json

  2. Научить наш AI выдавать дизайн с правильными компонентами и стилями.

  3. Или все вместе.

И мы будем благодарны, если читатель посоветует нам что-то из собственного опыта.

Алгоритмы и бизнес-логика

Каждое действие мы расшифровываем описанием алгоритма в отдельном файле.

Тут все индивидуально, но подходы у нас следующие:

1.        Если алгоритм CRUD-образный, то просто описываем по очень простому шаблону:

# Описание алгоритма действия "Добавить"

## Привязка алгоритма

Нажатие на кнопку:

| Модуль          | Грид                                     | Кнопка   |
|-----------------|------------------------------------------|----------|
| Условия оплаты  | Детейл-грид "Ссылки на внешние объекты " | Добавить |

## Предварительные проверки перед выполнением алгоритма

Отсутствуют

## Влияние на интерфейс

Показать модальную форму добавления записи в соответствии с макетом.

Инициализировать поля на форме значениями по-умолчанию:

- "Дата начала действия записи". Значение: из **сессионной** настройки SYS_DATE_PARAM.
  Для целей тестирования присвоить ей значение = CURRENT_DATE.
  В случае, если значение настройки не найдено или пустое, то не инициализировать поле по-умолчанию.

## Пост-проверки

Отсутствуют.

## Сохранение данных в сущностях

Произвести сохранение добавляемой записи в сущности: считать обозначения на макете технических имен полей
основанием для сохранения в одноименные поля сущностей.

- nsi_external_link

Особенности заполнения системных полей:

| Поле       | Описание порядка                                                                                                                      |
|------------|---------------------------------------------------------------------------------------------------------------------------------------|
| tab_id     | идентификатором таблицы id из general_data.sys_table внести туда запись (id, name) (очередной номер из sequence, `ref_payment_terms`) |
| int_id     | = "payment_term_id"                                                                                                                   |
| int_value  | =GUID головной записи из ref_payment_terms                                                                                            |

**Внимание:** Доработка для "недавних" папок:

После успешного сохранения данных вызвать общесистемный метод добавления сущности в "недавнее" с параметрами:

| Поле               | Значение                                                                       |
|--------------------|--------------------------------------------------------------------------------|
| moduleSignature    | = `GD_PAYMENT_TERMS`                                                           |
| userId             | Идентификатор текущего пользователя из nsi_users (pk)                          |
| entityId           | Идентификатор условия оплаты (**головной записи**)                             |
| entityRecentName   | Из поля `payment_term_sign` (сигнатура условия оплаты из **головной записи** ) |
| entityRecentAction | = `Добавление записи интеграции`    

2.        Если в начинке алгоритма есть сложная логика, то пишем диаграмму активностей в PlantUML – получается, что-то подобное (пример из другого ТП):

3.        Если нужны REST API (а они у нас разрабатываются не на каждый модуль), то в таблице действий привязываем методы, которые разрабатываем в едином контракте по спецификации openAPI.

В случае, если для алгоритма характерны особые метрики производительности, то они описываются, обычно так:

Метрики производительности: Время ожидания загрузки перечня материалов по классу материалов - не более 2сек  
при одновременном обращении до 500 пользователей системы и объеме данных для выбранного класса до 50 000 записей  
по материалам (на текущий момент на продуктивном сервере в БД есть классы в которые входит порядка 14 000 записей  
материалов без учета ограничений по связанным данным)

А в головном ТП фиксируются объемы данных по сущностям:

**Внимание!** Проверять соответствие метрикам производительности, обозначенным в пунктах алгоритма

Библиотека должна сохранять соответствие метрикам при работе с объёмами данных до 1 000 000 записей по материалам.

Метрики по конечным пользователям и объему данных ужасно важны! Без них разработчики, бывало, попадали в беду, не зная, что нужно предусмотреть lazy-load в гриде или поработать над оптимизацией запроса на действительно больших данных.

Служебные разделы ТП

Дадим некоторые пояснения:

В развертывании нам, как ан��литикам, интересен только «первичный» ландшафт, на который будет развернуто разработанное решение – там мы сможем посмотреть полноту и качество его исполнения по ТП. Дальнейшее – предмет регламента по разработке и непосредственно аналитики не касается.

#### Развертывание

Развернуть на [ландшафт](https:/xxxxx.nauka.local/)

Генерация тестовых данных – раздел специфический. Обычно, если аналитик располагает достаточным временем и при этом раздел несколько более сложный, чем CRUD-модуль с 2 полями, то аналитик разрабатывает генерацию тестовых данных, например, вот так:

#### Генерация тестовых данных

Выполнить генерацию данных для тестирования, последовательно исполнив:


1. [Скрипт создания функции генерации данных](../erd/test_data_scripts/data_generation_function.sql)
2. [Скрипт запуска генерации](../erd/test_data_scripts/data_generation_run.sql)
   в коде запуска можно оперировать параметрами:
    
    ```sql
    select general_data.ref_branches_test_data_generator  
    (
    comp_id => 'ROGA_I_KOPYTA', --балансовая единица, для которой нужно сгенерировать данные  
    ds => CURRENT_DATE - 10, --дата начала действия записей  
    de => CURRENT_DATE, --дата окончания действия записей
    num_trees => 5, --количество корневых записей-деревьев
    max_records => 10, --количество записей в ветке каждой корневой записи
    num_of_del_records => 3, --количество удаленных записей в каждой ветке
    num_of_resp => 10, --количество ответственных лиц в каждой службе
    num_of_state => 20, --количество строк штата в каждой службе
    del_old_data => true --удалять ли записи целиком из словаря перед их созданием
    )
    ```
3. Параметры запуска скрипта сообщаются программистом тестировщику для понимания тест-кейсов.

Т. е. пишет параметризированную хранимую функцию (обычно на PlPgSQL), которая создает тестовые данные, а также описывает специфические тест-кейсы:

#### Порядок тестирования

В тест-кейсах должно быть учтено:

1. Проверка корректности отражения данных только по заданной в системной сессионной
   настройке БЕ (балансовой единице) (в указанном примере данные генерируются по KNOS,
   соответственно, при установке иных БЕ данные видны быть не должны - тестировщик
   последовательно меняет значение сессионной настройки "Идентификатор компании")
2. Проверка корректности отражения имен служб на системную дату, выставленную в настройке
   пользователя - службы должны отражаться с разными именами - на DE, и на DE -6 дней
   (тестировщик последовательно меняет значение сессионной настройки "Системная рабочая дата") -
   имя должно поменяться во всех записях в словаре.
3. Для просмотровой библиотеки не должны показываться созданные скриптом удаленные записи.
   Для модуля ведения - должны в количестве, заданном в скрипте (num_of_del_records) - в указанном
   примере для каждого дерева будет 10 вложенных уровней со службами, три последних будут с отметкой удаления.
4. Для просмотровой библиотеки на должны показываться созданные скриптом удаленные записи
   ответственных лиц. Для модуля ведения - должны в количестве,
   заданном в скрипте (num_of_del_records) - в указанном примере для каждого дерева будет 10 подчиненных
   ответственных лиц, три последних будут с отметкой удаления.
5. **Upd. Refactor ADR-16** Для просмотровой библиотеки на должны показываться созданные скриптом удаленные запис��
   штата службы. Для модуля ведения - должны в количестве, заданном в скрипте (num_of_del_records):
   в указанном примере для каждого дерева будет 20 подчиненных строк штата, три последних будут с отметкой удаления.
6. Тест-кейсы должны включать проверку всего объема операций в модуле ведения в части
   проверки функционирования, кнопок всех тулбаров и констекстного меню на
   сгенерированых данных.
7. Тест-кейсы должны предусматривать последовательную проверку функционала при присвоении
   пользователю ролей для тестирования.

А если модуль простой, то ограничивается следующим:

#### Генерация тестовых данных

Генерация тестовых данных выполняется в рамках отдельной
задачи [AVRORA_III-1149](https://xxxx.nauka.local/?moduleSign=PROJECTS&route=task/AVRORA_III-1149)
впоследствии и при необходимости.

#### Порядок тестирования

В тест-кейсах должно быть учтено:

1. Тест-кейсы должны включать проверку всего объема операций в модуле ведения в части
   проверки функционирования, кнопок всех тулбаров и констекстного меню.
2. Тест-кейсы должны предусматривать последовательную проверку функционала при присвоении
   пользователю ролей для тестирования.

**Внимание!** В рамках настоящего ТП тестирование на данных не производится, оно
будет выполнено позднее при их генерации.

**Внимание!** При тестировании необходимо проверить корректность обновления данных в GD_TEST с  
использованием стандартного механизма интеграции (когда данные вносятся в словарь в GD,
а по подписке появляются в GD_TEST).

Здесь принципиально важно то, что только аналитик понимает то, как должны выглядеть бизнес-данные для тестирования – даже в простейшем справочнике возможны непростые комбинации по хронологии, признакам удаления, локализации на разные языки и т.д. Так что подготовка датасета для теста – его задача.

Вообще – у нас с командой тестирования есть соглашение: нет ТП – нет тестирования. В самом деле, без описанного функционала, алгоритмов и подготовленных данных тестировщик слеп (как и разработчик).

В ТП обязательно описывается использование объектов полномочий в рамках нашего платформенного компонента СУПД (Система Управления Полномочиями и Доступом):

#### Объекты полномочий

Ответственный администратор СУПД создает роли для тестирования функционала:

1. Только просмотр в библиотеке просмотра
2. Видимость модуля в Launcher и добавление\исправление записей (без удаления)
3. Видимость модуля в Launcher и полные права на все действия во всех гридах

Присваивает по одной из них трем типовым пользователям, которые используются
тестировщиком для проверки функционирования ОП.

Выше приведен самый простой вариант, поскольку ТП может предусматривать и специальную настройку групп или объектов полномочий, макроподстановок и т.д.

И фиксируется порядок документирования, в элементарном варианте – вот так:

#### Порядок документирования

#### Пользовательские инструкции

Оформление пользовательской инструкции выполняется в рамках
задачи [AVRORA_III-1151](https://xxxx.nauka.local/?moduleSign=PROJECTS&route=task/AVRORA_III-1151)
впоследствии и при необходимости.

**Внимание!** После оформления пользовательской инструкции необходимо оформить отдельную задачу
на пересборку приложения для включения в состав комплекта поставки созданных пользовательских инструкций.
В рамках реализации настоящего ТП в комплект поставки для пункта тулбара модуля "Справка" включается пустой
[файл](../user_instructions/GD_PAYMENT_TERMS_GRID_user_manual_actual.pdf)

Отметим, что рассмотренный шаблон ТП специфичен для задачи разработки ERP-модуля или библиотеки. У нас есть и другие, например, для интеграции с внешней системой – но общие принципы их написания – едины.

Заканчивая рассмотрение ТП, как нашего, подчеркнем, центрального артефакта, скажем, что каждый уважающий себя вендор ПО, вероятно, приходит к какому-то своему, особому подходу в отношении этого документа. У нас он такой – возможно, слишком классический, но – рабочий.

Как донести ТП до разработчика и проконтролировать его?

Как будто – это тема отдельной статьи. Но, как показывает практика, когда разработчик видит ТП, сформированное по описанному выше шаблону, он часто пугается («Ой, многабукоф!»), читает не все и делает так, как понял – т. е. неправильно.

Мы даже пытались их как-то, ну, не наказывать, а поругивать за большое количество отклонений от документации. Но отклонения никуда не девались. Поэтому мы ввели практику, которую можно назвать, «Чтение вслух на ночь». После согласования в Git ТП передается конкретному разработчику. Тут аналитик снова вступает в игру и на очной встрече с назначенным разработчиком «проговаривает» ТП, поясняя, в том числе на примерах, существующих в Платформе, что же нужно сделать. В общем, это – рабочий, хоть несколько затратный подход, но – лучше потратить 30 минут на «чтение», чем потом получить сюрприз.

Почему мы поступаем именно так?

Читатель может вполне логично спросить – почему мы поступаем именно так, как описали в статье? Ведь есть много альтернатив – ну, например, ТП с таблицами куда удобнее вести в Word, не заморачиваться с такими строгими физическими ERD, зачем этот markdown и т.д.

Ответ связан с нашими целями. На протяжении двух последних лет мы старались максимально стандартизировать наши документы, привести их одновременно к простому, но достаточному для понимания формату, сократив трудозатраты на аналитику.

Мы этой цели достигли.

В частности, был существенно ускорен онбординг – есть примеры, когда стажеры без опыта работы начинали писать по нашим шаблона вполне «годные» ТП уже через 2-3 недели.

И прикладникам коллегам есть куда обратиться за постановкой, чтобы понять – как же этот общесистемный платформенный компонент должен работать.

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

Пока что в области AI мы готовыми результатами в этом направлении похвастать не можем – мало наработок. Но работу мы такую ведем, набиваем много шишек – и часто потому, что просто нужен опыт в эффективном промпт-инжиниринге, что методические документы плохо «в лоб» ложатся в промпты, требуют переработки и т. д.

Думается, через какое-то время мы сможем описать наш путь и результаты, но это – тема отдельной большой статьи.

Спасибо, читатель, за внимание – мы будем рады обратной связи.