diff --git a/apps/wpm/migrations/0080_mlogb_mlogb_to.py b/apps/wpm/migrations/0080_mlogb_mlogb_to.py new file mode 100644 index 00000000..50da05e6 --- /dev/null +++ b/apps/wpm/migrations/0080_mlogb_mlogb_to.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.12 on 2025-01-06 02:20 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('wpm', '0079_auto_20250103_1652'), + ] + + operations = [ + migrations.AddField( + model_name='mlogb', + name='mlogb_to', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='wpm.mlogb', verbose_name='生成的'), + ), + ] diff --git a/apps/wpm/models.py b/apps/wpm/models.py index 7c31b936..bb055cd4 100644 --- a/apps/wpm/models.py +++ b/apps/wpm/models.py @@ -292,6 +292,7 @@ class Mlog(CommonADModel): return mlog_count_fields class Mlogb(BaseModel): + mlogb_to = models.ForeignKey("self", verbose_name='生成的', on_delete=models.SET_NULL, null=True, blank=True) mlog = models.ForeignKey(Mlog, verbose_name='关联日志', on_delete=models.CASCADE, related_name='b_mlog') note = models.TextField('备注', default='', blank=True) diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index 1bfab152..3eed30e4 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -570,7 +570,16 @@ class MlogbInUpdateSerializer(CustomModelSerializer): class MlogbwCreateUpdateSerializer(CustomModelSerializer): class Meta: model = Mlogbw - fields = ["id", "number", "note", "mlogb"] + fields = ["id", "number", "wpr", "note", "mlogb"] + + def validate(self, attrs): + mlogb:Mlogb = attrs["mlogb"] + material_in:Material = mlogb.material_in + material_out:Material = mlogb.material_out + if material_in and material_in.tracking != Material.MA_TRACKING_SINGLE: + raise ParseError("非追踪单件无需填写") + if material_out and material_out.tracking != Material.MA_TRACKING_SINGLE: + raise ParseError("非追踪单件无需填写") def update(self, instance, validated_data): validated_data.pop("mlogb") diff --git a/apps/wpm/services.py b/apps/wpm/services.py index 1bd1bf05..6e070d8f 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -274,7 +274,9 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): if item.wpr: Wpr.change_or_new(wpr=item.wpr, wm=wm) else: - Wpr.change_or_new(number=item.number, wm=wm) + wpr = Wpr.change_or_new(number=item.number, wm=wm) + item.wpr = wpr + item.save() mlog.submit_time = now mlog.submit_user = user @@ -399,7 +401,9 @@ def mlog_revert(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): if item.wpr: Wpr.change_or_new(wpr=item.wpr, wm=wm) else: - Wpr.change_or_new(number=item.number, wm=wm) + wpr = Wpr.change_or_new(number=item.number, wm=wm) + item.wpr = wpr + item.save() # 针对加工前不良的暂时额外处理 for item in m_ins_bl_list: diff --git a/apps/wpm/views.py b/apps/wpm/views.py index fffbaf60..04641e7e 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -24,6 +24,7 @@ from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer, from .services import mlog_submit, handover_submit, mlog_revert from apps.wpm.services import mlog_submit_validate, generate_new_batch from apps.wf.models import State +from apps.wpmw.models import Wpr # Create your views here. @@ -478,21 +479,35 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust @transaction.atomic def perform_create(self, serializer): - ins: Mlogb = serializer.save() - mlog: Mlog = ins.mlog + mlogbin: Mlogb = serializer.save() + mlog: Mlog = mlogbin.mlog # 创建输出 - if ins.mtask and ins.material_in: - material_out = mlog.material_out + # 以及mlogbw + if mlogbin.mtask and mlogbin.material_in: + material_in:Material = mlogbin.material_in + material_out:Material = mlog.material_out if material_out is None: raise ParseError('产物不可为空') m_dict = { - "mtask": ins.mtask, - "mlog": ins.mlog, - "material_out": ins.mlog.material_out + "mtask": mlogbin.mtask, + "mlog": mlog, + "material_out": material_out, } - m_dict['batch'] = generate_new_batch(ins.batch, mlog) - wm_in: WMaterial = ins.wm_in - Mlogb.objects.get_or_create(**m_dict, defaults={"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom}) + m_dict['batch'] = generate_new_batch(mlogbin.batch, mlog) + wm_in: WMaterial = mlogbin.wm_in + mlogbout, _ = Mlogb.objects.get_or_create(**m_dict, defaults={"batch_ofrom": wm_in.batch_ofrom, + "material_ofrom": wm_in.material_ofrom}) + mlogbin.mlogb_to = mlogbout + mlogbin.save() + if material_out.tracking == Material.MA_TRACKING_SINGLE: + if material_in.tracking == Material.MA_TRACKING_SINGLE: + if mlogbin.count_use == wm_in.count: # 自动创建mlogbw + # 先暂时不考虑合并与拆分 + mlogbout.count_real = wm_in.count + mlogbout.save() + for wpr in Wpr.objects.filter(wm=wm_in).order_by("number"): + Mlogbw.objects.get_or_create(wpr=wpr, mlogb=mlogbin, defaults={"number": wpr.number}) + Mlogbw.objects.get_or_create(wpr=wpr, mlogb=mlogbout, defaults={"number": wpr.number}) class MlogbOutViewSet(UpdateModelMixin, CustomGenericViewSet): @@ -544,20 +559,46 @@ class MlogbwViewSet(CustomModelViewSet): return super().filter_queryset(queryset) def cal_mlogb_count(self, mlogb): - count_real = Mlogbw.objects.filter(mlogb=mlogb).count() - mlogb.count_real = count_real - mlogb.count_ok = count_real + count = Mlogbw.objects.filter(mlogb=mlogb).count() + # 此处先不管检验问题 + # todo + if mlogb.material_in: + mlogb.count_use = count + elif mlogb.material_out: + mlogb.count_real = count + mlogb.count_ok = count mlogb.save() @transaction.atomic def perform_create(self, serializer): - ins = serializer.save() - self.cal_mlogb_count(ins.mlogb) + ins:Mlogbw = serializer.save() + mlogb:Mlogb = ins.mlogb + self.cal_mlogb_count(mlogb) + # 如果是输入且输出追踪到个,需同步创建 + material_in:Material = mlogb.material_in + if material_in is not None: + mlogb_to = mlogb.mlogb_to + material_out:Material = mlogb.mlog.material_out + if mlogb_to and material_out.tracking == Material.MA_TRACKING_SINGLE: + for item in Mlogbw.objects.filter(mlogb=mlogb).order_by("number"): + Mlogbw.objects.get_or_create(mlogb=mlogb_to, wpr=item.wpr, defaults={"number": item.number}) + self.cal_mlogb_count(mlogb_to) @transaction.atomic def perform_destroy(self, instance): mlogb = instance.mlogb instance.delete() self.cal_mlogb_count(mlogb) + # 如果是输入且输出追踪到个,需同步创建 + material_in: Material = mlogb.material_in + if material_in is not None: + mlogb_to = mlogb.mlogb_to + material_out: Material = mlogb.mlog.material_out + if mlogb_to and material_out.tracking == Material.MA_TRACKING_SINGLE: + number_list = Mlogbw.objects.filter(mlogb=mlogb).values_list("number", flat=True) + wprId_list = Mlogbw.objects.filter(mlogb=mlogb).values_list("wpr__id", flat=True) + Mlogbw.objects.filter(mlogb=mlogb_to, number__in=number_list).delete() + Mlogbw.objects.filter(mlogb=mlogb_to, wpr__id__in=wprId_list).delete() + self.cal_mlogb_count(mlogb_to) diff --git a/apps/wpmw/models.py b/apps/wpmw/models.py index 145d8ad5..809089f7 100644 --- a/apps/wpmw/models.py +++ b/apps/wpmw/models.py @@ -25,18 +25,26 @@ class Wpr(BaseModel): if mb and wm: raise ParseError("所属仓库批次和车间批次不可同时存在") - ins = wpr if wpr else cls.objects.filter(number=number).first() - if ins is None: - ins = cls(number=number) + if wpr: + ins = wpr + elif number: + try: + ins = cls.objects.get(number=number) + except cls.DoesNotExist: + ins = cls(number=number) if old_mb and ins.mb != old_mb: raise ParseError(f"请检查-{ins.number}-所属仓库批次") if old_wm and ins.wm != old_wm: raise ParseError(f"请检查-{ins.number}-所属车间批次") + if number: + ins.number = number + ins.mb = mb if mb: ins.material = mb.material + ins.wm = wm if wm: ins.material = wm.material