Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop

This commit is contained in:
shijing 2022-10-14 11:00:10 +08:00
commit 527f61d886
9 changed files with 133 additions and 52 deletions

View File

@ -458,6 +458,12 @@
<span v-else>不检验</span> <span v-else>不检验</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="复用上表">
<template slot-scope="scope">
<span v-if=" scope.row.reuse_form"></span>
<span v-else></span>
</template>
</el-table-column>
<el-table-column label="备注"> <el-table-column label="备注">
<template slot-scope="scope">{{ scope.row.remark }}</template> <template slot-scope="scope">{{ scope.row.remark }}</template>
</el-table-column> </el-table-column>
@ -500,12 +506,6 @@
label-width="100px" label-width="100px"
label-position="right" label-position="right"
> >
<el-form-item label="工序内检验">
<el-radio-group v-model="usedstep.need_test">
<el-radio :label="true">检验</el-radio>
<el-radio :label="false">不检验</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="子工序" prop="unit"> <el-form-item label="子工序" prop="unit">
<el-select style="width: 100%" v-model="usedstep.step" placeholder="请选择"> <el-select style="width: 100%" v-model="usedstep.step" placeholder="请选择">
<el-option <el-option
@ -516,6 +516,18 @@
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="工序内检验">
<el-radio-group v-model="usedstep.need_test">
<el-radio :label="true">检验</el-radio>
<el-radio :label="false">不检验</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="复用上表">
<el-radio-group v-model="usedstep.reuse_form">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input v-model="usedstep.remark" placeholder="输入备注信息"/> <el-input v-model="usedstep.remark" placeholder="输入备注信息"/>
</el-form-item> </el-form-item>

View File

@ -106,12 +106,12 @@ class ClockRecordViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
now = timezone.now() now = timezone.now()
now_local = timezone.localtime() now_local = timezone.localtime()
if 8<=now_local.hour<=17: if 6<=now_local.hour<=17:
base64_data = base64.urlsafe_b64decode(tran64( base64_data = base64.urlsafe_b64decode(tran64(
request.data.get('base64').replace(' ', '+'))) request.data.get('base64').replace(' ', '+')))
user, msg = HRMService.face_compare_from_base64(base64_data, request.data.get('tolerance', 0.36)) user, msg = HRMService.face_compare_from_base64(base64_data, request.data.get('tolerance', 0.36))
if user: if user:
ins, created = ClockRecord.objects.get_or_create( ClockRecord.objects.get_or_create(
create_by = user, create_time__hour__range = [8,18], create_by = user, create_time__hour__range = [8,18],
create_time__year=now_local.year, create_time__month=now_local.month, create_time__year=now_local.year, create_time__month=now_local.month,
create_time__day=now_local.day, create_time__day=now_local.day,
@ -120,9 +120,9 @@ class ClockRecordViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
'create_by':user, 'create_by':user,
'create_time':now 'create_time':now
}) })
if not created: # if not created:
ins.update_time = now # ins.update_time = now
ins.save() # ins.save()
# 设为在岗 # 设为在岗
Employee.objects.filter(user=user).update(is_atwork=True, last_check_time=now) Employee.objects.filter(user=user).update(is_atwork=True, last_check_time=now)
return Response(UserSimpleSerializer(instance=user).data) return Response(UserSimpleSerializer(instance=user).data)

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2022-06-27 05:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mtm', '0053_alter_material_unit'),
]
operations = [
migrations.AddField(
model_name='usedstep',
name='reuse_form',
field=models.BooleanField(default=True, verbose_name='复用上表'),
),
]

View File

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

View File

@ -163,7 +163,7 @@ class UsedStepCreateSerializer(serializers.ModelSerializer):
""" """
class Meta: class Meta:
model = UsedStep model = UsedStep
fields = ['step', 'subproduction', 'remark', 'need_test'] fields = ['step', 'subproduction', 'remark', 'need_test', 'reuse_form']
class UsedStepUpdateSerializer(serializers.ModelSerializer): class UsedStepUpdateSerializer(serializers.ModelSerializer):
""" """
@ -171,7 +171,7 @@ class UsedStepUpdateSerializer(serializers.ModelSerializer):
""" """
class Meta: class Meta:
model = UsedStep model = UsedStep
fields = ['remark', 'need_test'] fields = ['remark', 'need_test', 'reuse_form']
class UsedStepListSerializer(serializers.ModelSerializer): class UsedStepListSerializer(serializers.ModelSerializer):
""" """

