UNPKG

@accounter/shaam6111-generator

Version:

Fully typed application that generates, parses, and validates SHAAM 6111 tax reports.

103 lines (102 loc) 3.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.taxAdjustmentArraySchema = exports.negativeAllowedCodesSet = exports.allowedCodesSet = void 0; const zod_1 = require("zod"); const index_js_1 = require("../types/index.js"); /** * Tax Adjustment Record Schema * Based on the SHAAM 6111 specification (IncomeTax_software-houses-6111-2023.pdf) */ // Create a set for faster lookup of allowed codes exports.allowedCodesSet = new Set(index_js_1.ALLOWED_TAX_ADJUSTMENT_CODES); exports.negativeAllowedCodesSet = new Set(index_js_1.NEGATIVE_ALLOWED_TAX_ADJUSTMENTS_CODES); function codeToName(code) { return `${index_js_1.TAX_ADJUSTMENT_CODE_NAMES[code] ?? 'Unknown code'} (${code})`; } // Create the Tax Adjustment record schema const taxAdjustmentRecordSchema = zod_1.z .object({ // קוד שדה - Field code code: zod_1.z .number() .int() .refine(code => exports.allowedCodesSet.has(code), { message: 'Invalid code for tax adjustment section', }), // סכום - Amount amount: zod_1.z.number().int(), }) .superRefine((record, ctx) => { // Validate that non-negative codes don't have negative amounts if (!exports.negativeAllowedCodesSet.has(record.code) && record.amount < 0) { ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, message: `Code ${codeToName(record.code)} does not allow negative amounts`, path: ['amount'], }); } }); // Define the validation logic for each summary code const summaryValidations = { // 100: // 103: // 104: validated on the report level 370: { formula: (map) => { return ([110, 120, 140, 150, 160, 181, 182, 183, 184, 190, 310, 330, 350, 360] .map(code => map.get(code) || 0) .reduce((a, b) => a + b, 0) - [130, 135, 170, 180, 200, 300, 320] .map(code => map.get(code) || 0) .reduce((a, b) => a + b, 0)); }, description: '110+120-130-135+140+150+160-170-180+181+182+183+184+190-200-300+310-320+330+350+360', }, // 383: // 400: validated on the report level 500: { formula: (map) => { return (map.get(400) || 0) - (map.get(430) || 0) - (map.get(480) || 0) + (map.get(490) || 0); }, description: '400-430-480+490', }, // 600: }; // Schema for an array of Tax Adjustment records exports.taxAdjustmentArraySchema = zod_1.z .array(taxAdjustmentRecordSchema) .max(150) .superRefine((records, ctx) => { // Check for unique code values & create a map for faster lookups const codeToAmountMap = checkForUniqueCodes(records, ctx); // Validate each summary field with its formula for (const [codeStr, validation] of Object.entries(summaryValidations)) { const code = parseInt(codeStr); if (codeToAmountMap.has(code)) { const actualAmount = codeToAmountMap.get(code); const expectedAmount = validation.formula(codeToAmountMap); if (actualAmount !== expectedAmount) { const index = records.findIndex(r => r.code === code); ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, message: `Value for code ${codeToName(code)} should equal the sum: ${validation.description}`, path: [index, 'amount'], }); } } } }); function checkForUniqueCodes(records, ctx) { const codeMap = new Map(); records.map((record, index) => { if (codeMap.has(record.code)) { ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, message: `Duplicate code ${codeToName(record.code)} found`, path: [index, 'code'], }); } codeMap.set(record.code, record.amount); }); return codeMap; }