Skip to content

Instantly share code, notes, and snippets.

@ZhangHang
Created March 2, 2016 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZhangHang/601adbcd5294c18a50ab to your computer and use it in GitHub Desktop.
Save ZhangHang/601adbcd5294c18a50ab to your computer and use it in GitHub Desktop.
function LimitedTaxRule(from, to, rate) {
console.assert(from >= 0)
console.assert(to > from)
console.assert(rate >= 0)
//起始
this.from = from
//结束
this.to = to
//税率
this.rate = rate
//返回 判断 income 是否达到了当前税收规则的标准
this.reach = function(income) {
return income >= from
}
//返回 计算指定的 income 在当前税收规则需要交纳的税务
this.tax = function(income) {
if (!this.reach(income)) {
return 0
}
if (income > to) {
return rate * (to - from)
} else {
return rate * (income - from)
}
}
//返回当前规则若缴满所需要的税款
this.fullTax = function() {
return (to - from) * rate
}
this.toString = function() {
return "超过 " + from + " 到 " + to + " 按照 " + (rate * 100) + "% 缴税"
}
}
function UnlimitedTaxRule(from, rate) {
console.assert(from >= 0)
console.assert(rate >= 0)
this.from = from
this.rate = rate
this.reach = function(income) {
return income > from
}
this.tax = function(income) {
if (!this.reach(income)) {
return 0
}
return rate * (income - from)
}
}
function TaxCal(base, limitedRules, unlimitedTaxRule) {
var self = this
this.taxForSalary = function(salary) {
console.assert(salary > 0)
var tax = 0
for (var i = 0; i < limitedRules.length; i++) {
var currentRule = limitedRules[i]
if ( !currentRule.reach(salary - base) ) {
return tax
}
tax += currentRule.tax(salary - base)
}
if (unlimitedTaxRule) {
tax += unlimitedTaxRule.tax(salary - base)
}
return tax
}
// {from, to, rule}
var taxMap = (function() {
var map = []
for ( var i = 0; i < limitedRules.length; i++ ) {
var currentRule = limitedRules[i]
map.push({
bottom: currentRule.from - self.taxForSalary(currentRule.from + base) + base,
top: currentRule.to - self.taxForSalary(currentRule.to + base) + base,
rule: currentRule,
fullTax: currentRule.fullTax()
})
}
return map
})()
~function(){
console.log("税后低点|税后高点|本层级所缴|对应规则")
for ( var i = 0; i < taxMap.length; i++ ) {
var item = taxMap[i]
console.log(item.bottom + "|" + item.top + "|" + item.fullTax + "|" + item.rule.toString())
}
}()
//
this.incomeFromTaxedIncome = function(taxedIncome) {
var matchedTaxMapItem = null
for ( var i = taxMap.length - 1; i >= 0; i-- ) {
var taxMapItem = taxMap[i]
if (taxedIncome > taxMapItem.bottom && taxedIncome < taxMapItem.top) {
matchedTaxMapItem = taxMapItem
break
}
}
if (matchedTaxMapItem) {
console.log("找到符合中的最高标准 \(matchedTaxMapItem)")
var rule = matchedTaxMapItem.rule
return rule.from + (taxedIncome - matchedTaxMapItem.bottom) / (1 - rule.rate) + base
} else if (!!unlimitedTaxRule) {
var mapItem = taxMap[taxMap.length - 1]
return (taxedIncome - mapItem.top) / (1 - unlimitedTaxRule.rate) + mapItem.rule.to + base
} else {
console.log("没有符合的规则,且没有指定「无界限规则」")
console.assert(false)
}
console.log(taxMapItem)
}
}
function testTaxRule() {
var starRule = new LimitedTaxRule(0, 800, 0)
console.assert(starRule.reach(200) === true)
console.assert(starRule.reach(1000) === true)
console.assert(starRule.tax(200) === 0)
console.assert(starRule.tax(1000) === 0)
var middleRule = new LimitedTaxRule(800, 1200, 0.1)
console.assert(middleRule.reach(200) === false)
console.assert(middleRule.tax(200) === 0)
console.assert(middleRule.reach(1000) === true)
console.assert(middleRule.tax(1000) === 20)
console.assert(middleRule.reach(1300) === true)
console.assert(middleRule.tax(1300) === 40)
console.log("testTaxRule pass")
}
/*
  1 不超过1500元的 3
  2 超过1500元至4500元的部分 10
  3 超过4500元至9000元的部分 20
  4 超过9000元至35000元的部分 25
  5 超过35000元至55000元的部分 30
  6 超过55000元至80000元的部分 35
  7 超过80000元的部分 45
*/
function testTaxCal() {
var cal = new TaxCal(3500,
[new LimitedTaxRule(0, 1500, 0.03),
new LimitedTaxRule(1500, 4500, 0.10),
new LimitedTaxRule(4500, 9000, 0.20),
new LimitedTaxRule(9000, 35000, 0.25),
new LimitedTaxRule(35000, 55000, 0.30),
new LimitedTaxRule(55000, 80000, 0.35)],
new UnlimitedTaxRule(80000, 0.45))
console.assert(cal.taxForSalary(3500) === 0)
console.assert(cal.taxForSalary(4000) === 15)
console.assert(cal.taxForSalary(15000) === 1870)
console.assert(cal.taxForSalary(18000) === 2620)
console.assert(cal.taxForSalary(150000) === 52420)
console.log("testTaxCal pass")
console.log(cal.incomeFromTaxedIncome(90000))
}
testTaxRule()
testTaxCal()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment