From 91db54982c8cf5e79e84acff00f449fd19b09596 Mon Sep 17 00:00:00 2001 From: yueli Date: Tue, 22 Sep 2026 13:13:54 +0800 Subject: [PATCH] =?UTF-8?q?feat(track):=20=E5=85=A5=E5=BA=93/=E5=87=BA?= =?UTF-8?q?=E5=BA=93=20webhook=20=E6=8C=89=E5=85=AC=E5=8F=B8=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=E5=88=B0=E5=AF=B9=E5=BA=94=E5=AE=9E=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 三个触发点此前都不带 company_name,无从路由: · product_service / semi_service:入库通知补 material.company_name · outbound_service:track_notifications 元组加 company(取自 stock_record.base.company_name;维修单走 repair.base,两处 relationship 均已定义),发送时带进 payload 出库路径同时**去掉**了显式传入的 url=TRACK_OUTBOUND_WEBHOOK_URL —— url 参数优先级最高,保留它会让出库永远打到默认实例,company 路由形同 虚设。url 参数本身保留,需要强制覆盖时仍可用。 实测: LICA 入库:待仓库收货 → 已入库,IRIS 库该 SN 0 行 LICA 出库:已入库 → 已出库,IRIS 库该 SN 0 行 IRIS 回归:对已入库设备重发入库通知,状态幂等不变 精确隔离:发一条 IRIS 通知,lica_backend 日志 +0 行、track_backend +19 行 注意:不做"两个实例都推一遍"——两个 Track 的 webhook key 是同一把、 两边都会鉴权通过,而 Track 按 serial_number/sku 匹配,相同型号设备会 同时命中两库,把 IRIS 的设备误标成已入库,且产生 2 倍审计与流转节点。 --- .../app/services/inbound/product_service.py | 2 ++ .../app/services/inbound/semi_service.py | 2 ++ .../app/services/outbound_service.py | 23 +++++++++++++------ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/inventory-backend/app/services/inbound/product_service.py b/inventory-backend/app/services/inbound/product_service.py index 98af718..a08d2b1 100644 --- a/inventory-backend/app/services/inbound/product_service.py +++ b/inventory-backend/app/services/inbound/product_service.py @@ -226,6 +226,8 @@ class ProductInboundService: 'sku': material.spec_model or material.name, 'serial_number': new_stock.serial_number, 'quantity': float(new_stock.in_quantity or 0), + # ★ 公司名决定通知哪个 Track 实例(IRIS / LICA),缺失则回落默认 + 'company_name': getattr(material, 'company_name', None), 'operator': get_current_operator(), }) return new_stock diff --git a/inventory-backend/app/services/inbound/semi_service.py b/inventory-backend/app/services/inbound/semi_service.py index 20a4e79..1e0fc7a 100644 --- a/inventory-backend/app/services/inbound/semi_service.py +++ b/inventory-backend/app/services/inbound/semi_service.py @@ -265,6 +265,8 @@ class SemiInboundService: 'sku': material.spec_model or material.name, 'serial_number': webhook_sn, 'quantity': float(new_stock.in_quantity or 0), + # ★ 公司名决定通知哪个 Track 实例(IRIS / LICA),缺失则回落默认 + 'company_name': getattr(material, 'company_name', None), 'operator': get_current_operator(), }) return new_stock diff --git a/inventory-backend/app/services/outbound_service.py b/inventory-backend/app/services/outbound_service.py index 7b03c33..bb77bf4 100644 --- a/inventory-backend/app/services/outbound_service.py +++ b/inventory-backend/app/services/outbound_service.py @@ -359,7 +359,11 @@ class OutboundService: repair.shipping_date = current_time # 收集 Track 联动信息(维修单带 serial_number) - track_notifications.append((getattr(repair, 'serial_number', None), source_table, quantity)) + # ★ 连同 company_name 一起攒起来,发送时按公司路由到对应 Track 实例 + track_notifications.append(( + getattr(repair, 'serial_number', None), source_table, quantity, + getattr(getattr(repair, 'base', None), 'company_name', None), + )) # 创建出库记录 new_record = TransOutbound( @@ -394,7 +398,11 @@ class OutboundService: raise ValueError(f"库存记录不存在 (ID: {stock_id})") # 收集 Track 联动信息(库存表 serial_number = Track 身份证) - track_notifications.append((getattr(stock_record, 'serial_number', None), source_table, quantity)) + # ★ 连同 company_name 一起攒起来,发送时按公司路由到对应 Track 实例 + track_notifications.append(( + getattr(stock_record, 'serial_number', None), source_table, quantity, + getattr(getattr(stock_record, 'base', None), 'company_name', None), + )) new_record = TransOutbound( sku=item.get('sku'), @@ -419,11 +427,11 @@ class OutboundService: db.session.commit() # ★ 出库后通知 Track(发货出库 → Track 标记"已出库") - # 仅在配置 TRACK_OUTBOUND_WEBHOOK_URL 时生效;notify_track 自身容错不阻断业务 + # 按每条的 company_name 路由到对应实例(IRIS / LICA)。 + # 这里刻意**不**显式传 url:显式 url 优先级最高,会一律打到默认实例, + # 导致 LICA 的出库永远收不到联动。notify_track 自身容错,不阻断业务。 try: - from flask import current_app - outbound_url = current_app.config.get('TRACK_OUTBOUND_WEBHOOK_URL') - for sn, src_tbl, qty in track_notifications: + for sn, src_tbl, qty, company in track_notifications: if not sn: continue notify_track({ @@ -432,8 +440,9 @@ class OutboundService: 'serial_number': str(sn), 'quantity': float(qty or 0), 'outbound_type': common_data['outbound_type'], + 'company_name': company, 'operator': get_current_operator(), - }, url=outbound_url) + }) except Exception as e: import logging logging.getLogger(__name__).warning(f"⚠️ Track 出库通知失败: {e}")