产品调价继承工单币种(港币不再默成美元);陆运集拼空分档只填询价重量那一档,跨境整车按已选线路写起讫。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
linmianxun
2026-10-12 19:22:44 +08:00
co-authored by Cursor
parent 3a4c440354
commit 97f0219dfd
8 changed files with 678 additions and 47 deletions
+8 -3
View File
@@ -629,14 +629,19 @@ def apply_air_quote(
fields = extract_air_collab_fields(text)
if fields:
flow.ledger.patch_collab_facts(work_order_no=no, facts=fields, sender_id=sender_id)
view = ticket_view(ticket)
current = dict(view.get("quote") or {})
from agent.policy.sea_group_ops import _quote_currency_hint
quote = injected_quote or extract_product_quote(
text, business_line="AIR", transport_mode="空运"
text,
business_line="AIR",
transport_mode="空运",
baseline_currency=_quote_currency_hint(current),
) or {}
if not quote:
send_group_text(client, chat_id, copy.air_quote_not_recognized())
return "quote_empty"
view = ticket_view(ticket)
current = dict(view.get("quote") or {})
if _has_tms_quote(current) and not _is_product_quote(current):
_park_air_pending(flow, no, quote, sender_id)
send_group_text(client, chat_id, copy.group_ask_tms_or_product())
@@ -18,6 +18,7 @@ from agent.llm.extract_text import extract_collab_fields, extract_product_quote
from agent.policy import inquiry_copy as copy
from agent.policy.multi_segments import Segment, group_brief, includes_air, segments_from_payload
from agent.policy.sea_group_ops import (
_quote_currency_hint,
apply_group_deal,
group_client_of,
is_sales,
@@ -152,6 +153,12 @@ def handle_multi_inbound(
ticket = _reload(flow, no) or ticket
segments = load_segments(ticket)
target = next((seg for seg in segments if seg.mode == mode), target)
# 段报价币种优先;否则用工单顶层 quote(产品未写币种时继承 TMS)
baseline = ""
if target is not None:
baseline = _quote_currency_hint((segment_quotes(ticket) or {}).get(target.mode) or {})
if not baseline:
baseline = _quote_currency_hint(dict(ticket_view(ticket).get("quote") or {}))
quote = extract_product_quote(
text or "",
injected=injected_quote,
@@ -160,6 +167,7 @@ def handle_multi_inbound(
"陆运" if str(mode or "").upper() == "LAND"
else ("空运" if str(mode or "").upper() == "AIR" else "海运")
),
baseline_currency=baseline,
)
if not quote:
if fields:
+49 -1
View File
@@ -930,18 +930,19 @@ def apply_product_quote(
merged.update(fields)
sess.collab_facts = merged
line = str(view.get("business_line") or view.get("businessLine") or "").strip().upper()
base = _current_quote(view, sess)
quote = extract_product_quote(
text,
injected=injected_quote,
business_line=line,
transport_mode="陆运" if line == "LAND" else ("海运" if line == "SEA" else ""),
baseline_currency=_quote_currency_hint(base),
)
if not quote:
logger.info("产品报价未识别 wo=%s text=%s", no, (text or "")[:200])
send_group_text(client, chat_id, copy.group_quote_not_recognized())
return "quote_not_recognized"
quote = _attach_land_weight_band_segment(quote, view)
base = _current_quote(view, sess)
if _has_tms_quote(base):
_park_pending_quote(no, quote, sess, flow)
send_group_text(client, chat_id, copy.group_ask_tms_or_product())
@@ -1405,6 +1406,53 @@ def _current_quote(view: dict[str, Any], sess: Any) -> dict[str, Any]:
return base
def _quote_currency_hint(quote: dict[str, Any] | None) -> str:
"""
当前报价币种提示:顶层 currency → 金额前缀 → 费用行/线路段。
产品改价未写币种时继承此值,禁止默认 USD(WO202610090107 中港 HKD)。
"""
src = dict(quote or {})
for key in ("currency", "currencyCode"):
code = str(src.get(key) or "").strip().upper()
if code:
return code
for key in ("cost", "total", "freight", "land_freight"):
raw = str(src.get(key) or "").strip().upper()
for prefix in ("HKD", "CNY", "USD", "EUR", "JPY", "GBP", "RMB"):
if raw.startswith(prefix):
return "CNY" if prefix == "RMB" else prefix
for row in _quote_fee_rows(src):
code = str(row.get("currency") or row.get("currencyCode") or "").strip().upper()
if code:
return code
for key in ("landSegments", "route_rows", "selected_land_route"):
raw = src.get(key)
if isinstance(raw, str) and raw.strip():
try:
import json
raw = json.loads(raw)
except Exception:
continue
if isinstance(raw, dict):
legs = raw.get("legs") if isinstance(raw.get("legs"), list) else [raw]
for leg in legs:
if not isinstance(leg, dict):
continue
code = str(leg.get("currency") or "").strip().upper()
if code:
return code
elif isinstance(raw, list):
for leg in raw:
if not isinstance(leg, dict):
continue
code = str(leg.get("currency") or "").strip().upper()
if code:
return code
return ""
def _has_tms_quote(quote: dict[str, Any] | None) -> bool:
"""当前价来自 TMS 才要问;产品价、销售调价不再替用户选。"""
src = dict(quote or {})