@novha/calc-engines 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,10 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SouthAfricaIncomeTaxServiceImpl = void 0;
4
4
  class SouthAfricaIncomeTaxServiceImpl {
5
- constructor(income, age, rules) {
5
+ constructor(income, age, rules, medicalAidMembers = 0) {
6
+ this._medicalAidMembers = 0;
6
7
  this._income = income;
7
8
  this._age = age;
8
9
  this._rules = rules;
10
+ this._medicalAidMembers = medicalAidMembers;
9
11
  }
10
12
  calculateNetIncome() {
11
13
  const grossIncome = this._income;
@@ -22,7 +24,8 @@ class SouthAfricaIncomeTaxServiceImpl {
22
24
  }
23
25
  const grossTax = this.calculateBracketTax(this._income);
24
26
  const rebate = this.getRebate(this._age);
25
- const incomeTax = Math.max(0, grossTax - rebate);
27
+ const medicalAidCredit = this.calculateMedicalAidCredit(this._medicalAidMembers);
28
+ const incomeTax = Math.max(0, grossTax - rebate - medicalAidCredit);
26
29
  const uif = this.calculateUif(this._income);
27
30
  const totalDeductions = incomeTax + uif;
28
31
  const netIncome = grossIncome - totalDeductions;
@@ -71,9 +74,24 @@ class SouthAfricaIncomeTaxServiceImpl {
71
74
  const cappedIncome = Math.min(income, this._rules.uif.annualIncomeCap);
72
75
  return Math.min(cappedIncome * this._rules.uif.rate, this._rules.uif.maxAnnualContribution);
73
76
  }
77
+ calculateMedicalAidCredit(members) {
78
+ if (members <= 0)
79
+ return 0;
80
+ const monthly = this._rules.medicalAidTaxCredit.monthly;
81
+ let monthlyCredit = monthly.taxpayer;
82
+ if (members >= 2) {
83
+ monthlyCredit += monthly.firstDependant;
84
+ }
85
+ if (members > 2) {
86
+ monthlyCredit +=
87
+ (members - 2) * monthly.additionalDependant;
88
+ }
89
+ return (monthlyCredit *
90
+ this._rules.medicalAidTaxCredit.annualMultiplier);
91
+ }
74
92
  round(value, decimals = 2) {
75
93
  return Number(value.toFixed(decimals));
76
94
  }
77
95
  }
78
96
  exports.SouthAfricaIncomeTaxServiceImpl = SouthAfricaIncomeTaxServiceImpl;
79
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU291dGhBZnJpY2FJbmNvbWVUYXhTZXJ2aWNlSW1wbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9pbmNvbWUtdGF4L3NvdXRoLWFmcmljYS9Tb3V0aEFmcmljYUluY29tZVRheFNlcnZpY2VJbXBsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUdBLE1BQWEsK0JBQStCO0lBS3hDLFlBQVksTUFBYyxFQUFFLEdBQVcsRUFBRSxLQUFxQjtRQUMxRCxJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQztRQUN0QixJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQztRQUNoQixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztJQUN4QixDQUFDO0lBRUQsa0JBQWtCO1FBQ2QsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUVqQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVsRCxJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksU0FBUyxFQUFFLENBQUM7WUFDNUIsT0FBTztnQkFDSCxXQUFXO2dCQUNYLFNBQVMsRUFBRSxDQUFDO2dCQUNaLEdBQUcsRUFBRSxDQUFDO2dCQUNOLGVBQWUsRUFBRSxDQUFDO2dCQUNsQixTQUFTLEVBQUUsV0FBVztnQkFDdEIsZ0JBQWdCLEVBQUUsQ0FBQzthQUN0QixDQUFDO1FBQ04sQ0FBQztRQUVELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFeEQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsUUFBUSxHQUFHLE1BQU0sQ0FBQyxDQUFDO1FBRWpELE1BQU0sR0FBRyxH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QUVPLEtBQUssQ0FBQyxLQUFhLEVBQUUsUUFBUSxHQUFHLENBQUM7UUFDckMsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQzNDLENBQUM7Q0FDSjtBQXZHRCwwRUF1R0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wdXRlZEluY29tZVRheFZhbHVlcywgSW5jb21lVGF4UnVsZXMgfSBmcm9tIFwiLi9kb21haW4vdHlwZXNcIjtcbmltcG9ydCB7IFNvdXRoQWZyaWNhSW5jb21lVGF4U2VydmljZSB9IGZyb20gXCIuL1NvdXRoQWZyaWNhSW5jb21lVGF4U2VydmljZVwiO1xuXG5leHBvcnQgY2xhc3MgU291dGhBZnJpY2FJbmNvbWVUYXhTZXJ2aWNlSW1wbCBpbXBsZW1lbnRzIFNvdXRoQWZyaWNhSW5jb21lVGF4U2VydmljZSB7XG4gICAgcHJpdmF0ZSBfaW5jb21lOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBfYWdlOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBfcnVsZXM6IEluY29tZVRheFJ1bGVzO1xuXG4gICAgY29uc3RydWN0b3IoaW5jb21lOiBudW1iZXIsIGFnZTogbnVtYmVyLCBydWxlczogSW5jb21lVGF4UnVsZXMpIHtcbiAgICAgICAgdGhpcy5faW5jb21lID0gaW5jb21lO1xuICAgICAgICB0aGlzLl9hZ2UgPSBhZ2U7XG4gICAgICAgIHRoaXMuX3J1bGVzID0gcnVsZXM7XG4gICAgfVxuXG4gICAgY2FsY3VsYXRlTmV0SW5jb21lKCk6IENvbXB1dGVkSW5jb21lVGF4VmFsdWVzIHtcbiAgICAgICAgY29uc3QgZ3Jvc3NJbmNvbWUgPSB0aGlzLl9pbmNvbWU7XG5cbiAgICAgICAgY29uc3QgdGhyZXNob2xkID0gdGhpcy5nZXRUYXhUaHJlc2hvbGQodGhpcy5fYWdlKTtcblxuICAgICAgICBpZiAodGhpcy5faW5jb21lIDw9IHRocmVzaG9sZCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBncm9zc0luY29tZSxcbiAgICAgICAgICAgICAgICBpbmNvbWVUYXg6IDAsXG4gICAgICAgICAgICAgICAgdWlmOiAwLFxuICAgICAgICAgICAgICAgIHRvdGFsRGVkdWN0aW9uczogMCxcbiAgICAgICAgICAgICAgICBuZXRJbmNvbWU6IGdyb3NzSW5jb21lLFxuICAgICAgICAgICAgICAgIGVmZmVjdGl2ZVRheFJhdGU6IDAsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZ3Jvc3NUYXggPSB0aGlzLmNhbGN1bGF0ZUJyYWNrZXRUYXgodGhpcy5faW5jb21lKTtcblxuICAgICAgICBjb25zdCByZWJhdGUgPSB0aGlzLmdldFJlYmF0ZSh0aGlzLl9hZ2UpO1xuICAgICAgICBjb25zdCBpbmNvbWVUYXggPSBNYXRoLm1heCgwLCBncm9zc1RheCAtIHJlYmF0ZSk7XG5cbiAgICAgICAgY29uc3QgdWlmID0gdGhpcy5jYWxjdWxhdGVVaWYodGhpcy5faW5jb21lKTtcblxuICAgICAgICBjb25zdCB0b3RhbERlZHVjdGlvbnMgPSBpbmNvbWVUYXggKyB1aWY7XG4gICAgICAgIGNvbnN0IG5ldEluY29tZSA9IGdyb3NzSW5jb21lIC0gdG90YWxEZWR1Y3Rpb25zO1xuICAgICAgICBjb25zdCBlZmZlY3RpdmVUYXhSYXRlID0gaW5jb21lVGF4IC8gZ3Jvc3NJbmNvbWU7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGdyb3NzSW5jb21lLFxuICAgICAgICAgICAgaW5jb21lVGF4OiB0aGlzLnJvdW5kKGluY29tZVRheCksXG4gICAgICAgICAgICB1aWY6IHRoaXMucm91bmQodWlmKSxcbiAgICAgICAgICAgIHRvdGFsRGVkdWN0aW9uczogdGhpcy5yb3VuZCh0b3RhbERlZHVjdGlvbnMpLFxuICAgICAgICAgICAgbmV0SW5jb21lOiB0aGlzLnJvdW5kKG5ldEluY29tZSksXG4gICAgICAgICAgICBlZmZlY3RpdmVUYXhSYXRlOiB0aGlzLnJvdW5kKGVmZmVjdGl2ZVRheFJhdGUsIDQpLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgY2FsY3VsYXRlQnJhY2tldFRheChpbmNvbWU6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIGxldCB0YXggPSAwO1xuXG4gICAgICAgIGZvciAoY29uc3QgYnJhY2tldCBvZiB0aGlzLl9ydWxlcy50YXhCcmFja2V0cykge1xuICAgICAgICAgICAgaWYgKGluY29tZSA8PSBicmFja2V0LmZyb20pIGJyZWFrO1xuXG4gICAgICAgICAgICBjb25zdCB1cHBlciA9IGJyYWNrZXQudG8gPz8gaW5jb21lO1xuICAgICAgICAgICAgY29uc3QgdGF4YWJsZUFtb3VudCA9IE1hdGgubWluKHVwcGVyLCBpbmNvbWUpIC0gYnJhY2tldC5mcm9tO1xuXG4gICAgICAgICAgICBpZiAodGF4YWJsZUFtb3VudCA+IDApIHtcbiAgICAgICAgICAgICAgICB0YXggKz0gdGF4YWJsZUFtb3VudCAqIGJyYWNrZXQucmF0ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0YXg7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRUYXhUaHJlc2hvbGQoYWdlOiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICBjb25zdCB0aHJlc2hvbGRzID0gdGhpcy5fcnVsZXMudGF4VGhyZXNob2xkcztcblxuICAgICAgICBpZiAoYWdlID49IDc1KSByZXR1cm4gdGhyZXNob2xkcy5hZ2U3NVBsdXM7XG4gICAgICAgIGlmIChhZ2UgPj0gNjUpIHJldHVybiB0aHJlc2hvbGRzLmFnZTY1VG83NDtcblxuICAgICAgICByZXR1cm4gdGhyZXNob2xkcy51bmRlcjY1O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0UmViYXRlKGFnZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgbGV0IHJlYmF0ZSA9IHRoaXMuX3J1bGVzLnJlYmF0ZXMucHJpbWFyeS5hbW91bnQ7XG5cbiAgICAgICAgaWYgKGFnZSA+PSB0aGlzLl9ydWxlcy5yZWJhdGVzLnNlY29uZGFyeS5hZ2VNaW4pIHtcbiAgICAgICAgICAgIHJlYmF0ZSArPSB0aGlzLl9ydWxlcy5yZWJhdGVzLnNlY29uZGFyeS5hbW91bnQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYWdlID49IHRoaXMuX3J1bGVzLnJlYmF0ZXMudGVydGlhcnkuYWdlTWluKSB7XG4gICAgICAgICAgICByZWJhdGUgKz0gdGhpcy5fcnVsZXMucmViYXRlcy50ZXJ0aWFyeS5hbW91bnQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmViYXRlO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2FsY3VsYXRlVWlmKGluY29tZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgY2FwcGVkSW5jb21lID0gTWF0aC5taW4oXG4gICAgICAgICAgICBpbmNvbWUsXG4gICAgICAgICAgICB0aGlzLl9ydWxlcy51aWYuYW5udWFsSW5jb21lQ2FwLFxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiBNYXRoLm1pbihcbiAgICAgICAgICAgIGNhcHBlZEluY29tZSAqIHRoaXMuX3J1bGVzLnVpZi5yYXRlLFxuICAgICAgICAgICAgdGhpcy5fcnVsZXMudWlmLm1heEFubnVhbENvbnRyaWJ1dGlvbixcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJvdW5kKHZhbHVlOiBudW1iZXIsIGRlY2ltYWxzID0gMik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBOdW1iZXIodmFsdWUudG9GaXhlZChkZWNpbWFscykpO1xuICAgIH1cbn0iXX0=
97
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU291dGhBZnJpY2FJbmNvbWVUYXhTZXJ2aWNlSW1wbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9pbmNvbWUtdGF4L3NvdXRoLWFmcmljYS9Tb3V0aEFmcmljYUluY29tZVRheFNlcnZpY2VJbXBsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUdBLE1BQWEsK0JBQStCO0lBTXhDLFlBQVksTUFBYyxFQUFFLEdBQVcsRUFBRSxLQUFxQixFQUFFLG9CQUE0QixDQUFDO1FBRnJGLHVCQUFrQixHQUFXLENBQUMsQ0FBQztRQUduQyxJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQztRQUN0QixJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQztRQUNoQixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztRQUNwQixJQUFJLENBQUMsa0JBQWtCLEdBQUcsaUJBQWlCLENBQUM7SUFDaEQsQ0FBQztJQUVELGtCQUFrQjtRQUNkLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7UUFFakMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFbEQsSUFBSSxJQUFJLENBQUMsT0FBTyxJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQzVCLE9BQU87Z0JBQ0gsV0FBVztnQkFDWCxTQUFTLEVBQUUsQ0FBQztnQkFDWixHQUFHLEVBQUUsQ0FBQztnQkFDTixlQUFlLEVBQUUsQ0FBQztnQkFDbEIsU0FBUyxFQUFFLFdBQVc7Z0JBQ3RCLGdCQUFnQixFQUFFLENBQUM7YUFDdEIsQ0FBQztRQUNOLENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXhELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pDLE1B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QUFDLEdBQUcsQ0FBQyxlQUFlLENBQ2xDLENBQUM7UUFFRixPQUFPLElBQUksQ0FBQyxHQUFHLENBQ1gsWUFBWSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksRUFDbkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQ3hDLENBQUM7SUFDTixDQUFDO0lBRU8seUJBQXlCLENBQUMsT0FBZTtRQUM3QyxJQUFJLE9BQU8sSUFBSSxDQUFDO1lBQUUsT0FBTyxDQUFDLENBQUM7UUFFM0IsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLENBQUM7UUFFeEQsSUFBSSxhQUFhLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUVyQyxJQUFJLE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUNmLGFBQWEsSUFBSSxPQUFPLENBQUMsY0FBYyxDQUFDO1FBQzVDLENBQUM7UUFFRCxJQUFJLE9BQU8sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNkLGFBQWE7Z0JBQ1QsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDO1FBQ3BELENBQUM7UUFFRCxPQUFPLENBQ0gsYUFBYTtZQUNiLElBQUksQ0FBQyxNQUFNLENBQUMsbUJBQW1CLENBQUMsZ0JBQWdCLENBQ25ELENBQUM7SUFDTixDQUFDO0lBRU8sS0FBSyxDQUFDLEtBQWEsRUFBRSxRQUFRLEdBQUcsQ0FBQztRQUNyQyxPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDM0MsQ0FBQztDQUNKO0FBaklELDBFQWlJQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXB1dGVkSW5jb21lVGF4VmFsdWVzLCBJbmNvbWVUYXhSdWxlcyB9IGZyb20gXCIuL2RvbWFpbi90eXBlc1wiO1xuaW1wb3J0IHsgU291dGhBZnJpY2FJbmNvbWVUYXhTZXJ2aWNlIH0gZnJvbSBcIi4vU291dGhBZnJpY2FJbmNvbWVUYXhTZXJ2aWNlXCI7XG5cbmV4cG9ydCBjbGFzcyBTb3V0aEFmcmljYUluY29tZVRheFNlcnZpY2VJbXBsIGltcGxlbWVudHMgU291dGhBZnJpY2FJbmNvbWVUYXhTZXJ2aWNlIHtcbiAgICBwcml2YXRlIF9pbmNvbWU6IG51bWJlcjtcbiAgICBwcml2YXRlIF9hZ2U6IG51bWJlcjtcbiAgICBwcml2YXRlIF9ydWxlczogSW5jb21lVGF4UnVsZXM7XG4gICAgcHJpdmF0ZSBfbWVkaWNhbEFpZE1lbWJlcnM6IG51bWJlciA9IDA7XG5cbiAgICBjb25zdHJ1Y3RvcihpbmNvbWU6IG51bWJlciwgYWdlOiBudW1iZXIsIHJ1bGVzOiBJbmNvbWVUYXhSdWxlcywgbWVkaWNhbEFpZE1lbWJlcnM6IG51bWJlciA9IDApIHtcbiAgICAgICAgdGhpcy5faW5jb21lID0gaW5jb21lO1xuICAgICAgICB0aGlzLl9hZ2UgPSBhZ2U7XG4gICAgICAgIHRoaXMuX3J1bGVzID0gcnVsZXM7XG4gICAgICAgIHRoaXMuX21lZGljYWxBaWRNZW1iZXJzID0gbWVkaWNhbEFpZE1lbWJlcnM7XG4gICAgfVxuXG4gICAgY2FsY3VsYXRlTmV0SW5jb21lKCk6IENvbXB1dGVkSW5jb21lVGF4VmFsdWVzIHtcbiAgICAgICAgY29uc3QgZ3Jvc3NJbmNvbWUgPSB0aGlzLl9pbmNvbWU7XG5cbiAgICAgICAgY29uc3QgdGhyZXNob2xkID0gdGhpcy5nZXRUYXhUaHJlc2hvbGQodGhpcy5fYWdlKTtcblxuICAgICAgICBpZiAodGhpcy5faW5jb21lIDw9IHRocmVzaG9sZCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBncm9zc0luY29tZSxcbiAgICAgICAgICAgICAgICBpbmNvbWVUYXg6IDAsXG4gICAgICAgICAgICAgICAgdWlmOiAwLFxuICAgICAgICAgICAgICAgIHRvdGFsRGVkdWN0aW9uczogMCxcbiAgICAgICAgICAgICAgICBuZXRJbmNvbWU6IGdyb3NzSW5jb21lLFxuICAgICAgICAgICAgICAgIGVmZmVjdGl2ZVRheFJhdGU6IDAsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZ3Jvc3NUYXggPSB0aGlzLmNhbGN1bGF0ZUJyYWNrZXRUYXgodGhpcy5faW5jb21lKTtcblxuICAgICAgICBjb25zdCByZWJhdGUgPSB0aGlzLmdldFJlYmF0ZSh0aGlzLl9hZ2UpO1xuICAgICAgICBjb25zdCBtZWRpY2FsQWlkQ3JlZGl0ID1cbiAgICAgICAgICAgIHRoaXMuY2FsY3VsYXRlTWVkaWNhbEFpZENyZWRpdCh0aGlzLl9tZWRpY2FsQWlkTWVtYmVycyk7XG4gICAgICAgIGNvbnN0IGluY29tZVRheCA9IE1hdGgubWF4KDAsIGdyb3NzVGF4IC0gcmViYXRlIC0gbWVkaWNhbEFpZENyZWRpdCk7XG5cbiAgICAgICAgY29uc3QgdWlmID0gdGhpcy5jYWxjdWxhdGVVaWYodGhpcy5faW5jb21lKTtcblxuICAgICAgICBjb25zdCB0b3RhbERlZHVjdGlvbnMgPSBpbmNvbWVUYXggKyB1aWY7XG4gICAgICAgIGNvbnN0IG5ldEluY29tZSA9IGdyb3NzSW5jb21lIC0gdG90YWxEZWR1Y3Rpb25zO1xuICAgICAgICBjb25zdCBlZmZlY3RpdmVUYXhSYXRlID0gaW5jb21lVGF4IC8gZ3Jvc3NJbmNvbWU7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGdyb3NzSW5jb21lLFxuICAgICAgICAgICAgaW5jb21lVGF4OiB0aGlzLnJvdW5kKGluY29tZVRheCksXG4gICAgICAgICAgICB1aWY6IHRoaXMucm91bmQodWlmKSxcbiAgICAgICAgICAgIHRvdGFsRGVkdWN0aW9uczogdGhpcy5yb3VuZCh0b3RhbERlZHVjdGlvbnMpLFxuICAgICAgICAgICAgbmV0SW5jb21lOiB0aGlzLnJvdW5kKG5ldEluY29tZSksXG4gICAgICAgICAgICBlZmZlY3RpdmVUYXhSYXRlOiB0aGlzLnJvdW5kKGVmZmVjdGl2ZVRheFJhdGUsIDQpLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgY2FsY3VsYXRlQnJhY2tldFRheChpbmNvbWU6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIGxldCB0YXggPSAwO1xuXG4gICAgICAgIGZvciAoY29uc3QgYnJhY2tldCBvZiB0aGlzLl9ydWxlcy50YXhCcmFja2V0cykge1xuICAgICAgICAgICAgaWYgKGluY29tZSA8PSBicmFja2V0LmZyb20pIGJyZWFrO1xuXG4gICAgICAgICAgICBjb25zdCB1cHBlciA9IGJyYWNrZXQudG8gPz8gaW5jb21lO1xuICAgICAgICAgICAgY29uc3QgdGF4YWJsZUFtb3VudCA9IE1hdGgubWluKHVwcGVyLCBpbmNvbWUpIC0gYnJhY2tldC5mcm9tO1xuXG4gICAgICAgICAgICBpZiAodGF4YWJsZUFtb3VudCA+IDApIHtcbiAgICAgICAgICAgICAgICB0YXggKz0gdGF4YWJsZUFtb3VudCAqIGJyYWNrZXQucmF0ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0YXg7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRUYXhUaHJlc2hvbGQoYWdlOiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICBjb25zdCB0aHJlc2hvbGRzID0gdGhpcy5fcnVsZXMudGF4VGhyZXNob2xkcztcblxuICAgICAgICBpZiAoYWdlID49IDc1KSByZXR1cm4gdGhyZXNob2xkcy5hZ2U3NVBsdXM7XG4gICAgICAgIGlmIChhZ2UgPj0gNjUpIHJldHVybiB0aHJlc2hvbGRzLmFnZTY1VG83NDtcblxuICAgICAgICByZXR1cm4gdGhyZXNob2xkcy51bmRlcjY1O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0UmViYXRlKGFnZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgbGV0IHJlYmF0ZSA9IHRoaXMuX3J1bGVzLnJlYmF0ZXMucHJpbWFyeS5hbW91bnQ7XG5cbiAgICAgICAgaWYgKGFnZSA+PSB0aGlzLl9ydWxlcy5yZWJhdGVzLnNlY29uZGFyeS5hZ2VNaW4pIHtcbiAgICAgICAgICAgIHJlYmF0ZSArPSB0aGlzLl9ydWxlcy5yZWJhdGVzLnNlY29uZGFyeS5hbW91bnQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYWdlID49IHRoaXMuX3J1bGVzLnJlYmF0ZXMudGVydGlhcnkuYWdlTWluKSB7XG4gICAgICAgICAgICByZWJhdGUgKz0gdGhpcy5fcnVsZXMucmViYXRlcy50ZXJ0aWFyeS5hbW91bnQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmViYXRlO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2FsY3VsYXRlVWlmKGluY29tZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgY2FwcGVkSW5jb21lID0gTWF0aC5taW4oXG4gICAgICAgICAgICBpbmNvbWUsXG4gICAgICAgICAgICB0aGlzLl9ydWxlcy51aWYuYW5udWFsSW5jb21lQ2FwLFxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiBNYXRoLm1pbihcbiAgICAgICAgICAgIGNhcHBlZEluY29tZSAqIHRoaXMuX3J1bGVzLnVpZi5yYXRlLFxuICAgICAgICAgICAgdGhpcy5fcnVsZXMudWlmLm1heEFubnVhbENvbnRyaWJ1dGlvbixcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNhbGN1bGF0ZU1lZGljYWxBaWRDcmVkaXQobWVtYmVyczogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgaWYgKG1lbWJlcnMgPD0gMCkgcmV0dXJuIDA7XG5cbiAgICAgICAgY29uc3QgbW9udGhseSA9IHRoaXMuX3J1bGVzLm1lZGljYWxBaWRUYXhDcmVkaXQubW9udGhseTtcblxuICAgICAgICBsZXQgbW9udGhseUNyZWRpdCA9IG1vbnRobHkudGF4cGF5ZXI7XG5cbiAgICAgICAgaWYgKG1lbWJlcnMgPj0gMikge1xuICAgICAgICAgICAgbW9udGhseUNyZWRpdCArPSBtb250aGx5LmZpcnN0RGVwZW5kYW50O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG1lbWJlcnMgPiAyKSB7XG4gICAgICAgICAgICBtb250aGx5Q3JlZGl0ICs9XG4gICAgICAgICAgICAgICAgKG1lbWJlcnMgLSAyKSAqIG1vbnRobHkuYWRkaXRpb25hbERlcGVuZGFudDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBtb250aGx5Q3JlZGl0ICpcbiAgICAgICAgICAgIHRoaXMuX3J1bGVzLm1lZGljYWxBaWRUYXhDcmVkaXQuYW5udWFsTXVsdGlwbGllclxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgcm91bmQodmFsdWU6IG51bWJlciwgZGVjaW1hbHMgPSAyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIE51bWJlcih2YWx1ZS50b0ZpeGVkKGRlY2ltYWxzKSk7XG4gICAgfVxufSJdfQ==
@@ -4,11 +4,13 @@ export declare class SouthAfricaIncomeTaxServiceImpl implements SouthAfricaIncom
4
4
  private _income;
5
5
  private _age;
6
6
  private _rules;
7
- constructor(income: number, age: number, rules: IncomeTaxRules);
7
+ private _medicalAidMembers;
8
+ constructor(income: number, age: number, rules: IncomeTaxRules, medicalAidMembers?: number);
8
9
  calculateNetIncome(): ComputedIncomeTaxValues;
9
10
  private calculateBracketTax;
10
11
  private getTaxThreshold;
11
12
  private getRebate;
12
13
  private calculateUif;
14
+ private calculateMedicalAidCredit;
13
15
  private round;
14
16
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@novha/calc-engines",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/types/index.d.ts",
6
6
  "scripts": {
@@ -5,11 +5,13 @@ export class SouthAfricaIncomeTaxServiceImpl implements SouthAfricaIncomeTaxServ
5
5
  private _income: number;
6
6
  private _age: number;
7
7
  private _rules: IncomeTaxRules;
8
+ private _medicalAidMembers: number = 0;
8
9
 
9
- constructor(income: number, age: number, rules: IncomeTaxRules) {
10
+ constructor(income: number, age: number, rules: IncomeTaxRules, medicalAidMembers: number = 0) {
10
11
  this._income = income;
11
12
  this._age = age;
12
13
  this._rules = rules;
14
+ this._medicalAidMembers = medicalAidMembers;
13
15
  }
14
16
 
15
17
  calculateNetIncome(): ComputedIncomeTaxValues {
@@ -31,7 +33,9 @@ export class SouthAfricaIncomeTaxServiceImpl implements SouthAfricaIncomeTaxServ
31
33
  const grossTax = this.calculateBracketTax(this._income);
32
34
 
33
35
  const rebate = this.getRebate(this._age);
34
- const incomeTax = Math.max(0, grossTax - rebate);
36
+ const medicalAidCredit =
37
+ this.calculateMedicalAidCredit(this._medicalAidMembers);
38
+ const incomeTax = Math.max(0, grossTax - rebate - medicalAidCredit);
35
39
 
36
40
  const uif = this.calculateUif(this._income);
37
41
 
@@ -101,6 +105,28 @@ export class SouthAfricaIncomeTaxServiceImpl implements SouthAfricaIncomeTaxServ
101
105
  );
102
106
  }
103
107
 
108
+ private calculateMedicalAidCredit(members: number): number {
109
+ if (members <= 0) return 0;
110
+
111
+ const monthly = this._rules.medicalAidTaxCredit.monthly;
112
+
113
+ let monthlyCredit = monthly.taxpayer;
114
+
115
+ if (members >= 2) {
116
+ monthlyCredit += monthly.firstDependant;
117
+ }
118
+
119
+ if (members > 2) {
120
+ monthlyCredit +=
121
+ (members - 2) * monthly.additionalDependant;
122
+ }
123
+
124
+ return (
125
+ monthlyCredit *
126
+ this._rules.medicalAidTaxCredit.annualMultiplier
127
+ );
128
+ }
129
+
104
130
  private round(value: number, decimals = 2): number {
105
131
  return Number(value.toFixed(decimals));
106
132
  }