From 651366257cf3ed81939fa1f3b985461cb08b5ac3 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 12 May 2026 18:02:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=90=88=E6=89=B9=E6=94=AF=E6=8C=81=20?= =?UTF-8?q?clear=5Fdefect=EF=BC=8C=E5=90=88=E6=A0=BC=E5=93=81=E5=A4=9A=20d?= =?UTF-8?q?efect=20=E5=90=88=E6=89=B9=E5=90=8E=E7=BD=AE=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 Handover.clear_defect 字段:合批时若源批次 state 均为 WM_OK 且 defect 不一致,可由前端显式勾选开启,落库后目标 defect 为 None;默认 false 保持原有严格校验。 Co-Authored-By: Claude Opus 4.7 (1M context) --- .../migrations/0130_handover_clear_defect.py | 16 ++++++++++++++++ apps/wpm/models.py | 1 + apps/wpm/serializers.py | 9 +++++++-- apps/wpm/services.py | 17 ++++++++++++++--- 4 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 apps/wpm/migrations/0130_handover_clear_defect.py diff --git a/apps/wpm/migrations/0130_handover_clear_defect.py b/apps/wpm/migrations/0130_handover_clear_defect.py new file mode 100644 index 00000000..f56f93ea --- /dev/null +++ b/apps/wpm/migrations/0130_handover_clear_defect.py @@ -0,0 +1,16 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wpm', '0129_mlogbdefect_is_inherited'), + ] + + operations = [ + migrations.AddField( + model_name='handover', + name='clear_defect', + field=models.BooleanField(default=False, verbose_name='合批清除缺陷'), + ), + ] diff --git a/apps/wpm/models.py b/apps/wpm/models.py index abc604b6..1dcf1955 100644 --- a/apps/wpm/models.py +++ b/apps/wpm/models.py @@ -677,6 +677,7 @@ class Handover(CommonADModel): H_DIV = 20 new_batch = models.TextField('新批次号', null=True, blank=True, db_index=True) new_wm = models.ForeignKey(WMaterial, on_delete=models.SET_NULL, null=True, blank=True) + clear_defect = models.BooleanField('合批清除缺陷', default=False) mtype = models.PositiveSmallIntegerField("合并类型", default=H_NORMAL, choices= [(H_NORMAL, '正常'), (H_DIV, '分批'), (H_MERGE, '合批')]) type = models.PositiveSmallIntegerField('交接类型', choices=[ diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index 5276ed24..0ff39357 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -1304,16 +1304,21 @@ class HandoverSerializer(CustomModelSerializer): elif deptOrmgroupId != current_mdept_id: raise ParseError(f'第{ind+1}行-交接物料所属工段/车间不一致') if mtype == Handover.H_MERGE: + clear_defect = attrs.get('clear_defect', False) + if clear_defect and wm.state != WMaterial.WM_OK: + raise ParseError(f'第{ind+1}行-清除缺陷合批仅支持合格品') + if clear_defect and new_wm is not None and new_wm.defect is not None: + raise ParseError('清除缺陷合批的目标批次不能带缺陷') if next_mat is None: next_mat = wm.material next_state = wm.state - next_defect = wm.defect + next_defect = None if clear_defect else wm.defect else: if next_mat != wm.material: raise ParseError(f'第{ind+1}行-合并的物料不一致') if next_state != wm.state: raise ParseError(f'第{ind+1}行-合并的物料状态不一致') - if next_defect != wm.defect: + if not clear_defect and next_defect != wm.defect: raise ParseError(f'第{ind+1}行-合并的物料缺陷不一致') if tracking == Material.MA_TRACKING_SINGLE: handoverbw = item.get("handoverbw", []) diff --git a/apps/wpm/services.py b/apps/wpm/services.py index 91ddfe34..52901842 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -757,6 +757,8 @@ def handover_submit(handover:Handover, user: User, now: Union[datetime.datetime, mids = [] exclude_batchst_ids = [] check_batch_exist = False + merge_target_defect = None + merge_clear_defect = False if mtype == Handover.H_MERGE: if new_batch: batches = [new_batch] @@ -766,6 +768,12 @@ def handover_submit(handover:Handover, user: User, now: Union[datetime.datetime, check_batch_exist = True target_b, _ = BatchSt.g_create(batch=new_batch, handover=handover, material_start=material, check_batch_exist=check_batch_exist) exclude_batchst_ids.append(target_b.id) + merge_clear_defect = bool(handover.clear_defect) + if merge_clear_defect: + merge_target_defect = None + else: + source_wm_ids = [hb[0] for hb in handoverb_list] + merge_target_defect = WMaterial.objects.filter(id__in=source_wm_ids).first().defect elif mtype == Handover.H_DIV: if handover.wm is None: raise ParseError('拆批请选择车间库存') @@ -810,7 +818,10 @@ def handover_submit(handover:Handover, user: User, now: Union[datetime.datetime, if handover.type == Handover.H_NORMAL: if mtype == Handover.H_MERGE and handover.new_wm: wm_to = WMaterial.objects.select_for_update().get(id=handover.new_wm.id) - if wm_to.state != wm_from.state or wm_to.material != wm_from.material or wm_to.defect != wm_from.defect: + defect_ok = wm_to.defect == wm_from.defect or ( + merge_clear_defect and wm_to.defect is None and wm_from.state == WMaterial.WM_OK + ) + if wm_to.state != wm_from.state or wm_to.material != wm_from.material or not defect_ok: raise ParseError("正常合并到的车间库存状态或物料异常") else: wm_to, _ = WMaterial.locked_get_or_create( @@ -820,7 +831,7 @@ def handover_submit(handover:Handover, user: User, now: Union[datetime.datetime, belong_dept=recive_dept, state=wm_from.state, notok_sign=wm_from.notok_sign, - defect=wm_from.defect, + defect=merge_target_defect if mtype == Handover.H_MERGE else wm_from.defect, defaults={ "batch_ofrom": wm_from.batch_ofrom, "material_ofrom": wm_from.material_ofrom, @@ -916,7 +927,7 @@ def handover_submit(handover:Handover, user: User, now: Union[datetime.datetime, belong_dept=recive_dept, state=wm_from.state, notok_sign=wm_from.notok_sign, - defect=wm_from.defect, + defect=merge_target_defect if mtype == Handover.H_MERGE else wm_from.defect, defaults={ "batch_ofrom": wm_from.batch_ofrom, "material_ofrom": wm_from.material_ofrom,