1124 lines
		
	
	
		
			49 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			1124 lines
		
	
	
		
			49 KiB
		
	
	
	
		
			Python
		
	
	
	
from django.db.models.expressions import F
 | 
						|
from django.shortcuts import render
 | 
						|
from rest_framework.generics import CreateAPIView, GenericAPIView
 | 
						|
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin
 | 
						|
from rest_framework.utils import serializer_helpers
 | 
						|
from rest_framework.utils.field_mapping import get_relation_kwargs
 | 
						|
from rest_framework.views import APIView
 | 
						|
from rest_framework.viewsets import GenericViewSet, ModelViewSet
 | 
						|
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse
 | 
						|
from apps.inm.signals import update_inm
 | 
						|
from apps.mtm.models import Material, RecordForm, RecordFormField, Step, SubprodctionMaterial, TechDoc
 | 
						|
from apps.mtm.serializers import RecordFormDetailSerializer, SubprodctionMaterialListSerializer, TechDocListSerializer
 | 
						|
from apps.pm.models import SubProductionPlan, SubProductionProgress
 | 
						|
from apps.pm.serializers import SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
 | 
						|
from apps.qm.models import TestRecord, TestRecordItem
 | 
						|
from apps.qm.serializers import TestRecordDetailSerializer
 | 
						|
 | 
						|
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
 | 
						|
from rest_framework.decorators import action
 | 
						|
from apps.wf.models import Workflow
 | 
						|
from apps.wf.serializers import WorkflowSimpleSerializer
 | 
						|
from apps.wpm.filters import CuttingFilterSet, WMaterialFilterSet, WProductFilterSet
 | 
						|
from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem, WprouctTicket
 | 
						|
 | 
						|
from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordDetailSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickHalfsSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, WProductCardSerializer, WProductDetailSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestFormInitSerializer, WpmTestRecordCreateSerializer, WproductMtestSerializer, WproductPutInSerializer, WproductPutInsSerializer, WproductTicketListSerializer
 | 
						|
from rest_framework.response import Response
 | 
						|
from django.db import transaction
 | 
						|
from rest_framework import exceptions, serializers
 | 
						|
 | 
						|
from apps.wpm.services import WpmServies
 | 
						|
from django.utils import timezone
 | 
						|
from utils.tools import ranstr
 | 
						|
from rest_framework import status
 | 
						|
from django.db.models import Count
 | 
						|
# Create your views here.
 | 
						|
class WPlanViewSet(ListModelMixin, GenericViewSet):
 | 
						|
    """
 | 
						|
    车间生产计划
 | 
						|
    """
 | 
						|
    perms_map = {'*': '*'}
 | 
						|
    queryset = SubProductionPlan.objects.select_related('process', 'workshop', 'subproduction', 'product').exclude(state=0)
 | 
						|
    search_fields = []
 | 
						|
    serializer_class = SubProductionPlanListSerializer
 | 
						|
    filterset_fields = ['production_plan', 'process', 'state', 'product', 'workshop']
 | 
						|
    ordering_fields = []
 | 
						|
    ordering = ['-update_time']
 | 
						|
 | 
						|
    @action(methods=['post', 'get'], detail=True, perms_map={'post':'*', 'get':'*'}, serializer_class=PickHalfsSerializer)
 | 
						|
    @transaction.atomic
 | 
						|
    def pick_half(self, request, pk=None):
 | 
						|
        """
 | 
						|
        领半成品
 | 
						|
        """
 | 
						|
        sp = self.get_object()
 | 
						|
        if request.method=='GET':
 | 
						|
            """
 | 
						|
            领半成品
 | 
						|
            """
 | 
						|
            spps = SubProductionProgress.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN, 
 | 
						|
                material__type=Material.MA_TYPE_HALFGOOD, subproduction_plan=sp).select_related('material')
 | 
						|
            return Response(SubProductionProgressSerializer(instance=spps, many=True).data)
 | 
						|
        elif request.method=='POST':
 | 
						|
            serializer= PickHalfsSerializer(data=request.data)
 | 
						|
            serializer.is_valid(raise_exception=True)
 | 
						|
            vdata = serializer.validated_data
 | 
						|
            first_step = Step.objects.get(pk=sp.steps[0]['id'])
 | 
						|
            # 创建领料记录
 | 
						|
            pick = Pick()
 | 
						|
            pick.subproduction_plan = sp
 | 
						|
            pick.type = Pick.PICK_FROM_WPRODUCT
 | 
						|
            pick.create_by = request.user
 | 
						|
            pick.save()
 | 
						|
            for i in vdata:
 | 
						|
                if 'wproducts' in i and len(i['wproducts'])>0:
 | 
						|
                    spp = i['id']
 | 
						|
                    spp.count_pick = spp.count_pick + len(i['wproducts'])
 | 
						|
                    # if spp.count_pick > spp.count:
 | 
						|
                    #     raise exceptions.APIException('超过计划数')
 | 
						|
                    spp.save()
 | 
						|
                    wps = WProduct.objects.filter(pk__in=[x.id for x in i['wproducts']], act_state=WProduct.WPR_ACT_STATE_OK)
 | 
						|
                    wps.update(step=first_step, 
 | 
						|
                    act_state=WProduct.WPR_ACT_STATE_TORETEST, is_hidden=False, warehouse=None,
 | 
						|
                    subproduction_plan=sp, update_by=request.user, update_time=timezone.now())
 | 
						|
                    
 | 
						|
                    for m in i['wproducts']:
 | 
						|
                        m.step = first_step
 | 
						|
                        m.act_state = WProduct.WPR_ACT_STATE_TORETEST
 | 
						|
                        m.is_hidden = False
 | 
						|
                        m.warehouse = None
 | 
						|
                        m.subproduction_plan = sp
 | 
						|
                        m.update_by = request.user
 | 
						|
                        m.update_time = timezone.now()
 | 
						|
                        m.save()
 | 
						|
                        WpmServies.add_wproduct_flow_log(instance=m, change_str='pick_half')
 | 
						|
                        pw = PickWproduct()
 | 
						|
                        pw.pick =pick
 | 
						|
                        pw.wproduct = m
 | 
						|
                        pw.number = m.number
 | 
						|
                        pw.material = m.material
 | 
						|
                        pw.subproduction_plan = m.subproduction_plan
 | 
						|
                        pw.save()
 | 
						|
            sp.is_picked = True
 | 
						|
            sp.save()
 | 
						|
            
 | 
						|
            return Response()
 | 
						|
        
 | 
						|
 | 
						|
    # @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WplanPutInSerializer)
 | 
						|
    # @transaction.atomic
 | 
						|
    # def putin(self, request, pk=None):
 | 
						|
    #     """
 | 
						|
    #     半成品入库
 | 
						|
    #     """
 | 
						|
    #     serializer= WplanPutInSerializer(data=request.data)
 | 
						|
    #     serializer.is_valid(raise_exception=True)
 | 
						|
    #     vdata = serializer.validated_data
 | 
						|
    #     subplan = self.get_object()
 | 
						|
    #     material = subplan.product
 | 
						|
    #     batch = subplan.number
 | 
						|
    #     warehouse = vdata['warehouse']
 | 
						|
    #     wproducts = WProduct.objects.filter(subproduction_plan=subplan, 
 | 
						|
    #         act_state=WProduct.WPR_ACT_STATE_OK, material=material, is_deleted=False)
 | 
						|
    #     if wproducts.exists():
 | 
						|
    #         # 创建入库记录
 | 
						|
    #         remark = vdata.get('remark', '')
 | 
						|
    #         fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN,
 | 
						|
    #             is_audited=True, auditor=request.user, inout_date=timezone.now(), create_by=request.user, remark=remark)
 | 
						|
    #         # 创建入库明细
 | 
						|
    #         fifoitem = FIFOItem()
 | 
						|
    #         fifoitem.is_tested = True
 | 
						|
    #         fifoitem.is_testok = True
 | 
						|
    #         fifoitem.warehouse = warehouse 
 | 
						|
    #         fifoitem.material = material
 | 
						|
    #         fifoitem.count = wproducts.count()
 | 
						|
    #         fifoitem.batch = batch
 | 
						|
    #         fifoitem.fifo = fifo
 | 
						|
    #         fifoitem.subproduction_plan = subplan
 | 
						|
    #         fifoitem.save()
 | 
						|
    #         # 创建入库明细半成品
 | 
						|
    #         ips = []
 | 
						|
    #         for i in wproducts:
 | 
						|
    #             ip = {}
 | 
						|
    #             ip['fifoitem'] = fifoitem
 | 
						|
    #             ip['wproduct'] = i
 | 
						|
    #             ip['number'] = i.number
 | 
						|
    #             ip['material'] = material
 | 
						|
    #             ips.append(FIFOItemProduct(**ip))
 | 
						|
    #         FIFOItemProduct.objects.bulk_create(ips)
 | 
						|
    #         # 创建IProduct
 | 
						|
    #         ips2 = []
 | 
						|
    #         for i in wproducts:
 | 
						|
    #             ip = {}
 | 
						|
    #             ip['warehouse'] = warehouse
 | 
						|
    #             ip['batch'] = batch
 | 
						|
    #             ip['wproduct'] = i
 | 
						|
    #             ip['number'] = i.number
 | 
						|
    #             ip['material'] = material
 | 
						|
    #             ips2.append(IProduct(**ip))
 | 
						|
    #         IProduct.objects.bulk_create(ips2)
 | 
						|
    #         # 更新库存并修改半成品进行状态
 | 
						|
    #         update_inm(fifo)
 | 
						|
    #         wproducts.update(act_sate=WProduct.WPR_ACT_STATE_INM, warehouse=warehouse, update_by=request.user, update_time=timezone.now())
 | 
						|
            
 | 
						|
    #     return Response()
 | 
						|
 | 
						|
 | 
						|
class WMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, GenericViewSet):
 | 
						|
    """
 | 
						|
    车间物料表
 | 
						|
    """
 | 
						|
    perms_map={'*':'*'}
 | 
						|
    queryset = WMaterial.objects.select_related('material', 'subproduction_plan').filter(count__gt=0)
 | 
						|
    serializer_class = WMaterialListSerializer
 | 
						|
    filterset_class = WMaterialFilterSet
 | 
						|
    ordering_fields = ['material__number']
 | 
						|
    ordering = ['material__number']
 | 
						|
 | 
						|
    @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=PickSerializer)
 | 
						|
    def pick(self, request, pk=None):
 | 
						|
        """
 | 
						|
        领料
 | 
						|
        """
 | 
						|
        serializer= PickSerializer(data=request.data, context={'request': request})
 | 
						|
        serializer.is_valid(raise_exception=True)
 | 
						|
        serializer.save()
 | 
						|
        return Response()
 | 
						|
 | 
						|
class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
 | 
						|
    """
 | 
						|
    半成品
 | 
						|
    """
 | 
						|
    perms_map={'*':'*'}
 | 
						|
    queryset = WProduct.objects.select_related('step', 'material', 
 | 
						|
                'subproduction_plan', 'warehouse').prefetch_related('wproduct_child')
 | 
						|
    serializer_class = WProductListSerializer
 | 
						|
    filterset_class = WProductFilterSet
 | 
						|
    search_fields = ['number']
 | 
						|
    ordering_fields = ['id']
 | 
						|
    ordering = ['id']
 | 
						|
    
 | 
						|
    def get_serializer_class(self):
 | 
						|
        if self.action == 'retrieve':
 | 
						|
            return WProductDetailSerializer
 | 
						|
        return super().get_serializer_class()
 | 
						|
 | 
						|
    def get_queryset(self):
 | 
						|
        queryset = self.queryset
 | 
						|
        if self.request.query_params.get('tag', None) != 'show_hidden':
 | 
						|
            queryset = queryset.filter(is_hidden=False)
 | 
						|
        return queryset
 | 
						|
 | 
						|
    @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=WpmTestFormInitSerializer)
 | 
						|
    @transaction.atomic
 | 
						|
    def test_init(self, request, pk=None):
 | 
						|
        """
 | 
						|
        检验记录创建及初始化
 | 
						|
        """
 | 
						|
        serializer = WpmTestFormInitSerializer(data=request.data)
 | 
						|
        serializer.is_valid(raise_exception=True)
 | 
						|
        vdata = serializer.validated_data
 | 
						|
        wproduct = vdata['wproduct']
 | 
						|
        form = vdata['form']
 | 
						|
        if wproduct.test:
 | 
						|
            raise exceptions.APIException('存在进行中检验')
 | 
						|
 | 
						|
        # 根据情况创建一条检验记录
 | 
						|
        if wproduct.act_state not in [WProduct.WPR_ACT_STATE_TOTEST, 
 | 
						|
                                    WProduct.WPR_ACT_STATE_TORETEST, WProduct.WPR_ACT_STATE_TOFINALTEST, WProduct.WPR_ACT_STATE_TOCOMBTEST]:
 | 
						|
            raise exceptions.APIException('该产品当前状态不可检验')
 | 
						|
        
 | 
						|
        savedict = dict(
 | 
						|
            create_by = self.request.user, 
 | 
						|
            wproduct=wproduct,
 | 
						|
        material=wproduct.material, 
 | 
						|
        number=wproduct.number, 
 | 
						|
        subproduction_plan=wproduct.subproduction_plan, 
 | 
						|
        step=wproduct.step,
 | 
						|
        form=form)
 | 
						|
        if wproduct.act_state == WProduct.WPR_ACT_STATE_TORETEST:
 | 
						|
            # 查找最近一条检验记录
 | 
						|
            trs = wproduct.last_process_test
 | 
						|
            savedict['origin_test'] = trs
 | 
						|
            if not trs:
 | 
						|
                raise exceptions.APIException('原工序检验记录不存在')
 | 
						|
            savedict['type'] = TestRecord.TEST_PROCESS_RE
 | 
						|
        elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOFINALTEST:
 | 
						|
            savedict['type'] = TestRecord.TEST_FINAL
 | 
						|
        elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOCOMBTEST:
 | 
						|
            savedict['type'] = TestRecord.TEST_COMB
 | 
						|
        tr = TestRecord.objects.create(**savedict)
 | 
						|
        # 更新wproduct
 | 
						|
        wproduct.test = tr
 | 
						|
        wproduct.update_by = request.user
 | 
						|
        wproduct.update_time = timezone.now()
 | 
						|
        wproduct.save()
 | 
						|
        WpmServies.add_wproduct_flow_log(wproduct, 'test_init')
 | 
						|
        # 创建检验条目
 | 
						|
        for i in RecordFormField.objects.filter(form=form, is_deleted=False):
 | 
						|
            tri = TestRecordItem()
 | 
						|
            tri.test_record = tr
 | 
						|
            tri.form_field = i
 | 
						|
            tri.is_hidden = i.is_hidden
 | 
						|
            tri.save()
 | 
						|
        return Response(TestRecordDetailSerializer(instance=tr).data)
 | 
						|
 | 
						|
    @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=WproductPutInsSerializer)
 | 
						|
    @transaction.atomic
 | 
						|
    def putins(self, request, pk=None):
 | 
						|
        """
 | 
						|
        半成品批量入库
 | 
						|
        """
 | 
						|
        serializer= WproductPutInsSerializer(data=request.data)
 | 
						|
        serializer.is_valid(raise_exception=True)
 | 
						|
        vdata = serializer.validated_data
 | 
						|
        wproducts = WProduct.objects.filter(pk__in=[x.id for x in vdata['wproducts']])
 | 
						|
        warehouse = vdata['warehouse']
 | 
						|
        for i in wproducts:
 | 
						|
            if i.act_state is not WProduct.WPR_ACT_STATE_OK:
 | 
						|
                raise exceptions.APIException('存在不可入库半成品')
 | 
						|
        # 聚合一下
 | 
						|
        wproducts_a = wproducts.values('subproduction_plan', 'material', 'subproduction_plan__number').annotate(total=Count('id'))
 | 
						|
        # 创建入库记录
 | 
						|
        remark = vdata.get('remark', '')
 | 
						|
        fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN,
 | 
						|
            is_audited=True, auditor=request.user, inout_date=timezone.now(), create_by=request.user, remark=remark)
 | 
						|
        # 创建入库明细
 | 
						|
        for i in wproducts_a:
 | 
						|
            spi = SubProductionPlan.objects.get(pk=i['subproduction_plan'])
 | 
						|
            fifoitem = FIFOItem()
 | 
						|
            fifoitem.is_tested = True
 | 
						|
            fifoitem.is_testok = True
 | 
						|
            fifoitem.warehouse = warehouse
 | 
						|
            fifoitem.material = Material.objects.get(pk=i['material'])
 | 
						|
            fifoitem.count = i['total']
 | 
						|
            fifoitem.batch = spi.number
 | 
						|
            fifoitem.fifo = fifo
 | 
						|
            fifoitem.subproduction_plan = spi
 | 
						|
            fifoitem.save()
 | 
						|
 | 
						|
            wproducts_items = wproducts.filter(subproduction_plan=i['subproduction_plan'], material=i['material'])
 | 
						|
            ips = []
 | 
						|
            for i in wproducts_items:       
 | 
						|
                # 创建入库明细半成品
 | 
						|
                ip = {}
 | 
						|
                ip['fifoitem'] = fifoitem
 | 
						|
                ip['wproduct'] = i
 | 
						|
                ip['number'] = i.number
 | 
						|
                ip['material'] = i.material
 | 
						|
                ips.append(FIFOItemProduct(**ip))
 | 
						|
            FIFOItemProduct.objects.bulk_create(ips)
 | 
						|
        # 更新库存并修改半成品进行状态
 | 
						|
        update_inm(fifo)
 | 
						|
        for i in wproducts:
 | 
						|
            i.act_state = WProduct.WPR_ACT_STATE_INM
 | 
						|
            i.warehouse = warehouse
 | 
						|
            i.update_by = request.user
 | 
						|
            i.update_time = timezone.now()
 | 
						|
            i.save()
 | 
						|
            WpmServies.add_wproduct_flow_log(i, 'putins')
 | 
						|
        return Response()
 | 
						|
    
 | 
						|
    @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WproductPutInSerializer)
 | 
						|
    @transaction.atomic
 | 
						|
    def putin(self, request, pk=None):
 | 
						|
        """
 | 
						|
        半成品入库
 | 
						|
        """
 | 
						|
        serializer= WproductPutInSerializer(data=request.data)
 | 
						|
        serializer.is_valid(raise_exception=True)
 | 
						|
        vdata = serializer.validated_data
 | 
						|
        wproduct = self.get_object()
 | 
						|
        warehouse = vdata['warehouse']
 | 
						|
        if wproduct.act_state != WProduct.WPR_ACT_STATE_OK:
 | 
						|
            raise exceptions.APIException('半成品不可入库')
 | 
						|
        material = wproduct.material
 | 
						|
        batch = wproduct.subproduction_plan.number
 | 
						|
        # 创建入库记录
 | 
						|
        remark = vdata.get('remark', '')
 | 
						|
        fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN,
 | 
						|
            is_audited=True, auditor=request.user, inout_date=timezone.now(), create_by=request.user, remark=remark)
 | 
						|
        # 创建入库明细
 | 
						|
        fifoitem = FIFOItem()
 | 
						|
        fifoitem.is_tested = True
 | 
						|
        fifoitem.is_testok = True
 | 
						|
        fifoitem.warehouse = warehouse
 | 
						|
        fifoitem.material = material
 | 
						|
        fifoitem.count = 1 # 单个半成品入库
 | 
						|
        fifoitem.batch = batch
 | 
						|
        fifoitem.fifo = fifo
 | 
						|
        fifoitem.subproduction_plan = wproduct.subproduction_plan
 | 
						|
        fifoitem.save()
 | 
						|
        # 创建入库明细半成品
 | 
						|
        ips = []
 | 
						|
        for i in [wproduct]:
 | 
						|
            ip = {}
 | 
						|
            ip['fifoitem'] = fifoitem
 | 
						|
            ip['wproduct'] = i
 | 
						|
            ip['number'] = i.number
 | 
						|
            ip['material'] = material
 | 
						|
            ips.append(FIFOItemProduct(**ip))
 | 
						|
        FIFOItemProduct.objects.bulk_create(ips)
 | 
						|
        # 更新库存并修改半成品进行状态
 | 
						|
        update_inm(fifo)
 | 
						|
        wproduct.act_state=WProduct.WPR_ACT_STATE_INM
 | 
						|
        wproduct.warehouse=warehouse
 | 
						|
        wproduct.save()
 | 
						|
        WpmServies.add_wproduct_flow_log(wproduct, 'putin')
 | 
						|
        return Response()
 | 
						|
 | 
						|
    @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=ScrapSerializer)
 | 
						|
    def scrap(self, request, pk=None):
 | 
						|
        """
 | 
						|
        报废操作
 | 
						|
        """
 | 
						|
        obj = self.get_object()
 | 
						|
        serializer = ScrapSerializer(data=request.data)
 | 
						|
        serializer.is_valid(raise_exception=True)
 | 
						|
        vdata = serializer.validated_data
 | 
						|
        if obj.act_state == WProduct.WPR_ACT_STATE_NOTOK:
 | 
						|
            pass
 | 
						|
        elif obj.step.process.id == 1 and \
 | 
						|
            obj.act_state in [WProduct.WPR_ACT_STATE_DOWAIT, WProduct.WPR_ACT_STATE_TOTEST]: # 如果是冷加工可直接报废
 | 
						|
            if vdata.get('scrap_reason', None):
 | 
						|
                obj.scrap_reason = vdata['scrap_reason']
 | 
						|
            else:
 | 
						|
                raise exceptions.APIException('请填写报废原因')
 | 
						|
        else:
 | 
						|
            raise exceptions.APIException('该产品不可报废')
 | 
						|
        obj.act_state = WProduct.WPR_ACT_STATE_SCRAP
 | 
						|
        obj.update_by = request.user
 | 
						|
        obj.update_time = timezone.now()
 | 
						|
        obj.save()
 | 
						|
        WpmServies.add_wproduct_flow_log(obj, 'scrap')
 | 
						|
        if obj.step.process.id == 1: #如果是冷加工
 | 
						|
            WpmServies.update_cutting_list_with_operation(obj.coperation)
 | 
						|
        return Response()
 | 
						|
 | 
						|
    # @action(methods=['get'], detail=False, perms_map={'get':'*'})
 | 
						|
    # def workflows(self, request, pk=None):
 | 
						|
    #     """
 | 
						|
    #     可发起的工作流
 | 
						|
    #     """
 | 
						|
    #     wfs = Workflow.objects.filter(key__startswith= 'wp_')
 | 
						|
    #     return WorkflowSimpleSerializer(instance=wfs, many=True).data
 | 
						|
 | 
						|
    @action(methods=['get'], detail=True, perms_map={'get':'*'})
 | 
						|
    def wf_bhg(self, request, pk=None):
 | 
						|
        """
 | 
						|
        发起不合格审理单
 | 
						|
        """
 | 
						|
        obj = self.get_object()
 | 
						|
        if obj.act_state != WProduct.WPR_ACT_STATE_NOTOK or obj.ng_sign is not None\
 | 
						|
            or obj.ticket is not None:
 | 
						|
            raise exceptions.APIException('该产品不可发起不合格审理')
 | 
						|
        workflow = Workflow.objects.filter(name='不合格品审理单', is_deleted=False).first()
 | 
						|
        if workflow:
 | 
						|
            test_record = TestRecord.objects.filter(wproduct=obj, is_deleted=False, is_testok=False).order_by('-id').first()
 | 
						|
            exist_data = {
 | 
						|
            'wproduct':obj.id,
 | 
						|
            'wproduct_number':obj.number,
 | 
						|
            'wproduct_name':obj.material.name,
 | 
						|
            'wproduct_specification':obj.material.specification,
 | 
						|
            'finder':request.user.id,
 | 
						|
            'find_process':obj.step.process.id, 
 | 
						|
            'tester':test_record.create_by.id
 | 
						|
            }
 | 
						|
            ret = {'workflow':workflow.id}
 | 
						|
            ret['exist_data'] = exist_data
 | 
						|
            return Response(ret)
 | 
						|
        else:
 | 
						|
            raise exceptions.APIException('未找到对应审批流程')
 | 
						|
        
 | 
						|
    @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WproductMtestSerializer)
 | 
						|
    @transaction.atomic
 | 
						|
    def mtest(self, request, pk=None):
 | 
						|
        """
 | 
						|
        军检
 | 
						|
        """
 | 
						|
        obj = self.get_object()
 | 
						|
        if obj.is_mtested:
 | 
						|
            raise exceptions.APIException('已进行军检')
 | 
						|
        if obj.material.type != Material.MA_TYPE_GOOD:
 | 
						|
            raise exceptions.APIException('军检必须是成品')
 | 
						|
        obj.remark_mtest = request.data.get('remark_mtest', None)
 | 
						|
        obj.is_mtested = True
 | 
						|
        is_mtestok = request.data.get('is_mtestok')
 | 
						|
        obj.is_mtestok = is_mtestok
 | 
						|
        if is_mtestok:
 | 
						|
            WpmServies.update_plan_state_by_mtestok(obj.subproduction_plan.production_plan)
 | 
						|
        obj.save()
 | 
						|
        change_str = 'mtest_notok'
 | 
						|
        if is_mtestok:
 | 
						|
            change_str = 'mtest_ok'
 | 
						|
        WpmServies.add_wproduct_flow_log(instance=obj, change_str=change_str)
 | 
						|
        return Response()
 | 
						|
 | 
						|
    @action(methods=['get'], detail=True, perms_map={'get':'*'})
 | 
						|
    def card(self, request, pk=None):
 | 
						|
        """
 | 
						|
        流程卡
 | 
						|
        """
 | 
						|
        obj = self.get_object()
 | 
						|
        card_data = WProductCardSerializer(instance=obj).data
 | 
						|
        ret = []
 | 
						|
        if card_data['parents']:
 | 
						|
            line1 = ['序号', '工序']
 | 
						|
            for i in card_data['parents']:
 | 
						|
                line1.append(i['number'])
 | 
						|
            ret.append(line1)
 | 
						|
            steps_list_full_1 = card_data['parents'][0]['step_list_full']
 | 
						|
            for index, item in enumerate(steps_list_full_1):
 | 
						|
                linex = [str(index+1), item['step_name']]
 | 
						|
                for i in card_data['parents']:
 | 
						|
                    linex.append(i['step_list_full'][index]['actions'])
 | 
						|
                ret.append(linex)
 | 
						|
        ret.append(['序号', '工序', card_data['number']])
 | 
						|
        step_list_full = card_data['step_list_full']
 | 
						|
        for index, item in enumerate(step_list_full):
 | 
						|
            ret.append([str(index+1), item['step_name'], item['actions']])
 | 
						|
        return Response(ret)
 | 
						|
 | 
						|
