diff --git a/.gitea/workflows/build-pr.yaml b/.gitea/workflows/build-pr.yaml deleted file mode 100644 index 90aad01..0000000 --- a/.gitea/workflows/build-pr.yaml +++ /dev/null @@ -1,14 +0,0 @@ -name: PR Builder -run-name: ${{ gitea.actor }} building PR -on: [pull_request] - -jobs: - Build-PR: - runs-on: ubuntu-22.04 - steps: - - 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 "${{ 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/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml deleted file mode 100644 index e64cc3a..0000000 --- a/.gitea/workflows/build.yaml +++ /dev/null @@ -1,16 +0,0 @@ -name: Builder -run-name: ${{ gitea.actor }} building -on: - push: - branches: - - main - -jobs: - Build-Project: - 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: | - 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 - - run: echo "This job's status is ${{ job.status }}." diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index 8895dd4..0000000 --- a/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2007-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import java.io.*; -import java.net.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is - * provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl - * property to use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download - * url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a - // custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if (mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if (mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if (!outputFile.getParentFile().exists()) { - if (!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index c1dd12f..0000000 Binary files a/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 8c79a83..0000000 --- a/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,18 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/pfs-intra.eml b/pfs-intra.eml new file mode 100644 index 0000000..238063b --- /dev/null +++ b/pfs-intra.eml @@ -0,0 +1,539 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/primefactorsolutions/model/Actividad.java b/src/main/java/com/primefactorsolutions/model/Actividad.java deleted file mode 100644 index 6b0a4b1..0000000 --- a/src/main/java/com/primefactorsolutions/model/Actividad.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.primefactorsolutions.model; - -public final class Actividad { - private String nombre; - private double lunes; - private double martes; - private double miercoles; - private double jueves; - private double viernes; - private double sabado; - private double domingo; - private String tarea; - private double horas; - - public Actividad(final Builder builder) { - this.nombre = builder.nombre; - this.lunes = builder.lunes; - this.martes = builder.martes; - this.miercoles = builder.miercoles; - this.jueves = builder.jueves; - this.viernes = builder.viernes; - this.sabado = builder.sabado; - this.domingo = builder.domingo; - this.tarea = builder.tarea; - this.horas = builder.horas; - } - - public String getNombre() { - return nombre; - } - - public double getLunes() { - return lunes; - } - - public double getMartes() { - return martes; - } - - public double getMiercoles() { - return miercoles; - } - - public double getJueves() { - return jueves; - } - - public double getViernes() { - return viernes; - } - - public double getSabado() { - return sabado; - } - - public double getDomingo() { - return domingo; - } - - public String getTarea() { // Cambié aquí también - return tarea; - } - - public double getHoras() { - return horas; - } - - // Builder para crear instancias de Actividad - public static class Builder { - private String nombre; - private double lunes; - private double martes; - private double miercoles; - private double jueves; - private double viernes; - private double sabado; - private double domingo; - private String tarea; // Cambié 'tarea' por 'descripcion' - private double horas; - - public Builder tarea(final String tarea, final double horas) { - this.tarea = tarea; - this.horas = horas; - return this; - } - - public Builder tarea(final String tarea) { - this.tarea = tarea; - return this; - } - - public Builder nombre(final String nombre) { - this.nombre = nombre; - return this; - } - - public Builder lunes(final double horas) { - this.lunes = horas; - return this; - } - - public Builder martes(final double horas) { - this.martes = horas; - return this; - } - - public Builder miercoles(final double horas) { - this.miercoles = horas; - return this; - } - - public Builder jueves(final double horas) { - this.jueves = horas; - return this; - } - - public Builder viernes(final double horas) { - this.viernes = horas; - return this; - } - - public Builder sabado(final double horas) { - this.sabado = horas; - return this; - } - - public Builder domingo(final double horas) { - this.domingo = horas; - return this; - } - - public Actividad build() { - return new Actividad(this); - } - } -} diff --git a/src/main/java/com/primefactorsolutions/model/Employee.java b/src/main/java/com/primefactorsolutions/model/Employee.java index 1d3df41..f4d3236 100644 --- a/src/main/java/com/primefactorsolutions/model/Employee.java +++ b/src/main/java/com/primefactorsolutions/model/Employee.java @@ -28,36 +28,42 @@ public class Employee extends BaseEntity implements UserDetails { @Pattern(regexp = "^[a-zA-Z ]+$", message = "El apellido solo debe contener letras") private String lastName; private LocalDate birthday; - @Pattern(regexp = "^[a-zA-Z ]+$", message = "La ciudad de nacimiento solo debe contener letras") + @Pattern(regexp = "^[a-zA-Z ,]+$", message = "La ciudad de nacimiento solo debe contener letras, espacios o comas") private String birthCity; private String age; - @Size(max = 100, message = "La dirección de residencia no debe exceder 100 caracteres") + @Size(max = 50, message = "La dirección de residencia no debe exceder 50 caracteres") private String residenceAddress; - @Size(max = 100, message = "La dirección local no debe exceder 100 caracteres") + @Size(max = 30, message = "La dirección local no debe exceder 100 caracteres") + @Pattern(regexp = "^[a-zA-Z -]+$", message = "La dirección local solo debe contener letras y guion") private String localAddress; @Pattern(regexp = "^[0-9]+$", message = "El número de teléfono debe contener solo números") private String phoneNumber; @Email(message = "El correo personal no tiene un formato válido") private String personalEmail; + @Pattern(regexp = "^[a-zA-Z ]+$", message = "El cargo solo debe contener letras") private String position; @ManyToOne @JoinColumn(name = "team_id", nullable = false) private Team team; - @Size(max = 100, message = "El nombre de contacto de emergencia no debe exceder 100 caracteres") + + @Pattern(regexp = "^[a-zA-Z ]+$", message = "El nombre y apellido de contacto" + + " de emergencia solo debe contener letras") private String emergencyCName; - @Size(max = 100, message = "La dirección de contacto de emergencia no debe exceder 100 caracteres") private String emergencyCAddress; - @Pattern(regexp = "^[0-9]+$", message = "El teléfono de contacto de emergencia debe contener solo números") + @Pattern(regexp = "^[0-9]+$", message = "El teléfono de contacto de emergencia " + + " debe contener solo números") private String emergencyCPhone; @Email(message = "El correo de contacto de emergencia no tiene un formato válido") private String emergencyCEmail; + + @Max(value = 10, message = "El número de hijos no puede exceder a 10") @Pattern(regexp = "^[0-9]+$", message = "La cantidad de hijos debe contener solo números") private String numberOfChildren; + @Pattern(regexp = "^[0-9]+$", message = "El CI debe contener solo números") private String ci; private String issuedIn; - @Size(max = 100, message = "El título no debe exceder 100 caracteres") private String pTitle1; private String pTitle2; private String pTitle3; @@ -70,9 +76,7 @@ public class Employee extends BaseEntity implements UserDetails { private String certification2; private String certification3; private String certification4; - @Size(max = 255, message = "El reconocimiento no debe exceder 255 caracteres") private String recognition; - @Size(max = 500, message = "Los logros no deben exceder 500 caracteres") private String achievements; private String language; diff --git a/src/main/java/com/primefactorsolutions/model/HoursWorked.java b/src/main/java/com/primefactorsolutions/model/HoursWorked.java index d02310f..560a6eb 100644 --- a/src/main/java/com/primefactorsolutions/model/HoursWorked.java +++ b/src/main/java/com/primefactorsolutions/model/HoursWorked.java @@ -1,41 +1,42 @@ package com.primefactorsolutions.model; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; -import java.util.UUID; +import java.time.LocalDate; +@Data @Entity +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) public class HoursWorked extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.UUID) - private UUID id; - @ManyToOne + @JoinColumn(name = "employee_id", nullable = true) private Employee employee; + @ManyToOne + @JoinColumn(name = "team_id", nullable = true) + private Team team; + private int weekNumber; + private LocalDate date; + private String actividad; + private String tareasEspecificas; + private double hours; + private double horasTareasEspecificas; + private double horaspendientes; private double totalHours; - public HoursWorked() { } - - public UUID getId() { - return id; - } - - public void setId(final UUID id) { - this.id = id; - } - public Employee getEmployee() { return employee; } - public void setEmployee(final Employee value) { - this.employee = value; + public void setEmployee(final Employee employee) { + this.employee = employee; } public int getWeekNumber() { @@ -46,6 +47,30 @@ public class HoursWorked extends BaseEntity { this.weekNumber = weekNumber; } + public LocalDate getDate() { + return date; + } + + public void setDate(final LocalDate date) { + this.date = date; + } + + public String getActividad() { + return actividad; + } + + public void setActividad(final String actividad) { + this.actividad = actividad; + } + + public double getHours() { + return hours; + } + + public void setHours(final double hours) { + this.hours = hours; + } + public double getTotalHours() { return totalHours; } @@ -53,4 +78,29 @@ public class HoursWorked extends BaseEntity { public void setTotalHours(final double totalHours) { this.totalHours = totalHours; } + + public Team getTeam() { + return team; + } + + public void setTeam(final Team team) { + this.team = team; + } + + public String getTareasEspecificas() { + return tareasEspecificas; + } + + public void setTareasEspecificas(final String tareasEspecificas) { + this.tareasEspecificas = tareasEspecificas; + } + + public double getHorasTareasEspecificas() { + return horasTareasEspecificas; + } + + public void setHorasTareasEspecificas(final double horasTareasEspecificas) { + this.tareasEspecificas = tareasEspecificas; + } } + diff --git a/src/main/java/com/primefactorsolutions/repositories/EmployeeRepository.java b/src/main/java/com/primefactorsolutions/repositories/EmployeeRepository.java index d57397f..3f09154 100644 --- a/src/main/java/com/primefactorsolutions/repositories/EmployeeRepository.java +++ b/src/main/java/com/primefactorsolutions/repositories/EmployeeRepository.java @@ -11,7 +11,7 @@ public interface EmployeeRepository extends JpaRepository { Optional findByUsername(String username); Optional findByPersonalEmail(String personalEmail); - Optional findByTeamId(UUID teamId); + Optional findByTeamIdAndLeadManagerTrue(UUID teamId); List findByTeamName(String teamName); } diff --git a/src/main/java/com/primefactorsolutions/repositories/HoursWorkedRepository.java b/src/main/java/com/primefactorsolutions/repositories/HoursWorkedRepository.java index 6e0e69c..06d8552 100644 --- a/src/main/java/com/primefactorsolutions/repositories/HoursWorkedRepository.java +++ b/src/main/java/com/primefactorsolutions/repositories/HoursWorkedRepository.java @@ -2,13 +2,13 @@ package com.primefactorsolutions.repositories; import com.primefactorsolutions.model.HoursWorked; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; +import java.time.LocalDate; import java.util.List; +import java.util.UUID; -@Repository -public interface HoursWorkedRepository extends JpaRepository { - // Puedes definir consultas personalizadas aquí si es necesario. + +public interface HoursWorkedRepository extends JpaRepository { List findByWeekNumber(int weekNumber); - -} + List findByDate(LocalDate date); +} \ No newline at end of file diff --git a/src/main/java/com/primefactorsolutions/service/EmployeeService.java b/src/main/java/com/primefactorsolutions/service/EmployeeService.java index 52c15dd..646278a 100644 --- a/src/main/java/com/primefactorsolutions/service/EmployeeService.java +++ b/src/main/java/com/primefactorsolutions/service/EmployeeService.java @@ -50,7 +50,7 @@ public class EmployeeService { public String getTeamLeadName(final UUID teamId) { // Encuentra al empleado con el rol de lead_manager en el equipo especificado - Optional leadManager = employeeRepository.findByTeamId(teamId); + Optional leadManager = employeeRepository.findByTeamIdAndLeadManagerTrue(teamId); return leadManager.map(employee -> employee.getFirstName() + " " + employee.getLastName()) .orElse("No asignado"); diff --git a/src/main/java/com/primefactorsolutions/service/HoursWorkedService.java b/src/main/java/com/primefactorsolutions/service/HoursWorkedService.java index 2bfe882..dc1b220 100644 --- a/src/main/java/com/primefactorsolutions/service/HoursWorkedService.java +++ b/src/main/java/com/primefactorsolutions/service/HoursWorkedService.java @@ -2,10 +2,12 @@ package com.primefactorsolutions.service; import com.primefactorsolutions.model.HoursWorked; import com.primefactorsolutions.repositories.HoursWorkedRepository; +import org.apache.commons.beanutils.BeanComparator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.List; +import java.time.LocalDate; +import java.util.*; @Service public class HoursWorkedService { @@ -20,6 +22,12 @@ public class HoursWorkedService { return hoursWorkedRepository.findAll(); } + public HoursWorked findHoursWorked(final UUID id) { + Optional hoursWorked = hoursWorkedRepository.findById(id); + HoursWorked hw = hoursWorked.get(); + return hw; + } + public HoursWorked saveHoursWorked(final HoursWorked hoursWorked) { return hoursWorkedRepository.save(hoursWorked); } @@ -28,13 +36,42 @@ public class HoursWorkedService { return hoursWorkedRepository.save(hoursWorked); } - public void deleteHoursWorked(final Long id) { - hoursWorkedRepository.deleteById(id); - } - public List findByWeekNumber(final int weekNumber) { return hoursWorkedRepository.findByWeekNumber(weekNumber); } -} + public List findByDate(final LocalDate date) { + return hoursWorkedRepository.findByDate(date); + } + public List findByDateAndWeekNumber(final LocalDate date, final int weekNumber) { + return hoursWorkedRepository.findByDate(date); + } + + public List findHoursWorkeds( + final int start, final int pageSize, final String sortProperty, final boolean asc) { + List hoursWorkeds = hoursWorkedRepository.findAll(); + + int end = Math.min(start + pageSize, hoursWorkeds.size()); + hoursWorkeds.sort(new BeanComparator<>(sortProperty)); + + if (!asc) { + Collections.reverse(hoursWorkeds); + } + + return hoursWorkeds.subList(start, end); + } + + public List findHoursWorkeds(final int start, final int pageSize) { + List hoursWorkeds = hoursWorkedRepository.findAll(); + + int end = Math.min(start + pageSize, hoursWorkeds.size()); + return hoursWorkeds.subList(start, end); + } + + public HoursWorked getHoursWorked(final UUID id) { + final Optional hoursWorked = hoursWorkedRepository.findById(id); + return hoursWorked.get(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/primefactorsolutions/views/EmployeeView.java b/src/main/java/com/primefactorsolutions/views/EmployeeView.java index 35b99ad..4e34abb 100644 --- a/src/main/java/com/primefactorsolutions/views/EmployeeView.java +++ b/src/main/java/com/primefactorsolutions/views/EmployeeView.java @@ -56,7 +56,6 @@ public class EmployeeView extends BeanValidationForm implements HasUrl private final TimeOffRequestService requestService; private final TeamService teamService; - // TODO: campo usado para registrar al empleado en LDAP. Este campo podria estar en otro form eventualmente. private final TextField username = createTextField("Username: ", 30, true); private final TextField firstName = createTextField("Nombres: ", 30, true); @@ -65,24 +64,21 @@ public class EmployeeView extends BeanValidationForm implements HasUrl private final ComboBox gender = createGenderComboBox(); private final VDatePicker birthday = new VDatePicker("Fecha de Nacimiento"); private final TextField age = createTextField("Edad", 3, false); - private final TextField birthCity = createTextField("Ciudad y País de Nacimiento", 20, false); + private final TextField birthCity = createTextField("Ciudad y País de Nacimiento ejemplo: (Ciudad, País) ", + 30, false); private final TextField residenceAddress = createTextField("Dirección de Residencia", 50, false); - private final TextField localAddress = createTextField("Dep/Provincia de Residencia", 10, false); + private final TextField localAddress = createTextField("Departamento y Provincia de Residencia " + + " ejemplo: (Departamento-Provincia)", 30, false); private final ComboBox maritalStatus = createMaritalStatusComboBox(); - private final TextField numberOfChildren = createTextField("Numero de Hijos", 3, false); - private final TextField ci = createTextField("CI", 30, false); - private final TextField issuedIn = createTextField("Expedido en ", 30, false); + private final TextField numberOfChildren = createTextField("Numero de Hijos", 2, false); + private final TextField ci = createTextField("CI", 10, false); + private final TextField issuedIn = createTextField("Expedido en ", 10, false); private final TextField phoneNumber = createTextField("Teléfono", 8, false); - private final EmailField personalEmail = createEmailField("E-mail"); - private final TextField cod = createTextField("Codigo de Empleado", 30, false); - private final TextField position = createTextField("Cargo", 30, false); - private final ComboBox team = new ComboBox<>("Equipo"); - private final TextField leadManager = createTextField("Lead/Manager", 30, false); - private final TextField project = createTextField("Proyecto", 30, false); + private final EmailField personalEmail = createEmailField("E-mail ejemplo: (ejemplo@gmail.com)"); private final TextField emergencyCName = createTextField("Nombres y Apellidos de Contacto", 50, false); private final TextField emergencyCAddress = createTextField("Dirección de Contacto", 50, false); private final TextField emergencyCPhone = createTextField("Teléfono de Contacto", 8, false); - private final EmailField emergencyCEmail = createEmailField("Email de Contacto"); + private final EmailField emergencyCEmail = createEmailField("Email de Contacto ejemplo: (ejemplo@gmail.com)"); private final MemoryBuffer buffer = new MemoryBuffer(); private final Upload upload = new Upload(buffer); @@ -101,10 +97,15 @@ public class EmployeeView extends BeanValidationForm implements HasUrl private final TextField certification4 = createTextField("Certificación 4", 30, false); private final TextField recognition = createTextField("Reconocimientos", 30, false); private final TextField achievements = createTextField("Logros Profesionales", 30, false); - private final TextField language = createTextField("Idioma", 30, false); + private final TextField language = createTextField("Idioma", 50, false); private final TextField languageLevel = createTextField("Nivel de Idioma", 30, false); - //INFORMACION DE CONTRATACION + //INFORMACION ADMINISTRATIVA + private final TextField cod = createTextField("Codigo de Empleado", 20, false); + private final TextField position = createTextField("Cargo", 30, false); + private final ComboBox team = new ComboBox<>("Equipo"); + private final TextField leadManager = createTextField("Lead/Manager", 30, false); + private final TextField project = createTextField("Proyecto", 30, false); private final VDatePicker dateOfEntry = new VDatePicker("Fecha de Ingreso"); private final VDatePicker dateOfExit = new VDatePicker("Fecha de Retiro"); private final TextField contractType = createTextField("Tipo de Contratación", 30, false); @@ -141,7 +142,7 @@ public class EmployeeView extends BeanValidationForm implements HasUrl //TITULOS PARA INFORMACIÓN ADMINISTRATIVA private final H2 infoAdm = new H2("Información Administrativa"); private final H3 infoCont = new H3("Información de Contratación"); - private final H3 datBanc = new H3("Datos Bancados"); + private final H3 datBanc = new H3("Datos Bancarios"); private final H3 datGest = new H3("Datos Gestora Pública y Seguro Social"); public EmployeeView(final EmployeeService employeeService, @@ -176,6 +177,9 @@ public class EmployeeView extends BeanValidationForm implements HasUrl editButton.setVisible(true); reportButton.setVisible(true); birthday.addValueChangeListener(event -> calculateAge()); + birthday.setMax(java.time.LocalDate.now()); + dateOfEntry.addValueChangeListener(event -> calculateSeniority()); + dateOfEntry.addValueChangeListener(event -> calculateSeniority()); reportButton.addClickListener((ComponentEventListener>) buttonClickEvent -> { var employee = getEntity(); @@ -203,10 +207,30 @@ public class EmployeeView extends BeanValidationForm implements HasUrl int birthYear = birthday.getValue().getYear(); int ages = currentYear - birthYear; age.setValue(String.valueOf(ages)); + if (ages < 18) { + birthday.setInvalid(true); + birthday.setErrorMessage("La edad no puede ser menor a 18 años."); + Notification.show("La edad ingresada no es válida, debe ser mayor o igual a 18 años."); + } else { + birthday.setInvalid(false); + } System.out.println(age); } } + private void calculateSeniority() { + LocalDate entryDate = dateOfEntry.getValue(); + LocalDate exitDate = dateOfExit.getValue() != null ? dateOfExit.getValue() : LocalDate.now(); + + if (entryDate != null) { + long yearsOfService = ChronoUnit.YEARS.between(entryDate, exitDate); + String seniorityValue = yearsOfService + " años "; + seniority.setValue(seniorityValue); + } else { + seniority.setValue("No disponible"); + } + } + private void configureUpload() { upload.setAcceptedFileTypes("image/jpeg", "image/png"); upload.setMaxFileSize(1024 * 1024); @@ -218,11 +242,15 @@ public class EmployeeView extends BeanValidationForm implements HasUrl getEntity().setProfileImage(base64Image); - profileImagePreview.setSrc("data:image/jpeg;base64," + base64Image); + profileImagePreview.setSrc("data:image/png;base64," + base64Image); profileImagePreview.setMaxWidth("150px"); profileImagePreview.setMaxHeight("150px"); } catch (IOException e) { - Notification.show("Error al subir la imagen."); + Notification.show("Error al subir la imagen: " + e.getMessage()); + e.printStackTrace(); + } catch (Exception e) { + Notification.show("Error en el servidor al procesar la imagen."); + e.printStackTrace(); } }); } @@ -393,12 +421,12 @@ public class EmployeeView extends BeanValidationForm implements HasUrl if (employee.getProfileImage() != null && !employee.getProfileImage().isEmpty()) { profileImagePreview.setSrc("data:image/jpeg;base64," + employee.getProfileImage()); profileImagePreview.setVisible(true); - profileImagePreview.setMaxWidth("150px"); - profileImagePreview.setMaxHeight("150px"); + profileImagePreview.setMaxWidth("250px"); + profileImagePreview.setMaxHeight("250px"); - upload.setVisible(false); + upload.setVisible(true); } else { - profileImagePreview.setVisible(false); + profileImagePreview.setVisible(true); upload.setVisible(true); } } @@ -478,6 +506,7 @@ public class EmployeeView extends BeanValidationForm implements HasUrl emergencyCPhone.setReadOnly(false); emergencyCEmail.setReadOnly(false); upload.setVisible(false); + profileImagePreview.setVisible(true); age.setReadOnly(false); gender.setReadOnly(false); status.setReadOnly(false); @@ -525,7 +554,6 @@ public class EmployeeView extends BeanValidationForm implements HasUrl birthCity, residenceAddress, localAddress, maritalStatus, ci, issuedIn, numberOfChildren, phoneNumber, personalEmail, - cod, position, team, leadManager, project, contEmerg, emergencyCName, emergencyCAddress, emergencyCPhone, emergencyCEmail, infProf, titulos, pTitle1, pTitle2, pTitle3, pStudy1, pStudy2, pStudy3, @@ -533,6 +561,7 @@ public class EmployeeView extends BeanValidationForm implements HasUrl logros, recognition, achievements, idioma, language, languageLevel, infoAdm, + cod, position, team, leadManager, project, infoCont, dateOfEntry, dateOfExit, contractType, seniority, salary, datBanc, bankName, accountNumber, datGest, gpss, sss, beneficiaries, diff --git a/src/main/java/com/primefactorsolutions/views/HoursWorkedListView.java b/src/main/java/com/primefactorsolutions/views/HoursWorkedListView.java new file mode 100644 index 0000000..26def46 --- /dev/null +++ b/src/main/java/com/primefactorsolutions/views/HoursWorkedListView.java @@ -0,0 +1,211 @@ +package com.primefactorsolutions.views; + +import com.primefactorsolutions.model.Employee; +import com.primefactorsolutions.model.Team; +import com.primefactorsolutions.service.EmployeeService; +import com.primefactorsolutions.service.HoursWorkedService; +import com.primefactorsolutions.service.TeamService; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.combobox.ComboBox; +import com.vaadin.flow.component.html.Main; +import com.vaadin.flow.component.notification.Notification; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.spring.annotation.SpringComponent; +import jakarta.annotation.security.PermitAll; +import org.springframework.context.annotation.Scope; +import org.vaadin.firitin.components.grid.PagingGrid; + +import java.util.*; +import java.util.stream.Collectors; + +@SpringComponent +@PermitAll +@Scope("prototype") +@PageTitle("Registro de Horas Trabajadas") +@Route(value = "/hours-worked-list", layout = MainLayout.class) +public class HoursWorkedListView extends Main { + + private final HoursWorkedService hoursWorkedService; + private final EmployeeService employeeService; + private final TeamService teamService; + private final PagingGrid hoursWorkedGrid = new PagingGrid<>(); + private final PagingGrid table = new PagingGrid<>(Employee.class); + private List employees = Collections.emptyList(); + private ComboBox employeeFilter; + private ComboBox teamFilter; + private UUID selectedEmployeeId; + + + public HoursWorkedListView(final HoursWorkedService hoursWorkedService, + final EmployeeService employeeService, + final TeamService teamService) { + this.hoursWorkedService = hoursWorkedService; + this.employeeService = employeeService; + this.teamService = teamService; + this.employees = employeeService.findAllEmployees(); + + initializeView(); + refreshGridListHoursWorked(null, null); + } + + private void refreshGridListHoursWorked(final Employee employee, + final Team team) { + hoursWorkedGrid.setPagingDataProvider((page, pageSize) -> { + int start = (int) (page * hoursWorkedGrid.getPageSize()); + return fetchFilteredEmployees(start, pageSize, employee, team); + }); + hoursWorkedGrid.getDataProvider().refreshAll(); + } + + private List fetchFilteredEmployees(final int start, + final int pageSize, + final Employee employee, + final Team team) { + List filteredEmployees = employeeService.findAllEmployees(); + + if (employee != null && !"TODOS".equals(employee.getFirstName())) { + filteredEmployees = filteredEmployees.stream() + .filter(emp -> emp.getId().equals(employee.getId())) + .collect(Collectors.toList()); + } + + if (team != null && !"TODOS".equals(team.getName())) { + filteredEmployees = filteredEmployees.stream() + .filter(emp -> emp.getTeam() != null && emp.getTeam().getId().equals(team.getId())) + .collect(Collectors.toList()); + } + + int end = Math.min(start + pageSize, filteredEmployees.size()); + return filteredEmployees.subList(start, end); + } + + private void initializeView() { + setupFilters(); + add(createAddHoursWorked()); + setupListHoursWorkedGrid(); + add(hoursWorkedGrid); + add(createActionButtons()); + } + + private void setupFilters() { + add(createEmployeeFilter()); + add(createTeamFilter()); + } + + private void setupListHoursWorkedGrid() { + hoursWorkedGrid.addColumn(this::getEmployeeFullName).setHeader("Empleado"); + hoursWorkedGrid.addColumn(this::getTeamName).setHeader("Equipo"); + + hoursWorkedGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM); + hoursWorkedGrid.setPageSize(5); + hoursWorkedGrid.asSingleSelect().addValueChangeListener(event -> { + Employee selectedRequest = event.getValue(); + if (selectedRequest != null) { + selectedEmployeeId = selectedRequest.getId(); + } + }); + } + + private String getTeamName(final Employee employee) { + Team team = employee.getTeam(); + return team != null ? team.getName() : "Sin asignar"; + } + + private String getTeamLabel(final Team team) { + return "TODOS".equals(team.getName()) ? "TODOS" : team.getName(); + } + + + private HorizontalLayout createActionButtons() { + Button viewButton = new Button("Ver", event -> { + if (selectedEmployeeId != null) { + navigateToHoursWorkedView(selectedEmployeeId); + } else { + Notification.show("Seleccione una solicitud.", 3000, Notification.Position.MIDDLE); + } + }); + Button closeButton = new Button("Salir", event -> navigateToListView()); + return new HorizontalLayout(viewButton, closeButton); + } + + private void navigateToListView() { + getUI().ifPresent(ui -> ui.navigate(MainView.class)); + } + + private void navigateToHoursWorkedView(final UUID idEmployee) { + getUI().ifPresent(ui -> ui.navigate("hours-worked-list/" + idEmployee.toString())); + } + + private Button createButton(final String label, final Runnable onClickAction) { + Button button = new Button(label); + button.addClickListener(event -> onClickAction.run()); + return button; + } + + private Button createAddHoursWorked() { + return createButton("Agregar Actividad", this::navigateToHours); + } + + private void navigateToHours() { + getUI().ifPresent(ui -> ui.navigate(HoursWorkedView.class, "new")); + } + + private ComboBox createEmployeeFilter() { + employeeFilter = new ComboBox<>("Empleado"); + List employees = new ArrayList<>(employeeService.findAllEmployees()); + employees.addFirst(createAllEmployeesOption()); + employeeFilter.setItems(employees); + employeeFilter.setItemLabelGenerator(this::getEmployeeFullName); + employeeFilter.setValue(employees.getFirst()); + employeeFilter.addValueChangeListener(event -> + refreshGridListHoursWorked( + event.getValue(), + teamFilter.getValue() + ) + ); + return employeeFilter; + } + + private String getEmployeeFullName(final Employee employee) { + return "TODOS".equals(employee.getFirstName()) + ? "TODOS" : employee.getFirstName() + " " + employee.getLastName(); + } + + private ComboBox createTeamFilter() { + teamFilter = new ComboBox<>("Equipo"); + List teams = new ArrayList<>(teamService.findAllTeams()); + teams.addFirst(createAllTeamsOption()); + teamFilter.setItems(teams); + teamFilter.setItemLabelGenerator(this::getTeamLabel); + teamFilter.setValue(teams.getFirst()); + teamFilter.addValueChangeListener(event -> + refreshGridListHoursWorked( + employeeFilter.getValue(), + event.getValue() + ) + ); + return teamFilter; + } + + + private Employee createAllEmployeesOption() { + Employee allEmployeesOption = new Employee(); + allEmployeesOption.setFirstName("TODOS"); + return allEmployeesOption; + } + + private Team createAllTeamsOption() { + Team allTeamsOption = new Team(); + allTeamsOption.setName("TODOS"); + return allTeamsOption; + } + + + private void setupPagingGrid() { + table.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM); + table.setPageSize(5); + } + +} diff --git a/src/main/java/com/primefactorsolutions/views/HoursWorkedMonthView.java b/src/main/java/com/primefactorsolutions/views/HoursWorkedMonthView.java deleted file mode 100644 index 88d86e6..0000000 --- a/src/main/java/com/primefactorsolutions/views/HoursWorkedMonthView.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.primefactorsolutions.views; - -import com.primefactorsolutions.model.Employee; -import com.primefactorsolutions.model.Actividad; -import com.primefactorsolutions.service.EmployeeService; -import com.vaadin.flow.component.button.Button; -import com.vaadin.flow.component.combobox.ComboBox; -import com.vaadin.flow.component.datepicker.DatePicker; -import com.vaadin.flow.component.grid.Grid; -import com.vaadin.flow.component.html.Label; -import com.vaadin.flow.component.notification.Notification; -import com.vaadin.flow.component.orderedlayout.HorizontalLayout; -import com.vaadin.flow.component.orderedlayout.VerticalLayout; -import com.vaadin.flow.router.PageTitle; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.spring.annotation.SpringComponent; -import jakarta.annotation.security.PermitAll; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; - -import java.time.LocalDate; -import java.util.List; - -@SpringComponent -@PermitAll -@Scope("prototype") -@PageTitle("Hours Worked Month") -@Route(value = "/hours-worked-month/me", layout = MainLayout.class) -public class HoursWorkedMonthView extends VerticalLayout { - private final EmployeeService employeeService; - private final ComboBox employeeComboBox = new ComboBox<>("Empleado"); - private final ComboBox equipoDropdown = new ComboBox<>("Equipo"); - private final Grid grid = new Grid<>(Actividad.class); - - private final Label totalCompletadoLabel = new Label(); - private final Label horasPendientesLabel = new Label(); - private final Label totalAcumuladasLabel = new Label(); - private final Label horasAdeudadasLabel = new Label(); - private final Button actualizarButton = new Button("Actualizar"); - private final Button guardarButton = new Button("Guardar"); - private final Button cerrarButton = new Button("Cerrar"); - - private LocalDate selectedMonth; - - @Autowired - public HoursWorkedMonthView(final EmployeeService employeeService) { - this.employeeService = employeeService; - configurarVista(); - } - - private void configurarVista() { - DatePicker monthPicker = new DatePicker("Selecciona un mes"); - monthPicker.setValue(LocalDate.now()); - monthPicker.addValueChangeListener(event -> { - selectedMonth = event.getValue().withDayOfMonth(1); - //cargarDatosMes(selectedMonth); - }); - - equipoDropdown.setItems("Equipo 1", "Equipo 2", "Equipo 3"); - equipoDropdown.setWidth("250px"); - - setEmployeeComboBoxProperties(); - - configurarGrid(); - - actualizarButton.addClickListener(event -> actualizarDatos()); - guardarButton.addClickListener(event -> guardarActividades()); - cerrarButton.addClickListener(event -> closeView()); - - HorizontalLayout headerLayout = new HorizontalLayout(monthPicker, equipoDropdown, employeeComboBox); - add( - headerLayout, grid, totalCompletadoLabel, - horasPendientesLabel, totalAcumuladasLabel, - horasAdeudadasLabel, actualizarButton, - guardarButton, cerrarButton); - } - - private void setEmployeeComboBoxProperties() { - employeeComboBox.setWidth("250px"); - employeeComboBox.setPlaceholder("Buscar empleado..."); - employeeComboBox.setItems(employeeService.findAllEmployees()); - employeeComboBox.setItemLabelGenerator(employee -> employee.getFirstName() + " " + employee.getLastName()); - } - - private void configurarGrid() { - grid.removeAllColumns(); - grid.addColumn(Actividad::getLunes).setHeader("Lunes"); - grid.addColumn(Actividad::getMartes).setHeader("Martes"); - grid.addColumn(Actividad::getMiercoles).setHeader("Miércoles"); - grid.addColumn(Actividad::getJueves).setHeader("Jueves"); - grid.addColumn(Actividad::getViernes).setHeader("Viernes"); - grid.addColumn(Actividad::getSabado).setHeader("Sábado"); - grid.addColumn(Actividad::getDomingo).setHeader("Domingo"); - grid.addColumn(this::calcularTotalPorDia).setHeader("Total Semanal").setKey("totalSemanal"); - } - -// 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); -// } - -// 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(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(); - } - - private double calcularHorasPendientes(final double totalCompletado) { - return 40 - totalCompletado; - } - - private void actualizarDatos() { - Notification.show("Datos actualizados."); - } - - private void guardarActividades() { - Notification.show("Actividades guardadas correctamente."); - } - - private void closeView() { - getUI().ifPresent(ui -> ui.navigate("")); - } -} diff --git a/src/main/java/com/primefactorsolutions/views/HoursWorkedView.java b/src/main/java/com/primefactorsolutions/views/HoursWorkedView.java index 7c1f644..c325795 100644 --- a/src/main/java/com/primefactorsolutions/views/HoursWorkedView.java +++ b/src/main/java/com/primefactorsolutions/views/HoursWorkedView.java @@ -1,419 +1,246 @@ package com.primefactorsolutions.views; -import com.primefactorsolutions.model.Actividad; import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.model.HoursWorked; +import com.primefactorsolutions.model.Team; import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.HoursWorkedService; -import com.vaadin.flow.component.datepicker.DatePicker; -import com.vaadin.flow.component.grid.Grid; +import com.primefactorsolutions.service.TeamService; +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.html.H2; +import com.vaadin.flow.component.html.Label; import com.vaadin.flow.component.notification.Notification; -import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.combobox.ComboBox; -import com.vaadin.flow.component.orderedlayout.VerticalLayout; -import com.vaadin.flow.router.PageTitle; -import com.vaadin.flow.router.Route; +import com.vaadin.flow.router.*; import com.vaadin.flow.spring.annotation.SpringComponent; import jakarta.annotation.security.PermitAll; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Scope; -import com.vaadin.flow.component.html.Label; -import org.springframework.web.servlet.HandlerMapping; -import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.vaadin.firitin.components.datepicker.VDatePicker; +import org.vaadin.firitin.form.BeanValidationForm; - -import java.time.DayOfWeek; import java.time.LocalDate; -import java.time.temporal.IsoFields; -import java.time.temporal.WeekFields; +import java.time.YearMonth; import java.util.ArrayList; import java.util.List; -import java.util.Locale; +import java.util.UUID; @SpringComponent @PermitAll @Scope("prototype") -@PageTitle("Hours Worked") -@Route(value = "/hours-worked/me", layout = MainLayout.class) -public class HoursWorkedView extends VerticalLayout { - private final List actividades = new ArrayList<>(); - private final List actividadesEspecificas = new ArrayList<>(); // Nueva lista para tareas específicas - private final Grid grid = new Grid<>(Actividad.class); - private final Grid gridActividadesEspecificas = new Grid<>(Actividad.class); +@PageTitle("Horas Trabajadas") +@Route(value = "/hours-worked-list/:hours-workedId?/:action?", layout = MainLayout.class) +public class HoursWorkedView extends BeanValidationForm implements HasUrlParameter { + private final VDatePicker dateField = new VDatePicker("Fecha"); + private final ComboBox teamField = new ComboBox<>("Equipo"); + private ComboBox employeeField; + private final ComboBox tareasEspecificasDropdown = new ComboBox<>("Tarea Específica"); + private final TextField tareaEspecificaInput = new TextField("Otra Tarea Específica"); + private final TextField horasTareaEspecificaField = new TextField("Horas Tarea Específica"); + private final TextField activityField = new TextField("Actividad"); + private final TextField hoursField = new TextField("Horas"); - private final ComboBox employeeComboBox = new ComboBox<>("Employee"); - private final ComboBox equipoDropdown = new ComboBox<>("Equipo"); - - private final ComboBox tareasEspecificasDropdown = new ComboBox<>("Tareas Específicas"); - private final TextField tareaEspecificaInput = new TextField("Especificar Tarea"); - private TextField horasTareaInput = crearCampoHora("Horas Tareas"); - - private LocalDate selectedStartOfWeek; - private int weekNumber; - - @Autowired - private final EmployeeService employeeService; - @Autowired - private final HoursWorkedService hoursWorkedService; - - private final Label fechasLabel = new Label("Selecciona una semana para ver las fechas."); + private final H2 equipoLabel = new H2("Tareas del Cliente/Equipo"); + private final H2 empresaLabel = new H2("Tareas de la Empresa"); private final Label totalCompletadoLabel = new Label(); - private final Label horasPendientesLabel = new Label(); - private final Label numeroSemanaLabel = new Label("Número de la Semana: "); + private final HoursWorkedService hoursWorkedService; + private final EmployeeService employeeService; + private final TeamService teamService; + private HoursWorked hoursWorked; + private Employee employee; - private DatePicker fechaPicker = new DatePicker("Selecciona una fecha"); - @Autowired - private InternalResourceViewResolver defaultViewResolver; - @Qualifier("defaultServletHandlerMapping") - @Autowired - private HandlerMapping defaultServletHandlerMapping; + private Button saveButton; - - public HoursWorkedView(final EmployeeService employeeService, final HoursWorkedService hoursWorkedService) { - this.employeeService = employeeService; + public HoursWorkedView(final HoursWorkedService hoursWorkedService, + final EmployeeService employeeService, + final TeamService teamService) { + super(HoursWorked.class); this.hoursWorkedService = hoursWorkedService; - configurarVista(); - configurarGrid(); - configurarGridActividadesEspecificas(); - cargarDatos(); - configurarTareasEspecificas(); + this.employeeService = employeeService; + this.teamService = teamService; + + initializeDateField(); + initializeTeamField(); + initializeEmployeeField(); + configureTareasEspecificas(); + } - private void configurarTareasEspecificas() { - tareasEspecificasDropdown.setItems("Entrevistas", "Reuniones", "Colaboraciones", - "Aprendizajes", "Proyectos PFS", "Otros"); + @Override + public void setParameter(final BeforeEvent beforeEvent, final String action) { + final RouteParameters params = beforeEvent.getRouteParameters(); + final String s = params.get("hours-workedId").orElse(null); + + if ("new".equals(action)) { + setEntityWithEnabledSave(new HoursWorked()); + } else { + UUID hoursWorkedId = UUID.fromString(s); + var hoursWorked = hoursWorkedService.getHoursWorked(hoursWorkedId); + setEntityWithEnabledSave(hoursWorked); + + if ("edit".equals(action) && !s.isEmpty()) { + saveButton.setVisible(true); + } else if ("view".equals(action) && !s.isEmpty()) { + saveButton.setVisible(false); + } + } + } + + @Override + protected List getFormComponents() { + return List.of( + dateField, + teamField, + employeeField, + equipoLabel, + activityField, + hoursField, + empresaLabel, + tareasEspecificasDropdown, + tareaEspecificaInput, + horasTareaEspecificaField, + createCloseButton() + ); + } + + private void configureTareasEspecificas() { + tareasEspecificasDropdown.setItems("Entrevistas", "Reuniones", + "Colaboraciones", "Aprendizajes", "Proyectos PFS", "Otros"); tareasEspecificasDropdown.setPlaceholder("Selecciona una tarea..."); tareasEspecificasDropdown.addValueChangeListener(event -> { String selected = event.getValue(); - // Activa el campo de texto si la opción seleccionada es "Otros" - tareaEspecificaInput.setVisible("Otros".equals(selected)); - if (!"Otros".equals(selected)) { + boolean isOtros = "Otros".equals(selected); + tareaEspecificaInput.setVisible(isOtros); + horasTareaEspecificaField.setVisible(true); + if (!isOtros) { tareaEspecificaInput.clear(); + horasTareaEspecificaField.clear(); } }); tareaEspecificaInput.setVisible(false); + horasTareaEspecificaField.setVisible(false); } - private void cargarDatos() { - if (selectedStartOfWeek != null && weekNumber > 0) { - actividades.clear(); - actividadesEspecificas.clear(); - List listaDeHorasTrabajadas = obtenerDatos(); - grid.setItems(actividades); - gridActividadesEspecificas.setItems(actividadesEspecificas); - calcularTotalHoras(listaDeHorasTrabajadas); - } + protected Button createSaveButton() { + saveButton = new Button("Guardar"); + saveButton.addClickListener(event -> saveHoursWorked()); + return saveButton; } - private void setEmployeeComboBoxProperties() { - employeeComboBox.setWidth("250px"); - employeeComboBox.setPlaceholder("Buscar empleado..."); - employeeComboBox.setItems(employeeService.findAllEmployees()); - employeeComboBox.setItemLabelGenerator(employee -> employee.getFirstName() + " " + employee.getLastName()); - employeeComboBox.setAllowCustomValue(false); - employeeComboBox.addCustomValueSetListener(event -> - Notification.show("Selecciona un empleado válido de la lista.") + protected Button createCloseButton() { + Button closeButton = new Button("Cerrar"); + closeButton.addClickListener(event -> closeForm()); + return closeButton; + } + + private void initializeTeamField() { + List teams = new ArrayList<>(teamService.findAllTeams()); + teamField.setItems(teamService.findAllTeams()); + teamField.setItemLabelGenerator(Team::getName); + teamField.setValue(teams.getFirst()); + teamField.addValueChangeListener(event -> { + if (teams != null) { + employeeField.getValue(); + event.getValue(); + } + } ); - - employeeComboBox.addValueChangeListener(event -> { - Employee selectedEmployee = event.getValue(); - if (selectedEmployee != null) { - Notification.show("Empleado seleccionado: " - + selectedEmployee.getFirstName() + " " - + selectedEmployee.getLastName()); - } - }); } - private int getWeekOfYear(final LocalDate date) { - return date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR); + private ComboBox initializeEmployeeField() { + employeeField = new ComboBox<>("Empleado"); + List employees = new ArrayList<>(employeeService.findAllEmployees()); + employeeField.setItems(employees); + employeeField.setItemLabelGenerator(this::getEmployeeFullName); + employeeField.setValue(employees.getFirst()); + return employeeField; } - private void configurarVista() { - fechaPicker.addValueChangeListener(event -> { - LocalDate selectedDate = event.getValue(); - if (selectedDate != null) { - selectedStartOfWeek = getStartOfWeek(selectedDate); - LocalDate endOfWeek = selectedStartOfWeek.plusDays(6); - weekNumber = getWeekOfYear(selectedDate); - fechasLabel.setText("Semana del " + selectedStartOfWeek + " al " + endOfWeek); - numeroSemanaLabel.setText("Número de la Semana: " + weekNumber); - cargarDatos(); - } - }); - - Button verMesButton = new Button("Ver Mes", event -> { - getUI().ifPresent(ui -> ui.navigate(HoursWorkedMonthView.class)); - }); - - equipoDropdown.setItems("ABC", "DEF", "XYZ"); - equipoDropdown.setWidth("250px"); - - equipoDropdown.addValueChangeListener(event -> { - String selectedEquipo = event.getValue(); - if (selectedEquipo != null) { - // Filtra la lista de empleados según el equipo seleccionado - List filteredEmployees = employeeService.findEmployeesByTeam(selectedEquipo); - employeeComboBox.setItems(filteredEmployees); - } - }); - - setEmployeeComboBoxProperties(); - - HorizontalLayout filtersLayout = new HorizontalLayout(equipoDropdown, employeeComboBox); - filtersLayout.setSpacing(true); - - HorizontalLayout actividadFormLayout = configurarFormularioActividades(); - HorizontalLayout tareasEspecificasLayout = configurarTareasEspecificasLayout(); - - - Button actualizarButton = new Button("Actualizar Totales", event -> actualizarTotales()); - Button guardarButton = new Button("Guardar", event -> guardarActividades()); - Button cerrarButton = new Button("Cerrar", event -> this.closeView()); - - HorizontalLayout buttonsLayout = new HorizontalLayout(actualizarButton, guardarButton, - cerrarButton, verMesButton); - - VerticalLayout totalesLayout = new VerticalLayout(totalCompletadoLabel, horasPendientesLabel); - totalesLayout.setSpacing(true); - totalesLayout.setPadding(true); - - add(fechaPicker, fechasLabel, numeroSemanaLabel, filtersLayout, actividadFormLayout, - tareasEspecificasLayout, grid, gridActividadesEspecificas, buttonsLayout, totalesLayout); + private String getEmployeeFullName(final Employee employee) { + return "TODOS".equals(employee.getFirstName()) + ? "TODOS" : employee.getFirstName() + " " + employee.getLastName(); } - private void configurarGrid() { - grid.removeAllColumns(); - grid.setItems(actividades); - grid.addColumn(Actividad::getNombre).setHeader("Actividad"); - grid.addColumn(Actividad::getLunes).setHeader("Lunes"); - grid.addColumn(Actividad::getMartes).setHeader("Martes"); - grid.addColumn(Actividad::getMiercoles).setHeader("Miércoles"); - grid.addColumn(Actividad::getJueves).setHeader("Jueves"); - grid.addColumn(Actividad::getViernes).setHeader("Viernes"); - grid.addColumn(Actividad::getSabado).setHeader("Sábado"); - grid.addColumn(Actividad::getDomingo).setHeader("Domingo"); - grid.addColumn(this::calcularTotalPorDia).setHeader("Total Día").setKey("totalDia"); + private void initializeDateField() { + LocalDate today = LocalDate.now(); + YearMonth currentMonth = YearMonth.of(today.getYear(), today.getMonth()); + + LocalDate startOfMonth = currentMonth.atDay(1); + + LocalDate maxSelectableDate = today; + + dateField.setMin(startOfMonth); + dateField.setMax(maxSelectableDate); + dateField.setValue(today); + + dateField.setLabel("Fecha"); } - private void configurarGridActividadesEspecificas() { - gridActividadesEspecificas.removeAllColumns(); - gridActividadesEspecificas.setItems(actividadesEspecificas); - gridActividadesEspecificas.addColumn(Actividad::getTarea).setHeader("Actividad"); - gridActividadesEspecificas.addColumn(Actividad::getLunes).setHeader("Lunes"); - gridActividadesEspecificas.addColumn(Actividad::getMartes).setHeader("Martes"); - gridActividadesEspecificas.addColumn(Actividad::getMiercoles).setHeader("Miércoles"); - gridActividadesEspecificas.addColumn(Actividad::getJueves).setHeader("Jueves"); - gridActividadesEspecificas.addColumn(Actividad::getViernes).setHeader("Viernes"); - gridActividadesEspecificas.addColumn(Actividad::getSabado).setHeader("Sábado"); - gridActividadesEspecificas.addColumn(Actividad::getDomingo).setHeader("Domingo"); - gridActividadesEspecificas.addColumn(this::calcularTotalPorDia).setHeader("Total Día Específico") - .setKey("totalDiaEspecifico"); - } - - private HorizontalLayout configurarFormularioActividades() { - TextField actividadNombre = new TextField("Actividad"); - actividadNombre.setWidth("200px"); - - TextField horasInput = crearCampoHora("Horas"); - - Button agregarActividadButton = new Button("Agregar Actividad", e -> { - try { - LocalDate selectedDate = fechaPicker.getValue(); - if (selectedDate == null) { - Notification.show("Por favor, selecciona una fecha."); - return; - } - DayOfWeek selectedDay = selectedDate.getDayOfWeek(); - - Actividad.Builder actividadBuilder = new Actividad.Builder() - .nombre(actividadNombre.getValue()); - - double horas = parseHoras(horasInput.getValue()); - switch (selectedDay) { - case MONDAY -> actividadBuilder.lunes(horas); - case TUESDAY -> actividadBuilder.martes(horas); - case WEDNESDAY -> actividadBuilder.miercoles(horas); - case THURSDAY -> actividadBuilder.jueves(horas); - case FRIDAY -> actividadBuilder.viernes(horas); - case SATURDAY -> actividadBuilder.sabado(horas); - case SUNDAY -> actividadBuilder.domingo(horas); - default -> throw new IllegalArgumentException("Día seleccionado no válido: " + selectedDay); - } - - String tareaSeleccionada = tareasEspecificasDropdown.getValue(); - double horasTarea = parseHoras(horasTareaInput.getValue()); - - if (tareaSeleccionada != null && !tareaSeleccionada.isEmpty()) { - actividadBuilder.tarea(tareaSeleccionada).lunes(horasTarea); - Actividad nuevaActividadEspecifica = actividadBuilder.build(); - actividadesEspecificas.add(nuevaActividadEspecifica); - gridActividadesEspecificas.setItems(actividadesEspecificas); - } else { - Actividad nuevaActividad = actividadBuilder.build(); - actividades.add(nuevaActividad); - grid.setItems(actividades); - } - actualizarTotales(); - Notification.show("Actividad agregada correctamente"); - actividadNombre.clear(); - horasInput.clear(); - tareasEspecificasDropdown.clear(); - horasTareaInput.clear(); - } catch (NumberFormatException ex) { - Notification.show("Error: Por favor ingresa números válidos para las horas."); - } - }); - - return new HorizontalLayout(actividadNombre, horasInput, agregarActividadButton); - } - - private HorizontalLayout configurarTareasEspecificasLayout() { - - Button agregarTareaButton = new Button("Agregar Tarea PFS", e -> { - try { - String tareaSeleccionada = tareasEspecificasDropdown.getValue(); - String tareaNombre = "Otros" - .equals(tareaSeleccionada) ? tareaEspecificaInput - .getValue() : tareaSeleccionada; - - if (tareaNombre == null || tareaNombre.isEmpty()) { - Notification.show("Por favor, especifica la tarea."); - return; - } - - double horasTarea = parseHoras(horasTareaInput.getValue()); - if (horasTarea <= 0) { - Notification.show("Por favor, ingresa un número válido para las horas."); - return; - } - - if (tareaSeleccionada != null && !tareaSeleccionada.isEmpty() && horasTarea > 0) { - LocalDate selectedDate = fechaPicker.getValue(); - if (selectedDate == null) { - Notification.show("Selecciona una fecha para asignar la tarea."); - return; - } - - DayOfWeek selectedDay = selectedDate.getDayOfWeek(); - Actividad.Builder actividadBuilder = new Actividad.Builder().tarea(tareaNombre); - - switch (selectedDay) { - case MONDAY -> actividadBuilder.lunes(horasTarea); - case TUESDAY -> actividadBuilder.martes(horasTarea); - case WEDNESDAY -> actividadBuilder.miercoles(horasTarea); - case THURSDAY -> actividadBuilder.jueves(horasTarea); - case FRIDAY -> actividadBuilder.viernes(horasTarea); - case SATURDAY -> actividadBuilder.sabado(horasTarea); - case SUNDAY -> actividadBuilder.domingo(horasTarea); - default -> throw new IllegalArgumentException("Día seleccionado no válido: " + selectedDay); - } - - Actividad nuevaActividadEspecifica = actividadBuilder.build(); - actividadesEspecificas.add(nuevaActividadEspecifica); - - gridActividadesEspecificas.setItems(actividadesEspecificas); - actualizarTotales(); - - tareasEspecificasDropdown.clear(); - tareaEspecificaInput.clear(); - horasTareaInput.clear(); - - Notification.show("Tarea específica agregada correctamente"); - } else { - Notification.show("Selecciona una tarea y asegúrate de ingresar horas válidas."); - } - } catch (NumberFormatException ex) { - Notification.show("Error: Por favor ingresa un número válido para las horas."); - } - }); - - HorizontalLayout layout = new HorizontalLayout(tareasEspecificasDropdown, - tareaEspecificaInput, horasTareaInput, agregarTareaButton); - layout.setSpacing(true); - return layout; - } - - private TextField crearCampoHora(final String placeholder) { - TextField field = new TextField(placeholder); - field.setWidth("80px"); - field.setPlaceholder("0.0"); - return field; - } - - private double parseHoras(final String value) { - if (value == null || value.trim().isEmpty()) { - return 0.0; + private void saveHoursWorked() { + if (isFormValid()) { + HoursWorked hoursWorked = getEntity(); + setFieldValues(hoursWorked); + hoursWorkedService.save(hoursWorked); + Notification.show("Horas trabajadas guardadas correctamente."); + closeForm(); } - return Double.parseDouble(value); } - private LocalDate getStartOfWeek(final LocalDate date) { - WeekFields weekFields = WeekFields.of(Locale.getDefault()); - return date.with(weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue()); - } - - private double calcularTotalPorDia(final Actividad actividad) { - return actividad.getLunes() + actividad.getMartes() + actividad.getMiercoles() - + actividad.getJueves() + actividad.getViernes() + actividad.getSabado() + actividad.getDomingo(); - } - - private void actualizarTotales() { - double totalActividadesGenerales = actividades.stream() - .mapToDouble(this::calcularTotalPorDia) - .sum(); - double totalActividadesEspecificas = actividadesEspecificas.stream() - .mapToDouble(this::calcularTotalPorDia) - .sum(); - double totalFinal = totalActividadesGenerales + totalActividadesEspecificas; - double horasPendientes = 40 - totalFinal; - - totalCompletadoLabel.setText("Total Hrs/Semana Completadas: " + totalFinal); - horasPendientesLabel.setText("Horas Pendientes: " + horasPendientes); - } - - private void guardarActividades() { - Employee selectedEmployee = employeeComboBox.getValue(); - String selectedEquipo = equipoDropdown.getValue(); - - if (selectedEmployee == null || selectedEquipo == null) { - Notification.show("Por favor selecciona un equipo y un empleado."); - return; - } - - double totalHorasSemana = actividades.stream() - .mapToDouble(this::calcularTotalPorDia) - .sum(); - - HoursWorked hoursWorked = new HoursWorked(); - hoursWorked.setEmployee(selectedEmployee); - hoursWorked.setWeekNumber(weekNumber); - hoursWorked.setTotalHours(totalHorasSemana); - + private void setFieldValues(final HoursWorked hoursWorked) { + hoursWorked.setDate(dateField.getValue()); + hoursWorked.setTeam(teamField.getValue()); + hoursWorked.setEmployee(employeeField.getValue()); + hoursWorked.setActividad(activityField.getValue()); try { - hoursWorkedService.saveHoursWorked(hoursWorked); // Usa saveHoursWorked directamente - Notification.show("Actividades guardadas correctamente."); - System.out.println(hoursWorked); - } catch (Exception e) { - Notification.show("Error al guardar actividades: " + e.getMessage()); + double hours = Double.parseDouble(hoursField.getValue()); + hoursWorked.setHours(hours); + } catch (NumberFormatException e) { + Notification.show("Por favor, ingrese un número válido para las horas."); + } + if ("Otros".equals(tareasEspecificasDropdown.getValue())) { + // Maneja horas y actividad específica adicional + hoursWorked.setTareasEspecificas(tareaEspecificaInput.getValue()); + try { + double horasEspecifica = Double.parseDouble(horasTareaEspecificaField.getValue()); + hoursWorked.setHorasTareasEspecificas(horasEspecifica); + } catch (NumberFormatException e) { + Notification.show("Por favor, ingrese un número válido para las horas de la tarea específica."); + } } } - private double calcularTotalHoras(final List listaDeHorasTrabajadas) { - return listaDeHorasTrabajadas.stream() - .mapToDouble(HoursWorked::getTotalHours) - .sum(); + private void closeForm() { + getUI().ifPresent(ui -> ui.navigate("hours-worked-list/" + hoursWorked.getId().toString())); } - private List obtenerDatos() { - return new ArrayList<>(); + private boolean isFormValid() { + return dateField.getValue() != null + && + teamField.getValue() != null + && + employeeField.getValue() != null + && + !activityField.isEmpty(); + } - private void closeView() { - getUI().ifPresent(ui -> ui.navigate(HoursWorkedView.class)); + private void configureViewOrEditAction(final String action) { + if ("edit".equals(action) && hoursWorked != null) { + setFieldsReadOnly(false); + } else if ("view".equals(action) && hoursWorked != null) { + setFieldsReadOnly(true); + saveButton.setEnabled(false); + } } + + private void setFieldsReadOnly(final boolean readOnly) { + dateField.setReadOnly(readOnly); + teamField.setReadOnly(readOnly); + employeeField.setReadOnly(readOnly); + activityField.setReadOnly(readOnly); + } + + } \ No newline at end of file diff --git a/src/main/java/com/primefactorsolutions/views/MainLayout.java b/src/main/java/com/primefactorsolutions/views/MainLayout.java index 62ca1fc..9545c99 100644 --- a/src/main/java/com/primefactorsolutions/views/MainLayout.java +++ b/src/main/java/com/primefactorsolutions/views/MainLayout.java @@ -150,7 +150,7 @@ public class MainLayout extends AppLayout { LineAwesomeIcon.LIST_ALT.create())); SideNavItem timesheet = new SideNavItem("My Timesheet", TimesheetView.class, LineAwesomeIcon.HOURGLASS_START_SOLID.create()); - timesheet.addItem(new SideNavItem("Horas Trabajadas", HoursWorkedView.class, + timesheet.addItem(new SideNavItem("Registro de Horas Trabajadas", HoursWorkedListView.class, LineAwesomeIcon.ID_CARD_SOLID.create())); timesheet.addItem(new SideNavItem("Reporte Horas Trabajadas", ReporteView.class, LineAwesomeIcon.ID_CARD_SOLID.create())); diff --git a/src/main/java/com/primefactorsolutions/views/ReporteView.java b/src/main/java/com/primefactorsolutions/views/ReporteView.java index 1594cc5..3e10457 100644 --- a/src/main/java/com/primefactorsolutions/views/ReporteView.java +++ b/src/main/java/com/primefactorsolutions/views/ReporteView.java @@ -50,7 +50,6 @@ public class ReporteView extends VerticalLayout { private final Span semanaInfoSpan = new Span(); - // Obtener el año actual private int currentYear = LocalDate.now().getYear(); @@ -76,22 +75,19 @@ public class ReporteView extends VerticalLayout { // Listener para actualizar `semanaInfoSpan` con la selección del usuario en `semanaComboBox` semanaComboBox.addValueChangeListener(event -> { String selectedWeek = event.getValue(); - semanaInfoSpan.setText(selectedWeek != null - ? selectedWeek : "Selecciona una semana"); + semanaInfoSpan.setText(selectedWeek != null ? selectedWeek : "Selecciona una semana"); }); Button reportButton = new Button("Generar Reporte de Horas Trabajadas", event -> generateHoursWorkedReport()); - HorizontalLayout filtersLayout = new HorizontalLayout(equipoComboBox, - semanaComboBox, reportButton); + HorizontalLayout filtersLayout = new HorizontalLayout(equipoComboBox, semanaComboBox, reportButton); add(filtersLayout); // Añadir `headerLayout` al diseño principal para el encabezado dinámico add(headerLayout); updateHeaderLayout(null, null); - grid.addColumn(map -> map.get("ID")).setHeader("ID") - .getElement().getStyle().set("font-weight", "bold"); + grid.addColumn(map -> map.get("ID")).setHeader("ID").getElement().getStyle().set("font-weight", "bold"); grid.addColumn(map -> map.get("Employee ID")).setHeader("Employee ID"); grid.addColumn(map -> map.get("Empleado")).setHeader("Empleado"); grid.addColumn(map -> map.get("Horas Trabajadas")).setHeader("Horas Trabajadas"); @@ -105,8 +101,7 @@ public class ReporteView extends VerticalLayout { int year = LocalDate.now().getYear(); LocalDate startOfYear = LocalDate.of(year, 1, 5); // Suponemos que la semana comienza el 5 de enero. - List semanas = startOfYear.datesUntil(LocalDate - .of(year + 1, 1, 1), + List semanas = startOfYear.datesUntil(LocalDate.of(year + 1, 1, 1), java.time.Period.ofWeeks(1)) .map(date -> { int weekNumber = date.get(WeekFields.of(DayOfWeek.MONDAY, 1) @@ -133,27 +128,23 @@ public class ReporteView extends VerticalLayout { String selectedWeek = semanaComboBox.getValue(); if (selectedEquipo == null || selectedWeek == null) { Notification.show("Por favor, selecciona un equipo y una semana para generar el reporte.", - 3000, - Notification.Position.MIDDLE); + 3000, Notification.Position.MIDDLE); return; } - int weekNumber = Integer.parseInt(selectedWeek.split(" ")[1] - .replace(":", "")); - LocalDate selectedDate = LocalDate.now() - .with(WeekFields.of(DayOfWeek.FRIDAY, 1) - .weekOfWeekBasedYear(), weekNumber); + int weekNumber = Integer.parseInt(selectedWeek.split(" ")[1].replace(":", "")); + LocalDate selectedDate = LocalDate.now().with(WeekFields.of(DayOfWeek.FRIDAY, 1) + .weekOfWeekBasedYear(), weekNumber); updateHeaderLayout(selectedEquipo, selectedDate); List hoursWorkedList = hoursWorkedService.findAll().stream() - .filter(hw -> hw.getEmployee().getTeam().getId() - .equals(selectedEquipo.getId()) && hw.getWeekNumber() == weekNumber) + .filter(hw -> hw.getEmployee().getTeam().getId().equals(selectedEquipo + .getId()) && hw.getWeekNumber() == weekNumber) .collect(Collectors.toList()); if (hoursWorkedList.isEmpty()) { Notification.show("No hay horas trabajadas disponibles para generar el reporte.", - 3000, - Notification.Position.MIDDLE); + 3000, Notification.Position.MIDDLE); return; } @@ -188,8 +179,8 @@ public class ReporteView extends VerticalLayout { String formattedEndDate = endOfWeek.getDayOfMonth() + " de " + endOfWeek.getMonth().getDisplayName(TextStyle.FULL, Locale.getDefault()); - headerLayout.add(new Span("Informe " + String.format("%03d", weekNumber) - + "/" + currentYear) {{ + headerLayout.add(new Span("Informe " + + String.format("%03d", weekNumber) + "/" + currentYear) {{ getStyle().set("font-size", "24px"); getStyle().set("font-weight", "bold"); }}); @@ -213,14 +204,13 @@ public class ReporteView extends VerticalLayout { } } - private void generateExcelDownloadLink(final List> data, - final int weekNumber) { + private void generateExcelDownloadLink(final List> data, final int weekNumber) { try { List headers = List.of("ID", "Employee ID", "Empleado", "Horas Trabajadas", "Horas Pendientes", "Observaciones"); String selectedTeam = equipoComboBox.getValue().getName(); - byte[] excelBytes = reportService.writeAsExcel("hours_worked_report", - headers, data, selectedTeam, weekNumber, currentYear); + byte[] excelBytes = reportService.writeAsExcel( + "hours_worked_report", headers, data, selectedTeam, weekNumber, currentYear); StreamResource excelResource = new StreamResource("hours_worked_report.xlsx", () -> new ByteArrayInputStream(excelBytes)); @@ -241,13 +231,4 @@ public class ReporteView extends VerticalLayout { return date.get(WeekFields.of(Locale.getDefault()).weekOfWeekBasedYear()); } - public int getCurrentYear() { - return currentYear; - } - - // Opcional: Si deseas permitir cambiar el año actual manualmente, agrega un setter - public void setCurrentYear(final int currentYear) { - this.currentYear = currentYear; - } - } diff --git a/src/main/java/com/primefactorsolutions/views/TimesheestReportView.java b/src/main/java/com/primefactorsolutions/views/TimesheestReportView.java index a2e0ff8..f45be8d 100644 --- a/src/main/java/com/primefactorsolutions/views/TimesheestReportView.java +++ b/src/main/java/com/primefactorsolutions/views/TimesheestReportView.java @@ -10,7 +10,7 @@ import org.springframework.context.annotation.Scope; @SpringComponent @Scope("prototype") @PageTitle("Timesheets") -@Route(value = "/timesheets", layout = MainLayout.class) +@Route(value = "/timesheets-report", layout = MainLayout.class) @PermitAll public class TimesheestReportView extends Main { } diff --git a/src/main/java/com/primefactorsolutions/views/TimesheetView.java b/src/main/java/com/primefactorsolutions/views/TimesheetView.java index 9a8b351..eb23e4d 100644 --- a/src/main/java/com/primefactorsolutions/views/TimesheetView.java +++ b/src/main/java/com/primefactorsolutions/views/TimesheetView.java @@ -11,7 +11,7 @@ import org.springframework.context.annotation.Scope; @PermitAll @Scope("prototype") @PageTitle("Timesheet") -@Route(value = "/timesheets/me", layout = MainLayout.class) +@Route(value = "/timesheets", layout = MainLayout.class) public class TimesheetView extends Main { } diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index 5833a0e..9b52b2b 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -90,3 +90,6 @@ insert into time_off_request (id, version, employee_id, category, state, availab values ('12ec8b74-983d-4a17-b67e-134f45ae904c', 1, '5c1a7b82-832d-4f24-8377-54b77b91b6a8', 'AÑO_NUEVO', 'PENDIENTE', 1, '2025-01-01', '2025-01-01', '2025-01-01', 1, 0); insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) values ('89bc4b2a-943f-487c-a9f3-bacf78145e67', 1, 'cba3efb7-32bc-44be-9fdc-fc5e4f211254', 'LUNES_CARNAVAL', 'APROBADO', 1, '2024-02-12', '2024-02-12', '2024-02-12', 1, 0); + +INSERT INTO HOURS_WORKED (ID, VERSION, ACTIVIDAD, DATE, HORAS_TAREAS_ESPECIFICAS, HORASPENDIENTES, HOURS, TAREAS_ESPECIFICAS, TOTAL_HOURS, WEEK_NUMBER, EMPLOYEE_ID, TEAM_ID) +VALUES ('6d6b3a71-9b11-4526-8335-b089627a8cd6', 0, 'Scrum Meeting', '2024-11-15', 0.0, 0.0, 2.0, NULL, 0.0, 0, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'b0e8f394-78c1-4d8a-9c57-dc6e8b36a5fa');