"""报表与 BI 大盘集成测试。""" import pytest from datetime import date from decimal import Decimal from model_bakery import baker from rest_framework.test import APIClient from rest_framework_simplejwt.tokens import RefreshToken from apps.catalog.models import Product from apps.inventory.models import Warehouse, Stock from apps.partner.models import Customer, Supplier from apps.sales.models import SalesBill, SalesBillLine from apps.purchase.models import PurchaseBill from apps.finance.models import Receivable, Payable from apps.report import services as report_services from apps.report.models import ReportDefinition @pytest.fixture def auth_client(db, user, tenant): client = APIClient() refresh = RefreshToken.for_user(user) client.credentials( HTTP_AUTHORIZATION=f"Bearer {refresh.access_token}", HTTP_X_TENANT_ID=tenant.code, ) return client @pytest.mark.django_db def test_init_system_reports(tenant): count = report_services.init_system_reports(tenant) assert count == 4 assert ReportDefinition.objects.filter(tenant=tenant).count() == 4 # 幂等性 assert report_services.init_system_reports(tenant) == 0 @pytest.mark.django_db def test_dashboard_summary_and_valuation(tenant): wh = baker.make(Warehouse, tenant=tenant, code="WH01", name="总仓") p1 = baker.make(Product, tenant=tenant, code="P01", name="商品1") p2 = baker.make(Product, tenant=tenant, code="P02", name="商品2") # 创建库存并设置成本 baker.make(Stock, tenant=tenant, warehouse=wh, product=p1, on_hand=Decimal("100"), avg_cost=Decimal("10")) baker.make(Stock, tenant=tenant, warehouse=wh, product=p2, on_hand=Decimal("50"), avg_cost=Decimal("20")) # 创建销售与采购 cust = baker.make(Customer, tenant=tenant, code="C01", name="客户1") sb = baker.make(SalesBill, tenant=tenant, customer=cust, bill_date=date.today(), total_amount=Decimal("5000"), state="confirmed") sup = baker.make(Supplier, tenant=tenant, code="S01", name="供应商1") pb = baker.make(PurchaseBill, tenant=tenant, supplier=sup, bill_date=date.today(), total_amount=Decimal("3000"), state="confirmed") # 应收应付 baker.make(Receivable, tenant=tenant, customer=cust, total_amount=Decimal("5000"), paid_amount=Decimal("2000"), status="partial", bill_date=date.today()) baker.make(Payable, tenant=tenant, supplier=sup, total_amount=Decimal("3000"), paid_amount=Decimal("1000"), status="partial", bill_date=date.today()) summary = report_services.get_dashboard_summary(tenant) assert summary["month_sales"]["amount"] == Decimal("5000") assert summary["month_purchase"]["amount"] == Decimal("3000") assert summary["inventory"]["sku_count"] == 2 assert summary["inventory"]["total_quantity"] == Decimal("150") # 估值 = 100*10 + 50*20 = 2000 assert summary["inventory"]["valuation"] == Decimal("2000") # 待收 3000,待付 2000 assert summary["finance"]["receivable_balance"] == Decimal("3000") assert summary["finance"]["payable_balance"] == Decimal("2000") @pytest.mark.django_db def test_sales_rank_analytics(tenant): cust1 = baker.make(Customer, tenant=tenant, code="C1", name="客户1") cust2 = baker.make(Customer, tenant=tenant, code="C2", name="客户2") prod1 = baker.make(Product, tenant=tenant, code="P1", name="雪碧") prod2 = baker.make(Product, tenant=tenant, code="P2", name="可乐") bill1 = baker.make(SalesBill, tenant=tenant, customer=cust1, state="confirmed", bill_date=date.today()) baker.make(SalesBillLine, tenant=tenant, bill=bill1, product=prod1, quantity=Decimal("10"), amount=Decimal("300")) baker.make(SalesBillLine, tenant=tenant, bill=bill1, product=prod2, quantity=Decimal("5"), amount=Decimal("200")) bill2 = baker.make(SalesBill, tenant=tenant, customer=cust2, state="confirmed", bill_date=date.today()) baker.make(SalesBillLine, tenant=tenant, bill=bill2, product=prod1, quantity=Decimal("20"), amount=Decimal("600")) # 按商品排行 prod_rank = report_services.get_sales_rank(tenant, rank_by="product") assert len(prod_rank) == 2 assert prod_rank[0]["product_code"] == "P1" assert prod_rank[0]["total_amount"] == Decimal("900") # 按客户排行 cust_rank = report_services.get_sales_rank(tenant, rank_by="customer") assert len(cust_rank) == 2 assert cust_rank[0]["customer_code"] == "C2" assert cust_rank[0]["total_amount"] == Decimal("600") @pytest.mark.django_db def test_report_api_endpoints(auth_client, tenant): # 初始化报表 r1 = auth_client.post("/api/v1/report/definitions/init-system/") assert r1.status_code == 200 assert r1.json()["ok"] is True # 查询大盘总览 API r2 = auth_client.get("/api/v1/report/dashboard/summary/") assert r2.status_code == 200 assert "inventory" in r2.json() # 查询销售排行 API r3 = auth_client.get("/api/v1/report/dashboard/sales-rank/?rank_by=product") assert r3.status_code == 200 assert "results" in r3.json()