import * as fs from 'fs'; import * as path from 'path'; import { DeterministicParser } from './BuyerSheetParser'; async function main() { // 1. Argument-Check const args = process.argv.slice(2); // Verzeichnis Parameter const dirArgIndex = args.indexOf('--dir'); if (dirArgIndex === -1 || !args[dirArgIndex + 1]) { console.error("Fehler: Bitte ein Verzeichnis angeben!"); console.error("Nutzung: npx tsx batch_runner.ts --dir \"/Pfad/zum/Ordner\" [--limit 10]"); process.exit(1); } const dirPath = args[dirArgIndex + 1]; // Limit Parameter const limitArgIndex = args.indexOf('--limit'); let limit = -1; // -1 bedeutet: Kein Limit, alle verarbeiten if (limitArgIndex !== -1 && args[limitArgIndex + 1]) { limit = parseInt(args[limitArgIndex + 1], 10); } if (!fs.existsSync(dirPath) || !fs.statSync(dirPath).isDirectory()) { console.error(`Fehler: Der Pfad "${dirPath}" existiert nicht oder ist kein Verzeichnis.`); process.exit(1); } // 2. PDFs finden und Metadaten (für die Sortierung) auslesen const filesWithStats = fs.readdirSync(dirPath) .filter(f => f.toLowerCase().endsWith('.pdf')) .map(file => { const fullPath = path.join(dirPath, file); return { file, fullPath, // Änderungsdatum der Datei auslesen (in Millisekunden) mtime: fs.statSync(fullPath).mtimeMs }; }); if (filesWithStats.length === 0) { console.log("Keine PDFs in diesem Verzeichnis gefunden."); process.exit(0); } // 3. Absteigend sortieren (Neueste zuerst) filesWithStats.sort((a, b) => b.mtime - a.mtime); // 4. Limit anwenden (falls gesetzt) const filesToProcess = limit > 0 ? filesWithStats.slice(0, limit) : filesWithStats; console.log(`Starte Verarbeitung: ${filesToProcess.length} von ${filesWithStats.length} PDFs ausgewählt (Sortierung: Neueste zuerst)...\n`); const parser = new DeterministicParser(); const finalResults = []; let skippedCounter = 0; // 5. PDFs iterieren for (const fileObj of filesToProcess) { const { file, fullPath } = fileObj; process.stdout.write(`-> Verarbeite: ${file} ... `); try { const data = await parser.parsePdf(fullPath, file); if (data === null) { console.log("ÜBERSPRUNGEN (> 10 Seiten)"); skippedCounter++; } else if (data.is_buyer_sheet === false) { console.log("IMAGE SCAN (Zuweisung an Vision AI)"); finalResults.push(data); } else { console.log("ERFOLGREICH"); finalResults.push(data); } } catch (error) { console.log("FEHLER BEIM PARSEN"); console.error(error); } } // 6. JSON Export unter ./out/buyers.json const outDir = path.join(process.cwd(), 'out'); if (!fs.existsSync(outDir)) { fs.mkdirSync(outDir); } const outPath = path.join(outDir, 'buyers.json'); fs.writeFileSync(outPath, JSON.stringify(finalResults, null, 2), 'utf-8'); console.log(`\n=================================================`); console.log(`Zusammenfassung:`); console.log(` Verarbeitet: ${finalResults.length}`); console.log(` Verworfen (>10 Seiten): ${skippedCounter}`); console.log(` Export gespeichert in: ${outPath}`); console.log(`=================================================`); } main();