UNPKG

@accounter/shaam6111-generator

Version:

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

329 lines (286 loc) • 14 kB
import { validateReport } from '../../src/index.js'; describe('Integration Test: validateReport', () => { it('should validate a valid company report', () => { // Create a sample valid company report let reportContent = // Header Section '123456782' + // taxFileNumber '2025' + // taxYear '987654324' + // idNumber '121212120' + // vatFileNumber '343434346' + // withholdingTaxFileNumber '1234' + // industryCode 'Sample Company Ltd ' + // businessDescription '02' + // businessType (COMMERCIAL) '02' + // reportingMethod (ACCRUAL) '02' + // accountingMethod (DOUBLE_ENTRY) '02' + // accountingSystem (COMPUTERIZED) '2' + // isPartnership (NO) '1' + // includesProfitLoss (YES) '1' + // includesTaxAdjustment (YES) '1' + // includesBalanceSheet (YES) '008' + // profitLossEntryCount '003' + // taxAdjustmentEntryCount '008' + // balanceSheetEntryCount '2023' + // ifrsImplementationYear '9' + // ifrsReportingOption (NONE) '12345678' + // softwareRegistrationNumber '000' + // partnershipCount '000000' + // partnershipProfitShare '01' + // currencyType (SHEKELS) '01' + // auditOpinionType (UNQUALIFIED) '2'; // amountsInThousands (NO) // Pad to reach position 512 where profit/loss section starts reportContent = reportContent.padEnd(512, '0'); // Profit and Loss Section (8 entries) reportContent += '010000000000100000'; // Code 1000, Amount 100000 reportContent += '010100000000100000'; // Code 1010, Amount 100000 reportContent += '030000000000050000'; // Code 3000, Amount 50000 reportContent += '030130000000050000'; // Code 3013, Amount 50000 reportContent += '050000000000200000'; // Code 5000, Amount 200000 reportContent += '050510000000150000'; // Code 5051, Amount 150000 reportContent += '050900000000050000'; // Code 5090, Amount 50000 reportContent += '066660000000250000'; // Code 6666, Amount 250000 // Fill remaining profit/loss entries with filler records for (let i = 0; i < 142; i++) { reportContent += '000000000000000000'; } // Tax Adjustment Section (3 entries) reportContent += '001000000000250000'; // Code 100, Amount 250000 (matches 6666 from profit/loss) reportContent += '001040000000250000'; // Code 104, Amount 250000 reportContent += '004000000000300000'; // Code 400, Amount 300000 // Fill remaining tax adjustment entries with filler records for (let i = 0; i < 147; i++) { reportContent += '000000000000000000'; } // Balance Sheet Section (8 entries) reportContent += '070000000000100000'; // Code 7000, Amount 100000 reportContent += '071000000000100000'; // Code 7100, Amount 100000 reportContent += '071100000000100000'; // Code 7110, Amount 100000 reportContent += '088880000000100000'; // Code 8888, Amount 100000 reportContent += '090000000000100000'; // Code 9000, Amount 100000 reportContent += '093600000000100000'; // Code 9360, Amount 100000 reportContent += '094000000000100000'; // Code 9400, Amount 100000 reportContent += '099990000000100000'; // Code 9999, Amount 100000 // Fill remaining balance sheet entries with filler records for (let i = 0; i < 142; i++) { reportContent += '000000000000000000'; } const result = validateReport(reportContent); expect(result.isValid).toBe(true); expect(result.errors?.length).toBe(0); }); it('should detect invalid report with mismatched code amounts', () => { // Create a report with mismatched values between code 6666 and code 100 let reportContent = // Header Section (simplified) '12345678220259876543241212121203434343461234Company Ltd 030101012112002002000 1234567800000000001092'; // Pad to reach position 512 where profit/loss section starts reportContent = reportContent.padEnd(512, '0'); // Profit and Loss Section (8 entries) reportContent += '010000000000100000'; // Code 1000, Amount 100000 reportContent += '010100000000100000'; // Code 1010, Amount 100000 reportContent += '030000000000050000'; // Code 3000, Amount 50000 reportContent += '030130000000050000'; // Code 3013, Amount 50000 reportContent += '050000000000200000'; // Code 5000, Amount 200000 reportContent += '050510000000150000'; // Code 5051, Amount 150000 reportContent += '050900000000050000'; // Code 5090, Amount 50000 reportContent += '066660000000250000'; // Code 6666, Amount 250000 // Fill remaining profit/loss entries with filler records for (let i = 0; i < 142; i++) { reportContent += '000000000000000000'; } // Tax Adjustment Section (2 entries) reportContent += '001000000000200000'; // Code 100, Amount 200000 (matches 6666 from profit/loss) reportContent += '004000000000300000'; // Code 400, Amount 300000 // Fill remaining tax adjustment entries with filler records for (let i = 0; i < 148; i++) { reportContent += '000000000000000000'; } // No Balance Sheet Section for individual for (let i = 0; i < 150; i++) { reportContent += '000000000000000000'; } const result = validateReport(reportContent); expect(result.isValid).toBe(false); expect(result.errors?.length).toBeGreaterThan(0); // Check if the error is related to the mismatch expect( result.errors?.some( err => err.message.includes('6666') && err.message.includes('100') && err.message.includes('equal'), ), ).toBe(true); }); it('should detect invalid report with missing balance sheet for company', () => { // Create a company report without balance sheet entries let reportContent = // Header Section with includesBalanceSheet=1 (YES) '12345678220259876543241212121203434343461234Company Ltd 020201012111008003000 91234567800000000001022'; // Pad to reach position 512 where profit/loss section starts reportContent = reportContent.padEnd(512, '0'); // Profit and Loss Section (8 entries) reportContent += '010000000000100000'; // Code 1000, Amount 100000 reportContent += '010100000000100000'; // Code 1010, Amount 100000 reportContent += '030000000000050000'; // Code 3000, Amount 50000 reportContent += '030130000000050000'; // Code 3013, Amount 50000 reportContent += '050000000000200000'; // Code 5000, Amount 200000 reportContent += '050510000000150000'; // Code 5051, Amount 150000 reportContent += '050900000000050000'; // Code 5090, Amount 50000 reportContent += '066660000000250000'; // Code 6666, Amount 250000 // Fill remaining profit/loss entries with filler records for (let i = 0; i < 142; i++) { reportContent += '000000000000000000'; } // Tax Adjustment Section (3 entries) reportContent += '001000000000250000'; // Code 100, Amount 250000 (matches 6666 from profit/loss) reportContent += '001040000000250000'; // Code 104, Amount 250000 reportContent += '004000000000300000'; // Code 400, Amount 300000 // Fill remaining tax adjustment entries with filler records for (let i = 0; i < 147; i++) { reportContent += '000000000000000000'; } // No Balance Sheet entries despite being a company and including balance sheet in header for (let i = 0; i < 150; i++) { reportContent += '000000000000000000'; } const result = validateReport(reportContent); expect(result.isValid).toBe(false); expect(result.errors?.length).toBeGreaterThan(0); // Check if the error is related to missing balance sheet expect( result.errors?.some( err => err.message.includes('Balance Sheet') || err.path?.includes('balanceSheet'), // TODO: remove path check after enhancing individual/company validation ), ).toBe(true); }); it('should detect report with invalid header fields', () => { // Create a report with invalid header fields let reportContent = // Invalid Header Section (tax file number too short, tax year too short) '12345' + // taxFileNumber (invalid - too short) '202' + // taxYear (invalid - too short) '987654324' + // idNumber '121212120' + // vatFileNumber '343434346' + // withholdingTaxFileNumber '1234' + // industryCode 'Sample Company Ltd ' + // businessDescription '02' + // businessType '02' + // reportingMethod '02' + // accountingMethod '02' + // accountingSystem '2' + // isPartnership '1' + // includesProfitLoss '1' + // includesTaxAdjustment '1' + // includesBalanceSheet '002' + // profitLossEntryCount '002' + // taxAdjustmentEntryCount '002' + // balanceSheetEntryCount '2023' + // ifrsImplementationYear '9' + // ifrsReportingOption (NONE) '12345678' + // softwareRegistrationNumber '000' + // partnershipCount '000000' + // partnershipProfitShare '01' + // currencyType '01' + // auditOpinionType '2'; // amountsInThousands // Pad to reach position 512 reportContent = reportContent.padEnd(512, '0'); // Add minimal sections to complete the report // Profit and Loss Section reportContent += '010010000000100000'; // Fill remaining with zeros reportContent = reportContent.padEnd(512 + 150 * 18, '0'); // Tax Adjustment Section reportContent += '001000000000100000'; // Fill remaining with zeros reportContent = reportContent.padEnd(512 + 150 * 18 + 150 * 18, '0'); // Balance Sheet Section reportContent += '060000000000100000'; // Fill remaining with zeros reportContent = reportContent.padEnd(512 + 150 * 18 + 150 * 18 + 150 * 18, '0'); const result = validateReport(reportContent); expect(result.isValid).toBe(false); expect(result.errors?.length).toBeGreaterThan(0); // Check if the errors include the invalid header fields expect( result.errors?.some( err => err.path?.includes('taxFileNumber') || err.path?.includes('taxYear'), ), ).toBe(true); }); it('should detect malformed report with truncated content', () => { // Create a truncated report (too short) const truncatedReport = '123456789202598765432112345678998765432112341234Company Ltd'; const result = validateReport(truncatedReport); expect(result.isValid).toBe(false); expect(result.errors?.length).toBeGreaterThan(0); // Check for appropriate error message expect(result.errors?.some(err => err.message.includes('incorrect length'))).toBe(true); }); it('should detect malformed report with invalid data types', () => { // Create a report with invalid data types in the header let reportContent = // Header with invalid data types (letters where numbers expected) '123456782' + // taxFileNumber '2025' + // taxYear '987654324' + // idNumber '121212120' + // vatFileNumber '343434346' + // withholdingTaxFileNumber 'ABCD' + // industryCode (invalid - should be numbers) 'Sample Company Ltd ' + // businessDescription '0X' + // businessType (invalid - should be number) '0Y' + // reportingMethod (invalid - should be number) '0Z' + // accountingMethod (invalid - should be number) '0W' + // accountingSystem (invalid - should be number) 'V' + // isPartnership (invalid - should be number) 'U' + // includesProfitLoss (invalid - should be number) 'T' + // includesTaxAdjustment (invalid - should be number) 'S' + // includesBalanceSheet (invalid - should be number) 'ABC' + // profitLossEntryCount (invalid - should be number) 'DEF' + // taxAdjustmentEntryCount (invalid - should be number) 'GHI' + // balanceSheetEntryCount (invalid - should be number) 'JKLM' + // ifrsImplementationYear (invalid format) 'N' + // ifrsReportingOption (invalid - should be number) 'OPQRSTUV' + // softwareRegistrationNumber (invalid format) 'WXY' + // partnershipCount (invalid - should be number) 'ZABCDE' + // partnershipProfitShare (invalid - should be number) '0F' + // currencyType (invalid - should be number) '0G' + // auditOpinionType (invalid - should be number) 'H'; // amountsInThousands (invalid - should be number) // Pad to reach position 512 reportContent = reportContent.padEnd(512, '0'); // Add minimal sections to complete the report // Profit and Loss Section reportContent += '010010000000100000'; // Fill remaining with zeros reportContent = reportContent.padEnd(512 + 150 * 18, '0'); // Tax Adjustment Section reportContent += '001000000000100000'; // Fill remaining with zeros reportContent = reportContent.padEnd(512 + 150 * 18 + 150 * 18, '0'); // Balance Sheet Section reportContent += '060000000000100000'; // Fill remaining with zeros reportContent = reportContent.padEnd(512 + 150 * 18 + 150 * 18 + 150 * 18, '0'); const result = validateReport(reportContent); expect(result.isValid).toBe(false); expect(result.errors?.length).toBeGreaterThan(0); expect( result.errors?.some(err => err.message.includes('Invalid option: expected one of')), ).toBe(true); }); it('should handle empty report content', () => { const result = validateReport(''); expect(result.isValid).toBe(false); expect(result.errors?.length).toBeGreaterThan(0); expect(result.errors?.[0]?.message).toContain('incorrect length'); }); it('should handle null report content', () => { const result = validateReport(null as unknown as string); expect(result.isValid).toBe(false); expect(result.errors?.length).toBeGreaterThan(0); }); });