hberp/hb_server/apps/wpm/views.py

1021 lines
44 KiB
Python

from rest_framework.generics import CreateAPIView, GenericAPIView
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, \
ListModelMixin, RetrieveModelMixin, UpdateModelMixin
from rest_framework.viewsets import GenericViewSet
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct
from apps.inm.services import InmService
from apps.mtm.models import Material, RecordForm, RecordFormField, Step, SubprodctionMaterial, TechDoc
from apps.mtm.serializers import RecordFormDetailSerializer, SubprodctionMaterialListSerializer, TechDocListSerializer
from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress
from apps.pm.serializers import SubProductionPlanListSerializer, SubProductionProgressSerializer
from apps.qm.models import TestRecord, TestRecordItem
from apps.qm.serializers import TestRecordDetailSerializer
from apps.system.mixins import CreateUpdateCustomMixin, CreateUpdateModelAMixin
from rest_framework.decorators import action
from apps.wf.models import Workflow
from apps.wpm.filters import CuttingFilterSet, OperationRecordFilterSet, WMaterialFilterSet, WProductFilterSet
from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, \
OperationMaterial, OperationRecord, OperationRecordItem, WproductFlow, WprouctTicket
from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerializer, OperationEquipUpdateSerializer, \
OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, \
OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, \
OperationRecordDetailSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, \
OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, \
OperationListSerializer, OperationWproductUpdateSerializer, PickHalfsSerializer, \
PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, \
WProductCardSerializer, WProductDetailSerializer, WProductListSerializer, \
WpmTestFormInitSerializer, WproductMtestSerializer, WproductNeedToOrderSerializer, WproductPutInSerializer, \
WproductPutInsSerializer, WproductTicketListSerializer, WproductToOrderSerializer
from rest_framework.response import Response
from django.db import transaction
from rest_framework import exceptions, serializers
from apps.wpm.services import WpmService
from django.utils import timezone
from rest_framework import status
from django.db.models import Count, Q
from utils.tools import ranstr
# Create your views here.
class WPlanViewSet(ListModelMixin, GenericViewSet):
"""
车间生产计划
"""
perms_map = {'get': '*'}
queryset = SubProductionPlan.objects.select_related(
'process', 'workshop', 'subproduction', 'product', 'production_plan').exclude(state=SubProductionPlan.SUBPLAN_STATE_PLANING)
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': 'pick_half', '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()
WpmService.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()
if sp.production_plan.state in \
[ProductionPlan.PLAN_STATE_ASSGINED, ProductionPlan.PLAN_STATE_ACCEPTED]:
sp.production_plan.state = ProductionPlan.PLAN_STATE_WORKING
sp.production_plan.save()
return Response()
class WMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, GenericViewSet):
"""
车间物料表
"""
perms_map = {'get': '*'}
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': 'wmaterial_pick'}, 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 = {'get': '*'}
queryset = WProduct.objects.select_related('step', 'material',
'subproduction_plan', 'warehouse', 'subproduction_plan__production_plan__order',
'to_order', 'update_by', 'create_by').prefetch_related('wp_child')
serializer_class = WProductListSerializer
filterset_class = WProductFilterSet
search_fields = ['number', 'material__name', 'subproduction_plan__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': 'wp_test_init'}, 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=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
elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and\
wproduct.step != wproduct.pre_step: # 如果是工序内检验
savedict['is_midtesting'] = True
tr = TestRecord.objects.create(**savedict)
# 更新wproduct
wproduct.test = tr
wproduct.update_by = request.user
wproduct.update_time = timezone.now()
wproduct.save()
WpmService.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.create_by = request.user
tri.save()
return Response(TestRecordDetailSerializer(instance=tr).data)
@action(methods=['post'], detail=False, perms_map={'post': 'wp_putins'}, 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, number='RK'+ranstr(7))
# 创建入库明细
for i in wproducts_a:
spi = SubProductionPlan.objects.get(pk=i['subproduction_plan'])
fifoitem = FIFOItem()
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
if i.number is None:
raise exceptions.APIException('缺少编号')
ip['number'] = i.number
ip['material'] = i.material
ips.append(FIFOItemProduct(**ip))
FIFOItemProduct.objects.bulk_create(ips)
# 更新库存并修改半成品进行状态
InmService.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()
WpmService.add_wproduct_flow_log(i, 'putins')
return Response()
@action(methods=['post'], detail=True, perms_map={'post': 'wp_putins'}, 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, number='RK'+ranstr(7))
# 创建入库明细
fifoitem = FIFOItem()
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
if i.number is None:
raise exceptions.APIException('缺少编号')
ip['number'] = i.number
ip['material'] = material
ips.append(FIFOItemProduct(**ip))
FIFOItemProduct.objects.bulk_create(ips)
# 更新库存并修改半成品进行状态
InmService.update_inm(fifo)
wproduct.act_state = WProduct.WPR_ACT_STATE_INM
wproduct.warehouse = warehouse
wproduct.save()
WpmService.add_wproduct_flow_log(wproduct, 'putin')
return Response()
@action(methods=['post'], detail=True, perms_map={'post': 'wp_scrap'}, 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.ticket is not None:
raise exceptions.APIException('该产品存在进行工单')
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()
WpmService.add_wproduct_flow_log(obj, 'scrap')
if obj.step.process.id == 1: # 如果是冷加工
WpmService.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': 'wp_mtest'}, serializer_class=WproductMtestSerializer)
@transaction.atomic
def mtest(self, request, pk=None):
"""
军检
"""
obj = self.get_object()
if obj.is_mtestok is not None:
raise exceptions.APIException('已进行军检')
if obj.material.type != Material.MA_TYPE_GOOD:
raise exceptions.APIException('军检必须是成品')
obj.remark_mtest = request.data.get('remark_mtest', None)
is_mtestok = request.data.get('is_mtestok')
obj.is_mtestok = is_mtestok
if is_mtestok:
WpmService.update_plan_state_by_mtestok(
obj.subproduction_plan.production_plan)
obj.update_by = request.user
obj.save()
change_str = 'mtest_notok'
if is_mtestok:
change_str = 'mtest_ok'
WpmService.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)
@action(methods=['post'], detail=False, perms_map={'post': 'wp_need_to_order'}, serializer_class=WproductNeedToOrderSerializer)
@transaction.atomic
def need_to_order(self, request, pk=None):
"""
设为需要指派订单
"""
serializer = WproductNeedToOrderSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
wps = WProduct.objects.filter(id__in = [i.id for i in vdata.get('wproducts')])
wps.update()
for i in wps:
i.need_to_order = True
i.update_by = request.user
i.save()
WpmService.add_wproduct_flow_log(i, change_str='need_to_order')
return Response()
@action(methods=['post'], detail=False, perms_map={'post': 'wp_to_order'}, serializer_class=WproductToOrderSerializer)
@transaction.atomic
def to_order(self, request, pk=None):
"""
指派发货订单
"""
serializer = WproductToOrderSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
wps = WProduct.objects.filter(id__in = [i.id for i in vdata.get('wproducts')])
wp = wps.first()
order = vdata['order']
if wp.material != order.product:
raise exceptions.ValidationError('所选订单与产品不符')
for i in wps:
if i.material != wp.material and i.material.type != Material.MA_TYPE_GOOD and i.act_state \
not in [WProduct.WPR_ACT_STATE_OK, WProduct.WPR_ACT_STATE_INM]:
raise exceptions.ValidationError('所选产品错误')
for i in wps:
i.to_order = order
i.update_by = request.user
i.save()
WpmService.add_wproduct_flow_log(i,change_str='to_order')
return Response()
class WproductTicketViewSet(ListModelMixin, GenericViewSet):
"""
玻璃审批工单
"""
perms_map = {'get': '*'}
queryset = WprouctTicket.objects.select_related('step', 'material', 'subproduction_plan',
'resp_process', 'subproduction_plan__production_plan__order',
'subproduction_plan__production_plan',
'ticket__workflow')
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 = {'get': '*', 'post':'operation_create',
'put':'operation_update', 'delete':'operation_delete'}
queryset = Operation.objects.select_related('step', 'create_by', 'update_by').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_serializer_class(self):
if self.action == 'retrieve':
return OperationListSerializer
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()
WpmService.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 = WpmService.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()
WpmService.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 = WpmService.get_subplans_queryset_from_wproducts(
vdata['wproducts'])
# 查询需要填写的自定义表格
forms = RecordForm.objects.filter(
step=step, type=RecordForm.RF_TYPE_DO, enabled=True)
# 根据产品不同进行筛选 这里其实是有问题的,应该是以产出物归属产品来查表,但操作刚创建是没有的,先这样吧
if 'wproducts' in vdata and splans:
xforms = forms.filter(material=splans[0].production_plan.product)
if xforms.exists():
forms = xforms
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.state = i.state
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(OperationListSerializer(instance=op).data)
@action(methods=['post'], detail=True, perms_map={'post': 'operation_submit'}, serializer_class=serializers.Serializer)
@transaction.atomic
def submit(self, request, pk=None):
"""
提交车间操作重要
"""
op = self.get_object()
step = op.step
processId = op.step.process.id
if op.is_submited:
raise exceptions.APIException('该操作已提交')
omis = OperationMaterial.objects.filter(operation=op,
type=SubprodctionMaterial.SUB_MA_TYPE_IN)
omos = OperationMaterial.objects.filter(operation=op,
type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
# 校验消耗产出是否正确填写
if op.step.type == Step.STEP_TYPE_DIV:
sps_omi_l = omis.values_list('subproduction_plan', flat=True)
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)):
raise exceptions.APIException('消耗与产出不一致')
else:
pass
# if omis.exists() and processId !=1: # 不是冷加工
# 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, needTest = WpmService.get_next_step(wsp, step)
wp.step = newstep
wp.pre_step = step
wp.material = wsp.product
if step == newstep:
wp.act_state = WProduct.WPR_ACT_STATE_TOTEST
if wp.test:# 如果有正在进行的工序中检验
wp.test.is_midtesting = False
wp.test.is_submited = False
wp.test.save()
else:
wp.act_state = WProduct.WPR_ACT_STATE_DOWAIT
if needTest:
wp.act_state = WProduct.WPR_ACT_STATE_TOTEST
if wp.test:# 如果有正在进行的工序中检验
wp.test.is_submited = False
wp.test.save()
wp.operation = None
wp.update_by = request.user
wp.save()
WpmService.add_wproduct_flow_log(wp, 'operation_submit')
for i in ows.values('subproduction_plan').distinct():
# 更新进度
WpmService.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, _ = WpmService.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)
# 添加日志
WpmService.add_wproduct_flow_log(
ins, 'wproduct_create')
# 更新进度
WpmService.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]
if oms_w.count!=1:
raise exceptions.APIException('产出数量应为1')
# 校验单片数量是否正确, 暂时未写
newstep, needTest = WpmService.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 step == newstep:
wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
if wproduct.test:# 如果有正在进行的工序中检验
wproduct.test.is_midtesting = False
wproduct.test.is_submited = False
wproduct.test.save()
else:
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
if needTest:
wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
# 更新子计划进度
WpmService.update_subproduction_progress_main(
sp=oms_w.subproduction_plan)
wproduct.create_by = request.user
wproduct.coperation = op
wproduct.save()
WpmService.add_wproduct_flow_log(wproduct, 'wproduct_create')
# 隐藏原半成品
wps = WProduct.objects.filter(ow_wproduct__operation=op)
wps.update(act_state=WProduct.WPR_ACT_STATE_USED, child=wproduct, is_hidden=True,
update_by=request.user, update_time=timezone.now())
WpmService.add_wproducts_flow_log(wps, change_str='wproduct_create')
else:
raise exceptions.APIException('产出物料未填写或填写错误')
op.is_submited = True
op.update_by = request.user
op.save()
# 如果是冷加工
if processId == 1:
WpmService.update_cutting_list_with_operation(op=op)
return Response()
class OperationWproductViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet):
"""
操作使用的半成品
"""
perms_map = {'get': '*', 'post':'operation_update',
'put':'operation_update', 'delete':'operation_update'}
queryset = OperationWproduct.objects.select_related(
'subproduction_plan', 'material').all()
serializer_class = OperationWproductListSerializer
filterset_fields = ['material', 'subproduction_plan', 'operation']
ordering_fields = ['id']
ordering = ['-id']
def get_serializer_class(self):
if self.action == 'update':
return OperationWproductUpdateSerializer
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()
wp = instance.wproduct
wp.act_state = WProduct.WPR_ACT_STATE_DOWAIT
wp.operation = None
wp.save()
return Response()
class OperationEquipViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet):
"""
操作使用的设备
"""
perms_map = {'get': '*', 'post':'operation_update',
'put':'operation_update', 'delete':'operation_update'}
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 = {'get': '*', 'post':'operation_update',
'put':'operation_update', 'delete':'operation_update'}
queryset = OperationRecord.objects.select_related(
'operation', 'form').all()
serializer_class = OperationRecordListSerializer
filterset_class = OperationRecordFilterSet
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 = {'get': '*', 'post':'operation_update', 'delete':'operation_update'}
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': 'operation_update'},
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 = {'get': '*'}
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 = {'get': '*', 'post':'operation_update', 'delete':'operation_update'}
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': 'operation_update'},
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 = {'get': '*', 'post':'operation_update', 'delete':'operation_update'}
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()