docs: sync docs with current package layout and auto-ingest hook
- config.example.yaml: replace stale site_yunda/main_router with new module paths (sites.yunda, runtime) - CLAUDE.md: add ingest-one to DB CLI list; new subsection documenting the download->PostgreSQL auto-ingest hook (_persist_to_db, ingest_task, ingest_state, /status.ingest, auto_ingest config) - README.md: store tree comment lists all 5 CLI commands (add ingest-one) - docs: /status row notes the ingest field; anneng CDP guide snippet gets timeout=15 - cli/server.py: docstring run command -> python -m inbound_verify.cli.server Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
18
CLAUDE.md
18
CLAUDE.md
@@ -33,9 +33,9 @@ playwright install chromium
|
|||||||
.venv/Scripts/python.exe -m inbound_verify.cli.server
|
.venv/Scripts/python.exe -m inbound_verify.cli.server
|
||||||
# 或:inbound-verify-server
|
# 或:inbound-verify-server
|
||||||
|
|
||||||
# DB CLI:建库 / 初始化 / 灌数据 / 全流程
|
# DB CLI:建库 / 初始化 / 灌数据 / 全流程 / 单站单类
|
||||||
.venv/Scripts/python.exe -m inbound_verify.store createdb # 或 init | ingest | all
|
.venv/Scripts/python.exe -m inbound_verify.store createdb # 或 init | ingest | ingest-one <site> <kind> | all
|
||||||
# 或:inbound-verify-db createdb|init|ingest|all
|
# 或:inbound-verify-db createdb|init|ingest|ingest-one|all
|
||||||
|
|
||||||
# 单站点联调:在 config.yaml 设 debug.enabled=true + debug.target_site=顺心|百世|中通|韵达|安能
|
# 单站点联调:在 config.yaml 设 debug.enabled=true + debug.target_site=顺心|百世|中通|韵达|安能
|
||||||
# 网页站:只挂载该站;安能:只启动 Electron 应用。
|
# 网页站:只挂载该站;安能:只启动 Electron 应用。
|
||||||
@@ -112,6 +112,18 @@ playwright install chromium
|
|||||||
`inbound_verify.compare`(菜单 [9])纯离线:读 `downloads/` 下各站应到/实到 xlsx,
|
`inbound_verify.compare`(菜单 [9])纯离线:读 `downloads/` 下各站应到/实到 xlsx,
|
||||||
比对生成 `output/应到未到数据.xlsx`(汇总 + 各站明细)。
|
比对生成 `output/应到未到数据.xlsx`(汇总 + 各站明细)。
|
||||||
|
|
||||||
|
### 自动入库(下载成功后 → PostgreSQL)
|
||||||
|
`dispatch_task` 下载成功后,在 `_record_business_date` 旁挂一个**尽力而为**钩子
|
||||||
|
`_persist_to_db(site, kind)`(`runtime`):懒导入 `store`,调 `store.ingest_task(site, kind)`
|
||||||
|
按 kind 幂等 UPSERT 进 PostgreSQL(expected/actual 各入其列;undelivered——百世入未到、
|
||||||
|
4 站连入 expected+actual)。**绝不影响下载任务的成功判定**:所有写库/写状态都包 try/except,
|
||||||
|
失败只告警。
|
||||||
|
- 开关 `postgres.auto_ingest`(默认开)+ `connect_timeout_seconds`(兜 cpolar 抖动)。
|
||||||
|
- 可见性:结果写 `state_store.ingest_state`(每站每类 ok/count/ingested_at/error),经
|
||||||
|
`GET /status` 的 `ingest` 字段暴露。
|
||||||
|
- 手动:`store` CLI `ingest-one <site> <kind>` 用同套路由单测(脱离下载)。
|
||||||
|
- 注意:跑在 Playwright 线程、同步阻塞;cpolar 慢/断靠超时 + try/except 降级,不重试不补入。
|
||||||
|
|
||||||
### 路径
|
### 路径
|
||||||
`inbound_verify.paths` 把 `DOWNLOAD_DIR` / `CONFIG_PATH` / `BASE_DIR` 全部锚定到项目目录,
|
`inbound_verify.paths` 把 `DOWNLOAD_DIR` / `CONFIG_PATH` / `BASE_DIR` 全部锚定到项目目录,
|
||||||
**不依赖运行时 cwd**——别用相对路径或 `os.getcwd()`。
|
**不依赖运行时 cwd**——别用相对路径或 `os.getcwd()`。
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ InboundVerify/
|
|||||||
│ ├── state_store.py # SQLite 状态持久化(state/state.db)
|
│ ├── state_store.py # SQLite 状态持久化(state/state.db)
|
||||||
│ ├── domain.py # 站点 / 文件名 / 列映射共享配置(单一来源,leaf)
|
│ ├── domain.py # 站点 / 文件名 / 列映射共享配置(单一来源,leaf)
|
||||||
│ ├── compare.py # 全站点应到未到离线比对,输出 output/应到未到数据.xlsx
|
│ ├── compare.py # 全站点应到未到离线比对,输出 output/应到未到数据.xlsx
|
||||||
│ ├── store.py # DB CLI 入口(createdb|init|ingest|all)
|
│ ├── store.py # DB CLI 入口(createdb|init|ingest|ingest-one|all)
|
||||||
│ ├── sites/ # 各站点模块(流程 + 重置 + 重试,自洽)
|
│ ├── sites/ # 各站点模块(流程 + 重置 + 重试,自洽)
|
||||||
│ │ ├── shunxin.py # 顺心(含双账号)
|
│ │ ├── shunxin.py # 顺心(含双账号)
|
||||||
│ │ ├── baishi.py # 百世
|
│ │ ├── baishi.py # 百世
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ zto:
|
|||||||
# 韵达快运 (https://ky-sso.yunda56.com)
|
# 韵达快运 (https://ky-sso.yunda56.com)
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
yunda:
|
yunda:
|
||||||
# 自动登录的账号与密码(由 site_yunda.yunda_login 读取并填入登录表单)。
|
# 自动登录的账号与密码(由 inbound_verify.sites.yunda.yunda_login 读取并填入登录表单)。
|
||||||
# 留空时自动登录会填入空串导致登录失败,届时可在浏览器中改为手动登录。
|
# 留空时自动登录会填入空串导致登录失败,届时可在浏览器中改为手动登录。
|
||||||
# 真实凭据仅写进被 .gitignore 忽略的 config.yaml,切勿提交示例值。
|
# 真实凭据仅写进被 .gitignore 忽略的 config.yaml,切勿提交示例值。
|
||||||
username: "YOUR_USERNAME_HERE"
|
username: "YOUR_USERNAME_HERE"
|
||||||
@@ -58,9 +58,9 @@ yunda:
|
|||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# 安能全网门户(Electron 桌面应用,非网页)
|
# 安能全网门户(Electron 桌面应用,非网页)
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# 与其他站点不同:安能不由 main_router 用浏览器打开,而是以调试模式启动其
|
# 与其他站点不同:安能不由浏览器打开,而是以调试模式启动其
|
||||||
# Electron 可执行文件(自动选取一个空闲端口作为 --remote-debugging-port,避免端口冲突),
|
# Electron 可执行文件(自动选取一个空闲端口作为 --remote-debugging-port,避免端口冲突),
|
||||||
# 启动后请在应用内手动登录,main_router 会自动轮询判断是否进入主页。
|
# 启动后请在应用内手动登录,runtime 会自动轮询判断是否进入主页。
|
||||||
anneng:
|
anneng:
|
||||||
# 【已废弃】下载日期改由 Web 前端/API 按站点设偏移(0=今天,1=昨天…,存 state.db),此项不再生效。
|
# 【已废弃】下载日期改由 Web 前端/API 按站点设偏移(0=今天,1=昨天…,存 state.db),此项不再生效。
|
||||||
query_days: 1
|
query_days: 1
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ class CDP:
|
|||||||
"""绑定到单个页面目标的同步 CDP 客户端。"""
|
"""绑定到单个页面目标的同步 CDP 客户端。"""
|
||||||
|
|
||||||
def __init__(self, ws_url):
|
def __init__(self, ws_url):
|
||||||
self.ws = websocket.create_connection(ws_url)
|
self.ws = websocket.create_connection(ws_url, timeout=15) # 15s socket 超时:防 Electron 业务 tab 偶发不回包时 recv 无限阻塞
|
||||||
self._id = 0
|
self._id = 0
|
||||||
|
|
||||||
def call(self, method, **params):
|
def call(self, method, **params):
|
||||||
|
|||||||
@@ -87,7 +87,7 @@
|
|||||||
|
|
||||||
| 接口 | 返回内容 | 是否含应到/已到计数 |
|
| 接口 | 返回内容 | 是否含应到/已到计数 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `GET /status` | 各站 `login_state` + `expected/actual/undelivered_ready` + `business_date` + `worker_ready` | **不含**计数,只给就绪标志 |
|
| `GET /status` | 各站 `login_state` + `expected/actual/undelivered_ready` + `business_date` + `worker_ready` + `ingest`(每站每类入库 ok/count/时间) | **不含**应到/已到件数计数(`ingest` 是入库条数,非核销件数) |
|
||||||
| `GET /report` | `FileResponse(output/应到未到数据.xlsx)` | 计数只在 xlsx 里 |
|
| `GET /report` | `FileResponse(output/应到未到数据.xlsx)` | 计数只在 xlsx 里 |
|
||||||
| `GET /data/{filename}` | 下载 `downloads/` 下某源文件 | 原始数据,非统计值 |
|
| `GET /data/{filename}` | 下载 `downloads/` 下某源文件 | 原始数据,非统计值 |
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
# 独占所有 page 操作;与主线程仅经 Queue + SQLite 通信。
|
# 独占所有 page 操作;与主线程仅经 Queue + SQLite 通信。
|
||||||
# 违反"路由不碰 Playwright"会崩(sync 对象跨线程访问)。
|
# 违反"路由不碰 Playwright"会崩(sync 对象跨线程访问)。
|
||||||
#
|
#
|
||||||
# 运行:python server.py (默认监听 0.0.0.0:8000)
|
# 运行:python -m inbound_verify.cli.server (或 inbound-verify-server;默认监听 0.0.0.0:8000)
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import queue
|
import queue
|
||||||
|
|||||||
Reference in New Issue
Block a user