ReporteController.java
package com.licensis.notaire.api;
import com.licensis.notaire.service.ReporteService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Positive;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* Controller REST para generación de reportes
* Expone endpoints para generar PDFs desde JasperReports
*/
@RestController
@RequestMapping("/api/v1/reportes")
@Validated
@Tag(name = "Reportes", description = "API para generación de reportes PDF")
public class ReporteController {
private static final Logger log = LoggerFactory.getLogger(ReporteController.class);
private final ReporteService reporteService;
public ReporteController(ReporteService reporteService) {
this.reporteService = reporteService;
}
@FunctionalInterface
private interface ReportGenerator {
byte[] generate() throws Exception;
}
private ResponseEntity<byte[]> buildPdfResponse(String filename, ReportGenerator generator) {
try {
byte[] pdfBytes = generator.generate();
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF_VALUE)
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + filename + "\"")
.body(pdfBytes);
} catch (Exception e) {
log.error("Failed to generate report '{}'", filename, e);
return ResponseEntity.internalServerError().build();
}
}
@GetMapping(value = "/presupuesto/{idPresupuesto}", produces = MediaType.APPLICATION_PDF_VALUE)
@Operation(summary = "Generar reporte de presupuesto",
description = "Genera un PDF con el presupuesto especificado")
public ResponseEntity<byte[]> generarReportePresupuesto(
@Parameter(description = "ID del presupuesto")
@PathVariable @Positive Integer idPresupuesto) {
return buildPdfResponse("presupuesto_" + idPresupuesto + ".pdf",
() -> reporteService.generarReportePresupuesto(idPresupuesto));
}
@GetMapping(value = "/presupuesto-inmuebles/{idPresupuesto}", produces = MediaType.APPLICATION_PDF_VALUE)
@Operation(summary = "Generar reporte de presupuesto con inmuebles",
description = "Genera un PDF con el presupuesto e información de inmuebles")
public ResponseEntity<byte[]> generarReportePresupuestoInmuebles(
@Parameter(description = "ID del presupuesto")
@PathVariable @Positive Integer idPresupuesto) {
return buildPdfResponse("presupuesto_inmuebles_" + idPresupuesto + ".pdf",
() -> reporteService.generarReportePresupuestoInmuebles(idPresupuesto));
}
@GetMapping(value = "/lista-documentos-tramite", produces = MediaType.APPLICATION_PDF_VALUE)
@Operation(summary = "Generar reporte de lista de documentos por trámite",
description = "Genera un PDF con la lista de documentos requeridos para un tipo de trámite")
public ResponseEntity<byte[]> generarReporteListaDocumentosTramite(
@Parameter(description = "Nombre del tipo de trámite")
@RequestParam @NotBlank String nombreTipoTramite) {
return buildPdfResponse("lista_documentos.pdf",
() -> reporteService.generarReporteListaDocumentosTramite(nombreTipoTramite));
}
@GetMapping(value = "/historial-gestion/{idGestion}", produces = MediaType.APPLICATION_PDF_VALUE)
@Operation(summary = "Generar reporte de historial de gestión",
description = "Genera un PDF con el historial de una gestión específica")
public ResponseEntity<byte[]> generarReporteHistorialGestion(
@Parameter(description = "ID de la gestión")
@PathVariable @Positive Integer idGestion) {
return buildPdfResponse("historial_gestion_" + idGestion + ".pdf",
() -> reporteService.generarReporteHistorialGestion(idGestion));
}
@GetMapping(value = "/documentos-por-vencer/{idDocumentoPresentado}", produces = MediaType.APPLICATION_PDF_VALUE)
@Operation(summary = "Generar reporte de documentos por vencer",
description = "Genera un PDF con información de documentos próximos a vencer")
public ResponseEntity<byte[]> generarReporteDocumentosPorVencer(
@Parameter(description = "ID del documento presentado")
@PathVariable @Positive Integer idDocumentoPresentado) {
return buildPdfResponse("documentos_vencer.pdf",
() -> reporteService.generarReporteDocumentosPorVencer(idDocumentoPresentado));
}
@GetMapping(value = "/consultar-deuda-documentos", produces = MediaType.APPLICATION_PDF_VALUE)
@Operation(summary = "Generar reporte de consulta de deuda de documentos",
description = "Genera un PDF con la consulta de deuda de documentos para una gestión")
public ResponseEntity<byte[]> generarReporteConsultarDeudaDocumentos(
@Parameter(description = "Número de gestión")
@RequestParam @Positive Integer numeroGestion) {
return buildPdfResponse("deuda_documentos_" + numeroGestion + ".pdf",
() -> reporteService.generarReporteConsultarDeudaDocumentos(numeroGestion));
}
@GetMapping(value = "/libro-indice", produces = MediaType.APPLICATION_PDF_VALUE)
@Operation(summary = "Generar libro de indice",
description = "Endpoint base para CU24. Requiere plantilla Jasper de libro de indice")
public ResponseEntity<byte[]> generarLibroIndice(
@Parameter(description = "Año del libro de indice")
@RequestParam @Positive Integer anio) {
return buildPdfResponse("libro_indice_" + anio + ".pdf",
() -> reporteService.generarReporteLibroIndice(anio));
}
@GetMapping(value = "/declaracion-jurada-mensual", produces = MediaType.APPLICATION_PDF_VALUE)
@Operation(summary = "Generar declaracion jurada mensual",
description = "Endpoint base para CU25. Requiere plantilla Jasper de DDJJ mensual")
public ResponseEntity<byte[]> generarDeclaracionJuradaMensual(
@Parameter(description = "Año del periodo")
@RequestParam @Positive Integer anio,
@Parameter(description = "Mes del periodo")
@RequestParam @Min(1) @Max(12) Integer mes) {
if (mes < 1 || mes > 12) {
return ResponseEntity.badRequest().build();
}
return buildPdfResponse("ddjj_mensual_" + anio + "_" + mes + ".pdf",
() -> reporteService.generarReporteDeclaracionJuradaMensual(anio, mes));
}
@GetMapping(value = "/declaracion-jurada-rentas", produces = MediaType.APPLICATION_PDF_VALUE)
@Operation(summary = "Generar declaracion jurada de rentas",
description = "Endpoint base para CU50. Requiere plantilla Jasper de DDJJ rentas")
public ResponseEntity<byte[]> generarDeclaracionJuradaRentas(
@Parameter(description = "Año del periodo")
@RequestParam @Positive Integer anio,
@Parameter(description = "Mes del periodo")
@RequestParam @Min(1) @Max(12) Integer mes) {
if (mes < 1 || mes > 12) {
return ResponseEntity.badRequest().build();
}
return buildPdfResponse("ddjj_rentas_" + anio + "_" + mes + ".pdf",
() -> reporteService.generarReporteDeclaracionJuradaRentas(anio, mes));
}
}