add - quota stat services

This commit is contained in:
2025-11-17 10:15:17 +03:30
parent 52cfc538d8
commit 2a34f1093a
2 changed files with 173 additions and 45 deletions

View File

@@ -0,0 +1,86 @@
from apps.product.models import QuotaDistribution, OrganizationQuotaStats
class QuotaStatsService:
@staticmethod
def apply_distribution(distribution: QuotaDistribution):
quota = distribution.quota
# origin org
assigner = distribution.assigner_organization
# destination org
assigned = distribution.assigned_organization
print(assigned)
# ================ origin ================
assigner_stat, _ = OrganizationQuotaStats.objects.get_or_create(
organization=assigner,
quota=quota
)
assigner_stat.remaining_amount -= distribution.weight
assigner_stat.total_distributed += distribution.weight
assigner_stat.save()
# ============== destination ================
assigned_stat, _ = OrganizationQuotaStats.objects.get_or_create(
organization=assigned,
quota=quota
)
assigned_stat.total_amount += distribution.weight
assigned_stat.remaining_amount += distribution.weight
assigned_stat.distributions.add(distribution)
assigned_stat.save()
@staticmethod
def update_distribution(distribution: QuotaDistribution, old_weight: int):
diff = distribution.weight - old_weight
if diff == 0:
return
quota = distribution.quota
assigner = distribution.assigner_organization
assigned = distribution.assigned_organization
assigner_stat = OrganizationQuotaStats.objects.get(
organization=assigner,
quota=quota
)
assigned_stat = OrganizationQuotaStats.objects.get(
organization=assigned,
quota=quota
)
# if diff > 0 it is added to destination
assigner_stat.remaining_amount -= diff
assigner_stat.total_distributed += diff
assigner_stat.save()
assigned_stat.total_amount += diff
assigned_stat.remaining_amount += diff
print(assigned_stat.id)
assigned_stat.save()
@staticmethod
def delete_distribution(distribution: QuotaDistribution):
quota = distribution.quota
# origin
assigner_stat = OrganizationQuotaStats.objects.get(
organization=distribution.assigner_organization,
quota=quota
)
assigner_stat.remaining_amount += distribution.weight
assigner_stat.total_distributed -= distribution.weight
assigner_stat.save()
# destination
assigned_stat = OrganizationQuotaStats.objects.get(
organization=distribution.assigned_organization,
quota=quota
)
assigned_stat.total_amount -= distribution.weight
assigned_stat.remaining_amount -= distribution.weight
assigned_stat.distributions.remove(distribution)
assigned_stat.save()

View File

@@ -2,7 +2,7 @@ from crum import get_current_user
from django.contrib.auth.models import AnonymousUser
from django.db import models
from django.db.models import Sum, Q
from django.db.models.signals import post_save, post_delete
from django.db.models.signals import post_save, post_delete, post_init
from django.dispatch import receiver
from apps.warehouse.models import (
@@ -12,12 +12,12 @@ from apps.warehouse.models import (
from common.helpers import get_organization_by_user
from .models import (
QuotaDistribution,
OrganizationQuotaStats,
Quota,
Product,
ProductStats,
QuotaStats
QuotaStats, OrganizationQuotaStats
)
from .services.quota_stat_service import QuotaStatsService
def recalculate_remaining_amount(quota):
@@ -255,6 +255,48 @@ def update_stats_on_change(sender, instance, **kwargs):
return
@receiver(post_init, sender=QuotaDistribution)
def store_original_weight(sender, instance, **kwargs):
pass
@receiver(post_init, sender=QuotaDistribution)
def distribution_pre_save(sender, instance, **kwargs):
if instance.pk:
instance._is_update = True
instance._old_weight = instance.weight
else:
instance._is_update = False
@receiver(post_save, sender=QuotaDistribution)
def update_stats_after_save(sender, instance, created, **kwargs):
if getattr(instance, 'stat_from_signal', False):
return
if instance.trash:
return
if not instance._is_update: # noqa
QuotaStatsService.apply_distribution(instance)
else:
QuotaStatsService.update_distribution(instance, instance._old_weight) # noqa
instance.stat_from_signal = True
@receiver(post_save, sender=QuotaDistribution)
def delete_stats_after_soft_delete(sender, instance, **kwargs):
if getattr(instance, 'stat_from_signal', False):
return
if instance.trash:
QuotaStatsService.delete_distribution(instance)
instance.stat_from_signal = True
@receiver(post_save, sender=Quota)
def organization_quota_stats(sender, instance: Quota, created: bool, **kwargs):
"""
@@ -285,45 +327,45 @@ def organization_quota_stats(sender, instance: Quota, created: bool, **kwargs):
# prevent from maximum recursion loop
instance.stat_from_signal = True
@receiver(post_save, sender=QuotaDistribution)
def update_quota_stats_on_distribution(sender, instance: QuotaDistribution, created, **kwargs):
if getattr(instance, 'one_time_loop_flag', False):
return
if instance.trash:
return
org = instance.assigned_organization
quota = instance.quota
stats, _ = OrganizationQuotaStats.objects.get_or_create(
quota=quota,
organization=org,
)
stats.distributions.add(instance)
stats.update_amount(main_quota=True)
instance.one_time_loop_flag = True
@receiver(post_save, sender=QuotaDistribution)
def handle_quota_stats_soft_delete_on_distribution(sender, instance: QuotaDistribution, created, **kwargs):
if getattr(instance, 'one_time_loop_flag', False):
return
if instance.trash:
org = instance.assigned_organization
quota = instance.quota
stats_qs = OrganizationQuotaStats.objects.filter(
quota=quota,
organization=org,
)
if stats_qs:
for stats in stats_qs:
stats.distributions.remove(instance)
stats.update_amount(main_quota=True)
instance.one_time_loop_flag = True
#
#
# @receiver(post_save, sender=QuotaDistribution)
# def update_quota_stats_on_distribution(sender, instance: QuotaDistribution, created, **kwargs):
# if getattr(instance, 'one_time_loop_flag', False):
# return
#
# if instance.trash:
# return
#
# org = instance.assigned_organization
# quota = instance.quota
#
# stats, _ = OrganizationQuotaStats.objects.get_or_create(
# quota=quota,
# organization=org,
# )
# stats.distributions.add(instance)
# stats.update_amount(main_quota=True)
# instance.one_time_loop_flag = True
#
#
# @receiver(post_save, sender=QuotaDistribution)
# def handle_quota_stats_soft_delete_on_distribution(sender, instance: QuotaDistribution, created, **kwargs):
# if getattr(instance, 'one_time_loop_flag', False):
# return
#
# if instance.trash:
# org = instance.assigned_organization
# quota = instance.quota
#
# stats_qs = OrganizationQuotaStats.objects.filter(
# quota=quota,
# organization=org,
# )
#
# if stats_qs:
# for stats in stats_qs:
# stats.distributions.remove(instance)
# stats.update_amount(main_quota=True)
#
# instance.one_time_loop_flag = True