"""Реестр разделов портала — единый источник для меню и проверки на view.""" from __future__ import annotations from dataclasses import dataclass @dataclass(frozen=True) class PortalSection: key: str path: str label: str nav: str # main | manage | support | none perm: str | None = None # 'core.access_' or None = any authenticated # Ограниченные разделы — нужны Django permissions core.access_* RESTRICTED_KEYS = ( 'hr_portal', 'recruiting', 'structure', 'timetrack', 'databases', 'reports', 'purchases', 'email', 'pharmacies', 'rro', 'utilities', 'internet_billing', 'it_manager', 'ad_mapping', ) # UI-заглушки (мок-страницы): в меню и по URL только для staff (доступ к /admin/). STUB_SECTION_KEYS = frozenset({ 'purchases', }) PORTAL_SECTIONS: dict[str, PortalSection] = { 'dashboard': PortalSection('dashboard', '/dashboard/', 'Главная', 'main'), 'news': PortalSection('news', '/news/', 'Новости', 'main'), 'employees': PortalSection('employees', '/employees/', 'Сотрудники', 'main'), 'tasks': PortalSection('tasks', '/tasks/', 'Задачи', 'main'), 'dislocation': PortalSection('dislocation', '/dislocation/', 'Дислокация', 'main'), 'documents': PortalSection('documents', '/documents/', 'Документы', 'main'), 'email': PortalSection('email', '/email/', 'Почта', 'main', 'core.access_email'), 'chat': PortalSection('chat', '/chat/', 'Чат', 'main'), 'calendar': PortalSection('calendar', '/calendar/', 'Календарь', 'main'), 'databases': PortalSection('databases', '/databases/', 'Системные справочники', 'main', 'core.access_databases'), 'reports': PortalSection('reports', '/reports/', 'Отчёты', 'main', 'core.access_reports'), 'purchases': PortalSection('purchases', '/purchases/', 'Закупки', 'main', 'core.access_purchases'), # Открыт всем; кадровые операции — по core.access_hr_portal (user_can_manage_hr_portal). 'hr_portal': PortalSection('hr_portal', '/hr-portal/', 'HR-портал', 'main'), 'settings': PortalSection('settings', '/settings/', 'Настройки', 'main'), 'profile': PortalSection('profile', '/profile/', 'Профиль', 'none'), 'structure': PortalSection('structure', '/structure/', 'Структура', 'manage', 'core.access_structure'), 'pharmacies': PortalSection('pharmacies', '/pharmacies/', 'Аптеки', 'manage', 'core.access_pharmacies'), 'pharmacy_detail': PortalSection('pharmacy_detail', '/pharmacies/', 'Карточка аптеки', 'none'), 'user_groups': PortalSection('user_groups', '/user-groups/', 'Группы пользователей', 'manage'), 'accounting_portal': PortalSection('accounting_portal', '/accounting/', 'Операционный учёт', 'main'), 'rro': PortalSection('rro', '/rro/', 'РРО / ПРРО', 'none', 'core.access_rro'), 'utilities': PortalSection('utilities', '/utilities/', 'Коммунальные услуги', 'none', 'core.access_utilities'), 'internet_billing': PortalSection( 'internet_billing', '/accounting/?tab=internet', 'Оплата провайдеров', 'none', 'core.access_internet_billing', ), 'recruiting': PortalSection('recruiting', '/hr-portal/?tab=vacancies', 'Рекрутинг', 'none', 'core.access_recruiting'), 'timetrack': PortalSection('timetrack', '/timetrack/', 'Учёт рабочего времени', 'none', 'core.access_timetrack'), 'help': PortalSection('help', '/help/', 'Справка', 'support'), 'it_support': PortalSection('it_support', '/it-support/', 'IT-поддержка', 'support'), 'it_manager': PortalSection('it_manager', '/it-manager/', 'IT-отдел', 'support', 'core.access_it_manager'), 'ad_mapping': PortalSection('ad_mapping', '/ad-mapping/', 'Active Directory', 'support', 'core.access_ad_mapping'), } def get_section(key: str) -> PortalSection | None: return PORTAL_SECTIONS.get(key) def portal_permission_codenames() -> list[tuple[str, str]]: """Список (codename, name) для Meta.permissions модели PortalAccess.""" return [ (f'access_{key}', f'Доступ к разделу: {PORTAL_SECTIONS[key].label}') for key in RESTRICTED_KEYS ]