75 lines
2.7 KiB
Python
75 lines
2.7 KiB
Python
from django.db import transaction
|
|
from rest_framework import status
|
|
|
|
from apps.product.models import QuotaDistribution, OrganizationQuotaStats
|
|
from apps.warehouse.exceptions import WareHouseException
|
|
from apps.warehouse.models import InventoryEntry, InventoryEntryAllocation
|
|
|
|
|
|
class WarehouseAllocationService:
|
|
|
|
@staticmethod
|
|
def allocate(entry: InventoryEntry):
|
|
"""
|
|
Auto allocate entry.total_weight between multiple distributions
|
|
"""
|
|
with transaction.atomic():
|
|
distributions = QuotaDistribution.objects.filter(
|
|
assigned_organization=entry.organization,
|
|
quota=entry.quota
|
|
).select_related('quota').order_by('-create_date')
|
|
|
|
if not distributions.exists():
|
|
raise WareHouseException("توزیعی برای این انبار وجود ندارد", status.HTTP_403_FORBIDDEN) # noqa
|
|
|
|
remaining = entry.weight
|
|
for dist in distributions:
|
|
if remaining <= 0:
|
|
break
|
|
stat = OrganizationQuotaStats.objects.get(
|
|
quota=dist.quota,
|
|
organization=dist.assigned_organization
|
|
)
|
|
capacity = stat.remaining_amount
|
|
if capacity <= 0:
|
|
continue
|
|
|
|
allocate_weight = min(remaining, capacity)
|
|
|
|
InventoryEntryAllocation.objects.create(
|
|
distribution=dist,
|
|
inventory_entry=entry,
|
|
weight=allocate_weight
|
|
)
|
|
|
|
stat.inventory_received += allocate_weight
|
|
stat.inventory_entry_balance += allocate_weight
|
|
stat.remaining_amount -= allocate_weight
|
|
stat.save()
|
|
|
|
remaining -= allocate_weight
|
|
|
|
if remaining > 0:
|
|
raise WareHouseException(
|
|
"مقدار وارد شده از انبار بیشتر از مقدار کل سهمیه توزیع داده شده است", # noqa
|
|
status.HTTP_400_BAD_REQUEST
|
|
)
|
|
|
|
parent_orgs = [entry.quota.registerer_organization]
|
|
parent_org_ids = [org.id for org in parent_orgs]
|
|
|
|
target_org_ids = set(parent_org_ids)
|
|
|
|
if entry.quota.registerer_organization.id not in target_org_ids:
|
|
target_org_ids.add(entry.quota.registerer_organization.id)
|
|
|
|
stats = (OrganizationQuotaStats.objects.filter(
|
|
quota=entry.quota,
|
|
organization__in=target_org_ids
|
|
))
|
|
|
|
for stat in stats:
|
|
stat.inventory_received += entry.weight
|
|
|
|
OrganizationQuotaStats.objects.bulk_update(stats, ["inventory_received"])
|