from django.utils import timezone from apps.account.models import User from .models import Notification, NotificationRead # آستانه‌ی هشدار پایان دوره‌ی آزمایشی — هر روزی که ≤ این عدد مانده باشد نشان داده می‌شود. TRIAL_WARNING_DAYS = 3 class NotificationService: @staticmethod def notify(user: User, title: str, body: str = "") -> Notification: """اعلان شخصی برای یک کاربر مشخص می‌سازد.""" return Notification.objects.create(user=user, title=title, body=body) @staticmethod def trial_warning(user: User) -> dict | None: if not user.is_in_trial or not user.trial_expires_at: return None days_left = (user.trial_expires_at - timezone.now()).days if days_left > TRIAL_WARNING_DAYS: return None return { "days_left": max(days_left, 0), "title": "دوره‌ی رایگانت داره تموم میشه!", "body": ( f"فقط {max(days_left, 0)} روز از دوره‌ی آزمایشی‌ات مونده — برای این‌که کارت زمین نمونه، " "از فروشگاه یکی از ابزارها رو با جم فعال کن." ), } @staticmethod def list_for_user(user: User) -> dict: notifications = Notification.objects.filter(user=user) | Notification.objects.filter(user__isnull=True) notifications = notifications.order_by("-created_at") read_ids = set(NotificationRead.objects.filter(user=user).values_list("notification_id", flat=True)) items = [ { "id": n.id, "title": n.title, "body": n.body, "created_at": n.created_at, "is_read": n.id in read_ids, } for n in notifications ] unread_count = sum(1 for i in items if not i["is_read"]) return { "unread_count": unread_count, "trial_warning": NotificationService.trial_warning(user), "items": items, } @staticmethod def mark_read(user: User, notification_id: int) -> None: NotificationRead.objects.get_or_create(user=user, notification_id=notification_id) @staticmethod def mark_all_read(user: User) -> None: notifications = Notification.objects.filter(user=user) | Notification.objects.filter(user__isnull=True) already_read = set(NotificationRead.objects.filter(user=user).values_list("notification_id", flat=True)) NotificationRead.objects.bulk_create( [ NotificationRead(user=user, notification_id=n.id) for n in notifications if n.id not in already_read ], ignore_conflicts=True, )