From cb16c0b91c4a5b95c1281738e8e2550ebb060475 Mon Sep 17 00:00:00 2001 From: Juan Felipe Zapata Moreno Date: Fri, 5 Dec 2025 16:49:19 -0600 Subject: [PATCH] =?UTF-8?q?A=C3=B1adir=20ruta=20para=20obtener=20constanci?= =?UTF-8?q?as=20generales=20en=20Excel=20y=20mejorar=20formato=20de=20fech?= =?UTF-8?q?as=20en=20constancias=20sustituidas=20y=20canceladas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Repuve/ExcelController.php | 298 +++++++++++++++++- routes/api.php | 5 +- 2 files changed, 298 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/Repuve/ExcelController.php b/app/Http/Controllers/Repuve/ExcelController.php index 98c7808..aca9d54 100644 --- a/app/Http/Controllers/Repuve/ExcelController.php +++ b/app/Http/Controllers/Repuve/ExcelController.php @@ -130,7 +130,7 @@ public function constanciasSustituidas(Request $request) // Fila 3: PERIODO A INFORMAR (empieza en B, fecha completa con año) $sheet->setCellValue('B' . $row, 'PERIODO A INFORMAR:'); $sheet->mergeCells('C' . $row . ':K' . $row); - $sheet->setCellValue('C' . $row, 'del ' . $fechaInicio->format('d') . ' al ' . $fechaFin->format('d') . ' de ' . $fechaInicio->translatedFormat('F') . ' de ' . $fechaInicio->year); + $sheet->setCellValue('C' . $row, $fechaInicio->format('d/m/Y') . ' al ' . $fechaFin->format('d/m/Y')); $sheet->getStyle('B' . $row)->getFont()->setBold(true)->setSize(11); $sheet->getStyle('B' . $row . ':K' . $row)->applyFromArray($borderStyle); $sheet->getStyle('B' . $row . ':K' . $row)->getAlignment()->setWrapText(true); @@ -341,7 +341,7 @@ public function constanciasCanceladas(Request $request) // PERIODO $sheet->setCellValue('B' . $row, 'PERIODO A INFORMAR:'); $sheet->mergeCells('C' . $row . ':K' . $row); - $sheet->setCellValue('C' . $row, 'del ' . $fechaInicio->format('d') . ' al ' . $fechaFin->format('d') . ' de ' . $fechaInicio->translatedFormat('F') . ' de ' . $fechaInicio->year); + $sheet->setCellValue('C' . $row, $fechaInicio->format('d/m/Y') . ' al ' . $fechaFin->format('d/m/Y')); $sheet->getStyle('B' . $row)->getFont()->setBold(true)->setSize(11); $sheet->getStyle('B' . $row . ':K' . $row)->applyFromArray($borderStyle); $sheet->getStyle('B' . $row . ':K' . $row)->getAlignment()->setWrapText(true); @@ -434,6 +434,300 @@ public function constanciasCanceladas(Request $request) return response()->download($filePath, $fileName)->deleteFileAfterSend(true); } + public function excelGeneral(Request $request) + { + $request->validate([ + 'fecha_inicio' => 'required|date', + 'fecha_fin' => 'required|date|after_or_equal:fecha_inicio', + 'module_id' => 'nullable|exists:modules,id', + ]); + + $fechaInicio = Carbon::parse($request->fecha_inicio)->startOfDay(); + $fechaFin = Carbon::parse($request->fecha_fin)->endOfDay(); + $moduleId = $request->module_id; + + // Obtener información del módulo + $module = $moduleId ? Module::find($moduleId) : null; + + // Obtener logs de cancelación en el rango de fechas + $logs = VehicleTagLog::with([ + 'vehicle.records.module', + 'tag', + 'cancellationReason' + ]) + ->whereIn('action_type', ['inscripcion', 'sustitucion', 'cancelacion']) + ->when($moduleId, function ($query) use ($moduleId) { + $query->whereHas('vehicle.records', function ($q) use ($moduleId) { + $q->where('module_id', $moduleId); + }); + }) + ->where(function ($query) use ($fechaInicio, $fechaFin) { + $query->where(function ($q) use ($fechaInicio, $fechaFin) { + $q->whereIn('action_type', ['inscripcion', 'sustitucion']) + ->whereBetween('created_at', [$fechaInicio, $fechaFin]); + }) + ->orWhere(function ($q) use ($fechaInicio, $fechaFin) { + $q->where('action_type', 'cancelacion') + ->whereBetween('cancellation_at', [$fechaInicio, $fechaFin]); + }); + })->get(); + + $logsT = TagCancellationLog::with([ + 'tag.module', + 'tag.vehicle', + 'cancellationReason' + ])->when($moduleId, function ($query) use ($moduleId) { + $query->whereHas('tag', function ($q) use ($moduleId) { + $q->where('module_id', $moduleId); + }); + }) + ->whereBetween('cancellation_at', [$fechaInicio, $fechaFin]) + ->get(); + + if ($logs->isEmpty() && $logsT->isEmpty()) { + return ApiResponse::NOT_FOUND->response([ + 'message' => 'No se encontraron constancias canceladas en el periodo especificado', + 'fecha_inicio' => $fechaInicio->format('Y-m-d'), + 'fecha_fin' => $fechaFin->format('Y-m-d'), + 'module_id' => $moduleId, + ]); + } + + $allLogs = collect(); + + foreach ($logs as $log) { + $log->sort_date = $log->action_type == 'cancelacion' ? $log->cancellation_at : $log->created_at; + $allLogs->push($log); + } + + foreach ($logsT as $log) { + $log->sort_date = $log->cancellation_at; + $allLogs->push($log); + } + + $allLogs = $allLogs->sortBy('sort_date'); + + $data = $this->prepareExcelDataGeneral($allLogs); + + $fileName = 'Reporte_General_' . $fechaInicio->format('Ymd') . '_' . $fechaFin->format('Ymd') . '.xlsx'; + $filePath = storage_path('app/temp/' . $fileName); + + if (!file_exists(storage_path('app/temp'))) { + mkdir(storage_path('app/temp'), 0755, true); + } + + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $logoPath = storage_path('app/images/logo-seguridad.png'); + if (file_exists($logoPath)) { + $drawing = new Drawing(); + $drawing->setName('Logo Seguridad'); + $drawing->setPath($logoPath); + $drawing->setHeight(100); + $drawing->setCoordinates('B1'); + $drawing->setWorksheet($sheet); + $sheet->getRowDimension(1)->setRowHeight(45); + } + + // Definir estilo de bordes + $borderStyle = [ + 'borders' => [ + 'allBorders' => [ + 'borderStyle' => PhpSpreadsheetBorder::BORDER_THIN, + 'color' => ['rgb' => '000000'], + ], + ], + ]; + + $row = 5; + + // ENTIDAD + $sheet->setCellValue('B' . $row, 'ENTIDAD:'); + $sheet->mergeCells('C' . $row . ':M' . $row); + $sheet->setCellValue('C' . $row, 'TABASCO'); + $sheet->getStyle('B' . $row)->getFont()->setBold(true)->setSize(11); + $sheet->getStyle('B' . $row . ':M' . $row)->applyFromArray($borderStyle); + $sheet->getStyle('B' . $row . ':M' . $row)->getAlignment()->setWrapText(true); + $row++; + + // MÓDULO + $sheet->setCellValue('B' . $row, 'MÓDULO:'); + $sheet->mergeCells('C' . $row . ':M' . $row); + $sheet->setCellValue('C' . $row, $module?->name ?? 'TODOS LOS MÓDULOS'); + $sheet->getStyle('B' . $row)->getFont()->setBold(true)->setSize(11); + $sheet->getStyle('B' . $row . ':M' . $row)->applyFromArray($borderStyle); + $sheet->getStyle('B' . $row . ':M' . $row)->getAlignment()->setWrapText(true); + $row++; + + // PERIODO + $sheet->setCellValue('B' . $row, 'PERIODO A INFORMAR:'); + $sheet->mergeCells('C' . $row . ':M' . $row); + $sheet->setCellValue('C' . $row, $fechaInicio->format('d/m/Y') . ' al ' . $fechaFin->format('d/m/Y')); + $sheet->getStyle('B' . $row)->getFont()->setBold(true)->setSize(11); + $sheet->getStyle('B' . $row . ':M' . $row)->applyFromArray($borderStyle); + $sheet->getStyle('B' . $row . ':M' . $row)->getAlignment()->setWrapText(true); + $row++; + + $row++; + + // Título + $sheet->mergeCells('B' . $row . ':M' . $row); + $sheet->setCellValue('B' . $row, 'REPORTE GENERAL DE CONSTANCIAS'); + $sheet->getStyle('B' . $row)->getFont()->setBold(true)->setSize(12); + $sheet->getStyle('B' . $row)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER)->setWrapText(true); + $sheet->getStyle('B' . $row . ':M' . $row)->applyFromArray($borderStyle); + $row++; + + $row++; + + // Encabezados (12 columnas: A-L) + $headers = [ + 'No.', + 'MÓDULO', + 'TIPO DE ACCIÓN', + 'NIV DEL VEHÍCULO', + 'NRPV/NCI', + 'MARCA DEL VEHÍCULO', + 'PLACA', + 'AÑO MODELO', + 'FOLIO', + 'ID DE LA CONSTANCIA (CHIP)', + 'FECHA', + 'MOTIVO/RAZÓN', + 'OBSERVACIONES', + ]; + + $col = 'A'; + foreach ($headers as $header) { + $sheet->setCellValue($col . $row, $header); + $col++; + } + + $sheet->getStyle('A' . $row . ':M' . $row)->applyFromArray([ + 'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF'], 'size' => 10], + 'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => '8B0000']], + 'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER, 'wrapText' => true], + 'borders' => [ + 'allBorders' => [ + 'borderStyle' => PhpSpreadsheetBorder::BORDER_THIN, + 'color' => ['rgb' => '000000'], + ], + ], + ]); + $row++; + + // Agregar datos + foreach ($data as $rowData) { + $col = 'A'; + foreach ($rowData as $value) { + $sheet->setCellValue($col . $row, $value); + $col++; + } + $sheet->getStyle('A' . $row . ':M' . $row)->applyFromArray([ + 'font' => ['size' => 10], + 'alignment' => ['wrapText' => true], + 'borders' => [ + 'allBorders' => [ + 'borderStyle' => PhpSpreadsheetBorder::BORDER_THIN, + 'color' => ['rgb' => '000000'], + ], + ], + ]); + $row++; + } + + // Ajustar anchos de columnas + $sheet->getColumnDimension('A')->setWidth(6); // No. + $sheet->getColumnDimension('B')->setWidth(25); // MÓDULO + $sheet->getColumnDimension('C')->setWidth(18); // TIPO DE ACCIÓN + $sheet->getColumnDimension('D')->setWidth(25); // NIV + $sheet->getColumnDimension('E')->setWidth(15); // NRPV/NCI + $sheet->getColumnDimension('F')->setWidth(20); // MARCA + $sheet->getColumnDimension('G')->setWidth(12); // PLACA + $sheet->getColumnDimension('H')->setWidth(12); // AÑO MODELO + $sheet->getColumnDimension('I')->setWidth(25); // FOLIO + $sheet->getColumnDimension('J')->setWidth(30); // CHIP + $sheet->getColumnDimension('K')->setWidth(20); // FECHA + $sheet->getColumnDimension('L')->setWidth(35); // MOTIVO/RAZÓN + $sheet->getColumnDimension('M')->setWidth(50); // OBSERVACIONES + + // Guardar archivo + $writer = new Xlsx($spreadsheet); + $writer->save($filePath); + + // Descargar archivo y eliminarlo después + return response()->download($filePath, $fileName)->deleteFileAfterSend(true); + } + + private function prepareExcelDataGeneral($logs) + { + $data = []; + $no = 1; + + foreach($logs as $log){ + $isVehicleTagLog = isset($log->action_type); + + if($isVehicleTagLog){ + $vehicle = $log->vehicle; + $tag = $log->tag; + $actionType = strtoupper($log->action_type); + + $moduleName = $vehicle->records->first()?->module?->name ?? 'SIN MODULO ASIGNADO'; + + $fecha = $log->action_type == 'cancelacion' + ? $log->cancellation_at?->format('d/m/Y') + : $log->created_at->format('d/m/Y'); + + $motivo = match($log->action_type){ + 'inscripcion' => 'INSCRIPCIÓN', + 'sustitucion' => 'SUSTITUCIÓN DE CONSTANCIA', + 'cancelacion' => $log->cancellationReason?->name ?? 'N/A', + default => 'N/A', + }; + + $data[] = [ + $no, + $moduleName, + $actionType, + $vehicle->niv ?? 'N/A', + $vehicle->nrpv ?? 'N/A', + strtoupper($vehicle->marca ?? 'N/A'), + strtoupper($vehicle->placa ?? 'N/A'), + $vehicle->modelo ?? 'N/A', + $tag->folio ?? 'N/A', + $tag->tag_number ?? 'N/A', + $fecha, + $motivo, + $log->cancellation_observations ?? 'N/A', + ]; + } else { + + $vehicle = $log->tag->vehicle; + $tag = $log->tag; + $moduleName = $tag->module?->name ?? 'SIN MODULO ASIGNADO'; + + $data[] = [ + $no, + $moduleName, + 'CANCELACION', + $vehicle->niv ?? 'N/A', + $vehicle->nrpv ?? 'N/A', + strtoupper($vehicle->marca ?? 'N/A'), + strtoupper($vehicle->placa ?? 'N/A'), + $vehicle->modelo ?? 'N/A', + $tag->folio ?? 'N/A', + $tag->tag_number ?? 'N/A', + $log->cancellation_at ? $log->cancellation_at->format('d/m/Y') : 'N/A', + $log->cancellationReason?->name ?? 'CANCELACIÓN', + $log->cancellation_observations ?? 'N/A', + ]; + } + $no++; + } + return $data; + } + private function prepareExcelData($logs) { $data = []; diff --git a/routes/api.php b/routes/api.php index e24db63..06bd098 100644 --- a/routes/api.php +++ b/routes/api.php @@ -46,7 +46,7 @@ Route::get('RecordErrors', [RecordController::class, 'errors']); //Rutas de Actualización - Route::get('consulta', [UpdateController::class, 'vehicleData']); + Route::post('sustitucion', [UpdateController::class, 'tagSubstitution']); Route::post('actualizar', [UpdateController::class, 'vehicleUpdate']); Route::post('actualizar-expediente/{id}', [UpdateController::class, 'updateData']); Route::post('/repuve/resend/{id}', [UpdateController::class, 'resendToRepuve']); @@ -57,6 +57,7 @@ Route::post('tags/cancelar', [CancellationController::class, 'cancelarTagNoAsignado']); Route::get('excel/constancias-sustituidas', [ExcelController::class, 'constanciasSustituidas']); Route::get('excel/constancias-canceladas', [ExcelController::class, 'constanciasCanceladas']); + Route::get('excel/constancias-general', [ExcelController::class, 'excelGeneral']); //Rutas de Modulos Route::patch('module/{id}/toggle-status', [ModuleController::class, 'toggleStatus']); @@ -87,5 +88,3 @@ /** Rutas públicas */ // Tus rutas públicas - -