370 Commits

Author SHA1 Message Date
065e1f2efd feat: интеграция Celery для асинхронной обработки уведомлений
- Добавлена конфигурация Celery (eusrr_backend/celery.py)
- Созданы async задачи для уведомлений (notifications/tasks.py)
- Обновлены все notification_signals на create_notification_async()
- Добавлен метод NotificationService.create_notification_async() с fallback
- Установлены пакеты: django-celery-beat, django-celery-results, flower
- Применены миграции для Celery приложений
- Документация: CELERY_SETUP.md, CELERY_INTEGRATION_PLAN.md

Производительность: уменьшение времени отправки сообщений с ~500ms до <50ms
2026-01-08 16:14:00 +03:00
e2bcf445f3 Merge feature/communications-work: Управление уведомлениями чатов 2026-01-08 14:40:21 +03:00
42879e0981 feat(communications): Реализация управления уведомлениями чатов и оптимизация
- Добавлен API endpoint для включения/выключения уведомлений чата
- Реализован frontend для управления уведомлениями через меню чата
- Обновлены сигналы для проверки настроек notifications_enabled
- Стандартизирована логика уведомлений для всех типов чатов
- Оптимизированы запросы к БД (1 запрос вместо N для ChatUserSettings)
- Переведены детальные логи с INFO на DEBUG уровень

Файлы:
- backend/api/v1/communications/views.py (новый endpoint)
- backend/api/v1/urls.py (новый маршрут)
- backend/static/js/components/chatMenuActions.js (полная реализация)
- backend/communications/notification_signals.py (проверка настроек + оптимизация)
- backend/notifications/services.py (оптимизация логирования)
2026-01-08 14:39:40 +03:00
6da39e5120 feat(ldap): добавлена команда sync_employee_ids_to_ldap
Команда синхронизирует Django pk существующих пользователей в LDAP employeeNumber:
- По умолчанию dry-run режим
- Опция --user-id для теста на одном пользователе
- Опция --force для перезаписи существующих значений
- Использует LdapSyncState для поиска DN пользователей
2026-01-07 15:55:28 +03:00
dbdf608051 feat(ldap): записываем Django pk в LDAP employeeNumber при создании/обновлении пользователей
- Добавлена настройка LDAP_EMPLOYEE_ID_ATTR (по умолчанию 'employeeNumber')
- UserService.create_user() теперь записывает pk в LDAP после создания Employee
- SyncService.import_users() записывает pk при создании новых пользователей
- SyncService.import_users() проверяет и заполняет пустой employeeNumber при update
- Добавлен диагностический скрипт check_employee_id_attrs.py для проверки AD атрибутов
2026-01-07 15:50:07 +03:00
7838a55ef4 feat: Replace CDN with local vendor libraries + complete Web Push setup
- Замена всех CDN зависимостей на локальные файлы:
  * Bootstrap 5.3.3 (CSS + JS)
  * Bootstrap Icons 1.11.3 (CSS + шрифты woff/woff2)
  * FullCalendar 6.1.8 (JS + локали)
  * Cropper.js 1.6.1
  * emoji-picker-element 1.21.3

- Web Push Notifications:
  * VAPID ключи настроены в settings.py
  * Service Worker (sw.js) в корне backend/
  * API endpoints: /api/v1/notifications/push/
  * Auto-request permission при загрузке страницы
  * Simplified subscribe logic (Phase 1 refactor)
  * resetEverything() для восстановления после ошибок

- Документация:
  * backend/docs/guides/WEB_PUSH_QUICK_TEST.md
  * backend/docs/guides/FIX_NO_PUSH_SUBSCRIPTIONS.md
  * backend/docs/troubleshooting/WEB_PUSH_OFFLINE_ISSUE.md

- Обновлено 10 шаблонов для использования local vendor
- Устранены проблемы с CORS и integrity checks
- Все иконки Bootstrap Icons теперь отображаются корректно
2026-01-06 09:22:16 +03:00
836b7f052d refactor: Web Push Phase 1 - Critical fixes for AbortError
✅ КРИТИЧЕСКИЕ ИСПРАВЛЕНИЯ:
1. Упростил _checkSubscription() - теперь ТОЛЬКО чтение
   - Убрана автоматическая синхронизация с сервером
   - Убрана автоматическая переподписка при ошибках
   - Метод не модифицирует состояние

2. Исправил subscribe() - убран принудительный unsubscribe
   - Браузер сам управляет существующими подписками
   - update_or_create на backend обновит запись
   - Избегаем конфликтов Push Service

