Files
market_page/backend/shop/serializers.py
jeremygan2021 5a7043fa1c forum
2026-02-12 16:54:16 +08:00

285 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from rest_framework import serializers
from .models import ESP32Config, Order, Salesperson, Service, VCCourse, ProductFeature, ServiceOrder, WeChatUser, Distributor, Withdrawal, CommissionLog, CourseEnrollment
class CommissionLogSerializer(serializers.ModelSerializer):
"""
佣金记录序列化器
"""
order_info = serializers.SerializerMethodField()
class Meta:
model = CommissionLog
fields = ['id', 'amount', 'level', 'status', 'created_at', 'order_info']
read_only_fields = ['id', 'amount', 'level', 'status', 'created_at', 'order_info']
def get_order_info(self, obj):
return {
'order_id': obj.order.id,
'total_price': obj.order.total_price,
'customer_name': obj.order.customer_name
}
class WeChatUserSerializer(serializers.ModelSerializer):
class Meta:
model = WeChatUser
fields = ['id', 'openid', 'nickname', 'avatar_url', 'gender', 'country', 'province', 'city', 'phone_number', 'is_star', 'title']
read_only_fields = ['id', 'openid', 'phone_number', 'is_star', 'title']
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 CourseEnrollmentSerializer(serializers.ModelSerializer):
"""
课程报名序列化器
"""
course_title = serializers.CharField(source='course.title', read_only=True)
ref_code = serializers.CharField(write_only=True, required=False, allow_blank=True)
class Meta:
model = CourseEnrollment
fields = ['id', 'course', 'course_title', 'customer_name', 'phone_number', 'email', 'wechat_id', 'message', 'status', 'created_at', 'ref_code']
read_only_fields = ['status', 'created_at']
def create(self, validated_data):
ref_code = validated_data.pop('ref_code', None)
# 尝试关联销售员或分销员
if ref_code:
try:
salesperson = Salesperson.objects.get(code=ref_code)
validated_data['salesperson'] = salesperson
except Salesperson.DoesNotExist:
pass
try:
distributor = Distributor.objects.get(invite_code=ref_code)
validated_data['distributor'] = distributor
except Distributor.DoesNotExist:
pass
return super().create(validated_data)
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 VCCourseSerializer(serializers.ModelSerializer):
"""
VC课程序列化器
"""
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 = VCCourse
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)
course_title = serializers.CharField(source='course.title', 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', 'course', 'course_title', '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},
}
def validate(self, data):
# 如果是部分更新 (PATCH),可能不需要校验所有字段,但这里主要用于创建
if self.instance:
return data
config = data.get('config')
course = data.get('course')
if not config and not course:
raise serializers.ValidationError("必须选择一种商品(硬件配置或课程)")
if config and course:
raise serializers.ValidationError("一次只能购买一种类型的商品")
if config and not data.get('shipping_address'):
raise serializers.ValidationError({"shipping_address": "购买硬件产品需要填写收货地址"})
return data
def get_config_image(self, obj):
if obj.config:
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
elif obj.course:
if obj.course.cover_image_url:
return obj.course.cover_image_url
if obj.course.cover_image:
return obj.course.cover_image.url
return None
def create(self, validated_data):
"""
重写创建方法,自动计算总价并关联销售员/分销员
"""
config = validated_data.get('config')
course = validated_data.get('course')
quantity = validated_data.get('quantity', 1)
ref_code = validated_data.pop('ref_code', None)
if config:
validated_data['total_price'] = config.price * quantity
elif course:
validated_data['total_price'] = course.price * quantity
# 尝试关联销售员或分销员
if ref_code:
# 1. 尝试查找旧版销售员
try:
salesperson = Salesperson.objects.get(code=ref_code)
validated_data['salesperson'] = salesperson
except Salesperson.DoesNotExist:
pass
# 2. 尝试查找新版分销员
try:
distributor = Distributor.objects.get(invite_code=ref_code)
validated_data['distributor'] = distributor
except Distributor.DoesNotExist:
pass
return super().create(validated_data)