From 4e5319b6256852eb5a970706dcfc1cfd88bf08e3 Mon Sep 17 00:00:00 2001 From: Mojtaba-z Date: Tue, 18 Nov 2025 09:11:35 +0330 Subject: [PATCH] fix - custom APIExceptions for quota stats --- apps/product/exceptions.py | 38 +++++++++++++++++++ .../validators/quota_stats_validator.py | 31 +++++++++++---- .../api/v1/serializers/quota_serializers.py | 9 +++-- 3 files changed, 67 insertions(+), 11 deletions(-) diff --git a/apps/product/exceptions.py b/apps/product/exceptions.py index 6a7a919..0f16526 100644 --- a/apps/product/exceptions.py +++ b/apps/product/exceptions.py @@ -2,6 +2,44 @@ from rest_framework import status from rest_framework.exceptions import APIException +class QuotaException(APIException): + """ if quota is not available """ + + status_code = status.HTTP_400_BAD_REQUEST + default_detail = "خطا در اطلاعات سهمیه" # noqa + default_code = 'error' + + def __init__(self, message=None, status_code=None, code=None): + if status_code is not None: + self.status_code = status_code + + detail = { + "message": message, + "status_code": status_code + } + + super().__init__(detail) + + +class DistributionException(APIException): + """ if distribution is not available """ + + status_code = status.HTTP_400_BAD_REQUEST + default_detail = "خطا در اطلاعات توزیع." # noqa + default_code = 'error' + + def __init__(self, message=None, status_code=None, code=None): + if status_code is not None: + self.status_code = status_code + + detail = { + "message": message, + "status_code": status_code + } + + super().__init__(detail) + + class QuotaWeightException(APIException): """ if quota distributions weight is more """ diff --git a/apps/product/validators/quota_stats_validator.py b/apps/product/validators/quota_stats_validator.py index de05dce..5175afc 100644 --- a/apps/product/validators/quota_stats_validator.py +++ b/apps/product/validators/quota_stats_validator.py @@ -1,6 +1,8 @@ from django.apps import apps from django.core.exceptions import ValidationError -from rest_framework.exceptions import APIException +from rest_framework import status + +from apps.product.exceptions import DistributionException def get_model(app_label, model_name): @@ -15,28 +17,41 @@ class QuotaStatsValidator: @staticmethod def _get_stat(quota, organization): organization_quota_stats = get_model("product", "OrganizationQuotaStats") - return organization_quota_stats.objects.filter(quota=quota, organization=organization).first() + return organization_quota_stats.objects.filter(quota=quota, organization=organization).first() # noqa @staticmethod - def validate_assigner_has_enough(assigner_org, quota, amount, allow_zero=False): + def validate_assigner_has_enough(assigner_org, quota, amount, allow_zero=False, update_operation=None): """ if organization has enough remaining weight """ stat = QuotaStatsValidator._get_stat(quota, assigner_org) if not stat: - raise APIException(f"Organization {assigner_org} has no quota record for quota {quota}.") + raise DistributionException( + f"سازمان {assigner_org.name} هیچ مدل میانی برای این سهمیه {quota} ندارد .", # noqa + status.HTTP_403_FORBIDDEN + ) remaining = getattr(stat, "remaining_amount", None) if remaining is None: # fallback to quota.remaining_weight subtraction from totals - raise APIException("remaining_amount field missing in OrganizationQuotaStats.") + raise DistributionException( + "فیلد باقی مانده در مدل میانی وجود ندارد", # noqa + status.HTTP_403_FORBIDDEN + ) if amount < 0: - raise APIException("Amount must be non-negative.") + raise DistributionException("مقدار وزن نباید منفی باشد", status.HTTP_403_FORBIDDEN) # noqa if remaining < amount and not allow_zero: - raise APIException( - f"Assigning {amount} exceeds remaining amount {remaining} for organization {assigner_org}." + if update_operation: + raise DistributionException( + "مقدار وزن ویرایش شده از وزن باقیمانده بیشتر است", # noqa + status.HTTP_403_FORBIDDEN + ) + raise DistributionException( + f"تخصیص مقدار {amount} بیشتر از مقدار باقیمانده {remaining} برای سازمان {assigner_org.name} میباشد.", + # noqa + status.HTTP_403_FORBIDDEN ) @staticmethod diff --git a/apps/product/web/api/v1/serializers/quota_serializers.py b/apps/product/web/api/v1/serializers/quota_serializers.py index 27c9bc3..a3c9008 100644 --- a/apps/product/web/api/v1/serializers/quota_serializers.py +++ b/apps/product/web/api/v1/serializers/quota_serializers.py @@ -1,8 +1,8 @@ -from rest_framework import serializers -from rest_framework.exceptions import APIException +from rest_framework import serializers, status from apps.livestock.web.api.v1.serializers import LiveStockTypeSerializer from apps.product import models as product_models +from apps.product.exceptions import QuotaException from apps.product.web.api.v1.serializers import product_serializers @@ -15,7 +15,10 @@ class QuotaSerializer(serializers.ModelSerializer): weight = attrs['quota_weight'] if self.instance: if self.instance.quota_distributed < weight: - raise APIException("Quota weight cannot be less than distributed weight.") + raise QuotaException( + "وزن سهمیه نمیتواند کمتر از وزن توزیع شده باشد", # noqa + status.HTTP_403_FORBIDDEN + ) return attrs def to_representation(self, instance: product_models.Quota):