feat: mejora la consulta y presentación de datos en la generación de constancias de sustitución de TAGs
This commit is contained in:
parent
f5c4fce98a
commit
633198e5ae
@ -59,7 +59,7 @@ public function vehicleActualizaciones(Request $request)
|
|||||||
|
|
||||||
$module = $moduleId ? Module::find($moduleId) : null;
|
$module = $moduleId ? Module::find($moduleId) : null;
|
||||||
|
|
||||||
// Consulta de Logs de actualizaciones
|
// Consulta de Logs de actualizaciones (último por vehículo)
|
||||||
$logs = VehicleTagLog::with(['vehicle', 'tag', 'performedBy.module'])
|
$logs = VehicleTagLog::with(['vehicle', 'tag', 'performedBy.module'])
|
||||||
->where('action_type', 'actualizacion')
|
->where('action_type', 'actualizacion')
|
||||||
->when($moduleId, function ($query) use ($moduleId) {
|
->when($moduleId, function ($query) use ($moduleId) {
|
||||||
@ -68,8 +68,11 @@ public function vehicleActualizaciones(Request $request)
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
->whereBetween('created_at', [$fechaInicio, $fechaFin])
|
->whereBetween('created_at', [$fechaInicio, $fechaFin])
|
||||||
->orderBy('created_at', 'asc')
|
->orderBy('created_at', 'desc')
|
||||||
->get();
|
->get()
|
||||||
|
->unique('vehicle_id')
|
||||||
|
->sortBy('created_at')
|
||||||
|
->values();
|
||||||
|
|
||||||
if ($logs->isEmpty()) {
|
if ($logs->isEmpty()) {
|
||||||
return response()->json(['message' => 'No se encontraron registros de actualizaciones.'], 404);
|
return response()->json(['message' => 'No se encontraron registros de actualizaciones.'], 404);
|
||||||
@ -83,7 +86,7 @@ public function vehicleActualizaciones(Request $request)
|
|||||||
'placa' => $log->vehicle->placa ?? '',
|
'placa' => $log->vehicle->placa ?? '',
|
||||||
'modelo' => $log->vehicle->modelo ?? '',
|
'modelo' => $log->vehicle->modelo ?? '',
|
||||||
'folio' => $log->tag->folio ?? '',
|
'folio' => $log->tag->folio ?? '',
|
||||||
'chip' => $log->tag->tag_number ?? '',
|
'chip' => substr($log->tag->rfid ?? $log->tag->tag_number ?? '', 0, 24),
|
||||||
'fecha' => $log->created_at->format('d/m/Y'),
|
'fecha' => $log->created_at->format('d/m/Y'),
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
@ -316,15 +319,26 @@ public function constanciasSustituidas(Request $request)
|
|||||||
|
|
||||||
// Consulta de Logs
|
// Consulta de Logs
|
||||||
$logs = VehicleTagLog::with(['vehicle', 'tag', 'cancellationReason'])
|
$logs = VehicleTagLog::with(['vehicle', 'tag', 'cancellationReason'])
|
||||||
->where('action_type', 'sustitucion')
|
->where(function ($query) use ($fechaInicio, $fechaFin) {
|
||||||
->whereNotNull('cancellation_at')
|
// sustitucion normal: el log del TAG viejo tiene cancellation_at
|
||||||
|
$query->where(function ($q) use ($fechaInicio, $fechaFin) {
|
||||||
|
$q->where('action_type', 'sustitucion')
|
||||||
|
->whereNotNull('cancellation_at')
|
||||||
|
->whereBetween('cancellation_at', [$fechaInicio, $fechaFin]);
|
||||||
|
})
|
||||||
|
// sustitucion_primera_vez: un solo log sin cancellation_at, filtrar por created_at
|
||||||
|
->orWhere(function ($q) use ($fechaInicio, $fechaFin) {
|
||||||
|
$q->where('action_type', 'sustitucion_primera_vez')
|
||||||
|
->whereNull('cancellation_at')
|
||||||
|
->whereBetween('created_at', [$fechaInicio, $fechaFin]);
|
||||||
|
});
|
||||||
|
})
|
||||||
->when($moduleId, function ($query) use ($moduleId) {
|
->when($moduleId, function ($query) use ($moduleId) {
|
||||||
$query->whereHas('performedBy', function ($q) use ($moduleId) {
|
$query->whereHas('performedBy', function ($q) use ($moduleId) {
|
||||||
$q->where('module_id', $moduleId);
|
$q->where('module_id', $moduleId);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
->whereBetween('cancellation_at', [$fechaInicio, $fechaFin])
|
->orderByRaw('COALESCE(cancellation_at, created_at) ASC')
|
||||||
->orderBy('cancellation_at', 'asc')
|
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
if ($logs->isEmpty()) {
|
if ($logs->isEmpty()) {
|
||||||
@ -333,9 +347,26 @@ public function constanciasSustituidas(Request $request)
|
|||||||
|
|
||||||
// PREPARACIÓN DE DATOS
|
// PREPARACIÓN DE DATOS
|
||||||
$data = $logs->map(function ($log) {
|
$data = $logs->map(function ($log) {
|
||||||
|
// sustitucion_primera_vez: un solo log, el log mismo ES el nuevo TAG asignado
|
||||||
|
if ($log->action_type === 'sustitucion_primera_vez') {
|
||||||
|
return [
|
||||||
|
'niv' => $log->vehicle->niv ?? '',
|
||||||
|
'nrpv' => $log->vehicle->nrpv ?? '',
|
||||||
|
'marca' => $log->vehicle->marca ?? '',
|
||||||
|
'placa' => $log->vehicle->placa ?? '',
|
||||||
|
'modelo' => $log->vehicle->modelo ?? '',
|
||||||
|
'folio_ant' => '',
|
||||||
|
'folio_act' => $log->tag->folio ?? '',
|
||||||
|
'chip' => substr($log->tag->rfid ?? $log->tag->tag_number ?? '', 0, 24),
|
||||||
|
'fecha' => $log->created_at->format('d/m/Y'),
|
||||||
|
'observaciones' => $log->cancellationReason?->name ?? $log->cancellation_observations ?? '',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// sustitucion normal: este log es el TAG viejo cancelado, buscar el nuevo TAG
|
||||||
$newTagLog = VehicleTagLog::with('tag')
|
$newTagLog = VehicleTagLog::with('tag')
|
||||||
->where('vehicle_id', $log->vehicle_id)
|
->where('vehicle_id', $log->vehicle_id)
|
||||||
->where('action_type', 'sustitucion')
|
->whereIn('action_type', ['sustitucion_primera_vez', 'sustitucion'])
|
||||||
->whereNull('cancellation_at')
|
->whereNull('cancellation_at')
|
||||||
->where('id', '!=', $log->id)
|
->where('id', '!=', $log->id)
|
||||||
->where('created_at', '>=', $log->created_at)
|
->where('created_at', '>=', $log->created_at)
|
||||||
@ -350,7 +381,7 @@ public function constanciasSustituidas(Request $request)
|
|||||||
'modelo' => $log->vehicle->modelo ?? '',
|
'modelo' => $log->vehicle->modelo ?? '',
|
||||||
'folio_ant' => $log->tag->folio ?? '',
|
'folio_ant' => $log->tag->folio ?? '',
|
||||||
'folio_act' => $newTagLog?->tag?->folio ?? '',
|
'folio_act' => $newTagLog?->tag?->folio ?? '',
|
||||||
'chip' => $newTagLog?->tag?->rfid ?? $newTagLog?->tag?->tag_number ?? '',
|
'chip' => substr($newTagLog?->tag?->rfid ?? $newTagLog?->tag?->tag_number ?? '', 0, 24),
|
||||||
'fecha' => $log->cancellation_at?->format('d/m/Y') ?? $log->created_at->format('d/m/Y'),
|
'fecha' => $log->cancellation_at?->format('d/m/Y') ?? $log->created_at->format('d/m/Y'),
|
||||||
'observaciones' => $log->cancellationReason?->name ?? $log->cancellation_observations ?? '',
|
'observaciones' => $log->cancellationReason?->name ?? $log->cancellation_observations ?? '',
|
||||||
];
|
];
|
||||||
@ -632,7 +663,7 @@ public function constanciasCanceladas(Request $request)
|
|||||||
$data = $allLogs->map(function ($log) {
|
$data = $allLogs->map(function ($log) {
|
||||||
return [
|
return [
|
||||||
'folio' => $log->tag->folio ?? 'S/F',
|
'folio' => $log->tag->folio ?? 'S/F',
|
||||||
'tag_number' => $log->tag->tag_number ?? 'N/A',
|
'tag_number' => substr( $log->tag->tag_number ?? '', 0, 24) ?? 'N/A',
|
||||||
'fecha' => $log->cancellation_at ? Carbon::parse($log->cancellation_at)->format('d/m/Y') : '',
|
'fecha' => $log->cancellation_at ? Carbon::parse($log->cancellation_at)->format('d/m/Y') : '',
|
||||||
'motivo' => $log->cancellationReason->name ?? 'DAÑADA',
|
'motivo' => $log->cancellationReason->name ?? 'DAÑADA',
|
||||||
];
|
];
|
||||||
@ -799,10 +830,10 @@ public function constanciasCanceladas(Request $request)
|
|||||||
$sheet->setCellValue("G{$h1}", "ID DE LA\nCONSTANCIA (CHIP)");
|
$sheet->setCellValue("G{$h1}", "ID DE LA\nCONSTANCIA (CHIP)");
|
||||||
|
|
||||||
$sheet->mergeCells("J{$h1}:K{$h2}");
|
$sheet->mergeCells("J{$h1}:K{$h2}");
|
||||||
$sheet->setCellValue("J{$h1}", "FECHA DE\nCANCELACIÓN");
|
$sheet->setCellValue("J{$h1}", "FECHA DE\nVINCULACIÓN");
|
||||||
|
|
||||||
$sheet->mergeCells("L{$h1}:N{$h2}");
|
$sheet->mergeCells("L{$h1}:N{$h2}");
|
||||||
$sheet->setCellValue("L{$h1}", "MOTIVO DE\nCANCELACIÓN");
|
$sheet->setCellValue("L{$h1}", "OBSERVACIONES \n(MOTIVO DEL DAÑO, ERRORES, ETC)");
|
||||||
// Aplicar estilo beige
|
// Aplicar estilo beige
|
||||||
$sheet->getStyle("A{$h1}:N{$h2}")->applyFromArray($styleTableHeader);
|
$sheet->getStyle("A{$h1}:N{$h2}")->applyFromArray($styleTableHeader);
|
||||||
$sheet->getRowDimension($h1)->setRowHeight(20);
|
$sheet->getRowDimension($h1)->setRowHeight(20);
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
use Barryvdh\DomPDF\Facade\Pdf;
|
use Barryvdh\DomPDF\Facade\Pdf;
|
||||||
use App\Models\Record;
|
use App\Models\Record;
|
||||||
use App\Models\Tag;
|
use App\Models\Tag;
|
||||||
|
use App\Models\VehicleTagLog;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Notsoweb\ApiResponse\Enums\ApiResponse;
|
use Notsoweb\ApiResponse\Enums\ApiResponse;
|
||||||
@ -387,50 +388,80 @@ public function pdfCancelledTag(Tag $tag)
|
|||||||
public function pdfSubstitutedTag($recordId)
|
public function pdfSubstitutedTag($recordId)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// Validar que el tag tenga una sustitución registrada
|
$record = Record::with(['vehicle.tag'])->findOrFail($recordId);
|
||||||
$record = Record::with([
|
|
||||||
'vehicle.vehicleTagLogs' => function ($query){
|
|
||||||
$query->where('action_type', 'sustitucion')
|
|
||||||
->whereNotNull('cancellation_at')
|
|
||||||
->latest();
|
|
||||||
}
|
|
||||||
])->findOrFail($recordId);
|
|
||||||
|
|
||||||
$oldTagLog = $record->vehicle->vehicleTagLogs->first();
|
// Sustitución real: existe un TAG anterior cancelado
|
||||||
|
$oldTagLog = VehicleTagLog::where('vehicle_id', $record->vehicle_id)
|
||||||
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')
|
->where('action_type', 'sustitucion')
|
||||||
->whereNotNull('cancellation_at')
|
->whereNotNull('cancellation_at')
|
||||||
->exists();
|
->latest()
|
||||||
|
->first();
|
||||||
|
|
||||||
if(!$hasSubstitution){
|
// Primera vez: inscripción vía vehicleInscription (action_type puede ser
|
||||||
return ApiResponse::BAD_REQUEST->response([
|
// 'sustitucion_primera_vez' o 'sustitucion' cuando el vehículo ya existe en REPUVE Nacional)
|
||||||
'message' => 'El tag no tiene sustitución registrada.',
|
$primeraVezLog = !$oldTagLog
|
||||||
'tag' => $oldTag->folio,
|
? VehicleTagLog::where('vehicle_id', $record->vehicle_id)
|
||||||
]);
|
->whereIn('action_type', ['sustitucion_primera_vez', 'sustitucion'])
|
||||||
|
->whereNull('cancellation_at')
|
||||||
|
->with('performedBy')
|
||||||
|
->latest()
|
||||||
|
->first()
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if ($primeraVezLog) {
|
||||||
|
$newTag = $record->vehicle->tag;
|
||||||
|
|
||||||
|
if (!$newTag) {
|
||||||
|
return ApiResponse::NOT_FOUND->response([
|
||||||
|
'message' => 'No se encontró el TAG asignado al vehículo.',
|
||||||
|
'record' => $recordId,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$substitutionData = $this->substitutionDataFirstTime($newTag, $primeraVezLog, $record->vehicle);
|
||||||
|
$isFirstTime = true;
|
||||||
|
$pdfFilename = 'constancia_primera_vez_' . $newTag->folio . '.pdf';
|
||||||
|
} else {
|
||||||
|
// Sustitución regular: TAG anterior cancelado
|
||||||
|
|
||||||
|
if (!$oldTagLog) {
|
||||||
|
$debugLogs = VehicleTagLog::where('vehicle_id', $record->vehicle_id)->get(['id', 'action_type', 'cancellation_at', 'vehicle_id', 'tag_id']);
|
||||||
|
return response()->json([
|
||||||
|
'debug_record_id' => $recordId,
|
||||||
|
'debug_vehicle_id' => $record->vehicle_id,
|
||||||
|
'debug_logs' => $debugLogs,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$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);
|
||||||
|
$isFirstTime = false;
|
||||||
|
$pdfFilename = 'constancia_sustituida_' . $oldTag->folio . '.pdf';
|
||||||
}
|
}
|
||||||
|
|
||||||
$substitutionData = $this->substitutionData($oldTag);
|
|
||||||
|
|
||||||
$pdf = Pdf::loadView('pdfs.tag_sustitution', [
|
$pdf = Pdf::loadView('pdfs.tag_sustitution', [
|
||||||
'substitution' => $substitutionData,
|
'substitution' => $substitutionData,
|
||||||
|
'is_first_time' => $isFirstTime,
|
||||||
])
|
])
|
||||||
->setPaper('a4', 'portrait')
|
->setPaper('a4', 'portrait')
|
||||||
->setOptions([
|
->setOptions([
|
||||||
@ -439,7 +470,7 @@ public function pdfSubstitutedTag($recordId)
|
|||||||
'isRemoteEnabled' => true,
|
'isRemoteEnabled' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $pdf->stream('constancia_sustituida_' . $oldTag->folio . '.pdf');
|
return $pdf->stream($pdfFilename);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return ApiResponse::INTERNAL_ERROR->response([
|
return ApiResponse::INTERNAL_ERROR->response([
|
||||||
'message' => 'Error al generar el PDF del tag sustituido.',
|
'message' => 'Error al generar el PDF del tag sustituido.',
|
||||||
@ -600,7 +631,7 @@ private function substitutionData(Tag $tag)
|
|||||||
// datos del motivo y operador
|
// datos del motivo y operador
|
||||||
$data['fecha'] = $oldTagLog->cancellation_at->format('d/m/Y');
|
$data['fecha'] = $oldTagLog->cancellation_at->format('d/m/Y');
|
||||||
$data['motivo'] = $oldTagLog->cancellationReason->name ?? 'No especificado';
|
$data['motivo'] = $oldTagLog->cancellationReason->name ?? 'No especificado';
|
||||||
$data['operador'] = $oldTagLog->cancelledBy->name ?? 'Sistema';
|
$data['operador'] = $oldTagLog->cancelledBy?->full_name ?? 'Sistema';
|
||||||
|
|
||||||
// módulo del usuario
|
// módulo del usuario
|
||||||
if ($oldTagLog->cancelledBy) {
|
if ($oldTagLog->cancelledBy) {
|
||||||
@ -621,6 +652,28 @@ private function substitutionData(Tag $tag)
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function substitutionDataFirstTime(Tag $newTag, $log, $vehicle)
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'fecha' => $log->created_at->format('d/m/Y'),
|
||||||
|
'folio' => $newTag->folio ?? '',
|
||||||
|
'folio_sustituto' => 'N/A',
|
||||||
|
'id_chip' => 'N/A',
|
||||||
|
'placa' => $vehicle->placa ?? '',
|
||||||
|
'niv' => $vehicle->niv ?? '',
|
||||||
|
'motivo' => 'Sustitución primera vez',
|
||||||
|
'operador' => $log->performedBy?->full_name ?? 'N/A',
|
||||||
|
'modulo' => '',
|
||||||
|
'ubicacion' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($log->performedBy) {
|
||||||
|
$this->loadUserModule($log->performedBy, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cargar módulo del usuario
|
* Cargar módulo del usuario
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
<title>Constancia Sustituida - REPUVE Tabasco</title>
|
<title>Constancia Sustituida - REPUVE Tabasco</title>
|
||||||
<style>
|
<style>
|
||||||
@page {
|
@page {
|
||||||
@ -139,11 +140,11 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr class="data-row">
|
<tr class="data-row">
|
||||||
<td class="data-label">MOTIVO:</td>
|
<td class="data-label">MOTIVO:</td>
|
||||||
<td class="data-value">{{ strtoupper($substitution['motivo'] ?? '') }}</td>
|
<td class="data-value">{{ mb_strtoupper($substitution['motivo'] ?? '', 'UTF-8') }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="data-row">
|
<tr class="data-row">
|
||||||
<td class="data-label">OPERADOR:</td>
|
<td class="data-label">OPERADOR:</td>
|
||||||
<td class="data-value">{{ strtoupper($substitution['operador'] ?? '') }}</td>
|
<td class="data-value">{{ mb_strtoupper($substitution['operador'] ?? '', 'UTF-8') }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="data-row">
|
<tr class="data-row">
|
||||||
<td class="data-label">MÓDULO:</td>
|
<td class="data-label">MÓDULO:</td>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user