From 942e54a7e456d98f4d3f776c07f4558ceef279a6 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 13 Jan 2025 09:39:18 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20ftestwork=E6=94=AF=E6=8C=81ftestworkdef?= =?UTF-8?q?ect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/qm/models.py | 34 +++++++++++++------- apps/qm/serializers.py | 71 ++++++++++++++++++++++++++++++++---------- 2 files changed, 77 insertions(+), 28 deletions(-) diff --git a/apps/qm/models.py b/apps/qm/models.py index dbb0120e..f90ae737 100644 --- a/apps/qm/models.py +++ b/apps/qm/models.py @@ -6,6 +6,8 @@ from apps.em.models import Equipment from apps.wpm.models import SfLog, WMaterial from django.utils.translation import gettext_lazy as _ from django.db import transaction +from django.db.models import Sum +from rest_framework.exceptions import ParseError class Defect(CommonAModel): # 缺陷项 @@ -226,6 +228,7 @@ class FtestWork(CommonBDModel): ticket = models.ForeignKey('wf.ticket', verbose_name='关联工单', on_delete=models.SET_NULL, related_name='ftestwork_ticket', null=True, blank=True, db_constraint=False) + qct = models.ForeignKey(Qct, verbose_name='关联质检表', on_delete=models.SET_NULL, null=True, blank=True) @classmethod def count_fields(cls): @@ -235,19 +238,26 @@ class FtestWork(CommonBDModel): ftestwork_count_fields.append(f.name) return ftestwork_count_fields - # def cal_count(self): - # self.count_notok = FtestworkDefect.objects.filter( - # mlogb=self, defect__okcate=30).aggregate(total=Sum("count"))["total"] or 0 - # self.count_ok = self.count_real - self.count_notok - # if self.count_ok < 0: - # raise ParseError('合格数量不能小于0') - # self.save(update_fields=['count_ok', 'count_notok']) + def cal_count(self): + self.count_notok = FtestworkDefect.objects.filter( + mlogb=self, defect__okcate=30).aggregate(total=Sum("count"))["total"] or 0 + self.count_ok = self.count - self.count_notok + if self.type2 == 20: #全检 + self.count_sampling = self.count + self.count_sampling_ok = self.count_ok + if self.count_ok < 0: + raise ParseError('合格数量不能小于0') + self.save(update_fields=['count_ok', 'count_notok']) + + @property + def ftestworkdefect(self): + return FtestworkDefect.objects.filter(ftestwork=self) -# class FtestworkDefect(BaseModel): -# ftestwork = models.ForeignKey(FtestWork, verbose_name='关联检验工作', on_delete=models.CASCADE, -# related_name='ftestwork_defect') -# defect = models.ForeignKey(Defect, verbose_name='缺陷', on_delete=models.CASCADE) -# count = models.PositiveIntegerField('数量', default=0) +class FtestworkDefect(BaseModel): + ftestwork = models.ForeignKey(FtestWork, verbose_name='关联检验工作', on_delete=models.CASCADE, + related_name='ftestwork_defect') + defect = models.ForeignKey(Defect, verbose_name='缺陷', on_delete=models.CASCADE) + count = models.PositiveIntegerField('数量', default=0) class Ftest(CommonBDModel): """ diff --git a/apps/qm/serializers.py b/apps/qm/serializers.py index 9a61a73b..287f6de5 100644 --- a/apps/qm/serializers.py +++ b/apps/qm/serializers.py @@ -1,6 +1,6 @@ from apps.qm.models import (QuaStat, TestItem, Ftest, FtestItem, FtestWork, Ptest, NotOkOption, Defect, Qct, QctTestItem, QctMat, - QctDefect, FtestDefect, FTEST_TYPE_CHOICES) + QctDefect, FtestDefect, FtestworkDefect) from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE from apps.utils.serializers import CustomModelSerializer from rest_framework import serializers @@ -8,6 +8,7 @@ from rest_framework.exceptions import ValidationError, ParseError from apps.wpm.models import SfLog, WMaterial from django.db import transaction from apps.inm.serializers import MaterialBatchDetailSerializer +from apps.mtm.models import Material class DefectSerializer(CustomModelSerializer): class Meta: @@ -114,52 +115,90 @@ class QuaStatUpdateSerializer(CustomModelSerializer): return super().validate(attrs) +class FtestworkdefectSerializer(CustomModelSerializer): + defect_name = serializers.CharField(source="defect.name", read_only=True) + class Meta: + model = FtestworkDefect + fields = "__all__" + read_only_fields = EXCLUDE_FIELDS_BASE + ["ftestwork"] + + class FtestWorkCreateUpdateSerializer(CustomModelSerializer): + ftestworkdefect = FtestworkdefectSerializer(many=True) class Meta: model = FtestWork fields = ['id', 'shift', 'wm', 'mb', 'type', 'type2', 'test_date', 'count', 'count_sampling', 'count_sampling_ok', 'count_ok', 'count_notok', 'count_notok_json', 'test_user', 'need_update_wm', - 'equipment', 'note'] + 'equipment', 'note', "qct", "ftestworkdefect"] extra_kwargs = {'test_user': {'required': True}, 'type': {'required': True}} def validate(self, attrs): + qct = attrs.get("qct", None) type2 = attrs.get('type2', 20) if type2 == 20: # 如果是全检 attrs['count_sampling'] = attrs['count'] if 'wm' in attrs and attrs['wm']: attrs['mb'] = None wm:WMaterial = attrs['wm'] + if wm.material.tracking != Material.MA_TRACKING_BATCH: + raise ParseError('只支持追踪批次的物料检验') if wm.state not in [WMaterial.WM_OK, WMaterial.WM_TEST]: raise ValidationError('不支持对该物料检验') attrs['material'] = wm.material attrs['batch'] = wm.batch count_notok_json = attrs.get('count_notok_json', None) - if count_notok_json is None: - raise ValidationError('不合格项不能为空') - count_notok = 0 - for k, v in count_notok_json.items(): - k_2 = k.replace('count_n_', '') - if k_2 not in NotOkOption.values: - raise ValidationError(f'不支持的不合格项{k_2}') - if isinstance(v, int) and v >= 0: - count_notok = count_notok + v - else: - raise ValidationError(f'不合格项{k_2}必须为非负整数') - attrs['count_notok'] = count_notok - if type2 == 20 and attrs['count'] != attrs['count_ok'] + attrs['count_notok']: - raise ValidationError('全检时总数必须等于合格数+不合格数') + if qct is None: # 没有qct时按原有逻辑处理 + if count_notok_json is None: + raise ValidationError('不合格项不能为空') + count_notok = 0 + for k, v in count_notok_json.items(): + k_2 = k.replace('count_n_', '') + if k_2 not in NotOkOption.values: + raise ValidationError(f'不支持的不合格项{k_2}') + if isinstance(v, int) and v >= 0: + count_notok = count_notok + v + else: + raise ValidationError(f'不合格项{k_2}必须为非负整数') + attrs['count_notok'] = count_notok + if type2 == 20 and attrs['count'] != attrs['count_ok'] + attrs['count_notok']: + raise ValidationError('全检时总数必须等于合格数+不合格数') elif 'mb' in attrs and attrs['mb']: attrs['wm'] = None attrs['material'] = attrs['mb'].material attrs['batch'] = attrs['mb'].batch + if attrs['material'].tracking != Material.MA_TRACKING_BATCH: + raise ParseError('只支持追踪批次的物料检验') else: raise ValidationError('请选择车间/仓库库存') if attrs['test_user']: attrs['belong_dept'] = attrs['test_user'].belong_dept return attrs + def create(self, validated_data): + ftestworkdefect = validated_data.pop("ftestworkdefect", []) + with transaction.atomic(): + ins: FtestWork = super().create(validated_data) + for ftestworkdefect in ftestworkdefect: + FtestworkDefect.objects.create(ftest=ins, **ftestworkdefect) + if ftestworkdefect: + ins.cal_count() + + def update(self, instance, validated_data): + ftestworkdefect = validated_data.pop("ftestworkdefect", []) + ins = super().update(instance, validated_data) + with transaction.atomic(): + for item in ftestworkdefect: + try: + ins = FtestworkDefect.objects.get(ftestwork=ins, defect=item["defect"]) + except FtestworkDefect.DoesNotExist: + raise ParseError("新的缺陷项!") + ins.count = item["count"] + ins.save() + if ftestworkdefect: + ins.cal_count() + return ins class FtestWorkSerializer(CustomModelSerializer): material_name = serializers.StringRelatedField(