Files

169 lines
5.1 KiB
Python

import typing
from django.db.models import Sum
from rest_framework.exceptions import APIException
from apps.core.models import SystemConfig
from apps.herd.services.services import rancher_quota_weight
from apps.product.models import QuotaDistribution, OrganizationQuotaStats
from apps.warehouse.models import (
InventoryEntry,
InventoryQuotaSaleTransaction,
InventoryQuotaSaleItem,
ExtraSale,
QuotaPreSaleItem
)
def get_total_sold(
rancher,
inventory_entry: InventoryEntry = None,
distribution: QuotaDistribution = None,
quota_stat: OrganizationQuotaStats = None
):
"""
"""
if inventory_entry:
return (
InventoryQuotaSaleTransaction.objects.filter(
inventory_entry=inventory_entry,
rancher=rancher
).aggregate(total=Sum('weight'))['total'] or 0
)
elif distribution:
return (
InventoryQuotaSaleTransaction.objects.filter(
inventory_entry=inventory_entry,
rancher=rancher
).aggregate(total=Sum('weight'))['total'] or 0
)
elif quota_stat:
return (
InventoryQuotaSaleItem.objects.filter(
quota_stat=quota_stat,
transaction__rancher=rancher
).aggregate(total=Sum('weight'))['total'] or 0
)
def can_buy_from_inventory(
rancher,
inventory_entry: InventoryEntry = None,
distribution: QuotaDistribution = None,
quota_stat: OrganizationQuotaStats = None
):
"""
"""
if SystemConfig.get("IGNORE_ALL_RANCHER_PURCHASE_LIMITS") == "true":
return True
if rancher.ignore_purchase_limit:
return True
if inventory_entry:
# check if quota is open and acceptable to sale
if inventory_entry.distribution.quota.is_in_valid_time():
quota_weight = rancher_quota_weight(rancher, inventory_entry=inventory_entry) # {total, by_type}
else:
return False
elif distribution:
# check if quota is open and acceptable to sale
if distribution.quota.is_in_valid_time():
quota_weight = rancher_quota_weight(rancher, distribution=distribution) # {total, by_type}
else:
return False
elif quota_stat:
if quota_stat.quota.is_in_valid_time():
quota_weight = rancher_quota_weight(
rancher, quota=quota_stat.quota, quota_stat=quota_stat
) # {total, by_type}
else:
return False
total_allowed = quota_weight['total'] # noqa
total_sold = get_total_sold(inventory_entry, rancher)
return total_sold < total_allowed
def create_extra_sale(
sale_item: InventoryQuotaSaleItem,
transaction: InventoryQuotaSaleTransaction
) -> typing.Any:
"""
:param sale_item
:param transaction
create extra sale for items that weight are
more than distribution warehouse balance
"""
if sale_item.quota_stat.quota.free_sale:
if sale_item.weight > sale_item.quota_stat.inventory_entry_balance:
# calculate extra weight between item weight and warehouse balance
extra_weight = sale_item.weight - sale_item.quota_stat.inventory_entry_balance
extra_sale = ExtraSale.objects.create( # create extra sale
transaction=transaction,
sale_item=sale_item,
distribution=sale_item.quota_distribution,
quota_stat=sale_item.quota_stat,
weight=extra_weight
)
# set distribution warehouse balance to 0 because we have extra sale
sale_item.quota_stat.inventory_entry_balance = 0
sale_item.quota_stat.free_sale_balance += extra_weight
sale_item.quota_stat.save()
# set transaction as free sale
transaction.free_sale_state = True
transaction.save()
# set sale item as extra sale
sale_item.is_extra = True
sale_item.save()
return extra_sale
pass
pass
def create_pre_sale(
transaction: InventoryQuotaSaleTransaction,
sale_item: InventoryQuotaSaleItem
) -> typing.Any:
"""
:param transaction
:param sale_item
Create pre_sale for distributions
"""
if sale_item.quota_stat.quota.pre_sale:
try:
# create pre sale
pre_sale = QuotaPreSaleItem.objects.create(
transaction=transaction,
sale_item=sale_item,
distribution=sale_item.quota_distribution,
quota_stat=sale_item.quota_stat,
weight=sale_item.weight
)
# set transaction as pre sale
transaction.pre_sale_state = True
transaction.save()
# set sale item as pre sale
sale_item.is_pre_sale = True
sale_item.quota_stat.pre_sale_balance += sale_item.weight
sale_item.save()
return pre_sale
except APIException as e:
pass
pass