@novha/calc-engines 1.7.0 → 1.7.2
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.
- package/dist/corporate/canada/CanadaCorporateTaxServiceImpl.js +11 -9
- package/dist/corporate/canada/domain/types.js +1 -1
- package/dist/corporate/domain/types.js +2 -1
- package/dist/corporate/france/FranceCorporateTaxServiceImpl.js +16 -9
- package/dist/corporate/france/domain/types.js +1 -1
- package/dist/corporate/south-africa/SouthAfricaCorporateTaxServiceImpl.js +18 -13
- package/dist/corporate/south-africa/domain/types.js +1 -1
- package/dist/shared/domain/types.js +2 -1
- package/dist/types/corporate/canada/domain/types.d.ts +2 -1
- package/dist/types/corporate/domain/types.d.ts +6 -0
- package/dist/types/corporate/france/domain/types.d.ts +2 -1
- package/dist/types/corporate/south-africa/domain/types.d.ts +2 -1
- package/dist/types/shared/domain/types.d.ts +2 -1
- package/package.json +1 -1
- package/src/corporate/canada/CanadaCorporateTaxServiceImpl.ts +12 -9
- package/src/corporate/canada/domain/types.ts +2 -2
- package/src/corporate/domain/types.ts +6 -0
- package/src/corporate/france/FranceCorporateTaxServiceImpl.ts +17 -9
- package/src/corporate/france/domain/types.ts +2 -1
- package/src/corporate/south-africa/SouthAfricaCorporateTaxServiceImpl.ts +20 -14
- package/src/corporate/south-africa/domain/types.ts +3 -1
- package/src/shared/domain/types.ts +2 -1
|
@@ -14,7 +14,7 @@ class CanadaCorporateTaxServiceImpl {
|
|
|
14
14
|
effectiveTaxRate: this._input.taxableIncome > 0
|
|
15
15
|
? (totalTax / this._input.taxableIncome) * 100
|
|
16
16
|
: 0,
|
|
17
|
-
|
|
17
|
+
breakdowns: result.breakdowns,
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
applyRules(rules, input) {
|
|
@@ -25,13 +25,13 @@ class CanadaCorporateTaxServiceImpl {
|
|
|
25
25
|
const tax = input.taxableIncome * regime.rate;
|
|
26
26
|
return {
|
|
27
27
|
tax,
|
|
28
|
-
|
|
28
|
+
breakdowns: [{ from: '0', to: 'Above', rate: regime.rate, amount: tax }],
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
if (regime.type === 'progressive') {
|
|
32
32
|
let remaining = input.taxableIncome;
|
|
33
33
|
let tax = 0;
|
|
34
|
-
const
|
|
34
|
+
const breakdowns = [];
|
|
35
35
|
for (const bracket of regime.brackets) {
|
|
36
36
|
if (remaining <= 0)
|
|
37
37
|
break;
|
|
@@ -40,15 +40,17 @@ class CanadaCorporateTaxServiceImpl {
|
|
|
40
40
|
const bracketTax = taxable * bracket.rate;
|
|
41
41
|
tax += bracketTax;
|
|
42
42
|
remaining -= taxable;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
:
|
|
46
|
-
|
|
43
|
+
breakdowns.push({
|
|
44
|
+
from: `${bracket.from}`,
|
|
45
|
+
to: `${bracket.to ?? 'Above'}`,
|
|
46
|
+
rate: bracket.rate,
|
|
47
|
+
amount: bracketTax,
|
|
48
|
+
});
|
|
47
49
|
}
|
|
48
|
-
return { tax,
|
|
50
|
+
return { tax, breakdowns };
|
|
49
51
|
}
|
|
50
52
|
throw new Error('Unsupported regime type');
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
exports.CanadaCorporateTaxServiceImpl = CanadaCorporateTaxServiceImpl;
|
|
54
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
56
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2FuYWRhQ29ycG9yYXRlVGF4U2VydmljZUltcGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29ycG9yYXRlL2NhbmFkYS9DYW5hZGFDb3Jwb3JhdGVUYXhTZXJ2aWNlSW1wbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFJQSxNQUFhLDZCQUE2QjtJQUl0QyxZQUFZLEtBQVksRUFBRSxLQUFZO1FBQ2xDLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO0lBQ3hCLENBQUM7SUFFRCxTQUFTO1FBQ0wsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUV6RCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDO1FBRTVCLE9BQU87WUFDSCxZQUFZLEVBQUUsUUFBUTtZQUN0QixnQkFBZ0IsRUFDWixJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsR0FBRyxDQUFDO2dCQUN6QixDQUFDLENBQUMsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsR0FBRyxHQUFHO2dCQUM5QyxDQUFDLENBQUMsQ0FBQztZQUNYLFVBQVUsRUFBRSxNQUFNLENBQUMsVUFBVTtTQUNoQyxDQUFDO0lBQ04sQ0FBQztJQUVPLFVBQVUsQ0FBQyxLQUFZLEVBQUUsS0FBWTtRQUN6QyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsZUFBZTtZQUNoQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxhQUFhO1lBQzdCLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztRQUU1QixJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssTUFBTSxFQUFFLENBQUM7WUFDekIsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDO1lBQzlDLE9BQU87Z0JBQ0gsR0FBRztnQkFDSCxVQUFVLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUM7YUFDM0UsQ0FBQztRQUNOLENBQUM7UUFFRCxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssYUFBYSxFQUFFLENBQUM7WUFDaEMsSUFBSSxTQUFTLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQztZQUNwQyxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7WUFDWixNQUFNLFVBQVUsR0FBZ0IsRUFBRSxDQUFDO1lBRW5DLEtBQUssTUFBTSxPQUFPLElBQUksTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNwQyxJQUFJLFNBQVMsSUFBSSxDQUFDO29CQUFFLE1BQU07Z0JBRTFCLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxFQUFFLElBQUksUUFBUSxDQUFDO2dCQUNyQyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxDQUFDO2dCQUUxRCxNQUFNLFVBQVUsR0FBRyxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztnQkFDMUMsR0FBRyxJQUFJLFVBQVUsQ0FBQztnQkFDbEIsU0FBUyxJQUFJLE9BQU8sQ0FBQztnQkFFckIsVUFBVSxDQUFDLElBQUksQ0FBQztvQkFDWixJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsSUFBSSxFQUFFO29CQUN2QixFQUFFLEVBQUUsR0FBRyxPQUFPLENBQUMsRUFBRSxJQUFJLE9BQU8sRUFBRTtvQkFDOUIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO29CQUNsQixNQUFNLEVBQUUsVUFBVTtpQkFDckIsQ0FBQyxDQUFDO1lBQ1AsQ0FBQztZQUVELE9BQU8sRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLENBQUM7UUFDL0IsQ0FBQztRQUVELE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQztJQUMvQyxDQUFDO0NBQ0o7QUFqRUQsc0VBaUVDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUnVsZXMsIElucHV0LCBSZXN1bHQsIFByb2dyZXNzaXZlVGF4QnJhY2tldCB9IGZyb20gJy4vZG9tYWluL3R5cGVzJztcbmltcG9ydCB7IENhbmFkYUNvcnBvcmF0ZVRheFNlcnZpY2UgfSBmcm9tICcuL0NhbmFkYUNvcnBvcmF0ZVRheFNlcnZpY2UnO1xuaW1wb3J0IHsgQnJlYWtkb3duIH0gZnJvbSAnLi4vZG9tYWluL3R5cGVzJztcblxuZXhwb3J0IGNsYXNzIENhbmFkYUNvcnBvcmF0ZVRheFNlcnZpY2VJbXBsIGltcGxlbWVudHMgQ2FuYWRhQ29ycG9yYXRlVGF4U2VydmljZSB7XG4gICAgcHJpdmF0ZSBfaW5wdXQ6IElucHV0O1xuICAgIHByaXZhdGUgX3J1bGVzOiBSdWxlcztcblxuICAgIGNvbnN0cnVjdG9yKGlucHV0OiBJbnB1dCwgcnVsZXM6IFJ1bGVzKSB7XG4gICAgICAgIHRoaXMuX2lucHV0ID0gaW5wdXQ7XG4gICAgICAgIHRoaXMuX3J1bGVzID0gcnVsZXM7XG4gICAgfVxuXG4gICAgY2FsY3VsYXRlKCk6IFJlc3VsdCB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuYXBwbHlSdWxlcyh0aGlzLl9ydWxlcywgdGhpcy5faW5wdXQpO1xuXG4gICAgICAgIGNvbnN0IHRvdGFsVGF4ID0gcmVzdWx0LnRheDtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29ycG9yYXRlVGF4OiB0b3RhbFRheCxcbiAgICAgICAgICAgIGVmZmVjdGl2ZVRheFJhdGU6XG4gICAgICAgICAgICAgICAgdGhpcy5faW5wdXQudGF4YWJsZUluY29tZSA+IDBcbiAgICAgICAgICAgICAgICAgICAgPyAodG90YWxUYXggLyB0aGlzLl9pbnB1dC50YXhhYmxlSW5jb21lKSAqIDEwMFxuICAgICAgICAgICAgICAgICAgICA6IDAsXG4gICAgICAgICAgICBicmVha2Rvd25zOiByZXN1bHQuYnJlYWtkb3ducyxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFwcGx5UnVsZXMocnVsZXM6IFJ1bGVzLCBpbnB1dDogSW5wdXQpOiB7IHRheDogbnVtYmVyOyBicmVha2Rvd25zOiBCcmVha2Rvd25bXSB9IHtcbiAgICAgICAgY29uc3QgcmVnaW1lID0gaW5wdXQuaXNTbWFsbEJ1c2luZXNzXG4gICAgICAgICAgICA/IHJ1bGVzLnJlZ2ltZXMuc21hbGxCdXNpbmVzc1xuICAgICAgICAgICAgOiBydWxlcy5yZWdpbWVzLmdlbmVyYWw7XG5cbiAgICAgICAgaWYgKHJlZ2ltZS50eXBlID09PSAnZmxhdCcpIHtcbiAgICAgICAgICAgIGNvbnN0IHRheCA9IGlucHV0LnRheGFibGVJbmNvbWUgKiByZWdpbWUucmF0ZTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdGF4LFxuICAgICAgICAgICAgICAgIGJyZWFrZG93bnM6IFt7IGZyb206ICcwJywgdG86ICdBYm92ZScsIHJhdGU6IHJlZ2ltZS5yYXRlLCBhbW91bnQ6IHRheCB9XSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmVnaW1lLnR5cGUgPT09ICdwcm9ncmVzc2l2ZScpIHtcbiAgICAgICAgICAgIGxldCByZW1haW5pbmcgPSBpbnB1dC50YXhhYmxlSW5jb21lO1xuICAgICAgICAgICAgbGV0IHRheCA9IDA7XG4gICAgICAgICAgICBjb25zdCBicmVha2Rvd25zOiBCcmVha2Rvd25bXSA9IFtdO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGJyYWNrZXQgb2YgcmVnaW1lLmJyYWNrZXRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlbWFpbmluZyA8PSAwKSBicmVhaztcblxuICAgICAgICAgICAgICAgIGNvbnN0IHVwcGVyID0gYnJhY2tldC50byA/PyBJbmZpbml0eTtcbiAgICAgICAgICAgICAgICBjb25zdCB0YXhhYmxlID0gTWF0aC5taW4odXBwZXIgLSBicmFja2V0LmZyb20sIHJlbWFpbmluZyk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBicmFja2V0VGF4ID0gdGF4YWJsZSAqIGJyYWNrZXQucmF0ZTtcbiAgICAgICAgICAgICAgICB0YXggKz0gYnJhY2tldFRheDtcbiAgICAgICAgICAgICAgICByZW1haW5pbmcgLT0gdGF4YWJsZTtcblxuICAgICAgICAgICAgICAgIGJyZWFrZG93bnMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGAke2JyYWNrZXQuZnJvbX1gLFxuICAgICAgICAgICAgICAgICAgICB0bzogYCR7YnJhY2tldC50byA/PyAnQWJvdmUnfWAsXG4gICAgICAgICAgICAgICAgICAgIHJhdGU6IGJyYWNrZXQucmF0ZSxcbiAgICAgICAgICAgICAgICAgICAgYW1vdW50OiBicmFja2V0VGF4LFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4geyB0YXgsIGJyZWFrZG93bnMgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVW5zdXBwb3J0ZWQgcmVnaW1lIHR5cGUnKTtcbiAgICB9XG59Il19
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29ycG9yYXRlL2NhbmFkYS9kb21haW4vdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJyZWFrZG93biB9IGZyb20gXCIuLi8uLi9kb21haW4vdHlwZXNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBSZWdpbWVJdGVtIHtcbiAgICB0eXBlOiAnZmxhdCcgfCAncHJvZ3Jlc3NpdmUnO1xuICAgIHJhdGU6IG51bWJlcjtcbiAgICBtYXhJbmNvbWU/OiBudW1iZXI7XG4gICAgYnJhY2tldHM/OiBQcm9ncmVzc2l2ZVRheEJyYWNrZXRbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZWdpbWUge1xuICAgIGdlbmVyYWw6IFJlZ2ltZUl0ZW1bXTtcbiAgICBzbWFsbEJ1c2luZXNzOiBSZWdpbWVJdGVtW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5wdXQge1xuXHR0YXhhYmxlSW5jb21lOiBudW1iZXI7XG4gICAgaXNTbWFsbEJ1c2luZXNzOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE91dHB1dCB7XG5cdG5hbWU6IHN0cmluZztcblx0dHlwZTogJ251bWJlcicgfCAnc3RyaW5nJztcblx0dW5pdD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGbGF0VGF4UnVsZSB7XG5cdHR5cGU6ICdmbGF0Jztcblx0cmF0ZTogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFByb2dyZXNzaXZlVGF4QnJhY2tldCB7XG5cdGZyb206IG51bWJlcjtcblx0dG86IG51bWJlciB8IG51bGw7XG5cdHJhdGU6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcm9ncmVzc2l2ZVRheFJ1bGUge1xuXHR0eXBlOiAncHJvZ3Jlc3NpdmUnO1xuXHRicmFja2V0czogUHJvZ3Jlc3NpdmVUYXhCcmFja2V0W107XG5cdGVsaWdpYmlsaXR5PzogUmVjb3JkPHN0cmluZywgYW55Pjtcbn1cblxuZXhwb3J0IHR5cGUgVGF4UnVsZSA9IEZsYXRUYXhSdWxlIHwgUHJvZ3Jlc3NpdmVUYXhSdWxlO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJ1bGVzIHtcbiAgXHRyZWdpbWVzOiBSZWNvcmQ8c3RyaW5nLCBUYXhSdWxlPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXN1bHQge1xuXHRjb3Jwb3JhdGVUYXg6IG51bWJlcjtcblx0ZWZmZWN0aXZlVGF4UmF0ZTogbnVtYmVyO1xuXHRicmVha2Rvd25zOiBCcmVha2Rvd25bXTtcbn1cblxuIl19
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29ycG9yYXRlL2RvbWFpbi90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGludGVyZmFjZSBCcmVha2Rvd24ge1xuICAgIGZyb206IHN0cmluZztcbiAgICB0bzogc3RyaW5nO1xuICAgIHJhdGU6IG51bWJlcjtcbiAgICBhbW91bnQ6IG51bWJlcjtcbn0iXX0=
|
|
@@ -14,7 +14,7 @@ class FranceCorporateTaxServiceImpl {
|
|
|
14
14
|
effectiveTaxRate: this._input.taxableIncome > 0
|
|
15
15
|
? (totalTax / this._input.taxableIncome) * 100
|
|
16
16
|
: 0,
|
|
17
|
-
|
|
17
|
+
breakdowns: result.breakdowns,
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
applyRules(rules, input) {
|
|
@@ -30,13 +30,18 @@ class FranceCorporateTaxServiceImpl {
|
|
|
30
30
|
const tax = input.taxableIncome * regime.rate;
|
|
31
31
|
return {
|
|
32
32
|
tax,
|
|
33
|
-
|
|
33
|
+
breakdowns: [{
|
|
34
|
+
from: '0',
|
|
35
|
+
to: 'Above',
|
|
36
|
+
rate: regime.rate,
|
|
37
|
+
amount: tax
|
|
38
|
+
}]
|
|
34
39
|
};
|
|
35
40
|
}
|
|
36
41
|
if (regime.type === 'progressive') {
|
|
37
42
|
let remaining = input.taxableIncome;
|
|
38
43
|
let tax = 0;
|
|
39
|
-
const
|
|
44
|
+
const breakdowns = [];
|
|
40
45
|
for (const bracket of regime.brackets) {
|
|
41
46
|
if (remaining <= 0)
|
|
42
47
|
break;
|
|
@@ -45,15 +50,17 @@ class FranceCorporateTaxServiceImpl {
|
|
|
45
50
|
const bracketTax = taxable * bracket.rate;
|
|
46
51
|
tax += bracketTax;
|
|
47
52
|
remaining -= taxable;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
:
|
|
51
|
-
|
|
53
|
+
breakdowns.push({
|
|
54
|
+
from: `${bracket.from}`,
|
|
55
|
+
to: `${bracket.to ?? 'Above'}`,
|
|
56
|
+
rate: bracket.rate,
|
|
57
|
+
amount: bracketTax,
|
|
58
|
+
});
|
|
52
59
|
}
|
|
53
|
-
return { tax,
|
|
60
|
+
return { tax, breakdowns };
|
|
54
61
|
}
|
|
55
62
|
throw new Error('Unsupported regime type');
|
|
56
63
|
}
|
|
57
64
|
}
|
|
58
65
|
exports.FranceCorporateTaxServiceImpl = FranceCorporateTaxServiceImpl;
|
|
59
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
66
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRnJhbmNlQ29ycG9yYXRlVGF4U2VydmljZUltcGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29ycG9yYXRlL2ZyYW5jZS9GcmFuY2VDb3Jwb3JhdGVUYXhTZXJ2aWNlSW1wbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFJQSxNQUFhLDZCQUE2QjtJQUl0QyxZQUFZLEtBQVksRUFBRSxLQUFZO1FBQ2xDLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO0lBQ3hCLENBQUM7SUFFRCxTQUFTO1FBQ0wsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUV6RCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDO1FBRTVCLE9BQU87WUFDSCxZQUFZLEVBQUUsUUFBUTtZQUN0QixnQkFBZ0IsRUFDWixJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsR0FBRyxDQUFDO2dCQUN6QixDQUFDLENBQUMsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsR0FBRyxHQUFHO2dCQUM5QyxDQUFDLENBQUMsQ0FBQztZQUNYLFVBQVUsRUFBRSxNQUFNLENBQUMsVUFBVTtTQUNoQyxDQUFDO0lBQ04sQ0FBQztJQUVPLFVBQVUsQ0FBQyxLQUFZLEVBQUUsS0FBWTtRQUN6QyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsZUFBZTtZQUNoQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxhQUFhO1lBQzdCLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztRQUU1QixJQUFJLE1BQU0sQ0FBQyxVQUFVLEVBQUUsV0FBVyxFQUFFLENBQUM7WUFDakMsSUFBSSxLQUFLLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQ3ZELE1BQU0sSUFBSSxLQUFLLENBQUMsOENBQThDLENBQUMsQ0FBQztZQUNwRSxDQUFDO1FBQ0wsQ0FBQztRQUVELElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUN6QixNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsYUFBYSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUM7WUFDOUMsT0FBTztnQkFDSCxHQUFHO2dCQUNILFVBQVUsRUFBQyxDQUFDO3dCQUNSLElBQUksRUFBRSxHQUFHO3dCQUNULEVBQUUsRUFBRSxPQUFPO3dCQUNYLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTt3QkFDakIsTUFBTSxFQUFFLEdBQUc7cUJBQ2QsQ0FBQzthQUNMLENBQUM7UUFDTixDQUFDO1FBRUQsSUFBSSxNQUFNLENBQUMsSUFBSSxLQUFLLGFBQWEsRUFBRSxDQUFDO1lBQ2hDLElBQUksU0FBUyxHQUFHLEtBQUssQ0FBQyxhQUFhLENBQUM7WUFDcEMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDO1lBQ1osTUFBTSxVQUFVLEdBQWdCLEVBQUUsQ0FBQztZQUVuQyxLQUFLLE1BQU0sT0FBTyxJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDcEMsSUFBSSxTQUFTLElBQUksQ0FBQztvQkFBRSxNQUFNO2dCQUUxQixNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsRUFBRSxJQUFJLFFBQVEsQ0FBQztnQkFDckMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztnQkFFMUQsTUFBTSxVQUFVLEdBQUcsT0FBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7Z0JBQzFDLEdBQUcsSUFBSSxVQUFVLENBQUM7Z0JBQ2xCLFNBQVMsSUFBSSxPQUFPLENBQUM7Z0JBRXJCLFVBQVUsQ0FBQyxJQUFJLENBQUM7b0JBQ1osSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLElBQUksRUFBRTtvQkFDdkIsRUFBRSxFQUFFLEdBQUcsT0FBTyxDQUFDLEVBQUUsSUFBSSxPQUFPLEVBQUU7b0JBQzlCLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDbEIsTUFBTSxFQUFFLFVBQVU7aUJBQ3JCLENBQUMsQ0FBQztZQUNQLENBQUM7WUFFRCxPQUFPLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxDQUFDO1FBQy9CLENBQUM7UUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLHlCQUF5QixDQUFDLENBQUM7SUFDL0MsQ0FBQztDQUNKO0FBNUVELHNFQTRFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJyZWFrZG93biB9IGZyb20gJy4uL2RvbWFpbi90eXBlcyc7XG5pbXBvcnQgeyBSdWxlcywgSW5wdXQsIFJlc3VsdCwgUHJvZ3Jlc3NpdmVUYXhCcmFja2V0IH0gZnJvbSAnLi9kb21haW4vdHlwZXMnO1xuaW1wb3J0IHsgRnJhbmNlQ29ycG9yYXRlVGF4U2VydmljZSB9IGZyb20gJy4vRnJhbmNlQ29ycG9yYXRlVGF4U2VydmljZSc7XG5cbmV4cG9ydCBjbGFzcyBGcmFuY2VDb3Jwb3JhdGVUYXhTZXJ2aWNlSW1wbCBpbXBsZW1lbnRzIEZyYW5jZUNvcnBvcmF0ZVRheFNlcnZpY2Uge1xuICAgIHByaXZhdGUgX2lucHV0OiBJbnB1dDtcbiAgICBwcml2YXRlIF9ydWxlczogUnVsZXM7XG5cbiAgICBjb25zdHJ1Y3RvcihpbnB1dDogSW5wdXQsIHJ1bGVzOiBSdWxlcykge1xuICAgICAgICB0aGlzLl9pbnB1dCA9IGlucHV0O1xuICAgICAgICB0aGlzLl9ydWxlcyA9IHJ1bGVzO1xuICAgIH1cblxuICAgIGNhbGN1bGF0ZSgpOiBSZXN1bHQge1xuICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLmFwcGx5UnVsZXModGhpcy5fcnVsZXMsIHRoaXMuX2lucHV0KTtcblxuICAgICAgICBjb25zdCB0b3RhbFRheCA9IHJlc3VsdC50YXg7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNvcnBvcmF0ZVRheDogdG90YWxUYXgsXG4gICAgICAgICAgICBlZmZlY3RpdmVUYXhSYXRlOlxuICAgICAgICAgICAgICAgIHRoaXMuX2lucHV0LnRheGFibGVJbmNvbWUgPiAwXG4gICAgICAgICAgICAgICAgICAgID8gKHRvdGFsVGF4IC8gdGhpcy5faW5wdXQudGF4YWJsZUluY29tZSkgKiAxMDBcbiAgICAgICAgICAgICAgICAgICAgOiAwLFxuICAgICAgICAgICAgYnJlYWtkb3duczogcmVzdWx0LmJyZWFrZG93bnMsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhcHBseVJ1bGVzKHJ1bGVzOiBSdWxlcywgaW5wdXQ6IElucHV0KTogeyB0YXg6IG51bWJlcjsgYnJlYWtkb3duczogQnJlYWtkb3duW10gfSB7XG4gICAgICAgIGNvbnN0IHJlZ2ltZSA9IGlucHV0LmlzU21hbGxCdXNpbmVzc1xuICAgICAgICAgICAgPyBydWxlcy5yZWdpbWVzLnNtYWxsQnVzaW5lc3NcbiAgICAgICAgICAgIDogcnVsZXMucmVnaW1lcy5nZW5lcmFsO1xuXG4gICAgICAgIGlmIChyZWdpbWUuY29uZGl0aW9ucz8ubWF4VHVybm92ZXIpIHtcbiAgICAgICAgICAgIGlmIChpbnB1dC5hbm51YWxUdXJub3ZlciA+IHJlZ2ltZS5jb25kaXRpb25zLm1heFR1cm5vdmVyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTTUUgcmVnaW1lIG5vdCBhcHBsaWNhYmxlOiB0dXJub3ZlciBleGNlZWRlZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJlZ2ltZS50eXBlID09PSAnZmxhdCcpIHtcbiAgICAgICAgICAgIGNvbnN0IHRheCA9IGlucHV0LnRheGFibGVJbmNvbWUgKiByZWdpbWUucmF0ZTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdGF4LFxuICAgICAgICAgICAgICAgIGJyZWFrZG93bnM6W3tcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogJzAnLFxuICAgICAgICAgICAgICAgICAgICB0bzogJ0Fib3ZlJyxcbiAgICAgICAgICAgICAgICAgICAgcmF0ZTogcmVnaW1lLnJhdGUsXG4gICAgICAgICAgICAgICAgICAgIGFtb3VudDogdGF4XG4gICAgICAgICAgICAgICAgfV1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmVnaW1lLnR5cGUgPT09ICdwcm9ncmVzc2l2ZScpIHtcbiAgICAgICAgICAgIGxldCByZW1haW5pbmcgPSBpbnB1dC50YXhhYmxlSW5jb21lO1xuICAgICAgICAgICAgbGV0IHRheCA9IDA7XG4gICAgICAgICAgICBjb25zdCBicmVha2Rvd25zOiBCcmVha2Rvd25bXSA9IFtdO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGJyYWNrZXQgb2YgcmVnaW1lLmJyYWNrZXRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlbWFpbmluZyA8PSAwKSBicmVhaztcblxuICAgICAgICAgICAgICAgIGNvbnN0IHVwcGVyID0gYnJhY2tldC50byA/PyBJbmZpbml0eTtcbiAgICAgICAgICAgICAgICBjb25zdCB0YXhhYmxlID0gTWF0aC5taW4odXBwZXIgLSBicmFja2V0LmZyb20sIHJlbWFpbmluZyk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBicmFja2V0VGF4ID0gdGF4YWJsZSAqIGJyYWNrZXQucmF0ZTtcbiAgICAgICAgICAgICAgICB0YXggKz0gYnJhY2tldFRheDtcbiAgICAgICAgICAgICAgICByZW1haW5pbmcgLT0gdGF4YWJsZTtcblxuICAgICAgICAgICAgICAgIGJyZWFrZG93bnMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGAke2JyYWNrZXQuZnJvbX1gLFxuICAgICAgICAgICAgICAgICAgICB0bzogYCR7YnJhY2tldC50byA/PyAnQWJvdmUnfWAsXG4gICAgICAgICAgICAgICAgICAgIHJhdGU6IGJyYWNrZXQucmF0ZSxcbiAgICAgICAgICAgICAgICAgICAgYW1vdW50OiBicmFja2V0VGF4LFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4geyB0YXgsIGJyZWFrZG93bnMgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVW5zdXBwb3J0ZWQgcmVnaW1lIHR5cGUnKTtcbiAgICB9XG59Il19
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29ycG9yYXRlL2ZyYW5jZS9kb21haW4vdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJyZWFrZG93biB9IGZyb20gXCIuLi8uLi9kb21haW4vdHlwZXNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBSZWdpbWVDb25kaXRpb24ge1xuXHRtYXhUdXJub3ZlcjogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlZ2ltZUl0ZW0ge1xuICAgIHR5cGU6ICdmbGF0JyB8ICdwcm9ncmVzc2l2ZSc7XG4gICAgcmF0ZT86IG51bWJlcjtcbiAgICBtYXhJbmNvbWU/OiBudW1iZXI7XG4gICAgYnJhY2tldHM/OiBQcm9ncmVzc2l2ZVRheEJyYWNrZXRbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZWdpbWUge1xuICAgIGdlbmVyYWw6IFJlZ2ltZUl0ZW1bXTtcbiAgICBzbWFsbEJ1c2luZXNzOiBSZWdpbWVJdGVtW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5wdXQge1xuXHR0YXhhYmxlSW5jb21lOiBudW1iZXI7XG5cdGFubnVhbFR1cm5vdmVyOiBudW1iZXI7XG4gICAgaXNTbWFsbEJ1c2luZXNzOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE91dHB1dCB7XG5cdG5hbWU6IHN0cmluZztcblx0dHlwZTogJ251bWJlcicgfCAnc3RyaW5nJztcblx0dW5pdD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGbGF0VGF4UnVsZSB7XG5cdHR5cGU6ICdmbGF0Jztcblx0cmF0ZTogbnVtYmVyO1xuXHRjb25kaXRpb25zPzogUmVnaW1lQ29uZGl0aW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFByb2dyZXNzaXZlVGF4QnJhY2tldCB7XG5cdGZyb206IG51bWJlcjtcblx0dG86IG51bWJlciB8IG51bGw7XG5cdHJhdGU6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcm9ncmVzc2l2ZVRheFJ1bGUge1xuXHR0eXBlOiAncHJvZ3Jlc3NpdmUnO1xuXHRicmFja2V0czogUHJvZ3Jlc3NpdmVUYXhCcmFja2V0W107XG5cdGVsaWdpYmlsaXR5PzogUmVjb3JkPHN0cmluZywgYW55Pjtcblx0Y29uZGl0aW9ucz86IFJlZ2ltZUNvbmRpdGlvbjtcbn1cblxuZXhwb3J0IHR5cGUgVGF4UnVsZSA9IEZsYXRUYXhSdWxlIHwgUHJvZ3Jlc3NpdmVUYXhSdWxlO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJ1bGVzIHtcbiAgXHRyZWdpbWVzOiBSZWNvcmQ8c3RyaW5nLCBUYXhSdWxlPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXN1bHQge1xuXHRjb3Jwb3JhdGVUYXg6IG51bWJlcjtcblx0ZWZmZWN0aXZlVGF4UmF0ZTogbnVtYmVyO1xuXHRicmVha2Rvd25zOiBCcmVha2Rvd25bXTtcbn1cblxuIl19
|
|
@@ -12,29 +12,32 @@ class SouthAfricaCorporateTaxServiceImpl {
|
|
|
12
12
|
throw new Error(`Unknown tax regime: ${this._input.regime}`);
|
|
13
13
|
}
|
|
14
14
|
let tax = 0;
|
|
15
|
-
let
|
|
15
|
+
let breakdowns = [];
|
|
16
16
|
if (rule.type === 'flat') {
|
|
17
17
|
tax = this._input.taxableIncome * rule.rate;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
breakdowns = [{
|
|
19
|
+
from: '0',
|
|
20
|
+
to: 'Above',
|
|
21
|
+
rate: rule.rate,
|
|
22
|
+
amount: tax
|
|
23
|
+
}];
|
|
21
24
|
}
|
|
22
25
|
if (rule.type === 'progressive') {
|
|
23
26
|
const result = this.calculateProgressiveTax(this._input.taxableIncome, rule.brackets);
|
|
24
27
|
tax = result.total;
|
|
25
|
-
|
|
28
|
+
breakdowns = result.breakdowns;
|
|
26
29
|
}
|
|
27
30
|
return {
|
|
28
31
|
corporateTax: tax,
|
|
29
32
|
effectiveTaxRate: this._input.taxableIncome > 0
|
|
30
33
|
? (tax / this._input.taxableIncome) * 100
|
|
31
34
|
: 0,
|
|
32
|
-
|
|
35
|
+
breakdowns,
|
|
33
36
|
};
|
|
34
37
|
}
|
|
35
38
|
calculateProgressiveTax(income, brackets) {
|
|
36
39
|
let tax = 0;
|
|
37
|
-
const
|
|
40
|
+
const breakdowns = [];
|
|
38
41
|
for (const bracket of brackets) {
|
|
39
42
|
if (income <= bracket.from)
|
|
40
43
|
continue;
|
|
@@ -43,14 +46,16 @@ class SouthAfricaCorporateTaxServiceImpl {
|
|
|
43
46
|
if (taxableAmount > 0) {
|
|
44
47
|
const bracketTax = taxableAmount * bracket.rate;
|
|
45
48
|
tax += bracketTax;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
:
|
|
49
|
-
|
|
49
|
+
breakdowns.push({
|
|
50
|
+
from: `${bracket.from}`,
|
|
51
|
+
to: `${bracket.to ?? 'Above'}`,
|
|
52
|
+
rate: bracket.rate,
|
|
53
|
+
amount: bracketTax,
|
|
54
|
+
});
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
|
-
return { total: tax,
|
|
57
|
+
return { total: tax, breakdowns };
|
|
53
58
|
}
|
|
54
59
|
}
|
|
55
60
|
exports.SouthAfricaCorporateTaxServiceImpl = SouthAfricaCorporateTaxServiceImpl;
|
|
56
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
61
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU291dGhBZnJpY2FDb3Jwb3JhdGVUYXhTZXJ2aWNlSW1wbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb3Jwb3JhdGUvc291dGgtYWZyaWNhL1NvdXRoQWZyaWNhQ29ycG9yYXRlVGF4U2VydmljZUltcGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUEsTUFBYSxrQ0FBa0M7SUFJM0MsWUFBWSxLQUFZLEVBQUUsS0FBWTtRQUNsQyxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztRQUNwQixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztJQUN4QixDQUFDO0lBRUQsU0FBUztRQUNMLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFckQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1IsTUFBTSxJQUFJLEtBQUssQ0FBQyx1QkFBdUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7UUFFRCxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDWixJQUFJLFVBQVUsR0FBZ0IsRUFBRSxDQUFDO1FBRWpDLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUN2QixHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztZQUM1QyxVQUFVLEdBQUcsQ0FBQztvQkFDVixJQUFJLEVBQUUsR0FBRztvQkFDVCxFQUFFLEVBQUUsT0FBTztvQkFDWCxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUk7b0JBQ2YsTUFBTSxFQUFFLEdBQUc7aUJBQ2QsQ0FBQyxDQUFDO1FBQ1AsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxhQUFhLEVBQUUsQ0FBQztZQUM5QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsdUJBQXVCLENBQ3ZDLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUN6QixJQUFJLENBQUMsUUFBUSxDQUNoQixDQUFDO1lBQ0YsR0FBRyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7WUFDbkIsVUFBVSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUM7UUFDbkMsQ0FBQztRQUVELE9BQU87WUFDSCxZQUFZLEVBQUUsR0FBRztZQUNqQixnQkFBZ0IsRUFDaEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEdBQUcsQ0FBQztnQkFDekIsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEdBQUcsR0FBRztnQkFDekMsQ0FBQyxDQUFDLENBQUM7WUFDUCxVQUFVO1NBQ2IsQ0FBQztJQUNOLENBQUM7SUFFTyx1QkFBdUIsQ0FBQyxNQUFjLEVBQUUsUUFBaUM7UUFDN0UsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBQ1osTUFBTSxVQUFVLEdBQWdCLEVBQUUsQ0FBQztRQUVuQyxLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQzdCLElBQUksTUFBTSxJQUFJLE9BQU8sQ0FBQyxJQUFJO2dCQUFFLFNBQVM7WUFFckMsTUFBTSxVQUFVLEdBQ2hCLE9BQU8sQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUU1RCxNQUFNLGFBQWEsR0FBRyxVQUFVLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztZQUVoRCxJQUFJLGFBQWEsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDcEIsTUFBTSxVQUFVLEdBQUcsYUFBYSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7Z0JBQ2hELEdBQUcsSUFBSSxVQUFVLENBQUM7Z0JBRWxCLFVBQVUsQ0FBQyxJQUFJLENBQUM7b0JBQ1osSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLElBQUksRUFBRTtvQkFDdkIsRUFBRSxFQUFFLEdBQUcsT0FBTyxDQUFDLEVBQUUsSUFBSSxPQUFPLEVBQUU7b0JBQzlCLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDbEIsTUFBTSxFQUFFLFVBQVU7aUJBQ3JCLENBQUMsQ0FBQztZQUNQLENBQUM7UUFDTCxDQUFDO1FBRUQsT0FBTyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLENBQUM7SUFDdEMsQ0FBQztDQUNKO0FBM0VELGdGQTJFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJyZWFrZG93biB9IGZyb20gJy4uL2RvbWFpbi90eXBlcyc7XG5pbXBvcnQgeyBSdWxlcywgSW5wdXQsIFJlc3VsdCwgUHJvZ3Jlc3NpdmVUYXhCcmFja2V0IH0gZnJvbSAnLi9kb21haW4vdHlwZXMnO1xuaW1wb3J0IHsgU291dGhBZnJpY2FDb3Jwb3JhdGVUYXhTZXJ2aWNlIH0gZnJvbSAnLi9Tb3V0aEFmcmljYUNvcnBvcmF0ZVRheFNlcnZpY2UnO1xuXG5leHBvcnQgY2xhc3MgU291dGhBZnJpY2FDb3Jwb3JhdGVUYXhTZXJ2aWNlSW1wbCBpbXBsZW1lbnRzIFNvdXRoQWZyaWNhQ29ycG9yYXRlVGF4U2VydmljZSB7XG4gICAgcHJpdmF0ZSBfaW5wdXQ6IElucHV0O1xuICAgIHByaXZhdGUgX3J1bGVzOiBSdWxlcztcblxuICAgIGNvbnN0cnVjdG9yKGlucHV0OiBJbnB1dCwgcnVsZXM6IFJ1bGVzKSB7XG4gICAgICAgIHRoaXMuX2lucHV0ID0gaW5wdXQ7XG4gICAgICAgIHRoaXMuX3J1bGVzID0gcnVsZXM7XG4gICAgfVxuXG4gICAgY2FsY3VsYXRlKCk6IFJlc3VsdCB7XG4gICAgICAgIGNvbnN0IHJ1bGUgPSB0aGlzLl9ydWxlcy5yZWdpbWVzW3RoaXMuX2lucHV0LnJlZ2ltZV07XG5cbiAgICAgICAgaWYgKCFydWxlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdGF4IHJlZ2ltZTogJHt0aGlzLl9pbnB1dC5yZWdpbWV9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgdGF4ID0gMDtcbiAgICAgICAgbGV0IGJyZWFrZG93bnM6IEJyZWFrZG93bltdID0gW107XG5cbiAgICAgICAgaWYgKHJ1bGUudHlwZSA9PT0gJ2ZsYXQnKSB7XG4gICAgICAgICAgICB0YXggPSB0aGlzLl9pbnB1dC50YXhhYmxlSW5jb21lICogcnVsZS5yYXRlO1xuICAgICAgICAgICAgYnJlYWtkb3ducyA9IFt7XG4gICAgICAgICAgICAgICAgZnJvbTogJzAnLFxuICAgICAgICAgICAgICAgIHRvOiAnQWJvdmUnLFxuICAgICAgICAgICAgICAgIHJhdGU6IHJ1bGUucmF0ZSxcbiAgICAgICAgICAgICAgICBhbW91bnQ6IHRheFxuICAgICAgICAgICAgfV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocnVsZS50eXBlID09PSAncHJvZ3Jlc3NpdmUnKSB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLmNhbGN1bGF0ZVByb2dyZXNzaXZlVGF4KFxuICAgICAgICAgICAgICAgIHRoaXMuX2lucHV0LnRheGFibGVJbmNvbWUsXG4gICAgICAgICAgICAgICAgcnVsZS5icmFja2V0c1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRheCA9IHJlc3VsdC50b3RhbDtcbiAgICAgICAgICAgIGJyZWFrZG93bnMgPSByZXN1bHQuYnJlYWtkb3ducztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb3Jwb3JhdGVUYXg6IHRheCxcbiAgICAgICAgICAgIGVmZmVjdGl2ZVRheFJhdGU6XG4gICAgICAgICAgICB0aGlzLl9pbnB1dC50YXhhYmxlSW5jb21lID4gMFxuICAgICAgICAgICAgICAgID8gKHRheCAvIHRoaXMuX2lucHV0LnRheGFibGVJbmNvbWUpICogMTAwXG4gICAgICAgICAgICAgICAgOiAwLFxuICAgICAgICAgICAgYnJlYWtkb3ducyxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNhbGN1bGF0ZVByb2dyZXNzaXZlVGF4KGluY29tZTogbnVtYmVyLCBicmFja2V0czogUHJvZ3Jlc3NpdmVUYXhCcmFja2V0W10pOiB7IHRvdGFsOiBudW1iZXI7IGJyZWFrZG93bnM6IEJyZWFrZG93bltdIH0ge1xuICAgICAgICBsZXQgdGF4ID0gMDtcbiAgICAgICAgY29uc3QgYnJlYWtkb3duczogQnJlYWtkb3duW10gPSBbXTtcblxuICAgICAgICBmb3IgKGNvbnN0IGJyYWNrZXQgb2YgYnJhY2tldHMpIHtcbiAgICAgICAgICAgIGlmIChpbmNvbWUgPD0gYnJhY2tldC5mcm9tKSBjb250aW51ZTtcblxuICAgICAgICAgICAgY29uc3QgdXBwZXJMaW1pdCA9XG4gICAgICAgICAgICBicmFja2V0LnRvID09PSBudWxsID8gaW5jb21lIDogTWF0aC5taW4oaW5jb21lLCBicmFja2V0LnRvKTtcblxuICAgICAgICAgICAgY29uc3QgdGF4YWJsZUFtb3VudCA9IHVwcGVyTGltaXQgLSBicmFja2V0LmZyb207XG5cbiAgICAgICAgICAgIGlmICh0YXhhYmxlQW1vdW50ID4gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJyYWNrZXRUYXggPSB0YXhhYmxlQW1vdW50ICogYnJhY2tldC5yYXRlO1xuICAgICAgICAgICAgICAgIHRheCArPSBicmFja2V0VGF4O1xuXG4gICAgICAgICAgICAgICAgYnJlYWtkb3ducy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogYCR7YnJhY2tldC5mcm9tfWAsXG4gICAgICAgICAgICAgICAgICAgIHRvOiBgJHticmFja2V0LnRvID8/ICdBYm92ZSd9YCxcbiAgICAgICAgICAgICAgICAgICAgcmF0ZTogYnJhY2tldC5yYXRlLFxuICAgICAgICAgICAgICAgICAgICBhbW91bnQ6IGJyYWNrZXRUYXgsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4geyB0b3RhbDogdGF4LCBicmVha2Rvd25zIH07XG4gICAgfVxufSAiXX0=
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29ycG9yYXRlL3NvdXRoLWFmcmljYS9kb21haW4vdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJyZWFrZG93biB9IGZyb20gXCIuLi8uLi9kb21haW4vdHlwZXNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBJbnB1dCB7XG5cdHRheGFibGVJbmNvbWU6IG51bWJlcjtcbiAgICByZWdpbWU6ICdMQVJHRScgfCAnU0JDJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPdXRwdXQge1xuXHRuYW1lOiBzdHJpbmc7XG5cdHR5cGU6ICdudW1iZXInIHwgJ3N0cmluZyc7XG5cdHVuaXQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmxhdFRheFJ1bGUge1xuXHR0eXBlOiAnZmxhdCc7XG5cdHJhdGU6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcm9ncmVzc2l2ZVRheEJyYWNrZXQge1xuXHRmcm9tOiBudW1iZXI7XG5cdHRvOiBudW1iZXIgfCBudWxsO1xuXHRyYXRlOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHJvZ3Jlc3NpdmVUYXhSdWxlIHtcblx0dHlwZTogJ3Byb2dyZXNzaXZlJztcblx0YnJhY2tldHM6IFByb2dyZXNzaXZlVGF4QnJhY2tldFtdO1xuXHRlbGlnaWJpbGl0eT86IFJlY29yZDxzdHJpbmcsIGFueT47XG59XG5cbmV4cG9ydCB0eXBlIFRheFJ1bGUgPSBGbGF0VGF4UnVsZSB8IFByb2dyZXNzaXZlVGF4UnVsZTtcblxuZXhwb3J0IGludGVyZmFjZSBSdWxlcyB7XG4gIFx0cmVnaW1lczogUmVjb3JkPHN0cmluZywgVGF4UnVsZT47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzdWx0IHtcblx0Y29ycG9yYXRlVGF4OiBudW1iZXI7XG5cdGVmZmVjdGl2ZVRheFJhdGU6IG51bWJlcjtcblx0YnJlYWtkb3duczogQnJlYWtkb3duW107XG59XG5cbiJdfQ==
|
|
@@ -6,5 +6,6 @@ var CalculatorType;
|
|
|
6
6
|
CalculatorType["INCOME_TAX"] = "INCOME_TAX";
|
|
7
7
|
CalculatorType["MORTGAGE"] = "MORTGAGE";
|
|
8
8
|
CalculatorType["LOAN"] = "LOAN";
|
|
9
|
+
CalculatorType["CORPORATE_TAX"] = "CORPORATE_TAX";
|
|
9
10
|
})(CalculatorType || (exports.CalculatorType = CalculatorType = {}));
|
|
10
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
11
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2hhcmVkL2RvbWFpbi90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxJQUFZLGNBS1g7QUFMRCxXQUFZLGNBQWM7SUFDdEIsMkNBQXlCLENBQUE7SUFDekIsdUNBQXFCLENBQUE7SUFDckIsK0JBQWEsQ0FBQTtJQUNiLGlEQUErQixDQUFBO0FBQ25DLENBQUMsRUFMVyxjQUFjLDhCQUFkLGNBQWMsUUFLekIiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZW51bSBDYWxjdWxhdG9yVHlwZSB7XG4gICAgSU5DT01FX1RBWCA9ICdJTkNPTUVfVEFYJyxcbiAgICBNT1JUR0FHRSA9ICdNT1JUR0FHRScsXG4gICAgTE9BTiA9ICdMT0FOJyxcbiAgICBDT1JQT1JBVEVfVEFYID0gJ0NPUlBPUkFURV9UQVgnLFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJ1bGVNZXRhIHtcbiAgICBpZDogc3RyaW5nO1xuICAgIGNvdW50cnk6IHN0cmluZztcbiAgICByZWdpb246IHN0cmluZztcbiAgICBjYWxjdWxhdG9yOiBDYWxjdWxhdG9yVHlwZTtcbiAgICB2ZXJzaW9uOiBzdHJpbmc7XG4gICAgZWZmZWN0aXZlZnJvbTogc3RyaW5nO1xuICAgIGVmZmVjdGl2ZXRvOiBzdHJpbmcgfCBudWxsO1xuICAgIHNvdXJjZT86IFJ1bGVTb3VyY2VbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSdWxlU291cmNlIHtcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgdXJsOiBzdHJpbmc7XG59Il19
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Breakdown } from "../../domain/types";
|
|
1
2
|
export interface RegimeItem {
|
|
2
3
|
type: 'flat' | 'progressive';
|
|
3
4
|
rate: number;
|
|
@@ -38,5 +39,5 @@ export interface Rules {
|
|
|
38
39
|
export interface Result {
|
|
39
40
|
corporateTax: number;
|
|
40
41
|
effectiveTaxRate: number;
|
|
41
|
-
|
|
42
|
+
breakdowns: Breakdown[];
|
|
42
43
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Breakdown } from "../../domain/types";
|
|
1
2
|
export interface RegimeCondition {
|
|
2
3
|
maxTurnover: number;
|
|
3
4
|
}
|
|
@@ -44,5 +45,5 @@ export interface Rules {
|
|
|
44
45
|
export interface Result {
|
|
45
46
|
corporateTax: number;
|
|
46
47
|
effectiveTaxRate: number;
|
|
47
|
-
|
|
48
|
+
breakdowns: Breakdown[];
|
|
48
49
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Breakdown } from "../../domain/types";
|
|
1
2
|
export interface Input {
|
|
2
3
|
taxableIncome: number;
|
|
3
4
|
regime: 'LARGE' | 'SBC';
|
|
@@ -28,5 +29,5 @@ export interface Rules {
|
|
|
28
29
|
export interface Result {
|
|
29
30
|
corporateTax: number;
|
|
30
31
|
effectiveTaxRate: number;
|
|
31
|
-
|
|
32
|
+
breakdowns: Breakdown[];
|
|
32
33
|
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Rules, Input, Result, ProgressiveTaxBracket } from './domain/types';
|
|
2
2
|
import { CanadaCorporateTaxService } from './CanadaCorporateTaxService';
|
|
3
|
+
import { Breakdown } from '../domain/types';
|
|
3
4
|
|
|
4
5
|
export class CanadaCorporateTaxServiceImpl implements CanadaCorporateTaxService {
|
|
5
6
|
private _input: Input;
|
|
@@ -21,11 +22,11 @@ export class CanadaCorporateTaxServiceImpl implements CanadaCorporateTaxService
|
|
|
21
22
|
this._input.taxableIncome > 0
|
|
22
23
|
? (totalTax / this._input.taxableIncome) * 100
|
|
23
24
|
: 0,
|
|
24
|
-
|
|
25
|
+
breakdowns: result.breakdowns,
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
private applyRules(rules: Rules, input: Input): { tax: number;
|
|
29
|
+
private applyRules(rules: Rules, input: Input): { tax: number; breakdowns: Breakdown[] } {
|
|
29
30
|
const regime = input.isSmallBusiness
|
|
30
31
|
? rules.regimes.smallBusiness
|
|
31
32
|
: rules.regimes.general;
|
|
@@ -34,14 +35,14 @@ export class CanadaCorporateTaxServiceImpl implements CanadaCorporateTaxService
|
|
|
34
35
|
const tax = input.taxableIncome * regime.rate;
|
|
35
36
|
return {
|
|
36
37
|
tax,
|
|
37
|
-
|
|
38
|
+
breakdowns: [{ from: '0', to: 'Above', rate: regime.rate, amount: tax }],
|
|
38
39
|
};
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
if (regime.type === 'progressive') {
|
|
42
43
|
let remaining = input.taxableIncome;
|
|
43
44
|
let tax = 0;
|
|
44
|
-
const
|
|
45
|
+
const breakdowns: Breakdown[] = [];
|
|
45
46
|
|
|
46
47
|
for (const bracket of regime.brackets) {
|
|
47
48
|
if (remaining <= 0) break;
|
|
@@ -53,13 +54,15 @@ export class CanadaCorporateTaxServiceImpl implements CanadaCorporateTaxService
|
|
|
53
54
|
tax += bracketTax;
|
|
54
55
|
remaining -= taxable;
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
:
|
|
59
|
-
|
|
57
|
+
breakdowns.push({
|
|
58
|
+
from: `${bracket.from}`,
|
|
59
|
+
to: `${bracket.to ?? 'Above'}`,
|
|
60
|
+
rate: bracket.rate,
|
|
61
|
+
amount: bracketTax,
|
|
62
|
+
});
|
|
60
63
|
}
|
|
61
64
|
|
|
62
|
-
return { tax,
|
|
65
|
+
return { tax, breakdowns };
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
throw new Error('Unsupported regime type');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { Breakdown } from "../../domain/types";
|
|
2
2
|
|
|
3
3
|
export interface RegimeItem {
|
|
4
4
|
type: 'flat' | 'progressive';
|
|
@@ -49,6 +49,6 @@ export interface Rules {
|
|
|
49
49
|
export interface Result {
|
|
50
50
|
corporateTax: number;
|
|
51
51
|
effectiveTaxRate: number;
|
|
52
|
-
|
|
52
|
+
breakdowns: Breakdown[];
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Breakdown } from '../domain/types';
|
|
1
2
|
import { Rules, Input, Result, ProgressiveTaxBracket } from './domain/types';
|
|
2
3
|
import { FranceCorporateTaxService } from './FranceCorporateTaxService';
|
|
3
4
|
|
|
@@ -21,11 +22,11 @@ export class FranceCorporateTaxServiceImpl implements FranceCorporateTaxService
|
|
|
21
22
|
this._input.taxableIncome > 0
|
|
22
23
|
? (totalTax / this._input.taxableIncome) * 100
|
|
23
24
|
: 0,
|
|
24
|
-
|
|
25
|
+
breakdowns: result.breakdowns,
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
private applyRules(rules: Rules, input: Input): { tax: number;
|
|
29
|
+
private applyRules(rules: Rules, input: Input): { tax: number; breakdowns: Breakdown[] } {
|
|
29
30
|
const regime = input.isSmallBusiness
|
|
30
31
|
? rules.regimes.smallBusiness
|
|
31
32
|
: rules.regimes.general;
|
|
@@ -40,14 +41,19 @@ export class FranceCorporateTaxServiceImpl implements FranceCorporateTaxService
|
|
|
40
41
|
const tax = input.taxableIncome * regime.rate;
|
|
41
42
|
return {
|
|
42
43
|
tax,
|
|
43
|
-
|
|
44
|
+
breakdowns:[{
|
|
45
|
+
from: '0',
|
|
46
|
+
to: 'Above',
|
|
47
|
+
rate: regime.rate,
|
|
48
|
+
amount: tax
|
|
49
|
+
}]
|
|
44
50
|
};
|
|
45
51
|
}
|
|
46
52
|
|
|
47
53
|
if (regime.type === 'progressive') {
|
|
48
54
|
let remaining = input.taxableIncome;
|
|
49
55
|
let tax = 0;
|
|
50
|
-
const
|
|
56
|
+
const breakdowns: Breakdown[] = [];
|
|
51
57
|
|
|
52
58
|
for (const bracket of regime.brackets) {
|
|
53
59
|
if (remaining <= 0) break;
|
|
@@ -59,13 +65,15 @@ export class FranceCorporateTaxServiceImpl implements FranceCorporateTaxService
|
|
|
59
65
|
tax += bracketTax;
|
|
60
66
|
remaining -= taxable;
|
|
61
67
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
:
|
|
65
|
-
|
|
68
|
+
breakdowns.push({
|
|
69
|
+
from: `${bracket.from}`,
|
|
70
|
+
to: `${bracket.to ?? 'Above'}`,
|
|
71
|
+
rate: bracket.rate,
|
|
72
|
+
amount: bracketTax,
|
|
73
|
+
});
|
|
66
74
|
}
|
|
67
75
|
|
|
68
|
-
return { tax,
|
|
76
|
+
return { tax, breakdowns };
|
|
69
77
|
}
|
|
70
78
|
|
|
71
79
|
throw new Error('Unsupported regime type');
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Breakdown } from "../../domain/types";
|
|
1
2
|
|
|
2
3
|
export interface RegimeCondition {
|
|
3
4
|
maxTurnover: number;
|
|
@@ -55,6 +56,6 @@ export interface Rules {
|
|
|
55
56
|
export interface Result {
|
|
56
57
|
corporateTax: number;
|
|
57
58
|
effectiveTaxRate: number;
|
|
58
|
-
|
|
59
|
+
breakdowns: Breakdown[];
|
|
59
60
|
}
|
|
60
61
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Breakdown } from '../domain/types';
|
|
1
2
|
import { Rules, Input, Result, ProgressiveTaxBracket } from './domain/types';
|
|
2
3
|
import { SouthAfricaCorporateTaxService } from './SouthAfricaCorporateTaxService';
|
|
3
4
|
|
|
@@ -18,13 +19,16 @@ export class SouthAfricaCorporateTaxServiceImpl implements SouthAfricaCorporateT
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
let tax = 0;
|
|
21
|
-
let
|
|
22
|
+
let breakdowns: Breakdown[] = [];
|
|
22
23
|
|
|
23
24
|
if (rule.type === 'flat') {
|
|
24
25
|
tax = this._input.taxableIncome * rule.rate;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
breakdowns = [{
|
|
27
|
+
from: '0',
|
|
28
|
+
to: 'Above',
|
|
29
|
+
rate: rule.rate,
|
|
30
|
+
amount: tax
|
|
31
|
+
}];
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
if (rule.type === 'progressive') {
|
|
@@ -33,7 +37,7 @@ export class SouthAfricaCorporateTaxServiceImpl implements SouthAfricaCorporateT
|
|
|
33
37
|
rule.brackets
|
|
34
38
|
);
|
|
35
39
|
tax = result.total;
|
|
36
|
-
|
|
40
|
+
breakdowns = result.breakdowns;
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
return {
|
|
@@ -42,13 +46,13 @@ export class SouthAfricaCorporateTaxServiceImpl implements SouthAfricaCorporateT
|
|
|
42
46
|
this._input.taxableIncome > 0
|
|
43
47
|
? (tax / this._input.taxableIncome) * 100
|
|
44
48
|
: 0,
|
|
45
|
-
|
|
49
|
+
breakdowns,
|
|
46
50
|
};
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
private calculateProgressiveTax(income: number, brackets: ProgressiveTaxBracket[]): { total: number;
|
|
53
|
+
private calculateProgressiveTax(income: number, brackets: ProgressiveTaxBracket[]): { total: number; breakdowns: Breakdown[] } {
|
|
50
54
|
let tax = 0;
|
|
51
|
-
const
|
|
55
|
+
const breakdowns: Breakdown[] = [];
|
|
52
56
|
|
|
53
57
|
for (const bracket of brackets) {
|
|
54
58
|
if (income <= bracket.from) continue;
|
|
@@ -61,14 +65,16 @@ export class SouthAfricaCorporateTaxServiceImpl implements SouthAfricaCorporateT
|
|
|
61
65
|
if (taxableAmount > 0) {
|
|
62
66
|
const bracketTax = taxableAmount * bracket.rate;
|
|
63
67
|
tax += bracketTax;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
:
|
|
68
|
-
|
|
68
|
+
|
|
69
|
+
breakdowns.push({
|
|
70
|
+
from: `${bracket.from}`,
|
|
71
|
+
to: `${bracket.to ?? 'Above'}`,
|
|
72
|
+
rate: bracket.rate,
|
|
73
|
+
amount: bracketTax,
|
|
74
|
+
});
|
|
69
75
|
}
|
|
70
76
|
}
|
|
71
77
|
|
|
72
|
-
return { total: tax,
|
|
78
|
+
return { total: tax, breakdowns };
|
|
73
79
|
}
|
|
74
80
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Breakdown } from "../../domain/types";
|
|
2
|
+
|
|
1
3
|
export interface Input {
|
|
2
4
|
taxableIncome: number;
|
|
3
5
|
regime: 'LARGE' | 'SBC';
|
|
@@ -35,6 +37,6 @@ export interface Rules {
|
|
|
35
37
|
export interface Result {
|
|
36
38
|
corporateTax: number;
|
|
37
39
|
effectiveTaxRate: number;
|
|
38
|
-
|
|
40
|
+
breakdowns: Breakdown[];
|
|
39
41
|
}
|
|
40
42
|
|