From d5d940c5e4db18e6b8872952812caa1011d5ec81 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 28 Jul 2026 16:11:11 +0800 Subject: [PATCH] Fix handover mgroup filtering --- apps/wpm/filters.py | 16 ++++-- apps/wpm/serializers.py | 9 +++- apps/wpm/tests.py | 110 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 126 insertions(+), 9 deletions(-) diff --git a/apps/wpm/filters.py b/apps/wpm/filters.py index fd0c496e..68772d9f 100644 --- a/apps/wpm/filters.py +++ b/apps/wpm/filters.py @@ -171,15 +171,23 @@ class HandoverFilter(filters.FilterSet): dept = filters.CharFilter(label='DeptId', method='filter_dept') def filter_mgroup(self, queryset, name, value): - return queryset.filter(send_mgroup__id=value)|queryset.filter(recive_mgroup__id=value) + return queryset.filter( + Q(send_mgroup_id=value) | Q(recive_mgroup_id=value) + ) def filter_mgroupx(self, queryset, name, value): dept = Mgroup.objects.get(id=value).belong_dept - return (queryset.filter(send_mgroup__id=value)|queryset.filter(recive_mgroup__id=value)| - queryset.filter(send_dept=dept, send_mgroup__isnull=True)|queryset.filter(recive_dept=dept, recive_mgroup__isnull=True)) + return queryset.filter( + Q(send_mgroup_id=value) + | Q(recive_mgroup_id=value) + | Q(send_dept=dept, send_mgroup__isnull=True) + | Q(recive_dept=dept, recive_mgroup__isnull=True) + ) def filter_dept(self, queryset, name, value): - return queryset.filter(send_dept__id=value)|queryset.filter(recive_dept__id=value) + return queryset.filter( + Q(send_dept_id=value) | Q(recive_dept_id=value) + ) def filter_cbatch(self, queryset, name, value): qs1 = queryset.filter(Q(batch=value)|Q(new_batch=value)|Q(wm__batch=value)) diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index d6d94b54..57bc8dfa 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -1315,9 +1315,14 @@ class HandoverSerializer(CustomModelSerializer): else: raise ParseError('必须指定车间库存') attrs['material'] = wm.material - attrs['send_dept'] = wm.belong_dept - attrs['send_mgroup'] = wm.mgroup is_global_source = wm.mgroup_id is None and wm.belong_dept_id is None + send_mgroup = attrs.get('send_mgroup') + if send_mgroup: + attrs['send_dept'] = send_mgroup.belong_dept + else: + attrs['send_dept'] = wm.belong_dept + if not send_mgroup and wm.mgroup: + attrs['send_mgroup'] = wm.mgroup if ( is_global_source diff --git a/apps/wpm/tests.py b/apps/wpm/tests.py index ac8e412b..2be91028 100644 --- a/apps/wpm/tests.py +++ b/apps/wpm/tests.py @@ -5,17 +5,98 @@ from types import SimpleNamespace from unittest.mock import MagicMock, patch from django.db import connection, connections, transaction -from django.test import SimpleTestCase, TransactionTestCase +from django.test import SimpleTestCase, TestCase, TransactionTestCase from unittest import skipUnless -from apps.mtm.models import Material, WmScope -from apps.wpm.filters import WMaterialFilter +from apps.mtm.models import Material, Mgroup, WmScope +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.views import MlogbwViewSet from rest_framework.exceptions import ParseError +class HandoverFilterTests(TestCase): + @classmethod + def setUpTestData(cls): + cls.dept = Dept.objects.create(name="交接筛选测试车间") + cls.other_dept = Dept.objects.create(name="其他测试车间") + cls.mgroup = Mgroup.objects.create( + name="交接筛选测试工段", + belong_dept=cls.dept, + ) + cls.peer_mgroup = Mgroup.objects.create( + name="同车间其他工段", + belong_dept=cls.dept, + ) + cls.other_mgroup = Mgroup.objects.create( + name="其他车间工段", + belong_dept=cls.other_dept, + ) + cls.user = User.objects.create_user(username="handover-filter-user") + cls.material = Material.objects.create(name="交接筛选测试物料") + + @classmethod + def create_handover(cls, **kwargs): + defaults = { + "send_date": "2026-07-28", + "send_user": cls.user, + "material": cls.material, + } + defaults.update(kwargs) + return Handover.objects.create(**defaults) + + def test_mgroup_only_returns_records_involving_the_selected_mgroup(self): + sent = self.create_handover( + send_mgroup=self.mgroup, + recive_mgroup=self.peer_mgroup, + ) + received = self.create_handover( + send_mgroup=self.peer_mgroup, + recive_mgroup=self.mgroup, + ) + self.create_handover( + send_mgroup=self.peer_mgroup, + recive_mgroup=self.other_mgroup, + ) + + queryset = HandoverFilter( + {"mgroup": self.mgroup.id}, + queryset=Handover.objects.all(), + ).qs + + self.assertCountEqual(queryset.values_list("id", flat=True), [ + sent.id, + received.id, + ]) + + def test_mgroupx_adds_only_department_level_records_for_same_dept(self): + direct = self.create_handover(send_mgroup=self.mgroup) + dept_level = self.create_handover( + send_dept=self.dept, + send_mgroup=None, + ) + self.create_handover( + send_mgroup=self.peer_mgroup, + recive_mgroup=self.other_mgroup, + ) + self.create_handover( + send_dept=self.other_dept, + send_mgroup=None, + ) + + queryset = HandoverFilter( + {"mgroupx": self.mgroup.id}, + queryset=Handover.objects.all(), + ).qs + + self.assertCountEqual(queryset.values_list("id", flat=True), [ + direct.id, + dept_level.id, + ]) + + class MlogbwViewSetTests(SimpleTestCase): @patch("apps.wpm.views.MlogViewSet.lock_and_check_can_update") @patch("apps.wpm.views.Mlogbw.cal_count_notok") @@ -242,6 +323,29 @@ class WMaterialScopeTests(SimpleTestCase): "mtype": Handover.H_NORMAL, }) + def test_handover_keeps_explicit_sending_mgroup(self): + inventory_dept = Dept(id="20", name="库存车间") + sending_dept = Dept(id="30", name="送料车间") + mgroup = Mgroup(id="10", name="测试工段", belong_dept=sending_dept) + wm = WMaterial( + material=Material(tracking=Material.MA_TRACKING_BATCH), + batch="DEPT-001", + count=1, + belong_dept=inventory_dept, + ) + + validated = HandoverSerializer().validate({ + "wm": wm, + "count": 1, + "send_mgroup": mgroup, + "recive_dept": object(), + "type": Handover.H_NORMAL, + "mtype": Handover.H_NORMAL, + }) + + self.assertIs(validated["send_mgroup"], mgroup) + self.assertIs(validated["send_dept"], sending_dept) + @skipUnless( connection.vendor == "postgresql",