💀填好个税,一年多给几千块 ~ 聊聊个人所得税,你该退税还是补税?写一个个税的计算器(退税、补税、个税)
前言
一年一度个税年度综合汇算清缴的时间又到了,作为开发者的你,肯定过了起征点了吧。🫤
去年退税退了 5676
,今年看这个估计得补好几千,但是个税年度汇算清缴还没有预约到,抓紧提前算算金额,做做心理建设。\同时,了解个税都扣在哪了,才可以让我们合理避税~
下面我们简单聊聊 补税 和 预缴 ,顺便讲讲专项附加扣除应该怎么填。
以及带大家写一个个税计算器。你可以通过码上掘金查看 在线 svelte(无UI) 版
,后续也会推出其他框架版。
为什么你需要补税?
大多数情况下,公司发工资会替你把税交了,这个行为叫预缴。
为什么预缴呢?因为国家规定:
《个人所得税扣缴申报管理办法(试行)》(国家税务总局公告2018年第61号发布)
第六条:扣缴义务人向居民个人支付工资、薪金所得时,应当按照累计预扣法计算预扣税款,并按月办理扣缴申报。
这也就是我们每个月发工资都会扣税的原因。
那为什么需要补税呢?因为预缴是根据你在当前公司的收入进行缴税,公司会计算你的累进税率,你会发现每到年底税交的越来越高了,这是累进预缴导致的。
有些人在年中换了工作了,新公司不知道你之前已经交到哪个阶段的个税了,因此预缴时计税金额会重新累计。
因此补税的原因不外乎:
- 工作变更
- 公司主体变更(如:公司拆分)
为什么说预缴是天才发明?
预缴制简直是个天才发明,不但会大大减少逃税人数,而且能减轻税务工作量(转移至各公司),且可以让缴税的人对税率的感知没有那么强烈。
达成这种效果主要原因有两点,分别是 损失厌恶 、 心理账户 。
损失厌恶
人们对损失的敏感程度通常远远大于对同等价值的收益的敏感程度
人们对损失的敏感程度通常远远大于对同等价值的收益的敏感程度
人们对损失的敏感程度通常远远大于对同等价值的收益的敏感程度
牢记这句话。
一个最简单的例子,短视频中经常会出现的 最有效的 6 条学习方式,最后一条最重要 。这种放大损失的语言,常常能诱发更高的完播率。
虽然我很讨厌以这种方式留住用户,但常常在刷到这类视频时,也忍不住多看一样,虽然知道它最终可能也没什么实质内容。
还有一种就是我们常常刷掉一个视频,又返回去看一眼,又刷掉又返回去。我常常会有这种心理,这个视频我是不是应该看一看的纠结。
个税也是同理,个税预缴是减少我们的收益,而个税年终汇算则是直接让我们从口袋中掏钱。
就算汇算综合到月度计算,同样也是,一种是公司扣完发给你,另一种是发给你之后你再掏出来一部分。大家感受一下这其中的区别。
心理账户
人们可能会将个税缴纳视作开销,而且是意外开销,意外开销总是让人痛苦的。
比如我每个月 1w 块,其中 3k 拿来租房,3k 拿来吃饭, 2k 拿来娱乐,2k 拿来缴五险一金。
这时候到年终汇算时,人们则容易苦不堪言。
且这种带来的直接后果是,我想把税留到最后一天交,同时最后一天也很容易忘记交,因为大脑也不想要这种意外支出。
最终则导致 漏交、拒交 个税的人数大大增加。
专项附加扣除严谨度
- 子女教育(未婚,无接触)
- 赡养老人(容易被查)
- 继续教育 - 学历提升(基本不查)
- 学历提升可以选择一个对应学历,每个学历 4 年,共 16 年左右抵税
- 继续教育 - 证书获取(基本不查)
- 证书获取有人一个证书可以一直抵税,建议: 营养师证、焊工证等
- 租房买房(基本不查)
- 大病医疗(未填过,未知)
开发
首先咱们先写个个税计算器的 class
,个人所得税英文简称 IIT (Individual Income Tas)
。
class IITCalulator {}
添加需要计算的内容
众所周知,
个税计算法:应缴税款 * 对应税率 - 速算扣除
应缴税款计算法:工资 - 五险一金缴纳额 - 专项附加扣除
因此我们先添加 工资 、 五险一金 、 专项附加扣除 的属性。
工资
我们工资有两个组成部分,分别是 固定工资 和 年终奖(如果有的话)。
class IITCalulator {
private salary: {
monthlySalary: number;
yearEnd: number;
} = {
monthlySalary: 0,
yearEnd: 0,
};
/**
* @description 添加工资(通过工资计算年薪)
*/
addSalary(
monthlySalary,
yearEnd?: { value: number; type: "month" | "amount" }
) {
this.salary.monthlySalary = monthlySalary;
if (yearEnd) {
this.salary.yearEnd =
yearEnd.type === "amount"
? yearEnd.value
: monthlySalary * yearEnd.value;
}
}
}
五险一金
这里直接给了固定金额,可以通过查看每月扣除得知。
考虑到有人不太清楚自己的五险一金缴纳基数,这里直接用了固定金额,后续可以扩展出通过缴纳比例自动计算
class IITCalulator {
private socialInsuranceMonthlyAmount = 0;
/**
* @description 添加五险一金,计算年五险一金缴纳额
* @param {number} monthlyAmount 月度缴纳金额
*/
addSocialInsurance(monthlyAmount) {
this.socialInsuranceMonthlyAmount = monthlyAmount;
}
}
专项附加扣除
专项附加扣除通过数组的方式存储扣除项。
- 子女教育
- 赡养老人
- 继续教育(学校)
- 继续教育(证书)
- 住房贷款
- 大病医疗
// 专项附加扣除类型
type SpecialDeductionType =
| "children"
| "elder"
| "education-school"
| "education-certificate"
| "housing"
| "medical";
class IITCalulator {
private specialDeductionTypes: Array<SpecialDeductionType> = [];
private medicalAmount = 0;
/**
* @description 添加专项附加扣除
* @param {string} type 专项附加扣除类型
*/
addSpecialDeduction(
SpecialDeductionType: SpecialDeductionType,
medicalAmount?: number
) {
this.specialDeductionTypes.some((t) => t !== SpecialDeductionType) &&
this.specialDeductionTypes.push(SpecialDeductionType);
if (medicalAmount) {
this.medicalAmount = medicalAmount;
}
}
}
计算 工资 、 五险一金 、 专项附加扣除
我们添加了基础属性,可以根据基础属性计算出对应金额。
工资
工资 = 月薪 * 12 + 年终奖
getYearSalary() {
return this.salary.monthlySalary * 12 + this.salary.yearEnd;
}
五险一金
五险一金 = 月缴纳额 * 12
getYearSocialInsurance() {
return this.socialInsuranceMonthlyAmount * 12;
}
专项附加扣除
专项附加扣除 = 扣除项的扣除金额合集
需要注意的是:大病扣除项是固定金额的
这里直接采用 reduce
进行累加。
/**
* @description 计算专项附加扣除
*/
private getSpecialDeduction() {
return this.specialDeductionTypes.reduce((r, v) => {
switch (v) {
case "children":
return r + 2000 * 12;
case "elder":
return r + 3000 * 12;
case "education-school":
return r + 400 * 12;
case "education-certificate":
return r + 3600;
case "housing":
return r + 1500 * 12;
case "medical":
return r + this.medicalAmount;
default:
return r;
}
}, 0);
}
计算纳税金额
我们基础数据都有了,就只差计算了。先通过基础数据计算应纳税所得额,再通过应纳税所得额计算个税。
计算应纳税所得额
calcIIT() {
// 计算年薪
const yearSalary = this.getYearSalary();
// 五险一金缴纳金额
const yearSocialInsurance = this.getYearSocialInsurance();
// 专项附加扣除金额
const specialDeduction = this.getSpecialDeduction();
// 计算需要缴纳个税的金额
let taxableAmount =
yearSalary - yearSocialInsurance - specialDeduction - 60000;
// 计算个税
return this.calcTaxableAmount(taxableAmount);
}
计算应缴个税
个税计算参考:
// 计算个税(金额 * 税率 - 速算扣除)
private calcTaxableAmount(taxableAmount: number) {
if (taxableAmount <= 36000) {
return taxableAmount * 0.03;
} else if (taxableAmount <= 144000) {
return taxableAmount * 0.1 - 2520;
} else if (taxableAmount <= 300000) {
return taxableAmount * 0.2 - 16920;
} else if (taxableAmount <= 420000) {
return taxableAmount * 0.25 - 31920;
} else if (taxableAmount <= 660000) {
return taxableAmount * 0.3 - 52920;
} else if (taxableAmount <= 960000) {
return taxableAmount * 0.35 - 85920;
} else {
return taxableAmount * 0.45 - 181920;
}
}
完整代码:
// 专项附加扣除类型
// 1. 子女教育
// 2. 赡养老人
// 3. 继续教育(学校)
// 4. 继续教育(证书)
// 5. 住房贷款
// 6. 大病医疗
type SpecialDeductionType =
| "children"
| "elder"
| "education-school"
| "education-certificate"
| "housing"
| "medical";
class IITCalculator {
private salary: {
monthlySalary: number;
yearEnd: number;
} = {
monthlySalary: 0,
yearEnd: 0,
};
private socialInsuranceMonthlyAmount = 0;
private specialDeductionTypes: Array<SpecialDeductionType> = [];
private medicalAmount = 0;
constructor() {}
/**
* @description 添加工资(通过工资计算年薪)
*/
addSalary(
monthlySalary,
yearEnd?: { value: number; type: "month" | "amount" }
) {
this.salary.monthlySalary = monthlySalary;
if (yearEnd) {
this.salary.yearEnd =
yearEnd.type === "amount"
? yearEnd.value
: monthlySalary * yearEnd.value;
}
}
getYearSalary() {
return this.salary.monthlySalary * 12 + this.salary.yearEnd;
}
/**
* @description 添加五险一金,计算年五险一金缴纳额
* @param {number} monthlyAmount 月度缴纳金额
*/
addSocialInsurance(monthlyAmount) {
this.socialInsuranceMonthlyAmount = monthlyAmount;
}
getYearSocialInsurance() {
return this.socialInsuranceMonthlyAmount * 12;
}
/**
* @description 添加专项附加扣除
* @param {string} type 专项附加扣除类型
*/
addSpecialDeduction(
SpecialDeductionType: SpecialDeductionType,
medicalAmount?: number
) {
this.specialDeductionTypes.some((t) => t !== SpecialDeductionType) &&
this.specialDeductionTypes.push(SpecialDeductionType);
if (medicalAmount) {
this.medicalAmount = medicalAmount;
}
}
/**
* @description 计算专项附加扣除
*/
private getSpecialDeduction() {
return this.specialDeductionTypes.reduce((r, v) => {
switch (v) {
case "children":
return r + 2000 * 12;
case "elder":
return r + 3000 * 12;
case "education-school":
return r + 400 * 12;
case "education-certificate":
return r + 3600;
case "housing":
return r + 1500 * 12;
case "medical":
return r + this.medicalAmount;
default:
return r;
}
}, 0);
}
calcIIT() {
// 计算年薪
const yearSalary = this.getYearSalary();
// 年终奖是否单独计税
// 五险一金缴纳金额
const yearSocialInsurance = this.getYearSocialInsurance();
// 专项附加扣除金额
const specialDeduction = this.getSpecialDeduction();
// 计算需要缴纳个税的金额
let taxableAmount =
yearSalary - yearSocialInsurance - specialDeduction - 60000;
// 计算个税
return this.calcTaxableAmount(taxableAmount);
}
// 计算个税(金额 * 税率 - 速算扣除)
private calcTaxableAmount(taxableAmount: number) {
if (taxableAmount <= 36000) {
return taxableAmount * 0.03;
} else if (taxableAmount <= 144000) {
return taxableAmount * 0.1 - 2520;
} else if (taxableAmount <= 300000) {
return taxableAmount * 0.2 - 16920;
} else if (taxableAmount <= 420000) {
return taxableAmount * 0.25 - 31920;
} else if (taxableAmount <= 660000) {
return taxableAmount * 0.3 - 52920;
} else if (taxableAmount <= 960000) {
return taxableAmount * 0.35 - 85920;
} else {
return taxableAmount * 0.45 - 181920;
}
}
}
最后
我最开始尝试写一个 UI 版。但后续感觉,UI 版对于不同语言的用户,会看起来很痛苦。
因此我通过纯 JS 实现,大家可以通过不同的 UI 调用该类,可以在各个框架中使用。
同时也通过 svelte 做了一个简略 UI 版,大家可以直接尝试。
最后,点赞、关注、收藏 ,祝大家多多退税~~
来源:juejin.cn/post/7342511044290789430