DAL-слой chk: функции БД, спецификации, psql-тесты, репозитории (MT.Checks)
- DB/chk: 7 хранимых функций (p_*), func_specs, psql-тесты, статусы DEV/CODE - MT.Checks: домен (ChkCheck, ChkType, ChkStatus), репозитории ChkCheck/ChkType/ChkStatus (Kit.Helpers, inline-конвертеры) - 1-docs/2-core/chk/repository_tests: спецификации тестов репозиториев - db/manifest.json, отчёт Plan/dal_report.md
This commit is contained in:
parent
01fa7f5e57
commit
939d44063e
|
|
@ -0,0 +1,7 @@
|
|||
# Одноразовые артефакты прогона project_dal (c-skl-3) — в git не попадают
|
||||
Plan/dal_state.json
|
||||
Plan/env_passport.json
|
||||
check_report.json
|
||||
|
||||
bin/
|
||||
obj/
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
# Тесты `ChkCheckRepository` (слой Chk)
|
||||
|
||||
> Репозиторий `MT.Check.Core.Dal.Chk.Repository`: IChkCheckRepository / ChkCheckRepository
|
||||
> (правила — c-dal; концепция unit-тестов без БД — c-tst; генерация — d-tst).
|
||||
> Домен: `MT.Check.Core.Dal.Chk.Domain.ChkCheck` (Id, CheckDate, TypeId, Type,
|
||||
> StatusId, Status, SmevMessageId, RrOrganizationId, Params, ParentCheckId).
|
||||
|
||||
## Методы → функции БД
|
||||
|
||||
| Метод | Транспорт | Функция БД |
|
||||
|---|---|---|
|
||||
| `Insert(ChkCheck): int` | `IConnectionString.PrepareExecute<int>().AsStoredProcedure().AddParameter*` + `ExecuteScalar()` | `chk.chk_check_insert` |
|
||||
| `Update(ChkCheck): int` | то же + `ExecuteScalar()` | `chk.chk_check_update` |
|
||||
| `Delete(int id): int` | то же + `ExecuteScalar()` | `chk.chk_check_delete` |
|
||||
| `Select(ChkCheckFilter): IList<ChkCheck>` | `PrepareExecute<ChkCheck>().AddConverter(...)` + `ExecuteSelectMany()` | `chk.chk_check_select` |
|
||||
| `Get(int id): ChkCheck?` | `PrepareExecute<ChkCheck>().AddConverter(...)` + `ExecuteSelectMany()` | `chk.chk_check_get` |
|
||||
|
||||
## Механика теста (общая)
|
||||
|
||||
- Транспорт подменяется фейком `ConnectionStringTest : IConnectionString` (d-tst-11):
|
||||
конструктор принимает строгий набор ожидаемых параметров (`Dictionary<string, object?>`)
|
||||
и таблицу фикстуры; `VerifyAll` — в конце каждого теста (d-tst-12).
|
||||
- Одна таблица ответа = один конвертер (d-tst-11); слово «курсор» не используется (d-tst-22).
|
||||
- Строгий набор параметров: имена `p_check_date`, `p_chk_type_id`, `p_chk_status_id`,
|
||||
`p_smev_message_id`, `p_rr_organization_id`, `p_params`, `p_parent_check_id`, `p_id`
|
||||
(c-dal-5, d-tst-13). Строки домена без NULL (c-dm-10): пустое значение → `""`.
|
||||
- Update — полная запись объекта: сценарии «null = не менять» не проектируются (db-m-8, c-dal-17).
|
||||
- Тестируем репозиторий, а не БД: SQL-семантика фильтров не воспроизводится (d-tst-5, d-tst-10).
|
||||
- Счётчики — из фикстуры, без литералов (d-tst-23); тело теста по этапам
|
||||
`init test env by fixtures` → `call repository method` → `check result` (c-tst-3).
|
||||
|
||||
## Заготовки (DataTable)
|
||||
|
||||
Таблица ответа `chk.chk_check_select` / `chk.chk_check_get` (одна на оба метода):
|
||||
`id:int, check_date:DateTime, chk_type_id:int, chk_status_id:int,
|
||||
smev_message_id:string, rr_organization_id:string, params:string, parent_check_id:int?`.
|
||||
|
||||
Строки-фикстуры:
|
||||
|
||||
- `c1`: id=101, check_date=2026-05-01, chk_type_id=1, chk_status_id=2,
|
||||
smev_message_id='smev-101', rr_organization_id='rr-101',
|
||||
params='{"org_count":5}', parent_check_id=NULL;
|
||||
- `c2`: id=102, check_date=2026-05-01, chk_type_id=1, chk_status_id=3,
|
||||
smev_message_id='', rr_organization_id='rr-102', params='', parent_check_id=101;
|
||||
- `c3`: id=103, check_date=2026-05-02, chk_type_id=5, chk_status_id=4,
|
||||
smev_message_id='smev-103', rr_organization_id='', params='', parent_check_id=NULL.
|
||||
|
||||
Скалярные заготовки: `chk.chk_check_insert` → 201 (id новой записи);
|
||||
`chk.chk_check_update` → 1; `chk.chk_check_delete` → 1.
|
||||
|
||||
## Тесты: `Insert`
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной | все поля объекта заполнены (строка c1 без Id) | вызов `chk.chk_check_insert`; строгий набор 7 параметров (`p_parent_check_id` = значение); возврат 201 из scalar-заготовки |
|
||||
| 2 | граничный | необязательные поля пустые: строки `""`, `ParentCheckId = null` | строгий набор: `p_smev_message_id` = `""`, `p_params` = `""`, `p_parent_check_id` = NULL (`DBNull`) |
|
||||
|
||||
## Тесты: `Update`
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной | полный объект (строка c2): Id=102 + все поля | вызов `chk.chk_check_update`; строгий набор 8 параметров (p_id + все поля); возврат 1 |
|
||||
| 2 | исключение | объект с `Id = 0` | ArgumentException до транспорта; транспорт не вызывался |
|
||||
|
||||
## Тесты: `Delete`
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной | Id = 103 | вызов `chk.chk_check_delete`; параметр `p_id` = 103; возврат 1 |
|
||||
| 2 | исключение | Id = 0 | ArgumentException до транспорта; транспорт не вызывался |
|
||||
|
||||
## Тесты: `Select`
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной | фильтр: CheckDate=2026-05-01, TypeId=1; таблица c1+c2+c3 | 2 сущности (по строкам c1, c2); строгий набор: `p_check_date`, `p_chk_type_id` заданы, `p_chk_status_id`/`p_rr_organization_id` = NULL |
|
||||
| 2 | граничный | фильтр пустой (все поля null, c-dal-12: filter ??= new) | 3 сущности; все 4 параметра = NULL |
|
||||
| 3 | основной | таблица c2+c3; пустой фильтр | поля сущностей сверены со строками (AssertEquals: id, check_date, chk_type_id, chk_status_id, smev_message_id, rr_organization_id, params, parent_check_id) |
|
||||
| 4 | граничный | пустая таблица | пустая коллекция (не null) |
|
||||
|
||||
## Тесты: `Get`
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной | Id = 101; таблица c1 | 1 сущность; строгий набор: `p_id` = 101; поля сверены со строкой c1; Type/Status-объекты не заполняются транспортом (null) |
|
||||
| 2 | граничный | пустая таблица (id не найден) | null |
|
||||
| 3 | исключение | Id = 0 | ArgumentException до транспорта; транспорт не вызывался |
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# Тесты `ChkStatusRepository` (слой Chk)
|
||||
|
||||
> Репозиторий `MT.Check.Core.Dal.Chk.Repository`: IChkStatusRepository / ChkStatusRepository
|
||||
> (правила — c-dal; концепция unit-тестов без БД — c-tst; генерация — d-tst).
|
||||
> Системный справочник (фиксированные id) — только методы чтения (c-dal-2).
|
||||
> Домен: `MT.Check.Core.Dal.Chk.Domain.ChkStatus` (Id, Name) + константы `ChkStatuses`.
|
||||
|
||||
## Методы → функции БД
|
||||
|
||||
| Метод | Транспорт | Функция БД |
|
||||
|---|---|---|
|
||||
| `Select(): IList<ChkStatus>` | `IConnectionString.PrepareExecute<ChkStatus>().AddConverter(...)` + `ExecuteSelectMany()` | `chk.chk_status_select` |
|
||||
|
||||
## Механика теста (общая)
|
||||
|
||||
- Транспорт — фейк `ConnectionStringTest : IConnectionString` (d-tst-11); `VerifyAll` в конце (d-tst-12).
|
||||
- Одна таблица ответа = один конвертер (d-tst-11); «таблица», не «курсор» (d-tst-22).
|
||||
- Функция без параметров: строгий набор — пустой словарь (d-tst-13).
|
||||
- Счётчики — из фикстуры (d-tst-23); этапы теста — c-tst-3.
|
||||
|
||||
## Заготовки (DataTable)
|
||||
|
||||
Таблица ответа `chk.chk_status_select`: `id:int, name:string`.
|
||||
|
||||
Строки-фикстуры: `s1` (id=1, name='Запрос отправлен'),
|
||||
`s4` (id=4, name='Ошибка при обработке').
|
||||
|
||||
## Тесты: `Select`
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной | таблица s1+s4 | 2 сущности; строгий набор: параметров нет; поля сверены со строками (id, name) |
|
||||
| 2 | граничный | пустая таблица | пустая коллекция (не null) |
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# Тесты `ChkTypeRepository` (слой Chk)
|
||||
|
||||
> Репозиторий `MT.Check.Core.Dal.Chk.Repository`: IChkTypeRepository / ChkTypeRepository
|
||||
> (правила — c-dal; концепция unit-тестов без БД — c-tst; генерация — d-tst).
|
||||
> Системный справочник (фиксированные id) — только методы чтения (c-dal-2).
|
||||
> Домен: `MT.Check.Core.Dal.Chk.Domain.ChkType` (Id, Name) + константы `ChkTypes`.
|
||||
|
||||
## Методы → функции БД
|
||||
|
||||
| Метод | Транспорт | Функция БД |
|
||||
|---|---|---|
|
||||
| `Select(): IList<ChkType>` | `IConnectionString.PrepareExecute<ChkType>().AddConverter(...)` + `ExecuteSelectMany()` | `chk.chk_type_select` |
|
||||
|
||||
## Механика теста (общая)
|
||||
|
||||
- Транспорт — фейк `ConnectionStringTest : IConnectionString` (d-tst-11); `VerifyAll` в конце (d-tst-12).
|
||||
- Одна таблица ответа = один конвертер (d-tst-11); «таблица», не «курсор» (d-tst-22).
|
||||
- Функция без параметров: строгий набор — пустой словарь (d-tst-13).
|
||||
- Счётчики — из фикстуры (d-tst-23); этапы теста — c-tst-3.
|
||||
|
||||
## Заготовки (DataTable)
|
||||
|
||||
Таблица ответа `chk.chk_type_select`: `id:int, name:string`.
|
||||
|
||||
Строки-фикстуры: `t1` (id=1, name='Запрос изменений (дельты) ЕГРЮЛ'),
|
||||
`t6` (id=6, name='Актуализация организации СОУТ').
|
||||
|
||||
## Тесты: `Select`
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной | таблица t1+t6 | 2 сущности; строгий набор: параметров нет; поля сверены со строками (id, name) |
|
||||
| 2 | граничный | пустая таблица | пустая коллекция (не null) |
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
1. имя проектов и namespaces
|
||||
2. Коментарии несущие не нужную информацибю с одной стороно сдругой не дающие никаой инофрмации для дальнейшей поддрежки кода.
|
||||
3. Не понятный репозитории RepositoryTransport.cs
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# `chk.chk_check_delete`
|
||||
|
||||
Удаление проверки по `id`.
|
||||
|
||||
| Параметр | Тип | Обяз. | Описание |
|
||||
|---|---|---|---|
|
||||
| `p_id` | int | да | идентификатор проверки |
|
||||
|
||||
**Возвращает** `int` — число удалённых строк (db-m-3).
|
||||
|
||||
## Логика/особенности
|
||||
|
||||
- NULL `p_id` → `RAISE EXCEPTION` (db-m-4). Несуществующий `id` — не ошибка: возврат 0.
|
||||
- Потомков у сущности нет; удаление родительской проверки, на которую ссылаются дочерние, даст исключение FK.
|
||||
|
||||
## Тесты
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной сценарий | существующая проверка (фикстура `TEST-`) | возврат 1; записи в таблице нет |
|
||||
| 2 | граничный случай | несуществующий `p_id` | возврат 0 |
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# `chk.chk_check_get`
|
||||
|
||||
Выборка одной проверки по идентификатору.
|
||||
|
||||
| Параметр | Тип | Обяз. | Описание |
|
||||
|---|---|---|---|
|
||||
| `p_id` | int | да | идентификатор проверки |
|
||||
|
||||
**Возвращает** `TABLE` — колонки `chk_check`: `id int`, `check_date date`, `chk_type_id int`, `chk_status_id int`, `smev_message_id text`, `rr_organization_id text`, `params jsonb`, `parent_check_id int`; не более одной строки.
|
||||
|
||||
## Логика/особенности
|
||||
|
||||
- NULL `p_id` → `RAISE EXCEPTION` (db-m-4). Несуществующий `id` — не ошибка: пустая таблица.
|
||||
|
||||
## Тесты
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной сценарий | существующая проверка (фикстура `TEST-`) | 1 строка; все колонки = значениям записи |
|
||||
| 2 | граничный случай | несуществующий `p_id` | пустая таблица |
|
||||
| 3 | исключение | NULL `p_id` | исключение «не задан p_id» |
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# `chk.chk_check_insert`
|
||||
|
||||
Создание новой проверки организаций.
|
||||
|
||||
| Параметр | Тип | Обяз. | Описание |
|
||||
|---|---|---|---|
|
||||
| `p_check_date` | date | да | день (дата) проверки |
|
||||
| `p_chk_type_id` | int | да | тип проверки (→ `chk.chk_type.id`) |
|
||||
| `p_chk_status_id` | int | да | статус проверки (→ `chk.chk_status.id`) |
|
||||
| `p_smev_message_id` | text | нет | идентификатор сообщения СМЭВ |
|
||||
| `p_rr_organization_id` | text | нет | идентификатор организации РР |
|
||||
| `p_params` | text | нет | параметры проверки (JSON); передаётся как `text`, каст в `jsonb` внутри (db-m-5) |
|
||||
| `p_parent_check_id` | int | нет | родительская проверка (→ `chk.chk_check.id`) |
|
||||
|
||||
**Возвращает** `int` — id созданной проверки.
|
||||
|
||||
## Логика/особенности
|
||||
|
||||
- Обязательные параметры проверяются в начале функции: NULL → `RAISE EXCEPTION` (db-m-4).
|
||||
- `p_params` — некорректный JSON → исключение приведения типа.
|
||||
|
||||
## Тесты
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной сценарий | все поля заполнены (фикстура `TEST-`) | id > 0; поля записи совпадают с параметрами |
|
||||
| 2 | граничный случай | только обязательные параметры | запись создана; необязательные поля NULL |
|
||||
| 3 | граничный случай | `p_params` — валидный JSON | в записи `params` = переданный JSON |
|
||||
| 4 | исключение | NULL `p_check_date` | исключение «не задан p_check_date» |
|
||||
| 5 | исключение | NULL `p_chk_type_id` | исключение «не задан p_chk_type_id» |
|
||||
| 6 | исключение | NULL `p_chk_status_id` | исключение «не задан p_chk_status_id» |
|
||||
| 7 | исключение | несуществующий `p_chk_type_id` | исключение FOREIGN KEY |
|
||||
| 8 | исключение | `p_params` — не JSON (`'не-json'`) | исключение приведения jsonb |
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
# `chk.chk_check_select`
|
||||
|
||||
Выборка проверок с необязательными фильтрами (NULL параметра = фильтр не применяется).
|
||||
|
||||
| Параметр | Тип | Обяз. | Описание |
|
||||
|---|---|---|---|
|
||||
| `p_check_date` | date | нет | фильтр по дню проверки; NULL = без фильтра |
|
||||
| `p_chk_type_id` | int | нет | фильтр по типу проверки; NULL = без фильтра |
|
||||
| `p_chk_status_id` | int | нет | фильтр по статусу проверки; NULL = без фильтра |
|
||||
| `p_rr_organization_id` | text | нет | фильтр по организации РР; NULL = без фильтра |
|
||||
|
||||
**Возвращает** `TABLE` — колонки `chk_check`: `id int`, `check_date date`, `chk_type_id int`, `chk_status_id int`, `smev_message_id text`, `rr_organization_id text`, `params jsonb`, `parent_check_id int`; сортировка по `id`.
|
||||
|
||||
## Логика/особенности
|
||||
|
||||
- Фильтры реализованы шаблоном `(p_x IS NULL OR t.x = p_x)` (db-func-7); фильтры — на корневом объекте (db-s-8).
|
||||
|
||||
## Тесты
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной сценарий | фикстура `TEST-` (3 проверки: разные дата/тип/статус/организация); все фильтры NULL | 3 строки фикстуры + существующие; все колонки заполнены |
|
||||
| 2 | основной сценарий | фильтр по `p_check_date` (дата двух фикстур) | только проверки с этой датой |
|
||||
| 3 | основной сценарий | фильтр по `p_chk_type_id` | только проверки этого типа |
|
||||
| 4 | основной сценарий | фильтр по `p_chk_status_id` | только проверки этого статуса |
|
||||
| 5 | основной сценарий | фильтр по `p_rr_organization_id` | только проверки этой организации |
|
||||
| 6 | основной сценарий | комбинированный фильтр (дата + статус) | только строки, удовлетворяющие обоим условиям |
|
||||
| 7 | граничный случай | фильтр без совпадений | пустая таблица |
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# `chk.chk_check_update`
|
||||
|
||||
Полное обновление проверки по `id` (read-modify-write, db-m-8).
|
||||
|
||||
| Параметр | Тип | Обяз. | Описание |
|
||||
|---|---|---|---|
|
||||
| `p_id` | int | да | идентификатор проверки |
|
||||
| `p_check_date` | date | да | день (дата) проверки |
|
||||
| `p_chk_type_id` | int | да | тип проверки (→ `chk.chk_type.id`) |
|
||||
| `p_chk_status_id` | int | да | статус проверки (→ `chk.chk_status.id`) |
|
||||
| `p_smev_message_id` | text | да | идентификатор сообщения СМЭВ (может быть NULL-значением) |
|
||||
| `p_rr_organization_id` | text | да | идентификатор организации РР (может быть NULL-значением) |
|
||||
| `p_params` | text | да | параметры проверки (JSON, `text` → `jsonb` внутри, db-m-5) |
|
||||
| `p_parent_check_id` | int | да | родительская проверка (может быть NULL-значением) |
|
||||
|
||||
**Возвращает** `int` — число строк, найденных по `id` и записанных (db-m-3).
|
||||
|
||||
## Логика/особенности
|
||||
|
||||
- Все поля пишутся безусловно: без `COALESCE` и `IS DISTINCT FROM` (db-m-8); NULL-семантики «не менять» нет.
|
||||
- NULL `p_id` → `RAISE EXCEPTION` (db-m-4). Несуществующий `id` — не ошибка: возврат 0.
|
||||
|
||||
## Тесты
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной сценарий | существующая проверка (фикстура `TEST-`); все поля новые | возврат 1; все поля записи = новым значениям |
|
||||
| 2 | граничный случай | несуществующий `p_id` | возврат 0; записи не изменились |
|
||||
| 3 | исключение | NULL `p_id` | исключение «не задан p_id» |
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# `chk.chk_status_select`
|
||||
|
||||
Выборка всех строк справочника статусов проверок.
|
||||
|
||||
| Параметр | Тип | Обяз. | Описание |
|
||||
|---|---|---|---|
|
||||
| — | — | — | параметров нет |
|
||||
|
||||
**Возвращает** `TABLE` — строки справочника: `id int`, `name text`, по возрастанию `id`.
|
||||
|
||||
## Логика/особенности
|
||||
|
||||
- Системный справочник (фиксированные id) — только чтение; функции редактирования не предусмотрены (c-dal-2).
|
||||
|
||||
## Тесты
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной сценарий | справочник сидирован (4 статуса, init.sql) | 4 строки; колонки id/name; сортировка по id |
|
||||
| 2 | граничный случай | строка, добавленная фикстурой `TEST-` | строка присутствует в результате |
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# `chk.chk_type_select`
|
||||
|
||||
Выборка всех строк справочника типов проверок.
|
||||
|
||||
| Параметр | Тип | Обяз. | Описание |
|
||||
|---|---|---|---|
|
||||
| — | — | — | параметров нет |
|
||||
|
||||
**Возвращает** `TABLE` — строки справочника: `id int`, `name text`, по возрастанию `id`.
|
||||
|
||||
## Логика/особенности
|
||||
|
||||
- Системный справочник (фиксированные id) — только чтение; функции редактирования не предусмотрены (c-dal-2).
|
||||
|
||||
## Тесты
|
||||
|
||||
| № | Тип | Условие | Ожидаемый результат |
|
||||
|---|---|---|---|
|
||||
| 1 | основной сценарий | справочник сидирован (6 типов, init.sql) | 6 строк; колонки id/name; сортировка по id |
|
||||
| 2 | граничный случай | строка, добавленная фикстурой `TEST-` | строка присутствует в результате |
|
||||
|
|
@ -1,16 +1,29 @@
|
|||
# Слой `chk` — функции
|
||||
# Слой `chk` — функции
|
||||
|
||||
## Список функций
|
||||
## СпиÑок функций
|
||||
|
||||
| Сущность | Функция | Статус | Параметры | Возвращает | Функция | Репозиторий | Комментарий |
|
||||
| СущноÑть | Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ | Ð¡Ñ‚Ð°Ñ‚ÑƒÑ | Параметры | Возвращает | Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ | Репозиторий | Комментарий |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| chk_type | chk_type_select | PLAN | — | TABLE — строки справочника | - | - | — |
|
||||
| chk_status | chk_status_select | PLAN | — | TABLE — строки справочника | - | - | — |
|
||||
| chk_check | chk_check_insert | PLAN | p_check_date, p_chk_type_id, p_chk_status_id, p_smev_message_id, p_rr_organization_id, p_params (JSON), p_parent_check_id | int — id проверки | - | - | — |
|
||||
| chk_check | chk_check_update | PLAN | p_id + все поля записи | int — число строк (db-m-3) | - | - | полная запись объекта (db-m-8) |
|
||||
| chk_check | chk_check_delete | PLAN | p_id | int — число строк | - | - | — |
|
||||
| chk_check | chk_check_select | PLAN | p_check_date, p_chk_type_id, p_chk_status_id, p_rr_organization_id | TABLE — строки chk_check | - | - | NULL параметра = фильтр не применяется |
|
||||
| chk_check | chk_check_get | PLAN | p_id | TABLE — строка chk_check | - | - | — |
|
||||
| chk_type | chk_type_select | DEV | — | TABLE — Ñтроки Ñправочника | CODE | REQ | код: `functions/chk_type_select.sql`; теÑты: `tests/test_chk_type_select.psql`; репозиторий: `MT.Checks/Repository/ChkTypeRepository.cs` |
|
||||
| chk_status | chk_status_select | DEV | — | TABLE — Ñтроки Ñправочника | CODE | REQ | код: `functions/chk_status_select.sql`; теÑты: `tests/test_chk_status_select.psql`; репозиторий: `MT.Checks/Repository/ChkStatusRepository.cs` |
|
||||
| chk_check | chk_check_insert | DEV | p_check_date, p_chk_type_id, p_chk_status_id, p_smev_message_id, p_rr_organization_id, p_params (JSON), p_parent_check_id | int — id проверки | CODE | REQ | код: `functions/chk_check_insert.sql`; теÑты: `tests/test_chk_check_insert.psql`; репозиторий: `MT.Checks/Repository/ChkCheckRepository.cs` |
|
||||
| chk_check | chk_check_update | DEV | p_id + вÑе Ð¿Ð¾Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи | int — чиÑло Ñтрок (db-m-3) | CODE | REQ | Ð¿Ð¾Ð»Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ объекта (db-m-8); код: `functions/chk_check_update.sql`; теÑты: `tests/test_chk_check_update.psql` |
|
||||
| chk_check | chk_check_delete | DEV | p_id | int — чиÑло Ñтрок | CODE | REQ | код: `functions/chk_check_delete.sql`; теÑты: `tests/test_chk_check_delete.psql` |
|
||||
| chk_check | chk_check_select | DEV | p_check_date, p_chk_type_id, p_chk_status_id, p_rr_organization_id | TABLE — Ñтроки chk_check | CODE | REQ | NULL параметра = фильтр не применÑетÑÑ; код: `functions/chk_check_select.sql`; теÑты: `tests/test_chk_check_select.psql` |
|
||||
| chk_check | chk_check_get | DEV | p_id | TABLE — Ñтрока chk_check | CODE | REQ | код: `functions/chk_check_get.sql`; теÑты: `tests/test_chk_check_get.psql` |
|
||||
|
||||
Функции в статусе `PLAN`: спецификации и тест-планы отсутствуют, файлы
|
||||
`func_specs/{функция}.md` создаются при переводе в `DEV` (d-db-9, d-dev-1).
|
||||
Спецификации функций и теÑÑ‚-планы: `func_specs/{функциÑ}.md` (d-db-9). Код функций:
|
||||
`functions/{ÑущноÑть}_{дейÑтвие}.sql` (db-func-4, раÑширение `.sql` — Ñоглашение
|
||||
репозиториÑ). psql-теÑты: `tests/test_{ÑущноÑть}_{дейÑтвие}.psql` (db-tst),
|
||||
Ð½ÑƒÐ¼ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€Ð¾Ðº = Ñтрокам таблиц «ТеÑты» Ñпецификаций. Выполнение теÑтов —
|
||||
на теÑтовой базе (db-tst-4): `psql -d <база> -f tests/test_*.psql`.
|
||||
|
||||
СтатуÑÑ‹ (d-dev-1, d-dev-2, d-dev-5): `СтатуÑ` = `DEV` (Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ð°Ñ‡Ð°Ñ‚Ð°);
|
||||
колонка «ФункциÑ» = `CODE` (код и теÑты напиÑаны; `DONE` — поÑле утверждениÑ
|
||||
пользователем); «Репозиторий» = `REQ`.
|
||||
|
||||
Примечание к колонке «Репозиторий» (2026-09-08, решение пользователÑ):
|
||||
unit-теÑты репозиториев не ÑоздаютÑÑ Ð²Ð¾Ð²Ñе; Ñпецификации теÑтов Ñохранены как
|
||||
Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ð¾Ð¶Ð¸Ð´Ð°ÐµÐ¼Ð¾Ð³Ð¾ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ñ â€” `1-docs/2-core/chk/repository_tests/`.
|
||||
Код репозиториев напиÑан (проект `MT.Checks`); ÑÑ‚Ð°Ñ‚ÑƒÑ `CODE` по d-dev-3
|
||||
неприменим, Ñ‚.к. требует Ð½Ð°Ð»Ð¸Ñ‡Ð¸Ñ Ñ‚ÐµÑтов.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
-- chk.chk_check_delete: удаление проверки по id.
|
||||
-- На основе: новая.
|
||||
-- Параметры: p_id — идентификатор проверки.
|
||||
-- Возвращает: int — число удалённых строк (db-m-3).
|
||||
CREATE OR REPLACE FUNCTION chk.chk_check_delete(
|
||||
p_id int
|
||||
)
|
||||
RETURNS int LANGUAGE plpgsql AS $$
|
||||
DECLARE
|
||||
v_count int;
|
||||
BEGIN
|
||||
IF p_id IS NULL THEN
|
||||
RAISE EXCEPTION 'chk.chk_check_delete: не задан p_id';
|
||||
END IF;
|
||||
|
||||
DELETE FROM chk.chk_check t
|
||||
WHERE t.id = p_id;
|
||||
|
||||
GET DIAGNOSTICS v_count = ROW_COUNT;
|
||||
RETURN v_count;
|
||||
END;
|
||||
$$;
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
-- chk.chk_check_get: выборка одной проверки по идентификатору.
|
||||
-- На основе: новая.
|
||||
-- Параметры: p_id — идентификатор проверки.
|
||||
-- Возвращает: TABLE — строка chk_check; несуществующий id — пустая таблица.
|
||||
CREATE OR REPLACE FUNCTION chk.chk_check_get(
|
||||
p_id int
|
||||
)
|
||||
RETURNS TABLE (
|
||||
id int,
|
||||
check_date date,
|
||||
chk_type_id int,
|
||||
chk_status_id int,
|
||||
smev_message_id text,
|
||||
rr_organization_id text,
|
||||
params jsonb,
|
||||
parent_check_id int
|
||||
) LANGUAGE plpgsql AS $$
|
||||
BEGIN
|
||||
IF p_id IS NULL THEN
|
||||
RAISE EXCEPTION 'chk.chk_check_get: не задан p_id';
|
||||
END IF;
|
||||
|
||||
RETURN QUERY
|
||||
SELECT t.id,
|
||||
t.check_date,
|
||||
t.chk_type_id,
|
||||
t.chk_status_id,
|
||||
t.smev_message_id,
|
||||
t.rr_organization_id,
|
||||
t.params,
|
||||
t.parent_check_id
|
||||
FROM chk.chk_check t
|
||||
WHERE t.id = p_id;
|
||||
END;
|
||||
$$;
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
-- chk.chk_check_insert: создание новой проверки организаций.
|
||||
-- На основе: новая.
|
||||
-- Параметры: p_check_date — день (дата) проверки; p_chk_type_id — тип проверки
|
||||
-- (chk.chk_type.id); p_chk_status_id — статус проверки (chk.chk_status.id);
|
||||
-- p_smev_message_id — идентификатор сообщения СМЭВ; p_rr_organization_id —
|
||||
-- идентификатор организации РР; p_params — параметры проверки (JSON, text);
|
||||
-- p_parent_check_id — родительская проверка (chk.chk_check.id).
|
||||
-- Возвращает: int — id созданной проверки.
|
||||
CREATE OR REPLACE FUNCTION chk.chk_check_insert(
|
||||
p_check_date date,
|
||||
p_chk_type_id int,
|
||||
p_chk_status_id int,
|
||||
p_smev_message_id text DEFAULT NULL,
|
||||
p_rr_organization_id text DEFAULT NULL,
|
||||
p_params text DEFAULT NULL,
|
||||
p_parent_check_id int DEFAULT NULL
|
||||
)
|
||||
RETURNS int LANGUAGE plpgsql AS $$
|
||||
DECLARE
|
||||
v_id int;
|
||||
BEGIN
|
||||
-- обязательные параметры проверяются в начале функции (db-m-4)
|
||||
IF p_check_date IS NULL THEN
|
||||
RAISE EXCEPTION 'chk.chk_check_insert: не задан p_check_date';
|
||||
END IF;
|
||||
IF p_chk_type_id IS NULL THEN
|
||||
RAISE EXCEPTION 'chk.chk_check_insert: не задан p_chk_type_id';
|
||||
END IF;
|
||||
IF p_chk_status_id IS NULL THEN
|
||||
RAISE EXCEPTION 'chk.chk_check_insert: не задан p_chk_status_id';
|
||||
END IF;
|
||||
|
||||
INSERT INTO chk.chk_check (
|
||||
check_date,
|
||||
chk_type_id,
|
||||
chk_status_id,
|
||||
smev_message_id,
|
||||
rr_organization_id,
|
||||
params,
|
||||
parent_check_id
|
||||
) VALUES (
|
||||
p_check_date,
|
||||
p_chk_type_id,
|
||||
p_chk_status_id,
|
||||
p_smev_message_id,
|
||||
p_rr_organization_id,
|
||||
p_params::jsonb, -- JSON-параметр передаётся как text, каст внутри (db-m-5)
|
||||
p_parent_check_id
|
||||
)
|
||||
RETURNING id INTO v_id;
|
||||
RETURN v_id;
|
||||
END;
|
||||
$$;
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
-- chk.chk_check_select: выборка проверок с необязательными фильтрами.
|
||||
-- На основе: новая.
|
||||
-- Параметры: p_check_date — день проверки; p_chk_type_id — тип проверки;
|
||||
-- p_chk_status_id — статус проверки; p_rr_organization_id — организация РР.
|
||||
-- NULL параметра = фильтр не применяется.
|
||||
-- Возвращает: TABLE — строки chk_check.
|
||||
CREATE OR REPLACE FUNCTION chk.chk_check_select(
|
||||
p_check_date date DEFAULT NULL,
|
||||
p_chk_type_id int DEFAULT NULL,
|
||||
p_chk_status_id int DEFAULT NULL,
|
||||
p_rr_organization_id text DEFAULT NULL
|
||||
)
|
||||
RETURNS TABLE (
|
||||
id int,
|
||||
check_date date,
|
||||
chk_type_id int,
|
||||
chk_status_id int,
|
||||
smev_message_id text,
|
||||
rr_organization_id text,
|
||||
params jsonb,
|
||||
parent_check_id int
|
||||
) LANGUAGE plpgsql AS $$
|
||||
BEGIN
|
||||
RETURN QUERY
|
||||
SELECT t.id,
|
||||
t.check_date,
|
||||
t.chk_type_id,
|
||||
t.chk_status_id,
|
||||
t.smev_message_id,
|
||||
t.rr_organization_id,
|
||||
t.params,
|
||||
t.parent_check_id
|
||||
FROM chk.chk_check t
|
||||
WHERE (p_check_date IS NULL OR t.check_date = p_check_date) -- NULL = фильтр не применяется
|
||||
AND (p_chk_type_id IS NULL OR t.chk_type_id = p_chk_type_id)
|
||||
AND (p_chk_status_id IS NULL OR t.chk_status_id = p_chk_status_id)
|
||||
AND (p_rr_organization_id IS NULL
|
||||
OR t.rr_organization_id = p_rr_organization_id)
|
||||
ORDER BY t.id;
|
||||
END;
|
||||
$$;
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
-- chk.chk_check_update: полное обновление проверки по id (read-modify-write, db-m-8).
|
||||
-- На основе: новая.
|
||||
-- Параметры: p_id — идентификатор проверки; далее все поля объекта без
|
||||
-- NULL-семантики «не менять»: p_check_date, p_chk_type_id, p_chk_status_id,
|
||||
-- p_smev_message_id, p_rr_organization_id, p_params (JSON, text),
|
||||
-- p_parent_check_id.
|
||||
-- Возвращает: int — число строк, найденных по id и записанных (db-m-3).
|
||||
CREATE OR REPLACE FUNCTION chk.chk_check_update(
|
||||
p_id int,
|
||||
p_check_date date,
|
||||
p_chk_type_id int,
|
||||
p_chk_status_id int,
|
||||
p_smev_message_id text,
|
||||
p_rr_organization_id text,
|
||||
p_params text,
|
||||
p_parent_check_id int
|
||||
)
|
||||
RETURNS int LANGUAGE plpgsql AS $$
|
||||
DECLARE
|
||||
v_count int;
|
||||
BEGIN
|
||||
IF p_id IS NULL THEN
|
||||
RAISE EXCEPTION 'chk.chk_check_update: не задан p_id';
|
||||
END IF;
|
||||
|
||||
-- полная запись объекта: без COALESCE и IS DISTINCT FROM (db-m-8)
|
||||
UPDATE chk.chk_check t
|
||||
SET check_date = p_check_date,
|
||||
chk_type_id = p_chk_type_id,
|
||||
chk_status_id = p_chk_status_id,
|
||||
smev_message_id = p_smev_message_id,
|
||||
rr_organization_id = p_rr_organization_id,
|
||||
params = p_params::jsonb, -- каст JSON из text внутри (db-m-5)
|
||||
parent_check_id = p_parent_check_id
|
||||
WHERE t.id = p_id;
|
||||
|
||||
GET DIAGNOSTICS v_count = ROW_COUNT;
|
||||
RETURN v_count;
|
||||
END;
|
||||
$$;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
-- chk.chk_status_select: выборка всех строк справочника статусов проверок.
|
||||
-- На основе: новая.
|
||||
-- Параметры: нет.
|
||||
-- Возвращает: TABLE — строки справочника chk_status (id, name), по возрастанию id.
|
||||
CREATE OR REPLACE FUNCTION chk.chk_status_select()
|
||||
RETURNS TABLE (
|
||||
id int,
|
||||
name text
|
||||
) LANGUAGE plpgsql AS $$
|
||||
BEGIN
|
||||
RETURN QUERY
|
||||
SELECT t.id,
|
||||
t.name
|
||||
FROM chk.chk_status t
|
||||
ORDER BY t.id;
|
||||
END;
|
||||
$$;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
-- chk.chk_type_select: выборка всех строк справочника типов проверок.
|
||||
-- На основе: новая.
|
||||
-- Параметры: нет.
|
||||
-- Возвращает: TABLE — строки справочника chk_type (id, name), по возрастанию id.
|
||||
CREATE OR REPLACE FUNCTION chk.chk_type_select()
|
||||
RETURNS TABLE (
|
||||
id int,
|
||||
name text
|
||||
) LANGUAGE plpgsql AS $$
|
||||
BEGIN
|
||||
RETURN QUERY
|
||||
SELECT t.id,
|
||||
t.name
|
||||
FROM chk.chk_type t
|
||||
ORDER BY t.id;
|
||||
END;
|
||||
$$;
|
||||
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
| Таблица | Тип | Набор функций | Функции | Комментарий |
|
||||
|---|---|---|---|---|
|
||||
| `chk_type` | системный справочник | chk_type_select | SELECT | функции запланированы, статус PLAN (functions.md) |
|
||||
| `chk_status` | системный справочник | chk_status_select | SELECT | функции запланированы, статус PLAN (functions.md) |
|
||||
| `chk_check` | сущность | chk_check_insert, chk_check_update, chk_check_delete, chk_check_select, chk_check_get | CRUD | функции запланированы, статус PLAN (functions.md) |
|
||||
| `chk_type` | системный справочник | chk_type_select | SELECT | функции в `functions/`, статус DEV/CODE (functions.md) |
|
||||
| `chk_status` | системный справочник | chk_status_select | SELECT | функции в `functions/`, статус DEV/CODE (functions.md) |
|
||||
| `chk_check` | сущность | chk_check_insert, chk_check_update, chk_check_delete, chk_check_select, chk_check_get | CRUD | функции в `functions/`, статус DEV/CODE (functions.md) |
|
||||
|
||||
## chk_type — типы проверок
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
-- Тесты chk.chk_check_delete — по func_specs/chk_check_delete.md (db-tst-6: № = строке таблицы).
|
||||
-- Запуск: psql -d <тестовая база> -f test_chk_check_delete.psql (одна транзакция, откат в конце).
|
||||
BEGIN;
|
||||
DO $$
|
||||
DECLARE
|
||||
v_id int;
|
||||
v_count int;
|
||||
BEGIN
|
||||
-- фикстуры TEST-: справочники вне диапазона сидированных значений
|
||||
INSERT INTO chk.chk_type (id, name) VALUES (990001, 'TEST-тип')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
INSERT INTO chk.chk_status (id, name) VALUES (990001, 'TEST-статус')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
v_id := chk.chk_check_insert(date '2026-04-01', 990001, 990001,
|
||||
'TEST-smev', 'TEST-org', NULL, NULL);
|
||||
|
||||
-- №1: существующая проверка — возврат 1, записи в таблице нет
|
||||
v_count := chk.chk_check_delete(v_id);
|
||||
SELECT count(*) INTO v_count FROM chk.chk_check WHERE id = v_id;
|
||||
IF v_count = 0 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_delete #1';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_delete #1: запись не удалена';
|
||||
END IF;
|
||||
|
||||
-- №2: несуществующий id — возврат 0
|
||||
v_count := chk.chk_check_delete(999999999);
|
||||
IF v_count = 0 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_delete #2';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_delete #2: ожидался 0, получено %', v_count;
|
||||
END IF;
|
||||
|
||||
-- удаление фикстур
|
||||
DELETE FROM chk.chk_type WHERE id = 990001;
|
||||
DELETE FROM chk.chk_status WHERE id = 990001;
|
||||
RAISE NOTICE 'ИТОГ chk.chk_check_delete: все проверки выполнены';
|
||||
END;
|
||||
$$;
|
||||
ROLLBACK;
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
-- Тесты chk.chk_check_get — по func_specs/chk_check_get.md (db-tst-6: № = строке таблицы).
|
||||
-- Запуск: psql -d <тестовая база> -f test_chk_check_get.psql (одна транзакция, откат в конце).
|
||||
BEGIN;
|
||||
DO $$
|
||||
DECLARE
|
||||
v_id int;
|
||||
v_count int;
|
||||
v_date date;
|
||||
v_smev text;
|
||||
v_org text;
|
||||
v_json jsonb;
|
||||
BEGIN
|
||||
-- фикстуры TEST-: справочники вне диапазона сидированных значений
|
||||
INSERT INTO chk.chk_type (id, name) VALUES (990001, 'TEST-тип')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
INSERT INTO chk.chk_status (id, name) VALUES (990001, 'TEST-статус')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
v_id := chk.chk_check_insert(date '2026-06-01', 990001, 990001,
|
||||
'TEST-smev', 'TEST-org', '{"a": 1}', NULL);
|
||||
|
||||
-- №1: существующий id — 1 строка, все колонки = значениям записи
|
||||
SELECT count(*), max(check_date), max(smev_message_id),
|
||||
max(rr_organization_id), max(params)
|
||||
INTO v_count, v_date, v_smev, v_org, v_json
|
||||
FROM chk.chk_check_get(v_id);
|
||||
IF v_count = 1
|
||||
AND v_date = date '2026-06-01'
|
||||
AND v_smev = 'TEST-smev'
|
||||
AND v_org = 'TEST-org'
|
||||
AND v_json = '{"a": 1}'::jsonb THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_get #1';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_get #1: поля не совпали';
|
||||
END IF;
|
||||
|
||||
-- №2: несуществующий id — пустая таблица
|
||||
SELECT count(*) INTO v_id FROM chk.chk_check_get(999999999);
|
||||
IF v_id = 0 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_get #2';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_get #2: ожидалась пустая таблица';
|
||||
END IF;
|
||||
|
||||
-- №3: NULL p_id — исключение
|
||||
BEGIN
|
||||
PERFORM chk.chk_check_get(NULL);
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_get #3: исключения не было';
|
||||
EXCEPTION
|
||||
WHEN raise_exception THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_get #3: %', SQLERRM;
|
||||
END;
|
||||
|
||||
-- удаление фикстур
|
||||
PERFORM chk.chk_check_delete(v_id);
|
||||
DELETE FROM chk.chk_type WHERE id = 990001;
|
||||
DELETE FROM chk.chk_status WHERE id = 990001;
|
||||
RAISE NOTICE 'ИТОГ chk.chk_check_get: все проверки выполнены';
|
||||
END;
|
||||
$$;
|
||||
ROLLBACK;
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
-- Тесты chk.chk_check_insert — по func_specs/chk_check_insert.md (db-tst-6: № = строке таблицы).
|
||||
-- Запуск: psql -d <тестовая база> -f test_chk_check_insert.psql (одна транзакция, откат в конце).
|
||||
BEGIN;
|
||||
DO $$
|
||||
DECLARE
|
||||
v_id int;
|
||||
v_count int;
|
||||
v_date date;
|
||||
v_json jsonb;
|
||||
v_smev text;
|
||||
v_org text;
|
||||
v_parent int;
|
||||
BEGIN
|
||||
-- фикстуры TEST-: справочники вне диапазона сидированных значений
|
||||
INSERT INTO chk.chk_type (id, name) VALUES (990001, 'TEST-тип')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
INSERT INTO chk.chk_status (id, name) VALUES (990001, 'TEST-статус')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
-- родительская проверка фикстуры
|
||||
v_parent := chk.chk_check_insert(date '2026-01-01', 990001, 990001,
|
||||
'TEST-parent-smev', 'TEST-parent-org', NULL, NULL);
|
||||
|
||||
-- №1: все поля заполнены — id > 0, поля записи совпадают с параметрами
|
||||
v_id := chk.chk_check_insert(date '2026-02-01', 990001, 990001,
|
||||
'TEST-smev-1', 'TEST-org-1', '{"a": 1}', v_parent);
|
||||
SELECT check_date, smev_message_id, rr_organization_id, params, parent_check_id
|
||||
INTO v_date, v_smev, v_org, v_json, v_parent
|
||||
FROM chk.chk_check_get(v_id);
|
||||
IF v_id > 0
|
||||
AND v_date = date '2026-02-01'
|
||||
AND v_smev = 'TEST-smev-1'
|
||||
AND v_org = 'TEST-org-1'
|
||||
AND v_json = '{"a": 1}'::jsonb
|
||||
AND v_parent IS NOT NULL THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_insert #1';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_insert #1: поля записи не совпали';
|
||||
END IF;
|
||||
|
||||
-- №2: только обязательные параметры — необязательные поля NULL
|
||||
v_id := chk.chk_check_insert(date '2026-02-02', 990001, 990001);
|
||||
SELECT smev_message_id, rr_organization_id, params, parent_check_id
|
||||
INTO v_smev, v_org, v_json, v_parent
|
||||
FROM chk.chk_check_get(v_id);
|
||||
IF v_id > 0 AND v_smev IS NULL AND v_org IS NULL AND v_json IS NULL AND v_parent IS NULL THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_insert #2';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_insert #2: необязательные поля не NULL';
|
||||
END IF;
|
||||
|
||||
-- №3: валидный JSON в p_params — сохранён как есть
|
||||
v_id := chk.chk_check_insert(date '2026-02-03', 990001, 990001,
|
||||
NULL, NULL, '{"org_count": 5, "req_count": 3}', NULL);
|
||||
SELECT params INTO v_json FROM chk.chk_check_get(v_id);
|
||||
IF v_json = '{"org_count": 5, "req_count": 3}'::jsonb THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_insert #3';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_insert #3: JSON не совпал';
|
||||
END IF;
|
||||
|
||||
-- №4: NULL p_check_date — исключение
|
||||
BEGIN
|
||||
PERFORM chk.chk_check_insert(NULL, 990001, 990001);
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_insert #4: исключения не было';
|
||||
EXCEPTION
|
||||
WHEN raise_exception THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_insert #4: %', SQLERRM;
|
||||
END;
|
||||
|
||||
-- №5: NULL p_chk_type_id — исключение
|
||||
BEGIN
|
||||
PERFORM chk.chk_check_insert(date '2026-02-04', NULL, 990001);
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_insert #5: исключения не было';
|
||||
EXCEPTION
|
||||
WHEN raise_exception THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_insert #5: %', SQLERRM;
|
||||
END;
|
||||
|
||||
-- №6: NULL p_chk_status_id — исключение
|
||||
BEGIN
|
||||
PERFORM chk.chk_check_insert(date '2026-02-04', 990001, NULL);
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_insert #6: исключения не было';
|
||||
EXCEPTION
|
||||
WHEN raise_exception THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_insert #6: %', SQLERRM;
|
||||
END;
|
||||
|
||||
-- №7: несуществующий тип — исключение FOREIGN KEY
|
||||
BEGIN
|
||||
PERFORM chk.chk_check_insert(date '2026-02-04', 999999, 990001);
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_insert #7: исключения не было';
|
||||
EXCEPTION
|
||||
WHEN foreign_key_violation THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_insert #7';
|
||||
END;
|
||||
|
||||
-- №8: некорректный JSON — исключение приведения
|
||||
BEGIN
|
||||
PERFORM chk.chk_check_insert(date '2026-02-04', 990001, 990001,
|
||||
NULL, NULL, 'не-json', NULL);
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_insert #8: исключения не было';
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_insert #8: %', SQLERRM;
|
||||
END;
|
||||
|
||||
-- удаление фикстур (родитель каскадом не удаляет — дочерние удаляем явно)
|
||||
PERFORM chk.chk_check_delete(v_parent);
|
||||
DELETE FROM chk.chk_check WHERE rr_organization_id LIKE 'TEST-%';
|
||||
DELETE FROM chk.chk_type WHERE id = 990001;
|
||||
DELETE FROM chk.chk_status WHERE id = 990001;
|
||||
RAISE NOTICE 'ИТОГ chk.chk_check_insert: все проверки выполнены';
|
||||
END;
|
||||
$$;
|
||||
ROLLBACK;
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
-- Тесты chk.chk_check_select — по func_specs/chk_check_select.md (db-tst-6: № = строке таблицы).
|
||||
-- Запуск: psql -d <тестовая база> -f test_chk_check_select.psql (одна транзакция, откат в конце).
|
||||
BEGIN;
|
||||
DO $$
|
||||
DECLARE
|
||||
v_id1 int;
|
||||
v_id2 int;
|
||||
v_id3 int;
|
||||
v_count int;
|
||||
BEGIN
|
||||
-- фикстуры TEST-: справочники вне диапазона сидированных значений
|
||||
INSERT INTO chk.chk_type (id, name) VALUES (990001, 'TEST-тип 1')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
INSERT INTO chk.chk_type (id, name) VALUES (990002, 'TEST-тип 2')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
INSERT INTO chk.chk_status (id, name) VALUES (990001, 'TEST-статус 1')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
INSERT INTO chk.chk_status (id, name) VALUES (990002, 'TEST-статус 2')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
-- три проверки: 1 и 2 — одна дата/тип/статус, 3 — все значения другие
|
||||
v_id1 := chk.chk_check_insert(date '2026-05-01', 990001, 990001,
|
||||
'TEST-smev-1', 'TEST-org-1', NULL, NULL);
|
||||
v_id2 := chk.chk_check_insert(date '2026-05-01', 990001, 990001,
|
||||
'TEST-smev-2', 'TEST-org-2', NULL, NULL);
|
||||
v_id3 := chk.chk_check_insert(date '2026-05-02', 990002, 990002,
|
||||
'TEST-smev-3', 'TEST-org-3', NULL, NULL);
|
||||
|
||||
-- №1: все фильтры NULL — все 3 строки фикстуры, все колонки
|
||||
SELECT count(*) INTO v_count
|
||||
FROM chk.chk_check_select(NULL, NULL, NULL, NULL)
|
||||
WHERE id IN (v_id1, v_id2, v_id3);
|
||||
IF v_count = 3 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_select #1';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_select #1: найдено % из 3', v_count;
|
||||
END IF;
|
||||
|
||||
-- №2: фильтр по дате — только строки с 2026-05-01
|
||||
SELECT count(*) INTO v_count
|
||||
FROM chk.chk_check_select(date '2026-05-01', NULL, NULL, NULL)
|
||||
WHERE id IN (v_id1, v_id2, v_id3);
|
||||
IF v_count = 2 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_select #2';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_select #2: найдено %, ожидалось 2', v_count;
|
||||
END IF;
|
||||
|
||||
-- №3: фильтр по типу
|
||||
SELECT count(*) INTO v_count
|
||||
FROM chk.chk_check_select(NULL, 990001, NULL, NULL)
|
||||
WHERE id IN (v_id1, v_id2, v_id3);
|
||||
IF v_count = 2 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_select #3';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_select #3: найдено %, ожидалось 2', v_count;
|
||||
END IF;
|
||||
|
||||
-- №4: фильтр по статусу
|
||||
SELECT count(*) INTO v_count
|
||||
FROM chk.chk_check_select(NULL, NULL, 990002, NULL)
|
||||
WHERE id IN (v_id1, v_id2, v_id3);
|
||||
IF v_count = 1 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_select #4';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_select #4: найдено %, ожидалось 1', v_count;
|
||||
END IF;
|
||||
|
||||
-- №5: фильтр по организации РР
|
||||
SELECT count(*) INTO v_count
|
||||
FROM chk.chk_check_select(NULL, NULL, NULL, 'TEST-org-2')
|
||||
WHERE id IN (v_id1, v_id2, v_id3);
|
||||
IF v_count = 1 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_select #5';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_select #5: найдено %, ожидалось 1', v_count;
|
||||
END IF;
|
||||
|
||||
-- №6: комбинированный фильтр (дата + статус) — только строка 3
|
||||
SELECT count(*) INTO v_count
|
||||
FROM chk.chk_check_select(date '2026-05-02', NULL, 990002, NULL)
|
||||
WHERE id IN (v_id1, v_id2, v_id3);
|
||||
IF v_count = 1 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_select #6';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_select #6: найдено %, ожидалось 1', v_count;
|
||||
END IF;
|
||||
|
||||
-- №7: фильтр без совпадений — пустая таблица
|
||||
SELECT count(*) INTO v_count
|
||||
FROM chk.chk_check_select(date '2026-05-02', NULL, 990001, NULL);
|
||||
IF v_count = 0 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_select #7';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_select #7: найдено %, ожидалось 0', v_count;
|
||||
END IF;
|
||||
|
||||
-- удаление фикстур
|
||||
PERFORM chk.chk_check_delete(v_id1);
|
||||
PERFORM chk.chk_check_delete(v_id2);
|
||||
PERFORM chk.chk_check_delete(v_id3);
|
||||
DELETE FROM chk.chk_type WHERE id IN (990001, 990002);
|
||||
DELETE FROM chk.chk_status WHERE id IN (990001, 990002);
|
||||
RAISE NOTICE 'ИТОГ chk.chk_check_select: все проверки выполнены';
|
||||
END;
|
||||
$$;
|
||||
ROLLBACK;
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
-- Тесты chk.chk_check_update — по func_specs/chk_check_update.md (db-tst-6: № = строке таблицы).
|
||||
-- Запуск: psql -d <тестовая база> -f test_chk_check_update.psql (одна транзакция, откат в конце).
|
||||
BEGIN;
|
||||
DO $$
|
||||
DECLARE
|
||||
v_id int;
|
||||
v_count int;
|
||||
v_date date;
|
||||
v_json jsonb;
|
||||
v_smev text;
|
||||
v_org text;
|
||||
v_type int;
|
||||
v_status int;
|
||||
BEGIN
|
||||
-- фикстуры TEST-: справочники вне диапазона сидированных значений
|
||||
INSERT INTO chk.chk_type (id, name) VALUES (990001, 'TEST-тип до')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
INSERT INTO chk.chk_type (id, name) VALUES (990002, 'TEST-тип после')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
INSERT INTO chk.chk_status (id, name) VALUES (990001, 'TEST-статус до')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
INSERT INTO chk.chk_status (id, name) VALUES (990002, 'TEST-статус после')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
v_id := chk.chk_check_insert(date '2026-03-01', 990001, 990001,
|
||||
'TEST-smev-до', 'TEST-org-до', '{"a": 1}', NULL);
|
||||
|
||||
-- №1: полное обновление всех полей — возврат 1, все поля = новым значениям
|
||||
v_count := chk.chk_check_update(v_id, date '2026-03-02', 990002, 990002,
|
||||
'TEST-smev-после', 'TEST-org-после', '{"b": 2}', NULL);
|
||||
SELECT check_date, chk_type_id, chk_status_id, smev_message_id,
|
||||
rr_organization_id, params
|
||||
INTO v_date, v_type, v_status, v_smev, v_org, v_json
|
||||
FROM chk.chk_check_get(v_id);
|
||||
IF v_count = 1
|
||||
AND v_date = date '2026-03-02'
|
||||
AND v_type = 990002
|
||||
AND v_status = 990002
|
||||
AND v_smev = 'TEST-smev-после'
|
||||
AND v_org = 'TEST-org-после'
|
||||
AND v_json = '{"b": 2}'::jsonb THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_update #1';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_update #1: поля не совпали';
|
||||
END IF;
|
||||
|
||||
-- №2: несуществующий id — возврат 0
|
||||
v_count := chk.chk_check_update(999999999, date '2026-03-02', 990002, 990002,
|
||||
NULL, NULL, NULL, NULL);
|
||||
IF v_count = 0 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_update #2';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_update #2: ожидался 0, получено %', v_count;
|
||||
END IF;
|
||||
|
||||
-- №3: NULL p_id — исключение
|
||||
BEGIN
|
||||
PERFORM chk.chk_check_update(NULL, date '2026-03-02', 990002, 990002,
|
||||
NULL, NULL, NULL, NULL);
|
||||
RAISE EXCEPTION 'FAIL chk.chk_check_update #3: исключения не было';
|
||||
EXCEPTION
|
||||
WHEN raise_exception THEN
|
||||
RAISE NOTICE 'PASS chk.chk_check_update #3: %', SQLERRM;
|
||||
END;
|
||||
|
||||
-- удаление фикстур
|
||||
PERFORM chk.chk_check_delete(v_id);
|
||||
DELETE FROM chk.chk_type WHERE id IN (990001, 990002);
|
||||
DELETE FROM chk.chk_status WHERE id IN (990001, 990002);
|
||||
RAISE NOTICE 'ИТОГ chk.chk_check_update: все проверки выполнены';
|
||||
END;
|
||||
$$;
|
||||
ROLLBACK;
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
-- Тесты chk.chk_status_select — по func_specs/chk_status_select.md (db-tst-6: № = строке таблицы).
|
||||
-- Запуск: psql -d <тестовая база> -f test_chk_status_select.psql (одна транзакция, откат в конце).
|
||||
BEGIN;
|
||||
DO $$
|
||||
DECLARE
|
||||
v_count int;
|
||||
BEGIN
|
||||
-- фикстура TEST- (id 990001 — вне диапазона сидированных значений)
|
||||
INSERT INTO chk.chk_status (id, name) VALUES (990001, 'TEST-статус проверки')
|
||||
ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name;
|
||||
|
||||
-- №1: сидированный справочник — не меньше 4 строк, сортировка по id
|
||||
SELECT count(*) INTO v_count FROM chk.chk_status_select();
|
||||
IF v_count >= 4 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_status_select #1';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_status_select #1: строк %, ожидалось >= 4', v_count;
|
||||
END IF;
|
||||
|
||||
-- №2: фикстура TEST- присутствует в результате
|
||||
SELECT count(*) INTO v_count FROM chk.chk_status_select() WHERE id = 990001;
|
||||
IF v_count = 1 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_status_select #2';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_status_select #2: фикстура не найдена';
|
||||
END IF;
|
||||
|
||||
-- удаление фикстур
|
||||
DELETE FROM chk.chk_status WHERE id = 990001;
|
||||
RAISE NOTICE 'ИТОГ chk.chk_status_select: все проверки выполнены';
|
||||
END;
|
||||
$$;
|
||||
ROLLBACK;
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
-- Тесты chk.chk_type_select — по func_specs/chk_type_select.md (db-tst-6: № = строке таблицы).
|
||||
-- Запуск: psql -d <тестовая база> -f test_chk_type_select.psql (одна транзакция, откат в конце).
|
||||
BEGIN;
|
||||
DO $$
|
||||
DECLARE
|
||||
v_count int;
|
||||
BEGIN
|
||||
-- фикстура TEST- (id 990001 — вне диапазона сидированных значений)
|
||||
INSERT INTO chk.chk_type (id, name) VALUES (990001, 'TEST-тип проверки')
|
||||
ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name;
|
||||
|
||||
-- №1: сидированный справочник — не меньше 6 строк, сортировка по id
|
||||
SELECT count(*) INTO v_count FROM chk.chk_type_select();
|
||||
IF v_count >= 6 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_type_select #1';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_type_select #1: строк %, ожидалось >= 6', v_count;
|
||||
END IF;
|
||||
|
||||
-- №2: фикстура TEST- присутствует в результате
|
||||
SELECT count(*) INTO v_count FROM chk.chk_type_select() WHERE id = 990001;
|
||||
IF v_count = 1 THEN
|
||||
RAISE NOTICE 'PASS chk.chk_type_select #2';
|
||||
ELSE
|
||||
RAISE EXCEPTION 'FAIL chk.chk_type_select #2: фикстура не найдена';
|
||||
END IF;
|
||||
|
||||
-- удаление фикстур
|
||||
DELETE FROM chk.chk_type WHERE id = 990001;
|
||||
RAISE NOTICE 'ИТОГ chk.chk_type_select: все проверки выполнены';
|
||||
END;
|
||||
$$;
|
||||
ROLLBACK;
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
{
|
||||
"Layer": "chk",
|
||||
"Schemas": [
|
||||
"chk"
|
||||
],
|
||||
"BuiltAt": "2026-09-08 18:36",
|
||||
"SourceHashes": {
|
||||
"DB\\chk\\functions\\chk_check_delete.sql": "ee9f93c78bf21ec9d3a7e46d097a6384e5f2bac9b7329dcb2b9e414356102744",
|
||||
"DB\\chk\\functions\\chk_check_get.sql": "586b744830852e2791b976370841098f8b144882e6fe0d64c25aea2cbce6d539",
|
||||
"DB\\chk\\functions\\chk_check_insert.sql": "f5aaa65daf3ae7b10485100398da3633c7646b025460130dba7500fe94b27624",
|
||||
"DB\\chk\\functions\\chk_check_select.sql": "466e9aecb0aa1c2f92448c0f41a608a1212700d474f25d9b35f31c0fbf9ac795",
|
||||
"DB\\chk\\functions\\chk_check_update.sql": "7c9b84c57c6333edc861f369fbf94cc3d6261dce31c6e86d573bc99687ea6a50",
|
||||
"DB\\chk\\functions\\chk_status_select.sql": "bf12313d3be965031abb3946b4ea3a9f3ec1ff0c5ada1272704ea5e0c1ef4b0c",
|
||||
"DB\\chk\\functions\\chk_type_select.sql": "90367b389c919971123236a51d6dd560219cfce08553633c29c7c27d9adb7677"
|
||||
},
|
||||
"Entities": {
|
||||
"ChkCheck": {
|
||||
"Table": "chk.chk_check",
|
||||
"Kind": "plain",
|
||||
"Children": [],
|
||||
"Functions": {
|
||||
"delete": {
|
||||
"Name": "chk.chk_check_delete",
|
||||
"SourceFile": "DB\\chk\\functions\\chk_check_delete.sql",
|
||||
"Params": {
|
||||
"p_id": "int"
|
||||
},
|
||||
"Returns": {
|
||||
"form": "scalar",
|
||||
"type": "int"
|
||||
}
|
||||
},
|
||||
"get": {
|
||||
"Name": "chk.chk_check_get",
|
||||
"SourceFile": "DB\\chk\\functions\\chk_check_get.sql",
|
||||
"Params": {
|
||||
"p_id": "int"
|
||||
},
|
||||
"Returns": {
|
||||
"form": "table",
|
||||
"columns": {
|
||||
"id": "int",
|
||||
"check_date": "date",
|
||||
"chk_type_id": "int",
|
||||
"chk_status_id": "int",
|
||||
"smev_message_id": "text",
|
||||
"rr_organization_id": "text",
|
||||
"params": "jsonb",
|
||||
"parent_check_id": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"insert": {
|
||||
"Name": "chk.chk_check_insert",
|
||||
"SourceFile": "DB\\chk\\functions\\chk_check_insert.sql",
|
||||
"Params": {
|
||||
"p_check_date": "date",
|
||||
"p_chk_type_id": "int",
|
||||
"p_chk_status_id": "int",
|
||||
"p_smev_message_id": "text",
|
||||
"p_rr_organization_id": "text",
|
||||
"p_params": "text",
|
||||
"p_parent_check_id": "int"
|
||||
},
|
||||
"Returns": {
|
||||
"form": "scalar",
|
||||
"type": "int"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"Name": "chk.chk_check_select",
|
||||
"SourceFile": "DB\\chk\\functions\\chk_check_select.sql",
|
||||
"Params": {
|
||||
"p_check_date": "date",
|
||||
"p_chk_type_id": "int",
|
||||
"p_chk_status_id": "int",
|
||||
"p_rr_organization_id": "text"
|
||||
},
|
||||
"Returns": {
|
||||
"form": "table",
|
||||
"columns": {
|
||||
"id": "int",
|
||||
"check_date": "date",
|
||||
"chk_type_id": "int",
|
||||
"chk_status_id": "int",
|
||||
"smev_message_id": "text",
|
||||
"rr_organization_id": "text",
|
||||
"params": "jsonb",
|
||||
"parent_check_id": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"Name": "chk.chk_check_update",
|
||||
"SourceFile": "DB\\chk\\functions\\chk_check_update.sql",
|
||||
"Params": {
|
||||
"p_id": "int",
|
||||
"p_check_date": "date",
|
||||
"p_chk_type_id": "int",
|
||||
"p_chk_status_id": "int",
|
||||
"p_smev_message_id": "text",
|
||||
"p_rr_organization_id": "text",
|
||||
"p_params": "text",
|
||||
"p_parent_check_id": "int"
|
||||
},
|
||||
"Returns": {
|
||||
"form": "scalar",
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ChkStatus": {
|
||||
"Table": "chk.chk_status",
|
||||
"Kind": "plain",
|
||||
"Children": [],
|
||||
"Functions": {
|
||||
"select": {
|
||||
"Name": "chk.chk_status_select",
|
||||
"SourceFile": "DB\\chk\\functions\\chk_status_select.sql",
|
||||
"Params": {},
|
||||
"Returns": {
|
||||
"form": "table",
|
||||
"columns": {
|
||||
"id": "int",
|
||||
"name": "text"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ChkType": {
|
||||
"Table": "chk.chk_type",
|
||||
"Kind": "plain",
|
||||
"Children": [],
|
||||
"Functions": {
|
||||
"select": {
|
||||
"Name": "chk.chk_type_select",
|
||||
"SourceFile": "DB\\chk\\functions\\chk_type_select.sql",
|
||||
"Params": {},
|
||||
"Returns": {
|
||||
"form": "table",
|
||||
"columns": {
|
||||
"id": "int",
|
||||
"name": "text"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,4 +28,5 @@
|
|||
## План миграции
|
||||
|
||||
1. `psql -d <база> -f chk/init/init.sql` — создание схемы, таблиц, сидирование справочников.
|
||||
2. Функции слоя — по `chk/functions.md` (все в статусе `PLAN`), реализация — отдельными задачами.
|
||||
2. `psql -d <база> -f chk/functions/chk_*.sql` — создание функций слоя (спецификации: `chk/func_specs/`).
|
||||
3. `psql -d <тестовая база> -f chk/tests/test_*.psql` — тесты функций (db-tst, каждая — одна транзакция с откатом).
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
<Solution>
|
||||
<Project Path="MT.Checks/MT.Checks.csproj" />
|
||||
</Solution>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
namespace MT.Checks.Domain;
|
||||
|
||||
/// <summary>
|
||||
/// Проверка организаций (chk.chk_check). Колонка params хранитÑÑ Ð² jsonb,
|
||||
/// в домене передаётÑÑ Ñтрокой JSON.
|
||||
/// </summary>
|
||||
public class ChkCheck
|
||||
{
|
||||
/// <summary>Идентификатор проверки.</summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>День (дата) проверки.</summary>
|
||||
public DateTime CheckDate { get; set; }
|
||||
|
||||
/// <summary>Тип проверки — ключ chk.chk_type.</summary>
|
||||
public int TypeId { get; set; }
|
||||
|
||||
/// <summary>Объект Ñправочника типов; заполнÑетÑÑ Ð¿Ñ€Ð¸ÐºÐ»Ð°Ð´Ð½Ñ‹Ð¼ кодом при необходимоÑти.</summary>
|
||||
public ChkType? Type { get; set; }
|
||||
|
||||
/// <summary>Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ — ключ chk.chk_status.</summary>
|
||||
public int StatusId { get; set; }
|
||||
|
||||
/// <summary>Объект Ñправочника ÑтатуÑов; заполнÑетÑÑ Ð¿Ñ€Ð¸ÐºÐ»Ð°Ð´Ð½Ñ‹Ð¼ кодом при необходимоÑти.</summary>
|
||||
public ChkStatus? Status { get; set; }
|
||||
|
||||
/// <summary>Идентификатор ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¡ÐœÐÐ’.</summary>
|
||||
public string SmevMessageId { get; set; } = "";
|
||||
|
||||
/// <summary>Идентификатор организации РР.</summary>
|
||||
public string RrOrganizationId { get; set; } = "";
|
||||
|
||||
/// <summary>Параметры проверки — JSON (результаты проверок, ÑоÑтав не фикÑирован).</summary>
|
||||
public string Params { get; set; } = "";
|
||||
|
||||
/// <summary>РодительÑÐºÐ°Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ°; null — ÐºÐ¾Ñ€Ð½ÐµÐ²Ð°Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ°.</summary>
|
||||
public int? ParentCheckId { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
namespace MT.Checks.Domain;
|
||||
|
||||
/// <summary>
|
||||
/// Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ (Ñправочник chk.chk_status, фикÑированные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ â€” Ñм. init.sql).
|
||||
/// </summary>
|
||||
public class ChkStatus
|
||||
{
|
||||
/// <summary>Идентификатор ÑтатуÑа.</summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>Ðаименование ÑтатуÑа проверки.</summary>
|
||||
public string Name { get; set; } = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Коды ÑтатуÑов проверок (chk.chk_status); Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ â€” DB/chk/init/init.sql.
|
||||
/// </summary>
|
||||
public static class ChkStatuses
|
||||
{
|
||||
/// <summary>Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½.</summary>
|
||||
public const int RequestSent = 1;
|
||||
|
||||
/// <summary>Ответ получен.</summary>
|
||||
public const int ResponseReceived = 2;
|
||||
|
||||
/// <summary>Ответ уÑпешно обработан.</summary>
|
||||
public const int ResponseProcessed = 3;
|
||||
|
||||
/// <summary>Ошибка при обработке.</summary>
|
||||
public const int ProcessingError = 4;
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
namespace MT.Checks.Domain;
|
||||
|
||||
/// <summary>
|
||||
/// Тип проверки (Ñправочник chk.chk_type, фикÑированные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ â€” Ñм. init.sql).
|
||||
/// </summary>
|
||||
public class ChkType
|
||||
{
|
||||
/// <summary>Идентификатор типа.</summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>Ðаименование типа проверки.</summary>
|
||||
public string Name { get; set; } = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Коды типов проверок (chk.chk_type); Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ â€” DB/chk/init/init.sql.
|
||||
/// </summary>
|
||||
public static class ChkTypes
|
||||
{
|
||||
/// <summary>Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹ (дельты) ЕГРЮЛ.</summary>
|
||||
public const int EgrulDelta = 1;
|
||||
|
||||
/// <summary>Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹ (дельты) ЕГРИП.</summary>
|
||||
public const int EgripDelta = 2;
|
||||
|
||||
/// <summary>Отправка запроÑа в ЕГРЮЛ.</summary>
|
||||
public const int EgrulRequest = 3;
|
||||
|
||||
/// <summary>Отправка запроÑа в ЕГРИП.</summary>
|
||||
public const int EgripRequest = 4;
|
||||
|
||||
/// <summary>ÐÐºÑ‚ÑƒÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ð¸ ОТ.</summary>
|
||||
public const int OtActualization = 5;
|
||||
|
||||
/// <summary>ÐÐºÑ‚ÑƒÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ð¸ СОУТ.</summary>
|
||||
public const int SoutActualization = 6;
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Транспорт хранимых функций: Kit.Helpers (проект Kit.Core, net8.0). -->
|
||||
<ProjectReference Include="..\..\..\Kit\Kit.Core\Kit.Core\Kit.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
namespace MT.Checks.Repository
|
||||
{
|
||||
using Kit.Helpers.SqlHelperAbstract;
|
||||
using MT.Checks.Domain;
|
||||
using MT.Checks.Repository.Filter;
|
||||
|
||||
/// <summary>
|
||||
/// Репозиторий проверок организаций: чтение и запиÑÑŒ через хранимые функции Ñхемы chk.
|
||||
/// Транзакцию из неÑкольких вызовов Ñобирает вызывающий код.
|
||||
/// </summary>
|
||||
public interface IChkCheckRepository
|
||||
{
|
||||
/// <summary>Создаёт проверку (chk.chk_check_insert); возвращает id новой запиÑи.</summary>
|
||||
int Insert(ChkCheck item);
|
||||
|
||||
/// <summary>ЗапиÑывает проверку целиком по Id (chk.chk_check_update);
|
||||
/// возвращает чиÑло запиÑанных Ñтрок. ИзменÑемый объект читаетÑÑ Ð·Ð°Ñ€Ð°Ð½ÐµÐµ
|
||||
/// методом Get (read-modify-write).</summary>
|
||||
int Update(ChkCheck item);
|
||||
|
||||
/// <summary>УдалÑет проверку по Id (chk.chk_check_delete);
|
||||
/// возвращает чиÑло удалённых Ñтрок.</summary>
|
||||
int Delete(int id);
|
||||
|
||||
/// <summary>Выбирает проверки по уÑловиÑм фильтра (chk.chk_check_select);
|
||||
/// null ÑвойÑтва фильтра = уÑловие не применÑетÑÑ.</summary>
|
||||
IList<ChkCheck> Select(ChkCheckFilter filter);
|
||||
|
||||
/// <summary>Возвращает проверку по Id (chk.chk_check_get); null — запиÑÑŒ не найдена.</summary>
|
||||
ChkCheck? Get(int id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// РеализациÑ: каждый метод вызывает ровно одну хранимую функцию; имена
|
||||
/// параметров вызова Ñовпадают Ñ Ð¸Ð¼ÐµÐ½Ð°Ð¼Ð¸ параметров функции (p_*).
|
||||
/// </summary>
|
||||
public class ChkCheckRepository : IChkCheckRepository
|
||||
{
|
||||
private readonly IConnectionString _connectionString;
|
||||
|
||||
/// <summary>Подключение передаётÑÑ Ñнаружи и не открываетÑÑ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸ÐµÐ¼.</summary>
|
||||
public ChkCheckRepository(IConnectionString connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
|
||||
/// <summary>Создаёт проверку (chk.chk_check_insert); возвращает id новой запиÑи.</summary>
|
||||
public int Insert(ChkCheck item)
|
||||
{
|
||||
return _connectionString.PrepareExecute<int>("chk.chk_check_insert")
|
||||
.AsStoredProcedure()
|
||||
.AddParameter("p_check_date", item.CheckDate)
|
||||
.AddParameter("p_chk_type_id", item.TypeId)
|
||||
.AddParameter("p_chk_status_id", item.StatusId)
|
||||
.AddParameter("p_smev_message_id", item.SmevMessageId)
|
||||
.AddParameter("p_rr_organization_id", item.RrOrganizationId)
|
||||
.AddParameter("p_params", item.Params)
|
||||
.AddParameterNullable("p_parent_check_id", item.ParentCheckId)
|
||||
.ExecuteScalar();
|
||||
}
|
||||
|
||||
/// <summary>ЗапиÑывает проверку целиком по Id (chk.chk_check_update);
|
||||
/// возвращает чиÑло запиÑанных Ñтрок. ИзменÑемый объект читаетÑÑ Ð·Ð°Ñ€Ð°Ð½ÐµÐµ
|
||||
/// методом Get (read-modify-write).</summary>
|
||||
public int Update(ChkCheck item)
|
||||
{
|
||||
if (item.Id == 0)
|
||||
{
|
||||
throw new ArgumentException("ChkCheckRepository.Update: не задан идентификатор запиÑи (Id = 0)");
|
||||
}
|
||||
|
||||
return _connectionString.PrepareExecute<int>("chk.chk_check_update")
|
||||
.AsStoredProcedure()
|
||||
.AddParameter("p_id", item.Id)
|
||||
.AddParameter("p_check_date", item.CheckDate)
|
||||
.AddParameter("p_chk_type_id", item.TypeId)
|
||||
.AddParameter("p_chk_status_id", item.StatusId)
|
||||
.AddParameter("p_smev_message_id", item.SmevMessageId)
|
||||
.AddParameter("p_rr_organization_id", item.RrOrganizationId)
|
||||
.AddParameter("p_params", item.Params)
|
||||
.AddParameterNullable("p_parent_check_id", item.ParentCheckId)
|
||||
.ExecuteScalar();
|
||||
}
|
||||
|
||||
/// <summary>УдалÑет проверку по Id (chk.chk_check_delete);
|
||||
/// возвращает чиÑло удалённых Ñтрок.</summary>
|
||||
public int Delete(int id)
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
throw new ArgumentException("ChkCheckRepository.Delete: не задан идентификатор запиÑи (id = 0)");
|
||||
}
|
||||
|
||||
return _connectionString.PrepareExecute<int>("chk.chk_check_delete")
|
||||
.AsStoredProcedure()
|
||||
.AddParameter("p_id", id)
|
||||
.ExecuteScalar();
|
||||
}
|
||||
|
||||
/// <summary>Выбирает проверки по уÑловиÑм фильтра (chk.chk_check_select);
|
||||
/// null ÑвойÑтва фильтра = уÑловие не применÑетÑÑ.</summary>
|
||||
public IList<ChkCheck> Select(ChkCheckFilter filter)
|
||||
{
|
||||
filter ??= new ChkCheckFilter();
|
||||
|
||||
return _connectionString.PrepareExecute<ChkCheck>("chk.chk_check_select")
|
||||
.AsStoredProcedure()
|
||||
.AddParameterNullable("p_check_date", filter.CheckDate)
|
||||
.AddParameterNullable("p_chk_type_id", filter.TypeId)
|
||||
.AddParameterNullable("p_chk_status_id", filter.StatusId)
|
||||
.AddParameterNullable("p_rr_organization_id", filter.RrOrganizationId)
|
||||
.AddConverter((record, list) =>
|
||||
{
|
||||
var entity = new ChkCheck
|
||||
{
|
||||
Id = record.Get<int>("id"),
|
||||
CheckDate = record.Get<DateTime>("check_date"),
|
||||
TypeId = record.Get<int>("chk_type_id"),
|
||||
StatusId = record.Get<int>("chk_status_id"),
|
||||
SmevMessageId = record.GetN<string>("smev_message_id") ?? string.Empty,
|
||||
RrOrganizationId = record.GetN<string>("rr_organization_id") ?? string.Empty,
|
||||
Params = record.GetN<string>("params") ?? string.Empty,
|
||||
ParentCheckId = record.GetN<int?>("parent_check_id"),
|
||||
};
|
||||
list.Add(entity);
|
||||
})
|
||||
.ExecuteSelectMany()
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>Возвращает проверку по Id (chk.chk_check_get); null — запиÑÑŒ не найдена.</summary>
|
||||
public ChkCheck? Get(int id)
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
throw new ArgumentException("ChkCheckRepository.Get: не задан идентификатор запиÑи (id = 0)");
|
||||
}
|
||||
|
||||
IList<ChkCheck> result = _connectionString.PrepareExecute<ChkCheck>("chk.chk_check_get")
|
||||
.AsStoredProcedure()
|
||||
.AddParameter("p_id", id)
|
||||
.AddConverter((record, list) =>
|
||||
{
|
||||
var entity = new ChkCheck
|
||||
{
|
||||
Id = record.Get<int>("id"),
|
||||
CheckDate = record.Get<DateTime>("check_date"),
|
||||
TypeId = record.Get<int>("chk_type_id"),
|
||||
StatusId = record.Get<int>("chk_status_id"),
|
||||
SmevMessageId = record.GetN<string>("smev_message_id") ?? string.Empty,
|
||||
RrOrganizationId = record.GetN<string>("rr_organization_id") ?? string.Empty,
|
||||
Params = record.GetN<string>("params") ?? string.Empty,
|
||||
ParentCheckId = record.GetN<int?>("parent_check_id"),
|
||||
};
|
||||
list.Add(entity);
|
||||
})
|
||||
.ExecuteSelectMany()
|
||||
.ToList();
|
||||
|
||||
return result.Count > 0 ? result[0] : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
namespace MT.Checks.Repository
|
||||
{
|
||||
using Kit.Helpers.SqlHelperAbstract;
|
||||
using MT.Checks.Domain;
|
||||
|
||||
/// <summary>Репозиторий Ñправочника ÑтатуÑов проверок (только чтение).</summary>
|
||||
public interface IChkStatusRepository
|
||||
{
|
||||
/// <summary>Возвращает вÑе Ñтроки Ñправочника (chk.chk_status_select).</summary>
|
||||
IList<ChkStatus> Select();
|
||||
}
|
||||
|
||||
/// <summary>РеализациÑ: ÐºÐ°Ð¶Ð´Ð°Ñ Ð²Ñ‹Ð±Ð¾Ñ€ÐºÐ° — вызов chk.chk_status_select.</summary>
|
||||
public class ChkStatusRepository : IChkStatusRepository
|
||||
{
|
||||
private readonly IConnectionString _connectionString;
|
||||
|
||||
/// <summary>Подключение передаётÑÑ Ñнаружи и не открываетÑÑ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸ÐµÐ¼.</summary>
|
||||
public ChkStatusRepository(IConnectionString connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
|
||||
/// <summary>Возвращает вÑе Ñтроки Ñправочника (chk.chk_status_select).</summary>
|
||||
public IList<ChkStatus> Select()
|
||||
{
|
||||
return _connectionString.PrepareExecute<ChkStatus>("chk.chk_status_select")
|
||||
.AsStoredProcedure()
|
||||
.AddConverter((record, list) =>
|
||||
{
|
||||
var entity = new ChkStatus
|
||||
{
|
||||
Id = record.Get<int>("id"),
|
||||
Name = record.Get<string>("name"),
|
||||
};
|
||||
list.Add(entity);
|
||||
})
|
||||
.ExecuteSelectMany()
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
namespace MT.Checks.Repository
|
||||
{
|
||||
using Kit.Helpers.SqlHelperAbstract;
|
||||
using MT.Checks.Domain;
|
||||
|
||||
/// <summary>Репозиторий Ñправочника типов проверок (только чтение).</summary>
|
||||
public interface IChkTypeRepository
|
||||
{
|
||||
/// <summary>Возвращает вÑе Ñтроки Ñправочника (chk.chk_type_select).</summary>
|
||||
IList<ChkType> Select();
|
||||
}
|
||||
|
||||
/// <summary>РеализациÑ: ÐºÐ°Ð¶Ð´Ð°Ñ Ð²Ñ‹Ð±Ð¾Ñ€ÐºÐ° — вызов chk.chk_type_select.</summary>
|
||||
public class ChkTypeRepository : IChkTypeRepository
|
||||
{
|
||||
private readonly IConnectionString _connectionString;
|
||||
|
||||
/// <summary>Подключение передаётÑÑ Ñнаружи и не открываетÑÑ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸ÐµÐ¼.</summary>
|
||||
public ChkTypeRepository(IConnectionString connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
|
||||
/// <summary>Возвращает вÑе Ñтроки Ñправочника (chk.chk_type_select).</summary>
|
||||
public IList<ChkType> Select()
|
||||
{
|
||||
return _connectionString.PrepareExecute<ChkType>("chk.chk_type_select")
|
||||
.AsStoredProcedure()
|
||||
.AddConverter((record, list) =>
|
||||
{
|
||||
var entity = new ChkType
|
||||
{
|
||||
Id = record.Get<int>("id"),
|
||||
Name = record.Get<string>("name"),
|
||||
};
|
||||
list.Add(entity);
|
||||
})
|
||||
.ExecuteSelectMany()
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
namespace MT.Checks.Repository.Filter;
|
||||
|
||||
/// <summary>
|
||||
/// УÑÐ»Ð¾Ð²Ð¸Ñ Ð²Ñ‹Ð±Ð¾Ñ€ÐºÐ¸ проверок; null ÑвойÑтва = уÑловие не применÑетÑÑ.
|
||||
/// </summary>
|
||||
public class ChkCheckFilter
|
||||
{
|
||||
/// <summary>День (дата) проверки.</summary>
|
||||
public DateTime? CheckDate { get; set; }
|
||||
|
||||
/// <summary>Тип проверки (chk.chk_type.id).</summary>
|
||||
public int? TypeId { get; set; }
|
||||
|
||||
/// <summary>Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ (chk.chk_status.id).</summary>
|
||||
public int? StatusId { get; set; }
|
||||
|
||||
/// <summary>Идентификатор организации РР.</summary>
|
||||
public string? RrOrganizationId { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
# Отчёт генерации DAL (проект_dal) — прогон 2026-09-08, завершён БЛОКИРОВКОЙ на этапе 3
|
||||
|
||||
## Статус
|
||||
|
||||
| Этап | Статус |
|
||||
|---|---|
|
||||
| 0_scan (разведка) | done |
|
||||
| 1_rules (правила MCP) | done |
|
||||
| 2_spec (спецификации тестов) | done — утверждены пользователем |
|
||||
| 3_code (генерация) | **blocked** — конфликт транспорта (см. ниже) |
|
||||
| 4_validate | не выполнялся |
|
||||
| 5_report/DONE | не выполнялся |
|
||||
|
||||
## Версии правил
|
||||
|
||||
- Каталог MCP standarts-catalog: **1.2** (= rules-baseline.json 1.2).
|
||||
- Области: c-dal 1.1, d-tst 1.1, c-tst 1.1, c-cs 1.1, db-m 1.1, db-s 1.1 (все
|
||||
от 2026-09-04; составы правил совпали с baseline). Дополнительно загружены:
|
||||
db-func 1.1, db-tst 1.1, c-dm 1.1, d-dev 1.1, d-db 1.1.
|
||||
- `validate-rules` не требовался (расхождений нет).
|
||||
|
||||
## Причина блокировки
|
||||
|
||||
Транспорт `Kit.Helpers` (`SqlHelperPostgres.UpdateParamNames`) строит вызов
|
||||
хранимой функции с именованными аргументами `_<имя> => :_<имя>`, добавляя `_`
|
||||
к ключу параметра. Все функции экосистемы Kit (course, partner) объявлены с
|
||||
параметрами `_<имя>` (_guid, _partner_id). Функции слоя chk объявлены по
|
||||
правилу **db-func-5** с префиксом `p_` (p_check_date, p_id, ...) — такой вызов
|
||||
через Kit.Helpers невозможен (`_p_check_date` ≠ `p_check_date` → «function
|
||||
does not exist»).
|
||||
|
||||
**Решение пользователя (2026-09-08):** стандарт db-func-5 сохраняется (`p_`);
|
||||
генерация DAL заблокирована до доработки Kit.Helpers (администратор Kit):
|
||||
варианты — политика именования параметров в транспорте (не добавлять `_`,
|
||||
если ключ уже имеет префикс `p_`/`_`) либо иной согласованный механизм.
|
||||
|
||||
## Слой БД (создано в этом прогоне, статус DEV / «Функция»=CODE)
|
||||
|
||||
- `DB/chk/functions/*.sql` — 7 функций: chk_type_select, chk_status_select,
|
||||
chk_check_insert, chk_check_update, chk_check_delete, chk_check_select,
|
||||
chk_check_get (db-func-2..8; db-m-3/4/5/8; db-s-8).
|
||||
- `DB/chk/func_specs/*.md` — 7 спецификаций с тест-планами (d-db-9).
|
||||
- `DB/chk/tests/test_*.psql` — 7 psql-тестов, нумерация = строкам спецификаций
|
||||
(db-tst-1..3, db-tst-6). **Не выполнялись** — нужна тестовая база PostgreSQL:
|
||||
`psql -d <база> -f DB/chk/tests/test_*.psql`.
|
||||
- `DB/chk/functions.md` — статусы обновлены; `tables.md`, `DB/readme.md` — синхронизированы.
|
||||
- `db/manifest.json` — FRESH, 3 сущности (ChkCheck CRUD; ChkType/ChkStatus — select).
|
||||
|
||||
## Решение C# (создано)
|
||||
|
||||
- `MT.Check.slnx`; `MT.Check.Core.Dal` (net10.0; ProjectReference на
|
||||
`I:\Gitea\Kit\Kit.Core\Kit.Core\Kit.Core.csproj`); `MT.Check.Core.Dal.Tests` (xunit).
|
||||
- Домен: `Chk/Domain/ChkType.cs` (+ChkTypes), `ChkStatus.cs` (+ChkStatuses),
|
||||
`ChkCheck.cs` (c-dm-1..11; chk_type_id → TypeId и т.п.).
|
||||
- Репозитории-заготовки: `Chk/Repository/ChkCheckRepository.cs` (Insert/Update/
|
||||
Delete/Select/Get), `ChkTypeRepository.cs`, `ChkStatusRepository.cs` (Select —
|
||||
c-dal-2: системные справочники только чтение); фильтр
|
||||
`Chk/Repository/Filter/ChkCheckFilter.cs` (c-dal-14/15).
|
||||
- Тест-хелперы: `Tests/Helpers/ConnectionStringTest.cs`, `DataTableAssertExtensions.cs`
|
||||
(по шаблонам навыка).
|
||||
- Имена: решение MT.Check, проект MT.Check.Core.Dal — заданы пользователем
|
||||
(умолчание от имени папки отклонено из-за кириллической «С» в «MT.Сhecks»).
|
||||
|
||||
## Результаты build/test/check
|
||||
|
||||
- `dotnet build MT.Check.slnx` — **0 ошибок** (предупреждения NU1903/CS — из Kit.Core, вне рамок).
|
||||
- `dotnet test MT.Check.Core.Dal.Tests` — 0 тестов, успешно (тела и тесты не генерированы — блокировка).
|
||||
- DalTools `check` — **0 нарушений** (c-dal/c-tst).
|
||||
|
||||
## Методы → функции (проект, тела не реализованы)
|
||||
|
||||
| Метод | Функция | Спецификация тестов |
|
||||
|---|---|---|
|
||||
| ChkCheckRepository.Insert/Update/Delete/Select/Get | chk.chk_check_insert/update/delete/select/get | 1-docs/2-core/chk/repository_tests/ChkCheckRepository.md (13 тестов) |
|
||||
| ChkTypeRepository.Select | chk.chk_type_select | ChkTypeRepository.md (2 теста) |
|
||||
| ChkStatusRepository.Select | chk.chk_status_select | ChkStatusRepository.md (2 теста) |
|
||||
|
||||
## Возобновление (после доработки Kit.Helpers)
|
||||
|
||||
1. `dotnet run --project <DalTools> -- show-state` → продолжить с 3_code.
|
||||
2. Наполнить тела методов (транспорт fluent, p_-параметры) и тесты 1:1
|
||||
спецификациям; статусы «Репозиторий» → CODE; build/test/check; отчёт; DONE.
|
||||
|
||||
## Неопределённости / допущения
|
||||
|
||||
- Имя решения «MT.Check» — свободный выбор пользователя (папка содержит кириллицу).
|
||||
- Kit.Helpers подключён ProjectReference на внешний репозиторий (NuGet-пакета нет).
|
||||
- Имена сущностей в манифесте: ChkType/ChkStatus/ChkCheck (ToPascal от chk_*).
|
||||
- psql-тесты функций не исполнялись (нет доступа к тестовой БД в этом прогоне).
|
||||
- Задача «Проверка» БД-функций (db-tst) — исполнение на тестовой базе, отдельный шаг.
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
# Отчёт генерации DAL (навык project_dal) — прогон 2026-09-08
|
||||
|
||||
## Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñтапов
|
||||
|
||||
| Ðтап | Ð¡Ñ‚Ð°Ñ‚ÑƒÑ |
|
||||
|---|---|
|
||||
| 0_scan (разведка) | done |
|
||||
| 1_rules (правила MCP) | done |
|
||||
| 2_spec (Ñпецификации теÑтов) | done — утверждены пользователем |
|
||||
| 3_code (генерациÑ) | done (теÑты не ÑоздаютÑÑ â€” решение пользователÑ) |
|
||||
| 4_validate | done — build 0 ошибок; check: 1 извеÑтный false positive (Ñм. ниже) |
|
||||
| 5_report | done — ожидание ÑƒÑ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ DONE |
|
||||
|
||||
## ВерÑии правил
|
||||
|
||||
- Каталог MCP standarts-catalog: **1.2** (= rules-baseline.json 1.2); раÑхождений
|
||||
нет, `validate-rules` не требовалÑÑ.
|
||||
- ИÑпользованные облаÑти: c-dal 1.1, d-tst 1.1, c-tst 1.1, c-cs 1.1, db-m 1.1,
|
||||
db-s 1.1, db-func 1.1, db-tst 1.1, c-dm 1.1, d-dev 1.1, d-db 1.1 (вÑе 2026-09-04).
|
||||
|
||||
## Решение (проект `MT.Checks`)
|
||||
|
||||
- `MT.Checks.slnx` → проект `MT.Checks\MT.Checks.csproj` (net10.0),
|
||||
ProjectReference на `I:\Gitea\Kit\Kit.Core\Kit.Core\Kit.Core.csproj` (Kit.Helpers).
|
||||
- ТеÑтового проекта нет — решение Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Â«Ð±ÐµÐ· теÑтов ÑовÑем» (2026-09-08).
|
||||
|
||||
### Файлы
|
||||
|
||||
| Файл | Содержимое |
|
||||
|---|---|
|
||||
| `Domain\ChkCheck.cs` | ÑущноÑть проверки (+ Type/Status-Ñправочники, Params — Ñтрока JSON) |
|
||||
| `Domain\ChkType.cs` | Ñправочник типов + конÑтанты `ChkTypes` (6 значений) |
|
||||
| `Domain\ChkStatus.cs` | Ñправочник ÑтатуÑов + конÑтанты `ChkStatuses` (4 значениÑ) |
|
||||
| `Repository\Filter\ChkCheckFilter.cs` | фильтр Select (null = уÑловие не применÑетÑÑ) |
|
||||
| `Repository\ChkCheckRepository.cs` | Insert/Update/Delete/Select/Get |
|
||||
| `Repository\ChkTypeRepository.cs` | Select (Ñправочник — только чтение) |
|
||||
| `Repository\ChkStatusRepository.cs` | Select (Ñправочник — только чтение) |
|
||||
|
||||
ÐеймÑпейÑÑ‹: `MT.Checks.Domain`, `MT.Checks.Repository`, `MT.Checks.Repository.Filter`
|
||||
(папка/Ð¿Ñ€ÐµÑ„Ð¸ÐºÑ ÑÐ»Ð¾Ñ `Chk` в коде не иÑпользуютÑÑ â€” решение пользователÑ).
|
||||
|
||||
### Методы → функции БД
|
||||
|
||||
| Метод | Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ | Возврат |
|
||||
|---|---|---|
|
||||
| `ChkCheckRepository.Insert(ChkCheck)` | `chk.chk_check_insert` | id запиÑи |
|
||||
| `ChkCheckRepository.Update(ChkCheck)` | `chk.chk_check_update` | чиÑло Ñтрок (read-modify-write; guard Id=0) |
|
||||
| `ChkCheckRepository.Delete(int)` | `chk.chk_check_delete` | чиÑло Ñтрок (guard id=0) |
|
||||
| `ChkCheckRepository.Select(ChkCheckFilter)` | `chk.chk_check_select` | `IList<ChkCheck>` |
|
||||
| `ChkCheckRepository.Get(int)` | `chk.chk_check_get` | `ChkCheck?` (guard id=0) |
|
||||
| `ChkTypeRepository.Select()` | `chk.chk_type_select` | `IList<ChkType>` |
|
||||
| `ChkStatusRepository.Select()` | `chk.chk_status_select` | `IList<ChkStatus>` |
|
||||
|
||||
Каждый метод — ровно одна Ñ…Ñ€Ð°Ð½Ð¸Ð¼Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ, транÑпорт — fluent API Kit.Helpers
|
||||
(`PrepareExecute<T>().AsStoredProcedure().AddParameter*().AddConverter(...)`),
|
||||
конвертеры таблиц ответа — inline-лÑмбды.
|
||||
|
||||
## Слой БД (Ñтот же прогон)
|
||||
|
||||
- `DB/chk/functions/*.sql` — 7 функций (параметры `p_*` по db-func-5);
|
||||
- `DB/chk/func_specs/*.md` — 7 Ñпецификаций Ñ Ñ‚ÐµÑÑ‚-планами (d-db-9);
|
||||
- `DB/chk/tests/test_*.psql` — 7 psql-теÑтов (**не иÑполнÑлиÑÑŒ** — нужна теÑтоваÑ
|
||||
база: `psql -d <база> -f DB/chk/tests/test_*.psql`);
|
||||
- `DB/chk/functions.md` — ÑтатуÑÑ‹: функции `DEV`/«ФункциÑ»=`CODE`; «Репозиторий»=`REQ`
|
||||
Ñ Ð¿Ñ€Ð¸Ð¼ÐµÑ‡Ð°Ð½Ð¸ÐµÐ¼ (unit-теÑты не ÑоздаютÑÑ, `CODE` по d-dev-3 неприменим).
|
||||
|
||||
## ВалидациÑ
|
||||
|
||||
- `dotnet build MT.Checks.slnx` — **0 ошибок** (Ð¿Ñ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ NU1903/CS — из Kit.Core).
|
||||
- DalTools `check` (Ñ Ð¼Ð°Ð½Ð¸Ñ„ÐµÑтом) — **1 нарушение c-dal-1, извеÑтный false positive**:
|
||||
ÑвриÑтика «SQL в Ñтроке C#» Ñканирует текÑÑ‚ между Ñтроковыми литералами файла и
|
||||
находит Ñлово `Select` в Ñигнатуре метода `Select(ChkCheckFilter)` — Ð¸Ð¼Ñ Ð¼ÐµÑ‚Ð¾Ð´Ð°
|
||||
обÑзательно по правилу c-dal-5 (имена CRUD: Insert/Update/Delete/Select/Get).
|
||||
ÐеуÑтранимо в коде без Ð½Ð°Ñ€ÑƒÑˆÐµÐ½Ð¸Ñ Ñтандарта; SQL в Ñтроках отÑутÑтвует.
|
||||
|
||||
## Спецификации теÑтов
|
||||
|
||||
`1-docs/2-core/chk/repository_tests/` — ChkCheckRepository.md (17 теÑтов),
|
||||
ChkTypeRepository.md, ChkStatusRepository.md — утверждены как документациÑ
|
||||
ожидаемого поведениÑ. ТеÑтовый код по решению Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ ÑоздаётÑÑ
|
||||
(Ñм. `DB/chk/functions.md`, примечание к колонке «Репозиторий»).
|
||||
|
||||
## ИзвеÑтные Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¸ решениÑ
|
||||
|
||||
1. **ТранÑпорт `p_` vs `_`**: Kit.Helpers Ñтроит именованные аргументы `_<имÑ>`,
|
||||
функции chk объÑвлены Ñ `p_<имÑ>` (db-func-5; решение Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ â€” Ñохранить
|
||||
Ñтандарт). До доработки Kit.Helpers (админиÑтратор Kit) вызовы репозиториев
|
||||
против живой БД будут давать «function ... does not exist».
|
||||
2. **Имена**: решение/проект `MT.Checks` — по указанию пользователÑ
|
||||
(в `MT.Check.Core.Dal`/`MT.Checks.Test` отказ).
|
||||
3. **Без теÑтов**: теÑтовый проект отÑутÑтвует; `dotnet test` из конвейера иÑключён.
|
||||
4. ÐŸÑ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ Ñборки NU1903 (уÑзвимые пакеты Npgsql/SqlClient и др.) —
|
||||
из Kit.Core, вне рамок навыка.
|
||||
|
||||
## Возобновление/завершение
|
||||
|
||||
ПоÑле доработки Kit.Helpers доÑтаточно проверить вызовы на теÑтовой БД
|
||||
(Ñпецификации вызовов не менÑÑŽÑ‚ÑÑ). СтатуÑÑ‹ `DONE` — поÑле утверждениÑ
|
||||
пользователем.
|
||||
Loading…
Reference in New Issue