落地私聊空运询价与TMS报价回填,按后台模板出单。

查到价后把币种、单位、数量、单价、备注写入报价单,避免销售只看到光秃秃的金额。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-14 20:25:35 +08:00
co-authored by Cursor
parent cea3a6e51e
commit 99da1faf30
78 changed files with 8838 additions and 321 deletions
+45 -2
View File
@@ -12,7 +12,6 @@ from dataclasses import dataclass
from typing import Any, Optional
from agent.jobs.libreoffice import LibreOfficeConverter, LibreOfficeResult
from agent.jobs.quote_fill import fill_then_convert_pdf
from agent.redis_coord import get_redis_runtime, try_acquire_idempotency
from agent.redis_coord.keys import STREAM_PDF
from agent.redis_coord.runtime import RedisRuntime
@@ -40,6 +39,8 @@ def enqueue_pdf_job(
quote_version: int = 0,
idempotency_key: str = "",
redis: Optional[RedisRuntime] = None,
touser: str = "",
filename: str = "",
) -> PdfEnqueueResult:
"""Excel→PDF 任务入队;真正转换只在 LibreOffice 槽。"""
rt = redis or get_redis_runtime()
@@ -58,6 +59,8 @@ def enqueue_pdf_job(
"xlsx_path": xlsx_path,
"inquiry_no": inquiry_no,
"quote_version": quote_version,
"touser": touser,
"filename": filename,
}
entry_id = q.enqueue(payload=payload, idempotency_key=idempotency_key)
logger.info("pdf.enqueue id=%s inquiry=%s", entry_id, inquiry_no or "-")
@@ -84,6 +87,11 @@ def process_pdf_job(
from pathlib import Path
import tempfile
try:
from agent.jobs.quote_fill import fill_then_convert_pdf
except ImportError:
return LibreOfficeResult(ok=False, error="quote_fill_missing")
wd = Path(work_dir) if work_dir else Path(tempfile.mkdtemp(prefix="quote_fill_"))
fill, pdf = fill_then_convert_pdf(
source_xlsx=template_xlsx,
@@ -95,9 +103,44 @@ def process_pdf_job(
if not fill.ok:
return LibreOfficeResult(ok=False, error=f"fill_failed:{fill.error}")
assert pdf is not None
_deliver_quote_file(data, pdf)
return pdf
path = str(data.get("xlsx_path") or "")
if not path:
return LibreOfficeResult(ok=False, error="missing_xlsx_path")
return conv.convert_xlsx_to_pdf(path)
result = conv.convert_xlsx_to_pdf(path)
_deliver_quote_file(data, result)
return result
def _deliver_quote_file(data: dict[str, Any], result: LibreOfficeResult) -> None:
"""
转换成功后把 PDF 写入 outbox,由企微通道发文件。
无 touser 则只落盘(旧任务);失败不抛,避免卡 LibreOffice 槽。
"""
if not result.ok:
return
touser = str(data.get("touser") or "").strip()
if not touser:
return
wo = str(data.get("inquiry_no") or "")
filename = str(data.get("filename") or "").strip() or f"{wo}_quote.pdf"
try:
from agent.channel.queue import get_message_store
from agent.policy.inquiry_copy import file_ready
store = get_message_store()
store.enqueue_outbound(
touser=touser,
content=file_ready(kind="PDF", work_order_no=wo, filename=filename),
dedupe_key=f"pdf-file:{wo}:{filename}",
payload={
"msgtype": "file",
"filepath": result.pdf_path,
"filename": filename,
},
)
except Exception:
logger.exception("PDF 出站入队失败 inquiry=%s", wo)