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;
|
||||
|
||||
// Consulta de Logs de actualizaciones
|
||||
// Consulta de Logs de actualizaciones (último por vehículo)
|
||||
$logs = VehicleTagLog::with(['vehicle', 'tag', 'performedBy.module'])
|
||||
->where('action_type', 'actualizacion')
|
||||
->when($moduleId, function ($query) use ($moduleId) {
|
||||
@ -68,8 +68,11 @@ public function vehicleActualizaciones(Request $request)
|
||||
});
|
||||
})
|
||||
->whereBetween('created_at', [$fechaInicio, $fechaFin])
|
||||
->orderBy('created_at', 'asc')
|
||||
->get();
|
||||
->orderBy('created_at', 'desc')
|
||||
->get()
|
||||
->unique('vehicle_id')
|
||||
->sortBy('created_at')
|
||||
->values();
|
||||
|
||||
if ($logs->isEmpty()) {
|
||||
return response()->json(['message' => 'No se encontraron registros de actualizaciones.'], 404);
|
||||
@ -83,7 +86,7 @@ public function vehicleActualizaciones(Request $request)
|
||||
'placa' => $log->vehicle->placa ?? '',
|
||||
'modelo' => $log->vehicle->modelo ?? '',
|
||||
'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'),
|
||||
];
|
||||
});
|
||||
@ -316,15 +319,26 @@ public function constanciasSustituidas(Request $request)
|
||||
|
||||
// Consulta de Logs
|
||||
$logs = VehicleTagLog::with(['vehicle', 'tag', 'cancellationReason'])
|
||||
->where('action_type', 'sustitucion')
|
||||
->where(function ($query) use ($fechaInicio, $fechaFin) {
|
||||
// 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) {
|
||||
$query->whereHas('performedBy', function ($q) use ($moduleId) {
|
||||
$q->where('module_id', $moduleId);
|
||||
});
|
||||
})
|
||||
->whereBetween('cancellation_at', [$fechaInicio, $fechaFin])
|
||||
->orderBy('cancellation_at', 'asc')
|
||||
->orderByRaw('COALESCE(cancellation_at, created_at) ASC')
|
||||
->get();
|
||||
|
||||
if ($logs->isEmpty()) {
|
||||
@ -333,9 +347,26 @@ public function constanciasSustituidas(Request $request)
|
||||
|
||||
// PREPARACIÓN DE DATOS
|
||||
$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')
|
||||
->where('vehicle_id', $log->vehicle_id)
|
||||
->where('action_type', 'sustitucion')
|
||||
->whereIn('action_type', ['sustitucion_primera_vez', 'sustitucion'])
|
||||
->whereNull('cancellation_at')
|
||||
->where('id', '!=', $log->id)
|
||||
->where('created_at', '>=', $log->created_at)
|
||||
@ -350,7 +381,7 @@ public function constanciasSustituidas(Request $request)
|
||||
'modelo' => $log->vehicle->modelo ?? '',
|
||||
'folio_ant' => $log->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'),
|
||||
'observaciones' => $log->cancellationReason?->name ?? $log->cancellation_observations ?? '',
|
||||
];
|
||||
@ -632,7 +663,7 @@ public function constanciasCanceladas(Request $request)
|
||||
$data = $allLogs->map(function ($log) {
|
||||
return [
|
||||
'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') : '',
|
||||
'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->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->setCellValue("L{$h1}", "MOTIVO DE\nCANCELACIÓN");
|
||||
$sheet->setCellValue("L{$h1}", "OBSERVACIONES \n(MOTIVO DEL DAÑO, ERRORES, ETC)");
|
||||
// Aplicar estilo beige
|
||||
$sheet->getStyle("A{$h1}:N{$h2}")->applyFromArray($styleTableHeader);
|
||||
$sheet->getRowDimension($h1)->setRowHeight(20);
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
use App\Models\Record;
|
||||
use App\Models\Tag;
|
||||
use App\Models\VehicleTagLog;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Notsoweb\ApiResponse\Enums\ApiResponse;
|
||||
@ -387,25 +388,51 @@ public function pdfCancelledTag(Tag $tag)
|
||||
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')
|
||||
$record = Record::with(['vehicle.tag'])->findOrFail($recordId);
|
||||
|
||||
// Sustitución real: existe un TAG anterior cancelado
|
||||
$oldTagLog = VehicleTagLog::where('vehicle_id', $record->vehicle_id)
|
||||
->where('action_type', 'sustitucion')
|
||||
->whereNotNull('cancellation_at')
|
||||
->latest();
|
||||
}
|
||||
])->findOrFail($recordId);
|
||||
->latest()
|
||||
->first();
|
||||
|
||||
$oldTagLog = $record->vehicle->vehicleTagLogs->first();
|
||||
// Primera vez: inscripción vía vehicleInscription (action_type puede ser
|
||||
// 'sustitucion_primera_vez' o 'sustitucion' cuando el vehículo ya existe en REPUVE Nacional)
|
||||
$primeraVezLog = !$oldTagLog
|
||||
? VehicleTagLog::where('vehicle_id', $record->vehicle_id)
|
||||
->whereIn('action_type', ['sustitucion_primera_vez', 'sustitucion'])
|
||||
->whereNull('cancellation_at')
|
||||
->with('performedBy')
|
||||
->latest()
|
||||
->first()
|
||||
: null;
|
||||
|
||||
if (!$oldTagLog) {
|
||||
return ApiResponse::BAD_REQUEST->response([
|
||||
'message' => 'No se encontró una sustitución registrada para este expediente.',
|
||||
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,
|
||||
]);
|
||||
}
|
||||
|
||||
// Obtener datos de sustitución
|
||||
$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')
|
||||
@ -428,9 +455,13 @@ public function pdfSubstitutedTag($recordId)
|
||||
}
|
||||
|
||||
$substitutionData = $this->substitutionData($oldTag);
|
||||
$isFirstTime = false;
|
||||
$pdfFilename = 'constancia_sustituida_' . $oldTag->folio . '.pdf';
|
||||
}
|
||||
|
||||
$pdf = Pdf::loadView('pdfs.tag_sustitution', [
|
||||
'substitution' => $substitutionData,
|
||||
'is_first_time' => $isFirstTime,
|
||||
])
|
||||
->setPaper('a4', 'portrait')
|
||||
->setOptions([
|
||||
@ -439,7 +470,7 @@ public function pdfSubstitutedTag($recordId)
|
||||
'isRemoteEnabled' => true,
|
||||
]);
|
||||
|
||||
return $pdf->stream('constancia_sustituida_' . $oldTag->folio . '.pdf');
|
||||
return $pdf->stream($pdfFilename);
|
||||
} catch (\Exception $e) {
|
||||
return ApiResponse::INTERNAL_ERROR->response([
|
||||
'message' => 'Error al generar el PDF del tag sustituido.',
|
||||
@ -600,7 +631,7 @@ private function substitutionData(Tag $tag)
|
||||
// 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';
|
||||
$data['operador'] = $oldTagLog->cancelledBy?->full_name ?? 'Sistema';
|
||||
|
||||
// módulo del usuario
|
||||
if ($oldTagLog->cancelledBy) {
|
||||
@ -621,6 +652,28 @@ private function substitutionData(Tag $tag)
|
||||
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
|
||||
*/
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Constancia Sustituida - REPUVE Tabasco</title>
|
||||
<style>
|
||||
@page {
|
||||
@ -139,11 +140,11 @@
|
||||
</tr>
|
||||
<tr class="data-row">
|
||||
<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 class="data-row">
|
||||
<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 class="data-row">
|
||||
<td class="data-label">MÓDULO:</td>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user