"""Часть 05 DBML v5.13 «ОСВ»: строка оборотно-сальдовой ведомости (ТЗ 6.2, 6.5). Первичка не мутируется: сырые значения хранятся как пришли, правка аналитика — рядом (`is_modified`, `original_values`, `modified_by/at` + audit_event(RECOGNIZED_DATA_EDIT)). """ import datetime import decimal import uuid from typing import Any from sqlalchemy import Boolean, DateTime, ForeignKey, Index, Integer, Numeric, SmallInteger, String, text from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped, mapped_column from .base import Base, UUIDPrimaryMixin, nullable_jsonb from .enums import OsvDataType, OsvGroupType, pg_enum class OsvEntry(UUIDPrimaryMixin, Base): """Строка ОСВ; суммы — рубли, `numeric(18,2)`.""" __tablename__ = "osv_entry" __table_args__ = ( Index("uq_osv_entry_document_id_row_number", "document_id", "row_number", unique=True), Index("ix_osv_entry_owner_account_counterparty", "owner_legal_entity_id", "account_id", "counterparty_id"), ) recognition_job_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("recognition_job.id"), nullable=False ) document_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("document.id"), nullable=False) owner_legal_entity_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("legal_entity.id"), nullable=False ) parent_entry_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("osv_entry.id")) group_type: Mapped[OsvGroupType | None] = mapped_column(pg_enum("osv_group_type")) group_name: Mapped[str | None] = mapped_column(String) row_number: Mapped[int | None] = mapped_column(Integer) level: Mapped[int | None] = mapped_column(SmallInteger) row_value: Mapped[str | None] = mapped_column(String) data_type: Mapped[OsvDataType | None] = mapped_column(pg_enum("osv_data_type")) account_code: Mapped[str | None] = mapped_column(String) account_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("chart_of_account.id")) account_root: Mapped[str | None] = mapped_column(String) counterparty_name: Mapped[str | None] = mapped_column(String) counterparty_inn: Mapped[str | None] = mapped_column(String) counterparty_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("legal_entity.id")) opening_debit: Mapped[decimal.Decimal | None] = mapped_column(Numeric(18, 2)) opening_credit: Mapped[decimal.Decimal | None] = mapped_column(Numeric(18, 2)) turnover_debit: Mapped[decimal.Decimal | None] = mapped_column(Numeric(18, 2)) turnover_credit: Mapped[decimal.Decimal | None] = mapped_column(Numeric(18, 2)) closing_debit: Mapped[decimal.Decimal | None] = mapped_column(Numeric(18, 2)) closing_credit: Mapped[decimal.Decimal | None] = mapped_column(Numeric(18, 2)) is_modified: Mapped[bool] = mapped_column(Boolean, nullable=False, server_default=text("false")) original_values: Mapped[Any | None] = mapped_column(nullable_jsonb()) modified_by: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("app_user.id")) modified_at: Mapped[datetime.datetime | None] = mapped_column(DateTime(timezone=True)) is_excisable: Mapped[bool | None] = mapped_column(Boolean)