forked from erp-dev/erp
388 lines
16 KiB
Python
388 lines
16 KiB
Python
"""
|
||
Printing API 序列化器
|
||
"""
|
||
from rest_framework import serializers
|
||
from printing import models
|
||
from .services import PrintingOrderService, PrintingJobService
|
||
from basic_info.models import Customer, Employee
|
||
|
||
|
||
class PrintingOrderListSerializer(serializers.ModelSerializer):
|
||
"""印染订单列表序列化器"""
|
||
customer_name = serializers.CharField(source='customer.name', read_only=True)
|
||
customer_phone = serializers.CharField(source='customer.mobile', read_only=True)
|
||
process_name = serializers.CharField(source='process.name', read_only=True)
|
||
progress = serializers.IntegerField(read_only=True)
|
||
|
||
class Meta:
|
||
model = models.PrintingOrder
|
||
fields = [
|
||
'id', 'human_id', 'customer', 'customer_name', 'customer_phone',
|
||
'fabric', 'width', 'is_urgent', 'area', 'address', 'curve',
|
||
'is_fabric_received', 'outgoing_date', 'is_invalid', 'new_curve',
|
||
'process', 'process_name', 'progress', 'position',
|
||
'created_at', 'updated_at',
|
||
]
|
||
read_only_fields = ['id', 'human_id', 'created_at', 'updated_at', 'progress']
|
||
|
||
|
||
class PrintingOrderDetailSerializer(serializers.ModelSerializer):
|
||
"""印染订单详情序列化器"""
|
||
customer_name = serializers.CharField(source='customer.name', read_only=True)
|
||
customer_phone = serializers.CharField(source='customer.mobile', read_only=True)
|
||
customer_area = serializers.CharField(source='customer.area', read_only=True)
|
||
process_name = serializers.CharField(source='process.name', read_only=True)
|
||
progress = serializers.IntegerField(read_only=True)
|
||
|
||
class Meta:
|
||
model = models.PrintingOrder
|
||
fields = [
|
||
'id', 'human_id', 'customer', 'customer_name', 'customer_phone', 'customer_area',
|
||
'fabric', 'width', 'is_urgent', 'area', 'address', 'fabric_source',
|
||
'is_fabric_received', 'craft', 'description', 'outgoing_date',
|
||
'curve', 'new_curve', 'position',
|
||
'printing_warn', 'rolling_warn', 'production_warn',
|
||
'is_invalid', 'process', 'process_name', 'progress',
|
||
'created_at', 'updated_at'
|
||
]
|
||
read_only_fields = ['id', 'human_id', 'created_at', 'updated_at', 'progress']
|
||
|
||
|
||
class PrintingOrderCreateUpdateSerializer(serializers.ModelSerializer):
|
||
"""印染订单创建/更新序列化器"""
|
||
|
||
class Meta:
|
||
model = models.PrintingOrder
|
||
fields = [
|
||
'id', 'customer', 'fabric', 'width', 'is_urgent', 'area', 'address',
|
||
'fabric_source', 'is_fabric_received', 'craft', 'description',
|
||
'outgoing_date', 'curve', 'new_curve', 'position',
|
||
'printing_warn', 'rolling_warn', 'production_warn', 'is_invalid',
|
||
'process'
|
||
]
|
||
read_only_fields = ['id']
|
||
|
||
def validate_customer(self, value):
|
||
"""验证客户是否存在"""
|
||
if not value:
|
||
raise serializers.ValidationError("客户不能为空")
|
||
return value
|
||
|
||
def validate(self, attrs):
|
||
"""验证流程修改权限"""
|
||
# 更新时验证 process 修改权限
|
||
if self.instance and 'process' in attrs:
|
||
new_process = attrs['process']
|
||
old_process = self.instance.process
|
||
|
||
if new_process != old_process:
|
||
if not PrintingOrderService.can_change_process(self.instance):
|
||
raise serializers.ValidationError({
|
||
'process': '存在已开始的印染任务,无法修改流程'
|
||
})
|
||
|
||
return attrs
|
||
|
||
def create(self, validated_data):
|
||
"""创建订单,使用 service 层"""
|
||
user = self.context['request'].user
|
||
return PrintingOrderService.create_printing_order(validated_data, user)
|
||
|
||
def update(self, instance, validated_data):
|
||
"""更新订单,使用 service 层"""
|
||
user = self.context['request'].user
|
||
success, message, updated_instance = PrintingOrderService.update_printing_order(
|
||
instance, validated_data, user
|
||
)
|
||
if not success:
|
||
raise serializers.ValidationError(message)
|
||
return updated_instance
|
||
|
||
|
||
class PrintingJobListSerializer(serializers.ModelSerializer):
|
||
"""印染款式明细列表序列化器"""
|
||
printing_order_id = serializers.CharField(source='printing_order.human_id', read_only=True)
|
||
product_name = serializers.CharField(source='product.name', read_only=True)
|
||
status = serializers.CharField(read_only=True)
|
||
is_completed = serializers.BooleanField(read_only=True)
|
||
business_object_id = serializers.SerializerMethodField()
|
||
|
||
class Meta:
|
||
model = models.PrintingJob
|
||
fields = [
|
||
'id', 'printing_order', 'printing_order_id', 'product', 'product_name',
|
||
'quantity', 'unit', 'size', 'pieces', 'description',
|
||
'status', 'is_completed', 'business_object_id',
|
||
'created_at', 'updated_at'
|
||
]
|
||
read_only_fields = ['id', 'created_at', 'updated_at', 'status', 'is_completed', 'business_object_id']
|
||
|
||
def get_business_object_id(self, obj):
|
||
"""安全地获取 business_object_id"""
|
||
return obj.business_object.id if obj.business_object else None
|
||
|
||
|
||
class PrintingJobDetailSerializer(serializers.ModelSerializer):
|
||
"""印染款式明细详情序列化器"""
|
||
printing_order_id = serializers.CharField(source='printing_order.human_id', read_only=True)
|
||
product_name = serializers.CharField(source='product.name', read_only=True)
|
||
product_code = serializers.CharField(source='product.human_id', read_only=True)
|
||
status = serializers.CharField(read_only=True)
|
||
status_id = serializers.IntegerField(read_only=True)
|
||
is_completed = serializers.BooleanField(read_only=True)
|
||
has_started = serializers.BooleanField(read_only=True)
|
||
business_object_id = serializers.SerializerMethodField()
|
||
|
||
class Meta:
|
||
model = models.PrintingJob
|
||
fields = [
|
||
'id', 'printing_order', 'printing_order_id', 'product', 'product_name', 'product_code',
|
||
'quantity', 'unit', 'size', 'pieces', 'description',
|
||
'status', 'status_id', 'is_completed', 'has_started', 'business_object_id',
|
||
'created_at', 'updated_at'
|
||
]
|
||
read_only_fields = [
|
||
'id', 'created_at', 'updated_at',
|
||
'status', 'status_id', 'is_completed', 'has_started', 'business_object_id'
|
||
]
|
||
|
||
def get_business_object_id(self, obj):
|
||
"""安全地获取 business_object_id"""
|
||
return obj.business_object.id if obj.business_object else None
|
||
|
||
|
||
class PrintingJobCreateUpdateSerializer(serializers.ModelSerializer):
|
||
"""印染款式明细创建/更新序列化器"""
|
||
|
||
class Meta:
|
||
model = models.PrintingJob
|
||
fields = [
|
||
'id', 'printing_order', 'product', 'quantity', 'unit', 'size', 'pieces', 'description'
|
||
]
|
||
read_only_fields = ['id']
|
||
extra_kwargs = {
|
||
'size': {'required': False, 'allow_null': True, 'allow_blank': True},
|
||
'pieces': {'required': False, 'allow_null': True},
|
||
'description': {'required': False, 'allow_null': True, 'allow_blank': True},
|
||
}
|
||
|
||
def validate_printing_order(self, value):
|
||
"""验证印染订单是否存在"""
|
||
if not value:
|
||
raise serializers.ValidationError("印染订单不能为空")
|
||
return value
|
||
|
||
def validate_product(self, value):
|
||
"""验证产品是否存在"""
|
||
if not value:
|
||
raise serializers.ValidationError("产品不能为空")
|
||
return value
|
||
|
||
def validate_quantity(self, value):
|
||
"""验证数量"""
|
||
if value <= 0:
|
||
raise serializers.ValidationError("数量必须大于0")
|
||
return value
|
||
|
||
def create(self, validated_data):
|
||
"""创建任务,使用 service 层"""
|
||
user = self.context['request'].user
|
||
return PrintingJobService.create_printing_job(validated_data, user)
|
||
|
||
def update(self, instance, validated_data):
|
||
"""更新任务,使用 service 层"""
|
||
user = self.context['request'].user
|
||
success, message, updated_instance = PrintingJobService.update_printing_job(
|
||
instance, validated_data, user
|
||
)
|
||
if not success:
|
||
raise serializers.ValidationError(message)
|
||
return updated_instance
|
||
|
||
|
||
class PlateOrderListSerializer(serializers.ModelSerializer):
|
||
"""开版订单列表序列化器"""
|
||
customer_name = serializers.CharField(source="customer.name", read_only=True)
|
||
salesperson_name = serializers.CharField(source="salesperson.name", read_only=True)
|
||
merchandiser_name = serializers.CharField(source="merchandiser.name", read_only=True)
|
||
status = serializers.CharField(read_only=True)
|
||
progress_percentage = serializers.IntegerField(read_only=True)
|
||
process_name = serializers.SerializerMethodField()
|
||
|
||
class Meta:
|
||
model = models.PlateOrder
|
||
fields = [
|
||
'id', 'design_code', 'plate_type', 'plate_date',
|
||
'urgency_level', 'is_invalid',
|
||
'customer', 'customer_name', 'area',
|
||
'salesperson', 'salesperson_name',
|
||
'merchandiser', 'merchandiser_name',
|
||
'style_name', 'fabric', 'width',
|
||
'required_completion_date', 'completion_date',
|
||
'is_ordered', 'process', 'process_name',
|
||
'status', 'progress_percentage',
|
||
'created_at', 'updated_at'
|
||
]
|
||
read_only_fields = [
|
||
'id', 'status', 'progress_percentage',
|
||
'created_at', 'updated_at'
|
||
]
|
||
|
||
def get_process_name(self, obj):
|
||
"""获取流程名称"""
|
||
if obj.process:
|
||
try:
|
||
from stateflow.models import Process
|
||
process = Process.objects.get(id=obj.process)
|
||
return process.name
|
||
except Process.DoesNotExist:
|
||
return None
|
||
return None
|
||
|
||
|
||
class PlateOrderDetailSerializer(serializers.ModelSerializer):
|
||
"""开版订单详情序列化器"""
|
||
customer_name = serializers.CharField(source="customer.name", read_only=True)
|
||
customer_phone = serializers.CharField(source="customer.mobile", read_only=True)
|
||
salesperson_name = serializers.CharField(source="salesperson.name", read_only=True)
|
||
merchandiser_name = serializers.CharField(source="merchandiser.name", read_only=True)
|
||
status = serializers.CharField(read_only=True)
|
||
status_id = serializers.IntegerField(read_only=True)
|
||
is_completed = serializers.BooleanField(read_only=True)
|
||
has_started = serializers.BooleanField(read_only=True)
|
||
progress_percentage = serializers.IntegerField(read_only=True)
|
||
business_object_id = serializers.SerializerMethodField()
|
||
plate_image_url = serializers.SerializerMethodField()
|
||
process_name = serializers.SerializerMethodField()
|
||
|
||
class Meta:
|
||
model = models.PlateOrder
|
||
fields = [
|
||
'id', 'design_code', 'plate_type', 'plate_date', 'plate_method',
|
||
'plate_image', 'plate_image_url', 'plate_notes', 'reprint_reason',
|
||
'urgency_level', 'is_invalid',
|
||
'customer', 'customer_name', 'customer_phone', 'area', 'default_address',
|
||
'salesperson', 'salesperson_name',
|
||
'merchandiser', 'merchandiser_name',
|
||
'style_name', 'fabric', 'width', 'production_method',
|
||
'is_mark_frame', 'drawing_rating', 'color_matching_rating',
|
||
'sample_rating', 'difficulty_rating',
|
||
'sample_meter', 'required_sample_meters',
|
||
'required_completion_date', 'completion_date',
|
||
'approval_result', 'is_ordered', 'customer_feedback',
|
||
'process', 'process_name',
|
||
'status', 'status_id', 'is_completed', 'has_started',
|
||
'progress_percentage', 'business_object_id',
|
||
'created_at', 'updated_at'
|
||
]
|
||
read_only_fields = [
|
||
'id', 'status', 'status_id', 'is_completed', 'has_started',
|
||
'progress_percentage', 'business_object_id',
|
||
'created_at', 'updated_at'
|
||
]
|
||
|
||
def get_business_object_id(self, obj):
|
||
"""安全地获取 business_object_id"""
|
||
return obj.business_object.id if obj.business_object else None
|
||
|
||
def get_plate_image_url(self, obj):
|
||
"""获取图片完整URL"""
|
||
if obj.plate_image:
|
||
request = self.context.get("request")
|
||
if request:
|
||
return request.build_absolute_uri(obj.plate_image.url)
|
||
return obj.plate_image.url
|
||
return None
|
||
|
||
def get_process_name(self, obj):
|
||
"""获取流程名称"""
|
||
if obj.process:
|
||
try:
|
||
from stateflow.models import Process
|
||
process = Process.objects.get(id=obj.process)
|
||
return process.name
|
||
except Process.DoesNotExist:
|
||
return None
|
||
return None
|
||
|
||
|
||
class PlateOrderCreateUpdateSerializer(serializers.ModelSerializer):
|
||
"""开版订单创建/更新序列化器"""
|
||
|
||
class Meta:
|
||
model = models.PlateOrder
|
||
fields = [
|
||
"id", "design_code", "plate_type", "plate_date", "plate_method",
|
||
"plate_image", "plate_notes", "reprint_reason",
|
||
"urgency_level", "is_invalid",
|
||
"customer", "area", "default_address",
|
||
"salesperson", "merchandiser",
|
||
"style_name", "fabric", "width", "production_method",
|
||
"is_mark_frame", "drawing_rating", "color_matching_rating",
|
||
"sample_rating", "difficulty_rating",
|
||
"sample_meter", "required_sample_meters",
|
||
"required_completion_date", "completion_date",
|
||
"approval_result", "is_ordered", "customer_feedback",
|
||
"process"
|
||
]
|
||
read_only_fields = ["id"]
|
||
|
||
def validate_customer(self, value):
|
||
"""验证客户是否存在"""
|
||
if not value:
|
||
raise serializers.ValidationError("客户不能为空")
|
||
return value
|
||
|
||
def validate_salesperson(self, value):
|
||
"""验证业务员是否存在"""
|
||
if value and not Employee.objects.filter(id=value.id).exists():
|
||
raise serializers.ValidationError("业务员不存在")
|
||
return value
|
||
|
||
def validate_merchandiser(self, value):
|
||
"""验证跟单员是否存在"""
|
||
if value and not Employee.objects.filter(id=value.id).exists():
|
||
raise serializers.ValidationError("跟单员不存在")
|
||
return value
|
||
|
||
def validate_sample_meter(self, value):
|
||
"""验证样品米数"""
|
||
if value is not None and value < 0:
|
||
raise serializers.ValidationError("样品米数不能为负数")
|
||
return value
|
||
|
||
def validate_required_sample_meters(self, value):
|
||
"""验证所需样品米数"""
|
||
if value is not None and value < 0:
|
||
raise serializers.ValidationError("所需样品米数不能为负数")
|
||
return value
|
||
|
||
def validate_process(self, value):
|
||
"""验证流程是否存在"""
|
||
if value:
|
||
from stateflow.models import Process
|
||
if not Process.objects.filter(id=value).exists():
|
||
raise serializers.ValidationError("流程不存在")
|
||
return value
|
||
|
||
def validate(self, attrs):
|
||
"""交叉验证"""
|
||
return attrs
|
||
|
||
def create(self, validated_data):
|
||
"""创建开版订单"""
|
||
user = self.context["request"].user
|
||
|
||
# 创建 PlateOrder,save 方法会自动创建 BusinessObject
|
||
plate_order = models.PlateOrder.objects.create(**validated_data)
|
||
|
||
return plate_order
|
||
|
||
def update(self, instance, validated_data):
|
||
"""更新开版订单"""
|
||
# 直接更新字段,save 方法会自动处理 BusinessObject 的创建
|
||
for attr, value in validated_data.items():
|
||
setattr(instance, attr, value)
|
||
instance.save()
|
||
return instance
|