feat(backend): migrate auth and notifications off email
Some checks failed
Backend CI/CD / test (push) Has been cancelled
Backend CI/CD / deploy (push) Has been cancelled

This commit is contained in:
2026-05-21 10:28:04 +03:30
parent b4903f7cb1
commit b7b21a6cc6
35 changed files with 2784 additions and 1390 deletions

View File

@@ -1,3 +1,4 @@
from django.conf import settings
from django.shortcuts import get_object_or_404
from django.db.models import Q, Case, When, IntegerField
from django.utils.text import slugify
@@ -25,11 +26,52 @@ from apps.events.api.schemas import (
)
from core.authentication import jwt_auth
from apps.events.models import Event, Registration
from apps.notifications.services import notify_user
from apps.payments.models import DiscountCode
from apps.users.tasks import send_critical_sms
from core.api.schemas import ErrorSchema, MessageSchema
events_router = Router()
def _frontend_event_url(event: Event) -> str:
root = getattr(settings, "FRONTEND_ROOT", "/") or "/"
if not root.endswith("/"):
root = f"{root}/"
return f"{root}events/{event.slug or event.id}"
def _notify_event_update(
event: Event,
*,
notification_type: str,
title: str,
message: str,
level: str,
sms_kind: str | None = None,
):
recipients = (
Registration.objects.filter(event=event, is_deleted=False)
.exclude(status=Registration.StatusChoices.CANCELLED)
.select_related("user")
)
for registration in recipients:
notify_user(
registration.user_id,
{
"type": notification_type,
"title": title,
"message": message,
"level": level,
"action_url": _frontend_event_url(event),
"entity_type": "event",
"entity_id": event.id,
"meta": {"event_status": event.status},
},
)
if sms_kind and registration.user.mobile and registration.user.is_mobile_verified:
send_critical_sms.delay(registration.user.mobile, sms_kind, event.title)
# Event endpoints
@events_router.get("/", response=List[EventListSchema])
def list_events(
@@ -103,6 +145,14 @@ def create_event(request, payload: EventCreateSchema):
def update_event(request, event_id: int, payload: EventUpdateSchema):
"""Update an existing event"""
event = get_object_or_404(Event, id=event_id, is_deleted=False)
previous_state = {
"status": event.status,
"start_time": event.start_time,
"end_time": event.end_time,
"address": event.address,
"location": event.location,
"online_link": event.online_link,
}
update_data = payload.dict(exclude_unset=True)
gallery_image_ids = update_data.pop('gallery_image_ids', None)
@@ -118,6 +168,34 @@ def update_event(request, event_id: int, payload: EventUpdateSchema):
if gallery_image_ids is not None:
event.gallery_images.set(gallery_image_ids)
schedule_changed = any(
previous_state[field] != getattr(event, field)
for field in ("start_time", "end_time", "address", "location", "online_link")
)
cancelled_now = (
previous_state["status"] != Event.StatusChoices.CANCELLED
and event.status == Event.StatusChoices.CANCELLED
)
if cancelled_now:
_notify_event_update(
event,
notification_type="event_cancelled",
title=f"رویداد {event.title} لغو شد",
message="این رویداد لغو شده است. برای جزئیات بیشتر صفحه رویداد را بررسی کنید.",
level="warning",
sms_kind="event_cancellation",
)
elif schedule_changed:
_notify_event_update(
event,
notification_type="event_rescheduled",
title=f"زمان یا محل {event.title} تغییر کرد",
message="جزئیات زمان‌بندی یا محل برگزاری این رویداد به‌روزرسانی شده است.",
level="info",
sms_kind="event_reschedule",
)
return event
@events_router.delete("/{int:event_id}", response=MessageSchema)