自 2022 年 1 月 1 日起,居民集体获得全年一次性奖金,应并入当年综合所得计算缴纳个人所得税。
这次调整会影响年终奖到手的金额,打算用 Streamlit 框架做个工资计算器 web app,岂但能晓得年终奖少了多少,也能看到每月 到手工资 以及变动。对代码不感兴趣的敌人能够 间接跳到文末看论断,那里列举对不同月薪群体的影响。
19 年个税改为累计预扣法计算后,大家会发现年初到手的工资高一些,年底就低一些了。
这是累计带来的效应,19 年之前是每个月独立算个税,互不影响,所以每月 到手工资 变动不大。19 年之后是每个月工资须要跟前几个月累计到一起来算个税。从年初到年底,累计金额越来越大,税率就会越高,缴纳的个税也就会 越高 。到手的工资天然就是前高后低。每月累计的工资就叫 当年综合所得 。调整前年终奖有独自的税率表,独自计算个税。调整后,并入当年综合所得,就会 导致税率比之前更高,到手的金额会变少。
1 计算公式
依照个税 累计预扣法 ,看下 到手工资 的计算方法。
咱们每月到手的工资须要从月薪里扣除个人所得税和缴纳的五险一金,所以第一个公式是:到手工资 = 月薪 – 当月个税 – 当月缴纳五险一金 当月个税 又波及 2 个公式:
应税金额 = 累计月薪 – 累计缴纳五险一金 – 累计 6 项附加扣除 – 累计个税起征点
当月个税 = 应税金额 税率(查表)- 速算扣除 – 前几月累计个税 五险一金 波及 1 个公式:每月缴纳五险一金 = 缴纳基数 缴纳比例
个税起征点是常量 5000,6 项附加扣除是本人填报的,也能够看做是常量。
有了公式,计算 到手工资 就很简略了
2 计算五险一金
五险一金包含养老保险、医疗保险、就业保险、工伤保险、生养保险和住房公积金,其中养老保险、医疗保险和公积金缴纳得多一些,对工资计算影响大,其余三个保险要么不须要集体缴纳,要么缴纳比例极低,能够疏忽。
所以,代码里用养老保险、医疗保险和住房公积金代替五险一金。
缴纳基数 是个范畴,月薪落在该范畴就依照 月薪 缴纳比例 来算,如果超过下限依照 下限 缴纳比例 来算。
缴纳比例 在不同城市、不同企业是不一样的,这里,我依照北京市最高比例作为默认值。别离是 2%、8%、12%。定义两个函数,一个用来获取缴纳基数,另一个依据基数和比例计算单月缴纳的五险一金。\
def get_cardinal_number(salary, low, high):
"""
依据月薪获取社保缴费基数
:param salary: 月薪
:param low: 上限基数
:param high: 下限基数
:return: 理论缴费基数
"""
if salary <= low:
return low
elif low < salary <= high:
return salary
else:
return high
def get_five_insurances(salary, yi_liao_rate=0.02, yang_lao_rate=0.08, gong_ji_jin_rate=0.12):
"""
计算集体五险一金的缴纳金额
:param salary: 月薪
:param yi_liao_rate: 医疗保险缴纳比例
:param yang_lao_rate: 养老保险缴纳比例
:param gong_ji_jin_rate: 公积金缴纳比例
:return: 缴纳金额
"""
yi_liao_cn = get_cardinal_number(salary, 5360, 29732)
yang_lao_cn = get_cardinal_number(salary, 3613, 26541)
gong_ji_jin_cn = get_cardinal_number(salary, 2320, 27786)
five_insurances = yi_liao_cn * yi_liao_rate + yang_lao_cn * yang_lao_rate + round(gong_ji_jin_cn * gong_ji_jin_rate)
return five_insurances
3 计算个税
首先,须要定义一张个人所得税税率表
在代码里用数组嵌套元组的形式实现 \
# 个税税率表
salary_tax_rate_tb = [(0, 36000, 0.03, 0),
(36000, 144000, 0.1, 2520),
(144000, 300000, 0.2, 16920),
(300000, 420000, 0.25, 31920),
(420000, 660000, 0.3, 52920),
(660000, 960000, 0.35, 85920),
(960000, sys.maxsize, 0.45, 181920),
]
定义函数,依据应税金额查表,返回税率和速算扣除
def get_tax_rate(tax_rate_tb, salary):
"""
依据月薪(年终奖)获取税率
:param tax_rate_tb: 税率表,格局 [(分段上限, 分段下限, 税率, 速算扣除), (...), ...]
:param salary: 月薪或年终奖
:return: salary 所在分段的税率和速算扣除金额
"""
for tax_rate in tax_rate_tb:
if tax_rate[0] < salary <= tax_rate[1]:
return tax_rate[2], tax_rate[3]
定义函数,依据月薪查表计算个税
def calc_salary_tax(salary, deduct_salary):
"""
计算月薪个税
:param salary: 累计月薪
:param deduct_salary: 累计缴纳五险一金 + 累计 6 项附加扣除 + 累计个税起征点
:return:
"""
# 应纳税额 = 累计月薪 - 累计缴纳五险一金 - 累计 6 项附加扣除 - 累计个税起征点
taxable_amount = salary - deduct_salary
# 查表获取税率和速算扣除
tax_rate = get_tax_rate(salary_tax_rate_tb, taxable_amount)
# 累计个税 = 应税金额 * 税率 - 速算扣除
return taxable_amount * tax_rate[0] - tax_rate[1]
4 计算一年的到手工资
写一个 for 循环调用下面的函数即可算出全年的工资和应缴个税。
def calc_salary(monthly_salary=20000, yi_liao_rate=0.02, yang_lao_rate=0.08, gong_ji_jin_rate=0.12,
six_special=1000, bonus_months=4):
total_salary = 0 # 累计月薪
total_five_insurances = 0 # 累计五险一金
total_tax_threshold = 0 # 累计个税起征点
total_six_special = 0 # 累计 6 项附加扣除
pre_tax_amount = 0 # 前几月累计个税
money_every_month = [] # 返回每个月到手工资
tax_every_month = [] # 返回每个月缴纳个税
for i in range(1, 13):
total_salary += monthly_salary
five_insurances = get_five_insurances(monthly_salary, yi_liao_rate, yang_lao_rate, gong_ji_jin_rate)
total_five_insurances += five_insurances
total_tax_threshold += 5000
total_six_special += six_special
# 不须要征税的局部
to_deduct = total_five_insurances + total_tax_threshold + total_six_special
# 当月个税 = 当年所得累计个税 - 前几月累计个税
taxed_amount = round(calc_salary_tax(total_salary, to_deduct) - pre_tax_amount, 2)
tax_every_month.append(taxed_amount)
# pre_tax_amount 累计当月个税,为下个月做筹备
pre_tax_amount += taxed_amount
# 到手工资 = 月薪 - 当月个税 - 当月缴纳五险一金
money = round(monthly_salary - taxed_amount - five_insurances, 2)
money_every_month.append(money)
return money_every_month, tax_every_month
调用 calc_salary 函数,须要传入以下参数:月薪、社保缴纳比例、6 项附加扣除和年终奖发几个月。函数会循环 12 次计算每个月到手工资与个税。
5 计算年终奖
每个企业发放年终奖的工夫不一样,这里我默认依照 12 月解决。为了比照年终奖变动,会把调整前后的年终奖到手金额都计算出来,调整后年终奖很简略,因为累计到全年所得,计算形式跟算每月个税是一样的。调整前的须要定义新的税率表和个税计算函数
# 年终奖税率表
bonus_tax_rate_tb = [(0, 3000, 0.03, 0),
(3000, 12000, 0.1, 210),
(12000, 25000, 0.2, 1410),
(25000, 35000, 0.25, 2660),
(35000, 55000, 0.3, 4410),
(55000, 80000, 0.35, 7160),
(80000, sys.maxsize, 0.45, 15160),
]
# 调整前年终奖个税计算
def calc_bonus_tax(salary):
"""
计算年终奖 v1 个税,须要把年终奖总额除以 12,再查税率表,相当于均匀每月的个税
:param salary:
:return:
"""
tax_rate = get_tax_rate(bonus_tax_rate_tb, salary / 12)
return salary * tax_rate[0] - tax_rate[1]
编写代码,计算两种年终奖的到手金额
# 默认依照 12 月份发年终奖计算
if i == 12:
# 年终奖 = bonus_months * 月薪
bonus = bonus_months * monthly_salary
# v1 版本 调整前
bonus_taxed_amount_v1 = calc_bonus_tax(bonus)
tax_every_month.append(bonus_taxed_amount_v1)
bonus_money_v1 = bonus - bonus_taxed_amount_v1
money_every_month.append(round(bonus_money_v1, 2))
# v2 版本 调整后
bonus_taxed_amount_v2 = round(calc_salary_tax(total_salary + bonus, to_deduct) - pre_tax_amount, 2)
tax_every_month.append(bonus_taxed_amount_v2)
bonus_money_v2 = bonus - bonus_taxed_amount_v2
money_every_month.append(round(bonus_money_v2, 2))
上述代码加到 cacl_salary 函数中,return 语句之前即可。
6 前端页面
工资计算局部就完结了,剩下还需编写前端页面。
依据用户在页面输出的值来调用 calc_salary 函数,并在页面展现返回的后果。\
页面用 Streamlit 实现,这里就间接贴代码。
import streamlit as st
import pandas as pd
from salary_funcs import calc_salary
st.title('工资计算器')
city_selectbox = st.sidebar.selectbox(
"抉择城市",
('北京市', '')
)
monthly_salary = st.sidebar.text_input(
'月薪',
value=20000
)
yi_liao_rate = st.sidebar.text_input('医疗保险缴纳比例(%)',
value=2
)
yang_lao_rate = st.sidebar.text_input('养老保险缴纳比例(%)',
value=8
)
gong_ji_jin_rate = st.sidebar.text_input('公积金缴纳比例(%)',
value=12
)
six_special = st.sidebar.text_input(
'六项附加扣除',
value=1000
)
bonus_months = st.sidebar.text_input(
'年终奖几个月',
value=4
)
money, tax = calc_salary(float(monthly_salary), float(yi_liao_rate) / 100, float(yang_lao_rate) / 100,
float(gong_ji_jin_rate) / 100, int(six_special), int(bonus_months))
money_pd = pd.DataFrame({'到手工资': money[:12]},
index=[i for i in range(1, 13)] # 调整 index 从 1 开始
)
st.bar_chart(money_pd)
bonus_v1 = money[12]
bonus_v2 = money[13]
st.write('改版前的年终奖:', bonus_v1, '元,改版后:', bonus_v2, '元')
bonus_delta, tax_delta = st.columns(2)
with bonus_delta:
st.metric('年终奖到手变动', value=bonus_v2, delta=round(bonus_v2-bonus_v1, 2), delta_color='inverse')
with tax_delta:
bonus_tax_v1 = tax[12]
bonus_tax_v2 = tax[13]
st.metric('年终奖征税变动', value=bonus_tax_v2, delta=round(bonus_tax_v2-bonus_tax_v1, 2), delta_color='inverse')
all_pd = pd.DataFrame(
{'缴纳个税': tax[:12],
'到手工资': money[:12],
}
, index=[f'{i}月' for i in range(1, 13)]
)
st.table(all_pd)
页面成果如下:
左侧能够设置月薪、五险一金缴纳基数、年终奖,右侧展现每个月薪、年终奖到手金额和个税。依照 4 个月年终奖算:
- 月薪 2w:年终奖少 5k
- 月薪 3w-4w:年终奖少 1.3w
- 月薪 5w:年终奖少 2w
每个企业年终奖金额、发放工夫、其余支出(如:补贴、加班费)都不太一样,感兴趣的敌人能够依据本人状况下载代码运行。
以上就是本次分享的所有内容,如果你感觉文章还不错,欢送关注公众号:Python 编程学习圈,每日干货分享,发送“J”还可支付大量学习材料。或是返回编程学习网,理解更多编程技术常识。