From d6bf6b42ed10997fb957c241609d443369e3e3fa Mon Sep 17 00:00:00 2001 From: Rubi Almora Date: Thu, 15 Jan 2026 12:38:10 -0600 Subject: [PATCH] Generar excel --- app/Console/Commands/SeedOwnerVehicle.php | 140 +++++++++ .../Controllers/Repuve/ExcelController.php | 276 ++++++++++++++++++ .../Repuve/InscriptionController.php | 8 +- routes/api.php | 1 + scripts/README.md | 53 ++++ scripts/seed_owner_vehicle.php | 115 ++++++++ scripts/seed_owner_vehicle_tinker.txt | 100 +++++++ 7 files changed, 691 insertions(+), 2 deletions(-) create mode 100644 app/Console/Commands/SeedOwnerVehicle.php create mode 100644 scripts/README.md create mode 100644 scripts/seed_owner_vehicle.php create mode 100644 scripts/seed_owner_vehicle_tinker.txt diff --git a/app/Console/Commands/SeedOwnerVehicle.php b/app/Console/Commands/SeedOwnerVehicle.php new file mode 100644 index 0000000..8bdb24d --- /dev/null +++ b/app/Console/Commands/SeedOwnerVehicle.php @@ -0,0 +1,140 @@ +info('Creando propietario...'); + + // Crear un propietario + $owner = Owner::create([ + 'name' => 'Juan', + 'paternal' => 'Pérez', + 'maternal' => 'García', + 'rfc' => 'PEGJ850101ABC', + 'curp' => 'PEGJ850101HDFRRN01', + 'address' => 'Calle Principal 123', + 'tipopers' => true, + 'pasaporte' => null, + 'licencia' => 'LIC123456789', + 'ent_fed' => 'Ciudad de México', + 'munic' => 'Benito Juárez', + 'callep' => 'Calle Principal', + 'num_ext' => '123', + 'num_int' => 'A', + 'colonia' => 'Centro', + 'cp' => '03100', + 'telefono' => '5551234567', + ]); + + $this->info("✓ Propietario creado: {$owner->full_name} (ID: {$owner->id})"); + + $this->info('Creando vehículo...'); + + // Crear un vehículo asociado al propietario + $vehicle = Vehicle::create([ + 'placa' => 'ABC-123', + 'niv' => '1HGBH41JXMN109186', + 'marca' => 'Honda', + 'linea' => 'Civic', + 'sublinea' => 'Sedan', + 'modelo' => '2020', + 'color' => 'Blanco', + 'numero_motor' => 'ENG123456789', + 'clase_veh' => 'Automóvil', + 'tipo_servicio' => 'Particular', + 'rfv' => 'RFV123456789', + 'ofcexpedicion' => 'Oficina Central', + 'fechaexpedicion' => '2020-01-15', + 'tipo_veh' => 'Sedan', + 'numptas' => '4', + 'observac' => 'Vehículo en buen estado', + 'cve_vehi' => 'CVE001', + 'tipo_mov' => 'Alta', + 'owner_id' => $owner->id, + ]); + + $this->info("✓ Vehículo creado: {$vehicle->marca} {$vehicle->linea} - Placa: {$vehicle->placa} (ID: {$vehicle->id})"); + $this->info("✓ Asociado al propietario: {$owner->full_name}"); + + $this->info('Creando tag...'); + + // Obtener el status "available" para crear el tag + $statusAvailable = CatalogTagStatus::where('code', Tag::STATUS_AVAILABLE)->first(); + + if (!$statusAvailable) { + throw new \Exception('No se encontró el status "available" en el catálogo. Ejecuta el seeder CatalogTagStatusSeeder primero.'); + } + + // Generar un folio único para el tag + $folio = str_pad(rand(1, 99999999), 8, '0', STR_PAD_LEFT); + + // Verificar que el folio no exista + while (Tag::where('folio', $folio)->exists()) { + $folio = str_pad(rand(1, 99999999), 8, '0', STR_PAD_LEFT); + } + + // Crear un tag disponible + $tag = Tag::create([ + 'folio' => $folio, + 'tag_number' => 'TAG' . str_pad(rand(1, 999999), 10, '0', STR_PAD_LEFT), + 'vehicle_id' => null, + 'package_id' => null, + 'module_id' => null, + 'status_id' => $statusAvailable->id, + ]); + + $this->info("✓ Tag creado: Folio {$tag->folio} - Tag Number: {$tag->tag_number} (ID: {$tag->id})"); + + // Asignar el tag al vehículo + $tag->markAsAssigned($vehicle->id, $folio); + + $this->info("✓ Tag asignado al vehículo: {$vehicle->placa}"); + + // Crear registro en el log de tags + VehicleTagLog::create([ + 'vehicle_id' => $vehicle->id, + 'tag_id' => $tag->id, + 'action_type' => 'inscripcion', + 'performed_by' => null, + ]); + + $this->info("✓ Registro de log creado"); + $this->newLine(); + $this->info('✓ Proceso completado exitosamente!'); + + return Command::SUCCESS; + } catch (\Exception $e) { + $this->error("✗ Error: " . $e->getMessage()); + return Command::FAILURE; + } + } +} + diff --git a/app/Http/Controllers/Repuve/ExcelController.php b/app/Http/Controllers/Repuve/ExcelController.php index af4c2b0..738e1f7 100644 --- a/app/Http/Controllers/Repuve/ExcelController.php +++ b/app/Http/Controllers/Repuve/ExcelController.php @@ -12,6 +12,7 @@ use App\Models\Tag; use App\Models\Module; use App\Models\TagCancellationLog; +use App\Models\Record; use Carbon\Carbon; use Notsoweb\ApiResponse\Enums\ApiResponse; use PhpOffice\PhpSpreadsheet\Spreadsheet; @@ -869,4 +870,279 @@ public function excelGeneral(Request $request) return response()->download($filePath, $fileName)->deleteFileAfterSend(true); } + + /** + * Exportar resultados de búsqueda a Excel + */ + public function exportSearchRecords(Request $request) + { + // Reutilizar la misma validación y lógica de búsqueda + $request->validate([ + 'folio' => 'nullable|string', + 'placa' => 'nullable|string', + 'vin' => 'nullable|string', + 'tag_number' => 'nullable|string', + 'module_id' => 'nullable|integer|exists:modules,id', + 'action_type' => 'nullable|string|in:inscripcion,actualizacion,sustitucion,cancelacion', + 'status' => 'nullable|string', + 'start_date' => 'nullable|date', + 'end_date' => 'nullable|date|after_or_equal:start_date', + ]); + + // Reutilizar la misma query de búsqueda (sin paginación) + $records = Record::with([ + 'vehicle', + 'vehicle.owner', + 'vehicle.tag:id,vehicle_id,folio,tag_number,status_id,package_id,module_id', + 'vehicle.tag.status:id,code,name', + 'vehicle.tag.package:id,lot,box_number', + 'vehicle.tag.module:id,name', + 'files:id,record_id,name_id,path,md5', + 'files.catalogName:id,name', + 'user:id,name,email,module_id', + 'module:id,name', + 'error:id,code,description', + 'vehicle.vehicleTagLogs' => function ($q) { + $q->with([ + 'tag:id,folio,tag_number,status_id,module_id,package_id', + 'tag.status:id,code,name', + 'tag.module:id,name', + 'tag.package:id,lot,box_number' + ])->orderBy('created_at', 'DESC'); + }, + ])->orderBy('id', 'ASC'); + + // Aplicar los mismos filtros + if ($request->filled('folio')) { + $records->whereHas('vehicle.tag', function ($q) use ($request) { + $q->where('folio', 'LIKE', '%' . $request->input('folio') . '%'); + }); + } + if ($request->filled('placa')) { + $records->whereHas('vehicle', function ($q) use ($request) { + $q->where('placa', 'LIKE', '%' . $request->input('placa') . '%'); + }); + } + if ($request->filled('vin')) { + $records->whereHas('vehicle', function ($q) use ($request) { + $q->where('niv', 'LIKE', '%' . $request->input('vin') . '%'); + }); + } + if ($request->filled('tag_number')) { + $records->whereHas('vehicle.tag', function ($q) use ($request) { + $q->where('tag_number', 'LIKE', '%' . $request->input('tag_number') . '%'); + }); + } + if ($request->filled('module_id')) { + $records->where('module_id', $request->input('module_id')); + } + if ($request->filled('action_type')) { + $records->whereHas('vehicle.vehicleTagLogs', function ($q) use ($request) { + $q->where('action_type', $request->input('action_type')) + ->whereRaw('id = ( + SELECT MAX(id) + FROM vehicle_tags_logs + WHERE vehicle_id = vehicle.id + )'); + }); + } + if ($request->filled('status')) { + $records->whereHas('vehicle.tag.status', function ($q) use ($request) { + $q->where('code', $request->input('status')); + }); + } + if ($request->filled('start_date')) { + $records->whereDate('created_at', '>=', $request->input('start_date')); + } + if ($request->filled('end_date')) { + $records->whereDate('created_at', '<=', $request->input('end_date')); + } + + $allRecords = $records->get(); + + if ($allRecords->isEmpty()) { + return ApiResponse::NOT_FOUND->response([ + 'message' => 'No se encontraron registros con los criterios de búsqueda proporcionados.', + ]); + } + + // Preparar datos para Excel: una fila por cada entrada del historial + $excelRows = []; + + foreach ($allRecords as $record) { + $niv = $record->vehicle->niv ?? ''; + $currentTagId = $record->vehicle->tag?->id; + $recordRows = []; // Filas para este registro principal + + // Obtener todos los logs ordenados por fecha ascendente + $vehicleLogs = $record->vehicle->vehicleTagLogs->sortBy('created_at'); + $processedTags = []; + + // Procesar tags del historial (excluyendo el tag actual) + foreach ($vehicleLogs as $log) { + $tagId = $log->tag_id; + + // Excluir el tag actual y solo procesar cada tag una vez + if ($tagId && $tagId !== $currentTagId && !in_array($tagId, $processedTags)) { + $processedTags[] = $tagId; + $tag = $log->tag; + + // Buscar todos los logs relacionados con este tag + $tagLogs = $vehicleLogs->where('tag_id', $tagId); + + // Buscar fecha de cancelación si existe + $cancelLog = $tagLogs + ->whereIn('action_type', ['cancelacion', 'sustitucion']) + ->whereNotNull('cancellation_at') + ->first(); + + // Obtener fecha de asignación (inscripción o sustitución) + $assignedLog = $tagLogs + ->whereIn('action_type', ['inscripcion', 'sustitucion']) + ->first(); + + // Determinar fecha: si fue cancelado, usar fecha de cancelación, sino fecha de asignación + $fecha = null; + $status = 'unknown'; + + if ($cancelLog && $cancelLog->cancellation_at) { + $fecha = Carbon::parse($cancelLog->cancellation_at); + $status = 'Cancelado'; + } elseif ($assignedLog && $assignedLog->created_at) { + $fecha = Carbon::parse($assignedLog->created_at); + $status = ucfirst($assignedLog->action_type); + } + + // Si no hay fecha, usar el status del tag + if (!$fecha) { + $status = $tag?->status?->name ?? 'unknown'; + } + + $recordRows[] = [ + 'status' => $status, + 'folio' => $tag?->folio ?? '', + 'tag' => $tag?->tag_number ?? '', + 'niv' => $niv, + 'fecha' => $fecha ? $fecha->format('d/m/Y H:i') : '', + 'sort_date' => $fecha ? $fecha->timestamp : 0, + 'record_id' => $record->id, // Para mantener agrupado + ]; + } + } + + // Ordenar las filas del historial por fecha ascendente + usort($recordRows, function ($a, $b) { + return $a['sort_date'] <=> $b['sort_date']; + }); + + // Agregar el registro principal (tag actual) al final del grupo + if ($record->vehicle->tag) { + $currentTag = $record->vehicle->tag; + $latestLog = $record->vehicle->vehicleTagLogs->first(); + + // Determinar fecha y status del tag actual + $fechaActual = null; + $statusActual = $currentTag->status?->name ?? 'unknown'; + + if ($latestLog) { + if ($latestLog->cancellation_at) { + $fechaActual = Carbon::parse($latestLog->cancellation_at); + $statusActual = 'Cancelado'; + } else { + $fechaActual = Carbon::parse($latestLog->created_at); + $statusActual = ucfirst($latestLog->action_type); + } + } else { + $fechaActual = $record->created_at ? Carbon::parse($record->created_at) : now(); + } + + $recordRows[] = [ + 'status' => $statusActual, + 'folio' => $currentTag->folio ?? '', + 'tag' => $currentTag->tag_number ?? '', + 'niv' => $niv, + 'fecha' => $fechaActual->format('d/m/Y H:i'), + 'sort_date' => $fechaActual->timestamp, + 'record_id' => $record->id, + ]; + } + + // Agregar todas las filas de este registro al array principal + $excelRows = array_merge($excelRows, $recordRows); + } + + // Crear Excel + $fileName = 'Busqueda_Registros_' . now()->format('Ymd_His') . '.xlsx'; + $filePath = storage_path('app/temp/' . $fileName); + if (!file_exists(dirname($filePath))) { + mkdir(dirname($filePath), 0755, true); + } + + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setTitle('Registros'); + + // Estilos + $headerStyle = [ + 'font' => ['bold' => true, 'size' => 11, 'color' => ['rgb' => 'FFFFFF']], + 'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => '4472C4']], + 'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER, 'wrapText' => true], + 'borders' => ['allBorders' => ['borderStyle' => PhpSpreadsheetBorder::BORDER_THIN]] + ]; + + $cellStyle = [ + 'borders' => ['allBorders' => ['borderStyle' => PhpSpreadsheetBorder::BORDER_THIN]], + 'alignment' => ['vertical' => Alignment::VERTICAL_CENTER, 'wrapText' => true], + ]; + + // Encabezados (solo las 5 columnas solicitadas) + $headers = [ + 'A' => 'Status', + 'B' => 'Folio', + 'C' => 'Tag', + 'D' => 'NIV', + 'E' => 'Fecha de Registro o Cancelación', + ]; + + $row = 1; + foreach ($headers as $col => $text) { + $sheet->setCellValue("{$col}{$row}", $text); + $sheet->getStyle("{$col}{$row}")->applyFromArray($headerStyle); + } + $sheet->getRowDimension($row)->setRowHeight(30); + + // Datos + $row = 2; + foreach ($excelRows as $item) { + $sheet->setCellValue('A' . $row, $item['status']); + $sheet->setCellValue('B' . $row, $item['folio']); + $sheet->setCellValue('C' . $row, $item['tag']); + $sheet->setCellValue('D' . $row, $item['niv']); + $sheet->setCellValue('E' . $row, $item['fecha']); + + // Aplicar estilos + foreach (range('A', 'E') as $col) { + $sheet->getStyle("{$col}{$row}")->applyFromArray($cellStyle); + } + + // Centrar algunas columnas + $sheet->getStyle("A{$row}")->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER); + $sheet->getStyle("E{$row}")->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER); + + $row++; + } + + // Ajustar anchos de columna + $sheet->getColumnDimension('A')->setWidth(20); + $sheet->getColumnDimension('B')->setWidth(18); + $sheet->getColumnDimension('C')->setWidth(20); + $sheet->getColumnDimension('D')->setWidth(22); + $sheet->getColumnDimension('E')->setWidth(25); + + // Guardar archivo + $writer = new Xlsx($spreadsheet); + $writer->save($filePath); + + return response()->download($filePath, $fileName)->deleteFileAfterSend(true); + } } diff --git a/app/Http/Controllers/Repuve/InscriptionController.php b/app/Http/Controllers/Repuve/InscriptionController.php index a015ca7..8aa6749 100644 --- a/app/Http/Controllers/Repuve/InscriptionController.php +++ b/app/Http/Controllers/Repuve/InscriptionController.php @@ -331,8 +331,10 @@ public function searchRecord(Request $request) // Log de acciones 'vehicle.vehicleTagLogs' => function ($q) { $q->with([ - 'tag:id,folio,tag_number,status_id', - 'tag.status:id,code,name' + 'tag:id,folio,tag_number,status_id,module_id,package_id', + 'tag.status:id,code,name', + 'tag.module:id,name', + 'tag.package:id,lot,box_number' ])->orderBy('created_at', 'DESC'); }, ])->orderBy('id', 'ASC'); @@ -428,6 +430,8 @@ public function searchRecord(Request $request) 'folio' => $tag?->folio, 'tag_number' => $tag?->tag_number, 'status' => $tag?->status?->code ?? 'unknown', + 'module_name' => $tag?->module?->name, + 'box_number' => $tag?->package?->box_number, 'assigned_at' => $vehicleLogs->where('tag_id', $tagId) ->whereIn('action_type', ['inscripcion', 'sustitucion']) ->first()?->created_at, diff --git a/routes/api.php b/routes/api.php index c9021b8..440cd8e 100644 --- a/routes/api.php +++ b/routes/api.php @@ -35,6 +35,7 @@ // Rutas de inscripción de vehículos Route::post('inscripcion', [InscriptionController::class, 'vehicleInscription']); Route::get('consultaV', [InscriptionController::class, 'searchRecord']); + Route::get('consultaV/export', [ExcelController::class, 'exportSearchRecords']); Route::post('reporte-robado', [InscriptionController::class, 'stolen']); // Rutas de expedientes y documentos diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..eec9e4f --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,53 @@ +# Scripts de Tinker + +## seed_owner_vehicle.php + +Script para crear un propietario y un vehículo de ejemplo en la base de datos. + +### Uso (Recomendado - Comando Artisan) + +La forma más fácil de ejecutar el script es usando el comando Artisan: + +```bash +# Desde el contenedor Docker +docker exec repuve-backend-v1-repuve-backend-1 php artisan seed:owner-vehicle + +# O si estás dentro del contenedor +php artisan seed:owner-vehicle +``` + +### Uso alternativo con Tinker + +#### Opción 1: Copiar y pegar en Tinker (Más confiable) +```bash +php artisan tinker +``` +Luego copia y pega el contenido del archivo `scripts/seed_owner_vehicle_tinker.txt` en la consola de Tinker. + +#### Opción 2: Ejecutar con require +```bash +php artisan tinker +``` +Luego dentro de Tinker: +```php +require 'scripts/seed_owner_vehicle.php'; +``` + +#### Opción 3: Ejecutar desde línea de comandos (puede no funcionar en todos los casos) +```bash +php artisan tinker < scripts/seed_owner_vehicle.php +``` + +### Personalización + +Puedes modificar los valores en el script antes de ejecutarlo para crear registros con datos específicos: + +- **Propietario**: Cambia los campos como `name`, `paternal`, `maternal`, `rfc`, `curp`, etc. +- **Vehículo**: Modifica `placa`, `niv`, `marca`, `linea`, `modelo`, etc. + +### Notas + +- El script crea un propietario y luego un vehículo asociado a ese propietario. +- Los campos únicos (`rfc`, `curp`, `placa`, `niv`, `rfv`) deben ser únicos en la base de datos. +- Si ejecutas el script múltiples veces, asegúrate de cambiar estos valores únicos. + diff --git a/scripts/seed_owner_vehicle.php b/scripts/seed_owner_vehicle.php new file mode 100644 index 0000000..34af9f1 --- /dev/null +++ b/scripts/seed_owner_vehicle.php @@ -0,0 +1,115 @@ + 'Juan', + 'paternal' => 'Pérez', + 'maternal' => 'García', + 'rfc' => 'PEGJ850101ABC', + 'curp' => 'PEGJ850101HDFRRN01', + 'address' => 'Calle Principal 123', + 'tipopers' => true, // true = Persona física, false = Persona moral + 'pasaporte' => null, + 'licencia' => 'LIC123456789', + 'ent_fed' => 'Ciudad de México', + 'munic' => 'Benito Juárez', + 'callep' => 'Calle Principal', + 'num_ext' => '123', + 'num_int' => 'A', + 'colonia' => 'Centro', + 'cp' => '03100', + 'telefono' => '5551234567', + ]); + + echo "✓ Propietario creado: {$owner->full_name} (ID: {$owner->id})\n"; + + // Crear un vehículo asociado al propietario + $vehicle = Vehicle::create([ + 'placa' => 'ABC-123', + 'niv' => '1HGBH41JXMN109186', + 'marca' => 'Honda', + 'linea' => 'Civic', + 'sublinea' => 'Sedan', + 'modelo' => '2020', + 'color' => 'Blanco', + 'numero_motor' => 'ENG123456789', + 'clase_veh' => 'Automóvil', + 'tipo_servicio' => 'Particular', + 'rfv' => 'RFV123456789', + 'ofcexpedicion' => 'Oficina Central', + 'fechaexpedicion' => '2020-01-15', + 'tipo_veh' => 'Sedan', + 'numptas' => '4', + 'observac' => 'Vehículo en buen estado', + 'cve_vehi' => 'CVE001', + 'tipo_mov' => 'Alta', + 'owner_id' => $owner->id, + ]); + + echo "✓ Vehículo creado: {$vehicle->marca} {$vehicle->linea} - Placa: {$vehicle->placa} (ID: {$vehicle->id})\n"; + echo "✓ Asociado al propietario: {$owner->full_name}\n"; + + // Obtener el status "available" para crear el tag + $statusAvailable = CatalogTagStatus::where('code', Tag::STATUS_AVAILABLE)->first(); + + if (!$statusAvailable) { + throw new \Exception('No se encontró el status "available" en el catálogo. Ejecuta el seeder CatalogTagStatusSeeder primero.'); + } + + // Generar un folio único para el tag + $folio = str_pad(rand(1, 99999999), 8, '0', STR_PAD_LEFT); + + // Verificar que el folio no exista + while (Tag::where('folio', $folio)->exists()) { + $folio = str_pad(rand(1, 99999999), 8, '0', STR_PAD_LEFT); + } + + // Crear un tag disponible + $tag = Tag::create([ + 'folio' => $folio, + 'tag_number' => 'TAG' . str_pad(rand(1, 999999), 10, '0', STR_PAD_LEFT), + 'vehicle_id' => null, + 'package_id' => null, + 'module_id' => null, + 'status_id' => $statusAvailable->id, + ]); + + echo "✓ Tag creado: Folio {$tag->folio} - Tag Number: {$tag->tag_number} (ID: {$tag->id})\n"; + + // Asignar el tag al vehículo + $tag->markAsAssigned($vehicle->id, $folio); + + echo "✓ Tag asignado al vehículo: {$vehicle->placa}\n"; + + // Crear registro en el log de tags (opcional pero recomendado) + VehicleTagLog::create([ + 'vehicle_id' => $vehicle->id, + 'tag_id' => $tag->id, + 'action_type' => 'inscripcion', + 'performed_by' => null, // Puedes asignar un user_id si tienes usuarios + ]); + + echo "✓ Registro de log creado\n"; + echo "\n✓ Proceso completado exitosamente!\n"; + + return [ + 'owner' => $owner, + 'vehicle' => $vehicle, + 'tag' => $tag, + ]; +} catch (\Exception $e) { + echo "✗ Error: " . $e->getMessage() . "\n"; + throw $e; +} + diff --git a/scripts/seed_owner_vehicle_tinker.txt b/scripts/seed_owner_vehicle_tinker.txt new file mode 100644 index 0000000..97f67de --- /dev/null +++ b/scripts/seed_owner_vehicle_tinker.txt @@ -0,0 +1,100 @@ +// Copia y pega este código directamente en Tinker (sin las etiquetas 'Juan', + 'paternal' => 'Pérez', + 'maternal' => 'García', + 'rfc' => 'PEGJ850101ABC', + 'curp' => 'PEGJ850101HDFRRN01', + 'address' => 'Calle Principal 123', + 'tipopers' => true, + 'pasaporte' => null, + 'licencia' => 'LIC123456789', + 'ent_fed' => 'Ciudad de México', + 'munic' => 'Benito Juárez', + 'callep' => 'Calle Principal', + 'num_ext' => '123', + 'num_int' => 'A', + 'colonia' => 'Centro', + 'cp' => '03100', + 'telefono' => '5551234567', +]); + +echo "Propietario creado: {$owner->full_name} (ID: {$owner->id})\n"; + +// Crear un vehículo asociado al propietario +$vehicle = Vehicle::create([ + 'placa' => 'ABC-123', + 'niv' => '1HGBH41JXMN109186', + 'marca' => 'Honda', + 'linea' => 'Civic', + 'sublinea' => 'Sedan', + 'modelo' => '2020', + 'color' => 'Blanco', + 'numero_motor' => 'ENG123456789', + 'clase_veh' => 'Automóvil', + 'tipo_servicio' => 'Particular', + 'rfv' => 'RFV123456789', + 'ofcexpedicion' => 'Oficina Central', + 'fechaexpedicion' => '2020-01-15', + 'tipo_veh' => 'Sedan', + 'numptas' => '4', + 'observac' => 'Vehículo en buen estado', + 'cve_vehi' => 'CVE001', + 'tipo_mov' => 'Alta', + 'owner_id' => $owner->id, +]); + +echo "Vehículo creado: {$vehicle->marca} {$vehicle->linea} - Placa: {$vehicle->placa} (ID: {$vehicle->id})\n"; +echo "Asociado al propietario: {$owner->full_name}\n"; + +// Obtener el status "available" para crear el tag +$statusAvailable = CatalogTagStatus::where('code', Tag::STATUS_AVAILABLE)->first(); + +if (!$statusAvailable) { + throw new Exception('No se encontró el status "available" en el catálogo. Ejecuta el seeder CatalogTagStatusSeeder primero.'); +} + +// Generar un folio único para el tag +$folio = str_pad(rand(1, 99999999), 8, '0', STR_PAD_LEFT); + +// Verificar que el folio no exista +while (Tag::where('folio', $folio)->exists()) { + $folio = str_pad(rand(1, 99999999), 8, '0', STR_PAD_LEFT); +} + +// Crear un tag disponible +$tag = Tag::create([ + 'folio' => $folio, + 'tag_number' => 'TAG' . str_pad(rand(1, 999999), 10, '0', STR_PAD_LEFT), + 'vehicle_id' => null, + 'package_id' => null, + 'module_id' => null, + 'status_id' => $statusAvailable->id, +]); + +echo "Tag creado: Folio {$tag->folio} - Tag Number: {$tag->tag_number} (ID: {$tag->id})\n"; + +// Asignar el tag al vehículo +$tag->markAsAssigned($vehicle->id, $folio); + +echo "Tag asignado al vehículo: {$vehicle->placa}\n"; + +// Crear registro en el log de tags +VehicleTagLog::create([ + 'vehicle_id' => $vehicle->id, + 'tag_id' => $tag->id, + 'action_type' => 'inscripcion', + 'performed_by' => null, +]); + +echo "Registro de log creado\n"; +echo "Proceso completado exitosamente!\n"; +