diff --git a/hb_client/src/views/mtm/productprocess.vue b/hb_client/src/views/mtm/productprocess.vue index ef23993..073a693 100644 --- a/hb_client/src/views/mtm/productprocess.vue +++ b/hb_client/src/views/mtm/productprocess.vue @@ -458,6 +458,12 @@ 不检验 + + + @@ -500,12 +506,6 @@ label-width="100px" label-position="right" > - - - 检验 - 不检验 - - + + + 检验 + 不检验 + + + + + + + + diff --git a/hb_server/apps/hrm/views.py b/hb_server/apps/hrm/views.py index c167784..303e25d 100644 --- a/hb_server/apps/hrm/views.py +++ b/hb_server/apps/hrm/views.py @@ -106,12 +106,12 @@ class ClockRecordViewSet(CreateModelMixin, ListModelMixin, GenericViewSet): def create(self, request, *args, **kwargs): now = timezone.now() now_local = timezone.localtime() - if 8<=now_local.hour<=17: + if 6<=now_local.hour<=17: base64_data = base64.urlsafe_b64decode(tran64( request.data.get('base64').replace(' ', '+'))) user, msg = HRMService.face_compare_from_base64(base64_data, request.data.get('tolerance', 0.36)) if user: - ins, created = ClockRecord.objects.get_or_create( + ClockRecord.objects.get_or_create( create_by = user, create_time__hour__range = [8,18], create_time__year=now_local.year, create_time__month=now_local.month, create_time__day=now_local.day, @@ -120,9 +120,9 @@ class ClockRecordViewSet(CreateModelMixin, ListModelMixin, GenericViewSet): 'create_by':user, 'create_time':now }) - if not created: - ins.update_time = now - ins.save() + # if not created: + # ins.update_time = now + # ins.save() # 设为在岗 Employee.objects.filter(user=user).update(is_atwork=True, last_check_time=now) return Response(UserSimpleSerializer(instance=user).data) diff --git a/hb_server/apps/mtm/migrations/0054_usedstep_reuse_form.py b/hb_server/apps/mtm/migrations/0054_usedstep_reuse_form.py new file mode 100644 index 0000000..1b803dc --- /dev/null +++ b/hb_server/apps/mtm/migrations/0054_usedstep_reuse_form.py @@ -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='复用上表'), + ), + ] diff --git a/hb_server/apps/mtm/models.py b/hb_server/apps/mtm/models.py index 4603bd5..80ab3b3 100644 --- a/hb_server/apps/mtm/models.py +++ b/hb_server/apps/mtm/models.py @@ -266,6 +266,7 @@ class UsedStep(CommonADModel): """ step = models.ForeignKey(Step, verbose_name='子工序', on_delete=models.CASCADE, related_name='usedstep') need_test = models.BooleanField('工序内检验', default=False) + reuse_form = models.BooleanField('复用上表', default=True) remark = models.TextField('生产备注', null=True, blank=True) subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE, related_name='usedstep_subproduction') diff --git a/hb_server/apps/mtm/serializers.py b/hb_server/apps/mtm/serializers.py index 43681b1..ec43e99 100644 --- a/hb_server/apps/mtm/serializers.py +++ b/hb_server/apps/mtm/serializers.py @@ -163,7 +163,7 @@ class UsedStepCreateSerializer(serializers.ModelSerializer): """ class Meta: model = UsedStep - fields = ['step', 'subproduction', 'remark', 'need_test'] + fields = ['step', 'subproduction', 'remark', 'need_test', 'reuse_form'] class UsedStepUpdateSerializer(serializers.ModelSerializer): """ @@ -171,7 +171,7 @@ class UsedStepUpdateSerializer(serializers.ModelSerializer): """ class Meta: model = UsedStep - fields = ['remark', 'need_test'] + fields = ['remark', 'need_test', 'reuse_form'] class UsedStepListSerializer(serializers.ModelSerializer): """ diff --git a/hb_server/apps/mtm/views.py b/hb_server/apps/mtm/views.py index c5932e5..7ab01d0 100644 --- a/hb_server/apps/mtm/views.py +++ b/hb_server/apps/mtm/views.py @@ -166,7 +166,7 @@ class UsedStepViewSet(OptimizationMixin, CreateModelMixin, DestroyModelMixin, Li 'put':'subproduction_update', 'delete':'subproduction_update'} queryset = UsedStep.objects.all() filterset_fields = ['subproduction', 'step'] - ordering = ['step__sort', '-step__create_time'] + ordering = ['step__number', 'step__create_time'] def get_serializer_class(self): if self.action =='create': diff --git a/hb_server/apps/wpm/models.py b/hb_server/apps/wpm/models.py index 085a20d..45c5fcb 100644 --- a/hb_server/apps/wpm/models.py +++ b/hb_server/apps/wpm/models.py @@ -136,6 +136,13 @@ class WProduct(CommonAModel): """ 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): """ diff --git a/hb_server/apps/wpm/services.py b/hb_server/apps/wpm/services.py index 384f036..1587c55 100644 --- a/hb_server/apps/wpm/services.py +++ b/hb_server/apps/wpm/services.py @@ -2,8 +2,9 @@ from django.utils import timezone from typing import List from django.db.models.expressions import F +from apps.mtm.serializers import UsedStepListSerializer 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.system.models import User from apps.wf.models import State, TicketFlow, Transition @@ -13,18 +14,42 @@ from rest_framework.exceptions import ParseError class WpmService(object): @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 - 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]), need_test - else: - return nowstep, need_test + used_steps = UsedStep.objects.filter(subproduction=subproduction_plan.subproduction).order_by('step__number') + if nowstep is None: + try: + nowstep = used_steps[0].step + except: + pass + for index, i in enumerate(used_steps): + 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 def get_subplans_queryset_from_wproducts(cls, wproducts:List): @@ -50,7 +75,6 @@ class WpmService(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 @@ -62,7 +86,6 @@ class WpmService(object): elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and \ test.is_midtesting 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 @@ -112,7 +135,7 @@ class WpmService(object): wproduct.update_by = user wproduct.update_time = timezone.now() - wproduct.test = test_i + wproduct.test = None wproduct.last_test_result = is_testok wproduct.save() # 添加日志 diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 99d619c..a72ae13 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -4,7 +4,7 @@ from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, \ 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.models import Material, RecordForm, RecordFormField, Step, SubprodctionMaterial, TechDoc, UsedStep from apps.mtm.serializers import RecordFormDetailSerializer, SubprodctionMaterialListSerializer, TechDocListSerializer from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress from apps.pm.serializers import SubProductionPlanListSerializer, SubProductionProgressSerializer @@ -36,7 +36,7 @@ from apps.wpm.services import WpmService from django.utils import timezone from rest_framework import status from django.db.models import Count, Q - +from rest_framework.exceptions import ParseError from utils.tools import ranstr @@ -185,14 +185,14 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): 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('该产品当前状态不可检验') + if wproduct.test: + raise exceptions.APIException('存在进行中检验') + savedict = dict( create_by=request.user, wproduct=wproduct, @@ -202,7 +202,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): 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: @@ -212,9 +212,11 @@ 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 + elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST: + _, need_test, _ = WpmService.get_step_info(wproduct.subproduction_plan, wproduct.pre_step) + 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) # 更新wproduct wproduct.test = tr @@ -698,24 +700,32 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd 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.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() + last_test = wp.last_wp_test + if last_test and reuseForm: + last_test.is_midtesting = False + last_test.is_submited = False + last_test.save() + wp.test = last_test + wp.save() else: wp.act_state = WProduct.WPR_ACT_STATE_DOWAIT - if needTest: + if needTest: #子工序若需要检验 + print(needTest, reuseForm) wp.act_state = WProduct.WPR_ACT_STATE_TOTEST - if wp.test:# 如果有正在进行的工序中检验 - wp.test.is_submited = False - wp.test.save() + last_test = wp.last_wp_test + if last_test and reuseForm: + last_test.is_midtesting = True + last_test.is_submited = False + last_test.save() + wp.test = last_test + wp.save() wp.operation = None wp.update_by = request.user @@ -732,7 +742,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd raise exceptions.APIException('请选择物料产出') for i in omos: if i.subproduction_progress.is_main: - newstep, _ = WpmService.get_next_step( + newstep, _, _ = WpmService.get_step_info( i.subproduction_plan, step) wpr = dict(material=i.material, step=newstep, act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='', @@ -753,7 +763,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd if oms_w.count!=1: raise exceptions.APIException('产出数量应为1') # 校验单片数量是否正确, 暂时未写 - newstep, needTest = WpmService.get_next_step( + newstep, needTest, reuseForm = WpmService.get_step_info( oms_w.subproduction_plan, step) wproduct = WProduct() wproduct.material = oms_w.material @@ -761,14 +771,24 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd 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() + last_test = wproduct.last_wp_test + if last_test and reuseForm: + last_test.is_midtesting = False + last_test.is_submited = False + last_test.save() + wproduct.test = last_test + wproduct.save() else: wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT if needTest: 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(