|
|
|
@ -1,5 +1,6 @@ |
|
|
|
package mx.gob.jumapacelaya.ui; |
|
|
|
|
|
|
|
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; |
|
|
|
import com.vaadin.flow.component.Component; |
|
|
|
import com.vaadin.flow.component.UI; |
|
|
|
import com.vaadin.flow.component.button.Button; |
|
|
|
@ -34,6 +35,7 @@ import com.vaadin.flow.component.textfield.TextField; |
|
|
|
import com.vaadin.flow.component.upload.Upload; |
|
|
|
import com.vaadin.flow.component.upload.receivers.MemoryBuffer; |
|
|
|
import com.vaadin.flow.data.provider.ListDataProvider; |
|
|
|
import com.vaadin.flow.data.renderer.ComponentRenderer; |
|
|
|
import com.vaadin.flow.data.value.ValueChangeMode; |
|
|
|
import com.vaadin.flow.function.ValueProvider; |
|
|
|
import com.vaadin.flow.router.PageTitle; |
|
|
|
@ -42,12 +44,15 @@ import com.vaadin.flow.server.StreamRegistration; |
|
|
|
import com.vaadin.flow.server.StreamResource; |
|
|
|
import jakarta.annotation.security.PermitAll; |
|
|
|
import mx.gob.jumapacelaya.models.PlanAnual; |
|
|
|
import mx.gob.jumapacelaya.models.encuestas.MantenimientosSinEncuesta; |
|
|
|
import mx.gob.jumapacelaya.services.DatabaseService; |
|
|
|
import mx.gob.jumapacelaya.services.EmailService; |
|
|
|
import mx.gob.jumapacelaya.services.ReportService; |
|
|
|
import net.sf.jasperreports.engine.JasperFillManager; |
|
|
|
import net.sf.jasperreports.engine.JasperPrint; |
|
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
|
import org.apache.poi.ss.usermodel.*; |
|
|
|
import org.springframework.beans.factory.annotation.Value; |
|
|
|
import org.springframework.core.env.Environment; |
|
|
|
import org.springframework.security.core.Authentication; |
|
|
|
import org.springframework.security.core.context.SecurityContextHolder; |
|
|
|
@ -70,6 +75,9 @@ import java.util.stream.IntStream; |
|
|
|
@CssImport("./themes/sistema-mantenimiento/styles.css") |
|
|
|
public class PlanAnualView extends VerticalLayout { |
|
|
|
|
|
|
|
private final EmailService emailService; |
|
|
|
@Value("${app.base-url}") |
|
|
|
private String baseUrl; |
|
|
|
private final Environment env; |
|
|
|
private final ReportService reportService; |
|
|
|
|
|
|
|
@ -90,7 +98,7 @@ public class PlanAnualView extends VerticalLayout { |
|
|
|
private Popover reportePopover; |
|
|
|
ComboBox<Integer> yearFilter; |
|
|
|
|
|
|
|
public PlanAnualView(DatabaseService databaseService, Environment env, ReportService reportService) { |
|
|
|
public PlanAnualView(DatabaseService databaseService, Environment env, ReportService reportService, EmailService emailService) { |
|
|
|
this.databaseService = databaseService; |
|
|
|
this.env = env; |
|
|
|
this.reportService = reportService; |
|
|
|
@ -113,9 +121,14 @@ public class PlanAnualView extends VerticalLayout { |
|
|
|
PlanAnualFilter planAnualFilter = new PlanAnualFilter(dataView); |
|
|
|
planAnualFilter.setExcludeRealizado(true); |
|
|
|
|
|
|
|
yearFilter.addValueChangeListener(event -> |
|
|
|
planAnualFilter.setYear(event.getValue()) |
|
|
|
); |
|
|
|
// Aplicar el valor actual del ComboBox al filtro al inicializar |
|
|
|
if (yearFilter != null && yearFilter.getValue() != null) { |
|
|
|
planAnualFilter.setYear(yearFilter.getValue()); |
|
|
|
} |
|
|
|
|
|
|
|
if (yearFilter != null) { |
|
|
|
yearFilter.addValueChangeListener(event -> planAnualFilter.setYear(event.getValue())); |
|
|
|
} |
|
|
|
|
|
|
|
HeaderRow headerRow = planAnualGrid.appendHeaderRow(); |
|
|
|
/*headerRow.getCell(planAnualGrid.getColumnByKey("smtColumnKey")) |
|
|
|
@ -130,6 +143,9 @@ public class PlanAnualView extends VerticalLayout { |
|
|
|
headerRow.getCell(planAnualGrid.getColumnByKey("mesplaneado")) |
|
|
|
.setComponent(createFilterHeader("Mes Planeado", planAnualFilter::setMesPlaneado)); |
|
|
|
|
|
|
|
headerRow.getCell(planAnualGrid.getColumnByKey("encuesta")) |
|
|
|
.setComponent(createFilterHeader("Encuesta", planAnualFilter::setEncuesta)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// MENU CONTEXTUAL DEL GRID |
|
|
|
@ -228,6 +244,7 @@ public class PlanAnualView extends VerticalLayout { |
|
|
|
this.setSizeFull(); |
|
|
|
add(filtrosLayout, uploadLayout); |
|
|
|
add(gridLayout); |
|
|
|
this.emailService = emailService; |
|
|
|
} |
|
|
|
|
|
|
|
private void setupHeader() { |
|
|
|
@ -369,14 +386,8 @@ public class PlanAnualView extends VerticalLayout { |
|
|
|
btnAddEquipo.setTooltipText("Agregar nuevo equipo"); |
|
|
|
|
|
|
|
btnEnviarEncuestas = new Button(VaadinIcon.ENVELOPE.create()); |
|
|
|
ConfirmDialog enviarEncConfirm = new ConfirmDialog(); |
|
|
|
enviarEncConfirm.setHeader("Enviar encuestas"); |
|
|
|
enviarEncConfirm.setText("¿Deseas enviar las encuestas de satisfacción?, Esto enviara la encuesta solo a los mantenimientos realizados"); |
|
|
|
enviarEncConfirm.setCancelable(true); |
|
|
|
enviarEncConfirm.addCancelListener(e -> enviarEncConfirm.close()); |
|
|
|
enviarEncConfirm.setConfirmText("Enviar"); |
|
|
|
enviarEncConfirm.addConfirmListener(e -> {}); |
|
|
|
btnEnviarEncuestas.addClickListener(e -> enviarEncConfirm.open()); |
|
|
|
btnEnviarEncuestas.addClickListener(e -> showParametrosDialog()); |
|
|
|
btnEnviarEncuestas.setTooltipText("Enviar encuestas masivamente"); |
|
|
|
|
|
|
|
yearFilter = new ComboBox<>(); |
|
|
|
int currentYear = Year.now().getValue(); |
|
|
|
@ -384,12 +395,14 @@ public class PlanAnualView extends VerticalLayout { |
|
|
|
.boxed().collect(Collectors.toList()); |
|
|
|
yearFilter.setItems(years); |
|
|
|
yearFilter.setPlaceholder("Año"); |
|
|
|
yearFilter.setValue(currentYear); |
|
|
|
yearFilter.setClearButtonVisible(true); |
|
|
|
|
|
|
|
|
|
|
|
List<PlanAnual> todosLosPlanes = databaseService.getPlanAnual(); |
|
|
|
|
|
|
|
|
|
|
|
btnImprimirLayout = new HorizontalLayout(btnColumns, btnImprimirRpt, btnAddEquipo/*, btnEnviarEncuestas*/, yearFilter); |
|
|
|
btnImprimirLayout = new HorizontalLayout(btnColumns, btnImprimirRpt, btnAddEquipo, btnEnviarEncuestas, yearFilter); |
|
|
|
btnImprimirLayout.setAlignItems(Alignment.BASELINE); |
|
|
|
HorizontalLayout columnSelectorLayout = new HorizontalLayout(); |
|
|
|
columnSelectorLayout.setAlignItems(Alignment.END); |
|
|
|
@ -541,6 +554,11 @@ public class PlanAnualView extends VerticalLayout { |
|
|
|
private String equipo; |
|
|
|
private String departamento; |
|
|
|
private String mesPlaneado; |
|
|
|
private LocalDate fechaProgramada; |
|
|
|
private LocalDate fechaRealizacion; |
|
|
|
private String encuesta; |
|
|
|
private String estado; |
|
|
|
private String situacion; |
|
|
|
private Integer year; |
|
|
|
private boolean excludeRealizado = true; |
|
|
|
|
|
|
|
@ -569,6 +587,11 @@ public class PlanAnualView extends VerticalLayout { |
|
|
|
this.dataView.refreshAll(); |
|
|
|
} |
|
|
|
|
|
|
|
public void setEncuesta(String encuesta) { |
|
|
|
this.encuesta = encuesta; |
|
|
|
this.dataView.refreshAll(); |
|
|
|
} |
|
|
|
|
|
|
|
public void setYear(Integer year) { |
|
|
|
this.year = year; |
|
|
|
dataView.refreshAll(); |
|
|
|
@ -586,6 +609,7 @@ public class PlanAnualView extends VerticalLayout { |
|
|
|
boolean matchesEquipo = matches(planAnual.getNomEquipo(), equipo); |
|
|
|
boolean matchesDepartamento = matches(planAnual.getDepartamento(), departamento); |
|
|
|
boolean matchesMesPlaneado = matches(planAnual.getMesplaneado(), mesPlaneado); |
|
|
|
boolean matchesEncuesta = matches(planAnual.getEncuesta(), encuesta); |
|
|
|
|
|
|
|
boolean matchesYear = true; |
|
|
|
if (year != null) { |
|
|
|
@ -608,7 +632,8 @@ public class PlanAnualView extends VerticalLayout { |
|
|
|
&& matchesDepartamento |
|
|
|
&& matchesMesPlaneado |
|
|
|
&& matchesYear |
|
|
|
&& matchesEstado; |
|
|
|
&& matchesEstado |
|
|
|
&& matchesEncuesta; |
|
|
|
} |
|
|
|
|
|
|
|
private boolean matches(String value, String serachTerm) { |
|
|
|
@ -1005,4 +1030,167 @@ public class PlanAnualView extends VerticalLayout { |
|
|
|
dialog.getFooter().add(dialogFooter); |
|
|
|
dialog.open(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void showParametrosDialog() { |
|
|
|
Dialog dialog = new Dialog(); |
|
|
|
dialog.setHeaderTitle("Ingresar periodo"); |
|
|
|
|
|
|
|
TextField txtMes = new TextField("Mes:"); |
|
|
|
txtMes.setPlaceholder("ENERO, FEBRERO, MARZO..."); |
|
|
|
txtMes.setClearButtonVisible(true); |
|
|
|
|
|
|
|
TextField txtAnio = new TextField("Año"); |
|
|
|
txtAnio.setPlaceholder("Ej. 2025"); |
|
|
|
|
|
|
|
Button btnBuscar = new Button("Buscar", VaadinIcon.SEARCH.create(), e -> { |
|
|
|
String mes = txtMes.getValue(); |
|
|
|
String anioTexto = txtAnio.getValue(); |
|
|
|
|
|
|
|
if (mes.isEmpty() || anioTexto.isEmpty()) { |
|
|
|
Notification.show("Mes y año son requeridos.", 3000, Notification.Position.MIDDLE); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
int anio; |
|
|
|
try { |
|
|
|
anio = Integer.parseInt(anioTexto); |
|
|
|
} catch (NumberFormatException ex) { |
|
|
|
Notification.show("El año debe ser numérico.", 3000, Notification.Position.MIDDLE); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
dialog.close(); |
|
|
|
showEncuestasDialog(mes, anio); |
|
|
|
}); |
|
|
|
btnBuscar.addThemeVariants(ButtonVariant.LUMO_PRIMARY); |
|
|
|
|
|
|
|
Button btnCancelar = new Button("Cancelar", VaadinIcon.CLOSE_CIRCLE.create(), e -> dialog.close()); |
|
|
|
|
|
|
|
HorizontalLayout actions = new HorizontalLayout(btnBuscar, btnCancelar); |
|
|
|
|
|
|
|
VerticalLayout layout = new VerticalLayout(txtMes, txtAnio, actions); |
|
|
|
layout.setPadding(false); |
|
|
|
layout.setSpacing(true); |
|
|
|
|
|
|
|
dialog.add(layout); |
|
|
|
dialog.open(); |
|
|
|
} |
|
|
|
|
|
|
|
private void showEncuestasDialog(String mes, int anio) { |
|
|
|
Dialog dialog = new Dialog(); |
|
|
|
dialog.setWidth("90%"); |
|
|
|
dialog.setHeight("90%"); |
|
|
|
dialog.setHeaderTitle("Encuestas pendientes por enviar..."); |
|
|
|
|
|
|
|
Grid<MantenimientosSinEncuesta> grid = new Grid<>(MantenimientosSinEncuesta.class, false); |
|
|
|
grid.addColumn(MantenimientosSinEncuesta::getMantenimientoId) |
|
|
|
.setHeader("ID") |
|
|
|
.setAutoWidth(true); |
|
|
|
|
|
|
|
grid.addColumn(item -> item.getFecha().format(DateTimeFormatter.ofPattern("dd/MM/yyyy"))) |
|
|
|
.setHeader("Fecha"); |
|
|
|
|
|
|
|
grid.addColumn(MantenimientosSinEncuesta::getPeriodo) |
|
|
|
.setHeader("Periodo"); |
|
|
|
|
|
|
|
grid.addColumn(createStatusRender()) |
|
|
|
.setHeader("Encuesta"); |
|
|
|
|
|
|
|
grid.addColumn(MantenimientosSinEncuesta::getDepartamento) |
|
|
|
.setHeader("Departamento") |
|
|
|
.setAutoWidth(true); |
|
|
|
|
|
|
|
grid.addColumn(MantenimientosSinEncuesta::getNomUsuario) |
|
|
|
.setHeader("Usuario") |
|
|
|
.setAutoWidth(true); |
|
|
|
|
|
|
|
grid.addColumn(MantenimientosSinEncuesta::getEmail) |
|
|
|
.setHeader("Correo") |
|
|
|
.setAutoWidth(true); |
|
|
|
|
|
|
|
grid.addComponentColumn(item -> { |
|
|
|
Button btnEnviar = new Button( |
|
|
|
"Enviar", |
|
|
|
LineAwesomeIcon.ENVELOPE_SOLID.create() |
|
|
|
); |
|
|
|
btnEnviar.addThemeVariants(ButtonVariant.LUMO_PRIMARY, |
|
|
|
ButtonVariant.LUMO_SUCCESS); |
|
|
|
|
|
|
|
btnEnviar.addClickListener(e -> { |
|
|
|
enviarEncuestaDesdeGrid(item); |
|
|
|
btnEnviar.setEnabled(false); |
|
|
|
}); |
|
|
|
|
|
|
|
return btnEnviar; |
|
|
|
}).setHeader("Accion"); |
|
|
|
|
|
|
|
List<MantenimientosSinEncuesta> lista = databaseService.getEncuestPendientes(mes, anio); |
|
|
|
|
|
|
|
grid.setItems(lista); |
|
|
|
dialog.add(grid); |
|
|
|
dialog.getFooter().add(new Button("Cerrar", LineAwesomeIcon.TIMES_SOLID.create(), e -> dialog.close())); |
|
|
|
|
|
|
|
dialog.open(); |
|
|
|
} |
|
|
|
|
|
|
|
private void enviarEncuestaDesdeGrid(MantenimientosSinEncuesta item) { |
|
|
|
|
|
|
|
if (item.getEmail() == null || item.getEmail().isBlank()) { |
|
|
|
Notification.show("El usuario no tiene correo", 3000, Notification.Position.MIDDLE) |
|
|
|
.addThemeVariants(NotificationVariant.LUMO_ERROR); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
int mantenimientoId = item.getMantenimientoId(); |
|
|
|
|
|
|
|
String token = databaseService.crearTokenEncuesta(mantenimientoId); |
|
|
|
String linkEncuesta = baseUrl + "/encuesta?token=" + token; |
|
|
|
|
|
|
|
String cuerpo = """ |
|
|
|
<html> |
|
|
|
<body> |
|
|
|
<a href="%s"> |
|
|
|
<img src="cid:image_id"/> |
|
|
|
</a> |
|
|
|
</body> |
|
|
|
</html> |
|
|
|
""".formatted(linkEncuesta); |
|
|
|
|
|
|
|
String asunto = "Encuesta de satisfacción - Mantenimiento #" + mantenimientoId; |
|
|
|
String imagePath = "META-INF/resources/images/imgCorreo/imgEncuesta.png"; |
|
|
|
|
|
|
|
emailService.enviarCorreo( |
|
|
|
item.getEmail(), |
|
|
|
asunto, |
|
|
|
cuerpo, |
|
|
|
imagePath |
|
|
|
); |
|
|
|
|
|
|
|
Notification.show("Encuesta enviada correctamente", 3000, Notification.Position.MIDDLE) |
|
|
|
.addThemeVariants(NotificationVariant.LUMO_SUCCESS); |
|
|
|
} |
|
|
|
|
|
|
|
private ComponentRenderer<Span, MantenimientosSinEncuesta> createStatusRender() { |
|
|
|
return new ComponentRenderer<>(encuesta -> { |
|
|
|
Span span = new Span(encuesta.getEncuesta()); |
|
|
|
|
|
|
|
switch (encuesta.getEncuesta().toUpperCase()) { |
|
|
|
case "N": |
|
|
|
String theme1 = String.format("badge %s", "error"); |
|
|
|
span.getElement().setAttribute("theme", theme1); |
|
|
|
break; |
|
|
|
case "S": |
|
|
|
String theme2 = String.format("badge %s", "success"); |
|
|
|
span.getElement().setAttribute("theme", theme2); |
|
|
|
break; |
|
|
|
default: |
|
|
|
String theme3 = String.format("badge %s", ""); |
|
|
|
span.getElement().setAttribute("theme", theme3); |
|
|
|
} |
|
|
|
|
|
|
|
return span; |
|
|
|
}); |
|
|
|
} |
|
|
|
} |