import - distributioin stat type for distribution tab
This commit is contained in:
@@ -12,7 +12,7 @@ class Command(BaseCommand):
|
||||
quotas = Quota.objects.prefetch_related('assigned_organizations').select_related(
|
||||
'registerer_organization', 'product'
|
||||
)
|
||||
|
||||
print("sssss")
|
||||
created = 0
|
||||
existing = 0
|
||||
updated = 0
|
||||
@@ -43,23 +43,24 @@ class Command(BaseCommand):
|
||||
qs.exclude(id=first.id).delete()
|
||||
|
||||
existing += 1
|
||||
continue
|
||||
# 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
|
||||
# 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
|
||||
|
||||
# ---- 2) Create OrganizationQuotaStats for each QuotaDistribution ----
|
||||
distributions = QuotaDistribution.objects.select_related(
|
||||
"assigned_organization", "quota"
|
||||
)
|
||||
print(len(distributions))
|
||||
|
||||
for dist in distributions:
|
||||
org = dist.assigned_organization
|
||||
@@ -68,27 +69,27 @@ class Command(BaseCommand):
|
||||
if not quota or not org:
|
||||
continue
|
||||
|
||||
qs = OrganizationQuotaStats.objects.filter(
|
||||
dist_qs = OrganizationQuotaStats.objects.filter(
|
||||
quota=quota, organization=org
|
||||
)
|
||||
|
||||
if qs.exists():
|
||||
if qs.count() > 1:
|
||||
first = qs.first()
|
||||
qs.exclude(id=first.id).delete()
|
||||
if dist_qs.exists():
|
||||
if dist_qs.count() > 1:
|
||||
first = dist_qs.first()
|
||||
dist_qs.exclude(id=first.id).delete()
|
||||
merged += 1
|
||||
|
||||
# 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
|
||||
# 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_stat = OrganizationQuotaStats.objects.create(
|
||||
dist_qs = OrganizationQuotaStats.objects.create(
|
||||
quota=quota,
|
||||
organization=org,
|
||||
total_amount=dist.weight,
|
||||
@@ -98,7 +99,7 @@ class Command(BaseCommand):
|
||||
pre_sale_balance=dist.pre_sale_balance,
|
||||
stat_type="distribution",
|
||||
)
|
||||
quota_stat.distributions.add(dist)
|
||||
qs.first().distributions.add(dist)
|
||||
created += 1
|
||||
|
||||
self.stdout.write(
|
||||
|
||||
@@ -16,14 +16,27 @@ class QuotaDashboardService:
|
||||
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):
|
||||
|
||||
distribution_number = 0
|
||||
|
||||
if org.type.key == 'ADM':
|
||||
org_quota_stats = OrganizationQuotaStats.objects.filter(stat_type='quota', quota__is_closed=quota_is_closed)
|
||||
print(len(org_quota_stats), quota_is_closed)
|
||||
org_quota_stats = OrganizationQuotaStats.objects.filter(
|
||||
stat_type='quota',
|
||||
quota__is_closed=quota_is_closed
|
||||
)
|
||||
dist_org_quota_stats = OrganizationQuotaStats.objects.filter(
|
||||
stat_type='distribution',
|
||||
quota__is_closed=quota_is_closed
|
||||
)
|
||||
else:
|
||||
org_quota_stats = OrganizationQuotaStats.objects.filter(
|
||||
organization=org,
|
||||
quota__is_closed=quota_is_closed,
|
||||
)
|
||||
dist_org_quota_stats = OrganizationQuotaStats.objects.filter(
|
||||
stat_type='distribution',
|
||||
organization=org,
|
||||
quota__is_closed=quota_is_closed
|
||||
)
|
||||
|
||||
# filter queryset (transactions & items) by date
|
||||
if (start_date and end_date) or query_string:
|
||||
@@ -36,6 +49,19 @@ 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()
|
||||
|
||||
org_quota_stats = org_quota_stats.aggregate(
|
||||
total_quotas=Count("quota", distinct=True),
|
||||
total_distributed=Coalesce(Sum("total_distributed", ), 0),
|
||||
@@ -46,12 +72,25 @@ class QuotaDashboardService:
|
||||
inventory_entry_balance=Coalesce(Sum("inventory_entry_balance", ), 0),
|
||||
)
|
||||
|
||||
org_quota_stats.update(
|
||||
distribution_number=distribution_number,
|
||||
dist_remaining_amount=dist_org_quota_stats.aggregate(
|
||||
remaining_amount=Coalesce(Sum("remaining_amount"), 0), )['remaining_amount'] or 0,
|
||||
)
|
||||
|
||||
return {
|
||||
"quotas_summary": org_quota_stats,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def get_dashboard_by_product(self, organization: Organization, products: dict):
|
||||
def get_dashboard_by_product(
|
||||
self,
|
||||
organization: Organization,
|
||||
products: dict,
|
||||
start_date: str = None, end_date: str = None,
|
||||
search_fields: list[str] = None, quota_is_closed: bool = False,
|
||||
query_string: str = None
|
||||
):
|
||||
|
||||
stat_by_prod = []
|
||||
for prod_name, prod_id in products.items():
|
||||
@@ -59,6 +98,18 @@ class QuotaDashboardService:
|
||||
organization=organization,
|
||||
quota__product_id=prod_id
|
||||
)
|
||||
|
||||
# filter queryset (transactions & items) by date
|
||||
if (start_date and end_date) or query_string:
|
||||
org_quota_stats = DynamicSearchService(
|
||||
queryset=org_quota_stat,
|
||||
start=start_date,
|
||||
end=end_date,
|
||||
date_field="create_date",
|
||||
search_fields=search_fields,
|
||||
query_string=query_string
|
||||
).apply()
|
||||
|
||||
product_stat_data = org_quota_stat.aggregate(
|
||||
quotas_count=Count('id'),
|
||||
total_quotas_weight=Coalesce(models.Sum('total_amount'), 0),
|
||||
@@ -88,13 +139,13 @@ class QuotaDashboardService:
|
||||
|
||||
# product total distributed weight from quota
|
||||
given_distribution_weight = QuotaDistribution.objects.select_related(
|
||||
'quota', 'assigned_organization'
|
||||
'quota', 'assigner_organization'
|
||||
).filter(
|
||||
quota__product_id=prod_id,
|
||||
quota__is_closed=False,
|
||||
assigner_organization=organization,
|
||||
) if not organization.type.key == 'ADM' else QuotaDistribution.objects.select_related(
|
||||
'quota', 'assigned_organization'
|
||||
'quota', 'assigner_organization'
|
||||
).filter(
|
||||
quota__product_id=prod_id,
|
||||
quota__is_closed=False,
|
||||
|
||||
@@ -410,12 +410,23 @@ class QuotaViewSet(BaseViewSet, SoftDeleteMixin, QuotaDashboardService, viewsets
|
||||
dashboard of all quotas & their information
|
||||
"""
|
||||
|
||||
search_fields = [
|
||||
"quota__registerer_organization__name",
|
||||
"quota__quota_id",
|
||||
"quota__product__name",
|
||||
"quota__sale_type",
|
||||
"quota__sale_unit__unit",
|
||||
"quota__group",
|
||||
"quota__creator_info",
|
||||
]
|
||||
|
||||
org = get_organization_by_user(request.user)
|
||||
query_param = self.request.query_params # noqa
|
||||
|
||||
# filter by date
|
||||
start_date = query_param.get('start') if 'start' in query_param.keys() else None
|
||||
end_date = query_param.get('end') if 'end' in query_param.keys() else None
|
||||
query_string = query_param.get('search') if 'search' in query_param.keys() else None
|
||||
|
||||
# filter by quota is close or open
|
||||
is_closed = True if 'is_closed' in query_param.keys() else False
|
||||
@@ -428,7 +439,16 @@ class QuotaViewSet(BaseViewSet, SoftDeleteMixin, QuotaDashboardService, viewsets
|
||||
|
||||
products = {f'{stat.quota.product.name}': stat.quota.product.id for stat in org_quota_stat}
|
||||
|
||||
dashboard_data_by_product = self.get_dashboard_by_product(self, org, products)
|
||||
dashboard_data_by_product = self.get_dashboard_by_product(
|
||||
self,
|
||||
org,
|
||||
products,
|
||||
start_date=start_date,
|
||||
end_date=end_date,
|
||||
search_fields=search_fields,
|
||||
quota_is_closed=is_closed,
|
||||
query_string=query_string
|
||||
)
|
||||
|
||||
return Response(dashboard_data_by_product)
|
||||
|
||||
|
||||
@@ -126,7 +126,11 @@ class InventoryQuotaSaleTransactionSerializer(serializers.ModelSerializer):
|
||||
'id': instance.rancher.id,
|
||||
'national_code': instance.rancher.national_code
|
||||
}
|
||||
|
||||
if instance.pos_device:
|
||||
representation['pos_device'] = {
|
||||
'device_identity': instance.pos_device.device_identity,
|
||||
'serial': instance.pos_device.serial
|
||||
}
|
||||
if instance.seller_organization:
|
||||
representation['seller_organization'] = {
|
||||
'id': instance.seller_organization.id,
|
||||
|
||||
Reference in New Issue
Block a user