From 5b0063e42da30529bc300f53f8452e8bf6440e04 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 9 Jan 2025 14:14:32 +0800 Subject: [PATCH 1/5] fix: mlogbin delete bug --- apps/wpm/views.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/wpm/views.py b/apps/wpm/views.py index b7161fe5..aefc6f0e 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -478,16 +478,22 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust ins: Mlogb = instance if ins.mlog.submit_time is not None: raise ParseError('生产日志已提交不可编辑') + qs = Mlogb.objects.none() + if ins.mlogb_to: + qs = qs|Mlogb.objects.filter(id=ins.mlogb_to.id) if ins.mtask: query_dict = {"material_out__isnull": False, "mlog": ins.mlog, "mtask": ins.mtask} route = ins.mtask.route if route.batch_bind: query_dict["batch__contains"] = ins.batch - qs = Mlogb.objects.filter(**query_dict) + qs = Mlogb.objects.filter(**query_dict) | qs # 需要删除子集ftest记录 - ftestIds = Mlogbw.objects.filter(mlogb__in=qs).values_list("ftest__id", flat=True) - Mlogb.objects.filter(**query_dict).delete() + mlogbw_qs = Mlogbw.objects.filter(mlogb__in=qs) + # 需用list 不然qs.delete 这个qs会变空 + ftestIds = list(mlogbw_qs.values_list("ftest__id", flat=True)) + qs.delete() Ftest.objects.filter(id__in=ftestIds).delete() + instance.delete() @transaction.atomic From 37cce1664b16d53e67f3eb330ae5df57d2184fa9 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 9 Jan 2025 15:28:31 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20mlog=20submit=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E8=B4=A8=E6=A3=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/qm/migrations/0035_auto_20250109_1526.py | 24 +++++++++++ apps/qm/models.py | 3 +- apps/qm/serializers.py | 13 +++++- .../wpm/migrations/0084_alter_mlogbw_ftest.py | 20 +++++++++ apps/wpm/services.py | 42 +++++++++++++------ apps/wpmw/models.py | 8 +++- 6 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 apps/qm/migrations/0035_auto_20250109_1526.py create mode 100644 apps/wpm/migrations/0084_alter_mlogbw_ftest.py diff --git a/apps/qm/migrations/0035_auto_20250109_1526.py b/apps/qm/migrations/0035_auto_20250109_1526.py new file mode 100644 index 00000000..dd587e34 --- /dev/null +++ b/apps/qm/migrations/0035_auto_20250109_1526.py @@ -0,0 +1,24 @@ +# Generated by Django 3.2.12 on 2025-01-09 07:26 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('qm', '0034_auto_20250108_1016'), + ] + + operations = [ + migrations.AddField( + model_name='ftestdefect', + name='is_main', + field=models.BooleanField(default=False, verbose_name='是否主要缺陷'), + ), + migrations.AlterField( + model_name='ftestdefect', + name='ftest', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='defects_ftest', to='qm.ftest', verbose_name='关联检验'), + ), + ] diff --git a/apps/qm/models.py b/apps/qm/models.py index 32110ff3..dbb0120e 100644 --- a/apps/qm/models.py +++ b/apps/qm/models.py @@ -307,10 +307,11 @@ class FtestDefect(BaseModel): 缺陷明细 """ ftest = models.ForeignKey( - Ftest, verbose_name='关联检验', on_delete=models.CASCADE) + Ftest, verbose_name='关联检验', on_delete=models.CASCADE, related_name="defects_ftest") test_user = models.ForeignKey(User, verbose_name='操作人', on_delete=models.CASCADE, null=True, blank=True) defect = models.ForeignKey(Defect, verbose_name='缺陷', on_delete=models.CASCADE) has = models.BooleanField('是否发现', default=False) + is_main = models.BooleanField('是否主要缺陷', default=False) class Ptest(CommonAModel): diff --git a/apps/qm/serializers.py b/apps/qm/serializers.py index 5cd71303..7cffa00a 100644 --- a/apps/qm/serializers.py +++ b/apps/qm/serializers.py @@ -249,7 +249,7 @@ class FtestDefectSerializer(CustomModelSerializer): class Meta: model = FtestDefect fields = '__all__' - read_only_fields = EXCLUDE_FIELDS_BASE + ['ftest'] + read_only_fields = EXCLUDE_FIELDS_BASE + ['ftest', 'is_main'] class FtestItemProcessSerializer(CustomModelSerializer): @@ -285,10 +285,13 @@ class FtestProcessSerializer(CustomModelSerializer): for item in ftestitems: FtestItem.objects.create(ftest=instance, **item) is_ok = True + has_is_main = False for item2 in ftestdefects: defect:Defect = item2["defect"] if defect.okcate in [Defect.DEFECT_NOTOK] and item2["has"]: is_ok = False + if not has_is_main: + item2["is_main"] = True FtestDefect.objects.create(ftest=instance, **item2) instance.is_ok = is_ok instance.save() @@ -308,16 +311,22 @@ class FtestProcessSerializer(CustomModelSerializer): setattr(ins, k, v) ins.save() is_ok = True + has_is_main = False for item2 in ftestdefects: try: - ins = FtestDefect.objects.get(ftest=instance, defect=item2["defect"]) + ins:FtestDefect = FtestDefect.objects.get(ftest=instance, defect=item2["defect"]) except FtestDefect.DoesNotExist: raise ParseError("新的缺陷项!") for k, v in item2.items(): setattr(ins, k, v) ins.save() + if ins.is_main: + has_is_main = True if ins.has and ins.defect.okcate in [Defect.DEFECT_NOTOK]: is_ok = False + if not has_is_main: + ins.is_main = True + ins.save() instance.is_ok = is_ok instance.save() return instance \ No newline at end of file diff --git a/apps/wpm/migrations/0084_alter_mlogbw_ftest.py b/apps/wpm/migrations/0084_alter_mlogbw_ftest.py new file mode 100644 index 00000000..90415fb0 --- /dev/null +++ b/apps/wpm/migrations/0084_alter_mlogbw_ftest.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.12 on 2025-01-09 07:26 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('qm', '0035_auto_20250109_1526'), + ('wpm', '0083_mlogbw_ftest'), + ] + + operations = [ + migrations.AlterField( + model_name='mlogbw', + name='ftest', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='mlogbw_ftest', to='qm.ftest', verbose_name='关联检验'), + ), + ] diff --git a/apps/wpm/services.py b/apps/wpm/services.py index 36a6d14b..067c6e59 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -19,6 +19,7 @@ import logging from apps.wpm.services_2 import get_alldata_with_batch_and_store from datetime import timedelta from apps.wpmw.models import Wpr, WprDefect +from ..qm.models import Defect myLogger = logging.getLogger('log') @@ -177,7 +178,8 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): else: wm_qs = WMaterial.objects.filter(batch=mi_batch, material=mi_ma, mgroup=mgroup, state=WMaterial.WM_OK) if not wm_qs.exists(): - wm_qs = WMaterial.objects.filter(batch=mi_batch, material=mi_ma, belong_dept=belong_dept, mgroup=None, state=WMaterial.WM_OK) + wm_qs = WMaterial.objects.filter(batch=mi_batch, material=mi_ma, + belong_dept=belong_dept, mgroup=None, state=WMaterial.WM_OK) count_x = wm_qs.count() if count_x == 1: @@ -219,7 +221,7 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): wm.update_by = user wm.save() if material_in.tracking == Material.MA_TRACKING_SINGLE: - raise ParseError("加工前不良的物料暂不支持单件") + raise ParseError("加工前不良的物料暂不支持单件追踪") if material_out: # 需要入车间库存 @@ -232,11 +234,22 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): 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 need_store_notok: for item in m_outs: - for f in Mlogb._meta.fields: - if 'count_n_' in f.name and getattr(item, f.name) > 0: - notok_sign = f.name.replace('count_n_', '') - m_outs_list.append( (item.material_out, item.batch if item.batch else mlog.batch, getattr(item, f.name), mlog.count_real_eweight, notok_sign, item)) - stored_notok = True + if Mlogbw.objects.filter(mlogb=item).exists(): + # 获取所有主要的不合格项 + bw_qs = Mlogbw.objects.filter(mlogb=item) + defect_qs = Mlogbw.objects.filter(mlogb=item, ftest__defects_ftest__is_main=True).values_list( + "defect", flat=True) + for defect in defect_qs: + xcount = bw_qs.filter(ftest__defects_ftest__defect=defect).count() + if xcount > 0: + 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: + notok_sign = f.name.replace('count_n_', '') + m_outs_list.append( (item.material_out, item.batch if item.batch else mlog.batch, getattr(item, f.name), mlog.count_real_eweight, notok_sign, item)) + stored_notok = True # 这里有一个漏洞,在产出物为兄弟件的情况下,不合格品的数量是记录在mlog上的, # 而不是mlogb上,以上的额外处理就没有效果了, 不过光子不记录不合格品 else: @@ -244,9 +257,14 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): # 一次填写的暂时不处理不合格品 for mo in m_outs_list: - mo_ma, mo_batch, mo_count, mo_count_eweight, notok_sign, mlog_or_b = mo - wm_state = WMaterial.WM_OK if notok_sign is None else WMaterial.WM_NOTOK - lookup = {'batch': mo_batch, 'material': mo_ma, 'mgroup': None, 'notok_sign': notok_sign, 'state': wm_state} + mo_ma, mo_batch, mo_count, mo_count_eweight, notok_sign_or_defect, mlog_or_b = mo + wm_state = WMaterial.WM_OK if notok_sign_or_defect is None else WMaterial.WM_NOTOK + lookup = {'batch': mo_batch, 'material': mo_ma, 'mgroup': None, + 'notok_sign': None, 'defect': None, 'state': wm_state} + if isinstance(notok_sign_or_defect, Defect): + lookup['defect'] = notok_sign_or_defect + elif notok_sign_or_defect is not None: + lookup['notok_sign'] = notok_sign_or_defect if into_wm_mgroup: lookup['mgroup'] = mgroup stored_mgroup = True @@ -274,9 +292,9 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): raise ParseError("日志与明细数量不一致,操作失败") for item in mlogbws: if item.wpr: - Wpr.change_or_new(wpr=item.wpr, wm=wm) + Wpr.change_or_new(wpr=item.wpr, wm=wm, ftest=item.ftest) else: - wpr = Wpr.change_or_new(number=item.number, wm=wm) + wpr = Wpr.change_or_new(number=item.number, wm=wm, ftest=item.ftest) item.wpr = wpr item.save() diff --git a/apps/wpmw/models.py b/apps/wpmw/models.py index d2f71a4b..678f6db9 100644 --- a/apps/wpmw/models.py +++ b/apps/wpmw/models.py @@ -1,4 +1,6 @@ from django.db import models + +from apps.qm.models import FtestDefect from apps.utils.models import BaseModel from apps.mtm.models import Material from rest_framework.exceptions import ParseError @@ -19,7 +21,7 @@ class Wpr(BaseModel): wm = models.ForeignKey("wpm.wmaterial", verbose_name="车间物料", on_delete=models.CASCADE, null=True, blank=True) @classmethod - def change_or_new(cls, wpr=None, number=None, mb=None, wm=None, old_mb=None, old_wm=None): + def change_or_new(cls, wpr=None, number=None, mb=None, wm=None, old_mb=None, old_wm=None, ftest=None): if wpr is None and number is None: raise ParseError("id和number不能同时为空") if mb and wm: @@ -51,6 +53,10 @@ class Wpr(BaseModel): if wm: ins.material = wm.material ins.save() + if ftest: # 通过检验变更其缺陷项 + WprDefect.objects.filter(wpr=ins).delete() + for ftestdefect in FtestDefect.objects.filter(ftest=ftest): + WprDefect.objects.create(wpr=ins, defect=ftestdefect.defect, is_main=ftestdefect.is_main) return ins @classmethod From f241194c4099414f8ced81cb021e9a5e43c0d2b7 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 9 Jan 2025 15:36:19 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20mlog=E5=88=A0=E9=99=A4=E6=97=B6?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=88=A0=E9=99=A4ftest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wpm/views.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/wpm/views.py b/apps/wpm/views.py index b6de1812..62aa98f4 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -192,6 +192,7 @@ class MlogViewSet(CustomModelViewSet): # delete_auditlog(instance, instance.id) if instance.ticket: instance.ticket.delete() + Ftest.objects.filter(mlogbw_ftest__mlogb__mlog=instance).delete() instance.delete() @transaction.atomic @@ -499,12 +500,8 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust query_dict["batch__contains"] = ins.batch qs = Mlogb.objects.filter(**query_dict) | qs # 需要删除子集ftest记录 - mlogbw_qs = Mlogbw.objects.filter(mlogb__in=qs) - # 需用list 不然qs.delete 这个qs会变空 - ftestIds = list(mlogbw_qs.values_list("ftest__id", flat=True)) + Ftest.objects.filter(mlogbw_ftest__mlogb__in=qs).delete() qs.delete() - Ftest.objects.filter(id__in=ftestIds).delete() - instance.delete() @transaction.atomic From 56808f21ca38e0e7dc364b70b811811cb83d5015 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 9 Jan 2025 15:42:12 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20mlog=E5=88=A0=E9=99=A4=E6=97=B6?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=88=A0=E9=99=A4ftest2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wpm/views.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/wpm/views.py b/apps/wpm/views.py index 62aa98f4..483d08e9 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -192,8 +192,9 @@ class MlogViewSet(CustomModelViewSet): # delete_auditlog(instance, instance.id) if instance.ticket: instance.ticket.delete() - Ftest.objects.filter(mlogbw_ftest__mlogb__mlog=instance).delete() + ftestIds = list(Ftest.objects.filter(mlogbw_ftest__mlogb__mlog=instance).values_list('id', flat=True)) instance.delete() + Ftest.objects.filter(id__in=ftestIds).delete() @transaction.atomic def perform_update(self, serializer): @@ -500,8 +501,9 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust query_dict["batch__contains"] = ins.batch qs = Mlogb.objects.filter(**query_dict) | qs # 需要删除子集ftest记录 - Ftest.objects.filter(mlogbw_ftest__mlogb__in=qs).delete() + ftestIds = list(Ftest.objects.filter(mlogbw_ftest__mlogb__in=qs).values_list('id', flat=True)) qs.delete() + Ftest.objects.filter(id__in=ftestIds).delete() instance.delete() @transaction.atomic From aca5cd8a6330bcb3d1213969cd6d455557d546a5 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 9 Jan 2025 15:57:23 +0800 Subject: [PATCH 5/5] fix: mlog submit defect_qs --- apps/wpm/services.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/wpm/services.py b/apps/wpm/services.py index 067c6e59..43d946ff 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -19,7 +19,7 @@ import logging from apps.wpm.services_2 import get_alldata_with_batch_and_store from datetime import timedelta from apps.wpmw.models import Wpr, WprDefect -from ..qm.models import Defect +from ..qm.models import Defect, FtestDefect myLogger = logging.getLogger('log') @@ -237,8 +237,9 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): if Mlogbw.objects.filter(mlogb=item).exists(): # 获取所有主要的不合格项 bw_qs = Mlogbw.objects.filter(mlogb=item) - defect_qs = Mlogbw.objects.filter(mlogb=item, ftest__defects_ftest__is_main=True).values_list( - "defect", flat=True) + defect_qs = FtestDefect.objects.filter(ftest__is_ok=False, + ftest__mlogbw_ftest__mlogb=item, is_main=True).values_list( + "defect", flat=True).distinct() for defect in defect_qs: xcount = bw_qs.filter(ftest__defects_ftest__defect=defect).count() if xcount > 0: