Created
March 2, 2016 14:09
-
-
Save ZhangHang/601adbcd5294c18a50ab to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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