业务日期端到端:状态库快照 + 下载写入 + 报告读库
- state_store: site_status 加 expected/actual/undelivered_business_date 列(建表+旧库迁移);set_data_state 加可选 business_date(None 时保留,心跳不覆盖下载快照) - runtime: dispatch_task 下载成功后快照业务日期(today−offset);4 站 undelivered 一并补写 expected/actual/undelivered 三列(_site_undelivered_handler 内部连下绕过 dispatch,否则应到/实到业务日期丢失) - expected_undelivered: 报告数据日期列改读状态库(_read_business_dates),退役 mtime 反推;KPI 卡 2-3-2-2 等宽对齐 + 柱状图图例 overlay 分行 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -44,6 +44,9 @@ def init_db():
|
||||
actual_generated_at TEXT,
|
||||
undelivered_ready INTEGER,
|
||||
undelivered_generated_at TEXT,
|
||||
expected_business_date TEXT,
|
||||
actual_business_date TEXT,
|
||||
undelivered_business_date TEXT,
|
||||
updated_at TEXT
|
||||
)
|
||||
""")
|
||||
@@ -51,6 +54,9 @@ def init_db():
|
||||
for _col, _typedef in [
|
||||
("undelivered_ready", "INTEGER NOT NULL DEFAULT 0"),
|
||||
("undelivered_generated_at", "TEXT NOT NULL DEFAULT ''"),
|
||||
("expected_business_date", "TEXT NOT NULL DEFAULT ''"),
|
||||
("actual_business_date", "TEXT NOT NULL DEFAULT ''"),
|
||||
("undelivered_business_date", "TEXT NOT NULL DEFAULT ''"),
|
||||
]:
|
||||
try:
|
||||
conn.execute(f"ALTER TABLE site_status ADD COLUMN {_col} {_typedef}")
|
||||
@@ -111,7 +117,8 @@ def _upsert(conn, site, **fields):
|
||||
"""更新(或插入)单站:保留未传字段,刷新 updated_at。"""
|
||||
row = conn.execute(
|
||||
"SELECT login_state, login_checked_at, expected_ready, expected_generated_at, "
|
||||
"actual_ready, actual_generated_at, undelivered_ready, undelivered_generated_at "
|
||||
"expected_business_date, actual_ready, actual_generated_at, actual_business_date, "
|
||||
"undelivered_ready, undelivered_generated_at, undelivered_business_date "
|
||||
"FROM site_status WHERE site = ?",
|
||||
(site,),
|
||||
).fetchone()
|
||||
@@ -120,10 +127,13 @@ def _upsert(conn, site, **fields):
|
||||
"login_checked_at": "",
|
||||
"expected_ready": 0,
|
||||
"expected_generated_at": "",
|
||||
"expected_business_date": "",
|
||||
"actual_ready": 0,
|
||||
"actual_generated_at": "",
|
||||
"actual_business_date": "",
|
||||
"undelivered_ready": 0,
|
||||
"undelivered_generated_at": "",
|
||||
"undelivered_business_date": "",
|
||||
}
|
||||
if row:
|
||||
(
|
||||
@@ -131,10 +141,13 @@ def _upsert(conn, site, **fields):
|
||||
cur["login_checked_at"],
|
||||
cur["expected_ready"],
|
||||
cur["expected_generated_at"],
|
||||
cur["expected_business_date"],
|
||||
cur["actual_ready"],
|
||||
cur["actual_generated_at"],
|
||||
cur["actual_business_date"],
|
||||
cur["undelivered_ready"],
|
||||
cur["undelivered_generated_at"],
|
||||
cur["undelivered_business_date"],
|
||||
) = row
|
||||
cur.update(fields)
|
||||
cur["updated_at"] = _now()
|
||||
@@ -145,26 +158,31 @@ def _upsert(conn, site, **fields):
|
||||
cur["login_checked_at"],
|
||||
cur["expected_ready"],
|
||||
cur["expected_generated_at"],
|
||||
cur["expected_business_date"],
|
||||
cur["actual_ready"],
|
||||
cur["actual_generated_at"],
|
||||
cur["actual_business_date"],
|
||||
cur["undelivered_ready"],
|
||||
cur["undelivered_generated_at"],
|
||||
cur["undelivered_business_date"],
|
||||
cur["updated_at"],
|
||||
)
|
||||
if row:
|
||||
conn.execute(
|
||||
"UPDATE site_status SET login_state=?, login_checked_at=?, expected_ready=?, "
|
||||
"expected_generated_at=?, actual_ready=?, actual_generated_at=?, "
|
||||
"undelivered_ready=?, undelivered_generated_at=?, updated_at=? "
|
||||
"expected_generated_at=?, expected_business_date=?, actual_ready=?, "
|
||||
"actual_generated_at=?, actual_business_date=?, undelivered_ready=?, "
|
||||
"undelivered_generated_at=?, undelivered_business_date=?, updated_at=? "
|
||||
"WHERE site=?",
|
||||
values[1:] + (site,),
|
||||
)
|
||||
else:
|
||||
conn.execute(
|
||||
"INSERT INTO site_status (site, login_state, login_checked_at, expected_ready, "
|
||||
"expected_generated_at, actual_ready, actual_generated_at, "
|
||||
"undelivered_ready, undelivered_generated_at, updated_at) "
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
"expected_generated_at, expected_business_date, actual_ready, actual_generated_at, "
|
||||
"actual_business_date, undelivered_ready, undelivered_generated_at, "
|
||||
"undelivered_business_date, updated_at) "
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
values,
|
||||
)
|
||||
conn.commit()
|
||||
@@ -185,14 +203,17 @@ def reset_login_states(sites):
|
||||
_upsert(conn, site, login_state=LOGIN_UNKNOWN, login_checked_at="")
|
||||
|
||||
|
||||
def set_data_state(site, kind, ready, generated_at):
|
||||
"""更新单站数据态。kind: 'expected'/'actual'/'undelivered';ready: bool;generated_at: str。"""
|
||||
key_ready = f"{kind}_ready"
|
||||
key_at = f"{kind}_generated_at"
|
||||
def set_data_state(site, kind, ready, generated_at, business_date=None):
|
||||
"""更新单站数据态。kind: 'expected'/'actual'/'undelivered';ready: bool;
|
||||
generated_at: str。business_date: str 或 None——None 时保留原值(心跳不覆盖下载快照)。"""
|
||||
fields = {
|
||||
f"{kind}_ready": 1 if ready else 0,
|
||||
f"{kind}_generated_at": generated_at or "",
|
||||
}
|
||||
if business_date is not None:
|
||||
fields[f"{kind}_business_date"] = business_date or ""
|
||||
with sqlite3.connect(STATE_DB_PATH) as conn:
|
||||
_upsert(
|
||||
conn, site, **{key_ready: 1 if ready else 0, key_at: generated_at or ""}
|
||||
)
|
||||
_upsert(conn, site, **fields)
|
||||
|
||||
|
||||
def get_all_status():
|
||||
@@ -202,8 +223,9 @@ def get_all_status():
|
||||
with sqlite3.connect(STATE_DB_PATH) as conn:
|
||||
rows = conn.execute(
|
||||
"SELECT site, login_state, login_checked_at, expected_ready, "
|
||||
"expected_generated_at, actual_ready, actual_generated_at, "
|
||||
"undelivered_ready, undelivered_generated_at, updated_at "
|
||||
"expected_generated_at, expected_business_date, actual_ready, "
|
||||
"actual_generated_at, actual_business_date, undelivered_ready, "
|
||||
"undelivered_generated_at, undelivered_business_date, updated_at "
|
||||
"FROM site_status"
|
||||
).fetchall()
|
||||
return {
|
||||
@@ -212,11 +234,14 @@ def get_all_status():
|
||||
"login_checked_at": r[2],
|
||||
"expected_ready": bool(r[3]),
|
||||
"expected_generated_at": r[4],
|
||||
"actual_ready": bool(r[5]),
|
||||
"actual_generated_at": r[6],
|
||||
"undelivered_ready": bool(r[7]),
|
||||
"undelivered_generated_at": r[8],
|
||||
"updated_at": r[9],
|
||||
"expected_business_date": r[5],
|
||||
"actual_ready": bool(r[6]),
|
||||
"actual_generated_at": r[7],
|
||||
"actual_business_date": r[8],
|
||||
"undelivered_ready": bool(r[9]),
|
||||
"undelivered_generated_at": r[10],
|
||||
"undelivered_business_date": r[11],
|
||||
"updated_at": r[12],
|
||||
}
|
||||
for r in rows
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user