# management/serializers.py # -*- coding: utf-8 -*- from rest_framework import serializers from django.utils import timezone import datetime from .models import ( CustomUser, Panel, License, PushSubscription, MarzbanAdmin, SecurityToken, DiscountCode, Plan, Subscription, Payment, EndUser, PaymentMethod, PaymentSetting, PaymentDetail, ) # --- Serializers for Django Rest Framework --- # ADDED: LicenseSerializer (was missing) class LicenseSerializer(serializers.ModelSerializer): """Serializer for the License model.""" class Meta: model = License fields = ['key', 'is_active', 'owner', 'created_at', 'expiry_date'] read_only_fields = ['key', 'created_at'] class CustomUserSerializer(serializers.ModelSerializer): class Meta: model = CustomUser fields = ['id', 'username', 'role'] class PushSubscriptionSerializer(serializers.Serializer): subscription_info = serializers.JSONField() class MarzbanAdminSerializer(serializers.ModelSerializer): class Meta: model = MarzbanAdmin fields = ['id', 'username', 'password', 'permission'] extra_kwargs = {'password': {'write_only': True}} class SecurityTokenSerializer(serializers.ModelSerializer): class Meta: model = SecurityToken fields = ['admin_id', 'token', 'expiration_date'] class DiscountCodeSerializer(serializers.ModelSerializer): class Meta: model = DiscountCode fields = ['id', 'code', 'discount_percentage', 'is_active'] read_only_fields = ['id', 'admin'] class PanelSerializer(serializers.ModelSerializer): license_key = serializers.CharField(write_only=True, required=True) class Meta: model = Panel fields = ['id', 'name', 'marzban_host', 'marzban_username', 'marzban_password', 'telegram_bot_token', 'license_key'] read_only_fields = ['id', 'owner'] def validate_license_key(self, value): owner = self.context['request'].user try: license_obj = License.objects.get(key=value, owner=owner, is_active=True) if hasattr(license_obj, 'linked_panel') and license_obj.linked_panel is not None: raise serializers.ValidationError('This license key has already been used.') return license_obj except License.DoesNotExist: raise serializers.ValidationError('Invalid or inactive license key.') def create(self, validated_data): license_obj = validated_data.pop('license_key') panel = Panel.objects.create( owner=self.context['request'].user, license=license_obj, **validated_data ) return panel class PlanSerializer(serializers.ModelSerializer): class Meta: model = Plan fields = ['id', 'name', 'price', 'duration_days', 'data_limit_gb', 'is_active'] read_only_fields = ['id'] class SubscriptionSerializer(serializers.ModelSerializer): end_user = serializers.CharField(source='end_user.username', read_only=True) plan = PlanSerializer(read_only=True) class Meta: model = Subscription fields = ['id', 'end_user', 'plan', 'status', 'start_date', 'end_date', 'remaining_data_gb'] class AdminLevel3SubscriptionSerializer(serializers.ModelSerializer): end_user_username = serializers.CharField(write_only=True) plan_id = serializers.IntegerField(write_only=True) end_user = SubscriptionSerializer(source='end_user', read_only=True) # To show user details on response plan = PlanSerializer(read_only=True) # To show plan details on response class Meta: model = Subscription fields = ['id', 'end_user_username', 'plan_id', 'status', 'start_date', 'end_date', 'remaining_data_gb', 'end_user', 'plan'] read_only_fields = ['id', 'status', 'start_date', 'end_date', 'remaining_data_gb', 'end_user', 'plan'] def validate(self, data): request_user = self.context['request'].user try: panel = request_user.owned_panel except Panel.DoesNotExist: raise serializers.ValidationError("Admin does not own a panel.") try: end_user = EndUser.objects.get(username=data.get('end_user_username'), panel=panel) data['end_user_instance'] = end_user except EndUser.DoesNotExist: raise serializers.ValidationError({"end_user_username": "User not found in your panel."}) try: plan = Plan.objects.get(id=data.get('plan_id'), is_active=True, panel=panel) data['plan_instance'] = plan except Plan.DoesNotExist: raise serializers.ValidationError({"plan_id": "Plan not found or is not active in your panel."}) data['panel_instance'] = panel return data def create(self, validated_data): end_user = validated_data.get('end_user_instance') plan = validated_data.get('plan_instance') panel = validated_data.get('panel_instance') start_date = timezone.now().date() end_date = start_date + datetime.timedelta(days=plan.duration_days) subscription = Subscription.objects.create( end_user=end_user, plan=plan, panel=panel, status='active', # Assuming direct creation by admin activates it start_date=start_date, end_date=end_date, remaining_data_gb=plan.data_limit_gb ) return subscription class PurchaseSubscriptionForUserSerializer(serializers.Serializer): end_user_username = serializers.CharField(max_length=150) plan_id = serializers.IntegerField() amount = serializers.DecimalField(max_digits=10, decimal_places=2) def validate_plan_id(self, value): if not Plan.objects.filter(id=value, is_active=True).exists(): raise serializers.ValidationError("Plan not found or is not active.") return value class ReceiptUploadSerializer(serializers.ModelSerializer): payment_token = serializers.UUIDField(write_only=True) class Meta: model = Payment fields = ['receipt_image', 'receipt_text', 'payment_token'] def validate(self, data): if not data.get('receipt_image') and not data.get('receipt_text'): raise serializers.ValidationError("Either receipt image or text is required.") return data # --- Payment System Serializers --- class PaymentMethodSerializer(serializers.ModelSerializer): class Meta: model = PaymentMethod fields = ['id', 'name', 'is_active', 'can_be_managed_by_level3'] read_only_fields = ['id'] class PaymentDetailSerializer(serializers.ModelSerializer): class Meta: model = PaymentDetail fields = ['id', 'card_number', 'card_holder_name', 'wallet_address'] read_only_fields = ['id'] class EndUserPaymentDetailSerializer(serializers.Serializer): method_name = serializers.CharField(source='payment_method.get_name_display') method_key = serializers.CharField(source='payment_method.name') is_active = serializers.BooleanField(source='is_active') card_number = serializers.CharField(source='admin_level_3.payment_details.card_number', read_only=True) card_holder_name = serializers.CharField(source='admin_level_3.payment_details.card_holder_name', read_only=True) wallet_address = serializers.CharField(source='admin_level_3.payment_details.wallet_address', read_only=True)