15 Commits

Author SHA1 Message Date
lizerk
dac0234007 Enforce repository-wide code quality 2026-09-07 19:43:48 +03:00
lizerk
53cf1918c0 Add message mentions and unread mention tracking 2026-08-17 16:08:14 +03:00
lizerk
3c5a8c87e2 Update application functionality and supporting components 2026-08-17 13:54:35 +03:00
lizerk
aaa1da663c refactor: unify observability and realtime updates 2026-08-14 22:49:20 +03:00
lizerk
6ee32111db chore: configure vscode flake8 and commit lint cleanup 2026-03-31 19:17:56 +03:00
lizerk
2815efe069 chore: finalize backend lint cleanup 2026-03-31 17:53:29 +03:00
lizerk
8e2d4ad231 мини баф 2026-03-11 21:56:51 +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
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
f56e256a2a feat(communications): Phase 2 - Update views, signals, rules for GenericFK
BREAKING CHANGES (backward compatible):
- All code updated to support both old and new fields
- context_object (GenericFK) and flags now primary
- department and is_main still work (DEPRECATED)

FILES UPDATED:

1. signals.py:
   - create_main_department_chat() uses context_object + flags
   - Creates both old and new fields for compatibility
   - Checks existence using Q() for both fields

2. views.py (4 critical updates):
   - has_user_access_to_chat(): uses get_participants() (supports both)
   - ChatListView.get_queryset(): checks department OR context_object
   - ChatDetailView.get_queryset(): checks department OR context_object
   - mark_as_read_ajax(): uses get_participants() and include_all_users

3. rules.py:
   - is_department_chat(): checks both department and context_object
   - Supports GenericFK for Department context

4. apps.py:
   - create_main_global_chat(): checks and sets flags['is_primary']
   - Backward compatible with is_main

5. admin.py:
   - get_readonly_fields(): checks flags['is_primary'] OR is_main
   - Prevents editing primary chats

6. notifications/config.py:
   - get_chat_display_name(): uses context_object OR department

7. models.py:
   - Chat.__str__(): uses context_object OR department

TESTED:
✅ Signal creates chat with context_object + flags
✅ get_participants() works with both fields
✅ __str__ displays correctly
✅ is_department_chat rule works
✅ Backward compatibility preserved
2026-03-11 14:30:23 +03:00
lizerk
7dcc775b71 feat: денормализация unread_count для оптимизации чатов
- Добавлено поле unread_count в ChatReadState для кеширования счетчика
- Создана миграция 0030 с автоматическим пересчетом существующих данных
- Обновлен _auto_mark_read() для обнуления счетчика при прочтении
- Добавлен signal increment_unread_count_on_new_message для автоинкремента
- Упрощен get_queryset() - убраны подзапросы, используется Prefetch
- Обновлены сериализаторы для использования denormalized поля

Производительность: 4 SQL запроса вместо 100+ подзапросов
Решает проблему N+1 при загрузке списка чатов

Архитектура описана в backend/docs/architecture/UNREAD_COUNT_OPTIMIZATION.md
2026-03-10 18:09:06 +03:00
81d9178ec9 Улучшена структура списков чатов: круглые аватары, поддержка изображений, названия отделов, badge 'Основной' 2025-11-30 11:29:54 +03:00
afb45e4328 Расширен модал создания чатов: добавлены все поля модели (аватар, отдел, include_all_employees, is_main) + автосжатие аватаров чатов 2025-11-30 11:18:59 +03:00
2c85086f78 feat(feed,employees,communications): dept news, invites, chat sync; forms/admin cleanup; templates polish
## Что сделано

### Модели
- **employees**
  - : теперь включает отделы, где сотрудник является **руководителем**.
  - Уточнены :
    -  →  у ,  у .
  - : добавлены удобные геттеры , ; улучшён .
  - Модели , ,  приведены к актуальным полям (без start_date/end_date/level и т.п., чтобы не конфликтовать с формами/админкой).

- **feed**
  - Вынесены константы типов постов: , ,  + .
  - Жёсткие **CheckConstraint**:
    - для департаментских постов ,
    - для остальных — .
  - Индексы по , , .

- **communications**
  - :
    -  для  (чаты отдела удаляются вместе с отделом).
    - Метод : активные сотрудники отдела + **руководитель**; для глобального — все активные.
    - Запрет удаления **основных** чатов (global/department), но обычные удаляются нормально.

### Админка
- Приведена в соответствие моделям: убраны несуществующие поля, добавлены фильтры/поиск по реальным полям, inlines для отделов (связи сотрудников).
- Исправлены ошибки system check (E033/E108/E116).

### Формы
- , : валидация аватара, корректные required/optional, PhoneNumberField для WhatsApp/WeChat.
- ,  (динамический queryset сотрудников, не состоящих в отделе).
- , , : соответствуют актуальным моделям, с базовой валидацией диапазонов дат (если применимо).

### Вьюхи (employees)
- Переписаны аккуратно и проще:
  - Списки/детали отделов на CBV (, ), в контексте — сотрудники, новости отдела, новые сотрудники.
  - Профиль и чужой профиль использует общий шаблон с подключаемыми блоками.
  - : доступ только **админу/руководителю**; добавление связи  и автодобавление участника (и руководителя) в **чат отдела**.
  - : подготовлено к фильтрации по .

### Вьюхи (feed)
-  — **универсальная** форма:
  - контекст определяется автоматически из GET:  | ,
  - скрываем поля , чтобы пользователь не ломал контекст,
  - редирект — на **красивые** страницы: главная лента / страница отдела / лента сотрудника.
- : только админ — для компании, только **руководитель отдела** — для департамента.
- : комментарии + форма добавления.
- **Добавлены** CRUD для постов и комментариев:
  - ,  — автор/админ/руководитель отдела.
  - ,  — только автор комментария.

### URL-ы
- : добавлены маршруты , , , .
- : все нужные эндпоинты в рабочем состоянии,  на месте.

### Шаблоны
- : опрятная шапка, линк на «Все сотрудники отдела», кнопка «Пригласить» (для админа/руководителя), внизу — include **новостей отдела**.
- : приведение к общему стилю, кнопка «Новая публикация» с автоподстановкой department.
- : отображает бейдж контекста (Компания/Отдел/Личное), **одна** кнопка «Отмена»,  приходит из вьюхи.
- : контекстная кнопка «Назад к ленте» (определяется автоматически), кнопки **Редактировать/Удалить** (по правам), комментарии с кнопками **ред./удал.** у автора.
- Исправлены include-пути (везде , без обратных слешей).

## Почему всё ок
- Нет циклических импортов,  выровнены.
- Никакой магии в шаблонах: вся логика определения контекста — во вьюхах.
- Чаты отдела удаляются вместе с отделом; основные чаты защищены от удаления.
- Учитываем **руководителя отдела** везде, где нужно (новости, чат, права).

## Что проверить локально
1) Миграции:
   - python manage.py makemigrations
   - python manage.py migrate
2) Создать отдел, назначить руководителя.
3) Пригласить сотрудника → автоматически попадёт в чат отдела.
4) Создать новости:
   - с главной → тип company,
   - со страницы отдела → тип department, поле Department скрыто,
   - из ленты сотрудника → тип employee.
5) Закрепление новостей:
   - компания — только staff,
   - отдел — только head.
6) Редактирование/удаление постов и комментариев — по правам.

## Примечания
- Если ранее в БД были посты с типом 'personal' — вручную мигрируйте на 'employee'.
2025-08-08 15:16:19 +03:00