class WproductTicketViewSet(ListModelMixin, GenericViewSet):
 | 
						|
    """
 | 
						|
    玻璃审批工单
 | 
						|
    """
 | 
						|
    perms_map={'*':'*'}
 | 
						|
    queryset = WprouctTicket.objects.select_related('step', 'material', 'subproduction_plan', 
 | 
						|
    'resp_process', 'subproduction_plan__production_plan__order', 'subproduction_plan__production_plan')
 | 
						|
    serializer_class = WproductTicketListSerializer
 | 
						|
    filterset_fields = ['step', 'material', 'subproduction_plan', 'resp_process']
 | 
						|
    ordering_fields = ['id']
 | 
						|
    ordering = ['-id']
 | 
						|
 | 
						|
 | 
						|
class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet):
 | 
						|
    """
 | 
						|
    生产操作记录
 | 
						|
    """
 | 
						|
    perms_map={'*':'*'}
 | 
						|
    queryset = Operation.objects.select_related('step').prefetch_related('ow_operation', 'oe_operation', 'or_operation').all()
 | 
						|
    serializer_class = OperationListSerializer
 | 
						|
    filterset_fields = ['step', 'step__process', 'is_submited']
 | 
						|
    ordering_fields = ['id']
 | 
						|
    ordering = ['-id']
 | 
						|
 | 
						|
    def get_queryset(self):
 | 
						|
        return self.queryset.filter(create_by=self.request.user)
 | 
						|
 | 
						|
    def get_serializer_class(self):
 | 
						|
        if self.action == 'retrieve':
 | 
						|
            return OperationDetailSerializer
 | 
						|
        elif self.action == 'create':
 | 
						|
            return OperationCreateSerializer
 | 
						|
        elif self.action == 'update':
 | 
						|
            return OperationUpdateSerializer
 | 
						|
        return super().get_serializer_class()
 | 
						|
 | 
						|
    def update(self, request, *args, **kwargs):
 | 
						|
        instance = self.get_object()
 | 
						|
        if instance.is_submited:
 | 
						|
            raise exceptions.APIException('该操作已提交')
 | 
						|
        return super().update(request, *args, **kwargs)
 | 
						|
 | 
						|
    def destroy(self, request, *args, **kwargs):
 | 
						|
        instance = self.get_object()
 | 
						|
        if instance.is_submited:
 | 
						|
            raise exceptions.APIException('该操作已提交')
 | 
						|
        # 恢复半成品可操作
 | 
						|
        for i in instance.wp_operation.all():
 | 
						|
            i.act_state = WProduct.WPR_ACT_STATE_DOWAIT
 | 
						|
            i.update_by = request.user
 | 
						|
            i.save()
 | 
						|
            WpmServies.add_wproduct_flow_log(i, 'operation_delete')
 | 
						|
        self.perform_destroy(instance)
 | 
						|
        return Response(status=status.HTTP_204_NO_CONTENT)
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def create(self, request, *args, **kwargs):
 | 
						|
        data = request.data
 | 
						|
        serializer = OperationCreateSerializer(data=data, context={'request':self.request})
 | 
						|
        serializer.is_valid(raise_exception=True)
 | 
						|
        vdata = serializer.validated_data #校验之后的数据
 | 
						|
        step = vdata['step']
 | 
						|
        op = Operation()
 | 
						|
        op.step = step
 | 
						|
        op.is_submited = False
 | 
						|
        op.create_by = request.user
 | 
						|
        op.save()
 | 
						|
        splans = []
 | 
						|
        # 创建操作所用半成品关联记录
 | 
						|
        if 'wproducts' in vdata:
 | 
						|
            owps = []
 | 
						|
            splans = WpmServies.get_subplans_queryset_from_wproducts(vdata['wproducts'])
 | 
						|
            for wpd in vdata['wproducts']:
 | 
						|
                wpd.operation= op
 | 
						|
                wpd.act_state = WProduct.WPR_ACT_STATE_DOING
 | 
						|
                wpd.update_by = request.user
 | 
						|
                wpd.save()
 | 
						|
                WpmServies.add_wproduct_flow_log(wpd, 'operation_create')
 | 
						|
                owp = {}
 | 
						|
                owp['operation'] = op
 | 
						|
                owp['wproduct'] = wpd
 | 
						|
                owp['number'] = wpd.number
 | 
						|
                owp['material'] = wpd.material
 | 
						|
                owp['subproduction_plan'] = wpd.subproduction_plan
 | 
						|
                owp['ng_sign'] = wpd.ng_sign
 | 
						|
                owps.append(OperationWproduct(**owp))
 | 
						|
            OperationWproduct.objects.bulk_create(owps)
 | 
						|
        else:
 | 
						|
            splans = WpmServies.get_subplans_queryset_from_wproducts(vdata['wproducts'])
 | 
						|
        # 查询需要填写的自定义表格
 | 
						|
        forms = RecordForm.objects.filter(step=step, type=RecordForm.RF_TYPE_DO, enabled=True)
 | 
						|
        for i in forms:
 | 
						|
            opr = OperationRecord()
 | 
						|
            opr.operation = op
 | 
						|
            opr.form = i
 | 
						|
            opr.is_filled = False
 | 
						|
            opr.save()
 | 
						|
            opri_list = []
 | 
						|
            for m in RecordFormField.objects.filter(form=i, is_deleted=False):
 | 
						|
                opri_dict = {}
 | 
						|
                opri_dict['operation_record'] = opr
 | 
						|
                opri_dict['form_field'] = m
 | 
						|
                opri_list.append(OperationRecordItem(**opri_dict))
 | 
						|
            OperationRecordItem.objects.bulk_create(opri_list)
 | 
						|
        # 查询需要使用的生产设备
 | 
						|
        for i in step.equipments.all():
 | 
						|
            ope = OperationEquip()
 | 
						|
            ope.operation = op
 | 
						|
            ope.equip = i
 | 
						|
            ope.save()
 | 
						|
        # 查询所需的工具工装
 | 
						|
        for i in SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL,
 | 
						|
                        subproduction__subplan_subprod__in = splans, is_deleted=False).distinct():
 | 
						|
            opm = OperationMaterial()
 | 
						|
            opm.operation = op
 | 
						|
            opm.material = i.material
 | 
						|
            opm.type = SubprodctionMaterial.SUB_MA_TYPE_TOOL
 | 
						|
            opm.save()
 | 
						|
        return Response()
 | 
						|
    
 | 
						|
    @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=serializers.Serializer)
 | 
						|
    @transaction.atomic
 | 
						|
    def submit(self, request, pk=None):
 | 
						|
        """
 | 
						|
        提交车间操作重要
 | 
						|
        """
 | 
						|
        op = self.get_object()
 | 
						|
        step = op.step
 | 
						|
        if op.is_submited:
 | 
						|
            raise exceptions.APIException('该操作已提交')
 | 
						|
        # 校验消耗产出是否正确填写
 | 
						|
        omis = OperationMaterial.objects.filter(operation=op, 
 | 
						|
                type=SubprodctionMaterial.SUB_MA_TYPE_IN)
 | 
						|
        sps_omi_l = omis.values_list('subproduction_plan', flat=True)
 | 
						|
        omos = OperationMaterial.objects.filter(operation=op, 
 | 
						|
                type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
 | 
						|
        sps_omo_l = omos.filter(use_scrap=False).values_list('subproduction_plan', flat=True)
 | 
						|
        if set(list(sps_omi_l)) == set(list(sps_omo_l)) or op.step.type == Step.STEP_TYPE_COMB:
 | 
						|
            pass
 | 
						|
        else:
 | 
						|
            raise exceptions.APIException('消耗与产出不一致')
 | 
						|
        # 检查自定义表单填写
 | 
						|
        if OperationRecord.objects.filter(operation=op, is_filled=False).exists():
 | 
						|
            raise exceptions.APIException('存在自定义表单未填写')
 | 
						|
        # 更新物料消耗进度
 | 
						|
        for i in omis:
 | 
						|
            # 更新车间物料
 | 
						|
            i_wmat = i.wmaterial
 | 
						|
            i_wmat.count = i_wmat.count- i.count
 | 
						|
            i_wmat.save()
 | 
						|
            # 更新子计划物料消耗情况
 | 
						|
            spp = SubProductionProgress.objects.get(subproduction_plan=i_wmat.subproduction_plan,
 | 
						|
                    material=i_wmat.material)
 | 
						|
            spp.count_real = spp.count_real + i.count
 | 
						|
            spp.save()
 | 
						|
        # 更新产出
 | 
						|
        for i in omos:
 | 
						|
            if not i.subproduction_progress.is_main:
 | 
						|
                # 更新车间物料产出情况
 | 
						|
                ins, _ = WMaterial.objects.get_or_create(subproduction_plan=i.subproduction_plan, material=i.material)
 | 
						|
                ins.count = ins.count + i.count
 | 
						|
                ins.save()
 | 
						|
                # 更新子计划物料产出情况
 | 
						|
                spp = i.subproduction_progress
 | 
						|
                spp.count_real = spp.count_real + i.count
 | 
						|
                spp.save()
 | 
						|
        # 更新动态产品表
 | 
						|
        if step.type == Step.STEP_TYPE_NOM:
 | 
						|
            ows = OperationWproduct.objects.filter(operation=op)
 | 
						|
            for i in ows:
 | 
						|
                wp = i.wproduct
 | 
						|
                wsp = i.subproduction_plan
 | 
						|
 | 
						|
                # 获取下一步子工序
 | 
						|
                newstep, hasNext = WpmServies.get_next_step(wsp, step)
 | 
						|
                wp.step = newstep
 | 
						|
                wp.pre_step = step
 | 
						|
                if hasNext:
 | 
						|
                    wp.act_state= WProduct.WPR_ACT_STATE_DOWAIT
 | 
						|
                else:
 | 
						|
                    wp.act_state = WProduct.WPR_ACT_STATE_TOTEST
 | 
						|
                    wp.material = wsp.product
 | 
						|
                wp.operation = None
 | 
						|
                wp.update_by = request.user
 | 
						|
                wp.save()
 | 
						|
                WpmServies.add_wproduct_flow_log(wp, 'operation_submit')
 | 
						|
 | 
						|
            for i in ows.values('subproduction_plan').distinct():
 | 
						|
                # 更新进度
 | 
						|
                WpmServies.update_subproduction_progress_main(sp=wsp)
 | 
						|
 | 
						|
        elif step.type == Step.STEP_TYPE_DIV:
 | 
						|
            # 更新物料产出情况
 | 
						|
            if not omos.exists():
 | 
						|
                raise exceptions.APIException('请选择物料产出')
 | 
						|
            for i in omos:
 | 
						|
                if i.subproduction_progress.is_main:
 | 
						|
                    newstep, _ = WpmServies.get_next_step(i.subproduction_plan, step)
 | 
						|
                    wpr = dict(material=i.material, step=newstep,
 | 
						|
                        act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='', 
 | 
						|
                        subproduction_plan=i.subproduction_plan, 
 | 
						|
                        create_by=request.user, coperation=op)
 | 
						|
                    for x in range(i.count):
 | 
						|
                        ins = WProduct.objects.create(**wpr)
 | 
						|
                        # 添加日志
 | 
						|
                        WpmServies.add_wproduct_flow_log(ins, 'wproduct_create')
 | 
						|
                    # 更新进度
 | 
						|
                    WpmServies.update_subproduction_progress_main(sp=i.subproduction_plan)              
 | 
						|
        elif step.type == Step.STEP_TYPE_COMB:
 | 
						|
            oms_w = omos.filter(subproduction_progress__is_main=True)
 | 
						|
            if len(oms_w) == 1:
 | 
						|
                oms_w = oms_w[0]
 | 
						|
                # 校验单片数量是否正确, 暂时未写
 | 
						|
                newstep, hasNext = WpmServies.get_next_step(oms_w.subproduction_plan, step)
 | 
						|
                wproduct = WProduct()
 | 
						|
                wproduct.material = oms_w.material
 | 
						|
                wproduct.step = newstep
 | 
						|
                wproduct.subproduction_plan = oms_w.subproduction_plan
 | 
						|
                if hasNext:
 | 
						|
                    wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
 | 
						|
                else:
 | 
						|
                    wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
 | 
						|
                    # 更新子计划进度
 | 
						|
                    WpmServies.update_subproduction_progress_main(sp=oms_w.subproduction_plan)
 | 
						|
                wproduct.create_by = request.user
 | 
						|
                wproduct.coperation = op
 | 
						|
                wproduct.save()
 | 
						|
                WpmServies.add_wproduct_flow_log(wproduct, 'wproduct_create')
 | 
						|
                # 隐藏原半成品
 | 
						|
                wps = WProduct.objects.filter(ow_wproduct__operation = op)
 | 
						|
                wps.update(is_hidden=True, child=wproduct, update_by=request.user, update_time=timezone.now())
 | 
						|
            else:
 | 
						|
                raise exceptions.APIException('产出物料未填写或填写错误')
 | 
						|
        op.is_submited = True
 | 
						|
        op.save()
 | 
						|
 | 
						|
        # 如果是冷加工
 | 
						|
        if step.process.id==1:
 | 
						|
            WpmServies.update_cutting_list_with_operation(op=op)
 | 
						|
        return Response()
 | 
						|
        
 | 
						|
 | 
						|
 | 
						|
class OperationWproductViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
 | 
						|
    """
 | 
						|
    操作使用的半成品
 | 
						|
    """
 | 
						|
    perms_map={'*':'*'}
 | 
						|
    queryset = OperationWproduct.objects.select_related('subproduction_plan', 'material').all()
 | 
						|
    serializer_class = OperationWproductListSerializer
 | 
						|
    filterset_fields = ['material', 'subproduction_plan', 'operation']
 | 
						|
    ordering_fields = ['id']
 | 
						|
    ordering = ['-id']
 | 
						|
 | 
						|
    @transaction.atomic()
 | 
						|
    def destroy(self, request, *args, **kwargs):
 | 
						|
        instance = self.get_object()
 | 
						|
        if instance.operation.is_submited:
 | 
						|
            raise exceptions.APIException('该操作已提交')
 | 
						|
        instance.delete()
 | 
						|
        wp = instance.wproduct
 | 
						|
        wp.operation = None
 | 
						|
        wp.save()
 | 
						|
        return Response()
 | 
						|
 | 
						|
class OperationEquipViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet):
 | 
						|
    """
 | 
						|
    操作使用的设备
 | 
						|
    """
 | 
						|
    perms_map={'*':'*'}
 | 
						|
    queryset = OperationEquip.objects.select_related('operation', 'equip').all()
 | 
						|
    serializer_class = OperationEquipListSerializer
 | 
						|
    filterset_fields = ['operation', 'equip']
 | 
						|
    ordering_fields = ['id']
 | 
						|
    ordering = ['-id']
 | 
						|
 | 
						|
    def get_serializer_class(self):
 | 
						|
        if self.action == 'update':
 | 
						|
            return OperationEquipUpdateSerializer
 | 
						|
        return super().get_serializer_class()
 | 
						|
    
 | 
						|
    def update(self, request, *args, **kwargs):
 | 
						|
        instance = self.get_object()
 | 
						|
        if instance.operation.is_submited:
 | 
						|
            raise exceptions.APIException('该操作已提交')
 | 
						|
        return super().update(request, *args, **kwargs)
 | 
						|
 | 
						|
    @transaction.atomic()
 | 
						|
    def destroy(self, request, *args, **kwargs):
 | 
						|
        instance = self.get_object()
 | 
						|
        if instance.operation.is_submited:
 | 
						|
            raise exceptions.APIException('该操作已提交')
 | 
						|
        instance.delete()
 | 
						|
        return Response()
 | 
						|
 | 
						|
class OperationRecordViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, RetrieveModelMixin, GenericViewSet):
 | 
						|
    """
 | 
						|
    操作使用的自定义表格
 | 
						|
    """
 | 
						|
    perms_map={'*':'*'}
 | 
						|
    queryset = OperationRecord.objects.select_related('operation', 'form').all()
 | 
						|
    serializer_class = OperationRecordListSerializer
 | 
						|
    filterset_fields = ['operation', 'form']
 | 
						|
    ordering_fields = ['id']
 | 
						|
    ordering = ['-id']
 | 
						|
 | 
						|
    def get_serializer_class(self):
 | 
						|
        if self.action == 'update':
 | 
						|
            return OperationRecordSubmitSerializer
 | 
						|
        elif self.action == 'retrieve':
 | 
						|
            return OperationRecordDetailSerializer
 | 
						|
        return super().get_serializer_class()
 | 
						|
    @transaction.atomic()
 | 
						|
    def destroy(self, request, *args, **kwargs):
 | 
						|
        instance = self.get_object()
 | 
						|
        if instance.operation.is_submited:
 | 
						|
            raise exceptions.APIException('该操作已提交')
 | 
						|
        instance.delete()
 | 
						|
        return Response()
 | 
						|
 | 
						|
 | 
						|
    def update(self, request, *args, **kwargs):
 | 
						|
        serializer = OperationRecordSubmitSerializer(data=request.data)
 | 
						|
        serializer.is_valid(raise_exception=True)
 | 
						|
        vdata = serializer.validated_data
 | 
						|
        opr = self.get_object()
 | 
						|
        if opr.operation.is_submited:
 | 
						|
            raise exceptions.APIException('操作已提交不可修改')
 | 
						|
        for i in vdata['record_data']:
 | 
						|
            ori = i['id']
 | 
						|
            ori.field_value = i['field_value']
 | 
						|
            ori.save()
 | 
						|
        opr.is_filled = True
 | 
						|
        opr.update_by = request.user
 | 
						|
        opr.save()
 | 
						|
        return Response()
 | 
						|
 | 
						|
 | 
						|
class OperationMaterialInputViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
 | 
						|
    """
 | 
						|
    消耗物料
 | 
						|
    """
 | 
						|
    perms_map={'*':'*'}
 | 
						|
    queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN)
 | 
						|
    serializer_class = OperationMaterialListSerializer
 | 
						|
    filterset_fields = ['operation', 'subproduction_plan']
 | 
						|
    ordering_fields = ['id']
 | 
						|
    ordering = ['-id']
 | 
						|
 | 
						|
    def get_serializer_class(self):
 | 
						|
        if self.action == 'create':
 | 
						|
            return OperationMaterialCreate1Serailizer
 | 
						|
        return super().get_serializer_class()
 | 
						|
    
 | 
						|
    @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=OperationMaterialCreate1ListSerailizer)
 | 
						|
    def creates(self, request, pk=None):
 | 
						|
        """
 | 
						|
        批量创建消耗物料
 | 
						|
        """
 | 
						|
        serializer = OperationMaterialCreate1ListSerailizer(data=request.data)
 | 
						|
        serializer.is_valid(raise_exception=True)
 | 
						|
        serializer.save()
 | 
						|
        return Response()
 | 
						|
 | 
						|
 | 
						|
    @transaction.atomic()
 | 
						|
    def destroy(self, request, *args, **kwargs):
 | 
						|
        instance = self.get_object()
 | 
						|
        if instance.operation.is_submited:
 | 
						|
            raise exceptions.APIException('该操作已提交')
 | 
						|
        instance.delete()
 | 
						|
        return Response()
 | 
						|
 | 
						|
