工序中检验基本完成

This commit is contained in:
caoqianming 2022-01-29 15:25:17 +08:00
parent 41bcda4f5c
commit 8c35630840
17 changed files with 247 additions and 285 deletions

View File

@ -10,7 +10,7 @@ from apps.pm.models import ProductionPlan, SubProductionPlan
from apps.sam.models import Order
from apps.wf.models import Ticket
from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow
from apps.wpm.services import WpmServies
from apps.wpm.services import WpmService
from apps.em.tasks import update_equip_state_by_next_check_date
# Create your views here.
@ -46,7 +46,7 @@ class UpdateCuttingView(APIView):
i.coperation = op
i.save()
WproductFlow.objects.filter(wproduct=i).update(coperation=op)
WpmServies.update_cutting_list_with_operation(op)
WpmService.update_cutting_list_with_operation(op)
return Response()
from apps.qm.models import TestRecord
@ -90,7 +90,7 @@ class UpdateSpg(APIView):
冷加工重新计算合格率
"""
for i in SubProductionPlan.objects.filter(subproduction__process__id=1):
WpmServies.update_subproduction_progress_main(sp=i)
WpmService.update_subproduction_progress_main(sp=i)
return Response()

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2022-01-29 07:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mtm', '0044_subproduction_need_combtest'),
]
operations = [
migrations.AddField(
model_name='usedstep',
name='need_test',
field=models.BooleanField(default=False, verbose_name='工序内检验'),
),
]

View File

@ -242,6 +242,7 @@ class UsedStep(CommonADModel):
涉及的生产子工序
"""
step = models.ForeignKey(Step, verbose_name='子工序', on_delete=models.CASCADE, related_name='usedstep')
need_test = models.BooleanField('工序内检验', default=False)
remark = models.TextField('生产备注', null=True, blank=True)
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE, related_name='usedstep_subproduction')

View File

@ -3,7 +3,7 @@ from apps.mtm.models import Material, Step
from apps.pm.models import ProductionPlan, SubProductionProgress
from apps.wpm.models import Operation, WProduct
from datetime import *
from apps.wpm.services import WpmServies
from apps.wpm.services import WpmService
from django.db.models import F
from utils.mixins import DynamicFieldsFilterMixin
@ -52,9 +52,9 @@ class SubproductionProgressFilterSet(filters.FilterSet):
wproducts = WProduct.objects.filter(ow_wproduct__operation=value)
step = operation.step
if wproducts.exists():
subplans = WpmServies.get_subplans_queryset_from_wproducts(wproducts)
subplans = WpmService.get_subplans_queryset_from_wproducts(wproducts)
else:
subplans = WpmServies.get_subplans_queyset_from_step(step)
subplans = WpmService.get_subplans_queyset_from_step(step)
queryset = queryset.filter(subproduction_plan__in=subplans)
if step.type == Step.STEP_TYPE_NOM:
queryset = queryset.exclude(material__type__in =[Material.MA_TYPE_HALFGOOD, Material.MA_TYPE_GOOD])

View File

