From 9eab3aa5921149bf843971ada4a793a892d32e9f Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 26 Jan 2022 09:21:23 +0800 Subject: [PATCH] =?UTF-8?q?iproduct=20list=E5=A2=9E=E5=8A=A0order=20to=5Fo?= =?UTF-8?q?rder=20=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/inm/filters.py | 4 +- hb_server/apps/inm/serializers.py | 7 +- hb_server/apps/inm/views.py | 4 +- hb_server/apps/sam/serializers.py | 51 +-------- hb_server/apps/sam/serializers_sale.py | 51 +++++++++ hb_server/apps/sam/urls.py | 4 +- hb_server/apps/sam/views.py | 143 +------------------------ hb_server/apps/sam/views_sale.py | 142 ++++++++++++++++++++++++ 8 files changed, 214 insertions(+), 192 deletions(-) create mode 100644 hb_server/apps/sam/serializers_sale.py create mode 100644 hb_server/apps/sam/views_sale.py diff --git a/hb_server/apps/inm/filters.py b/hb_server/apps/inm/filters.py index 41dcf61..3209136 100644 --- a/hb_server/apps/inm/filters.py +++ b/hb_server/apps/inm/filters.py @@ -3,7 +3,7 @@ from django_filters import rest_framework as filters from apps.mtm.models import Material from .models import IProduct, MaterialBatch from django.utils import timezone - +from utils.mixins import DynamicFieldsFilterMixin class MbFilterSet(filters.FilterSet): material = filters.ModelMultipleChoiceFilter(field_name="material", queryset=Material.objects.all()) @@ -20,7 +20,7 @@ class MbFilterSet(filters.FilterSet): return queryset -class IProductFilterSet(filters.FilterSet): +class IProductFilterSet(DynamicFieldsFilterMixin, filters.FilterSet): order = filters.NumberFilter(field_name="wproduct__subproduction_plan__production_plan__order") to_order = filters.NumberFilter(field_name="wproduct__to_order") update_time_start = filters.DateFilter(field_name="update_time", lookup_expr='gte') diff --git a/hb_server/apps/inm/serializers.py b/hb_server/apps/inm/serializers.py index 1a35e32..6f4b97a 100644 --- a/hb_server/apps/inm/serializers.py +++ b/hb_server/apps/inm/serializers.py @@ -3,11 +3,13 @@ from rest_framework import serializers from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, MaterialBatch, WareHouse, Inventory from apps.qm.models import TestRecord, TestRecordItem +from apps.sam.serializers import OrderSimpleSerializer from apps.system.serializers import FileSimpleSerializer, UserSimpleSerializer from apps.mtm.serializers import MaterialSimpleSerializer from django.db import transaction +from utils.mixins import DynamicFieldsSerializerMixin @@ -49,12 +51,15 @@ class MaterialBatchSerializer(serializers.ModelSerializer): fields = '__all__' -class IProductListSerializer(serializers.ModelSerializer): +class IProductListSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializer): material_ = MaterialSimpleSerializer(source='material', read_only=True) warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True) need_to_order = serializers.BooleanField(source='wproduct.need_to_order', read_only=True) is_mtestok = serializers.BooleanField(source='wproduct.is_mtestok', read_only=True) remark_mtest = serializers.CharField(source='wproduct.remark_mtest', read_only=True) + to_order_ = OrderSimpleSerializer(source='wproduct.to_order', read_only=True) + order_ = OrderSimpleSerializer( + source='wproduct.subproduction_plan.production_plan.order', read_only=True) class Meta: model = IProduct fields = '__all__' diff --git a/hb_server/apps/inm/views.py b/hb_server/apps/inm/views.py index 8f20cf7..26823cb 100644 --- a/hb_server/apps/inm/views.py +++ b/hb_server/apps/inm/views.py @@ -187,7 +187,9 @@ class IProductViewSet(ListModelMixin, GenericViewSet): """ perms_map = {'*': '*'} queryset = IProduct.objects.select_related( - 'material', 'warehouse', 'wproduct__subproduction_plan__production_plan__order') + 'material', 'warehouse', + 'wproduct__subproduction_plan__production_plan__order', + 'wproduct__to_order') serializer_class = IProductListSerializer filterset_class = IProductFilterSet search_fields = [] diff --git a/hb_server/apps/sam/serializers.py b/hb_server/apps/sam/serializers.py index a7d618b..ac0e9a6 100644 --- a/hb_server/apps/sam/serializers.py +++ b/hb_server/apps/sam/serializers.py @@ -1,10 +1,7 @@ -from django.db import transaction -from rest_framework import exceptions, serializers -from apps.inm.models import IProduct -from apps.inm.serializers import IProductListSerializer +from rest_framework import serializers -from .models import Contract, Customer, Order, Sale, SaleProduct +from .models import Contract, Customer, Order from apps.mtm.serializers import MaterialSimpleSerializer from utils.tools import ranstr @@ -65,47 +62,3 @@ class OrderSimpleSerializer(serializers.ModelSerializer): model = Order fields = ['id', 'number', 'contract_', 'customer_', 'need_mtest', 'delivery_date'] -class SaleCreateSerializer(serializers.ModelSerializer): - iproducts = serializers.PrimaryKeyRelatedField(queryset= - IProduct.objects.all(), many=True) - class Meta: - model = Sale - fields = ['customer', 'order', 'product', 'iproducts'] - - def validate(self, attrs): - order = attrs.get('order', None) - if order: - if order.customer: - attrs['customer'] = order.customer - attrs['product'] = order.product - for i in attrs['iproducts']: - if i.material != attrs['product']: - raise exceptions.APIException('产品选取错误') - return super().validate(attrs) - - -class SaleListSerializer(serializers.ModelSerializer): - customer_ = CustomerSimpleSerializer(source='customer', read_only=True) - order_ = OrderSimpleSerializer(source='order', read_only=True) - product_ = MaterialSimpleSerializer(source='product', read_only=True) - class Meta: - model = Sale - fields = '__all__' - -class SaleProductListSerializer(serializers.ModelSerializer): - iproduct_ = IProductListSerializer(source='iproduct', read_only=True) - class Meta: - model = SaleProduct - fields = '__all__' - -class SaleProductCreateSerializer(serializers.ModelSerializer): - class Meta: - model = SaleProduct - fields = ['sale', 'iproduct'] - - def create(self, validated_data): - validated_data['number'] = validated_data['iproduct'].number - instance = SaleProduct.objects.create(**validated_data) - instance.sale.count = SaleProduct.objects.filter(sale=instance.sale).count() - instance.sale.save() - return instance \ No newline at end of file diff --git a/hb_server/apps/sam/serializers_sale.py b/hb_server/apps/sam/serializers_sale.py new file mode 100644 index 0000000..627c4f2 --- /dev/null +++ b/hb_server/apps/sam/serializers_sale.py @@ -0,0 +1,51 @@ +from rest_framework import serializers +from rest_framework import exceptions +from apps.inm.models import IProduct +from apps.inm.serializers import IProductListSerializer +from apps.mtm.serializers import MaterialSimpleSerializer +from apps.sam.models import Sale, SaleProduct +from apps.sam.serializers import CustomerSimpleSerializer, OrderSimpleSerializer +class SaleCreateSerializer(serializers.ModelSerializer): + iproducts = serializers.PrimaryKeyRelatedField(queryset= + IProduct.objects.all(), many=True) + class Meta: + model = Sale + fields = ['customer', 'order', 'product', 'iproducts'] + + def validate(self, attrs): + order = attrs.get('order', None) + if order: + if order.customer: + attrs['customer'] = order.customer + attrs['product'] = order.product + for i in attrs['iproducts']: + if i.material != attrs['product']: + raise exceptions.APIException('产品选取错误') + return super().validate(attrs) + + +class SaleListSerializer(serializers.ModelSerializer): + customer_ = CustomerSimpleSerializer(source='customer', read_only=True) + order_ = OrderSimpleSerializer(source='order', read_only=True) + product_ = MaterialSimpleSerializer(source='product', read_only=True) + class Meta: + model = Sale + fields = '__all__' + +class SaleProductListSerializer(serializers.ModelSerializer): + iproduct_ = IProductListSerializer(source='iproduct', read_only=True) + class Meta: + model = SaleProduct + fields = '__all__' + +class SaleProductCreateSerializer(serializers.ModelSerializer): + class Meta: + model = SaleProduct + fields = ['sale', 'iproduct'] + + def create(self, validated_data): + validated_data['number'] = validated_data['iproduct'].number + instance = SaleProduct.objects.create(**validated_data) + instance.sale.count = SaleProduct.objects.filter(sale=instance.sale).count() + instance.sale.save() + return instance \ No newline at end of file diff --git a/hb_server/apps/sam/urls.py b/hb_server/apps/sam/urls.py index 7a66e01..5907df0 100644 --- a/hb_server/apps/sam/urls.py +++ b/hb_server/apps/sam/urls.py @@ -1,9 +1,11 @@ from django.db.models import base from rest_framework import urlpatterns -from apps.sam.views import CustomerViewSet,ContractViewSet,OrderViewSet, SaleProductViewSet, SaleViewSet +from apps.sam.views import CustomerViewSet,ContractViewSet, OrderViewSet from django.urls import path, include from rest_framework.routers import DefaultRouter +from apps.sam.views_sale import SaleProductViewSet, SaleViewSet + router = DefaultRouter() router.register('customer', CustomerViewSet, basename='customer') router.register('contract', ContractViewSet, basename='contract') diff --git a/hb_server/apps/sam/views.py b/hb_server/apps/sam/views.py index 357706e..ea52cb4 100644 --- a/hb_server/apps/sam/views.py +++ b/hb_server/apps/sam/views.py @@ -1,22 +1,12 @@ -from django.db import transaction -from django.db.models.aggregates import Count -from rest_framework import exceptions, serializers -from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin -from apps.mtm.models import Material -from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse -from apps.inm.signals import update_inm from apps.sam.filters import ContractFilterSet, OrderFilterSet -from apps.sam.serializers import ContractCreateUpdateSerializer, ContractSerializer, CustomerCreateUpdateSerializer, CustomerSerializer, OrderCreateUpdateSerializer, OrderSerializer, SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer -from apps.sam.models import Contract, Customer, Order, Sale, SaleProduct -from rest_framework.viewsets import GenericViewSet, ModelViewSet +from apps.sam.serializers import ContractCreateUpdateSerializer, ContractSerializer, \ + CustomerCreateUpdateSerializer, CustomerSerializer, OrderCreateUpdateSerializer, OrderSerializer +from apps.sam.models import Contract, Customer, Order +from rest_framework.viewsets import ModelViewSet from apps.system.mixins import CreateUpdateCustomMixin -from django.shortcuts import render -from rest_framework.decorators import action from django.db.models import F from rest_framework.response import Response -from django.utils import timezone - -from apps.wf.models import Workflow +from rest_framework.decorators import action # Create your views here. class CustomerViewSet(CreateUpdateCustomMixin, ModelViewSet): """ @@ -81,129 +71,6 @@ class OrderViewSet(CreateUpdateCustomMixin, ModelViewSet): return Response(serializer.data) -class SaleViewSet(CreateUpdateCustomMixin, ListModelMixin, RetrieveModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet): - """ - 销售记录 - """ - perms_map = {'*': '*'} - 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 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) - sale = Sale.objects.create(**vdata) - i_l = [] - for i in iproducts: - 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':'*'}, serializer_class=serializers.Serializer) - @transaction.atomic - def audit(self, request, pk=None): - """ - 审核 - """ - obj = self.get_object() - if obj.is_audited: - raise exceptions.APIException('已审核通过') - # 创建出库记录 - fifo = FIFO() - fifo.type = FIFO.FIFO_TYPE_SALE_OUT - fifo.is_audited = True - fifo.auditor = request.user - fifo.inout_date = timezone.now() - fifo.create_by = request.user - fifo.save() - # 创建出库条目 - ips = IProduct.objects.filter(sale_iproduct__sale=obj) - items = ips.values('warehouse', 'material', 'batch').annotate(total=Count('id')) - for i in items: - warehouse = WareHouse.objects.get(id=i['warehouse']) - material = Material.objects.get(id=i['material']) - fifoitem = FIFOItem() - fifoitem.need_test = False - fifoitem.warehouse = warehouse - fifoitem.material = material - fifoitem.count = i['total'] - fifoitem.batch = i['batch'] - fifoitem.fifo = fifo - fifoitem.save() - items_p = ips.filter(warehouse=warehouse, batch=i['batch']) - ipxs = [] - for i in items_p: - # 创建出库明细半成品 - ip = {} - ip['fifoitem'] = fifoitem - ip['number'] = i.number - ip['material'] = i.material - ip['iproduct'] = i - ipxs.append(FIFOItemProduct(**ip)) - FIFOItemProduct.objects.bulk_create(ipxs) - # 更新成品库情况 - ips.update(is_saled=True) - # 更新动态产品表情况 - from apps.wpm.models import WProduct - WProduct.objects.filter(iproduct_wproduct__sale_iproduct__sale=obj).update( - act_state=WProduct.WPR_ACT_STATE_SELLED) - # 更新库存 - update_inm(fifo) - # 变更审核状态 - obj.is_audited = True - obj.save() - # 变更订单状态 - if obj.order: - order = obj.order - order.delivered_count = order.delivered_count + obj.count - order.save() - return Response() - -class SaleProductViewSet(ListModelMixin, DestroyModelMixin, CreateModelMixin, GenericViewSet): - """ - 销售记录关联产品 - """ - perms_map = {'*': '*'} - 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('该销售记录已审核,不可删除产品') - sale.count = SaleProduct.objects.filter(sale=obj.sale).count() - sale.save() - obj.delete() - return Response() \ No newline at end of file diff --git a/hb_server/apps/sam/views_sale.py b/hb_server/apps/sam/views_sale.py new file mode 100644 index 0000000..c2c81a1 --- /dev/null +++ b/hb_server/apps/sam/views_sale.py @@ -0,0 +1,142 @@ +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.mtm.models import Material +from apps.sam.models import Sale, SaleProduct +from apps.sam.serializers_sale import SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer +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 apps.inm.signals import update_inm +from rest_framework import serializers + +class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet): + """ + 销售记录 + """ + perms_map = {'*': '*'} + 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 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) + sale = Sale.objects.create(**vdata) + i_l = [] + for i in iproducts: + 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':'*'}, serializer_class=serializers.Serializer) + @transaction.atomic + def audit(self, request, pk=None): + """ + 审核 + """ + obj = self.get_object() + if obj.is_audited: + raise exceptions.APIException('已审核通过') + # 创建出库记录 + fifo = FIFO() + fifo.type = FIFO.FIFO_TYPE_SALE_OUT + fifo.is_audited = True + fifo.auditor = request.user + fifo.inout_date = timezone.now() + fifo.create_by = request.user + fifo.save() + # 创建出库条目 + ips = IProduct.objects.filter(sale_iproduct__sale=obj) + items = ips.values('warehouse', 'material', 'batch').annotate(total=Count('id')) + for i in items: + warehouse = WareHouse.objects.get(id=i['warehouse']) + material = Material.objects.get(id=i['material']) + fifoitem = FIFOItem() + fifoitem.need_test = False + fifoitem.warehouse = warehouse + fifoitem.material = material + fifoitem.count = i['total'] + fifoitem.batch = i['batch'] + fifoitem.fifo = fifo + fifoitem.save() + items_p = ips.filter(warehouse=warehouse, batch=i['batch']) + ipxs = [] + for i in items_p: + # 创建出库明细半成品 + ip = {} + ip['fifoitem'] = fifoitem + ip['number'] = i.number + ip['material'] = i.material + ip['iproduct'] = i + ipxs.append(FIFOItemProduct(**ip)) + FIFOItemProduct.objects.bulk_create(ipxs) + # 更新成品库情况 + ips.update(is_saled=True) + # 更新动态产品表情况 + from apps.wpm.models import WProduct + WProduct.objects.filter(iproduct_wproduct__sale_iproduct__sale=obj).update( + act_state=WProduct.WPR_ACT_STATE_SELLED) + # 更新库存 + update_inm(fifo) + # 变更审核状态 + obj.is_audited = True + obj.save() + # 变更订单状态 + if obj.order: + order = obj.order + order.delivered_count = order.delivered_count + obj.count + order.save() + return Response() + + + +class SaleProductViewSet(ListModelMixin, DestroyModelMixin, CreateModelMixin, GenericViewSet): + """ + 销售记录关联产品 + """ + perms_map = {'*': '*'} + 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('该销售记录已审核,不可删除产品') + sale.count = SaleProduct.objects.filter(sale=obj.sale).count() + sale.save() + obj.delete() + return Response() \ No newline at end of file