import datetime from django.utils import timezone from rest_framework import serializers, status, permissions from rest_framework.response import Response from rest_framework.views import APIView from printing import models as printing_models from api_man.serializers import ProductSerializer class PrintingJobV2Serializer(serializers.ModelSerializer): """v2 独立的印染任务序列化器,包含开单数量""" billed_quantity = serializers.DecimalField(max_digits=18, decimal_places=2, read_only=True) business_object_id = serializers.SerializerMethodField() width = serializers.SerializerMethodField() fabric = serializers.SerializerMethodField() product = ProductSerializer(read_only=True) class Meta: model = printing_models.PrintingJob fields = [ 'id', 'printing_order', 'product', 'work_state', 'quantity', 'width', 'fabric', 'unit', 'size', 'pieces', 'description', 'business_object_id', 'created_at', 'updated_at', 'billed_quantity', ] read_only_fields = ['id', 'created_at', 'updated_at', 'billed_quantity'] def get_business_object_id(self, obj): return obj.business_object_id def get_width(self, obj: printing_models.PrintingJob) -> float: return obj.printing_order.width def get_fabric(self, obj: printing_models.PrintingJob) -> str: return obj.printing_order.fabric class PrintingJobByCustomerView(APIView): """ 按客户与日期范围查询印染任务。 必填 query 参数: - customer_id: 客户 ID - date_from: 开始日期 (YYYY-MM-DD) - date_to: 结束日期 (YYYY-MM-DD),闭区间,包含 23:59:59 可选过滤: - printing_order: 按印染主订单 ID - product_id / product_name / product_human_id / product_width_size / product_color """ serializer_class = PrintingJobV2Serializer permission_classes = [permissions.AllowAny] def get(self, request): qp = request.query_params customer_id = qp.get('customer_id') date_from = qp.get('date_from') date_to = qp.get('date_to') printing_order_id = qp.get('printing_order') product_id = qp.get('product_id') product_name = qp.get('product_name') product_human_id = qp.get('product_human_id') product_width_size = qp.get('product_width_size') product_color = qp.get('product_color') if not customer_id: return Response({'detail': 'customer_id 为必填参数'}, status=status.HTTP_400_BAD_REQUEST) if not date_from or not date_to: return Response({'detail': 'date_from 与 date_to 为必填参数'}, status=status.HTTP_400_BAD_REQUEST) try: customer_id_int = int(customer_id) except (TypeError, ValueError): return Response({'detail': 'customer_id 必须为数字'}, status=status.HTTP_400_BAD_REQUEST) try: start_date = datetime.datetime.strptime(date_from, '%Y-%m-%d').date() end_date = datetime.datetime.strptime(date_to, '%Y-%m-%d').date() except ValueError: return Response({'detail': '日期格式需为 YYYY-MM-DD'}, status=status.HTTP_400_BAD_REQUEST) # 闭区间:包含当日 00:00:00 和 23:59:59.999999 start_dt = datetime.datetime.combine(start_date, datetime.time.min) end_dt = datetime.datetime.combine(end_date, datetime.time.max) if timezone.is_naive(start_dt): start_dt = timezone.make_aware(start_dt, timezone.get_default_timezone()) if timezone.is_naive(end_dt): end_dt = timezone.make_aware(end_dt, timezone.get_default_timezone()) queryset = printing_models.PrintingJob.objects.select_related('printing_order', 'product').filter( printing_order__customer_id=customer_id_int, created_at__gte=start_dt, created_at__lte=end_dt, ) # 可选过滤:printing_order if printing_order_id: try: queryset = queryset.filter(printing_order_id=int(printing_order_id)) except (TypeError, ValueError): return Response({'detail': 'printing_order 必须为数字'}, status=status.HTTP_400_BAD_REQUEST) # 可选过滤:product if product_id: try: queryset = queryset.filter(product_id=int(product_id)) except (TypeError, ValueError): return Response({'detail': 'product_id 必须为数字'}, status=status.HTTP_400_BAD_REQUEST) if product_name: queryset = queryset.filter(product__name__icontains=product_name) if product_human_id: queryset = queryset.filter(product__human_id__icontains=product_human_id) if product_width_size: try: width_decimal = float(product_width_size) except (TypeError, ValueError): return Response({'detail': 'product_width_size 必须为数字'}, status=status.HTTP_400_BAD_REQUEST) queryset = queryset.filter(product__width_size=width_decimal) if product_color: queryset = queryset.filter(product__color__icontains=product_color) queryset = queryset.order_by('-created_at') serializer = self.serializer_class(queryset, many=True) return Response(serializer.data)