出海报价测算 · 到岸成本一键算
定位与服务边界
这个 Skill 只做一件事——把一单出海生意的到岸成本和该报的价格算清楚。
不替你选国家,不替你找货代,不替你做 HS 编码归类。
它做的是:你已经有了一票货的基本信息,现在需要知道
「落地成本是多少、报多少才有钱赚、关税涨了我会亏多少」。
市面上大多数报价表的问题不是公式错,而是把税率写死在表里——
半年后税率变了,没人记得改。本 Skill 的反做法是:
脚本里一个税率数字都没有,税率必须你给,拿不到就报错退出。
触发条件
出现以下信号时立即启动:
- 问出海/跨境报价怎么算(「这单要报多少」「这个价格能不能接」)
- 需要到岸成本、落地成本、Landed Cost 拆解
- 需要算关税、进口环节税、出口退税对成本的影响
- 需要 FOB / CIF / DDP 口径换算
- 需要知道「关税涨 X% 我会不会亏」「运费涨了报价要不要改」
- 已有目标毛利率,反推报价
非触发边界(重要)
- 还没决定去哪个国家 → 属于出海准备度问题,不是报价问题,先做体检再谈报价。
- 找货代 / 报关行 / 比价 → 资源对接,本 Skill 不做。
- HS 编码归类咨询 → 需要官方税则与归类裁定,本 Skill 不提供归类服务。
- 纯汇率换算 → 一条乘法,不需要整套测算。
- 转让定价 / 关联交易 / 税务筹划 → 超出边界,需专业税务意见。
> 判断不清时用一句澄清:「您是要算这一票货的落地成本和报价,还是还在决定要不要出海?」
三分钟上手(渐进路径)
第 1 分钟|先看结果长什么样(不填任何数据)
python scripts/quote.py --demo --out ./报价输出
出一份示例报告 + JSON。看完你就知道要准备哪些数字。
第 2 分钟|拿模板,填自己的数
python scripts/quote.py --template > mycase.json
模板字段含义见下方「输入契约」。
第 3 分钟|算
python scripts/quote.py --data mycase.json --out ./报价输出
顺手做的一步:把税率存成本地缓存
税率是反复用的。存一次,之后 spec 里不用再写:
python scripts/quote.py --rates rates.json --save-rates
python scripts/quote.py --show-rates
输入契约(spec.json)
| 字段 | 必填 | 含义 |
|---|---|---|
case |
否 | 场景名,用于报告标题与文件名(会做路径注入净化) |
goods.qty |
是 | 数量,正整数 |
goods.fob_unit_cny |
是 | FOB 单价(人民币) |
goods.name / goods.unit |
否 | 品名 / 单位,仅用于报告展示 |
freight.amount_cny |
否 | 运费(人民币),默认 0 |
freight.insurance_cny |
否 | 保险(人民币),默认 0 |
rates.duty |
是 | 关税率,小数(0.10 = 10%) |
rates.import_vat |
是 | 进口环节税率,小数 |
rates.refund |
否 | 出口退税率,默认 0 |
rates.domestic_vat |
否 | 国内增值税率,refund_base=purchase 时分母用 |
refund_base |
否 | purchase(采购含税口径)/ fob(离岸价口径)/ none |
purchase_unit_cny |
条件必填 | refund_base=purchase 时必填 |
channel.commission |
否 | 渠道/平台佣金率,默认 0 |
channel.other_cny |
否 | 清关、仓储、本地配送等杂费,默认 0 |
target_margin |
否 | 目标毛利率,默认 0 |
fx |
否 | 汇率:1 单位报价币种 = 多少 CNY,默认 1 |
quote_currency |
否 | 报价币种符号(如 USD),仅展示用 |
sensitivity |
否 | 敏感度配置,数值为相对比例(0.10 = 上浮 10%) |
税率三档来源,优先级从高到低:spec.rates → 本地缓存 → 报错退出码 2。
脚本不会 fallback 到任何内置默认值。
计算口径(报告里原文写明,避免被当成官方口径)
| 项目 | 公式 |
|---|---|
| CIF | FOB 货值 + 运费 + 保险 |
| 关税 | CIF × 关税率 |
| 进口环节税 | (CIF + 关税) × 进口环节税率 |
| 出口退税 | fob 口径:FOB 货值 × 退税率<br>purchase 口径:采购含税金额 × 退税率 ÷ (1 + 国内增值税率) |
| 到岸成本 | CIF + 关税 + 进口环节税 + 其他杂费 − 出口退税 |
| 建议报价 | 到岸成本 ÷ (1 − 目标毛利率 − 佣金率) |
| 盈亏平衡报价 | 到岸成本 ÷ (1 − 佣金率) |
退税的两种口径差异很大,务必按主管税务机关认可的口径选。
purchase 口径需要 purchase_unit_cny,不给就报错,不会默默按 fob 算。
输出契约
每个场景产出两份文件(同名不同后缀):
<场景名>_报价测算.md—— 四段式报告:成本拆解表 / 报价结论表(CNY + 报价币种双列)/ 敏感度表 / 交付前自检清单<场景名>_报价测算.json——{"result": {...}, "sensitivity": [...]},供下游程序消费
报告里固定带两条声明:口径说明 + 「税率为用户提供,最终以官方税则为准」。
这两条不是免责套话,是本 Skill 的核心设计——把不确定性的归属标清楚。
常见错误与应对
| 现象 | 原因 | 应对 |
|---|---|---|
| 报「缺少税率(rates)」 | spec 没给 rates,本地也没缓存 | 补 rates 字段,或 --rates <文件> --save-rates 存缓存 |
| 报「目标毛利率 + 渠道佣金率 = X,需 < 1」 | 数学上无解:收入覆盖不了成本+佣金+毛利 | 降毛利率目标,或换低佣金渠道 |
| 报「refund_base=purchase 时必须给 purchase_unit_cny」 | 选了采购口径却没给采购价 | 补 purchase_unit_cny,或改 refund_base 为 fob / none |
| JSON 解析失败 | 末尾多了逗号,或文件编码异常 | 本工具已做 utf-8-sig / utf-8 / gbk / utf-16 四档兜底;仍失败请检查逗号 |
| 报「--demo 与 --data 不能同时使用」 | 两个数据源同时给,会静默丢一个 | 二选一 |
| 报告里的数字和手算差一点 | 检查是否漏了 channel.other_cny,或退税口径选错 |
对照「计算口径」表逐项核 |
| 敏感度一栏全是 0 | sensitivity 里给了 0,或没给这个因子 |
0 表示该因子不参与敏感度,属正常 |
异常与兜底
| 异常场景 | 行为 | 退出码 |
|---|---|---|
| 税率缺失 | 明确报错并告诉你怎么补,绝不填默认值 | 2 |
| 毛利率 + 佣金率 ≥ 1 | 报「数学上无解」,不给荒谬报价 | 2 |
| 数据文件不存在 | 报「找不到数据文件」并提示用 --template,不会误报成 JSON 解析失败 |
2 |
| JSON 非法 | 报解析错误 + 常见原因提示 | 2 |
| 带 BOM 的 JSON | utf-8-sig 优先解码,正常解析(utf-8 解 BOM 不报错但留 U+FEFF,会误导排查方向) |
0 |
| GBK 编码 spec | 四档编码兜底读取 | 0 |
case 含路径分隔符 |
文件名净化,不会在输出目录外创建嵌套目录 | 0 |
| 输出目录不可写 / 创建失败 | 报「环境错误」并提示换目录 | 3 |
| 产物写入后为空或缺失 | 成功路径也二次校验产物,报环境错误而不是假装成功 | 3 |
参数错误、--help |
argparse 抛的 SystemExit 被显式捕获(SystemExit 是 BaseException,except Exception 抓不到) |
2 / 0 |
| 未预期异常 | 顶层兜底输出 [错误] 未预期异常,不抛裸 traceback |
2 |
退出码封闭为 0 / 2 / 3,任何输入都不会产生第四个值。
实战案例(真实跑通,数字为脚本实跑输出)
需求:一批 500 台的货要报给俄罗斯客户,想知道落地成本和该报多少。
选型:有明确数量、FOB 单价、运费、税率 → 走 --data 真实测算,不走 --demo。
数据(spec 关键字段):qty 500、fob_unit_cny 260、运费 18000、保险 2200、
关税率 10%、进口环节税率 20%、退税率 13%(purchase 口径,采购单价 210)、
佣金率 8%、杂费 3000、目标毛利率 35%、汇率 7.10、报价币种 USD。
命令:
python scripts/quote.py --data mycase.json --out ./报价输出
产出(脚本实跑):
| 项目 | 结果 |
|---|---|
| CIF | 150,200.00 CNY |
| 关税 | 15,020.00 CNY |
| 进口环节税 | 33,044.00 CNY |
| 出口退税(冲减) | −12,079.65 CNY |
| 到岸成本 | 189,184.35 CNY(单件 378.37) |
| 盈亏平衡报价 | 411.27 CNY / 单件 |
| 建议报价 | 663.80 CNY / 单件(93.49 USD) |
| 预计毛利额 | 116,165.83 CNY |
敏感度(单因子 +10%,汇率 +5%):
| 因子 | 到岸成本变化 | 单件报价变化 |
|---|---|---|
| 关税率 +10% | +1,802.40 | +6.32 |
| 运费 +10% | +2,376.00 | +8.34 |
| FOB 单价 +10% | +17,160.00 | +60.21 |
→ 结论一眼可见:这一单对 FOB 采购价最敏感,谈价重点应该压采购成本,而不是纠结关税。
已验证清单(全部 2026-10-01 实跑,未跑的不写)
| # | 验证项 | 结果 |
|---|---|---|
| 1 | --selftest 自检 |
19/19 通过 |
| 2 | 核心算例手算核对(CIF 22,000 / 关税 2,200 / 进口环节税 4,840 / 到岸成本 29,040) | 一致 |
| 3 | 报价公式 到岸成本 ÷ (1−毛利率−佣金率) |
一致 |
| 4 | 毛利率+佣金率 ≥ 1 报错而非给出荒谬值 | 通过 |
| 5 | 退税两种口径(purchase / fob)分别核对 | 一致 |
| 6 | 缺税率报错,不填默认值 | 通过 |
| 7 | 非字典输入报 ValueError,不抛裸 AttributeError |
通过 |
| 8 | qty 为 0 报错 |
通过 |
| 9 | case 含斜杠/冒号被净化,不产生嵌套目录 |
通过 |
| 10 | GBK 编码 spec 可正常解析 | 通过 |
| 11 | 带 BOM 的 JSON 可正常解析 | 通过 |
| 12 | 税率缓存 save / show / 复用 | 通过 |
| 13 | 敏感度:关税率 +10% 后到岸成本上升 | 通过 |
| 14 | --demo 出 md + json 双份产物 |
通过 |
| 15 | stdin 管道 --data - |
通过 |
| 16 | 8 条错误路径(缺 --out / demo+data 互斥 / 缺税率 / 毛利率非法 / 坏 JSON / 文件不存在 / 无参数 / save 缺文件) | 全部 rc=2,无 traceback |
| 17 | 成功路径二次校验产物非空 | 通过 |
发布前质量门:frontmatter 六字段齐全且 tags 为行内数组 / 目录无点开头文件、
__pycache__、*.pyc、*.bak.* / 冒烟零报错 / 全文档异常 Unicode 扫描通过。