fix heart refill and grant unlimited hearts to active subscribers

next_refill_at was set on UserHearts but never read or recalculated,
so a heart lost to zero never came back. UserHearts.apply_regen() now
catches up missed 24h intervals on read/deduct, and lose_heart() starts
the timer only when it isn't already running.

Any user with an active (non-expired) subscription now skips heart
deduction entirely, regardless of which plan they're on — good enough
for now until per-plan perks are needed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-05 13:26:49 +03:30
parent a367685b2e
commit a275eac7fd
7 changed files with 189 additions and 7 deletions

View File

@@ -1,4 +1,4 @@
from django.db import transaction
from django.db import models, transaction
from django.utils import timezone
from statuslog.signals import status_changed
@@ -6,6 +6,19 @@ from statuslog.signals import status_changed
from .models import Subscription
def has_unlimited_hearts(user_id: int) -> bool:
"""آیا کاربر اشتراکِ فعال داره (progress.UserHearts از این استفاده می‌کنه تا
هارت کم نکنه). فعلاً هر اشتراکِ فعال، فارغ از پلن/مدت، این پرک رو می‌ده —
وقتی محصول پلن‌های متفاوت با پرکِ متفاوت خواست، این تابع دقیق‌تر می‌شه.
expires_at=None یعنی اشتراکِ نامحدود (grant_free_subscription با duration_days=None)."""
now = timezone.now()
return Subscription.objects.filter(
user_id=user_id, status='active',
).filter(
models.Q(expires_at__isnull=True) | models.Q(expires_at__gt=now)
).exists()
def activate_subscription(subscription_id: int):
"""
بعد از تایید پرداخت (payment webhook) صدا زده می‌شود؛ اشتراک را active