Compare commits

...

1 Commits

4 changed files with 87 additions and 1 deletions

View File

@ -458,3 +458,11 @@ JetStream** (3 subject `files.*` — как в старом АРМ, решени
`expires_at` → `status ready|timeout|error` + `error_code`, без ack `processing`, без `Nats-Msg-Id`, без queue group
(один экземпляр), дедуп только в памяти процесса — доставка at-most-once. Это параллельный сервис старого АРМ, а не
замена scan-gateway; из него берём только инфраструктурные решения (как и из `reference-old-arm`).
### Ручной повтор и уточнение ОСВ (AURORA-1442)
Повтор tabular после TIMEOUT/NO_ACK создаёт новый recognition_job через существующий outbox,
сохраняя прежнее задание и исходник S3. Реализация: services/file_retry.py; аудит FILE_REPROCESS (v5.21).
services/osv_header.py уточняет шапку ОСВ на месте, сохраняя document.original_values (v5.20),
снимает подтверждение/рабочие привязки и пишет RECOGNIZED_DATA_EDIT. Правила — §9.5 п.12–13,
контракты API — dev/frontend-api-guide.md. Две отдельные миграции: 0008 (v5.20), 0009 (v5.21).

View File

@ -1042,7 +1042,10 @@ replay: dlq → queued (`attempt + 1`); по кнопке пользовател
12. **Уточнение периода и счёта ОСВ** (`PATCH /documents/{id}/osv-header`, `DOCUMENT_EDIT`, policy по ЮЛ; v5.20, решения
владельца 21.10.2026, OQ-161 вариант 2, AURORA-1442). Аналитик исправляет период или счёт документа ОСВ, распознанные
неверно. Тело — любые из полей `period_year`, `period_quarter`, `is_cumulative`, `osv_account_code`; отсутствующее поле
не меняется. Проверки, по порядку: документ не ОСВ — 409 `DOCUMENT_NOT_OSV`; файл `SUPERSEDED` — 409
не меняется. Типы тела строгие: год — integer, квартал и счёт — string, признак — boolean;
приведения типов нет. Неверные типы отклоняются стандартным 422 валидации тела до доменных проверок;
явный null проверяется доменом. Следующий порядок применяется к запросам с корректными типами.
Проверки, по порядку: документ не ОСВ — 409 `DOCUMENT_NOT_OSV`; файл `SUPERSEDED` — 409
`FILE_SUPERSEDED`; `period_year` — четыре цифры 19xx/20xx, `period_quarter` — `Q1`…`Q4`, `is_cumulative` — `true` /
`false`; если в теле есть хоть одно поле периода, после правки все три не пусты и у `Q1` `is_cumulative = true`
(§1.5), иначе 422 `INVALID_PERIOD` (правка одного счёта период без квартала не трогает);
@ -1081,6 +1084,12 @@ replay: dlq → queued (`attempt + 1`); по кнопке пользовател
файл снова уходит в обработку (§9.2). Прежнее задание остаётся в истории. Предел — `max_attempts` задания (у парсера
3): на нём — отказ. В остальных случаях — 409. Права — `DOCUMENT_EDIT` и policy по ЮЛ. **Пакет версии** — то же
одним запросом для всех файлов версии, подходящих под условие; версия после `VERIFIED` read-only — запрет.
Уточнение состава пакета AURORA-1442: файлы с `stored_file.consolidation_id` консолидации выбранной версии
и ЮЛ из её текущего периметра; файлы без контекста консолидации не включаются. Версии одной консолидации
могут использовать общие файлы. API: `POST /files/{file_id}/retry` и
`POST /consolidations/versions/{version_id}/files/retry`. Версия пакета — только «в работе»; одиночный файл
консолидации требует наличия рабочей версии с его ЮЛ. Пользовательская блокировка не требуется.
Неподходящие файлы пакета — `skipped`, подходящие — `accepted`; общий статус версии не меняется.
Аудит — `audit_event(FILE_REPROCESS)` на каждый файл, отправленный на повтор (раздел `PRIMARY_DOCUMENTS`,
`object_type = stored_file`, `object_id` — файл, `user_id` — инициатор): `before_value` — прежнее задание (`job_id`,
`attempt`, `status`, `error_code`), `after_value` — новое (`job_id`, `attempt`); при обработке пакета — ещё

View File

@ -179,3 +179,8 @@
| OQ-171 | Вид субконто «Организации» в строке между названием ведомости и периодом (файл-письмо «ОСВ сч. 60 за 2 кв. 2026», план счетов ООО Хреновская Нива): что это за вид в 1С — организации-контрагенты (справочник «Организации» или «Контрагенты» под другим названием) или собственные организации учёта; на каких счетах встречается | tabular-parser #59, change `osv-flat-form` (R-10, решение сессии при одобрении запуска 19.10.2026) | §1.1 (синоним в `osv_groups.yaml`), сопоставление контрагентов | открыт; допущение принято: синоним `COUNTERPARTY` — только множественное число «Организации» (`^организации\b`, R-17); единственное «Организация» (собственная организация учёта в шапке) остаётся `OTHER`; другой смысл «Организации» на иных счетах даст `COUNTERPARTY` вместо `OTHER`, виден по предупреждениям |
| OQ-172 | Безымянная аналитика первого уровня на счёте **63** (резервы по сомнительным долгам) в плоской форме без названия вида: на файлах контура таких строк нет; 51 строка — в fixtures, golden `osv-dkb/nm/2025-Q3/НМ_ОСВ_63_Контрагенты_…json` (имя файла «63_Контрагенты» — довод за включение 63); счёт 63 не входит в `counterparty_accounts` (§1.3), строки остаются `OTHER` без имени. Нужен ли 63 в списке (аналитика резерва — контрагенты-должники) | tabular-parser #59, приёмка Task 6 (19.10.2026) | §1.3, сопоставление контрагентов | открыт; допущение принято: 63 в список не входит, строки `OTHER` |
| OQ-173 | Пересечение правил в сумме элиминации: счета сторон правил §4 пересекаются — дебет № 5–8 (76 у № 5; 60/62/76 у № 6–8), кредит: 67.03 (№ 3 и маска 67 у № 7), 66.03 (№ 4 и маска 66 у № 8), 66.04/67.04 (№ 5 и № 7/8). Строка такого счёта входит в Σ стороны каждого правила, и сумма min(ΣA, ΣB) по правилам может превысить Σ самой стороны — двойная элиминация. Считать ΣA правила только по строкам, которые упаковка (§5 п. 2) отнесла к этому правилу? Или распределять сторону по правилам в фиксированном порядке? | решение по OQ-07 (docs #136, 19.10.2026), описание AURORA-1536 | §5 п. 1, AURORA-1536, КФО (§8 `eliminated_auto`) | **закрыт решением владельца 19.10.2026 (docs #136):** каскад по остатку — правила пары (A, B) считаются по порядку `rule_no` (в Прил. 3 он уже от частного к общему: № 3/4 раньше № 7/8, № 5 раньше № 6, № 6 → 7 → 8), каждое берёт min из остатка сторон после предыдущих, как в правиле № 1 Прил. 3 («сначала из 1450 до обнуления…»); упаковка — в том же порядке, строка сопоставляется одним правилом; ничьей между правилами нет. Поле порядка не нужно. Алгоритм — `05-domain-rules.md` §5 |
Уточнение реализации OQ-161 / AURORA-1442: правка шапки ОСВ следует DBML v5.20 и §9.5 п.12;
ручной повтор — §9.5 п.13, FILE_REPROCESS из DBML v5.21. Состав пакета согласован:
consolidation_id выбранной версии + её периметр. Флаг CONSOLIDATION_PERIOD_FROM_VERSION сохраняется
до отдельной поставки экрана правки ОСВ. Новых открытых вопросов по хранению и действию аудита нет.

View File

@ -776,3 +776,67 @@ async function download(path: string, fallbackName: string): Promise<void> {
9. Ячейки чек-листа — по `document_type`/`account`.
10. Файлы — `fetch` → blob с токеном; имя из `filename*`.
11. После действий — перечитать по таблице §6.1; во время распознавания — опрос 3–5 с.
## Повторная обработка и уточнение ОСВ (AURORA-1442, DBML v5.20–v5.21)
Все маршруты ниже требуют `DOCUMENT_EDIT` и видимость ЮЛ; чужой объект отвечает тем же 404, что несуществующий.
| Запрос (префикс `/api/v1`) | Успех | Назначение |
|---|---|---|
| `POST /files/{file_id}/retry` | 202 `FileOut` | Новая попытка обработки одного файла |
| `POST /consolidations/versions/{version_id}/files/retry` | 202 `{accepted, skipped}` | Подходящие файлы консолидации по периметру выбранной версии |
| `PATCH /documents/{document_id}/osv-header` | 200 `DocumentOut` | Уточнение периода и счёта ОСВ |
Ручной повтор разрешён для файла `ERROR`, только если его текущее задание `tabular` завершилось
`timeout/TIMEOUT` или `dlq/NO_ACK`, документов нет и `attempt < max_attempts`. Создаётся новый job
`queued`, `attempt + 1`; файл становится `UPLOADED`, исходный S3-объект сохраняется, старый job остаётся
в истории. NATS не требуется в момент запроса: публикация выполняется существующим outbox после commit.
OCR, `error` сервиса и ошибки маппинга не повторяются. Ошибки: 409 `FILE_NOT_RETRYABLE`,
`MAX_ATTEMPTS_REACHED`, `VERSION_NOT_EDITABLE`.
Пакет включает файлы с `stored_file.consolidation_id` выбранной консолидации и ЮЛ из периметра выбранной
версии; файлы другой консолидации и загрузки без контекста не включаются. Версия должна быть «в работе»
(`INITIATED`, `DOCUMENTS_PROCESSING`, `DATA_CORRECTION`), пользовательская блокировка не нужна.
Версии одной консолидации могут видеть общий файл. Неподходящие файлы пропускаются:
`accepted: [{file_id, job_id, attempt}]`, `skipped: [{file_id, code}]`. Пустой пакет также отвечает 202.
Для одиночного файла консолидации требуется хотя бы одна рабочая версия с ЮЛ файла в периметре.
Повтор не меняет статусы версий. Два конкурентных запроса не создают две новые попытки.
`PATCH …/osv-header` принимает любые из четырёх полей; отсутствующие не меняются. Пример:
```json
{"period_year": 2025, "period_quarter": "Q3", "is_cumulative": true, "osv_account_code": "60.1"}
```
Типы тела строгие: `period_year` — integer, `period_quarter` и `osv_account_code` — string,
`is_cumulative` — boolean; приведения строк и чисел нет. Неверный тип — стандартный 422 валидации
до доменных проверок. Явный `null` передаётся в домен, отсутствующие поля не меняются.
Счёт нормализуется (`60.1` → `60.01`). Если передано поле периода, итоговые три поля периода обязательны:
год 1900–2099, квартал Q1–Q4, boolean; у Q1 `is_cumulative=true`. Правка только счёта неполный период не трогает.
Новые значения сохраняются в прежнем `document`; перед первой фактической правкой все четыре исходных
значения сохраняются в `original_values`, неизменном при следующих правках. `is_modified` показывает отличие
текущих значений от оригинала, `modified_by/at` — последнюю правку. Возврат к оригиналу снимает признак,
но сохраняет снимок. Файл, JSON результата, `file_ordinal` и строки `osv_entry` не меняются.
Правка `CONFIRMED` сбрасывает статус в `NEEDS_CHECK` и очищает `confirmed_by/at`; привязки к рабочим версиям
снимаются, `CANCELLED` сохраняются, статусы версий не меняются. Нужно новое ручное подтверждение;
автоподтверждения и автозамены файлов нет. Колонка «ОСВ», подходящесть версиям и чек-лист читают актуальные
поля; `period_check/counterparty_check` не меняются. Флаг `CONSOLIDATION_PERIOD_FROM_VERSION` остаётся.
Запрос без фактических изменений — 200 без аудита, снимка и сброса подтверждения.
Ошибки PATCH по порядку: 409 `DOCUMENT_NOT_OSV`, `FILE_SUPERSEDED`; 422 `INVALID_PERIOD`,
`INVALID_ACCOUNT_CODE`; 409 `DUPLICATE_ACCOUNT` (`detail.document_id`); 409 `VERSION_NOT_EDITABLE`
(`detail.version_ids`). Последняя означает привязку к версии вне рабочих статусов и `CANCELLED`.
Аудит: `FILE_REPROCESS`, раздел `PRIMARY_DOCUMENTS`, объект `stored_file`, на каждый принятый файл.
`before_value={job_id, attempt, status, error_code}` описывает прежнее задание;
`after_value={job_id, attempt}` — новое; для пакета добавляется `consolidation_id`.
Пропущенные файлы и автоматические republish таких событий не пишут.
Правка ОСВ — одно `RECOGNIZED_DATA_EDIT` (`RECOGNITION`, `document`) с изменёнными полями,
сброшенным подтверждением и `after_value.unbound_version_ids`. Аудит и мутация фиксируются вместе.
Поставка: сначала `0008_dbml_v5_20` (четыре поля document), затем `0009_dbml_v5_21` (только enum
`FILE_REPROCESS`), затем приложение. Итоговая сверка — DBML v5.21. Откат 0009 → 0008 запрещён при
наличии `FILE_REPROCESS` в аудите; откат 0008 → 0007 — при `document.is_modified=true`.
При возврате к исходным значениям признак false, откат v5.20 удалит снимок; файл/JSON в S3 и аудит сохраняются.
UI повторной обработки и правки ОСВ поставляется отдельными задачами.