1
0
forked from erp-dev/erp

feat: shipment customer aou

This commit is contained in:
2026-03-30 22:03:14 +08:00
parent 38f40644a3
commit aff10b8925
7 changed files with 690 additions and 6 deletions

View File

@@ -3,11 +3,11 @@ Shipment API ViewSet
"""
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from flower.viewsets import LimitedLimitOffsetPagination
from shipment.models import Shipment
@@ -17,10 +17,39 @@ from .serializers import (
ShipmentSerializer,
ShipmentCreateNormalSerializer,
ShipmentCreateExternalSerializer,
ShipmentSalesItemCustomerSerializer,
ShipmentUpdateSerializer,
)
def _build_sales_item_serializer_context(items):
customer_ids = {item.customer_id for item in items if item.customer_id}
printing_job_ids = {item.printing_job_id for item in items if item.printing_job_id}
customer_name_map = {}
if customer_ids:
from basic_info.models import Customer
customer_name_map = dict(
Customer.objects.filter(id__in=customer_ids).values_list("id", "name")
)
printing_order_map = {}
if printing_job_ids:
from printing.models import PrintingJob
printing_order_map = dict(
PrintingJob.objects.filter(id__in=printing_job_ids).values_list(
"id", "printing_order_id"
)
)
return {
"customer_name_map": customer_name_map,
"printing_order_map": printing_order_map,
}
class ShipmentListCreateView(ListModelMixin, GenericAPIView):
"""
出货单:查询列表 / 创建
@@ -259,6 +288,50 @@ class ShipmentExternalCreateView(APIView):
return Response(response_serializer.data, status=status.HTTP_201_CREATED)
class ShipmentSalesItemCustomerListView(GenericAPIView):
"""
从未出货销售品反推出“当前可出货客户”列表。
GET /api/v1/shipment/sales-items/customers/
"""
permission_classes = [IsAuthenticated]
serializer_class = ShipmentSalesItemCustomerSerializer
pagination_class = LimitedLimitOffsetPagination
def get_queryset(self):
user = self.request.user
if getattr(user, "is_superuser", False):
from basic_info.models import Customer, Merchant
merchant_id = self.request.query_params.get("merchant")
if not merchant_id:
return Customer.objects.none()
try:
merchant = Merchant.objects.get(id=merchant_id)
except Merchant.DoesNotExist:
return Customer.objects.none()
else:
from basic_info.models import Customer
emp = getattr(user, "employee", None)
merchant = getattr(emp, "merchant", None) if emp else None
if not merchant:
return Customer.objects.none()
from shipment.services import get_customers_with_unshipped_sales_items
return get_customers_with_unshipped_sales_items(merchant=merchant)
def get(self, request):
queryset = self.get_queryset()
page = self.paginate_queryset(queryset)
serializer = self.get_serializer(page if page is not None else queryset, many=True)
if page is not None:
return self.get_paginated_response(serializer.data)
return Response(serializer.data)
class SalesItemByPrintingOrderView(APIView):
"""
通过生产订单查询销售品
@@ -324,11 +397,73 @@ class SalesItemByPrintingOrderView(APIView):
)
# 序列化返回
serializer = SalesItemSerializer(sales_items, many=True)
items = list(sales_items)
serializer = SalesItemSerializer(
items,
many=True,
context=_build_sales_item_serializer_context(items),
)
return Response({"count": len(serializer.data), "results": serializer.data})
class SalesItemByCustomerView(GenericAPIView):
"""
通过客户查询销售品。
GET /api/v1/shipment/sales-items/by-customer/<customer_id>/
"""
permission_classes = [IsAuthenticated]
serializer_class = SalesItemSerializer
pagination_class = LimitedLimitOffsetPagination
def get(self, request, customer_id: int):
from basic_info.models import Customer
user = request.user
if getattr(user, "is_superuser", False):
customer = Customer.objects.filter(id=customer_id).first()
else:
emp = getattr(user, "employee", None)
merchant = getattr(emp, "merchant", None) if emp else None
if not merchant:
return Response(
{"detail": f"客户 {customer_id} 不存在"},
status=status.HTTP_404_NOT_FOUND,
)
customer = Customer.objects.filter(id=customer_id, merchant=merchant).first()
if customer is None:
return Response(
{"detail": f"客户 {customer_id} 不存在"},
status=status.HTTP_404_NOT_FOUND,
)
include_already_has_shipment = (
request.query_params.get("include_already_has_shipment", "false").lower()
== "true"
)
from shipment.services import get_sales_items_by_customer
queryset = get_sales_items_by_customer(
merchant=customer.merchant,
customer_id=customer.id,
include_already_has_shipment=include_already_has_shipment,
)
page = self.paginate_queryset(queryset)
items = list(page) if page is not None else list(queryset)
serializer = self.get_serializer(
items,
many=True,
context=_build_sales_item_serializer_context(items),
)
if page is not None:
return self.get_paginated_response(serializer.data)
return Response(serializer.data)
class SalesItemCreateView(APIView):
"""
手动创建销售品