Compare commits

...

8 Commits

Author SHA1 Message Date
Melina Gutierrez
b4826f1720 #46 Perfil de Empleado - Registro Semanal de Horas trabajadas con el numero de semanas pero sin la bd 2024-10-16 15:08:08 -04:00
Melina Gutierrez
b5396ae373 #46 Perfil de Empleado - Registro Semanal de Horas trabajadas con el numero de semanas 2024-10-15 10:11:14 -04:00
Melina Gutierrez
3e57c50378 #46 Perfil de Empleado - Registro Semanal de Horas trabajadas 2024-10-14 12:56:02 -04:00
2a59bc4e7e Merge pull request '#37, #41, #42, #43, #44 Perfil de Personal Administrativo - Listado General de Vacaciones y Filtrado' (#48) from Listado-General-Vacaciones into main
All checks were successful
Builder / Build-Project (push) Successful in 2m32s
Reviewed-on: #48
2024-10-10 19:56:03 +00:00
02c0b848af Actualizar src/main/java/com/primefactorsolutions/model/TimeOffRequest.java
All checks were successful
PR Builder / Build-PR (pull_request) Successful in 2m27s
2024-10-09 14:44:28 +00:00
b14e7902cc Correcciones
All checks were successful
PR Builder / Build-PR (pull_request) Successful in 2m27s
2024-10-08 15:38:41 -04:00
d6dce9a4d0 #37, #41, #42, #43, #44 Perfil de Personal Administrativo - Listado General de Vacaciones y Filtrado
Some checks failed
PR Builder / Build-PR (pull_request) Failing after 19s
2024-10-08 14:47:50 -04:00
ef78cc91a8 Merge pull request '#10-Registro-Informacion-Profesional' (#38) from #10-Registro-Informacion-Profesional into main
All checks were successful
Builder / Build-Project (push) Successful in 2m29s
Reviewed-on: #38
2024-10-08 18:00:43 +00:00
12 changed files with 692 additions and 58 deletions

View File

@ -0,0 +1,61 @@
package com.primefactorsolutions.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.AssertTrue;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class HoursWorked extends BaseEntity {
@ManyToOne
@JoinColumn(name = "employee_id", nullable = false)
private Employee employee;
private LocalDate workDate;
private int regularHours;
private int overtimeHours;
private int weekendHours;
private int holidayHours;
@Enumerated(EnumType.STRING)
private WorkType workType;
@Enumerated(EnumType.STRING)
private ApprovalStatus approvalStatus;
@Column(columnDefinition = "TEXT")
private String notes;
public enum WorkType {
ONSITE, REMOTE, HYBRID
}
public enum ApprovalStatus {
PENDING, APPROVED, REJECTED
}
@AssertTrue(message = "Las horas no pueden ser negativas")
public boolean areHoursValid() {
return regularHours >= 0 && overtimeHours >= 0 &&
weekendHours >= 0 && holidayHours >= 0;
}
@AssertTrue(message = "La suma de horas no puede superar 24 en un día")
public boolean isTotalHoursValid() {
int totalHours = regularHours + overtimeHours + weekendHours + holidayHours;
return totalHours <= 24;
}
}

View File

@ -0,0 +1,14 @@
package com.primefactorsolutions.model;
import jakarta.persistence.*;
import lombok.*;
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class Team extends BaseEntity {
private String name;
}

View File

@ -1,21 +1,46 @@
package com.primefactorsolutions.model;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.OneToMany;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Date;
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class TimeOffRequest extends BaseEntity {
@OneToMany(fetch = FetchType.EAGER, mappedBy = "request", cascade = {CascadeType.ALL})
private List<TimeOffRequestEntry> entries;
private TimeOffRequestType type;
@ManyToOne
@JoinColumn(name = "employee_id", nullable = false)
private Employee employee;
@ManyToOne
@JoinColumn(name = "team_id", nullable = false)
private Team team;
@Enumerated(EnumType.STRING)
private TimeOffRequestType category;
@Enumerated(EnumType.STRING)
private Status state;
private Double availableDays;
private Date expiration;
private Date startDate;
private Date endDate;
private Double daysToBeTake;
private Double daysBalance;
public enum Status {
ALL,
TAKEN,
REQUESTED,
APPROVED,
IN_USE,
UNDER_REVIEW,
PENDING,
REJECTED,
COMPLETED,
CANCELLED,
EXPIRED,
}
}

View File

@ -1,7 +1,10 @@
package com.primefactorsolutions.model;
public enum TimeOffRequestType {
ALL,
VACATION,
MATERNITY,
BIRTHDAY,
FIXED_HOLIDAY,
OTHER
}

View File

@ -0,0 +1,9 @@
package com.primefactorsolutions.repositories;
import com.primefactorsolutions.model.Team;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.UUID;
public interface TeamRepository extends JpaRepository<Team, UUID> {
}

View File

@ -0,0 +1,9 @@
package com.primefactorsolutions.repositories;
import com.primefactorsolutions.model.TimeOffRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.UUID;
public interface TimeOffRequestRepository extends JpaRepository<TimeOffRequest, UUID> {
}

View File

@ -0,0 +1,27 @@
package com.primefactorsolutions.service;
import com.primefactorsolutions.model.Team;
import com.primefactorsolutions.repositories.TeamRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.UUID;
@Service
@AllArgsConstructor
public class TeamService {
private final TeamRepository teamRepository;
public void saveTeam(final Team newTeam) {
teamRepository.save(newTeam);
}
public void deleteTeam(final UUID id) {
teamRepository.deleteById(id);
}
public List<Team> findAllTeams() {
return teamRepository.findAll();
}
}

View File

@ -0,0 +1,88 @@
package com.primefactorsolutions.service;
import com.primefactorsolutions.model.*;
import com.primefactorsolutions.repositories.TimeOffRequestRepository;
import lombok.AllArgsConstructor;
import org.apache.commons.beanutils.BeanComparator;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
@AllArgsConstructor
public class TimeOffRequestService {
private final TimeOffRequestRepository timeOffRequestRepository;
public void saveTimeOffRequest(final TimeOffRequest newTimeOffRequest) {
timeOffRequestRepository.save(newTimeOffRequest);
}
public void deleteTimeOffRequest(final UUID id) {
timeOffRequestRepository.deleteById(id);
}
public List<TimeOffRequest> getAllTimeOffRequests() {
return timeOffRequestRepository.findAll();
}
public TimeOffRequest getTimeOffRequest(final UUID id) {
Optional<TimeOffRequest> timeOffRequest = timeOffRequestRepository.findById(id);
return timeOffRequest.orElse(null);
}
public List<TimeOffRequest> findTimeOffRequests(
final int start, final int pageSize, final String sortProperty, final boolean asc) {
List<TimeOffRequest> timeOffRequests = timeOffRequestRepository.findAll();
int end = Math.min(start + pageSize, timeOffRequests.size());
timeOffRequests.sort(new BeanComparator<>(sortProperty));
if (!asc) {
Collections.reverse(timeOffRequests);
}
return timeOffRequests.subList(start, end);
}
public List<TimeOffRequest> findTimeOffRequests(final int start, final int pageSize) {
List<TimeOffRequest> timeOffRequests = timeOffRequestRepository.findAll();
int end = Math.min(start + pageSize, timeOffRequests.size());
return timeOffRequests.subList(start, end);
}
public List<TimeOffRequest> findTimeOffRequestBy(final Employee employee,
final Team team,
final TimeOffRequestType category,
final TimeOffRequest.Status state,
final int start,
final int pageSize) {
List<TimeOffRequest> timeOffRequests = timeOffRequestRepository.findAll();
if (employee != null && !"ALL".equals(employee.getFirstName())) {
timeOffRequests = timeOffRequests.stream()
.filter(req -> req.getEmployee().equals(employee))
.collect(Collectors.toList());
}
if (team != null && !"ALL".equals(team.getName())) {
timeOffRequests = timeOffRequests.stream()
.filter(req -> req.getTeam().equals(team))
.collect(Collectors.toList());
}
if (category != null && !"ALL".equals(category.name())) {
timeOffRequests = timeOffRequests.stream()
.filter(req -> req.getCategory().equals(category))
.collect(Collectors.toList());
}
if (state != null && !"ALL".equals(state.name())) {
timeOffRequests = timeOffRequests.stream()
.filter(req -> req.getState().equals(state))
.collect(Collectors.toList());
}
int end = Math.min(start + pageSize, timeOffRequests.size());
return timeOffRequests.subList(start, end);
}
}

View File

@ -1,19 +1,29 @@
package com.primefactorsolutions.views;
import com.primefactorsolutions.model.Employee;
import com.primefactorsolutions.service.EmployeeService;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.grid.Grid;
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.grid.Grid;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.html.H2;
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 com.vaadin.flow.component.html.Label;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@SpringComponent
@PermitAll
@ -21,20 +31,79 @@ import java.time.LocalDate;
@PageTitle("Hours Worked")
@Route(value = "/hours-worked/me", layout = MainLayout.class)
public class HoursWorkedView extends VerticalLayout {
public HoursWorkedView() {
H2 title = new H2("Registro de Horas Trabajadas");
private final List<Actividad> actividades = new ArrayList<>();
private final Grid<Actividad> grid = new Grid<>(Actividad.class);
private final Grid<Actividad> totalsGrid = new Grid<>(Actividad.class);
private final ComboBox<Employee> employeeComboBox = new ComboBox<>("Employee");
private LocalDate selectedStartOfWeek;
DatePicker datePicker = new DatePicker("Selecciona una fecha");
datePicker.setValue(LocalDate.now());
@Autowired
private final EmployeeService employeeService;
private final Label fechasLabel = new Label("Selecciona una semana para ver las fechas.");
@Autowired
public HoursWorkedView(final EmployeeService employeeService) {
this.employeeService = employeeService;
configurarVista();
}
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.")
);
employeeComboBox.addValueChangeListener(event -> {
Employee selectedEmployee = event.getValue();
if (selectedEmployee != null) {
Notification.show("Empleado seleccionado: " +
selectedEmployee.getFirstName() + " " + selectedEmployee.getLastName());
}
});
}
private void configurarVista() {
DatePicker fechaPicker = new DatePicker("Selecciona una fecha");
fechaPicker.addValueChangeListener(event -> {
LocalDate selectedDate = event.getValue();
if (selectedDate != null) {
selectedStartOfWeek = getStartOfWeek(selectedDate);
LocalDate endOfWeek = selectedStartOfWeek.plusDays(6);
fechasLabel.setText("Semana del " + selectedStartOfWeek + " al " + endOfWeek);
}
});
ComboBox<String> equipoDropdown = new ComboBox<>("Equipo");
equipoDropdown.setItems("Equipo 1", "Equipo 2", "Equipo 3"); // Ejemplo de datos
equipoDropdown.setItems("Equipo 1", "Equipo 2", "Equipo 3");
equipoDropdown.setWidth("250px");
TextField empleadoSearch = new TextField("Empleado (Search)");
setEmployeeComboBoxProperties();
HorizontalLayout filtersLayout = new HorizontalLayout(equipoDropdown, empleadoSearch);
HorizontalLayout filtersLayout = new HorizontalLayout(equipoDropdown, employeeComboBox);
filtersLayout.setSpacing(true);
Grid<Actividad> grid = new Grid<>(Actividad.class, false);
configurarGrid();
HorizontalLayout actividadFormLayout = configurarFormularioActividades();
Button actualizarButton = new Button("Actualizar Totales", event -> actualizarTotales());
Button guardarButton = new Button("Guardar");
Button cerrarButton = new Button("Cerrar");
HorizontalLayout buttonsLayout = new HorizontalLayout(actualizarButton, guardarButton, cerrarButton);
add(fechaPicker, fechasLabel, filtersLayout, grid, actividadFormLayout, buttonsLayout, totalsGrid);
configurarTablaTotales();
}
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");
@ -43,47 +112,116 @@ public class HoursWorkedView extends VerticalLayout {
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");
}
grid.setItems(
new Actividad.Builder()
.nombre("Actividad 1")
.lunes(3)
.martes(3)
.miercoles(3)
.jueves(3)
.viernes(3)
.sabado(1)
.domingo(2)
.build(),
new Actividad.Builder()
.nombre("Actividad 2")
.lunes(2)
.martes(2)
.miercoles(2)
.jueves(2)
.viernes(2)
.sabado(0)
.domingo(1)
.build(),
new Actividad.Builder()
.nombre("Meeting 1")
.lunes(0)
.martes(0.5)
.miercoles(0.5)
.jueves(0)
.viernes(0)
.sabado(0.5)
.domingo(0)
.build()
);
private HorizontalLayout configurarFormularioActividades() {
TextField actividadNombre = new TextField("Actividad");
TextField lunesHoras = new TextField("Lunes");
TextField martesHoras = new TextField("Martes");
TextField miercolesHoras = new TextField("Miércoles");
TextField juevesHoras = new TextField("Jueves");
TextField viernesHoras = new TextField("Viernes");
TextField sabadoHoras = new TextField("Sábado");
TextField domingoHoras = new TextField("Domingo");
Button actualizarButton = new Button("Actualizar");
Button guardarButton = new Button("Guardar");
Button cerrarButton = new Button("Cerrar");
Button agregarActividadButton = new Button("Agregar Actividad", e -> {
try {
Actividad nuevaActividad = new Actividad.Builder()
.nombre(actividadNombre.getValue())
.lunes(Double.parseDouble(lunesHoras.getValue()))
.martes(Double.parseDouble(martesHoras.getValue()))
.miercoles(Double.parseDouble(miercolesHoras.getValue()))
.jueves(Double.parseDouble(juevesHoras.getValue()))
.viernes(Double.parseDouble(viernesHoras.getValue()))
.sabado(Double.parseDouble(sabadoHoras.getValue()))
.domingo(Double.parseDouble(domingoHoras.getValue()))
.build();
HorizontalLayout buttonsLayout = new HorizontalLayout(actualizarButton, guardarButton, cerrarButton);
actividades.add(nuevaActividad);
grid.setItems(actividades);
actualizarTotales();
Notification.show("Actividad agregada correctamente");
} catch (NumberFormatException ex) {
Notification.show("Error: Por favor ingresa números válidos para las horas.");
}
});
add(title, datePicker, filtersLayout, grid, buttonsLayout);
return new HorizontalLayout(
actividadNombre, lunesHoras, martesHoras, miercolesHoras,
juevesHoras, viernesHoras, sabadoHoras, domingoHoras, agregarActividadButton);
}
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 configurarTablaTotales() {
totalsGrid.removeAllColumns();
totalsGrid.addColumn(Actividad::getNombre).setHeader("Descripción");
totalsGrid.addColumn(Actividad::getLunes).setHeader("Lunes");
totalsGrid.addColumn(Actividad::getMartes).setHeader("Martes");
totalsGrid.addColumn(Actividad::getMiercoles).setHeader("Miércoles");
totalsGrid.addColumn(Actividad::getJueves).setHeader("Jueves");
totalsGrid.addColumn(Actividad::getViernes).setHeader("Viernes");
totalsGrid.addColumn(Actividad::getSabado).setHeader("Sábado");
totalsGrid.addColumn(Actividad::getDomingo).setHeader("Domingo");
totalsGrid.addColumn(this::calcularTotalPorSemana).setHeader("Total");
totalsGrid.setItems(calcularTotales());
}
private double calcularTotalPorSemana(final Actividad actividad) {
return actividad.getLunes() + actividad.getMartes() + actividad.getMiercoles()
+ actividad.getJueves() + actividad.getViernes() + actividad.getSabado()
+ actividad.getDomingo();
}
private List<Actividad> calcularTotales() {
Actividad totalActividad = new Actividad.Builder()
.nombre("Total Semanal")
.lunes(actividades.stream().mapToDouble(Actividad::getLunes).sum())
.martes(actividades.stream().mapToDouble(Actividad::getMartes).sum())
.miercoles(actividades.stream().mapToDouble(Actividad::getMiercoles).sum())
.jueves(actividades.stream().mapToDouble(Actividad::getJueves).sum())
.viernes(actividades.stream().mapToDouble(Actividad::getViernes).sum())
.sabado(actividades.stream().mapToDouble(Actividad::getSabado).sum())
.domingo(actividades.stream().mapToDouble(Actividad::getDomingo).sum())
.build();
return List.of(totalActividad);
}
private void actualizarTotales() {
double totalLunes = actividades.stream().mapToDouble(Actividad::getLunes).sum();
double totalMartes = actividades.stream().mapToDouble(Actividad::getMartes).sum();
double totalMiercoles = actividades.stream().mapToDouble(Actividad::getMiercoles).sum();
double totalJueves = actividades.stream().mapToDouble(Actividad::getJueves).sum();
double totalViernes = actividades.stream().mapToDouble(Actividad::getViernes).sum();
double totalSabado = actividades.stream().mapToDouble(Actividad::getSabado).sum();
double totalDomingo = actividades.stream().mapToDouble(Actividad::getDomingo).sum();
double totalSemanaCompletada = totalLunes + totalMartes + totalMiercoles + totalJueves + totalViernes + totalSabado + totalDomingo;
double horasPendientes = 40 - totalSemanaCompletada;
List<Actividad> totales = new ArrayList<>();
totales.add(new Actividad.Builder()
.nombre("Total Hrs/Semana Completadas")
.lunes(totalSemanaCompletada)
.build());
totales.add(new Actividad.Builder()
.nombre("Total Hrs/Semana Pendientes")
.lunes(horasPendientes)
.build());
totalsGrid.setItems(totales);
}
public static final class Actividad {

View File

@ -107,6 +107,8 @@ public class MainLayout extends AppLayout {
SideNavItem timeOff = new SideNavItem("My Time-off", TimeoffView.class,
LineAwesomeIcon.PLANE_DEPARTURE_SOLID.create());
timeOff.addItem(new SideNavItem("Vacations", RequestsListView.class,
LineAwesomeIcon.SUN.create()));
SideNavItem timesheet = new SideNavItem("My Timesheet", TimesheetView.class,
LineAwesomeIcon.HOURGLASS_START_SOLID.create());
timesheet.addItem(new SideNavItem("Hours Worked", HoursWorkedView.class,

View File

@ -1,11 +1,24 @@
package com.primefactorsolutions.views;
import com.primefactorsolutions.model.*;
import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.service.TeamService;
import com.primefactorsolutions.service.TimeOffRequestService;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.grid.GridSortOrder;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.data.provider.SortDirection;
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.List;
@SpringComponent
@Scope("prototype")
@ -13,4 +26,211 @@ import org.springframework.context.annotation.Scope;
@Route(value = "/requests", layout = MainLayout.class)
@PermitAll
public class RequestsListView extends Main {
private final TimeOffRequestService requestService;
private final EmployeeService employeeService;
private final TeamService teamService;
private final PagingGrid<TimeOffRequest> requestGrid;
private ComboBox<Employee> employeeFilter;
private ComboBox<Team> teamFilter;
private ComboBox<TimeOffRequestType> categoryFilter;
private ComboBox<TimeOffRequest.Status> stateFilter;
public RequestsListView(final TimeOffRequestService requestService,
final EmployeeService employeeService,
final TeamService teamService) {
this.requestService = requestService;
this.employeeService = employeeService;
this.teamService = teamService;
this.requestGrid = new PagingGrid<>(TimeOffRequest.class);
initializeView();
refreshRequestGrid(null, null, null, null);
}
private void initializeView() {
setupFilters();
setupRequestGrid();
add(requestGrid);
add(createActionButtons());
}
private void setupFilters() {
add(createEmployeeFilter());
add(createTeamFilter());
add(createCategoryFilter());
add(createStateFilter());
}
private void setupRequestGrid() {
requestGrid.setColumns(
"category",
"state",
"availableDays",
"expiration",
"startDate",
"endDate",
"daysToBeTake",
"daysBalance"
);
requestGrid.addComponentColumn(this::createEmployeeSpan).setHeader("Employee");
requestGrid.addComponentColumn(this::createTeamSpan).setHeader("Team");
requestGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
requestGrid.setPageSize(5);
}
private HorizontalLayout createActionButtons() {
Button viewButton = new Button("View");
Button editButton = new Button("Edit");
Button saveButton = new Button("Save");
Button closeButton = new Button("Close", event -> closeView());
return new HorizontalLayout(viewButton, editButton, saveButton, closeButton);
}
private void refreshRequestGrid(final Employee employee,
final Team team,
final TimeOffRequestType category,
final TimeOffRequest.Status state) {
requestGrid.setPagingDataProvider((page, pageSize) -> {
if (allFiltersAreNull(employee, team, category, state)) {
return fetchTimeOffRequests((int) page, pageSize);
} else {
return fetchFilteredTimeOffRequests((int) page, pageSize, employee, team, category, state);
}
});
requestGrid.getDataProvider().refreshAll();
}
private boolean allFiltersAreNull(final Employee employee,
final Team team,
final TimeOffRequestType category,
final TimeOffRequest.Status state) {
return employee == null && team == null && category == null && state == null;
}
private List<TimeOffRequest> fetchTimeOffRequests(final int page, final int pageSize) {
int start = page * pageSize;
if (requestGrid.getSortOrder().isEmpty()) {
return requestService.findTimeOffRequests(start, pageSize);
} else {
return fetchSortedTimeOffRequests(start, pageSize);
}
}
private List<TimeOffRequest> fetchSortedTimeOffRequests(final int start, final int pageSize) {
GridSortOrder<TimeOffRequest> sortOrder = requestGrid.getSortOrder().getFirst();
return requestService.findTimeOffRequests(
start,
pageSize,
sortOrder.getSorted().getKey(),
sortOrder.getDirection() == SortDirection.ASCENDING
);
}
private List<TimeOffRequest> fetchFilteredTimeOffRequests(final int page,
final int pageSize,
final Employee employee,
final Team team,
final TimeOffRequestType category,
final TimeOffRequest.Status state) {
return requestService.findTimeOffRequestBy(employee, team, category, state, page, pageSize);
}
private Span createEmployeeSpan(final TimeOffRequest timeOffRequest) {
Employee employee = timeOffRequest.getEmployee();
return new Span(employee.getFirstName() + " " + employee.getLastName());
}
private Span createTeamSpan(final TimeOffRequest timeOffRequest) {
return new Span(timeOffRequest.getTeam().getName());
}
private ComboBox<Employee> createEmployeeFilter() {
employeeFilter = new ComboBox<>("Employee");
List<Employee> employees = employeeService.findAllEmployees();
employees.addFirst(createAllEmployeesOption());
employeeFilter.setItems(employees);
employeeFilter.setItemLabelGenerator(this::getEmployeeLabel);
employeeFilter.setValue(employees.getFirst());
employeeFilter.addValueChangeListener(event ->
refreshRequestGrid(
event.getValue(),
teamFilter.getValue(),
categoryFilter.getValue(),
stateFilter.getValue()
)
);
return employeeFilter;
}
private ComboBox<Team> createTeamFilter() {
teamFilter = new ComboBox<>("Team");
List<Team> teams = teamService.findAllTeams();
teams.addFirst(createAllTeamsOption());
teamFilter.setItems(teams);
teamFilter.setItemLabelGenerator(this::getTeamLabel);
teamFilter.setValue(teams.getFirst());
teamFilter.addValueChangeListener(event ->
refreshRequestGrid(
employeeFilter.getValue(),
event.getValue(),
categoryFilter.getValue(),
stateFilter.getValue()
)
);
return teamFilter;
}
private ComboBox<TimeOffRequestType> createCategoryFilter() {
categoryFilter = new ComboBox<>("Category");
categoryFilter.setItems(TimeOffRequestType.values());
categoryFilter.setValue(TimeOffRequestType.values()[0]);
categoryFilter.addValueChangeListener(event ->
refreshRequestGrid(
employeeFilter.getValue(),
teamFilter.getValue(),
event.getValue(),
stateFilter.getValue()
)
);
return categoryFilter;
}
private ComboBox<TimeOffRequest.Status> createStateFilter() {
stateFilter = new ComboBox<>("State");
stateFilter.setItems(TimeOffRequest.Status.values());
stateFilter.setValue(TimeOffRequest.Status.values()[0]);
stateFilter.addValueChangeListener(event ->
refreshRequestGrid(
employeeFilter.getValue(),
teamFilter.getValue(),
categoryFilter.getValue(),
event.getValue()
)
);
return stateFilter;
}
private Employee createAllEmployeesOption() {
Employee allEmployeesOption = new Employee();
allEmployeesOption.setFirstName("ALL");
return allEmployeesOption;
}
private Team createAllTeamsOption() {
Team allTeamsOption = new Team();
allTeamsOption.setName("ALL");
return allTeamsOption;
}
private String getEmployeeLabel(final Employee employee) {
return "ALL".equals(employee.getFirstName()) ? "ALL" : employee.getFirstName() + " " + employee.getLastName();
}
private String getTeamLabel(final Team team) {
return "ALL".equals(team.getName()) ? "ALL" : team.getName();
}
private void closeView() {
getUI().ifPresent(ui -> ui.navigate(MainView.class));
}
}

View File

@ -27,3 +27,41 @@ insert into employee (id, version, username, first_name, last_name, status) valu
insert into employee (id, version, username, first_name, last_name, status) values ('f20b7c5a-5a67-44f0-9ec1-4c1b8e80de05', 1, 'mvargas', 'Marta', 'Vargas Soria', 'ACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('19b5a76e-d7b1-4b76-8b02-4d0748e85809', 1, 'aespinoza', 'Andres', 'Espinoza Chura', 'INACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('5c1a7b82-832d-4f24-8377-54b77b91b6a8', 1, 'cvillanueva', 'Carla', 'Villanueva Arce', 'ACTIVE');
INSERT INTO team (id, version, name) VALUES ('b0e8f394-78c1-4d8a-9c57-dc6e8b36a5fa', 1, 'ABC');
INSERT INTO team (id, version, name) VALUES ('6d63bc15-3f8b-46f7-9cf1-7e9b0b9a2b28', 1, 'XYZ');
INSERT INTO team (id, version, name) VALUES ('c3a8a7b1-f2d9-48c0-86ea-f215c2e6b3a3', 1, 'DEF');
INSERT INTO team (id, version, name) VALUES ('8f6b61e7-efb2-4de7-b8ed-7438c9d8babe', 1, 'GHI');
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('9d6f12ba-e341-4e7a-b8a6-cab0982bd8c1', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'b0e8f394-78c1-4d8a-9c57-dc6e8b36a5fa', 'VACATION', 'TAKEN', 15, '2025-12-31', '2024-10-01', '2024-10-10', 5, 10);
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('2fa314bc-f547-4b12-a8b6-bb789feabc12', 1, '19b5a76e-d7b1-4b76-8b02-4d0748e85809', 'b0e8f394-78c1-4d8a-9c57-dc6e8b36a5fa', 'BIRTHDAY', 'APPROVED', 15, '2025-12-31', '2024-12-01', '2024-12-15', 7, 8);
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('d5f6341a-913d-4e7f-a0b2-cfe0786acd34', 1, 'cba3efb7-32bc-44be-9fdc-fc5e4f211254', '8f6b61e7-efb2-4de7-b8ed-7438c9d8babe', 'FIXED_HOLIDAY', 'IN_USE', 20, '2025-11-30', '2024-11-10', '2024-11-20', 10, 10);
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('4f913b23-ff23-4527-bcd6-adfe01234567', 1, 'e99b7af5-7d3a-4c0f-b8bc-e8d0388d8fc4', 'b0e8f394-78c1-4d8a-9c57-dc6e8b36a5fa', 'MATERNITY', 'TAKEN', 18, '2025-06-30', '2024-07-01', '2024-07-15', 10, 8);
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('8c653f2a-f9a3-4d67-b3b6-12ad98fe0983', 1, 'f6ab3c6d-7078-45f6-9b22-4e37637bfec6', '8f6b61e7-efb2-4de7-b8ed-7438c9d8babe', 'VACATION', 'REQUESTED', 10, '2025-10-31', '2024-09-15', '2024-09-20', 5, 5);
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('fb9d9d75-b2ab-4ea4-b8b3-0a8f89e5c123', 1, '2e2293b1-3f9a-4f3d-abc8-32639b0a5e15', '6d63bc15-3f8b-46f7-9cf1-7e9b0b9a2b28', 'FIXED_HOLIDAY', 'IN_USE', 12, '2025-08-31', '2024-08-05', '2024-08-15', 6, 6);
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('1c913a12-46e9-47b7-9e31-ab903fedc789', 1, '4b1c6c35-4627-4b35-b6e9-dc75c68b2c31', 'c3a8a7b1-f2d9-48c0-86ea-f215c2e6b3a3', 'BIRTHDAY', 'TAKEN', 14, '2025-12-31', '2024-10-20', '2024-10-25', 5, 9);
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('b1249d3a-cc34-4954-88d9-1e4f67fe2436', 1, 'afc5c741-f70a-4394-853b-39d51b118927', 'c3a8a7b1-f2d9-48c0-86ea-f215c2e6b3a3', 'MATERNITY', 'APPROVED', 20, '2025-11-30', '2024-11-05', '2024-11-12', 7, 13);
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('6fdc47a8-127b-41c4-8d12-7fc12098ab12', 1, 'b2436b82-7b9f-4f0d-9463-f2c3173a45c3', 'c3a8a7b1-f2d9-48c0-86ea-f215c2e6b3a3', 'VACATION', 'TAKEN', 18, '2025-06-30', '2024-07-10', '2024-07-20', 8, 10);
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('12ec8b74-983d-4a17-b67e-134f45ae904c', 1, '5c1a7b82-832d-4f24-8377-54b77b91b6a8', '8f6b61e7-efb2-4de7-b8ed-7438c9d8babe', 'FIXED_HOLIDAY', 'PENDING', 15, '2025-12-31', '2024-09-01', '2024-09-05', 4, 11);
insert into time_off_request (id, version, employee_id, team_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', '8f6b61e7-efb2-4de7-b8ed-7438c9d8babe', 'VACATION', 'APPROVED', 20, '2025-11-30', '2024-10-25', '2024-11-05', 9, 11);
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('37adfc2a-7463-4b2d-a7c1-fae04567cdef', 1, 'e99b7af5-7d3a-4c0f-b8bc-e8d0388d8fc4', 'c3a8a7b1-f2d9-48c0-86ea-f215c2e6b3a3', 'BIRTHDAY', 'TAKEN', 18, '2025-06-30', '2024-06-01', '2024-06-10', 6, 12);
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('2bc138ea-12db-4b89-a0b4-78e045e34b4e', 1, 'f6ab3c6d-7078-45f6-9b22-4e37637bfec6', 'b0e8f394-78c1-4d8a-9c57-dc6e8b36a5fa', 'MATERNITY', 'REQUESTED', 10, '2025-10-31', '2024-10-01', '2024-10-10', 3, 7);
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('14de1a56-6893-4e12-90f3-4faec457f002', 1, 'cd80e1d0-9a08-44a6-bd63-2c63eaa003d4', 'b0e8f394-78c1-4d8a-9c57-dc6e8b36a5fa', 'FIXED_HOLIDAY', 'PENDING', 22, '2025-08-31', '2024-07-15', '2024-07-25', 8, 14);
insert into time_off_request (id, version, employee_id, team_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('fb08a6c9-cd17-42e8-b9e2-734ec834cae2', 1, '4b1c6c35-4627-4b35-b6e9-dc75c68b2c31', 'c3a8a7b1-f2d9-48c0-86ea-f215c2e6b3a3', 'VACATION', 'TAKEN', 16, '2025-12-31', '2024-09-30', '2024-10-05', 4, 12);