1
0
forked from erp-dev/erp

feat: mes module

This commit is contained in:
2026-05-11 21:37:41 +08:00
parent d7b388e935
commit 9359013b4c
20 changed files with 3232 additions and 133 deletions

View File

@@ -12,6 +12,7 @@ from rest_framework.views import APIView
from basic_info import models as basic_models
from flower.viewsets import LimitedLimitOffsetPagination
from mes import models as mes_models
from printing.models import PrintingJob
from shipment.models import SalesItem, Shipment
@@ -330,3 +331,175 @@ class AgentTransportVehicleDetailView(APIView):
raise Http404
return Response(AgentTransportVehicleSerializer(vehicle).data)
class AgentMesDeviceCategorySerializer(serializers.ModelSerializer):
class Meta:
model = mes_models.DeviceCategory
fields = ["id", "merchant", "name", "created_at", "updated_at"]
class AgentMesDeviceSerializer(serializers.ModelSerializer):
category = AgentMesDeviceCategorySerializer(read_only=True)
capacity_unit_label = serializers.CharField(source='get_capacity_unit_display', read_only=True)
class Meta:
model = mes_models.Device
fields = [
"id",
"merchant",
"category",
"name",
"peak_capacity",
"capacity_unit",
"capacity_unit_label",
"extra",
"created_at",
"updated_at",
]
class AgentMesDeviceListView(mixins.ListModelMixin, GenericAPIView):
"""
Agent 专用:查询商户下所有 MES 设备,并返回设备分类信息。
GET /api/v2/ai/mes/devices/?merchant_id=<id>
"""
authentication_classes = [AgentAccessKeyAuthentication]
permission_classes = [IsAuthenticated]
serializer_class = AgentMesDeviceSerializer
pagination_class = LimitedLimitOffsetPagination
def get(self, request):
query_serializer = AgentMerchantQuerySerializer(data=request.query_params)
query_serializer.is_valid(raise_exception=True)
self.merchant = query_serializer.validated_data["merchant_id"]
return self.list(request)
def get_queryset(self):
merchant = getattr(self, "merchant", None)
if merchant is None:
query_serializer = AgentMerchantQuerySerializer(data=self.request.query_params)
query_serializer.is_valid(raise_exception=True)
merchant = query_serializer.validated_data["merchant_id"]
return mes_models.Device.objects.filter(merchant=merchant).select_related("category").order_by("id")
class AgentMesProductionAssignmentQuerySerializer(AgentMerchantQuerySerializer):
start_date = serializers.DateField()
end_date = serializers.DateField()
device_id = serializers.IntegerField(required=False, min_value=1)
status = serializers.ChoiceField(required=False, choices=mes_models.ProductionAssignmentStatusEnum.choices)
def validate(self, attrs):
attrs = super().validate(attrs)
if attrs["start_date"] > attrs["end_date"]:
raise serializers.ValidationError({"end_date": "结束日期不能早于开始日期"})
merchant = attrs["merchant_id"]
device_id = attrs.get("device_id")
if device_id is not None:
device = mes_models.Device.objects.filter(id=device_id, merchant=merchant).first()
if device is None:
raise serializers.ValidationError({"device_id": "设备不存在"})
attrs["device"] = device
return attrs
class AgentMesProductionAssignmentEmployeeSerializer(serializers.ModelSerializer):
class Meta:
model = basic_models.Employee
fields = ["id", "name", "merchant_id"]
class AgentMesProductionAssignmentDeviceSerializer(serializers.ModelSerializer):
category = AgentMesDeviceCategorySerializer(read_only=True)
capacity_unit_label = serializers.CharField(source='get_capacity_unit_display', read_only=True)
class Meta:
model = mes_models.Device
fields = [
"id",
"merchant",
"category",
"name",
"peak_capacity",
"capacity_unit",
"capacity_unit_label",
"extra",
"created_at",
"updated_at",
]
class AgentMesProductionAssignmentSerializer(serializers.ModelSerializer):
device = AgentMesProductionAssignmentDeviceSerializer(read_only=True)
assigner = AgentMesProductionAssignmentEmployeeSerializer(read_only=True)
assignee = AgentMesProductionAssignmentEmployeeSerializer(read_only=True)
status_label = serializers.CharField(source='get_status_display', read_only=True)
class Meta:
model = mes_models.ProductionAssignment
fields = [
"id",
"merchant",
"device",
"content_type",
"object_id",
"assigner",
"assignee",
"production_quantity",
"status",
"status_label",
"extra",
"created_at",
"updated_at",
]
class AgentMesProductionAssignmentListView(mixins.ListModelMixin, GenericAPIView):
"""
Agent 专用:查询指定日期范围内创建的生产安排。
GET /api/v2/ai/mes/production-assignments/?merchant_id=<id>&start_date=<YYYY-MM-DD>&end_date=<YYYY-MM-DD>
"""
authentication_classes = [AgentAccessKeyAuthentication]
permission_classes = [IsAuthenticated]
serializer_class = AgentMesProductionAssignmentSerializer
pagination_class = LimitedLimitOffsetPagination
def get(self, request):
query_serializer = AgentMesProductionAssignmentQuerySerializer(data=request.query_params)
query_serializer.is_valid(raise_exception=True)
self.validated_query = query_serializer.validated_data
return self.list(request)
def get_queryset(self):
validated_query = getattr(self, "validated_query", None)
if validated_query is None:
query_serializer = AgentMesProductionAssignmentQuerySerializer(data=self.request.query_params)
query_serializer.is_valid(raise_exception=True)
validated_query = query_serializer.validated_data
merchant = validated_query["merchant_id"]
queryset = (
mes_models.ProductionAssignment.objects.filter(
merchant=merchant,
created_at__date__gte=validated_query["start_date"],
created_at__date__lte=validated_query["end_date"],
)
.select_related("device", "device__category", "assigner", "assignee", "content_type")
.order_by("-created_at", "-id")
)
device = validated_query.get("device")
if device is not None:
queryset = queryset.filter(device=device)
status_value = validated_query.get("status")
if status_value is not None:
queryset = queryset.filter(status=status_value)
return queryset