Last active
August 2, 2020 19:01
-
-
Save mitsos1os/ae87dbc4ee7ae12459e5ab819b68aba8 to your computer and use it in GitHub Desktop.
Simple NodeJS utility for calculating greek tax for 2020
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
'use strict'; | |
const readline = require('readline'); | |
// Tax percentages per salary level | |
const taxLevels = [10000, 20000, 30000, 40000, Infinity]; | |
const taxPercentages = [0.09, 0.22, 0.28, 0.36, 0.44]; | |
// Eisfora percentages | |
const eisforaLevels = [12000, 20000, 30000, 40000, 65000, 220000, Infinity]; | |
const eisforaPercentages = [0, 0.022, 0.05, 0.065, 0.075, 0.09, 0.1]; | |
// Tax reduction per kids - salary combo | |
const reductionPerKids = [777, 810, 900, 1120, 1340]; | |
const reductionPerExtraKid = 220; | |
const getReadLine = () => readline.createInterface({ | |
input: process.stdin, | |
output: process.stdout | |
}); | |
const getAnswer = (rl, prompt) => new Promise((resolve) => rl.question(prompt + ' ', resolve)); | |
const getSalary = async (rl) => { | |
const salaryText = await getAnswer(rl, 'Please input your taxable annual salary'); | |
return parseFloat(salaryText); | |
}; | |
const getKids = async (rl) => { | |
const kidsText = await getAnswer(rl, 'How many kids have you got?'); | |
return parseInt(kidsText, 10); | |
}; | |
const getInsurance = async (rl) => { | |
const insuranceText = await getAnswer(rl, 'How much insurance should be deducted?'); | |
return parseFloat(insuranceText); | |
}; | |
const getReduction = (salary, kids = 0) => { | |
const maxDefinedKidsInTable = reductionPerKids.length - 1; | |
let reduction = kids > maxDefinedKidsInTable ? // more than specific kids from table | |
reductionPerKids[maxDefinedKidsInTable] + (kids - maxDefinedKidsInTable) * 220 : // max reduction + 220 per extra kid | |
reductionPerKids[kids]; // specific reduction | |
if (salary > 12000 && kids < 5) { // no decrease in reduction for salaries under 12000 or more than 5 kids | |
reduction -= ((salary - 12000) / 1000 * 20); // decrease reduction for 20 per 1000 extra in salary above 12000 | |
} | |
return Math.max(reduction, 0); | |
}; | |
const calculatePercentageLevels = (amount, levelTables, percentageTables) => { | |
let total = 0 ; | |
for (let i = 0; i < levelTables.length; i++) { // browse tax levels | |
const currentLevel = levelTables[i]; | |
const previousLevel = i === 0 ? 0 : levelTables[i-1]; // get previous taxLevel or 0 if start | |
const currentPercentage = percentageTables[i]; | |
if (amount < currentLevel) { // in tax level range | |
total += (amount - previousLevel) * currentPercentage; | |
break; // currentLevel already bigger, no need to continue | |
} else { // exceeds level | |
total += (currentLevel - previousLevel) * currentPercentage; | |
} | |
} | |
return total; | |
}; | |
const calculateTax = (salary) => calculatePercentageLevels(salary, taxLevels, taxPercentages); | |
const calculateEisfora = (salary) => calculatePercentageLevels(salary, eisforaLevels, eisforaPercentages); | |
const getSalaryParts = (salary, insurance, kids) => { | |
const taxableSalary = salary - insurance; | |
const initialTax = calculateTax(taxableSalary); | |
const eisfora = calculateEisfora(taxableSalary); | |
const reduction = getReduction(taxableSalary, kids); | |
const totalTax = Math.round((initialTax - reduction + eisfora) * 100) / 100; // round tax to two decimals | |
const netSalary = salary - totalTax; | |
return { taxableSalary, initialTax, eisfora, reduction, totalTax, netSalary }; | |
}; | |
const grossForNetSalary = (targetNetSalary, insurance, kids, threshold = 1, step = 1) => { | |
let grossSalary = targetNetSalary; | |
while (targetNetSalary - getSalaryParts(grossSalary, insurance, kids).netSalary > threshold) { | |
grossSalary += step; | |
} | |
return grossSalary; | |
}; | |
const main = async () => { | |
const rl = getReadLine(); | |
const salary = await getSalary(rl); | |
const insurance = await getInsurance(rl); | |
const kids = await getKids(rl); | |
const { taxableSalary, initialTax, eisfora, reduction, totalTax, netSalary } = getSalaryParts(salary, insurance, kids); | |
// ------- Printing ---------- | |
console.log(`Tax calculation for ${salary} with ${kids} kids`); | |
console.log('Taxable salary:', taxableSalary); | |
console.log('Initial Tax:', initialTax); | |
console.log('Eisfora:', eisfora); | |
console.log('Tax Reduction:', reduction); | |
console.log('Total tax:', totalTax); | |
console.log('Net Salary:', netSalary); | |
// Target Net salary | |
const targetGrossSalary = grossForNetSalary(salary, insurance, kids); | |
console.log('Gross salary needed to clear taxes:', targetGrossSalary); | |
console.log('Virtual tax difference:', targetGrossSalary - salary); | |
rl.close(); | |
}; | |
main() | |
.then(() => { | |
process.exit(0); | |
}) | |
.catch(err => { | |
console.error('Error with operation', err); | |
process.exit(1); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment