adding timeoff views
All checks were successful
Builder / Build-Project (push) Successful in 2m57s

This commit is contained in:
alex 2024-12-29 20:13:56 -05:00
parent 48cbea25c3
commit 9266a5f634
31 changed files with 610 additions and 307 deletions

Binary file not shown.

View File

@ -8,20 +8,22 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.time.LocalDate;
@Data @Data
@Entity @Entity
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class Vacation extends BaseEntity { public class TimeOff extends BaseEntity {
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
private TimeOffRequestType category; private TimeOffRequestType category;
private Integer monthOfYear; private LocalDate date;
private Integer dayOfMonth;
private Double duration; private Double duration;
private Double expiration; private Double expiration;
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
private Type type; private Type type;
public enum Type { public enum Type {
FIXED, FIXED,
MOVABLE, MOVABLE,

View File

@ -0,0 +1,41 @@
package com.primefactorsolutions.model;
import java.time.LocalDate;
import java.time.Year;
import java.time.format.DateTimeFormatter;
import java.time.temporal.IsoFields;
import java.time.temporal.WeekFields;
import java.util.List;
import java.util.Locale;
import java.util.stream.IntStream;
public record Week(LocalDate from, LocalDate to) {
@Override
public String toString() {
final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE;
return String.format("from %s to %s", formatter.format(from), formatter.format(to));
}
public static Week getCurrent() {
final int weekNumber = LocalDate.now().get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
final LocalDate from = getFirstDayOfWeek(weekNumber);
return new Week(from, from.plusDays(6));
}
public static List<Week> getLastWeeks(final int numberOfWeeks) {
final int weekNumber = LocalDate.now().get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
return IntStream.range(0, numberOfWeeks).mapToObj(idx -> {
LocalDate from = getFirstDayOfWeek(weekNumber - idx);
return new Week(from, from.plusDays(6));
}).toList();
}
private static LocalDate getFirstDayOfWeek(final int weekNumber) {
return LocalDate
.of(Year.now().getValue(), 2, 1)
.with(WeekFields.of(Locale.US).getFirstDayOfWeek())
.with(WeekFields.of(Locale.US).weekOfWeekBasedYear(), weekNumber);
}
}

View File

@ -0,0 +1,14 @@
package com.primefactorsolutions.repositories;
import com.primefactorsolutions.model.TimeOff;
import com.primefactorsolutions.model.TimeOffRequestType;
import org.springframework.data.jpa.repository.JpaRepository;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;
public interface TimeOffRepository extends JpaRepository<TimeOff, UUID> {
TimeOff findByCategory(TimeOffRequestType category);
List<TimeOff> findByDateBetween(LocalDate from, LocalDate to);
}

View File

@ -7,6 +7,6 @@ import java.time.LocalDate;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
public interface HoursWorkedRepository extends JpaRepository<TimesheetEntry, UUID> { public interface TimesheetEntryRepository extends JpaRepository<TimesheetEntry, UUID> {
List<TimesheetEntry> findByEmployeeIdAndDateBetween(UUID employeeId, LocalDate from, LocalDate to); List<TimesheetEntry> findByDateBetween(LocalDate from, LocalDate to);
} }

View File

@ -1,11 +0,0 @@
package com.primefactorsolutions.repositories;
import com.primefactorsolutions.model.TimeOffRequestType;
import com.primefactorsolutions.model.Vacation;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.UUID;
public interface VacationRepository extends JpaRepository<Vacation, UUID> {
Vacation findByCategory(TimeOffRequestType category);
}

View File

@ -0,0 +1,39 @@
package com.primefactorsolutions.service;
import com.primefactorsolutions.model.TimeOffRequestType;
import com.primefactorsolutions.model.TimeOff;
import com.primefactorsolutions.repositories.TimeOffRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;
@Service
@AllArgsConstructor
public class TimeOffService {
private final TimeOffRepository timeOffRepository;
public TimeOff getTimeOff(final UUID id) {
return timeOffRepository.findById(id).orElse(null);
}
public void saveTimeOff(final TimeOff timeOff) {
timeOffRepository.save(timeOff);
}
public TimeOff findVacationByCategory(final TimeOffRequestType category) {
return timeOffRepository.findByCategory(category);
}
public List<TimeOff> findVacations() {
return timeOffRepository.findAll();
}
public List<TimeOff> findTimeOffs(final Integer year) {
final LocalDate from = LocalDate.of(year, 1, 1);
final LocalDate to = LocalDate.of(year, 12, 31);
return timeOffRepository.findByDateBetween(from, to);
}
}

View File

@ -1,48 +1,37 @@
package com.primefactorsolutions.service; package com.primefactorsolutions.service;
import com.primefactorsolutions.model.TimesheetEntry; import com.primefactorsolutions.model.TimesheetEntry;
import com.primefactorsolutions.repositories.HoursWorkedRepository; import com.primefactorsolutions.repositories.TimesheetEntryRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.Year;
import java.time.temporal.WeekFields;
import java.util.*; import java.util.*;
@Service @Service
public class TimesheetService { public class TimesheetService {
private final HoursWorkedRepository hoursWorkedRepository; private final TimesheetEntryRepository timesheetEntryRepository;
@Autowired @Autowired
public TimesheetService(final HoursWorkedRepository hoursWorkedRepository) { public TimesheetService(final TimesheetEntryRepository timesheetEntryRepository) {
this.hoursWorkedRepository = hoursWorkedRepository; this.timesheetEntryRepository = timesheetEntryRepository;
} }
public List<TimesheetEntry> findAll() { public List<TimesheetEntry> findAll() {
return hoursWorkedRepository.findAll(); return timesheetEntryRepository.findAll();
} }
public TimesheetEntry save(final TimesheetEntry timesheetEntry) { public TimesheetEntry save(final TimesheetEntry timesheetEntry) {
return hoursWorkedRepository.save(timesheetEntry); return timesheetEntryRepository.save(timesheetEntry);
} }
public TimesheetEntry getHoursWorked(final UUID id) { public TimesheetEntry getTimesheetEntry(final UUID id) {
final Optional<TimesheetEntry> hoursWorked = hoursWorkedRepository.findById(id); final Optional<TimesheetEntry> hoursWorked = timesheetEntryRepository.findById(id);
return hoursWorked.orElse(null); return hoursWorked.orElse(null);
} }
public List<TimesheetEntry> findListHoursWorkedEmployee(final UUID employeeId, final int weekNumber) { public List<TimesheetEntry> findListHoursWorkedEmployee(final LocalDate from,
final LocalDate from = getFirstDayOfWeek(weekNumber); final LocalDate to) {
final LocalDate to = from.plusDays(7); return timesheetEntryRepository.findByDateBetween(from, to);
return hoursWorkedRepository.findByEmployeeIdAndDateBetween(employeeId, from, to);
}
private static LocalDate getFirstDayOfWeek(final int weekNumber) {
return LocalDate
.of(Year.now().getValue(), 2, 1)
.with(WeekFields.of(Locale.US).getFirstDayOfWeek())
.with(WeekFields.of(Locale.US).weekOfWeekBasedYear(), weekNumber);
} }
} }

View File

@ -1,23 +0,0 @@
package com.primefactorsolutions.service;
import com.primefactorsolutions.model.TimeOffRequestType;
import com.primefactorsolutions.model.Vacation;
import com.primefactorsolutions.repositories.VacationRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@AllArgsConstructor
public class VacationService {
private final VacationRepository vacationRepository;
public Vacation findVacationByCategory(final TimeOffRequestType category) {
return vacationRepository.findByCategory(category);
}
public List<Vacation> findVacations() {
return vacationRepository.findAll();
}
}

View File

@ -1,11 +1,13 @@
package com.primefactorsolutions.views; package com.primefactorsolutions.views;
import com.primefactorsolutions.views.util.AuthUtils;
import com.vaadin.flow.component.html.Main; import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.spring.security.AuthenticationContext; import com.vaadin.flow.spring.security.AuthenticationContext;
import lombok.Getter; import lombok.Getter;
import static com.primefactorsolutions.views.util.AuthUtils.isAdmin; import java.util.Optional;
import java.util.UUID;
@Getter @Getter
public abstract class BaseView extends Main { public abstract class BaseView extends Main {
@ -20,6 +22,10 @@ public abstract class BaseView extends Main {
} }
protected boolean isRoleAdmin() { protected boolean isRoleAdmin() {
return isAdmin(this.authenticationContext); return AuthUtils.isAdmin(this.authenticationContext);
}
protected Optional<UUID> getEmployeeId() {
return AuthUtils.getEmployeeId(this.authenticationContext);
} }
} }

View File

@ -7,6 +7,8 @@ import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.service.ReportService; import com.primefactorsolutions.service.ReportService;
import com.primefactorsolutions.service.TeamService; import com.primefactorsolutions.service.TeamService;
import com.primefactorsolutions.service.TimeOffRequestService; import com.primefactorsolutions.service.TimeOffRequestService;
import com.primefactorsolutions.views.admin.EmployeeReportView;
import com.primefactorsolutions.views.admin.EmployeesListView;
import com.vaadin.componentfactory.pdfviewer.PdfViewer; import com.vaadin.componentfactory.pdfviewer.PdfViewer;
import com.vaadin.flow.component.ClickEvent; import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;

View File

@ -1,6 +1,11 @@
package com.primefactorsolutions.views; package com.primefactorsolutions.views;
import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.model.Employee;
import com.primefactorsolutions.views.admin.EmployeesListView;
import com.primefactorsolutions.views.admin.TimeOffListView;
import com.primefactorsolutions.views.assessment.AssessmentsListView;
import com.primefactorsolutions.views.assessment.CandidatesListView;
import com.primefactorsolutions.views.assessment.QuestionsListView;
import com.primefactorsolutions.views.timeoff.TimeOffNewRequestView; import com.primefactorsolutions.views.timeoff.TimeOffNewRequestView;
import com.primefactorsolutions.views.timeoff.TimeOffPendingRequestsListView; import com.primefactorsolutions.views.timeoff.TimeOffPendingRequestsListView;
import com.primefactorsolutions.views.timeoff.TimeOffRequestListView; import com.primefactorsolutions.views.timeoff.TimeOffRequestListView;
@ -141,6 +146,8 @@ public class MainLayout extends AppLayout {
LineAwesomeIcon.USER_EDIT_SOLID.create())); LineAwesomeIcon.USER_EDIT_SOLID.create()));
admin.addItem(new SideNavItem("Documents", DocumentsListView.class, admin.addItem(new SideNavItem("Documents", DocumentsListView.class,
LineAwesomeIcon.FILE_ALT_SOLID.create())); LineAwesomeIcon.FILE_ALT_SOLID.create()));
admin.addItem(new SideNavItem("Calendario", TimeOffListView.class,
LineAwesomeIcon.CALENDAR.create()));
nav.addItem(admin); nav.addItem(admin);
SideNavItem recruiting = new SideNavItem("Recruiting"); SideNavItem recruiting = new SideNavItem("Recruiting");
@ -158,7 +165,7 @@ public class MainLayout extends AppLayout {
timeOff.setPrefixComponent(LineAwesomeIcon.PLANE_DEPARTURE_SOLID.create()); timeOff.setPrefixComponent(LineAwesomeIcon.PLANE_DEPARTURE_SOLID.create());
timeOff.addItem(new SideNavItem("Vacations", TimeOffRequestListView.class, timeOff.addItem(new SideNavItem("Vacations", TimeOffRequestListView.class,
LineAwesomeIcon.UMBRELLA_BEACH_SOLID.create())); LineAwesomeIcon.UMBRELLA_BEACH_SOLID.create()));
timeOff.addItem(new SideNavItem("Add Vacation", TimeOffNewRequestView.class, timeOff.addItem(new SideNavItem("Add TimeOff", TimeOffNewRequestView.class,
LineAwesomeIcon.CALENDAR_PLUS.create())); LineAwesomeIcon.CALENDAR_PLUS.create()));
if (isAdmin(authContext)) { if (isAdmin(authContext)) {

View File

@ -1,4 +1,4 @@
package com.primefactorsolutions.views; package com.primefactorsolutions.views.admin;
import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.model.Employee;
import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.EmployeeService;

View File

@ -1,7 +1,11 @@
package com.primefactorsolutions.views; package com.primefactorsolutions.views.admin;
import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.model.Employee;
import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.views.BaseView;
import com.primefactorsolutions.views.Constants;
import com.primefactorsolutions.views.EmployeeView;
import com.primefactorsolutions.views.MainLayout;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Anchor; import com.vaadin.flow.component.html.Anchor;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;

View File

@ -0,0 +1,135 @@
package com.primefactorsolutions.views.admin;
import com.primefactorsolutions.model.*;
import com.primefactorsolutions.service.TimeOffService;
import com.primefactorsolutions.views.BaseView;
import com.primefactorsolutions.views.MainLayout;
import com.primefactorsolutions.views.util.MenuBarUtils;
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.contextmenu.MenuItem;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.menubar.MenuBar;
import com.vaadin.flow.component.menubar.MenuBarVariant;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.data.provider.ListDataProvider;
import com.vaadin.flow.function.ValueProvider;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent;
import com.vaadin.flow.spring.security.AuthenticationContext;
import jakarta.annotation.security.PermitAll;
import org.springframework.context.annotation.Scope;
import org.vaadin.firitin.components.grid.VGrid;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;
import java.util.stream.IntStream;
@SpringComponent
@PermitAll
@Scope("prototype")
@PageTitle("Registro de Vacaciones")
@Route(value = "/time-off/list", layout = MainLayout.class)
public class TimeOffListView extends BaseView {
private final TimeOffService timeOffService;
private final VGrid<TimeOff> timeOffGrid = new VGrid<>();
private ComboBox<Integer> yearFilter;
public TimeOffListView(final AuthenticationContext authenticationContext,
final TimeOffService timeOffService) {
super(authenticationContext);
this.timeOffService = timeOffService;
initializeView();
}
private void refreshGridListHoursWorked(final Integer year) {
final List<TimeOff> timeOffs = timeOffService.findTimeOffs(year);
timeOffGrid.setDataProvider(new ListDataProvider<>(timeOffs));
timeOffGrid.getDataProvider().refreshAll();
}
private void initializeView() {
getCurrentPageLayout().add(createAddTimeOff());
setupFilters();
setupListHoursWorkedGrid();
getCurrentPageLayout().add(timeOffGrid);
refreshGridListHoursWorked(yearFilter.getValue());
}
private void setupFilters() {
final HorizontalLayout hl = new HorizontalLayout();
hl.add(createYearFilter());
getCurrentPageLayout().add(hl);
}
private ComboBox<Integer> createYearFilter() {
yearFilter = new ComboBox<>("Year");
final int nowYear = LocalDate.now().getYear();
final List<Integer> years = IntStream.range(0, 2).mapToObj(y -> nowYear - y).toList();
yearFilter.setItems(years);
yearFilter.setValue(years.getFirst());
yearFilter.addValueChangeListener(event ->
refreshGridListHoursWorked(event.getValue())
);
return yearFilter;
}
private void setupListHoursWorkedGrid() {
timeOffGrid.addColumn(e -> e.getCategory().name())
.setHeader("Categoria");
timeOffGrid.addColumn(e -> e.getType().name())
.setHeader("Tipo");
timeOffGrid.addColumn(TimeOff::getDate)
.setHeader("Fecha");
timeOffGrid.addColumn(TimeOff::getDuration).setHeader("Duracion");
timeOffGrid.addColumn(TimeOff::getExpiration).setHeader("Expiracion");
timeOffGrid.addComponentColumn((ValueProvider<TimeOff, Component>) timeOff -> {
final MenuBar menuBar = new MenuBar();
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
final MenuItem viewItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.EYE, "Ver");
viewItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
navigateToTimeOffView(timeOff.getId(), "view");
});
final MenuItem editItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.PENCIL, "Editar");
editItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
navigateToTimeOffView(timeOff.getId(), "edit");
});
return menuBar;
});
}
private void navigateToTimeOffView(final UUID idRecord, final String action) {
getUI().ifPresent(ui -> ui.navigate(TimeOffView.class, idRecord.toString() + "/" + action));
}
private Button createButton(final String label, final Runnable onClickAction, final boolean isPrimary) {
final Button button = new Button(label);
if (isPrimary) {
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
}
button.addClickListener(event -> onClickAction.run());
return button;
}
private Button createAddTimeOff() {
return createButton("Agregar Vacacion", this::navigateToTimeOff, true);
}
private void navigateToTimeOff() {
getUI().ifPresent(ui -> ui.navigate(TimeOffView.class, "new"));
}
}

