add - import validator for organization quota stats
This commit is contained in:
@@ -1,15 +1,23 @@
|
||||
from apps.product.models import QuotaDistribution, OrganizationQuotaStats
|
||||
from apps.product.validators.quota_stats_validator import QuotaStatsValidator
|
||||
|
||||
|
||||
class QuotaStatsService:
|
||||
@staticmethod
|
||||
def apply_distribution(distribution: QuotaDistribution):
|
||||
quota = distribution.quota
|
||||
|
||||
print("ssss")
|
||||
# origin org
|
||||
assigner = distribution.assigner_organization
|
||||
# destination org
|
||||
assigned = distribution.assigned_organization
|
||||
|
||||
QuotaStatsValidator.validate_assigner_has_enough(
|
||||
assigner_org=assigner,
|
||||
quota=quota,
|
||||
amount=distribution.weight
|
||||
)
|
||||
|
||||
# ================ origin ================
|
||||
assigner_stat, created = OrganizationQuotaStats.objects.get_or_create(
|
||||
organization=assigner,
|
||||
@@ -46,6 +54,14 @@ class QuotaStatsService:
|
||||
assigner = distribution.assigner_organization
|
||||
assigned = distribution.assigned_organization
|
||||
|
||||
QuotaStatsValidator.validate_distribution_update(
|
||||
assigner_org=assigner,
|
||||
assigned_org=assigned,
|
||||
quota=quota,
|
||||
old_amount=old_weight,
|
||||
new_amount=distribution.weight
|
||||
)
|
||||
|
||||
assigner_stat = OrganizationQuotaStats.objects.get(
|
||||
organization=assigner,
|
||||
quota=quota
|
||||
@@ -57,13 +73,9 @@ class QuotaStatsService:
|
||||
if assigner_stat.stat_type == 'distribution':
|
||||
# if diff > 0 it is added to destination
|
||||
assigner_stat.remaining_amount -= diff
|
||||
print("distributed : ", assigner_stat.total_distributed)
|
||||
assigner_stat.total_distributed += diff
|
||||
print(assigner_stat.total_distributed, diff)
|
||||
assigner_stat.save()
|
||||
print(assigned_stat.total_amount)
|
||||
assigned_stat.total_amount += diff
|
||||
print(assigned_stat.total_amount)
|
||||
assigned_stat.remaining_amount += diff
|
||||
assigned_stat.save()
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ from django.db.models import Sum, Q
|
||||
from django.db.models.signals import post_save, post_delete, post_init
|
||||
from django.dispatch import receiver
|
||||
|
||||
from apps.product.validators.quota_stats_validator import QuotaStatsValidator
|
||||
from apps.warehouse.models import (
|
||||
InventoryQuotaSaleTransaction,
|
||||
InventoryEntry
|
||||
@@ -80,7 +81,11 @@ def update_product_stats(instance: Product, distribution: QuotaDistribution = No
|
||||
user = get_current_user() # get user object
|
||||
if not isinstance(user, AnonymousUser):
|
||||
organization = get_organization_by_user(user)
|
||||
|
||||
QuotaStatsValidator.validate_assigner_has_enough(
|
||||
organization,
|
||||
distribution.quota,
|
||||
distribution.weight
|
||||
)
|
||||
if ProductStats.objects.filter(
|
||||
organization=organization,
|
||||
product=instance,
|
||||
|
||||
0
apps/product/validators/__init__.py
Normal file
0
apps/product/validators/__init__.py
Normal file
60
apps/product/validators/quota_stats_validator.py
Normal file
60
apps/product/validators/quota_stats_validator.py
Normal file
@@ -0,0 +1,60 @@
|
||||
from django.apps import apps
|
||||
from django.core.exceptions import ValidationError
|
||||
from rest_framework.exceptions import APIException
|
||||
|
||||
|
||||
def get_model(app_label, model_name):
|
||||
return apps.get_model(app_label, model_name)
|
||||
|
||||
|
||||
class QuotaStatsValidator:
|
||||
"""
|
||||
Validator static methods for distribution/sale/quota edits.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _get_stat(quota, organization):
|
||||
organization_quota_stats = get_model("product", "OrganizationQuotaStats")
|
||||
return organization_quota_stats.objects.filter(quota=quota, organization=organization).first()
|
||||
|
||||
@staticmethod
|
||||
def validate_assigner_has_enough(assigner_org, quota, amount, allow_zero=False):
|
||||
"""
|
||||
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}.")
|
||||
|
||||
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.")
|
||||
|
||||
if amount < 0:
|
||||
raise APIException("Amount must be non-negative.")
|
||||
|
||||
if remaining < amount and not allow_zero:
|
||||
raise APIException(
|
||||
f"Assigning {amount} exceeds remaining amount {remaining} for organization {assigner_org}."
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def validate_distribution_create(assigner_org, assigned_org, quota, amount, parent_distribution=None):
|
||||
# rule: assigner must have enough remaining weight
|
||||
QuotaStatsValidator.validate_assigner_has_enough(assigner_org, quota, amount)
|
||||
|
||||
@staticmethod
|
||||
def validate_distribution_update(assigner_org, assigned_org, quota, old_amount, new_amount,
|
||||
parent_distribution=None):
|
||||
# if diff is positive we must check
|
||||
diff = new_amount - (old_amount or 0)
|
||||
if diff > 0:
|
||||
QuotaStatsValidator.validate_assigner_has_enough(assigner_org, quota, diff)
|
||||
|
||||
@staticmethod
|
||||
def validate_distribution_delete(distribution):
|
||||
# اگر already sold (been_sold > 0) نباید حذف شود
|
||||
been_sold = getattr(distribution, "been_sold", None)
|
||||
if been_sold and been_sold > 0:
|
||||
raise ValidationError("Cannot delete distribution: it has sold items.")
|
||||
@@ -1,4 +1,5 @@
|
||||
from rest_framework import serializers
|
||||
from rest_framework.exceptions import APIException
|
||||
|
||||
from apps.livestock.web.api.v1.serializers import LiveStockTypeSerializer
|
||||
from apps.product import models as product_models
|
||||
@@ -10,6 +11,13 @@ class QuotaSerializer(serializers.ModelSerializer):
|
||||
model = product_models.Quota
|
||||
fields = '__all__'
|
||||
|
||||
def validate(self, attrs):
|
||||
weight = attrs['quota_weight']
|
||||
if self.instance:
|
||||
if self.instance.quota_distributed < weight:
|
||||
raise APIException("Quota weight cannot be less than distributed weight.")
|
||||
return attrs
|
||||
|
||||
def to_representation(self, instance: product_models.Quota):
|
||||
representation = super().to_representation(instance)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user