198 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Python
		
	
	
	
| 
 | |
| from rest_framework.mixins import ListModelMixin, DestroyModelMixin, CreateModelMixin, RetrieveModelMixin
 | |
| from rest_framework.viewsets import GenericViewSet
 | |
| from rest_framework.response import Response
 | |
| from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse
 | |
| from apps.inm.services import InmService
 | |
| from apps.mtm.models import Material, PackItem
 | |
| from apps.sam.models import Sale, SalePack, SaleProduct
 | |
| from apps.sam.serializers_sale import SRemarkItemCreateSerializer, SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer, SaleProductPackDetailSerializer, SaleProductPackSerializer, SaleUpShipPicSerializer
 | |
| from rest_framework import exceptions
 | |
| from django.db import transaction
 | |
| from rest_framework.decorators import action
 | |
| from django.utils import timezone
 | |
| 
 | |
| from apps.system.mixins import CreateUpdateModelAMixin
 | |
| from rest_framework import serializers
 | |
| from django.db.models import Count
 | |
| 
 | |
| from utils.tools import ranstr
 | |
| 
 | |
| class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
 | |
|     """
 | |
|     销售记录
 | |
|     """
 | |
|     perms_map = {'get': '*', 'post':'sale_create', 'delete':'sale_delete'}
 | |
|     queryset = Sale.objects.select_related('customer', 'order', 'product', 'order__contract').all()
 | |
|     serializer_class = SaleListSerializer
 | |
|     search_fields = ['customer__name', 'order__number']
 | |
|     filterset_fields = ['product', 'order', 'customer']
 | |
|     ordering_fields = ['create_time']
 | |
|     ordering = ['-create_time']
 | |
| 
 | |
|     def get_serializer_class(self):
 | |
|         if self.action == 'create':
 | |
|             return SaleCreateSerializer
 | |
|         elif self.action == 'retrieve':
 | |
|             return SaleListSerializer
 | |
|         return super().get_serializer_class()
 | |
|         
 | |
|     @transaction.atomic
 | |
|     def destroy(self, request, *args, **kwargs):
 | |
|         obj = self.get_object()
 | |
|         if obj.is_audited:
 | |
|             raise exceptions.APIException('该销售记录已审核,不可删除')
 | |
|         obj.delete()
 | |
|         IProduct.objects.filter(sale_iproduct__sale=obj).update(state=IProduct.SALE_OK)
 | |
|         return Response()
 | |
| 
 | |
|     def create(self, request, *args, **kwargs):
 | |
|         data = request.data
 | |
|         serializer = SaleCreateSerializer(data=data)
 | |
|         serializer.is_valid(raise_exception=True)
 | |
|         vdata = serializer.validated_data
 | |
|         with transaction.atomic():
 | |
|             iproducts = vdata.pop('iproducts')
 | |
|             vdata['count'] = len(iproducts)
 | |
|             if vdata['count'] + vdata['order'].delivered_count > vdata['order'].count:
 | |
|                 raise exceptions.APIException('超过订单所需数量')
 | |
|             sale = Sale.objects.create(**vdata)
 | |
|             i_l = []
 | |
|             for i in iproducts:
 | |
|                 i.state = IProduct.SALE_LOCK
 | |
|                 i.save()
 | |
|                 i_d ={}
 | |
|                 i_d['sale'] = sale
 | |
|                 i_d['number'] = i.number
 | |
|                 i_d['iproduct'] = i
 | |
|                 i_l.append(SaleProduct(**i_d))
 | |
|             SaleProduct.objects.bulk_create(i_l)
 | |
|         return Response()
 | |
| 
 | |
|     @action(methods=['post'], detail=True, perms_map={'post':'sale_audit'}, serializer_class=serializers.Serializer)
 | |
|     @transaction.atomic
 | |
|     def audit(self, request, pk=None):
 | |
|         """
 | |
|         审核
 | |
|         """
 | |
|         obj = self.get_object()
 | |
|         if obj.is_audited:
 | |
|             raise exceptions.APIException('已审核通过')
 | |
|         if obj.order:
 | |
|             if obj.count + obj.order.delivered_count > obj.order.count:
 | |
|                 raise exceptions.APIException('超过订单所需数量')
 | |
|         # 创建出库记录
 | |
|         fifo = FIFO()
 | |
|         fifo.sale = obj
 | |
|         fifo.type = FIFO.FIFO_TYPE_SALE_OUT
 | |
|         fifo.is_audited = False
 | |
|         fifo.create_by = request.user
 | |
|         fifo.number = 'CK' + ranstr(7)
 | |
|         fifo.save()
 | |
|         
 | |
|         obj.is_audited = True
 | |
|         obj.save()
 | |
| 
 | |
|         return Response()
 | |
|     
 | |
|     @action(methods=['post'], detail=True, perms_map={'post':'sale_up_ship'}, serializer_class=SaleUpShipPicSerializer)
 | |
