Срез 3b (docs): §7/§9 по факту, контракт API форм и мелких дыр, OQ #49
@ -660,7 +660,7 @@ replay: dlq → queued (`attempt + 1`). `max_attempts`: OCR 1, парсер 3; `
|
||||
форма — 409 `DOCUMENT_NOT_STATEMENT`; ячейка не этого документа — 422 `UNKNOWN_CELL`. Исходное сохраняется: у значения при
|
||||
первой правке `original_amount` = прежняя сумма, `is_modified = (amount ≠ original_amount)` (возврат к исходному снимает
|
||||
признак), `modified_by/at`; у поля шапки `*_modified = true`, `*_original_value` не меняется. После правки: акцепт проверок
|
||||
сбрасывается (§7), проверки и статус пересчитываются (§9.3), пишется одно `audit_event(RECOGNIZED_DATA_EDIT)`; запрос
|
||||
сбрасывается (§7; прежний акцепт, включая комментарий, остаётся в `before_value.checks_accepted` записи аудита), проверки и статус пересчитываются (§9.3), пишется одно `audit_event(RECOGNIZED_DATA_EDIT)`; запрос
|
||||
без изменений — 200 без аудита. Автозамена при правке не запускается (только при маппинге): правка даты, давшая период
|
||||
другого файла ЮЛ, привязывает документ к версии лишь при подтверждении. Порядок блокировок — как у подтверждения (файл →
|
||||
документ).
|
||||
|
||||
@ -103,6 +103,8 @@ expected, actual}` (суммы — строками) внутри `detail`: `{"d
|
||||
`inn` пересчитывает `counterparty_check`. Статус документа (`RECOGNIZED`/`NEEDS_CHECK`) пересчитывается после каждой правки.
|
||||
6. **Акцепт сбрасывается любой правкой формы.** После `PATCH`, который что-то изменил, `checks.accepted` снова `null`. Запрос,
|
||||
который ничего не меняет (те же значения, пустое тело), — 200 с неизменным состоянием, без записи в журнал и без сброса акцепта.
|
||||
Если акцепт был, в записи журнала `RECOGNIZED_DATA_EDIT` его прежнее значение сохраняется в `before.checks_accepted`
|
||||
(`by`, `at`, `comment`), поэтому текст сброшенного акцепта можно восстановить из аудита.
|
||||
7. **`checks.failed` не очищается акцептом.** Акцепт не скрывает нарушения: `failed` остаётся заполненным, а `accepted` непусто —
|
||||
это сигнал «нарушения приняты аналитиком». Блокируют подтверждение только нарушения **без** акцепта.
|
||||
8. **Что блокирует подтверждение** (`POST …/confirm`): период не определён — 409 `PERIOD_REQUIRED` (исправить датой отчёта);
|
||||
@ -121,8 +123,8 @@ expected, actual}` (суммы — строками) внутри `detail`: `{"d
|
||||
12. **Исходный файл.** `GET /files/{id}/content` отдаёт байты через ядро; прямой ссылки на S3 нет. Забирайте как blob с `Authorization`
|
||||
(`<a href>` и `<img src>` без заголовка не сработают). `Content-Type` — по типу файла (`application/pdf`, `image/png`,
|
||||
`image/jpeg`, для xls/xlsx/xlsb — свои MIME). `Content-Disposition`: `attachment` (по умолчанию) или `inline` (для просмотра в
|
||||
браузере) с ASCII-именем `file.<ext>` и `filename*=UTF-8''…` — исходным именем в percent-кодировке; берите имя из `filename*`.
|
||||
Работает и для файла `SUPERSEDED`. Объекта нет в хранилище (убран ретеншном) — 404 `FILE_CONTENT_NOT_FOUND` (не путать с `NOT_FOUND`:
|
||||
браузере) с ASCII-именем `file.<ext>` и `filename*=UTF-8''…` — исходным именем в percent-кодировке; берите имя из `filename*`. Ответ несёт
|
||||
`X-Content-Type-Options: nosniff` (браузер не угадывает тип по содержимому; тип задаёт `Content-Type`). Работает и для файла `SUPERSEDED`. Объекта нет в хранилище (убран ретеншном) — 404 `FILE_CONTENT_NOT_FOUND` (не путать с `NOT_FOUND`:
|
||||
файл в БД есть, а байтов нет); хранилище не подключено — 503 `STORAGE_UNAVAILABLE`. Скачивание в журнал не пишется (OQ-153).
|
||||
13. **Комментарии.** Только добавление и чтение; правки и удаления нет. `created_at` — порядок показа (по возрастанию). `text`
|
||||
обрезается по краям, пустой после обрезки или длиннее 4000 символов — 422 в формате pydantic. Автор — пользователь запроса.
|
||||
@ -134,9 +136,13 @@ expected, actual}` (суммы — строками) внутри `detail`: `{"d
|
||||
15. **CSV чек-листа.** `text/csv; charset=utf-8`, **BOM** в начале, разделитель `;`, переводы строк CRLF. Первая строка —
|
||||
«Организация;ИНН;<правило>…», где правило — «Бух. баланс», «ОФР», «ОСВ <счёт>» (в порядке `rules[]` чек-листа). Ячейки — подписи
|
||||
макета: `CONFIRMED` «Загружен», `PROCESSING` «Обработка», `NEEDS_CHECK` и `RECOGNIZED` «Требуется проверка», `ERROR` «Ошибка
|
||||
загрузки», `MISSING` «Отсутствует»; при пропущенных кварталах — с хвостом « (нет: Q1, Q2)». Имя файла —
|
||||
`Content-Disposition: attachment` с `filename*=UTF-8''checklist-<ГК>-<год>-<квартал>.csv`. Забирайте как blob с `Authorization`.
|
||||
Без `format=csv` маршрут по-прежнему отдаёт JSON `ChecklistOut` (Срез 4).
|
||||
загрузки», `MISSING` «Отсутствует»; при пропущенных кварталах — с хвостом « (нет: Q1, Q2)». Заголовок ответа —
|
||||
`Content-Disposition: attachment; filename="checklist.csv"; filename*=UTF-8''checklist-<ГК>-<год>-<квартал>.csv` (ASCII-имя
|
||||
фиксированное; настоящее имя — в `filename*`, percent-кодировка целиком, кириллица и пробелы экранируются; берите имя оттуда).
|
||||
Забирайте как blob с `Authorization`. Правило подписи — по `document_type` правила чек-листа; ячейки с текстом (имя ЮЛ) в CSV не
|
||||
нейтрализуются от формул Excel (design №19, R-9): значение, начинающееся с `=`, `+`, `-`, `@`, Excel может принять за формулу.
|
||||
Без `format=csv` (по умолчанию `format=json`) маршрут отдаёт JSON `ChecklistOut` (Срез 4); значение `format`, кроме `json` и `csv`,
|
||||
— 422 (pydantic-массив); право — `CONSOLIDATION_VIEW`, версия вне видимости — 404 `NOT_FOUND`.
|
||||
16. **`documents_count` у ЮЛ** считается на странице списка и в карточке одним запросом; заменённые файлы (`SUPERSEDED`) не входят.
|
||||
Число документов, а не файлов: один файл с ББ и ОФР даёт 2.
|
||||
17. **Что не вошло в срез.** Правка кода и названия строки, добавление и удаление строк и колонок, отмена подтверждения, смена
|
||||
|
||||
@ -501,7 +501,7 @@ 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=<uploaded_by файла>,<случайный 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; подтвердить ББ и ОФР (F11, F12); `GET …/checklist` и `GET …/checklist?format=csv` | ячейки «Бух. баланс» и «ОФР» ЮЛ — `CONFIRMED`; CSV: файл начинается с BOM (`EF BB BF`), первая строка «Организация;ИНН;Бух. баланс;ОФР;ОСВ …», разделитель `;`, у ЮЛ «Загружен»; `Content-Disposition` с `filename*=UTF-8''checklist-<ГК>-2025-Q3.csv` |
|
||||
| F17 | ka_go | в ГК «Агрофирма Межениновская» завести второе ЮЛ и ГСК из двух ЮЛ (раздел 7, «Подготовка»), создать версию за 2025 Q3; подтвердить ББ и ОФР (F11, F12); `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` |
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user