UNPKG

@accounter/shaam-uniform-format-generator

Version:

Fully typed application that generates, parses, and validates SHAAM uniform format tax reports (INI.TXT and BKMVDATA.TXT).

144 lines (130 loc) 3.59 kB
/** * BKMVDATA.TXT file parsing utilities */ import { parseA100, parseB100, parseB110, parseC100, parseD110, parseD120, parseM100, parseZ900, } from '../generator/records/index.js'; export interface ParseError { lineNumber: number; recordType: string; message: string; line: string; } export interface UnknownRecord { lineNumber: number; recordType: string; line: string; } export interface ParsedDataRecords { a100: ReturnType<typeof parseA100> | null; b100: ReturnType<typeof parseB100>[]; b110: ReturnType<typeof parseB110>[]; c100: ReturnType<typeof parseC100>[]; d110: ReturnType<typeof parseD110>[]; d120: ReturnType<typeof parseD120>[]; m100: ReturnType<typeof parseM100>[]; z900: ReturnType<typeof parseZ900> | null; } export interface ParseDataFileResult { records: ParsedDataRecords; summary: { totalLines: number; parsedRecords: number; failedRecords: number; unknownRecords: number; perType: Record<string, number>; }; errors: ParseError[]; unknownRecords: UnknownRecord[]; } /** * Parses BKMVDATA.TXT file content * * @param content - Raw BKMVDATA.TXT file content * @returns Parsed data structure */ export function parseDataFile(content: string): ParseDataFileResult { const lines = content.split(/\r?\n/).map(line => line.replace(/\r$/, '')); const records = { a100: null as ReturnType<typeof parseA100> | null, b100: [] as ReturnType<typeof parseB100>[], b110: [] as ReturnType<typeof parseB110>[], c100: [] as ReturnType<typeof parseC100>[], d110: [] as ReturnType<typeof parseD110>[], d120: [] as ReturnType<typeof parseD120>[], m100: [] as ReturnType<typeof parseM100>[], z900: null as ReturnType<typeof parseZ900> | null, }; const recordCounts: Record<string, number> = {}; const errors: ParseError[] = []; const unknownRecords: UnknownRecord[] = []; for (let index = 0; index < lines.length; index++) { const line = lines[index]; if (line.trim().length === 0) continue; if (line.length < 4) continue; const lineNumber = index + 1; const recordType = line.slice(0, 4); try { switch (recordType) { case 'A100': records.a100 = parseA100(line); break; case 'B100': records.b100.push(parseB100(line)); break; case 'B110': records.b110.push(parseB110(line)); break; case 'C100': records.c100.push(parseC100(line)); break; case 'D110': records.d110.push(parseD110(line)); break; case 'D120': records.d120.push(parseD120(line)); break; case 'M100': records.m100.push(parseM100(line)); break; case 'Z900': records.z900 = parseZ900(line); break; default: unknownRecords.push({ lineNumber, recordType, line, }); continue; } recordCounts[recordType] = (recordCounts[recordType] || 0) + 1; } catch (error) { errors.push({ lineNumber, recordType, message: error instanceof Error ? error.message : 'Unknown parse error', line, }); } } return { records, summary: { totalLines: lines.length, parsedRecords: Object.values(recordCounts).reduce((sum, count) => sum + count, 0), failedRecords: errors.length, unknownRecords: unknownRecords.length, perType: recordCounts, }, errors, unknownRecords, }; }