"""Часть 06 DBML v5.15 «Бухгалтерская отчётность»: шапка, колонки-периоды, строки и значения форм ББ/ОФР (157н). Первичка не мутируется: `*_original_value` / `original_amount` / `is_modified` — рядом с распознанным значением. Логические проверки (ТЗ 6.3) и «требует проверки» не хранятся — считаются на лету. """ import datetime import decimal import uuid from sqlalchemy import Boolean, Date, DateTime, ForeignKey, Index, Numeric, SmallInteger, String, Text, text from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped, mapped_column from .base import Base, UUIDPrimaryMixin from .enums import StatementType, pg_enum class FinancialStatementMeta(UUIDPrimaryMixin, Base): """Шапка распознанной формы ББ/ОФР; 1:1 с `document`.""" __tablename__ = "financial_statement_meta" document_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("document.id"), nullable=False, unique=True ) recognition_job_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("recognition_job.id"), nullable=False ) statement_type: Mapped[StatementType] = mapped_column(pg_enum("statement_type"), nullable=False) inn: Mapped[str | None] = mapped_column(String) inn_original_value: Mapped[str | None] = mapped_column(String) inn_confidence: Mapped[decimal.Decimal | None] = mapped_column(Numeric(5, 2)) inn_verified: Mapped[bool | None] = mapped_column(Boolean) inn_modified: Mapped[bool | None] = mapped_column(Boolean) organization_name: Mapped[str | None] = mapped_column(String) report_date: Mapped[datetime.date | None] = mapped_column(Date) report_date_original_value: Mapped[str | None] = mapped_column(String) report_date_verified: Mapped[bool | None] = mapped_column(Boolean) report_date_modified: Mapped[bool | None] = mapped_column(Boolean) units: Mapped[str | None] = mapped_column(String) units_original_value: Mapped[str | None] = mapped_column(String) units_verified: Mapped[bool | None] = mapped_column(Boolean) units_modified: Mapped[bool | None] = mapped_column(Boolean) currency: Mapped[str | None] = mapped_column(String, server_default=text("'RUB'")) okpo: Mapped[str | None] = mapped_column(String) okopf: Mapped[str | None] = mapped_column(String) okfs: Mapped[str | None] = mapped_column(String) okud: Mapped[str | None] = mapped_column(String) okei: Mapped[str | None] = mapped_column(String) legal_form: Mapped[str | None] = mapped_column(String) ownership_form: Mapped[str | None] = mapped_column(String) address: Mapped[str | None] = mapped_column(String) subject_to_audit: Mapped[bool | None] = mapped_column(Boolean) reviewed_by: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("app_user.id")) reviewed_at: Mapped[datetime.datetime | None] = mapped_column(DateTime(timezone=True)) checks_accepted_by: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("app_user.id")) checks_accepted_at: Mapped[datetime.datetime | None] = mapped_column(DateTime(timezone=True)) checks_accepted_comment: Mapped[str | None] = mapped_column(Text) class FinancialStatementColumn(UUIDPrimaryMixin, Base): """Колонка-период формы (2–3 сравнительные даты); `period_date` нужна межформенным проверкам и гудвиллу.""" __tablename__ = "financial_statement_column" __table_args__ = ( Index("uq_financial_statement_column_meta_id_column_index", "meta_id", "column_index", unique=True), ) meta_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("financial_statement_meta.id"), nullable=False ) column_index: Mapped[int] = mapped_column(SmallInteger, nullable=False) label: Mapped[str | None] = mapped_column(String) period_date: Mapped[datetime.date | None] = mapped_column(Date) is_current: Mapped[bool | None] = mapped_column(Boolean) class FinancialStatementLine(UUIDPrimaryMixin, Base): """Строка формы с кодом; порядок, разделы и итоговые строки — шаблон формы на фронте.""" __tablename__ = "financial_statement_line" __table_args__ = (Index("uq_financial_statement_line_meta_id_line_code", "meta_id", "line_code", unique=True),) meta_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("financial_statement_meta.id"), nullable=False ) line_code: Mapped[str | None] = mapped_column(String) line_code_original_value: Mapped[str | None] = mapped_column(String) line_code_confidence: Mapped[decimal.Decimal | None] = mapped_column(Numeric(5, 2)) line_code_modified: Mapped[bool | None] = mapped_column(Boolean) line_name: Mapped[str | None] = mapped_column(String) line_name_original_value: Mapped[str | None] = mapped_column(String) line_name_confidence: Mapped[decimal.Decimal | None] = mapped_column(Numeric(5, 2)) line_name_modified: Mapped[bool | None] = mapped_column(Boolean) class FinancialStatementValue(UUIDPrimaryMixin, Base): """Распознанное значение (строка x колонка): сумма, уверенность, признак ручной правки (Прил. 2 ТЗ).""" __tablename__ = "financial_statement_value" __table_args__ = (Index("uq_financial_statement_value_line_id_column_id", "line_id", "column_id", unique=True),) line_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("financial_statement_line.id"), nullable=False ) column_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("financial_statement_column.id", name="fk_financial_statement_value_column_id_fs_column"), nullable=False, ) amount: Mapped[decimal.Decimal | None] = mapped_column(Numeric(18, 2)) string_value: Mapped[str | None] = mapped_column(String) confidence: Mapped[decimal.Decimal | None] = mapped_column(Numeric(5, 2)) is_recognized: Mapped[bool | None] = mapped_column(Boolean) is_modified: Mapped[bool] = mapped_column(Boolean, nullable=False, server_default=text("false")) original_amount: Mapped[decimal.Decimal | None] = mapped_column(Numeric(18, 2)) 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))