From e9caad0dbf10260b782133c98619280aa30cc384 Mon Sep 17 00:00:00 2001 From: Mojtaba-z Date: Sun, 28 Sep 2025 10:36:58 +0330 Subject: [PATCH] rancher service & quota usage service --- apps/herd/services/rancher_service.py | 13 ++++ apps/herd/services/services.py | 13 +++- apps/warehouse/pos/api/v1/serializers.py | 53 +++------------- .../services/quota_usage_services.py | 61 +++++++++++++++++++ 4 files changed, 91 insertions(+), 49 deletions(-) create mode 100644 apps/herd/services/rancher_service.py create mode 100644 apps/warehouse/services/quota_usage_services.py diff --git a/apps/herd/services/rancher_service.py b/apps/herd/services/rancher_service.py new file mode 100644 index 0000000..7b4c0ba --- /dev/null +++ b/apps/herd/services/rancher_service.py @@ -0,0 +1,13 @@ +from django.db.models import Sum, functions, Value + + +class RancherService: + + @staticmethod + def get_total_used_weight(rancher, sale_item): + return sale_item.objects.filter( + transaction__rancher=rancher, + transaction__transaction_status='success' + ).aggregate( + total_weight=functions.Coalesce(Sum('weight'), Value(0)) + )['total_weight'] diff --git a/apps/herd/services/services.py b/apps/herd/services/services.py index 59406a2..7513280 100644 --- a/apps/herd/services/services.py +++ b/apps/herd/services/services.py @@ -1,8 +1,13 @@ from decimal import Decimal from apps.herd.models import Rancher from apps.livestock.models import LiveStock -from apps.warehouse.models import InventoryEntry +from apps.warehouse.models import ( + InventoryEntry, + InventoryQuotaSaleItem +) +from django.db.models import Sum from apps.product.models import Quota, QuotaDistribution +from apps.herd.services.rancher_service import RancherService from django.db.models import Count, Q import typing @@ -89,11 +94,13 @@ def rancher_quota_weight(rancher, inventory_entry: InventoryEntry = None, distri # incentive plan quantity by this livestock type rancher_plan_weight = rancher_plans.first().allowed_quantity * item.quantity_kg total_weight += rancher_plan_weight - print(total_weight) + + # get rancher remaining usage of quota for purchase + rancher_remaining_usage = RancherService.get_total_used_weight(rancher, InventoryQuotaSaleItem) return { "total_weight": total_weight, - "remaining_weight": 20, + "remaining_weight": total_weight - rancher_remaining_usage, "by_type": [{ "name": key, "name_fa": value['name_fa'], diff --git a/apps/warehouse/pos/api/v1/serializers.py b/apps/warehouse/pos/api/v1/serializers.py index 8b553ee..bab4d4f 100644 --- a/apps/warehouse/pos/api/v1/serializers.py +++ b/apps/warehouse/pos/api/v1/serializers.py @@ -6,6 +6,7 @@ from apps.product.services.services import ( quota_attribute_value ) from apps.pos_device.services.services import pos_organizations_sharing_information +from apps.warehouse.services.quota_usage_services import QuotaUsageService from apps.pos_device.pos.api.v1.serializers.device import DeviceSerializer from apps.product.exceptions import DistributionWeightException from apps.pos_device.models import POSFreeProducts @@ -171,52 +172,12 @@ class InventoryQuotaSaleTransactionSerializer(serializers.ModelSerializer): # create pre sale for distribution create_pre_sale(transaction=transaction, sale_item=item) - # purchase quota usage of rancher - if 'livestock_statistic' in item_data.keys(): - - # get list of livestock types object for transaction item - livestock_types = { - lt.en_name: lt - for lt in LiveStockType.objects.filter( - en_name__in=[i['name'] for i in item_data.get('livestock_statistic', [])] - ) - } - - # get list of incentive plans object for transaction item - incentive_plans = { - iplan.id: iplan - for iplan in IncentivePlan.objects.all() - } - - for item in item_data['livestock_statistic']: - # get livestock by en name - livestock_type = livestock_types.get(item['name']) - if not livestock_types: - continue - - # true or false - is_incentive = item['id'] != 0 - - # get usage & calculate - usage, created = QuotaUsage.objects.get_or_create( - rancher=rancher, - livestock_type=livestock_type, - distribution=distribution, - incentive_plan=incentive_plans.get(item['id']) if is_incentive else None, - defaults={ - "count": item['count'], - 'usage_type': 'incentive' if is_incentive else 'base', - 'incentive_quota_used': item['total_weight'] if is_incentive else 0, - 'base_quota_used': item['total_weight'] if is_incentive else 0 - } - ) - - if not created: - if usage.usage_type == 'incentive': - usage.incentive_quota_used += item['total_weight'] - else: - usage.base_quota_used += item['total_weight'] - usage.save() + # calculate quota usage of rancher + usages = QuotaUsageService.allocate_usage( + rancher=rancher, + distribution=distribution, + item_data=item_data + ) transaction.transaction_price = total_price transaction.save() diff --git a/apps/warehouse/services/quota_usage_services.py b/apps/warehouse/services/quota_usage_services.py new file mode 100644 index 0000000..5fd9236 --- /dev/null +++ b/apps/warehouse/services/quota_usage_services.py @@ -0,0 +1,61 @@ +from apps.product.models import QuotaUsage, IncentivePlan +from apps.livestock.models import LiveStockType + + +class QuotaUsageService: + + @staticmethod + def allocate_usage(rancher, distribution, item_data): + """ save & calculate quota usage of rancher """ + + # purchase quota usage of rancher + if 'livestock_statistic' in item_data.keys(): + + # get list of livestock types object for transaction item + livestock_types = { + lt.en_name: lt + for lt in LiveStockType.objects.filter( + en_name__in=[i['name'] for i in item_data.get('livestock_statistic', [])] + ) + } + + # get list of incentive plans object for transaction item + incentive_plans = { + iplan.id: iplan + for iplan in IncentivePlan.objects.all() + } + + usages = [] # list of usages objects + for item in item_data['livestock_statistic']: + # get livestock by en name + livestock_type = livestock_types.get(item['name']) + if not livestock_types: + continue + + # true or false + is_incentive = item['id'] != 0 + + # get usage & calculate + usage, created = QuotaUsage.objects.get_or_create( + rancher=rancher, + livestock_type=livestock_type, + distribution=distribution, + incentive_plan=incentive_plans.get(item['id']) if is_incentive else None, + defaults={ + "count": item['count'], + 'usage_type': 'incentive' if is_incentive else 'base', + 'incentive_quota_used': item['total_weight'] if is_incentive else 0, + 'base_quota_used': item['total_weight'] if is_incentive else 0 + } + ) + + if not created: + if usage.usage_type == 'incentive': + usage.incentive_quota_used += item['total_weight'] + else: + usage.base_quota_used += item['total_weight'] + usage.save() + + usages.append(usage) + + return usages