725 Commits

Author SHA1 Message Date
lizerk
bda5e841cb refactor(departments): удалить BFF агрегатор ui_context
- Удален метод 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)
2026-03-18 17:47:58 +03:00
lizerk
6e970741d8 refactor(departments): удалить избыточные @transaction.atomic декораторы
- Удалены все @transaction.atomic из actions (set_head, set_member_role, add_member, remove_member)
- Удален импорт transaction
- Одиночные операции БД уже атомарны по умолчанию
- Django request уже в транзакции если настроен ATOMIC_REQUESTS

-5 строк (485 → 480)
2026-03-18 17:29:23 +03:00
lizerk
64a1fb463e refactor(departments): удалить дублирующие create/destroy методы
Методы дублировали стандартную функциональность ModelViewSet:
- create(): serializer.save() делает то же самое
- destroy(): стандартный метод идентичен

-25 строк (510 → 485)
2026-03-18 17:26:03 +03:00
lizerk
d0f6eee644 feat(departments): добавить Django сигналы для LDAP синхронизации
- Создан 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
2026-03-18 17:14:54 +03:00
lizerk
9eb1487cee refactor(departments): упростить DepartmentViewSet, убрать явную LDAP логику
- Удалены импорты 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)
2026-03-18 17:12:56 +03:00
lizerk
adc72aa814 refactor(employees): удалить вспомогательные actions из ViewSet
- Удален add_skill/remove_skill (дублируют PATCH /employees/{id}/)
- Удален ldap_info (LDAP логика не в CRUD ViewSet)
- Удален export_excel (не относится к CRUD)
- Убран импорт LdapSyncState
- Упрощен required_perms_by_action и get_permissions()
- Обновлен docstring

ViewSet теперь чистый CRUD + профиль: -253 строки, 272 вместо 525
2026-03-18 17:00:15 +03:00
lizerk
9187afda5e refactor(employees): упростить EmployeeViewSet, убрать явную LDAP логику
- Убраны импорты DirectoryService, LDAP ошибок, _is_ldap_enabled
- perform_create теперь просто создает Employee (без пароля)
- perform_update упрощен: убраны проверки is_ldap_enabled/is_ldap_managed
- Сигналы сами разбираются с LDAP синхронизацией
- ldap_info endpoint оставлен (readonly, полезен)

ViewSet теперь занимается только бизнес-логикой Employee, -15 строк
2026-03-18 16:50:53 +03:00
lizerk
016d73ff56 docs(ldap): добавить руководство по LdapPasswordMixin
Примеры использования миксина для endpoint'ов смены пароля
2026-03-18 16:48:30 +03:00
lizerk
e2a15f57a3 refactor(ldap): упростить архитектуру сигналов + добавить LdapPasswordMixin
- Убрана логика создания LDAP пользователей из сигналов
- Сигналы ТОЛЬКО синхронизируют изменения существующих LDAP пользователей
- Создание LDAP пользователей - ответственность RegisterAPIView
- Убран _ldap_password из perform_create (создание через API не создает LDAP пользователей)
- Создан LdapPasswordMixin для endpoint'ов работы с паролями
- perform_create теперь только создает Employee в БД (административное создание)

Архитектурное улучшение: разделение ответственности
- Auth views (RegisterAPIView) - создают LDAP пользователей напрямую
- Сигналы - только синхронизация изменений
- LdapPasswordMixin - для endpoint'ов смены пароля
2026-03-18 16:47:04 +03:00
lizerk
f2f8a67dd3 chore(ldap): remove unused ExternalSystemSyncMixin
Миксин больше не используется после перехода на Django сигналы
2026-03-18 16:15:33 +03:00
lizerk
5585758ede refactor(ldap): replace ExternalSystemSyncMixin with Django signals
- Удалён 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 (синхронизация)
2026-03-18 16:13:20 +03:00
lizerk
50169ec09d refactor(api): удалить монолитный views.py (4500 строк)
- Удалён дублирующий монолит api/v1/employees/views.py (4622 строки)
- Все ViewSet'ы уже реэкспортированы в views/__init__.py
- Обновлены импорты в extended_views.py, analyze_queries.py, тестах
- -4622 строки дублированного кода

Импорты 'from api.v1.employees.views import X' работают через views/__init__.py
2026-03-18 15:46:23 +03:00
lizerk
c38493a18b refactor(ldap): sync_service employeeNumber через ORM
- sync_service: заменены read_attrs + modify_user_attrs на LdapUser ORM
  для записи employeeNumber при импорте пользователей
