from rest_framework import serializers from .models import ESP32Config, Order, Salesperson, Service, VBCourse, ProductFeature, ServiceOrder, WeChatUser, Distributor, Withdrawal class WeChatUserSerializer(serializers.ModelSerializer): class Meta: model = WeChatUser fields = ['id', 'nickname', 'avatar_url', 'gender', 'country', 'province', 'city'] read_only_fields = ['id'] class DistributorSerializer(serializers.ModelSerializer): user_info = WeChatUserSerializer(source='user', read_only=True) class Meta: model = Distributor fields = ['id', 'user_info', 'level', 'commission_rate', 'total_earnings', 'withdrawable_balance', 'status', 'invite_code', 'qr_code_url'] read_only_fields = ['level', 'commission_rate', 'total_earnings', 'withdrawable_balance', 'status', 'invite_code', 'qr_code_url'] class WithdrawalSerializer(serializers.ModelSerializer): class Meta: model = Withdrawal fields = ['id', 'amount', 'status', 'remark', 'created_at'] read_only_fields = ['status', 'created_at', 'remark'] class ProductFeatureSerializer(serializers.ModelSerializer): """ 产品特性序列化器 """ display_icon = serializers.SerializerMethodField() class Meta: model = ProductFeature fields = ['title', 'description', 'icon_name', 'display_icon', 'order'] def get_display_icon(self, obj): if obj.icon_url: return obj.icon_url if obj.icon_image: return obj.icon_image.url return None class ServiceSerializer(serializers.ModelSerializer): """ AI服务序列化器 """ features_list = serializers.SerializerMethodField() display_icon = serializers.SerializerMethodField() display_detail_image = serializers.SerializerMethodField() class Meta: model = Service fields = '__all__' def get_features_list(self, obj): if obj.features: return [line.strip() for line in obj.features.split('\n') if line.strip()] return [] def get_display_icon(self, obj): if obj.icon_url: return obj.icon_url if obj.icon: return obj.icon.url return None def get_display_detail_image(self, obj): if obj.detail_image_url: return obj.detail_image_url if obj.detail_image: return obj.detail_image.url return None class ServiceOrderSerializer(serializers.ModelSerializer): """ AI服务订单序列化器 """ service_name = serializers.CharField(source='service.title', read_only=True) # 接收前端传来的 ref_code ref_code = serializers.CharField(write_only=True, required=False, allow_blank=True) class Meta: model = ServiceOrder fields = ['id', 'service', 'service_name', 'customer_name', 'company_name', 'phone_number', 'email', 'requirements', 'total_price', 'status', 'created_at', 'ref_code'] read_only_fields = ['total_price', 'status', 'created_at'] def create(self, validated_data): ref_code = validated_data.pop('ref_code', None) service = validated_data.get('service') # 默认设置预估总价为服务起步价 if service: validated_data['total_price'] = service.price # 尝试关联销售员 if ref_code: try: salesperson = Salesperson.objects.get(code=ref_code) validated_data['salesperson'] = salesperson except Salesperson.DoesNotExist: pass return super().create(validated_data) class VBCourseSerializer(serializers.ModelSerializer): """ VB课程序列化器 """ display_cover_image = serializers.SerializerMethodField() display_detail_image = serializers.SerializerMethodField() course_type_display = serializers.CharField(source='get_course_type_display', read_only=True) class Meta: model = VBCourse fields = '__all__' def get_display_cover_image(self, obj): if obj.cover_image_url: return obj.cover_image_url if obj.cover_image: return obj.cover_image.url return None def get_display_detail_image(self, obj): if obj.detail_image_url: return obj.detail_image_url if obj.detail_image: return obj.detail_image.url return None class ESP32ConfigSerializer(serializers.ModelSerializer): """ ESP32配置序列化器 """ display_detail_image = serializers.SerializerMethodField() features = ProductFeatureSerializer(many=True, read_only=True) class Meta: model = ESP32Config fields = '__all__' def get_display_detail_image(self, obj): if obj.detail_image_url: return obj.detail_image_url if obj.detail_image: return obj.detail_image.url return None class OrderSerializer(serializers.ModelSerializer): """ 订单序列化器 """ config_name = serializers.CharField(source='config.name', read_only=True) config_image = serializers.SerializerMethodField() salesperson_name = serializers.CharField(source='salesperson.name', read_only=True) salesperson_code = serializers.CharField(source='salesperson.code', read_only=True) # 接收前端传来的 ref_code,用于查找 Salesperson ref_code = serializers.CharField(write_only=True, required=False, allow_blank=True) class Meta: model = Order fields = ['id', 'config', 'config_name', 'config_image', 'quantity', 'total_price', 'status', 'created_at', 'updated_at', 'wechat_trade_no', 'customer_name', 'phone_number', 'shipping_address', 'ref_code', 'salesperson_name', 'salesperson_code', 'courier_name', 'tracking_number'] read_only_fields = ['total_price', 'status', 'wechat_trade_no', 'created_at', 'updated_at'] extra_kwargs = { 'customer_name': {'required': True}, 'phone_number': {'required': True}, 'shipping_address': {'required': True}, } def get_config_image(self, obj): if obj.config.static_image_url: return obj.config.static_image_url if obj.config.detail_image_url: return obj.config.detail_image_url if obj.config.detail_image: return obj.config.detail_image.url return None def create(self, validated_data): """ 重写创建方法,自动计算总价并关联销售员 """ config = validated_data.get('config') quantity = validated_data.get('quantity', 1) ref_code = validated_data.pop('ref_code', None) validated_data['total_price'] = config.price * quantity # 尝试关联销售员 if ref_code: try: salesperson = Salesperson.objects.get(code=ref_code) validated_data['salesperson'] = salesperson except Salesperson.DoesNotExist: # 如果找不到对应的销售员,忽略该推广码,仍继续创建订单(算作自然流量) pass return super().create(validated_data)