diff --git a/apps/notification/signals.py b/apps/notification/signals.py index dc7111b..6b46997 100644 --- a/apps/notification/signals.py +++ b/apps/notification/signals.py @@ -3,32 +3,31 @@ from django.db.models.signals import post_save from django.dispatch import receiver from apps.pos_device.models import Device -from apps.warehouse.models import InventoryEntry from apps.warehouse.models import product_models from .models import Notification -@receiver(post_save, sender=InventoryEntry) -def create_inventory_entry_notification(sender, instance, created, **kwargs): - """ Create notification for organization after inventory entry creation """ - - if not created: - return - - def _create_notification(): - # create notification for organization on pos device - devices = Device.objects.filter(assignment__client__organization=instance.organization) - for device in devices: - Notification.objects.create( - device=device, - organization=instance.organization, - title=f" {instance.distribution.distribution_id} ورودی جدید به انبار از توزیع با کد ", # noqa - message=f' مقدار {instance.distribution.weight} کیلوگرم' # noqa - f' از توزیع با کد {instance.distribution.distribution_id} به انبار ورود خورده است ', # noqa - type='inventory', - ) - - transaction.on_commit(_create_notification) +# @receiver(post_save, sender=InventoryEntry) +# def create_inventory_entry_notification(sender, instance, created, **kwargs): +# """ Create notification for organization after inventory entry creation """ +# +# if not created: +# return +# +# def _create_notification(): +# # create notification for organization on pos device +# devices = Device.objects.filter(assignment__client__organization=instance.organization) +# for device in devices: +# Notification.objects.create( +# device=device, +# organization=instance.organization, +# title=f" {instance.distribution.distribution_id} ورودی جدید به انبار از توزیع با کد ", # noqa +# message=f' مقدار {instance.distribution.weight} کیلوگرم' # noqa +# f' از توزیع با کد {instance.distribution.distribution_id} به انبار ورود خورده است ', # noqa +# type='inventory', +# ) +# +# transaction.on_commit(_create_notification) @receiver(post_save, sender=product_models.QuotaDistribution) # noqa diff --git a/apps/product/pos/api/v1/serializers/quota_serializers.py b/apps/product/pos/api/v1/serializers/quota_serializers.py index eb56bb9..89d79eb 100644 --- a/apps/product/pos/api/v1/serializers/quota_serializers.py +++ b/apps/product/pos/api/v1/serializers/quota_serializers.py @@ -273,6 +273,9 @@ class OrganizationQuotaStatsSerializer(serializers.ModelSerializer): representation['free_sale'] = instance.quota.free_sale representation['pre_sale'] = instance.quota.pre_sale + if instance.distributions: + representation['distributions'] = [dist.id for dist in instance.distributions.all()] + if instance.quota: representation['quota'] = { 'quota_identity': instance.quota.quota_id, diff --git a/apps/warehouse/apps.py b/apps/warehouse/apps.py index 019c386..3f27647 100644 --- a/apps/warehouse/apps.py +++ b/apps/warehouse/apps.py @@ -6,4 +6,4 @@ class WarehouseConfig(AppConfig): name = 'apps.warehouse' def ready(self): - import apps.warehouse.signals + pass diff --git a/apps/warehouse/migrations/0045_inventoryquotasaleitem_quota_stat.py b/apps/warehouse/migrations/0045_inventoryquotasaleitem_quota_stat.py new file mode 100644 index 0000000..9ba05d5 --- /dev/null +++ b/apps/warehouse/migrations/0045_inventoryquotasaleitem_quota_stat.py @@ -0,0 +1,20 @@ +# Generated by Django 5.0 on 2025-11-26 07:30 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('product', '0097_organizationquotastats_inventory_entry_balance'), + ('warehouse', '0044_inventoryentry_org_quota_stat'), + ] + + operations = [ + migrations.AddField( + model_name='inventoryquotasaleitem', + name='quota_stat', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sale_items', to='product.organizationquotastats'), + ), + ] diff --git a/apps/warehouse/models.py b/apps/warehouse/models.py index 45d2570..b1f2860 100644 --- a/apps/warehouse/models.py +++ b/apps/warehouse/models.py @@ -185,6 +185,12 @@ class InventoryQuotaSaleItem(BaseModel): related_name='sale_items', null=True ) + quota_stat = models.ForeignKey( + product_models.OrganizationQuotaStats, + on_delete=models.CASCADE, + related_name='sale_items', + null=True + ) gov_product = models.ForeignKey( product_models.Product, on_delete=models.CASCADE, diff --git a/apps/warehouse/signals/__init__.py b/apps/warehouse/signals/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/warehouse/signals.py b/apps/warehouse/signals/signals_v1.py similarity index 95% rename from apps/warehouse/signals.py rename to apps/warehouse/signals/signals_v1.py index 6a3cce8..0c3d5f2 100644 --- a/apps/warehouse/signals.py +++ b/apps/warehouse/signals/signals_v1.py @@ -3,9 +3,9 @@ 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 +from apps.product.services.quota_stat_service import QuotaStatsService +from apps.warehouse.models import InventoryEntry, InventoryQuotaSaleItem +from apps.warehouse.services.warehouse_allocation_service import WarehouseAllocationService def calculate_warehouse_entry(quota_distribution): diff --git a/apps/warehouse/signals/signals_v2.py b/apps/warehouse/signals/signals_v2.py new file mode 100644 index 0000000..c609afe --- /dev/null +++ b/apps/warehouse/signals/signals_v2.py @@ -0,0 +1,59 @@ +from django.db.models import Sum +from django.db.models.signals import post_save, post_delete +from django.dispatch import receiver + +from apps.product.models import OrganizationQuotaStats +from apps.warehouse.models import InventoryQuotaSaleItem + + +def warehouse_sold_and_balance(quota_stat: OrganizationQuotaStats): + total_sold = quota_stat.sale_items.aggregate( + total=Sum('weight') + )['total'] or 0 + + quota_stat.sold_amount = total_sold + quota_stat.inventory_entry_balance = quota_stat.inventory_received - total_sold + # if quota_stat.inventory_entry_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 + + # 'free_sale_balance', 'pre_sale_balance' + quota_stat.save(update_fields=['sold_amount', 'inventory_entry_balance']) + + +@receiver(post_save, sender=InventoryQuotaSaleItem) +@receiver(post_delete, sender=InventoryQuotaSaleItem) +def update_distribution_warehouse_sold_and_balance(sender, instance: InventoryQuotaSaleItem, **kwargs): + # if object exists & pre sale is true + if instance.quota_stat and not instance.quota_stat.quota.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_stat=instance.quota_stat, + ) + else: + print("quota distribution is null - warehouse app signals")