from django.db.models import Sum from django.db.models.signals import post_save, post_delete, post_init from django.dispatch import receiver from apps.product.models import QuotaDistribution from .models import InventoryEntry, InventoryQuotaSaleItem from .services.warehouse_allocation_service import WarehouseAllocationService from ..product.services.quota_stat_service import QuotaStatsService def calculate_warehouse_entry(quota_distribution): total_entry = quota_distribution.inventory_entry.aggregate( total=Sum('weight') )['total'] or 0 quota_distribution.warehouse_entry = total_entry quota_distribution.save(update_fields=['warehouse_entry']) def warehouse_sold_and_balance(quota_distribution: QuotaDistribution): total_sold = quota_distribution.sale_items.aggregate( total=Sum('weight') )['total'] or 0 quota_distribution.been_sold = total_sold quota_distribution.warehouse_balance = quota_distribution.warehouse_entry - total_sold if quota_distribution.warehouse_balance >= 0: # calculate extra sales & mines total extra sales weight from new inventory entry # and set the warehouse balance extra_sales = quota_distribution.extra_sales.all() total_extra_sales_weight = extra_sales.aggregate(total=Sum('weight'))['total'] or 0 if quota_distribution.free_sale_balance != 0: if quota_distribution.warehouse_balance >= quota_distribution.free_sale_balance: quota_distribution.warehouse_balance -= total_extra_sales_weight quota_distribution.free_sale_balance = 0 else: quota_distribution.free_sale_balance -= quota_distribution.warehouse_balance quota_distribution.warehouse_balance = 0 # calculate pre_sales & mines total pre_sales weight from new inventory entry # and set the warehouse balance pre_sales = quota_distribution.pre_sales.all() total_pre_sales_weight = pre_sales.aggregate(total=Sum('weight'))['total'] or 0 if total_pre_sales_weight != 0: if quota_distribution.warehouse_balance >= quota_distribution.pre_sale_balance: quota_distribution.warehouse_balance -= total_pre_sales_weight quota_distribution.pre_sale_balance = 0 else: quota_distribution.pre_sale_balance -= quota_distribution.warehouse_balance quota_distribution.warehouse_balance = 0 quota_distribution.save(update_fields=['been_sold', 'warehouse_balance', 'free_sale_balance', 'pre_sale_balance']) @receiver(post_init, sender=InventoryEntry) def inventory_entry_pre_save(sender, instance: InventoryEntry, **kwargs): if instance.pk: instance._is_update = True instance._old_weight = instance.weight else: instance._is_update = False @receiver(post_save, sender=InventoryEntry) def update_quota_stat_on_entry_update(sender, instance: InventoryEntry, created, **kwargs): if instance._is_update: # noqa QuotaStatsService.apply_inventory_entry(instance, created=False) else: WarehouseAllocationService.allocate(entry=instance) @receiver(post_save, sender=InventoryEntry) def update_quota_stat_on_entry_soft_delete(sender, instance, **kwargs): if instance.trash: QuotaStatsService.remove_inventory_entry(instance) # @receiver(post_save, sender=InventoryEntry) # @receiver(post_delete, sender=InventoryEntry) # def update_distribution_warehouse_entry(sender, instance, **kwargs): # calculate_warehouse_entry(instance.distribution) # warehouse_sold_and_balance(instance.distribution) @receiver(post_save, sender=InventoryQuotaSaleItem) @receiver(post_delete, sender=InventoryQuotaSaleItem) def update_distribution_warehouse_sold_and_balance(sender, instance: InventoryQuotaSaleItem, **kwargs): if instance.quota_distribution and not instance.quota_distribution.pre_sale: # if transaction status is success and warehouse management Done once, inventory_calculation set to true if instance.transaction.transaction_status == 'success' and instance.inventory_calculation is False: warehouse_sold_and_balance( quota_distribution=instance.quota_distribution, ) else: print("quota distribution is null - warehouse app signals") # @receiver(post_save, sender=InventoryQuotaSaleItem) # def update_quota_stats_on_sale(sender, instance: InventoryQuotaSaleItem, created, **kwargs): # if instance.transaction.transaction_status == 'success': # return # # stats = OrganizationQuotaStats.objects.filter( # organization=instance.quota_distribution.assigned_organization, # quota=instance.quota_distribution.quota # ).first() # # if stats: # stats.update_amounts() # برای محصولات ازاد چک شود و کنترل