- Убран неиспользуемый импорт modify_user_attrs
2026-03-18 15:10:32 +03:00
lizerk
ea0a7e1f29 refactor(ldap): углубить замену ldap3 → ORM
- user_service: _enable_user через LdapUser ORM (убран ldap_modify_or_ignore)
- user_service: _unique_logins через LdapUser.objects.filter (убран is_taken)
- user_service: удалены импорты MODIFY_REPLACE, is_taken, ldap_modify_or_ignore
- group_service: set_description, list_members, add/remove/replace_members,
  find_dn, groups_with_member — все через LdapGroup ORM
- group_service: удалены ldap_modify_or_ignore, MODIFY_*, BASE, esc_filter
- department_service: _set_ou_managed_by через LdapOrganizationalUnit ORM
  (заменены ~60 строк ADD/REPLACE/DELETE логики на 4 строки ORM)
- department_service: удалены MODIFY_ADD/DELETE/REPLACE
- position_service: delete_position_group и _reconcile_position_nesting
  через groups_with_member (ORM) вместо conn.search

Итого: -94 строки, убраны 3 импорта ldap_repository из сервисов.
2026-03-18 14:48:27 +03:00
lizerk
95ff0dc0af refactor(ldap): заменить ldap3 CRUD на django-ldapdb ORM
- user_service.py: read_attrs/modify_user_attrs → LdapUser ORM,
  sync_user_groups_by_cns → ORM, delete_user без _ldap() контекста
- group_service.py: _wrapped методы через LdapGroup ORM
- department_service.py: _set_ou_description/_delete_department_ou → ORM
- views.py, employees.py: ldap_info через LdapUser ORM
- sync_employee_ids_to_ldap: полная замена на LdapUser ORM
- __init__.py: ORM реэкспорты, обёртки import_*/export_*
- orm_models.py: compatibility shim для django-ldapdb + Django 5.x
- Создан group_utils_orm.py (ORM замена group_utils)
- Удалён deprecated sync_service.py (352 строки)

TODO(ldap-orm) помечены: _set_password, _enable_user, _unique_logins,
_create_user_in_ldap, _move_user_to_base, rename (modify_dn),
sync_catalog (paged search), _set_ou_managed_by
2026-03-18 14:25:53 +03:00
lizerk
8cdfbfb6ef feat(ldap): добавлена интеграция с LdapSyncState
Добавлена полная поддержка связи 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 (разные БД)
2026-03-18 13:53:22 +03:00
lizerk
2eb2da4c5a feat(ldap): интеграция django-ldapdb ORM в employees/ldap/
Добавлена поддержка 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
2026-03-18 13:42:32 +03:00
lizerk
5f1d897b7f feat: добавлена поддержка создания событий возврата из отпуска/больничного
- Добавлен RETURN_ACTION_MAPPING для vacation/sick_leave → returned_from_leave
- Migration команда теперь создаёт события возврата на date_to + 1 день
- Исправлена конвертация date в datetime с timezone
- Обработка случаев когда основное событие уже существует, но нужно создать возврат
- Статистика показывает количество созданных событий возврата
2026-03-18 10:16:21 +03:00
lizerk
46daefcdec test: добавлены тесты для сигналов и migration команда
- Добавлена management команда migrate_requests_to_actions для миграции существующих заявок
- Добавлен conftest.py с фикстурой user_factory для тестов requests_app
- Добавлены 13 тестов для проверки автоматизации создания EmployeeAction
- Покрытие: немедленные/отложенные события, дубликаты, условия срабатывания, маппинги
2026-03-18 09:42:13 +03:00
lizerk
c5a8455421 feat: автоматическое создание EmployeeAction из заявок
- Добавлены сигналы в employees/signals.py для автоматизации создания кадровых событий
- Реализованы стратегии: немедленные (transfer, dismissal) и отложенные (vacation, sick_leave)
- Добавлены Celery tasks для отложенного создания событий и авто-возврата
- Настроен periodic task для очистки пропущенных возвратов
- Архитектура: employees (ядро) обрабатывает события из requests_app (модуль)
2026-03-17 20:34:14 +03:00
lizerk
f28eda6929 feat: Улучшения страницы сотрудника и миграция на ChatMembership
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 для поиска чатов
2026-03-16 18:21:24 +03:00
lizerk
6e566b1dee фикс уведомлений через почту 2026-03-13 12:17:40 +03:00
lizerk
3910079223 фикс селоери 2026-03-13 12:09:20 +03:00
lizerk
a98c403116 Мигрировать участников из participants в ChatMembership 2026-03-12 17:11:49 +03:00
lizerk
2d818b6064 проверка видимости 2026-03-12 17:08:22 +03:00
lizerk
c59f8a77af Добавлю максимум диагностической информации для выявления проблемы: 2026-03-12 17:02:34 +03:00
lizerk
15b9b216ed Добавил диагностические опции в команду чек чат 2026-03-12 16:53:19 +03:00
lizerk
bfcafd219f фиус чек чат 2026-03-12 16:37:44 +03:00
lizerk
387d5bb672 проверка типов чатов 2026-03-12 16:28:30 +03:00
lizerk
b94c6499d4 chore: очистка устаревшей документации
- Удалена устаревшая документация из backend/docs/
- Актуальные гайды сохранены в backend/docs/guides/ и других подпапках
- Удален migrate_participants_to_memberships.py (уже был создан в communications/management/commands/)
2026-03-12 16:12:17 +03:00
lizerk
91342d199d feat: миграция на ChatMembership.is_active, удаление дублирования participants
АРХИТЕКТУРНЫЙ РЕФАКТОРИНГ:
✅ Убрано дублирование логики Chat.participants vs ChatMembership.is_active
✅ Теперь единственный источник истины - ChatMembership.is_active
✅ Исправлен баг с изменением ролей (роли не отображались после изменения)