class CuttingListViewSet(ListModelMixin, GenericViewSet):
 | 
						|
    """
 | 
						|
    下料清单
 | 
						|
    """
 | 
						|
    perms_map={'*':'*'}
 | 
						|
    queryset = OperationMaterial.objects.select_related('operation', 
 | 
						|
            'subproduction_plan', 'material', 'operation__create_by').filter(operation__step__id=1, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
 | 
						|
    serializer_class = CuttingListSerializer
 | 
						|
    filterset_class = CuttingFilterSet
 | 
						|
    ordering_fields = ['id']
 | 
						|
    ordering = ['-id']
 | 
						|
 | 
						|
 | 
						|
class OperationMaterialOutputViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
 | 
						|
    """
 | 
						|
    产出物料
 | 
						|
    """
 | 
						|
    perms_map={'*':'*'}
 | 
						|
    queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
 | 
						|
    serializer_class = OperationMaterialListSerializer
 | 
						|
    filterset_fields = ['operation', 'subproduction_plan']
 | 
						|
    ordering_fields = ['id']
 | 
						|
    ordering = ['-id']
 | 
						|
 | 
						|
    def get_serializer_class(self):
 | 
						|
        if self.action == 'create':
 | 
						|
            return OperationMaterialCreate2Serailizer
 | 
						|
        return super().get_serializer_class()
 | 
						|
    
 | 
						|
    @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=OperationMaterialCreate2ListSerailizer)
 | 
						|
    def creates(self, request, pk=None):
 | 
						|
        """
 | 
						|
        批量创建产出物料
 | 
						|
        """
 | 
						|
        serializer = OperationMaterialCreate2ListSerailizer(data=request.data)
 | 
						|
        serializer.is_valid(raise_exception=True)
 | 
						|
        serializer.save()
 | 
						|
        return Response()
 | 
						|
 | 
						|
    @transaction.atomic()
 | 
						|
    def destroy(self, request, *args, **kwargs):
 | 
						|
        instance = self.get_object()
 | 
						|
        if instance.operation.is_submited:
 | 
						|
            raise exceptions.APIException('该操作已提交')
 | 
						|
        instance.delete()
 | 
						|
        return Response()
 | 
						|
 | 
						|
class OperationMaterialToolViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
 | 
						|
    """
 | 
						|
    工具工装
 | 
						|
    """
 | 
						|
    perms_map={'*':'*'}
 | 
						|
    queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL)
 | 
						|
    serializer_class = OperationMaterialListSerializer
 | 
						|
    filterset_fields = ['operation', 'subproduction_plan']
 | 
						|
    ordering_fields = ['id']
 | 
						|
    ordering = ['-id']
 | 
						|
 | 
						|
    def get_serializer_class(self):
 | 
						|
        if self.action == 'create':
 | 
						|
            return OperationMaterialCreate3Serializer
 | 
						|
        return super().get_serializer_class()
 | 
						|
        
 | 
						|
    @transaction.atomic()
 | 
						|
    def destroy(self, request, *args, **kwargs):
 | 
						|
        instance = self.get_object()
 | 
						|
        if instance.operation.is_submited:
 | 
						|
            raise exceptions.APIException('该操作已提交')
 | 
						|
        instance.delete()
 | 
						|
        return Response()
 | 
						|
 | 
						|
class DoFormInit(CreateAPIView, GenericAPIView):
 | 
						|
    perms_map={'*':'*'}
 | 
						|
    serializer_class=OperationInitSerializer
 | 
						|
    def post(self, request, format=None):
 | 
						|
        """
 | 
						|
        调用操作表单
 | 
						|
        """
 | 
						|
        data = request.data
 | 
						|
        serializer = OperationInitSerializer(data=data)
 | 
						|
        serializer.is_valid(raise_exception=True)
 | 
						|
        vdata = serializer.validated_data
 | 
						|
        ret = {}
 | 
						|
        ret_0 = {}
 | 
						|
        ret_0['step'] = data['step']
 | 
						|
        splans =[]
 | 
						|
        ret_0['input'] = []
 | 
						|
        # ret_0['subproduction_plan'] = data['subproduction_plan']
 | 
						|
        if 'wproducts' in data and data['wproducts']:
 | 
						|
            ret_0['wproducts'] = data['wproducts']
 | 
						|
            splans = WProduct.objects.filter(id__in=data['wproducts']).values_list('subproduction_plan', flat=True)
 | 
						|
            # 调出所属子计划现有物料
 | 
						|
            ret_0['input'] = WMaterialListSerializer(instance=WMaterial.objects.filter(subproduction_plan__in=splans), many=True).data
 | 
						|
        else:
 | 
						|
            if 'subproduction_plan' in vdata:
 | 
						|
                splans = [vdata['subproduction_plan']]
 | 
						|
            else:
 | 
						|
                splans = SubProductionPlan.objects.filter(is_deleted=False, 
 | 
						|
                subproduction__usedstep_subproduction__step=vdata['step'], state=3)
 | 
						|
            ret_0['wproducts'] = []
 | 
						|
            ret_0['input'] = WMaterialListSerializer(instance=WMaterial.objects.filter(subproduction_plan__in=splans), many=True).data
 | 
						|
 | 
						|
        
 | 
						|
        for i in ret_0['input']:
 | 
						|
            i['count_input'] = 0
 | 
						|
        # 需要输出的物料
 | 
						|
        if ret_0['wproducts']:
 | 
						|
            # 排除主要产物, 因为已经放到半成品里了, 由半成品进行处理, 夹层可能需要特殊处理
 | 
						|
            o_objs = SubProductionProgress.objects.filter(
 | 
						|
                subproduction_plan__in=splans, type=SubprodctionMaterial.SUB_MA_TYPE_OUT).exclude(is_main=True)
 | 
						|
            
 | 
						|
        else:
 | 
						|
            # 此时显示所有子计划需要输出的物料
 | 
						|
            o_objs = SubProductionProgress.objects.filter(
 | 
						|
                subproduction_plan__in=splans, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
 | 
						|
        ret_0['output'] = list(o_objs.values('subproduction_plan', 'material', 'material__name', 'material__number'))
 | 
						|
        for i in ret_0['output']:
 | 
						|
            i['count_output']=0
 | 
						|
        ret['forms'] = []
 | 
						|
        ret_0['id'] = 0
 | 
						|
        ret_0['name'] = '基本信息'
 | 
						|
        # 查询工具工装
 | 
						|
        ret_0['tools'] = SubprodctionMaterialListSerializer(instance=
 | 
						|
                        SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL,
 | 
						|
                        subproduction__subplan_subprod__in = splans), many=True).data
 | 
						|
        # 查询技术文档
 | 
						|
        ret_0['techdocs'] = TechDocListSerializer(instance = 
 | 
						|
                TechDoc.objects.filter(subproduction__subplan_subprod__in = splans, enabled=True)\
 | 
						|
            .distinct(), many=True).data
 | 
						|
 | 
						|
        ret['forms'].append(ret_0)
 | 
						|
        forms = RecordForm.objects.filter(step=vdata['step'], type=RecordForm.RF_TYPE_DO)
 | 
						|
        if forms.exists():
 | 
						|
            ret['forms'].extend(RecordFormDetailSerializer(instance=forms, many=True).data) 
 | 
						|
        return Response(ret)
 | 
						|
 | 
						|
 | 
						|
