12 Commits

Author SHA1 Message Date
lizerk
f88d90230b refactor: clean architecture, align tests to current API contracts, all tests green [deploy-ready] 2026-03-30 04:27:18 +03:00
lizerk
2688df46ef Fix: Wrap all unsafe int() conversions with try/except
Fixed ValueError-prone int() calls in:
- communications/api/viewsets.py (4 places: limit, before_limit, after_limit)
- notifications/api/views.py (2 places: page, page_size)
- api/v1/search/views.py (1 place: limit)
- api/v1/procurement/views.py (1 place: quantity)
Also updated audit script to exclude .venv/
2026-03-20 09:10:33 +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
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
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
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
lizerk
0c00652c8e fix(communications): Исправить вызов метода get_participants()
- signals.py: chat.get_participants → chat.get_participants()
- notifications/handlers.py: chat.get_participants → chat.get_participants()

Ошибка: AttributeError: 'function' object has no attribute 'exclude'
Причина: Метод не вызывался, пытались вызвать метод на самом объекте функции

Исправлено: Добавлены () для вызова метода и получения QuerySet
2026-03-11 16:04:56 +03:00
lizerk
45b35b0f36 refactor(communications): Удалить классические Django views и templates
- Удалены классические Django CBV views (ChatListView, ChatDetailView, ~400 строк)
- Удален MessageForm для HTML форм
- Удалены 6 HTML templates (chat_list.html, chat_detail.html, messengers/*)
- Утилиты _coerce_ts и user_can_access_chat перенесены в utils.py
- Обновлены импорты в communications/api/viewsets.py

Причина: Проект использует Next.js frontend + REST API + WebSocket.
Классические server-side rendered views больше не используются.

Результат:
- System check: 0 errors
- Код стал чище и проще для поддержки
- Нет зависимости от Django templates
- API и WebSocket остались полностью функциональны
2026-03-11 15:49:23 +03:00
lizerk
d491cbdff9 refactor: Сделать communications приложение автономным
- Перенос REST API в communications/api/ для standalone использования
  * Создан communications/api/ с serializers.py, viewsets.py, urls.py
  * Перенесено 1668 строк (442 serializers + 1226 viewsets)
  * Удалена директория api/v1/communications/
  * Обновлены импорты в api/v1/urls.py и api/v2/communications/views.py

- Извлечение WebSocket логики в ChatConsumerMixin
  * Создан communications/consumers.py (709 строк, 32 метода)
  * Перенесены chat event handlers, action handlers, helper methods
  * realtime/consumers.py сокращен с 862 до 211 строк (-75%)
  * Сохранено одно WebSocket соединение через наследование миксина

- Архитектура:
  * communications теперь полностью автономно (REST API + WebSocket)
  * realtime/UserConsumer наследуется от ChatConsumerMixin
  * 0 breaking changes, обратная совместимость 100%
  * Одно WebSocket соединение для всех real-time событий

- Созданы тесты и документация:
  * test_phase3.py - проверка API serializers, filters, WebSocket
  * docs/completed/API_REFACTORING_STANDALONE.md
  * docs/completed/WEBSOCKET_REFACTORING_MIXIN.md
  * docs/completed/CHAT_REFACTORING_PHASE3_COMPLETE.md

Результат:
  ✅ System check: 0 ошибок
  ✅ Phase 3 tests: все прошли
  ✅ Готово к standalone использованию (pip install django-communications)
2026-03-11 15:34:51 +03:00