argument('file'); if (!file_exists($filePath)) { $this->error("File not found: {$filePath}"); return 1; } if (!is_readable($filePath)) { $this->error("File is not readable: {$filePath}"); return 1; } $this->info("Processing CSV file: {$filePath}"); try { $csv = Reader::createFromPath($filePath, 'r'); $csv->setHeaderOffset(0); $headers = $csv->getHeader(); $records = $csv->getRecords(); // Find "Connect od Order" in headers $connectOrderKey = null; //print_r($headers); exit; foreach ($headers as $header) { if (trim(strtolower($header)) === 'connect od order') { $connectOrderKey = $header; break; } } if (!$connectOrderKey) { $this->error('Column "Connect od Order" not found in the file.'); return 1; } $updatedCount = 0; $notFoundCount = 0; $errorCount = 0; $errors = []; // Count total records for progress bar (this consumes the iterator) $totalRecords = iterator_count($records); // Recreate CSV reader to reset iterator $csv = Reader::createFromPath($filePath, 'r'); $csv->setHeaderOffset(0); $records = $csv->getRecords(); // Process each record $rowIndex = 0; $bar = $this->output->createProgressBar($totalRecords); $bar->start(); foreach ($records as $row) { $rowIndex++; $bar->advance(); try { $connectOrderId = trim($row[$connectOrderKey] ?? ''); if (empty($connectOrderId)) { continue; } // Check if record exists $record = DB::table('neblogistic')->where('id', $connectOrderId)->first(); if (!$record) { $notFoundCount++; $errors[] = "Row " . ($rowIndex + 1) . ": Record with ID {$connectOrderId} not found."; continue; } // Build update data $updateData = []; foreach ($row as $columnName => $value) { if ($columnName === $connectOrderKey) { continue; // Skip the ID column } if (!empty(trim($value))) { $dbField = $this->mapColumnToDbField($columnName); if ($dbField) { $trimmedValue = trim($value); // Convert date format for lr_date field from d.m.Y to Y-m-d if ($dbField === 'lr_date') { try { $date = \DateTime::createFromFormat('d.m.Y', $trimmedValue); if ($date) { $trimmedValue = $date->format('Y-m-d'); } } catch (\Exception $e) { // If parsing fails, keep original value } } $updateData[$dbField] = $trimmedValue; } } } //print_r($updateData); exit; // Update the record if there's data to update if (!empty($updateData)) { // Get old data before update for audit trail $oldRecord = DB::table('neblogistic')->where('id', $connectOrderId)->first(); $oldDataArray = $oldRecord ? json_decode(json_encode($oldRecord), true) : null; DB::table('neblogistic') ->where('id', $connectOrderId) ->update($updateData); // Log UPDATE operation (console command - no request object) NeblogisticAuditService::logUpdate( $connectOrderId, $oldDataArray, $updateData, null, null // No request object in console command ); $updatedCount++; } } catch (\Exception $e) { $errorCount++; $errors[] = "Row " . ($rowIndex + 1) . ": " . $e->getMessage(); Log::error('Import row error', [ 'row' => $rowIndex + 1, 'error' => $e->getMessage() ]); } } $bar->finish(); $this->newLine(2); // Display results $this->info("Import completed!"); $this->info("Updated: {$updatedCount}"); $this->info("Not Found: {$notFoundCount}"); $this->info("Errors: {$errorCount}"); if (!empty($errors) && count($errors) <= 20) { $this->warn("\nErrors:"); foreach ($errors as $error) { $this->line($error); } } elseif (!empty($errors)) { $this->warn("\nFirst 20 errors:"); foreach (array_slice($errors, 0, 20) as $error) { $this->line($error); } $this->warn("... and " . (count($errors) - 20) . " more errors. Check logs for details."); } Log::info('CSV import completed', [ 'file' => $filePath, 'updated' => $updatedCount, 'not_found' => $notFoundCount, 'errors' => $errorCount ]); return 0; } catch (\Exception $e) { $this->error("Import failed: " . $e->getMessage()); Log::error('CSV import error', [ 'file' => $filePath, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return 1; } } private function mapColumnToDbField($columnName) { // Map Excel/CSV column names to database field names // Only allow updating these specific fields $mapping = [ 'Connect od Order' => 'id', 'ORDER NO' => 'order_no', 'INVOICE NO' => 'invoice_no', 'COURIER NAME' => 'courier_name', 'LR NO' => 'lr_no', 'LR DATE' => 'lr_date', 'DOCTOR NAME' => 'doctor_name', 'DELIVERY DATE' => 'delivery_at', 'STATUS' => 'status', ]; $normalizedColumn = trim($columnName); return $mapping[$normalizedColumn] ?? null; } }