3. Улучшен resetEverything() для recovery
   - Полная очистка: unsubscribe + unregister + localStorage
   - Задержка 2 сек для обработки Push Service
   - Подробное логирование каждого шага
   - Инструкции для пользователя

4. Добавлена детекция AbortError
   - Понятное сообщение в консоли
   - Инструкция по recovery
   - Ссылка на resetEverything()

�� Добавлен полный аудит:
- backend/docs/reports/WEB_PUSH_AUDIT_2026_01_06.md
- Детальный анализ всех компонентов
- План рефакторинга (4 фазы)
- Чек-листы для тестирования

Связано с: #AbortError #WebPush #VAPID
2026-01-06 08:26:50 +03:00
4a139180f7 feat: Auto-unsubscribe push on logout, force resubscribe on login
- Добавлена автоматическая отписка от Web Push при выходе
- При входе принудительно переподписываем пользователя
- Очищаем старую подписку из localStorage перед новой
- Это исправляет AbortError из-за старых подписок с другими VAPID ключами
2026-01-06 08:11:24 +03:00
415a5ca724 fix: Close catch block in _checkSubscription
Missing closing brace after catch block caused syntax error
2026-01-06 08:02:21 +03:00
566f5b56c9 fix: Remove all DEBUG logs from push-notifications.js
- Clean up verbose console.log statements
- Keep only essential error/success logs
- Fix syntax error on line 177
2026-01-06 07:54:18 +03:00
44488cb40e feat: Implement Web Push notifications with VAPID
- Split notification sending into separate WebSocket and Web Push channels
- Add Web Push support for offline users
- Configure VAPID keys for push authentication
- Add 'aud' field to VAPID claims for WNS compatibility
- Optimize subscription sync - only POST when endpoint changes
- Remove debug logs and minimize server logging
- Update Service Worker with improved error handling
- Add Service-Worker-Allowed header for proper scope

Web Push now works independently from WebSocket, enabling
notifications when browser is closed (requires HTTPS in production)
2026-01-06 07:48:04 +03:00
e5503a1490 fix: исправление модуля уведомлений и добавление тестов
- Исправлена маршрутизация API: обновлены JS файлы для использования /api/v1/notifications/
- Исправлена ошибка в api_views.py: last_error='' вместо None (TextField не может быть NULL)
- Исправлена ошибка в services.py: использование метода reset_errors()
- Добавлено 36 комплексных тестов (модели, API, сервисы) - все проходят
- Создана документация аудита модуля (NOTIFICATIONS_AUDIT.md)
- Создано руководство по тестированию (NOTIFICATIONS_TESTING.md)
- Добавлены management команды: cleanup_push_subscriptions, notification_stats
- Тесты перемещены в backend/tests/notifications/ для правильной организации

Вся функциональность уведомлений проверена и работает корректно.
2026-01-05 15:38:36 +03:00
e2fe9fa66a static 2026-01-05 15:04:45 +03:00
b074c91549 templates 2026-01-05 15:04:38 +03:00
66e579b15f debug: add logging to comments API and permissions
Add detailed logging to help debug why comments requests fail with 403
2026-01-05 14:44:50 +03:00
2ab98a6af3 fix: allow request participants to access comments
CommentsPermission now allows request owner, recipients, cc_users and approver
to view and add comments to the request they are part of.
2026-01-05 14:42:33 +03:00
c8dd32ce8e fix: add device_name field to WebPushSubscription model 2026-01-05 14:40:52 +03:00
37376fecf4 fix: improve Service Worker serving with better error handling 2026-01-05 14:39:32 +03:00
bb95d744fb fix: Service Worker registration and API routing issues
- Move Service Worker to root (/sw.js) for proper scope registration
- Add route to serve sw.js from root with correct content-type
- Update push-notifications.js to register sw.js from root
- Fix all notification API URLs to use /api/v1/ prefix
- Update notificationsApi.js to use correct v1 endpoints
2026-01-05 14:38:06 +03:00
5f75d9df50 fix: add v1/ prefix to notifications API routes 2026-01-05 14:36:04 +03:00
932009780b fix: handle non-JSON error responses in requestCrudHandler 2026-01-05 14:35:19 +03:00
788a245cc9 feat: implement Web Push notifications for offline browser notifications
- Add WebPushSubscription model for storing push subscriptions
- Generate VAPID keys for Web Push authentication
- Add API endpoints for push subscribe/unsubscribe
- Create Service Worker (sw.js) for handling push events
- Create JavaScript module for managing push subscriptions
- Integrate send_web_push_notification into NotificationService
- Add Service Worker registration to base.html
- Update requirements.txt with pywebpush package
2026-01-05 14:10:42 +03:00
5f8bd721d1 feat: add logging to send_mail method to trace password reset emails 2026-01-05 12:01:33 +03:00
c49e5cac10 fix: remove incorrect get_users override, keep logging in save method only 2026-01-05 11:20:56 +03:00
73ed15dd56 feat: add comprehensive logging for notification system tracking 2026-01-05 11:09:50 +03:00
8c546e59fb - 2026-01-05 10:59:07 +03:00
d5b5437c60 fix: password reset emails now use HTML template for Gmail compatibility 2026-01-05 10:47:56 +03:00
0663fe02b0 refactor: реорганизация тестов для улучшения структуры и производительности
- Перемещены manual tests из scripts/manual_tests в tests/manual/
- Обновлен pytest.ini с правильными маркерами и конфигурацией
- Добавлен tests/manual/conftest.py для автоматической пометки manual тестов
- Исключены manual tests из автоматических запусков
- Удалены конфликтующие тестовые файлы