View File

@ -0,0 +1,108 @@
package com.primefactorsolutions.views.admin;
import com.primefactorsolutions.model.TimeOff;
import com.primefactorsolutions.model.TimeOffRequestType;
import com.primefactorsolutions.service.TimeOffService;
import com.primefactorsolutions.views.MainLayout;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.router.*;
import com.vaadin.flow.spring.annotation.SpringComponent;
import jakarta.annotation.security.PermitAll;
import org.springframework.context.annotation.Scope;
import org.vaadin.firitin.components.datepicker.VDatePicker;
import org.vaadin.firitin.form.BeanValidationForm;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.List;
import java.util.UUID;
@SuppressWarnings("deprecation")
@SpringComponent
@PermitAll
@Scope("prototype")
@PageTitle("Vacaciones")
@Route(value = "/time-off/:hours-workedId?/:action?", layout = MainLayout.class)
public class TimeOffView extends BeanValidationForm<TimeOff> implements HasUrlParameter<String> {
private final ComboBox<TimeOffRequestType> category = new ComboBox<>("Categoria");
private final ComboBox<TimeOff.Type> type = new ComboBox<>("Tipo");
private final VDatePicker date = new VDatePicker("Fecha");
private final NumberField duration = new NumberField("Duracion");
private final NumberField expiration = new NumberField("Expiracion");
private final TimeOffService timeOffService;
public TimeOffView(final TimeOffService timeOffService) {
super(TimeOff.class);
this.timeOffService = timeOffService;
initializeDateField();
category.setItems(TimeOffRequestType.values());
type.setItems(TimeOff.Type.values());
this.setSavedHandler(this::saveTimeOff);
}
@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) || s == null) {
setEntityWithEnabledSave(new TimeOff());
} else {
final UUID timeOffId = UUID.fromString(s);
final TimeOff timeOff = timeOffService.getTimeOff(timeOffId);
if ("edit".equals(action) && !s.isEmpty()) {
setEntityWithEnabledSave(timeOff);
} else if ("view".equals(action) && !s.isEmpty()) {
setEntity(timeOff);
duration.setEnabled(false);
expiration.setEnabled(false);
category.setEnabled(false);
type.setEnabled(false);
date.setEnabled(false);
}
}
}
@Override
protected List<Component> getFormComponents() {
return List.of(
category,
type,
date,
duration,
expiration
);
}
private void initializeDateField() {
final LocalDate today = LocalDate.now();
final YearMonth currentMonth = YearMonth.of(today.getYear(), today.getMonth());
final LocalDate startOfMonth = currentMonth.atDay(1);
date.setWidthFull();
date.setMin(startOfMonth);
date.setMax(today);
date.setValue(today);
}
private void saveTimeOff(final TimeOff timeOff) {
if (isFormValid()) {
timeOffService.saveTimeOff(timeOff);
closeForm();
}
}
private void closeForm() {
getUI().ifPresent(ui -> ui.navigate(TimeOffListView.class));
}
private boolean isFormValid() {
return date.getValue() != null;
}
}

View File

@ -1,4 +1,4 @@
package com.primefactorsolutions.views; package com.primefactorsolutions.views.assessment;
import com.primefactorsolutions.model.Candidate; import com.primefactorsolutions.model.Candidate;
import com.primefactorsolutions.model.Assessment; import com.primefactorsolutions.model.Assessment;
@ -6,6 +6,7 @@ import com.primefactorsolutions.model.Question;
import com.primefactorsolutions.service.AssessmentService; import com.primefactorsolutions.service.AssessmentService;
import com.primefactorsolutions.service.QuestionService; import com.primefactorsolutions.service.QuestionService;
import com.primefactorsolutions.service.CandidateService; import com.primefactorsolutions.service.CandidateService;
import com.primefactorsolutions.views.MainLayout;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ItemLabelGenerator; import com.vaadin.flow.component.ItemLabelGenerator;
import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.combobox.ComboBox;