ИЗМЕНЕНИЯ:

Backend (viewsets.py):
- get_queryset: мигрировано на memberships__is_active=True
- create: убрано participants.add, только memberships
- leave/remove_member: только is_active=False + left_at
- add_member: восстанавливает is_active=True если был False
- change_role: явно устанавливает is_active=True + left_at=None

Backend (serializers.py):
- Убрано поле participants из ChatDetailSerializer
- get_participant_details: через memberships.filter(is_active=True)
- get_participant_names: через memberships

Backend (models.py):
- get_participants(): только через ChatMembership.is_active=True
- __str__(): получаем участников через memberships
- participants помечен как устаревший (в комментариях)

Backend (rules.py):
- is_member_of_chat: только ChatMembership.is_active=True
- has_send_messages_permission: убран fallback на participants

Миграции:
- Создана 0038: убирает 'owner' из choices, очищает help_text
- Исправлены зависимости в requests_app/documents/feed 0010/0014/0006
  (заменили __latest__ на конкретную версию 0037)
- Создан management command migrate_participants_to_memberships
  (перенос данных participants → memberships)

Frontend:
- Добавлено оптимистичное обновление UI при изменении ролей
- Детальное логирование для диагностики

Тесты:
- test_change_role_improved.py: проверка изменения ролей с задержкой
- Обновлен test_chat_roles.py

Удаление устаревшей документации:
- Удалены старые отчеты из docs/ (73 файла)
- Сохранены актуальные руководства

ИСПРАВЛЕННЫЙ БАГ:
До: При изменении роли is_active оставался False → membership не попадал в filter(is_active=True) → исчезал с фронтенда
После: Явно устанавливаем is_active=True при любом действии с членством
2026-03-12 15:58:49 +03:00
lizerk
80cdc36d92 fix: исправлена система прав доступа к чатам и сообщениям
Backend:
- Исправлен user_can_access_chat() для поддержки context-based чатов
- Обновлен is_chat_member() для использования get_participants()
- Добавлена проверка has_send_messages_permission (блокирует гостей)
- Исправлен MessageViewSet.get_queryset() для комментариев
- Добавлена поддержка Feed Post resolver в resolve_chat_participants()
- Чаты типа 'comments' исключены из общего списка
- Добавлены permissions для mark_read, messages, messages_around
- Добавлена команда manage_chat_permissions для управления ролями

Frontend:
- Скрыто поле ввода сообщений для гостей (role='guest')
- Добавлена проверка can_send_messages из membership
- Показывается информативная заглушка для пользователей без прав

Tests & Docs:
- Добавлены тесты для guest роли (send_message + reactions)
- Документация по ролям и правам в чатах
- Troubleshooting guide для отладки permissions

