@novha/calc-engines 6.0.0 → 6.2.0
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/capital-gains/canada/CanadaCapitalGainsServiceImpl.js +17 -29
- package/dist/capital-gains/index.js +1 -1
- package/dist/types/capital-gains/canada/CanadaCapitalGainsServiceImpl.d.ts +1 -1
- package/dist/types/capital-gains/index.d.ts +2 -1
- package/package.json +1 -1
- package/src/capital-gains/canada/CanadaCapitalGainsServiceImpl.ts +21 -34
- package/src/capital-gains/index.ts +3 -1
|
@@ -20,47 +20,35 @@ class CanadaCapitalGainsServiceImpl {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
const taxableGain = gain * this._rules.inclusionRate;
|
|
23
|
-
|
|
24
|
-
const
|
|
23
|
+
// income BEFORE the capital gain
|
|
24
|
+
const baseIncome = this._input.totalTaxableIncome;
|
|
25
|
+
const incomeWithGain = baseIncome + taxableGain;
|
|
26
|
+
const baseTax = this.calculateProgressiveTax(baseIncome, this._rules.taxBrackets);
|
|
27
|
+
const taxWithGain = this.calculateProgressiveTax(incomeWithGain, this._rules.taxBrackets);
|
|
28
|
+
const capitalGainTax = taxWithGain - baseTax;
|
|
25
29
|
return {
|
|
26
30
|
taxableGain,
|
|
27
|
-
capitalGainTax
|
|
31
|
+
capitalGainTax,
|
|
28
32
|
socialContributions: 0,
|
|
29
33
|
netInvestmentIncomeTax: 0,
|
|
30
|
-
totalTax:
|
|
31
|
-
effectiveRate: gain > 0 ? (
|
|
32
|
-
breakdowns
|
|
34
|
+
totalTax: capitalGainTax,
|
|
35
|
+
effectiveRate: gain > 0 ? (capitalGainTax / gain) * 100 : 0,
|
|
36
|
+
breakdowns: []
|
|
33
37
|
};
|
|
34
38
|
}
|
|
35
|
-
|
|
39
|
+
calculateProgressiveTax(income, brackets) {
|
|
36
40
|
let tax = 0;
|
|
37
|
-
const breakdowns = [];
|
|
38
|
-
let remaining = taxableGain;
|
|
39
|
-
let incomeUsed = otherIncome;
|
|
40
41
|
for (const bracket of brackets) {
|
|
41
|
-
if (remaining <= 0)
|
|
42
|
-
break;
|
|
43
42
|
const upper = bracket.to ?? Infinity;
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
const bracketSpace = upper - bracketStart;
|
|
48
|
-
const taxable = Math.min(bracketSpace, remaining);
|
|
43
|
+
if (income <= bracket.from)
|
|
44
|
+
break;
|
|
45
|
+
const taxable = Math.min(income, upper) - bracket.from;
|
|
49
46
|
if (taxable > 0) {
|
|
50
|
-
|
|
51
|
-
tax += bracketTax;
|
|
52
|
-
remaining -= taxable;
|
|
53
|
-
incomeUsed += taxable;
|
|
54
|
-
breakdowns.push({
|
|
55
|
-
from: `${bracket.from}`,
|
|
56
|
-
to: `${bracket.to ?? 'Above'}`,
|
|
57
|
-
rate: bracket.rate,
|
|
58
|
-
amount: bracketTax,
|
|
59
|
-
});
|
|
47
|
+
tax += taxable * bracket.rate;
|
|
60
48
|
}
|
|
61
49
|
}
|
|
62
|
-
return
|
|
50
|
+
return tax;
|
|
63
51
|
}
|
|
64
52
|
}
|
|
65
53
|
exports.CanadaCapitalGainsServiceImpl = CanadaCapitalGainsServiceImpl;
|
|
66
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
54
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2FuYWRhQ2FwaXRhbEdhaW5zU2VydmljZUltcGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY2FwaXRhbC1nYWlucy9jYW5hZGEvQ2FuYWRhQ2FwaXRhbEdhaW5zU2VydmljZUltcGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUEsTUFBYSw2QkFBNkI7SUFJdEMsWUFBWSxLQUFZLEVBQUUsS0FBWTtRQUNsQyxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztRQUNwQixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztJQUN4QixDQUFDO0lBRUQsU0FBUztRQUNMLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDO1FBRXJDLElBQUksSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ1osT0FBTztnQkFDSCxXQUFXLEVBQUUsQ0FBQztnQkFDZCxjQUFjLEVBQUUsQ0FBQztnQkFDakIsbUJBQW1CLEVBQUUsQ0FBQztnQkFDdEIsc0JBQXNCLEVBQUUsQ0FBQztnQkFDekIsUUFBUSxFQUFFLENBQUM7Z0JBQ1gsYUFBYSxFQUFFLENBQUM7Z0JBQ2hCLFVBQVUsRUFBRSxFQUFFO2FBQ2pCLENBQUM7UUFDTixDQUFDO1FBRUQsTUFBTSxXQUFXLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDO1FBRXJELGlDQUFpQztRQUNqQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDO1FBRWxELE1BQU0sY0FBYyxHQUFHLFVBQVUsR0FBRyxXQUFXLENBQUM7UUFFaEQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2xGLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxjQUFjLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUUxRixNQUFNLGNBQWMsR0FBRyxXQUFXLEdBQUcsT0FBTyxDQUFDO1FBRTdDLE9BQU87WUFDSCxXQUFXO1lBQ1gsY0FBYztZQUNkLG1CQUFtQixFQUFFLENBQUM7WUFDdEIsc0JBQXNCLEVBQUUsQ0FBQztZQUN6QixRQUFRLEVBQUUsY0FBYztZQUN4QixhQUFhLEVBQUUsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzNELFVBQVUsRUFBRSxFQUFFO1NBQ2pCLENBQUM7SUFDTixDQUFDO0lBRU8sdUJBQXVCLENBQUMsTUFBYyxFQUFFLFFBQXNCO1FBQ2xFLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQztRQUVaLEtBQUssTUFBTSxPQUFPLElBQUksUUFBUSxFQUFFLENBQUM7WUFDN0IsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEVBQUUsSUFBSSxRQUFRLENBQUM7WUFFckMsSUFBSSxNQUFNLElBQUksT0FBTyxDQUFDLElBQUk7Z0JBQUUsTUFBTTtZQUVsQyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO1lBRXZELElBQUksT0FBTyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUNkLEdBQUcsSUFBSSxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztZQUNsQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQztDQUNKO0FBaEVELHNFQWdFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFJlc3VsdCB9IGZyb20gXCIuLi9kb21haW4vdHlwZXNcIjtcbmltcG9ydCB7IENhbmFkYUNhcGl0YWxHYWluc1NlcnZpY2UgfSBmcm9tIFwiLi9DYW5hZGFDYXBpdGFsR2FpbnNTZXJ2aWNlXCI7XG5pbXBvcnQgeyBJbnB1dCwgUnVsZXMsIFRheEJyYWNrZXQgfSBmcm9tIFwiLi9kb21haW4vdHlwZXNcIjtcblxuZXhwb3J0IGNsYXNzIENhbmFkYUNhcGl0YWxHYWluc1NlcnZpY2VJbXBsIGltcGxlbWVudHMgQ2FuYWRhQ2FwaXRhbEdhaW5zU2VydmljZSB7XG4gICAgcHJpdmF0ZSBfaW5wdXQ6IElucHV0O1xuICAgIHByaXZhdGUgX3J1bGVzOiBSdWxlcztcblxuICAgIGNvbnN0cnVjdG9yKGlucHV0OiBJbnB1dCwgcnVsZXM6IFJ1bGVzKSB7XG4gICAgICAgIHRoaXMuX2lucHV0ID0gaW5wdXQ7XG4gICAgICAgIHRoaXMuX3J1bGVzID0gcnVsZXM7XG4gICAgfVxuXG4gICAgY2FsY3VsYXRlKCk6IFJlc3VsdCB7XG4gICAgICAgIGNvbnN0IGdhaW4gPSB0aGlzLl9pbnB1dC5jYXBpdGFsR2FpbjtcblxuICAgICAgICBpZiAoZ2FpbiA8PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHRheGFibGVHYWluOiAwLFxuICAgICAgICAgICAgICAgIGNhcGl0YWxHYWluVGF4OiAwLFxuICAgICAgICAgICAgICAgIHNvY2lhbENvbnRyaWJ1dGlvbnM6IDAsXG4gICAgICAgICAgICAgICAgbmV0SW52ZXN0bWVudEluY29tZVRheDogMCxcbiAgICAgICAgICAgICAgICB0b3RhbFRheDogMCxcbiAgICAgICAgICAgICAgICBlZmZlY3RpdmVSYXRlOiAwLFxuICAgICAgICAgICAgICAgIGJyZWFrZG93bnM6IFtdXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdGF4YWJsZUdhaW4gPSBnYWluICogdGhpcy5fcnVsZXMuaW5jbHVzaW9uUmF0ZTtcblxuICAgICAgICAvLyBpbmNvbWUgQkVGT1JFIHRoZSBjYXBpdGFsIGdhaW5cbiAgICAgICAgY29uc3QgYmFzZUluY29tZSA9IHRoaXMuX2lucHV0LnRvdGFsVGF4YWJsZUluY29tZTtcblxuICAgICAgICBjb25zdCBpbmNvbWVXaXRoR2FpbiA9IGJhc2VJbmNvbWUgKyB0YXhhYmxlR2FpbjtcblxuICAgICAgICBjb25zdCBiYXNlVGF4ID0gdGhpcy5jYWxjdWxhdGVQcm9ncmVzc2l2ZVRheChiYXNlSW5jb21lLCB0aGlzLl9ydWxlcy50YXhCcmFja2V0cyk7XG4gICAgICAgIGNvbnN0IHRheFdpdGhHYWluID0gdGhpcy5jYWxjdWxhdGVQcm9ncmVzc2l2ZVRheChpbmNvbWVXaXRoR2FpbiwgdGhpcy5fcnVsZXMudGF4QnJhY2tldHMpO1xuXG4gICAgICAgIGNvbnN0IGNhcGl0YWxHYWluVGF4ID0gdGF4V2l0aEdhaW4gLSBiYXNlVGF4O1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0YXhhYmxlR2FpbixcbiAgICAgICAgICAgIGNhcGl0YWxHYWluVGF4LFxuICAgICAgICAgICAgc29jaWFsQ29udHJpYnV0aW9uczogMCxcbiAgICAgICAgICAgIG5ldEludmVzdG1lbnRJbmNvbWVUYXg6IDAsXG4gICAgICAgICAgICB0b3RhbFRheDogY2FwaXRhbEdhaW5UYXgsXG4gICAgICAgICAgICBlZmZlY3RpdmVSYXRlOiBnYWluID4gMCA/IChjYXBpdGFsR2FpblRheCAvIGdhaW4pICogMTAwIDogMCxcbiAgICAgICAgICAgIGJyZWFrZG93bnM6IFtdXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjYWxjdWxhdGVQcm9ncmVzc2l2ZVRheChpbmNvbWU6IG51bWJlciwgYnJhY2tldHM6IFRheEJyYWNrZXRbXSk6IG51bWJlciB7XG4gICAgICAgIGxldCB0YXggPSAwO1xuXG4gICAgICAgIGZvciAoY29uc3QgYnJhY2tldCBvZiBicmFja2V0cykge1xuICAgICAgICAgICAgY29uc3QgdXBwZXIgPSBicmFja2V0LnRvID8/IEluZmluaXR5O1xuXG4gICAgICAgICAgICBpZiAoaW5jb21lIDw9IGJyYWNrZXQuZnJvbSkgYnJlYWs7XG5cbiAgICAgICAgICAgIGNvbnN0IHRheGFibGUgPSBNYXRoLm1pbihpbmNvbWUsIHVwcGVyKSAtIGJyYWNrZXQuZnJvbTtcblxuICAgICAgICAgICAgaWYgKHRheGFibGUgPiAwKSB7XG4gICAgICAgICAgICAgICAgdGF4ICs9IHRheGFibGUgKiBicmFja2V0LnJhdGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGF4O1xuICAgIH1cbn0iXX0=
|
|
@@ -22,4 +22,4 @@ Object.defineProperty(exports, "USACapitalGainsService", { enumerable: true, get
|
|
|
22
22
|
// Capital Gains - Germany
|
|
23
23
|
const GermanyCapitalGainsServiceImpl_1 = require("./germany/GermanyCapitalGainsServiceImpl");
|
|
24
24
|
Object.defineProperty(exports, "GermanyCapitalGainsService", { enumerable: true, get: function () { return GermanyCapitalGainsServiceImpl_1.GermanyCapitalGainsServiceImpl; } });
|
|
25
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2FwaXRhbC1nYWlucy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5QkFBeUI7QUFDekIsMEZBQW9IO0FBa0RoSCwwR0FsRHNDLDZEQUF5QixPQWtEdEM7QUE1QzdCLHlCQUF5QjtBQUN6QiwwRkFBb0g7QUE4Q2hILDBHQTlDc0MsNkRBQXlCLE9BOEN0QztBQXhDN0IsK0JBQStCO0FBQy9CLDBHQUF5STtBQTBDckksK0dBMUMyQyx1RUFBOEIsT0EwQzNDO0FBcENsQyw0QkFBNEI7QUFDNUIsbUdBQWdJO0FBc0M1SCw2R0F0Q3lDLG1FQUE0QixPQXNDekM7QUFoQ2hDLHFCQUFxQjtBQUNyQiw4RUFBb0c7QUFrQ2hHLHNHQWxDa0MscURBQXFCLE9Ba0NsQztBQTVCekIsc0JBQXNCO0FBQ3RCLGlGQUF3RztBQThCcEcsdUdBOUJtQyx1REFBc0IsT0E4Qm5DO0FBeEIxQiwwQkFBMEI7QUFDMUIsNkZBQXdIO0FBMEJwSCwyR0ExQnVDLCtEQUEwQixPQTBCdkMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDYXBpdGFsIEdhaW5zIC0gQ2FuYWRhXG5pbXBvcnQgeyBDYW5hZGFDYXBpdGFsR2FpbnNTZXJ2aWNlSW1wbCBhcyBDYW5hZGFDYXBpdGFsR2FpbnNTZXJ2aWNlIH0gZnJvbSAnLi9jYW5hZGEvQ2FuYWRhQ2FwaXRhbEdhaW5zU2VydmljZUltcGwnO1xuaW1wb3J0IHtcbiAgICBJbnB1dCBhcyBDYW5hZGFDYXBpdGFsR2FpbnNJbnB1dCxcbiAgICBSdWxlcyBhcyBDYW5hZGFDYXBpdGFsR2FpbnNSdWxlc1xufSBmcm9tICcuL2NhbmFkYS9kb21haW4vdHlwZXMnO1xuXG4vLyBDYXBpdGFsIEdhaW5zIC0gRnJhbmNlXG5pbXBvcnQgeyBGcmFuY2VDYXBpdGFsR2FpbnNTZXJ2aWNlSW1wbCBhcyBGcmFuY2VDYXBpdGFsR2FpbnNTZXJ2aWNlIH0gZnJvbSAnLi9mcmFuY2UvRnJhbmNlQ2FwaXRhbEdhaW5zU2VydmljZUltcGwnO1xuaW1wb3J0IHtcbiAgICBJbnB1dCBhcyBGcmFuY2VDYXBpdGFsR2FpbnNJbnB1dCxcbiAgICBSdWxlcyBhcyBGcmFuY2VDYXBpdGFsR2FpbnNSdWxlc1xufSBmcm9tICcuL2ZyYW5jZS9kb21haW4vdHlwZXMnO1xuXG4vLyBDYXBpdGFsIEdhaW5zIC0gU291dGggQWZyaWNhXG5pbXBvcnQgeyBTb3V0aEFmcmljYUNhcGl0YWxHYWluc1NlcnZpY2VJbXBsIGFzIFNvdXRoQWZyaWNhQ2FwaXRhbEdhaW5zU2VydmljZSB9IGZyb20gJy4vc291dGgtYWZyaWNhL1NvdXRoQWZyaWNhQ2FwaXRhbEdhaW5zU2VydmljZUltcGwnO1xuaW1wb3J0IHtcbiAgICBJbnB1dCBhcyBTb3V0aEFmcmljYUNhcGl0YWxHYWluc0lucHV0LFxuICAgIFJ1bGVzIGFzIFNvdXRoQWZyaWNhQ2FwaXRhbEdhaW5zUnVsZXNcbn0gZnJvbSAnLi9zb3V0aC1hZnJpY2EvZG9tYWluL3R5cGVzJztcblxuLy8gQ2FwaXRhbCBHYWlucyAtIEF1c3RyYWxpYVxuaW1wb3J0IHsgQXVzdHJhbGlhQ2FwaXRhbEdhaW5zU2VydmljZUltcGwgYXMgQXVzdHJhbGlhQ2FwaXRhbEdhaW5zU2VydmljZSB9IGZyb20gJy4vYXVzdHJhbGlhL0F1c3RyYWxpYUNhcGl0YWxHYWluc1NlcnZpY2VJbXBsJztcbmltcG9ydCB7XG4gICAgSW5wdXQgYXMgQXVzdHJhbGlhQ2FwaXRhbEdhaW5zSW5wdXQsXG4gICAgUnVsZXMgYXMgQXVzdHJhbGlhQ2FwaXRhbEdhaW5zUnVsZXNcbn0gZnJvbSAnLi9hdXN0cmFsaWEvZG9tYWluL3R5cGVzJztcblxuLy8gQ2FwaXRhbCBHYWlucyAtIFVLXG5pbXBvcnQgeyBVS0NhcGl0YWxHYWluc1NlcnZpY2VJbXBsIGFzIFVLQ2FwaXRhbEdhaW5zU2VydmljZSB9IGZyb20gJy4vdWsvVUtDYXBpdGFsR2FpbnNTZXJ2aWNlSW1wbCc7XG5pbXBvcnQge1xuICAgIElucHV0IGFzIFVLQ2FwaXRhbEdhaW5zSW5wdXQsXG4gICAgUnVsZXMgYXMgVUtDYXBpdGFsR2FpbnNSdWxlc1xufSBmcm9tICcuL3VrL2RvbWFpbi90eXBlcyc7XG5cbi8vIENhcGl0YWwgR2FpbnMgLSBVU0FcbmltcG9ydCB7IFVTQUNhcGl0YWxHYWluc1NlcnZpY2VJbXBsIGFzIFVTQUNhcGl0YWxHYWluc1NlcnZpY2UgfSBmcm9tICcuL3VzYS9VU0FDYXBpdGFsR2FpbnNTZXJ2aWNlSW1wbCc7XG5pbXBvcnQge1xuICAgIElucHV0IGFzIFVTQUNhcGl0YWxHYWluc0lucHV0LFxuICAgIFJ1bGVzIGFzIFVTQUNhcGl0YWxHYWluc1J1bGVzXG59IGZyb20gJy4vdXNhL2RvbWFpbi90eXBlcyc7XG5cbi8vIENhcGl0YWwgR2FpbnMgLSBHZXJtYW55XG5pbXBvcnQgeyBHZXJtYW55Q2FwaXRhbEdhaW5zU2VydmljZUltcGwgYXMgR2VybWFueUNhcGl0YWxHYWluc1NlcnZpY2UgfSBmcm9tICcuL2dlcm1hbnkvR2VybWFueUNhcGl0YWxHYWluc1NlcnZpY2VJbXBsJztcbmltcG9ydCB7XG4gICAgSW5wdXQgYXMgR2VybWFueUNhcGl0YWxHYWluc0lucHV0LFxuICAgIFJ1bGVzIGFzIEdlcm1hbnlDYXBpdGFsR2FpbnNSdWxlc1xufSBmcm9tICcuL2dlcm1hbnkvZG9tYWluL3R5cGVzJztcbmltcG9ydCB7IFJlc3VsdCB9IGZyb20gJy4vZG9tYWluL3R5cGVzJztcblxuZXhwb3J0IHtcbiAgICBDYW5hZGFDYXBpdGFsR2FpbnNTZXJ2aWNlLFxuICAgIENhbmFkYUNhcGl0YWxHYWluc0lucHV0LFxuICAgIENhbmFkYUNhcGl0YWxHYWluc1J1bGVzLFxuICAgIEZyYW5jZUNhcGl0YWxHYWluc1NlcnZpY2UsXG4gICAgRnJhbmNlQ2FwaXRhbEdhaW5zSW5wdXQsXG4gICAgRnJhbmNlQ2FwaXRhbEdhaW5zUnVsZXMsXG4gICAgU291dGhBZnJpY2FDYXBpdGFsR2FpbnNTZXJ2aWNlLFxuICAgIFNvdXRoQWZyaWNhQ2FwaXRhbEdhaW5zSW5wdXQsXG4gICAgU291dGhBZnJpY2FDYXBpdGFsR2FpbnNSdWxlcyxcbiAgICBBdXN0cmFsaWFDYXBpdGFsR2FpbnNTZXJ2aWNlLFxuICAgIEF1c3RyYWxpYUNhcGl0YWxHYWluc0lucHV0LFxuICAgIEF1c3RyYWxpYUNhcGl0YWxHYWluc1J1bGVzLFxuICAgIFVLQ2FwaXRhbEdhaW5zU2VydmljZSxcbiAgICBVS0NhcGl0YWxHYWluc0lucHV0LFxuICAgIFVLQ2FwaXRhbEdhaW5zUnVsZXMsXG4gICAgVVNBQ2FwaXRhbEdhaW5zU2VydmljZSxcbiAgICBVU0FDYXBpdGFsR2FpbnNJbnB1dCxcbiAgICBVU0FDYXBpdGFsR2FpbnNSdWxlcyxcbiAgICBHZXJtYW55Q2FwaXRhbEdhaW5zU2VydmljZSxcbiAgICBHZXJtYW55Q2FwaXRhbEdhaW5zSW5wdXQsXG4gICAgR2VybWFueUNhcGl0YWxHYWluc1J1bGVzLFxuICAgIFJlc3VsdFxufTsiXX0=
|
|
@@ -12,4 +12,5 @@ import { USACapitalGainsServiceImpl as USACapitalGainsService } from './usa/USAC
|
|
|
12
12
|
import { Input as USACapitalGainsInput, Rules as USACapitalGainsRules } from './usa/domain/types';
|
|
13
13
|
import { GermanyCapitalGainsServiceImpl as GermanyCapitalGainsService } from './germany/GermanyCapitalGainsServiceImpl';
|
|
14
14
|
import { Input as GermanyCapitalGainsInput, Rules as GermanyCapitalGainsRules } from './germany/domain/types';
|
|
15
|
-
|
|
15
|
+
import { Result } from './domain/types';
|
|
16
|
+
export { CanadaCapitalGainsService, CanadaCapitalGainsInput, CanadaCapitalGainsRules, FranceCapitalGainsService, FranceCapitalGainsInput, FranceCapitalGainsRules, SouthAfricaCapitalGainsService, SouthAfricaCapitalGainsInput, SouthAfricaCapitalGainsRules, AustraliaCapitalGainsService, AustraliaCapitalGainsInput, AustraliaCapitalGainsRules, UKCapitalGainsService, UKCapitalGainsInput, UKCapitalGainsRules, USACapitalGainsService, USACapitalGainsInput, USACapitalGainsRules, GermanyCapitalGainsService, GermanyCapitalGainsInput, GermanyCapitalGainsRules, Result };
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Result } from "../domain/types";
|
|
2
2
|
import { CanadaCapitalGainsService } from "./CanadaCapitalGainsService";
|
|
3
3
|
import { Input, Rules, TaxBracket } from "./domain/types";
|
|
4
4
|
|
|
@@ -27,56 +27,43 @@ export class CanadaCapitalGainsServiceImpl implements CanadaCapitalGainsService
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const taxableGain = gain * this._rules.inclusionRate;
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
|
|
31
|
+
// income BEFORE the capital gain
|
|
32
|
+
const baseIncome = this._input.totalTaxableIncome;
|
|
33
|
+
|
|
34
|
+
const incomeWithGain = baseIncome + taxableGain;
|
|
35
|
+
|
|
36
|
+
const baseTax = this.calculateProgressiveTax(baseIncome, this._rules.taxBrackets);
|
|
37
|
+
const taxWithGain = this.calculateProgressiveTax(incomeWithGain, this._rules.taxBrackets);
|
|
38
|
+
|
|
39
|
+
const capitalGainTax = taxWithGain - baseTax;
|
|
32
40
|
|
|
33
41
|
return {
|
|
34
42
|
taxableGain,
|
|
35
|
-
capitalGainTax
|
|
43
|
+
capitalGainTax,
|
|
36
44
|
socialContributions: 0,
|
|
37
45
|
netInvestmentIncomeTax: 0,
|
|
38
|
-
totalTax:
|
|
39
|
-
effectiveRate: gain > 0 ? (
|
|
40
|
-
breakdowns
|
|
46
|
+
totalTax: capitalGainTax,
|
|
47
|
+
effectiveRate: gain > 0 ? (capitalGainTax / gain) * 100 : 0,
|
|
48
|
+
breakdowns: []
|
|
41
49
|
};
|
|
42
50
|
}
|
|
43
51
|
|
|
44
|
-
private
|
|
45
|
-
taxableGain: number,
|
|
46
|
-
otherIncome: number,
|
|
47
|
-
brackets: TaxBracket[],
|
|
48
|
-
): { tax: number; breakdowns: Breakdown[] } {
|
|
52
|
+
private calculateProgressiveTax(income: number, brackets: TaxBracket[]): number {
|
|
49
53
|
let tax = 0;
|
|
50
|
-
const breakdowns: Breakdown[] = [];
|
|
51
|
-
let remaining = taxableGain;
|
|
52
|
-
let incomeUsed = otherIncome;
|
|
53
54
|
|
|
54
55
|
for (const bracket of brackets) {
|
|
55
|
-
if (remaining <= 0) break;
|
|
56
|
-
|
|
57
56
|
const upper = bracket.to ?? Infinity;
|
|
58
57
|
|
|
59
|
-
if (
|
|
58
|
+
if (income <= bracket.from) break;
|
|
60
59
|
|
|
61
|
-
const
|
|
62
|
-
const bracketSpace = upper - bracketStart;
|
|
63
|
-
const taxable = Math.min(bracketSpace, remaining);
|
|
60
|
+
const taxable = Math.min(income, upper) - bracket.from;
|
|
64
61
|
|
|
65
62
|
if (taxable > 0) {
|
|
66
|
-
|
|
67
|
-
tax += bracketTax;
|
|
68
|
-
remaining -= taxable;
|
|
69
|
-
incomeUsed += taxable;
|
|
70
|
-
|
|
71
|
-
breakdowns.push({
|
|
72
|
-
from: `${bracket.from}`,
|
|
73
|
-
to: `${bracket.to ?? 'Above'}`,
|
|
74
|
-
rate: bracket.rate,
|
|
75
|
-
amount: bracketTax,
|
|
76
|
-
});
|
|
63
|
+
tax += taxable * bracket.rate;
|
|
77
64
|
}
|
|
78
65
|
}
|
|
79
66
|
|
|
80
|
-
return
|
|
67
|
+
return tax;
|
|
81
68
|
}
|
|
82
|
-
}
|
|
69
|
+
}
|
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
Input as GermanyCapitalGainsInput,
|
|
47
47
|
Rules as GermanyCapitalGainsRules
|
|
48
48
|
} from './germany/domain/types';
|
|
49
|
+
import { Result } from './domain/types';
|
|
49
50
|
|
|
50
51
|
export {
|
|
51
52
|
CanadaCapitalGainsService,
|
|
@@ -68,5 +69,6 @@ export {
|
|
|
68
69
|
USACapitalGainsRules,
|
|
69
70
|
GermanyCapitalGainsService,
|
|
70
71
|
GermanyCapitalGainsInput,
|
|
71
|
-
GermanyCapitalGainsRules
|
|
72
|
+
GermanyCapitalGainsRules,
|
|
73
|
+
Result
|
|
72
74
|
};
|