Andrey Epifancev 186ae802e6 feat: seed ролей, прав, матрицы §10 и Головного офиса, загрузчик scripts.seed
Двухфазный загрузчик: валидация yaml целиком до записи (SeedError), затем upsert по
натуральному ключу без удалений; run_seed(session, *, dev, seed_dir) без commit, CLI коммитит.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-03 21:07:07 +04:00

70 lines
2.1 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.

"""Модель проверенного набора seed и отчёта о применении (без доступа к БД)."""
from dataclasses import dataclass, field
from src.models.enums import PermissionAction, PermissionObject
class SeedError(Exception):
"""Ошибка файлов seed (отсутствие, формат, ссылочная целостность); сообщение — по-русски, с файлом и записью."""
@dataclass(frozen=True)
class RegionalOfficeSeed:
name: str
is_head_office: bool
is_active: bool
@dataclass(frozen=True)
class RoleSeed:
code: str
name: str
description: str | None
is_system: bool
is_active: bool
@dataclass(frozen=True)
class PermissionSeed:
code: str
object_type: PermissionObject
action: PermissionAction
name: str
description: str | None
@dataclass
class SeedData:
"""Проверенный набор seed; ничего не знает о БД."""
regional_offices: list[RegionalOfficeSeed] = field(default_factory=list)
roles: list[RoleSeed] = field(default_factory=list)
permissions: list[PermissionSeed] = field(default_factory=list)
#: код роли -> коды прав (порядок как в файле)
role_permissions: dict[str, list[str]] = field(default_factory=dict)
@dataclass
class TableStat:
inserted: int = 0
updated: int = 0
unchanged: int = 0
@dataclass
class SeedReport:
"""Итог применения: по таблицам — сколько строк вставлено / обновлено / не изменилось."""
tables: dict[str, TableStat] = field(default_factory=dict)
def stat(self, table: str) -> TableStat:
return self.tables.setdefault(table, TableStat())
def format(self) -> str:
lines = ["Seed применён (вставлено / обновлено / без изменений):"]
lines += [
f" {name}: {stat.inserted} / {stat.updated} / {stat.unchanged}" for name, stat in self.tables.items()
]
return "\n".join(lines)