fix(dupont): reject out-of-domain window + bidirectional clip + suffix discipline (R1-R4/M2)
ci/woodpecker/push/main Pipeline failed
ci/woodpecker/push/main Pipeline failed
Per finance ruling 2026-10-05 (project-20261005-dupont-oob-window-fix): - R1: no intersection with available month domain => explicit error (endpoint 400), no window fields - R2: with intersection => intersection window, months>=1 (kills inversion and months<=0) - R3: quarter/half/... suffix kept only when returned window == nominal window (clipped flag) - R4: symmetric lower-bound clip note; M2: TTM nominal window = [anchor-11, anchor] (12 months) - M1: docstring correction (lower-bound overflow is clipped, not 400) No push / no deploy / no restart / no DB write.
This commit is contained in:
@@ -23,7 +23,7 @@ from app.utils.deviation_engine import calc_period_deviation, calc_period_diff,
|
||||
from app.utils.alert_entity_scope import month_period_clause
|
||||
from app.utils.profitability_params import load_profitability_params
|
||||
from app.utils.dupont_basis import (
|
||||
annualize_factors, available_months, build_window_meta, check_identity,
|
||||
annualize_factors, apply_period_suffix, available_months, build_window_meta, check_identity,
|
||||
compute_factors, latest_stock_month, load_dupont_params, months_between, prev_month,
|
||||
resolve_window, stock_balance, sum_flows,
|
||||
)
|
||||
@@ -2330,9 +2330,9 @@ def get_dupont_analysis(
|
||||
name_row = db.execute(
|
||||
text("SELECT name FROM entities WHERE id = :eid"), {"eid": entity_id}).first()
|
||||
entity_name = (name_row[0] if name_row else None) or ("陕西酣客文化传媒" if slug == "hanke" else "陕西博海网络科技")
|
||||
suffix = {"ytd": "(YTD 年初至今)", "ttm": "(TTM 滚动 12 月)", "month": "(单月)",
|
||||
"quarter": "(季度)", "half": "(半年)", "year": "(全年)", "custom": "(自定义区间)"}
|
||||
label = win["label"] + suffix.get(win["period_key"], "")
|
||||
# R3 后缀纪律:仅在「返回窗口 == 名义窗口」(未裁剪)时保留「(季度)/(半年)…」后缀;
|
||||
# 发生任何裁剪 ⇒ 去后缀,period = 实际窗口标签(判据由 resolve_window 回传 `clipped`)。
|
||||
label = apply_period_suffix(win["label"], win["period_key"], bool(win.get("clipped")))
|
||||
|
||||
cur = _dupont_window_values(db, entity_id, caliber, win["period_start"], win["period_end"])
|
||||
ann = annualize_factors(dict(cur["factors"]), win["months"], annualize)
|
||||
|
||||
Reference in New Issue
Block a user