Rapport-Laravel/app/Console/Commands/ImportCsv.php

244 lines
8.2 KiB
PHP

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use League\Csv\Reader;
use App\Services\NeblogisticAuditService;
class ImportCsv extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'import:csv {file : Path to the CSV file}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import data from a CSV file (similar to postimport functionality)';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$filePath = $this->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;
}
}