hoursworked #75
60
package.json
60
package.json
@ -4,7 +4,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@f0rce/ace-widget": "1.0.2",
|
"@f0rce/ace-widget": "1.0.2",
|
||||||
"@polymer/polymer": "3.5.1",
|
"@polymer/polymer": "3.5.2",
|
||||||
"@vaadin-component-factory/vcf-pdf-viewer": "2.0.1",
|
"@vaadin-component-factory/vcf-pdf-viewer": "2.0.1",
|
||||||
"@vaadin/bundles": "24.5.1",
|
"@vaadin/bundles": "24.5.1",
|
||||||
"@vaadin/common-frontend": "0.0.19",
|
"@vaadin/common-frontend": "0.0.19",
|
||||||
@ -19,29 +19,30 @@
|
|||||||
"@vaadin/vaadin-usage-statistics": "2.1.3",
|
"@vaadin/vaadin-usage-statistics": "2.1.3",
|
||||||
"construct-style-sheets-polyfill": "3.1.0",
|
"construct-style-sheets-polyfill": "3.1.0",
|
||||||
"date-fns": "2.29.3",
|
"date-fns": "2.29.3",
|
||||||
"lit": "3.1.4",
|
"lit": "3.2.1",
|
||||||
"print-js": "1.6.0",
|
"print-js": "1.6.0",
|
||||||
"proj4": "2.12.1",
|
"proj4": "2.12.1",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"react-router-dom": "6.23.1"
|
"react-router-dom": "6.26.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/preset-react": "7.24.7",
|
"@babel/preset-react": "7.25.7",
|
||||||
"@rollup/plugin-replace": "5.0.7",
|
"@preact/signals-react-transform": "0.4.0",
|
||||||
"@rollup/pluginutils": "5.1.0",
|
"@rollup/plugin-replace": "6.0.1",
|
||||||
"@types/react": "18.3.3",
|
"@rollup/pluginutils": "5.1.2",
|
||||||
"@types/react-dom": "18.3.0",
|
"@types/react": "18.3.11",
|
||||||
"@vitejs/plugin-react": "4.3.1",
|
"@types/react-dom": "18.3.1",
|
||||||
"async": "3.2.5",
|
"@vitejs/plugin-react": "4.3.3",
|
||||||
"glob": "10.4.1",
|
"async": "3.2.6",
|
||||||
|
"glob": "10.4.5",
|
||||||
"rollup-plugin-brotli": "3.1.0",
|
"rollup-plugin-brotli": "3.1.0",
|
||||||
"rollup-plugin-visualizer": "5.12.0",
|
"rollup-plugin-visualizer": "5.12.0",
|
||||||
"strip-css-comments": "5.0.0",
|
"strip-css-comments": "5.0.0",
|
||||||
"transform-ast": "2.4.4",
|
"transform-ast": "2.4.4",
|
||||||
"typescript": "5.4.5",
|
"typescript": "5.6.3",
|
||||||
"vite": "5.3.3",
|
"vite": "5.4.9",
|
||||||
"vite-plugin-checker": "0.6.4",
|
"vite-plugin-checker": "0.8.0",
|
||||||
"workbox-build": "7.1.1",
|
"workbox-build": "7.1.1",
|
||||||
"workbox-core": "7.1.0",
|
"workbox-core": "7.1.0",
|
||||||
"workbox-precaching": "7.1.0"
|
"workbox-precaching": "7.1.0"
|
||||||
@ -49,7 +50,7 @@
|
|||||||
"vaadin": {
|
"vaadin": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@f0rce/ace-widget": "1.0.2",
|
"@f0rce/ace-widget": "1.0.2",
|
||||||
"@polymer/polymer": "3.5.1",
|
"@polymer/polymer": "3.5.2",
|
||||||
"@vaadin-component-factory/vcf-pdf-viewer": "2.0.1",
|
"@vaadin-component-factory/vcf-pdf-viewer": "2.0.1",
|
||||||
"@vaadin/bundles": "24.5.1",
|
"@vaadin/bundles": "24.5.1",
|
||||||
"@vaadin/common-frontend": "0.0.19",
|
"@vaadin/common-frontend": "0.0.19",
|
||||||
@ -64,34 +65,35 @@
|
|||||||
"@vaadin/vaadin-usage-statistics": "2.1.3",
|
"@vaadin/vaadin-usage-statistics": "2.1.3",
|
||||||
"construct-style-sheets-polyfill": "3.1.0",
|
"construct-style-sheets-polyfill": "3.1.0",
|
||||||
"date-fns": "2.29.3",
|
"date-fns": "2.29.3",
|
||||||
"lit": "3.1.4",
|
"lit": "3.2.1",
|
||||||
"print-js": "1.6.0",
|
"print-js": "1.6.0",
|
||||||
"proj4": "2.12.1",
|
"proj4": "2.12.1",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"react-router-dom": "6.23.1"
|
"react-router-dom": "6.26.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/preset-react": "7.24.7",
|
"@babel/preset-react": "7.25.7",
|
||||||
"@rollup/plugin-replace": "5.0.7",
|
"@preact/signals-react-transform": "0.4.0",
|
||||||
"@rollup/pluginutils": "5.1.0",
|
"@rollup/plugin-replace": "6.0.1",
|
||||||
"@types/react": "18.3.3",
|
"@rollup/pluginutils": "5.1.2",
|
||||||
"@types/react-dom": "18.3.0",
|
"@types/react": "18.3.11",
|
||||||
"@vitejs/plugin-react": "4.3.1",
|
"@types/react-dom": "18.3.1",
|
||||||
"async": "3.2.5",
|
"@vitejs/plugin-react": "4.3.3",
|
||||||
"glob": "10.4.1",
|
"async": "3.2.6",
|
||||||
|
"glob": "10.4.5",
|
||||||
"rollup-plugin-brotli": "3.1.0",
|
"rollup-plugin-brotli": "3.1.0",
|
||||||
"rollup-plugin-visualizer": "5.12.0",
|
"rollup-plugin-visualizer": "5.12.0",
|
||||||
"strip-css-comments": "5.0.0",
|
"strip-css-comments": "5.0.0",
|
||||||
"transform-ast": "2.4.4",
|
"transform-ast": "2.4.4",
|
||||||
"typescript": "5.4.5",
|
"typescript": "5.6.3",
|
||||||
"vite": "5.3.3",
|
"vite": "5.4.9",
|
||||||
"vite-plugin-checker": "0.6.4",
|
"vite-plugin-checker": "0.8.0",
|
||||||
"workbox-build": "7.1.1",
|
"workbox-build": "7.1.1",
|
||||||
"workbox-core": "7.1.0",
|
"workbox-core": "7.1.0",
|
||||||
"workbox-precaching": "7.1.0"
|
"workbox-precaching": "7.1.0"
|
||||||
},
|
},
|
||||||
"hash": "1a0f17d48b329307b5862bc57499307d1b89f7d89260121c2b7189f76957c436"
|
"hash": "2dc40a4f634ae025081ca2239cba00b14a35fe94ab78ac0a4dd3023d882081d5"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"@vaadin/bundles": "$@vaadin/bundles",
|
"@vaadin/bundles": "$@vaadin/bundles",
|
||||||
|
@ -102,5 +102,31 @@ public class HoursWorked extends BaseEntity {
|
|||||||
public void setHorasTareasEspecificas(final double horasTareasEspecificas) {
|
public void setHorasTareasEspecificas(final double horasTareasEspecificas) {
|
||||||
this.tareasEspecificas = tareasEspecificas;
|
this.tareasEspecificas = tareasEspecificas;
|
||||||
}
|
}
|
||||||
|
public double getHoraspendientes() {
|
||||||
|
double horasTrabajadas = this.getTotalHours() + this.getHorasTareasEspecificas();
|
||||||
|
return 40 - horasTrabajadas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHoraspendientes(final double horaspendientes) {
|
||||||
|
this.horaspendientes = horaspendientes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHoursWorked() {
|
||||||
|
return hours;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHoursWorked(final double hoursWorked) {
|
||||||
|
this.hours = hoursWorked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getTotalHoursWorked() {
|
||||||
|
return totalHours;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotalHoursWorked(final double totalHoursWorked) {
|
||||||
|
this.totalHours = totalHoursWorked;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,4 +11,5 @@ import java.util.UUID;
|
|||||||
public interface HoursWorkedRepository extends JpaRepository<HoursWorked, UUID> {
|
public interface HoursWorkedRepository extends JpaRepository<HoursWorked, UUID> {
|
||||||
List<HoursWorked> findByWeekNumber(int weekNumber);
|
List<HoursWorked> findByWeekNumber(int weekNumber);
|
||||||
List<HoursWorked> findByDate(LocalDate date);
|
List<HoursWorked> findByDate(LocalDate date);
|
||||||
|
List<HoursWorked> findByEmployeeIdAndWeekNumber(UUID employeeId, int weekNumber);
|
||||||
}
|
}
|
@ -22,6 +22,14 @@ public class HoursWorkedService {
|
|||||||
return hoursWorkedRepository.findAll();
|
return hoursWorkedRepository.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getTotalHoursWorkedByEmployeeForWeek(UUID employeeId, int weekNumber) {
|
||||||
|
List<HoursWorked> hoursWorkedList = hoursWorkedRepository.findByWeekNumber(weekNumber);
|
||||||
|
return hoursWorkedList.stream()
|
||||||
|
.filter(hw -> hw.getEmployee().getId().equals(employeeId))
|
||||||
|
.mapToDouble(HoursWorked::getTotalHours)
|
||||||
|
.sum();
|
||||||
|
}
|
||||||
|
|
||||||
public HoursWorked findHoursWorked(final UUID id) {
|
public HoursWorked findHoursWorked(final UUID id) {
|
||||||
Optional<HoursWorked> hoursWorked = hoursWorkedRepository.findById(id);
|
Optional<HoursWorked> hoursWorked = hoursWorkedRepository.findById(id);
|
||||||
HoursWorked hw = hoursWorked.get();
|
HoursWorked hw = hoursWorked.get();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.primefactorsolutions.views;
|
package com.primefactorsolutions.views;
|
||||||
|
|
||||||
import com.primefactorsolutions.model.Employee;
|
import com.primefactorsolutions.model.Employee;
|
||||||
|
import com.primefactorsolutions.model.HoursWorked;
|
||||||
import com.primefactorsolutions.model.Team;
|
import com.primefactorsolutions.model.Team;
|
||||||
import com.primefactorsolutions.service.EmployeeService;
|
import com.primefactorsolutions.service.EmployeeService;
|
||||||
import com.primefactorsolutions.service.HoursWorkedService;
|
import com.primefactorsolutions.service.HoursWorkedService;
|
||||||
@ -14,9 +15,12 @@ import com.vaadin.flow.router.PageTitle;
|
|||||||
import com.vaadin.flow.router.Route;
|
import com.vaadin.flow.router.Route;
|
||||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||||
import jakarta.annotation.security.PermitAll;
|
import jakarta.annotation.security.PermitAll;
|
||||||
|
import org.joda.time.Hours;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.vaadin.firitin.components.grid.PagingGrid;
|
import org.vaadin.firitin.components.grid.PagingGrid;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.temporal.IsoFields;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -30,8 +34,7 @@ public class HoursWorkedListView extends Main {
|
|||||||
private final HoursWorkedService hoursWorkedService;
|
private final HoursWorkedService hoursWorkedService;
|
||||||
private final EmployeeService employeeService;
|
private final EmployeeService employeeService;
|
||||||
private final TeamService teamService;
|
private final TeamService teamService;
|
||||||
private final PagingGrid<Employee> hoursWorkedGrid = new PagingGrid<>();
|
private final PagingGrid<HoursWorked> hoursWorkedGrid = new PagingGrid<>();
|
||||||
private final PagingGrid<Employee> table = new PagingGrid<>(Employee.class);
|
|
||||||
private List<Employee> employees = Collections.emptyList();
|
private List<Employee> employees = Collections.emptyList();
|
||||||
private ComboBox<Employee> employeeFilter;
|
private ComboBox<Employee> employeeFilter;
|
||||||
private ComboBox<Team> teamFilter;
|
private ComboBox<Team> teamFilter;
|
||||||
@ -54,31 +57,55 @@ public class HoursWorkedListView extends Main {
|
|||||||
final Team team) {
|
final Team team) {
|
||||||
hoursWorkedGrid.setPagingDataProvider((page, pageSize) -> {
|
hoursWorkedGrid.setPagingDataProvider((page, pageSize) -> {
|
||||||
int start = (int) (page * hoursWorkedGrid.getPageSize());
|
int start = (int) (page * hoursWorkedGrid.getPageSize());
|
||||||
return fetchFilteredEmployees(start, pageSize, employee, team);
|
List<HoursWorked> hoursWorkedList = fetchFilteredHoursWorked(start, pageSize, employee, team);
|
||||||
|
|
||||||
|
double totalHours = hoursWorkedList.stream()
|
||||||
|
.mapToDouble(HoursWorked::getTotalHours)
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
Notification.show("Total de horas trabajadas: " + totalHours, 3000, Notification.Position.BOTTOM_CENTER);
|
||||||
|
|
||||||
|
return hoursWorkedList;
|
||||||
});
|
});
|
||||||
hoursWorkedGrid.getDataProvider().refreshAll();
|
hoursWorkedGrid.getDataProvider().refreshAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Employee> fetchFilteredEmployees(final int start,
|
private List<HoursWorked> fetchFilteredHoursWorked(final int start,
|
||||||
final int pageSize,
|
final int pageSize,
|
||||||
final Employee employee,
|
final Employee employee,
|
||||||
final Team team) {
|
final Team team) {
|
||||||
List<Employee> filteredEmployees = employeeService.findAllEmployees();
|
List<HoursWorked> filteredHoursWorked = hoursWorkedService.findAll();
|
||||||
|
|
||||||
if (employee != null && !"TODOS".equals(employee.getFirstName())) {
|
if (employee != null && !"TODOS".equals(employee.getFirstName())) {
|
||||||
filteredEmployees = filteredEmployees.stream()
|
filteredHoursWorked = filteredHoursWorked.stream()
|
||||||
.filter(emp -> emp.getId().equals(employee.getId()))
|
.filter(hw -> hw.getEmployee().getId().equals(employee.getId()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (team != null && !"TODOS".equals(team.getName())) {
|
if (team != null && !"TODOS".equals(team.getName())) {
|
||||||
filteredEmployees = filteredEmployees.stream()
|
filteredHoursWorked = filteredHoursWorked.stream()
|
||||||
.filter(emp -> emp.getTeam() != null && emp.getTeam().getId().equals(team.getId()))
|
.filter(hw -> hw.getEmployee().getTeam() != null && hw.getEmployee().getTeam().getId().equals(team.getId()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
int end = Math.min(start + pageSize, filteredEmployees.size());
|
for (HoursWorked hoursWorked : filteredHoursWorked) {
|
||||||
return filteredEmployees.subList(start, end);
|
if (employee != null && hoursWorked.getEmployee().getId().equals(employee.getId())) {
|
||||||
|
LocalDate date = hoursWorked.getDate();
|
||||||
|
int currentWeek = date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
|
||||||
|
|
||||||
|
double totalWorkedInSameWeek = filteredHoursWorked.stream()
|
||||||
|
.filter(hw -> hw.getEmployee().getId().equals(employee.getId()) &&
|
||||||
|
hw.getDate().get(IsoFields.WEEK_OF_WEEK_BASED_YEAR) == currentWeek)
|
||||||
|
.mapToDouble(HoursWorked::getHours)
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
double updatedPendingHours = totalWorkedInSameWeek - hoursWorked.getHours();
|
||||||
|
hoursWorked.setHoraspendientes(updatedPendingHours);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int end = Math.min(start + pageSize, filteredHoursWorked.size());
|
||||||
|
return filteredHoursWorked.subList(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeView() {
|
private void initializeView() {
|
||||||
@ -95,29 +122,27 @@ public class HoursWorkedListView extends Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupListHoursWorkedGrid() {
|
private void setupListHoursWorkedGrid() {
|
||||||
hoursWorkedGrid.addColumn(this::getEmployeeFullName).setHeader("Empleado");
|
hoursWorkedGrid.addColumn(hw -> hw.getDate() != null ? hw.getDate().toString() : "")
|
||||||
hoursWorkedGrid.addColumn(this::getTeamName).setHeader("Equipo");
|
.setHeader("Fecha")
|
||||||
|
.setSortable(true);
|
||||||
|
hoursWorkedGrid.addColumn(hw -> hw.getEmployee().getFirstName() + " " + hw.getEmployee().getLastName())
|
||||||
|
.setHeader("Empleado");
|
||||||
|
hoursWorkedGrid.addColumn(hw -> hw.getEmployee().getTeam() != null ? hw.getEmployee().getTeam().getName() : "Sin asignar")
|
||||||
|
.setHeader("Equipo");
|
||||||
|
hoursWorkedGrid.addColumn(HoursWorked::getActividad).setHeader("Actividad");
|
||||||
|
hoursWorkedGrid.addColumn(hw -> hw.getHours()).setHeader("Total Horas").setSortable(true);
|
||||||
|
hoursWorkedGrid.addColumn(hw -> hw.getHoraspendientes()).setHeader("Horas Pendientes").setSortable(true);
|
||||||
|
|
||||||
hoursWorkedGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
|
hoursWorkedGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
|
||||||
hoursWorkedGrid.setPageSize(5);
|
hoursWorkedGrid.setPageSize(5);
|
||||||
hoursWorkedGrid.asSingleSelect().addValueChangeListener(event -> {
|
hoursWorkedGrid.asSingleSelect().addValueChangeListener(event -> {
|
||||||
Employee selectedRequest = event.getValue();
|
HoursWorked selectedHoursWorked = event.getValue();
|
||||||
if (selectedRequest != null) {
|
if (selectedHoursWorked != null) {
|
||||||
selectedEmployeeId = selectedRequest.getId();
|
selectedEmployeeId = selectedHoursWorked.getEmployee().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() {
|
private HorizontalLayout createActionButtons() {
|
||||||
Button viewButton = new Button("Ver", event -> {
|
Button viewButton = new Button("Ver", event -> {
|
||||||
if (selectedEmployeeId != null) {
|
if (selectedEmployeeId != null) {
|
||||||
@ -178,7 +203,7 @@ public class HoursWorkedListView extends Main {
|
|||||||
List<Team> teams = new ArrayList<>(teamService.findAllTeams());
|
List<Team> teams = new ArrayList<>(teamService.findAllTeams());
|
||||||
teams.addFirst(createAllTeamsOption());
|
teams.addFirst(createAllTeamsOption());
|
||||||
teamFilter.setItems(teams);
|
teamFilter.setItems(teams);
|
||||||
teamFilter.setItemLabelGenerator(this::getTeamLabel);
|
teamFilter.setItemLabelGenerator(team -> getTeamLabel(team));
|
||||||
teamFilter.setValue(teams.getFirst());
|
teamFilter.setValue(teams.getFirst());
|
||||||
teamFilter.addValueChangeListener(event ->
|
teamFilter.addValueChangeListener(event ->
|
||||||
refreshGridListHoursWorked(
|
refreshGridListHoursWorked(
|
||||||
@ -189,6 +214,9 @@ public class HoursWorkedListView extends Main {
|
|||||||
return teamFilter;
|
return teamFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getTeamLabel(final Team team) {
|
||||||
|
return team != null && !"TODOS".equals(team.getName()) ? team.getName() : "TODOS";
|
||||||
|
}
|
||||||
|
|
||||||
private Employee createAllEmployeesOption() {
|
private Employee createAllEmployeesOption() {
|
||||||
Employee allEmployeesOption = new Employee();
|
Employee allEmployeesOption = new Employee();
|
||||||
@ -201,11 +229,4 @@ public class HoursWorkedListView extends Main {
|
|||||||
allTeamsOption.setName("TODOS");
|
allTeamsOption.setName("TODOS");
|
||||||
return allTeamsOption;
|
return allTeamsOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void setupPagingGrid() {
|
|
||||||
table.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
|
|
||||||
table.setPageSize(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -243,4 +243,6 @@ public class HoursWorkedView extends BeanValidationForm<HoursWorked> implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user