落地销售调价:按自然语言改价并单独记销售价,拉群和后台不再把调后价当成 TMS 原价。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -65,6 +65,7 @@ def ticket_view(ticket: object) -> dict[str, Any]:
|
||||
)
|
||||
view.setdefault("sales_name", view.get("salesName") or view.get("sales_name") or "")
|
||||
view.setdefault("lost_reason", view.get("lostReason") or view.get("lost_reason") or "")
|
||||
view.setdefault("tms_quote", view.get("tmsQuote") or view.get("tms_quote") or {})
|
||||
facts = dict(view.get("collab_facts") or view.get("collabFacts") or {})
|
||||
view.setdefault("collab_facts", facts)
|
||||
flag = str(facts.get("__ended") or view.get("collab_ended") or view.get("collabEnded") or "").strip().lower()
|
||||
@@ -83,6 +84,7 @@ def ticket_view(ticket: object) -> dict[str, Any]:
|
||||
"business_line": getattr(ticket, "business_line", "") or "SEA",
|
||||
"facts": dict(getattr(ticket, "facts", {}) or {}),
|
||||
"quote": dict(getattr(ticket, "quote", {}) or {}),
|
||||
"tms_quote": dict(getattr(ticket, "tms_quote", None) or {}),
|
||||
"collab_facts": dict(getattr(ticket, "collab_facts", {}) or {}),
|
||||
"collab_chat_id": getattr(ticket, "collab_chat_id", "") or "",
|
||||
"collab_member_ids": list(getattr(ticket, "collab_member_ids", []) or []),
|
||||
@@ -327,7 +329,9 @@ def hydrate_ticket(flow: Any, ticket: object) -> object:
|
||||
quote = dict(view.get("quote") or {})
|
||||
has_quote = bool(quote.get("total") or _quote_fee_rows(quote))
|
||||
has_status = bool(ticket_status(ticket))
|
||||
if has_facts and has_quote and has_status:
|
||||
has_tms = bool(dict(view.get("tms_quote") or view.get("tmsQuote") or {}))
|
||||
# 调价后 latest quote 仍有价,但不能因此跳过补 TMS 原价。
|
||||
if has_facts and has_quote and has_status and has_tms:
|
||||
return ticket
|
||||
no = ticket_no(ticket)
|
||||
sales = str(view.get("sales_wecom_id") or view.get("salesWecomId") or "").strip()
|
||||
@@ -352,6 +356,8 @@ def hydrate_ticket(flow: Any, ticket: object) -> object:
|
||||
merged["facts"] = dict(full_view.get("facts") or {})
|
||||
if (not has_quote) and full_view.get("quote"):
|
||||
merged["quote"] = dict(full_view.get("quote") or {})
|
||||
if full_view.get("tms_quote") or full_view.get("tmsQuote"):
|
||||
merged["tms_quote"] = dict(full_view.get("tms_quote") or full_view.get("tmsQuote") or {})
|
||||
if (not has_status) and full_view.get("status"):
|
||||
merged["status"] = full_view.get("status")
|
||||
collab = dict(full_view.get("collab_facts") or {})
|
||||
@@ -393,10 +399,7 @@ def send_brief_and_sheet(
|
||||
tms = dict(tms_quote) if tms_quote is not None else {}
|
||||
manual = dict(product_quote or {})
|
||||
if tms_quote is None:
|
||||
if _has_tms_quote(view_q) and not copy.quote_is_product(view_q):
|
||||
tms = view_q
|
||||
elif _has_tms_quote(sess_q) and not copy.quote_is_product(sess_q):
|
||||
tms = sess_q
|
||||
tms = copy.resolve_tms_quote(sess, view)
|
||||
if not manual:
|
||||
if copy.quote_is_product(override):
|
||||
manual = override
|
||||
@@ -691,6 +694,8 @@ def apply_product_quote(
|
||||
_park_pending_quote(no, quote, sess, flow)
|
||||
send_group_text(client, chat_id, copy.group_ask_tms_or_product())
|
||||
return "wait_tms_choice"
|
||||
if _quote_fee_rows(base):
|
||||
quote = merge_quote_fees(base, quote)
|
||||
_save_product_quote(flow, no, quote, sess)
|
||||
ticket2 = _reload(flow, chat_id, no) or ticket
|
||||
send_brief_and_sheet(
|
||||
@@ -954,7 +959,18 @@ def emit_group_deal(
|
||||
text = copy.group_deal_followup(sales_name=sales_name, work_order_no=no)
|
||||
send_group_text(client, chat_id, text)
|
||||
carder = getattr(client, "send_group_card", None)
|
||||
payload = copy.deal_wecom_payload(work_order_no=no, quote=q, facts=facts, card_version=ver)
|
||||
payload = copy.deal_wecom_payload(
|
||||
work_order_no=no,
|
||||
quote=q,
|
||||
facts=facts,
|
||||
card_version=ver,
|
||||
business_line=str(
|
||||
view.get("business_line")
|
||||
or getattr(sess, "business_line", "")
|
||||
or q.get("business_line")
|
||||
or ""
|
||||
),
|
||||
)
|
||||
if callable(carder):
|
||||
carder(chat_id=chat_id, template_card=payload.get("template_card") or {})
|
||||
|
||||
@@ -1104,14 +1120,11 @@ def _current_quote(view: dict[str, Any], sess: Any) -> dict[str, Any]:
|
||||
|
||||
|
||||
def _has_tms_quote(quote: dict[str, Any] | None) -> bool:
|
||||
"""当前价来自 TMS 才要问;已经是产品价不再替用户选。"""
|
||||
"""当前价来自 TMS 才要问;产品价、销售调价不再替用户选。"""
|
||||
src = dict(quote or {})
|
||||
label = str(src.get("source_label") or src.get("source") or "")
|
||||
if "产品" in label:
|
||||
return False
|
||||
if not (src.get("total") or _quote_fee_rows(src)):
|
||||
return False
|
||||
return "TMS" in label.upper() or "标准报价" in label or not label
|
||||
return copy.quote_is_tms(src)
|
||||
|
||||
|
||||
def _park_pending_quote(no: str, quote: dict[str, Any], sess: Any, flow: Any) -> None:
|
||||
@@ -1378,12 +1391,39 @@ def merge_quote_fees(base: dict[str, Any] | None, overlay: dict[str, Any] | None
|
||||
return out
|
||||
|
||||
|
||||
def _save_product_quote(flow: Any, no: str, quote: dict[str, Any], sess: Any) -> None:
|
||||
def _save_product_quote(
|
||||
flow: Any,
|
||||
no: str,
|
||||
quote: dict[str, Any],
|
||||
sess: Any,
|
||||
*,
|
||||
remark: str = "",
|
||||
kind: str = "",
|
||||
) -> None:
|
||||
writer = getattr(flow.ledger, "upsert_product_quote", None) or getattr(
|
||||
flow.ledger, "upsert_quote", None
|
||||
)
|
||||
persist = dict(quote or {})
|
||||
if (kind or "").strip() == "adjust":
|
||||
persist["source"] = "SALES_ADJUST"
|
||||
persist["source_label"] = "销售调价"
|
||||
quote["source"] = persist["source"]
|
||||
quote["source_label"] = persist["source_label"]
|
||||
else:
|
||||
persist.setdefault("source", "PRODUCT")
|
||||
label = str(persist.get("source_label") or "")
|
||||
if (not label) or ("TMS" in label.upper()):
|
||||
persist["source_label"] = "手工报价"
|
||||
if callable(writer):
|
||||
saved = writer(work_order_no=no, quote=quote, to_status="已报价") or {}
|
||||
extras: dict[str, Any] = {}
|
||||
if remark:
|
||||
extras["remark"] = remark
|
||||
if kind:
|
||||
extras["kind"] = kind
|
||||
try:
|
||||
saved = writer(work_order_no=no, quote=persist, to_status="已报价", **extras) or {}
|
||||
except TypeError:
|
||||
saved = writer(work_order_no=no, quote=persist, to_status="已报价") or {}
|
||||
if not saved.get("ok") and saved.get("error"):
|
||||
logger.warning("产品报价未入主账 wo=%s err=%s", no, saved.get("error"))
|
||||
if sess is not None:
|
||||
|
||||
Reference in New Issue
Block a user