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 ) org = entry.organization.parent_organization parent_orgs = [] while org: # import parent org to list parent_orgs.append(org) org = org.parent_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"])