2026-09-07 19:43:48 +03:00

278 lines
9.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Бизнес-логика отправки уведомлений для django-scheduler.
Функции:
- get_event_recipients - определение получателей уведомлений
- notify_event_created - уведомление о новом событии
- notify_event_changed - уведомление об изменении события
- notify_event_cancelled - уведомление об отмене события
"""
import logging
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
logger = logging.getLogger(__name__)
Employee = get_user_model()
def get_event_recipients(event) -> list:
"""
Возвращает список получателей уведомлений для события django-scheduler.
Args:
event: Объект schedule.Event
Returns:
list: Список пользователей (Employee) с доступом к календарю события
"""
from schedule.models import CalendarRelation
if not event.calendar:
return []
# Получаем всех пользователей с доступом к календарю
user_ct = ContentType.objects.get_for_model(Employee)
relations = CalendarRelation.objects.filter(
calendar=event.calendar, content_type=user_ct, object_id__isnull=False
)
# Собираем активных пользователей
user_ids = relations.values_list("object_id", flat=True)
recipients = list(Employee.objects.filter(id__in=user_ids, is_active=True))
return recipients
def notify_event_created(event, creator=None):
"""
Отправляет уведомления о новом событии всем участникам календаря.
Args:
event: Объект schedule.Event
creator: Пользователь, создавший событие (исключается из получателей)
"""
from scheduling.services import calendar_notification_enabled
if not calendar_notification_enabled(event.calendar, "notify_event_created"):
return
try:
from notifications.signals import notify
from .config import (
ActionURLs,
MessageTemplates,
NotificationVerbs,
format_date,
)
recipients = get_event_recipients(event)
# Исключаем создателя события
if creator:
recipients = [r for r in recipients if r.id != creator.id]
if not recipients:
return
# Формируем сообщение
event_date = format_date(event.start)
calendar_name = event.calendar.name if event.calendar else None
description = MessageTemplates.event_created(
event.title, event_date, calendar_name
)
# Отправляем уведомления
for recipient in recipients:
notify.send(
sender=creator,
recipient=recipient,
verb=NotificationVerbs.EVENT_CREATED,
action_object=event,
description=description,
action_url=ActionURLs.CALENDAR,
data={
"title": MessageTemplates.event_created_title(),
"event_id": event.id,
"event_title": event.title,
"event_start": (event.start.isoformat() if event.start else None),
"calendar_id": (event.calendar.id if event.calendar else None),
"calendar_name": calendar_name,
"creator_id": creator.id if creator else None,
},
)
logger.info(
"Schedule event creation notifications sent",
extra={
"event": "schedule.event.created_notifications_sent",
"schedule_event_id": event.id,
"recipient_count": len(recipients),
},
)
except Exception as e:
logger.exception(
"Schedule event creation notifications failed",
extra={
"event": "schedule.event.created_notifications_failed",
"schedule_event_id": getattr(event, "id", None),
"error_type": type(e).__name__,
},
)
def notify_event_changed(event, changed_fields: list[str] = None, modifier=None):
"""
Отправляет уведомления об изменении события.
Args:
event: Объект schedule.Event
changed_fields: Список изменённых полей
modifier: Пользователь, изменивший событие
"""
from scheduling.services import calendar_notification_enabled
if not calendar_notification_enabled(event.calendar, "notify_event_changed"):
return
try:
from notifications.signals import notify
from .config import (
ActionURLs,
MessageTemplates,
NotificationVerbs,
format_changes,
)
recipients = get_event_recipients(event)
# Исключаем модификатора
if modifier:
recipients = [r for r in recipients if r.id != modifier.id]
if not recipients:
return
# Формируем сообщение об изменениях
changes_text = format_changes(changed_fields) if changed_fields else None
description = MessageTemplates.event_changed(event.title, changes_text)
# Отправляем уведомления
for recipient in recipients:
notify.send(
sender=modifier,
recipient=recipient,
verb=NotificationVerbs.EVENT_CHANGED,
action_object=event,
description=description,
action_url=ActionURLs.CALENDAR,
data={
"title": MessageTemplates.event_changed_title(),
"event_id": event.id,
"event_title": event.title,
"changed_fields": changed_fields,
"event_start": event.start.isoformat() if event.start else None,
"calendar_id": event.calendar.id if event.calendar else None,
"modifier_id": modifier.id if modifier else None,
},
)
logger.info(
"Schedule event update notifications sent",
extra={
"event": "schedule.event.updated_notifications_sent",
"schedule_event_id": event.id,
"recipient_count": len(recipients),
"changed_field_count": len(changed_fields or []),
},
)
except Exception as e:
logger.exception(
"Schedule event update notifications failed",
extra={
"event": "schedule.event.updated_notifications_failed",
"schedule_event_id": getattr(event, "id", None),
"error_type": type(e).__name__,
},
)
def notify_event_cancelled(event, canceller=None):
"""
Отправляет уведомления об отмене (удалении) события.
Args:
event: Объект schedule.Event
canceller: Пользователь, отменивший событие
"""
from scheduling.services import calendar_notification_enabled
if not calendar_notification_enabled(event.calendar, "notify_event_cancelled"):
return
try:
from notifications.signals import notify
from .config import (
ActionURLs,
MessageTemplates,
NotificationVerbs,
format_date,
)
recipients = get_event_recipients(event)
# Исключаем отменившего
if canceller:
recipients = [r for r in recipients if r.id != canceller.id]
if not recipients:
return
# Формируем сообщение
event_date = format_date(event.start)
description = MessageTemplates.event_cancelled(event.title, event_date)
# Отправляем уведомления
for recipient in recipients:
notify.send(
sender=canceller,
recipient=recipient,
verb=NotificationVerbs.EVENT_CANCELLED,
description=description,
action_url=ActionURLs.CALENDAR,
data={
"title": MessageTemplates.event_cancelled_title(),
"event_id": event.id,
"event_title": event.title,
"event_start": event.start.isoformat() if event.start else None,
"calendar_id": event.calendar.id if event.calendar else None,
"canceller_id": canceller.id if canceller else None,
},
)
logger.info(
"Schedule event cancellation notifications sent",
extra={
"event": "schedule.event.cancelled_notifications_sent",
"schedule_event_id": event.id,
"recipient_count": len(recipients),
},
)
except Exception as e:
logger.exception(
"Schedule event cancellation notifications failed",
extra={
"event": "schedule.event.cancelled_notifications_failed",
"schedule_event_id": getattr(event, "id", None),
"error_type": type(e).__name__,
},
)