fix(reports): profit-summary 真实科目取数重建(去 KPI 比率倒推/硬编码 0.50 + 勾稽自检 + entity 隔离)
ci/woodpecker/push/main Pipeline was canceled

This commit is contained in:
hermes
2026-10-14 23:14:41 +08:00
parent 6d8ef0d443
commit 2244cd79b7
4 changed files with 829 additions and 118 deletions
+29 -14
View File
@@ -91,31 +91,46 @@ class TestProfitSummary:
BASE = "/api/cma/reports/profit-summary"
def test_profit_summary_with_data(self, client: TestClient, db: Session):
"""有数据时:营收/变动成本/边际贡献/固定成本/息税前利润 + 环比"""
"""有真账数据时:收入/变动成本/边际贡献/固定成本/营业利润 + 勾稽自检
2026-10-14 重建:原断言编码了被审计实锤的 3 处硬伤(KPI 比率倒推 / 变动成本=营收×五成 /
末行装净利率值却贴「息税前利润」),故改为断言**真实科目发生额**与勾稽自检。
口径与逐行取数证据见 tests/test_profit_summary_real_caliber_20261014.py。
"""
import datetime as _dt
from app.models import VoucherDetail
create_test_user(db)
token = get_token_for_user(client)
seed_profit_kpis(db)
# e1 口径真账:收入 5001 贷 1,000,000;变动 5401 借 600,000;固定 5602 借 250,000(元)
d = _dt.datetime(2026, 6, 30)
for i, (code, dr, cr) in enumerate(
[("5001", 0.0, 1_000_000.0), ("5401", 600_000.0, 0.0), ("5602", 250_000.0, 0.0)], start=1):
db.add(VoucherDetail(entity_id=1, voucher_no=f"U{i}", voucher_date=d,
subject_code=code, subject_name="单测科目",
debit_amount=dr, credit_amount=cr, summary="单测",
carry_forward=0, period="2026-06", batch="unit-test"))
db.commit()
resp = client.get(f"{self.BASE}?period=2026-06", headers=auth_header(token))
assert resp.status_code == 200
data = resp.json()
assert data["period"] == "2026-06"
assert data["prev_period"] == "2026-05"
assert data["available"] is True
items = {i["name"]: i for i in data["items"]}
# 营业收入 100 vs 上期80 → +25%
assert items["营业收入"]["value"] == 100.0
assert items["营业收入"]["prev_value"] == 80.0
assert items["营业收入"]["change_rate"] == 25.0
# 变动成本 = 营收×50% = 50
assert items["减:变动成本"]["value"] == 50.0
# 边际贡献 = 毛利 = 100×20% = 20
assert items["= 边际贡献"]["value"] == 20.0
assert items["减:变动成本"]["value"] == 60.0 # 5401 借 600,000 元
assert items["= 边际贡献"]["value"] == 40.0
assert items["= 边际贡献"]["is_subtotal"] is True
# 固定成本 = 总成本60 - 变动成本50 = 10
assert items["减:固定成本"]["value"] == 10.0
# 息税前利润 = 100×10% = 10
assert items["= 息税前利润"]["value"] == 10.0
assert items["= 息税前利润"]["is_total"] is True
assert items["减:固定成本"]["value"] == 25.0
# 末行标签与算法一致(原为「= 息税前利润」装净利率值)
assert data["bottom_label"] == "营业利润"
assert items["= 营业利润"]["value"] == 15.0
assert items["= 营业利润"]["is_total"] is True
# 勾稽自检:收入 − 变动成本 − 固定成本 = 末行
assert data["reconciliation"]["balanced"] is True
assert data["reconciliation"]["diff"] == 0.0
def test_profit_summary_empty_db(self, client: TestClient, db: Session):
"""无任何KPI数据 → 200,值全部为None,不报错"""