fix: correción de archivos

This commit is contained in:
Juan Felipe Zapata Moreno 2025-12-09 16:53:54 -06:00
parent dcac63f953
commit b68d360274
6 changed files with 324 additions and 182 deletions

View File

@ -0,0 +1,59 @@
<?php
namespace App\Helpers;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Facades\Log;
class EncryptionHelper
{
/**
* Encrypt the given data.
*/
public static function encryptData($data)
{
try{
return Crypt::encryptString(json_encode($data));
}catch(\Exception $e){
throw new \RuntimeException("Error al encriptar los datos: " . $e->getMessage());
}
}
/**
* Decrypt the given data.
*/
public static function decryptData($encryptedData)
{
try{
$decrypted = Crypt::decryptString($encryptedData);
return json_decode($decrypted, true);
}catch(DecryptException $e){
Log::error('Error al desencriptar los datos: ' . $e->getMessage());
return null;
}catch(\Exception $e){
Log::error('Error inesperado al desencriptar los datos: ' . $e->getMessage());
return null;
}
}
public static function encryptFields(array $data, array $fields)
{
foreach ($fields as $field){
if(isset($data[$field])){
$data[$field] = self::encryptData($data[$field]);
}
}
return $data;
}
public static function decryptFields(array $data, array $fields)
{
foreach ($fields as $field){
if(isset($data[$field])){
$data[$field] = self::decryptData($data[$field]);
}
}
return $data;
}
}

View File

