"""Каталог колонок таблицы дислокации аптек (whitelist). Секреты (пароль Carbonio и т.п.) сюда не входят. Колонка ``pharmacy`` всегда обязательна, но порядок среди колонок свободный. """ from __future__ import annotations from dataclasses import dataclass from django.utils.translation import gettext_lazy as _ LOCKED_KEY = 'pharmacy' STANDARD_COLUMNS = [ 'pharmacy', 'organization', 'head', 'staff', 'phone', 'hours', 'status', 'generator', 'inverter', 'mikrotik', 'provider', 'contract', 'gpon', ] HR_COLUMNS = [ 'pharmacy', 'organization', 'head', 'staff', 'curator', 'manager', ] OPS_COLUMNS = [ 'pharmacy', 'region', 'phone', 'hours', 'status', 'category', 'generator', 'inverter', 'mikrotik', 'provider', 'contract', 'gpon', ] @dataclass(frozen=True) class ColumnDef: key: str label: str sort_type: str # 'string' | 'number' locked: bool = False COLUMN_DEFS: dict[str, ColumnDef] = { 'pharmacy': ColumnDef('pharmacy', _('Аптека'), 'number', locked=True), 'organization': ColumnDef('organization', _('Организация'), 'string'), 'head': ColumnDef('head', _('Заведующий'), 'string'), 'staff': ColumnDef('staff', _('Персонал'), 'number'), 'phone': ColumnDef('phone', _('Телефон'), 'string'), 'hours': ColumnDef('hours', _('Режим работы'), 'string'), 'status': ColumnDef('status', _('Статус'), 'number'), 'region': ColumnDef('region', _('Регион'), 'string'), 'category': ColumnDef('category', _('Категория'), 'string'), 'curator': ColumnDef('curator', _('Куратор'), 'string'), 'manager': ColumnDef('manager', _('Ответственный менеджер'), 'string'), 'license': ColumnDef('license', _('Лицензия'), 'string'), 'vat': ColumnDef('vat', _('ПДВ'), 'string'), 'email': ColumnDef('email', _('Email'), 'string'), 'generator': ColumnDef('generator', _('Генератор'), 'string'), 'inverter': ColumnDef('inverter', _('Инвертор'), 'string'), 'mikrotik': ColumnDef('mikrotik', _('MikroTik'), 'string'), 'provider': ColumnDef('provider', _('Провайдер'), 'string'), 'contract': ColumnDef('contract', _('Договор'), 'string'), 'gpon': ColumnDef('gpon', _('GPON'), 'string'), } ALLOWED_KEYS = frozenset(COLUMN_DEFS) def normalize_columns(keys) -> list[str]: """Оставляет только известные ключи без дублей; ``pharmacy`` всегда в наборе.""" seen = set() result = [] for key in keys or []: if key not in ALLOWED_KEYS or key in seen: continue seen.add(key) result.append(key) if LOCKED_KEY not in result: result.insert(0, LOCKED_KEY) return result def column_defs_for(keys: list[str]) -> list[ColumnDef]: return [COLUMN_DEFS[k] for k in keys if k in COLUMN_DEFS] def all_column_defs() -> list[ColumnDef]: # pharmacy first in the registry list, then the rest in declaration order rest = [d for k, d in COLUMN_DEFS.items() if k != LOCKED_KEY] return [COLUMN_DEFS[LOCKED_KEY], *rest] def resolve_columns_for_user(user) -> list[str]: """Персональный override → пресет отдела → is_default → STANDARD.""" custom = getattr(user, 'dislocation_columns', None) if custom: return normalize_columns(custom) from apps.locations.models import DislocationColumnPreset dept_id = getattr(user, 'department_id', None) if dept_id: preset = ( DislocationColumnPreset.objects .filter(department_id=dept_id) .order_by('id') .first() ) if preset and preset.columns: return normalize_columns(preset.columns) preset = DislocationColumnPreset.objects.filter(is_default=True).first() if preset and preset.columns: return normalize_columns(preset.columns) return list(STANDARD_COLUMNS)