From 1471e31aa4d8411ed91bd190441807f3d42180ad Mon Sep 17 00:00:00 2001 From: Mojtaba-z Date: Mon, 16 Jun 2025 10:44:12 +0330 Subject: [PATCH] fix update organization - set signal for calculate remaining quota weight after distribution --- apps/authentication/api/v1/api.py | 28 +++++++++++++++++++ .../api/v1/serializers/serializer.py | 10 +++---- apps/product/models.py | 1 + apps/product/signals.py | 19 +++++++++++++ apps/product/web/api/v1/product_api.py | 1 + .../api/v1/quota_distribution_serializers.py | 5 ++-- 6 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 apps/product/signals.py diff --git a/apps/authentication/api/v1/api.py b/apps/authentication/api/v1/api.py index 5962f18..6cdae40 100644 --- a/apps/authentication/api/v1/api.py +++ b/apps/authentication/api/v1/api.py @@ -221,6 +221,34 @@ class OrganizationViewSet(ModelViewSet): else: return Response(serializer.errors, status=status.HTTP_406_NOT_ACCEPTABLE) + @transaction.atomic + def update(self, request, *args, **kwargs): + """ update organization data """ + + partial = kwargs.pop('partial', False) + instance = self.get_object() # get organization instance + serializer = self.get_serializer( + instance, + data=request.data['organization'], + partial=partial + ) + serializer.is_valid(raise_exception=True) + organization = serializer.save() + + if 'user_relations' in request.data.keys(): + user_relations = CustomOperations().custom_update( # update user relations + request=request, + view=authorize_view.UserRelationViewSet(), + data_key='user_relations', + additional_data={'organization': organization.id} # noqa + ) + serializer_data = serializer.data + serializer_data.update( + {'user_relations': user_relations} + ) + return Response(serializer_data, status=status.HTTP_200_OK) + return Response(serializer.data, status=status.HTTP_200_OK) + @action( methods=['get'], detail=False, diff --git a/apps/authentication/api/v1/serializers/serializer.py b/apps/authentication/api/v1/serializers/serializer.py index 21c5adb..c1dcd72 100644 --- a/apps/authentication/api/v1/serializers/serializer.py +++ b/apps/authentication/api/v1/serializers/serializer.py @@ -214,15 +214,13 @@ class OrganizationSerializer(serializers.ModelSerializer): """ update user organization information """ # noqa instance.name = validated_data.get('name', instance.name) if validated_data.get('type'): - instance.type = OrganizationType.objects.get(id=validated_data.get('type', instance.type)) + instance.type = validated_data['type'] if validated_data.get('province'): - instance.province = Province.objects.get(id=validated_data.get('province', instance.province)) + instance.province = validated_data['province'] if validated_data.get('city'): - instance.city = City.objects.get(id=validated_data.get('city', instance.city)) + instance.city = validated_data['city'] if validated_data.get('parent_organization'): - instance.parent_organization = Organization.objects.get( - id=validated_data.get('parent_organization', instance.parent_organization) - ) + instance.parent_organization = validated_data['parent_organization'] instance.national_unique_id = validated_data.get('national_unique_id', instance.national_unique_id) instance.save() return instance diff --git a/apps/product/models.py b/apps/product/models.py index bdcfd71..10ccf38 100644 --- a/apps/product/models.py +++ b/apps/product/models.py @@ -246,6 +246,7 @@ class Quota(BaseModel): quota_id = models.PositiveBigIntegerField(null=True, blank=True) quota_code = models.CharField(max_length=15, null=True) quota_weight = models.PositiveIntegerField(default=0) + remaining_quota_weight = models.PositiveBigIntegerField(default=0) quota_distributed = models.PositiveIntegerField(default=0) quota_balance = models.PositiveIntegerField(default=0) product = models.ForeignKey( diff --git a/apps/product/signals.py b/apps/product/signals.py new file mode 100644 index 0000000..89150aa --- /dev/null +++ b/apps/product/signals.py @@ -0,0 +1,19 @@ +from django.db.models import Sum +from django.db.models.signals import post_save, post_delete +from django.dispatch import receiver +from .models import QuotaDistribution, Quota + + +def recalculate_remaining_amount(quota): + total_distributed = quota.distributions.aggregate( + total=Sum('amount_kg') + )['total'] or 0 + + quota.remaining_amount_kg = quota.total_amount_kg - total_distributed + quota.save(update_fields=["remaining_amount_kg"]) + + +@receiver(post_save, sender=QuotaDistribution) +@receiver(post_delete, sender=QuotaDistribution) +def update_quota_remaining(sender, instance, **kwargs): + recalculate_remaining_amount(instance.quota) diff --git a/apps/product/web/api/v1/product_api.py b/apps/product/web/api/v1/product_api.py index 33d95ff..6344f79 100644 --- a/apps/product/web/api/v1/product_api.py +++ b/apps/product/web/api/v1/product_api.py @@ -352,6 +352,7 @@ class QuotaViewSet(viewsets.ModelViewSet): # noqa serializer = self.serializer_class(data=request.data) if serializer.is_valid(): quota = serializer.save() + quota.remaining_quota_weight = quota.quota_weight # create incentive plan if 'incentive_plan_data' in request.data.keys(): diff --git a/apps/product/web/api/v1/quota_distribution_serializers.py b/apps/product/web/api/v1/quota_distribution_serializers.py index 29596e8..f75844d 100644 --- a/apps/product/web/api/v1/quota_distribution_serializers.py +++ b/apps/product/web/api/v1/quota_distribution_serializers.py @@ -20,7 +20,7 @@ class QuotaDistributionSerializer(serializers.ModelSerializer): """ to validate if distribution weight more than quota weight raise exception """ - quota = product_models.Quota.objects.get(id=data['quota']) + quota = data['quota'] amount = data['weight'] instance_id = self.instance.id if self.instance else None @@ -29,8 +29,7 @@ class QuotaDistributionSerializer(serializers.ModelSerializer): ).exclude(id=instance_id).aggregate( total=models.Sum('weight') )['total'] or 0 - print(total) - if total + amount > self.instance.weight: + if total + amount > quota.quota_weight: raise QuotaWeightException() return data