Corp/docs/reports/NOTIFICATION_BUG_INVESTIGATION.md
Игорь Надеин 7f5c7443e6 refactor: реорганизация тестов для улучшения структуры и производительности
- Перемещены manual tests из scripts/manual_tests в tests/manual/
- Обновлен pytest.ini с правильными маркерами и конфигурацией
- Добавлен tests/manual/conftest.py для автоматической пометки manual тестов
- Исключены manual tests из автоматических запусков
- Удалены конфликтующие тестовые файлы

Результаты:
- Провалы: 113 → 94 (-19, -17%)
- Ошибки: 12 → 3 (-9, -75%)
- Успешность: 65% → 70% (+5%)
- Скорость: 20.71s → 16.46s (+20% быстрее)

Все изменения не влияют на основной код, только на структуру тестов.
2026-01-05 07:41:34 +03:00

9.7 KiB
Raw Blame History

Отчет: Исследование багов уведомлений при согласовании заявлений

📋 Проблема

Пользователи жалуются, что автор заявления не получает уведомление, когда согласующий одобряет или отклоняет заявление.

🔍 Анализ истории коммитов

Найденная причина: Коммит c0b659f9 от 29 декабря 11:02

Сообщение коммита:

fix: исключен approver из получателей уведомлений о решении

- Approver (тот кто принял решение) не получает уведомление о своем действии
- Исключены employee.id и approver_id из recipients при approve/reject
- Упрощен signal create_request_notifications (убран лишний запрос в БД)
- Теперь передается актуальный request_obj с установленным approver_id

Проблемный код

Файл: backend/requests_app/notification_signals.py
Функция: notify_status_change() (строки 356-362)

# ID пользователей которых НЕ нужно уведомлять при approve/reject
exclude_ids = set()
if new_status in ("approved", "rejected"):
    # Не уведомляем автора заявки (он видит результат на странице)
    exclude_ids.add(request_obj.employee.id)  # ❌ ПРОБЛЕМА!
    # Не уведомляем того кто принял решение (он сам нажал кнопку)
    if request_obj.approver_id:
        exclude_ids.add(request_obj.approver_id)

Цепочка исключения

  1. exclude_ids содержит employee.id (автора) и approver_id
  2. Эти ID исключаются на строках 370, 375, 390 при фильтрации:
    • Recipients (основные получатели)
    • CC users (в копии)
    • Сотрудники отделов (если sent_to_all_department=True)

Ошибочное предположение

Комментарий в коде указывает на ошибочное предположение:

# Не уведомляем автора заявки (он видит результат на странице)

Это неверно, потому что:

  • Автор может не находиться на странице в момент согласования
  • Коммит 935c12a от 29 декабря 11:19 показывает, что alert был убран
  • Поэтому уведомление становится единственным способом уведомить автора

📅 Временная шкала

Дата/время Коммит Описание
29 дек, 11:02 c0b659f9 Добавлена логика исключения автора из уведомлений
29 дек, 11:19 935c12a Убран alert() и reload при approve/reject на странице списка
29 дек, 11:26 a178fcd Улучшены уведомления (эмодзи, описания и т.д.)

🔗 Связанные коммиты

  • a178fcd - "feat(requests): улучшены уведомления о заявлениях"

    • Добавлены эмодзи и детализация уведомлений
    • Но логика исключения автора осталась нетронутой
  • 935c12a - "fix(requests): убраны alert и немедленный reload при approve/reject"

    • Изменилась логика UI (alert → modal close + delayed reload)
    • Это сделало уведомление критически важным для информирования автора

🐛 Почему это стало проблемой?

  1. До коммита c0b659f9:

    • Автор видел результат через alert() на странице
    • Уведомление было "бонусом"
  2. После коммита c0b659f9 + 935c12a:

    • alert() убран → нет синхронного уведомления
    • Автор исключен из уведомлений → нет асинхронного уведомления
    • Результат: автор вообще ничего не узнает!

✅ Решение

Статус: ИСПРАВЛЕНО в коммите de0caea

Был удален автор из exclude_ids, чтобы он получал уведомления о решениях:

# ID пользователей которых НЕ нужно уведомлять при approve/reject
exclude_ids = set()
if new_status in ("approved", "rejected"):
    # ВАЖНО: Уведомляем автора заявки о решении - это единственный способ
    # информировать его, так как alert() был убран из UI (коммит 935c12a)
    # Не уведомляем только того кто принял решение (он сам нажал кнопку)
    if request_obj.approver_id:
        exclude_ids.add(request_obj.approver_id)

# 1. Автор - УВЕДОМЛЯЕМ всегда (даже при approved/rejected, это важно!)
recipients_to_notify.add(request_obj.employee)

Что изменилось:

  1. Удалено: exclude_ids.add(request_obj.employee.id) - автор больше не исключается
  2. Упрощена логика:
    • Старое: if new_status not in (...): recipients_to_notify.add(request_obj.employee)
    • Новое: recipients_to_notify.add(request_obj.employee) (всегда добавляем)
  3. Сохранено: exclude_ids.add(request_obj.approver_id) - approver остается исключенным (правильно)

✅ Решение (ИСПРАВЛЕНО)

📊 Дополнительные замечания

Логика исключения approver верна ✅

  • approver_id должен быть исключен (он сам нажал кнопку, не нужно ему уведомление)

Логика исключения employee неверна ❌

  • Была добавлена с ошибочным предположением о том, что пользователь видит результат на странице
  • После убрания alert() это предположение больше не верно
  • Пользователь должен получать уведомление

🔗 Файлы для исправления

  1. backend/requests_app/notification_signals.py (строки 356-362)
    • Функция: notify_status_change()
    • Действие: Удалить exclude_ids.add(request_obj.employee.id)

📝 Коммит с исправлением

Hash: de0caea
Дата: 5 января 2026
Сообщение:

fix: автор заявления должен получать уведомления о решении (approve/reject)

- Удалено исключение employee.id из notify_status_change()
- Коммит c0b659f9 ошибочно исключал автора, предполагая что он видит результат на странице
- После удаления alert() в коммите 935c12a уведомление стало единственным способом информирования
- Теперь автор получает уведомление о одобрении/отклонении заявления
- Approver остается исключенным (он сам нажал кнопку, не нужно ему уведомление)

✔️ Проверочный список

  • Найдена причина: Коммит c0b659f9 добавил ошибочное исключение автора
  • Проанализирована цепочка: 935c12a убрал alert → уведомление стало критичным
  • Реализовано решение: Удаление автора из exclude_ids
  • Создан коммит: de0caea с исправлением
  • Документировано: Этот отчет

🧪 Как проверить исправление?

  1. Создать заявление через интерфейс (автор = Current User)
  2. От другого аккаунта (approver) одобрить заявление
  3. Ожидаемый результат:
    • ✅ Автор заявления получит уведомление об одобрении
    • ✅ Approver НЕ получит уведомление о своем решении
    • ✅ Recipients и CC users получат уведомления

📌 Важные замечания

Почему approver остается исключенным?

  • Он сам нажал кнопку "Одобрить/Отклонить"
  • Он видит результат немедленно
  • Ему не нужно уведомление о собственном действии

Почему employee ДОЛЖЕН быть включен?

  • Коммит 935c12a убрал alert() с синхронным уведомлением
  • Автор может не находиться на странице в момент согласования
  • Уведомление - это единственный способ информировать его результат