View File

@ -166,7 +166,7 @@ class UsedStepViewSet(OptimizationMixin, CreateModelMixin, DestroyModelMixin, Li
'put':'subproduction_update', 'delete':'subproduction_update'} 'put':'subproduction_update', 'delete':'subproduction_update'}
queryset = UsedStep.objects.all() queryset = UsedStep.objects.all()
filterset_fields = ['subproduction', 'step'] filterset_fields = ['subproduction', 'step']
ordering = ['step__sort', '-step__create_time'] ordering = ['step__number', 'step__create_time']
def get_serializer_class(self): def get_serializer_class(self):
if self.action =='create': if self.action =='create':

View File

@ -136,6 +136,13 @@ class WProduct(CommonAModel):
""" """
return self.test_wproduct.filter(type=TestRecord.TEST_PROCESS, is_submited=True).order_by('-id').first() return self.test_wproduct.filter(type=TestRecord.TEST_PROCESS, is_submited=True).order_by('-id').first()
@property
def last_wp_test(self):
"""
最后提交的本产品本工序自检
"""
return self.test_wproduct.filter(is_submited=True, type=TestRecord.TEST_PROCESS, subproduction_plan=self.subproduction_plan).order_by('-id').first()
class WprouctTicket(CommonAModel): class WprouctTicket(CommonAModel):
""" """

View File

@ -2,8 +2,9 @@ from django.utils import timezone
from typing import List from typing import List
from django.db.models.expressions import F from django.db.models.expressions import F
from apps.mtm.serializers import UsedStepListSerializer
from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress
from apps.mtm.models import Material, Step, SubprodctionMaterial from apps.mtm.models import Material, Step, SubprodctionMaterial, UsedStep
from apps.qm.models import TestRecord from apps.qm.models import TestRecord
from apps.system.models import User from apps.system.models import User
from apps.wf.models import State, TicketFlow, Transition from apps.wf.models import State, TicketFlow, Transition
@ -13,18 +14,42 @@ from rest_framework.exceptions import ParseError
class WpmService(object): class WpmService(object):
@classmethod @classmethod
def get_next_step(cls, subproduction_plan:SubProductionPlan, nowstep:Step): def get_step_info(cls, subproduction_plan:SubProductionPlan, nowstep:Step):
""" """
获取下一步骤 返回下一步骤 当前步骤是否需要检验 当前步骤是否需要复用表
""" """
steps_list = subproduction_plan.steps used_steps = UsedStep.objects.filter(subproduction=subproduction_plan.subproduction).order_by('step__number')
stepIds = [i['id'] for i in steps_list] if nowstep is None:
pindex = stepIds.index(nowstep.id) try:
need_test = steps_list[pindex].get('need_test', False) nowstep = used_steps[0].step
if pindex + 1 < len(stepIds): except:
return Step.objects.get(pk=stepIds[pindex+1]), need_test pass
else: for index, i in enumerate(used_steps):
return nowstep, need_test if i.step == nowstep:
try:
used_step = used_steps[index+1]
return used_step.step, i.need_test, i.reuse_form
except:
return nowstep, i.need_test, i.reuse_form
raise ParseError('获取步骤信息失败')
# steps_list = subproduction_plan.steps
# stepIds = [i['id'] for i in steps_list]
# pindex = stepIds.index(nowstep.id)
# if get_next:
# if pindex + 1 < len(stepIds):
# pindex = pindex + 1
# need_test = steps_list[pindex].get('need_test', False)
# reuse_form = steps_list[pindex].get('reuse_form', True)
# return Step.objects.get(pk=stepIds[pindex]), need_test, reuse_form
# else:
# need_test = steps_list[pindex].get('need_test', False)
# reuse_form = steps_list[pindex].get('reuse_form', True)
# return nowstep, need_test, reuse_form
# else:
# need_test = steps_list[pindex].get('need_test', False)
# reuse_form = steps_list[pindex].get('reuse_form', True)
# return
@classmethod @classmethod
def get_subplans_queryset_from_wproducts(cls, wproducts:List): def get_subplans_queryset_from_wproducts(cls, wproducts:List):
@ -50,7 +75,6 @@ class WpmService(object):
""" """
is_testok = test.is_testok is_testok = test.is_testok
wproduct = test.wproduct wproduct = test.wproduct
test_i = None
if is_testok: if is_testok:
if wproduct.act_state == WProduct.WPR_ACT_STATE_TORETEST: # 复检 if wproduct.act_state == WProduct.WPR_ACT_STATE_TORETEST: # 复检
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
@ -62,7 +86,6 @@ class WpmService(object):
elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and \ elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and \
test.is_midtesting is True: test.is_midtesting is True:
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT 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: # 成品检验 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 wproduct.act_state = WProduct.WPR_ACT_STATE_TOFINALTEST
@ -112,7 +135,7 @@ class WpmService(object):
wproduct.update_by = user wproduct.update_by = user
wproduct.update_time = timezone.now() wproduct.update_time = timezone.now()
wproduct.test = test_i wproduct.test = None
wproduct.last_test_result = is_testok wproduct.last_test_result = is_testok
wproduct.save() wproduct.save()
# 添加日志 # 添加日志

