From 286a5306e37f83eeaece1a1037708a4ebfcecf1a Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 28 Feb 2025 15:31:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=89=B9=E6=AC=A1=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=81=9A=E5=85=BC=E5=AE=B9=E6=80=A7=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/qm/models.py | 2 +- apps/wpm/models.py | 20 +++++++++ apps/wpm/serializers.py | 2 +- apps/wpm/services.py | 95 +++++++++++++++++++++++------------------ apps/wpm/views.py | 43 ++++++------------- 5 files changed, 89 insertions(+), 73 deletions(-) diff --git a/apps/qm/models.py b/apps/qm/models.py index cdaf2701..b5557dfb 100644 --- a/apps/qm/models.py +++ b/apps/qm/models.py @@ -151,7 +151,7 @@ QC_TRACE_CHOICES = ( class Qct(CommonAModel): name = models.CharField(max_length=50, verbose_name="名称") number = models.CharField(max_length=20, verbose_name="编号") - tags = models.JSONField('检测类型', default=list, blank=True) + tags = models.JSONField('检测类型', default=list, blank=True) # process 和 inm testitems = models.ManyToManyField(TestItem, verbose_name="检测项", blank=True, through='qm.qcttestitem') defects = models.ManyToManyField(Defect, verbose_name="缺陷项", blank=True, through='qm.qctdefect') materials = models.ManyToManyField(Material, verbose_name="物料", blank=True, through='qm.qctmat') diff --git a/apps/wpm/models.py b/apps/wpm/models.py index 8cb6e55a..ee86b37a 100644 --- a/apps/wpm/models.py +++ b/apps/wpm/models.py @@ -382,6 +382,26 @@ class Mlogbw(BaseModel): on_delete=models.PROTECT, null=True, blank=True, related_name="mlogbw_ftest") note = models.TextField('备注', null=True, blank=True) + @classmethod + def cal_count_notok(mlogb: Mlog): + count = Mlogbw.objects.filter(mlogb=mlogb).count() + if mlogb.material_in: + mlogb.count_use = count + elif mlogb.material_out: + mlogb.count_real = count + count_notok = 0 + tqs = Mlogbw.objects.filter(mlogb=mlogb, ftest__is_ok=False).values("defect_main").annotate(xcount=Count('id')) + md_ids = [] + for t in tqs: + md, _ = MlogbDefect.objects.get_or_create(mlogb=mlogb, defect=t["defect_main"]) + md.count = t["xcount"] + md.save() + md_ids.append(md.id) + count_notok += t["xcount"] + MlogbDefect.objects.filter(mlogb=mlogb).exclude(id__in=md_ids).delete() + mlogb.count_notok = count_notok + mlogb.count_ok = count - mlogb.count_notok + mlogb.save() class Handover(CommonADModel): """ diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index e4660110..3a29fb50 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -724,7 +724,7 @@ class MlogbOutUpdateSerializer(CustomModelSerializer): return ins def update(self, instance, validated_data): - material_out:Material = validated_data["material_out"] + material_out:Material = instance.material_out mlogbdefect = validated_data.pop("mlogbdefect", []) with transaction.atomic(): ins:Mlogb = super().update(instance, validated_data) diff --git a/apps/wpm/services.py b/apps/wpm/services.py index 80b3254b..59edc78f 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -11,7 +11,7 @@ from apps.system.models import User from apps.pm.models import Mtask from apps.mtm.models import Mgroup, Shift, Material, Route, RoutePack, Team, Srule -from .models import SfLog, WMaterial, Mlog, Mlogb, Mlogbw, Handover, Handoverb, Handoverbw +from .models import SfLog, WMaterial, Mlog, Mlogb, Mlogbw, Handover, Handoverb, Handoverbw, MlogbDefect from apps.mtm.services_2 import cal_material_count from apps.wf.models import Ticket from apps.utils.thread import MyThread @@ -233,29 +233,35 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): process = mgroup.process into_wm_mgroup = process.into_wm_mgroup need_store_notok = process.store_notok - m_outs = Mlogb.objects.filter(mlog=mlog, material_out__isnull=False) + mlogb_out_qs = Mlogb.objects.filter(mlog=mlog, material_out__isnull=False) stored_notok = need_store_notok stored_mgroup = need_store_notok - if m_outs.exists(): - m_outs_list = [(mo.material_out, mo.batch if mo.batch else mlog.batch, mo.count_ok, mlog.count_real_eweight, None, mo) for mo in m_outs.all()] + if mlogb_out_qs.exists(): + m_outs_list = [(mo.material_out, mo.batch if mo.batch else mlog.batch, mo.count_ok, mlog.count_real_eweight, None, mo) for mo in mlogb_out_qs.all()] if need_store_notok: - for item in m_outs: - if item.material_out.tracking == Material.MA_TRACKING_SINGLE: - # 获取所有主要的不合格项 - bw_qs = Mlogbw.objects.filter(mlogb=item) - defectIds= Ftest.objects.filter(mlogbw_ftest__in=bw_qs).exclude(defect_main=None).values_list("defect_main__id", flat=True).distinct() - defects_map = {d.id: d for d in Defect.objects.filter(id__in=defectIds)} - # 过滤并统计相关数据 - filtered_bw_qs = bw_qs.filter( - ftest__defect_main__id__in=defects_map.keys() - ).values('ftest__defect_main__id').annotate(xcount=Count('id')) - # 整理结果 - for defect_data in filtered_bw_qs: - defect_id = defect_data['ftest__defect_main__id'] - xcount = defect_data['xcount'] - if xcount > 0: - defect = defects_map[defect_id] - m_outs_list.append((item.material_out, item.batch, xcount, 0, defect, item)) + for item in mlogb_out_qs: + if item.qct is not None: + if MlogbDefect.objects.filter(mlogb=item).exists(): + pass + else: + Mlogbw.cal_count_notok(item) + for itemx in MlogbDefect.objects.filter(mlogb=item): + m_outs_list.append((item.material_out, item.batch, itemx.count, 0, itemx.defect, item)) + # # 获取所有主要的不合格项/先暂时保留 + # bw_qs = Mlogbw.objects.filter(mlogb=item) + # defectIds= Ftest.objects.filter(mlogbw_ftest__in=bw_qs).exclude(defect_main=None).values_list("defect_main__id", flat=True).distinct() + # defects_map = {d.id: d for d in Defect.objects.filter(id__in=defectIds)} + # # 过滤并统计相关数据 + # filtered_bw_qs = bw_qs.filter( + # ftest__defect_main__id__in=defects_map.keys() + # ).values('ftest__defect_main__id').annotate(xcount=Count('id')) + # # 整理结果 + # for defect_data in filtered_bw_qs: + # defect_id = defect_data['ftest__defect_main__id'] + # xcount = defect_data['xcount'] + # if xcount > 0: + # defect = defects_map[defect_id] + # m_outs_list.append((item.material_out, item.batch, xcount, 0, defect, item)) else: for f in Mlogb._meta.fields: if 'count_n_' in f.name and getattr(item, f.name) > 0: @@ -358,29 +364,36 @@ def mlog_revert(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): if material_out or is_fix: # 产物退回 # 有多个产物的情况 # 需要考虑不合格品退回的情况 - m_outs = Mlogb.objects.filter(mlog=mlog, material_out__isnull=False) - if m_outs.exists(): + mlogb_out_qs = Mlogb.objects.filter(mlog=mlog, material_out__isnull=False) + if mlogb_out_qs.exists(): m_outs_list = [ (mo.material_out, mo.batch if mo.batch else mlog.batch, mo.count_ok, mlog.count_real_eweight, None, mo) - for mo in m_outs.all()] + for mo in mlogb_out_qs.all()] if stored_notok: - for item in m_outs: - if item.material_out.tracking == Material.MA_TRACKING_SINGLE: - # 获取所有主要的不合格项 - bw_qs = Mlogbw.objects.filter(mlogb=item) - defectIds= Ftest.objects.filter(mlogbw_ftest__in=bw_qs).exclude(defect_main=None).values_list("defect_main__id", flat=True).distinct() - defects_map = {d.id: d for d in Defect.objects.filter(id__in=defectIds)} - # 过滤并统计相关数据 - filtered_bw_qs = bw_qs.filter( - ftest__defect_main__id__in=defects_map.keys() - ).values('ftest__defect_main__id').annotate(xcount=Count('id')) - # 整理结果 - for defect_data in filtered_bw_qs: - defect_id = defect_data['ftest__defect_main__id'] - xcount = defect_data['xcount'] - if xcount > 0: - defect = defects_map[defect_id] - m_outs_list.append((item.material_out, item.batch, xcount, 0, defect, item)) + for item in mlogb_out_qs: + if item.qct is not None: + if MlogbDefect.objects.filter(mlogb=item).exists(): + pass + else: + Mlogbw.cal_count_notok(item) + for itemx in MlogbDefect.objects.filter(mlogb=item): + m_outs_list.append((item.material_out, item.batch, itemx.count, 0, itemx.defect, item)) + # if item.material_out.tracking == Material.MA_TRACKING_SINGLE: + # # 获取所有主要的不合格项 + # bw_qs = Mlogbw.objects.filter(mlogb=item) + # defectIds= Ftest.objects.filter(mlogbw_ftest__in=bw_qs).exclude(defect_main=None).values_list("defect_main__id", flat=True).distinct() + # defects_map = {d.id: d for d in Defect.objects.filter(id__in=defectIds)} + # # 过滤并统计相关数据 + # filtered_bw_qs = bw_qs.filter( + # ftest__defect_main__id__in=defects_map.keys() + # ).values('ftest__defect_main__id').annotate(xcount=Count('id')) + # # 整理结果 + # for defect_data in filtered_bw_qs: + # defect_id = defect_data['ftest__defect_main__id'] + # xcount = defect_data['xcount'] + # if xcount > 0: + # defect = defects_map[defect_id] + # m_outs_list.append((item.material_out, item.batch, xcount, 0, defect, item)) else: for f in Mlogb._meta.fields: if 'count_n_' in f.name and getattr(item, f.name) > 0: diff --git a/apps/wpm/views.py b/apps/wpm/views.py index f8da0bab..7c76c189 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -592,13 +592,17 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust d_count_real = mlogbin.count_use d_count_ok = mlogbin.count_use # 找寻质检表 - if material_out.tracking == Material.MA_TRACKING_SINGLE: - if is_fix and mgroup.process.type == Process.PRO_PROD: - # 如果是生产返修,则忽略质检 - pass - else: - qctmat = QctMat.objects.filter(material=material_out, qct__is_deleted=False).order_by("-create_time").first() - mlogbout.qct = qctmat.qct if qctmat else None + if is_fix and mgroup.process.type == Process.PRO_PROD: + # 如果是生产返修,则忽略质检 + pass + elif mlogbout.qct: + try: + qctmat = QctMat.objects.get(material=material_out, qct__is_deleted=False, qct__tags__contains="process").order_by("-create_time") + except QctMat.DoesNotExist: + qctmat = None + except QctMat.MultipleObjectsReturned: + raise ParseError("存在多个质检表,请手动选择") + mlogbout.qct = qctmat.qct if qctmat else None mlogbout.count_real = d_count_real mlogbout.count_ok = d_count_ok mlogbout.save() @@ -672,27 +676,6 @@ class MlogbwViewSet(CustomModelViewSet): raise ParseError('请指定所属消耗/产出明细') return super().filter_queryset(queryset) - def cal_mlogb_count(self, mlogb): - count = Mlogbw.objects.filter(mlogb=mlogb).count() - # 此处先不管检验问题 - if mlogb.material_in: - mlogb.count_use = count - elif mlogb.material_out: - mlogb.count_real = count - count_notok = 0 - tqs = Mlogbw.objects.filter(mlogb=mlogb, ftest__is_ok=False).values("defect_main").annotate(xcount=Count('id')) - md_ids = [] - for t in tqs: - md, _ = MlogbDefect.objects.get_or_create(mlogb=mlogb, defect=t["defect_main"]) - md.count = t["xcount"] - md.save() - md_ids.append(md.id) - count_notok += t["xcount"] - MlogbDefect.objects.filter(mlogb=mlogb).exclude(id__in=md_ids).delete() - mlogb.count_notok = count_notok - mlogb.count_ok = count - mlogb.count_notok - mlogb.save() - @transaction.atomic def perform_create(self, serializer): ins:Mlogbw = serializer.save() @@ -715,7 +698,7 @@ class MlogbwViewSet(CustomModelViewSet): @transaction.atomic def perform_update(self, serializer): mlogbw = serializer.save() - self.cal_mlogb_count(mlogbw.mlogb) + Mlogbw.cal_count_notok(mlogbw.mlogb) @transaction.atomic def perform_destroy(self, instance:Mlogbw): @@ -736,4 +719,4 @@ class MlogbwViewSet(CustomModelViewSet): mbws = Mlogbw.objects.filter(Q(wpr=instance.wpr)|Q(number__contains=instance.number), mlogb=mlogb_to) Ftest.objects.filter(id__in=mbws.values_list('ftest__id', flat=True)).delete() mbws.delete() - self.cal_mlogb_count(mlogb_to) + Mlogbw.cal_count_notok(mlogb)