@novha/calc-engines 1.2.1 → 1.3.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.
- package/dist/income-tax/canada/CanadaIncomeTaxServiceImpl.js +1 -1
- package/dist/income-tax/canada/domain/types.js +1 -1
- package/dist/income-tax/domain/types.js +3 -0
- package/dist/income-tax/france/domain/types.js +1 -1
- package/dist/index.js +5 -3
- package/dist/mortgage/canada/CanadaMortgageService.js +3 -0
- package/dist/mortgage/canada/CanadaMortgageServiceImpl.js +82 -0
- package/dist/mortgage/canada/domain/types.js +3 -0
- package/dist/shared/domain/types.js +10 -0
- package/dist/types/income-tax/canada/domain/types.d.ts +1 -1
- package/dist/types/income-tax/domain/types.d.ts +23 -0
- package/dist/types/income-tax/france/domain/types.d.ts +2 -1
- package/dist/types/index.d.ts +4 -2
- package/dist/types/mortgage/canada/CanadaMortgageService.d.ts +4 -0
- package/dist/types/mortgage/canada/CanadaMortgageServiceImpl.d.ts +7 -0
- package/dist/types/mortgage/canada/domain/types.d.ts +85 -0
- package/dist/types/shared/domain/types.d.ts +19 -0
- package/package.json +1 -1
- package/src/income-tax/canada/CanadaIncomeTaxServiceImpl.ts +1 -1
- package/src/income-tax/canada/domain/types.ts +2 -1
- package/src/{domain → income-tax/domain}/types.ts +1 -21
- package/src/income-tax/france/domain/types.ts +2 -1
- package/src/index.ts +8 -2
- package/src/mortgage/canada/CanadaMortgageService.ts +8 -0
- package/src/mortgage/canada/CanadaMortgageServiceImpl.ts +129 -0
- package/src/mortgage/canada/domain/types.ts +100 -0
- package/src/shared/domain/types.ts +21 -0
|
@@ -48,4 +48,4 @@ class CanadaIncomeTaxServiceImpl {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
exports.CanadaIncomeTaxServiceImpl = CanadaIncomeTaxServiceImpl;
|
|
51
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
51
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2FuYWRhSW5jb21lVGF4U2VydmljZUltcGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaW5jb21lLXRheC9jYW5hZGEvQ2FuYWRhSW5jb21lVGF4U2VydmljZUltcGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBV0EsTUFBYSwwQkFBMEI7SUFJbkMsWUFBWSxNQUFjLEVBQUUsS0FBcUI7UUFDN0MsSUFBSSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7UUFDdEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7SUFDeEIsQ0FBQztJQUVNLGtCQUFrQjtRQUVyQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM3RSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2hFLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUMxRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFdkUsT0FBTztZQUNILFdBQVcsRUFBRSxJQUFJLENBQUMsT0FBTztZQUN6QixTQUFTLEVBQUUsTUFBTTtZQUNqQixHQUFHO1lBQ0gsRUFBRTtZQUNGLGVBQWUsRUFBRSxNQUFNLEdBQUcsR0FBRyxHQUFHLEVBQUU7WUFDbEMsU0FBUyxFQUFFLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxHQUFHLEdBQUcsR0FBRyxFQUFFO1lBQzNDLGdCQUFnQixFQUFFLE1BQU0sR0FBRyxJQUFJLENBQUMsT0FBTztTQUMxQyxDQUFDO0lBQ04sQ0FBQztJQUVPLGVBQWUsQ0FBQyxNQUFjLEVBQUUsUUFBc0I7UUFDMUQsT0FBTyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ2hDLElBQUksTUFBTSxJQUFJLENBQUMsQ0FBQyxJQUFJO2dCQUFFLE9BQU8sS0FBSyxDQUFDO1lBRW5DLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksTUFBTSxDQUFDO1lBQzdCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFFakQsT0FBTyxLQUFLLEdBQUcsT0FBTyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDcEMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ1YsQ0FBQztJQUVPLFlBQVksQ0FBQyxHQUFXLEVBQUUsVUFBcUMsRUFBRTtRQUNyRSxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FDOUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsSUFBSSxFQUNuQyxDQUFDLENBQ0osQ0FBQztRQUVGLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxHQUFHLFlBQVksQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFTyxVQUFVLENBQUMsTUFBYyxFQUFFLEdBQXFCO1FBQ3BELElBQUksQ0FBQyxHQUFHLElBQUksTUFBTSxJQUFJLEdBQUcsQ0FBQyxTQUFTO1lBQUUsT0FBTyxDQUFDLENBQUM7UUFFOUMsTUFBTSxhQUFhLEdBQUcsTUFBTSxHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUM7UUFDN0MsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUNYLGFBQWEsR0FBRyxHQUFHLENBQUMsSUFBSSxFQUN4QixHQUFHLENBQUMsZUFBZSxDQUN0QixDQUFDO0lBQ04sQ0FBQztJQUVPLFNBQVMsQ0FBQyxNQUFjLEVBQUUsRUFBbUI7UUFDakQsSUFBSSxDQUFDLEVBQUU7WUFBRSxPQUFPLENBQUMsQ0FBQztRQUVsQixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUM1QixNQUFNLEVBQ04sRUFBRSxDQUFDLG9CQUFvQixDQUMxQixDQUFDO1FBRUYsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUNYLGVBQWUsR0FBRyxFQUFFLENBQUMsSUFBSSxFQUN6QixFQUFFLENBQUMsZUFBZSxDQUNyQixDQUFDO0lBQ04sQ0FBQztDQUNKO0FBdEVELGdFQXNFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRheEJyYWNrZXQgfSBmcm9tIFwiLi4vZG9tYWluL3R5cGVzXCI7XG5pbXBvcnQgeyBDYW5hZGFJbmNvbWVUYXhTZXJ2aWNlIH0gZnJvbSBcIi4vQ2FuYWRhSW5jb21lVGF4U2VydmljZVwiO1xuaW1wb3J0IHtcbiAgICBDUFBDb250cmlidXRpb24sXG4gICAgQ29tcHV0ZWRJbmNvbWVUYXhWYWx1ZXMsXG4gICAgRUlDb250cmlidXRpb24sXG4gICAgSW5jb21lVGF4UnVsZXMsXG4gICAgVGF4Q3JlZGl0XG59IGZyb20gXCIuL2RvbWFpbi90eXBlc1wiO1xuXG5cbmV4cG9ydCBjbGFzcyBDYW5hZGFJbmNvbWVUYXhTZXJ2aWNlSW1wbCBpbXBsZW1lbnRzIENhbmFkYUluY29tZVRheFNlcnZpY2Uge1xuICAgIHByaXZhdGUgX2luY29tZTogbnVtYmVyO1xuICAgIHByaXZhdGUgX3J1bGVzOiBJbmNvbWVUYXhSdWxlcztcblxuICAgIGNvbnN0cnVjdG9yKGluY29tZTogbnVtYmVyLCBydWxlczogSW5jb21lVGF4UnVsZXMpIHtcbiAgICAgICAgdGhpcy5faW5jb21lID0gaW5jb21lO1xuICAgICAgICB0aGlzLl9ydWxlcyA9IHJ1bGVzO1xuICAgIH1cblxuICAgIHB1YmxpYyBjYWxjdWxhdGVOZXRJbmNvbWUoKTogQ29tcHV0ZWRJbmNvbWVUYXhWYWx1ZXMge1xuXG4gICAgICAgIGNvbnN0IGdyb3NzVGF4ID0gdGhpcy5jb21wdXRlR3Jvc3NUYXgodGhpcy5faW5jb21lLCB0aGlzLl9ydWxlcy50YXhCcmFja2V0cyk7XG4gICAgICAgIGNvbnN0IG5ldFRheCA9IHRoaXMuYXBwbHlDcmVkaXRzKGdyb3NzVGF4LCB0aGlzLl9ydWxlcy5jcmVkaXRzKTtcbiAgICAgICAgY29uc3QgY3BwID0gdGhpcy5jb21wdXRlQ1BQKHRoaXMuX2luY29tZSwgdGhpcy5fcnVsZXMuY29udHJpYnV0aW9ucz8uY3BwKTtcbiAgICAgICAgY29uc3QgZWkgPSB0aGlzLmNvbXB1dGVFSSh0aGlzLl9pbmNvbWUsIHRoaXMuX3J1bGVzLmNvbnRyaWJ1dGlvbnM/LmVpKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZ3Jvc3NJbmNvbWU6IHRoaXMuX2luY29tZSxcbiAgICAgICAgICAgIGluY29tZVRheDogbmV0VGF4LFxuICAgICAgICAgICAgY3BwLFxuICAgICAgICAgICAgZWksXG4gICAgICAgICAgICB0b3RhbERlZHVjdGlvbnM6IG5ldFRheCArIGNwcCArIGVpLFxuICAgICAgICAgICAgbmV0SW5jb21lOiB0aGlzLl9pbmNvbWUgLSBuZXRUYXggLSBjcHAgLSBlaSxcbiAgICAgICAgICAgIGVmZmVjdGl2ZVRheFJhdGU6IG5ldFRheCAvIHRoaXMuX2luY29tZSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNvbXB1dGVHcm9zc1RheChpbmNvbWU6IG51bWJlciwgYnJhY2tldHM6IFRheEJyYWNrZXRbXSk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBicmFja2V0cy5yZWR1Y2UoKHRvdGFsLCBiKSA9PiB7XG4gICAgICAgICAgICBpZiAoaW5jb21lIDw9IGIuZnJvbSkgcmV0dXJuIHRvdGFsO1xuICAgIFxuICAgICAgICAgICAgY29uc3QgdXBwZXIgPSBiLnRvID8/IGluY29tZTtcbiAgICAgICAgICAgIGNvbnN0IHRheGFibGUgPSBNYXRoLm1pbihpbmNvbWUsIHVwcGVyKSAtIGIuZnJvbTtcbiAgICBcbiAgICAgICAgICAgIHJldHVybiB0b3RhbCArIHRheGFibGUgKiBiLnJhdGU7XG4gICAgICAgIH0sIDApO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXBwbHlDcmVkaXRzKHRheDogbnVtYmVyLCBjcmVkaXRzOiBSZWNvcmQ8c3RyaW5nLCBUYXhDcmVkaXQ+ID0ge30pOiBudW1iZXIge1xuICAgICAgICBjb25zdCB0b3RhbENyZWRpdHMgPSBPYmplY3QudmFsdWVzKGNyZWRpdHMpLnJlZHVjZShcbiAgICAgICAgICAgIChzdW0sIGMpID0+IHN1bSArIGMuYW1vdW50ICogYy5yYXRlLFxuICAgICAgICAgICAgMCxcbiAgICAgICAgKTtcbiAgICBcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KDAsIHRheCAtIHRvdGFsQ3JlZGl0cyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb21wdXRlQ1BQKGluY29tZTogbnVtYmVyLCBjcHA/OiBDUFBDb250cmlidXRpb24pOiBudW1iZXIge1xuICAgICAgICBpZiAoIWNwcCB8fCBpbmNvbWUgPD0gY3BwLmV4ZW1wdGlvbikgcmV0dXJuIDA7XG4gICAgXG4gICAgICAgIGNvbnN0IGNvbnRyaWJ1dGFibGUgPSBpbmNvbWUgLSBjcHAuZXhlbXB0aW9uO1xuICAgICAgICByZXR1cm4gTWF0aC5taW4oXG4gICAgICAgICAgICBjb250cmlidXRhYmxlICogY3BwLnJhdGUsXG4gICAgICAgICAgICBjcHAubWF4Q29udHJpYnV0aW9uLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgY29tcHV0ZUVJKGluY29tZTogbnVtYmVyLCBlaT86IEVJQ29udHJpYnV0aW9uKTogbnVtYmVyIHtcbiAgICAgICAgaWYgKCFlaSkgcmV0dXJuIDA7XG4gICAgXG4gICAgICAgIGNvbnN0IGluc3VyYWJsZUluY29tZSA9IE1hdGgubWluKFxuICAgICAgICAgICAgaW5jb21lLFxuICAgICAgICAgICAgZWkubWF4SW5zdXJhYmxlRWFybmluZ3MsXG4gICAgICAgICk7XG4gICAgXG4gICAgICAgIHJldHVybiBNYXRoLm1pbihcbiAgICAgICAgICAgIGluc3VyYWJsZUluY29tZSAqIGVpLnJhdGUsXG4gICAgICAgICAgICBlaS5tYXhDb250cmlidXRpb24sXG4gICAgICAgICk7XG4gICAgfVxufSJdfQ==
|
|
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaW5jb21lLXRheC9jYW5hZGEvZG9tYWluL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBUYXhCcmFja2V0IH0gZnJvbSBcIi4uLy4uL2RvbWFpbi90eXBlc1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIEluY29tZVRheFJ1bGVzIHtcbiAgICB0YXhCcmFja2V0czogVGF4QnJhY2tldFtdO1xuICAgIGNyZWRpdHM/OiBSZWNvcmQ8c3RyaW5nLCBUYXhDcmVkaXQ+O1xuICAgIGNvbnRyaWJ1dGlvbnM/OiBDb250cmlidXRpb25zO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRheENyZWRpdCB7XG4gICAgYW1vdW50OiBudW1iZXI7XG4gICAgdHlwZTogJ25vblJlZnVuZGFibGUnIHwgJ3JlZnVuZGFibGUnO1xuICAgIHJhdGU6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb250cmlidXRpb25zIHtcbiAgICBjcHA/OiBDUFBDb250cmlidXRpb247XG4gICAgZWk/OiBFSUNvbnRyaWJ1dGlvbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDUFBDb250cmlidXRpb24ge1xuICAgIHJhdGU6IG51bWJlcjtcbiAgICBtYXhDb250cmlidXRpb246IG51bWJlcjtcbiAgICBleGVtcHRpb246IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFSUNvbnRyaWJ1dGlvbiB7XG4gICAgcmF0ZTogbnVtYmVyO1xuICAgIG1heEluc3VyYWJsZUVhcm5pbmdzOiBudW1iZXI7XG4gICAgbWF4Q29udHJpYnV0aW9uOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcHV0ZWRJbmNvbWVUYXhWYWx1ZXMge1xuICAgIGdyb3NzSW5jb21lOiBudW1iZXI7XG4gICAgaW5jb21lVGF4OiBudW1iZXI7XG4gICAgY3BwOiBudW1iZXI7XG4gICAgZWk6IG51bWJlcjtcbiAgICB0b3RhbERlZHVjdGlvbnM6IG51bWJlcjtcbiAgICBuZXRJbmNvbWU6IG51bWJlcjtcbiAgICBlZmZlY3RpdmVUYXhSYXRlOiBudW1iZXI7XG59XG5cbiJdfQ==
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaW5jb21lLXRheC9kb21haW4vdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFJ1bGVNZXRhIH0gZnJvbSBcIi4uLy4uL3NoYXJlZC9kb21haW4vdHlwZXNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBSdWxlSW5wdXQge1xuICAgIG5hbWU6IHN0cmluZztcbiAgICB0eXBlOiAnbnVtYmVyJyB8ICdzZWxlY3QnIHwgJ3RleHQnO1xuICAgIHJlcXVpcmVkOiBib29sZWFuO1xuICAgIHVuaXQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUnVsZU91dHB1dCB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIHR5cGU6ICdudW1iZXInIHwgJ3N0cmluZyc7XG4gICAgdW5pdD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUYXhCcmFja2V0IHtcbiAgICBmcm9tOiBudW1iZXI7XG4gICAgdG86IG51bWJlciB8IG51bGw7XG4gICAgcmF0ZTogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEluY29tZVRheENhbGN1bGF0b3JTY2hlbWE8VD4ge1xuICAgIG1ldGE6IFJ1bGVNZXRhO1xuICAgIGlucHV0czogUnVsZUlucHV0W107XG4gICAgb3V0cHV0czogUnVsZU91dHB1dFtdO1xuICAgIHJ1bGVzOiBUO1xufSJdfQ==
|
|
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaW5jb21lLXRheC9mcmFuY2UvZG9tYWluL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBSdWxlTWV0YSB9IGZyb20gXCIuLi8uLi8uLi9zaGFyZWQvZG9tYWluL3R5cGVzXCI7XG5pbXBvcnQgeyBSdWxlSW5wdXQsIFJ1bGVPdXRwdXQsIFRheEJyYWNrZXQgfSBmcm9tIFwiLi4vLi4vZG9tYWluL3R5cGVzXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5jb21lVGF4UnVsZXMge1xuICAgIHRheEJyYWNrZXRzOiBUYXhCcmFja2V0W107XG4gICAgcXVvdGllbnRGYW1pbGlhbDogUXVvdGllbnRGYW1pbGlhbDtcbiAgICBzb2NpYWxDb250cmlidXRpb25zOiBDb250cmlidXRpb25zO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbnRyaWJ1dGlvbnMge1xuICAgIGVtcGxveWVlOiB7IHJhdGU6IG51bWJlcjsgfTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBRdW90aWVudEZhbWlsaWFsIHtcbiAgICBlbmFibGVkOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEluY29tZVRheENhbGN1bGF0b3JTY2hlbWEge1xuICAgIG1ldGE6IFJ1bGVNZXRhO1xuICAgIGlucHV0czogUnVsZUlucHV0W107XG4gICAgb3V0cHV0czogUnVsZU91dHB1dFtdO1xuICAgIHJ1bGVzOiBJbmNvbWVUYXhSdWxlcztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb21wdXRlZEluY29tZVRheFZhbHVlcyB7XG4gICAgZ3Jvc3NJbmNvbWU6IG51bWJlcjtcblx0aW5jb21lVGF4OiBudW1iZXI7XG5cdHNvY2lhbENvbnRyaWJ1dGlvbnM6IG51bWJlcjtcblx0dG90YWxEZWR1Y3Rpb25zOiBudW1iZXI7XG5cdG5ldEluY29tZTogbnVtYmVyO1xuXHRhdmVyYWdlVGF4UmF0ZTogbnVtYmVyO1xuXHRtYXJnaW5hbFRheFJhdGU6IG51bWJlcjtcbn0iXX0=
|
package/dist/index.js
CHANGED
|
@@ -14,10 +14,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.FranceIncomeTaxService = exports.CanadaIncomeTaxService = void 0;
|
|
17
|
+
exports.FranceIncomeTaxService = exports.CanadaMortgageService = exports.CanadaIncomeTaxService = void 0;
|
|
18
18
|
var CanadaIncomeTaxServiceImpl_1 = require("./income-tax/canada/CanadaIncomeTaxServiceImpl");
|
|
19
19
|
Object.defineProperty(exports, "CanadaIncomeTaxService", { enumerable: true, get: function () { return CanadaIncomeTaxServiceImpl_1.CanadaIncomeTaxServiceImpl; } });
|
|
20
|
+
var CanadaMortgageServiceImpl_1 = require("./mortgage/canada/CanadaMortgageServiceImpl");
|
|
21
|
+
Object.defineProperty(exports, "CanadaMortgageService", { enumerable: true, get: function () { return CanadaMortgageServiceImpl_1.CanadaMortgageServiceImpl; } });
|
|
20
22
|
var FranceIncomeTaxServiceImpl_1 = require("./income-tax/france/FranceIncomeTaxServiceImpl");
|
|
21
23
|
Object.defineProperty(exports, "FranceIncomeTaxService", { enumerable: true, get: function () { return FranceIncomeTaxServiceImpl_1.FranceIncomeTaxServiceImpl; } });
|
|
22
|
-
__exportStar(require("./domain/types"), exports);
|
|
23
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
24
|
+
__exportStar(require("./income-tax/domain/types"), exports);
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSw2RkFBc0g7QUFBN0csb0lBQUEsMEJBQTBCLE9BQTBCO0FBQzdELHlGQUFpSDtBQUF4RyxrSUFBQSx5QkFBeUIsT0FBeUI7QUFDM0QsNkZBQXNIO0FBQTdHLG9JQUFBLDBCQUEwQixPQUEwQjtBQWU3RCw0REFBMEMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgeyBDYW5hZGFJbmNvbWVUYXhTZXJ2aWNlSW1wbCBhcyBDYW5hZGFJbmNvbWVUYXhTZXJ2aWNlIH0gZnJvbSAnLi9pbmNvbWUtdGF4L2NhbmFkYS9DYW5hZGFJbmNvbWVUYXhTZXJ2aWNlSW1wbCc7XG5leHBvcnQgeyBDYW5hZGFNb3J0Z2FnZVNlcnZpY2VJbXBsIGFzIENhbmFkYU1vcnRnYWdlU2VydmljZSB9IGZyb20gJy4vbW9ydGdhZ2UvY2FuYWRhL0NhbmFkYU1vcnRnYWdlU2VydmljZUltcGwnO1xuZXhwb3J0IHsgRnJhbmNlSW5jb21lVGF4U2VydmljZUltcGwgYXMgRnJhbmNlSW5jb21lVGF4U2VydmljZSB9IGZyb20gJy4vaW5jb21lLXRheC9mcmFuY2UvRnJhbmNlSW5jb21lVGF4U2VydmljZUltcGwnO1xuZXhwb3J0IHtcbiAgICBDb21wdXRlZEluY29tZVRheFZhbHVlcyBhcyBDYW5hZGFDb21wdXRlZEluY29tZVRheFZhbHVlcyxcbiAgICBJbmNvbWVUYXhSdWxlcyBhcyBDYW5hZGFJbmNvbWVUYXhSdWxlcyxcbn0gZnJvbSAnLi9pbmNvbWUtdGF4L2NhbmFkYS9kb21haW4vdHlwZXMnO1xuZXhwb3J0IHtcbiAgICBNb3J0Z2FnZVJ1bGVzIGFzIENhbmFkYU1vcnRnYWdlUnVsZXMsXG4gICAgTW9ydGdhZ2VDYWxjdWxhdGlvbklucHV0IGFzIENhbmFkYU1vcnRnYWdlQ2FsY3VsYXRpb25JbnB1dCxcbiAgICBNb3J0Z2FnZUNhbGN1bGF0aW9uUmVzdWx0IGFzIENhbmFkYU1vcnRnYWdlQ2FsY3VsYXRpb25SZXN1bHQsXG59IGZyb20gJy4vbW9ydGdhZ2UvY2FuYWRhL2RvbWFpbi90eXBlcyc7XG5leHBvcnQgeyBcbiAgICBDb21wdXRlZEluY29tZVRheFZhbHVlcyBhcyBGcmFuY2VDb21wdXRlZEluY29tZVRheFZhbHVlcyxcbiAgICBJbmNvbWVUYXhSdWxlcyBhcyBGcmFuY2VJbmNvbWVUYXhSdWxlcyxcbn0gZnJvbSAnLi9pbmNvbWUtdGF4L2ZyYW5jZS9kb21haW4vdHlwZXMnO1xuZXhwb3J0IHsgSW5jb21lVGF4Q2FsY3VsYXRvclNjaGVtYSB9IGZyb20gJy4vaW5jb21lLXRheC9kb21haW4vdHlwZXMnO1xuZXhwb3J0ICogZnJvbSAnLi9pbmNvbWUtdGF4L2RvbWFpbi90eXBlcyc7Il19
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2FuYWRhTW9ydGdhZ2VTZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21vcnRnYWdlL2NhbmFkYS9DYW5hZGFNb3J0Z2FnZVNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE1vcnRnYWdlQ2FsY3VsYXRpb25JbnB1dCwgTW9ydGdhZ2VDYWxjdWxhdGlvblJlc3VsdCwgTW9ydGdhZ2VSdWxlcyB9IGZyb20gXCIuL2RvbWFpbi90eXBlc1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIENhbmFkYU1vcnRnYWdlU2VydmljZSB7XG4gICAgY2FsY3VsYXRlKFxuICAgICAgICBpbnB1dDogTW9ydGdhZ2VDYWxjdWxhdGlvbklucHV0LFxuICAgICAgICBydWxlczogTW9ydGdhZ2VSdWxlc1xuICAgICk6IE1vcnRnYWdlQ2FsY3VsYXRpb25SZXN1bHQ7XG59ICJdfQ==
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CanadaMortgageServiceImpl = void 0;
|
|
4
|
+
class CanadaMortgageServiceImpl {
|
|
5
|
+
calculate(input, rules) {
|
|
6
|
+
const { propertyPrice, downPayment, interestRate, amortizationYears, paymentFrequency } = input;
|
|
7
|
+
/* -----------------------------
|
|
8
|
+
1. Loan Amount & LTV
|
|
9
|
+
------------------------------ */
|
|
10
|
+
const loanAmount = propertyPrice - downPayment;
|
|
11
|
+
if (loanAmount <= 0) {
|
|
12
|
+
throw new Error('Invalid loan amount');
|
|
13
|
+
}
|
|
14
|
+
const ltv = loanAmount / propertyPrice;
|
|
15
|
+
/* -----------------------------
|
|
16
|
+
2. CMHC Insurance
|
|
17
|
+
------------------------------ */
|
|
18
|
+
let insurancePremium = 0;
|
|
19
|
+
if (ltv > rules.mortgageInsurance.requiredBelowLtv) {
|
|
20
|
+
const premiumRule = rules.mortgageInsurance.premiumRates
|
|
21
|
+
.find(r => ltv <= r.maxLtv);
|
|
22
|
+
if (!premiumRule) {
|
|
23
|
+
throw new Error('LTV exceeds maximum insurable limit');
|
|
24
|
+
}
|
|
25
|
+
insurancePremium = loanAmount * premiumRule.rate;
|
|
26
|
+
}
|
|
27
|
+
const totalMortgage = rules.mortgageInsurance.premiumAddedToLoan
|
|
28
|
+
? loanAmount + insurancePremium
|
|
29
|
+
: loanAmount;
|
|
30
|
+
/* -----------------------------
|
|
31
|
+
3. Interest Rate Conversion
|
|
32
|
+
(Canada semi-annual compounding)
|
|
33
|
+
------------------------------ */
|
|
34
|
+
const periodicRate = this.convertCanadianRate(interestRate, rules.interest.compounding, rules.paymentFrequencyRules[paymentFrequency].paymentsPerYear);
|
|
35
|
+
/* -----------------------------
|
|
36
|
+
4. Payment Frequency
|
|
37
|
+
------------------------------ */
|
|
38
|
+
const frequencyRule = rules.paymentFrequencyRules[paymentFrequency];
|
|
39
|
+
const paymentsPerYear = frequencyRule.paymentsPerYear;
|
|
40
|
+
const totalPayments = amortizationYears * paymentsPerYear;
|
|
41
|
+
/* -----------------------------
|
|
42
|
+
5. Mortgage Payment Formula
|
|
43
|
+
P = L × [ r(1+r)^n ] / [ (1+r)^n − 1 ]
|
|
44
|
+
------------------------------ */
|
|
45
|
+
const paymentAmount = this.calculatePayment(totalMortgage, periodicRate, totalPayments);
|
|
46
|
+
/* -----------------------------
|
|
47
|
+
6. Totals
|
|
48
|
+
------------------------------ */
|
|
49
|
+
const totalPaid = paymentAmount * totalPayments;
|
|
50
|
+
const totalInterestPaid = totalPaid - totalMortgage;
|
|
51
|
+
return {
|
|
52
|
+
loanAmount: loanAmount,
|
|
53
|
+
insurancePremium: insurancePremium,
|
|
54
|
+
totalMortgage: totalMortgage,
|
|
55
|
+
paymentAmount: paymentAmount,
|
|
56
|
+
totalInterestPaid: totalInterestPaid,
|
|
57
|
+
totalPaid: totalPaid
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/* ======================================================
|
|
61
|
+
Helper Methods
|
|
62
|
+
====================================================== */
|
|
63
|
+
convertCanadianRate(annualRate, compounding, paymentsPerYear) {
|
|
64
|
+
if (compounding !== 'SEMI_ANNUAL') {
|
|
65
|
+
throw new Error('Only Canadian semi-annual compounding supported');
|
|
66
|
+
}
|
|
67
|
+
// Canadian standard conversion
|
|
68
|
+
const semiAnnualRate = annualRate / 2;
|
|
69
|
+
const effectiveAnnualRate = Math.pow(1 + semiAnnualRate, 2) - 1;
|
|
70
|
+
return Math.pow(1 + effectiveAnnualRate, 1 / paymentsPerYear) - 1;
|
|
71
|
+
}
|
|
72
|
+
calculatePayment(principal, rate, periods) {
|
|
73
|
+
if (rate === 0) {
|
|
74
|
+
return principal / periods;
|
|
75
|
+
}
|
|
76
|
+
return principal *
|
|
77
|
+
(rate * Math.pow(1 + rate, periods)) /
|
|
78
|
+
(Math.pow(1 + rate, periods) - 1);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.CanadaMortgageServiceImpl = CanadaMortgageServiceImpl;
|
|
82
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2FuYWRhTW9ydGdhZ2VTZXJ2aWNlSW1wbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tb3J0Z2FnZS9jYW5hZGEvQ2FuYWRhTW9ydGdhZ2VTZXJ2aWNlSW1wbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFPQSxNQUFhLHlCQUF5QjtJQUU3QixTQUFTLENBQUMsS0FBK0IsRUFBRSxLQUFvQjtRQUVwRSxNQUFNLEVBQ0osYUFBYSxFQUNiLFdBQVcsRUFDWCxZQUFZLEVBQ1osaUJBQWlCLEVBQ2pCLGdCQUFnQixFQUNqQixHQUFHLEtBQUssQ0FBQztRQUVWOzt5Q0FFaUM7UUFFakMsTUFBTSxVQUFVLEdBQUcsYUFBYSxHQUFHLFdBQVcsQ0FBQztRQUMvQyxJQUFJLFVBQVUsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUNwQixNQUFNLElBQUksS0FBSyxDQUFDLHFCQUFxQixDQUFDLENBQUM7UUFDekMsQ0FBQztRQUVELE1BQU0sR0FBRyxHQUFHLFVBQVUsR0FBRyxhQUFhLENBQUM7UUFFdkM7O3lDQUVpQztRQUVqQyxJQUFJLGdCQUFnQixHQUFHLENBQUMsQ0FBQztRQUV6QixJQUFJLEdBQUcsR0FBRyxLQUFLLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUNuRCxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsaUJBQWlCLENBQUMsWUFBWTtpQkFDckQsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUU5QixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMscUNBQXFDLENBQUMsQ0FBQztZQUN6RCxDQUFDO1lBRUQsZ0JBQWdCLEdBQUcsVUFBVSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUM7UUFDbkQsQ0FBQztRQUVELE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxrQkFBa0I7WUFDOUQsQ0FBQyxDQUFDLFVBQVUsR0FBRyxnQkFBZ0I7WUFDL0IsQ0FBQyxDQUFDLFVBQVUsQ0FBQztRQUVmOzs7eUNBR2lDO1FBRWpDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FDM0MsWUFBWSxFQUNaLEtBQUssQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUMxQixLQUFLLENBQUMscUJBQXFCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxlQUFlLENBQzlELENBQUM7UUFFRjs7eUNBRWlDO1FBRWpDLE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3BFLE1BQU0sZUFBZSxHQUFHLGFBQWEsQ0FBQyxlQUFlLENBQUM7UUFDdEQsTUFBTSxhQUFhLEdBQUcsaUJBQWlCLEdBQUcsZUFBZSxDQUFDO1FBRTFEOzs7eUNBR2lDO1FBRWpDLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FDekMsYUFBYSxFQUNiLFlBQVksRUFDWixhQUFhLENBQ2QsQ0FBQztRQUVGOzt5Q0FFaUM7UUFFakMsTUFBTSxTQUFTLEdBQUcsYUFBYSxHQUFHLGFBQWEsQ0FBQztRQUNoRCxNQUFNLGlCQUFpQixHQUFHLFNBQVMsR0FBRyxhQUFhLENBQUM7UUFFcEQsT0FBTztZQUNMLFVBQVUsRUFBRSxVQUFVO1lBQ3RCLGdCQUFnQixFQUFFLGdCQUFnQjtZQUNsQyxhQUFhLEVBQUUsYUFBYTtZQUM1QixhQUFhLEVBQUUsYUFBYTtZQUM1QixpQkFBaUIsRUFBRSxpQkFBaUI7WUFDcEMsU0FBUyxFQUFFLFNBQVM7U0FDckIsQ0FBQztJQUNKLENBQUM7SUFFRDs7NkRBRXlEO0lBRWpELG1CQUFtQixDQUN6QixVQUFrQixFQUNsQixXQUFpRCxFQUNqRCxlQUF1QjtRQUd2QixJQUFJLFdBQVcsS0FBSyxhQUFhLEVBQUUsQ0FBQztZQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLGlEQUFpRCxDQUFDLENBQUM7UUFDckUsQ0FBQztRQUVELCtCQUErQjtRQUMvQixNQUFNLGNBQWMsR0FBRyxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ3RDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsY0FBYyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUVoRSxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLG1CQUFtQixFQUFFLENBQUMsR0FBRyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDcEUsQ0FBQztJQUVPLGdCQUFnQixDQUFDLFNBQWlCLEVBQUUsSUFBWSxFQUFFLE9BQWU7UUFDdkUsSUFBSSxJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDZixPQUFPLFNBQVMsR0FBRyxPQUFPLENBQUM7UUFDN0IsQ0FBQztRQUVELE9BQU8sU0FBUztZQUNkLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNwQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN0QyxDQUFDO0NBQ0Y7QUF6SEQsOERBeUhDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2FuYWRhTW9ydGdhZ2VTZXJ2aWNlIH0gZnJvbSAnLi9DYW5hZGFNb3J0Z2FnZVNlcnZpY2UnO1xuaW1wb3J0IHtcbiAgTW9ydGdhZ2VSdWxlcyxcbiAgTW9ydGdhZ2VDYWxjdWxhdGlvbklucHV0LFxuICBNb3J0Z2FnZUNhbGN1bGF0aW9uUmVzdWx0XG59IGZyb20gJy4vZG9tYWluL3R5cGVzJztcblxuZXhwb3J0IGNsYXNzIENhbmFkYU1vcnRnYWdlU2VydmljZUltcGwgaW1wbGVtZW50cyBDYW5hZGFNb3J0Z2FnZVNlcnZpY2Uge1xuXG4gIHB1YmxpYyBjYWxjdWxhdGUoaW5wdXQ6IE1vcnRnYWdlQ2FsY3VsYXRpb25JbnB1dCwgcnVsZXM6IE1vcnRnYWdlUnVsZXMpOiBNb3J0Z2FnZUNhbGN1bGF0aW9uUmVzdWx0IHtcblxuICAgIGNvbnN0IHtcbiAgICAgIHByb3BlcnR5UHJpY2UsXG4gICAgICBkb3duUGF5bWVudCxcbiAgICAgIGludGVyZXN0UmF0ZSxcbiAgICAgIGFtb3J0aXphdGlvblllYXJzLFxuICAgICAgcGF5bWVudEZyZXF1ZW5jeVxuICAgIH0gPSBpbnB1dDtcblxuICAgIC8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgMS4gTG9hbiBBbW91bnQgJiBMVFZcbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuICAgIGNvbnN0IGxvYW5BbW91bnQgPSBwcm9wZXJ0eVByaWNlIC0gZG93blBheW1lbnQ7XG4gICAgaWYgKGxvYW5BbW91bnQgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGxvYW4gYW1vdW50Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgbHR2ID0gbG9hbkFtb3VudCAvIHByb3BlcnR5UHJpY2U7XG5cbiAgICAvKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgIDIuIENNSEMgSW5zdXJhbmNlXG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cbiAgICBsZXQgaW5zdXJhbmNlUHJlbWl1bSA9IDA7XG5cbiAgICBpZiAobHR2ID4gcnVsZXMubW9ydGdhZ2VJbnN1cmFuY2UucmVxdWlyZWRCZWxvd0x0dikge1xuICAgICAgY29uc3QgcHJlbWl1bVJ1bGUgPSBydWxlcy5tb3J0Z2FnZUluc3VyYW5jZS5wcmVtaXVtUmF0ZXNcbiAgICAgICAgLmZpbmQociA9PiBsdHYgPD0gci5tYXhMdHYpO1xuXG4gICAgICBpZiAoIXByZW1pdW1SdWxlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTFRWIGV4Y2VlZHMgbWF4aW11bSBpbnN1cmFibGUgbGltaXQnKTtcbiAgICAgIH1cblxuICAgICAgaW5zdXJhbmNlUHJlbWl1bSA9IGxvYW5BbW91bnQgKiBwcmVtaXVtUnVsZS5yYXRlO1xuICAgIH1cblxuICAgIGNvbnN0IHRvdGFsTW9ydGdhZ2UgPSBydWxlcy5tb3J0Z2FnZUluc3VyYW5jZS5wcmVtaXVtQWRkZWRUb0xvYW5cbiAgICAgID8gbG9hbkFtb3VudCArIGluc3VyYW5jZVByZW1pdW1cbiAgICAgIDogbG9hbkFtb3VudDtcblxuICAgIC8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgMy4gSW50ZXJlc3QgUmF0ZSBDb252ZXJzaW9uXG4gICAgICAgKENhbmFkYSBzZW1pLWFubnVhbCBjb21wb3VuZGluZylcbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuICAgIGNvbnN0IHBlcmlvZGljUmF0ZSA9IHRoaXMuY29udmVydENhbmFkaWFuUmF0ZShcbiAgICAgIGludGVyZXN0UmF0ZSxcbiAgICAgIHJ1bGVzLmludGVyZXN0LmNvbXBvdW5kaW5nLFxuICAgICAgcnVsZXMucGF5bWVudEZyZXF1ZW5jeVJ1bGVzW3BheW1lbnRGcmVxdWVuY3ldLnBheW1lbnRzUGVyWWVhclxuICAgICk7XG5cbiAgICAvKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgIDQuIFBheW1lbnQgRnJlcXVlbmN5XG4gICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cbiAgICBjb25zdCBmcmVxdWVuY3lSdWxlID0gcnVsZXMucGF5bWVudEZyZXF1ZW5jeVJ1bGVzW3BheW1lbnRGcmVxdWVuY3ldO1xuICAgIGNvbnN0IHBheW1lbnRzUGVyWWVhciA9IGZyZXF1ZW5jeVJ1bGUucGF5bWVudHNQZXJZZWFyO1xuICAgIGNvbnN0IHRvdGFsUGF5bWVudHMgPSBhbW9ydGl6YXRpb25ZZWFycyAqIHBheW1lbnRzUGVyWWVhcjtcblxuICAgIC8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgNS4gTW9ydGdhZ2UgUGF5bWVudCBGb3JtdWxhXG4gICAgICAgUCA9IEwgw5cgWyByKDErcilebiBdIC8gWyAoMStyKV5uIOKIkiAxIF1cbiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuICAgIGNvbnN0IHBheW1lbnRBbW91bnQgPSB0aGlzLmNhbGN1bGF0ZVBheW1lbnQoXG4gICAgICB0b3RhbE1vcnRnYWdlLFxuICAgICAgcGVyaW9kaWNSYXRlLFxuICAgICAgdG90YWxQYXltZW50c1xuICAgICk7XG5cbiAgICAvKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgIDYuIFRvdGFsc1xuICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4gICAgY29uc3QgdG90YWxQYWlkID0gcGF5bWVudEFtb3VudCAqIHRvdGFsUGF5bWVudHM7XG4gICAgY29uc3QgdG90YWxJbnRlcmVzdFBhaWQgPSB0b3RhbFBhaWQgLSB0b3RhbE1vcnRnYWdlO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGxvYW5BbW91bnQ6IGxvYW5BbW91bnQsXG4gICAgICBpbnN1cmFuY2VQcmVtaXVtOiBpbnN1cmFuY2VQcmVtaXVtLFxuICAgICAgdG90YWxNb3J0Z2FnZTogdG90YWxNb3J0Z2FnZSxcbiAgICAgIHBheW1lbnRBbW91bnQ6IHBheW1lbnRBbW91bnQsXG4gICAgICB0b3RhbEludGVyZXN0UGFpZDogdG90YWxJbnRlcmVzdFBhaWQsXG4gICAgICB0b3RhbFBhaWQ6IHRvdGFsUGFpZFxuICAgIH07XG4gIH1cblxuICAvKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAgSGVscGVyIE1ldGhvZHNcbiAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cbiAgcHJpdmF0ZSBjb252ZXJ0Q2FuYWRpYW5SYXRlKFxuICAgIGFubnVhbFJhdGU6IG51bWJlcixcbiAgICBjb21wb3VuZGluZzogJ1NFTUlfQU5OVUFMJyB8ICdBTk5VQUwnIHwgJ01PTlRITFknLFxuICAgIHBheW1lbnRzUGVyWWVhcjogbnVtYmVyXG4gICk6IG51bWJlciB7XG5cbiAgICBpZiAoY29tcG91bmRpbmcgIT09ICdTRU1JX0FOTlVBTCcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignT25seSBDYW5hZGlhbiBzZW1pLWFubnVhbCBjb21wb3VuZGluZyBzdXBwb3J0ZWQnKTtcbiAgICB9XG5cbiAgICAvLyBDYW5hZGlhbiBzdGFuZGFyZCBjb252ZXJzaW9uXG4gICAgY29uc3Qgc2VtaUFubnVhbFJhdGUgPSBhbm51YWxSYXRlIC8gMjtcbiAgICBjb25zdCBlZmZlY3RpdmVBbm51YWxSYXRlID0gTWF0aC5wb3coMSArIHNlbWlBbm51YWxSYXRlLCAyKSAtIDE7XG5cbiAgICByZXR1cm4gTWF0aC5wb3coMSArIGVmZmVjdGl2ZUFubnVhbFJhdGUsIDEgLyBwYXltZW50c1BlclllYXIpIC0gMTtcbiAgfVxuXG4gIHByaXZhdGUgY2FsY3VsYXRlUGF5bWVudChwcmluY2lwYWw6IG51bWJlciwgcmF0ZTogbnVtYmVyLCBwZXJpb2RzOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmIChyYXRlID09PSAwKSB7XG4gICAgICByZXR1cm4gcHJpbmNpcGFsIC8gcGVyaW9kcztcbiAgICB9XG5cbiAgICByZXR1cm4gcHJpbmNpcGFsICpcbiAgICAgIChyYXRlICogTWF0aC5wb3coMSArIHJhdGUsIHBlcmlvZHMpKSAvXG4gICAgICAoTWF0aC5wb3coMSArIHJhdGUsIHBlcmlvZHMpIC0gMSk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbW9ydGdhZ2UvY2FuYWRhL2RvbWFpbi90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUnVsZU1ldGEgfSBmcm9tIFwiLi4vLi4vLi4vc2hhcmVkL2RvbWFpbi90eXBlc1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJ1bGVJbnB1dERlZmluaXRpb24ge1xuICAgIHR5cGU6ICdudW1iZXInIHwgJ3N0cmluZyc7XG4gICAgbWluPzogbnVtYmVyO1xuICAgIG1heD86IG51bWJlcjtcbiAgICBlbnVtPzogc3RyaW5nW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUnVsZUlucHV0cyB7XG4gICAgcHJvcGVydHlQcmljZTogUnVsZUlucHV0RGVmaW5pdGlvbjtcbiAgICBkb3duUGF5bWVudDogUnVsZUlucHV0RGVmaW5pdGlvbjtcbiAgICBpbnRlcmVzdFJhdGU6IFJ1bGVJbnB1dERlZmluaXRpb247XG4gICAgYW1vcnRpemF0aW9uWWVhcnM6IFJ1bGVJbnB1dERlZmluaXRpb247XG4gICAgcGF5bWVudEZyZXF1ZW5jeTogUnVsZUlucHV0RGVmaW5pdGlvbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSdWxlT3V0cHV0cyB7XG4gICAgbG9hbkFtb3VudDogJ251bWJlcic7XG4gICAgaW5zdXJhbmNlUHJlbWl1bTogJ251bWJlcic7XG4gICAgdG90YWxNb3J0Z2FnZTogJ251bWJlcic7XG4gICAgcGF5bWVudEFtb3VudDogJ251bWJlcic7XG4gICAgdG90YWxJbnRlcmVzdFBhaWQ6ICdudW1iZXInO1xuICAgIHRvdGFsUGFpZDogJ251bWJlcic7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9hbkNvbnN0cmFpbnRzIHtcbiAgICBtYXhBbW9ydGl6YXRpb25ZZWFyczogbnVtYmVyO1xuICAgIGluc3VyZWRNYXhBbW9ydGl6YXRpb25ZZWFyczogbnVtYmVyO1xuICAgIG1pbkRvd25QYXltZW50OiB7XG4gICAgICAgIHVwVG81MDBrOiBudW1iZXI7XG4gICAgICAgIGFib3ZlNTAwazogbnVtYmVyO1xuICAgIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9ydGdhZ2VJbnN1cmFuY2VSYXRlIHtcbiAgICBtYXhMdHY6IG51bWJlcjtcbiAgICByYXRlOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9ydGdhZ2VJbnN1cmFuY2VSdWxlcyB7XG4gICAgcmVxdWlyZWRCZWxvd0x0djogbnVtYmVyO1xuICAgIHByZW1pdW1SYXRlczogTW9ydGdhZ2VJbnN1cmFuY2VSYXRlW107XG4gICAgcHJlbWl1bUFkZGVkVG9Mb2FuOiBib29sZWFuO1xufVxuXG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9ydGdhZ2VSdWxlcyB7XG4gICAgbG9hbkNvbnN0cmFpbnRzOiBMb2FuQ29uc3RyYWludHM7XG4gICAgbW9ydGdhZ2VJbnN1cmFuY2U6IE1vcnRnYWdlSW5zdXJhbmNlUnVsZXM7XG4gICAgaW50ZXJlc3Q6IEludGVyZXN0UnVsZXM7XG4gICAgcGF5bWVudEZyZXF1ZW5jeVJ1bGVzOiBQYXltZW50RnJlcXVlbmN5UnVsZXM7XG4gICAgc3RyZXNzVGVzdDogU3RyZXNzVGVzdFJ1bGVzO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEludGVyZXN0UnVsZXMge1xuICAgIGNvbXBvdW5kaW5nOiAnU0VNSV9BTk5VQUwnIHwgJ0FOTlVBTCcgfCAnTU9OVEhMWSc7XG4gICAgY29udmVyc2lvbkZvcm11bGE6ICdDQU5BREFfU1RBTkRBUkQnIHwgc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBheW1lbnRGcmVxdWVuY3lSdWxlIHtcbiAgICBwYXltZW50c1BlclllYXI6IG51bWJlcjtcbiAgICBhY2NlbGVyYXRpb24/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBheW1lbnRGcmVxdWVuY3lSdWxlcyB7XG4gICAgTU9OVEhMWTogUGF5bWVudEZyZXF1ZW5jeVJ1bGU7XG4gICAgQklfV0VFS0xZOiBQYXltZW50RnJlcXVlbmN5UnVsZTtcbiAgICBBQ0NFTEVSQVRFRF9CSV9XRUVLTFk6IFBheW1lbnRGcmVxdWVuY3lSdWxlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0cmVzc1Rlc3RSdWxlcyB7XG4gICAgYXBwbHk6IGJvb2xlYW47XG4gICAgbWluaW11bVJhdGVCdWZmZXI6IG51bWJlcjtcbiAgICBtaW5pbXVtUXVhbGlmeWluZ1JhdGU6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNb3J0Z2FnZVJ1bGVTZXQge1xuICAgIG1ldGE6IFJ1bGVNZXRhO1xuICAgIGlucHV0czogUnVsZUlucHV0cztcbiAgICBydWxlczogTW9ydGdhZ2VSdWxlcztcbiAgICBvdXRwdXRzOiBSdWxlT3V0cHV0cztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNb3J0Z2FnZUNhbGN1bGF0aW9uSW5wdXQge1xuICBwcm9wZXJ0eVByaWNlOiBudW1iZXI7XG4gIGRvd25QYXltZW50OiBudW1iZXI7XG4gIGludGVyZXN0UmF0ZTogbnVtYmVyOyAvLyBBbm51YWwgbm9taW5hbCByYXRlIChlLmcuIDAuMDUyKVxuICBhbW9ydGl6YXRpb25ZZWFyczogbnVtYmVyO1xuICBwYXltZW50RnJlcXVlbmN5OiAnTU9OVEhMWScgfCAnQklfV0VFS0xZJyB8ICdBQ0NFTEVSQVRFRF9CSV9XRUVLTFknO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1vcnRnYWdlQ2FsY3VsYXRpb25SZXN1bHQge1xuICBsb2FuQW1vdW50OiBudW1iZXI7XG4gIGluc3VyYW5jZVByZW1pdW06IG51bWJlcjtcbiAgdG90YWxNb3J0Z2FnZTogbnVtYmVyO1xuICBwYXltZW50QW1vdW50OiBudW1iZXI7XG4gIHRvdGFsSW50ZXJlc3RQYWlkOiBudW1iZXI7XG4gIHRvdGFsUGFpZDogbnVtYmVyO1xufVxuIl19
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CalculatorType = void 0;
|
|
4
|
+
var CalculatorType;
|
|
5
|
+
(function (CalculatorType) {
|
|
6
|
+
CalculatorType["INCOME_TAX"] = "INCOME_TAX";
|
|
7
|
+
CalculatorType["MORTGAGE"] = "MORTGAGE";
|
|
8
|
+
CalculatorType["LOAN"] = "LOAN";
|
|
9
|
+
})(CalculatorType || (exports.CalculatorType = CalculatorType = {}));
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2hhcmVkL2RvbWFpbi90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxJQUFZLGNBSVg7QUFKRCxXQUFZLGNBQWM7SUFDdEIsMkNBQXlCLENBQUE7SUFDekIsdUNBQXFCLENBQUE7SUFDckIsK0JBQWEsQ0FBQTtBQUNqQixDQUFDLEVBSlcsY0FBYyw4QkFBZCxjQUFjLFFBSXpCIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGVudW0gQ2FsY3VsYXRvclR5cGUge1xuICAgIElOQ09NRV9UQVggPSAnSU5DT01FX1RBWCcsXG4gICAgTU9SVEdBR0UgPSAnTU9SVEdBR0UnLFxuICAgIExPQU4gPSAnTE9BTidcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSdWxlTWV0YSB7XG4gICAgaWQ6IHN0cmluZztcbiAgICBjb3VudHJ5OiBzdHJpbmc7XG4gICAgcmVnaW9uOiBzdHJpbmc7XG4gICAgY2FsY3VsYXRvcjogQ2FsY3VsYXRvclR5cGU7XG4gICAgdmVyc2lvbjogc3RyaW5nO1xuICAgIGVmZmVjdGl2ZWZyb206IHN0cmluZztcbiAgICBlZmZlY3RpdmV0bzogc3RyaW5nIHwgbnVsbDtcbiAgICBzb3VyY2U/OiBSdWxlU291cmNlW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUnVsZVNvdXJjZSB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIHVybDogc3RyaW5nO1xufSJdfQ==
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RuleMeta } from "../../shared/domain/types";
|
|
2
|
+
export interface RuleInput {
|
|
3
|
+
name: string;
|
|
4
|
+
type: 'number' | 'select' | 'text';
|
|
5
|
+
required: boolean;
|
|
6
|
+
unit?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface RuleOutput {
|
|
9
|
+
name: string;
|
|
10
|
+
type: 'number' | 'string';
|
|
11
|
+
unit?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface TaxBracket {
|
|
14
|
+
from: number;
|
|
15
|
+
to: number | null;
|
|
16
|
+
rate: number;
|
|
17
|
+
}
|
|
18
|
+
export interface IncomeTaxCalculatorSchema<T> {
|
|
19
|
+
meta: RuleMeta;
|
|
20
|
+
inputs: RuleInput[];
|
|
21
|
+
outputs: RuleOutput[];
|
|
22
|
+
rules: T;
|
|
23
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RuleMeta } from "../../../shared/domain/types";
|
|
2
|
+
import { RuleInput, RuleOutput, TaxBracket } from "../../domain/types";
|
|
2
3
|
export interface IncomeTaxRules {
|
|
3
4
|
taxBrackets: TaxBracket[];
|
|
4
5
|
quotientFamilial: QuotientFamilial;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { CanadaIncomeTaxServiceImpl as CanadaIncomeTaxService } from './income-tax/canada/CanadaIncomeTaxServiceImpl';
|
|
2
|
+
export { CanadaMortgageServiceImpl as CanadaMortgageService } from './mortgage/canada/CanadaMortgageServiceImpl';
|
|
2
3
|
export { FranceIncomeTaxServiceImpl as FranceIncomeTaxService } from './income-tax/france/FranceIncomeTaxServiceImpl';
|
|
3
4
|
export { ComputedIncomeTaxValues as CanadaComputedIncomeTaxValues, IncomeTaxRules as CanadaIncomeTaxRules, } from './income-tax/canada/domain/types';
|
|
5
|
+
export { MortgageRules as CanadaMortgageRules, MortgageCalculationInput as CanadaMortgageCalculationInput, MortgageCalculationResult as CanadaMortgageCalculationResult, } from './mortgage/canada/domain/types';
|
|
4
6
|
export { ComputedIncomeTaxValues as FranceComputedIncomeTaxValues, IncomeTaxRules as FranceIncomeTaxRules, } from './income-tax/france/domain/types';
|
|
5
|
-
export { IncomeTaxCalculatorSchema } from './domain/types';
|
|
6
|
-
export * from './domain/types';
|
|
7
|
+
export { IncomeTaxCalculatorSchema } from './income-tax/domain/types';
|
|
8
|
+
export * from './income-tax/domain/types';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CanadaMortgageService } from './CanadaMortgageService';
|
|
2
|
+
import { MortgageRules, MortgageCalculationInput, MortgageCalculationResult } from './domain/types';
|
|
3
|
+
export declare class CanadaMortgageServiceImpl implements CanadaMortgageService {
|
|
4
|
+
calculate(input: MortgageCalculationInput, rules: MortgageRules): MortgageCalculationResult;
|
|
5
|
+
private convertCanadianRate;
|
|
6
|
+
private calculatePayment;
|
|
7
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { RuleMeta } from "../../../shared/domain/types";
|
|
2
|
+
export interface RuleInputDefinition {
|
|
3
|
+
type: 'number' | 'string';
|
|
4
|
+
min?: number;
|
|
5
|
+
max?: number;
|
|
6
|
+
enum?: string[];
|
|
7
|
+
}
|
|
8
|
+
export interface RuleInputs {
|
|
9
|
+
propertyPrice: RuleInputDefinition;
|
|
10
|
+
downPayment: RuleInputDefinition;
|
|
11
|
+
interestRate: RuleInputDefinition;
|
|
12
|
+
amortizationYears: RuleInputDefinition;
|
|
13
|
+
paymentFrequency: RuleInputDefinition;
|
|
14
|
+
}
|
|
15
|
+
export interface RuleOutputs {
|
|
16
|
+
loanAmount: 'number';
|
|
17
|
+
insurancePremium: 'number';
|
|
18
|
+
totalMortgage: 'number';
|
|
19
|
+
paymentAmount: 'number';
|
|
20
|
+
totalInterestPaid: 'number';
|
|
21
|
+
totalPaid: 'number';
|
|
22
|
+
}
|
|
23
|
+
export interface LoanConstraints {
|
|
24
|
+
maxAmortizationYears: number;
|
|
25
|
+
insuredMaxAmortizationYears: number;
|
|
26
|
+
minDownPayment: {
|
|
27
|
+
upTo500k: number;
|
|
28
|
+
above500k: number;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export interface MortgageInsuranceRate {
|
|
32
|
+
maxLtv: number;
|
|
33
|
+
rate: number;
|
|
34
|
+
}
|
|
35
|
+
export interface MortgageInsuranceRules {
|
|
36
|
+
requiredBelowLtv: number;
|
|
37
|
+
premiumRates: MortgageInsuranceRate[];
|
|
38
|
+
premiumAddedToLoan: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface MortgageRules {
|
|
41
|
+
loanConstraints: LoanConstraints;
|
|
42
|
+
mortgageInsurance: MortgageInsuranceRules;
|
|
43
|
+
interest: InterestRules;
|
|
44
|
+
paymentFrequencyRules: PaymentFrequencyRules;
|
|
45
|
+
stressTest: StressTestRules;
|
|
46
|
+
}
|
|
47
|
+
export interface InterestRules {
|
|
48
|
+
compounding: 'SEMI_ANNUAL' | 'ANNUAL' | 'MONTHLY';
|
|
49
|
+
conversionFormula: 'CANADA_STANDARD' | string;
|
|
50
|
+
}
|
|
51
|
+
export interface PaymentFrequencyRule {
|
|
52
|
+
paymentsPerYear: number;
|
|
53
|
+
acceleration?: boolean;
|
|
54
|
+
}
|
|
55
|
+
export interface PaymentFrequencyRules {
|
|
56
|
+
MONTHLY: PaymentFrequencyRule;
|
|
57
|
+
BI_WEEKLY: PaymentFrequencyRule;
|
|
58
|
+
ACCELERATED_BI_WEEKLY: PaymentFrequencyRule;
|
|
59
|
+
}
|
|
60
|
+
export interface StressTestRules {
|
|
61
|
+
apply: boolean;
|
|
62
|
+
minimumRateBuffer: number;
|
|
63
|
+
minimumQualifyingRate: number;
|
|
64
|
+
}
|
|
65
|
+
export interface MortgageRuleSet {
|
|
66
|
+
meta: RuleMeta;
|
|
67
|
+
inputs: RuleInputs;
|
|
68
|
+
rules: MortgageRules;
|
|
69
|
+
outputs: RuleOutputs;
|
|
70
|
+
}
|
|
71
|
+
export interface MortgageCalculationInput {
|
|
72
|
+
propertyPrice: number;
|
|
73
|
+
downPayment: number;
|
|
74
|
+
interestRate: number;
|
|
75
|
+
amortizationYears: number;
|
|
76
|
+
paymentFrequency: 'MONTHLY' | 'BI_WEEKLY' | 'ACCELERATED_BI_WEEKLY';
|
|
77
|
+
}
|
|
78
|
+
export interface MortgageCalculationResult {
|
|
79
|
+
loanAmount: number;
|
|
80
|
+
insurancePremium: number;
|
|
81
|
+
totalMortgage: number;
|
|
82
|
+
paymentAmount: number;
|
|
83
|
+
totalInterestPaid: number;
|
|
84
|
+
totalPaid: number;
|
|
85
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare enum CalculatorType {
|
|
2
|
+
INCOME_TAX = "INCOME_TAX",
|
|
3
|
+
MORTGAGE = "MORTGAGE",
|
|
4
|
+
LOAN = "LOAN"
|
|
5
|
+
}
|
|
6
|
+
export interface RuleMeta {
|
|
7
|
+
id: string;
|
|
8
|
+
country: string;
|
|
9
|
+
region: string;
|
|
10
|
+
calculator: CalculatorType;
|
|
11
|
+
version: string;
|
|
12
|
+
effectivefrom: string;
|
|
13
|
+
effectiveto: string | null;
|
|
14
|
+
source?: RuleSource[];
|
|
15
|
+
}
|
|
16
|
+
export interface RuleSource {
|
|
17
|
+
name: string;
|
|
18
|
+
url: string;
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TaxBracket } from "../../domain/types";
|
|
2
2
|
|
|
3
3
|
export interface IncomeTaxRules {
|
|
4
4
|
taxBrackets: TaxBracket[];
|
|
@@ -38,3 +38,4 @@ export interface ComputedIncomeTaxValues {
|
|
|
38
38
|
netIncome: number;
|
|
39
39
|
effectiveTaxRate: number;
|
|
40
40
|
}
|
|
41
|
+
|
|
@@ -1,24 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
INCOME_TAX = 'INCOME_TAX',
|
|
3
|
-
MORTGAGE = 'MORTGAGE',
|
|
4
|
-
LOAN = 'LOAN'
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface RuleMeta {
|
|
8
|
-
id: string;
|
|
9
|
-
country: string;
|
|
10
|
-
region: string;
|
|
11
|
-
calculator: CalculatorType;
|
|
12
|
-
version: string;
|
|
13
|
-
effectivefrom: string;
|
|
14
|
-
effectiveto: string | null;
|
|
15
|
-
source?: RuleSource[];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface RuleSource {
|
|
19
|
-
name: string;
|
|
20
|
-
url: string;
|
|
21
|
-
}
|
|
1
|
+
import { RuleMeta } from "../../shared/domain/types";
|
|
22
2
|
|
|
23
3
|
export interface RuleInput {
|
|
24
4
|
name: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RuleMeta } from "../../../shared/domain/types";
|
|
2
|
+
import { RuleInput, RuleOutput, TaxBracket } from "../../domain/types";
|
|
2
3
|
|
|
3
4
|
export interface IncomeTaxRules {
|
|
4
5
|
taxBrackets: TaxBracket[];
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
export { CanadaIncomeTaxServiceImpl as CanadaIncomeTaxService } from './income-tax/canada/CanadaIncomeTaxServiceImpl';
|
|
2
|
+
export { CanadaMortgageServiceImpl as CanadaMortgageService } from './mortgage/canada/CanadaMortgageServiceImpl';
|
|
2
3
|
export { FranceIncomeTaxServiceImpl as FranceIncomeTaxService } from './income-tax/france/FranceIncomeTaxServiceImpl';
|
|
3
4
|
export {
|
|
4
5
|
ComputedIncomeTaxValues as CanadaComputedIncomeTaxValues,
|
|
5
6
|
IncomeTaxRules as CanadaIncomeTaxRules,
|
|
6
7
|
} from './income-tax/canada/domain/types';
|
|
8
|
+
export {
|
|
9
|
+
MortgageRules as CanadaMortgageRules,
|
|
10
|
+
MortgageCalculationInput as CanadaMortgageCalculationInput,
|
|
11
|
+
MortgageCalculationResult as CanadaMortgageCalculationResult,
|
|
12
|
+
} from './mortgage/canada/domain/types';
|
|
7
13
|
export {
|
|
8
14
|
ComputedIncomeTaxValues as FranceComputedIncomeTaxValues,
|
|
9
15
|
IncomeTaxRules as FranceIncomeTaxRules,
|
|
10
16
|
} from './income-tax/france/domain/types';
|
|
11
|
-
export { IncomeTaxCalculatorSchema } from './domain/types';
|
|
12
|
-
export * from './domain/types';
|
|
17
|
+
export { IncomeTaxCalculatorSchema } from './income-tax/domain/types';
|
|
18
|
+
export * from './income-tax/domain/types';
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { CanadaMortgageService } from './CanadaMortgageService';
|
|
2
|
+
import {
|
|
3
|
+
MortgageRules,
|
|
4
|
+
MortgageCalculationInput,
|
|
5
|
+
MortgageCalculationResult
|
|
6
|
+
} from './domain/types';
|
|
7
|
+
|
|
8
|
+
export class CanadaMortgageServiceImpl implements CanadaMortgageService {
|
|
9
|
+
|
|
10
|
+
public calculate(input: MortgageCalculationInput, rules: MortgageRules): MortgageCalculationResult {
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
propertyPrice,
|
|
14
|
+
downPayment,
|
|
15
|
+
interestRate,
|
|
16
|
+
amortizationYears,
|
|
17
|
+
paymentFrequency
|
|
18
|
+
} = input;
|
|
19
|
+
|
|
20
|
+
/* -----------------------------
|
|
21
|
+
1. Loan Amount & LTV
|
|
22
|
+
------------------------------ */
|
|
23
|
+
|
|
24
|
+
const loanAmount = propertyPrice - downPayment;
|
|
25
|
+
if (loanAmount <= 0) {
|
|
26
|
+
throw new Error('Invalid loan amount');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const ltv = loanAmount / propertyPrice;
|
|
30
|
+
|
|
31
|
+
/* -----------------------------
|
|
32
|
+
2. CMHC Insurance
|
|
33
|
+
------------------------------ */
|
|
34
|
+
|
|
35
|
+
let insurancePremium = 0;
|
|
36
|
+
|
|
37
|
+
if (ltv > rules.mortgageInsurance.requiredBelowLtv) {
|
|
38
|
+
const premiumRule = rules.mortgageInsurance.premiumRates
|
|
39
|
+
.find(r => ltv <= r.maxLtv);
|
|
40
|
+
|
|
41
|
+
if (!premiumRule) {
|
|
42
|
+
throw new Error('LTV exceeds maximum insurable limit');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
insurancePremium = loanAmount * premiumRule.rate;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const totalMortgage = rules.mortgageInsurance.premiumAddedToLoan
|
|
49
|
+
? loanAmount + insurancePremium
|
|
50
|
+
: loanAmount;
|
|
51
|
+
|
|
52
|
+
/* -----------------------------
|
|
53
|
+
3. Interest Rate Conversion
|
|
54
|
+
(Canada semi-annual compounding)
|
|
55
|
+
------------------------------ */
|
|
56
|
+
|
|
57
|
+
const periodicRate = this.convertCanadianRate(
|
|
58
|
+
interestRate,
|
|
59
|
+
rules.interest.compounding,
|
|
60
|
+
rules.paymentFrequencyRules[paymentFrequency].paymentsPerYear
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
/* -----------------------------
|
|
64
|
+
4. Payment Frequency
|
|
65
|
+
------------------------------ */
|
|
66
|
+
|
|
67
|
+
const frequencyRule = rules.paymentFrequencyRules[paymentFrequency];
|
|
68
|
+
const paymentsPerYear = frequencyRule.paymentsPerYear;
|
|
69
|
+
const totalPayments = amortizationYears * paymentsPerYear;
|
|
70
|
+
|
|
71
|
+
/* -----------------------------
|
|
72
|
+
5. Mortgage Payment Formula
|
|
73
|
+
P = L × [ r(1+r)^n ] / [ (1+r)^n − 1 ]
|
|
74
|
+
------------------------------ */
|
|
75
|
+
|
|
76
|
+
const paymentAmount = this.calculatePayment(
|
|
77
|
+
totalMortgage,
|
|
78
|
+
periodicRate,
|
|
79
|
+
totalPayments
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
/* -----------------------------
|
|
83
|
+
6. Totals
|
|
84
|
+
------------------------------ */
|
|
85
|
+
|
|
86
|
+
const totalPaid = paymentAmount * totalPayments;
|
|
87
|
+
const totalInterestPaid = totalPaid - totalMortgage;
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
loanAmount: loanAmount,
|
|
91
|
+
insurancePremium: insurancePremium,
|
|
92
|
+
totalMortgage: totalMortgage,
|
|
93
|
+
paymentAmount: paymentAmount,
|
|
94
|
+
totalInterestPaid: totalInterestPaid,
|
|
95
|
+
totalPaid: totalPaid
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* ======================================================
|
|
100
|
+
Helper Methods
|
|
101
|
+
====================================================== */
|
|
102
|
+
|
|
103
|
+
private convertCanadianRate(
|
|
104
|
+
annualRate: number,
|
|
105
|
+
compounding: 'SEMI_ANNUAL' | 'ANNUAL' | 'MONTHLY',
|
|
106
|
+
paymentsPerYear: number
|
|
107
|
+
): number {
|
|
108
|
+
|
|
109
|
+
if (compounding !== 'SEMI_ANNUAL') {
|
|
110
|
+
throw new Error('Only Canadian semi-annual compounding supported');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Canadian standard conversion
|
|
114
|
+
const semiAnnualRate = annualRate / 2;
|
|
115
|
+
const effectiveAnnualRate = Math.pow(1 + semiAnnualRate, 2) - 1;
|
|
116
|
+
|
|
117
|
+
return Math.pow(1 + effectiveAnnualRate, 1 / paymentsPerYear) - 1;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private calculatePayment(principal: number, rate: number, periods: number): number {
|
|
121
|
+
if (rate === 0) {
|
|
122
|
+
return principal / periods;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return principal *
|
|
126
|
+
(rate * Math.pow(1 + rate, periods)) /
|
|
127
|
+
(Math.pow(1 + rate, periods) - 1);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { RuleMeta } from "../../../shared/domain/types";
|
|
2
|
+
|
|
3
|
+
export interface RuleInputDefinition {
|
|
4
|
+
type: 'number' | 'string';
|
|
5
|
+
min?: number;
|
|
6
|
+
max?: number;
|
|
7
|
+
enum?: string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface RuleInputs {
|
|
11
|
+
propertyPrice: RuleInputDefinition;
|
|
12
|
+
downPayment: RuleInputDefinition;
|
|
13
|
+
interestRate: RuleInputDefinition;
|
|
14
|
+
amortizationYears: RuleInputDefinition;
|
|
15
|
+
paymentFrequency: RuleInputDefinition;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RuleOutputs {
|
|
19
|
+
loanAmount: 'number';
|
|
20
|
+
insurancePremium: 'number';
|
|
21
|
+
totalMortgage: 'number';
|
|
22
|
+
paymentAmount: 'number';
|
|
23
|
+
totalInterestPaid: 'number';
|
|
24
|
+
totalPaid: 'number';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface LoanConstraints {
|
|
28
|
+
maxAmortizationYears: number;
|
|
29
|
+
insuredMaxAmortizationYears: number;
|
|
30
|
+
minDownPayment: {
|
|
31
|
+
upTo500k: number;
|
|
32
|
+
above500k: number;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface MortgageInsuranceRate {
|
|
37
|
+
maxLtv: number;
|
|
38
|
+
rate: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface MortgageInsuranceRules {
|
|
42
|
+
requiredBelowLtv: number;
|
|
43
|
+
premiumRates: MortgageInsuranceRate[];
|
|
44
|
+
premiumAddedToLoan: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
export interface MortgageRules {
|
|
49
|
+
loanConstraints: LoanConstraints;
|
|
50
|
+
mortgageInsurance: MortgageInsuranceRules;
|
|
51
|
+
interest: InterestRules;
|
|
52
|
+
paymentFrequencyRules: PaymentFrequencyRules;
|
|
53
|
+
stressTest: StressTestRules;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface InterestRules {
|
|
57
|
+
compounding: 'SEMI_ANNUAL' | 'ANNUAL' | 'MONTHLY';
|
|
58
|
+
conversionFormula: 'CANADA_STANDARD' | string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface PaymentFrequencyRule {
|
|
62
|
+
paymentsPerYear: number;
|
|
63
|
+
acceleration?: boolean;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface PaymentFrequencyRules {
|
|
67
|
+
MONTHLY: PaymentFrequencyRule;
|
|
68
|
+
BI_WEEKLY: PaymentFrequencyRule;
|
|
69
|
+
ACCELERATED_BI_WEEKLY: PaymentFrequencyRule;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface StressTestRules {
|
|
73
|
+
apply: boolean;
|
|
74
|
+
minimumRateBuffer: number;
|
|
75
|
+
minimumQualifyingRate: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface MortgageRuleSet {
|
|
79
|
+
meta: RuleMeta;
|
|
80
|
+
inputs: RuleInputs;
|
|
81
|
+
rules: MortgageRules;
|
|
82
|
+
outputs: RuleOutputs;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface MortgageCalculationInput {
|
|
86
|
+
propertyPrice: number;
|
|
87
|
+
downPayment: number;
|
|
88
|
+
interestRate: number; // Annual nominal rate (e.g. 0.052)
|
|
89
|
+
amortizationYears: number;
|
|
90
|
+
paymentFrequency: 'MONTHLY' | 'BI_WEEKLY' | 'ACCELERATED_BI_WEEKLY';
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface MortgageCalculationResult {
|
|
94
|
+
loanAmount: number;
|
|
95
|
+
insurancePremium: number;
|
|
96
|
+
totalMortgage: number;
|
|
97
|
+
paymentAmount: number;
|
|
98
|
+
totalInterestPaid: number;
|
|
99
|
+
totalPaid: number;
|
|
100
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export enum CalculatorType {
|
|
2
|
+
INCOME_TAX = 'INCOME_TAX',
|
|
3
|
+
MORTGAGE = 'MORTGAGE',
|
|
4
|
+
LOAN = 'LOAN'
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface RuleMeta {
|
|
8
|
+
id: string;
|
|
9
|
+
country: string;
|
|
10
|
+
region: string;
|
|
11
|
+
calculator: CalculatorType;
|
|
12
|
+
version: string;
|
|
13
|
+
effectivefrom: string;
|
|
14
|
+
effectiveto: string | null;
|
|
15
|
+
source?: RuleSource[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RuleSource {
|
|
19
|
+
name: string;
|
|
20
|
+
url: string;
|
|
21
|
+
}
|