View File

@ -4,7 +4,7 @@ from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, \
from rest_framework.viewsets import GenericViewSet from rest_framework.viewsets import GenericViewSet
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct
from apps.inm.services import InmService from apps.inm.services import InmService
from apps.mtm.models import Material, RecordForm, RecordFormField, Step, SubprodctionMaterial, TechDoc from apps.mtm.models import Material, RecordForm, RecordFormField, Step, SubprodctionMaterial, TechDoc, UsedStep
from apps.mtm.serializers import RecordFormDetailSerializer, SubprodctionMaterialListSerializer, TechDocListSerializer from apps.mtm.serializers import RecordFormDetailSerializer, SubprodctionMaterialListSerializer, TechDocListSerializer
from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress
from apps.pm.serializers import SubProductionPlanListSerializer, SubProductionProgressSerializer from apps.pm.serializers import SubProductionPlanListSerializer, SubProductionProgressSerializer
@ -36,7 +36,7 @@ from apps.wpm.services import WpmService
from django.utils import timezone from django.utils import timezone
from rest_framework import status from rest_framework import status
from django.db.models import Count, Q from django.db.models import Count, Q
from rest_framework.exceptions import ParseError
from utils.tools import ranstr from utils.tools import ranstr
@ -185,14 +185,14 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
vdata = serializer.validated_data vdata = serializer.validated_data
wproduct = vdata['wproduct'] wproduct = vdata['wproduct']
form = vdata['form'] form = vdata['form']
if wproduct.test:
raise exceptions.APIException('存在进行中检验')
# 根据情况创建一条检验记录 # 根据情况创建一条检验记录
if wproduct.act_state not in [WProduct.WPR_ACT_STATE_TOTEST, 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_TORETEST, WProduct.WPR_ACT_STATE_TOFINALTEST,
WProduct.WPR_ACT_STATE_TOCOMBTEST]: WProduct.WPR_ACT_STATE_TOCOMBTEST]:
raise exceptions.APIException('该产品当前状态不可检验') raise exceptions.APIException('该产品当前状态不可检验')
if wproduct.test:
raise exceptions.APIException('存在进行中检验')
savedict = dict( savedict = dict(
create_by=request.user, create_by=request.user,
wproduct=wproduct, wproduct=wproduct,
@ -202,7 +202,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
step=wproduct.step, step=wproduct.step,
form=form) form=form)
if wproduct.act_state == WProduct.WPR_ACT_STATE_TORETEST: if wproduct.act_state == WProduct.WPR_ACT_STATE_TORETEST:
# 查找最近一条检验记录 # 查找最近一条工序检验记录
trs = wproduct.last_process_test trs = wproduct.last_process_test
savedict['origin_test'] = trs savedict['origin_test'] = trs
if not trs: if not trs:
@ -212,9 +212,11 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
savedict['type'] = TestRecord.TEST_FINAL savedict['type'] = TestRecord.TEST_FINAL
elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOCOMBTEST: elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOCOMBTEST:
savedict['type'] = TestRecord.TEST_COMB savedict['type'] = TestRecord.TEST_COMB
elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and\ elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST:
wproduct.step != wproduct.pre_step: # 如果是工序内检验 _, need_test, _ = WpmService.get_step_info(wproduct.subproduction_plan, wproduct.pre_step)
savedict['is_midtesting'] = True if need_test and wproduct.step != wproduct.pre_step:
savedict['is_midtesting'] = True
# if UsedStep.objects.filter(subproduction=wproduct.subproduction_plan.subproduction).first().need_test:
tr = TestRecord.objects.create(**savedict) tr = TestRecord.objects.create(**savedict)
# 更新wproduct # 更新wproduct
wproduct.test = tr wproduct.test = tr
@ -698,24 +700,32 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
wsp = i.subproduction_plan wsp = i.subproduction_plan
# 获取下一步子工序 # 获取下一步子工序
newstep, needTest = WpmService.get_next_step(wsp, step) newstep, needTest, reuseForm = WpmService.get_step_info(wsp, step)
wp.step = newstep wp.step = newstep
wp.pre_step = step wp.pre_step = step
wp.material = wsp.product wp.material = wsp.product
if step == newstep: if step == newstep:
wp.act_state = WProduct.WPR_ACT_STATE_TOTEST wp.act_state = WProduct.WPR_ACT_STATE_TOTEST
if wp.test:# 如果有正在进行的工序中检验 last_test = wp.last_wp_test
wp.test.is_midtesting = False if last_test and reuseForm:
wp.test.is_submited = False last_test.is_midtesting = False
wp.test.save() last_test.is_submited = False
last_test.save()
wp.test = last_test
wp.save()
else: else:
wp.act_state = WProduct.WPR_ACT_STATE_DOWAIT wp.act_state = WProduct.WPR_ACT_STATE_DOWAIT
if needTest: if needTest: #子工序若需要检验
print(needTest, reuseForm)
wp.act_state = WProduct.WPR_ACT_STATE_TOTEST wp.act_state = WProduct.WPR_ACT_STATE_TOTEST
if wp.test:# 如果有正在进行的工序中检验 last_test = wp.last_wp_test
wp.test.is_submited = False if last_test and reuseForm:
wp.test.save() last_test.is_midtesting = True
last_test.is_submited = False
last_test.save()
wp.test = last_test
wp.save()
wp.operation = None wp.operation = None
wp.update_by = request.user wp.update_by = request.user
@ -732,7 +742,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
raise exceptions.APIException('请选择物料产出') raise exceptions.APIException('请选择物料产出')
for i in omos: for i in omos:
if i.subproduction_progress.is_main: if i.subproduction_progress.is_main:
newstep, _ = WpmService.get_next_step( newstep, _, _ = WpmService.get_step_info(
i.subproduction_plan, step) i.subproduction_plan, step)
wpr = dict(material=i.material, step=newstep, wpr = dict(material=i.material, step=newstep,
act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='', act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='',
@ -753,7 +763,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
if oms_w.count!=1: if oms_w.count!=1:
raise exceptions.APIException('产出数量应为1') raise exceptions.APIException('产出数量应为1')
# 校验单片数量是否正确, 暂时未写 # 校验单片数量是否正确, 暂时未写
newstep, needTest = WpmService.get_next_step( newstep, needTest, reuseForm = WpmService.get_step_info(
oms_w.subproduction_plan, step) oms_w.subproduction_plan, step)
wproduct = WProduct() wproduct = WProduct()
wproduct.material = oms_w.material wproduct.material = oms_w.material
@ -761,14 +771,24 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
wproduct.subproduction_plan = oms_w.subproduction_plan wproduct.subproduction_plan = oms_w.subproduction_plan
if step == newstep: if step == newstep:
wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
if wproduct.test:# 如果有正在进行的工序中检验 last_test = wproduct.last_wp_test
wproduct.test.is_midtesting = False if last_test and reuseForm:
wproduct.test.is_submited = False last_test.is_midtesting = False
wproduct.test.save() last_test.is_submited = False
last_test.save()
wproduct.test = last_test
wproduct.save()
else: else:
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
if needTest: if needTest:
wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
last_test = wproduct.last_wp_test
if last_test and reuseForm:
last_test.is_midtesting = True
last_test.is_submited = False
last_test.save()
wproduct.test = last_test
wproduct.save()
# 更新子计划进度 # 更新子计划进度
WpmService.update_subproduction_progress_main( WpmService.update_subproduction_progress_main(