From 6e7e6c584e944b2887979ed50448f39978a61d09 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 4 Sep 2024 15:25:14 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=80=E4=BA=8C=E7=BA=A7=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E5=BD=95=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wpm/models.py | 13 +++++--- apps/wpm/serializers.py | 68 ++++++++++++++++++++++++++++++++++++----- apps/wpm/services.py | 30 +++++++++++++----- apps/wpm/views.py | 15 ++------- 4 files changed, 93 insertions(+), 33 deletions(-) diff --git a/apps/wpm/models.py b/apps/wpm/models.py index ea45c53f..18cdf269 100644 --- a/apps/wpm/models.py +++ b/apps/wpm/models.py @@ -1,7 +1,7 @@ from django.db import models from apps.utils.models import CommonADModel, CommonBDModel, BaseModel from apps.mtm.models import Mgroup, Team, Shift, Material, Route -from apps.pm.models import Mtask +from apps.pm.models import Mtask, Mtaskb from apps.system.models import User from django.utils.timezone import localtime from apps.em.models import Equipment @@ -118,12 +118,14 @@ class Mlog(CommonADModel): 生产日志 """ # 变成父级的字段 - MLOG_ONETIME = 10 - MLOG_STEP = 20 + MLOG_2 = 10 + MLOG_23 = 20 + MLOG_12 = 30 MTYPE_SELF = 10 MTYPE_OUT = 20 fmlog = models.ForeignKey(Fmlog, verbose_name='关联生产日志', on_delete=models.SET_NULL, null=True, blank=True, related_name='mlog_fmlog') - fill_way = models.PositiveSmallIntegerField("填写方式", default=10, help_text='10:一次填写;20:分步填写') + mtaskb = models.ForeignKey(Mtaskb, verbose_name='关联个人任务', on_delete=models.CASCADE, related_name='mlog_mtaskb', null=True, blank=True) + fill_way = models.PositiveSmallIntegerField("填写方式", default=10, help_text='10:仅二级;20:二三级;30:一二级') mtype = models.PositiveSmallIntegerField('生产类型', default=10, help_text='10:自生产;20:外协生产', choices=((10, '自生产'), (20, '外协生产'))) supplier = models.ForeignKey(Supplier, verbose_name='外协供应商', on_delete=models.SET_NULL, null=True, blank=True) work_start_time = models.DateTimeField('生产开始时间', null=True, blank=True) @@ -223,6 +225,9 @@ class Mlog(CommonADModel): ticket = models.ForeignKey('wf.ticket', verbose_name='关联工单', on_delete=models.SET_NULL, related_name='mlog_ticket', null=True, blank=True, db_constraint=False) test_file = models.TextField('检验文件', null=True, blank=True) + test_user = models.ForeignKey( + User, verbose_name='检验人', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_test_user') + test_time = models.DateTimeField('检验时间', null=True, blank=True) @property def mlogb(self): diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index cab75060..b36bb633 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -7,9 +7,9 @@ from datetime import datetime from .models import SfLog, StLog, SfLogExp, WMaterial, Mlog, Handover, Mlogb, AttLog, OtherLog, Fmlog from apps.system.models import Dept, User from apps.system.serializers import UserSimpleSerializer -from apps.pm.models import Mtask +from apps.pm.models import Mtask, Mtaskb from apps.wpm.tasks import cal_enstat_when_pcoal_heat_change, cal_enstat_when_team_change, cal_exp_duration_sec -from apps.wpm.services import get_sflog, find_material_can_change +from apps.wpm.services import get_sflog, find_material_can_change, generate_new_batch from apps.mtm.models import Mgroup, TeamMember, Shift, Material, Route from apps.mtm.serializers import MaterialSimpleSerializer from django.db import transaction @@ -275,13 +275,20 @@ class MlogSerializer(CustomModelSerializer): } def create(self, validated_data): - mtask: Mtask = validated_data.get('mtask', None) + mtaskb: Mtaskb = validated_data.get('mtaskb', None) + if mtaskb: + mtask = mtaskb.mtask + validated_data['mtask'] = mtask + validated_data['handle_user'] = mtaskb.handle_user + else: + mtask: Mtask = validated_data.get('mtask', None) if mtask: validated_data['mgroup'] = mtask.mgroup validated_data['material_in'] = mtask.material_in material_out = mtask.material_out validated_data['material_out'] = material_out - validated_data['handle_date'] = mtask.end_date + if mtask.start_date == mtask.end_date: + validated_data['handle_date'] = mtask.end_date else: mgroup = validated_data['mgroup'] material_out = validated_data['material_out'] @@ -290,6 +297,19 @@ class MlogSerializer(CustomModelSerializer): with transaction.atomic(): mlogb = validated_data.pop('mlogb', []) instance: Mlog = super().create(validated_data) + # 自动生成mlogb + batch_in = instance.batch + if instance.wm_in: + batch_in = instance.wm_in.batch + add_dict = { + 'mlog': instance, 'batch': batch_in, 'wm_in': instance.wm_in, + 'mtask': instance.mtask, 'material_in': instance.material_in, + 'count_use': instance.count_use, 'count_break': instance.count_break, + 'count_n_jgqbl': instance.count_n_jgqbl + } + Mlogb.objects.create(**add_dict) + + # mlogb只用于组合件输出物填写 brotherId_should_list = material_out.brothers if brotherId_should_list: if mlogb: @@ -299,9 +319,29 @@ class MlogSerializer(CustomModelSerializer): mlog=instance, batch=instance.batch, mtask=instance.mtask, material_out=item['material_out'], count_ok=item['count_ok']) else: raise ValidationError('缺少产出物信息') + else: + # 生成产出物 + batch_out = validated_data.get('batch', None) + if batch_out: + pass + else: + batch_out = generate_new_batch(batch_in, instance) + + add_dict_2 = { + 'mlog': instance, 'batch': batch_out, + 'mtask': instance.mtask, 'material_out': instance.material_out, + 'count_ok': instance.count_ok, 'count_notok': instance.count_notok, + 'count_break_t': instance.count_break_t + } + for f in Mlogb._meta.fields: + if 'count_n_' in f.name and f.name != 'count_n_jgqbl': + add_dict_2[f.name] = getattr(instance, f.name) + Mlogb.objects.create(**add_dict_2) return instance def update(self, instance, validated_data): + if instance.fill_way != Mlog.MLOG_2: + raise ValidationError('不支持编辑!') validated_data.pop('mtask', None) validated_data.pop('mgroup', None) if instance.mtask: @@ -318,8 +358,16 @@ class MlogSerializer(CustomModelSerializer): return instance def validate(self, attrs): - attrs['fill_way'] = Mlog.MLOG_ONETIME + attrs['fill_way'] = Mlog.MLOG_2 attrs['mtype'] = Mlog.MTYPE_SELF # 默认为自生产 + fmlog = attrs.get('fmlog', None) + mtaskb = attrs.get('mtaskb', None) + if fmlog: + attrs['route'] = fmlog.route + attrs['mgroup'] = fmlog.mgroup + attrs['mtask'] = fmlog.mtask + if mtaskb and mtaskb.mtask != fmlog.mtask: + raise ValidationError('子任务不一致') mtask = attrs.get('mtask', None) count_notok = 0 for i in attrs: @@ -361,7 +409,7 @@ class MlogInitSerializer(CustomModelSerializer): attrs['hour_work'] = route.hour_work attrs['material_in'] = route.material_in attrs['material_out'] = route.material_out - attrs['fill_way'] = Mlog.MLOG_STEP + attrs['fill_way'] = Mlog.MLOG_23 if mtype == Mlog.MTYPE_OUT: supplier = attrs.get('supplier', None) if not supplier: @@ -371,7 +419,7 @@ class MlogInitSerializer(CustomModelSerializer): class MlogChangeSerializer(CustomModelSerializer): class Meta: model = Mlog - fields = ['id', 'work_end_time', 'handle_user', 'note', 'oinfo_json', 'test_file'] + fields = ['id', 'work_end_time', 'handle_user', 'note', 'oinfo_json', 'test_file', 'test_user', 'test_time'] def validate(self, attrs): if attrs.get('work_end_time', None): @@ -620,4 +668,8 @@ class FmlogSerializer(CustomModelSerializer): class FmlogUpdateSerializer(CustomModelSerializer): class Meta: model = Fmlog - fields = ['id', 'note'] \ No newline at end of file + fields = ['id', 'note'] + + +class MlogTCreateSerializer(CustomModelSerializer): + pass \ No newline at end of file diff --git a/apps/wpm/services.py b/apps/wpm/services.py index 5f56828a..efc6e5a6 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -18,6 +18,20 @@ from apps.wf.models import Ticket from django.db import transaction from apps.utils.thread import MyThread +def generate_new_batch(old_batch: str, mlog: Mlog): + new_batch = old_batch + supplier = mlog.supplier + process = mlog.mgroup.process + if mlog.mtype == Mlog.MTYPE_OUT: + supplier_number = supplier.number if supplier else '' + if supplier_number: + new_batch = f'{new_batch}-{supplier_number}' + elif process.batch_append_equip: + number = mlog.equipment.number if mlog.equipment else '' + if number: + new_batch = f'{new_batch}-{number}' + return new_batch + def find_material_can_change(material: Material, mgroup_to: Mgroup): """ 找到可转变为的物料(返工交接用) @@ -424,7 +438,7 @@ def cal_mlog_count_from_mlogb(mlog: Mlog): """ 通过mlogb计算mlog count 合计 """ - if mlog.fill_way == Mlog.MLOG_STEP: + if mlog.fill_way == Mlog.MLOG_23: a_dict = { "total_count_use": Sum('count_use'), "total_count_break": Sum('count_break'), @@ -455,9 +469,9 @@ def cal_mtask_progress_from_mlog(mlog: Mlog): """ 更新mlog关联的任务进度(可线程中执行) """ - if mlog.fill_way == Mlog.MLOG_ONETIME and mlog.mtask: - update_mtask(mlog.mtask, fill_way=Mlog.MLOG_ONETIME) - elif mlog.fill_way == Mlog.MLOG_STEP: + if mlog.fill_way in [Mlog.MLOG_2, Mlog.MLOG_12] and mlog.mtask: + update_mtask(mlog.mtask, fill_way=mlog.fill_way) + elif mlog.fill_way == Mlog.MLOG_23: cal_mlog_count_from_mlogb(mlog) m_outs_qs = Mlogb.objects.filter(mlog=mlog, material_out__isnull=False) caled_mtask = [] @@ -465,7 +479,7 @@ def cal_mtask_progress_from_mlog(mlog: Mlog): mtask = item.mtask if mtask in caled_mtask: continue - update_mtask(mtask, fill_way=Mlog.MLOG_STEP) + update_mtask(mtask, fill_way=mlog.fill_way) caled_mtask.append(mtask) def cal_material_count_from_mlog(mlog: Mlog): @@ -488,7 +502,7 @@ def cal_material_count_from_mlog(mlog: Mlog): def update_mtask(mtask: Mtask, fill_way: int = 10): from apps.pm.models import Utask - if fill_way == Mlog.MLOG_ONETIME: + if fill_way == Mlog.MLOG_2: res = Mlog.objects.filter(mtask=mtask).exclude(submit_time=None).aggregate(sum_count_real=Sum( 'count_real'), sum_count_ok=Sum('count_ok'), sum_count_notok=Sum('count_notok')) mtask.count_real = res['sum_count_real'] if res['sum_count_real'] else 0 @@ -507,7 +521,7 @@ def update_mtask(mtask: Mtask, fill_way: int = 10): if Mtask.objects.filter(utask=utask).exclude(state=Mtask.MTASK_SUBMIT).count() == 0: utask.state = Utask.UTASK_SUBMIT utask.save() - elif fill_way == Mlog.MLOG_STEP: + elif fill_way in [Mlog.MLOG_23, Mlog.MLOG_12]: # 已经提交的日志 m_outs_qs_mtask = Mlogb.objects.filter(mtask=mtask, material_out__isnull=False, mlog__submit_time__isnull=False) res = m_outs_qs_mtask.aggregate( @@ -640,7 +654,7 @@ def mlog_submit_validate(ins: Mlog): raise ParseError('该日志已提交!') if ins.mtask and ins.mtask.state == Mtask.MTASK_STOP: raise ParseError('该任务已停止!') - if ins.fill_way == Mlog.MLOG_STEP: + if ins.fill_way == Mlog.MLOG_23: if not Mlogb.objects.filter(material_out__isnull=False, mlog=ins).exists(): raise ParseError('该日志未指定产出!') if not Mlogb.objects.filter(material_in__isnull=False, mlog=ins).exists(): diff --git a/apps/wpm/views.py b/apps/wpm/views.py index 525951b2..e0ac32d5 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -26,7 +26,7 @@ from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer, from .services import mlog_submit, update_mtask, handover_submit, mlog_revert, cal_material_count_from_mlog, cal_mtask_progress_from_mlog from apps.utils.thread import MyThread from apps.monitor.services import create_auditlog, delete_auditlog -from apps.wpm.services import mlog_submit_validate +from apps.wpm.services import mlog_submit_validate, generate_new_batch # Create your views here. @@ -470,8 +470,6 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust def perform_create(self, serializer): ins: Mlogb = serializer.save() mlog: Mlog = ins.mlog - process: Process = mlog.mgroup.process - supplier = mlog.supplier # 创建输出 if ins.mtask and ins.material_in: material_out = mlog.material_out @@ -482,16 +480,7 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust "mlog": ins.mlog, "material_out": ins.mlog.material_out } - new_batch = ins.batch - if mlog.mtype == Mlog.MTYPE_OUT: - supplier_number = supplier.number if supplier else '' - if supplier_number: - new_batch = f'{new_batch}-{supplier_number}' - elif process.batch_append_equip: - number = mlog.equipment.number if mlog.equipment else '' - if number: - new_batch = f'{new_batch}-{number}' - m_dict['batch'] = new_batch + m_dict['batch'] = generate_new_batch(ins.batch, mlog) Mlogb.objects.get_or_create(**m_dict, defaults=m_dict)