@ -89,7 +89,8 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
subps = SubProduction.objects.filter(product=production_plan.product).order_by('process__number')
for index, i in enumerate(subps):
steps = Step.objects.filter(usedstep__subproduction=i, usedstep__subproduction__is_deleted=False,
usedstep__is_deleted=False, is_deleted=False).values('id', 'number', 'name', 'usedstep__remark')
usedstep__is_deleted=False, is_deleted=False
).values('id', 'number', 'name', 'usedstep__remark', need_test=F('usedstep__need_test'))
instance = SubProductionPlan.objects.create(production_plan=production_plan, subproduction=i,
start_date=production_plan.start_date, end_date=production_plan.end_date,
workshop=i.process.workshop, process=i.process, create_by=request.user,

View File

@ -0,0 +1,36 @@
# Generated by Django 3.2.9 on 2022-01-29 07:12
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('qm', '0022_auto_20211216_1401'),
]
operations = [
migrations.AddField(
model_name='testrecord',
name='is_midtesing',
field=models.BooleanField(default=False, verbose_name='是否子工序检验中'),
),
migrations.AddField(
model_name='testrecorditem',
name='create_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='testrecorditem_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人'),
),
migrations.AddField(
model_name='testrecorditem',
name='update_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='testrecorditem_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'),
),
migrations.AlterField(
model_name='testrecord',
name='type',
field=models.PositiveSmallIntegerField(choices=[(20, '工序检验'), (30, '工序复检'), (36, '夹层检验'), (40, '成品检验')], default=20),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2022-01-29 07:24
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('qm', '0023_auto_20220129_1512'),
]
operations = [
migrations.RenameField(
model_name='testrecord',
old_name='is_midtesing',
new_name='is_midtesting',
),
]

View File

@ -47,13 +47,11 @@ class TestRecord(CommonADModel):
"""
检验记录
"""
TEST_STEP = 10
TEST_PROCESS = 20
TEST_PROCESS_RE = 30
TEST_COMB = 36
TEST_FINAL = 40
type_choice = (
(TEST_STEP, '子工序检验'),
(TEST_PROCESS, '工序检验'),
(TEST_PROCESS_RE, '工序复检'),
(TEST_COMB, '夹层检验'),
@ -70,6 +68,7 @@ class TestRecord(CommonADModel):
fifo_item = models.ForeignKey('inm.fifoitem', verbose_name='关联的出入库批次', on_delete=models.CASCADE, null=True, blank=True)
origin_test = models.ForeignKey('self', verbose_name='原检验记录', on_delete=models.CASCADE, null=True, blank=True)
is_submited = models.BooleanField('是否提交', default=False)
is_midtesting = models.BooleanField('是否子工序检验中', default=False)
remark = models.TextField('备注', default='')

View File

@ -135,7 +135,7 @@ class TestRecordUpdateSerializer(serializers.ModelSerializer):
if i['field_value'] != tri.field_value:
tri.field_value = i['field_value']
tri.update_by = update_by
tri.is_testok = i['is_testok']
tri.is_hidden = i['is_hidden']
tri.save()
tri.is_testok = i['is_testok']
tri.is_hidden = i['is_hidden']
tri.save()
return instance

View File

@ -12,7 +12,7 @@ from django.db import transaction
from rest_framework.decorators import action
from apps.wpm.models import WProduct
from apps.wpm.services import WpmServies
from apps.wpm.services import WpmService
# Create your views here.
class StandardViewSet(CreateUpdateModelAMixin, ModelViewSet):
"""
@ -69,7 +69,7 @@ class TestRecordViewSet(ListModelMixin, UpdateModelMixin, RetrieveModelMixin, De
def update(self, request, *args, **kwargs):
obj = self.get_object()
if obj.is_submited:
if obj.is_submited and obj.is_midtesting is False:
raise exceptions.APIException('该记录已提交不可编辑')
return super().update(request, *args, **kwargs)
@ -77,20 +77,22 @@ class TestRecordViewSet(ListModelMixin, UpdateModelMixin, RetrieveModelMixin, De
obj = self.get_object()
if obj.is_submited:
raise exceptions.APIException('该记录已提交不可删除')
WpmServies.add_wproduct_flow_log(obj.wproduct, 'test_delete')
WpmService.add_wproduct_flow_log(obj.wproduct, 'test_delete')
return super().destroy(request, *args, **kwargs)
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=TestRecordUpdateSerializer)
def submit(self, request, pk=None):
obj = self.get_object()
if obj.is_submited and obj.is_midtesting is False:
raise exceptions.APIException('该记录已提交')
# 校验是否有未填项目
if obj.type != TestRecord.TEST_PROCESS_RE:
if obj.type != TestRecord.TEST_PROCESS_RE and obj.is_midtesting is False:
if TestRecordItem.objects.filter(field_value__isnull=True, is_hidden=False, test_record=obj).exists():
raise exceptions.APIException('存在未填写项目')
with transaction.atomic():
obj.is_submited=True
obj.save()
WpmServies.update_wproduct_by_test(obj, request.user) # 这里已经做了日志记录和进度计算
WpmService.update_wproduct_by_test(obj, request.user) # 这里已经做了日志记录和进度计算
return Response()
# def create(self, request, *args, **kwargs):

View File

@ -1,7 +1,7 @@
from django_filters import rest_framework as filters
from apps.mtm.models import Material, Step
from apps.wpm.services import WpmServies
from apps.wpm.services import WpmService
from utils.mixins import DynamicFieldsFilterMixin
from .models import Operation, OperationMaterial, OperationRecord, WMaterial, WProduct
@ -20,10 +20,10 @@ class WMaterialFilterSet(filters.FilterSet):
wproducts = WProduct.objects.filter(ow_wproduct__operation=value)
step = operation.step
if wproducts.exists():
subplans = WpmServies.get_subplans_queryset_from_wproducts(
subplans = WpmService.get_subplans_queryset_from_wproducts(
wproducts)
else:
subplans = WpmServies.get_subplans_queyset_from_step(step)
subplans = WpmService.get_subplans_queyset_from_step(step)
queryset = queryset.filter(subproduction_plan__in=subplans).exclude(
material__type=Material.MA_TYPE_HALFGOOD)
return queryset

View File

@ -0,0 +1,65 @@
# Generated by Django 3.2.9 on 2022-01-29 07:12
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('mtm', '0045_usedstep_need_test'),
('wpm', '0052_auto_20220125_1116'),
]
operations = [
migrations.AddField(
model_name='wproduct',
name='material_check',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wp_material_check', to='mtm.material', verbose_name='按物料状态检查'),
),
migrations.AddField(
model_name='wproductflow',
name='material_check',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wpf_material_check', to='mtm.material', verbose_name='按物料状态检查'),
),
migrations.AlterField(
model_name='wproduct',
name='child',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wp_child', to='wpm.wproduct'),
),
migrations.AlterField(
model_name='wproduct',
name='material',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='wp_material', to='mtm.material', verbose_name='所属物料状态'),
),
migrations.AlterField(
model_name='wproduct',
name='pre_step',
field=models.ForeignKey(blank=True, help_text='已执行完的步骤', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wp_pre_step', to='mtm.step', verbose_name='已执行到'),
),
migrations.AlterField(
model_name='wproduct',
name='step',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wp_step', to='mtm.step', verbose_name='所在步骤'),
),
migrations.AlterField(
model_name='wproductflow',
name='child',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wpf_child', to='wpm.wproductflow'),
),
migrations.AlterField(
model_name='wproductflow',
name='material',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='wpf_material', to='mtm.material', verbose_name='所属物料状态'),
),
migrations.AlterField(
model_name='wproductflow',
name='pre_step',
field=models.ForeignKey(blank=True, help_text='已执行完的步骤', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wpf_pre_step', to='mtm.step', verbose_name='已执行到'),
),
migrations.AlterField(
model_name='wproductflow',
name='step',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wpf_step', to='mtm.step', verbose_name='所在步骤'),
),
]

View File

@ -1,4 +1,5 @@
import re
from rest_framework import exceptions
from django.db import models
from django.db.models.base import Model
@ -88,16 +89,20 @@ class WProduct(CommonAModel):
number = models.CharField(
'物品编号', unique=True, null=True, blank=True, max_length=50)
material = models.ForeignKey(
Material, verbose_name='所属物料状态', on_delete=models.CASCADE)
Material, verbose_name='所属物料状态', on_delete=models.CASCADE,
related_name='wp_material')
material_check = models.ForeignKey(
Material, verbose_name='按物料状态检查', on_delete=models.CASCADE,
null=True, blank=True, related_name='wp_material_check')
pre_step = models.ForeignKey(Step, verbose_name='已执行到', help_text='已执行完的步骤', null=True, blank=True,
on_delete=models.CASCADE, related_name='w_pre_step')
on_delete=models.CASCADE, related_name='wp_pre_step')
step = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE, null=True, blank=True,
related_name='w_step')
related_name='wp_step')
act_state = models.IntegerField(
'进行状态', default=0, choices=act_state_choices)
is_hidden = models.BooleanField('是否隐藏', default=False)
child = models.ForeignKey('self', blank=True, null=True,
on_delete=models.CASCADE, related_name='wproduct_child')
on_delete=models.CASCADE, related_name='wp_child')
remark = models.CharField('备注', max_length=200, null=True, blank=True)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE,
related_name='wproduct_subplan')
@ -164,16 +169,19 @@ class WproductFlow(CommonAModel):
WProduct, on_delete=models.CASCADE, verbose_name='关联产品', null=True, blank=True)
number = models.CharField('物品编号', null=True, blank=True, max_length=50)
material = models.ForeignKey(
Material, verbose_name='所属物料状态', on_delete=models.CASCADE)
Material, verbose_name='所属物料状态', on_delete=models.CASCADE, related_name='wpf_material')
material_check = models.ForeignKey(
Material, verbose_name='按物料状态检查', on_delete=models.CASCADE,
null=True, blank=True, related_name='wpf_material_check')
pre_step = models.ForeignKey(Step, verbose_name='已执行到', help_text='已执行完的步骤', null=True, blank=True,
on_delete=models.CASCADE, related_name='wl_pre_step')
on_delete=models.CASCADE, related_name='wpf_pre_step')
step = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE, null=True, blank=True,
related_name='wl_step')
related_name='wpf_step')
act_state = models.IntegerField(
'进行状态', default=0, choices=WProduct.act_state_choices)
is_hidden = models.BooleanField('是否隐藏', default=False)
child = models.ForeignKey('self', blank=True, null=True,
on_delete=models.CASCADE, related_name='wproduct_child')
on_delete=models.CASCADE, related_name='wpf_child')
remark = models.CharField('备注', max_length=200, null=True, blank=True)
subproduction_plan = models.ForeignKey(
SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE)

View File

@ -9,19 +9,21 @@ from apps.system.models import User
from apps.wf.models import State, TicketFlow, Transition
from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow, WprouctTicket
from utils.tools import ranstr
class WpmServies(object):
class WpmService(object):
@classmethod
def get_next_step(cls, subproduction_plan:SubProductionPlan, nowstep:Step):
"""
获取下一步骤
"""
stepIds = [i['id'] for i in subproduction_plan.steps]
steps_list = subproduction_plan.steps
stepIds = [i['id'] for i in steps_list]
pindex = stepIds.index(nowstep.id)
need_test = steps_list[pindex].get('need_test', False)
if pindex + 1 < len(stepIds):
return Step.objects.get(pk=stepIds[pindex+1]), True
return Step.objects.get(pk=stepIds[pindex+1]), need_test
else:
return nowstep, False
return nowstep, need_test
@classmethod
def get_subplans_queryset_from_wproducts(cls, wproducts:List):
@ -47,9 +49,15 @@ class WpmServies(object):
"""
is_testok = test.is_testok
wproduct = test.wproduct
test_i = None
if is_testok:
if wproduct.act_state == WProduct.WPR_ACT_STATE_TORETEST: # 复检
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and \
test.is_midtesing is True:
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
test_i = test
elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and wproduct.material.type == Material.MA_TYPE_GOOD: # 成品检验
wproduct.act_state = WProduct.WPR_ACT_STATE_TOFINALTEST
@ -97,7 +105,7 @@ class WpmServies(object):
wproduct.update_by = user
wproduct.update_time = timezone.now()
wproduct.test = None
wproduct.test = test_i
wproduct.last_test_result = is_testok
wproduct.save()
# 添加日志

View File

@ -8,7 +8,7 @@ from django.dispatch import receiver
from rest_framework import exceptions
from apps.wpm.models import WProduct, WproductFlow, WprouctTicket
from apps.wpm.models import OperationWproduct
from apps.wpm.services import WpmServies
from apps.wpm.services import WpmService
@receiver(post_save, sender=Ticket)
@ -34,7 +34,7 @@ def handleTicket(sender, instance, created, **kwargs):
# 工单绑定半成品
wproduct.ticket = instance
wproduct.save()
WpmServies.add_wproduct_flow_log(wproduct, 'ticket_create')
WpmService.add_wproduct_flow_log(wproduct, 'ticket_create')
elif instance.act_state == Ticket.TICKET_ACT_STATE_FINISH:
@ -77,7 +77,7 @@ def handleTicket(sender, instance, created, **kwargs):
wp.save()
# 添加日志
WpmServies.add_wproduct_flow_log(wp, 'ticket_finish')
WpmService.add_wproduct_flow_log(wp, 'ticket_finish')
# 更新子计划合格进度
WpmServies.update_subproduction_progress_main(sp=wp.subproduction_plan)
WpmService.update_subproduction_progress_main(sp=wp.subproduction_plan)

View File

@ -3,7 +3,7 @@ from rest_framework import urlpatterns
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from apps.wpm.views import CuttingListViewSet, DoFormInit, DoFormSubmit, OperationEquipViewSet, OperationMaterialInputViewSet, OperationMaterialOutputViewSet, OperationMaterialToolViewSet, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet, WproductTicketViewSet
from apps.wpm.views import CuttingListViewSet, OperationEquipViewSet, OperationMaterialInputViewSet, OperationMaterialOutputViewSet, OperationMaterialToolViewSet, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet, WproductTicketViewSet
router = DefaultRouter()
router.register('wmaterial', WMaterialViewSet, basename='wmaterial')
@ -19,8 +19,6 @@ router.register('operation_tool', OperationMaterialToolViewSet, basename='operat
router.register('subplan', WPlanViewSet, basename='wplan')
router.register('cutting_list', CuttingListViewSet, basename='cutting_list')
urlpatterns = [
path('do/init/', DoFormInit.as_view()),
path('do/submit/', DoFormSubmit.as_view()),
path('', include(router.urls)),
]

View File

@ -32,7 +32,7 @@ from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerial
from rest_framework.response import Response
from django.db import transaction
from rest_framework import exceptions, serializers
from apps.wpm.services import WpmServies
from apps.wpm.services import WpmService
from django.utils import timezone
from rest_framework import status
from django.db.models import Count
@ -105,7 +105,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
m.update_by = request.user
m.update_time = timezone.now()
m.save()
WpmServies.add_wproduct_flow_log(
WpmService.add_wproduct_flow_log(
instance=m, change_str='pick_half')
pw = PickWproduct()
pw.pick = pick
@ -151,7 +151,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
perms_map = {'*': '*'}
queryset = WProduct.objects.select_related('step', 'material',
'subproduction_plan', 'warehouse', 'subproduction_plan__production_plan__order',
'to_order').prefetch_related('wproduct_child')
'to_order').prefetch_related('wp_child')
serializer_class = WProductListSerializer
filterset_class = WProductFilterSet
search_fields = ['number']
@ -188,7 +188,6 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
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,
@ -208,13 +207,16 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
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()
WpmServies.add_wproduct_flow_log(wproduct, 'test_init')
WpmService.add_wproduct_flow_log(wproduct, 'test_init')
# 创建检验条目
for i in RecordFormField.objects.filter(form=form, is_deleted=False):
tri = TestRecordItem()
@ -224,6 +226,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
tri.create_by = request.user
tri.save()
return Response(TestRecordDetailSerializer(instance=tr).data)
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=WproductPutInsSerializer)
@transaction.atomic
@ -281,7 +284,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
i.update_by = request.user
i.update_time = timezone.now()
i.save()
WpmServies.add_wproduct_flow_log(i, 'putins')
WpmService.add_wproduct_flow_log(i, 'putins')
return Response()
@action(methods=['post'], detail=True, perms_map={'post': '*'}, serializer_class=WproductPutInSerializer)
@ -328,7 +331,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
wproduct.act_state = WProduct.WPR_ACT_STATE_INM
wproduct.warehouse = warehouse
wproduct.save()
WpmServies.add_wproduct_flow_log(wproduct, 'putin')
WpmService.add_wproduct_flow_log(wproduct, 'putin')
return Response()
@action(methods=['post'], detail=True, perms_map={'post': '*'}, serializer_class=ScrapSerializer)
@ -354,9 +357,9 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
obj.update_by = request.user
obj.update_time = timezone.now()
obj.save()
WpmServies.add_wproduct_flow_log(obj, 'scrap')
WpmService.add_wproduct_flow_log(obj, 'scrap')
if obj.step.process.id == 1: # 如果是冷加工
WpmServies.update_cutting_list_with_operation(obj.coperation)
WpmService.update_cutting_list_with_operation(obj.coperation)
return Response()
# @action(methods=['get'], detail=False, perms_map={'get':'*'})
@ -411,14 +414,14 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
is_mtestok = request.data.get('is_mtestok')
obj.is_mtestok = is_mtestok
if is_mtestok:
WpmServies.update_plan_state_by_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'
WpmServies.add_wproduct_flow_log(instance=obj, change_str=change_str)
WpmService.add_wproduct_flow_log(instance=obj, change_str=change_str)
return Response()
@action(methods=['get'], detail=True, perms_map={'get': '*'})
@ -461,7 +464,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
i.need_to_order = True
i.update_by = request.user
i.save()
WpmServies.add_wproduct_flow_log(i, change_str='need_to_order')
WpmService.add_wproduct_flow_log(i, change_str='need_to_order')
return Response()
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=WproductToOrderSerializer)
@ -486,7 +489,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
i.to_order = order
i.update_by = request.user
i.save()
WpmServies.add_wproduct_flow_log(i,change_str='to_order')
WpmService.add_wproduct_flow_log(i,change_str='to_order')
return Response()
class WproductTicketViewSet(ListModelMixin, GenericViewSet):
@ -544,7 +547,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
i.act_state = WProduct.WPR_ACT_STATE_DOWAIT
i.update_by = request.user
i.save()
WpmServies.add_wproduct_flow_log(i, 'operation_delete')
WpmService.add_wproduct_flow_log(i, 'operation_delete')
self.perform_destroy(instance)
return Response(status=status.HTTP_204_NO_CONTENT)
@ -565,14 +568,14 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
# 创建操作所用半成品关联记录
if 'wproducts' in vdata:
owps = []
splans = WpmServies.get_subplans_queryset_from_wproducts(
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()
WpmServies.add_wproduct_flow_log(wpd, 'operation_create')
WpmService.add_wproduct_flow_log(wpd, 'operation_create')
owp = {}
owp['operation'] = op
owp['wproduct'] = wpd
@ -583,7 +586,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
owps.append(OperationWproduct(**owp))
OperationWproduct.objects.bulk_create(owps)
else:
splans = WpmServies.get_subplans_queryset_from_wproducts(
splans = WpmService.get_subplans_queryset_from_wproducts(
vdata['wproducts'])
# 查询需要填写的自定义表格
forms = RecordForm.objects.filter(
@ -677,22 +680,30 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
wsp = i.subproduction_plan
# 获取下一步子工序
newstep, hasNext = WpmServies.get_next_step(wsp, step)
newstep, needTest = WpmService.get_next_step(wsp, step)
wp.step = newstep
wp.pre_step = step
if hasNext:
wp.act_state = WProduct.WPR_ACT_STATE_DOWAIT
else:
if step == newstep:
wp.act_state = WProduct.WPR_ACT_STATE_TOTEST
wp.material = wsp.product
if wp.test:# 如果有正在进行的工序中检验
wp.test.is_midtesting = False
wp.test.save()
else:
wp.act_state = WProduct.WPR_ACT_STATE_DOWAIT
if needTest:
wp.act_state = WProduct.WPR_ACT_STATE_TOTEST
wp.material_check = wsp.product
wp.operation = None
wp.update_by = request.user
wp.save()
WpmServies.add_wproduct_flow_log(wp, 'operation_submit')
WpmService.add_wproduct_flow_log(wp, 'operation_submit')
for i in ows.values('subproduction_plan').distinct():
# 更新进度
WpmServies.update_subproduction_progress_main(sp=wsp)
WpmService.update_subproduction_progress_main(sp=wsp)
elif step.type == Step.STEP_TYPE_DIV:
# 更新物料产出情况
@ -700,7 +711,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
raise exceptions.APIException('请选择物料产出')
for i in omos:
if i.subproduction_progress.is_main:
newstep, _ = WpmServies.get_next_step(
newstep, _ = WpmService.get_next_step(
i.subproduction_plan, step)
wpr = dict(material=i.material, step=newstep,
act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='',
@ -709,33 +720,40 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
for x in range(i.count):
ins = WProduct.objects.create(**wpr)
# 添加日志
WpmServies.add_wproduct_flow_log(
WpmService.add_wproduct_flow_log(
ins, 'wproduct_create')
# 更新进度
WpmServies.update_subproduction_progress_main(
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]
# 校验单片数量是否正确, 暂时未写
newstep, hasNext = WpmServies.get_next_step(
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 hasNext:
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
else:
if step == newstep:
wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
# 更新子计划进度
WpmServies.update_subproduction_progress_main(
sp=oms_w.subproduction_plan)
if wproduct.test:# 如果有正在进行的工序中检验
wproduct.test.is_midtesting = False
wproduct.test.save()
else:
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
if needTest:
wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
wproduct.material_check = wproduct.product
# 更新子计划进度
WpmService.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')
WpmService.add_wproduct_flow_log(wproduct, 'wproduct_create')
# 隐藏原半成品
wps = WProduct.objects.filter(ow_wproduct__operation=op)
wps.update(is_hidden=True, child=wproduct,
@ -747,7 +765,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
# 如果是冷加工
if step.process.id == 1:
WpmServies.update_cutting_list_with_operation(op=op)
WpmService.update_cutting_list_with_operation(op=op)
return Response()
@ -971,213 +989,3 @@ class OperationMaterialToolViewSet(ListModelMixin, CreateModelMixin, DestroyMode
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()