|     @transaction.atomic
 | |
|     def up_ship(self, request, pk=None):
 | |
|         """
 | |
|         上传物流信息
 | |
|         """
 | |
|         serializer = SaleUpShipPicSerializer(data=request.data)
 | |
|         serializer.is_valid(raise_exception=True)
 | |
|         vdata = serializer.validated_data
 | |
|         obj = self.get_object()
 | |
|         obj.ship_pic = vdata['path']
 | |
|         obj.save()
 | |
|         return Response()
 | |
| 
 | |
| 
 | |
| 
 | |
| class SaleProductViewSet(ListModelMixin, DestroyModelMixin, CreateModelMixin, GenericViewSet):
 | |
|     """
 | |
|     销售记录关联产品
 | |
|     """
 | |
|     perms_map = {'get': '*', 'post':'sale_update', 'delete':'sale_delete'}
 | |
|     queryset = SaleProduct.objects.select_related('iproduct', 'iproduct__material', 'iproduct__warehouse').all()
 | |
|     serializer_class = SaleProductListSerializer
 | |
|     search_fields = []
 | |
|     filterset_fields = ['sale', 'iproduct']
 | |
|     ordering_fields = ['create_time']
 | |
|     ordering = ['id']
 | |
| 
 | |
|     def get_serializer_class(self):
 | |
|         if self.action == 'create':
 | |
|             return SaleProductCreateSerializer
 | |
|         return super().get_serializer_class()
 | |
|     
 | |
|     def destroy(self, request, *args, **kwargs):
 | |
|         obj = self.get_object()
 | |
|         sale = obj.sale
 | |
|         if sale.is_audited:
 | |
|             raise exceptions.APIException('该销售记录已审核,不可删除产品')
 | |
|         obj.delete()
 | |
|         sale.count = SaleProduct.objects.filter(sale=obj.sale).count()
 | |
|         sale.save()
 | |
|         return Response()
 | |
| 
 | |
|     def create(self, request, *args, **kwargs):
 | |
|         obj = self.get_object()
 | |
|         sale = obj.sale
 | |
|         if sale.is_audited:
 | |
|             raise exceptions.APIException('该销售记录已审核,不可添加产品')
 | |
|         return super().create(request, *args, **kwargs)
 | |
| 
 | |
|     @action(methods=['get', 'post'], detail=True, perms_map={'post':'sale_pack', 'get':'*'}, serializer_class=SaleProductPackSerializer)
 | |
|     @transaction.atomic
 | |
|     def pack(self, request, pk=None):
 | |
|         """
 | |
|         打包装箱
 | |
|         """
 | |
|         obj = self.get_object()
 | |
|         if request.method == 'GET':
 | |
|             for i in PackItem.objects.filter(product=obj.iproduct.material, is_deleted=False):
 | |
|                 SalePack.objects.get_or_create(sale_product=obj, packitem=i,
 | |
|                 defaults={
 | |
|                     "sale_product":obj,
 | |
|                     "packitem":i,
 | |
|                     "count":i.count
 | |
|                 })
 | |
|             return Response(SaleProductPackDetailSerializer(instance=obj).data)
 | |
|         elif request.method == 'POST':
 | |
|             if not obj.sale.is_audited:
 | |
|                 raise exceptions.APIException('该销售记录未审核,不可装箱')
 | |
|             if obj.sale.fifo_sale.first().is_audited:
 | |
|                 raise exceptions.APIException('该销售记录已出库,不可装箱')
 | |
|         
 | |
|             serializer = SaleProductPackSerializer(data=request.data)
 | |
|             serializer.is_valid(raise_exception=True)
 | |
|             vdata = serializer.validated_data
 | |
|             obj.packnum = vdata['packnum']
 | |
|             obj.remark = vdata.get('remark', '')
 | |
|             for i in vdata['detail']:
 | |
|                 pi = i['id']
 | |
|                 pi.count = i['count']
 | |
|                 pi.save()
 | |
|             obj.save()
 | |
|             return Response()
 | |
| 
 | |
|     @action(methods=['post'], detail=True, perms_map={'post':'sale_pack'}, serializer_class=SRemarkItemCreateSerializer)
 | |
|     @transaction.atomic
 | |
|     def remark(self, request, pk=None):
 | |
|         """
 | |
|         不装箱备注
 | |
|         """
 | |
|         obj = self.get_object()
 | |
|         if obj.sale.is_audited:
 | |
|             raise exceptions.APIException('该销售记录已审核,不可填写备注')
 | |
|         if obj.sale.fifo_sale.first().is_audited:
 | |
|             raise exceptions.APIException('该销售记录已出库,不可装箱')
 | |
|         serializer = self.get_serializer(data=request.data)
 | |
|         serializer.is_valid(raise_exception=True)
 | |
|         vdata = serializer.validated_data
 | |
|         obj.remark = vdata['remark']
 | |
|         obj.save()
 | |
|         return Response() |