- Добавлен RETURN_ACTION_MAPPING для vacation/sick_leave → returned_from_leave
- Migration команда теперь создаёт события возврата на date_to + 1 день
- Исправлена конвертация date в datetime с timezone
- Обработка случаев когда основное событие уже существует, но нужно создать возврат
- Статистика показывает количество созданных событий возврата
- Добавлена 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 (модуль)
АРХИТЕКТУРНЫЙ РЕФАКТОРИНГ:
✅ Убрано дублирование логики 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 при любом действии с членством
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 при удалении/редактировании комментариев
- Комментарии в общем списке чатов
- Гости могли отправлять сообщения
- 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
- constants.py → config.py для более точного отражения содержимого
- Файл содержит не только константы, но и конфигурацию уведомлений:
* NotificationVerbs - типы уведомлений
* MessageTemplates - шаблоны сообщений
* ActionURLs - URL для переходов
- Обновлены импорты во всех зависимых файлах:
* handlers.py
* __init__.py
Название 'config' более семантически верное для файла с конфигурацией.
- Создана папка backend/requests_app/notifications/ вместо одного файла
- Разделена логика на модули:
* constants.py - типы уведомлений (verbs) и шаблоны сообщений
* handlers.py - бизнес-логика отправки уведомлений
* signals.py - Django сигналы для автоматической генерации
* __init__.py - публичный API модуля
Преимущества новой структуры:
- ✅ Лучшая организация кода (SRP - Single Responsibility Principle)
- ✅ Легче поддерживать и расширять
- ✅ Константы в одном месте (NotificationVerbs, MessageTemplates)
- ✅ Переиспользуемые шаблоны сообщений
- ✅ Обратная совместимость через __init__.py
Удален: notification_signals.py (сохранен как .old для истории)
Добавлен: notifications/ модуль с 4 файлами
- Remove hard-coded Russian translations from backend API
- Backend now returns raw verb values (language-agnostic)
- Implement frontend translation functions for notification titles and categories
- Add category badge system with filters on notifications page
- Create translation utilities in frontend (verbTranslations.ts)
- Add notification settings page structure
- Update API endpoints to return simplified notification data
- Refactor notification signals across all apps
- Remove deprecated code and tests
- Add comprehensive documentation for v2 migration
Backend changes:
- notifications/api/views.py: Remove translation logic, simplify responses
- All notification_signals.py: Update to use consistent patterns
- Remove deprecated Telegram bot command
- Update Celery tasks for new notification structure
Frontend changes:
- app/notifications/page.tsx: Add translation functions and category badges
- hooks/useNotificationWebSocket.ts: New WebSocket hook for real-time updates
- lib/verbTranslations.ts: Centralized translation mappings
- components/NotificationCenter.tsx: Update to use new API format
This makes the notifications module fully reusable and project-independent.
- requests_app/rules.py: 8 предикатов + 10 правил
* Предикаты: is_request_author, is_request_assignee, can_manage_requests и др.
* Правила: view/change/delete/assign/approve requests, комментирование, статистика
- communications/rules.py: 9 предикатов + 15 правил
* Предикаты: is_chat_member, is_chat_owner, is_chat_admin, is_message_author и др.
* Правила: view/send/change/delete чаты и сообщения, управление участниками, закрепление
* Включены примеры для WebSocket consumers
- calendar_app/rules.py: 9 предикатов + 12 правил
* Предикаты: is_calendar_owner, is_personal_calendar, has_calendar_access и др.
* Правила: view/change/delete календари и события, подписки, экспорт iCal, приглашения
- procurement/rules.py: 8 предикатов + 13 правил
* Предикаты: is_procurement_manager, is_purchase_request_author, can_approve_purchases и др.
* Правила: view/change/delete заявки на закупку, управление поставщиками и договорами
- feed/rules.py: 8 предикатов + 11 правил
* Предикаты: is_post_author, can_publish_posts, can_moderate_posts и др.
* Правила: view/create/change/delete посты, публикация, закрепление, комментирование, реакции
Во всех apps.py добавлен импорт rules для автозагрузки правил при старте Django
- Исправлен PollSerializer для создания опросов с опциями
- Добавлено поле read_only_fields для корректной валидации
- Реализована отправка WebSocket уведомлений при создании опроса
- Исправлен импорт serialize_message из communications.serialization
- Добавлен обработчик poll_update в UserConsumer для WebSocket событий
- Исправлен эндпоинт /results/ для возврата user_voted_option_ids
- Добавлено поле voters в PollOptionSerializer для списка проголосовавших
- Реализована инициализация poll виджетов после рендера сообщений
- Добавлено игнорирование poll_update в notification-manager
- Исправлены стили для request list badges (height, word-break, flex)
- Восстановлены стили team-wheel (.wheel-focus, .scroll-arc) из git истории
- Реализовано отображение forwarded message info в messageRendererV2
- Множественные улучшения UI и UX для опросов
Fixes: создание опросов, голосование, отображение результатов, список проголосовавших
- Добавлен эндпоинт удаления комментариев к заявкам (DELETE /api/v1/requests/{pk}/comments/{comment_id}/)
- Исправлены references на переменную в сигналах комментариев (comment -> instance)
- Добавлена обработка статуса cancelled для заявок в notification_type_map
- Обновлены процессоры уведомлений в task_base.py (правильные поля моделей)
- Создан скрипт генерации тестовых пользователей (scripts/create_test_users.py)
Обновлены сигналы для полностью асинхронной обработки:
- requests_app: новые заявки, комментарии, изменения статуса
- documents: новые документы для всех сотрудников
Добавлена задача process_document_notifications_task
Все циклы for recipient in recipients теперь выполняются в фоне:
✅ Сигналы используют transaction.on_commit + .delay()
✅ Signal handlers сразу возвращают управление
✅ API не блокируется при массовых рассылках
Fixes: Блокировка транзакций при создании заявок/документов
- Добавлена конфигурация 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
- Удалено исключение employee.id из notify_status_change()
- Коммит 087cff79 ошибочно исключал автора, предполагая что он видит результат на странице
- После удаления alert() в коммите 1a5de8c уведомление стало единственным способом информирования
- Теперь автор получает уведомление о одобрении/отклонении заявления
- Approver остается исключенным (он сам нажал кнопку, не нужно ему уведомление)
Fixes: Users not receiving notifications when their request is approved/rejected
- Полная переделка шаблона 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)
- Кнопки одобрения/отклонения с правильными иконками
Исправлено:
- Добавлена правильная структура card-header с аватаром 48x48px
- Добавлены все необходимые детали: получатели, копия, согласующий
- Исправлены стили для badge и card-body
- Добавлена корректная форма комментария с emoji picker и auto-expand
- Подключены правильные JavaScript компоненты
- Исправлен формат дат (d.m.Y H:i)
- Добавлена передача can_process в контексте view
Добавлено:
- Иконки для каждого раздела (получатели, копия, согласующий)
- Ссылки на карточки сотрудников
- Правильные Badge с subtle цветами
- Форма комментария с message-field компонентом
ПРОБЛЕМА: Уведомления не отправлялись при создании нового заявления
ПРИЧИНА: Сигнал 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
Добавлено подробное логирование для диагностики проблемы с уведомлениями:
- Логируется срабатывание сигнала create_request_notifications
- Логируется статус заявления при создании
- Логируется каждый добавленный получатель
- Логируется итоговый список получателей
- Логируется роль каждого получателя при отправке уведомления
- Исправлена терминология: 'заявка' → 'заявление' во всех уведомлениях
- Добавлены эмодзи-иконки для визуального различия типов уведомлений
- Разделены типы уведомлений для основных получателей и cc_users:
* request_new_primary - � адресовано непосредственно
* request_new_cc - � в копии (информирование)
* request_new_approver - ✅ на согласование
* request_new_dept - � в отделе
- Добавлены детали в уведомления:
* Имя автора заявления
* Тип заявления
* Превью комментария (до 150 символов)
* Имя approver в уведомлениях о решении
- Улучшены заголовки с указанием типа заявления
- В metadata добавлены employee_name и approver_name
- Approver (тот кто принял решение) не получает уведомление о своем действии
- Исключены employee.id и approver_id из recipients при approve/reject
- Упрощен signal create_request_notifications (убран лишний запрос в БД)
- Теперь передается актуальный request_obj с установленным approver_id
- Добавлен IsRecipientOfRequest permission для API
- Обновлен get_allowed_request_qs: теперь включает заявки где пользователь - получатель
- Добавлена проверка recipients в request_process view
- Staff/superuser могут обрабатывать любые заявки (обход проверки)
MOBILE FIXES:
- request-list.css: переделан мобильный layout с flexbox вместо grid
- page-header.css: оптимизирован padding/margin для мобильных экранов
- requestListHandler.js:
* Добавлен AbortController с таймаутом (10/15 сек для мобильных)
* Обработка offline/online событий сети
* Информативные сообщения об ошибках (отсутствие интернета, таймаут)
* Адаптивный Intersection Observer (rootMargin 200px для мобильных)
* Лучшая обработка network failures
UI/UX:
- Скрыт счётчик на экранах < 480px
- Контент теперь отображается на всех разрешениях
- Исчезновение спиннера при ошибке сети
- Визуальное различие между ошибками загрузки
NEW FEATURE:
- Добавлен новый тип заявления 'Отгул' (day_off)
- Обновлена миграция 0009_alter_request_type
- Добавлен во все формы создания/редактирования
- Добавлен в фильтры списка
- Добавлена функция удаления комментариев в views_front.py
- Добавлена обработка удаления в URL routing
- Расширен JavaScript модуль для работы с добавлением/удалением комментариев
- Добавлена обработка формы добавления комментариев с JSON
- Улучшена обработка ошибок при добавлении комментария
- Добавлена инициализация emoji picker в модали
- Обновлен счетчик комментариев при добавлении/удалении
- Обновлены шаблоны для работы с данными из API
- Добавлена поддержка перезагрузки содержимого модали после каждого действия
Этап 2 разработки включает:
✅ Создан RequestDetailView класс в views_front.py:
- Наследуется от LoginRequiredMixin, TemplateView
- Загружает данные о заявлении через API (/api/v1/requests/{pk}/)
- Загружает комментарии к заявлению
- Проверяет права доступа (обрабатывает 404, 403)
- Форматирует даты для отображения
✅ Обновлены URLs (urls_front.py):
- Добавлен маршрут: path('<int:pk>/', RequestDetailView.as_view(), name='request_detail')
- Импортирован RequestDetailView
✅ Обновлен шаблон request_detail.html:
- Раскомментированы комментарии (были закрыты)
- Добавлена обработка ошибок (404, 403)
- Оформлено отображение заявления и комментариев
- Включен функционал добавления комментариев
� URLs в notification_signals.py уже правильные (проверено)
Готово для следующего этапа 3: Frontend разработка
- Шаблоны используют obj.attachment_url напрямую из API
- Удален templatetag absolute_url (больше не нужен)
- Упрощена проверка наличия вложения
- Создан requestListHandler.js для AJAX загрузки с infinite scroll
- Обновлен requestList.js для поддержки AJAX режима
- Подход аналогичен приложению документов
- Добавлен templatetag absolute_url для преобразования относительных путей
- Обновлены все шаблоны заявлений: request_list_full, request_detail, request_process
- Теперь все ссылки на вложения используют {% absolute_url %} для полных URL
- Добавлен use_url=True для attachment_url в сериализаторе API
- Исправлена проблема с локальными URL вместо доменных
- Создан компонент requestListHandler.js для AJAX загрузки
- Упрощен view my_requests - данные загружаются через API
- Обновлен шаблон my_requests.html на AJAX загрузку
- Добавлен поиск по типу заявления и комментарию
- Intersection Observer для автоматической подгрузки
- Фильтрация по статусу заявления
- Удалена серверная пагинация
- Добавлены спиннеры загрузки
Стили комментариев:
- Приведены к единому стилю с лентой новостей
- Убрана фоновая подложка блока комментариев
- Убрана разделительная линия между заявлением и комментариями
- Обновлена структура: comment-header, comment-body, comment-separator
- Добавлены кликабельные ссылки на профили авторов
Исправления формы комментариев:
- Исправлена перезагрузка страницы при нажатии Enter
- Улучшена обработка submit события (preventDefault + stopPropagation)
- Правильная проверка формы через matches() вместо closest()
API endpoints:
- Использование правильных API endpoints для комментариев
- Переход с /requests/comments/{id}/ на /api/v1/requests/{id}/comments/
- Устранено дублирование запросов к старым и новым endpoints
CSRF токены:
- Добавлена функция getCsrfToken() для извлечения из cookie
- CSRF токен добавлен во все POST запросы к API
- Исправлены ошибки 403 Forbidden для действий (cancel, approve, reject)
Расширенные фильтры:
- Добавлен фильтр 'Все доступные' (свои + адресованные + с правами)
- Добавлен фильтр 'Мои заявления' (только созданные мной)
- Добавлен фильтр 'Мне адресовано' (recipients + cc_users + sent_to_all_department)
- Поддержка параметра addressed_to_me=true в API
- Обновлена логика views_front.py для обработки новых фильтров
- Исправлены lint ошибки (длинные строки)