View File

@ -1,7 +1,10 @@
package com.primefactorsolutions.views; package com.primefactorsolutions.views.assessment;
import com.primefactorsolutions.model.Assessment; import com.primefactorsolutions.model.Assessment;
import com.primefactorsolutions.service.AssessmentService; import com.primefactorsolutions.service.AssessmentService;
import com.primefactorsolutions.views.BaseView;
import com.primefactorsolutions.views.MainLayout;
import com.primefactorsolutions.views.SubmissionView;
import com.vaadin.flow.component.ClickEvent; import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener; import com.vaadin.flow.component.ComponentEventListener;

View File

@ -1,7 +1,8 @@
package com.primefactorsolutions.views; package com.primefactorsolutions.views.assessment;
import com.primefactorsolutions.model.Candidate; import com.primefactorsolutions.model.Candidate;
import com.primefactorsolutions.service.CandidateService; import com.primefactorsolutions.service.CandidateService;
import com.primefactorsolutions.views.MainLayout;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.textfield.EmailField; import com.vaadin.flow.component.textfield.EmailField;
import com.vaadin.flow.router.BeforeEvent; import com.vaadin.flow.router.BeforeEvent;

View File

@ -1,7 +1,9 @@
package com.primefactorsolutions.views; package com.primefactorsolutions.views.assessment;
import com.primefactorsolutions.model.Candidate; import com.primefactorsolutions.model.Candidate;
import com.primefactorsolutions.service.CandidateService; import com.primefactorsolutions.service.CandidateService;
import com.primefactorsolutions.views.BaseView;
import com.primefactorsolutions.views.MainLayout;
import com.vaadin.flow.component.ClickEvent; import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener; import com.vaadin.flow.component.ComponentEventListener;

View File

@ -1,7 +1,8 @@
package com.primefactorsolutions.views; package com.primefactorsolutions.views.assessment;
import com.primefactorsolutions.model.Question; import com.primefactorsolutions.model.Question;
import com.primefactorsolutions.service.QuestionService; import com.primefactorsolutions.service.QuestionService;
import com.primefactorsolutions.views.MainLayout;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.textfield.IntegerField; import com.vaadin.flow.component.textfield.IntegerField;
import com.vaadin.flow.component.textfield.TextArea; import com.vaadin.flow.component.textfield.TextArea;

View File

@ -1,7 +1,9 @@
package com.primefactorsolutions.views; package com.primefactorsolutions.views.assessment;
import com.primefactorsolutions.model.Question; import com.primefactorsolutions.model.Question;
import com.primefactorsolutions.service.QuestionService; import com.primefactorsolutions.service.QuestionService;
import com.primefactorsolutions.views.BaseView;
import com.primefactorsolutions.views.MainLayout;
import com.vaadin.flow.component.ClickEvent; import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener; import com.vaadin.flow.component.ComponentEventListener;

View File

