feat: OCR 面单 enrichment flow (api/ocr/ + flows/sds/label_ocr.py + db OCR 方法)

This commit is contained in:
yeuimu
2026-07-23 16:15:24 +00:00
parent 8ab0aededa
commit 51dbde4538
6 changed files with 266 additions and 0 deletions
+53
View File
@@ -98,6 +98,59 @@ class SyncDB:
rows = cur.fetchall()
return [(r[0], r[1]) for r in rows]
# ---------- OCR 面单 enrichment ----------
def get_ocr_pending(self, limit: int = 200) -> list[tuple[str, datetime, str, str | None]]:
"""查待 OCR 的 SDS 订单:(orderNo, createdAt, labelPdfUrl, destinationCountry)。
条件:SDS、有 labelPdfUrl、ocr_layout 未处理(Null)、已发货/已完成。
"""
with self._conn() as conn:
with conn.cursor() as cur:
cur.execute(
'''SELECT "orderNo","createdAt","labelPdfUrl","destinationCountry"
FROM "Orders"
WHERE "systemName"=%s AND "labelPdfUrl" IS NOT NULL
AND "ocr_layout" IS NULL
AND "systemStatus"=ANY(%s)
ORDER BY "orderedAt" DESC LIMIT %s''',
("SDS", ["已完成", "部分发货", "备货中", "待确认"], limit),
)
return [(r[0], r[1], r[2], r[3]) for r in cur.fetchall()]
def update_ocr_fields(
self, order_no: str, created_at: datetime, fields: dict[str, str | None]
) -> None:
"""更新单个订单的 ocr_* 字段。fields 为 {ocr_xxx: value} 字典。"""
if not fields:
return
assignments = ", ".join(f'"{k}"=%s' for k in fields)
params = list(fields.values()) + [order_no, created_at]
with self._conn() as conn:
with conn.cursor() as cur:
cur.execute(
f'''UPDATE "Orders" SET {assignments}
WHERE "orderNo"=%s AND "createdAt"=%s''',
params,
)
conn.commit()
def count_ocr_status(self) -> dict[str, int]:
"""统计 OCR 处理状态(done/error/unsupported/pending)。"""
with self._conn() as conn:
with conn.cursor() as cur:
cur.execute(
'''SELECT
COUNT(*) FILTER (WHERE "ocr_layout" IS NOT NULL AND "ocr_layout" NOT IN ('ERROR','UNSUPPORTED')) AS done,
COUNT(*) FILTER (WHERE "ocr_layout"='ERROR') AS error,
COUNT(*) FILTER (WHERE "ocr_layout"='UNSUPPORTED') AS unsupported,
COUNT(*) FILTER (WHERE "ocr_layout" IS NULL AND "labelPdfUrl" IS NOT NULL) AS pending
FROM "Orders" WHERE "systemName"=%s''',
("SDS",),
)
row = cur.fetchone()
return {"done": row[0], "error": row[1], "unsupported": row[2], "pending": row[3]} if row else {}
# ---------- 主 upsert ----------
def sync_orders_and_goods(