fix(P0-01): missing score 不得变 0:0 — score_status + CHECK 约束

新增 matches.score_status(known/missing/unknown):
- 替换 ck_matches_finished_has_score 为 ck_matches_score_integrity:
  known → 必须有分; missing/unknown → goals 必须 NULL(不伪造 0:0)
- normalize: 完赛缺分不再静默降级为 scheduled,改设 score_status=missing
- events ingest: 创建/更新 Match 同步 score_status(比分由缺变 known / 确认缺分 missing)
- slices(form/h2h/home_away)/backtest: 显式加 score_status='known' 过滤完赛样本
- 迁移 0022 回填现有数据(绝不 UPDATE goals=0)

测试 tests/test_p0_score_status.py(9/9):约束存在性/Match 构造/normalize 行为。
54 相关测试全绿。
This commit is contained in:
shangfangjian
2026-09-22 02:32:53 +08:00
parent f563d5cc99
commit 63caa6736c
9 changed files with 226 additions and 4 deletions
+11
View File
@@ -202,6 +202,7 @@ class BzzoiroSource:
match_date=nm.date,
match_date_date=_to_date(nm.date),
match_status=nm.match_status,
score_status=nm.score_status,
home_goals=nm.home_goals,
away_goals=nm.away_goals,
home_ht_goals=nm.home_ht_goals,
@@ -238,6 +239,16 @@ class BzzoiroSource:
existing_match.away_goals = nm.away_goals
existing_match.home_ht_goals = nm.home_ht_goals
existing_match.away_ht_goals = nm.away_ht_goals
# 比分由缺变有 → 标记 known
existing_match.score_status = "known"
changed = True
elif (
nm.match_status == "finished"
and nm.home_goals is None
and existing_match.score_status == "unknown"
):
# 确认完赛仍缺分 → 标记 missing(不伪造 0:0)
existing_match.score_status = "missing"
changed = True
if existing_match.match_stage is None and nm.match_stage:
existing_match.match_stage = nm.match_stage