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 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() 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() 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.auditor = request.user fifo.inout_date = timezone.now() fifo.create_by = request.user fifo.number = 'CK' + ranstr(7) fifo.save() obj.is_audited = True 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': 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() 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()