feat(backend): migrate auth and notifications off email
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user