859 lines
38 KiB
Python
859 lines
38 KiB
Python
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 TestRecordItem
|
|
|
|
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
|
from rest_framework.decorators import action
|
|
from apps.wpm.filters import WMaterialFilterSet
|
|
from apps.wpm.models import OperationEquip, OperationWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem
|
|
|
|
from apps.wpm.serializers import OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer
|
|
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
|
|
# Create your views here.
|
|
class WPlanViewSet(ListModelMixin, GenericViewSet):
|
|
"""
|
|
车间生产计划
|
|
"""
|
|
perms_map = {'*': '*'}
|
|
queryset = SubProductionPlan.objects.select_related('process', 'workshop', 'subproduction', 'main_product').exclude(state=0)
|
|
search_fields = []
|
|
serializer_class = SubProductionPlanListSerializer
|
|
filterset_fields = ['production_plan', 'process', 'state', 'main_product', 'workshop']
|
|
ordering_fields = []
|
|
ordering = ['-update_time']
|
|
|
|
@action(methods=['post', 'get'], detail=True, perms_map={'post':'*', 'get':'*'}, serializer_class=PickHalfSerializer)
|
|
@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= PickHalfSerializer(data=request.data, many=True)
|
|
serializer.is_valid(raise_exception=True)
|
|
vdata = serializer.data
|
|
first_step = Step.objects.get(pk=sp.steps[0]['id'])
|
|
for i in vdata:
|
|
if 'wproducts' in i and len(i['wproducts'])>0:
|
|
spp = SubProductionProgress.objects.get(pk=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 for x in i['wproducts']])
|
|
wps.update(step=first_step, is_executed=False,
|
|
act_state=WProduct.WPR_ACT_STATE_TORETEST, is_hidden=False, warehouse=None,
|
|
subproduction_plan=sp, update_by=request.user, update_time=timezone.now())
|
|
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.data
|
|
subplan = self.get_object()
|
|
material = subplan.main_product
|
|
batch = subplan.number
|
|
warehouse = WareHouse.objects.get(id=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, GenericViewSet):
|
|
"""
|
|
半成品
|
|
"""
|
|
perms_map={'*':'*'}
|
|
queryset = WProduct.objects.select_related('step', 'material').filter(is_hidden=False, operation=None)
|
|
serializer_class = WProductListSerializer
|
|
filterset_fields = ['step', 'subproduction_plan', 'material', 'step__process', 'act_state']
|
|
search_fields = ['number']
|
|
ordering_fields = ['id']
|
|
ordering = ['id']
|
|
|
|
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=WpmTestRecordCreateSerializer)
|
|
@transaction.atomic
|
|
def test(self, request, pk=None):
|
|
"""
|
|
检测
|
|
"""
|
|
serializer = WpmTestRecordCreateSerializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
vdata = serializer.validated_data
|
|
record_data = vdata.pop('record_data')
|
|
wproduct = vdata['wproduct']
|
|
if wproduct.act_state not in [WProduct.WPR_ACT_STATE_TOTEST, WProduct.WPR_ACT_STATE_TORETEST]:
|
|
raise exceptions.APIException('该产品当前状态不可检验')
|
|
if 'is_testok' not in vdata:
|
|
raise exceptions.APIException('未填写检测结论')
|
|
|
|
obj = serializer.save(create_by = self.request.user,
|
|
material=wproduct.material, number=wproduct.number, subproduction_plan=wproduct.subproduction_plan)
|
|
tris = []
|
|
for m in 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['need_judge'] = form_field.need_judge
|
|
m['is_testok'] = m['is_testok'] if 'is_testok' in m else None
|
|
m['test_record'] = obj
|
|
tris.append(TestRecordItem(**m))
|
|
TestRecordItem.objects.bulk_create(tris)
|
|
|
|
# 如果检测合格, 变更动态产品进行状态
|
|
|
|
if obj.is_testok:
|
|
wproduct.act_state = WProduct.WPR_ACT_STATE_OK
|
|
if wproduct.number is None: # 产生半成品编号
|
|
wproduct.number = 'WP'+ranstr(7)
|
|
wproduct.save()
|
|
# 更新子计划状态
|
|
# 更新子计划主产品数
|
|
instance = SubProductionProgress.objects.get(subproduction_plan=wproduct.subproduction_plan,
|
|
is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
|
|
instance.count_ok = instance.count_ok + 1 # 这个地方可能会有问题
|
|
instance.save()
|
|
else:# 如果不合格
|
|
wproduct.act_state = WProduct.WPR_ACT_STATE_NOTOK
|
|
wproduct.save()
|
|
|
|
return Response()
|
|
|
|
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=WpmTestRecordCreateSerializer)
|
|
@transaction.atomic
|
|
def retest(self, request, pk=None):
|
|
"""
|
|
复检
|
|
"""
|
|
serializer = WpmTestRecordCreateSerializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
vdata = serializer.validated_data
|
|
record_data = vdata.pop('record_data')
|
|
wproduct = vdata['wproduct']
|
|
if wproduct.act_state != WProduct.WPR_ACT_STATE_TORETEST:
|
|
raise exceptions.APIException('该产品当前状态不可检验')
|
|
if 'is_testok' not in vdata:
|
|
raise exceptions.APIException('未填写检测结论')
|
|
|
|
obj = serializer.save(create_by = self.request.user,
|
|
material=wproduct.material, number=wproduct.number, subproduction_plan=wproduct.subproduction_plan)
|
|
tris = []
|
|
for m in 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['need_judge'] = form_field.need_judge
|
|
m['is_testok'] = m['is_testok'] if 'is_testok' in m else None
|
|
m['test_record'] = obj
|
|
tris.append(TestRecordItem(**m))
|
|
TestRecordItem.objects.bulk_create(tris)
|
|
|
|
# 如果检测合格, 变更动态产品进行状态
|
|
|
|
if obj.is_testok:
|
|
wproduct.act_state = WProduct.WPR_ACT_STATE_DOING
|
|
wproduct.save()
|
|
else:# 如果不合格
|
|
wproduct.act_state = WProduct.WPR_ACT_STATE_NOTOK
|
|
wproduct.save()
|
|
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.data
|
|
wproduct = self.get_object()
|
|
warehouse = WareHouse.objects.get(id=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()
|
|
return Response()
|
|
|
|
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('该操作已提交')
|
|
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 = []
|
|
WProduct.objects.filter(pk__in=[x.id for x in vdata['wproducts']]).update(operation=op)
|
|
splans = WpmServies.get_subplans_queryset_from_wproducts(vdata['wproducts'])
|
|
for wpd in vdata['wproducts']:
|
|
owp = {}
|
|
owp['operation'] = op
|
|
owp['wproduct'] = wpd
|
|
owp['number'] = wpd.number
|
|
owp['material'] = wpd.material
|
|
owp['subproduction_plan'] = wpd.subproduction_plan
|
|
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)
|
|
for i in forms:
|
|
opr = OperationRecord()
|
|
opr.operation = op
|
|
opr.form = i
|
|
opr.is_filled = False
|
|
opr.save()
|
|
# 查询需要使用的生产设备
|
|
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 OperationRecord.objects.filter(operation=op, is_filled=False).exists():
|
|
raise exceptions.APIException('存在自定义表单未填写')
|
|
# 更新物料消耗进度
|
|
for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_IN):
|
|
# 更新车间物料
|
|
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 OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT):
|
|
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:
|
|
for i in OperationWproduct.objects.filter(operation=op):
|
|
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.is_executed= False
|
|
else:
|
|
wp.is_executed = True
|
|
wp.act_state = WProduct.WPR_ACT_STATE_TOTEST
|
|
wp.material = wsp.main_product
|
|
# 更新子计划进度
|
|
instance = SubProductionProgress.objects.get(subproduction_plan=wsp,
|
|
is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
|
|
instance.count_real = instance.count_real + 1 # 这个地方可能会有问题,不够严谨
|
|
instance.save()
|
|
wp.operation = None
|
|
wp.save()
|
|
elif step.type == Step.STEP_TYPE_DIV:
|
|
# 更新物料产出情况
|
|
for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT):
|
|
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_DOING, is_executed=False, remark='',
|
|
subproduction_plan=i.subproduction_plan)
|
|
for x in range(i.count):
|
|
WProduct.objects.create(**wpr)
|
|
elif step.type == Step.STEP_TYPE_COMB:
|
|
if i.subproduction_progress.is_main:
|
|
newstep, hasNext = WpmServies.get_next_step(i.subproduction_plan, step)
|
|
wproduct = WProduct()
|
|
wproduct.material = i.material
|
|
wproduct.step = newstep
|
|
wproduct.subproduction_plan = i.subproduction_plan
|
|
if hasNext:
|
|
wproduct.act_state = WProduct.WPR_ACT_STATE_DOING
|
|
wproduct.is_executed = False
|
|
else:
|
|
wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
|
|
wproduct.is_executed = True
|
|
# 更新子计划进度
|
|
instance = SubProductionProgress.objects.get(subproduction_plan=i.subproduction_plan,
|
|
is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
|
|
instance.count_real = instance.count_real + 1 # 这个地方可能会有问题,不够严谨
|
|
instance.save()
|
|
wproduct.save()
|
|
# 隐藏原半成品
|
|
wps = WProduct.objects.filter(ow_wproduct__operation = op)
|
|
wps.update(is_hidden=True, child=wproduct)
|
|
op.is_submited = True
|
|
op.save()
|
|
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, GenericViewSet):
|
|
"""
|
|
操作使用的自定义表格
|
|
"""
|
|
perms_map={'*':'*'}
|
|
queryset = OperationRecord.objects.select_related('operation', 'form').all()
|
|
serializer_class = OperationRecordListSerializer
|
|
filterset_fields = ['operation', 'form']
|
|
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()
|
|
return Response()
|
|
|
|
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=OperationRecordSubmitSerializer)
|
|
def submit(self, request, pk=None):
|
|
serializer = OperationRecordSubmitSerializer(data=request.data, context={'request':self.request})
|
|
serializer.is_valid(raise_exception=True)
|
|
vdata = serializer.data
|
|
opr = self.get_object()
|
|
wrds = []
|
|
for m in vdata['record_data']: # 保存记录详情
|
|
form_field = RecordFormField.objects.get(pk=m['form_field'])
|
|
m['form_field'] = 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'] = opr
|
|
wrds.append(OperationRecordItem(**m))
|
|
OperationRecordItem.objects.bulk_create(wrds)
|
|
opr.is_filled = True
|
|
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()
|
|
|
|
@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 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()
|
|
|
|
@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'].main_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_DOING, is_executed=False, 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'].main_product
|
|
wproduct.step = newstep
|
|
wproduct.subproduction_plan=vdata['subproduction_plan']
|
|
wproduct.parent = data['wproducts']
|
|
if hasNext:
|
|
wproduct.act_state=WProduct.WPR_ACT_STATE_DOING
|
|
wproduct.is_executed=False
|
|
else:
|
|
wproduct.act_state=WProduct.WPR_ACT_STATE_TOTEST
|
|
wproduct.is_executed=True
|
|
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.is_executed= False
|
|
else:
|
|
wproduct.is_executed= True
|
|
wproduct.act_state=WProduct.WPR_ACT_STATE_TOTEST
|
|
wproduct.material=wproduct.subproduction_plan.main_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()
|
|
|
|
|