@ -56,28 +56,34 @@ private function consultarPadron(string $tipo, string $valor): array
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $soapBody); curl_setopt($ch, CURLOPT_POSTFIELDS, $soapBody);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_HTTPHEADER, [ curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: text/xml; charset=utf-8', 'Content-Type: text/xml; charset=utf-8',
'SOAPAction: ""', 'SOAPAction: ""',
'Content-Length: ' . strlen($soapBody) 'Content-Length: ' . strlen($soapBody)
]); ]);
// Ejecutar la petición try {
$response = curl_exec($ch); // Ejecutar la petición
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $response = curl_exec($ch);
$error = curl_error($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch); $error = curl_error($ch);
if ($error) { if ($error) {
throw new Exception("Error en la petición al padrón estatal: {$error}"); throw new Exception("Error en la petición al padrón estatal: {$error}");
}
if ($httpCode !== 200) {
throw new Exception("Error HTTP {$httpCode} al consultar padrón estatal");
}
// Parsear la respuesta
return $this->parsearRespuesta($response);
} finally {
// Liberar recursos del CurlHandle (PHP 8.0+)
unset($ch);
} }
if ($httpCode !== 200) {
throw new Exception("Error HTTP {$httpCode} al consultar padrón estatal");
}
// Parsear la respuesta
return $this->parsearRespuesta($response);
} }
/** /**

View File

@ -44,27 +44,32 @@ public function consultarPadron(string $niv)
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $soapBody); curl_setopt($ch, CURLOPT_POSTFIELDS, $soapBody);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_HTTPHEADER, [ curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: text/xml; charset=utf-8', 'Content-Type: text/xml; charset=utf-8',
'SOAPAction: "doConsPadron"', 'SOAPAction: "doConsPadron"',
'Content-Length: ' . strlen($soapBody), 'Content-Length: ' . strlen($soapBody),
]); ]);
// Ejecutar la solicitud try {
$response = curl_exec($ch); // Ejecutar la solicitud
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $response = curl_exec($ch);
$error = curl_error($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch); $error = curl_error($ch);
if ($error) { if ($error) {
throw new Exception("Error en la petición SOAP: {$error}"); throw new Exception("Error en la petición SOAP: {$error}");
}
if ($httpCode !== 200) {
throw new Exception("Error al consultar REPUVE: Código HTTP {$httpCode}");
}
return $this->parseVehicleResponse($response, $niv);
} finally {
unset($ch);
} }
if ($httpCode !== 200) {
throw new Exception("Error al consultar REPUVE: Código HTTP {$httpCode}");
}
return $this->parseVehicleResponse($response, $niv);
} }
@ -214,60 +219,65 @@ public function verificarRobo(?string $niv = null, ?string $placa = null): array
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $soapBody); curl_setopt($ch, CURLOPT_POSTFIELDS, $soapBody);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_HTTPHEADER, [ curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: text/xml; charset=utf-8', 'Content-Type: text/xml; charset=utf-8',
'SOAPAction: "doConsRepRobo"', 'SOAPAction: "doConsRepRobo"',
'Content-Length: ' . strlen($soapBody), 'Content-Length: ' . strlen($soapBody),
]); ]);
$response = curl_exec($ch); try {
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $response = curl_exec($ch);
$error = curl_error($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch); $error = curl_error($ch);
// Si hay error de conexión, retornar error // Si hay error de conexión, retornar error
if ($error) { if ($error) {
logger()->error('REPUVE verificarRobo: Error de conexión', [ logger()->error('REPUVE verificarRobo: Error de conexión', [
'error' => $error, 'error' => $error,
'niv' => $niv, 'niv' => $niv,
'placa' => $placa, 'placa' => $placa,
]); ]);
return [ return [
'is_robado' => false, 'is_robado' => false,
'has_error' => true, 'has_error' => true,
'error_message' => 'Error de conexión con el servicio REPUVE', 'error_message' => 'Error de conexión con el servicio REPUVE',
]; ];
}
// Si hay error HTTP, retornar error
if ($httpCode !== 200) {
logger()->error('REPUVE verificarRobo: HTTP error', [
'http_code' => $httpCode,
'niv' => $niv,
'placa' => $placa,
]);
return [
'is_robado' => false,
'has_error' => true,
'error_message' => "Error HTTP {$httpCode} del servicio REPUVE",
];
}
// Parsear respuesta
$valorBuscado = $niv ?: $placa ?: 'N/A';
$resultado = $this->parseRoboResponse($response, $valorBuscado);
// Si hubo error al parsear, loguear pero retornar el resultado completo
if ($resultado['has_error'] ?? false) {
logger()->warning('REPUVE verificarRobo: Error al parsear respuesta', [
'niv' => $niv,
'placa' => $placa,
'error' => $resultado['error_message'] ?? 'Desconocido',
]);
}
// Retornar el array completo con toda la información
return $resultado;
} finally {
unset($ch);
} }
// Si hay error HTTP, retornar error
if ($httpCode !== 200) {
logger()->error('REPUVE verificarRobo: HTTP error', [
'http_code' => $httpCode,
'niv' => $niv,
'placa' => $placa,
]);
return [
'is_robado' => false,
'has_error' => true,
'error_message' => "Error HTTP {$httpCode} del servicio REPUVE",
];
}
// Parsear respuesta
$valorBuscado = $niv ?: $placa ?: 'N/A';
$resultado = $this->parseRoboResponse($response, $valorBuscado);
// Si hubo error al parsear, loguear pero retornar el resultado completo
if ($resultado['has_error'] ?? false) {
logger()->warning('REPUVE verificarRobo: Error al parsear respuesta', [
'niv' => $niv,
'placa' => $placa,
'error' => $resultado['error_message'] ?? 'Desconocido',
]);
}
// Retornar el array completo con toda la información
return $resultado;
} catch (Exception $e) { } catch (Exception $e) {
logger()->error('REPUVE verificarRobo: Excepción capturada', [ logger()->error('REPUVE verificarRobo: Excepción capturada', [
'niv' => $niv, 'niv' => $niv,
@ -311,55 +321,60 @@ public function consultarVehiculo(?string $niv = null, ?string $placa = null)
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $soapBody); curl_setopt($ch, CURLOPT_POSTFIELDS, $soapBody);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_HTTPHEADER, [ curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: text/xml; charset=utf-8', 'Content-Type: text/xml; charset=utf-8',
'SOAPAction: "doConsRPV"', 'SOAPAction: "doConsRPV"',
'Content-Length: ' . strlen($soapBody), 'Content-Length: ' . strlen($soapBody),
]); ]);
$response = curl_exec($ch); try {
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $response = curl_exec($ch);
$error = curl_error($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch); $error = curl_error($ch);
if ($error) { if ($error) {
logger()->error('REPUVE consultarVehiculo: Error de conexión', [ logger()->error('REPUVE consultarVehiculo: Error de conexión', [
'error' => $error, 'error' => $error,
'niv' => $niv, 'niv' => $niv,
'placa' => $placa, 'placa' => $placa,
]); ]);
return [ return [
'success' => false, 'success' => false,
'has_error' => true, 'has_error' => true,
'error_message' => 'Error de conexión con el servicio REPUVE', 'error_message' => 'Error de conexión con el servicio REPUVE',
]; ];
}
if ($httpCode !== 200) {
logger()->error('REPUVE consultarVehiculo: HTTP error', [
'http_code' => $httpCode,
'niv' => $niv,
'placa' => $placa,
]);
return [
'success' => false,
'has_error' => true,
'error_message' => "Error HTTP {$httpCode} del servicio REPUVE",
];
}
// Parsear respuesta
$resultado = $this->parseConsultarVehiculoResponse($response);
if ($resultado['has_error'] ?? false) {
logger()->warning('REPUVE consultarVehiculo: Error al parsear', [
'niv' => $niv,
'placa' => $placa,
'error' => $resultado['error_message'] ?? 'Desconocido',
]);
}
return $resultado;
} finally {
unset($ch);
} }
if ($httpCode !== 200) {
logger()->error('REPUVE consultarVehiculo: HTTP error', [
'http_code' => $httpCode,
'niv' => $niv,
'placa' => $placa,
]);
return [
'success' => false,
'has_error' => true,
'error_message' => "Error HTTP {$httpCode} del servicio REPUVE",
];
}
// Parsear respuesta
$resultado = $this->parseConsultarVehiculoResponse($response);
if ($resultado['has_error'] ?? false) {
logger()->warning('REPUVE consultarVehiculo: Error al parsear', [
'niv' => $niv,
'placa' => $placa,
'error' => $resultado['error_message'] ?? 'Desconocido',
]);
}
return $resultado;
} catch (Exception $e) { } catch (Exception $e) {
logger()->error('REPUVE consultarVehiculo: Excepción', [ logger()->error('REPUVE consultarVehiculo: Excepción', [
'niv' => $niv, 'niv' => $niv,
@ -438,58 +453,63 @@ public function inscribirVehiculo(array $datos)
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $soapBody); curl_setopt($ch, CURLOPT_POSTFIELDS, $soapBody);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_HTTPHEADER, [ curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: text/xml; charset=utf-8', 'Content-Type: text/xml; charset=utf-8',
'SOAPAction: "inscribe"', 'SOAPAction: "inscribe"',
'Content-Length: ' . strlen($soapBody), 'Content-Length: ' . strlen($soapBody),
]); ]);
// Ejecutar la petición try {
$response = curl_exec($ch); // Ejecutar la petición
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $response = curl_exec($ch);
$curlError = curl_error($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch); $curlError = curl_error($ch);
// Loguear para debug // Loguear para debug
logger()->info('REPUVE Inscripción Request', [ logger()->info('REPUVE Inscripción Request', [
'url' => $url, 'url' => $url,
'soap_body' => $soapBody 'soap_body' => $soapBody
]); ]);
logger()->info('REPUVE Inscripción Response', [ logger()->info('REPUVE Inscripción Response', [
'http_code' => $httpCode,
'curl_error' => $curlError,
'response' => $response
]);
if ($curlError) {
$errorFromDb = Error::where('code', '103')->first();
return [
'has_error' => true,
'error_code' => '103',
'error_name' => $errorFromDb?->name,
'error_message' => $errorFromDb?->description ?? "Error de conexión: {$curlError}",
'timestamp' => now()->toDateTimeString(),
'http_code' => $httpCode, 'http_code' => $httpCode,
'raw_response' => $response, 'curl_error' => $curlError,
]; 'response' => $response
} ]);
if ($httpCode !== 200) { if ($curlError) {
$errorFromDb = Error::where('code', '-1')->first(); $errorFromDb = Error::where('code', '103')->first();
return [ return [
'has_error' => true, 'has_error' => true,
'error_code' => '-1', 'error_code' => '103',
'error_name' => $errorFromDb?->name, 'error_name' => $errorFromDb?->name,
'error_message' => $errorFromDb?->description ?? "Error interno HTTP {$httpCode}", 'error_message' => $errorFromDb?->description ?? "Error de conexión: {$curlError}",
'timestamp' => now()->toDateTimeString(), 'timestamp' => now()->toDateTimeString(),
'http_code' => $httpCode, 'http_code' => $httpCode,
'raw_response' => $response, 'raw_response' => $response,
]; ];
} }
// Parsear la respuesta if ($httpCode !== 200) {
return $this->parsearRespuestaInscripcion($response); $errorFromDb = Error::where('code', '-1')->first();
return [
'has_error' => true,
'error_code' => '-1',
'error_name' => $errorFromDb?->name,
'error_message' => $errorFromDb?->description ?? "Error interno HTTP {$httpCode}",
'timestamp' => now()->toDateTimeString(),
'http_code' => $httpCode,
'raw_response' => $response,
];
}
// Parsear la respuesta
return $this->parsearRespuestaInscripcion($response);
} finally {
unset($ch);
}
} }
/** /**

View File

@ -39,13 +39,13 @@
.left-col-marca { .left-col-marca {
position: absolute; position: absolute;
left: 5mm; left: 5mm;
top: 35mm; top: 33mm;
} }
.left-col-linea-modelo { .left-col-linea-modelo {
position: absolute; position: absolute;
left: 5mm; left: 5mm;
top: 41mm; top: 39mm;
width: 75mm; width: 75mm;
} }
@ -63,20 +63,20 @@
.left-col-propietario { .left-col-propietario {
position: absolute; position: absolute;
left: 5mm; left: 5mm;
top: 45mm; top: 43mm;
} }
.left-col-direccion { .left-col-direccion {
position: absolute; position: absolute;
left: 5mm; left: 5mm;
top: 50mm; top: 48mm;
font-size: 8pt; font-size: 8pt;
} }
.left-col-municipio { .left-col-municipio {
position: absolute; position: absolute;
left: 5mm; left: 5mm;
top: 55mm; top: 52mm;
} }
/* COLUMNA DERECHA */ /* COLUMNA DERECHA */
@ -191,7 +191,7 @@
<!-- PARTICULAR --> <!-- PARTICULAR -->
<div class="right-col-particular "> <div class="right-col-particular ">
{{ strtoupper($record->vehicle->tipo_veh) }} {{ strtoupper($record->vehicle->tipo_servicio) }}
</div> </div>
</div> </div>
</body> </body>