Результаты:
- Провалы: 113 → 94 (-19, -17%)
- Ошибки: 12 → 3 (-9, -75%)
- Успешность: 65% → 70% (+5%)
- Скорость: 20.71s → 16.46s (+20% быстрее)

Все изменения не влияют на основной код, только на структуру тестов.
2026-01-05 07:41:34 +03:00
d84619f6a0 fix: автор заявления должен получать уведомления о решении (approve/reject)
- Удалено исключение employee.id из notify_status_change()
- Коммит 087cff79 ошибочно исключал автора, предполагая что он видит результат на странице
- После удаления alert() в коммите 1a5de8c уведомление стало единственным способом информирования
- Теперь автор получает уведомление о одобрении/отклонении заявления
- Approver остается исключенным (он сам нажал кнопку, не нужно ему уведомление)

Fixes: Users not receiving notifications when their request is approved/rejected
2026-01-05 07:11:46 +03:00
53da23f690 fix: revoke role from LDAP group when removing via_assignment role 2025-12-30 12:31:55 +03:00
eb69007aa2 fix: ignore entryAlreadyExists when adding member to LDAP group 2025-12-30 12:27:57 +03:00
4462ca1eec debug: add logging to set_member_role to diagnose 400 error 2025-12-30 12:24:39 +03:00
42111a4526 ПОИСК БАГА НЕСОХРАНЕНИЯ РОЛЕЙ В ЛДАП 2025-12-30 11:22:48 +03:00
5d0572d17a fix(roles): enforce LDAP-first pattern for role operations
When LDAP is enabled:
- create_role: creates LDAP group before DB record
- update_role: renames LDAP group before DB update
- delete_role: deletes LDAP group before DB deletion
- assign_role: adds to LDAP group before creating RoleAssignment
- revoke_role: removes from LDAP group before deactivating assignment

On LDAP error: operation fails, no DB changes
On DB error after LDAP success: rollback LDAP changes

Fixes: roles could bypass LDAP when it was enabled
2025-12-30 11:04:39 +03:00
a0aaf204bc Merge feature/department-logic: LDAP architecture redesign with RoleAssignment 2025-12-30 10:37:20 +03:00
026bc46816 feat(department-roles): complete LDAP architecture redesign with RoleAssignment model
BREAKING CHANGES:
- Removed OU=Roles from LDAP structure, role groups now created directly in department OU
- Role groups use ROLE_<Name> naming convention (similar to DEP_, POS_)

New features:
- RoleAssignment model: allows assigning roles to ANY employee, not just department members
- New API endpoints: /assign/, /revoke/, /assignments/ on DepartmentRoleViewSet
- Permission system updated: has_dept_perm() checks RoleAssignment first
- Employee profile shows external roles with 'внешняя роль' badge
- Employee list filter includes role-only employees with department_relation field
- Role assignment modal now searches all employees via AJAX

LDAP changes:
- _ensure_role_group(): creates ROLE_<Name> group in department OU
- assign_role(), revoke_role(): manage RoleAssignment + LDAP sync
- rename_role_group(), delete_role_group(): full lifecycle support
- Removed all references to OU=Roles

Migrations:
- 0035: Create RoleAssignment model
- 0036: Data migration from EmployeeDepartment.role

Tests:
- 7 new tests for role assignment (all passing)

