@novha/calc-engines 1.2.1 → 1.3.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.
@@ -48,4 +48,4 @@ class CanadaIncomeTaxServiceImpl {
48
48
  }
49
49
  }
50
50
  exports.CanadaIncomeTaxServiceImpl = CanadaIncomeTaxServiceImpl;
51
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2FuYWRhSW5jb21lVGF4U2VydmljZUltcGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaW5jb21lLXRheC9jYW5hZGEvQ2FuYWRhSW5jb21lVGF4U2VydmljZUltcGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBV0EsTUFBYSwwQkFBMEI7SUFJbkMsWUFBWSxNQUFjLEVBQUUsS0FBcUI7UUFDN0MsSUFBSSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7UUFDdEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7SUFDeEIsQ0FBQztJQUVNLGtCQUFrQjtRQUVyQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM3RSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2hFLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUMxRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFdkUsT0FBTztZQUNILFdBQVcsRUFBRSxJQUFJLENBQUMsT0FBTztZQUN6QixTQUFTLEVBQUUsTUFBTTtZQUNqQixHQUFHO1lBQ0gsRUFBRTtZQUNGLGVBQWUsRUFBRSxNQUFNLEdBQUcsR0FBRyxHQUFHLEVBQUU7WUFDbEMsU0FBUyxFQUFFLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxHQUFHLEdBQUcsR0FBRyxFQUFFO1lBQzNDLGdCQUFnQixFQUFFLE1BQU0sR0FBRyxJQUFJLENBQUMsT0FBTztTQUMxQyxDQUFDO0lBQ04sQ0FBQztJQUVPLGVBQWUsQ0FBQyxNQUFjLEVBQUUsUUFBc0I7UUFDMUQsT0FBTyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ2hDLElBQUksTUFBTSxJQUFJLENBQUMsQ0FBQyxJQUFJO2dCQUFFLE9BQU8sS0FBSyxDQUFDO1lBRW5DLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksTUFBTSxDQUFDO1lBQzdCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFFakQsT0FBTyxLQUFLLEdBQUcsT0FBTyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDcEMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ1YsQ0FBQztJQUVPLFlBQVksQ0FBQyxHQUFXLEVBQUUsVUFBcUMsRUFBRTtRQUNyRSxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FDOUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsSUFBSSxFQUNuQyxDQUFDLENBQ0osQ0FBQztRQUVGLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxHQUFHLFlBQVksQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFTyxVQUFVLENBQUMsTUFBYyxFQUFFLEdBQXFCO1FBQ3BELElBQUksQ0FBQyxHQUFHLElBQUksTUFBTSxJQUFJLEdBQUcsQ0FBQyxTQUFTO1lBQUUsT0FBTyxDQUFDLENBQUM7UUFFOUMsTUFBTSxhQUFhLEdBQUcsTUFBTSxHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUM7UUFDN0MsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUNYLGFBQWEsR0FBRyxHQUFHLENBQUMsSUFBSSxFQUN4QixHQUFHLENBQUMsZUFBZSxDQUN0QixDQUFDO0lBQ04sQ0FBQztJQUVPLFNBQVMsQ0FBQyxNQUFjLEVBQUUsRUFBbUI7UUFDakQsSUFBSSxDQUFDLEVBQUU7WUFBRSxPQUFPLENBQUMsQ0FBQztRQUVsQixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUM1QixNQUFNLEVBQ04sRUFBRSxDQUFDLG9CQUFvQixDQUMxQixDQUFDO1FBRUYsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUNYLGVBQWUsR0FBRyxFQUFFLENBQUMsSUFBSSxFQUN6QixFQUFFLENBQUMsZUFBZSxDQUNyQixDQUFDO0lBQ04sQ0FBQztDQUNKO0FBdEVELGdFQXNFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRheEJyYWNrZXQgfSBmcm9tIFwiLi4vLi4vZG9tYWluL3R5cGVzXCI7XG5pbXBvcnQgeyBDYW5hZGFJbmNvbWVUYXhTZXJ2aWNlIH0gZnJvbSBcIi4vQ2FuYWRhSW5jb21lVGF4U2VydmljZVwiO1xuaW1wb3J0IHtcbiAgICBDUFBDb250cmlidXRpb24sXG4gICAgQ29tcHV0ZWRJbmNvbWVUYXhWYWx1ZXMsXG4gICAgRUlDb250cmlidXRpb24sXG4gICAgSW5jb21lVGF4UnVsZXMsXG4gICAgVGF4Q3JlZGl0XG59IGZyb20gXCIuL2RvbWFpbi90eXBlc1wiO1xuXG5cbmV4cG9ydCBjbGFzcyBDYW5hZGFJbmNvbWVUYXhTZXJ2aWNlSW1wbCBpbXBsZW1lbnRzIENhbmFkYUluY29tZVRheFNlcnZpY2Uge1xuICAgIHByaXZhdGUgX2luY29tZTogbnVtYmVyO1xuICAgIHByaXZhdGUgX3J1bGVzOiBJbmNvbWVUYXhSdWxlcztcblxuICAgIGNvbnN0cnVjdG9yKGluY29tZTogbnVtYmVyLCBydWxlczogSW5jb21lVGF4UnVsZXMpIHtcbiAgICAgICAgdGhpcy5faW5jb21lID0gaW5jb21lO1xuICAgICAgICB0aGlzLl9ydWxlcyA9IHJ1bGVzO1xuICAgIH1cblxuICAgIHB1YmxpYyBjYWxjdWxhdGVOZXRJbmNvbWUoKTogQ29tcHV0ZWRJbmNvbWVUYXhWYWx1ZXMge1xuXG4gICAgICAgIGNvbnN0IGdyb3NzVGF4ID0gdGhpcy5jb21wdXRlR3Jvc3NUYXgodGhpcy5faW5jb21lLCB0aGlzLl9ydWxlcy50YXhCcmFja2V0cyk7XG4gICAgICAgIGNvbnN0IG5ldFRheCA9IHRoaXMuYXBwbHlDcmVkaXRzKGdyb3NzVGF4LCB0aGlzLl9ydWxlcy5jcmVkaXRzKTtcbiAgICAgICAgY29uc3QgY3BwID0gdGhpcy5jb21wdXRlQ1BQKHRoaXMuX2luY29tZSwgdGhpcy5fcnVsZXMuY29udHJpYnV0aW9ucz8uY3BwKTtcbiAgICAgICAgY29uc3QgZWkgPSB0aGlzLmNvbXB1dGVFSSh0aGlzLl9pbmNvbWUsIHRoaXMuX3J1bGVzLmNvbnRyaWJ1dGlvbnM/LmVpKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZ3Jvc3NJbmNvbWU6IHRoaXMuX2luY29tZSxcbiAgICAgICAgICAgIGluY29tZVRheDogbmV0VGF4LFxuICAgICAgICAgICAgY3BwLFxuICAgICAgICAgICAgZWksXG4gICAgICAgICAgICB0b3RhbERlZHVjdGlvbnM6IG5ldFRheCArIGNwcCArIGVpLFxuICAgICAgICAgICAgbmV0SW5jb21lOiB0aGlzLl9pbmNvbWUgLSBuZXRUYXggLSBjcHAgLSBlaSxcbiAgICAgICAgICAgIGVmZmVjdGl2ZVRheFJhdGU6IG5ldFRheCAvIHRoaXMuX2luY29tZSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNvbXB1dGVHcm9zc1RheChpbmNvbWU6IG51bWJlciwgYnJhY2tldHM6IFRheEJyYWNrZXRbXSk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBicmFja2V0cy5yZWR1Y2UoKHRvdGFsLCBiKSA9PiB7XG4gICAgICAgICAgICBpZiAoaW5jb21lIDw9IGIuZnJvbSkgcmV0dXJuIHRvdGFsO1xuICAgIFxuICAgICAgICAgICAgY29uc3QgdXBwZXIgPSBiLnRvID8/IGluY29tZTtcbiAgICAgICAgICAgIGNvbnN0IHRheGFibGUgPSBNYXRoLm1pbihpbmNvbWUsIHVwcGVyKSAtIGIuZnJvbTtcbiAgICBcbiAgICAgICAgICAgIHJldHVybiB0b3RhbCArIHRheGFibGUgKiBiLnJhdGU7XG4gICAgICAgIH0sIDApO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXBwbHlDcmVkaXRzKHRheDogbnVtYmVyLCBjcmVkaXRzOiBSZWNvcmQ8c3RyaW5nLCBUYXhDcmVkaXQ+ID0ge30pOiBudW1iZXIge1xuICAgICAgICBjb25zdCB0b3RhbENyZWRpdHMgPSBPYmplY3QudmFsdWVzKGNyZWRpdHMpLnJlZHVjZShcbiAgICAgICAgICAgIChzdW0sIGMpID0+IHN1bSArIGMuYW1vdW50ICogYy5yYXRlLFxuICAgICAgICAgICAgMCxcbiAgICAgICAgKTtcbiAgICBcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KDAsIHRheCAtIHRvdGFsQ3JlZGl0cyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb21wdXRlQ1BQKGluY29tZTogbnVtYmVyLCBjcHA/OiBDUFBDb250cmlidXRpb24pOiBudW1iZXIge1xuICAgICAgICBpZiAoIWNwcCB8fCBpbmNvbWUgPD0gY3BwLmV4ZW1wdGlvbikgcmV0dXJuIDA7XG4gICAgXG4gICAgICAgIGNvbnN0IGNvbnRyaWJ1dGFibGUgPSBpbmNvbWUgLSBjcHAuZXhlbXB0aW9uO1xuICAgICAgICByZXR1cm4gTWF0aC5taW4oXG4gICAgICAgICAgICBjb250cmlidXRhYmxlICogY3BwLnJhdGUsXG4gICAgICAgICAgICBjcHAubWF4Q29udHJpYnV0aW9uLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgY29tcHV0ZUVJKGluY29tZTogbnVtYmVyLCBlaT86IEVJQ29udHJpYnV0aW9uKTogbnVtYmVyIHtcbiAgICAgICAgaWYgKCFlaSkgcmV0dXJuIDA7XG4gICAgXG4gICAgICAgIGNvbnN0IGluc3VyYWJsZUluY29tZSA9IE1hdGgubWluKFxuICAgICAgICAgICAgaW5jb21lLFxuICAgICAgICAgICAgZWkubWF4SW5zdXJhYmxlRWFybmluZ3MsXG4gICAgICAgICk7XG4gICAgXG4gICAgICAgIHJldHVybiBNYXRoLm1pbihcbiAgICAgICAgICAgIGluc3VyYWJsZUluY29tZSAqIGVpLnJhdGUsXG4gICAgICAgICAgICBlaS5tYXhDb250cmlidXRpb24sXG4gICAgICAgICk7XG4gICAgfVxufSJdfQ==
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaW5jb21lLXRheC9jYW5hZGEvZG9tYWluL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBSdWxlSW5wdXQsIFJ1bGVNZXRhLCBSdWxlT3V0cHV0LCBUYXhCcmFja2V0IH0gZnJvbSBcIi4uLy4uLy4uL2RvbWFpbi90eXBlc1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIEluY29tZVRheFJ1bGVzIHtcbiAgICB0YXhCcmFja2V0czogVGF4QnJhY2tldFtdO1xuICAgIGNyZWRpdHM/OiBSZWNvcmQ8c3RyaW5nLCBUYXhDcmVkaXQ+O1xuICAgIGNvbnRyaWJ1dGlvbnM/OiBDb250cmlidXRpb25zO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRheENyZWRpdCB7XG4gICAgYW1vdW50OiBudW1iZXI7XG4gICAgdHlwZTogJ25vblJlZnVuZGFibGUnIHwgJ3JlZnVuZGFibGUnO1xuICAgIHJhdGU6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb250cmlidXRpb25zIHtcbiAgICBjcHA/OiBDUFBDb250cmlidXRpb247XG4gICAgZWk/OiBFSUNvbnRyaWJ1dGlvbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDUFBDb250cmlidXRpb24ge1xuICAgIHJhdGU6IG51bWJlcjtcbiAgICBtYXhDb250cmlidXRpb246IG51bWJlcjtcbiAgICBleGVtcHRpb246IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFSUNvbnRyaWJ1dGlvbiB7XG4gICAgcmF0ZTogbnVtYmVyO1xuICAgIG1heEluc3VyYWJsZUVhcm5pbmdzOiBudW1iZXI7XG4gICAgbWF4Q29udHJpYnV0aW9uOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcHV0ZWRJbmNvbWVUYXhWYWx1ZXMge1xuICAgIGdyb3NzSW5jb21lOiBudW1iZXI7XG4gICAgaW5jb21lVGF4OiBudW1iZXI7XG4gICAgY3BwOiBudW1iZXI7XG4gICAgZWk6IG51bWJlcjtcbiAgICB0b3RhbERlZHVjdGlvbnM6IG51bWJlcjtcbiAgICBuZXRJbmNvbWU6IG51bWJlcjtcbiAgICBlZmZlY3RpdmVUYXhSYXRlOiBudW1iZXI7XG59XG4iXX0=
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaW5jb21lLXRheC9mcmFuY2UvZG9tYWluL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBSdWxlSW5wdXQsIFJ1bGVNZXRhLCBSdWxlT3V0cHV0LCBUYXhCcmFja2V0IH0gZnJvbSBcIi4uLy4uLy4uL2RvbWFpbi90eXBlc1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIEluY29tZVRheFJ1bGVzIHtcbiAgICB0YXhCcmFja2V0czogVGF4QnJhY2tldFtdO1xuICAgIHF1b3RpZW50RmFtaWxpYWw6IFF1b3RpZW50RmFtaWxpYWw7XG4gICAgc29jaWFsQ29udHJpYnV0aW9uczogQ29udHJpYnV0aW9ucztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb250cmlidXRpb25zIHtcbiAgICBlbXBsb3llZTogeyByYXRlOiBudW1iZXI7IH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUXVvdGllbnRGYW1pbGlhbCB7XG4gICAgZW5hYmxlZDogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbmNvbWVUYXhDYWxjdWxhdG9yU2NoZW1hIHtcbiAgICBtZXRhOiBSdWxlTWV0YTtcbiAgICBpbnB1dHM6IFJ1bGVJbnB1dFtdO1xuICAgIG91dHB1dHM6IFJ1bGVPdXRwdXRbXTtcbiAgICBydWxlczogSW5jb21lVGF4UnVsZXM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcHV0ZWRJbmNvbWVUYXhWYWx1ZXMge1xuICAgIGdyb3NzSW5jb21lOiBudW1iZXI7XG5cdGluY29tZVRheDogbnVtYmVyO1xuXHRzb2NpYWxDb250cmlidXRpb25zOiBudW1iZXI7XG5cdHRvdGFsRGVkdWN0aW9uczogbnVtYmVyO1xuXHRuZXRJbmNvbWU6IG51bWJlcjtcblx0YXZlcmFnZVRheFJhdGU6IG51bWJlcjtcblx0bWFyZ2luYWxUYXhSYXRlOiBudW1iZXI7XG59Il19
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaW5jb21lLXRheC9mcmFuY2UvZG9tYWluL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBSdWxlTWV0YSB9IGZyb20gXCIuLi8uLi8uLi9zaGFyZWQvZG9tYWluL3R5cGVzXCI7XG5pbXBvcnQgeyBSdWxlSW5wdXQsIFJ1bGVPdXRwdXQsIFRheEJyYWNrZXQgfSBmcm9tIFwiLi4vLi4vZG9tYWluL3R5cGVzXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5jb21lVGF4UnVsZXMge1xuICAgIHRheEJyYWNrZXRzOiBUYXhCcmFja2V0W107XG4gICAgcXVvdGllbnRGYW1pbGlhbDogUXVvdGllbnRGYW1pbGlhbDtcbiAgICBzb2NpYWxDb250cmlidXRpb25zOiBDb250cmlidXRpb25zO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbnRyaWJ1dGlvbnMge1xuICAgIGVtcGxveWVlOiB7IHJhdGU6IG51bWJlcjsgfTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBRdW90aWVudEZhbWlsaWFsIHtcbiAgICBlbmFibGVkOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEluY29tZVRheENhbGN1bGF0b3JTY2hlbWEge1xuICAgIG1ldGE6IFJ1bGVNZXRhO1xuICAgIGlucHV0czogUnVsZUlucHV0W107XG4gICAgb3V0cHV0czogUnVsZU91dHB1dFtdO1xuICAgIHJ1bGVzOiBJbmNvbWVUYXhSdWxlcztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb21wdXRlZEluY29tZVRheFZhbHVlcyB7XG4gICAgZ3Jvc3NJbmNvbWU6IG51bWJlcjtcblx0aW5jb21lVGF4OiBudW1iZXI7XG5cdHNvY2lhbENvbnRyaWJ1dGlvbnM6IG51bWJlcjtcblx0dG90YWxEZWR1Y3Rpb25zOiBudW1iZXI7XG5cdG5ldEluY29tZTogbnVtYmVyO1xuXHRhdmVyYWdlVGF4UmF0ZTogbnVtYmVyO1xuXHRtYXJnaW5hbFRheFJhdGU6IG51bWJlcjtcbn0iXX0=
package/dist/index.js CHANGED
@@ -19,5 +19,5 @@ var CanadaIncomeTaxServiceImpl_1 = require("./income-tax/canada/CanadaIncomeTaxS
19
19
  Object.defineProperty(exports, "CanadaIncomeTaxService", { enumerable: true, get: function () { return CanadaIncomeTaxServiceImpl_1.CanadaIncomeTaxServiceImpl; } });
20
20
  var FranceIncomeTaxServiceImpl_1 = require("./income-tax/france/FranceIncomeTaxServiceImpl");
21
21
  Object.defineProperty(exports, "FranceIncomeTaxService", { enumerable: true, get: function () { return FranceIncomeTaxServiceImpl_1.FranceIncomeTaxServiceImpl; } });
22
- __exportStar(require("./domain/types"), exports);
23
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSw2RkFBc0g7QUFBN0csb0lBQUEsMEJBQTBCLE9BQTBCO0FBQzdELDZGQUFzSDtBQUE3RyxvSUFBQSwwQkFBMEIsT0FBMEI7QUFVN0QsaURBQStCIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgQ2FuYWRhSW5jb21lVGF4U2VydmljZUltcGwgYXMgQ2FuYWRhSW5jb21lVGF4U2VydmljZSB9IGZyb20gJy4vaW5jb21lLXRheC9jYW5hZGEvQ2FuYWRhSW5jb21lVGF4U2VydmljZUltcGwnO1xuZXhwb3J0IHsgRnJhbmNlSW5jb21lVGF4U2VydmljZUltcGwgYXMgRnJhbmNlSW5jb21lVGF4U2VydmljZSB9IGZyb20gJy4vaW5jb21lLXRheC9mcmFuY2UvRnJhbmNlSW5jb21lVGF4U2VydmljZUltcGwnO1xuZXhwb3J0IHtcbiAgICBDb21wdXRlZEluY29tZVRheFZhbHVlcyBhcyBDYW5hZGFDb21wdXRlZEluY29tZVRheFZhbHVlcyxcbiAgICBJbmNvbWVUYXhSdWxlcyBhcyBDYW5hZGFJbmNvbWVUYXhSdWxlcyxcbn0gZnJvbSAnLi9pbmNvbWUtdGF4L2NhbmFkYS9kb21haW4vdHlwZXMnO1xuZXhwb3J0IHsgXG4gICAgQ29tcHV0ZWRJbmNvbWVUYXhWYWx1ZXMgYXMgRnJhbmNlQ29tcHV0ZWRJbmNvbWVUYXhWYWx1ZXMsXG4gICAgSW5jb21lVGF4UnVsZXMgYXMgRnJhbmNlSW5jb21lVGF4UnVsZXMsXG59IGZyb20gJy4vaW5jb21lLXRheC9mcmFuY2UvZG9tYWluL3R5cGVzJztcbmV4cG9ydCB7IEluY29tZVRheENhbGN1bGF0b3JTY2hlbWEgfSBmcm9tICcuL2RvbWFpbi90eXBlcyc7XG5leHBvcnQgKiBmcm9tICcuL2RvbWFpbi90eXBlcyc7Il19
22
+ __exportStar(require("./income-tax/domain/types"), exports);
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSw2RkFBc0g7QUFBN0csb0lBQUEsMEJBQTBCLE9BQTBCO0FBQzdELDZGQUFzSDtBQUE3RyxvSUFBQSwwQkFBMEIsT0FBMEI7QUFVN0QsNERBQTBDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgQ2FuYWRhSW5jb21lVGF4U2VydmljZUltcGwgYXMgQ2FuYWRhSW5jb21lVGF4U2VydmljZSB9IGZyb20gJy4vaW5jb21lLXRheC9jYW5hZGEvQ2FuYWRhSW5jb21lVGF4U2VydmljZUltcGwnO1xuZXhwb3J0IHsgRnJhbmNlSW5jb21lVGF4U2VydmljZUltcGwgYXMgRnJhbmNlSW5jb21lVGF4U2VydmljZSB9IGZyb20gJy4vaW5jb21lLXRheC9mcmFuY2UvRnJhbmNlSW5jb21lVGF4U2VydmljZUltcGwnO1xuZXhwb3J0IHtcbiAgICBDb21wdXRlZEluY29tZVRheFZhbHVlcyBhcyBDYW5hZGFDb21wdXRlZEluY29tZVRheFZhbHVlcyxcbiAgICBJbmNvbWVUYXhSdWxlcyBhcyBDYW5hZGFJbmNvbWVUYXhSdWxlcyxcbn0gZnJvbSAnLi9pbmNvbWUtdGF4L2NhbmFkYS9kb21haW4vdHlwZXMnO1xuZXhwb3J0IHsgXG4gICAgQ29tcHV0ZWRJbmNvbWVUYXhWYWx1ZXMgYXMgRnJhbmNlQ29tcHV0ZWRJbmNvbWVUYXhWYWx1ZXMsXG4gICAgSW5jb21lVGF4UnVsZXMgYXMgRnJhbmNlSW5jb21lVGF4UnVsZXMsXG59IGZyb20gJy4vaW5jb21lLXRheC9mcmFuY2UvZG9tYWluL3R5cGVzJztcbmV4cG9ydCB7IEluY29tZVRheENhbGN1bGF0b3JTY2hlbWEgfSBmcm9tICcuL2luY29tZS10YXgvZG9tYWluL3R5cGVzJztcbmV4cG9ydCAqIGZyb20gJy4vaW5jb21lLXRheC9kb21haW4vdHlwZXMnOyJdfQ==
@@ -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==
@@ -1,4 +1,4 @@
1
- import { TaxBracket } from "../../../domain/types";
1
+ import { TaxBracket } from "../../domain/types";
2
2
  export interface IncomeTaxRules {
3
3
  taxBrackets: TaxBracket[];
4
4
  credits?: Record<string, TaxCredit>;
@@ -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 { RuleInput, RuleMeta, RuleOutput, TaxBracket } from "../../../domain/types";
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;
@@ -2,5 +2,5 @@ export { CanadaIncomeTaxServiceImpl as CanadaIncomeTaxService } from './income-t
2
2
  export { FranceIncomeTaxServiceImpl as FranceIncomeTaxService } from './income-tax/france/FranceIncomeTaxServiceImpl';
3
3
  export { ComputedIncomeTaxValues as CanadaComputedIncomeTaxValues, IncomeTaxRules as CanadaIncomeTaxRules, } from './income-tax/canada/domain/types';
4
4
  export { ComputedIncomeTaxValues as FranceComputedIncomeTaxValues, IncomeTaxRules as FranceIncomeTaxRules, } from './income-tax/france/domain/types';
5
- export { IncomeTaxCalculatorSchema } from './domain/types';
6
- export * from './domain/types';
5
+ export { IncomeTaxCalculatorSchema } from './income-tax/domain/types';
6
+ export * from './income-tax/domain/types';
@@ -0,0 +1,4 @@
1
+ import { MortgageCalculationInput, MortgageCalculationResult, MortgageRules } from "./domain/types";
2
+ export interface CanadaMortgageService {
3
+ calculate(input: MortgageCalculationInput, rules: MortgageRules): MortgageCalculationResult;
4
+ }
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "@novha/calc-engines",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/types/index.d.ts",
6
6
  "scripts": {
@@ -1,4 +1,4 @@
1
- import { TaxBracket } from "../../domain/types";
1
+ import { TaxBracket } from "../domain/types";
2
2
  import { CanadaIncomeTaxService } from "./CanadaIncomeTaxService";
3
3
  import {
4
4
  CPPContribution,
@@ -1,4 +1,4 @@
1
- import { RuleInput, RuleMeta, RuleOutput, TaxBracket } from "../../../domain/types";
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
- 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
- }
1
+ import { RuleMeta } from "../../shared/domain/types";
22
2
 
23
3
  export interface RuleInput {
24
4
  name: string;
@@ -1,4 +1,5 @@
1
- import { RuleInput, RuleMeta, RuleOutput, TaxBracket } from "../../../domain/types";
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
@@ -8,5 +8,5 @@ export {
8
8
  ComputedIncomeTaxValues as FranceComputedIncomeTaxValues,
9
9
  IncomeTaxRules as FranceIncomeTaxRules,
10
10
  } from './income-tax/france/domain/types';
11
- export { IncomeTaxCalculatorSchema } from './domain/types';
12
- export * from './domain/types';
11
+ export { IncomeTaxCalculatorSchema } from './income-tax/domain/types';
12
+ export * from './income-tax/domain/types';
@@ -0,0 +1,8 @@
1
+ import { MortgageCalculationInput, MortgageCalculationResult, MortgageRules } from "./domain/types";
2
+
3
+ export interface CanadaMortgageService {
4
+ calculate(
5
+ input: MortgageCalculationInput,
6
+ rules: MortgageRules
7
+ ): MortgageCalculationResult;
8
+ }
@@ -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
+ }