Generar excel

This commit is contained in:
Rubi Almora 2026-01-15 12:38:10 -06:00
parent 7c530595f4
commit d6bf6b42ed
7 changed files with 691 additions and 2 deletions

View File

@ -0,0 +1,140 @@
<?php
namespace App\Console\Commands;
use App\Models\Owner;
use App\Models\Vehicle;
use App\Models\Tag;
use App\Models\CatalogTagStatus;
use App\Models\VehicleTagLog;
use Illuminate\Console\Command;
class SeedOwnerVehicle extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'seed:owner-vehicle';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Crear un propietario y un vehículo de ejemplo';
/**
* Execute the console command.
*/
public function handle()
{
try {
$this->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;
}
}
}

View File

@ -12,6 +12,7 @@
use App\Models\Tag; use App\Models\Tag;
use App\Models\Module; use App\Models\Module;
use App\Models\TagCancellationLog; use App\Models\TagCancellationLog;
use App\Models\Record;
use Carbon\Carbon; use Carbon\Carbon;
use Notsoweb\ApiResponse\Enums\ApiResponse; use Notsoweb\ApiResponse\Enums\ApiResponse;
use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Spreadsheet;
@ -869,4 +870,279 @@ public function excelGeneral(Request $request)
return response()->download($filePath, $fileName)->deleteFileAfterSend(true); 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);
}
} }

View File

@ -331,8 +331,10 @@ public function searchRecord(Request $request)
// Log de acciones // Log de acciones
'vehicle.vehicleTagLogs' => function ($q) { 'vehicle.vehicleTagLogs' => function ($q) {
$q->with([ $q->with([
'tag:id,folio,tag_number,status_id', 'tag:id,folio,tag_number,status_id,module_id,package_id',
'tag.status:id,code,name' 'tag.status:id,code,name',
'tag.module:id,name',
'tag.package:id,lot,box_number'
])->orderBy('created_at', 'DESC'); ])->orderBy('created_at', 'DESC');
}, },
])->orderBy('id', 'ASC'); ])->orderBy('id', 'ASC');
@ -428,6 +430,8 @@ public function searchRecord(Request $request)
'folio' => $tag?->folio, 'folio' => $tag?->folio,
'tag_number' => $tag?->tag_number, 'tag_number' => $tag?->tag_number,
'status' => $tag?->status?->code ?? 'unknown', 'status' => $tag?->status?->code ?? 'unknown',
'module_name' => $tag?->module?->name,
'box_number' => $tag?->package?->box_number,
'assigned_at' => $vehicleLogs->where('tag_id', $tagId) 'assigned_at' => $vehicleLogs->where('tag_id', $tagId)
->whereIn('action_type', ['inscripcion', 'sustitucion']) ->whereIn('action_type', ['inscripcion', 'sustitucion'])
->first()?->created_at, ->first()?->created_at,

View File

@ -35,6 +35,7 @@
// Rutas de inscripción de vehículos // Rutas de inscripción de vehículos
Route::post('inscripcion', [InscriptionController::class, 'vehicleInscription']); Route::post('inscripcion', [InscriptionController::class, 'vehicleInscription']);
Route::get('consultaV', [InscriptionController::class, 'searchRecord']); Route::get('consultaV', [InscriptionController::class, 'searchRecord']);
Route::get('consultaV/export', [ExcelController::class, 'exportSearchRecords']);
Route::post('reporte-robado', [InscriptionController::class, 'stolen']); Route::post('reporte-robado', [InscriptionController::class, 'stolen']);
// Rutas de expedientes y documentos // Rutas de expedientes y documentos

53
scripts/README.md Normal file
View File

@ -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.

View File

@ -0,0 +1,115 @@
<?php
// Script para ejecutar en Tinker
// Copia y pega este contenido directamente en Tinker o ejecuta:
// php artisan tinker --execute="require 'scripts/seed_owner_vehicle.php';"
use App\Models\Owner;
use App\Models\Vehicle;
use App\Models\Tag;
use App\Models\CatalogTagStatus;
use App\Models\VehicleTagLog;
try {
// Crear un propietario
$owner = Owner::create([
'name' => '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;
}

View File

@ -0,0 +1,100 @@
// Copia y pega este código directamente en Tinker (sin las etiquetas <?php)
use App\Models\Owner;
use App\Models\Vehicle;
use App\Models\Tag;
use App\Models\CatalogTagStatus;
use App\Models\VehicleTagLog;
// 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',
]);
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";