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(
|
quotas = Quota.objects.prefetch_related('assigned_organizations').select_related(
|
||||||
'registerer_organization', 'product'
|
'registerer_organization', 'product'
|
||||||
)
|
)
|
||||||
|
print("sssss")
|
||||||
created = 0
|
created = 0
|
||||||
existing = 0
|
existing = 0
|
||||||
updated = 0
|
updated = 0
|
||||||
@@ -43,23 +43,24 @@ class Command(BaseCommand):
|
|||||||
qs.exclude(id=first.id).delete()
|
qs.exclude(id=first.id).delete()
|
||||||
|
|
||||||
existing += 1
|
existing += 1
|
||||||
continue
|
# continue
|
||||||
|
|
||||||
# Create new one
|
# Create new one
|
||||||
quota_stat = OrganizationQuotaStats.objects.create(
|
# quota_stat = OrganizationQuotaStats.objects.create(
|
||||||
quota=quota,
|
# quota=quota,
|
||||||
organization=org,
|
# organization=org,
|
||||||
total_amount=quota.quota_weight,
|
# total_amount=quota.quota_weight,
|
||||||
remaining_amount=quota.remaining_weight,
|
# remaining_amount=quota.remaining_weight,
|
||||||
total_distributed=quota.quota_distributed,
|
# total_distributed=quota.quota_distributed,
|
||||||
stat_type="quota"
|
# stat_type="quota"
|
||||||
)
|
# )
|
||||||
created += 1
|
# created += 1
|
||||||
|
|
||||||
# ---- 2) Create OrganizationQuotaStats for each QuotaDistribution ----
|
# ---- 2) Create OrganizationQuotaStats for each QuotaDistribution ----
|
||||||
distributions = QuotaDistribution.objects.select_related(
|
distributions = QuotaDistribution.objects.select_related(
|
||||||
"assigned_organization", "quota"
|
"assigned_organization", "quota"
|
||||||
)
|
)
|
||||||
|
print(len(distributions))
|
||||||
|
|
||||||
for dist in distributions:
|
for dist in distributions:
|
||||||
org = dist.assigned_organization
|
org = dist.assigned_organization
|
||||||
@@ -68,27 +69,27 @@ class Command(BaseCommand):
|
|||||||
if not quota or not org:
|
if not quota or not org:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
qs = OrganizationQuotaStats.objects.filter(
|
dist_qs = OrganizationQuotaStats.objects.filter(
|
||||||
quota=quota, organization=org
|
quota=quota, organization=org
|
||||||
)
|
)
|
||||||
|
|
||||||
if qs.exists():
|
if dist_qs.exists():
|
||||||
if qs.count() > 1:
|
if dist_qs.count() > 1:
|
||||||
first = qs.first()
|
first = dist_qs.first()
|
||||||
qs.exclude(id=first.id).delete()
|
dist_qs.exclude(id=first.id).delete()
|
||||||
merged += 1
|
merged += 1
|
||||||
|
|
||||||
# Update existing record with distribution weight (optional)
|
# Update existing record with distribution weight (optional)
|
||||||
record = qs.first()
|
# record = qs.first()
|
||||||
record.total_distributed += dist.weight
|
# record.total_distributed += dist.weight
|
||||||
record.total_amount += dist.weight
|
# record.total_amount += dist.weight
|
||||||
record.remaining_amount = max(record.total_amount - record.sold_amount, 0)
|
# record.remaining_amount = max(record.total_amount - record.sold_amount, 0)
|
||||||
record.save()
|
# record.save()
|
||||||
updated += 1
|
# updated += 1
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Create new stats for this distribution
|
# Create new stats for this distribution
|
||||||
dist_stat = OrganizationQuotaStats.objects.create(
|
dist_qs = OrganizationQuotaStats.objects.create(
|
||||||
quota=quota,
|
quota=quota,
|
||||||
organization=org,
|
organization=org,
|
||||||
total_amount=dist.weight,
|
total_amount=dist.weight,
|
||||||
@@ -98,7 +99,7 @@ class Command(BaseCommand):
|
|||||||
pre_sale_balance=dist.pre_sale_balance,
|
pre_sale_balance=dist.pre_sale_balance,
|
||||||
stat_type="distribution",
|
stat_type="distribution",
|
||||||
)
|
)
|
||||||
quota_stat.distributions.add(dist)
|
qs.first().distributions.add(dist)
|
||||||
created += 1
|
created += 1
|
||||||
|
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
|
|||||||
@@ -16,14 +16,27 @@ class QuotaDashboardService:
|
|||||||
def get_dashboard(self, org: Organization, start_date: str = None, end_date: str = None,
|
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):
|
||||||
|
|
||||||
|
distribution_number = 0
|
||||||
|
|
||||||
if org.type.key == 'ADM':
|
if org.type.key == 'ADM':
|
||||||
org_quota_stats = OrganizationQuotaStats.objects.filter(stat_type='quota', quota__is_closed=quota_is_closed)
|
org_quota_stats = OrganizationQuotaStats.objects.filter(
|
||||||
print(len(org_quota_stats), quota_is_closed)
|
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:
|
else:
|
||||||
org_quota_stats = OrganizationQuotaStats.objects.filter(
|
org_quota_stats = OrganizationQuotaStats.objects.filter(
|
||||||
organization=org,
|
organization=org,
|
||||||
quota__is_closed=quota_is_closed,
|
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
|
# filter queryset (transactions & items) by date
|
||||||
if (start_date and end_date) or query_string:
|
if (start_date and end_date) or query_string:
|
||||||
@@ -36,6 +49,19 @@ class QuotaDashboardService:
|
|||||||
query_string=query_string
|
query_string=query_string
|
||||||
).apply()
|
).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(
|
org_quota_stats = org_quota_stats.aggregate(
|
||||||
total_quotas=Count("quota", distinct=True),
|
total_quotas=Count("quota", distinct=True),
|
||||||
total_distributed=Coalesce(Sum("total_distributed", ), 0),
|
total_distributed=Coalesce(Sum("total_distributed", ), 0),
|
||||||
@@ -46,12 +72,25 @@ class QuotaDashboardService:
|
|||||||
inventory_entry_balance=Coalesce(Sum("inventory_entry_balance", ), 0),
|
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 {
|
return {
|
||||||
"quotas_summary": org_quota_stats,
|
"quotas_summary": org_quota_stats,
|
||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@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 = []
|
stat_by_prod = []
|
||||||
for prod_name, prod_id in products.items():
|
for prod_name, prod_id in products.items():
|
||||||
@@ -59,6 +98,18 @@ class QuotaDashboardService:
|
|||||||
organization=organization,
|
organization=organization,
|
||||||
quota__product_id=prod_id
|
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(
|
product_stat_data = org_quota_stat.aggregate(
|
||||||
quotas_count=Count('id'),
|
quotas_count=Count('id'),
|
||||||
total_quotas_weight=Coalesce(models.Sum('total_amount'), 0),
|
total_quotas_weight=Coalesce(models.Sum('total_amount'), 0),
|
||||||
@@ -88,13 +139,13 @@ class QuotaDashboardService:
|
|||||||
|
|
||||||
# product total distributed weight from quota
|
# product total distributed weight from quota
|
||||||
given_distribution_weight = QuotaDistribution.objects.select_related(
|
given_distribution_weight = QuotaDistribution.objects.select_related(
|
||||||
'quota', 'assigned_organization'
|
'quota', 'assigner_organization'
|
||||||
).filter(
|
).filter(
|
||||||
quota__product_id=prod_id,
|
quota__product_id=prod_id,
|
||||||
quota__is_closed=False,
|
quota__is_closed=False,
|
||||||
assigner_organization=organization,
|
assigner_organization=organization,
|
||||||
) if not organization.type.key == 'ADM' else QuotaDistribution.objects.select_related(
|
) if not organization.type.key == 'ADM' else QuotaDistribution.objects.select_related(
|
||||||
'quota', 'assigned_organization'
|
'quota', 'assigner_organization'
|
||||||
).filter(
|
).filter(
|
||||||
quota__product_id=prod_id,
|
quota__product_id=prod_id,
|
||||||
quota__is_closed=False,
|
quota__is_closed=False,
|
||||||
|
|||||||
@@ -410,12 +410,23 @@ class QuotaViewSet(BaseViewSet, SoftDeleteMixin, QuotaDashboardService, viewsets
|
|||||||
dashboard of all quotas & their information
|
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)
|
org = get_organization_by_user(request.user)
|
||||||
query_param = self.request.query_params # noqa
|
query_param = self.request.query_params # noqa
|
||||||
|
|
||||||
# filter by date
|
# filter by date
|
||||||
start_date = query_param.get('start') if 'start' in query_param.keys() else None
|
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
|
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
|
# filter by quota is close or open
|
||||||
is_closed = True if 'is_closed' in query_param.keys() else False
|
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}
|
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)
|
return Response(dashboard_data_by_product)
|
||||||
|
|
||||||
|
|||||||
@@ -126,7 +126,11 @@ class InventoryQuotaSaleTransactionSerializer(serializers.ModelSerializer):
|
|||||||
'id': instance.rancher.id,
|
'id': instance.rancher.id,
|
||||||
'national_code': instance.rancher.national_code
|
'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:
|
if instance.seller_organization:
|
||||||
representation['seller_organization'] = {
|
representation['seller_organization'] = {
|
||||||
'id': instance.seller_organization.id,
|
'id': instance.seller_organization.id,
|
||||||
|
|||||||
Reference in New Issue
Block a user