Files
dealerhub/backend/apps/report/views.py
T

86 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""报表中心 ViewSets:
1. ReportDefinitionViewSet: 报表元数据 CRUD + run 执行报表 + init_system 预置报表
2. DashboardViewSet: 经营大盘总览指标、销售排行、库存透视
"""
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.exceptions import ValidationError
from asgiref.sync import sync_to_async
from adrf.viewsets import ViewSet
from apps.core.viewset import BaseTenantViewSet
from .models import ReportDefinition
from .serializers import ReportDefinitionSerializer
from . import services as report_services
class ReportDefinitionViewSet(BaseTenantViewSet):
model = ReportDefinition
serializer_class = ReportDefinitionSerializer
search_fields = ["code", "name", "description"]
@action(detail=False, methods=["post"], url_path="init-system")
async def init_system(self, request):
"""一键初始化系统预置标准报表。"""
tenant = await self.get_tenant()
if not tenant:
raise ValidationError({"tenant": "无法识别租户"})
n = await sync_to_async(report_services.init_system_reports)(tenant)
return Response({"ok": True, "created_count": n, "message": f"成功初始化 {n} 个系统报表定义"})
@action(detail=True, methods=["post", "get"], url_path="run")
async def run_report(self, request, pk=None):
"""执行指定报表定义并返回数据。"""
tenant = await self.get_tenant()
try:
report_def = await sync_to_async(self.model.objects.get)(tenant=tenant, pk=pk)
except self.model.DoesNotExist:
return Response({"detail": "报表不存在"}, status=status.HTTP_404_NOT_FOUND)
data = await sync_to_async(report_services.execute_report_definition)(tenant, report_def)
return Response(data)
class DashboardViewSet(ViewSet):
"""进销存与财务经营大盘。"""
async def get_tenant(self):
from apps.core.viewset import resolve_tenant
from django.conf import settings
code = self.request.META.get("HTTP_X_TENANT_ID", settings.TENANT_DEFAULT)
return await sync_to_async(resolve_tenant)(code)
@action(detail=False, methods=["get"], url_path="summary")
async def summary(self, request):
"""获取本月经营总览指标(销售额、采购额、库存估值、应收应付总额)。"""
tenant = await self.get_tenant()
if not tenant:
raise ValidationError({"tenant": "无法识别租户"})
data = await sync_to_async(report_services.get_dashboard_summary)(tenant)
return Response(data)
@action(detail=False, methods=["get"], url_path="sales-rank")
async def sales_rank(self, request):
"""销售排行:参数 rank_by=product/customer,top_n=10。"""
tenant = await self.get_tenant()
if not tenant:
raise ValidationError({"tenant": "无法识别租户"})
rank_by = request.query_params.get("rank_by", "product")
try:
top_n = int(request.query_params.get("top_n", 10))
except ValueError:
top_n = 10
data = await sync_to_async(report_services.get_sales_rank)(tenant, rank_by=rank_by, top_n=top_n)
return Response({"rank_by": rank_by, "results": data})
@action(detail=False, methods=["get"], url_path="inventory-status")
async def inventory_status(self, request):
"""各仓库库存分布与资产估值。"""
tenant = await self.get_tenant()
if not tenant:
raise ValidationError({"tenant": "无法识别租户"})
data = await sync_to_async(report_services.get_inventory_status_report)(tenant)
return Response(data)