From 320822019a2dfb3dc97db80ed7ba726afe1b6a4d Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 27 Mar 2026 10:08:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20WMaterialViewSet=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=89=8B=E5=8A=A8=E6=9D=A5=E6=96=99=E5=88=9B=E5=BB=BA=E5=92=8C?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 WMaterialCreateSerializer,validate 中自动推导 belong_dept - ViewSet 使用 create_serializer_class,perform_create 设置 is_manual=True - 删除校验逻辑移至模型 delete 方法,校验 is_manual 及关联记录(mlogb/handoverb/ftestwork/mioitem) Co-Authored-By: Claude Sonnet 4.6 --- apps/wpm/models.py | 14 ++++++++++++++ apps/wpm/serializers.py | 10 ++++++++++ apps/wpm/views.py | 6 +++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/apps/wpm/models.py b/apps/wpm/models.py index ad38dbed..0840bf6b 100644 --- a/apps/wpm/models.py +++ b/apps/wpm/models.py @@ -128,6 +128,20 @@ class WMaterial(CommonBDModel): number_from = models.TextField("来源于个号", null=True, blank=True) is_manual = models.BooleanField('手动创建', default=False) + def delete(self, *args, **kwargs): + if not self.is_manual: + raise ParseError('只能删除手动创建的车间库存') + checks = [ + (self.mlogb_set.exists, '存在关联的生产明细'), + (self.handoverb_wm.exists, '存在关联的交接明细'), + (self.ftestwork_set.exists, '存在关联的检验记录'), + (self.wm_mioitem.exists, '存在关联的出入库明细'), + ] + for check, msg in checks: + if check(): + raise ParseError(msg) + super().delete(*args, **kwargs) + @property def belong_dept_or_mgroup_id(self): return self.mgroup.id if self.mgroup else self.belong_dept.id diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index 80331c9e..1788594f 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -207,6 +207,16 @@ class WMaterialSerializer(CustomModelSerializer): ret['count_canhandover'] = str(Decimal(ret['count']) - Decimal(ret['count_handovering'])) return ret +class WMaterialCreateSerializer(CustomModelSerializer): + class Meta: + model = WMaterial + fields = ['material', 'count', 'batch', 'mgroup'] + + def validate(self, attrs): + attrs['belong_dept'] = attrs['mgroup'].belong_dept + return attrs + + class MlogbDefectSerializer(CustomModelSerializer): defect_name = serializers.CharField(source="defect.name", read_only=True) defect_okcate = serializers.CharField(source="defect.okcate", read_only=True) diff --git a/apps/wpm/views.py b/apps/wpm/views.py index 19c3b24b..2dc9145c 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -21,6 +21,7 @@ from .serializers import ( SfLogSerializer, StLogSerializer, WMaterialSerializer, + WMaterialCreateSerializer, MlogRevertSerializer, MlogSerializer, MlogRelatedSerializer, @@ -173,6 +174,7 @@ class WMaterialViewSet(CustomCreateModelMixin, DestroyModelMixin, CustomListMode perms_map = {"get": "*", "post": "wmaterial.create", "delete": "wmaterial.delete"} queryset = WMaterial.objects.filter(count__gt=0) serializer_class = WMaterialSerializer + create_serializer_class = WMaterialCreateSerializer select_related_fields = ["material", "belong_dept", "material__process", "supplier"] search_fields = ["material__name", "material__specification", "batch", "material__model", "defect__name", "notok_sign"] filterset_class = WMaterialFilter @@ -190,11 +192,9 @@ class WMaterialViewSet(CustomCreateModelMixin, DestroyModelMixin, CustomListMode return queryset.exclude(state=WMaterial.WM_SCRAP) def perform_create(self, serializer): - serializer.save(create_by=self.request.user, belong_dept=self.request.user.dept, is_manual=True) + serializer.save(create_by=self.request.user, is_manual=True) def perform_destroy(self, instance): - if not instance.is_manual: - raise ParseError('只能删除手动创建的车间库存') instance.delete() @action(methods=["post"], detail=False, perms_map={"post": "*"}, serializer_class=DeptBatchSerializer)