From 1205a6481254cf383ed01780334a236aec4a36d7 Mon Sep 17 00:00:00 2001 From: Mojtaba-z Date: Tue, 9 Dec 2025 13:46:15 +0330 Subject: [PATCH] fix - product filtering on distribuition dashboard --- .../commands/rebuild_org_quota_stats.py | 130 +++++++----------- .../services/quota_dashboard_service.py | 42 +++--- 2 files changed, 74 insertions(+), 98 deletions(-) diff --git a/apps/product/management/commands/rebuild_org_quota_stats.py b/apps/product/management/commands/rebuild_org_quota_stats.py index 03487cf..cf56d23 100644 --- a/apps/product/management/commands/rebuild_org_quota_stats.py +++ b/apps/product/management/commands/rebuild_org_quota_stats.py @@ -1,7 +1,7 @@ from django.core.management.base import BaseCommand from django.db import transaction -from apps.product.models import Quota, OrganizationQuotaStats, QuotaDistribution +from apps.product.models import Quota, OrganizationQuotaStats class Command(BaseCommand): @@ -11,102 +11,70 @@ class Command(BaseCommand): def handle(self, *args, **options): quotas = Quota.objects.prefetch_related('assigned_organizations').select_related( 'registerer_organization', 'product' - ) - print("sssss") + ).all() + created = 0 existing = 0 updated = 0 merged = 0 for quota in quotas: + create_org_stat_by_quota(quota) + create_org_stat_by_distribution(quota) - # 1) registerer org - target_orgs = {quota.registerer_organization} - # 2) assigned orgs - # for org in quota.assigned_organizations.all(): - # target_orgs.add(org) +def create_org_stat_by_quota(quota: Quota): + was_created = 0 + is_created = 0 - for org in target_orgs: - if not org: - continue + org_quota_stat, created = OrganizationQuotaStats.objects.get_or_create( + quota=quota, + organization=quota.registerer_organization, + total_amount=quota.quota_weight, + total_distributed=quota.quota_distributed, + remaining_amount=quota.remaining_weight, + free_sale_balance=quota.free_sale_balance, + pre_sale_balance=quota.pre_sale_balance, + stat_type='quota' + ) - qs = OrganizationQuotaStats.objects.filter( - quota=quota, - organization=org, - ) + if created: + is_created += 1 + else: + was_created += 1 - if qs.exists(): - # If multiple exist → keep one, delete others - if qs.count() > 1: - first = qs.first() - qs.exclude(id=first.id).delete() + print('is_created:', is_created, '\n', 'was_created:', was_created) - existing += 1 - # continue - # Create new one - # quota_stat = OrganizationQuotaStats.objects.create( - # quota=quota, - # organization=org, - # total_amount=quota.quota_weight, - # remaining_amount=quota.remaining_weight, - # total_distributed=quota.quota_distributed, - # stat_type="quota" - # ) - # created += 1 +def create_org_stat_by_distribution(quota: Quota): + main_stat = OrganizationQuotaStats.objects.get(quota=quota, stat_type="quota") + distributions = quota.distributions_assigned.filter() - # ---- 2) Create OrganizationQuotaStats for each QuotaDistribution ---- - distributions = QuotaDistribution.objects.select_related( - "assigned_organization", "quota" - ) - print(len(distributions)) + was_created = 0 + created = 0 - for dist in distributions: - org = dist.assigned_organization - quota = dist.quota + for dist in distributions: + org_quota_stat, created = OrganizationQuotaStats.objects.get_or_create( + quota=quota, + organization=dist.assigned_organization, + total_amount=dist.weight, + total_distributed=dist.distributed, + remaining_amount=dist.remaining_weight, + free_sale_balance=dist.free_sale_balance, + pre_sale_balance=dist.pre_sale_balance, + inventory_received=dist.warehouse_entry, + inventory_entry_balance=dist.warehouse_balance, + sold_amount=dist.been_sold, + stat_type="distributions", + ) - if not quota or not org: - continue + if created: + created += 1 + else: + was_created += 1 - dist_qs = OrganizationQuotaStats.objects.filter( - quota=quota, organization=org - ) + main_stat.distributions.add(dist) - if dist_qs.exists(): - if dist_qs.count() > 1: - first = dist_qs.first() - dist_qs.exclude(id=first.id).delete() - merged += 1 + print(org_quota_stat) - # Update existing record with distribution weight (optional) - # record = qs.first() - # record.total_distributed += dist.weight - # record.total_amount += dist.weight - # record.remaining_amount = max(record.total_amount - record.sold_amount, 0) - # record.save() - # updated += 1 - - else: - # Create new stats for this distribution - dist_qs = OrganizationQuotaStats.objects.create( - quota=quota, - organization=org, - total_amount=dist.weight, - total_distributed=dist.distributed, - remaining_amount=dist.remaining_weight, - free_sale_balance=dist.free_sale_balance, - pre_sale_balance=dist.pre_sale_balance, - stat_type="distribution", - ) - qs.first().distributions.add(dist) - created += 1 - - self.stdout.write( - self.style.SUCCESS( - f"OrganizationQuotaStats Rebuild Completed:" - f"\n Created: {created}" - f"\n Updated: {updated}" - f"\n Merged: {merged}" - ) - ) + print('created:', created, '\n', 'was_created:', was_created) diff --git a/apps/product/services/quota_dashboard_service.py b/apps/product/services/quota_dashboard_service.py index 50df7b4..d386df3 100644 --- a/apps/product/services/quota_dashboard_service.py +++ b/apps/product/services/quota_dashboard_service.py @@ -14,28 +14,36 @@ class QuotaDashboardService: @staticmethod def get_dashboard(self, org: Organization, start_date: str = None, end_date: str = None, - search_fields: list[str] = None, quota_is_closed: bool = False, query_string: str = None): + search_fields: list[str] = None, quota_is_closed: bool = False, query_string: str = None, + product_id: int = None, + ): distribution_number = 0 + base_filter = {} # filter queries + + if product_id: + base_filter['quota__product_id'] = product_id + if quota_is_closed: + base_filter['quota__is_closed'] = quota_is_closed if org.type.key == 'ADM': org_quota_stats = OrganizationQuotaStats.objects.filter( stat_type='quota', - quota__is_closed=quota_is_closed + **base_filter ) dist_org_quota_stats = OrganizationQuotaStats.objects.filter( stat_type='distribution', - quota__is_closed=quota_is_closed + **base_filter ) else: org_quota_stats = OrganizationQuotaStats.objects.filter( organization=org, - quota__is_closed=quota_is_closed, + **base_filter ) dist_org_quota_stats = OrganizationQuotaStats.objects.filter( stat_type='distribution', organization=org, - quota__is_closed=quota_is_closed + **base_filter ) # filter queryset (transactions & items) by date @@ -49,18 +57,18 @@ class QuotaDashboardService: query_string=query_string ).apply() - for stat in org_quota_stats.distinct('quota'): - if org.type.key == 'ADM': - distribution_number += QuotaDistribution.objects.select_related('quota').filter( - quota=stat.quota, - quota__is_closed=False - ).count() - else: - distribution_number += QuotaDistribution.objects.filter( - Q(assigner_organization=org), - quota=stat.quota, - quota__is_closed=False - ).count() + quota_ids = org_quota_stats.values_list("quota_id", flat=True) + if org.type.key == 'ADM': + distribution_number += QuotaDistribution.objects.select_related('quota').filter( + quota_id__in=quota_ids, + quota__is_closed=False + ).count() + else: + distribution_number += QuotaDistribution.objects.filter( + Q(assigner_organization=org), + quota_id__in=quota_ids, + quota__is_closed=False + ).count() org_quota_stats = org_quota_stats.aggregate( total_quotas=Count("quota", distinct=True),