diff --git a/apps/wpm/filters.py b/apps/wpm/filters.py index 68772d9f..705ef4f6 100644 --- a/apps/wpm/filters.py +++ b/apps/wpm/filters.py @@ -132,7 +132,8 @@ class WMaterialFilter(filters.FilterSet): "notok_sign": ["exact", "in", "isnull"], "count_xtest": ["gte", "isnull"], "supplier": ["exact"], - "defect": ["exact", "isnull"] + "defect": ["exact", "isnull"], + "defect__okcate": ["exact", "in"], } class MlogFilter(filters.FilterSet): diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index 7b53df64..c01dae8c 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -190,12 +190,20 @@ class WMaterialSerializer(CustomModelSerializer): notok_sign_name = serializers.SerializerMethodField() defect_name = serializers.CharField(source="defect.name", read_only=True) defect_okcate = serializers.IntegerField(source="defect.okcate", read_only=True) + defect_grade = serializers.SerializerMethodField() + defect_grade_name = serializers.SerializerMethodField() count_working = serializers.SerializerMethodField(label='在制数量') count_handovering = serializers.SerializerMethodField(label='正在交送的数量') def get_notok_sign_name(self, obj): return getattr(NotOkOption, obj.notok_sign, NotOkOption.qt).label if obj.notok_sign else None + def get_defect_grade(self, obj): + return obj.defect.okcate if obj.defect else None + + def get_defect_grade_name(self, obj): + return obj.defect.get_okcate_display() if obj.defect else None + def get_count_working(self, obj): # 列表接口 queryset 已注解(单次聚合); 嵌套等无注解场景回退模型属性 # 保留 decimal 精度(原 IntegerField 会截断在途量, 导致可用/可交接量偏大) diff --git a/apps/wpm/tests.py b/apps/wpm/tests.py index 22a10353..189faf9e 100644 --- a/apps/wpm/tests.py +++ b/apps/wpm/tests.py @@ -13,7 +13,11 @@ from apps.qm.models import Defect from apps.system.models import Dept, User from apps.wpm.filters import HandoverFilter, WMaterialFilter from apps.wpm.models import Handover, WMaterial -from apps.wpm.serializers import HandoverSerializer, WMaterialCreateSerializer +from apps.wpm.serializers import ( + HandoverSerializer, + WMaterialCreateSerializer, + WMaterialSerializer, +) from apps.wpm.services import restore_mlog_wpr_defects, snapshot_mlog_wpr_defects from apps.wpm.views import MlogbwViewSet from apps.wpmw.models import Wpr, WprDefect @@ -100,6 +104,87 @@ class HandoverFilterTests(TestCase): ]) +class WMaterialDefectGradeTests(TestCase): + @classmethod + def setUpTestData(cls): + cls.material = Material.objects.create(name="缺陷等级测试物料") + cls.defect_b = Defect.objects.create( + name="B类缺陷", + cate=Defect.cate_list[0], + okcate=Defect.DEFECT_OK_B, + ) + cls.defect_notok = Defect.objects.create( + name="不合格缺陷", + cate=Defect.cate_list[0], + okcate=Defect.DEFECT_NOTOK, + ) + cls.normal_with_notok_defect = WMaterial.objects.create( + material=cls.material, + batch="NORMAL-NOTOK", + count=1, + state=WMaterial.WM_OK, + defect=cls.defect_notok, + ) + cls.notok_with_b_defect = WMaterial.objects.create( + material=cls.material, + batch="NOTOK-B", + count=1, + state=WMaterial.WM_NOTOK, + defect=cls.defect_b, + ) + cls.normal_without_defect = WMaterial.objects.create( + material=cls.material, + batch="NORMAL-NONE", + count=1, + state=WMaterial.WM_OK, + ) + + def test_serializer_exposes_nullable_defect_grade_without_using_state(self): + normal_notok_data = WMaterialSerializer( + self.normal_with_notok_defect + ).data + notok_b_data = WMaterialSerializer(self.notok_with_b_defect).data + no_defect_data = WMaterialSerializer(self.normal_without_defect).data + + self.assertEqual( + normal_notok_data["defect_grade"], Defect.DEFECT_NOTOK + ) + self.assertEqual(normal_notok_data["defect_grade_name"], "不合格") + self.assertEqual( + notok_b_data["defect_grade"], Defect.DEFECT_OK_B + ) + self.assertEqual(notok_b_data["defect_grade_name"], "合格B类") + self.assertIsNone(no_defect_data["defect_grade"]) + self.assertIsNone(no_defect_data["defect_grade_name"]) + + def test_filtering_state_and_defect_grade_are_independent(self): + normal_notok = WMaterialFilter( + { + "state": WMaterial.WM_OK, + "defect__okcate": Defect.DEFECT_NOTOK, + }, + queryset=WMaterial.objects.all(), + ).qs + notok_b = WMaterialFilter( + { + "state": WMaterial.WM_NOTOK, + "defect__okcate": Defect.DEFECT_OK_B, + }, + queryset=WMaterial.objects.all(), + ).qs + + self.assertQuerySetEqual( + normal_notok, + [self.normal_with_notok_defect], + transform=lambda item: item, + ) + self.assertQuerySetEqual( + notok_b, + [self.notok_with_b_defect], + transform=lambda item: item, + ) + + class MlogbwViewSetTests(SimpleTestCase): @patch("apps.wpm.views.MlogViewSet.lock_and_check_can_update") @patch("apps.wpm.views.Mlogbw.cal_count_notok")