diff --git a/context/05-domain-rules.md b/context/05-domain-rules.md index 372fda9..722fbab 100644 --- a/context/05-domain-rules.md +++ b/context/05-domain-rules.md @@ -573,8 +573,7 @@ NEEDS_CHECK`; пройдено/акцептовано + нажато «Подт (`current_recognition_job_id`): `PROCESSING` — ack сервиса (или результат `done`/`needs_check`, если ack потерян); `ERROR` — задание `error`/`timeout`/`dlq` либо ошибка маппинга; `PROCESSED` — маппинг завершён; `SUPERSEDED` — автозамена. `PROCESSED` и `SUPERSEDED` событиями обмена не перезаписываются. Физическое удаление: ANL-020 запрещает его после -INITIATED; в Срезе 2c консолидаций ещё нет, поэтому удаление разрешено, кроме файла с документом, подтверждённым пользователем, автоподтверждённого документа в версии вне INITIATED/DOCUMENTS_PROCESSING/DATA_CORRECTION и файла, -заменившего другие (§9.5); поведение после появления консолидаций — OQ-110. +INITIATED; в Срезе 2c консолидаций ещё нет, поэтому удаление разрешено, кроме: (а) файла с документом, подтверждённым пользователем; (б) файла с автоподтверждённым документом, привязанным к версии вне INITIATED/DOCUMENTS_PROCESSING/DATA_CORRECTION; (в) файла, заменившего другие (§9.5); поведение после появления консолидаций — OQ-110. ### 9.3 Документ (`document_status`): создаётся ядром при маппинге результата, по одному на лист ОСВ: `RECOGNIZED` — задание `done`, `checks` парсера без нарушений, `counterparty_check ≠ MISMATCH` и нет предупреждений diff --git a/dev/qa-guide.md b/dev/qa-guide.md index 0f04750..44ae082 100644 --- a/dev/qa-guide.md +++ b/dev/qa-guide.md @@ -358,7 +358,7 @@ curl -s -X DELETE "localhost:8000/api/v1/files/$FILE" -H "$H" -w '%{http_code}\n | U5 | ka_go | загрузить тот же файл ещё раз | 422, `rejected[0].code = DUPLICATE_FILE`, `rejected[0].file_id` — файл из U1; новых файлов нет | | U6 | ka_go | загрузить `.docx` (или `.xlsx`, переименованный из `.xls`) | 422, `rejected[0].code = UNSUPPORTED_FILE` | | U7 | ka_go | загрузить `ОСВ_67 за 2024.xls` и `.docx` одним запросом (`-F 'files=@…' -F 'files=@…'`) | 201, один в `accepted`, один в `rejected` с `UNSUPPORTED_FILE` | -| U8 | ka_go | `POST /documents/{id}/confirm` для документа из U1 (уже `CONFIRMED` автоматически) | 409 `ALREADY_CONFIRMED`; ручное подтверждение `NEEDS_CHECK`-документа — в W17 (UI) | +| U8 | ka_go | `POST /documents/{id}/confirm` для документа из U1 (уже `CONFIRMED` автоматически) | 409 `ALREADY_CONFIRMED`; ручное подтверждение `NEEDS_CHECK`-документа — в W17 (API) | | U9 | ka_go | `DELETE /files/{file_id}` файла из U1 (документ автоподтверждён, к версии не привязан) | 204; `GET /files/{id}` — 404; документы и строки удалены | | U10 | ka_go | для того же ЮЛ загрузить `ОСВ_60 за 2024.xls` (rb) и дождаться `PROCESSED`; затем `../fixtures/osv/schastl/2024-FY/Оборотносальдовая ведомость по счету 60 за 2024 г..xlsx` | второй файл — `PROCESSED`, `version_no = 2` (если оба документа 60 / 2024 / Q4); первый — `SUPERSEDED`, `superseded_by_file_id` = второй; у документа второго файла `counterparty_check = MISMATCH`, `status = NEEDS_CHECK` (шапка — другая организация) | | U11 | ka_go | `GET /legal-entities/{id}/files`, затем с `include_superseded=true` | в первом — только актуальные файлы; во втором — и заменённый `SUPERSEDED` | @@ -534,7 +534,7 @@ curl -s "localhost:8000/api/v1/documents/$DOC/statement" -H "$H" | python3 -m js |---|---|---|---| | F1 | ka_go | загрузить `1_Форма1_бух_09.xlsx` для ЮЛ с ИНН 7016006635, дождаться `PROCESSED` | один документ: `document_type = BALANCE`, `osv_account_code` пуст, `period_year = 2025`, `period_quarter = Q3`, `counterparty_check = MATCH`, `comments_count = 0`, `status = CONFIRMED` (автоподтверждение: `confirmed_by` пуст, `reviewed_by` NULL) | | F2 | ka_go | `GET /documents/{id}/statement` | 200; `edition = fsbu4`; `document.reporting_date = 2025-09-30`; `columns` — 3 (у колонки 0 `is_current = true`); `lines` — 37, отсортированы по `line_code`, у каждой `values` на все колонки; суммы — строки; `header.inn.value = "7016006635"`, `confidence = "100.00"`, `modified = false`; `checks.failed`, `soft_failed` пусты, `accepted = null` | -| F3 | ka_go | `PATCH …/statement` `{"values":[{"line_id":…,"column_id":…,"amount":"<сумма строки 1600, колонки 0, увеличенная на 100>"}]}` (id — из F2) | 200; у ячейки `amount` новая, `original_amount` = прежняя, `is_modified = true`, `modified_by` = пользователь; `checks.failed` непуст (нарушено `1600 = 1100 + 1200` и/или `1600 = 1700`), `document.status = NEEDS_CHECK`; в `audit_event` одно `RECOGNIZED_DATA_EDIT` (раздел `RECOGNITION`, `object_type = document`) с `before`/`after` ячейки (6.4) | +| F3 | ka_go | `PATCH …/statement` `{"values":[{"line_id":…,"column_id":…,"amount":"<сумма строки 1600, колонки 0, увеличенная на 100>"}]}` (`line_id`/`column_id` — из `GET …/statement` файла-копии, не из F2) | 200; у ячейки `amount` новая, `original_amount` = прежняя, `is_modified = true`, `modified_by` = пользователь; `checks.failed` непуст (нарушено `1600 = 1100 + 1200` и/или `1600 = 1700`), `document.status = NEEDS_CHECK`; в `audit_event` одно `RECOGNIZED_DATA_EDIT` (раздел `RECOGNITION`, `object_type = document`) с `before`/`after` ячейки (6.4) | | F4 | ka_go | `POST …/confirm` | 409 `CHECKS_NOT_PASSED`, `detail.failures[]` — нарушения (`column_index`, `relation`, `expected`, `actual`) | | F5 | ka_go | `POST …/statement/checks/accept` `{"comment":"округление в форме клиента"}` | 200; `checks.accepted = {by, at, comment}`, `checks.failed` по-прежнему непуст; статус документа пересчитан (`RECOGNIZED`, если других причин `NEEDS_CHECK` нет); `POST …/confirm` теперь проходит (но F11 делайте после возврата значений) | | F6 | ka_go | снова `PATCH` той же ячейки другой суммой | 200; `checks.accepted = null` (акцепт сброшен правкой) | @@ -548,11 +548,11 @@ curl -s "localhost:8000/api/v1/documents/$DOC/statement" -H "$H" | python3 -m js | F14 | ka_go | `POST /documents/{id}/comments` `{"text":"нет подписи руководителя"}`; `{"text":" "}`; затем `GET …/comments` и `GET /files/{file_id}` | 201 с `author.full_name`; пустой после обрезки текст — 422; в списке один комментарий; в карточке файла и `GET /documents/{id}` у документа `comments_count = 1`; комментарий к `CONFIRMED` документу разрешён | | F15 | ka_go | `GET /users/brief?ids=,<случайный uuid>`; с 201 id; с `ids=abc` | 200, один элемент `{id, full_name, is_active}`; 422 `TOO_MANY_IDS`; 422 `INVALID_IDS`; то же под `expert` (без `USERS_ADMIN`) — 200 | | F16 | ka_go | `GET /directories/legal-entities?q=7016006635` после F1 и F12 | `documents_count = 2` (ББ и ОФР) | -| F17 | ka_go | в ГК «Агрофирма Межениновская» завести второе ЮЛ и ГСК из двух ЮЛ (раздел 7, «Подготовка»), создать версию за 2025 Q3; убедиться, что ББ и ОФР второго ЮЛ `CONFIRMED` (чистые формы автоподтверждаются; при `NEEDS_CHECK` — проверить значения и подтвердить вручную, F11); `GET …/checklist` и `GET …/checklist?format=csv` | ячейки «Бух. баланс» и «ОФР» ЮЛ — `CONFIRMED`; CSV: файл начинается с BOM (`EF BB BF`), первая строка «Организация;ИНН;Бух. баланс;ОФР;ОСВ …», разделитель `;`, у ЮЛ «Загружен»; `Content-Disposition` с `filename="checklist.csv"` и `filename*=UTF-8''checklist-<ГК>-2025-Q3.csv` | +| F17 | ka_go | в ГК «Агрофирма Межениновская» завести второе ЮЛ и ГСК из двух ЮЛ (раздел 7, «Подготовка»), создать версию за 2025 Q3; убедиться, что ББ и ОФР ЮЛ с ИНН 7016006635 (файлы F1/F12) `CONFIRMED` (чистые формы автоподтверждаются; при `NEEDS_CHECK` — проверить значения и подтвердить вручную, F11); `GET …/checklist` и `GET …/checklist?format=csv` | ячейки «Бух. баланс» и «ОФР» ЮЛ — `CONFIRMED`; CSV: файл начинается с BOM (`EF BB BF`), первая строка «Организация;ИНН;Бух. баланс;ОФР;ОСВ …», разделитель `;`, у ЮЛ «Загружен»; `Content-Disposition` с `filename="checklist.csv"` и `filename*=UTF-8''checklist-<ГК>-2025-Q3.csv` | | F18 | expert | `PATCH …/statement`, `POST …/comments`, `POST …/accept` | 403 (нет `DOCUMENT_EDIT`); `GET …/statement` и `GET …/comments` — 200 | | F19 | client_manager | `GET …/statement`, `GET /files/{id}/content` документа ЮЛ другого филиала | 404 `NOT_FOUND`, тело как у случайного uuid | | F20 | ka_go | `GET …/statement` документа `OSV` (раздел 6.6) | 409 `DOCUMENT_NOT_STATEMENT` | -| F21 | ka_go | загрузить второй файл с формой ББ за тот же период (книга Form1, пересохранённая в Excel — другой sha256); `PATCH` по документу первого файла | старый файл `SUPERSEDED`; `PATCH`/`accept` по его документу — 409 `FILE_SUPERSEDED`; чтение `GET …/statement` и комментарии работают | +| F21 | ka_go | загрузить второй файл с формой ББ за тот же период (книга Form1, пересохранённая в Excel — другой sha256); `PATCH` по документу первого файла (это копия с нарушением из F3–F10; чистая F1 удалена по предусловию §6.9) | старый файл `SUPERSEDED`; в коде (`statements.py`) проверка `FILE_SUPERSEDED` идёт раньше `DOCUMENT_READONLY`, поэтому ответ — 409 `FILE_SUPERSEDED` даже для подтверждённой формы; `PATCH`/`accept` по его документу — 409 `FILE_SUPERSEDED`; чтение `GET …/statement` и комментарии работают | Что не считать багом: формы из OCR (PDF) почти всегда `NEEDS_CHECK` — уверенность значений меньше 100, ИНН распознан неуверенно (`aep_3.pdf`, `aep_6.pdf`, раздел 6.8), аналитик правит значения и подтверждает; у форм без колонки кодов документ создаётся без @@ -768,7 +768,7 @@ docker compose -f ../docs/dev/docker-compose.yml --profile services up -d --buil | № | Шаги | Ожидание | |---|---|---| | W16 | В панели Счастливочной клик по «ОСВ 60» | экран «Просмотр ОСВ»: крошки «Отчётность › ПЕКАРНЯ СЧАСТЛИВОЧНАЯ, ООО › Проверка документа», подзаголовок «<имя файла> · XLS · <дата>», справа статус «Загружен», кнопка «✓ Подтвердить» неактивна; надпись «Суммы в рублях; строки ОСВ только для чтения»; дерево счёт → субсчёт → контрагент, колонки «Счёт / контрагент», «ИНН» и шесть сумм. Корневая строка `60`: «—», «27 923 002,09», «107 554 149,33», «99 188 100,32», «—», «19 556 953,08» (сальдо нач. Кт + обороты Кт − обороты Дт = сальдо кон. Кт) | -| W17 | Загрузить один файл из `../fixtures/osv/schastl/2024-Q3/` в ЮЛ вне демо-периметра (любое ЮЛ стенда вне ГСК демо, без `consolidation_version_id`; проверка `Контрагент ✗` — шапка другой организации; не РБ, чтобы не заменить файлы и не сдвинуть счётчики W18), в панели открыть «ОСВ 60» → статус «Требуется проверка» → «✓ Подтвердить» | до подтверждения статус «Требуется проверка»; после — уведомление «Документ подтверждён», статус «Загружен», кнопка неактивна; в панели документ — «Загружен» | +| W17 | ka_go, через API (в UI не воспроизводится: загрузка только из панели ЮЛ внутри версии, см. раздел 8.7). Загрузить один файл из `../fixtures/osv/schastl/2024-Q3/` в QA-ЮЛ `$LE_QA` (id ЮЛ, заведённого для QA, не входящего в ГСК демо; без `consolidation_version_id`): `curl -s -X POST "localhost:8000/api/v1/legal-entities/$LE_QA/files" -H "$H" -F "files=@<файл>"`; дождаться `PROCESSED` (`GET /files/{file_id}`); `POST /documents/{id}/confirm` | документ `NEEDS_CHECK` («Контрагент ✗», шапка другой организации) до подтверждения; после — 200 `CONFIRMED`, `confirmed_by` заполнен; повтор — 409 `ALREADY_CONFIRMED`. Файл остаётся на стенде вне версий демо: счётчики W18 не затрагивает; `DELETE` после ручного подтверждения даёт 409 | | W18 | Остальные файлы РБ и Счастливочной 2024 Q1–Q3 (всего 22, список — 7.1): через «Загрузить документы» у каждого ЮЛ и подтверждение каждого ОСВ, либо скриптом из каталога `arm-web`: `scripts/demo-prepare.sh ` (id — из адреса `?version=`) | скрипт печатает строку на каждый файл (пять файлов из W13 — «уже загружен», это нормально), ждёт распознавания (до 5 мин), подтверждает только неподтверждённые ОСВ (чистые уже «Загружен», автоподтверждение, OQ-157) и в конце печатает `строк: 1385 документов: 22 несопоставленных: 1381 пробелов: 7`. Статус версии — «Коррекция данных» (K9) появляется сразу после распознавания (автоподтверждение чистых документов, OQ-157), в «Организации» в колонке «ОСВ» — счета ЮЛ | `demo-prepare.sh` берёт пользователя вторым аргументом (по умолчанию `ka_go@armka.local`), адрес ядра — из `API`