2026-08-24 15:54:08 +03:30
|
|
|
from rest_framework import serializers
|
|
|
|
|
|
|
|
|
|
from apps.billing.api.services import REFERRAL_MILESTONES, FeatureAccessService
|
|
|
|
|
from apps.billing.models import FeaturePlan, FeaturePlanTier, GemPack
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WalletSerializer(serializers.Serializer):
|
|
|
|
|
gem_balance = serializers.IntegerField()
|
|
|
|
|
is_in_trial = serializers.BooleanField()
|
|
|
|
|
trial_expires_at = serializers.DateTimeField()
|
|
|
|
|
referral_code = serializers.CharField()
|
|
|
|
|
referral_count = serializers.IntegerField()
|
|
|
|
|
next_referral_milestone = serializers.SerializerMethodField()
|
|
|
|
|
|
|
|
|
|
def get_next_referral_milestone(self, obj):
|
|
|
|
|
count = obj["referral_count"]
|
|
|
|
|
for milestone, bonus in sorted(REFERRAL_MILESTONES.items()):
|
|
|
|
|
if count < milestone:
|
|
|
|
|
return {"referrals_needed": milestone, "referrals_remaining": milestone - count, "bonus_gems": bonus}
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FeaturePlanTierSerializer(serializers.ModelSerializer):
|
|
|
|
|
class Meta:
|
|
|
|
|
model = FeaturePlanTier
|
|
|
|
|
fields = ["duration_months", "gem_price"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FeaturePlanSerializer(serializers.ModelSerializer):
|
|
|
|
|
tiers = FeaturePlanTierSerializer(many=True, read_only=True)
|
|
|
|
|
is_active = serializers.SerializerMethodField()
|
|
|
|
|
expires_at = serializers.SerializerMethodField()
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
model = FeaturePlan
|
2026-09-04 13:05:54 +03:30
|
|
|
fields = ["key", "name", "tiers", "is_active", "is_free", "expires_at"]
|
2026-08-24 15:54:08 +03:30
|
|
|
|
|
|
|
|
def get_is_active(self, obj: FeaturePlan) -> bool:
|
2026-09-04 13:05:54 +03:30
|
|
|
# مهمان (بدون حساب): فقط ابزارهای رایگان باز است — بدونِ این شاخه،
|
|
|
|
|
# AnonymousUser به is_active میرسید و خطا میداد.
|
|
|
|
|
user = self.context["request"].user
|
|
|
|
|
if not user.is_authenticated:
|
|
|
|
|
return obj.is_free
|
|
|
|
|
return FeatureAccessService.is_active(user, obj.key)
|
2026-08-24 15:54:08 +03:30
|
|
|
|
|
|
|
|
def get_expires_at(self, obj: FeaturePlan):
|
2026-09-04 13:05:54 +03:30
|
|
|
user = self.context["request"].user
|
|
|
|
|
if not user.is_authenticated:
|
|
|
|
|
return None
|
|
|
|
|
return FeatureAccessService.expires_at(user, obj.key)
|
2026-08-24 15:54:08 +03:30
|
|
|
|
|
|
|
|
|
|
|
|
|
class GemPackSerializer(serializers.ModelSerializer):
|
|
|
|
|
class Meta:
|
|
|
|
|
model = GemPack
|
|
|
|
|
fields = ["id", "bazaar_sku", "display_name", "gem_amount"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ActivateFeatureSerializer(serializers.Serializer):
|
|
|
|
|
duration_months = serializers.IntegerField(min_value=1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CreatePurchaseSerializer(serializers.Serializer):
|
|
|
|
|
gem_pack_id = serializers.IntegerField()
|
|
|
|
|
purchase_token = serializers.CharField(max_length=255)
|