Fixes:
- 403 при доступе к чатам-комментариям
- 404 при удалении/редактировании комментариев
- Комментарии в общем списке чатов
- Гости могли отправлять сообщения
2026-03-12 14:30:25 +03:00
lizerk
d87e8ed796 фикс 2026-03-12 01:09:51 +03:00
lizerk
f58b87c9a8 фикс 2026-03-12 01:08:11 +03:00
lizerk
0e133a4633 фикс 2026-03-12 01:01:53 +03:00
lizerk
77551b5240 фикс 2026-03-12 00:59:39 +03:00
lizerk
66c243879f фикс миграций 2026-03-12 00:57:41 +03:00
lizerk
6eaadeef43 фикс миграций 2026-03-12 00:54:58 +03:00
lizerk
9462f08825 оптимизация веб сокет 2026-03-12 00:42:10 +03:00
lizerk
0217bc1a38 refactor: migrate comments to unified communications system
- Delete legacy Comment models (feed.Comment, documents.DocumentComment, requests_app.RequestComment)
- Create migration scripts to move data to communications.Message
- Add comments_helpers.py for unified comment operations
- Update API endpoints: /api/v1/posts/{id}/comments/, /api/v1/requests/{id}/comments/
- Fix notifications.0010_drop_old_tables migration with SeparateDatabaseAndState
- Implement real-time comments_count via GenericForeignKey annotations
- Update frontend API client to use new endpoints
- Update JavaScript files for new comment API routes
- Remove deprecated API endpoints and serializers
- Clean up signal handlers and admin registrations

Deployment tested: all migrations apply successfully on fresh database
2026-03-11 23:56:41 +03:00
lizerk
8e2d4ad231 мини баф 2026-03-11 21:56:51 +03:00
lizerk
359c5f7f9d fix: Обновить тесты и диагностические скрипты после удаления type='department'
- Обновлена фикстура department_chat: использует GenericFK и type='channel'
- Обновлен тест test_create_department_chat для новой модели
- Обновлен скрипт check_chat_access.py: удалена логика department
- Добавлена поддержка типов group/channel в диагностике
- Удалены все ссылки на удаленное поле department
2026-03-11 17:57:17 +03:00
lizerk
9744009d6b fix(employees): Заменить устаревший type='department' на 'channel' в сигналах
- Тип 'department' был полностью удален из communications
- Чаты отделов теперь используют type='channel'
- Исправлено 2 вхождения в create_main_department_chat()
2026-03-11 17:51:51 +03:00
lizerk
ae21c7cae7 refactor(communications): Сделать автоматические уведомления опциональными через COMMUNICATIONS_AUTO_NOTIFY
- Добавлен флаг COMMUNICATIONS_AUTO_NOTIFY (по умолчанию True)
- Оба сигнала теперь проверяют флаг перед выполнением
- Улучшена документация: объяснено что сигналы опциональны
- Для standalone использования можно отключить автоуведомления
2026-03-11 17:38:55 +03:00
lizerk
2e1f413264 refactor(communications): Сделать зависимость от notifications опциональной
BREAKING CHANGE: notifications теперь опциональная зависимость.

Проблема:
- communications имел жесткую зависимость от notifications модуля
- from notifications.signals import notify - обязательный импорт
- Нарушало независимость модуля

Решение:
- Импорт notifications обернут в try/except ImportError
- Создана функция _send_notification() - обертка над notify.send()
- Если notifications не установлен - уведомления тихо игнорируются
- Модуль работает БЕЗ notifications (graceful degradation)

Изменения:
- notifications/handlers.py:
  * Опциональный импорт: try/except ImportError
  * Флаг NOTIFICATIONS_AVAILABLE для проверки доступности
  * Функция _send_notification() вместо прямых вызовов
  * 4 вызова notify.send() → _send_notification()

Результат:
✅ communications работает БЕЗ notifications модуля
✅ Если notifications установлен - все работает как раньше
✅ Полная независимость для standalone использования
✅ System check: 0 errors

Теперь можно использовать communications как:
1. С notifications - полная функциональность
2. Без notifications - только чаты без уведомлений
3. С собственной системой уведомлений - переопределить _send_notification()
2026-03-11 17:25:15 +03:00
lizerk
5ebf9dd71a refactor(communications): Полное удаление проектно-специфичного типа department
BREAKING CHANGE: Тип чата 'department' полностью удален из модуля.

