excelHandler = new ExcelHandler(); $this->pdfConverter = new PdfConverter(); } /** * Process single TP line */ public function processLine(array $lineData, array $documents, array $settings): array { $startTime = microtime(true); $jobId = $settings['job_id']; $testPackageNo = $lineData['test_package_number']; $path = $settings['path'] ?? ''; $override = $settings['override'] ?? true; $this->updateProgress($jobId, 0, "Starting TP: $testPackageNo"); // 1. Prepare Data $testPackage = db("test_pack_base_statuses") ->where("test_package_no", $testPackageNo) ->first(); if(!$testPackage) { throw new Exception("Test Package not found: $testPackageNo"); } // 2. Prepare Folders $basePath = "storage/documents/$path"; $fullFolder = "$basePath/$testPackageNo/"; $justFolder = "$path/$testPackageNo/"; if (!file_exists($fullFolder)) { mkdir($fullFolder, 0777, true); } // Initialize Log File and Create Info File $this->initializeLogFile($fullFolder, $testPackageNo); $this->createInfoFile($fullFolder, $testPackageNo, $settings); // 3. Load Template $documentInfo = document_template("register"); if (!$documentInfo) { throw new Exception("Register template not found!"); } $this->excelHandler->loadTemplate($documentInfo->files); $sheet = $this->excelHandler->getSheet(); // 4. Initial Setup $startRow = setting("register_creator_start_row") ?: 16; $currentRow = $startRow; $rowNo = 1; // 5. Process Documents $totalDocs = count($documents); $processedDocs = 0; foreach($documents as $doc) { $docType = $doc['type']; $docPath = $doc['path']; $docTitle = $doc['title2'] ?? ''; $this->updateProgress($jobId, round(($processedDocs / $totalDocs) * 90), "Processing $docTitle"); try { // Use Factory to get appropriate processor $processor = TpDocumentProcessorFactory::make($docType, $docPath); // Prepare settings for processor $processorSettings = [ 'override' => $override, 'full_folder' => $fullFolder, 'row_no' => $rowNo, // Add other settings if needed by specific processors ]; // Process document $newRow = $processor->process( $lineData, $doc, $sheet, $currentRow, $rowNo, $fullFolder, $testPackageNo, $override ); // If rows were added, update currentRow and rowNo // The processor returns the *next* row number (e.g., if it added 2 rows, it returns currentRow + 2) // Actually, my interface implementation returns the new rowNo/count. // Let's standardize: Processors should return the new currentRow index in Excel. // Wait, QaTpProcessor returns rowNo (count) not currentRow (Excel index). // Let's re-check the AbstractTpDocumentProcessor and implementations. // QaTpProcessor returns $rowNo (the counter, not Excel row index). // WdbTpProcessor returns $rowNo. // AbstractTpDocumentProcessor adds rows and increments currentRow and rowNo by reference passed to addRow helper. // But rowNo is passed by value to process() method unless specified otherwise. // CORRECTION: In my implementation of processors, I passed $rowNo by value. // And process() returns int. QaTpProcessor returns $rowNo. // This means the returned value is the new Row Number counter. // I need to calculate how many rows were added to update $currentRow. // Let's assume process() returns the new $rowNo. // Then diff = $newRowNo - $oldRowNo. // $currentRow += diff. // Let's verify AbstractTpDocumentProcessor signature I wrote: // public function process(..., int $rowNo, ...): int $oldRowNo = $rowNo; $rowNo = $newRow; // Update global row counter $rowsAdded = $rowNo - $oldRowNo; $currentRow += $rowsAdded; } catch (Exception $e) { Log::error("Error processing document type $docType: " . $e->getMessage()); // Continue to next document } $processedDocs++; } // 6. Save & Convert $registerFileName = $justFolder . "Register.xlsx"; $this->excelHandler->save($registerFileName, $override); $this->pdfConverter->convert($registerFileName, $justFolder, $override); $this->updateProgress($jobId, 100, "Completed"); return ['status' => 'success']; } private function updateProgress($jobId, $percent, $desc) { $queue = Cache::get('tp-creator-queue', []); if(isset($queue[$jobId])) { $queue[$jobId]['progress'] = $percent; $queue[$jobId]['description'] = $desc; Cache::put('tp-creator-queue', $queue, now()->addHours(24)); } } /** * Initialize log file */ private function initializeLogFile(string $fullFolder, string $lineIdentifier): void { $logPath = $fullFolder . 'log.txt'; if (file_exists($logPath)) { unlink($logPath); } $header = str_repeat("🚀", 30) . "\n"; $header .= "TP CREATOR LOG FILE\n"; $header .= "Line: {$lineIdentifier}\n"; $header .= "Started: " . now()->toDateTimeString() . "\n"; $header .= str_repeat("🚀", 30) . "\n\n"; file_put_contents($logPath, $header); } /** * Create info.txt file with user information (JSON format) */ private function createInfoFile(string $fullFolder, string $lineIdentifier, array $settings): void { $infoPath = $fullFolder . 'info.txt'; // Delete old info file if exists if (file_exists($infoPath)) { unlink($infoPath); } // Create simple JSON with user information $infoData = [ 'user_name' => $settings['user_name'] ?? 'Unknown', 'user_id' => $settings['user_id'] ?? null, 'created_at' => now()->format('Y-m-d H:i:s'), 'line_identifier' => $lineIdentifier ]; file_put_contents($infoPath, json_encode($infoData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); } }