Изменения:
- VerifyEmailAPIView: 331 → 271 строк (-60 строк)
- Удалена вся логика if ldap_enabled с DirectoryService
- Удалены проверки LdapSyncState и обработка LDAP ошибок
- Активация пользователя теперь через сигнал sync_employee_to_ldap_on_save
- Используется _ldap_changes для передачи данных в сигнал
- Удален импорт DirectoryServiceError
Логика:
- ViewSet устанавливает is_active = True и _ldap_changes
- Сигнал автоматически синхронизирует активацию в LDAP
- Обработка ldap_enabled и ошибок происходит в сигнале
- Код стал в 3 раза короче и понятнее
- Удален метод ui_context (42 строки)
- Все его данные доступны через отдельные endpoints:
- dept → GET /departments/{id}/
- roles → можно добавить /departments/{id}/roles/
- links → GET /departments/{id}/members/
- user_perms → GET /departments/{id}/user-perms/
- choices → UI логика (фронтенд)
Преимущества:
- Кешируемые отдельные endpoints
- Фронт запрашивает только нужное
- Проще тестировать
- Более RESTful
-42 строки (480 → 438)
- Удалены все @transaction.atomic из actions (set_head, set_member_role, add_member, remove_member)
- Удален импорт transaction
- Одиночные операции БД уже атомарны по умолчанию
- Django request уже в транзакции если настроен ATOMIC_REQUESTS
-5 строк (485 → 480)
Методы дублировали стандартную функциональность ModelViewSet:
- create(): serializer.save() делает то же самое
- destroy(): стандартный метод идентичен
-25 строк (510 → 485)
- Создан employees/signals_department.py
- post_save(Department): создание/обновление OU в LDAP
- При created: создает OU, устанавливает description, managedBy
- При update: синхронизирует name, description, head
- post_delete(Department): удаление OU из LDAP
- post_save(EmployeeDepartment): синхронизация членства
- При is_active=True: перемещает пользователя в OU отдела + роль
- При is_active=False: перемещает обратно в Users OU
Подключено в employees/apps.py
- Удалены импорты DirectoryService, DirectoryDepartmentDTO, LDAP errors
- Удален импорт _is_ldap_enabled
- Убраны все блоки if ldap_enabled: ... else: ...
- ViewSet теперь только работает с БД (сигналы синхронизируют LDAP)
Методы упрощены до чистой БД логики:
- partial_update: просто обновляет поля
- set_head: просто устанавливает head + head_appointed_at
- set_member_role: обновляет link.role и RoleAssignment
- add_member: создает/активирует EmployeeDepartment
- remove_member: деактивирует EmployeeDepartment
- create: просто создает Department
- destroy: просто удаляет Department
DepartmentViewSet теперь чистый CRUD: -189 строк (699 → 510)
- Убрана логика создания LDAP пользователей из сигналов
- Сигналы ТОЛЬКО синхронизируют изменения существующих LDAP пользователей
- Создание LDAP пользователей - ответственность RegisterAPIView
- Убран _ldap_password из perform_create (создание через API не создает LDAP пользователей)
- Создан LdapPasswordMixin для endpoint'ов работы с паролями
- perform_create теперь только создает Employee в БД (административное создание)
Архитектурное улучшение: разделение ответственности
- Auth views (RegisterAPIView) - создают LDAP пользователей напрямую
- Сигналы - только синхронизация изменений
- LdapPasswordMixin - для endpoint'ов смены пароля
- Удалён ExternalSystemSyncMixin из EmployeeViewSet
- ViewSet теперь использует временные атрибуты (_ldap_password, _ldap_avatar, _ldap_changes)
- Создан employees/signals_ldap.py с post_save/post_delete handlers
- Сигналы автоматически синхронизируют Employee с LDAP через DirectoryService
- Убран дублирующий блок required_perms_by_action из EmployeeViewSet
- Упрощены perform_create и perform_update (-170 строк)
Архитектурное улучшение: разделение ответственности ViewSet (HTTP) и signals (синхронизация)
- sync_service: заменены read_attrs + modify_user_attrs на LdapUser ORM
для записи employeeNumber при импорте пользователей
- Убран неиспользуемый импорт modify_user_attrs
Добавлена полная поддержка связи Employee ↔ LdapUser через LdapSyncState.
Ключевые изменения:
- orm_services.py теперь автоматически создает/обновляет/удаляет LdapSyncState
- create_user() создает LdapSyncState при указании employee_pk
- update_user() обновляет last_django_modify_ts в LdapSyncState
- delete_user() удаляет LdapSyncState при hard delete
- Добавлен метод get_user_dn_by_employee_pk() для быстрого получения DN
- Улучшен метод get_user_by_employee_pk() - сначала ищет через LdapSyncState
Архитектура связи:
Employee (pk=123, PostgreSQL)
↓ object_pk
LdapSyncState (ldap_dn='CN=...', PostgreSQL)
↓ ldap_dn
LdapUser (dn='CN=...', employee_number='123', LDAP server)
Обновлена документация:
- ORM_INTEGRATION.md теперь объясняет связь моделей
- Добавлена диаграмма архитектуры
- Описаны роли каждой модели
- Объяснено почему нет ForeignKey (разные БД)
Добавлена поддержка django-ldapdb для упрощения работы с LDAP через Django ORM.
Ключевые изменения:
- Установлен django-ldapdb==1.5.1 в requirements.txt
- Созданы LDAP ORM модели (LdapUser, LdapGroup, LdapOrganizationalUnit) в employees/ldap/orm_models.py
- Реализованы ORM сервисы для CRUD операций в employees/ldap/orm_services.py
- Настроен database router в eusrr_backend/db_routers.py
- Добавлена LDAP database конфигурация в settings.py
- Создана документация ORM_INTEGRATION.md
Архитектура:
✅ GET → Employee (PostgreSQL) - быстро
✅ POST/PUT/DELETE → LdapUser (django-ldapdb ORM) - просто
Преимущества:
- Django ORM вместо низкоуровневого ldap3
- Автоматическая валидация через Django fields
- Унифицированный CRUD API
- Меньше кода, больше удобства
Файлы:
+ employees/ldap/orm_models.py - LDAP ORM модели (LdapUser, LdapGroup, LdapOrganizationalUnit)
+ employees/ldap/orm_services.py - ORM сервисы (LdapOrmUserService, LdapOrmGroupService, LdapOrmDepartmentService)
+ employees/ldap/ORM_INTEGRATION.md - документация по интеграции
+ eusrr_backend/db_routers.py - database router для LDAP моделей
~ requirements.txt - добавлен django-ldapdb==1.5.1
~ eusrr_backend/settings.py - настроена LDAP database и router
- Добавлен RETURN_ACTION_MAPPING для vacation/sick_leave → returned_from_leave
- Migration команда теперь создаёт события возврата на date_to + 1 день
- Исправлена конвертация date в datetime с timezone
- Обработка случаев когда основное событие уже существует, но нужно создать возврат
- Статистика показывает количество созданных событий возврата
Добавлена автоматизация создания кадровых событий из заявок:
- Сигналы в employees/signals.py для авто-создания EmployeeAction
- Celery tasks для отложенных событий (vacation, sick_leave)
- Management команда migrate_requests_to_actions
- 13 тестов покрытия функционала
- Документация в docs/completed/REQUESTS_CELERY_AUTOMATION.md
- Добавлена management команда migrate_requests_to_actions для миграции существующих заявок
- Добавлен conftest.py с фикстурой user_factory для тестов requests_app
- Добавлены 13 тестов для проверки автоматизации создания EmployeeAction
- Покрытие: немедленные/отложенные события, дубликаты, условия срабатывания, маппинги
- Добавлены сигналы в employees/signals.py для автоматизации создания кадровых событий
- Реализованы стратегии: немедленные (transfer, dismissal) и отложенные (vacation, sick_leave)
- Добавлены Celery tasks для отложенного создания событий и авто-возврата
- Настроен periodic task для очистки пропущенных возвратов
- Архитектура: employees (ядро) обрабатывает события из requests_app (модуль)
Backend:
- Полная миграция на ChatMembership для всех типов чатов
- Удалены проверки participants M2M поля
- Добавлена обработка participants при создании чатов
- API методы для создания/редактирования/удаления кадровых событий
Frontend:
- Редизайн страницы пользователя с lucide-react иконами
- Добавлено редактирование профиля (ФИО, контакты, аватар)
- Функциональные кадровые события (создание/редактирование/удаление)
- История кадровых событий с цветовой кодировкой
- Исправлено создание дубликатов чатов (поиск по member_ids)
- Удалены визуальные статусные индикаторы (is_active ≠ online)
- Добавлен статус сотрудника из последнего action
Fixes:
- type 'private' вместо 'direct' для личных чатов
- ChatMembership проверки в user_can_access_chat()
- member_ids в ChatListSerializer для поиска чатов