产品调价继承工单币种(港币不再默成美元);陆运集拼空分档只填询价重量那一档,跨境整车按已选线路写起讫。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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 {})
|
||||
|
||||
Reference in New Issue
Block a user