Initial commit - clean project structure

This commit is contained in:
2026-08-18 16:48:15 +03:30
commit 331148037e
147 changed files with 5543 additions and 0 deletions

59
subscription/services.py Normal file
View File

@@ -0,0 +1,59 @@
from django.utils import timezone
from statuslog.signals import status_changed
from .models import Subscription
def activate_subscription(subscription_id: int):
"""
بعد از تایید پرداخت (payment webhook) صدا زده می‌شه؛ اشتراک رو active
می‌کنه و expires_at رو بر اساس Plan.duration_days محاسبه می‌کنه.
(قبلاً چون Plan فیلد duration‌ای نداشت، این مقدار با یک قاعده‌ی stub
بر اساس متن title حدس زده می‌شد؛ الان duration_days مستقیماً از مدل
Plan خونده می‌شه.)
"""
try:
subscription = Subscription.objects.get(pk=subscription_id)
except Subscription.DoesNotExist:
return None
old_status = subscription.status
duration_days = subscription.plan.duration_days if subscription.plan else 30
subscription.status = 'active'
subscription.expires_at = timezone.now() + timezone.timedelta(days=duration_days)
subscription.save(update_fields=['status', 'expires_at'])
status_changed.send(
sender='subscription.Subscription', object_id=subscription.id,
old_status=old_status, new_status='active',
event='payment_confirmed', user_id=subscription.user_id,
)
return subscription
def grant_free_subscription(user_id: int, *, duration_days: int | None = None, event: str = 'offer_applied'):
"""
فعال‌سازی اشتراک بدون هیچ Order/پرداختی — برای Offer (آفر رایگان
محدود/کامل). duration_days=None یعنی نامحدود (free_full)؛ عدد یعنی
trial با همون تعداد روز.
از discount/services.py (apply_offer) صدا زده می‌شه؛ مثل بقیه‌ی
ارتباطات بین‌اپیِ این پروژه، یک import مستقیم به تابع سرویس، نه FK
واقعی و نه HTTP call به خودمون.
"""
subscription, _ = Subscription.objects.get_or_create(user_id=user_id)
old_status = subscription.status
subscription.status = 'active'
subscription.expires_at = (
timezone.now() + timezone.timedelta(days=duration_days) if duration_days else None
)
subscription.save(update_fields=['status', 'expires_at'])
status_changed.send(
sender='subscription.Subscription', object_id=subscription.id,
old_status=old_status, new_status='active',
event=event, user_id=user_id,
)
return subscription