- RelatedGroupMember.kind (related_group_kind, NOT NULL) между legal_entity_id и valid_from, как в DBML; частичный уникальный индекс uq_related_group_member_entity_kind_current (legal_entity_id, kind) WHERE is_current — ЮЛ одновременно в одной ГСК и одной ГСЗ. - AuditAction: LEGAL_ENTITY_CHANGE (после GROUP_CHANGE), USER_CHANGE (после USER_ROLE_CHANGE). - Последовательности company_group_code_seq / related_group_code_seq в metadata (design D-5). - Миграция 0002_dbml_v5_14: related_group_member пересоздаётся с переносом строк (kind из группы), чтобы порядок колонок совпал с DBML и create_all; ALTER TYPE ADD VALUE ×2; downgrade пересоздаёт audit_action v5.13. - DBML_VERSION = 5.14, пути к data-model-v5.14.dbml (Makefile, dbml_parity), тесты: откат на шаг, перенос строк, уникальность gsk+gsz, офлайн-SQL до head. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
"""Enum'ы ORM против блоков `Enum {}` DBML v5.14: имена, значения и их порядок (без БД)."""
|
|
|
|
import enum
|
|
import re
|
|
|
|
import pytest
|
|
from sqlalchemy import Enum as SAEnum
|
|
|
|
from src.models import DBML_VERSION
|
|
from src.models.enums import ENUMS, pg_enum
|
|
from tests.dbml_helpers import dbml_path, load_dbml
|
|
|
|
EXPECTED_ENUM_COUNT = 27
|
|
|
|
|
|
def test_dbml_version_format() -> None:
|
|
assert re.fullmatch(r"\d+\.\d+", DBML_VERSION)
|
|
assert DBML_VERSION == "5.14"
|
|
assert f"v{DBML_VERSION}" in dbml_path().name
|
|
|
|
|
|
def test_enums_count_and_names_match_dbml() -> None:
|
|
dbml_enums = {e.name for e in load_dbml().enums}
|
|
assert len(dbml_enums) == EXPECTED_ENUM_COUNT
|
|
assert set(ENUMS) == dbml_enums
|
|
|
|
|
|
def test_enum_values_match_dbml_in_order() -> None:
|
|
for dbml_enum in load_dbml().enums:
|
|
expected = [item.name for item in dbml_enum.items]
|
|
actual = [m.value for m in ENUMS[dbml_enum.name]]
|
|
assert actual == expected, f"enum {dbml_enum.name}: ожидалось {expected}, фактически {actual}"
|
|
|
|
|
|
def test_enum_classes_are_str_enums_with_member_name_equal_value() -> None:
|
|
for name, cls in ENUMS.items():
|
|
assert issubclass(cls, enum.Enum) and issubclass(cls, str), name
|
|
assert [m.name for m in cls] == [m.value for m in cls], name
|
|
|
|
|
|
def test_cyrillic_values_kept_verbatim() -> None:
|
|
assert [m.value for m in ENUMS["entity_type"]] == ["ЮЛ", "ИП"]
|
|
|
|
|
|
def test_pg_enum_factory_gives_dbml_named_type_in_dkb_schema() -> None:
|
|
for name, cls in ENUMS.items():
|
|
sa_enum = pg_enum(name)
|
|
assert isinstance(sa_enum, SAEnum)
|
|
assert sa_enum.name == name
|
|
assert sa_enum.schema == "dkb"
|
|
assert sa_enum.native_enum is True
|
|
assert sa_enum.enums == [m.value for m in cls], name
|
|
|
|
|
|
def test_pg_enum_unknown_name_fails() -> None:
|
|
with pytest.raises(KeyError):
|
|
pg_enum("no_such_enum")
|