arm-core/api/src/models/enums.py
Andrey Epifancev 4abfa03539 fix-волна ревью: delta статусов, блокировка версий консолидации, тесты (#96)
I-2: delta MODIFIED consolidations-api «Статусы Среза 4» (загрузка в консолидацию).
T1.1: шапки моделей — DBML v5.18.
T3.1: lock_versions_of_consolidation — двухшаговая блокировка (FOR UPDATE без членства, затем выборка членов);
тесты гонки и выборки.
M-1: тест миграции 0006 — порядок кварталов внутри года.
M-2: тест 404 для ЮЛ чужого филиала на столе своей консолидации.
T4.1: docstring supersede_previous — перенос строк.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-10 02:23:09 +04:00

357 lines
9.2 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.18 (28 штук) и фабрика `pg_enum` для PostgreSQL-колонок.
Источник истины — docs/model/data-model-v5.18.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 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,
"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],
)