Skip to content

Instantly share code, notes, and snippets.

@mitsos1os
Last active August 2, 2020 19:01
Show Gist options
  • Save mitsos1os/ae87dbc4ee7ae12459e5ab819b68aba8 to your computer and use it in GitHub Desktop.
Save mitsos1os/ae87dbc4ee7ae12459e5ab819b68aba8 to your computer and use it in GitHub Desktop.
Simple NodeJS utility for calculating greek tax for 2020
'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