From 3f62e8709f113ebc3c41a5a5b94b7fe429bb468c Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 31 Jul 2024 19:18:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=87=87=E8=B4=AD=E8=AE=A1=E5=88=92?= =?UTF-8?q?=E5=92=8C=E8=AE=A2=E5=8D=95=E5=A2=9E=E5=8A=A0=E5=8D=95=E4=BB=B7?= =?UTF-8?q?=E5=92=8C=E6=80=BB=E4=BB=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pum/migrations/0008_auto_20240731_1829.py | 43 +++++++++++++++++++ apps/pum/models.py | 6 +++ apps/pum/serializers.py | 28 +++++++++--- apps/pum/services.py | 12 +++++- apps/pum/views.py | 15 +++++-- 5 files changed, 93 insertions(+), 11 deletions(-) create mode 100644 apps/pum/migrations/0008_auto_20240731_1829.py diff --git a/apps/pum/migrations/0008_auto_20240731_1829.py b/apps/pum/migrations/0008_auto_20240731_1829.py new file mode 100644 index 00000000..2d4efb71 --- /dev/null +++ b/apps/pum/migrations/0008_auto_20240731_1829.py @@ -0,0 +1,43 @@ +# Generated by Django 3.2.12 on 2024-07-31 10:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pum', '0007_supplier_number'), + ] + + operations = [ + migrations.AddField( + model_name='puorder', + name='total_price', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=14, null=True, verbose_name='总价'), + ), + migrations.AddField( + model_name='puorderitem', + name='total_price', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=14, null=True, verbose_name='总价'), + ), + migrations.AddField( + model_name='puorderitem', + name='unit_price', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=14, null=True, verbose_name='单价'), + ), + migrations.AddField( + model_name='puplan', + name='total_price', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=14, null=True, verbose_name='总价'), + ), + migrations.AddField( + model_name='puplanitem', + name='total_price', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=14, null=True, verbose_name='总价'), + ), + migrations.AddField( + model_name='puplanitem', + name='unit_price', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=14, null=True, verbose_name='单价'), + ), + ] diff --git a/apps/pum/models.py b/apps/pum/models.py index f88ae489..df42ab11 100644 --- a/apps/pum/models.py +++ b/apps/pum/models.py @@ -39,6 +39,7 @@ class PuPlan(CommonBModel): submit_time = models.DateTimeField('提交时间', null=True, blank=True) submit_user = models.ForeignKey( 'system.user', verbose_name='提交人', related_name='submit_user_puplan', on_delete=models.CASCADE, null=True, blank=True) + total_price = models.DecimalField('总价', max_digits=14, decimal_places=2, null=True, blank=True) class PuOrder(CommonBModel): @@ -66,6 +67,7 @@ class PuOrder(CommonBModel): 'system.user', verbose_name='提交人', related_name='submit_user_puorder', on_delete=models.CASCADE, null=True, blank=True) materials = models.ManyToManyField( Material, verbose_name='多个物料', blank=True, through='pum.puorderitem', related_name='pu_order_materials') + total_price = models.DecimalField('总价', max_digits=14, decimal_places=2, null=True, blank=True) class PuOrderItem(BaseModel): @@ -73,6 +75,8 @@ class PuOrderItem(BaseModel): Material, verbose_name='物料', on_delete=models.CASCADE, related_name='pu_orderitem_material') count = models.PositiveIntegerField('所需数量', default=0) delivered_count = models.PositiveIntegerField('已到货数量', default=0) + unit_price = models.DecimalField('单价', max_digits=14, decimal_places=2, null=True, blank=True) + total_price = models.DecimalField('总价', max_digits=14, decimal_places=2, null=True, blank=True) pu_order = models.ForeignKey(PuOrder, verbose_name='关联采购订单', on_delete=models.CASCADE, null=True, blank=True, related_name='item_puorder') @@ -85,6 +89,8 @@ class PuPlanItem(CommonBDModel): Material, verbose_name='所需物料', on_delete=models.CASCADE) need_count = models.PositiveIntegerField('所属数量') need_date = models.DateField('需求日期') + unit_price = models.DecimalField('单价', max_digits=14, decimal_places=2, null=True, blank=True) + total_price = models.DecimalField('总价', max_digits=14, decimal_places=2, null=True, blank=True) note = models.TextField('备注', default='') pu_plan = models.ForeignKey(PuPlan, verbose_name='采购计划', on_delete=models.CASCADE, null=True, blank=True, related_name='item_puplan') diff --git a/apps/pum/serializers.py b/apps/pum/serializers.py index 384d0d73..c216ab93 100644 --- a/apps/pum/serializers.py +++ b/apps/pum/serializers.py @@ -5,6 +5,8 @@ from rest_framework.exceptions import ValidationError from apps.pum.models import Supplier, PuPlan, PuPlanItem, PuOrder, PuOrderItem from apps.mtm.serializers import MaterialSerializer, MaterialSimpleSerializer +from django.db import transaction +from .services import PumService class SupplierSerializer(CustomModelSerializer): @@ -18,7 +20,7 @@ class PuPlanSerializer(CustomModelSerializer): class Meta: model = PuPlan fields = '__all__' - read_only_fields = EXCLUDE_FIELDS_DEPT + ['state', 'submit_time'] + read_only_fields = EXCLUDE_FIELDS_DEPT + ['state', 'submit_time', 'total_price'] def update(self, instance, validated_data): if instance.state != PuPlan.PUPLAN_CREATE: @@ -41,6 +43,7 @@ class PuPlanItemSerializer(CustomModelSerializer): fields = '__all__' read_only_fields = EXCLUDE_FIELDS + ['pu_order'] + @transaction.atomic def create(self, validated_data): pu_plan = validated_data['pu_plan'] if pu_plan.state != PuPlan.PUPLAN_CREATE: @@ -49,7 +52,9 @@ class PuPlanItemSerializer(CustomModelSerializer): self.complete_belong_dept(validated_data) if PuPlanItem.objects.filter(material=material, belong_dept=validated_data['belong_dept']).exists(): raise ValidationError('同部门已提交该物料需求,请确认!') - return super().create(validated_data) + ins = super().create(validated_data) + PumService.cal_pu_plan_total_price(pu_plan) + return ins def complete_belong_dept(self, validated_data): belong_dept = validated_data.get('belong_dept', None) @@ -59,7 +64,8 @@ class PuPlanItemSerializer(CustomModelSerializer): raise ValidationError('所属部门不可为空') else: validated_data['belong_dept'] = belong_dept - + + @transaction.atomic def update(self, instance, validated_data): validated_data.pop('pu_plan') pu_plan = instance.pu_plan @@ -73,7 +79,9 @@ class PuPlanItemSerializer(CustomModelSerializer): self.complete_belong_dept(validated_data) if PuPlanItem.objects.exclude(id=instance.id).filter(material=material, belong_dept=validated_data['belong_dept']).exists(): raise ValidationError('同部门已提交该物料需求,请确认!') - return super().update(instance, validated_data) + ins = super().update(instance, validated_data) + PumService.cal_pu_plan_total_price(pu_plan) + return ins class PuOrderSerializer(CustomModelSerializer): @@ -89,7 +97,7 @@ class PuOrderSerializer(CustomModelSerializer): class Meta: model = PuOrder fields = '__all__' - read_only_fields = EXCLUDE_FIELDS_DEPT + ['state', 'submit_time'] + read_only_fields = EXCLUDE_FIELDS_DEPT + ['state', 'submit_time', 'total_price'] def update(self, instance, validated_data): validated_data.pop('supplier') @@ -106,6 +114,7 @@ class PuOrderItemSerializer(CustomModelSerializer): fields = '__all__' read_only_fields = EXCLUDE_FIELDS_BASE + ['delivered_count'] + @transaction.atomic def create(self, validated_data): pu_order = validated_data['pu_order'] material = validated_data['material'] @@ -113,15 +122,20 @@ class PuOrderItemSerializer(CustomModelSerializer): raise ValidationError('采购订单该状态下不可添加明细') if PuOrderItem.objects.filter(pu_order=pu_order, material=material).exists(): raise ValidationError('该物料已添加') - return super().create(validated_data) + ins = super().create(validated_data) + PumService.cal_pu_order_total_price(pu_order) + return ins + @transaction.atomic def update(self, instance, validated_data): validated_data.pop('material') validated_data.pop('pu_order') pu_order = instance.pu_order if pu_order.state != PuOrder.PUORDER_CREATE: raise ValidationError('采购订单该状态下不可编辑') - return super().update(instance, validated_data) + ins = super().update(instance, validated_data) + PumService.cal_pu_order_total_price(pu_order) + return ins class AddSerializer(serializers.Serializer): diff --git a/apps/pum/services.py b/apps/pum/services.py index cd54e4a9..ac7aaa92 100644 --- a/apps/pum/services.py +++ b/apps/pum/services.py @@ -1,11 +1,21 @@ from rest_framework.exceptions import ValidationError from apps.pum.models import PuOrderItem, PuPlan, PuPlanItem, PuOrder -from django.db.models import F +from django.db.models import F, Sum from apps.inm.models import MIO, MIOItem class PumService: + def cal_pu_order_total_price(puorder: PuOrder): + total_price = PuOrderItem.objects.filter(pu_order=puorder).aggregate(total=Sum("total_price"))["total"] or 0 + puorder.total_price = total_price + puorder.save() + + def cal_pu_plan_total_price(puplan: PuPlan): + total_price = PuPlanItem.objects.filter(pu_plan=puplan).aggregate(total=Sum("total_price"))["total"] or 0 + puplan.total_price = total_price + puplan.save() + def change_puplan_state_when_puorder_sumbit(puorder: PuOrder): puplanIds = PuPlanItem.objects.filter( pu_order=puorder).values_list('pu_plan', flat=True) diff --git a/apps/pum/views.py b/apps/pum/views.py index 3b7044b7..140a4f95 100644 --- a/apps/pum/views.py +++ b/apps/pum/views.py @@ -45,7 +45,7 @@ class PuPlanViewSet(CustomModelViewSet): def perform_destroy(self, instance): if PuPlanItem.objects.filter(pu_plan=instance).exists(): raise ParseError('该计划存在明细不可删除') - return super().perform_destroy(instance) + instance.delete(soft=False) @action(methods=['post'], detail=True, perms_map={'post': 'pu_plan.submit'}, serializer_class=serializers.Serializer) def submit(self, request, *args, **kwargs): @@ -80,6 +80,7 @@ class PuPlanItemViewSet(CustomModelViewSet): ordering_fields = ['create_time', 'material', 'need_date', 'need_count'] ordering = ['create_time'] + @transaction.atomic def perform_destroy(self, instance): user = self.request.user pu_plan = instance.pu_plan @@ -87,7 +88,8 @@ class PuPlanItemViewSet(CustomModelViewSet): raise ParseError('非创建人不可删除') elif instance.pu_order is not None: raise ParseError('存在采购订单不可删除') - return super().perform_destroy(instance) + instance.delete() + PumService.cal_pu_plan_total_price(pu_plan) class PuOrderViewSet(CustomModelViewSet): @@ -149,6 +151,7 @@ class PuOrderItemViewSet(CustomModelViewSet): if pu_order.state != PuOrder.PUORDER_CREATE: raise ParseError('采购订单非创建中不可删除') instance.delete() + PumService.cal_pu_order_total_price(pu_order) @action(methods=['post'], detail=False, perms_map={'post': 'pu_order.update'}, serializer_class=AddSerializer) @transaction.atomic @@ -172,10 +175,16 @@ class PuOrderItemViewSet(CustomModelViewSet): puorderitem, is_created = PuOrderItem.objects.get_or_create( pu_order=puorder, material=item.material, defaults={'pu_order': puorder, - 'material': item.material, 'count': item.need_count} + 'material': item.material, + 'count': item.need_count, + 'unit_price': item.unit_price, + 'total_price': item.total_price + } ) if not is_created: puorderitem.count = puorderitem.count + item.need_count + if item.total_price: + puorderitem.total_price = puorderitem.total_price if puorderitem.total_price else 0 + item.total_price puorderitem.save() if puorder.delivery_date is None: puorder.delivery_date = item.need_date