Files
KCGL/inventory-backend/app/services/track_query_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

64 lines
2.4 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_query_service.py
"""
Track 系统产品查询服务(拉取侧)
扫码入库时,通过 httpx GET 调用 Track 的对外查询接口 /api/v1/external/products/lookup
根据身份证serial_number获取产品基础信息。
容错策略:
- 未配置 TRACK_API_URL / TRACK_WEBHOOK_KEY 时返回 None。
- 全包裹 try-except任何异常连接拒绝/超时/网络错误/4xx/5xx仅记录日志
返回 None 交给上层决定如何提示,绝不抛出异常阻断业务。
"""
import logging
import httpx
from flask import current_app
logger = logging.getLogger(__name__)
# 请求超时(秒):查询属于同步交互,超时后由上层提示失败
_QUERY_TIMEOUT = 5.0
def lookup_product(code):
"""
根据身份证16 位 serial_number或业务序列号查询 Track 产品信息。
返回 Track 查询接口的 data 字典(含 serial_number/external_serial/material_id/
sku/material_name/spec_model/material_type/order_no未命中或异常返回 None。
"""
try:
base_url = (current_app.config.get('TRACK_API_URL') or '').strip()
api_key = (current_app.config.get('TRACK_WEBHOOK_KEY') or '').strip()
if not base_url:
logger.info("[TrackQuery] 未配置 TRACK_API_URL跳过查询")
return None
if not api_key:
logger.info("[TrackQuery] 未配置 TRACK_WEBHOOK_KEY跳过查询")
return None
url = f'{base_url}/api/v1/external/products/lookup'
headers = {
'Content-Type': 'application/json',
# ★ 鉴权字段名必须为 X-API-Key与 Track 接收端严格对齐
'X-API-Key': api_key,
}
resp = httpx.get(url, params={'code': code}, headers=headers, timeout=_QUERY_TIMEOUT)
if resp.status_code == 200:
data = resp.json()
track_info = (data or {}).get('data')
if track_info:
logger.info("[TrackQuery] 查询命中 code=%s", code)
return track_info
logger.info("[TrackQuery] 查询返回空数据 code=%s status=%s", code, resp.status_code)
return None
logger.info(
"[TrackQuery] 查询未命中 code=%s status=%s body=%s",
code, resp.status_code, resp.text[:200],
)
return None
except Exception as e:
logger.error("[TrackQuery] 查询失败 code=%s, err=%s", code, e)
return None