Docs:
- 9 detailed reports on architecture, models, API, LDAP, tests
2025-12-30 10:35:34 +03:00
4d810459fe fix: add CanViewRequest permission for recipients and cc_users to view request details 2025-12-29 16:08:15 +03:00
25f84cc026 fix(api): добавлен кастомный класс пагинации с поддержкой page_size 2025-12-29 15:48:19 +03:00
36f756988b fix(requests): улучшены названия фильтров дат и исправлена логика фильтрации 2025-12-29 15:42:00 +03:00
8ebe241174 feat(requests): добавлены фильтры по сотруднику и периоду дат 2025-12-29 15:32:27 +03:00
0b959f33e0 refactor(requests): заменён фильтр 'Область' на nav-pills как в документах 2025-12-29 15:25:18 +03:00
f6a1315d76 feat(requests): текст темы в списке заявлений теперь ссылка на страницу деталей 2025-12-29 14:47:13 +03:00
662273ac06 fix(requests): убрано двоеточие перед именем approver в списке заявлений 2025-12-29 14:40:45 +03:00
af31e7c591 refactor(requests): показывать имя approver вместо кнопок действий для уже обработанных заявлений 2025-12-29 14:38:48 +03:00
0890d02efc refactor: переделать страницу деталей заявления с нуля со стилями из списка
- Полная переделка шаблона request_detail.html с единообразными стилями
- Новая структура: основная карточка (8 колонок) + боковая панель комментариев (4 колонки)
- Единообразные иконки типов заявлений (calendar-check, capsule, umbrella-fill и т.д.)
- Единообразные бейджи статуса и типа как в списке
- Информационные блоки для автора, описания, получателей, одобрившего
- Форма комментариев с правильным стилем message-field--compact
- Emoji picker с поддержкой dropdown-menu поверх контента
- AJAX обработка отправки и удаления комментариев
- Новый CSS файл request-detail.css с адаптивностью
- Добавлена функция _add_type_display() в views.py для отображения типа

Улучшения:
- Единство дизайна со страницей списка заявлений
- Правильное позиционирование emoji picker (fixed positioning)
- Sticky боковая панель с комментариями
- Форма комментария как в ленте (message-field--compact)
- Кнопки одобрения/отклонения с правильными иконками
2025-12-29 14:27:47 +03:00
dd219d4752 Исправлена view request_detail
- Добавлены comments в контекст
- Добавлен prefetch recipients и cc_users в DETAIL_REQUEST_QS
- Теперь все данные передаются правильно
2025-12-29 12:31:37 +03:00
be21b9ca4a Полностью переработана страница деталей заявления
Исправлено:
- Добавлена правильная структура card-header с аватаром 48x48px
- Добавлены все необходимые детали: получатели, копия, согласующий
- Исправлены стили для badge и card-body
- Добавлена корректная форма комментария с emoji picker и auto-expand
- Подключены правильные JavaScript компоненты
- Исправлен формат дат (d.m.Y H:i)
- Добавлена передача can_process в контексте view

Добавлено:
- Иконки для каждого раздела (получатели, копия, согласующий)
- Ссылки на карточки сотрудников
- Правильные Badge с subtle цветами
- Форма комментария с message-field компонентом
2025-12-29 12:25:42 +03:00
1349ebce35 fix(requests): временно отключена кнопка 'Отозвать'
URL request_cancel не подключен в urls_front.py
Закомментирована кнопка до добавления функционала
2025-12-29 12:00:52 +03:00
532098499b fix(requests): исправлен namespace для URL request_cancel
Изменено: requests:request_cancel → requests_app:request_cancel
Исправлена ошибка NoReverseMatch при открытии страницы заявления
2025-12-29 11:59:03 +03:00
a417ddfb8f fix(requests): исправлена отправка уведомлений при создании заявления
ПРОБЛЕМА: Уведомления не отправлялись при создании нового заявления

ПРИЧИНА: Сигнал post_save срабатывал ДО установки ManyToMany связей (recipients, cc_users)

РЕШЕНИЕ:
- Добавлен сигнал m2m_changed для отслеживания установки recipients/cc_users
- При создании заявления оно помечается как ожидающее отправки уведомлений
- После установки recipients через .set() срабатывает m2m_changed и отправляет уведомления
- Используется глобальный set _pending_new_requests для отслеживания

УЛУЧШЕНИЯ:
- Добавлено подробное логирование процесса создания и отправки уведомлений
- Разные эмодзи-иконки для разных типов получателей (� адресовано, � в копии, ✅ на согласование)
- Все типы используют notification_type='request_new' (существующий в БД)

Файлы:
- notification_signals.py: добавлены сигналы m2m_changed
- serializers.py: добавлено логирование создания и установки recipients
2025-12-29 11:56:56 +03:00