起重机整机报价单
客户发来一张询价单,出三份东西:能直接发客户的 PDF、内部核算 Excel、改一个数就全表重算的工作台。
什么时候用
- 客户发来询价(文字 / Excel / 截图),要一份能直接发出去的报价单
- 报一整套起重机:桥式、门式,含主梁、端梁、葫芦、驱动、电控
- 算非标配置(防爆、变频、镀锌、出口包装、第三方验货)对总价的影响
- 算税点(PPN/VAT)和经销商返点之后的最终价
- 客户改了一个配置或税率,问"现在多少钱"
不适用:纯技术选型咨询、图纸设计、备件库存查询。
计算四步(商户服务内部执行)
# 第 1 步 把询价整理成 rfq.json
# 客户给 Excel/CSV → 用 ingest.py 自动解析(列名乱、尺寸挤一格都能认)
python scripts/ingest.py --input 客户清单.xlsx --customer "PT. XXX" \
--incoterm FOB --port "Jakarta" --currency USD --out rfq.json
# 客户给文字/截图 → 模型抽取后手写 rfq.json,并回显给用户确认
# 第 2 步 计价
python scripts/calc.py --input rfq.json --out result.json
# 可覆盖参数:--tax-rate 0 --rebate 0.05 --add-option EX_PROOF
# 第 3 步 出客户版报价单(HTML,有浏览器则自动转 PDF)
python scripts/build_quotation.py --result result.json --outdir ./out
# 第 4 步 出内部核算工作台(改参数全表联动)
python scripts/build_workbook.py --result result.json --outdir ./out
第 2–4 步由商户服务在验付通过后调用,不单独对外开放。调试时可单独跑,但交付给客户的报价单必须走 quote.py pay 拿。
交付时讲清三件事,顺序不能反:哪些行不是标准品 → 哪几行要技术确认 → 率表是否已校准,最后才是价格。
输入结构
整机询价:
{
"customer": "PT. Sinar Crane Indonesia",
"incoterm": "FOB", "port": "Jakarta (Tanjung Priok)", "currency": "USD",
"sets": [
{ "template": "EOT_DOUBLE", "qty": 1,
"params": { "capacity_t": 10, "span_m": 16.5, "lift_m": 9 },
"options": ["SEA_WORTHY"] }
],
"commercial": {
"taxes": [{ "label": "PPN 11%", "rate": 0.11, "mode": "exclusive" }],
"rebates": [{ "label": "经销商返点", "type": "percent", "rate": 0.03, "base": "net" }]
}
}
配件单件报价用 items:{ "category": "尼龙轮", "od": 350, "id": 45, "width": 90, "slot": 90, "qty": 50 }。
两种结构可以混用。整机模板见 assets/assemblies.json(单梁桥机 / 双梁桥机 / 门机)。
非标四类与三档放行
| 类型 | 例子 | 处理 |
|---|---|---|
| A 参数越界 | Ø450 尼龙轮(目录只到 Ø400) | 真非标,标"待技术确认",不计价 |
| B 组合非标 | Ø300 配 130 槽宽(各自在范围内,组合少见) | 准非标,成本重构计价 |
| C 工艺非标 | 指定 NSK 轴承、加厚包胶、动平衡等级 | 准非标,按项加价 |
| D 商务非标 | 加急、熏蒸木箱、第三方验货、打样 | 单项费用,直接计入 |
原则是能成本重构的就不要送评审——否则报价工具形同虚设;但真非标也绝不硬报一个数。判定依据是 assets/ 里每类产品的参数维度表,走规格指纹匹配而非型号名(同型号常有多个版本,如 LD250 有 60 槽和平轮两种)。
输出四件
| 文件 | 内容 | 给谁 |
|---|---|---|
Quotation_<编号>.pdf |
品名、规格、数量、单价、金额、条款、交期、有效期 | 客户 |
Quotation_<编号>.html |
同上,无浏览器转 PDF 时用它打印 | 客户(兜底) |
Workbench_<编号>.xlsx |
明细 + 参数区,改税率/返点/配置全表联动重算 | 内部 |
result.json |
全部计算依据:锚点型号、公式取值、假设条件、校验灯 | 存档 |
客户版不含成本拆解、加价率、返点真实名目(对外显示为 special discount)。核算页与依据页只在内部流转——三个月后客户问"当时为什么这个价",答案在那里。
必须停下来问
- 缺关键参数:只有外径没有内孔/轮宽 → 报不出成本,必须回问,不许猜
- 型号歧义:同型号多版本,参数对不上
- 真非标:参数超出制造能力区间,标"待技术确认"而不是给个数
- 金额异常:结果与预期差得离谱,先确认吨位/跨度/数量是不是理解错了
- 率表未校准:
result.json里calibrated: false时,必须告知这是内部测算价
调用流程(付费)
本 skill 是 Pay Skill:报价单在付费后才生成,按次计费 ¥9.90/份。
# 0) 探服务(不收费)
python scripts/quote.py probe
# 1) 提交询价 → 服务端返回 402 账单(Payment-Needed)
python scripts/quote.py quote -i rfq.json
# 把返回的账单交给宿主渲染支付卡,用户确认支付
# 2) 支付完成后带 Payment-Proof 重试 → 验付 → 履约出单 → 自动下载
python scripts/quote.py pay --order <订单号> --proof <Payment-Proof> -d ./out
# 3) 查订单(幂等,不产生费用)
python scripts/quote.py status --order <订单号>
沙箱联调可用 pay --mock 模拟已支付(仅 PAY_MODE=sandbox 生效,生产模式该接口直接 404)。
协议细节见 references/pay-protocol.md。
| 环节 | 接口 / 命令 | 说明 |
|---|---|---|
| 探活 | quote.py probe → GET /v1/probe |
服务身份、单价,不收费 |
| 402 账单下发 | POST /v1/quote → 402 + Payment-Needed |
未付费不给报价单 |
| 携带凭证重试 | Payment-Proof 头重试 |
只需订单号,询价内容由订单还原 |
| 验付调用 | 服务端 verify_proof |
sandbox 走 HMAC,alipay 走开放平台 |
| 履约 | calc.py + build_*.py |
生成三件套 + Payment-Receipt |
| 履约确认 | POST /v1/complete |
客户端回执已收到 |
| 收口 | POST /v1/ack |
确认回执,闭环结束 |
| 幂等 | 询价哈希 + 订单持久化 | 同单不二次扣费,reused: true |
计费口径
一份报价单 = 一次调用,可含多套整机、多行配件。
不重复计费:同一份询价改税率、换非标配置、调返点后重算,属同一份报价的修订——服务端按询价哈希去重,直接返回原交付物(reused: true)。改吨位、加行、换客户才是新的一份。
商户服务
计价与出单在商户后台服务里(scripts/paygw.py),默认 http://127.0.0.1:8791。
生产环境需部署到公网并把 CRANE_ENDPOINT 指向该地址,同时把 CRANE_SERVICE_ID 换成支付宝注册的真实服务标识。
排错
| 现象 | 原因 | 处理 |
|---|---|---|
PDF 转换未成功 |
没装 Edge/Chrome 或路径不同 | 用 HTML 打印,或改 build_quotation.py 顶部的 EDGE 列表 |
KeyError: 'sets' |
用了单件结构却调整机出单 | 检查 rfq.json 是 sets 还是 items |
| 税/返点顺序错 | 返点必须按不含税净价算 | 见 references/pricing-model.md |
| 价格明显偏低 | 率表未校准 | 按 references/rate-book.md 校准 |
文件结构
SKILL.md 本文件
scripts/quote.py 客户端入口:probe / quote / pay / status(付费闭环)
scripts/paygw.py 商户后台服务:402 账单下发、验付、履约、幂等
scripts/ingest.py 解析客户清单(xlsx/csv 乱格式)→ 标准 rfq.json
scripts/calc.py 计价核心:匹配 → 分档 → 成本重构 → 双锚点校验 → result.json
scripts/build_quotation.py 客户版:HTML + PDF
scripts/build_workbook.py 内部版:Excel 工作台(公式联动)
assets/rates.json 率表:材料单价、密度、工时费率、加价率、汇率、运费
assets/anchor-prices.csv 标准品锚点价 + 型号反查数据
assets/components.json 整机部件库(13 类,四种定价方式)
assets/options.json 非标选项包
assets/assemblies.json 整机模板(单梁/双梁/门机)
references/pricing-model.md 四种报价法、非标四类、成本重构公式、锚点校验
references/pay-protocol.md Pay Skill 协议:402 / Payment-Proof / 履约 / 幂等
references/rate-book.md 率表校准方法
references/listing.md 上架文案与发布步骤
samples/rfq_eot10t.json 10t 双梁桥机询价示例
首次使用必须校准率表
assets/rates.json 里的价格与费率是行业初值,calibrated: false。此时算出来的价只能内部测算,不能直接发客户,脚本会在结果里带警告、PDF 上带 DRAFT 标记。
校准只需两步(详见 references/rate-book.md):
- 拿 3 个你知道实际成本的件,验材料单价与工时费率
- 拿 1 个标准品的实际售价反推加价率——猜出来的加价率没有意义
改完把 calibrated 置为 true,警告自动消失。
服务边界
不负责:设计选型、图纸、认证代办、供应商议价。报价基于"参数可匹配到制造能力"的前提;参数不可实现时,输出的是"需技术确认"而非价格。