Для миграции существующих department чатов используйте:
- type='group' вместо type='department'
- context_object (GenericFK) для привязки к объектам
- flags={'is_department': True} для пометки
- COMMUNICATIONS_PARTICIPANT_RESOLVER callback для логики участников

Удалено из:
- models.py: тип 'department' из CHAT_TYPE_CHOICES
- models.py: упоминания Department из комментариев
- api/viewsets.py: логика фильтрации по department (30 строк)
- consumers.py: WebSocket логика для department (19 строк)
- utils.py: проверки доступа для department
- rules.py: is_department_chat → deprecated_is_department_chat (disabled)
- notifications/: обработка department в handlers и config
- signals.py: комментарии обновлены на универсальные

Добавлено:
- migrations/0037: удаление department из choices
- Обновлен help_text для context_content_type (без Department)
- Поддержка type='comments' в utils.py и consumers.py

Результат:
✅ 100% независимость от проекта EUSRR
✅ Нет импортов из employees
✅ Нет упоминаний department (кроме deprecated функции)
✅ Универсальный модуль готов для PyPI

Статистика: 9 файлов, -85/+44 строк
2026-03-11 17:16:10 +03:00
lizerk
6ddd3f69ba feat(communications): Добавить тип 'comments', пометить 'department' как legacy
BREAKING CHANGE: Тип 'department' помечен как deprecated.

Изменения:
- Добавлен новый тип чата 'comments' для систем комментариев
- Тип 'department' перемещен в конец списка и помечен как [Legacy]
- Обновлен help_text: рекомендуется использовать 'group' + context_object
- Обновлен __str__() для обработки типа 'comments'
- Создана миграция 0036_add_comments_type_deprecate_department

Универсальность:
- 'comments' + context_object работает с любыми моделями
- Треды, реакции, вложения доступны из коробки
- Real-time обновления через WebSocket
- Автоматические уведомления при упоминаниях и ответах

Рекомендации:
- Для проектно-специфичных чатов используй type='group' + context_object
- Department: type='group' + context_object=department + flags={'is_department': True}
- Comments: type='comments' + context_object=any_model

Документация:
- Создан docs/guides/COMMENTS_USAGE.md с примерами
- Описаны все возможности системы комментариев
- Примеры API, WebSocket, миграции с legacy типов
2026-03-11 17:06:06 +03:00
lizerk
c670246dd5 fix(communications): Удалить поле department из ChatListSerializer и ChatDetailSerializer
- Убрано поле 'department' из списка полей в ChatListSerializer
- Убрано поле 'department' из списка полей в ChatDetailSerializer
- Исправлена ошибка ImproperlyConfigured при запросе списка чатов
- Поле было удалено из модели, но осталось в сериализаторах
2026-03-11 16:51:05 +03:00
lizerk
7c8ed68a6b refactor(communications): Переименовать Employee в User для универсальности
- Заменено Employee на User во всех файлах модуля communications
- Использование нейтрального названия вместо проектно-специфичного
- Изменено 6 файлов: models.py, viewsets.py, serializers.py, handlers.py, signals.py, utils.py
- Улучшена переиспользуемость модуля communications
2026-03-11 16:48:20 +03:00
lizerk
0164c328f7 refactor(communications): Удалить зависимость от employees app
BREAKING CHANGE: Полная независимость communications модуля

Удалено:
- Поле Chat.department (FK на employees.Department)
- Импорты Department из всех файлов communications
- Q(department=...) фильтры в API/WebSocket/rules

Перемещено:
- Сигнал create_main_department_chat → employees/signals.py (проектоспецифичная логика)

Обновлено:
- models.py: удалено поле department, constraint, index
- api/viewsets.py: использует GenericFK через ContentType.objects.get()
- consumers.py: использует GenericFK через ContentType.objects.get()
- rules.py: is_department_chat теперь использует get_participants()
- admin.py: удален department из list_display/search_fields

Миграция:
- 0035_remove_department_field.py: удаляет поле, constraint, index

Результат:
✅ communications НЕ зависит от employees
✅ System check: 0 errors
✅ Использует только GenericFK (context_object)
✅ Полностью переиспользуемый модуль

Для EUSRR-специфичной логики department чатов:
- Настроить COMMUNICATIONS_PARTICIPANT_RESOLVER в settings.py
- Сигнал автосоздания чатов теперь в employees/signals.py
2026-03-11 16:39:37 +03:00