Section-based portal access, matrix прав по группам, аккаунтинг-портал,
управление группами пользователей, справочники, дашборд и общий каркас
навигации/стилей.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Remove the is_staff permission bridge, tighten intern credential handling with one-time PDFs and random seed passwords, and let staff manage cash registers from the portal.
Co-authored-by: Cursor <cursoragent@cursor.com>
Let admins set per-section access levels so operational data on pharmacy detail is no longer all-or-nothing for every logged-in user.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Строка поиска перенесена наверх страницы (над всем чатом), результаты
по-прежнему открываются в области сообщений
- В списке ЛС у собеседников-ботов рядом выводится метка «бот»
- Закрытые/архивные разговоры (delete_at>0) скрыты по умолчанию, показываются
только по галочке «Показувати закриті розмови» (тянем include_deleted=true)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Порядок каналов/ЛС — по реальному времени последнего поста (тянем per-channel,
т.к. last_post_at из списка каналов ненадёжен), архивные (delete_at>0) — вниз
- Непрочитанные: счётчик по websocket, бейдж на строке + жирное имя, префикс
«(N)» в тайтле, браузерное уведомление; сброс при открытии канала
- Кнопка «Написати в чат» на карточке сотрудника → /chat/?dm=<mm_id>,
чат открывает/создаёт ЛС с этим человеком (идемпотентный /channels/direct)
- Тесты кнопки чата в EmployeeDetailTests
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Единый скролл вместо жёсткого max-height:35% на ЛС и flex:1 на каналах
(убран пустой провал под каналами)
- Секции-заголовки — компактные uppercase-подписи в стиле портала
- Строки ЛС и каналов выровнены по единому левому краю (0.75rem)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Списки каналов и ЛС сортируются по last_post_at (свежие сверху)
- При открытии чата автоматически выбирается самая свежая розмова — сразу
видны последние сообщения, а не пустой экран
- Поиск сообщений через Mattermost /teams/{id}/posts/search: строка поиска
над лентой, результаты списком (кто/канал/время/текст), клик открывает канал
- Выход из поиска при открытии канала и смене команды
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 2FA: убраны /api/ и /media/ из ALLOWED_PREFIXES — staff-сессия без TOTP
больше не дотягивается до API/медиа (устройства в /api/ идут без staff-сессии)
- Nextcloud «Обмен»: writable только для staff (не для любого logged-in)
- Nextcloud путь отдела/адрес аптеки: safe_component() санитайзит сегмент
(сепараторы/управляющие/ведущие точки) в провижининге и в браузере
- Mattermost: shared secret кнопки «Виконано» перенесён из query string в
context (тело POST) — без утечки в логи/Referer
- Login: throttle на кэше (5 попыток / 5 мин, 429); logout только POST (CSRF),
logout-ссылки в шаблонах → POST-формы
Тесты обновлены под enforcement 2FA (login_2fa helper) и новые правила.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Заменяет статичный макет documents.html реальным браузером Group Folders:
- access.py: accessible_sections (разделы по правам: Компания/Обучение/Обмен,
отдел сотрудника, Кадровые дела для суперюзера) + safe_relpath (посегментная
валидация подпути от path traversal); раздел резолвится только из whitelist
- views: documents_browse/download/upload с проверкой раздела и пути на каждом
эндпоинте, запись — только в writable-разделы
- documents.html: вкладки разделов + ленивый HTMX-браузер с хлебными крошками,
навигацией по папкам, скачиванием и загрузкой
- documents_view отдаёт доступные разделы; тесты разделов, путей и авторизации
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- WebDAV-клиент (PROPFIND/GET/PUT/DELETE) под сервисным аккаунтом
- access.py: can_access_pharmacy_docs (аптека видит только свою) + safe_filename
(защита от path traversal); путь папки выводится только из объекта аптеки
- Вьюхи documents/download/upload/delete с проверкой доступа на каждом эндпоинте
- Вкладка «Документы» на pharmacy-detail с ленивой HTMX-загрузкой
- Тесты авторизации: свой/чужой скоуп, 403, traversal, аноним
Аптечные сотрудники учёток Nextcloud не имеют — доступ идёт через портал под
сервисным аккаунтом, вся авторизация на стороне ACORE.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Самая большая страница (1131 строка, ~155 строк): вкладки (оборудование/
заявки/провайдеры/расходники/работы), каталог моделей, формы выдачи/создания,
таблицы, статусы, панели, интернет-договоры, показания — помечены {% trans %}
и переведены на uk/en.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Учёт рабочего времени: заголовок, навигация по месяцам, фильтры,
столбцы таблицы, пустое состояние — {% trans %}; метрики (из вью)
переведены через gettext. uk/en.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Список публикаций, форма создания/редактирования, детальная (комментарии,
публикация в Mattermost, важное/закреплённое), JS-строки (загрузка картинок,
свернуть/развернуть) помечены {% trans %} и переведены на uk/en.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
HR-портал: метрики, вкладки (сотрудники/заявки/тренинги/вакансии/стажировка),
форма найма, отпуска/больничные, документы — помечены {% trans %} и
переведены на uk/en (включая строчные/смешанные строки, кнопки, hx-confirm).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Список аптек (фильтры, метрики, таблица, пагинация) и карточка аптеки
(инфо, лицензия, персонал, оборудование, интернет-договоры, показания
счётчиков) помечены {% trans %} и переведены на uk/en.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- FIELD_ENCRYPTION_KEY: production требует явный ключ (ImproperlyConfigured
при пустом), local — fallback на SECRET_KEY с предупреждением (crypto.py)
- MATTERMOST_INTERACTIVE_TOKEN: fail-closed токен для интерактивных кнопок
Mattermost (bot_service task-done URL + проверка в mattermost views)
- Ужесточение прав API (employees/visit_manager) + тесты
(employees, mattermost_connector, visit_manager)
- .env.example с описанием переменных; правки шаблонов (index/dislocation/pharmacies)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Настройки портала, профиль пользователя и структура офиса помечены
{% trans %} и переведены на uk/en.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Вкладки аптеки/офис, метрики, фильтры, таблицы, пагинация, карта и её
popup/JS-строки помечены {% trans %} (в т.ч. внутри <script>, с обходом
кавычек) и переведены на uk/en. 51 строка.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Task.STATUS_CHOICES/PRIORITY_CHOICES переведены на русские msgid
(консистентно с ru-базой); миграция choices
- task_detail_view: метки ролей через gettext
- Шаблоны tasks/task-detail/task-edit размечены {% trans %}; статусы,
приоритеты, чек-лист, комментарии, участники, кнопки действий — uk/en
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Личные данные, контакты, работа, интеграции, руководство, статусы, задачи —
помечены {% trans %} и переведены на uk/en.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
JS определял плейсхолдер сравнением с захардкоженным «Завантаження...», а
текст загрузчика стал переводиться ({% trans %}) — из-за чего в ru/en
контент не подгружался (и при обычной загрузке, и после смены языка).
Теперь плейсхолдер определяется по #page-loader (язык-независимо).
Переключатель языка возвращает на текущую страницу (next=pathname).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Все видимые строки главной страницы помечены {% trans %} (русский msgid),
переведены на uk/en; часть переиспользует msgid из меню. Сняты fuzzy-метки,
неверные авто-переводы перезаписаны корректными. .mo пересобраны.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Мультиязычность: русский — базовый (msgid), украинский и английский — переводы.
- Настройки: LocaleMiddleware, LANGUAGES=[ru,uk,en], LOCALE_PATHS, i18n
context_processor; urls: django.conf.urls.i18n (set_language)
- Шелл index.html: {% load i18n %}, все пункты навигации/меню/пользовательского
меню/нижней навигации помечены {% trans %}; динамический <html lang>;
переключатель языков в хедере (select -> set_language)
- Каталоги locale/uk и locale/en: переведены строки меню/шелла (34), собраны .mo
- .gitignore: разрешено трекать locale/**/*.mo (нужны на проде, CI нет)
Остальные страницы пока на украинском (хардкод) — переводятся дальше поэтапно.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
При створенні HR-заявки з обраними базами/доступами тепер одразу ставиться
задача IT-відділу (замість тікета на затвердженні):
- TaskChecklistItem: чек-лист задачі, виконавець відмічає зроблене
(task-detail: чекбокси, лічильник виконаного, хто/коли відмітив)
- create_hiring_request → _create_access_task: задача з чек-листом по базах,
creator = HR (постановник), co_executors = IT-група (тригерить сповіщення
ботом Ричард), priority=high, due_date рахується за робочим часом
- add_working_hours (visit_manager/services): дедлайн за робочим вікном
09:00–18:00 з урахуванням вихідних і свят (Holiday)
- Постановнику (HR) бот пише, що заявку взято в роботу, строк — 24 год
робочого часу (до розрахованої дати)
- approve більше не створює дублюючий IT-тікет (доступи вже задачею)
- HiringRequest.access_task; чек-лист в адмінці задач (inline)
- Тести: hiring (задача+чек-лист, approve без тікета), робочі години
(вихідні/свята), відмітка чек-листа через в'ю
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Активовано закладений механізм Directory.location_types (використовується в
Employee.clean(), але справочник був порожній):
- Міграція core 0005: сид довідника «Тип локации» (office/pharmacy/warehouse) —
тепер посадам можна призначати типи локацій в адмінці (M2M location_types)
- _hr_portal_context віддає карту hr_post_location_types {post_id: [коди]}
- Форма найму: селект «Посада» фільтрується за обраним типом локації
(hrHiringFilterPosts). Порожній список типів у посади = доступна скрізь
(та сама семантика, що в clean()); невідповідну обрану посаду скидає
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Вкладку «Стажування» прибрано з панелі вкладок; біла форма заявки на найм
(панель hr-panel-hiring: форма + список заявок) тепер відкривається кнопкою
«Створити» (hrTabSwitch('hiring')). Кнопка й панель — лише для staff.
Автовідкриття панелі після створення заявки (hr_active_tab) працює як раніше.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Аватар співрозмовника напроти особистого повідомлення (лівий список):
chatBuildChannelRow отримав опцію avatar; id співрозмовника ЛС резолвиться
в chatResolveDmLabel і підвантажує фото (chatApplyAvatar). Групові ЛС —
без фото, з ініціалами.
- Верхній перемикач «кімнат» — команди Mattermost (Офіс / Аптеки / Склад):
chatRenderTeamSwitcher/chatSelectTeam; chatRenderChannelList фільтрує канали
за обраною командою; за замовчуванням — перша команда. ЛС показуються завжди.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Было: статичный макет timetrack.html (хардкод «10 співробітників»,
пустой tbody, JS не наполнял). Стало — реальные данные из WorkShift:
- timetrack_view агрегирует смены за выбранный месяц по сотрудникам:
часы (Sum duration), дни (distinct date), незакрытые смены (без ухода),
среднее/день; сводные метрики; счётчики по типам локаций
- Фильтр по типу локации (всі/офіс/аптеки) и помесячная навигация —
через HTMX, с сохранением параметров в URL
- Шаблон перестроен в стиле портала (метрики, таблица, пагинация);
строки ведут на детальную сотрудника; пустое состояние
- Невалидный месяц откатывается на текущий
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ad_connector: страницы управления OU и импорта из AD, поле ad_ou_dn
в Directory, ADSyncLog; расширение sync-сервиса и клиента
- mattermost_connector: personal access token шифруется (Fernet,
token_service), бот-сервис, команды создания бота и синхронизации;
публикация постов в каналы. Тесты (19)
- core: ConnectorConfig, Directory (ad_ou_dn), обновления админки
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Task: ответственный/соисполнители/наблюдатели (M2M), статусы, приоритет,
дедлайн. Видимость for_user(), наблюдатели не меняют статус
- Список с табами-статусами (один aggregate вместо 4 count), детальная
со сменой статуса и комментариями, edit/delete с правами
- Выбор людей — дерево отделов с фото/должностями и поиском (people-picker),
вместо select multiple; назначение задачи со страницы сотрудника
- ROLE_PREFETCH с select_related('post') против N+1; сигналы
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Post (категории, важное/закреплено/опубликовано, автор) + PostComment;
тело — HTML из TinyMCE, санитизация nh3 в save() (XSS), загрузка картинок
отдельным endpoint с проверкой содержимого (data:-URI вырезаются)
- Лента с полным выводом постов, фильтры, сворачивание длинных;
детальная страница с комментариями; edit — автор/staff, delete — автор
- Публикация постов в каналы Mattermost (mattermost_targets), сигналы
- Тесты (40): публикация/черновики, права, санитизация, картинки,
выравнивание, комментарии, лента/дашборд
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ad_connector: restrict provisioning to office employees
(user_location_type='office') in sync service, signals and command;
disable AD account on transfer out of office, re-enable on return
- ad_connector: /ad-mapping/ page (staff only) — match office employees
to AD accounts with suggestions by email/login/full name, link/unlink/
create actions, list of unmatched domain accounts; sidebar nav item
- core: auto-rebuild treenode Directory tree (_path/_depth) after
import-export imports and post_migrate; "rebuild tree" button in
DirectoryAdmin and rebuild_directory_tree management command
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Remove Employee.role CharField — was a display-only label with no
actual permission logic
- 3 migrations: create groups, migrate data, remove field
- Admin: list/filter/fieldset now use groups; added groups_display method
- Serializer: role → groups (SlugRelatedField returning group names)
- Template: get_role_display → groups.first.name
- EmployeePermissionOverride and PermissionGroup remain for fine-grained
per-employee and per-group permission management