feat(db_compare): add PostgreSQL-based comparison engine with SF handling
Replace Excel-based undelivered comparison with DB queries for all four sites. The engine anchors on actual scan_time, reverse-lookups handover batches, and compares expected vs actual waybill-by-waybill. Shunxin SF waybills: use COUNT(*) instead of COUNT(DISTINCT piece_no) since SF piece numbers are random and not derivable from the waybill. Changes: - db_compare.py: new module with compare_site_date(), compare_site_batch(), write_result_excel(), and POST /compare API endpoint - runtime.py: switch _site_undelivered_handler from compare.write_site_file (Excel) to db_compare (DB); downloads succeed independently of comparison - server.py: add POST /compare endpoint with date validation - docs: implementation plan for Shunxin DB comparison Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -476,23 +476,44 @@ def _web_handler(site, download_func):
|
||||
|
||||
|
||||
def _site_undelivered_handler(site):
|
||||
"""4 站未到:下应到+实到 → 比对写 downloads/<站>-未到数据.xlsx。
|
||||
任一下载失败 → 清掉旧未到文件、返回 False(前端不展示陈旧未到)。"""
|
||||
"""4 站未到:下应到+实到 → DB 比对 → 写 output/<站>-<日期>-未到数据.xlsx。
|
||||
应到全量去重(已落库则跳过导出),因此比对不依赖 Excel 文件,走数据库查询。
|
||||
下载成功则返回 True(比对失败不影响任务判定,数据已入库)。"""
|
||||
|
||||
def handler(ctx, force=False, date=None):
|
||||
# 各站下载入口约定返回 True/False;顺心历史返回 None(视为成功,与 dispatch 一致)
|
||||
exp_ok = TASK_HANDLERS[(site, "expected")](ctx, force, date) is not False
|
||||
act_ok = (
|
||||
(TASK_HANDLERS[(site, "actual")](ctx, force, date) is not False)
|
||||
if exp_ok
|
||||
else False
|
||||
)
|
||||
if exp_ok and act_ok:
|
||||
return compare.write_site_file(site)
|
||||
stale = os.path.join(DOWNLOAD_DIR, SITE_UNDELIVERED_FILE.format(name=site))
|
||||
if os.path.exists(stale):
|
||||
os.remove(stale)
|
||||
return False
|
||||
if not exp_ok or not act_ok:
|
||||
stale = os.path.join(DOWNLOAD_DIR, SITE_UNDELIVERED_FILE.format(name=site))
|
||||
if os.path.exists(stale):
|
||||
os.remove(stale)
|
||||
return False
|
||||
|
||||
# ── DB 比对(替代旧 Excel 比对)──
|
||||
try:
|
||||
from inbound_verify import db_compare # 懒导入,避免成环
|
||||
|
||||
if date:
|
||||
target_date = date
|
||||
else:
|
||||
offset = state_store.get_offset(site, "expected")
|
||||
target_date = (datetime.now().date() - timedelta(days=offset)).strftime(
|
||||
"%Y-%m-%d"
|
||||
)
|
||||
|
||||
result = db_compare.compare_site_date(site, target_date)
|
||||
if result is not None:
|
||||
db_compare.write_result_excel(result)
|
||||
else:
|
||||
print(f">> [未到] {site} {target_date}: 当天无实到数据,跳过比对")
|
||||
except Exception as e:
|
||||
print(f">> [未到] {site} DB 比对异常(不影响下载结果): {e}")
|
||||
|
||||
return True # 下载成功即返回 True,比对失败不影响任务判定
|
||||
|
||||
return handler
|
||||
|
||||
|
||||
Reference in New Issue
Block a user