From 8eddeb4f7055c24cc1a84f40f3a17199c12435cd Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 8 Jan 2025 10:29:12 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20mlogb=E8=B4=A8=E6=A3=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/qm/migrations/0034_auto_20250108_1016.py | 43 ++++++++++ apps/qm/models.py | 17 ++++ apps/qm/serializers.py | 80 ++++++++++++++++++- apps/wpm/migrations/0083_mlogbw_ftest.py | 20 +++++ apps/wpm/models.py | 1 + apps/wpm/serializers.py | 7 +- apps/wpm/views.py | 8 +- 7 files changed, 170 insertions(+), 6 deletions(-) create mode 100644 apps/qm/migrations/0034_auto_20250108_1016.py create mode 100644 apps/wpm/migrations/0083_mlogbw_ftest.py diff --git a/apps/qm/migrations/0034_auto_20250108_1016.py b/apps/qm/migrations/0034_auto_20250108_1016.py new file mode 100644 index 00000000..a5b04805 --- /dev/null +++ b/apps/qm/migrations/0034_auto_20250108_1016.py @@ -0,0 +1,43 @@ +# Generated by Django 3.2.12 on 2025-01-08 02:16 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('qm', '0033_alter_ftest_test_numer'), + ] + + operations = [ + migrations.AddField( + model_name='ftest', + name='qct', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='qm.qct', verbose_name='所用质检表'), + ), + migrations.AddField( + model_name='ftestitem', + name='test_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='操作人'), + ), + migrations.CreateModel( + name='FtestDefect', + fields=[ + ('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('has', models.BooleanField(default=False, verbose_name='是否发现')), + ('defect', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='qm.defect', verbose_name='缺陷')), + ('ftest', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='qm.ftest', verbose_name='关联检验')), + ('test_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='操作人')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/apps/qm/models.py b/apps/qm/models.py index 48facc03..1f1939f0 100644 --- a/apps/qm/models.py +++ b/apps/qm/models.py @@ -240,6 +240,7 @@ class Ftest(CommonBDModel): """ type = models.CharField('检验类型', max_length=20, choices=FTEST_TYPE_CHOICES) test_date = models.DateField('检验日期') + qct = models.ForeignKey(Qct, verbose_name='所用质检表', on_delete=models.SET_NULL, null=True, blank=True) test_numer = models.TextField('检测编号', default='') test_group = models.CharField( '检验工序集', max_length=20, default='', blank=True) @@ -256,6 +257,10 @@ class Ftest(CommonBDModel): def ftestitems(self): return FtestItem.objects.filter(ftest=self) + @property + def ftestdefects(self): + return FtestDefect.objects.filter(ftest=self) + class FtestItem(BaseModel): """ @@ -265,12 +270,24 @@ class FtestItem(BaseModel): Ftest, verbose_name='关联检验', on_delete=models.CASCADE) testitem = models.ForeignKey( TestItem, verbose_name='质检项目', on_delete=models.CASCADE) + test_user = models.ForeignKey(User, verbose_name='操作人', on_delete=models.CASCADE, null=True, blank=True) test_val = models.FloatField('测量值', null=True, blank=True) check_val = models.FloatField('专检测量值', null=True, blank=True) test_val_json = models.JSONField('测量值', null=True, blank=True) check_val_json = models.JSONField('专检测量值', null=True, blank=True) +class FtestDefect(BaseModel): + """ + 缺陷明细 + """ + ftest = models.ForeignKey( + Ftest, verbose_name='关联检验', on_delete=models.CASCADE) + 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) + + class Ptest(CommonAModel): """ 性能测试记录 diff --git a/apps/qm/serializers.py b/apps/qm/serializers.py index 9bc6351b..1b09a417 100644 --- a/apps/qm/serializers.py +++ b/apps/qm/serializers.py @@ -1,5 +1,6 @@ from apps.qm.models import (QuaStat, TestItem, Ftest, FtestItem, FtestWork, Ptest, - NotOkOption, Defect, Qct, QctTestItem, QctMat, QctDefect) + NotOkOption, Defect, Qct, QctTestItem, QctMat, + QctDefect, FtestDefect, FTEST_TYPE_CHOICES) from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE from apps.utils.serializers import CustomModelSerializer from rest_framework import serializers @@ -241,3 +242,80 @@ class PtestSerializer(CustomModelSerializer): if Ptest.objects.filter(sample_number=validated_data['sample_number']).exists(): raise serializers.ValidationError('该样品编号已存在') return super().create(validated_data) + + +class FtestDefectSerializer(CustomModelSerializer): + defect_name = serializers.CharField(source='defect.name', read_only=True) + class Meta: + model = FtestDefect + fields = '__all__' + read_only_fields = EXCLUDE_FIELDS_BASE + ['ftest'] + + +class FtestItemProcessSerializer(CustomModelSerializer): + testitem_name = serializers.CharField( + source='testitem.name', read_only=True) + testitem_description = serializers.CharField( + source='testitem.description', read_only=True) + class Meta: + model = FtestItem + fields = ["id", "testitem", "test_user", "test_val_json", "testitem_name", "testitem_description"] + +class FtestProcessSerializer(CustomModelSerializer): + test_user_name = serializers.CharField( + source='test_user.name', read_only=True) + ftestitems = FtestItemProcessSerializer(label='检验明细', many=True) + ftestdefects = FtestDefectSerializer(label='缺陷明细', many=True) + + class Meta: + model = Ftest + fields = ["id", "test_date", + "test_user", "note", "ftestitems", "ftestdefects", "qct", "test_user_name"] + extra_kwargs = {"qct": {"required": True}} + + def validate(self, attrs): + attrs["type"] = "process" + return attrs + + def create(self, validated_data): + ftestitems = validated_data.pop('ftestitems', []) + ftestdefects = validated_data.pop('ftestdefects', []) + with transaction.atomic(): + instance = super().create(validated_data) + for item in ftestitems: + FtestItem.objects.create(ftest=instance, **item) + is_ok = True + for item2 in ftestdefects: + defect:Defect = item["defect"] + if defect.okcate in [Defect.DEFECT_NOTOK] and item["has"]: + is_ok = False + FtestDefect.objects.create(ftest=instance, **item2) + instance.is_ok = is_ok + instance.save() + return instance + + def update(self, instance, validated_data): + ftestitems = validated_data.pop('ftestitems', []) + ftestdefects = validated_data.pop('ftestdefects', []) + with transaction.atomic(): + instance = super().update(instance, validated_data) + for item in ftestitems: + if "id" in item and item["id"]: + FtestItem.objects.filter(id=item["id"]).update( + test_user = item["test_user"], + test_val_json = item["test_val_json"]) + else: + FtestItem.objects.create(ftest=instance, **item) + is_ok = True + for item2 in ftestdefects: + if "id" in item2 and item2["id"]: + ins: FtestDefect = FtestDefect.objects.get(id=item2["id"]) + else: + ins = FtestDefect.objects.create(ftest=instance, **item2) + ins.has = item2["has"] + ins.save() + if ins.has and ins.defect.okcate in [Defect.DEFECT_NOTOK]: + is_ok = False + instance.is_ok = is_ok + instance.save() + return instance \ No newline at end of file diff --git a/apps/wpm/migrations/0083_mlogbw_ftest.py b/apps/wpm/migrations/0083_mlogbw_ftest.py new file mode 100644 index 00000000..4dbb27c2 --- /dev/null +++ b/apps/wpm/migrations/0083_mlogbw_ftest.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.12 on 2025-01-08 02:16 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('qm', '0034_auto_20250108_1016'), + ('wpm', '0082_mlogb_qct'), + ] + + operations = [ + migrations.AddField( + model_name='mlogbw', + name='ftest', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='qm.ftest', verbose_name='关联检验'), + ), + ] diff --git a/apps/wpm/models.py b/apps/wpm/models.py index 84648529..fee7cbf1 100644 --- a/apps/wpm/models.py +++ b/apps/wpm/models.py @@ -354,6 +354,7 @@ class Mlogbw(BaseModel): mlogb = models.ForeignKey(Mlogb, verbose_name='生产记录', on_delete=models.CASCADE) wpr = models.ForeignKey("wpmw.wpr", verbose_name='关联产品', on_delete=models.SET_NULL , related_name='wpr_mlogbw', null=True, blank=True) + ftest = models.OneToOneField("qm.ftest", verbose_name='关联检验', on_delete=models.PROTECT, null=True, blank=True) note = models.TextField('备注', null=True, blank=True) diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index 9aa7541c..b6b40e06 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -21,6 +21,7 @@ from django.utils.timezone import localdate from apps.qm.models import NotOkOption from apps.wf.serializers import TicketSimpleSerializer from apps.wpmw.models import Wpr +from apps.qm.serializers import FtestProcessSerializer import logging mylogger = logging.getLogger("log") @@ -572,9 +573,10 @@ class MlogbInUpdateSerializer(CustomModelSerializer): fields = ['id', 'count_use', 'count_break', 'count_pn_jgqbl', 'note'] class MlogbwCreateUpdateSerializer(CustomModelSerializer): + ftest = FtestProcessSerializer(required=False) class Meta: model = Mlogbw - fields = ["id", "number", "wpr", "note", "mlogb"] + fields = ["id", "number", "wpr", "note", "mlogb", "ftest"] def validate(self, attrs): mlogb:Mlogb = attrs["mlogb"] @@ -588,8 +590,7 @@ class MlogbwCreateUpdateSerializer(CustomModelSerializer): def update(self, instance, validated_data): validated_data.pop("mlogb") - return super().update(instance, validated_data) - + super().update(instance, validated_data) class MlogbOutUpdateSerializer(CustomModelSerializer): class Meta: diff --git a/apps/wpm/views.py b/apps/wpm/views.py index bfb8982d..92d77984 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -521,8 +521,10 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust d_count_ok = xcount # 找寻质检表 qctmat = QctMat.objects.filter(material=material_out).order_by("-create_time").first() + qct = None if qctmat: - mlogbout.qct = qctmat.qct + qct = qctmat.qct + mlogbout.qct = qct mlogbout.count_real = d_count_real mlogbout.count_ok = d_count_ok mlogbout.save() @@ -614,11 +616,13 @@ class MlogbwViewSet(CustomModelViewSet): self.cal_mlogb_count(mlogb_to) @transaction.atomic - def perform_destroy(self, instance): + def perform_destroy(self, instance:Mlogbw): mlogb = instance.mlogb if mlogb.mlog.submit_time is not None: raise ParseError('日志已提交不可修改') instance.delete() + if instance.ftest: + instance.ftest.delete() self.cal_mlogb_count(mlogb) # 如果是输入且输出追踪到个,需同步创建 material_in: Material = mlogb.material_in