arm-core/api/src/models/enums.py
Andrey Epifancev 19d8bbbd59 feat(models): DBML v5.19 — колонки форм, document_issue, file_ordinal, crm_id ГСК (миграция 0007)
Модели и upgrade ревизии 0007_dbml_v5_19: пять enum'ов, колонки строк/значений/колонок/шапок форм,
document.file_ordinal (уникален в файле, уникальность типа только для не-форм), recognition_job.statements_version,
related_group.crm_id, таблица document_issue; заполнение по умолчанию (row_index, needs_review, header_source и др.).
delete_file_statements удаляет document_issue; make_document берёт следующий file_ordinal; маппер пока нумерует
документы по порядку создания. downgrade — заглушка (задача A2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 13:28:37 +04:00

400 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Enum'ы модели данных DBML v5.19 (33 штуки) и фабрика `pg_enum` для PostgreSQL-колонок.
Источник истины — docs/model/data-model-v5.19.dbml (блоки `Enum {}`). Значения — строки DBML буквально, в порядке
DBML (включая кириллические `"ЮЛ"`/`"ИП"` и значения в разном регистре); `notes` DBML значениями не являются.
Имя члена совпадает со значением (все значения DBML — валидные python-идентификаторы, кириллица допустима).
Классы — `enum.StrEnum` (подкласс `str`) — удобно для pydantic/JSON; `values_callable` в `pg_enum` в БД пишет `.value`.
"""
import enum
from sqlalchemy import Enum as SAEnum
from .base import SCHEMA
class EntityType(enum.StrEnum):
"""DBML `entity_type`."""
ЮЛ = "ЮЛ" # noqa: PLC2401 — значение DBML буквально
ИП = "ИП" # noqa: PLC2401 — значение DBML буквально
class RelatedGroupKind(enum.StrEnum):
"""DBML `related_group_kind`."""
gsk = "gsk"
gsz = "gsz"
class AccountKind(enum.StrEnum):
"""DBML `account_kind`."""
A = "A"
P = "P"
AP = "AP"
class AccountRowType(enum.StrEnum):
"""DBML `account_row_type`."""
account = "account"
subaccount = "subaccount"
analytic = "analytic"
class BusinessSegment(enum.StrEnum):
"""DBML `business_segment`."""
DKB = "DKB"
DMSB = "DMSB"
DM = "DM"
class DocumentType(enum.StrEnum):
"""DBML `document_type`."""
BALANCE = "BALANCE"
INCOME = "INCOME"
OSV = "OSV"
DISCLOSURE = "DISCLOSURE"
OTHER = "OTHER"
class FileType(enum.StrEnum):
"""DBML `file_type`."""
XLS = "XLS"
XLSX = "XLSX"
XLSB = "XLSB"
PDF = "PDF"
PNG = "PNG"
JPG = "JPG"
class RecognitionPipeline(enum.StrEnum):
"""DBML `recognition_pipeline`."""
tabular = "tabular"
image = "image"
class PeriodQuarter(enum.StrEnum):
"""DBML `period_quarter`."""
Q1 = "Q1"
Q2 = "Q2"
Q3 = "Q3"
Q4 = "Q4"
class FileStatus(enum.StrEnum):
"""DBML `file_status`."""
UPLOADED = "UPLOADED"
PROCESSING = "PROCESSING"
PROCESSED = "PROCESSED"
ERROR = "ERROR"
SUPERSEDED = "SUPERSEDED"
class DocumentStatus(enum.StrEnum):
"""DBML `document_status`."""
RECOGNIZED = "RECOGNIZED"
NEEDS_CHECK = "NEEDS_CHECK"
CONFIRMED = "CONFIRMED"
ERROR = "ERROR"
class S3BucketRole(enum.StrEnum):
"""DBML `s3_bucket_role`."""
uploads = "uploads"
results = "results"
exports = "exports"
archive = "archive"
class RecognitionStatus(enum.StrEnum):
"""DBML `recognition_status`."""
queued = "queued"
published = "published"
processing = "processing"
done = "done"
needs_check = "needs_check"
error = "error"
timeout = "timeout"
dlq = "dlq"
class StatementType(enum.StrEnum):
"""DBML `statement_type`."""
balance = "balance"
income = "income"
class StatementLineStatus(enum.StrEnum):
"""DBML `statement_line_status` (v5.19): статус строки формы; `line_code` пуст ⇔ статус не `ok`."""
ok = "ok"
unreadable = "unreadable"
missing = "missing"
detail = "detail"
class StatementFormVariant(enum.StrEnum):
"""DBML `statement_form_variant` (v5.19): вариант формы по структуре кодов (§11.7)."""
full = "full"
simplified = "simplified"
class DocumentIssueKind(enum.StrEnum):
"""DBML `document_issue_kind` (v5.19): вид записи `document_issue`."""
warning = "warning"
relation = "relation"
soft = "soft"
class IssueSeverity(enum.StrEnum):
"""DBML `issue_severity` (v5.19): `error` — документ `needs_check`, `info` — на статус не влияет."""
error = "error"
info = "info"
class IssueSource(enum.StrEnum):
"""DBML `issue_source` (v5.19): откуда запись — из результата распознавания или посчитана ядром."""
service = "service"
core = "core"
class OsvGroupType(enum.StrEnum):
"""DBML `osv_group_type`."""
ACCOUNT = "ACCOUNT"
DEPARTMENT = "DEPARTMENT"
COUNTERPARTY = "COUNTERPARTY"
CONTRACT = "CONTRACT"
OTHER = "OTHER"
class CounterpartyMatchKind(enum.StrEnum):
"""DBML `counterparty_match_kind` (v5.16): способ сопоставления контрагента строки ОСВ.
`INN` / `NAME` / `ALIAS` — шаг автоматического резолва при маппинге; `MANUAL` — ручное сопоставление;
`PROPAGATED` — автоприменение по имени в версии (DOC-221278 п. 12–13).
"""
INN = "INN"
NAME = "NAME"
ALIAS = "ALIAS"
MANUAL = "MANUAL"
PROPAGATED = "PROPAGATED"
class OsvDataType(enum.StrEnum):
"""DBML `osv_data_type`."""
BU = "BU"
NU = "NU"
CURRENCY = "CURRENCY"
QUANTITY = "QUANTITY"
SUM = "SUM"
class ConsolidationScenario(enum.StrEnum):
"""DBML `consolidation_scenario`."""
CREATE = "CREATE"
CONFIRM = "CONFIRM"
class ConsolidationApproach(enum.StrEnum):
"""DBML `consolidation_approach`."""
BASIC = "BASIC"
EXTENDED = "EXTENDED"
class ConsolidationStatus(enum.StrEnum):
"""DBML `consolidation_status`."""
INITIATED = "INITIATED"
DOCUMENTS_PROCESSING = "DOCUMENTS_PROCESSING"
DATA_CORRECTION = "DATA_CORRECTION"
CONSOLIDATION_RF = "CONSOLIDATION_RF"
ADJUSTMENT = "ADJUSTMENT"
VERIFICATION_RF = "VERIFICATION_RF"
CONSOLIDATION_GO = "CONSOLIDATION_GO"
VERIFICATION_GO = "VERIFICATION_GO"
VERIFIED = "VERIFIED"
CANCELLED = "CANCELLED"
REJECTED = "REJECTED"
ARCHIVED = "ARCHIVED"
class CorrectionStatus(enum.StrEnum):
"""DBML `correction_status`."""
DRAFT = "DRAFT"
APPLIED = "APPLIED"
REVOKED = "REVOKED"
class DocumentCheckResult(enum.StrEnum):
"""DBML `document_check_result`."""
MATCH = "MATCH"
MISMATCH = "MISMATCH"
UNKNOWN = "UNKNOWN"
class LeHistoryEvent(enum.StrEnum):
"""DBML `le_history_event`."""
CREATE = "CREATE"
UPDATE = "UPDATE"
MOVE_TO_GROUP = "MOVE_TO_GROUP"
CLOSE = "CLOSE"
REMOVE_FROM_GROUP = "REMOVE_FROM_GROUP"
class ExSnapshotStatus(enum.StrEnum):
"""DBML `ex_snapshot_status`."""
ACTUAL = "ACTUAL"
ARCHIVE = "ARCHIVE"
class PermissionObject(enum.StrEnum):
"""DBML `permission_object`."""
DIRECTORY = "DIRECTORY"
DOCUMENT = "DOCUMENT"
CONSOLIDATION = "CONSOLIDATION"
KFO = "KFO"
EX = "EX"
EXPORT = "EXPORT"
USERS = "USERS"
AUDIT = "AUDIT"
class PermissionAction(enum.StrEnum):
"""DBML `permission_action`."""
VIEW = "VIEW"
EDIT = "EDIT"
APPROVE = "APPROVE"
VERIFY = "VERIFY"
DELETE = "DELETE"
EXPORT = "EXPORT"
ADMIN = "ADMIN"
class AuditSection(enum.StrEnum):
"""DBML `audit_section`."""
DIRECTORIES = "DIRECTORIES"
CONSOLIDATION = "CONSOLIDATION"
PRIMARY_DOCUMENTS = "PRIMARY_DOCUMENTS"
RECOGNITION = "RECOGNITION"
KFO = "KFO"
EXPORT = "EXPORT"
ACCESS = "ACCESS"
SESSION = "SESSION"
USERS = "USERS"
class AuditAction(enum.StrEnum):
"""DBML `audit_action`."""
LOGIN = "LOGIN"
LOGIN_FAILED = "LOGIN_FAILED"
LOGOUT = "LOGOUT"
CONSOLIDATION_CREATE = "CONSOLIDATION_CREATE"
CONSOLIDATION_STATUS_CHANGE = "CONSOLIDATION_STATUS_CHANGE"
CONSOLIDATION_APPROVE = "CONSOLIDATION_APPROVE"
CONSOLIDATION_VERIFY = "CONSOLIDATION_VERIFY"
GROUP_CHANGE = "GROUP_CHANGE"
LEGAL_ENTITY_CHANGE = "LEGAL_ENTITY_CHANGE"
MEMBERSHIP_CHANGE = "MEMBERSHIP_CHANGE"
ASSIGNMENT_CHANGE = "ASSIGNMENT_CHANGE"
FILE_UPLOAD = "FILE_UPLOAD"
FILE_DELETE = "FILE_DELETE"
FILE_REPLACE = "FILE_REPLACE"
DOCUMENT_CONFIRM = "DOCUMENT_CONFIRM"
CONSOLIDATION_LOCK = "CONSOLIDATION_LOCK"
CONSOLIDATION_LOCK_TAKEOVER = "CONSOLIDATION_LOCK_TAKEOVER"
DISCLOSURE_EDIT = "DISCLOSURE_EDIT"
RECOGNIZED_DATA_EDIT = "RECOGNIZED_DATA_EDIT"
OSV_COUNTERPARTY_MAP = "OSV_COUNTERPARTY_MAP"
OSV_TYPE_OVERRIDE = "OSV_TYPE_OVERRIDE"
CORRECTION_CREATE = "CORRECTION_CREATE"
CORRECTION_EDIT = "CORRECTION_EDIT"
CORRECTION_REVOKE = "CORRECTION_REVOKE"
GOODWILL_EDIT = "GOODWILL_EDIT"
EXPORT = "EXPORT"
DIRECTORY_IMPORT = "DIRECTORY_IMPORT"
USER_ROLE_CHANGE = "USER_ROLE_CHANGE"
USER_CHANGE = "USER_CHANGE"
ROLE_PERMISSION_CHANGE = "ROLE_PERMISSION_CHANGE"
#: Реестр: имя enum в DBML (= имя типа в PostgreSQL) → класс.
ENUMS: dict[str, type[enum.Enum]] = {
"entity_type": EntityType,
"related_group_kind": RelatedGroupKind,
"account_kind": AccountKind,
"account_row_type": AccountRowType,
"business_segment": BusinessSegment,
"document_type": DocumentType,
"file_type": FileType,
"recognition_pipeline": RecognitionPipeline,
"period_quarter": PeriodQuarter,
"file_status": FileStatus,
"document_status": DocumentStatus,
"s3_bucket_role": S3BucketRole,
"recognition_status": RecognitionStatus,
"statement_type": StatementType,
"statement_line_status": StatementLineStatus,
"statement_form_variant": StatementFormVariant,
"document_issue_kind": DocumentIssueKind,
"issue_severity": IssueSeverity,
"issue_source": IssueSource,
"osv_group_type": OsvGroupType,
"counterparty_match_kind": CounterpartyMatchKind,
"osv_data_type": OsvDataType,
"consolidation_scenario": ConsolidationScenario,
"consolidation_approach": ConsolidationApproach,
"consolidation_status": ConsolidationStatus,
"correction_status": CorrectionStatus,
"document_check_result": DocumentCheckResult,
"le_history_event": LeHistoryEvent,
"ex_snapshot_status": ExSnapshotStatus,
"permission_object": PermissionObject,
"permission_action": PermissionAction,
"audit_section": AuditSection,
"audit_action": AuditAction,
}
def pg_enum(name: str) -> SAEnum:
"""Тип колонки для enum DBML `name`: нативный PG-enum `<схема>.<name>`, значения — `.value` членов.
Создание типа — поведение SQLAlchemy по умолчанию (`create_type=True`, `checkfirst`): `Base.metadata.create_all`
создаёт типы сам; миграция 0001 создаёт их явно.
"""
return SAEnum(
ENUMS[name],
name=name,
schema=SCHEMA,
native_enum=True,
values_callable=lambda e: [m.value for m in e],
)