"""Схемы API документов и строк ОСВ (spec documents-api «Документ и строки», «Подтверждение документа»; design D-11). `DocumentOut` — карточка документа: поля `document`, `file_id`, схема группировок листа из `recognition_job.group_schema` (элемент с `locator` документа) и предупреждения маппинга файла целиком (R-6). `EntryOut` — строка `osv_entry`; суммы — `Decimal` (в JSON — строка, без `float`). `EntriesPageParams` — пагинация строк: `limit` ≤ 2000, по умолчанию 500. """ import datetime import uuid from decimal import Decimal from pydantic import BaseModel, ConfigDict, Field from src.models.enums import ( CounterpartyMatchKind, DocumentCheckResult, DocumentStatus, DocumentType, OsvDataType, OsvGroupType, PeriodQuarter, ) DEFAULT_ENTRIES_LIMIT = 500 MAX_ENTRIES_LIMIT = 2000 class GroupOut(BaseModel): """Группировка из шапки листа ОСВ (как в результате распознавания): тип, исходный текст, есть ли ИНН.""" type: str name: str | None = None has_inn: bool | None = None class DocumentOut(BaseModel): """Карточка документа: статус, проверки, `locator`, схема группировок листа и предупреждения маппинга файла.""" id: uuid.UUID file_id: uuid.UUID legal_entity_id: uuid.UUID document_type: DocumentType osv_account_code: str | None period_year: int | None period_quarter: PeriodQuarter | None is_cumulative: bool | None locator: str | None status: DocumentStatus period_check: DocumentCheckResult | None counterparty_check: DocumentCheckResult | None confirmed_by: uuid.UUID | None confirmed_at: datetime.datetime | None group_schema: list[GroupOut] | None warnings: list[str] class EntryOut(BaseModel): """Строка ОСВ (`osv_entry`); дерево восстанавливается по `parent_entry_id`.""" model_config = ConfigDict(from_attributes=True) id: uuid.UUID row_number: int | None level: int | None parent_entry_id: uuid.UUID | None row_value: str | None group_type: OsvGroupType | None group_name: str | None data_type: OsvDataType | None account_code: str | None account_root: str | None account_id: uuid.UUID | None counterparty_name: str | None counterparty_inn: str | None counterparty_id: uuid.UUID | None # способ сопоставления контрагента (v5.16); в API — `match_kind`, в ORM — `counterparty_match_kind` match_kind: CounterpartyMatchKind | None = Field(validation_alias="counterparty_match_kind") opening_debit: Decimal | None opening_credit: Decimal | None turnover_debit: Decimal | None turnover_credit: Decimal | None closing_debit: Decimal | None closing_credit: Decimal | None class EntriesPageParams(BaseModel): """Пагинация строк документа из query: `Annotated[EntriesPageParams, Query()]`.""" limit: int = Field(DEFAULT_ENTRIES_LIMIT, ge=1, le=MAX_ENTRIES_LIMIT) offset: int = Field(0, ge=0)