From 67a4311150dcb5aca4e58473c38ed938e1269c4a Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Sun, 4 Oct 2026 03:29:28 +0400 Subject: [PATCH] =?UTF-8?q?docs:=20=D0=B4=D0=BE=D0=BA=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D0=B3=D0=B8=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D0=BA=D1=82=D0=B0=20=D1=81=20=D1=82=D0=BE=D1=87=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=B7=D1=80=D0=B5=D0=BD=D0=B8=D1=8F=20tabular-parser,=20=D0=BF?= =?UTF-8?q?=D0=B0=D1=80=D0=B8=D1=82=D0=B5=D1=82=20subjects=20=D1=81=20arm-?= =?UTF-8?q?core=20(T6.1-T6.3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5.1 --- api/src/contract/request.py | 9 +++++---- api/src/contract/result.py | 6 ++++-- api/src/contract/subjects.py | 4 ++++ api/tests/unit/test_contract.py | 5 +++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/api/src/contract/request.py b/api/src/contract/request.py index 5165080..4877790 100644 --- a/api/src/contract/request.py +++ b/api/src/contract/request.py @@ -1,8 +1,9 @@ -"""Запрос распознавания файла (arm-core → tabular-parser / scan-gateway): `recognition-request.schema.json` v1.0. +"""Запрос распознавания файла: `recognition-request.schema.json` v1.0. -Формируется из `recognition_job ⋈ stored_file ⋈ s3_object` (spec recognition-job-exchange); один файл — один job. -Subject — по `pipeline` (`request_subject`); заголовок `Nats-Msg-Id = :` -(`request_msg_id`) — не поле тела. +tabular-parser принимает этот запрос из `recognition.tabular.request` (производитель — arm-core); один файл — один job. +Модель намеренно совпадает с копией в arm-core (контракт — `../docs/contracts`, обзор — +`docs/context/03-architecture.md`). Subject — по `pipeline` (`request_subject`); заголовок +`Nats-Msg-Id = :` (`request_msg_id`) — не поле тела. """ from typing import Annotated, Literal diff --git a/api/src/contract/result.py b/api/src/contract/result.py index d591872..18d752c 100644 --- a/api/src/contract/result.py +++ b/api/src/contract/result.py @@ -1,7 +1,9 @@ """Файл результата в S3 (`results/{file_id}/{job_id}/result.json`): `recognition-result.schema.json` v1.0. -Один файл → один job → N документов (ОСВ по счёту / ББ / ОФР / прочее). В Срезе 0 — модели и валидация примеров; -маппинг в таблицы — Срез 2. Суммы — `Decimal` в модели и строка в JSON (`"106311116.46"`, без `float`). +tabular-parser формирует этот файл по запросу; один файл → один job → N документов (ОСВ по счёту / ББ / ОФР / прочее). +Модель намеренно совпадает с копией в arm-core (контракт — `../docs/contracts`, обзор — +`docs/context/03-architecture.md`). +Суммы — `Decimal` в модели и строка в JSON (`"106311116.46"`, без `float`). Нормализация счетов, резолв контрагентов и проверки — в arm-core, не здесь. """ diff --git a/api/src/contract/subjects.py b/api/src/contract/subjects.py index be58d01..7ea38d6 100644 --- a/api/src/contract/subjects.py +++ b/api/src/contract/subjects.py @@ -3,6 +3,10 @@ Источник: `docs/context/03-architecture.md`, «Контракт обмена через NATS»; схема recognition-request (`Nats-Msg-Id = :`) и recognition-result-message (`ack::` / `result::`). + +Модуль намеренно совпадает с копией в arm-core. `request_subject`, `REQUEST_SUBJECTS`, `IMAGE_REQUEST_SUBJECT` и +значение `"image"` в `Pipeline` tabular-parser не использует (он слушает только `tabular`) — это сознательный паритет +с arm-core, а не мёртвый код. """ import uuid diff --git a/api/tests/unit/test_contract.py b/api/tests/unit/test_contract.py index 16ae4be..8aea34c 100644 --- a/api/tests/unit/test_contract.py +++ b/api/tests/unit/test_contract.py @@ -1,5 +1,6 @@ -"""Контракт обмена с сервисами распознавания v1.0 (spec recognition-contract, design D-7). +"""Контракт обмена с сервисами распознавания v1.0. +Спека сервиса — `tabular-recognition-service`; change `recognition-contract` лежит в `../docs`. Быстрые тесты без БД: вендоренные схемы `api/contracts/` идентичны `../docs/contracts/`; каждый пример проходит и JSON Schema, и pydantic-модель (с round-trip); модели и схемы выносят один и тот же вердикт на негативных кейсах. """ @@ -598,7 +599,7 @@ def test_python_float_amount_is_rejected_with_clear_error() -> None: def test_decimal_object_input_is_accepted_and_dumped_as_string() -> None: - """Для кода, собирающего результат из `Decimal` (тесты, будущие производители): объект `Decimal` принимается.""" + """Для кода, собирающего результат из `Decimal` (тесты, парсер при сборке результата): `Decimal` принимается.""" payload = _example("result-statement-minimal.json") payload["documents"][0]["lines"][0]["values"][0]["amount"] = Decimal("1234.50") result = RecognitionResult.model_validate(payload)