changes 0230092025
This commit is contained in:
@@ -4,16 +4,15 @@
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Models\Import;
|
||||
use App\Models\ImportTemplate;
|
||||
use App\Models\ImportRow;
|
||||
use App\Models\ImportEvent;
|
||||
use App\Models\ImportTemplate;
|
||||
use App\Services\CsvImportService;
|
||||
use App\Services\ImportProcessor;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Inertia\Inertia;
|
||||
use App\Services\CsvImportService;
|
||||
|
||||
class ImportController extends Controller
|
||||
{
|
||||
@@ -64,7 +63,7 @@ public function index(Request $request)
|
||||
'full_name' => $imp->client->person->full_name,
|
||||
] : null,
|
||||
] : null,
|
||||
'template' => $imp->template ? [ 'id' => $imp->template->id, 'name' => $imp->template->name ] : null,
|
||||
'template' => $imp->template ? ['id' => $imp->template->id, 'name' => $imp->template->name] : null,
|
||||
];
|
||||
}, $imports['data']);
|
||||
|
||||
@@ -99,7 +98,6 @@ public function create(Request $request)
|
||||
DB::raw('person.full_name as name'),
|
||||
]);
|
||||
|
||||
|
||||
return Inertia::render('Imports/Create', [
|
||||
'templates' => $templates,
|
||||
'clients' => $clients,
|
||||
@@ -129,7 +127,7 @@ public function store(Request $request)
|
||||
|
||||
// Resolve client_uuid to client_id if provided
|
||||
$clientId = null;
|
||||
if (!empty($validated['client_uuid'] ?? null)) {
|
||||
if (! empty($validated['client_uuid'] ?? null)) {
|
||||
$clientId = Client::where('uuid', $validated['client_uuid'])->value('id');
|
||||
}
|
||||
|
||||
@@ -163,6 +161,7 @@ public function process(Import $import, Request $request, ImportProcessor $proce
|
||||
{
|
||||
$import->update(['status' => 'validating', 'started_at' => now()]);
|
||||
$result = $processor->process($import, user: $request->user());
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
|
||||
@@ -188,25 +187,44 @@ public function columns(Request $request, Import $import, CsvImportService $csv)
|
||||
if ($tplDelimiter) {
|
||||
$explicitDelimiter = (string) $tplDelimiter;
|
||||
}
|
||||
} elseif (!empty($import->meta['forced_delimiter'] ?? null)) {
|
||||
} elseif (! empty($import->meta['forced_delimiter'] ?? null)) {
|
||||
$explicitDelimiter = (string) $import->meta['forced_delimiter'];
|
||||
}
|
||||
|
||||
// Only implement CSV/TSV detection for now; others can be added later
|
||||
if (!in_array($import->source_type, ['csv','txt'])) {
|
||||
return response()->json([
|
||||
'columns' => [],
|
||||
'note' => 'Column preview supported for CSV/TXT at this step.',
|
||||
]);
|
||||
// Prefer CSV/TXT; if source_type is unknown, attempt best-effort based on file extension
|
||||
$treatAsText = in_array($import->source_type, ['csv', 'txt']);
|
||||
if (! $treatAsText) {
|
||||
$orig = strtolower(pathinfo($import->original_name ?? '', PATHINFO_EXTENSION));
|
||||
if (in_array($orig, ['csv', 'txt'])) {
|
||||
$treatAsText = true;
|
||||
}
|
||||
}
|
||||
|
||||
$fullPath = Storage::disk($import->disk)->path($import->path);
|
||||
if ($explicitDelimiter !== null && $explicitDelimiter !== '') {
|
||||
$columns = $csv->parseColumnsFromCsv($fullPath, $explicitDelimiter, $hasHeader);
|
||||
$delimiter = $explicitDelimiter;
|
||||
} else {
|
||||
[$delimiter, $columns] = $csv->detectColumnsFromCsv($fullPath, $hasHeader);
|
||||
}
|
||||
$fullPath = Storage::disk($import->disk)->path($import->path);
|
||||
$note = '';
|
||||
if ($treatAsText) {
|
||||
if ($explicitDelimiter !== null && $explicitDelimiter !== '') {
|
||||
$columns = $csv->parseColumnsFromCsv($fullPath, $explicitDelimiter, $hasHeader);
|
||||
$delimiter = $explicitDelimiter;
|
||||
} else {
|
||||
[$delimiter, $columns] = $csv->detectColumnsFromCsv($fullPath, $hasHeader);
|
||||
// Backstop: if single column but file clearly has separators, try common ones
|
||||
if (is_array($columns) && count($columns) <= 1) {
|
||||
foreach ([';', "\t", '|', ' ', ','] as $try) {
|
||||
$alt = $csv->parseColumnsFromCsv($fullPath, $try, $hasHeader);
|
||||
if (is_array($alt) && count($alt) > 1) {
|
||||
$delimiter = $try;
|
||||
$columns = $alt;
|
||||
$note = 'Delimiter auto-detection backstopped to '.json_encode($try);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Best-effort: try detect anyway
|
||||
[$delimiter, $columns] = $csv->detectColumnsFromCsv($fullPath, $hasHeader);
|
||||
}
|
||||
|
||||
// Save meta
|
||||
$meta = $import->meta ?? [];
|
||||
@@ -225,6 +243,7 @@ public function columns(Request $request, Import $import, CsvImportService $csv)
|
||||
'columns' => $columns,
|
||||
'has_header' => $hasHeader,
|
||||
'detected_delimiter' => $delimiter,
|
||||
'note' => $note,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -236,9 +255,9 @@ public function saveMappings(Request $request, Import $import)
|
||||
$data = $request->validate([
|
||||
'mappings' => 'required|array',
|
||||
'mappings.*.source_column' => 'required|string',
|
||||
'mappings.*.entity' => 'nullable|string|in:person,person_addresses,person_phones,emails,accounts,contracts',
|
||||
'mappings.*.entity' => 'nullable|string|in:person,person_addresses,person_phones,emails,accounts,contracts,client_cases',
|
||||
'mappings.*.target_field' => 'required|string',
|
||||
'mappings.*.transform' => 'nullable|string|in:trim,upper,lower',
|
||||
'mappings.*.transform' => 'nullable|string|in:trim,upper,lower,decimal,ref',
|
||||
'mappings.*.apply_mode' => 'nullable|string|in:insert,update,both',
|
||||
'mappings.*.options' => 'nullable|array',
|
||||
]);
|
||||
@@ -247,14 +266,14 @@ public function saveMappings(Request $request, Import $import)
|
||||
$now = now();
|
||||
$existing = \DB::table('import_mappings')
|
||||
->where('import_id', $import->id)
|
||||
->get(['id','source_column','position']);
|
||||
->get(['id', 'source_column', 'position']);
|
||||
|
||||
$bySource = [];
|
||||
$dupes = [];
|
||||
foreach ($existing as $row) {
|
||||
$src = (string) $row->source_column;
|
||||
if (!array_key_exists($src, $bySource)) {
|
||||
$bySource[$src] = [ 'id' => $row->id, 'position' => $row->position ];
|
||||
if (! array_key_exists($src, $bySource)) {
|
||||
$bySource[$src] = ['id' => $row->id, 'position' => $row->position];
|
||||
} else {
|
||||
$dupes[$src] = ($dupes[$src] ?? []);
|
||||
$dupes[$src][] = $row->id;
|
||||
@@ -262,7 +281,9 @@ public function saveMappings(Request $request, Import $import)
|
||||
}
|
||||
|
||||
$basePosition = (int) (\DB::table('import_mappings')->where('import_id', $import->id)->max('position') ?? -1);
|
||||
$inserted = 0; $updated = 0; $deduped = 0;
|
||||
$inserted = 0;
|
||||
$updated = 0;
|
||||
$deduped = 0;
|
||||
|
||||
foreach ($data['mappings'] as $pos => $m) {
|
||||
$src = (string) $m['source_column'];
|
||||
@@ -281,7 +302,7 @@ public function saveMappings(Request $request, Import $import)
|
||||
\DB::table('import_mappings')->where('id', $bySource[$src]['id'])->update($payload);
|
||||
$updated++;
|
||||
// Remove duplicates if any
|
||||
if (!empty($dupes[$src])) {
|
||||
if (! empty($dupes[$src])) {
|
||||
$deleted = \DB::table('import_mappings')->whereIn('id', $dupes[$src])->delete();
|
||||
$deduped += (int) $deleted;
|
||||
unset($dupes[$src]);
|
||||
@@ -325,8 +346,9 @@ public function getMappings(Import $import)
|
||||
'transform',
|
||||
'apply_mode',
|
||||
'options',
|
||||
'position'
|
||||
'position',
|
||||
]);
|
||||
|
||||
return response()->json(['mappings' => $rows]);
|
||||
}
|
||||
|
||||
@@ -339,7 +361,8 @@ public function getEvents(Import $import)
|
||||
->where('import_id', $import->id)
|
||||
->orderByDesc('id')
|
||||
->limit($limit)
|
||||
->get(['id','created_at','level','event','message','import_row_id','context']);
|
||||
->get(['id', 'created_at', 'level', 'event', 'message', 'import_row_id', 'context']);
|
||||
|
||||
return response()->json(['events' => $events]);
|
||||
}
|
||||
|
||||
@@ -363,7 +386,6 @@ public function show(Import $import)
|
||||
'clients.uuid as client_uuid',
|
||||
]);
|
||||
|
||||
|
||||
$clients = Client::query()
|
||||
->join('person', 'person.id', '=', 'clients.person_id')
|
||||
->orderBy('person.full_name')
|
||||
@@ -371,7 +393,7 @@ public function show(Import $import)
|
||||
->get([
|
||||
'clients.id',
|
||||
'clients.uuid',
|
||||
'person.full_name as name'
|
||||
'person.full_name as name',
|
||||
]);
|
||||
|
||||
// Import client
|
||||
@@ -383,7 +405,6 @@ public function show(Import $import)
|
||||
'person.full_name as name',
|
||||
]);
|
||||
|
||||
|
||||
// Render a dedicated page to continue the import
|
||||
return Inertia::render('Imports/Import', [
|
||||
'import' => [
|
||||
@@ -398,11 +419,11 @@ public function show(Import $import)
|
||||
'imported_rows' => $import->imported_rows,
|
||||
'invalid_rows' => $import->invalid_rows,
|
||||
'valid_rows' => $import->valid_rows,
|
||||
'finished_at' => $import->finished_at
|
||||
'finished_at' => $import->finished_at,
|
||||
],
|
||||
'templates' => $templates,
|
||||
'clients' => $clients,
|
||||
'client' => $client
|
||||
'client' => $client,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user