View File

@ -24,7 +24,6 @@
.header { .header {
text-align: center; text-align: center;
border-bottom: 2px solid #000;
padding-bottom: 15px; padding-bottom: 15px;
margin-bottom: 25px; margin-bottom: 25px;
} }
@ -98,14 +97,41 @@
} }
.data-row { .data-row {
margin-bottom: 9px; margin-bottom: 8px;
position: relative;
font-size: 10pt; font-size: 10pt;
} }
.data-label { .data-label {
font-weight: bold; font-weight: bold;
position: absolute;
left: 0;
}
.data-label-long {
font-weight: bold;
position: absolute;
left: 0;
font-size: 9pt;
}
.data-value {
margin-left: 80px;
}
.data-value-long {
margin-left: 144px;
}
.extra-field {
font-weight: bold;
margin-left: 40px;
display: inline-block; display: inline-block;
min-width: 100px; }
.extra-value {
display: inline-block;
margin-left: 10px;
} }
.address-row { .address-row {
@ -114,12 +140,12 @@
} }
.signatures { .signatures {
margin-top: 60px; margin-top: 100px;
} }
.footer-registro { .footer-registro {
text-align: center; text-align: center;
margin-top: 15px; margin-top: 120px;
color: red; color: red;
font-weight: bold; font-weight: bold;
font-size: 9pt; font-size: 9pt;
@ -153,6 +179,23 @@
font-size: 10pt; font-size: 10pt;
font-weight: bold; font-weight: bold;
} }
.date-section {
text-align: right;
margin-bottom: 20px;
font-size: 10pt;
}
.date-label {
font-weight: bold;
display: inline-block;
}
.date-value {
display: inline-block;
margin-left: 10px;
text-transform: uppercase;
}
</style> </style>
</head> </head>
@ -199,37 +242,45 @@
<div class="owner-section"> <div class="owner-section">
<div class="data-row"> <div class="data-row">
<span class="data-label">RFC:</span> <span class="data-label">RFC:</span>
<span>{{ $record->vehicle->owner->rfc ?? '' }}</span> <span class="data-value">{{ $record->vehicle->owner->rfc ?? '' }}</span>
</div> </div>
<div class="data-row"> <div class="data-row">
<span class="data-label">NOMBRE:</span> <span class="data-label">NOMBRE:</span>
<span>{{ $record->vehicle->owner->full_name ?? '' }}</span> <span class="data-value">{{ $record->vehicle->owner->full_name ?? '' }}</span>
</div> </div>
<div class="data-row"> <div class="data-row">
<span class="data-label">CALLE:</span> <span class="data-label">CALLE:</span>
<span style="display: inline-block; min-width: 200px;">{{ $record->vehicle->owner->callep ?? '' }}</span> <span class="data-value">{{ $record->vehicle->owner->callep ?? '' }}</span>
<span style="display: inline-block; margin-left: 20px;"><strong>No Ext:</strong> {{ $record->vehicle->owner->num_ext ?? '' }}</span> <span class="extra-field">No Ext:</span>
<span style="display: inline-block; margin-left: 20px;"><strong>No Int:</strong> {{ $record->vehicle->owner->num_int ?? '' }}</span> <span class="extra-value">{{ $record->vehicle->owner->num_ext ?? '' }}</span>
<span class="extra-field">No Int:</span>
<span class="extra-value">{{ $record->vehicle->owner->num_int ?? '' }}</span>
</div> </div>
<div class="data-row"> <div class="data-row">
<span class="data-label">COLONIA:</span> <span class="data-label">COLONIA:</span>
<span>{{ $record->vehicle->owner->colonia ?? '' }}</span> <span class="data-value">{{ $record->vehicle->owner->colonia ?? '' }}</span>
</div> </div>
<div class="data-row"> <div class="data-row">
<span class="data-label">MUNICIPIO:</span> <span class="data-label">MUNICIPIO:</span>
<span>{{ $record->vehicle->owner->munic ?? '' }}</span> <span class="data-value">{{ $record->vehicle->owner->municipality->name ?? '' }}</span>
</div> </div>
<div class="data-row"> <div class="data-row">
<span class="data-label">NUMERO TELEFONICO:</span> <span class="data-label-long">NUMERO TELEFONICO:</span>
<span>{{ $record->vehicle->owner->telefono ?? '' }}</span> <span class="data-value-long">{{ $record->vehicle->owner->telefono ?? '' }}</span>
</div> </div>
</div> </div>
<!-- Fecha -->
<div class="date-section">
<span class="date-value">VILLAHERMOSA, TABASCO A {{ \Carbon\Carbon::parse($record->created_at)->locale('es')->isoFormat('D [DE] MMMM [DE] YYYY') }}</span>
</div>
<!-- Firmas --> <!-- Firmas -->
<div class="signatures"> <div class="signatures">
<table class="signature-table"> <table class="signature-table">

