import { PrismaClient } from '@prisma/client'; import { DatabaseExcelReaderService } from './database-excel-reader'; import { BulkInserter } from './bulk-inserter'; import { ImportProgressServer } from './websocket-server'; import { ImportProgress, ImportResult } from './types'; export class DatabaseCintasImportProcessor { private prisma: PrismaClient; private reader: DatabaseExcelReaderService; private inserter: BulkInserter; private progressServer: ImportProgressServer; constructor() { this.prisma = new PrismaClient(); this.reader = new DatabaseExcelReaderService(); this.inserter = new BulkInserter(); this.progressServer = ImportProgressServer.getInstance(); } async processCintasImport(importId: number): Promise { try { console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Starting import processing for ID: ${importId}`); // Initialize the progress server if not already done if (!this.progressServer.isServerInitialized()) { this.progressServer.initialize(); } // Get import record with layout configuration const importRecord = await this.prisma.import.findUnique({ where: { id: importId }, include: { layout: { include: { sections: { include: { fields: true } } } } } }); if (!importRecord) { throw new Error('Import not found'); } console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Loaded import record: ${importRecord.id}`); // Initialize progress tracking const progress: ImportProgress = { importId, status: 'processing', currentSection: '', currentRow: 0, totalRows: 0, errors: [], processedSections: 0, totalSections: importRecord.layout?.sections?.length || 0 }; // Read Excel file directly from database console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Starting Excel file reading from database...`); const sections = await this.reader.readExcelFromDatabase( importRecord.fileId!, importRecord.layout, (sectionProgress) => { this.progressServer.broadcastProgress(importId, sectionProgress); } ); console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Excel file read successfully. Found ${sections.length} sections`); // Process each section const processedSections = []; let totalInserted = 0; for (let i = 0; i < sections.length; i++) { const section = sections[i]; console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Processing section ${i + 1}/${sections.length}: ${section.name}`); progress.currentSection = section.name; progress.processedSections = i + 1; this.progressServer.broadcastProgress(importId, progress); try { // Ensure table exists for this section console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Creating table ${section.tableName} for section ${section.name}`); await this.inserter.createImportTable(section.tableName, section.fields); const insertedRows = await this.inserter.insertSectionData( section, importId, (rows) => { progress.currentRow = rows; this.progressServer.broadcastProgress(importId, progress); } ); processedSections.push({ sectionData: section, insertedRows }); totalInserted += insertedRows; console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Completed section ${section.name}: ${insertedRows} rows inserted`); } catch (error) { const errorMessage = `Error processing section ${section.name}: ${error instanceof Error ? error.message : 'Unknown error'}`; progress.errors.push(errorMessage); console.error(`[${new Date().toISOString()}] [DatabaseCintasImport] ERROR: ${errorMessage}`); this.progressServer.broadcastProgress(importId, progress); } } progress.status = 'completed'; this.progressServer.broadcastProgress(importId, progress); console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Import processing completed successfully. Total inserted: ${totalInserted}`); return { success: true, totalInserted, sections: processedSections }; } catch (error) { const progress: ImportProgress = { importId, status: 'failed', currentSection: '', currentRow: 0, totalRows: 0, errors: [error instanceof Error ? error.message : 'Unknown error'], processedSections: 0, totalSections: 0 }; this.progressServer.broadcastProgress(importId, progress); console.error(`[${new Date().toISOString()}] [DatabaseCintasImport] ERROR: Import processing failed: ${error instanceof Error ? error.message : 'Unknown error'}`); return { success: false, totalInserted: 0, sections: [], errors: [error instanceof Error ? error.message : 'Unknown error'] }; } } async processCintasImportFromBuffer( buffer: Buffer, layoutConfig: any, onProgress: (progress: ImportProgress) => void ): Promise { try { console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Starting import processing from buffer`); // Initialize progress tracking const progress: ImportProgress = { importId: 0, status: 'processing', currentSection: '', currentRow: 0, totalRows: 0, errors: [], processedSections: 0, totalSections: layoutConfig.sections?.length || 0 }; // Read Excel file directly from buffer console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Starting Excel file reading from buffer...`); const sections = await this.reader.readExcelFromBuffer( buffer, layoutConfig, (sectionProgress) => { onProgress(sectionProgress); } ); console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Excel file read successfully. Found ${sections.length} sections`); // Process each section const processedSections = []; let totalInserted = 0; for (let i = 0; i < sections.length; i++) { const section = sections[i]; console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Processing section ${i + 1}/${sections.length}: ${section.name}`); progress.currentSection = section.name; progress.processedSections = i + 1; onProgress(progress); try { // Ensure table exists for this section console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Creating table ${section.tableName} for section ${section.name}`); await this.inserter.createImportTable(section.tableName, section.fields); const insertedRows = await this.inserter.insertSectionData( section, 0, // Use 0 for buffer-based imports (rows) => { progress.currentRow = rows; onProgress(progress); } ); processedSections.push({ sectionData: section, insertedRows }); totalInserted += insertedRows; console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Completed section ${section.name}: ${insertedRows} rows inserted`); } catch (error) { const errorMessage = `Error processing section ${section.name}: ${error instanceof Error ? error.message : 'Unknown error'}`; progress.errors.push(errorMessage); console.error(`[${new Date().toISOString()}] [DatabaseCintasImport] ERROR: ${errorMessage}`); onProgress(progress); } } console.log(`[${new Date().toISOString()}] [DatabaseCintasImport] Import processing completed successfully. Total inserted: ${totalInserted}`); return { success: true, totalInserted, sections: processedSections }; } catch (error) { const progress: ImportProgress = { importId: 0, status: 'failed', currentSection: '', currentRow: 0, totalRows: 0, errors: [error instanceof Error ? error.message : 'Unknown error'], processedSections: 0, totalSections: 0 }; onProgress(progress); console.error(`[${new Date().toISOString()}] [DatabaseCintasImport] ERROR: Import processing failed: ${error instanceof Error ? error.message : 'Unknown error'}`); return { success: false, totalInserted: 0, sections: [], errors: [error instanceof Error ? error.message : 'Unknown error'] }; } } }