- packs (20 / 60 / 150 questions for 45,000 / 119,000 / 259,000 toman) never expire and give 7 / 30 / 60 days of unlimited hearts; old subscription plans stay for existing subscribers but are no longer on sale - credit ledger (subscription.QuestionCredit): +N per paid pack (once per order), -1 per tutor question that reaches the API; the free daily questions are spent first; questions stopped by the server filter, cached answers and failed answers cost nothing - unlimited hearts from packs live in HeartsPass, so buying a pack never rewrites a running subscription - Message.charge records how each question was paid; GET /api/ai/quota and the ask responses report free-left-today and credits - HEARTS_ENFORCED now defaults to on: zero hearts stops answering until refill or a pack Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
44 lines
2.4 KiB
Python
44 lines
2.4 KiB
Python
from rest_framework import serializers
|
|
|
|
|
|
class PlanSerializer(serializers.Serializer):
|
|
id = serializers.CharField()
|
|
title = serializers.CharField()
|
|
price = serializers.IntegerField()
|
|
currency = serializers.CharField(required=False)
|
|
popular = serializers.BooleanField()
|
|
discountPercent = serializers.IntegerField(required=False)
|
|
durationDays = serializers.IntegerField(required=False)
|
|
features = serializers.ListField(child=serializers.CharField())
|
|
badge = serializers.CharField(allow_blank=True)
|
|
aiDailyQuota = serializers.IntegerField(help_text='سوال در روز از دستیار برای مشترکِ این پلن.')
|
|
kind = serializers.ChoiceField(choices=['pack', 'subscription'])
|
|
questionCredits = serializers.IntegerField(help_text='بسته: سوالهایی که به اعتبار اضافه میشود (منقضی نمیشود).')
|
|
heartsDays = serializers.IntegerField(help_text='بسته: روزهای قلبِ نامحدودِ هدیه.')
|
|
|
|
|
|
class PlansListResponseSerializer(serializers.Serializer):
|
|
plans = PlanSerializer(many=True)
|
|
# تا کارتِ پلن بتواند بگوید «۵ سوال در روز (رایگان: ۳)» بیآنکه عدد در فرانت هاردکد شود.
|
|
freeAiDailyQuota = serializers.IntegerField()
|
|
|
|
|
|
class PurchaseRequestSerializer(serializers.Serializer):
|
|
# هدر Idempotency-Key هم روی همین درخواست لازمه (بخش ۴.۳ سند API)؛
|
|
# از request.headers خونده میشه، نه از بدنه.
|
|
planId = serializers.CharField()
|
|
paymentMethod = serializers.CharField(required=False, default='zarinpal')
|
|
|
|
|
|
class PurchaseResponseSerializer(serializers.Serializer):
|
|
orderId = serializers.CharField()
|
|
paymentUrl = serializers.CharField()
|
|
|
|
|
|
class SubscriptionStatusResponseSerializer(serializers.Serializer):
|
|
active = serializers.BooleanField(help_text='اشتراکِ زمانی (ماهانه/سالانهی قدیمی)؛ نه بسته.')
|
|
planId = serializers.CharField(allow_null=True)
|
|
expiresAt = serializers.DateTimeField(allow_null=True)
|
|
questionCredits = serializers.IntegerField(help_text='سوالهای خریدهشدهی باقیمانده (منقضی نمیشوند).')
|
|
unlimitedHeartsUntil = serializers.DateTimeField(allow_null=True, help_text='پایانِ قلبِ نامحدودِ هدیهی بسته.')
|