mramirezg 1 week ago
parent
commit
65759cbab0
7 changed files with 192 additions and 61 deletions
  1. BIN
      src/main/bundles/prod.bundle
  2. +11
    -1
      src/main/java/mx/gob/jumapacelaya/models/encuestas/MantenimientosSinEncuesta.java
  3. +85
    -34
      src/main/java/mx/gob/jumapacelaya/services/DatabaseService.java
  4. +22
    -16
      src/main/java/mx/gob/jumapacelaya/ui/DetallesMantView.java
  5. +1
    -1
      src/main/java/mx/gob/jumapacelaya/ui/MainLayout.java
  6. +28
    -2
      src/main/java/mx/gob/jumapacelaya/ui/PlanAnualView.java
  7. +45
    -7
      src/main/java/mx/gob/jumapacelaya/ui/ResultEncuestasView.java

BIN
src/main/bundles/prod.bundle View File


+ 11
- 1
src/main/java/mx/gob/jumapacelaya/models/encuestas/MantenimientosSinEncuesta.java View File

@ -12,10 +12,11 @@ public class MantenimientosSinEncuesta {
private String nomUsuario;
private String email;
private String encuesta;
private boolean tieneToken;
public MantenimientosSinEncuesta(int mantenimientoId, int planId, LocalDate fecha,
String periodo, String tipomant, String departamento,
String nomUsuario, String email, String encuesta) {
String nomUsuario, String email, String encuesta, boolean tieneToken) {
this.mantenimientoId = mantenimientoId;
this.planId = planId;
@ -26,6 +27,7 @@ public class MantenimientosSinEncuesta {
this.nomUsuario = nomUsuario;
this.email = email;
this.encuesta = encuesta;
this.tieneToken = tieneToken;
}
public int getMantenimientoId() {
@ -99,4 +101,12 @@ public class MantenimientosSinEncuesta {
public void setEncuesta(String encuesta) {
this.encuesta = encuesta;
}
public boolean isTieneToken() {
return tieneToken;
}
public void setTieneToken(boolean tieneToken) {
this.tieneToken = tieneToken;
}
}

+ 85
- 34
src/main/java/mx/gob/jumapacelaya/services/DatabaseService.java View File

@ -15,7 +15,10 @@ import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@ -319,7 +322,7 @@ public class DatabaseService {
public List<MantenimientosSinEncuesta> getEncuestPendientes(String mes, int anio) {
List<MantenimientosSinEncuesta> lista = new ArrayList<>();
String query = """
SELECT
SELECT DISTINCT
m.MANTENIMIENTOID MANTID,
m.PLANANUALID PLANID,
m.FECHA,
@ -328,7 +331,8 @@ public class DatabaseService {
d.DESCRIPCION DEPTO,
u.NOMBRE NOMUSUARIO,
u.EMAIL,
m.ENCUESTA
m.ENCUESTA,
CASE WHEN e.TOKEN IS NOT NULL THEN 1 ELSE 0 END AS TIENE_TOKEN
FROM MANTENIMIENTOS m
JOIN TIPOMANT t
ON t.TIPOMANTID = m.TIPOMANTID
@ -340,8 +344,10 @@ public class DatabaseService {
ON p.PLANANUALID = m.PLANANUALID
JOIN MESES ms
ON ms.MESID = p.MESID
WHERE m.ENCUESTA = 'N'
AND m.TIPOMANTID = 1
LEFT JOIN ENCUESTATOKENS e
ON e.MANTENIMIENTOID = m.MANTENIMIENTOID
WHERE
m.TIPOMANTID = 1
AND m.PLANANUALID IS NOT NULL
AND UPPER(ms.NOMBRE) = UPPER(?)
AND EXTRACT(YEAR FROM m.FECHA) = ?
@ -365,7 +371,8 @@ public class DatabaseService {
rs.getString("DEPTO"),
rs.getString("NOMUSUARIO"),
rs.getString("EMAIL"),
rs.getString("ENCUESTA")
rs.getString("ENCUESTA"),
rs.getBoolean("TIENE_TOKEN")
));
}
} catch (SQLException e) {
@ -1037,21 +1044,39 @@ public class DatabaseService {
public String crearTokenEncuesta(int mantenimientoid) {
String token = UUID.randomUUID().toString();
Timestamp expira = new Timestamp(System.currentTimeMillis() + (24 * 60 * 60 * 1000));
ZoneId zonaMX = ZoneId.of("America/Mexico_City");
ZonedDateTime ahora = ZonedDateTime.now(zonaMX);
ZonedDateTime fechaExp = ahora;
int diasPorSumar = 3;
while (diasPorSumar > 0) {
fechaExp = fechaExp.plusDays(1);
if (!(fechaExp.getDayOfWeek() == DayOfWeek.SATURDAY ||
fechaExp.getDayOfWeek() == DayOfWeek.SUNDAY)) {
diasPorSumar--;
}
}
String query = "INSERT INTO ENCUESTATOKENS (TOKEN, MANTENIMIENTOID, FECHAEXPIRACION) VALUES (?, ?, ?)";
Timestamp expira = Timestamp.from(fechaExp.toInstant());
LocalDate fechaEnvio = ahora.toLocalDate();
String query = "INSERT INTO ENCUESTATOKENS (TOKEN, MANTENIMIENTOID, FECHAENVIO, FECHAEXPIRACION) VALUES (?, ?, ?, ?)";
try (Connection conn = getMysqlConnection();
PreparedStatement stmt = conn.prepareStatement(query)) {
stmt.setString(1, token);
stmt.setInt(2, mantenimientoid);
stmt.setTimestamp(3, expira);
stmt.setDate(3, java.sql.Date.valueOf(fechaEnvio));
stmt.setTimestamp(4, expira);
stmt.executeUpdate();
return token;
} catch (SQLException e) {
logger.error("Error al crear el token de encuesta: ", e);
throw new RuntimeException("Ya existe una encuesta para este mantenimiento o error en DB", e);
}
return token;
}
public Integer validarTokenYObtenerId(String token) {
@ -1071,21 +1096,34 @@ public class DatabaseService {
return null;
}
public List<ConteoEncuestas> getTotalEncuestas() {
public List<ConteoEncuestas> getTotalEncuestas(Integer mesId, Integer anio) {
List<ConteoEncuestas> totalEncuestas = new ArrayList<>();
String query = "SELECT * FROM VW_CONTEO_ENCUESTAS";
String query = "{call sp_reporte_encuestas(?, ?)}";
try (Connection conn = getMysqlConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query)) {
CallableStatement cstmt = conn.prepareCall(query)) {
while (rs.next()) {
ConteoEncuestas conteo = new ConteoEncuestas(
rs.getInt("TOTAL_ENVIADAS"),
rs.getInt("TOTAL_RESPONDIDAS"),
rs.getDouble("PORCENTAJE_TOTAL")
);
totalEncuestas.add(conteo);
if (mesId != null) {
cstmt.setInt(1, mesId);
} else {
cstmt.setNull(1, Types.INTEGER);
}
if (anio != null) {
cstmt.setInt(2, anio);
} else {
cstmt.setNull(2, Types.INTEGER);
}
try (ResultSet rs = cstmt.executeQuery()) {
while (rs.next()) {
ConteoEncuestas conteo = new ConteoEncuestas(
rs.getInt("TOTAL_ENVIADAS"),
rs.getInt("TOTAL_RESPONDIDAS"),
rs.getDouble("PORCENTAJE_TOTAL")
);
totalEncuestas.add(conteo);
}
}
} catch (SQLException e) {
logger.error("Error al obtener el total de encuestas: ", e);
@ -1093,24 +1131,37 @@ public class DatabaseService {
return totalEncuestas;
}
public List<ConteoRespuestas> getTotalRespuestas() {
public List<ConteoRespuestas> getTotalRespuestas(Integer mesId, Integer anio) {
List<ConteoRespuestas> totalRespuestas = new ArrayList<>();
String query = "SELECT * FROM VW_CONTEO_RESPUESTAS";
String query = "{call sp_reporte_respuestas(?, ?)}";
try (Connection conn = getMysqlConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query)) {
CallableStatement cstmt = conn.prepareCall(query)) {
while (rs.next()) {
ConteoRespuestas conteo = new ConteoRespuestas(
rs.getInt("PREGUNTAID"),
rs.getString("PREGUNTA"),
rs.getInt("TOTALREGISTROS"),
rs.getInt("TOTALSI"),
rs.getInt("TOTALNO"),
rs.getDouble("PORCENTAJE")
);
totalRespuestas.add(conteo);
if (mesId != null) {
cstmt.setInt(1, mesId);
} else {
cstmt.setNull(1, Types.INTEGER);
}
if (anio != null) {
cstmt.setInt(2, anio);
} else {
cstmt.setNull(2, Types.INTEGER);
}
try (ResultSet rs = cstmt.executeQuery()) {
while (rs.next()) {
ConteoRespuestas conteo = new ConteoRespuestas(
rs.getInt("PREGUNTAID"),
rs.getString("PREGUNTA"),
rs.getInt("TOTALREGISTROS"),
rs.getInt("TOTALSI"),
rs.getInt("TOTALNO"),
rs.getDouble("PORCENTAJE")
);
totalRespuestas.add(conteo);
}
}
} catch (SQLException e) {
logger.error("Error al obtener el total de respuestas: ", e);


+ 22
- 16
src/main/java/mx/gob/jumapacelaya/ui/DetallesMantView.java View File

@ -63,6 +63,7 @@ public class DetallesMantView extends VerticalLayout implements BeforeEnterObser
private String baseUrl;
private final H3 id;
private final TextField mantId;
private final EmailService emailService;
private HorizontalLayout fechasLayout;
private TextField txtId;
@ -114,10 +115,12 @@ public class DetallesMantView extends VerticalLayout implements BeforeEnterObser
id = new H3();
mantId = new TextField();
HorizontalLayout headerLayout = new HorizontalLayout();
headerLayout.setWidthFull();
headerLayout.add(id);
headerLayout.setAlignItems(Alignment.BASELINE);
headerLayout.add(id, mantId);
cbTipo = new ComboBox<>("Tipo:");
cbTipo.setItems(service.getTiposDeMantenimientos());
@ -536,25 +539,25 @@ public class DetallesMantView extends VerticalLayout implements BeforeEnterObser
private void enviarCorreo() {
Usuario usuarioDestino = cbUsuario.getValue();
if (usuarioDestino != null && usuarioDestino.getEmail() != null) {
String destinatario = usuarioDestino.getEmail();
String asunto = "Encuesta de satisfacción -Mantenimiento #" + mantenimientoIdActual;
try {
String token = service.crearTokenEncuesta(mantenimientoIdActual);
String token = service.crearTokenEncuesta(mantenimientoIdActual);
String linkEncuesta = baseUrl + "/encuesta?token=" + token;
String destinatario = usuarioDestino.getEmail();
String asunto = "Encuesta de satisfacción - Mantenimiento #" + mantenimientoIdActual;
String linkEncuesta = baseUrl + "/encuesta?token=" + token;
String cuerpo = "<html><body><a href='" + linkEncuesta + "'><img src='cid:image_id'/></a></body></html>";
String imagePath = "META-INF/resources/images/imgCorreo/imgEncuesta.png";
String cuerpo = "<html>" +
"<body>" +
"<a href = "+linkEncuesta+">" +
"<img src='cid:image_id'/>"+
"</a>" +
"</body>" +
"</html>";
emailService.enviarCorreo(destinatario, asunto, cuerpo, imagePath);
String imagePath = "META-INF/resources/images/imgCorreo/imgEncuesta.png";
Notification.show("Encuesta enviada correctamente", 3000, Notification.Position.BOTTOM_END)
.addThemeVariants(NotificationVariant.LUMO_SUCCESS);
emailService.enviarCorreo(destinatario,asunto,cuerpo,imagePath);
Notification.show("Encuesta enviada correctamente para el mantenimiento No. " + mantenimientoIdActual, 3000, Notification.Position.BOTTOM_END)
.addThemeVariants(NotificationVariant.LUMO_SUCCESS);
} catch (Exception e) {
Notification.show("Error: No se pudo enviar. Es probable que ya exista una encuesta generada.",
5000, Notification.Position.MIDDLE)
.addThemeVariants(NotificationVariant.LUMO_ERROR);
}
} else {
Notification.show("Por favor, seleccione un usuario destino", 3000, Notification.Position.MIDDLE);
}
@ -612,6 +615,9 @@ public class DetallesMantView extends VerticalLayout implements BeforeEnterObser
.filter(t -> t.getNombre().equals(detalle.getTipo()))
.findFirst().orElse(null)
);
mantId.setValue(String.valueOf(mantenimientoIdActual));
mantId.setReadOnly(true);
mantId.setWidth("100px");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String fechaProg = detalle.getFechaprog() != null ? detalle.getFechaprog().format(formatter) : "";


+ 1
- 1
src/main/java/mx/gob/jumapacelaya/ui/MainLayout.java View File

@ -93,7 +93,7 @@ public class MainLayout extends AppLayout implements BeforeEnterObserver {
nav.addItem(new SideNavItem("Plan Anual", PlanAnualView.class, VaadinIcon.CALENDAR.create()));
nav.addItem(new SideNavItem("Listado de Actividades", ActDiariaView.class, VaadinIcon.EDIT.create()));
nav.addItem(new SideNavItem("Mantenimiento Correctivo", MantCorrectivoView.class, VaadinIcon.WRENCH.create()));
nav.addItem(new SideNavItem("Resultados de Encuestas", ResultEncuestasView.class, VaadinIcon.CLIPBOARD_TEXT.create()));
nav.addItem(new SideNavItem("Resultados de Encuestas", ResultEncuestasView.class, VaadinIcon.BAR_CHART_H.create()));
nav.addItem(new SideNavItem("Preferencias del Sistema", ConfiguracionView.class, VaadinIcon.COG.create()));
nav.getStyle().set("border-radius", "5px");


+ 28
- 2
src/main/java/mx/gob/jumapacelaya/ui/PlanAnualView.java View File

@ -1095,8 +1095,11 @@ public class PlanAnualView extends VerticalLayout {
grid.addColumn(createStatusRender())
.setHeader("Encuesta");
grid.addColumn(MantenimientosSinEncuesta::getDepartamento)
.setHeader("Departamento");
grid.addColumn(createTokenRender())
.setHeader("Token");
/*grid.addColumn(MantenimientosSinEncuesta::getDepartamento)
.setHeader("Departamento");*/
grid.addColumn(MantenimientosSinEncuesta::getNomUsuario)
.setHeader("Usuario")
@ -1114,6 +1117,11 @@ public class PlanAnualView extends VerticalLayout {
btnEnviar.addThemeVariants(ButtonVariant.LUMO_PRIMARY,
ButtonVariant.LUMO_SUCCESS);
if (item.isTieneToken()) {
btnEnviar.setEnabled(false);
btnEnviar.setText("Enviado");
}
btnEnviar.addClickListener(e -> {
enviarEncuestaDesdeGrid(item);
btnEnviar.setEnabled(false);
@ -1191,4 +1199,22 @@ public class PlanAnualView extends VerticalLayout {
return span;
});
}
private ComponentRenderer<Span, MantenimientosSinEncuesta> createTokenRender() {
return new ComponentRenderer<>(token -> {
Span span = new Span(String.valueOf(token.isTieneToken()));
if (token.isTieneToken()) {
span.setText("S");
String theme2 = String.format("badge %s", "success");
span.getElement().setAttribute("theme", theme2);
} else {
span.setText("N");
String theme1 = String.format("badge %s", "error");
span.getElement().setAttribute("theme", theme1);
}
return span;
});
}
}

+ 45
- 7
src/main/java/mx/gob/jumapacelaya/ui/ResultEncuestasView.java View File

@ -2,6 +2,7 @@ package mx.gob.jumapacelaya.ui;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.dashboard.Dashboard;
import com.vaadin.flow.component.dashboard.DashboardSection;
import com.vaadin.flow.component.dashboard.DashboardWidget;
@ -23,7 +24,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vaadin.lineawesome.LineAwesomeIcon;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@PermitAll
@PageTitle("Resultados de Encuestas")
@ -41,6 +44,7 @@ public class ResultEncuestasView extends VerticalLayout {
private DashboardWidget pregunta4;
private DashboardWidget pregunta5;
private DashboardWidget pregunta6;
private ComboBox<Integer> cmbMes;
public ResultEncuestasView(DatabaseService databaseService) {
this.databaseService = databaseService;
@ -52,7 +56,32 @@ public class ResultEncuestasView extends VerticalLayout {
Button btnExport = new Button("Exportar a PDF", LineAwesomeIcon.FILE_PDF.create());
btnExport.addThemeVariants(ButtonVariant.LUMO_SMALL);
HorizontalLayout toolbar = new HorizontalLayout(btnExport);
Map<Integer, String> meses = new HashMap<>();
meses.put(1, "Enero");
meses.put(2, "Febrero");
meses.put(3, "Marzo");
meses.put(4, "Abril");
meses.put(5, "Mayo");
meses.put(6, "Junio");
meses.put(7, "Julio");
meses.put(8, "Agosto");
meses.put(9, "Septiembre");
meses.put(10, "Octubre");
meses.put(11, "Noviembre");
meses.put(12, "Diciembre");
cmbMes = new ComboBox<>();
cmbMes.setItems(meses.keySet());
cmbMes.setItemLabelGenerator(meses::get);
cmbMes.setPlaceholder("Filtrar por mes");
cmbMes.setClearButtonVisible(true);
cmbMes.addValueChangeListener(e -> {
Integer mesSeleccionado = e.getValue();
actualizarDashboard(mesSeleccionado, 2026);
});
HorizontalLayout toolbar = new HorizontalLayout(btnExport, cmbMes);
toolbar.setAlignItems(Alignment.BASELINE);
toolbar.setWidthFull();
@ -94,8 +123,7 @@ public class ResultEncuestasView extends VerticalLayout {
preguntasSection.add(pregunta5);
preguntasSection.add(pregunta6);
mostrarTotales();
mostrarPreguntas();
actualizarDashboard(null, null);
add(dashboard);
return dashboard;
}
@ -160,8 +188,13 @@ public class ResultEncuestasView extends VerticalLayout {
return vl;
}
public void mostrarTotales() {
List<ConteoEncuestas> datos = databaseService.getTotalEncuestas();
private void actualizarDashboard(Integer mes, Integer anio) {
mostrarTotales(mes, anio);
mostrarPreguntas(mes, anio);
}
public void mostrarTotales(Integer mes, Integer anio) {
List<ConteoEncuestas> datos = databaseService.getTotalEncuestas(mes, anio);
if (!datos.isEmpty()) {
ConteoEncuestas totales = datos.get(0);
@ -180,15 +213,20 @@ public class ResultEncuestasView extends VerticalLayout {
String.valueOf(totales.getPorcentajeRespondidas()),
LineAwesomeIcon.PERCENT_SOLID, "#BC955B"
));
} else {
totalEncu.setContent(createDiv("0", LineAwesomeIcon.CLIPBOARD_LIST_SOLID, "#BC955B"));
}
}
public void mostrarPreguntas() {
List<ConteoRespuestas> lista = databaseService.getTotalRespuestas();
public void mostrarPreguntas(Integer mes, Integer anio) {
List<ConteoRespuestas> lista = databaseService.getTotalRespuestas(mes, anio);
DashboardWidget[] widgets = {pregunta1,pregunta2,pregunta3,pregunta4,pregunta5,pregunta6};
for (DashboardWidget w : widgets) w.setContent(new Span("Sin datos"));
for (int i = 0; i < lista.size() && i < widgets.length; i++) {
ConteoRespuestas data = lista.get(i);
DashboardWidget widget = widgets[i];


Loading…
Cancel
Save