From 74f0db77edecec01221b9a5d9d73eaf65a230767 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 6 Mar 2025 14:15:45 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20Handoverb=20=E6=94=AF=E6=8C=81=E6=8B=86?= =?UTF-8?q?=E6=89=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wpm/migrations/0094_auto_20250306_1414.py | 29 ++++++++++++ apps/wpm/models.py | 11 ++++- apps/wpm/serializers.py | 44 ++++++++++++------- apps/wpm/services.py | 22 +++++++--- apps/wpm/views.py | 1 - 5 files changed, 83 insertions(+), 24 deletions(-) create mode 100644 apps/wpm/migrations/0094_auto_20250306_1414.py diff --git a/apps/wpm/migrations/0094_auto_20250306_1414.py b/apps/wpm/migrations/0094_auto_20250306_1414.py new file mode 100644 index 00000000..1498d78b --- /dev/null +++ b/apps/wpm/migrations/0094_auto_20250306_1414.py @@ -0,0 +1,29 @@ +# Generated by Django 3.2.12 on 2025-03-06 06:14 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('wpm', '0093_alter_handover_recive_user'), + ] + + operations = [ + migrations.AddField( + model_name='handover', + name='mtype', + field=models.PositiveSmallIntegerField(choices=[(10, '正常'), (20, '分批'), (30, '合批')], default=10, verbose_name='合并类型'), + ), + migrations.AddField( + model_name='handoverb', + name='batch', + field=models.TextField(blank=True, null=True, verbose_name='批次号'), + ), + migrations.AddField( + model_name='handoverb', + name='wm_to', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='handoverb_wm_to', to='wpm.wmaterial', verbose_name='所到车间库存'), + ), + ] diff --git a/apps/wpm/models.py b/apps/wpm/models.py index 9f16a8e3..4ac03abb 100644 --- a/apps/wpm/models.py +++ b/apps/wpm/models.py @@ -440,8 +440,14 @@ class Handover(CommonADModel): H_TEST = 30 H_SCRAP = 40 H_CHANGE = 50 + H_MERGE = 30 + H_DIV = 20 new_batch = models.TextField('新批次号', null=True, blank=True) - type = models.PositiveSmallIntegerField('交接类型', choices=[(H_NORMAL, '正常交接'), (H_REPAIR, '返修交接'), (H_TEST, '检验交接'), (H_SCRAP, '报废交接'), (H_CHANGE, '改版交接')], default=H_NORMAL) + mtype = models.PositiveSmallIntegerField("合并类型", default=H_NORMAL, choices= + [(H_NORMAL, '正常'), (H_DIV, '分批'), (H_MERGE, '合批')]) + type = models.PositiveSmallIntegerField('交接类型', choices=[ + (H_NORMAL, '正常交接'), (H_REPAIR, '返修交接'), + (H_TEST, '检验交接'), (H_SCRAP, '报废交接'), (H_CHANGE, '改版交接')], default=H_NORMAL) send_date = models.DateField('送料日期') send_user = models.ForeignKey( User, verbose_name='交送人', on_delete=models.CASCADE, related_name='handover_send_user') @@ -480,8 +486,11 @@ class Handoverb(BaseModel): """TN: 子级交接记录 """ handover = models.ForeignKey(Handover, verbose_name='关联交接记录', on_delete=models.CASCADE) + batch = models.TextField("批次号", null=True, blank=True) wm = models.ForeignKey(WMaterial, verbose_name='关联车间库存', on_delete=models.SET_NULL, null=True, blank=True, related_name='handoverb_wm') + wm_to = models.ForeignKey(WMaterial, verbose_name='所到车间库存', on_delete=models.SET_NULL, + null=True, blank=True, related_name='handoverb_wm_to') count = models.PositiveIntegerField('送料数', default=0) @property diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index eb642089..fa0197a4 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -738,7 +738,7 @@ class MlogbOutUpdateSerializer(CustomModelSerializer): model = Mlogb fields = "__all__" read_only_fields = EXCLUDE_FIELDS_BASE + ['mlog', 'mtask', 'wm_in', 'material_in', 'material_out', - 'count_use', 'count_break', 'count_pn_jgqbl', 'mlogbdefect', "qct"] + 'count_use', 'count_break', 'count_pn_jgqbl', 'mlogbdefect', "qct", "batch"] # def create(self, validated_data): # material_out:Material = validated_data["material_out"] @@ -837,7 +837,6 @@ class Handoverbwserializer(CustomModelSerializer): extra_kwargs = {'wpr': {'required': True}} class HandoverbSerializer(CustomModelSerializer): - batch = serializers.CharField(source='wm.batch', read_only=True) notok_sign = serializers.CharField(source='wm.notok_sign', read_only=True) defect_name = serializers.CharField(source="wm.defect.name", read_only=True) handoverbw = Handoverbwserializer(many=True, required=False) @@ -867,11 +866,16 @@ class HandoverSerializer(CustomModelSerializer): handoverb = HandoverbSerializer(many=True, required=False) def validate(self, attrs): + if "mtype" not in attrs: + attrs['mtype'] = Handover.H_NORMAL + mtype = attrs["mtype"] if 'type' not in attrs: attrs['type'] = Handover.H_NORMAL if attrs["type"] == Handover.H_CHANGE: if "material_changed" not in attrs: - raise ParseError("必须指定变更后的物料") + raise ParseError("必须指定改版后的物料") + if mtype == Handover.H_MERGE and not attrs.get("new_batch", None): + raise ParseError("必须指定合并后的批次") wm:WMaterial = attrs.get('wm', None) handoverb = attrs.get('handoverb', []) if wm: @@ -939,11 +943,17 @@ class HandoverSerializer(CustomModelSerializer): handoverb = validated_data.pop('handoverb', []) with transaction.atomic(): ins = super().create(validated_data) - for item in handoverb: + mtype = validated_data["mtype"] + for ind, item in enumerate(handoverb): wm = item["wm"] count = item["count"] handoverbw = item.pop("handoverbw", []) - handoverb, _ = Handoverb.objects.get_or_create(handover=ins, wm=wm, count=count) + if mtype == Handover.H_DIV: + if not item["batch"]: + raise ParseError(f'第{ind+1}行-请提供拆批批次号') + handoverb = Handoverb.objects.create(handover=ins, batch=item["batch"], count=count) + else: + handoverb = Handoverb.objects.create(handover=ins, wm=wm, count=count, batch=wm.batch) if wm.material.tracking == Material.MA_TRACKING_SINGLE: if handoverbw: handoverb.count = len(handoverbw) @@ -955,40 +965,40 @@ class HandoverSerializer(CustomModelSerializer): for item in Wpr.get_qs_by_wm(wm): Handoverbw.objects.get_or_create(wpr=item, handoverb=handoverb, defaults={"number":item.number}) else: - raise ParseError(f'请提供交接物料明细编号') + raise ParseError(f'第{ind+1}行-请提供交接物料明细编号') return ins def update(self, instance, validated_data): handoverb = validated_data.pop('handoverb', []) with transaction.atomic(): super().update(instance, validated_data) - wmIds = [] - for item in handoverb: + Handoverb.objects.filter(handover=instance).delete() + for ind, item in enumerate(handoverb): wm = item["wm"] count = item["count"] handoverbw = item.pop("handoverbw", []) - wmIds.append(item["wm"].id) - hb, _ = Handoverb.objects.get_or_create(handover=instance, wm=wm) - hb.count = count - hb.save() + if validated_data["mtype"] == Handover.H_DIV: + if not item["batch"]: + raise ParseError(f'第{ind+1}行-请提供拆批批次号') + hb, _ = Handoverb.objects.get_or_create(handover=instance, batch=item["batch"], defaults={"count": count}) + else: + hb, _ = Handoverb.objects.get_or_create(handover=instance, wm=wm, defaults={"count": count, + "batch": wm.batch}) if wm.material.tracking == Material.MA_TRACKING_SINGLE: + Handoverbw.objects.filter(handoverb=hb).delete() if handoverbw: hb.count = len(handoverbw) hb.save() - wprIds = [item["wpr"].id for item in handoverbw] - Handoverbw.objects.filter(handoverb=hb).exclude(wpr__in=wprIds).delete() for item in handoverbw: wpr = item["wpr"] Handoverbw.objects.get_or_create(wpr=wpr, handoverb=hb, defaults={"number": wpr.number, "note": item.get("note", None)}) elif count == wm.count: wpr_qs = Wpr.get_qs_by_wm(wm) - Handoverbw.objects.filter(handoverb=hb).exclude(wpr__in=wpr_qs).delete() for item in wpr_qs: Handoverbw.objects.get_or_create(wpr=item, handoverb=handoverb, defaults={"number": item.number}) else: - raise ParseError(f'请提供交接物料明细编号') - Handoverb.objects.filter(handover=instance).exclude(wm__in=wmIds).delete() + raise ParseError(f'第{ind+1}行-请提供交接物料明细') return instance class HandoverUpdateSerializer(CustomModelSerializer): diff --git a/apps/wpm/services.py b/apps/wpm/services.py index 4d59f455..e760b365 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -672,6 +672,7 @@ def handover_submit(handover:Handover, user: User, now: Union[datetime.datetime, handoverb_qs = Handoverb.objects.filter(handover=handover) need_add = True material:Material = handover.material + mtype = handover.mtype if '混料' in material.name: # hard code need_add = False if handoverb_qs.exists(): @@ -683,15 +684,22 @@ def handover_submit(handover:Handover, user: User, now: Union[datetime.datetime, recive_dept = handover.recive_dept batches = [] new_batch = handover.new_batch - if new_batch: - batches = [new_batch] + if mtype == Handover.H_MERGE: + if new_batch: + batches = [new_batch] + else: + raise ParseError("合并批次时请提供新批次号") for item in handoverb_list: wm_from, xcount, handover_or_b = item - batch = wm_from.batch - batches.append(batch) + # 合并为新批 - if new_batch: + if mtype == Handover.H_MERGE: batch = new_batch + elif mtype == Handover.H_DIV: + batch = handover_or_b.batch + else: + batch = wm_from.batch + batches.append(batch) if wm_from is None: raise ParseError('找不到车间库存') @@ -713,6 +721,8 @@ def handover_submit(handover:Handover, user: User, now: Union[datetime.datetime, mgroup=recive_mgroup, belong_dept=recive_dept, state=WMaterial.WM_OK, + notok_sign=wm_from.notok_sign, + defect=wm_from.defect, defaults={ "batch_ofrom": wm_from.batch_ofrom, "material_ofrom": wm_from.material_ofrom, @@ -801,6 +811,8 @@ def handover_submit(handover:Handover, user: User, now: Union[datetime.datetime, wm_to.count = wm_to.count + xcount wm_to.count_eweight = handover.count_eweight # 这行代码有隐患 wm_to.save() + handover_or_b.wm_to = wm_to + handover_or_b.save() if material.tracking == Material.MA_TRACKING_SINGLE: handoverbws = Handoverbw.objects.filter(handoverb=handover_or_b) if handoverbws.count() != xcount: diff --git a/apps/wpm/views.py b/apps/wpm/views.py index f69a9195..0efd2dc4 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -374,7 +374,6 @@ class HandoverViewSet(CustomModelViewSet): """ queryset = Handover.objects.all() serializer_class = HandoverSerializer - update_serializer_class = HandoverUpdateSerializer select_related_fields = ['send_user', 'send_mgroup', 'send_dept', 'recive_user', 'recive_mgroup', 'recive_dept', 'wm'] filterset_class = HandoverFilter search_fields = ['id', 'material__name',