View File

@ -29,7 +29,7 @@
} }
.header h1 { .header h1 {
font-size: 11pt; font-size: 20pt;
font-weight: bold; font-weight: bold;
margin: 0; margin: 0;
padding: 2px 0; padding: 2px 0;
@ -60,21 +60,21 @@
table { table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
margin-top: 86px; margin-top: 150px;
} }
table th { table th {
background-color: #c00040; background-color: #c00040;
color: white; color: white;
font-weight: bold; font-weight: bold;
padding: 8px 5px; padding: 4.5px 5px;
text-align: center; text-align: center;
border: 1px solid #000; border: 1px solid #000;
} }
table td { table td {
background-color: #f5deb3; background-color: #f5deb3;
padding: 6px 5px; padding: 4px 5px;
border: 1px solid #000; border: 1px solid #000;
font-size: 8pt; font-size: 8pt;
} }
@ -105,6 +105,10 @@
.obs-column { .obs-column {
min-width: 150px; min-width: 150px;
} }
.correct-column{
width: 120px;
}
</style> </style>
</head> </head>
@ -112,7 +116,7 @@
<div class="container"> <div class="container">
<!-- Header --> <!-- Header -->
<div class="header"> <div class="header">
<h1>HOJA DE VERIFICACION VEHICULAR</h1> <h1>HOJA DE VERIFICACIÓN </h1>
</div> </div>
<!-- Firma del operador --> <!-- Firma del operador -->
<div class="signature-section"> <div class="signature-section">
@ -126,14 +130,16 @@
<thead> <thead>
<tr> <tr>
<th colspan="2">ORIGINAL</th> <th colspan="2">ORIGINAL</th>
<th>CORRECTO</th> <th class="correct-column">CORRECTO</th>
<th>NUEVO</th> <th>NUEVO</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr class="section-original"> <tr class="section-original">
<td class="id-column">COLOR</td> <td class="id-column">COLOR</td>
<td colspan="3">{{ strtoupper($record->vehicle->color) }}</td> <td>{{ strtoupper($record->vehicle->color) }}</td>
<td class="white-bg"></td>
<td class="gray-bg"></td>
</tr> </tr>
<tr class="section-original"> <tr class="section-original">
<td class="id-column">PLACA</td> <td class="id-column">PLACA</td>