Files
KCGL/inventory-backend/app/services/track_webhook_service.py
yueli bee037f925 feat: MOM 扫码入库对接 Track 产品身份证自动填充
- 半成品/成品入库弹窗顶部新增'扫码入库'按钮,打开扫码面板(扫码枪/摄像头)
- 扫码 Track 身份证后自动填充物料信息与序列号,不再二次搜索
- 后端新增 track_query_service(httpx 调 Track lookup)、track-lookup 接口
- 入库成功后 notify_track 通知 Track 闭环
2026-09-01 13:52:56 +08:00

79 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# app/services/track_webhook_service.py
"""
Track 系统 Webhook 通知服务(发送侧)
真实扫码入库成功后,通过后台线程 + httpx 异步 POST 通知 Track 系统。
容错策略:
- 未配置 TRACK_WEBHOOK_URL 时静默跳过,不通知。
- 全包裹 try-except任何异常连接拒绝/超时/网络错误)仅记录 logger.error
绝不抛出异常阻断入库主业务流程。
"""
import logging
import threading
import httpx
from flask import current_app
logger = logging.getLogger(__name__)
# 请求超时(秒):后台线程,宁可超时失败也不能拖住业务
_WEBHOOK_TIMEOUT = 5.0
def _post_to_track(payload, url, api_key):
"""后台线程中执行的真正 POST 请求(含详细日志)"""
headers = {
'Content-Type': 'application/json',
# ★ 鉴权字段名必须为 X-API-Key与 Track 接收端严格对齐
'X-API-Key': api_key,
}
try:
resp = httpx.post(url, json=payload, headers=headers, timeout=_WEBHOOK_TIMEOUT)
logger.info(
"[TrackWebhook] event=%s source_table=%s status=%s",
payload.get('event'), payload.get('source_table'), resp.status_code,
)
except Exception as e:
logger.error("[TrackWebhook] 发送失败 url=%s, err=%s", url, e)
def get_current_operator():
"""从 JWT 中安全获取当前操作人姓名(失败返回空字符串,不抛异常)"""
try:
from flask_jwt_extended import get_jwt
claims = get_jwt()
if not claims:
return ''
# 优先显示名(如"张三"回退到账号ID
return claims.get('display_name') or claims.get('username') or ''
except Exception:
return ''
def notify_track(payload, url=None):
"""
异步通知 Track 系统业务事件(入库/出库等)。
调用方在 db.session.commit() 成功后调用,本函数绝不抛出异常:
- 未配置 URL / Key 为空 -> 静默跳过
- 网络异常 / 超时 -> 仅记录日志
:param url: 指定 Track webhook 地址;不传则用默认 TRACK_WEBHOOK_URL入库
"""
try:
url = (url or current_app.config.get('TRACK_WEBHOOK_URL') or '').strip()
api_key = (current_app.config.get('TRACK_WEBHOOK_KEY') or '').strip()
if not url:
logger.info("[TrackWebhook] 未配置 webhook URL跳过通知")
return
thread = threading.Thread(
target=_post_to_track,
args=(payload, url, api_key),
daemon=True, # 守护线程:不阻塞进程退出
name='track_webhook_notify',
)
thread.start()
except Exception as e:
logger.error("[TrackWebhook] 通知调用失败(不影响业务): %s", e)