From 07680704ec87e21e52ad6742953abc6297796626 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 15 Jul 2024 16:57:09 +0800 Subject: [PATCH] feat: cal_mtask_progress_from_mlog --- apps/pm/services.py | 12 ++-- apps/wpm/models.py | 4 ++ apps/wpm/serializers.py | 2 + apps/wpm/services.py | 124 ++++++++++++++++++++++++++++++++-------- apps/wpm/views.py | 10 +--- 5 files changed, 112 insertions(+), 40 deletions(-) diff --git a/apps/pm/services.py b/apps/pm/services.py index 392e716f..a049102c 100644 --- a/apps/pm/services.py +++ b/apps/pm/services.py @@ -305,21 +305,17 @@ class PmService: @classmethod def mtask_submit(cls, mtask: Mtask, user: User): """ - 锁定生产任务 + 生产任务提交 """ from apps.wpm.models import Mlog - from apps.wpm.services import mlog_submit, update_mtask now = timezone.now() if mtask.state == Mtask.MTASK_ASSGINED: - mlogs = Mlog.objects.filter(mtask=mtask) - # if ignore_nologs is False and mlogs.count() == 0: - # raise ParseError(f'{mtask.mgroup.name}_未填写日志') - for mlog in mlogs: - mlog_submit(mlog, user, now) + mlogs = Mlog.objects.filter(mtask=mtask)|Mlog.objects.filter(b_mlog__mtask=mtask) + if mlogs.filter(submit_time__isnull=True).exists(): + raise ParseError('存在未提交的日志') mtask.state = Mtask.MTASK_SUBMIT mtask.submit_time = now mtask.submit_user = user mtask.save() - update_mtask(mtask) else: raise ParseError('该任务状态不可提交') diff --git a/apps/wpm/models.py b/apps/wpm/models.py index 1ecf948b..5508da03 100644 --- a/apps/wpm/models.py +++ b/apps/wpm/models.py @@ -103,6 +103,9 @@ class Mlog(CommonADModel): 生产日志 """ # 变成父级的字段 + MLOG_ONETIME = 10 + MLOG_STEP = 20 + fill_way = models.PositiveSmallIntegerField("填写方式", default=10, help_text='10:一次填写;20:分步填写') work_start_time = models.DateTimeField('生产开始时间', null=True, blank=True) work_end_time = models.DateTimeField('生产结束时间', null=True, blank=True) hour_work = models.FloatField('预计工时', null=True, blank=True) @@ -218,6 +221,7 @@ class Mlogb(BaseModel): count_ok = models.PositiveIntegerField('合格数量', default=0) count_notok = models.PositiveIntegerField('不合格数', default=0) + # 添加不合格字段后需要更改cal_mlog_count_from_mlogb count_n_hs = models.PositiveIntegerField('划伤', default=0) count_n_qp = models.PositiveIntegerField('气泡', default=0) count_n_swen = models.PositiveIntegerField('水纹', default=0) diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index f81f33ef..5fe72cd3 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -304,6 +304,7 @@ class MlogSerializer(CustomModelSerializer): return instance def validate(self, attrs): + attrs['fill_way'] = Mlog.MLOG_ONETIME mtask = attrs.get('mtask', None) count_notok = 0 for i in attrs: @@ -343,6 +344,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 return attrs class MlogChangeSerializer(CustomModelSerializer): diff --git a/apps/wpm/services.py b/apps/wpm/services.py index 97046d6d..332deff7 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -186,7 +186,6 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): belong_dept = mgroup.belong_dept material_out = mlog.material_out material_in = mlog.material_in - if material_in: # 需要进行车间库存管理 m_ins = Mlogb.objects.filter(mlog=mlog, material_in__isnull=False) if m_ins.exists(): @@ -317,18 +316,63 @@ def mlog_revert(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): mlog.submit_user = None mlog.save() + # mtask变更状态 + update_mtaskIds = [] + if mlog.mtask: + update_mtaskIds.append(mlog.mtask.id) + list_m = Mlogb.objects.filter(mlog=mlog).values_list('mtask__id', flat=True).distinct() + update_mtaskIds += list(list_m) + if update_mtaskIds: + Mtask.objects.filter(id__in=update_mtaskIds, state=Mtask.MTASK_SUBMIT).update(status=Mtask.MTASK_ASSGINED) -def cal_mtask_progress(mtask: Mtask): - """ - 计算任务进度 - """ - +def cal_mlog_count_from_mlogb(mlog: Mlog): + """ + 通过mlogb计算mlog count 合计 + """ + if mlog.fill_way == Mlog.MLOG_STEP: + a_dict = { + "total_count_use": Sum('count_use'), + "total_count_break": Sum('count_break'), + "total_count_break_t": Sum('count_break_t'), + "total_count_real": Sum('count_real'), + "total_count_ok": Sum('count_ok'), + "total_count_notok": Sum('count_notok'), + } + f_names = [f.name for f in Mlogb._meta.fields if 'count_n' in f.name] + for f in f_names: + a_dict[f'total_{f}'] = Sum(f) + mlogb_summary = Mlogb.objects.filter(mlog=mlog).aggregate( + **a_dict + ) + # 更新Mlog对象的相应字段 + mlog.count_use = mlogb_summary['total_count_use'] or 0 + mlog.count_break = mlogb_summary['total_count_break'] or 0 + mlog.count_break_t = mlogb_summary['total_count_break_t'] or 0 + mlog.count_real = mlogb_summary['total_count_real'] or 0 + mlog.count_ok = mlogb_summary['total_count_ok'] or 0 + mlog.count_notok = mlogb_summary['total_count_notok'] or 0 + for f in f_names: + setattr(mlog, f, mlogb_summary[f'total_{f}'] or 0) + # 保存更新后的Mlog对象 + mlog.save() 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: + cal_mlog_count_from_mlogb(mlog) + m_outs_qs = Mlogb.objects.filter(mlog=mlog, material_out__isnull=False) + caled_mtask = [] + for item in m_outs_qs.all(): + mtask = item.mtask + if mtask in caled_mtask: + continue + update_mtask(mtask, fill_way=Mlog.MLOG_STEP) + caled_mtask.append(mtask) def cal_material_count_from_mlog(mlog: Mlog): """ @@ -348,26 +392,58 @@ def cal_material_count_from_mlog(mlog: Mlog): cal_material_count(matid_list) -def update_mtask(mtask: Mtask): +def update_mtask(mtask: Mtask, fill_way: int = 10): from apps.pm.models import Utask - 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 - mtask.count_ok = res['sum_count_ok'] if res['sum_count_ok'] else 0 - mtask.count_notok = res['sum_count_notok'] if res['sum_count_notok'] else 0 - mtask.save() - utask = mtask.utask - if utask and mtask.is_count_utask: - res2 = Mtask.objects.filter(utask=utask, mgroup=mtask.mgroup).aggregate(sum_count_real=Sum( + if fill_way == Mlog.MLOG_ONETIME: + 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')) - utask.count_real = res2['sum_count_real'] if res2['sum_count_real'] else 0 - utask.count_ok = res2['sum_count_ok'] if res2['sum_count_ok'] else 0 - utask.count_notok = res2['sum_count_notok'] if res2['sum_count_notok'] else 0 - if utask.count_ok > 0 and utask.state == Utask.UTASK_ASSGINED: - utask.state = Utask.UTASK_WORKING - if Mtask.objects.filter(utask=utask).exclude(state=Mtask.MTASK_SUBMIT).count() == 0: - utask.state = Utask.UTASK_SUBMIT - utask.save() + mtask.count_real = res['sum_count_real'] if res['sum_count_real'] else 0 + mtask.count_ok = res['sum_count_ok'] if res['sum_count_ok'] else 0 + mtask.count_notok = res['sum_count_notok'] if res['sum_count_notok'] else 0 + mtask.save() + utask = mtask.utask + if utask and mtask.is_count_utask: + res2 = Mtask.objects.filter(utask=utask, mgroup=mtask.mgroup).aggregate(sum_count_real=Sum( + 'count_real'), sum_count_ok=Sum('count_ok'), sum_count_notok=Sum('count_notok')) + utask.count_real = res2['sum_count_real'] if res2['sum_count_real'] else 0 + utask.count_ok = res2['sum_count_ok'] if res2['sum_count_ok'] else 0 + utask.count_notok = res2['sum_count_notok'] if res2['sum_count_notok'] else 0 + if utask.count_ok > 0 and utask.state == Utask.UTASK_ASSGINED: + utask.state = Utask.UTASK_WORKING + 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: + # 已经提交的日志 + m_outs_qs_mtask = Mlogb.objects.filter(mtask=mtask, material_out__isnull=False, mlog__submit_time__isnull=False) + res = m_outs_qs_mtask.aggregate( + sum_count_real=Sum('count_real', default=0), + sum_count_ok=Sum('count_ok', default=0), + sum_count_notok=Sum('count_notok', default=0) + ) + mtask.count_real = res['sum_count_real'] or 0 + mtask.count_ok = res['sum_count_ok'] or 0 + mtask.count_notok = res['sum_count_notok'] or 0 + mtask.save() + utask = mtask.utask + is_main_mgroup = False + if utask: + if utask.state == Utask.UTASK_ASSGINED: + utask.state = Utask.UTASK_WORKING + utask.save() + if mtask.is_count_utask: + is_main_mgroup = True + elif mtask.material_out == utask.material: + is_main_mgroup = True + if is_main_mgroup: + res2 = Mtask.objects.filter(utask=utask, mgroup=mtask.mgroup).aggregate(sum_count_real=Sum( + 'count_real'), sum_count_ok=Sum('count_ok'), sum_count_notok=Sum('count_notok')) + utask.count_real = res2['sum_count_real'] if res2['sum_count_real'] else 0 + utask.count_ok = res2['sum_count_ok'] if res2['sum_count_ok'] else 0 + utask.count_notok = res2['sum_count_notok'] if res2['sum_count_notok'] else 0 + if Mtask.objects.filter(utask=utask).exclude(state=Mtask.MTASK_SUBMIT).count() == 0: + utask.state = Utask.UTASK_SUBMIT + utask.save() def handover_submit(handover: Handover, user: User, now: Union[datetime.datetime, None]): diff --git a/apps/wpm/views.py b/apps/wpm/views.py index 83751182..12582eef 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -207,11 +207,10 @@ class MlogViewSet(CustomModelViewSet): raise ParseError('该任务已停止!') with transaction.atomic(): mlog_submit(ins, self.request.user, now) - if ins.mtask: - update_mtask(ins.mtask) vdata_new = MlogSerializer(ins).data create_auditlog('submit', ins, vdata_new, vdata_old, now, self.request.user) + MyThread(cal_mtask_progress_from_mlog,args=(ins,)).start() MyThread(cal_material_count_from_mlog,args=(ins,)).start() return Response(vdata_new) @@ -230,14 +229,9 @@ class MlogViewSet(CustomModelViewSet): now = timezone.now() with transaction.atomic(): mlog_revert(ins, user, now) - if ins.mtask: - mtask = ins.mtask - if mtask.state == Mtask.MTASK_SUBMIT: - mtask.state = Mtask.MTASK_ASSGINED - mtask.save() - update_mtask(ins.mtask) create_auditlog('revert', ins, {}, {}, now, user, request.data.get('change_reason', '')) + MyThread(cal_mtask_progress_from_mlog,args=(ins,)).start() MyThread(cal_material_count_from_mlog,args=(ins,)).start() return Response(MlogSerializer(instance=ins).data)