Срез 0 реализован и влит (PR #3), change перенесён в openspec/changes/archive, спеки — в openspec/specs. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
59 lines
4.9 KiB
Markdown
59 lines
4.9 KiB
Markdown
# reference-data-seed Specification
|
||
|
||
## Purpose
|
||
Справочники продукта (роли, права и их матрица, план счетов, правила элиминации, состав обязательных документов) и
|
||
dev-данные загружаются из файлов репозитория одной идемпотентной командой; повторный запуск ничего не дублирует.
|
||
|
||
## Requirements
|
||
|
||
### Requirement: Идемпотентный seed справочников продукта
|
||
Команда `python -m scripts.seed` (из `api/`) SHALL загрузить из `api/seed/core/`: `regional_office` (Головной офис,
|
||
`is_head_office = true`), `role` — 7 системных ролей ТЗ 8.1 (`KA_RF`, `KA_GO`, `RKA`, `CLIENT_MANAGER`, `CURATOR_GO`,
|
||
`EXPERT`, `ADMIN`, `is_system = true`), `permission` — 16 сочетаний объект × действие из §10 правил с кодами
|
||
`<OBJECT>_<ACTION>` (`EXPORT` при совпадении), `role_permission` по матрице §10 (ASSUMPTION(OQ-16)), `chart_of_account`,
|
||
`elimination_rule` + `elimination_rule_account` версии 1 для ББ (§4), `required_document_rule` для `BASIC` и `EXTENDED`.
|
||
Записи SHALL вставляться или обновляться по натуральному ключу; удаление MUST NOT выполняться.
|
||
|
||
#### Scenario: Первый запуск на пустой схеме
|
||
- **WHEN** после `alembic upgrade head` выполняется `python -m scripts.seed`
|
||
- **THEN** в `role` 7 строк, в `permission` 16, в `role_permission` — число строк равно сумме прав по матрице §10,
|
||
в `elimination_rule` 8 строк с `statement_type = balance`, `version_no = 1`, в `required_document_rule` для `BASIC`
|
||
10 строк (BALANCE, INCOME, OSV × 01, 58, 60, 62, 66, 67, 76, 90) и для `EXTENDED` 27 строк
|
||
|
||
#### Scenario: Повторный запуск
|
||
- **WHEN** `python -m scripts.seed` выполняется второй раз без изменения файлов
|
||
- **THEN** число строк во всех затронутых таблицах не меняется, команда завершается с кодом 0
|
||
|
||
#### Scenario: Изменение названия роли в файле
|
||
- **WHEN** в `roles.yaml` изменено `name` роли `EXPERT` и seed запущен снова
|
||
- **THEN** строка `role` с `code = EXPERT` обновлена, новая не создана
|
||
|
||
### Requirement: Счета правил и чек-листа существуют в плане счетов
|
||
Все коды счетов, на которые ссылаются `elimination_rules_v1.yaml` и `required_document_rules.yaml`, SHALL резолвиться в
|
||
`chart_of_account.code` после seed; `elimination_rule_account.is_excluded = true` SHALL быть у исключений вида
|
||
«76 кроме 76.07.5, 76.07.9»; `chart_of_account.kind` SHALL быть задан для всех синтетических счетов, `is_off_balance = true`
|
||
для 001–011.
|
||
|
||
#### Scenario: Правило № 6 (основная пара)
|
||
- **WHEN** seed завершён
|
||
- **THEN** у правила `rule_no = 6` сторона 1 содержит счета 60.02, 60.22, 60.32, 62.01, 62.03, 62.21, 62.31, 76 и исключения
|
||
76.07.5, 76.07.9; сторона 2 — 60.01, 60.03, 60.21, 60.31, 62.02, 62.22, 62.32, 76 и исключение 76.07.1;
|
||
`elimination_mode = min`, `measure = closing`, `side_1 = D`
|
||
|
||
#### Scenario: Ссылка на несуществующий счёт
|
||
- **WHEN** в файл правил добавлен счёт, которого нет в `chart_of_accounts.csv`
|
||
- **THEN** seed падает до записи в БД с сообщением, какой счёт и в каком правиле не найден
|
||
|
||
### Requirement: Dev-данные только по явному флагу
|
||
`python -m scripts.seed --dev` SHALL дополнительно загрузить из `api/seed/dev/`: примеры региональных филиалов и по одному
|
||
`app_user` на каждую системную роль (`<role>@armka.local`, активные, с назначенной ролью через `user_role`). Без флага
|
||
`--dev` эти данные MUST NOT загружаться.
|
||
|
||
#### Scenario: Dev-пользователи
|
||
- **WHEN** выполнен `python -m scripts.seed --dev`
|
||
- **THEN** в `app_user` 7 строк с email вида `ka_rf@armka.local`, каждая связана ровно с одной ролью через `user_role`
|
||
|
||
#### Scenario: Прод-режим
|
||
- **WHEN** выполнен `python -m scripts.seed` без `--dev`
|
||
- **THEN** таблица `app_user` пуста, `regional_office` содержит только Головной офис
|