Files
RasadDam_Backend/apps/product/services/quota_stat_service.py

159 lines
5.3 KiB
Python

from apps.product.models import QuotaDistribution, OrganizationQuotaStats
from apps.product.validators.quota_stats_validator import QuotaStatsValidator
from apps.warehouse.models import InventoryEntry
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,
quota=quota,
)
if created:
assigner_stat.stat_type = 'distribution'
assigner_stat.save()
if assigner_stat.stat_type == 'distribution':
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,
stat_type='distribution'
)
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
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
)
assigned_stat = OrganizationQuotaStats.objects.get(
organization=assigned,
quota=quota
)
if assigner_stat.stat_type == 'distribution':
# 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
assigned_stat.save()
@staticmethod
def delete_distribution(distribution: QuotaDistribution):
quota = distribution.quota
# origin
assigner_stat = OrganizationQuotaStats.objects.get(
organization=distribution.assigner_organization,
quota=quota
)
if assigner_stat.stat_type == 'distribution':
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()
@staticmethod
def apply_inventory_entry(entry: InventoryEntry, created):
quota = entry.quota
weight = entry.weight
if not created:
old_weight = entry._old_weight # noqa
diff = weight - old_weight
else:
diff = weight
print("0000", diff)
QuotaStatsService._propagate_inventory(
organization=entry.organization,
quota=quota,
diff=diff
)
@staticmethod
def remove_inventory_entry(entry: InventoryEntry):
quota = entry.quota
weight = entry.weight
QuotaStatsService._propagate_inventory(
organization=entry.organization,
quota=quota,
diff=-weight
)
@staticmethod
def _propagate_inventory(organization, quota, diff):
org = organization
stat_queryset = OrganizationQuotaStats.objects.select_related('quota', 'organization')
update_my_remaining_stat = True
while org:
stat = stat_queryset.filter(
organization=org,
quota=quota
).first()
if stat:
stat.inventory_received = (stat.inventory_received or 0) + diff
# just update my own stat remaining quota weight
if update_my_remaining_stat:
stat.remaining_amount -= diff
update_my_remaining_stat = False
if stat.inventory_received < 0:
stat.inventory_received = 0
stat.save(update_fields=['inventory_received', 'remaining_amount'])
org = org.parent_organization