diff --git a/src/main/java/mx/gob/jumapacelaya/models/encuestas/Respuesta.java b/src/main/java/mx/gob/jumapacelaya/models/encuestas/Respuesta.java index 5265cf5..535cb9d 100644 --- a/src/main/java/mx/gob/jumapacelaya/models/encuestas/Respuesta.java +++ b/src/main/java/mx/gob/jumapacelaya/models/encuestas/Respuesta.java @@ -9,15 +9,11 @@ public class Respuesta { private int preguntaId; private Timestamp fechaResp; private Boolean respuesta; - private int emepleadoId; + private int empleadoId; - public Respuesta(int respuestaId, int mantenimientoId, int preguntaId, Timestamp fechaResp, Boolean respuesta, int emepleadoId) { - this.respuestaId = respuestaId; - this.mantenimientoId = mantenimientoId; + public Respuesta(int preguntaId, Boolean respuesta) { this.preguntaId = preguntaId; - this.fechaResp = fechaResp; this.respuesta = respuesta; - this.emepleadoId = emepleadoId; } public int getRespuestaId() { @@ -60,11 +56,11 @@ public class Respuesta { this.respuesta = respuesta; } - public int getEmepleadoId() { - return emepleadoId; + public int getEmpleadoId() { + return empleadoId; } - public void setEmepleadoId(int emepleadoId) { - this.emepleadoId = emepleadoId; + public void setEmpleadoId(int empleadoId) { + this.empleadoId = empleadoId; } } diff --git a/src/main/java/mx/gob/jumapacelaya/services/DatabaseService.java b/src/main/java/mx/gob/jumapacelaya/services/DatabaseService.java index 09574d9..538de10 100644 --- a/src/main/java/mx/gob/jumapacelaya/services/DatabaseService.java +++ b/src/main/java/mx/gob/jumapacelaya/services/DatabaseService.java @@ -1,6 +1,8 @@ package mx.gob.jumapacelaya.services; import mx.gob.jumapacelaya.models.*; +import mx.gob.jumapacelaya.models.encuestas.Pregunta; +import mx.gob.jumapacelaya.models.encuestas.Respuesta; import oracle.jdbc.OracleConnection; import oracle.jdbc.OraclePreparedStatement; import oracle.sql.CLOB; @@ -17,6 +19,7 @@ import java.sql.*; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; +import java.util.UUID; @Service public class DatabaseService { @@ -904,4 +907,137 @@ public class DatabaseService { e.printStackTrace(); } } + + + +/*************************************** ENCUESTAS ******************************************************************************************************/ + public List getPreguntas() { + List preguntas = new ArrayList<>(); + String query = """ + select p.* + from PREGUNTAS p + join ENCUESTAS e on e.ENCUESTAID = p.ENCUESTAID + where e.ENCUESTAID = 1 + order by p.ORDEN ASC + """; + + try (Connection conn = getMysqlConnection(); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(query)) { + + while (rs.next()) { + Pregunta pregunta = new Pregunta( + rs.getInt("preguntaid"), + rs.getInt("encuestaid"), + rs.getString("pregunta"), + rs.getInt("orden") + ); + preguntas.add(pregunta); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return preguntas; + } + + + public void insertRespuestas(int manteniminetoId, List respuestas, int empleadoid, String token) { + + String insertQuery = """ + insert into RESPUESTAS + (MANTENIMIENTOID,PREGUNTAID,FECHARESPUESTA,RESPUESTA,EMPLEADOID) + values + (?,?,?,?,?) + """; + + String updateQuery = """ + update MANTENIMIENTOS + set ENCUESTA = 'S' + where MANTENIMIENTOID = ? + """; + + String markTokenUsedQuery = """ + update ENCUESTATOKENS + set USADO = '1' where TOKEN = ? + """; + + try (Connection conn = getMysqlConnection()) { + + conn.setAutoCommit(false); + + try (PreparedStatement insertStmt = conn.prepareStatement(insertQuery); + PreparedStatement updateStmt = conn.prepareStatement(updateQuery); + PreparedStatement tokenStmt = conn.prepareStatement(markTokenUsedQuery)) { + + Timestamp ahora = new Timestamp(System.currentTimeMillis()); + + // 1. Insertar las respuestas en el Batch + for (Respuesta r : respuestas) { + insertStmt.setInt(1, manteniminetoId); + insertStmt.setInt(2, r.getPreguntaId()); + insertStmt.setTimestamp(3, ahora); + insertStmt.setBoolean(4, r.getRespuesta()); + insertStmt.setInt(5, empleadoid); + insertStmt.addBatch(); + } + + insertStmt.executeBatch(); + + // 2. Marcar mantenimiento como encuestado + updateStmt.setInt(1, manteniminetoId); + updateStmt.executeUpdate(); + + // 3. Invalidar el token para que no se use de nuevo + tokenStmt.setString(1, token); + tokenStmt.executeUpdate(); + + conn.commit(); + + } catch (SQLException e) { + conn.rollback(); + throw e; + } + + } catch (Exception e) { + throw new RuntimeException("Error al guardar encuesta y procesar el token", e); + } + } + + + public String crearTokenEncuesta(int mantenimientoid) { + String token = UUID.randomUUID().toString(); + Timestamp expira = new Timestamp(System.currentTimeMillis() + (24 * 60 * 60 * 1000)); + + String query = "INSERT INTO ENCUESTATOKENS (TOKEN, MANTENIMIENTOID, FECHAEXPIRACION) VALUES (?, ?, ?)"; + + try (Connection conn = getMysqlConnection(); + PreparedStatement stmt = conn.prepareStatement(query)) { + stmt.setString(1, token); + stmt.setInt(2, mantenimientoid); + stmt.setTimestamp(3, expira); + stmt.executeUpdate(); + + } catch (SQLException e) { + e.printStackTrace(); + } + return token; + } + + public Integer validarTokenYObtenerId(String token) { + String query = "SELECT MANTENIMIENTOID FROM ENCUESTATOKENS " + + "WHERE TOKEN = ? AND FECHAEXPIRACION > NOW() AND USADO = FALSE"; + + try (Connection conn = getMysqlConnection(); + PreparedStatement stmt = conn.prepareStatement(query)) { + stmt.setString(1, token); + ResultSet rs = stmt.executeQuery(); + if (rs.next()) { + return rs.getInt("MANTENIMIENTOID"); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + /***************************************************************************************************************************************/ } diff --git a/src/main/java/mx/gob/jumapacelaya/services/EmailService.java b/src/main/java/mx/gob/jumapacelaya/services/EmailService.java index d5c675a..06ad057 100644 --- a/src/main/java/mx/gob/jumapacelaya/services/EmailService.java +++ b/src/main/java/mx/gob/jumapacelaya/services/EmailService.java @@ -36,7 +36,6 @@ public class EmailService { helper.addInline("image_id", imgResource); - mailSender.send(mensaje); System.out.println("Correo enviado con imagen exitosamente"); diff --git a/src/main/java/mx/gob/jumapacelaya/services/encuestas/EncuestasDBService.java b/src/main/java/mx/gob/jumapacelaya/services/encuestas/EncuestasDBService.java deleted file mode 100644 index bba634b..0000000 --- a/src/main/java/mx/gob/jumapacelaya/services/encuestas/EncuestasDBService.java +++ /dev/null @@ -1,84 +0,0 @@ -package mx.gob.jumapacelaya.services.encuestas; - -import mx.gob.jumapacelaya.models.encuestas.Pregunta; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -import java.sql.*; -import java.util.ArrayList; -import java.util.List; - -@Service -public class EncuestasDBService { - - @Value("${db.url}") - private String dbUrl; - @Value("${db.user}") - private String dbUser; - @Value("${db.pass}") - private String dbPass; - - private Connection getEncuestasConn() throws SQLException { - return DriverManager.getConnection(dbUrl, dbUser, dbPass); - } - - - public List getPreguntas() { - List preguntas = new ArrayList<>(); - String query = """ - select p.* - from PREGUNTAS p - join ENCUESTAS e on e.ENCUESTAID = p.ENCUESTAID - where e.ENCUESTAID = 1 - order by p.ORDEN ASC - """; - - try (Connection conn = getEncuestasConn(); - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(query)) { - - while (rs.next()) { - Pregunta pregunta = new Pregunta( - rs.getInt("preguntaid"), - rs.getInt("encuestaid"), - rs.getString("pregunta"), - rs.getInt("orden") - ); - preguntas.add(pregunta); - } - } catch (SQLException e) { - e.printStackTrace(); - } - return preguntas; - } - - - public void insertRespuestas(int manteniminetoId, int preguntaId, Timestamp fechaResp, - boolean respuesta, int empleadoid) { - - String query = """ - insert into RESPUESTAS - (MANTENIMIENTOID,PREGUNTAID,FECHARESPUESTA,RESPUESTA,EMPLEADOID) - values - (?,?,?,?,?) - """; - - try (Connection conn = getEncuestasConn(); - PreparedStatement st = conn.prepareStatement(query)) { - - st.setInt(1,manteniminetoId); - st.setInt(2, preguntaId); - if (fechaResp != null) { - st.setTimestamp(3, fechaResp); - } else - st.setNull(3, Types.DATE); - st.setBoolean(4, respuesta); - st.setInt(5, empleadoid); - - st.executeUpdate(); - } catch (SQLException e) { - e.printStackTrace(); - System.err.println("Error al insertar respuesta: " + e.getMessage()); - } - } -} diff --git a/src/main/java/mx/gob/jumapacelaya/ui/DetallesMantView.java b/src/main/java/mx/gob/jumapacelaya/ui/DetallesMantView.java index 62c3989..a06ec7f 100644 --- a/src/main/java/mx/gob/jumapacelaya/ui/DetallesMantView.java +++ b/src/main/java/mx/gob/jumapacelaya/ui/DetallesMantView.java @@ -9,7 +9,7 @@ import java.util.List; import java.util.Map; import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.html.Anchor; +import com.vaadin.flow.component.html.*; import com.vaadin.flow.server.StreamRegistration; import com.vaadin.flow.server.StreamResource; import mx.gob.jumapacelaya.services.EmailService; @@ -24,9 +24,6 @@ import com.vaadin.flow.component.dependency.CssImport; import com.vaadin.flow.component.dialog.Dialog; import com.vaadin.flow.component.grid.GridVariant; import com.vaadin.flow.component.gridpro.GridPro; -import com.vaadin.flow.component.html.H3; -import com.vaadin.flow.component.html.Image; -import com.vaadin.flow.component.html.Span; import com.vaadin.flow.component.icon.Icon; import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.notification.Notification; @@ -88,6 +85,7 @@ public class DetallesMantView extends VerticalLayout implements BeforeEnterObser private Image firmaUsuarioImg; private Image firmaSmtImg; private Image firmaGciaImg; + Notification avisoEncuestaNtf; private VerticalLayout userSignLayout; private VerticalLayout smtSignLayout; @@ -304,7 +302,10 @@ public class DetallesMantView extends VerticalLayout implements BeforeEnterObser }); - btnEnviarEncuesta.addClickListener(e -> enviarCorreo()); + btnEnviarEncuesta.addClickListener(e -> { + avisoEncuestaNtf.close(); + enviarCorreo(); + }); // Se dispara el dialogo de confirmacion @@ -527,7 +528,8 @@ public class DetallesMantView extends VerticalLayout implements BeforeEnterObser String destinatario = usuarioDestino.getEmail(); String asunto = "Encuesta de satisfacción -Mantenimiento #" + mantenimientoIdActual; - String linkEncuesta = baseUrl + "/encuesta?mantenimientoId=" + mantenimientoIdActual; + String token = service.crearTokenEncuesta(mantenimientoIdActual); + String linkEncuesta = baseUrl + "/encuesta?token=" + token; String cuerpo = "" + "" + @@ -554,12 +556,40 @@ public class DetallesMantView extends VerticalLayout implements BeforeEnterObser ? event.getLocation().getQueryParameters().getParameters().get("id").stream().findFirst().orElse(null) : null; + String encParam = event.getLocation().getQueryParameters().getParameters().getOrDefault("enc", List.of()) + .stream().findFirst().orElse("N").toUpperCase(); + if (idParam != null) { try { int planId = Integer.parseInt(idParam); DetalleMantenimientoModel detalle = service.getDetalleMantenimientoPorPlanAnualId(planId); + if (encParam.equalsIgnoreCase("N")) { + Icon icono = new Icon(VaadinIcon.WARNING); + icono.setSize("40px"); + NativeLabel aviso = new NativeLabel("Aviso:"); + aviso.getStyle().set("font-weight", "bold"); + NativeLabel label = new NativeLabel("¡No se ha respondido una encuesta para este mantenimiento!"); + + VerticalLayout textLyt = new VerticalLayout(aviso,label); + textLyt.setPadding(false); + textLyt.setSpacing(false); + HorizontalLayout layout = new HorizontalLayout(icono, textLyt); + layout.setJustifyContentMode(JustifyContentMode.CENTER); + layout.setAlignItems(Alignment.CENTER); + + avisoEncuestaNtf = new Notification(layout); + avisoEncuestaNtf.setPosition(Notification.Position.TOP_CENTER); + avisoEncuestaNtf.addThemeVariants(NotificationVariant.LUMO_WARNING); + avisoEncuestaNtf.setDuration(5000); + avisoEncuestaNtf.open(); + + } else { + btnEnviarEncuesta.setEnabled(false); + btnEnviarEncuesta.getStyle().set("opacity", "0.5"); + } + if (detalle != null) { this.planAnualIdActual = detalle.getPlanAnualId(); this.mantenimientoIdActual = detalle.getId(); diff --git a/src/main/java/mx/gob/jumapacelaya/ui/EncuestaView.java b/src/main/java/mx/gob/jumapacelaya/ui/EncuestaView.java index 0670416..57e70a1 100644 --- a/src/main/java/mx/gob/jumapacelaya/ui/EncuestaView.java +++ b/src/main/java/mx/gob/jumapacelaya/ui/EncuestaView.java @@ -18,7 +18,7 @@ import com.vaadin.flow.router.Route; import com.vaadin.flow.server.auth.AnonymousAllowed; import mx.gob.jumapacelaya.models.encuestas.Pregunta; import mx.gob.jumapacelaya.models.encuestas.Respuesta; -import mx.gob.jumapacelaya.services.encuestas.EncuestasDBService; +import mx.gob.jumapacelaya.services.DatabaseService; import javax.swing.*; import java.sql.Timestamp; @@ -31,13 +31,14 @@ import java.util.Timer; @AnonymousAllowed public class EncuestaView extends VerticalLayout implements BeforeEnterObserver { - private EncuestasDBService encuestasDBService; + private DatabaseService encuestasDBService; private int mantenimientoId = -1; private final VerticalLayout mainLyt = new VerticalLayout(); private Span pregunta1Txt = new Span(); private RadioButtonGroup pregunta1Rb = new RadioButtonGroup<>(); private Button btnEnviar = new Button("Enviar"); private TextField txtNumEmpl = new TextField("No. Empleado:"); + private String token; private static class RespuestaComponente { @@ -52,7 +53,7 @@ public class EncuestaView extends VerticalLayout implements BeforeEnterObserver private final List respuestasUI = new ArrayList<>(); - public EncuestaView(EncuestasDBService encuestasDBService) { + public EncuestaView(DatabaseService encuestasDBService) { this.encuestasDBService = encuestasDBService; setSpacing(true); @@ -80,23 +81,6 @@ public class EncuestaView extends VerticalLayout implements BeforeEnterObserver this.add(mainLyt); } - @Override - public void beforeEnter(BeforeEnterEvent beforeEnterEvent) { - List params = beforeEnterEvent.getLocation().getQueryParameters() - .getParameters().get("mantenimientoId"); - - if (params != null && !params.isEmpty()) { - try { - mantenimientoId = Integer.parseInt(params.get(0)); - mostrarMensaje(); - } catch (NumberFormatException e) { - add(new H2("Enlace inválido")); - } - } else { - add(new H2("No se recibió ningún numero de mantenimiento")); - } - } - private void mostrarMensaje() { txtNumEmpl.setRequired(true); @@ -163,28 +147,24 @@ public class EncuestaView extends VerticalLayout implements BeforeEnterObserver int empleadoId = Integer.parseInt(txtNumEmpl.getValue()); Timestamp ahora = new Timestamp(System.currentTimeMillis()); + List respuestas = new ArrayList<>(); for (RespuestaComponente rc : respuestasUI) { + if (rc.radios.getValue() == null) continue; - Pregunta pregunta = rc.pregunta; - String respuestaTexto = rc.radios.getValue(); - - if (respuestaTexto == null) { - System.out.println("Pregunta no respondida: " + pregunta.getPregunta()); - continue; - } - - boolean respuestaBool = respuestaTexto.equals("Si"); - - encuestasDBService.insertRespuestas( - mantenimientoId, - pregunta.getPreguntaId(), - ahora, - respuestaBool, - empleadoId - ); + respuestas.add(new Respuesta( + rc.pregunta.getPreguntaId(), + rc.radios.getValue().equals("Si") + )); } + encuestasDBService.insertRespuestas( + mantenimientoId, + respuestas, + empleadoId, + this.token + ); + NotiEncuesta(); mainLyt.setVisible(false); @@ -211,4 +191,28 @@ public class EncuestaView extends VerticalLayout implements BeforeEnterObserver ntf.add(layout); ntf.open(); } + + + @Override + public void beforeEnter(BeforeEnterEvent beforeEnterEvent) { + String token = beforeEnterEvent.getLocation().getQueryParameters() + .getParameters().getOrDefault("token", List.of("")).get(0); + + if (!token.isEmpty()) { + Integer idRecuperado = encuestasDBService.validarTokenYObtenerId(token); + + if (idRecuperado != null) { + this.mantenimientoId = idRecuperado; + this.token = token; + mostrarMensaje(); + + } else { + mainLyt.add(new H2("El enlace ha expírado o ya fue utilizado.")); + mainLyt.setAlignItems(Alignment.CENTER); + } + } else { + mainLyt.add(new H2("Acceso no autorizado.")); + mainLyt.setAlignItems(Alignment.CENTER); + } + } } diff --git a/src/main/java/mx/gob/jumapacelaya/ui/PlanAnualView.java b/src/main/java/mx/gob/jumapacelaya/ui/PlanAnualView.java index 9e73cfd..490ed28 100644 --- a/src/main/java/mx/gob/jumapacelaya/ui/PlanAnualView.java +++ b/src/main/java/mx/gob/jumapacelaya/ui/PlanAnualView.java @@ -268,13 +268,16 @@ public class PlanAnualView extends VerticalLayout { LocalDate fechaSistema = LocalDate.now(); String nomEquipo = planAnual.getNomEquipo(); String departamento = planAnual.getDepartamento(); + String encuesta = planAnual.getEncuesta(); btn.getUI().ifPresent(ui -> ui.navigate( "mantenimiento?id=" + idPlananual + "&fecha=" + fechaSistema + "&tipo=1" + "&nomEquipo=" + nomEquipo + - "&departamento=" + departamento)); + "&departamento=" + departamento + + "&enc=" + encuesta + )); }); } else if ("REALIZADO".equalsIgnoreCase(estado)) { @@ -284,8 +287,12 @@ public class PlanAnualView extends VerticalLayout { btn.addClickListener(event -> { int idPlananual = planAnual.getNumero(); + String encuesta = planAnual.getEncuesta(); + btn.getUI().ifPresent(ui -> ui.navigate( - "detalles?id=" + idPlananual)); + "detalles?id=" + idPlananual + + "&enc=" + encuesta + )); }); } else { btn = new Button("N/A");