Income Tax (Operating) — 个人经营所得税测算
Overview
按经营所得五级超额累进税率表(2019 年起施行)测算个体工商户/个独合伙的年度个税:
- 正算 direct:已知税前经营收入 → 应缴个税、税后收入
- 反算 reverse:已知税后到手 → 倒推税前收入、应缴个税
- 公式:应纳税所得额 = 税前收入 − 成本费用扣除;应缴个税 = 应纳税所得额 × 税率 − 速算扣除数
- 反算公式:应纳税所得额 = (税后收入 − 扣除 − 速算扣除) ÷ (1 − 税率),逐档试算并校验区间
- 预缴与汇算:反向开票累计收入(不含税)× 0.5% 为已预缴;补/退税 = 应缴 − 预缴(正数需补税)
When to use this skill
触发场景:
- "我开票 50 万,要交多少个税"
- "个体户一年流水 80 万成本 30 万,个税多少"
- "我想税后到手 30 万,得开多少票"
- "反向开票已经预缴了,汇算还要补多少"
不要触发:工资薪金个税(月度预扣、专项附加扣除、年度汇算——另一套税率表)、劳务报酬/稿酬、增值税、企业所得税。
Workflow
第 1 步:收集参数(必问清单 + 选择题规则)
提问形式(重要):
1. 向用户收集参数时必须用选择题。宿主有结构化提问/选项工具(如选择题、AskUserQuestion 类)时必须使用该工具;没有选项 UI 的宿主在文本里用编号列表
2. 选择题只用于"方向/类型"类决策;数值一律开放式输入,绝不做"选一个数字选项"或"选项里套填空"(如"有,填累计不含税金额"这种选项是错误设计——用户不知道点了之后还要不要填)。数值参数就直接让用户填数字
3. 首轮一次性问完必问清单里所有缺失项,不要逐个追问
必问清单(每一项都要过一遍,用户已明确给出的跳过;可选参数也必须问,不许自行默认跳过):
| # | 参数 | CLI | 问法 |
|---|---|---|---|
| 1 | 计算方向 | 子命令 | 选择题:A. 知道开票/经营收入,算要交多少税(正算) / B. 想税后到手某个数,倒推要开多少票(反算) |
| 2 | 收入金额 | --income 或 --post-tax |
开放数值。正算问"税前经营收入多少";反算问"想税后到手多少"。用户答"流水/开票额/营业额"即收入;"到手/净落"即税后 |
| 3 | 成本费用扣除 | --deductions |
开放数值 + 一句说明:"年度成本、费用、损失合计,没有就填 0"。用户说"个体户核定征收"时提醒:本工具按查账征收算,仅供参考 |
| 4 | 反向开票预缴 | --rev-invoice |
选择题(必问,即使预判用户没有):A. 没有,不用算预缴 / B. 有反向开票。选 B 后追加一个开放数值问题:"累计不含税金额多少?"(有预缴才能算汇算补/退税) |
首轮提问示例(选项工具支持多问题时一次发四个;不支持时按此顺序文字列出):
- 问题1(单选):算税方向? A. 知道收入算要交多少税 B. 想到手某个数倒推开票额
- 问题2(填空):税前经营收入(或税后收入)多少元/年?
- 问题3(填空):年度成本费用合计多少元?没有填 0
- 问题4(单选):有反向开票预缴吗? A. 没有 B. 有 →(选B再问)累计不含税金额?
概念翻译规则(用户说人话 → 参数):
- "开票收入/流水/营业额/营收" → 税前经营收入 --income
- "成本/费用/进货/开销/支出" → 合计填 --deductions
- "到手/税后净落/净赚(扣完税)" → --post-tax
- "净赚" 若指"收入−成本"而非"扣完税" → 那是利润,应作为应纳税所得额的线索,引导用户分别提供收入与成本
- 用户问"开 30 万的票"但没说含不含税 → 问一句是价税合计还是不含税,口径要一致
第 2 步:运行脚本(禁止心算)
禁止人工推算任何数值——五级累进选档、反算逐档试算、速算扣除,人工算必错。一律执行脚本,且默认带 --image 生成卡片(卡片是本 skill 的标准交付物):
# 正算
python3 scripts/income_tax.py direct \
--income 500000 --deductions 200000 \
--image /tmp/iit_direct_<amount>.png
# 反算
python3 scripts/income_tax.py reverse \
--post-tax 450500 --deductions 200000 \
--image /tmp/iit_reverse_<amount>.png
# 带反向开票预缴
python3 scripts/income_tax.py direct \
--income 600000 --deductions 100000 --rev-invoice 80000 \
--image /tmp/iit_direct_<amount>.png
加 --json 得结构化结果。
出图规则:
- 首次计算 → 必须出图。这是视觉交付物,不是可选项
- 调整假设重算对比("要是成本有 30 万呢")→ 中间过程只出文本对比,用户确定的最终方案再出图
- 用户明确说"不用图/直接说结果" → 尊重,纯文本
- 图片生成失败(缺 Pillow 等)→ 不要中断,回退文本表格并说明可 pip install pillow 后重试
第 3 步:向用户呈现
- 引用 headline 数字:应缴个税 ¥X,正算附税后到手 ¥Y,反算附需开票 ¥Z
- 展示卡片(mandatory):宿主有
present_files类工具必须用它展示 PNG;没有的宿主把图片路径告诉用户 - 说明适用税率档(第几级、税率、速算扣除数),让用户理解数字来源
- 有反向开票数据时,明确"已预缴多少、汇算需补/退多少"(正数=补税)
- 反算结果要提醒:倒推的是"刚好到手该金额"的开票额,未考虑增值税及附加
- 结果以"实际以税务机关核定为准"收尾
Quick reference
五级累进税率表(按年应纳税所得额,权威数据在 references/tax_rates.json):
| 级数 | 应纳税所得额 | 税率 | 速算扣除数 |
|---|---|---|---|
| 1 | ≤ 3 万 | 5% | 0 |
| 2 | 3 万 ~ 9 万 | 10% | 1,500 |
| 3 | 9 万 ~ 30 万 | 20% | 10,500 |
| 4 | 30 万 ~ 50 万 | 30% | 40,500 |
| 5 | > 50 万 | 35% | 65,500 |
(区间口径:超过下限、不超过上限;30000 落第 1 级,30000.01 起第 2 级。)
边界行为(脚本自动处理):
- 扣除 ≥ 税后收入 → 免税(税率 0)
- 应纳税所得额 ≤ 0 → 个税为 0
- 正算税后为负 → 显示税前收入(极端扣除场景兜底)
- 预缴税率固定 0.5%(反向开票不含税收入)
Examples
例 1 — 正算:开票 50 万,成本 20 万
python3 scripts/income_tax.py direct --income 500000 --deductions 200000 \
--image /tmp/iit_500k.png
应缴 ¥49,500(第 3 级 20%),税后 ¥450,500。
例 2 — 反算:想税后到手 450,500
python3 scripts/income_tax.py reverse --post-tax 450500 --deductions 200000 \
--image /tmp/iit_rev.png
倒推税前 ¥500,000,应缴 ¥49,500。
例 3 — 带反向开票预缴汇算
python3 scripts/income_tax.py direct --income 600000 --deductions 100000 --rev-invoice 80000 \
--image /tmp/iit_600k.png
应缴 ¥109,500,已预缴 ¥400(80,000×0.5%),汇算需补 ¥109,100。
例 4 — 对比场景(中间不出图)
python3 scripts/income_tax.py direct --income 600000 --deductions 300000
文本对比后用户定稿再补 --image。
Updating the data
- 税率表自 2019 年沿用;如税法修订:改
references/tax_rates.json的brackets与meta.updated - 预缴 0.5% 政策变化:改
constants.rev_invoice_prepay_rate - 改完 json 记得同步
scripts/income_tax.py顶部EMBEDDED_RATES(兜底值)
Resources
scripts/
income_tax.py— 唯一入口。子命令direct/reverse;纯标准库;decimal.Decimal复刻 Java BigDecimal HALF_UP 精度(乘法先舍入到分再减速算扣除、除法 scale 2)。render_card.py— 被--image懒加载调用;也可单独运行(stdin 读 JSON)。需 Pillow;跨平台中文字体 fallback。
references/
tax_rates.json— 权威税率表(五级级距/税率/速算扣除/预缴率/政策依据),脚本运行时读取。
assets/
logo.png— 公司 logo(透明底 PNG 佳)。存在时自动贴到卡片右下角;删除则卡片无 logo,不影响运行。