注册

💀填好个税,一年多给几千块 ~ 聊聊个人所得税,你该退税还是补税?写一个个税的计算器(退税、补税、个税)

前言


一年一度个税年度综合汇算清缴的时间又到了,作为开发者的你,肯定过了起征点了吧。🫤


去年退税退了 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;
}
}

专项附加扣除


专项附加扣除通过数组的方式存储扣除项。



  1. 子女教育
  2. 赡养老人
  3. 继续教育(学校)
  4. 继续教育(证书)
  5. 住房贷款
  6. 大病医疗

// 专项附加扣除类型
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);
}

计算应缴个税


个税计算参考:


image.png


// 计算个税(金额 * 税率 - 速算扣除)
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 版,大家可以直接尝试。


最后,点赞、关注、收藏 ,祝大家多多退税~~


作者:sincenir
来源:juejin.cn/post/7342511044290789430

0 个评论

要回复文章请先登录注册