forked from erp-dev/erp
141 lines
5.4 KiB
Python
141 lines
5.4 KiB
Python
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)
|