From 186d66bf8468a6f416b7aaa5b6f56ef33be1da24 Mon Sep 17 00:00:00 2001 From: Mojtaba-z Date: Sun, 21 Sep 2025 16:54:55 +0330 Subject: [PATCH] pre sale & free sale deployment --- apps/herd/services/services.py | 1 - ...distribution_free_sale_balance_and_more.py | 33 +++++++++++++++++++ apps/product/models.py | 2 ++ apps/warehouse/pos/api/v1/serializers.py | 14 +++++--- apps/warehouse/services/services.py | 32 ++++++++++++++---- apps/warehouse/signals.py | 30 ++++++++++++++--- 6 files changed, 95 insertions(+), 17 deletions(-) create mode 100644 apps/product/migrations/0075_historicalquotadistribution_free_sale_balance_and_more.py diff --git a/apps/herd/services/services.py b/apps/herd/services/services.py index 6e53ba7..184d74a 100644 --- a/apps/herd/services/services.py +++ b/apps/herd/services/services.py @@ -22,7 +22,6 @@ def get_rancher_statistics(rancher: Rancher = None) -> typing.Any: camel_count=Count('id', filter=Q(type__name='شتر')), horse_count=Count('id', filter=Q(type__name='بز')), ) - stats.update({'dhi_stat': rancher.dhi_state}) # add rancher dhi stat to dict result return stats diff --git a/apps/product/migrations/0075_historicalquotadistribution_free_sale_balance_and_more.py b/apps/product/migrations/0075_historicalquotadistribution_free_sale_balance_and_more.py new file mode 100644 index 0000000..abc32c2 --- /dev/null +++ b/apps/product/migrations/0075_historicalquotadistribution_free_sale_balance_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 5.0 on 2025-09-21 13:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('product', '0074_quota_limit_by_herd_size'), + ] + + operations = [ + migrations.AddField( + model_name='historicalquotadistribution', + name='free_sale_balance', + field=models.PositiveBigIntegerField(default=0), + ), + migrations.AddField( + model_name='historicalquotadistribution', + name='pre_sale_balance', + field=models.PositiveBigIntegerField(default=0), + ), + migrations.AddField( + model_name='quotadistribution', + name='free_sale_balance', + field=models.PositiveBigIntegerField(default=0), + ), + migrations.AddField( + model_name='quotadistribution', + name='pre_sale_balance', + field=models.PositiveBigIntegerField(default=0), + ), + ] diff --git a/apps/product/models.py b/apps/product/models.py index e99cd71..ae45a74 100644 --- a/apps/product/models.py +++ b/apps/product/models.py @@ -597,7 +597,9 @@ class QuotaDistribution(BaseModel): been_sold = models.PositiveBigIntegerField(default=0) history = HistoricalRecords() pre_sale = models.BooleanField(default=False) + pre_sale_balance = models.PositiveBigIntegerField(default=0) free_sale = models.BooleanField(default=False) + free_sale_balance = models.PositiveBigIntegerField(default=0) def generate_distribution_id(self): """ generate special id for quota distribution """ diff --git a/apps/warehouse/pos/api/v1/serializers.py b/apps/warehouse/pos/api/v1/serializers.py index 2dee61c..3f6292d 100644 --- a/apps/warehouse/pos/api/v1/serializers.py +++ b/apps/warehouse/pos/api/v1/serializers.py @@ -8,7 +8,10 @@ from apps.product.services.services import ( from apps.pos_device.services.services import pos_organizations_sharing_information from apps.pos_device.pos.api.v1.serializers.device import DeviceSerializer from apps.product.exceptions import DistributionWeightException -from apps.warehouse.services.services import create_extra_sale +from apps.warehouse.services.services import ( + create_extra_sale, + create_pre_sale +) from apps.herd.pos.api.v1.serializers import RancherSerializer from apps.product.models import QuotaDistribution, Product from apps.warehouse import models as warehouse_models @@ -76,12 +79,12 @@ class InventoryEntrySerializer(serializers.ModelSerializer): ), 'base_prices': [ { - "text": "قیمت درب کارخانه", # noqa + "text": "درب کارخانه", # noqa "name": "base_price_factory", "value": instance.distribution.quota.base_price_factory }, { - "text": "قیمت درب اتحادیه", # noqa + "text": "درب اتحادیه", # noqa "name": "base_price_cooperative", "value": instance.distribution.quota.base_price_cooperative } @@ -146,9 +149,12 @@ class InventoryQuotaSaleTransactionSerializer(serializers.ModelSerializer): ) total_price += item.total_price - # create extra sale + # create extra sale for distribution create_extra_sale(transaction=transaction, sale_item=item) + # create pre sale for distribution + create_pre_sale(transaction=transaction, sale_item=item) + transaction.transaction_price = total_price transaction.save() diff --git a/apps/warehouse/services/services.py b/apps/warehouse/services/services.py index 46ed54b..3d18ab4 100644 --- a/apps/warehouse/services/services.py +++ b/apps/warehouse/services/services.py @@ -1,4 +1,5 @@ from apps.herd.services.services import rancher_quota_weight, get_rancher_statistics +from rest_framework.exceptions import APIException from apps.warehouse.models import ( InventoryEntry, InventoryQuotaSaleTransaction, @@ -86,6 +87,7 @@ def create_extra_sale( # set distribution warehouse balance to 0 because we have extra sale sale_item.quota_distribution.warehouse_balance = 0 + sale_item.quota_distribution.free_sale_balance += extra_weight sale_item.quota_distribution.save() # set transaction as free sale @@ -112,10 +114,26 @@ def create_pre_sale( """ if sale_item.quota_distribution.pre_sale: - # create pre sale - pre_sale = QuotaPreSaleItem.objects.create( - transaction=transaction, - sale_item=sale_item, - distribution=sale_item.quota_distribution, - weight=sale_item.weight - ) + try: + # create pre sale + pre_sale = QuotaPreSaleItem.objects.create( + transaction=transaction, + sale_item=sale_item, + distribution=sale_item.quota_distribution, + 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_distribution.pre_sale_balance += sale_item.weight + sale_item.save() + + return pre_sale + except APIException as e: + pass + pass + diff --git a/apps/warehouse/signals.py b/apps/warehouse/signals.py index 4f7817e..7886168 100644 --- a/apps/warehouse/signals.py +++ b/apps/warehouse/signals.py @@ -22,11 +22,31 @@ def warehouse_sold_and_balance(quota_distribution: QuotaDistribution): 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 total_extra_sales_weight != 0: - quota_distribution.warehouse_balance = quota_distribution.warehouse_entry - total_extra_sales_weight - quota_distribution.save(update_fields=['been_sold', 'warehouse_balance']) + 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_save, sender=InventoryEntry) @@ -38,8 +58,8 @@ def update_distribution_warehouse_entry(sender, instance, **kwargs): @receiver(post_save, sender=InventoryQuotaSaleItem) @receiver(post_delete, sender=InventoryQuotaSaleItem) -def update_distribution_warehouse_sold_and_balance(sender, instance, **kwargs): - if instance.quota_distribution: +def update_distribution_warehouse_sold_and_balance(sender, instance: InventoryQuotaSaleItem, **kwargs): + if instance.quota_distribution and not instance.quota_distribution.pre_sale: warehouse_sold_and_balance( quota_distribution=instance.quota_distribution, )