@ -3,7 +3,7 @@ package com.primefactorsolutions.views.timeoff;
import com.primefactorsolutions.model.*; import com.primefactorsolutions.model.*;
import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.service.TimeOffRequestService; import com.primefactorsolutions.service.TimeOffRequestService;
import com.primefactorsolutions.service.VacationService; import com.primefactorsolutions.service.TimeOffService;
import com.primefactorsolutions.views.MainLayout; import com.primefactorsolutions.views.MainLayout;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.combobox.ComboBox;
@ -44,10 +44,10 @@ public class TimeOffNewRequestView extends VerticalLayout {
private final TimeOffRequestService requestService; private final TimeOffRequestService requestService;
private final EmployeeService employeeService; private final EmployeeService employeeService;
private final VacationService vacationService; private final TimeOffService timeOffService;
private final Binder<TimeOffRequest> binder; private final Binder<TimeOffRequest> binder;
private Vacation vacation; private TimeOff timeoff;
private Employee employee; private Employee employee;
private LocalDate endDate; private LocalDate endDate;
@ -56,10 +56,10 @@ public class TimeOffNewRequestView extends VerticalLayout {
public TimeOffNewRequestView(final TimeOffRequestService requestService, public TimeOffNewRequestView(final TimeOffRequestService requestService,
final EmployeeService employeeService, final EmployeeService employeeService,
final VacationService vacationService) { final TimeOffService timeOffService) {
this.requestService = requestService; this.requestService = requestService;
this.employeeService = employeeService; this.employeeService = employeeService;
this.vacationService = vacationService; this.timeOffService = timeOffService;
this.binder = new Binder<>(TimeOffRequest.class); this.binder = new Binder<>(TimeOffRequest.class);
initializeView(); initializeView();
} }
@ -249,11 +249,11 @@ public class TimeOffNewRequestView extends VerticalLayout {
} }
private void updateAvailableDays(final TimeOffRequestType selectedCategory) { private void updateAvailableDays(final TimeOffRequestType selectedCategory) {
vacation = vacationService.findVacationByCategory(selectedCategory); timeoff = timeOffService.findVacationByCategory(selectedCategory);
UUID employeeId = employeeComboBox.getValue().getId(); UUID employeeId = employeeComboBox.getValue().getId();
List<TimeOffRequest> requests = requestService.findByEmployeeAndCategory(employeeId, selectedCategory); List<TimeOffRequest> requests = requestService.findByEmployeeAndCategory(employeeId, selectedCategory);
if (vacation != null) { if (timeoff != null) {
TimeOffRequest requestWithBalance = requests.stream() TimeOffRequest requestWithBalance = requests.stream()
.filter(request -> request.getDaysBalance() > 0 .filter(request -> request.getDaysBalance() > 0
&& request.getState() != TimeOffRequestStatus.VENCIDO && request.getState() != TimeOffRequestStatus.VENCIDO
@ -266,7 +266,7 @@ public class TimeOffNewRequestView extends VerticalLayout {
&& requestWithBalance.getDaysBalance() > 0) { && requestWithBalance.getDaysBalance() > 0) {
availableDaysField.setValue(requestWithBalance.getDaysBalance()); availableDaysField.setValue(requestWithBalance.getDaysBalance());
} else { } else {
availableDaysField.setValue(vacation.getDuration()); availableDaysField.setValue(timeoff.getDuration());
} }
} else if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ACTUAL } else if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ACTUAL
|| selectedCategory == TimeOffRequestType.VACACION_GESTION_ANTERIOR) { || selectedCategory == TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
@ -288,31 +288,31 @@ public class TimeOffNewRequestView extends VerticalLayout {
availableDaysField.setValue(0.0); availableDaysField.setValue(0.0);
} }
} else { } else {
availableDaysField.setValue(vacation.getDuration()); availableDaysField.setValue(timeoff.getDuration());
} }
setDatePickerLimits(vacation); setDatePickerLimits(timeoff);
} }
} }
private void setDatePickerLimits(final Vacation vacation) { private void setDatePickerLimits(final TimeOff timeoff) {
LocalDate startDate; LocalDate startDate;
endDate = null; endDate = null;
UUID employeeId = employee.getId(); UUID employeeId = employee.getId();
List<TimeOffRequest> previousRequests List<TimeOffRequest> previousRequests
= requestService.findByEmployeeAndCategory(employeeId, vacation.getCategory()); = requestService.findByEmployeeAndCategory(employeeId, timeoff.getCategory());
int startYear = calculateStartYear(previousRequests); int startYear = calculateStartYear(previousRequests);
startDate = determineStartDate(vacation, startYear); startDate = determineStartDate(timeoff, startYear);
if (startDate.isBefore(LocalDate.now())) { if (startDate.isBefore(LocalDate.now())) {
startDate = determineStartDate(vacation, startYear + 1); startDate = determineStartDate(timeoff, startYear + 1);
} }
if (startDate != null) { if (startDate != null) {
if (vacation.getExpiration() != null) { if (timeoff.getExpiration() != null) {
endDate = startDate.plusDays(vacation.getExpiration().intValue() - 1); endDate = startDate.plusDays(timeoff.getExpiration().intValue() - 1);
} else { } else {
endDate = LocalDate.of(startDate.getYear(), 12, 31); endDate = LocalDate.of(startDate.getYear(), 12, 31);
} }
@ -320,7 +320,7 @@ public class TimeOffNewRequestView extends VerticalLayout {
startDate = LocalDate.now(); startDate = LocalDate.now();
} }
setPickerValues(vacation, startDate); setPickerValues(timeoff, startDate);
setPickerLimits(startDate, endDate); setPickerLimits(startDate, endDate);
} }
@ -342,32 +342,28 @@ public class TimeOffNewRequestView extends VerticalLayout {
return Math.max(lastRequestYear, currentYear); return Math.max(lastRequestYear, currentYear);
} }
private LocalDate determineStartDate(final Vacation vacation, final int startYear) { private LocalDate determineStartDate(final TimeOff timeoff, final int startYear) {
if (vacation.getCategory() == TimeOffRequestType.CUMPLEAÑOS && employee.getBirthday() != null) { if (timeoff.getCategory() == TimeOffRequestType.CUMPLEAÑOS && employee.getBirthday() != null) {
return LocalDate.of(startYear, employee.getBirthday().getMonth(), employee.getBirthday().getDayOfMonth()); return LocalDate.of(startYear, employee.getBirthday().getMonth(), employee.getBirthday().getDayOfMonth());
} }
if (vacation.getMonthOfYear() != null && vacation.getDayOfMonth() != null) { if (timeoff.getDate() != null) {
return LocalDate.of(startYear, vacation.getMonthOfYear().intValue(), vacation.getDayOfMonth().intValue()); return LocalDate.of(startYear, timeoff.getDate().getMonthValue(), timeoff.getDate().getDayOfMonth());
}
if (vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD) {
return LocalDate.now();
} }
return LocalDate.now(); return LocalDate.now();
} }
private void setPickerValues(final Vacation vacation, final LocalDate startDate) { private void setPickerValues(final TimeOff timeoff, final LocalDate startDate) {
startDatePicker.setValue(startDate); startDatePicker.setValue(startDate);
if ((vacation.getDuration() != null && vacation.getDuration() == 0.5) if ((timeoff.getDuration() != null && timeoff.getDuration() == 0.5)
|| vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD || timeoff.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD
|| vacation.getCategory() == TimeOffRequestType.CUMPLEAÑOS) { || timeoff.getCategory() == TimeOffRequestType.CUMPLEAÑOS) {
endDatePicker.setValue(startDate); endDatePicker.setValue(startDate);
} else { } else {
int durationDays = (vacation.getDuration() != null ? vacation.getDuration().intValue() - 1 : 0); int durationDays = (timeoff.getDuration() != null ? timeoff.getDuration().intValue() - 1 : 0);
endDatePicker.setValue(startDate.plusDays(durationDays)); endDatePicker.setValue(startDate.plusDays(durationDays));
} }
} }
@ -442,12 +438,12 @@ public class TimeOffNewRequestView extends VerticalLayout {
} }
private void setDaysToBeTakenField(final double daysToBeTaken) { private void setDaysToBeTakenField(final double daysToBeTaken) {
if (vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD if (timeoff.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD
|| vacation.getCategory() == TimeOffRequestType.CUMPLEAÑOS || timeoff.getCategory() == TimeOffRequestType.CUMPLEAÑOS
|| vacation.getCategory() == TimeOffRequestType.DIA_DEL_PADRE || timeoff.getCategory() == TimeOffRequestType.DIA_DEL_PADRE
|| vacation.getCategory() == TimeOffRequestType.DIA_DE_LA_MADRE || timeoff.getCategory() == TimeOffRequestType.DIA_DE_LA_MADRE
|| vacation.getCategory() == TimeOffRequestType.DIA_DE_LA_MUJER_INTERNACIONAL || timeoff.getCategory() == TimeOffRequestType.DIA_DE_LA_MUJER_INTERNACIONAL
|| vacation.getCategory() == TimeOffRequestType.DIA_DE_LA_MUJER_NACIONAL) { || timeoff.getCategory() == TimeOffRequestType.DIA_DE_LA_MUJER_NACIONAL) {
daysToBeTakenField.setValue(0.5); daysToBeTakenField.setValue(0.5);
} else { } else {
daysToBeTakenField.setValue(daysToBeTaken); daysToBeTakenField.setValue(daysToBeTaken);

View File

@ -4,7 +4,7 @@ import com.primefactorsolutions.model.*;
import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.service.TeamService; import com.primefactorsolutions.service.TeamService;
import com.primefactorsolutions.service.TimeOffRequestService; import com.primefactorsolutions.service.TimeOffRequestService;
import com.primefactorsolutions.service.VacationService; import com.primefactorsolutions.service.TimeOffService;
import com.primefactorsolutions.views.BaseView; import com.primefactorsolutions.views.BaseView;
import com.primefactorsolutions.views.MainLayout; import com.primefactorsolutions.views.MainLayout;
import com.vaadin.flow.component.ClickEvent; import com.vaadin.flow.component.ClickEvent;
@ -53,7 +53,7 @@ public class TimeOffRequestListView extends BaseView {
private final TimeOffRequestService requestService; private final TimeOffRequestService requestService;
private final EmployeeService employeeService; private final EmployeeService employeeService;
private final TeamService teamService; private final TeamService teamService;
private final VacationService vacationService; private final TimeOffService timeOffService;
private final PagingGrid<Employee> requestGrid = new PagingGrid<>(); private final PagingGrid<Employee> requestGrid = new PagingGrid<>();
private ComboBox<Employee> employeeFilter; private ComboBox<Employee> employeeFilter;
private ComboBox<Team> teamFilter; private ComboBox<Team> teamFilter;
@ -65,12 +65,12 @@ public class TimeOffRequestListView extends BaseView {
final TimeOffRequestService requestService, final TimeOffRequestService requestService,
final EmployeeService employeeService, final EmployeeService employeeService,
final TeamService teamService, final TeamService teamService,
final VacationService vacationService) { final TimeOffService timeOffService) {
super(authenticationContext); super(authenticationContext);
this.requestService = requestService; this.requestService = requestService;
this.employeeService = employeeService; this.employeeService = employeeService;
this.teamService = teamService; this.teamService = teamService;
this.vacationService = vacationService; this.timeOffService = timeOffService;
initializeView(); initializeView();
refreshGeneralRequestGrid(null, null, null, null); refreshGeneralRequestGrid(null, null, null, null);
} }
@ -199,7 +199,7 @@ public class TimeOffRequestListView extends BaseView {
private String getGeneralTotal(final Employee employee) { private String getGeneralTotal(final Employee employee) {
List<TimeOffRequest> employeeRequests = requestService.findRequestsByEmployeeId(employee.getId()); List<TimeOffRequest> employeeRequests = requestService.findRequestsByEmployeeId(employee.getId());
List<Vacation> vacations = vacationService.findVacations(); List<TimeOff> timeOffs = timeOffService.findVacations();
List<Double> vacationDays = calculateVacationDays(employee); List<Double> vacationDays = calculateVacationDays(employee);
@ -223,7 +223,7 @@ public class TimeOffRequestListView extends BaseView {
double totalUtilized = calculateTotalUtilized(employeeRequests); double totalUtilized = calculateTotalUtilized(employeeRequests);
double totalVacations = totalVacationCurrentDays + totalVacationPreviousDays; double totalVacations = totalVacationCurrentDays + totalVacationPreviousDays;
double totalAvailable = calculateTotalAvailable(vacations, employeeRequests, employee); double totalAvailable = calculateTotalAvailable(timeOffs, employeeRequests, employee);
double generalTotal = totalAvailable + totalVacations - totalUtilized; double generalTotal = totalAvailable + totalVacations - totalUtilized;
@ -320,7 +320,7 @@ public class TimeOffRequestListView extends BaseView {
return vacationDays; return vacationDays;
} }
private double calculateTotalAvailable(final List<Vacation> vacations, final List<TimeOffRequest> employeeRequests, private double calculateTotalAvailable(final List<TimeOff> timeOffs, final List<TimeOffRequest> employeeRequests,
final Employee employee) { final Employee employee) {
Set<TimeOffRequestType> excludedCategories = getExcludedCategories(); Set<TimeOffRequestType> excludedCategories = getExcludedCategories();
Set<TimeOffRequestType> genderSpecificExclusions = getGenderSpecificExclusions(); Set<TimeOffRequestType> genderSpecificExclusions = getGenderSpecificExclusions();
@ -335,7 +335,7 @@ public class TimeOffRequestListView extends BaseView {
healthLicence = healthRequests.getLast().getDaysBalance(); healthLicence = healthRequests.getLast().getDaysBalance();
} }
double totalAvailable = vacations.stream() double totalAvailable = timeOffs.stream()
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(vacation -> vacation.getCategory() != TimeOffRequestType.PERMISOS_DE_SALUD) .filter(vacation -> vacation.getCategory() != TimeOffRequestType.PERMISOS_DE_SALUD)
.filter(vacation -> shouldIncludeVacation( .filter(vacation -> shouldIncludeVacation(
@ -364,17 +364,17 @@ public class TimeOffRequestListView extends BaseView {
return 0; return 0;
} }
private boolean shouldIncludeVacation(final Vacation vacation, private boolean shouldIncludeVacation(final TimeOff timeoff,
final Set<TimeOffRequestType> excludedCategories, final Set<TimeOffRequestType> excludedCategories,
final Set<TimeOffRequestType> genderSpecificExclusions, final Set<TimeOffRequestType> genderSpecificExclusions,
final Employee employee, final Employee employee,
final Set<TimeOffRequestType> employeeRequestCategories) { final Set<TimeOffRequestType> employeeRequestCategories) {
if (excludedCategories.contains(vacation.getCategory()) if (excludedCategories.contains(timeoff.getCategory())
&& !employeeRequestCategories.contains(vacation.getCategory())) { && !employeeRequestCategories.contains(timeoff.getCategory())) {
return false; return false;
} }
return isFemale(employee) || !genderSpecificExclusions.contains(vacation.getCategory()); return isFemale(employee) || !genderSpecificExclusions.contains(timeoff.getCategory());
} }
private boolean isFemale(final Employee employee) { private boolean isFemale(final Employee employee) {

View File

@ -2,15 +2,12 @@ package com.primefactorsolutions.views.timeoff;
import com.primefactorsolutions.model.*; import com.primefactorsolutions.model.*;
import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.service.TeamService;
import com.primefactorsolutions.service.TimeOffRequestService; import com.primefactorsolutions.service.TimeOffRequestService;
import com.primefactorsolutions.views.MainLayout; import com.primefactorsolutions.views.MainLayout;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.datepicker.DatePicker; import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.html.H3; import com.vaadin.flow.component.html.H3;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.textfield.NumberField; import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.router.*; import com.vaadin.flow.router.*;
import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.annotation.SpringComponent;
@ -21,6 +18,7 @@ import org.vaadin.firitin.form.BeanValidationForm;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@SuppressWarnings("deprecation")
@SpringComponent @SpringComponent
@PermitAll @PermitAll
@Scope("prototype") @Scope("prototype")
@ -40,15 +38,14 @@ public class TimeOffRequestView extends BeanValidationForm<TimeOffRequest> imple
private TimeOffRequest request; private TimeOffRequest request;
private Employee employee; private Employee employee;
private Button saveButton;
public TimeOffRequestView(final TimeOffRequestService requestService, public TimeOffRequestView(final TimeOffRequestService requestService,
final EmployeeService employeeService, final EmployeeService employeeService) {
final TeamService teamService) {
super(TimeOffRequest.class); super(TimeOffRequest.class);
this.requestService = requestService; this.requestService = requestService;
this.employeeService = employeeService; this.employeeService = employeeService;
state.setItems(List.of(TimeOffRequestStatus.values())); state.setItems(List.of(TimeOffRequestStatus.values()));
this.setSavedHandler(this::saveRequest);
} }
@Override @Override
@ -80,23 +77,10 @@ public class TimeOffRequestView extends BeanValidationForm<TimeOffRequest> imple
startDate, startDate,
endDate, endDate,
availableDays, availableDays,
daysToBeTake, daysToBeTake
createCloseButton()
); );
} }
protected Button createSaveButton() {
saveButton = new Button("Guardar");
saveButton.addClickListener(event -> saveRequest());
return saveButton;
}
protected Button createCloseButton() {
Button closeButton = new Button("Salir");
closeButton.addClickListener(event -> closeForm());
return closeButton;
}
private void setFieldsReadOnly(final boolean option) { private void setFieldsReadOnly(final boolean option) {
state.setReadOnly(option); state.setReadOnly(option);
expiration.setReadOnly(option); expiration.setReadOnly(option);
@ -106,12 +90,10 @@ public class TimeOffRequestView extends BeanValidationForm<TimeOffRequest> imple
daysToBeTake.setReadOnly(option); daysToBeTake.setReadOnly(option);
} }
private void saveRequest() { private void saveRequest(final TimeOffRequest request) {
if (isFormValid()) { if (isFormValid()) {
TimeOffRequest request = getEntity();
setRequestFieldValues(request); setRequestFieldValues(request);
requestService.saveTimeOffRequest(request); requestService.saveTimeOffRequest(request);
Notification.show("Solicitud guardada correctamente.");
closeForm(); closeForm();
} }
} }
@ -143,7 +125,6 @@ public class TimeOffRequestView extends BeanValidationForm<TimeOffRequest> imple
setFieldsReadOnly(false); setFieldsReadOnly(false);
} else if ("view".equals(action) && !request.getId().toString().isEmpty()) { } else if ("view".equals(action) && !request.getId().toString().isEmpty()) {
setFieldsReadOnly(true); setFieldsReadOnly(true);
saveButton.setEnabled(false);
} }
} }

View File

@ -3,7 +3,7 @@ package com.primefactorsolutions.views.timeoff;
import com.primefactorsolutions.model.*; import com.primefactorsolutions.model.*;
import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.service.TimeOffRequestService; import com.primefactorsolutions.service.TimeOffRequestService;
import com.primefactorsolutions.service.VacationService; import com.primefactorsolutions.service.TimeOffService;
import com.primefactorsolutions.views.BaseView; import com.primefactorsolutions.views.BaseView;
import com.primefactorsolutions.views.MainLayout; import com.primefactorsolutions.views.MainLayout;
import com.vaadin.flow.component.ClickEvent; import com.vaadin.flow.component.ClickEvent;
@ -59,7 +59,7 @@ public class TimeOffRequestsByEmployeeView extends BaseView implements HasUrlPar
private final TimeOffRequestService requestService; private final TimeOffRequestService requestService;
private final EmployeeService employeeService; private final EmployeeService employeeService;
private final VacationService vacationService; private final TimeOffService timeOffService;
private final PagingGrid<TimeOffRequest> requestGrid = new PagingGrid<>(TimeOffRequest.class); private final PagingGrid<TimeOffRequest> requestGrid = new PagingGrid<>(TimeOffRequest.class);
private List<TimeOffRequest> requests = Collections.emptyList(); private List<TimeOffRequest> requests = Collections.emptyList();
private ComboBox<TimeOffRequestType> categoryFilter; private ComboBox<TimeOffRequestType> categoryFilter;
@ -72,11 +72,11 @@ public class TimeOffRequestsByEmployeeView extends BaseView implements HasUrlPar
public TimeOffRequestsByEmployeeView(final AuthenticationContext authenticationContext, public TimeOffRequestsByEmployeeView(final AuthenticationContext authenticationContext,
final TimeOffRequestService requestService, final TimeOffRequestService requestService,
final EmployeeService employeeService, final EmployeeService employeeService,
final VacationService vacationService) { final TimeOffService timeOffService) {
super(authenticationContext); super(authenticationContext);
this.requestService = requestService; this.requestService = requestService;
this.employeeService = employeeService; this.employeeService = employeeService;
this.vacationService = vacationService; this.timeOffService = timeOffService;
} }
private void initializeView() { private void initializeView() {
@ -166,12 +166,12 @@ public class TimeOffRequestsByEmployeeView extends BaseView implements HasUrlPar
int currentYear = LocalDate.now().getYear(); int currentYear = LocalDate.now().getYear();
LocalDate currentDate = LocalDate.now(); LocalDate currentDate = LocalDate.now();
List<Vacation> vacations = vacationService.findVacations(); List<TimeOff> timeOffs = timeOffService.findVacations();
double healthLicence = getHealthLicence(employeeId); double healthLicence = getHealthLicence(employeeId);
double totalFixedAndMovableHolidays = calculateHolidayDays(vacations); double totalFixedAndMovableHolidays = calculateHolidayDays(timeOffs);
double totalPersonalDays = calculatePersonalDays(vacations, isMale); double totalPersonalDays = calculatePersonalDays(timeOffs, isMale);
List<Double> vacationDays = calculateVacationDays(employee); List<Double> vacationDays = calculateVacationDays(employee);
double totalVacationCurrentDays = calculateUtilizedVacationDays( double totalVacationCurrentDays = calculateUtilizedVacationDays(
@ -261,21 +261,21 @@ public class TimeOffRequestsByEmployeeView extends BaseView implements HasUrlPar
return 0; return 0;
} }
private double calculateHolidayDays(final List<Vacation> vacations) { private double calculateHolidayDays(final List<TimeOff> timeOffs) {
return vacations.stream() return timeOffs.stream()
.filter(req -> req.getType() != Vacation.Type.OTHER) .filter(req -> req.getType() != TimeOff.Type.OTHER)
.mapToDouble(Vacation::getDuration) .mapToDouble(TimeOff::getDuration)
.sum(); .sum();
} }
private double calculatePersonalDays(final List<Vacation> vacations, final boolean isMale) { private double calculatePersonalDays(final List<TimeOff> timeOffs, final boolean isMale) {
return vacations.stream() return timeOffs.stream()
.filter(req -> req.getType() == Vacation.Type.OTHER) .filter(req -> req.getType() == TimeOff.Type.OTHER)
.filter(req -> !getStandardExclusions().contains(req.getCategory())) .filter(req -> !getStandardExclusions().contains(req.getCategory()))
.filter(req -> !(isMale && getMaleSpecificExclusions().contains(req.getCategory()))) .filter(req -> !(isMale && getMaleSpecificExclusions().contains(req.getCategory())))
.filter(req -> !req.getCategory().name().startsWith("VACACION")) .filter(req -> !req.getCategory().name().startsWith("VACACION"))
.filter(req -> req.getCategory() != TimeOffRequestType.PERMISOS_DE_SALUD) .filter(req -> req.getCategory() != TimeOffRequestType.PERMISOS_DE_SALUD)
.mapToDouble(Vacation::getDuration) .mapToDouble(TimeOff::getDuration)
.sum(); .sum();
} }
@ -372,8 +372,8 @@ public class TimeOffRequestsByEmployeeView extends BaseView implements HasUrlPar
} }
private Boolean verificationIsHoliday(final TimeOffRequest request) { private Boolean verificationIsHoliday(final TimeOffRequest request) {
Vacation vacation = vacationService.findVacationByCategory(request.getCategory()); TimeOff timeoff = timeOffService.findVacationByCategory(request.getCategory());
return vacation.getType() != Vacation.Type.OTHER; return timeoff.getType() != TimeOff.Type.OTHER;
} }
private void navigateToEditRequest(final TimeOffRequest request) { private void navigateToEditRequest(final TimeOffRequest request) {
@ -449,11 +449,11 @@ public class TimeOffRequestsByEmployeeView extends BaseView implements HasUrlPar
} }
private boolean isVacationExpired(final TimeOffRequest request) { private boolean isVacationExpired(final TimeOffRequest request) {
Vacation vacation = vacationService.findVacationByCategory(request.getCategory()); TimeOff timeoff = timeOffService.findVacationByCategory(request.getCategory());
if (vacation != null && vacation.getMonthOfYear() != null && vacation.getDayOfMonth() != null) { if (timeoff != null && timeoff.getDate() != null) {
int vacationMonth = vacation.getMonthOfYear(); int vacationMonth = timeoff.getDate().getMonthValue();
int vacationDay = vacation.getDayOfMonth(); int vacationDay = timeoff.getDate().getDayOfMonth();
int currentMonth = LocalDate.now().getMonthValue(); int currentMonth = LocalDate.now().getMonthValue();
int currentDay = LocalDate.now().getDayOfMonth(); int currentDay = LocalDate.now().getDayOfMonth();
@ -533,8 +533,8 @@ public class TimeOffRequestsByEmployeeView extends BaseView implements HasUrlPar
String endDate = getDateString(request.getEndDate()); String endDate = getDateString(request.getEndDate());
String[] rowData = { String[] rowData = {
request.getCategory().name() != null ? request.getCategory().name() : "", request.getCategory().name(),
request.getState().name() != null ? request.getState().name() : "", request.getState().name(),
startDate, startDate,
endDate, endDate,
String.valueOf(request.getDaysToBeTake() != null ? request.getDaysToBeTake() : 0) String.valueOf(request.getDaysToBeTake() != null ? request.getDaysToBeTake() : 0)

View File

@ -10,7 +10,6 @@ import com.primefactorsolutions.views.MainLayout;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.textfield.NumberField; import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.component.textfield.TextField; 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.combobox.ComboBox;
import com.vaadin.flow.router.*; import com.vaadin.flow.router.*;
import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.annotation.SpringComponent;
@ -34,13 +33,11 @@ import java.util.stream.Collectors;
@Route(value = "/timesheet/:hours-workedId?/:action?", layout = MainLayout.class) @Route(value = "/timesheet/:hours-workedId?/:action?", layout = MainLayout.class)
public class TimesheetEntryView extends BeanValidationForm<TimesheetEntry> implements HasUrlParameter<String> { public class TimesheetEntryView extends BeanValidationForm<TimesheetEntry> implements HasUrlParameter<String> {
private final ComboBox<Team> team = new ComboBox<>("Equipo"); private final ComboBox<Team> team = new ComboBox<>("Equipo");
private ComboBox<Employee> employee; private final ComboBox<Employee> employee = new ComboBox<>("Empleado");
private final ComboBox<String> task = new ComboBox<>("Tarea"); private final ComboBox<String> task = new ComboBox<>("Tarea");
private final TextField details = new TextField("Detalle"); private final TextField details = new TextField("Detalle");
private final VDatePicker date = new VDatePicker("Fecha"); private final VDatePicker date = new VDatePicker("Fecha");
private final NumberField hours = new NumberField("Horas"); private final NumberField hours = new NumberField("Horas");
private Button saveButton;
private final TimesheetService timesheetService; private final TimesheetService timesheetService;
private final EmployeeService employeeService; private final EmployeeService employeeService;
@ -62,6 +59,8 @@ public class TimesheetEntryView extends BeanValidationForm<TimesheetEntry> imple
initializeTeamField(); initializeTeamField();
initializeEmployeeField(); initializeEmployeeField();
configureTasks(); configureTasks();
this.setSavedHandler(this::saveHoursWorked);
} }
@Override @Override
@ -73,13 +72,18 @@ public class TimesheetEntryView extends BeanValidationForm<TimesheetEntry> imple
setEntityWithEnabledSave(new TimesheetEntry()); setEntityWithEnabledSave(new TimesheetEntry());
} else { } else {
final UUID hoursWorkedId = UUID.fromString(s); final UUID hoursWorkedId = UUID.fromString(s);
timesheetEntry = timesheetService.getHoursWorked(hoursWorkedId); timesheetEntry = timesheetService.getTimesheetEntry(hoursWorkedId);
setEntityWithEnabledSave(timesheetEntry);
if ("edit".equals(action) && !s.isEmpty()) { if ("edit".equals(action) && !s.isEmpty()) {
saveButton.setVisible(true); setEntityWithEnabledSave(timesheetEntry);
} else if ("view".equals(action) && !s.isEmpty()) { } else if ("view".equals(action) && !s.isEmpty()) {
saveButton.setVisible(false); setEntity(timesheetEntry);
employee.setEnabled(false);
team.setEnabled(false);
task.setEnabled(false);
details.setEnabled(false);
date.setEnabled(false);
hours.setEnabled(false);
} }
} }
} }
@ -92,12 +96,12 @@ public class TimesheetEntryView extends BeanValidationForm<TimesheetEntry> imple
employee, employee,
task, task,
details, details,
hours, hours
createCloseButton()
); );
} }
private void configureTasks() { private void configureTasks() {
task.setWidthFull();
task.setItems( task.setItems(
"Entrevistas", "Entrevistas",
"Reuniones", "Reuniones",
@ -111,19 +115,8 @@ public class TimesheetEntryView extends BeanValidationForm<TimesheetEntry> imple
task.setPlaceholder("Selecciona una tarea..."); task.setPlaceholder("Selecciona una tarea...");
} }
protected Button createSaveButton() {
saveButton = new Button("Guardar");
saveButton.addClickListener(event -> saveHoursWorked());
return saveButton;
}
protected Button createCloseButton() {
final Button closeButton = new Button("Cancelar");
closeButton.addClickListener(event -> closeForm());
return closeButton;
}
private void initializeTeamField() { private void initializeTeamField() {
team.setWidthFull();
team.setItems(teamService.findAllTeams()); team.setItems(teamService.findAllTeams());
team.setItemLabelGenerator(Team::getName); team.setItemLabelGenerator(Team::getName);
team.setValue(null); team.setValue(null);
@ -148,14 +141,15 @@ public class TimesheetEntryView extends BeanValidationForm<TimesheetEntry> imple
} }
private void initializeEmployeeField() { private void initializeEmployeeField() {
employee = new ComboBox<>("Empleado");
List<Employee> employees = new ArrayList<>(employeeService.findAllEmployees()); List<Employee> employees = new ArrayList<>(employeeService.findAllEmployees());
employee.setWidthFull();
employee.setItems(employees); employee.setItems(employees);
employee.setItemLabelGenerator(this::getEmployeeFullName); employee.setItemLabelGenerator(TimesheetEntryView::getEmployeeFullName);
employee.setValue(null); employee.setValue(null);
employee.setRequired(true);
} }
private String getEmployeeFullName(final Employee employee) { private static String getEmployeeFullName(final Employee employee) {
return employee.getFirstName() + " " + employee.getLastName(); return employee.getFirstName() + " " + employee.getLastName();
} }
@ -164,34 +158,19 @@ public class TimesheetEntryView extends BeanValidationForm<TimesheetEntry> imple
final YearMonth currentMonth = YearMonth.of(today.getYear(), today.getMonth()); final YearMonth currentMonth = YearMonth.of(today.getYear(), today.getMonth());
final LocalDate startOfMonth = currentMonth.atDay(1); final LocalDate startOfMonth = currentMonth.atDay(1);
date.setWidthFull();
date.setMin(startOfMonth); date.setMin(startOfMonth);
date.setMax(today); date.setMax(today);
date.setValue(today); date.setValue(today);
} }
private void saveHoursWorked() { private void saveHoursWorked(final TimesheetEntry timesheetEntry) {
if (isFormValid()) { if (isFormValid()) {
final TimesheetEntry timesheetEntry = getEntity();
final String details = this.details.getValue();
final String task = this.task.getValue();
timesheetEntry.setDetails(details);
timesheetEntry.setTask(task);
setFieldValues(timesheetEntry);
timesheetService.save(timesheetEntry); timesheetService.save(timesheetEntry);
closeForm(); closeForm();
} }
} }
private void setFieldValues(final TimesheetEntry timesheetEntry) {
timesheetEntry.setDate(date.getValue());
timesheetEntry.setTeam(team.getValue());
timesheetEntry.setEmployee(employee.getValue());
timesheetEntry.setDetails(details.getValue());
timesheetEntry.setHours(hours.getValue());
}
private void closeForm() { private void closeForm() {
getUI().ifPresent(ui -> ui.navigate(TimesheetListView.class)); getUI().ifPresent(ui -> ui.navigate(TimesheetListView.class));
} }

View File

@ -3,6 +3,7 @@ package com.primefactorsolutions.views.timesheet;
import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.model.Employee;
import com.primefactorsolutions.model.TimesheetEntry; import com.primefactorsolutions.model.TimesheetEntry;
import com.primefactorsolutions.model.Team; import com.primefactorsolutions.model.Team;
import com.primefactorsolutions.model.Week;
import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.service.TimesheetService; import com.primefactorsolutions.service.TimesheetService;
import com.primefactorsolutions.service.TeamService; import com.primefactorsolutions.service.TeamService;
@ -13,6 +14,7 @@ import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener; import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.contextmenu.MenuItem; import com.vaadin.flow.component.contextmenu.MenuItem;
import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.icon.VaadinIcon;
@ -46,6 +48,7 @@ public class TimesheetListView extends BaseView {
private final PagingGrid<TimesheetEntry> timesheetPagingGrid = new PagingGrid<>(); private final PagingGrid<TimesheetEntry> timesheetPagingGrid = new PagingGrid<>();
private ComboBox<Employee> employeeFilter; private ComboBox<Employee> employeeFilter;
private ComboBox<Team> teamFilter; private ComboBox<Team> teamFilter;
private ComboBox<Week> weekFilter;
public TimesheetListView(final AuthenticationContext authenticationContext, public TimesheetListView(final AuthenticationContext authenticationContext,
final TimesheetService timesheetService, final TimesheetService timesheetService,
@ -57,14 +60,14 @@ public class TimesheetListView extends BaseView {
this.teamService = teamService; this.teamService = teamService;
initializeView(); initializeView();
refreshGridListHoursWorked(null, null);
} }
private void refreshGridListHoursWorked(final Employee employee, private void refreshGridListHoursWorked(final Employee employee,
final Team team) { final Team team,
final Week week) {
timesheetPagingGrid.setPagingDataProvider((page, pageSize) -> { timesheetPagingGrid.setPagingDataProvider((page, pageSize) -> {
final int start = (int) (page * timesheetPagingGrid.getPageSize()); final int start = (int) (page * timesheetPagingGrid.getPageSize());
return fetchFilteredHoursWorked(start, pageSize, employee, team); return fetchFilteredHoursWorked(start, pageSize, employee, team, week);
}); });
timesheetPagingGrid.getDataProvider().refreshAll(); timesheetPagingGrid.getDataProvider().refreshAll();
} }
@ -72,19 +75,21 @@ public class TimesheetListView extends BaseView {
private List<TimesheetEntry> fetchFilteredHoursWorked(final int start, private List<TimesheetEntry> fetchFilteredHoursWorked(final int start,
final int pageSize, final int pageSize,
final Employee employee, final Employee employee,
final Team team) { final Team team,
List<TimesheetEntry> filteredTimesheetEntry = timesheetService.findAll(); final Week week) {
List<TimesheetEntry> filteredTimesheetEntry = timesheetService.findListHoursWorkedEmployee(week.from(),
week.to());
if (employee != null) { if (employee != null) {
filteredTimesheetEntry = filteredTimesheetEntry.stream() filteredTimesheetEntry = filteredTimesheetEntry.stream()
.filter(hw -> hw.getEmployee().getId().equals(employee.getId())) .filter(e -> e.getEmployee().getId().equals(employee.getId()))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
if (team != null) { if (team != null) {
filteredTimesheetEntry = filteredTimesheetEntry.stream() filteredTimesheetEntry = filteredTimesheetEntry.stream()
.filter(hw -> hw.getEmployee().getTeam() != null .filter(e -> e.getEmployee().getTeam() != null
&& hw.getEmployee().getTeam().getId().equals(team.getId())) && e.getEmployee().getTeam().getId().equals(team.getId()))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@ -98,10 +103,12 @@ public class TimesheetListView extends BaseView {
setupFilters(); setupFilters();
setupListHoursWorkedGrid(); setupListHoursWorkedGrid();
getCurrentPageLayout().add(timesheetPagingGrid); getCurrentPageLayout().add(timesheetPagingGrid);
refreshGridListHoursWorked(employeeFilter.getValue(), teamFilter.getValue(), weekFilter.getValue());
} }
private void setupFilters() { private void setupFilters() {
final HorizontalLayout hl = new HorizontalLayout(); final HorizontalLayout hl = new HorizontalLayout();
hl.add(createWeekFilter());
hl.add(createEmployeeFilter()); hl.add(createEmployeeFilter());
hl.add(createTeamFilter()); hl.add(createTeamFilter());
@ -109,38 +116,32 @@ public class TimesheetListView extends BaseView {
} }
private void setupListHoursWorkedGrid() { private void setupListHoursWorkedGrid() {
timesheetPagingGrid.addColumn(hw -> hw.getDate() != null ? hw.getDate().toString() : "") timesheetPagingGrid.addColumn(e -> e.getDate() != null ? e.getDate().toString() : "")
.setHeader("Fecha") .setHeader("Fecha")
.setSortable(true); .setSortable(true);
timesheetPagingGrid.addColumn(TimesheetEntry::getWeekNumber) timesheetPagingGrid.addColumn(e -> e.getEmployee().getFirstName() + " " + e.getEmployee().getLastName())
.setHeader("Semana")
.setSortable(true);
timesheetPagingGrid.addColumn(hw -> hw.getEmployee().getFirstName() + " " + hw.getEmployee().getLastName())
.setHeader("Empleado"); .setHeader("Empleado");
timesheetPagingGrid.addColumn(hw -> hw.getEmployee().getTeam() != null ? hw.getEmployee().getTeam() timesheetPagingGrid.addColumn(e -> e.getEmployee().getTeam() != null
.getName() : "Sin asignar") ? e.getEmployee().getTeam().getName()
: "Sin asignar")
.setHeader("Equipo"); .setHeader("Equipo");
timesheetPagingGrid.addColumn(hw -> { timesheetPagingGrid.addColumn(e -> {
String details = hw.getDetails() != null ? hw.getDetails() : "Sin Detalle"; String details = e.getDetails() != null ? e.getDetails() : "Sin Detalle";
String task = hw.getTask() != null ? hw.getTask() : ""; String task = e.getTask() != null ? e.getTask() : "";
return !task.isEmpty() ? task : details; return !task.isEmpty() ? task : details;
}).setHeader("Details"); }).setHeader("Details");
timesheetPagingGrid.addColumn(hw -> { timesheetPagingGrid.addColumn(TimesheetEntry::getHours).setHeader("Horas").setSortable(true);
if (hw.getTask() != null && !hw.getTask().isEmpty()) {
return calculateHoursPerTask(hw);
} else {
return 0.0;
}
}).setHeader("Total Horas").setSortable(true);
timesheetPagingGrid.addColumn(hw -> 40 - calculateTotal(hw)).setHeader("Horas Pendientes") timesheetPagingGrid.addComponentColumn((ValueProvider<TimesheetEntry, Component>) entry -> {
.setSortable(true);
timesheetPagingGrid.addComponentColumn((ValueProvider<TimesheetEntry, Component>) hoursWorked -> {
final MenuBar menuBar = new MenuBar(); final MenuBar menuBar = new MenuBar();
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE); menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
final MenuItem viewItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.EYE, "Ver"); final MenuItem viewItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.EYE, "Ver");
viewItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> { viewItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
navigateToHoursWorkedView(hoursWorked.getId()); navigateToTimesheetEntryView(entry.getId(), "view");
});
final MenuItem editItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.PENCIL, "Editar");
editItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
navigateToTimesheetEntryView(entry.getId(), "edit");
}); });
return menuBar; return menuBar;
}); });
@ -149,41 +150,24 @@ public class TimesheetListView extends BaseView {
timesheetPagingGrid.setPageSize(PAGE_SIZE); timesheetPagingGrid.setPageSize(PAGE_SIZE);
} }
private double calculateHoursPerTask(final TimesheetEntry timesheetEntry) { private void navigateToTimesheetEntryView(final UUID idRecord, final String action) {
final List<TimesheetEntry> tasks = timesheetService.findListHoursWorkedEmployee( getUI().ifPresent(ui -> ui.navigate(TimesheetEntryView.class, idRecord.toString() + "/" + action));
timesheetEntry.getEmployee().getId(), timesheetEntry.getWeekNumber());
return tasks.stream()
.filter(hw -> Objects.equals(hw.getTask(), timesheetEntry.getTask()))
.mapToDouble(TimesheetEntry::getHours)
.sum();
} }
private void navigateToHoursWorkedView(final UUID idRecord) { private Button createButton(final String label, final Runnable onClickAction, final boolean isPrimary) {
getUI().ifPresent(ui -> ui.navigate(TimesheetEntryView.class, idRecord.toString() + "/view"));
}
private double calculateTotal(final TimesheetEntry timesheetEntry) {
final List<TimesheetEntry> listHoursworkedEmployee = timesheetService.findListHoursWorkedEmployee(
timesheetEntry.getEmployee().getId(), timesheetEntry.getWeekNumber());
return calculateTotalUtilized(listHoursworkedEmployee);
}
private double calculateTotalUtilized(final List<TimesheetEntry> employeeRequests) {
return employeeRequests.stream()
.filter(Objects::nonNull)
.mapToDouble(TimesheetEntry::getHours)
.sum();
}
private Button createButton(final String label, final Runnable onClickAction) {
final Button button = new Button(label); final Button button = new Button(label);
if (isPrimary) {
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
}
button.addClickListener(event -> onClickAction.run()); button.addClickListener(event -> onClickAction.run());
return button; return button;
} }
private Button createAddHoursWorked() { private Button createAddHoursWorked() {
return createButton("Agregar Actividad", this::navigateToHours); return createButton("Agregar Actividad", this::navigateToHours, true);
} }
private void navigateToHours() { private void navigateToHours() {
@ -192,18 +176,34 @@ public class TimesheetListView extends BaseView {
private ComboBox<Employee> createEmployeeFilter() { private ComboBox<Employee> createEmployeeFilter() {
employeeFilter = new ComboBox<>("Empleado"); employeeFilter = new ComboBox<>("Empleado");
employeeFilter.setPlaceholder("TODOS"); employeeFilter.setPlaceholder("Seleccionar empleado ...");
employeeFilter.setClearButtonVisible(true); employeeFilter.setClearButtonVisible(true);
final List<Employee> employees = new ArrayList<>(employeeService.findAllEmployees());
List<Employee> employees = new ArrayList<>(employeeService.findAllEmployees());
if (!isRoleAdmin()) {
employeeFilter.setEnabled(false);
employees = employees.stream()
.filter(e -> getEmployeeId().equals(Optional.ofNullable(e.getId())))
.toList();
}
employeeFilter.setItems(employees); employeeFilter.setItems(employees);
if (!isRoleAdmin()) {
employeeFilter.setValue(employees.getFirst());
}
employeeFilter.setItemLabelGenerator(this::getEmployeeFullName); employeeFilter.setItemLabelGenerator(this::getEmployeeFullName);
employeeFilter.addValueChangeListener(event -> employeeFilter.addValueChangeListener(event ->
refreshGridListHoursWorked( refreshGridListHoursWorked(
event.getValue(), event.getValue(),
teamFilter.getValue() teamFilter.getValue(),
weekFilter.getValue()
) )
); );
return employeeFilter; return employeeFilter;
} }
@ -214,19 +214,36 @@ public class TimesheetListView extends BaseView {
private ComboBox<Team> createTeamFilter() { private ComboBox<Team> createTeamFilter() {
teamFilter = new ComboBox<>("Equipo"); teamFilter = new ComboBox<>("Equipo");
final List<Team> teams = new ArrayList<>(teamService.findAllTeams()); final List<Team> teams = new ArrayList<>(teamService.findAllTeams());
teamFilter.setPlaceholder("TODOS"); teamFilter.setPlaceholder("Seleccionar equipo ...");
teamFilter.setClearButtonVisible(true); teamFilter.setClearButtonVisible(true);
teamFilter.setItems(teams); teamFilter.setItems(teams);
teamFilter.setItemLabelGenerator(this::getTeamLabel); teamFilter.setItemLabelGenerator(this::getTeamLabel);
teamFilter.addValueChangeListener(event -> teamFilter.addValueChangeListener(event ->
refreshGridListHoursWorked( refreshGridListHoursWorked(
employeeFilter.getValue(), employeeFilter.getValue(),
event.getValue() event.getValue(),
weekFilter.getValue()
) )
); );
return teamFilter; return teamFilter;
} }
private ComboBox<Week> createWeekFilter() {
final List<Week> weeks = Week.getLastWeeks(4);
weekFilter = new ComboBox<>("Week");
weekFilter.setItems(weeks);
weekFilter.setValue(weeks.getFirst());
weekFilter.addValueChangeListener(event ->
refreshGridListHoursWorked(
employeeFilter.getValue(),
teamFilter.getValue(),
event.getValue()
)
);
return weekFilter;
}
private String getTeamLabel(final Team team) { private String getTeamLabel(final Team team) {
return team.getName(); return team.getName();
} }

View File

@ -1,16 +1,28 @@
package com.primefactorsolutions.views.util; package com.primefactorsolutions.views.util;
import com.primefactorsolutions.model.Employee;
import com.vaadin.flow.spring.security.AuthenticationContext; import com.vaadin.flow.spring.security.AuthenticationContext;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import java.util.Optional;
import java.util.UUID;
@UtilityClass @UtilityClass
public class AuthUtils { public class AuthUtils {
public static boolean isAdmin(final AuthenticationContext authenticationContext) { public static boolean isAdmin(final AuthenticationContext authenticationContext) {
return authenticationContext.getAuthenticatedUser(UserDetails.class).map(u -> return authenticationContext.getAuthenticatedUser(UserDetails.class)
u.getAuthorities().stream() .map(u ->
.map(GrantedAuthority::getAuthority) u.getAuthorities().stream()
.anyMatch("ROLE_ADMIN"::equals)).orElse(false); .map(GrantedAuthority::getAuthority)
.anyMatch("ROLE_ADMIN"::equals)).orElse(false);
}
public static Optional<UUID> getEmployeeId(final AuthenticationContext authenticationContext) {
return authenticationContext.getAuthenticatedUser(UserDetails.class)
.map(u -> u instanceof Employee
? ((Employee) u).getId()
: null);
} }
} }

View File

@ -5,47 +5,41 @@ insert into question (id, version, content, title, description) values ('8a4b213
insert into assessment(id, version, candidate_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', 1, '23471ab3-f639-4d2b-9541-7227f4ea7ee6'); insert into assessment(id, version, candidate_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', 1, '23471ab3-f639-4d2b-9541-7227f4ea7ee6');
insert into ASSESSMENT_QUESTIONS (assessment_id, question_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', 'a7e00ff8-da41-4624-b31c-1b13c3f2e3ae'); insert into assessment_questions (assessment_id, question_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', 'a7e00ff8-da41-4624-b31c-1b13c3f2e3ae');
insert into assessment_questions (assessment_id, question_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', '8a4b213c-ca81-4c38-b56d-d7028c2dde88');
insert into ASSESSMENT_QUESTIONS (assessment_id, question_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', '8a4b213c-ca81-4c38-b56d-d7028c2dde88');
INSERT INTO team (id, version, name) VALUES ('b0e8f394-78c1-4d8a-9c57-dc6e8b36a5fa', 1, 'ABC'); 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 ('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 ('c3a8a7b1-f2d9-48c0-86ea-f215c2e6b3a3', 1, 'DEF');
INSERT INTO team (id, version, name) VALUES ('8f6b61e7-efb2-4de7-b8ed-7438c9d8babe', 1, 'GHI'); INSERT INTO team (id, version, name) VALUES ('8f6b61e7-efb2-4de7-b8ed-7438c9d8babe', 1, 'GHI');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('123e4567-e89b-12d3-a456-426614174000', 1, 'AÑO_NUEVO', '2024-1-1', 1, 1, 'FIXED');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('223e4567-e89b-12d3-a456-426614174001', 1, 'LUNES_CARNAVAL', '2024-2-12', 1, 1, 'FIXED');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('323e4567-e89b-12d3-a456-426614174002', 1, 'MARTES_CARNAVAL', '2024-2-13', 1, 1, 'FIXED');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('423e4567-e89b-12d3-a456-426614174003', 1, 'VIERNES_SANTO', '2024-3-29', 1, 1, 'FIXED');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('523e4567-e89b-12d3-a456-426614174004', 1, 'DIA_DEL_TRABAJADOR', '2024-5-1', 1, 1, 'FIXED');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('623e4567-e89b-12d3-a456-426614174005', 1, 'DIA_DE_LA_INDEPENDENCIA', '2024-8-6', 1, 1, 'FIXED');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('723e4567-e89b-12d3-a456-426614174006', 1, 'NAVIDAD', '2024-12-25', 1, 1, 'FIXED');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('823e4567-e89b-12d3-a456-426614174007', 1, 'DIA_DEL_ESTADO_PLURINACIONAL', '2024-1-21', 1, 30, 'MOVABLE');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('923e4567-e89b-12d3-a456-426614174008', 1, 'CORPUS_CHRISTI', '2024-5-30', 1, 30, 'MOVABLE');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('a23e4567-e89b-12d3-a456-426614174009', 1, 'AÑO_NUEVO_ANDINO', '2024-6-21', 1, 30, 'MOVABLE');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('b23e4567-e89b-12d3-a456-42661417400a', 1, 'ANIVERSARIO_DEPARTAMENTAL', '2024-9-14', 1, 30, 'MOVABLE');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400b', 1, 'DIA_DE_TODOS_LOS_DIFUNTOS', '2024-11-2', 1, 30, 'MOVABLE');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401a', 1, 'DIA_DEL_PADRE', '2024-3-19', 0.5, 30, 'OTHER');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401b', 1, 'DIA_DE_LA_MADRE', '2024-5-27', 0.5, 30, 'OTHER');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401c', 1, 'DIA_DE_LA_MUJER_INTERNACIONAL', '2024-3-8', 0.5, 30, 'OTHER');
INSERT INTO time_off (id, version, category, date, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401d', 1, 'DIA_DE_LA_MUJER_NACIONAL', '2024-10-11', 0.5, 30, 'OTHER');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('123e4567-e89b-12d3-a456-426614174000', 1, 'AÑO_NUEVO', 1, 1, 1, 1, 'FIXED'); INSERT INTO time_off (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400c', 1, 'CUMPLEAÑOS', 0.5, 0.5, 'OTHER');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('223e4567-e89b-12d3-a456-426614174001', 1, 'LUNES_CARNAVAL', 2, 12, 1, 1, 'FIXED'); INSERT INTO time_off (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400d', 1, 'MATERNIDAD', 90, 90, 'OTHER');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('323e4567-e89b-12d3-a456-426614174002', 1, 'MARTES_CARNAVAL', 2, 13, 1, 1, 'FIXED'); INSERT INTO time_off (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400e', 1, 'PATERNIDAD', 3, 3, 'OTHER');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('423e4567-e89b-12d3-a456-426614174003', 1, 'VIERNES_SANTO', 3, 29, 1, 1, 'FIXED'); INSERT INTO time_off (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400f', 1, 'MATRIMONIO', 3, 3, 'OTHER');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('523e4567-e89b-12d3-a456-426614174004', 1, 'DIA_DEL_TRABAJADOR', 5, 1, 1, 1, 'FIXED'); INSERT INTO time_off (id, version, category, duration, expiration, type) VALUES ('550e8400-e29b-41d4-a716-446655440000', 1, 'DUELO_1ER_GRADO', 3, 3, 'OTHER');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('623e4567-e89b-12d3-a456-426614174005', 1, 'DIA_DE_LA_INDEPENDENCIA', 8, 6, 1, 1, 'FIXED'); INSERT INTO time_off (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400a', 1, 'DUELO_2ER_GRADO', 2, 2, 'OTHER');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('723e4567-e89b-12d3-a456-426614174006', 1, 'NAVIDAD', 12, 25, 1, 1, 'FIXED');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('823e4567-e89b-12d3-a456-426614174007', 1, 'DIA_DEL_ESTADO_PLURINACIONAL', 1, 21, 1, 30, 'MOVABLE');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('923e4567-e89b-12d3-a456-426614174008', 1, 'CORPUS_CHRISTI', 5, 30, 1, 30, 'MOVABLE');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('a23e4567-e89b-12d3-a456-426614174009', 1, 'AÑO_NUEVO_ANDINO', 6, 21, 1, 30, 'MOVABLE');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('b23e4567-e89b-12d3-a456-42661417400a', 1, 'ANIVERSARIO_DEPARTAMENTAL', 9, 14, 1, 30, 'MOVABLE');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400b', 1, 'DIA_DE_TODOS_LOS_DIFUNTOS', 11, 2, 1, 30, 'MOVABLE');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400c', 1, 'CUMPLEAÑOS', 12, 31, 0.5, 'OTHER');
INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400d', 1, 'MATERNIDAD', 90, 90, 'OTHER');
INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400e', 1, 'PATERNIDAD', 3, 3, 'OTHER');
INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400f', 1, 'MATRIMONIO', 3, 3, 'OTHER');
INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('550e8400-e29b-41d4-a716-446655440000', 1, 'DUELO_1ER_GRADO', 3, 3, 'OTHER');
INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400a', 1, 'DUELO_2ER_GRADO', 2, 2, 'OTHER');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401a', 1, 'DIA_DEL_PADRE', 3, 19, 0.5, 30, 'OTHER');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401b', 1, 'DIA_DE_LA_MADRE', 5, 27, 0.5, 30, 'OTHER');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401c', 1, 'DIA_DE_LA_MUJER_INTERNACIONAL', 3, 8, 0.5, 30, 'OTHER');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401d', 1, 'DIA_DE_LA_MUJER_NACIONAL', 10, 11, 0.5, 30, 'OTHER');
INSERT INTO vacation (id, version, category, duration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401e', 1, 'PERMISOS_DE_SALUD', 2, 'OTHER');
INSERT INTO vacation (id, version, category, expiration, type) VALUES ('490e5fbe-895b-42f8-b914-95437f7b39c0', 1, 'VACACION_GESTION_ACTUAL', 360, 'OTHER');
INSERT INTO vacation (id, version, category, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-4266141740ff', 1, 'VACACION_GESTION_ANTERIOR', 360, 'OTHER');
INSERT INTO time_off (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417401e', 1, 'PERMISOS_DE_SALUD', 2, 360, 'OTHER');
INSERT INTO time_off (id, version, category, expiration, type) VALUES ('490e5fbe-895b-42f8-b914-95437f7b39c0', 1, 'VACACION_GESTION_ACTUAL', 360, 'OTHER');
INSERT INTO time_off (id, version, category, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-4266141740ff', 1, 'VACACION_GESTION_ANTERIOR', 360, 'OTHER');
insert into employee (id, version, username, first_name, last_name, status, team_id, gender, birthday, date_of_entry, lead_manager, role) values ('5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 1, 'bob', 'Bob', 'Test', 'ACTIVE','b0e8f394-78c1-4d8a-9c57-dc6e8b36a5fa', 'MALE', '2024-02-20', '2013-10-22', 'ben', 'ADMIN'); insert into employee (id, version, username, first_name, last_name, status, team_id, gender, birthday, date_of_entry, lead_manager, role) values ('5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 1, 'bob', 'Bob', 'Test', 'ACTIVE','b0e8f394-78c1-4d8a-9c57-dc6e8b36a5fa', 'MALE', '2024-02-20', '2013-10-22', 'ben', 'ADMIN');
insert into employee (id, version, username, first_name, last_name, status, team_id, gender, date_of_entry, role) values ('cba3efb7-32bc-44be-9fdc-fc5e4f211254', 1, 'ben', 'Ben', 'Test', 'ACTIVE', '6d63bc15-3f8b-46f7-9cf1-7e9b0b9a2b28', 'MALE', '2016-10-23', 'USER'); insert into employee (id, version, username, first_name, last_name, status, team_id, gender, date_of_entry, role) values ('cba3efb7-32bc-44be-9fdc-fc5e4f211254', 1, 'ben', 'Ben', 'Test', 'ACTIVE', '6d63bc15-3f8b-46f7-9cf1-7e9b0b9a2b28', 'MALE', '2016-10-23', 'USER');

View File

@ -1,5 +1,6 @@
package com.primefactorsolutions.views; package com.primefactorsolutions.views;
import com.primefactorsolutions.views.assessment.CandidateView;
import com.vaadin.flow.component.UI; import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.textfield.EmailField; import com.vaadin.flow.component.textfield.EmailField;