class DoFormSubmit(CreateAPIView, GenericAPIView):
 | 
						|
    perms_map={'*':'*'}
 | 
						|
    serializer_class = OperationSubmitSerializer
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def post(self, request, format=None):
 | 
						|
        """
 | 
						|
        提交操作表单
 | 
						|
        """
 | 
						|
        data = request.data
 | 
						|
        serializer = OperationSubmitSerializer(data=data, context={'request':self.request})
 | 
						|
        serializer.is_valid(raise_exception=True)
 | 
						|
        vdata = serializer.validated_data #校验之后的数据
 | 
						|
 | 
						|
        # 创建一个生产操作记录
 | 
						|
        action_obj = Operation()
 | 
						|
        action_obj.step = vdata['step']
 | 
						|
        action_obj.remark = vdata.get('remark', '') # 操作备注
 | 
						|
        action_obj.create_by = request.user
 | 
						|
        action_obj.use_scrap = vdata.get('use_scrap', False)
 | 
						|
        action_obj.save()
 | 
						|
        
 | 
						|
        # 保存关联半成品
 | 
						|
        if 'wproducts' in data and data['wproducts']:
 | 
						|
            owps = []
 | 
						|
            for i in data['wproducts']:
 | 
						|
                owp = {}
 | 
						|
                owp['operation'] = action_obj
 | 
						|
                wp = WProduct.objects.get(pk=i)
 | 
						|
                owp['wproduct'] = wp
 | 
						|
                owp['number'] = wp.number
 | 
						|
                owp['material'] = wp.material
 | 
						|
                owp['subproduction_plan'] = wp.subproduction_plan
 | 
						|
                owps.append(OperationWproduct(**owp))
 | 
						|
            OperationWproduct.objects.bulk_create(owps)
 | 
						|
 | 
						|
        # 保存物料消耗
 | 
						|
        for i in vdata['input']:
 | 
						|
            if i['count_input']: #如果有消耗
 | 
						|
                i_wmat = i['id']
 | 
						|
                OperationMaterial.objects.create(type=1, operation=action_obj,
 | 
						|
                    wmaterial= i_wmat, count=i['count_input'])
 | 
						|
                # 更新车间物料
 | 
						|
                i_wmat.count = i_wmat.count- i['count_input']
 | 
						|
                i_wmat.save()
 | 
						|
                # 更新子计划物料消耗情况
 | 
						|
                sp = SubProductionProgress.objects.get(subproduction_plan=i_wmat.subproduction_plan,
 | 
						|
                    material=i_wmat.material)
 | 
						|
                sp.count_real = sp.count_real + i['count_input']
 | 
						|
                sp.save()
 | 
						|
        
 | 
						|
        # 物料产出
 | 
						|
        if 'output' in data and data['output']:
 | 
						|
            for i in vdata['output']: # 已经序列化好的数据
 | 
						|
                ma = i['material']
 | 
						|
                if i['subproduction_plan'].product == ma: # 如果是该计划主产物
 | 
						|
                    # 如果是切割
 | 
						|
                    # 获取下一步子工序
 | 
						|
                    if vdata['step'].type == Step.STEP_TYPE_DIV:
 | 
						|
                        newstep, _ = WpmServies.get_next_step(i['subproduction_plan'], vdata['step'])
 | 
						|
                        wpr = dict(material=ma, step=newstep,
 | 
						|
                            act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='', 
 | 
						|
                            subproduction_plan=i['subproduction_plan'])
 | 
						|
                        for x in range(i['count_output']):
 | 
						|
                            WProduct.objects.create(**wpr)
 | 
						|
                else:
 | 
						|
                    # 更新操作产出物料表
 | 
						|
                    OperationMaterial.objects.create(type=2, operation=action_obj,
 | 
						|
                    material= ma, count=i['count_output'])
 | 
						|
                    # 更新车间物料表
 | 
						|
                    ins, _ = WMaterial.objects.get_or_create(subproduction_plan=i['subproduction_plan'],
 | 
						|
                        material=ma)
 | 
						|
                    ins.count = ins.count + i['count_output']
 | 
						|
                    ins.save()
 | 
						|
                    # 更新子计划进度表
 | 
						|
                    sp = SubProductionProgress.objects.get(subproduction_plan=i['subproduction_plan'],
 | 
						|
                    material=ma)
 | 
						|
                    sp.count_real = sp.count_real + i['count_input']
 | 
						|
                    sp.save()
 | 
						|
 | 
						|
        # 更新动态产品表
 | 
						|
        if 'wproducts' in vdata and vdata['wproducts']:
 | 
						|
            if vdata['step'].type == Step.STEP_TYPE_COMB:
 | 
						|
                wproducts = vdata['wproducts']
 | 
						|
                if 'suproduction_plan' in vdata:
 | 
						|
                    wproducts.update(is_hidden=True) # 隐藏
 | 
						|
                    newstep, hasNext = WpmServies.get_next_step(i['subproduction_plan'], vdata['step'])
 | 
						|
                    wproduct = WProduct()
 | 
						|
                    wproduct.material = vdata['subproduction_plan'].product
 | 
						|
                    wproduct.step = newstep
 | 
						|
                    wproduct.subproduction_plan=vdata['subproduction_plan']
 | 
						|
                    wproduct.parent = data['wproducts']
 | 
						|
                    if hasNext:
 | 
						|
                        wproduct.act_state=WProduct.WPR_ACT_STATE_DOWAIT
 | 
						|
                    else:
 | 
						|
                        wproduct.act_state=WProduct.WPR_ACT_STATE_TOTEST
 | 
						|
                    wproduct.save()
 | 
						|
                else:
 | 
						|
                    raise exceptions.APIException('请指定子计划')
 | 
						|
            else:
 | 
						|
                for wproduct in vdata['wproducts']:
 | 
						|
                    # 获取下一步子工序
 | 
						|
                    newstep, hasNext = WpmServies.get_next_step(wproduct.subproduction_plan, vdata['step'])
 | 
						|
                    wproduct.step = newstep
 | 
						|
                    wproduct.pre_step=vdata['step']
 | 
						|
                    if hasNext:
 | 
						|
                        wproduct.act_state=WProduct.WPR_ACT_STATE_DOWAIT
 | 
						|
                    else:
 | 
						|
                        wproduct.act_state=WProduct.WPR_ACT_STATE_TOTEST
 | 
						|
                        wproduct.material=wproduct.subproduction_plan.product
 | 
						|
                    wproduct.save()
 | 
						|
 | 
						|
        # 保存自定义表单结果
 | 
						|
        for i in vdata['forms']:
 | 
						|
            wr = OperationRecord()
 | 
						|
            wr.form = i['form']
 | 
						|
            wr.create_by = request.user
 | 
						|
            wr.operation = action_obj
 | 
						|
            wr.save()
 | 
						|
            wrds = []
 | 
						|
            for m in i['record_data']: # 保存记录详情
 | 
						|
                form_field = m['form_field']
 | 
						|
                m['field_name'] = form_field.field_name
 | 
						|
                m['field_key'] = form_field.field_key
 | 
						|
                m['field_type'] = form_field.field_type
 | 
						|
                m['field_value'] = m['field_value']
 | 
						|
                m['sort'] = form_field.sort
 | 
						|
                m['operation_record'] = wr
 | 
						|
                wrds.append(OperationRecordItem(**m))
 | 
						|
            OperationRecordItem.objects.bulk_create(wrds)
 | 
						|
        return Response()
 | 
						|
 | 
						|
         |