244 lines
8.2 KiB
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;
|
|
}
|
|
}
|
|
|