This commit is contained in:
2026-08-24 15:54:08 +03:30
commit 236002a87c
133 changed files with 5946 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
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,
)