657 lines
23 KiB
PHP
657 lines
23 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Repuve;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Barryvdh\DomPDF\Facade\Pdf;
|
|
use App\Models\Record;
|
|
use App\Models\Tag;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Notsoweb\ApiResponse\Enums\ApiResponse;
|
|
use Codedge\Fpdf\Fpdf\Fpdf;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Routing\Controllers\HasMiddleware;
|
|
|
|
class RecordController extends Controller implements HasMiddleware
|
|
{
|
|
/**
|
|
* Middleware
|
|
*/
|
|
public static function middleware(): array
|
|
{
|
|
return [
|
|
self::can('records.generate_pdf', ['generatePdf']),
|
|
self::can('records.generate_pdf_form', ['generatePdfForm']),
|
|
self::can('records.generate_pdf_constancia', ['generatePdfConstancia']),
|
|
self::can('records.generate_pdf_verification', ['generatePdfVerification']),
|
|
];
|
|
}
|
|
|
|
public function generatePdf($id)
|
|
{
|
|
$record = Record::with('vehicle.owner', 'user', 'module')->findOrFail($id);
|
|
|
|
$pdf = Pdf::loadView('pdfs.record', compact('record'))
|
|
->setPaper('a4', 'portrait')
|
|
->setOptions([
|
|
'defaultFont' => 'sans-serif',
|
|
'isHtml5ParserEnabled' => true,
|
|
'isRemoteEnabled' => true,
|
|
]);
|
|
|
|
return $pdf->stream('constancia-inscripcion-' . $id . '.pdf');
|
|
}
|
|
|
|
public function generatePdfVerification($id)
|
|
{
|
|
$record = Record::with('vehicle.owner', 'user')->findOrFail($id);
|
|
|
|
$pdf = Pdf::loadView('pdfs.verification', compact('record'))
|
|
->setPaper('a4', 'landscape')
|
|
->setOptions([
|
|
'defaultFont' => 'sans-serif',
|
|
'isHtml5ParserEnabled' => true,
|
|
'isRemoteEnabled' => true,
|
|
]);
|
|
|
|
return $pdf->stream('hoja-verificacion-' . $id . '.pdf');
|
|
}
|
|
|
|
public function generatePdfConstancia($id)
|
|
{
|
|
$record = Record::with('vehicle.owner.municipality', 'user')->findOrFail($id);
|
|
|
|
// Preparar datos con conversión UTF-8 a mayúsculas
|
|
$data = [
|
|
'niv' => $record->vehicle->niv,
|
|
'placa' => mb_strtoupper($record->vehicle->placa, 'UTF-8'),
|
|
'marca' => mb_strtoupper($record->vehicle->marca, 'UTF-8'),
|
|
'linea' => mb_strtoupper($record->vehicle->linea, 'UTF-8'),
|
|
'modelo' => $record->vehicle->modelo,
|
|
'full_name' => mb_strtoupper($record->vehicle->owner->full_name, 'UTF-8'),
|
|
'callep' => mb_strtoupper($record->vehicle->owner->callep ?? '', 'UTF-8'),
|
|
'num_ext' => $record->vehicle->owner->num_ext,
|
|
'municipality' => mb_strtoupper($record->vehicle->owner->municipality->name ?? '', 'UTF-8'),
|
|
'tipo_servicio' => mb_strtoupper($record->vehicle->tipo_servicio, 'UTF-8'),
|
|
];
|
|
|
|
$pdf = Pdf::loadView('pdfs.constancia', $data)
|
|
->setPaper('a4', 'landscape')
|
|
->setOptions([
|
|
'defaultFont' => 'DejaVu Sans',
|
|
'isHtml5ParserEnabled' => true,
|
|
'isRemoteEnabled' => true,
|
|
]);
|
|
|
|
return $pdf->stream('constancia-inscripcion' . $id . '.pdf');
|
|
}
|
|
|
|
/**
|
|
* Generar PDF con las imágenes
|
|
*/
|
|
public function generatePdfImages($id)
|
|
{
|
|
try {
|
|
// Obtener el record con sus archivos
|
|
$record = Record::with(['vehicle.owner', 'files'])->findOrFail($id);
|
|
|
|
// Validar que tenga archivos
|
|
if ($record->files->isEmpty()) {
|
|
return ApiResponse::NOT_FOUND->response([
|
|
'message' => 'El expediente no tiene imágenes adjuntas.',
|
|
'record_id' => $id,
|
|
]);
|
|
}
|
|
|
|
// Crear instancia de FPDF
|
|
$pdf = new Fpdf('P', 'mm', 'A4');
|
|
$pdf->SetAutoPageBreak(false);
|
|
$pdf->SetMargins(10, 10, 10);
|
|
|
|
$currentImage = 0;
|
|
|
|
foreach ($record->files as $file) {
|
|
$currentImage++;
|
|
|
|
// Buscar archivo en disk 'records'
|
|
$diskRecords = Storage::disk('records');
|
|
|
|
$fileContent = null;
|
|
if ($diskRecords->exists($file->path)) {
|
|
$fileContent = $diskRecords->get($file->path);
|
|
}
|
|
|
|
// Si no se encontró el archivo, continuar
|
|
if ($fileContent === null) {
|
|
continue;
|
|
}
|
|
|
|
// Agregar nueva página
|
|
$pdf->AddPage();
|
|
|
|
// Header con folio
|
|
$pdf->SetFillColor(44, 62, 80);
|
|
$pdf->Rect(0, 0, 210, 20, 'F');
|
|
$pdf->SetTextColor(255, 255, 255);
|
|
$pdf->SetFont('Arial', 'B', 14);
|
|
$pdf->SetXY(10, 7);
|
|
$pdf->Cell(0, 6, 'FOLIO: ' . $record->folio, 0, 1, 'L');
|
|
|
|
// Obtener ruta temporal del archivo
|
|
$tempPath = tempnam(sys_get_temp_dir(), 'pdf_img_');
|
|
file_put_contents($tempPath, $fileContent);
|
|
|
|
// Obtener dimensiones de la imagen
|
|
$imageInfo = getimagesize($tempPath);
|
|
|
|
if ($imageInfo !== false) {
|
|
list($originalWidth, $originalHeight) = $imageInfo;
|
|
$imageType = $imageInfo[2];
|
|
|
|
$availableWidth = 190; // 210mm - 20mm márgenes
|
|
$availableHeight = 247; // 297mm - 20mm header - 20mm footer - 10mm márgenes
|
|
|
|
// Calcular dimensiones manteniendo proporción
|
|
$ratio = min($availableWidth / $originalWidth, $availableHeight / $originalHeight);
|
|
$newWidth = $originalWidth * $ratio;
|
|
$newHeight = $originalHeight * $ratio;
|
|
|
|
// Centrar imagen
|
|
$x = (210 - $newWidth) / 2;
|
|
$y = 25 + (($availableHeight - $newHeight) / 2);
|
|
|
|
// Determinar tipo de imagen
|
|
$imageExtension = '';
|
|
switch ($imageType) {
|
|
case IMAGETYPE_JPEG:
|
|
$imageExtension = 'JPEG';
|
|
break;
|
|
case IMAGETYPE_JPEG:
|
|
$imageExtension = 'JPG';
|
|
break;
|
|
case IMAGETYPE_PNG:
|
|
$imageExtension = 'PNG';
|
|
break;
|
|
default:
|
|
// Si no es un formato soportado, continuar
|
|
unlink($tempPath);
|
|
continue 2;
|
|
}
|
|
|
|
// Insertar imagen
|
|
$pdf->Image($tempPath, $x, $y, $newWidth, $newHeight, $imageExtension);
|
|
}
|
|
|
|
// Limpiar archivo temporal
|
|
unlink($tempPath);
|
|
}
|
|
|
|
// Verificar que se agregaron páginas
|
|
if ($pdf->PageNo() == 0) {
|
|
return ApiResponse::NOT_FOUND->response([
|
|
'message' => 'No se pudieron procesar las imágenes del expediente.',
|
|
'record_id' => $id,
|
|
]);
|
|
}
|
|
|
|
// Generar PDF
|
|
$pdfContent = $pdf->Output('S');
|
|
|
|
return response($pdfContent, 200)
|
|
->header('Content-Type', 'application/pdf')
|
|
->header('Content-Disposition', 'inline; filename="expediente-imagenes-' . $record->folio . '.pdf"');
|
|
} catch (\Exception $e) {
|
|
return ApiResponse::INTERNAL_ERROR->response([
|
|
'message' => 'Error al generar el PDF de imágenes',
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function generatePdfForm($id)
|
|
{
|
|
try {
|
|
$record = Record::with([
|
|
'vehicle',
|
|
'vehicle.owner',
|
|
'vehicle.tag',
|
|
])->findOrFail($id);
|
|
|
|
if (!$record->vehicle) {
|
|
return ApiResponse::NOT_FOUND->response([
|
|
'message' => 'El registro no tiene un vehículo asociado.',
|
|
'record_id' => $id,
|
|
]);
|
|
}
|
|
|
|
$vehicle = $record->vehicle;
|
|
$owner = $vehicle->owner;
|
|
$tag = $vehicle->tag;
|
|
|
|
$now = Carbon::now()->locale('es_MX');
|
|
|
|
$data = [
|
|
// Datos del vehículo
|
|
'marca' => strtoupper($vehicle->marca ?? ''),
|
|
'linea' => strtoupper($vehicle->linea ?? ''),
|
|
'modelo' => $vehicle->modelo ?? '',
|
|
'niv' => strtoupper($vehicle->niv ?? ''),
|
|
'numero_motor' => strtoupper($vehicle->numero_motor ?? ''),
|
|
'placa' => strtoupper($vehicle->placa ?? ''),
|
|
'folio' => $tag?->folio ?? $record->folio ?? '',
|
|
|
|
// Datos del propietario
|
|
'telefono' => $owner?->telefono ?? '',
|
|
|
|
// Fecha actual
|
|
'fecha' => $now->format('d'),
|
|
'mes' => ucfirst($now->translatedFormat('F')),
|
|
'anio' => $now->format('Y'),
|
|
|
|
'record_id' => $record->id,
|
|
'owner_name' => $owner?->full_name ?? '',
|
|
];
|
|
|
|
$pdf = Pdf::loadView('pdfs.form', $data)
|
|
->setPaper('a4', 'portrait')
|
|
->setOptions([
|
|
'defaultFont' => 'sans-serif',
|
|
'isHtml5ParserEnabled' => true,
|
|
'isRemoteEnabled' => true,
|
|
]);
|
|
|
|
return $pdf->stream('solicitud-sustitucion-' . time() . '.pdf');
|
|
} catch (\Exception $e) {
|
|
return ApiResponse::NOT_FOUND->response([
|
|
'message' => 'No se encontró el registro del expediente proporcionado.',
|
|
'record_id' => $id,
|
|
]);
|
|
} catch (\Exception $e) {
|
|
return ApiResponse::INTERNAL_ERROR->response([
|
|
'message' => 'Error al generar el PDF del formulario',
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function pdfDamagedTag(Tag $tag)
|
|
{
|
|
try{
|
|
$tag->load('status');
|
|
|
|
if(!$tag->status){
|
|
return ApiResponse::NOT_FOUND->response([
|
|
'message' => 'El tag no tiene un estado asociado.',
|
|
'tag_id' => $tag->id,
|
|
]);
|
|
}
|
|
|
|
// Validar que el tag esté cancelado
|
|
if (!$tag->isDamaged()) {
|
|
return ApiResponse::BAD_REQUEST->response([
|
|
'message' => 'Solo se puede generar PDF para tags dañados.',
|
|
'current_status' => $tag->status->name,
|
|
]);
|
|
}
|
|
|
|
// Obtener datos de cancelación
|
|
$cancellationData = $this->cancellationData($tag);
|
|
|
|
$pdf = Pdf::loadView('pdfs.tag', [
|
|
'cancellation' => $cancellationData,
|
|
])
|
|
->setPaper('a4', 'portrait')
|
|
->setOptions([
|
|
'defaultFont' => 'sans-serif',
|
|
'isHtml5ParserEnabled' => true,
|
|
'isRemoteEnabled' => true,
|
|
]);
|
|
|
|
return $pdf->stream('constancia_dañada_' . $tag->tag_number . '.pdf');
|
|
|
|
} catch (\Exception $e) {
|
|
return ApiResponse::INTERNAL_ERROR->response([
|
|
'message' => 'Error al generar el PDF.',
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function pdfCancelledTag(Tag $tag)
|
|
{
|
|
try {
|
|
$tag->load('status');
|
|
|
|
if(!$tag->status){
|
|
return ApiResponse::NOT_FOUND->response([
|
|
'message' => 'El tag no tiene un estado asociado.',
|
|
'tag_id' => $tag->id,
|
|
]);
|
|
}
|
|
|
|
// Validar que el tag esté cancelado
|
|
if (!$tag->isCancelled()) {
|
|
return ApiResponse::BAD_REQUEST->response([
|
|
'message' => 'Solo se puede generar PDF para tags cancelados.',
|
|
'current_status' => $tag->status->name,
|
|
]);
|
|
}
|
|
|
|
// Obtener datos de cancelación
|
|
$cancellationData = $this->cancellationData($tag);
|
|
|
|
$pdf = Pdf::loadView('pdfs.tag_cancelada', [
|
|
'cancellation' => $cancellationData,
|
|
])
|
|
->setPaper('a4', 'portrait')
|
|
->setOptions([
|
|
'defaultFont' => 'sans-serif',
|
|
'isHtml5ParserEnabled' => true,
|
|
'isRemoteEnabled' => true,
|
|
]);
|
|
|
|
return $pdf->stream('constancia_cancelada_' . $tag->tag_number . '.pdf');
|
|
} catch (\Exception $e) {
|
|
return ApiResponse::INTERNAL_ERROR->response([
|
|
'message' => 'Error al generar el PDF.',
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function pdfSubstitutedTag($recordId)
|
|
{
|
|
try {
|
|
// Validar que el tag tenga una sustitución registrada
|
|
$record = Record::with([
|
|
'vehicle.vehicleTagLogs' => function ($query){
|
|
$query->where('action_type', 'sustitucion')
|
|
->whereNotNull('cancellation_at')
|
|
->latest();
|
|
}
|
|
])->findOrFail($recordId);
|
|
|
|
$oldTagLog = $record->vehicle->vehicleTagLogs->first();
|
|
|
|
if (!$oldTagLog) {
|
|
return ApiResponse::BAD_REQUEST->response([
|
|
'message' => 'No se encontró una sustitución registrada para este expediente.',
|
|
'record' => $recordId,
|
|
]);
|
|
}
|
|
|
|
// Obtener datos de sustitución
|
|
$oldTag = Tag::with([
|
|
'vehicleTagLogs' => function($query){
|
|
$query->where('action_type', 'sustitucion')
|
|
->whereNotNull('cancellation_at')
|
|
->with(['cancellationReason', 'cancelledBy', 'vehicle'])
|
|
->latest();
|
|
}
|
|
])->findOrFail($oldTagLog->tag_id);
|
|
|
|
$hasSubstitution = $oldTag->vehicleTagLogs()
|
|
->where('action_type', 'sustitucion')
|
|
->whereNotNull('cancellation_at')
|
|
->exists();
|
|
|
|
if(!$hasSubstitution){
|
|
return ApiResponse::BAD_REQUEST->response([
|
|
'message' => 'El tag no tiene sustitución registrada.',
|
|
'tag' => $oldTag->folio,
|
|
]);
|
|
}
|
|
|
|
$substitutionData = $this->substitutionData($oldTag);
|
|
|
|
$pdf = Pdf::loadView('pdfs.tag_sustitution', [
|
|
'substitution' => $substitutionData,
|
|
])
|
|
->setPaper('a4', 'portrait')
|
|
->setOptions([
|
|
'defaultFont' => 'sans-serif',
|
|
'isHtml5ParserEnabled' => true,
|
|
'isRemoteEnabled' => true,
|
|
]);
|
|
|
|
return $pdf->stream('constancia_sustituida_' . $oldTag->folio . '.pdf');
|
|
} catch (\Exception $e) {
|
|
return ApiResponse::INTERNAL_ERROR->response([
|
|
'message' => 'Error al generar el PDF del tag sustituido.',
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
|
|
private function cancellationData(Tag $tag)
|
|
{
|
|
$data = [
|
|
'fecha' => now()->format('d/m/Y'),
|
|
'folio' => $tag->folio ?? '',
|
|
'tag_number' => $tag->tag_number ?? '',
|
|
'placa' => '',
|
|
'niv' => '',
|
|
'motivo' => 'N/A',
|
|
'operador' => 'N/A',
|
|
'modulo' => 'No especificado',
|
|
'ubicacion' => 'No especificado',
|
|
];
|
|
|
|
// Cargar módulo del tag si existe
|
|
if ($tag->module_id) {
|
|
$tag->load('module');
|
|
if ($tag->module) {
|
|
$data['modulo'] = $tag->module->name ?? '';
|
|
$data['ubicacion'] = $tag->module->address ?? '';
|
|
}
|
|
}
|
|
|
|
// Intentar obtener datos del vehículo si existe
|
|
if ($tag->vehicle_id && $tag->vehicle) {
|
|
$data['id_chip'] = $tag->vehicle->id_chip ?? '';
|
|
$data['placa'] = $tag->vehicle->placa ?? '';
|
|
$data['niv'] = $tag->vehicle->niv ?? '';
|
|
} else {
|
|
// Si el tag no tiene vehicle_id, buscar en el último log
|
|
$lastLog = $tag->vehicleTagLogs()
|
|
->with('vehicle')
|
|
->whereNotNull('vehicle_id')
|
|
->latest('created_at')
|
|
->first();
|
|
|
|
if ($lastLog && $lastLog->vehicle) {
|
|
$data['id_chip'] = $lastLog->vehicle->id_chip ?? '';
|
|
$data['placa'] = $lastLog->vehicle->placa ?? '';
|
|
$data['niv'] = $lastLog->vehicle->niv ?? '';
|
|
}
|
|
}
|
|
|
|
// Buscar log de cancelación directa
|
|
$tagCancellationLog = $tag->cancellationLogs()
|
|
->with(['cancellationReason', 'cancelledBy'])
|
|
->latest()
|
|
->first();
|
|
|
|
if ($tagCancellationLog) {
|
|
$data['fecha'] = $tagCancellationLog->cancellation_at->format('d/m/Y');
|
|
$data['motivo'] = $tagCancellationLog->cancellationReason->name ?? 'No especificado';
|
|
$data['operador'] = $tagCancellationLog->cancelledBy->name ?? 'Sistema';
|
|
|
|
// Extraer datos adicionales de las observaciones
|
|
$this->extractAdditionalDataFromObservations($tagCancellationLog->cancellation_observations, $data);
|
|
|
|
// Cargar módulo del tag si existe, sino cargar módulo del usuario
|
|
if ($tag->module_id && $tag->module) {
|
|
$data['modulo'] = $tag->module->name;
|
|
$data['ubicacion'] = $tag->module->address;
|
|
} elseif ($tagCancellationLog->cancelledBy) {
|
|
$user = $tagCancellationLog->cancelledBy;
|
|
$this->loadUserModule($user, $data);
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
// Buscar log de vehículo (tag asignado y luego cancelado)
|
|
$vehicleTagLog = $tag->vehicleTagLogs()
|
|
->where('action_type', ['cancelacion', 'sustitucion'])
|
|
->with(['cancellationReason', 'cancelledBy', 'vehicle'])
|
|
->latest()
|
|
->first();
|
|
|
|
if ($vehicleTagLog) {
|
|
$data['motivo'] = $vehicleTagLog->cancellationReason->name ?? 'No especificado';
|
|
$data['operador'] = $vehicleTagLog->cancelledBy->name ?? 'Sistema';
|
|
|
|
// Cargar módulo del cual el usuario es responsable
|
|
if ($vehicleTagLog->cancelledBy) {
|
|
$user = $vehicleTagLog->cancelledBy;
|
|
$this->loadUserModule($user, $data);
|
|
}
|
|
|
|
if ($vehicleTagLog->vehicle) {
|
|
$data['id_chip'] = $vehicleTagLog->vehicle->id_chip ?? '';
|
|
$data['placa'] = $vehicleTagLog->vehicle->placa ?? '';
|
|
$data['niv'] = $vehicleTagLog->vehicle->niv ?? '';
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Extraer datos adicionales de las observaciones de cancelación
|
|
*/
|
|
private function extractAdditionalDataFromObservations($observations, &$data)
|
|
{
|
|
if (empty($observations)) {
|
|
return;
|
|
}
|
|
|
|
// Extraer ID CHIP
|
|
if (preg_match('/ID CHIP:\s*([^|]+)/', $observations, $matches)) {
|
|
$data['id_chip'] = trim($matches[1]);
|
|
}
|
|
|
|
// Extraer PLACA
|
|
if (preg_match('/PLACA:\s*([^|]+)/', $observations, $matches)) {
|
|
$data['placa'] = trim($matches[1]);
|
|
}
|
|
|
|
// Extraer VIN
|
|
if (preg_match('/VIN:\s*([^|]+)/', $observations, $matches)) {
|
|
$data['niv'] = trim($matches[1]);
|
|
}
|
|
}
|
|
|
|
private function substitutionData(Tag $tag)
|
|
{
|
|
$data = [
|
|
'fecha' => now()->format('d/m/Y'),
|
|
'folio' => $tag->folio ?? '',
|
|
'folio_sustituto' => '',
|
|
'id_chip' => '',
|
|
'placa' => '',
|
|
'niv' => '',
|
|
'motivo' => 'N/A',
|
|
'operador' => 'N/A',
|
|
'modulo' => '',
|
|
'ubicacion' => '',
|
|
];
|
|
|
|
// log de CANCELACIÓN del tag original
|
|
$oldTagLog = $tag->vehicleTagLogs()
|
|
->where('action_type', 'sustitucion')
|
|
->whereNotNull('cancellation_at')
|
|
->with(['cancellationReason', 'cancelledBy', 'vehicle'])
|
|
->latest()
|
|
->first();
|
|
|
|
if (!$oldTagLog) {
|
|
return $data; // No se encontró sustitución
|
|
}
|
|
|
|
// datos del motivo y operador
|
|
$data['fecha'] = $oldTagLog->cancellation_at->format('d/m/Y');
|
|
$data['motivo'] = $oldTagLog->cancellationReason->name ?? 'No especificado';
|
|
$data['operador'] = $oldTagLog->cancelledBy->name ?? 'Sistema';
|
|
|
|
// módulo del usuario
|
|
if ($oldTagLog->cancelledBy) {
|
|
$this->loadUserModule($oldTagLog->cancelledBy, $data);
|
|
}
|
|
|
|
// datos del vehículo
|
|
if ($oldTagLog->vehicle) {
|
|
$data['id_chip'] = $oldTagLog->vehicle->id_chip ?? '';
|
|
$data['placa'] = $oldTagLog->vehicle->placa ?? '';
|
|
$data['niv'] = $oldTagLog->vehicle->niv ?? '';
|
|
|
|
// tag NUEVO
|
|
$newTag = $oldTagLog->vehicle->tag;
|
|
$data['folio_sustituto'] = $newTag?->folio ?? '';
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Cargar módulo del usuario
|
|
*/
|
|
private function loadUserModule($user, &$data)
|
|
{
|
|
// Intentar cargar module
|
|
$user->load('module');
|
|
|
|
// Si no tiene module, usar responsibleModule
|
|
if (!$user->module) {
|
|
$user->load('responsibleModule');
|
|
|
|
if ($user->responsibleModule) {
|
|
$data['modulo'] = $user->responsibleModule->name;
|
|
$data['ubicacion'] = $user->responsibleModule->address;
|
|
}
|
|
} else {
|
|
$data['modulo'] = $user->module->name;
|
|
$data['ubicacion'] = $user->module->address;
|
|
}
|
|
}
|
|
|
|
public function errors(Request $request)
|
|
{
|
|
$request->validate([
|
|
'folio' => 'nullable|string',
|
|
'placa' => 'nullable|string',
|
|
'vin' => 'nullable|string',
|
|
]);
|
|
|
|
$records = Record::with(['vehicle.owner', 'vehicle.tag', 'files', 'user', 'error'])
|
|
->whereNotNull('api_response')
|
|
->whereRaw("JSON_EXTRACT(api_response, '$.has_error') = true")
|
|
->orderBy('id', 'ASC');
|
|
|
|
if ($request->filled('folio')) {
|
|
$records->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') . '%');
|
|
});
|
|
}
|
|
|
|
return ApiResponse::OK->response([
|
|
'message' => 'Expedientes con errores encontrados exitosamente',
|
|
'records' => $records->paginate(config('app.pagination')),
|
|
]);
|
|
}
|
|
}
|