""" Printing API ViewSet """ from rest_framework import viewsets, filters, status from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.permissions import BasePermission from rest_framework.pagination import LimitOffsetPagination from rest_framework.permissions import DjangoModelPermissions from django_filters.rest_framework import DjangoFilterBackend from django_filters import rest_framework as django_filters from printing import models from basic_info.models import MerchantTypeEnum from printing.serializers import ( PrintingOrderListSerializer, PrintingOrderDetailSerializer, PrintingOrderCreateUpdateSerializer, PrintingJobListSerializer, PrintingJobDetailSerializer, PrintingJobCreateUpdateSerializer, ) class IsPrintingFactory(BasePermission): """自定义权限类,允许印染工厂用户访问""" message = '您没有访问印染订单的权限' def has_permission(self, request, view): if not request.user.is_authenticated: return False if hasattr(request.user, 'employee'): return request.user.employee.merchant.type == MerchantTypeEnum.FACTORY return False class HasInvalidatePrintingOrderPermission(BasePermission): """自定义权限类,检查用户是否有作废印染订单的权限""" message = '您没有权限作废订单' def has_permission(self, request, view): if not request.user.is_authenticated: return False return request.user.has_perm('printing.can_invalidate_printingorder') class HasActivatePrintingOrderPermission(BasePermission): """自定义权限类,检查用户是否有恢复印染订单的权限""" message = '您没有权限恢复订单' def has_permission(self, request, view): if not request.user.is_authenticated: return False return request.user.has_perm('printing.can_activate_printingorder') class PrintingOrderFilterSet(django_filters.FilterSet): """印染订单过滤器""" customer_name = django_filters.CharFilter(field_name='customer__name', lookup_expr='icontains') customer_phone = django_filters.CharFilter(field_name='customer__phone', lookup_expr='icontains') fabric = django_filters.CharFilter(lookup_expr='icontains') is_urgent = django_filters.BooleanFilter() is_fabric_received = django_filters.BooleanFilter() is_invalid = django_filters.BooleanFilter() area = django_filters.CharFilter(lookup_expr='icontains') outgoing_date_from = django_filters.DateFilter(field_name='outgoing_date', lookup_expr='gte') outgoing_date_to = django_filters.DateFilter(field_name='outgoing_date', lookup_expr='lte') created_date_from = django_filters.DateFilter(field_name='created_at', lookup_expr='gte') created_date_to = django_filters.DateFilter(field_name='created_at', lookup_expr='lte') class Meta: model = models.PrintingOrder fields = ['customer', 'is_urgent', 'is_fabric_received', 'is_invalid'] class PrintingOrderViewSet(viewsets.ModelViewSet): """ 印染订单 ViewSet 提供印染订单的增改查功能(不支持删除) list: 获取印染订单列表 retrieve: 获取印染订单详情 create: 创建印染订单 update: 更新印染订单 partial_update: 部分更新印染订单 查询参数: - customer: 客户ID - customer_name: 客户名称(模糊查询) - customer_phone: 客户电话(模糊查询) - fabric: 面料(模糊查询) - is_urgent: 是否紧急(true/false) - is_fabric_received: 布料是否已收(true/false) - is_invalid: 是否作废(true/false) - area: 地区(模糊查询) - outgoing_date_from: 出货日期起始 - outgoing_date_to: 出货日期结束 - created_date_from: 创建日期起始 - created_date_to: 创建日期结束 - search: 全文搜索(客户名称、面料、地区、工艺) - ordering: 排序字段 """ queryset = models.PrintingOrder.objects.all() permission_classes = [DjangoModelPermissions] pagination_class = LimitOffsetPagination filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter] filterset_class = PrintingOrderFilterSet search_fields = ['customer__name', 'fabric', 'area', 'craft', 'description'] ordering_fields = [ 'id', 'created_at', 'updated_at', 'outgoing_date', 'is_urgent', 'is_fabric_received', 'is_invalid' ] ordering = ['-created_at'] def get_permissions(self): permissions = super().get_permissions() + [IsPrintingFactory()] if self.action == 'invalidate': permissions.append(HasInvalidatePrintingOrderPermission()) elif self.action == 'activate': permissions.append(HasActivatePrintingOrderPermission()) return permissions def get_serializer_class(self): """根据动作选择序列化器""" if self.action == 'list': return PrintingOrderListSerializer elif self.action in ['create', 'update', 'partial_update']: return PrintingOrderCreateUpdateSerializer else: # retrieve return PrintingOrderDetailSerializer def get_queryset(self): """优化查询""" queryset = super().get_queryset() if self.action in ['list', 'retrieve']: queryset = queryset.select_related('customer') return queryset def destroy(self, request, *args, **kwargs): """禁用删除操作""" return Response( {'detail': '印染订单不支持删除操作,请使用作废功能'}, status=status.HTTP_405_METHOD_NOT_ALLOWED ) @action(detail=True, methods=['post']) def invalidate(self, request, pk=None): """ 作废订单 需要权限: printing.can_invalidate_printingorder """ # 检查权限 if not request.user.has_perm('printing.can_invalidate_printingorder'): return Response( {'detail': '您没有权限作废订单'}, status=status.HTTP_403_FORBIDDEN ) printing_order = self.get_object() if printing_order.is_invalid: return Response( {'detail': '该订单已经作废'}, status=status.HTTP_400_BAD_REQUEST ) printing_order.is_invalid = True printing_order.save() serializer = PrintingOrderDetailSerializer(printing_order) return Response({ 'detail': '订单已作废', 'data': serializer.data }) @action(detail=True, methods=['post']) def activate(self, request, pk=None): """ 恢复订单 需要权限: printing.can_activate_printingorder """ # 检查权限 if not request.user.has_perm('printing.can_activate_printingorder'): return Response( {'detail': '您没有权限恢复订单'}, status=status.HTTP_403_FORBIDDEN ) printing_order = self.get_object() if not printing_order.is_invalid: return Response( {'detail': '该订单未作废,无需恢复'}, status=status.HTTP_400_BAD_REQUEST ) printing_order.is_invalid = False printing_order.save() serializer = PrintingOrderDetailSerializer(printing_order) return Response({ 'detail': '订单已恢复', 'data': serializer.data }) @action(detail=True, methods=['post']) def mark_fabric_received(self, request, pk=None): """标记布料已收""" printing_order = self.get_object() if printing_order.is_fabric_received: return Response( {'detail': '布料已经标记为已收'}, status=status.HTTP_400_BAD_REQUEST ) printing_order.is_fabric_received = True printing_order.save() serializer = PrintingOrderDetailSerializer(printing_order) return Response({ 'detail': '已标记布料已收', 'data': serializer.data }) class PrintingJobFilterSet(django_filters.FilterSet): """印染款式明细过滤器""" printing_order = django_filters.NumberFilter() product = django_filters.NumberFilter() product_name = django_filters.CharFilter(field_name='product__name', lookup_expr='icontains') unit = django_filters.CharFilter(lookup_expr='icontains') quantity_min = django_filters.NumberFilter(field_name='quantity', lookup_expr='gte') quantity_max = django_filters.NumberFilter(field_name='quantity', lookup_expr='lte') pieces_min = django_filters.NumberFilter(field_name='pieces', lookup_expr='gte') pieces_max = django_filters.NumberFilter(field_name='pieces', lookup_expr='lte') class Meta: model = models.PrintingJob fields = ['printing_order', 'product'] class PrintingJobViewSet(viewsets.ModelViewSet): """ 印染款式明细 ViewSet 提供印染款式明细的增改查功能(不支持删除) list: 获取款式明细列表 retrieve: 获取款式明细详情 create: 创建款式明细 update: 更新款式明细 partial_update: 部分更新款式明细 查询参数: - printing_order: 印染订单ID - product: 产品ID - product_name: 产品名称(模糊查询) - unit: 单位(模糊查询) - quantity_min: 最小数量 - quantity_max: 最大数量 - pieces_min: 最小件数 - pieces_max: 最大件数 - search: 全文搜索(产品名称、单位、尺寸、备注) - ordering: 排序字段 """ queryset = models.PrintingJob.objects.all() permission_classes = [DjangoModelPermissions, IsPrintingFactory] pagination_class = LimitOffsetPagination filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter] filterset_class = PrintingJobFilterSet search_fields = ['product__name', 'unit', 'size', 'description'] ordering_fields = ['id', 'created_at', 'updated_at', 'quantity', 'pieces'] ordering = ['-created_at'] def get_serializer_class(self): """根据动作选择序列化器""" if self.action == 'list': return PrintingJobListSerializer elif self.action in ['create', 'update', 'partial_update']: return PrintingJobCreateUpdateSerializer else: # retrieve return PrintingJobDetailSerializer def get_queryset(self): """优化查询""" queryset = super().get_queryset() if self.action in ['list', 'retrieve']: queryset = queryset.select_related('printing_order', 'product') return queryset def destroy(self, request, *args, **kwargs): """禁用删除操作""" return Response( {'detail': '印染款式明细不支持删除操作'}, status=status.HTTP_405_METHOD_NOT_ALLOWED )