From c5484de9a01f8776338f768e85b5f4d5935fb7cf Mon Sep 17 00:00:00 2001 From: Melina Gutierrez Date: Tue, 29 Oct 2024 14:55:57 -0400 Subject: [PATCH] #46 Perfil de Empleado - Registro Semanal mas reporte, falta mejorar el reporte semanal --- .gitea/workflows/build.yaml | 18 ++- pom.xml | 41 +++--- .../primefactorsolutions/model/Actividad.java | 2 +- .../model/HoursWorked.java | 24 ++-- .../repositories/EmployeeRepository.java | 6 +- .../service/HoursWorkedService.java | 8 +- .../service/ReportService.java | 122 +++++++++--------- .../views/EmployeeView.java | 18 +-- .../views/HoursWorkedMonthView.java | 86 ++++++------ .../views/HoursWorkedView.java | 54 ++++++-- .../views/ReporteView.java | 87 +++++++++++++ 11 files changed, 289 insertions(+), 177 deletions(-) create mode 100644 src/main/java/com/primefactorsolutions/views/ReporteView.java diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index e64cc3a..90aad01 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -1,16 +1,14 @@ -name: Builder -run-name: ${{ gitea.actor }} building -on: - push: - branches: - - main +name: PR Builder +run-name: ${{ gitea.actor }} building PR +on: [pull_request] jobs: - Build-Project: + Build-PR: runs-on: ubuntu-22.04 steps: - - run: echo "The job was automatically triggered by a ${{ gitea.event_name }} event on branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}." - - name: Build package + - run: echo "The job was automatically triggered by a ${{ gitea.event_name }} event on branch ${{ gitea.head_ref }} and ref is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}." + - name: Build PR + if: gitea.base_ref == 'main' run: | - git clone --single-branch --branch main https://git.primefactorsolutions.com/PFS/pfs-intra.git && cd pfs-intra && ./mvnw clean package -Pproduction && unlink /home/ubuntu/pfs-intra/app.jar && cp target/*.jar /home/ubuntu/pfs-intra/app.jar && sudo systemctl restart pfs-intra + git clone --single-branch --branch "${{ gitea.head_ref }}" https://git.primefactorsolutions.com/PFS/pfs-intra.git && cd pfs-intra && ./mvnw clean package -Pproduction - run: echo "This job's status is ${{ job.status }}." diff --git a/pom.xml b/pom.xml index b27ada9..17c2965 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.primefactorsolutions @@ -72,12 +72,6 @@ runtime - - org.apache.pdfbox - pdfbox - 2.0.29 - - org.springframework.boot spring-boot-starter-data-jpa @@ -187,6 +181,21 @@ viritin 2.8.22 + + org.apache.poi + poi-ooxml + 5.2.3 + + + org.apache.poi + poi-ooxml-schemas + 4.1.2 + + + org.apache.commons + commons-collections4 + 4.4 + com.flowingcode.addons simple-timer @@ -386,22 +395,8 @@ - - org.apache.maven.plugins - maven-failsafe-plugin - - - - integration-test - verify - - - - - false - true - - + + diff --git a/src/main/java/com/primefactorsolutions/model/Actividad.java b/src/main/java/com/primefactorsolutions/model/Actividad.java index a12164c..f7df96d 100644 --- a/src/main/java/com/primefactorsolutions/model/Actividad.java +++ b/src/main/java/com/primefactorsolutions/model/Actividad.java @@ -1,6 +1,6 @@ package com.primefactorsolutions.model; -final public class Actividad { +public final class Actividad { private String nombre; private double lunes; private double martes; diff --git a/src/main/java/com/primefactorsolutions/model/HoursWorked.java b/src/main/java/com/primefactorsolutions/model/HoursWorked.java index 3824bfe..d02310f 100644 --- a/src/main/java/com/primefactorsolutions/model/HoursWorked.java +++ b/src/main/java/com/primefactorsolutions/model/HoursWorked.java @@ -1,26 +1,32 @@ package com.primefactorsolutions.model; -import com.vaadin.flow.component.template.Id; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; import java.util.UUID; @Entity public class HoursWorked extends BaseEntity { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; + @GeneratedValue(strategy = GenerationType.UUID) + private UUID id; + @ManyToOne private Employee employee; private int weekNumber; private double totalHours; - public HoursWorked() {} + public HoursWorked() { } - public void setId(Long id) { + public UUID getId() { + return id; + } + + public void setId(final UUID id) { this.id = id; } @@ -28,15 +34,15 @@ public class HoursWorked extends BaseEntity { return employee; } - public void setEmployee(Employee value) { - this.employee = value; // Asignar el objeto Employee al campo + public void setEmployee(final Employee value) { + this.employee = value; } public int getWeekNumber() { return weekNumber; } - public void setWeekNumber(int weekNumber) { + public void setWeekNumber(final int weekNumber) { this.weekNumber = weekNumber; } @@ -44,7 +50,7 @@ public class HoursWorked extends BaseEntity { return totalHours; } - public void setTotalHours(double totalHours) { + public void setTotalHours(final double totalHours) { this.totalHours = totalHours; } } diff --git a/src/main/java/com/primefactorsolutions/repositories/EmployeeRepository.java b/src/main/java/com/primefactorsolutions/repositories/EmployeeRepository.java index e27a88b..51dc129 100644 --- a/src/main/java/com/primefactorsolutions/repositories/EmployeeRepository.java +++ b/src/main/java/com/primefactorsolutions/repositories/EmployeeRepository.java @@ -2,10 +2,12 @@ package com.primefactorsolutions.repositories; import com.primefactorsolutions.model.Employee; import org.springframework.data.jpa.repository.JpaRepository; - +import org.springframework.stereotype.Repository; import java.util.Optional; import java.util.UUID; +@Repository public interface EmployeeRepository extends JpaRepository { + Optional findByUsername(String username); -} +} \ No newline at end of file diff --git a/src/main/java/com/primefactorsolutions/service/HoursWorkedService.java b/src/main/java/com/primefactorsolutions/service/HoursWorkedService.java index 855a305..2da3c4b 100644 --- a/src/main/java/com/primefactorsolutions/service/HoursWorkedService.java +++ b/src/main/java/com/primefactorsolutions/service/HoursWorkedService.java @@ -12,7 +12,7 @@ public class HoursWorkedService { private final HoursWorkedRepository hoursWorkedRepository; @Autowired - public HoursWorkedService(HoursWorkedRepository hoursWorkedRepository) { + public HoursWorkedService(final HoursWorkedRepository hoursWorkedRepository) { this.hoursWorkedRepository = hoursWorkedRepository; } @@ -20,15 +20,15 @@ public class HoursWorkedService { return hoursWorkedRepository.findAll(); } - public HoursWorked saveHoursWorked(HoursWorked hoursWorked) { + public HoursWorked saveHoursWorked(final HoursWorked hoursWorked) { return hoursWorkedRepository.save(hoursWorked); } - public HoursWorked save(HoursWorked hoursWorked) { + public HoursWorked save(final HoursWorked hoursWorked) { return hoursWorkedRepository.save(hoursWorked); } - public void deleteHoursWorked(Long id) { + public void deleteHoursWorked(final Long id) { hoursWorkedRepository.deleteById(id); } } diff --git a/src/main/java/com/primefactorsolutions/service/ReportService.java b/src/main/java/com/primefactorsolutions/service/ReportService.java index 0de93fd..6baf0d0 100644 --- a/src/main/java/com/primefactorsolutions/service/ReportService.java +++ b/src/main/java/com/primefactorsolutions/service/ReportService.java @@ -1,72 +1,76 @@ package com.primefactorsolutions.service; -import com.openhtmltopdf.pdfboxout.PdfBoxRenderer; -import com.openhtmltopdf.pdfboxout.PdfRendererBuilder; -import freemarker.template.Configuration; -import freemarker.template.DefaultObjectWrapper; -import freemarker.template.Template; -import freemarker.template.TemplateExceptionHandler; -import lombok.SneakyThrows; -import org.apache.pdfbox.io.MemoryUsageSetting; -import org.apache.pdfbox.pdmodel.PDDocument; -import org.jetbrains.annotations.NotNull; +import com.primefactorsolutions.repositories.HoursWorkedRepository; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.ss.usermodel.*; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.util.TimeZone; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.List; +import java.util.Map; @Service public class ReportService { - @SneakyThrows - public byte[] writeAsPdf(final String reportName, final Object model) { - try (var os = new ByteArrayOutputStream()) { - writeAsPdf(reportName, model, os); + private final HoursWorkedRepository hoursWorkedRepository; + @Autowired + public ReportService(final HoursWorkedRepository hoursWorkedRepository) { + this.hoursWorkedRepository = hoursWorkedRepository; + } + + // Este método ahora solo crea el archivo Excel a partir de los datos que recibe. + public byte[] writeAsExcel(final String reportName, final List headers, + final List> data) + throws IOException { + return createExcelFile(reportName, headers, data); + } + + private byte[] createExcelFile(final String reportName, final List headers, + final List> data) + throws IOException { + try (Workbook workbook = new XSSFWorkbook(); + ByteArrayOutputStream os = new ByteArrayOutputStream()) { + Sheet sheet = workbook.createSheet(reportName); + + // Crear encabezados + Row headerRow = sheet.createRow(0); + CellStyle headerStyle = workbook.createCellStyle(); + Font headerFont = workbook.createFont(); + headerFont.setBold(true); + headerStyle.setFont(headerFont); + + for (int i = 0; i < headers.size(); i++) { + Cell cell = headerRow.createCell(i); + cell.setCellValue(headers.get(i)); + cell.setCellStyle(headerStyle); + } + + // Crear filas de datos + for (int i = 0; i < data.size(); i++) { + Row dataRow = sheet.createRow(i + 1); + Map rowData = data.get(i); + int cellIndex = 0; + for (String key : headers) { + Cell cell = dataRow.createCell(cellIndex++); + Object value = rowData.get(key); + if (value instanceof String) { + cell.setCellValue((String) value); + } else if (value instanceof Number) { + cell.setCellValue(((Number) value).doubleValue()); + } else if (value == null) { + cell.setCellValue(""); // Manejo de valores nulos + } + } + } + + workbook.write(os); return os.toByteArray(); + } catch (IOException e) { + System.err.println("Error al generar el archivo Excel: " + e.getMessage()); + throw e; // Propagar la excepción después de registrarla } } - - @SneakyThrows - public void writeAsPdf(final String reportName, final Object model, final OutputStream out) { - var in = getTemplate(reportName); - final Configuration cfg = getConfiguration(); - final Reader reader = new InputStreamReader(in); - final Template temp = new Template(reportName, reader, cfg); - - var wrapper = new DefaultObjectWrapper(Configuration.VERSION_2_3_32); - ByteArrayOutputStream oo = new ByteArrayOutputStream(); - Writer outTemplate = new OutputStreamWriter(oo); - - temp.process(wrapper.wrap(model), outTemplate); - - var builder = new PdfRendererBuilder(); - builder.usePDDocument(new PDDocument(MemoryUsageSetting.setupMixed(1000000))); - builder.withHtmlContent(oo.toString(StandardCharsets.UTF_8), "/test"); - builder.toStream(out); - - try (PdfBoxRenderer pdfBoxRenderer = builder.buildPdfRenderer()) { - pdfBoxRenderer.layout(); - pdfBoxRenderer.createPDF(); - } - } - - public static InputStream getTemplate(final String reportName) { - return ReportService.class.getResourceAsStream(String.format("/reports/%s.html", reportName)); - } - - - @NotNull - private static Configuration getConfiguration() { - final Configuration cfg = new Configuration(Configuration.VERSION_2_3_32); - cfg.setDefaultEncoding("UTF-8"); - cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); - cfg.setLogTemplateExceptions(false); - cfg.setWrapUncheckedExceptions(true); - cfg.setFallbackOnNullLoopVariable(false); - cfg.setSQLDateAndTimeTimeZone(TimeZone.getDefault()); - - return cfg; - } } diff --git a/src/main/java/com/primefactorsolutions/views/EmployeeView.java b/src/main/java/com/primefactorsolutions/views/EmployeeView.java index bdf5a82..5e969a8 100644 --- a/src/main/java/com/primefactorsolutions/views/EmployeeView.java +++ b/src/main/java/com/primefactorsolutions/views/EmployeeView.java @@ -4,9 +4,7 @@ import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.ReportService; import com.vaadin.componentfactory.pdfviewer.PdfViewer; -import com.vaadin.flow.component.ClickEvent; import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.ComponentEventListener; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.ButtonVariant; import com.vaadin.flow.component.combobox.ComboBox; @@ -24,14 +22,12 @@ import com.vaadin.flow.component.upload.Upload; import com.vaadin.flow.component.upload.receivers.MemoryBuffer; import com.vaadin.flow.data.value.ValueChangeMode; import com.vaadin.flow.router.*; -import com.vaadin.flow.server.StreamResource; import com.vaadin.flow.spring.annotation.SpringComponent; import jakarta.annotation.security.PermitAll; import org.springframework.context.annotation.Scope; import org.vaadin.firitin.components.datepicker.VDatePicker; import org.vaadin.firitin.form.BeanValidationForm; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Base64; @@ -156,13 +152,13 @@ public class EmployeeView extends BeanValidationForm implements HasUrl reportButton.setVisible(true); birthday.addValueChangeListener(event -> calculateAge()); - reportButton.addClickListener((ComponentEventListener>) buttonClickEvent -> { - var employee = getEntity(); - byte[] pdfContent = reportService.writeAsPdf("ficha", employee); - var resource = new StreamResource("ficha.pdf", () -> new ByteArrayInputStream(pdfContent)); - pdfViewer.setSrc(resource); - dialog.open(); - }); + // reportButton.addClickListener((ComponentEventListener>) buttonClickEvent -> { + // var employee = getEntity(); + // byte[] pdfContent = reportService.writeAsPdf("ficha", employee); + // var resource = new StreamResource("ficha.pdf", () -> new ByteArrayInputStream(pdfContent)); + // pdfViewer.setSrc(resource); + // dialog.open(); + // }); initDialog(); } diff --git a/src/main/java/com/primefactorsolutions/views/HoursWorkedMonthView.java b/src/main/java/com/primefactorsolutions/views/HoursWorkedMonthView.java index a908f16..88d86e6 100644 --- a/src/main/java/com/primefactorsolutions/views/HoursWorkedMonthView.java +++ b/src/main/java/com/primefactorsolutions/views/HoursWorkedMonthView.java @@ -19,8 +19,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import java.time.LocalDate; -import java.time.temporal.TemporalAdjusters; -import java.util.ArrayList; import java.util.List; @SpringComponent @@ -45,7 +43,7 @@ public class HoursWorkedMonthView extends VerticalLayout { private LocalDate selectedMonth; @Autowired - public HoursWorkedMonthView(EmployeeService employeeService) { + public HoursWorkedMonthView(final EmployeeService employeeService) { this.employeeService = employeeService; configurarVista(); } @@ -55,7 +53,7 @@ public class HoursWorkedMonthView extends VerticalLayout { monthPicker.setValue(LocalDate.now()); monthPicker.addValueChangeListener(event -> { selectedMonth = event.getValue().withDayOfMonth(1); - cargarDatosMes(selectedMonth); + //cargarDatosMes(selectedMonth); }); equipoDropdown.setItems("Equipo 1", "Equipo 2", "Equipo 3"); @@ -96,56 +94,56 @@ public class HoursWorkedMonthView extends VerticalLayout { grid.addColumn(this::calcularTotalPorDia).setHeader("Total Semanal").setKey("totalSemanal"); } - private void cargarDatosMes(LocalDate month) { - List actividadesDelMes = obtenerActividadesDelMes(month); - grid.setItems(actividadesDelMes); +// private void cargarDatosMes(final LocalDate month) { +// List actividadesDelMes = obtenerActividadesDelMes(month); +// grid.setItems(actividadesDelMes); +// +// double totalCompletado = calcularTotalCompletado(actividadesDelMes); +// double horasPendientes = calcularHorasPendientes(totalCompletado); +// double totalAcumuladas = 166; +// double horasAdeudadas = 2; +// +// totalCompletadoLabel.setText("Prom. Hrs/Semana Completadas: " + totalCompletado); +// horasPendientesLabel.setText("Prom. Hrs/Semana Pendientes: " + horasPendientes); +// totalAcumuladasLabel.setText("Total Hrs./Mes Acumuladas: " + totalAcumuladas); +// horasAdeudadasLabel.setText("Total Hrs./Mes Adeudadas: " + horasAdeudadas); +// } - double totalCompletado = calcularTotalCompletado(actividadesDelMes); - double horasPendientes = calcularHorasPendientes(totalCompletado); - double totalAcumuladas = 166; - double horasAdeudadas = 2; +// private List obtenerActividadesDelMes(final LocalDate month) { +// LocalDate startOfMonth = month.with(TemporalAdjusters.firstDayOfMonth()); +// LocalDate endOfMonth = month.with(TemporalAdjusters.lastDayOfMonth()); +// +// List actividadesDelMes = new ArrayList<>(); +// +// for (LocalDate date = startOfMonth; date.isBefore(endOfMonth.plusDays(1)); date = date.plusDays(1)) { +// Actividad actividad = new Actividad.Builder() +// .lunes(0) +// .martes(0) +// .miercoles(0) +// .jueves(0) +// .viernes(0) +// .sabado(0) +// .domingo(0) +// .build(); +// actividadesDelMes.add(actividad); +// } +// +// return actividadesDelMes; +// } - totalCompletadoLabel.setText("Prom. Hrs/Semana Completadas: " + totalCompletado); - horasPendientesLabel.setText("Prom. Hrs/Semana Pendientes: " + horasPendientes); - totalAcumuladasLabel.setText("Total Hrs./Mes Acumuladas: " + totalAcumuladas); - horasAdeudadasLabel.setText("Total Hrs./Mes Adeudadas: " + horasAdeudadas); - } - - private List obtenerActividadesDelMes(final LocalDate month) { - LocalDate startOfMonth = month.with(TemporalAdjusters.firstDayOfMonth()); - LocalDate endOfMonth = month.with(TemporalAdjusters.lastDayOfMonth()); - - List actividadesDelMes = new ArrayList<>(); - - for (LocalDate date = startOfMonth; date.isBefore(endOfMonth.plusDays(1)); date = date.plusDays(1)) { - Actividad actividad = new Actividad.Builder() - .lunes(0) - .martes(0) - .miercoles(0) - .jueves(0) - .viernes(0) - .sabado(0) - .domingo(0) - .build(); - actividadesDelMes.add(actividad); - } - - return actividadesDelMes; - } - - private double calcularTotalCompletado(List actividades) { + private double calcularTotalCompletado(final List actividades) { return actividades.stream() .mapToDouble(this::calcularTotalPorDia) .sum(); } private double calcularTotalPorDia(final Actividad actividad) { - return actividad.getLunes() + actividad.getMartes() + actividad.getMiercoles() + - actividad.getJueves() + actividad.getViernes() + actividad.getSabado() + - actividad.getDomingo(); + return actividad.getLunes() + actividad.getMartes() + actividad.getMiercoles() + + actividad.getJueves() + actividad.getViernes() + actividad.getSabado() + + actividad.getDomingo(); } - private double calcularHorasPendientes(double totalCompletado) { + private double calcularHorasPendientes(final double totalCompletado) { return 40 - totalCompletado; } diff --git a/src/main/java/com/primefactorsolutions/views/HoursWorkedView.java b/src/main/java/com/primefactorsolutions/views/HoursWorkedView.java index 2eb0c19..2c95054 100644 --- a/src/main/java/com/primefactorsolutions/views/HoursWorkedView.java +++ b/src/main/java/com/primefactorsolutions/views/HoursWorkedView.java @@ -37,6 +37,7 @@ import java.util.Locale; public class HoursWorkedView extends VerticalLayout { private final List actividades = new ArrayList<>(); private final Grid grid = new Grid<>(Actividad.class); + private final ComboBox employeeComboBox = new ComboBox<>("Employee"); private LocalDate selectedStartOfWeek; private int weekNumber; @@ -78,13 +79,14 @@ public class HoursWorkedView extends VerticalLayout { employeeComboBox.addValueChangeListener(event -> { Employee selectedEmployee = event.getValue(); if (selectedEmployee != null) { - Notification.show("Empleado seleccionado: " + - selectedEmployee.getFirstName() + " " + selectedEmployee.getLastName()); + Notification.show("Empleado seleccionado: " + + selectedEmployee.getFirstName() + " " + + selectedEmployee.getLastName()); } }); } - private int getWeekOfYear(LocalDate date) { + private int getWeekOfYear(final LocalDate date) { return date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR); } @@ -120,7 +122,8 @@ public class HoursWorkedView extends VerticalLayout { Button guardarButton = new Button("Guardar", event -> guardarActividades()); Button cerrarButton = new Button("Cerrar", event -> this.closeView()); - HorizontalLayout buttonsLayout = new HorizontalLayout(actualizarButton, guardarButton, cerrarButton, verMesButton); + HorizontalLayout buttonsLayout = new HorizontalLayout(actualizarButton, guardarButton, + cerrarButton, verMesButton); VerticalLayout totalesLayout = new VerticalLayout(totalCompletadoLabel, horasPendientesLabel); totalesLayout.setSpacing(true); @@ -173,6 +176,15 @@ public class HoursWorkedView extends VerticalLayout { grid.setItems(actividades); actualizarTotales(); Notification.show("Actividad agregada correctamente"); + // Limpiar los campos de entrada + actividadNombre.clear(); + lunesHoras.clear(); + martesHoras.clear(); + miercolesHoras.clear(); + juevesHoras.clear(); + viernesHoras.clear(); + sabadoHoras.clear(); + domingoHoras.clear(); } catch (NumberFormatException ex) { Notification.show("Error: Por favor ingresa números válidos para las horas."); } @@ -183,14 +195,14 @@ public class HoursWorkedView extends VerticalLayout { juevesHoras, viernesHoras, sabadoHoras, domingoHoras, agregarActividadButton); } - private TextField crearCampoHora(String placeholder) { + private TextField crearCampoHora(final String placeholder) { TextField field = new TextField(placeholder); field.setWidth("80px"); field.setPlaceholder("0.0"); return field; } - private double parseHoras(String value) { + private double parseHoras(final String value) { if (value == null || value.trim().isEmpty()) { return 0.0; } @@ -218,17 +230,31 @@ public class HoursWorkedView extends VerticalLayout { } private void guardarActividades() { - HoursWorked hoursWorked = new HoursWorked(); - hoursWorked.setEmployee(employeeComboBox.getValue()); - hoursWorked.setWeekNumber(weekNumber); - hoursWorked.setTotalHours((actividades.stream() - .mapToDouble(this::calcularTotalPorDia).sum())); - hoursWorkedService.save(hoursWorked); + Employee selectedEmployee = employeeComboBox.getValue(); - Notification.show("Actividades guardadas correctamente."); + if (selectedEmployee == null) { + Notification.show("Por favor, selecciona un empleado antes de guardar."); + return; + } + + double totalHorasSemana = actividades.stream() + .mapToDouble(this::calcularTotalPorDia) + .sum(); + + HoursWorked hoursWorked = new HoursWorked(); + hoursWorked.setEmployee(selectedEmployee); + hoursWorked.setWeekNumber(weekNumber); + hoursWorked.setTotalHours(totalHorasSemana); + + try { + hoursWorkedService.saveHoursWorked(hoursWorked); // Usa saveHoursWorked directamente + Notification.show("Actividades guardadas correctamente."); + } catch (Exception e) { + Notification.show("Error al guardar actividades: " + e.getMessage()); + } } - private double calcularTotalHoras(List listaDeHorasTrabajadas) { + private double calcularTotalHoras(final List listaDeHorasTrabajadas) { return listaDeHorasTrabajadas.stream() .mapToDouble(HoursWorked::getTotalHours) .sum(); diff --git a/src/main/java/com/primefactorsolutions/views/ReporteView.java b/src/main/java/com/primefactorsolutions/views/ReporteView.java new file mode 100644 index 0000000..1416a56 --- /dev/null +++ b/src/main/java/com/primefactorsolutions/views/ReporteView.java @@ -0,0 +1,87 @@ +package com.primefactorsolutions.views; + +import com.primefactorsolutions.model.HoursWorked; +import com.primefactorsolutions.service.HoursWorkedService; +import com.primefactorsolutions.service.ReportService; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.html.Anchor; +import com.vaadin.flow.component.html.H2; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.server.StreamResource; +import jakarta.annotation.security.PermitAll; +import org.springframework.beans.factory.annotation.Autowired; +import com.vaadin.flow.component.notification.Notification; + +import java.io.ByteArrayInputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@PermitAll +@Route(value = "/reportes", layout = MainLayout.class) +@PageTitle("Reporte de Horas Trabajadas") +public class ReporteView extends VerticalLayout { + + private final HoursWorkedService hoursWorkedService; + private final ReportService reportService; + + @Autowired + public ReporteView(final HoursWorkedService hoursWorkedService, final ReportService reportService) { + this.hoursWorkedService = hoursWorkedService; + this.reportService = reportService; + + H2 title = new H2("Reporte de Horas Trabajadas"); + add(title); + + Button reportButton = new Button("Generar Reporte de Horas Trabajadas", event -> generateHoursWorkedReport()); + add(reportButton); + } + + private void generateHoursWorkedReport() { + List hoursWorkedList = hoursWorkedService.findAll(); // Obtener la lista de HoursWorked + + if (hoursWorkedList.isEmpty()) { + Notification.show("No hay horas trabajadas disponibles para generar el reporte.", + 3000, Notification.Position.MIDDLE); + return; + } + + try { + List headers = List.of("ID", "Employee ID", "Week Number", "Total Hours"); + + List> data = hoursWorkedList.stream() + .map(hoursWorked -> { + Map map = new HashMap<>(); + map.put("ID", hoursWorked.getId().toString()); + map.put("Employee ID", hoursWorked.getEmployee().getId().toString()); + map.put("Week Number", hoursWorked.getWeekNumber()); + map.put("Total Hours", hoursWorked.getTotalHours()); + return map; + }) + .collect(Collectors.toList()); + + byte[] excelBytes = reportService.writeAsExcel("hours_worked_report", headers, data); + + StreamResource excelResource = new StreamResource("hours_worked_report.xlsx", + () -> new ByteArrayInputStream(excelBytes)); + excelResource.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + excelResource.setCacheTime(0); + + Anchor downloadLink = new Anchor(excelResource, "Descargar Reporte de Horas Trabajadas"); + downloadLink.getElement().setAttribute("download", true); + + add(downloadLink); + Notification.show("Reporte de horas trabajadas generado exitosamente.", + 3000, Notification.Position.MIDDLE); + + } catch (Exception e) { + Notification.show("Error al generar el reporte de horas trabajadas. Inténtalo de nuevo.", + 3000, Notification.Position.MIDDLE); + e.printStackTrace(); + } + } + +}