UNPKG

@accounter/server

Version:
100 lines 3.83 kB
import { z } from 'zod'; import { ALLOWED_TAX_ADJUSTMENT_CODES, NEGATIVE_ALLOWED_TAX_ADJUSTMENTS_CODES, TAX_ADJUSTMENT_CODE_NAMES, } from '../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 export const allowedCodesSet = new Set(ALLOWED_TAX_ADJUSTMENT_CODES); export const negativeAllowedCodesSet = new Set(NEGATIVE_ALLOWED_TAX_ADJUSTMENTS_CODES); function codeToName(code) { return `${TAX_ADJUSTMENT_CODE_NAMES[code] ?? 'Unknown code'} (${code})`; } // Create the Tax Adjustment record schema const taxAdjustmentRecordSchema = z .object({ // קוד שדה - Field code code: z .number() .int() .refine(code => allowedCodesSet.has(code), { message: 'Invalid code for tax adjustment section', }), // סכום - Amount amount: z.number().int(), }) .superRefine((record, ctx) => { // Validate that non-negative codes don't have negative amounts if (!negativeAllowedCodesSet.has(record.code) && record.amount < 0) { ctx.addIssue({ code: 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 export const taxAdjustmentArraySchema = 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: 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: z.ZodIssueCode.custom, message: `Duplicate code ${codeToName(record.code)} found`, path: [index, 'code'], }); } codeMap.set(record.code, record.amount); }); return codeMap; } //# sourceMappingURL=tax-adjustment.js.map