This commit is contained in:
parent
9266a5f634
commit
87418e03e5
Binary file not shown.
@ -1,7 +1,6 @@
|
|||||||
package com.primefactorsolutions.model;
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
public enum DocumentType {
|
public enum DocumentType {
|
||||||
TODOS,
|
|
||||||
CARNET_DE_IDENTIDAD,
|
CARNET_DE_IDENTIDAD,
|
||||||
RECIBOS_DE_PAGO,
|
RECIBOS_DE_PAGO,
|
||||||
CONTRATO_DE_TRABAJO,
|
CONTRATO_DE_TRABAJO,
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
package com.primefactorsolutions.model;
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.Year;
|
import java.time.Year;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.temporal.IsoFields;
|
import java.time.temporal.IsoFields;
|
||||||
import java.time.temporal.WeekFields;
|
import java.time.temporal.WeekFields;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.stream.IntStream;
|
|
||||||
|
|
||||||
public record Week(LocalDate from, LocalDate to) {
|
public record Week(LocalDate from, LocalDate to) {
|
||||||
@Override
|
@Override
|
||||||
@ -25,11 +27,15 @@ public record Week(LocalDate from, LocalDate to) {
|
|||||||
|
|
||||||
public static List<Week> getLastWeeks(final int numberOfWeeks) {
|
public static List<Week> getLastWeeks(final int numberOfWeeks) {
|
||||||
final int weekNumber = LocalDate.now().get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
|
final int weekNumber = LocalDate.now().get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
|
||||||
|
LocalDate from = getFirstDayOfWeek(weekNumber);
|
||||||
|
final ArrayList<Week> result = Lists.newArrayList();
|
||||||
|
|
||||||
return IntStream.range(0, numberOfWeeks).mapToObj(idx -> {
|
for (int i = 0; i < numberOfWeeks; i++) {
|
||||||
LocalDate from = getFirstDayOfWeek(weekNumber - idx);
|
result.add(new Week(from, from.plusDays(6)));
|
||||||
return new Week(from, from.plusDays(6));
|
from = from.minusDays(7);
|
||||||
}).toList();
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LocalDate getFirstDayOfWeek(final int weekNumber) {
|
private static LocalDate getFirstDayOfWeek(final int weekNumber) {
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.primefactorsolutions.views;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.views.util.AuthUtils;
|
||||||
|
import com.vaadin.flow.component.ClickEvent;
|
||||||
|
import com.vaadin.flow.component.ComponentEventListener;
|
||||||
|
import com.vaadin.flow.component.UI;
|
||||||
|
import com.vaadin.flow.component.button.Button;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||||
|
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||||
|
import org.vaadin.firitin.form.BeanValidationForm;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public abstract class BaseEntityForm<T> extends BeanValidationForm<T> {
|
||||||
|
private final AuthenticationContext authenticationContext;
|
||||||
|
|
||||||
|
public BaseEntityForm(final AuthenticationContext authenticationContext, final Class<T> entityType) {
|
||||||
|
super(entityType);
|
||||||
|
this.authenticationContext = authenticationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HorizontalLayout getToolbar() {
|
||||||
|
return new HorizontalLayout(getCancelButton(), getSaveButton());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Button getCancelButton() {
|
||||||
|
final Button cancelButton = new Button("Cancel");
|
||||||
|
cancelButton.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent ->
|
||||||
|
UI.getCurrent().getPage().getHistory().back());
|
||||||
|
|
||||||
|
return cancelButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isRoleAdmin() {
|
||||||
|
return AuthUtils.isAdmin(this.authenticationContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Optional<UUID> getEmployeeId() {
|
||||||
|
return AuthUtils.getEmployeeId(this.authenticationContext);
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,6 @@ import elemental.json.JsonObject;
|
|||||||
import jakarta.annotation.security.PermitAll;
|
import jakarta.annotation.security.PermitAll;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.vaadin.firitin.form.BeanValidationForm;
|
|
||||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
@ -39,7 +38,7 @@ import java.io.InputStream;
|
|||||||
@Scope("prototype")
|
@Scope("prototype")
|
||||||
@PageTitle("Document")
|
@PageTitle("Document")
|
||||||
@Route(value = "/documents/:documentId?/:action?", layout = MainLayout.class)
|
@Route(value = "/documents/:documentId?/:action?", layout = MainLayout.class)
|
||||||
public class DocumentView extends BeanValidationForm<Document> implements HasUrlParameter<String> {
|
public class DocumentView extends BaseEntityForm<Document> implements HasUrlParameter<String> {
|
||||||
private final TextField fileName = new TextField("Nombre del documento");
|
private final TextField fileName = new TextField("Nombre del documento");
|
||||||
private final ComboBox<DocumentType> documentType = new ComboBox<>("Tipo de documento");
|
private final ComboBox<DocumentType> documentType = new ComboBox<>("Tipo de documento");
|
||||||
private final ComboBox<Employee> employeeComboBox = new ComboBox<>("Empleado");
|
private final ComboBox<Employee> employeeComboBox = new ComboBox<>("Empleado");
|
||||||
@ -50,17 +49,18 @@ public class DocumentView extends BeanValidationForm<Document> implements HasUrl
|
|||||||
private final EmployeeService employeeService;
|
private final EmployeeService employeeService;
|
||||||
private final AuthenticationContext authContext;
|
private final AuthenticationContext authContext;
|
||||||
private boolean fileUploaded = false;
|
private boolean fileUploaded = false;
|
||||||
private Button saveButton;
|
|
||||||
private Button viewDocumentButton;
|
private Button viewDocumentButton;
|
||||||
|
|
||||||
public DocumentView(final DocumentService documentService,
|
public DocumentView(final AuthenticationContext authenticationContext,
|
||||||
|
final DocumentService documentService,
|
||||||
final EmployeeService employeeService,
|
final EmployeeService employeeService,
|
||||||
final AuthenticationContext authContext) {
|
final AuthenticationContext authContext) {
|
||||||
super(Document.class);
|
super(authenticationContext, Document.class);
|
||||||
this.documentService = documentService;
|
this.documentService = documentService;
|
||||||
this.employeeService = employeeService;
|
this.employeeService = employeeService;
|
||||||
this.authContext = authContext;
|
this.authContext = authContext;
|
||||||
initializeView();
|
initializeView();
|
||||||
|
this.setSavedHandler(this::saveDocument);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeView() {
|
private void initializeView() {
|
||||||
@ -68,18 +68,6 @@ public class DocumentView extends BeanValidationForm<Document> implements HasUrl
|
|||||||
configureUploadButton();
|
configureUploadButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Button createSaveButton() {
|
|
||||||
saveButton = new Button("Guardar");
|
|
||||||
saveButton.addClickListener(event -> saveDocument());
|
|
||||||
return saveButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Button createCloseButton() {
|
|
||||||
Button closeButton = new Button("Salir");
|
|
||||||
closeButton.addClickListener(event -> closeForm());
|
|
||||||
return closeButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Button createViewDocumentButton() {
|
protected Button createViewDocumentButton() {
|
||||||
viewDocumentButton = new Button("Ver documento");
|
viewDocumentButton = new Button("Ver documento");
|
||||||
viewDocumentButton.setEnabled(false);
|
viewDocumentButton.setEnabled(false);
|
||||||
@ -135,13 +123,8 @@ public class DocumentView extends BeanValidationForm<Document> implements HasUrl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void navigateToDocumentsListView() {
|
private void saveDocument(final Document document) {
|
||||||
getUI().ifPresent(ui -> ui.navigate(DocumentsListView.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveDocument() {
|
|
||||||
if (isFormValid()) {
|
if (isFormValid()) {
|
||||||
Document document = getEntity();
|
|
||||||
document.setFileName(fileName.getValue());
|
document.setFileName(fileName.getValue());
|
||||||
document.setDocumentType(documentType.getValue());
|
document.setDocumentType(documentType.getValue());
|
||||||
document.setEmployee(employeeComboBox.getValue());
|
document.setEmployee(employeeComboBox.getValue());
|
||||||
@ -149,17 +132,12 @@ public class DocumentView extends BeanValidationForm<Document> implements HasUrl
|
|||||||
setDocumentCreator(document);
|
setDocumentCreator(document);
|
||||||
|
|
||||||
documentService.saveDocument(document);
|
documentService.saveDocument(document);
|
||||||
Notification.show("Archivo guardado correctamente.");
|
getUI().ifPresent(ui -> ui.navigate(DocumentsListView.class));
|
||||||
clearForm();
|
|
||||||
} else {
|
} else {
|
||||||
Notification.show("Error al guardar: Por favor, complete todos los campos y cargue un archivo.");
|
Notification.show("Error al guardar: Por favor, complete todos los campos y cargue un archivo.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeForm() {
|
|
||||||
navigateToDocumentsListView();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isFormValid() {
|
private boolean isFormValid() {
|
||||||
return !fileName.isEmpty()
|
return !fileName.isEmpty()
|
||||||
&& documentType.getValue() != null
|
&& documentType.getValue() != null
|
||||||
@ -167,15 +145,6 @@ public class DocumentView extends BeanValidationForm<Document> implements HasUrl
|
|||||||
&& fileUploaded;
|
&& fileUploaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearForm() {
|
|
||||||
fileName.clear();
|
|
||||||
documentType.clear();
|
|
||||||
employeeComboBox.clear();
|
|
||||||
fileUploaded = false;
|
|
||||||
uploadButton.getElement().setPropertyJson("files", Json.createArray());
|
|
||||||
viewDocumentButton.setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] readFileData() {
|
private byte[] readFileData() {
|
||||||
try {
|
try {
|
||||||
return buffer.getInputStream().readAllBytes();
|
return buffer.getInputStream().readAllBytes();
|
||||||
@ -197,23 +166,10 @@ public class DocumentView extends BeanValidationForm<Document> implements HasUrl
|
|||||||
fileUploaded = true;
|
fileUploaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSaveButtonState() {
|
|
||||||
boolean isModified = !fileName.getValue().equals(getEntity().getFileName())
|
|
||||||
|| documentType.getValue() != getEntity().getDocumentType()
|
|
||||||
|| employeeComboBox.getValue() != getEntity().getEmployee()
|
|
||||||
|| fileUploaded;
|
|
||||||
saveButton.setEnabled(isModified);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureComponents() {
|
private void configureComponents() {
|
||||||
setFileNameProperties();
|
setFileNameProperties();
|
||||||
setDocumentTypeProperties();
|
setDocumentTypeProperties();
|
||||||
setEmployeeComboBoxProperties();
|
setEmployeeComboBoxProperties();
|
||||||
fileName.addValueChangeListener(e -> updateSaveButtonState());
|
|
||||||
documentType.addValueChangeListener(e -> updateSaveButtonState());
|
|
||||||
employeeComboBox.addValueChangeListener(e -> updateSaveButtonState());
|
|
||||||
uploadButton.addSucceededListener(e -> updateSaveButtonState());
|
|
||||||
uploadButton.getElement().addEventListener("file-remove", event -> updateSaveButtonState());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureUploadButton() {
|
private void configureUploadButton() {
|
||||||
@ -223,29 +179,14 @@ public class DocumentView extends BeanValidationForm<Document> implements HasUrl
|
|||||||
fileUploaded = true;
|
fileUploaded = true;
|
||||||
Notification.show("Archivo cargado correctamente.");
|
Notification.show("Archivo cargado correctamente.");
|
||||||
viewDocumentButton.setEnabled(true);
|
viewDocumentButton.setEnabled(true);
|
||||||
updateSaveButtonState();
|
|
||||||
});
|
});
|
||||||
uploadButton.getElement().addEventListener("file-remove", event -> {
|
uploadButton.getElement().addEventListener("file-remove", event -> {
|
||||||
fileUploaded = false;
|
fileUploaded = false;
|
||||||
Notification.show("Archivo eliminado.");
|
Notification.show("Archivo eliminado.");
|
||||||
viewDocumentButton.setEnabled(false);
|
viewDocumentButton.setEnabled(false);
|
||||||
updateSaveButtonState();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureViewOrEditAction(final String action, final String documentIdString) {
|
|
||||||
if ("edit".equals(action) && !documentIdString.isEmpty()) {
|
|
||||||
setFieldsReadOnly(false);
|
|
||||||
preLoadFile(getEntity());
|
|
||||||
viewDocumentButton.setEnabled(true);
|
|
||||||
} else if ("view".equals(action) && !documentIdString.isEmpty()) {
|
|
||||||
setFieldsReadOnly(true);
|
|
||||||
preLoadFile(getEntity());
|
|
||||||
saveButton.setEnabled(false);
|
|
||||||
viewDocumentButton.setEnabled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setParameter(final BeforeEvent beforeEvent, final String action) {
|
public void setParameter(final BeforeEvent beforeEvent, final String action) {
|
||||||
final RouteParameters params = beforeEvent.getRouteParameters();
|
final RouteParameters params = beforeEvent.getRouteParameters();
|
||||||
@ -257,18 +198,30 @@ public class DocumentView extends BeanValidationForm<Document> implements HasUrl
|
|||||||
assert documentIdString != null;
|
assert documentIdString != null;
|
||||||
UUID documentId = UUID.fromString(documentIdString);
|
UUID documentId = UUID.fromString(documentIdString);
|
||||||
Document document = documentService.getDocument(documentId);
|
Document document = documentService.getDocument(documentId);
|
||||||
setEntity(document);
|
|
||||||
employeeComboBox.setValue(document.getEmployee());
|
employeeComboBox.setValue(document.getEmployee());
|
||||||
preLoadFile(document);
|
preLoadFile(document);
|
||||||
configureViewOrEditAction(action, documentIdString);
|
|
||||||
|
if ("edit".equals(action) && !documentIdString.isEmpty()) {
|
||||||
|
setEntityWithEnabledSave(document);
|
||||||
|
setFieldsReadOnly(false);
|
||||||
|
preLoadFile(document);
|
||||||
|
viewDocumentButton.setEnabled(true);
|
||||||
|
} else if ("view".equals(action) && !documentIdString.isEmpty()) {
|
||||||
|
setEntity(document);
|
||||||
|
setFieldsReadOnly(true);
|
||||||
|
preLoadFile(document);
|
||||||
|
viewDocumentButton.setEnabled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Component> getFormComponents() {
|
protected List<Component> getFormComponents() {
|
||||||
HorizontalLayout buttonLayout = new HorizontalLayout();
|
final HorizontalLayout buttonLayout = new HorizontalLayout();
|
||||||
buttonLayout.add(uploadButton, createViewDocumentButton());
|
buttonLayout.add(uploadButton, createViewDocumentButton());
|
||||||
buttonLayout.setSpacing(true);
|
buttonLayout.setSpacing(true);
|
||||||
return List.of(fileName, documentType, employeeComboBox, pdfOnlyMessage, buttonLayout, createCloseButton());
|
|
||||||
|
return List.of(documentType, fileName, employeeComboBox, pdfOnlyMessage, buttonLayout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import com.vaadin.flow.component.Component;
|
|||||||
import com.vaadin.flow.component.ComponentEventListener;
|
import com.vaadin.flow.component.ComponentEventListener;
|
||||||
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.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.grid.GridSortOrder;
|
import com.vaadin.flow.component.grid.GridSortOrder;
|
||||||
@ -60,7 +61,7 @@ public class DocumentsListView extends BaseView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initializeView() {
|
private void initializeView() {
|
||||||
getCurrentPageLayout().add(createActionButton("Añadir documento", this::navigateToAddDocumentView));
|
getCurrentPageLayout().add(createActionButton("Añadir documento", this::navigateToAddDocumentView, true));
|
||||||
|
|
||||||
final HorizontalLayout hl = new HorizontalLayout();
|
final HorizontalLayout hl = new HorizontalLayout();
|
||||||
hl.add(createDocumentTypeFilter());
|
hl.add(createDocumentTypeFilter());
|
||||||
@ -105,16 +106,22 @@ public class DocumentsListView extends BaseView {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Button createActionButton(final String label, final Runnable onClickAction) {
|
private Button createActionButton(final String label, final Runnable onClickAction, final boolean isPrimary) {
|
||||||
Button actionButton = new Button(label);
|
Button actionButton = new Button(label);
|
||||||
|
|
||||||
|
if (isPrimary) {
|
||||||
|
actionButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
|
}
|
||||||
|
|
||||||
actionButton.addClickListener(event -> onClickAction.run());
|
actionButton.addClickListener(event -> onClickAction.run());
|
||||||
return actionButton;
|
return actionButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ComboBox<DocumentType> createDocumentTypeFilter() {
|
private ComboBox<DocumentType> createDocumentTypeFilter() {
|
||||||
documentTypeFilter = new ComboBox<>("Tipo de documento");
|
documentTypeFilter = new ComboBox<>("Tipo de documento");
|
||||||
|
documentTypeFilter.setClearButtonVisible(true);
|
||||||
|
documentTypeFilter.setPlaceholder("Seleccionar ...");
|
||||||
documentTypeFilter.setItems(DocumentType.values());
|
documentTypeFilter.setItems(DocumentType.values());
|
||||||
documentTypeFilter.setValue(DocumentType.values()[0]);
|
|
||||||
documentTypeFilter.addValueChangeListener(event -> {
|
documentTypeFilter.addValueChangeListener(event -> {
|
||||||
updateDocumentGrid(event.getValue(), employeeFilter.getValue());
|
updateDocumentGrid(event.getValue(), employeeFilter.getValue());
|
||||||
});
|
});
|
||||||
@ -123,26 +130,19 @@ public class DocumentsListView extends BaseView {
|
|||||||
|
|
||||||
private ComboBox<Employee> createEmployeeFilter() {
|
private ComboBox<Employee> createEmployeeFilter() {
|
||||||
employeeFilter = new ComboBox<>("Empleado");
|
employeeFilter = new ComboBox<>("Empleado");
|
||||||
|
employeeFilter.setPlaceholder("Seleccionar ...");
|
||||||
|
employeeFilter.setClearButtonVisible(true);
|
||||||
List<Employee> employees = employeeService.findAllEmployees();
|
List<Employee> employees = employeeService.findAllEmployees();
|
||||||
employees.addFirst(createAllEmployeesOption());
|
|
||||||
employeeFilter.setItems(employees);
|
employeeFilter.setItems(employees);
|
||||||
employeeFilter.setItemLabelGenerator(this::getEmployeeLabel);
|
employeeFilter.setItemLabelGenerator(this::getEmployeeLabel);
|
||||||
employeeFilter.setValue(employees.getFirst());
|
|
||||||
employeeFilter.addValueChangeListener(event -> {
|
employeeFilter.addValueChangeListener(event -> {
|
||||||
updateDocumentGrid(documentTypeFilter.getValue(), event.getValue());
|
updateDocumentGrid(documentTypeFilter.getValue(), event.getValue());
|
||||||
});
|
});
|
||||||
return employeeFilter;
|
return employeeFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Employee createAllEmployeesOption() {
|
|
||||||
Employee allEmployeesOption = new Employee();
|
|
||||||
allEmployeesOption.setFirstName("TODOS");
|
|
||||||
return allEmployeesOption;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getEmployeeLabel(final Employee employee) {
|
private String getEmployeeLabel(final Employee employee) {
|
||||||
return employee.getFirstName().equals("TODOS")
|
return employee.getFirstName() + " " + employee.getLastName();
|
||||||
? "TODOS" : employee.getFirstName() + " " + employee.getLastName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void navigateToEditDocumentView(final Document document) {
|
private void navigateToEditDocumentView(final Document document) {
|
||||||
|
@ -6,9 +6,8 @@ import com.primefactorsolutions.views.admin.TimeOffListView;
|
|||||||
import com.primefactorsolutions.views.assessment.AssessmentsListView;
|
import com.primefactorsolutions.views.assessment.AssessmentsListView;
|
||||||
import com.primefactorsolutions.views.assessment.CandidatesListView;
|
import com.primefactorsolutions.views.assessment.CandidatesListView;
|
||||||
import com.primefactorsolutions.views.assessment.QuestionsListView;
|
import com.primefactorsolutions.views.assessment.QuestionsListView;
|
||||||
import com.primefactorsolutions.views.timeoff.TimeOffNewRequestView;
|
import com.primefactorsolutions.views.timeoff.TimeOffRequestsListView;
|
||||||
import com.primefactorsolutions.views.timeoff.TimeOffPendingRequestsListView;
|
import com.primefactorsolutions.views.timeoff.TimeOffSummaryListView;
|
||||||
import com.primefactorsolutions.views.timeoff.TimeOffRequestListView;
|
|
||||||
import com.primefactorsolutions.views.timesheet.TimesheetListView;
|
import com.primefactorsolutions.views.timesheet.TimesheetListView;
|
||||||
import com.primefactorsolutions.views.timesheet.TimesheetReportView;
|
import com.primefactorsolutions.views.timesheet.TimesheetReportView;
|
||||||
import com.vaadin.flow.component.Component;
|
import com.vaadin.flow.component.Component;
|
||||||
@ -142,10 +141,6 @@ public class MainLayout extends AppLayout {
|
|||||||
if (isAdmin(authContext)) {
|
if (isAdmin(authContext)) {
|
||||||
SideNavItem admin = new SideNavItem("Admin");
|
SideNavItem admin = new SideNavItem("Admin");
|
||||||
admin.setPrefixComponent(LineAwesomeIcon.BUILDING.create());
|
admin.setPrefixComponent(LineAwesomeIcon.BUILDING.create());
|
||||||
admin.addItem(new SideNavItem("Employees", EmployeesListView.class,
|
|
||||||
LineAwesomeIcon.USER_EDIT_SOLID.create()));
|
|
||||||
admin.addItem(new SideNavItem("Documents", DocumentsListView.class,
|
|
||||||
LineAwesomeIcon.FILE_ALT_SOLID.create()));
|
|
||||||
admin.addItem(new SideNavItem("Calendario", TimeOffListView.class,
|
admin.addItem(new SideNavItem("Calendario", TimeOffListView.class,
|
||||||
LineAwesomeIcon.CALENDAR.create()));
|
LineAwesomeIcon.CALENDAR.create()));
|
||||||
nav.addItem(admin);
|
nav.addItem(admin);
|
||||||
@ -163,15 +158,10 @@ public class MainLayout extends AppLayout {
|
|||||||
|
|
||||||
final SideNavItem timeOff = new SideNavItem("Time-off");
|
final SideNavItem timeOff = new SideNavItem("Time-off");
|
||||||
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", TimeOffSummaryListView.class,
|
||||||
LineAwesomeIcon.UMBRELLA_BEACH_SOLID.create()));
|
LineAwesomeIcon.UMBRELLA_BEACH_SOLID.create()));
|
||||||
timeOff.addItem(new SideNavItem("Add TimeOff", TimeOffNewRequestView.class,
|
timeOff.addItem(new SideNavItem("Requests", TimeOffRequestsListView.class,
|
||||||
LineAwesomeIcon.CALENDAR_PLUS.create()));
|
LineAwesomeIcon.LIST_ALT.create()));
|
||||||
|
|
||||||
if (isAdmin(authContext)) {
|
|
||||||
timeOff.addItem(new SideNavItem("Pending Requests", TimeOffPendingRequestsListView.class,
|
|
||||||
LineAwesomeIcon.LIST_ALT.create()));
|
|
||||||
}
|
|
||||||
|
|
||||||
final SideNavItem timesheet = new SideNavItem("Timesheet");
|
final SideNavItem timesheet = new SideNavItem("Timesheet");
|
||||||
timesheet.setPrefixComponent(LineAwesomeIcon.HOURGLASS_START_SOLID.create());
|
timesheet.setPrefixComponent(LineAwesomeIcon.HOURGLASS_START_SOLID.create());
|
||||||
@ -183,8 +173,12 @@ public class MainLayout extends AppLayout {
|
|||||||
LineAwesomeIcon.ID_CARD_SOLID.create()));
|
LineAwesomeIcon.ID_CARD_SOLID.create()));
|
||||||
}
|
}
|
||||||
|
|
||||||
final SideNavItem profile = new SideNavItem("Profile", ProfileView.class,
|
final SideNavItem profile = new SideNavItem("Employee");
|
||||||
LineAwesomeIcon.USER_EDIT_SOLID.create());
|
profile.setPrefixComponent(LineAwesomeIcon.USER_TIE_SOLID.create());
|
||||||
|
profile.addItem(new SideNavItem("Profiles", EmployeesListView.class,
|
||||||
|
LineAwesomeIcon.USER_EDIT_SOLID.create()));
|
||||||
|
profile.addItem(new SideNavItem("Documents", DocumentsListView.class,
|
||||||
|
LineAwesomeIcon.FILE_ALT_SOLID.create()));
|
||||||
|
|
||||||
nav.addItem(profile);
|
nav.addItem(profile);
|
||||||
nav.addItem(timesheet);
|
nav.addItem(timesheet);
|
||||||
|
@ -7,7 +7,9 @@ import com.primefactorsolutions.views.Constants;
|
|||||||
import com.primefactorsolutions.views.EmployeeView;
|
import com.primefactorsolutions.views.EmployeeView;
|
||||||
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.button.ButtonVariant;
|
||||||
import com.vaadin.flow.component.html.Anchor;
|
import com.vaadin.flow.component.html.Anchor;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||||
import com.vaadin.flow.router.PageTitle;
|
import com.vaadin.flow.router.PageTitle;
|
||||||
import com.vaadin.flow.router.Route;
|
import com.vaadin.flow.router.Route;
|
||||||
import com.vaadin.flow.server.StreamResource;
|
import com.vaadin.flow.server.StreamResource;
|
||||||
@ -45,8 +47,8 @@ public class EmployeesListView extends BaseView {
|
|||||||
|
|
||||||
private void setupView() {
|
private void setupView() {
|
||||||
configureTable();
|
configureTable();
|
||||||
getCurrentPageLayout().add(createAddEmployeeButton());
|
final HorizontalLayout hl = new HorizontalLayout(createAddEmployeeButton(), createExportButton());
|
||||||
getCurrentPageLayout().add(createExportButton());
|
getCurrentPageLayout().add(hl);
|
||||||
getCurrentPageLayout().add(table);
|
getCurrentPageLayout().add(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,18 +145,23 @@ public class EmployeesListView extends BaseView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addEditButtonColumn(final String label, final ButtonClickHandler handler) {
|
private void addEditButtonColumn(final String label, final ButtonClickHandler handler) {
|
||||||
table.addComponentColumn(employee -> createButton(label, () -> handler.handle(employee)));
|
table.addComponentColumn(employee -> createButton(label, () -> handler.handle(employee), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Button createButton(final String label, final Runnable onClickAction) {
|
private Button createButton(final String label, final Runnable onClickAction, final boolean isPrimary) {
|
||||||
Button button = new Button(label);
|
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 createAddEmployeeButton() {
|
private Button createAddEmployeeButton() {
|
||||||
|
|
||||||
return createButton("Add Employee", this::navigateToAddEmployeeView);
|
return createButton("Add Employee", this::navigateToAddEmployeeView, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void navigateToEditView(final Employee employee) {
|
private void navigateToEditView(final Employee employee) {
|
||||||
|
@ -1,560 +0,0 @@
|
|||||||
package com.primefactorsolutions.views.timeoff;
|
|
||||||
|
|
||||||
import com.primefactorsolutions.model.*;
|
|
||||||
import com.primefactorsolutions.service.EmployeeService;
|
|
||||||
import com.primefactorsolutions.service.TimeOffRequestService;
|
|
||||||
import com.primefactorsolutions.service.TimeOffService;
|
|
||||||
import com.primefactorsolutions.views.MainLayout;
|
|
||||||
import com.vaadin.flow.component.button.Button;
|
|
||||||
import com.vaadin.flow.component.combobox.ComboBox;
|
|
||||||
import com.vaadin.flow.component.datepicker.DatePicker;
|
|
||||||
import com.vaadin.flow.component.html.H3;
|
|
||||||
import com.vaadin.flow.component.notification.Notification;
|
|
||||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
|
||||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
|
||||||
import com.vaadin.flow.component.textfield.NumberField;
|
|
||||||
import com.vaadin.flow.data.binder.Binder;
|
|
||||||
import com.vaadin.flow.router.*;
|
|
||||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
|
||||||
import jakarta.annotation.security.PermitAll;
|
|
||||||
import org.springframework.context.annotation.Scope;
|
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.DayOfWeek;
|
|
||||||
import java.time.temporal.ChronoUnit;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@SpringComponent
|
|
||||||
@PermitAll
|
|
||||||
@Scope("prototype")
|
|
||||||
@PageTitle("Request")
|
|
||||||
@Route(value = "/time-off/requests/new", layout = MainLayout.class)
|
|
||||||
public class TimeOffNewRequestView extends VerticalLayout {
|
|
||||||
|
|
||||||
private final ComboBox<Employee> employeeComboBox = new ComboBox<>("Empleado");
|
|
||||||
private final ComboBox<TimeOffRequestType> categoryComboBox = new ComboBox<>("Categoría");
|
|
||||||
private final NumberField availableDaysField = new NumberField("Días disponibles");
|
|
||||||
private final DatePicker startDatePicker = new DatePicker("Fecha de inicio");
|
|
||||||
private final DatePicker endDatePicker = new DatePicker("Fecha final");
|
|
||||||
private final NumberField daysToBeTakenField = new NumberField("Días a tomar");
|
|
||||||
private final NumberField balanceDaysField = new NumberField("Días de saldo");
|
|
||||||
|
|
||||||
private final TimeOffRequestService requestService;
|
|
||||||
private final EmployeeService employeeService;
|
|
||||||
private final TimeOffService timeOffService;
|
|
||||||
|
|
||||||
private final Binder<TimeOffRequest> binder;
|
|
||||||
private TimeOff timeoff;
|
|
||||||
private Employee employee;
|
|
||||||
private LocalDate endDate;
|
|
||||||
|
|
||||||
private Button saveButton;
|
|
||||||
private Button closeButton;
|
|
||||||
|
|
||||||
public TimeOffNewRequestView(final TimeOffRequestService requestService,
|
|
||||||
final EmployeeService employeeService,
|
|
||||||
final TimeOffService timeOffService) {
|
|
||||||
this.requestService = requestService;
|
|
||||||
this.employeeService = employeeService;
|
|
||||||
this.timeOffService = timeOffService;
|
|
||||||
this.binder = new Binder<>(TimeOffRequest.class);
|
|
||||||
initializeView();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeView() {
|
|
||||||
requestService.updateRequestStatuses();
|
|
||||||
configureFormFields();
|
|
||||||
configureButtons();
|
|
||||||
configureBinder();
|
|
||||||
setupFormLayout();
|
|
||||||
configureInitialFieldStates();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureInitialFieldStates() {
|
|
||||||
categoryComboBox.setEnabled(false);
|
|
||||||
startDatePicker.setEnabled(false);
|
|
||||||
endDatePicker.setEnabled(false);
|
|
||||||
availableDaysField.setReadOnly(true);
|
|
||||||
daysToBeTakenField.setReadOnly(true);
|
|
||||||
balanceDaysField.setReadOnly(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureFormFields() {
|
|
||||||
employeeComboBox.setItems(employeeService.findAllEmployees());
|
|
||||||
employeeComboBox.setItemLabelGenerator(emp -> emp.getFirstName() + " " + emp.getLastName());
|
|
||||||
employeeComboBox.addValueChangeListener(event -> {
|
|
||||||
employee = event.getValue();
|
|
||||||
handleEmployeeSelection(event.getValue());
|
|
||||||
});
|
|
||||||
categoryComboBox.addValueChangeListener(event -> {
|
|
||||||
onCategoryChange(event.getValue());
|
|
||||||
handleCategorySelection(event.getValue());
|
|
||||||
});
|
|
||||||
startDatePicker.addValueChangeListener(event -> {
|
|
||||||
LocalDate selectedDate = event.getValue();
|
|
||||||
if (selectedDate != null && (selectedDate.getDayOfWeek().getValue() == 6
|
|
||||||
|| selectedDate.getDayOfWeek().getValue() == 7)) {
|
|
||||||
startDatePicker.setValue(selectedDate.minusDays(1));
|
|
||||||
}
|
|
||||||
updateDatePickerMinValues();
|
|
||||||
});
|
|
||||||
endDatePicker.addValueChangeListener(event -> {
|
|
||||||
if (startDatePicker.getValue() != null) {
|
|
||||||
endDatePicker.setMin(startDatePicker.getValue());
|
|
||||||
}
|
|
||||||
LocalDate selectedDate = event.getValue();
|
|
||||||
if (selectedDate != null && (selectedDate.getDayOfWeek().getValue() == 6
|
|
||||||
|| selectedDate.getDayOfWeek().getValue() == 7)) {
|
|
||||||
endDatePicker.setValue(selectedDate.minusDays(1));
|
|
||||||
}
|
|
||||||
calculateDays();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureBinder() {
|
|
||||||
binder.forField(employeeComboBox)
|
|
||||||
.bind(TimeOffRequest::getEmployee, TimeOffRequest::setEmployee);
|
|
||||||
binder.forField(categoryComboBox)
|
|
||||||
.bind(TimeOffRequest::getCategory, TimeOffRequest::setCategory);
|
|
||||||
binder.forField(availableDaysField)
|
|
||||||
.bind(TimeOffRequest::getAvailableDays, TimeOffRequest::setAvailableDays);
|
|
||||||
binder.forField(startDatePicker)
|
|
||||||
.bind(TimeOffRequest::getStartDate, TimeOffRequest::setStartDate);
|
|
||||||
binder.forField(endDatePicker)
|
|
||||||
.bind(TimeOffRequest::getEndDate, TimeOffRequest::setEndDate);
|
|
||||||
binder.forField(daysToBeTakenField)
|
|
||||||
.bind(TimeOffRequest::getDaysToBeTake, TimeOffRequest::setDaysToBeTake);
|
|
||||||
binder.forField(balanceDaysField)
|
|
||||||
.bind(TimeOffRequest::getDaysBalance, TimeOffRequest::setDaysBalance);
|
|
||||||
binder.setBean(new TimeOffRequest());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleEmployeeSelection(final Employee selectedEmployee) {
|
|
||||||
if (selectedEmployee != null) {
|
|
||||||
categoryComboBox.clear();
|
|
||||||
availableDaysField.clear();
|
|
||||||
startDatePicker.clear();
|
|
||||||
endDatePicker.clear();
|
|
||||||
daysToBeTakenField.clear();
|
|
||||||
balanceDaysField.clear();
|
|
||||||
categoryComboBox.setEnabled(true);
|
|
||||||
startDatePicker.setEnabled(false);
|
|
||||||
endDatePicker.setEnabled(false);
|
|
||||||
filterCategories(selectedEmployee);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void filterCategories(final Employee employee) {
|
|
||||||
categoryComboBox.clear();
|
|
||||||
List<TimeOffRequest> employeeRequests = requestService.findRequestsByEmployeeId(employee.getId());
|
|
||||||
List<TimeOffRequestType> allCategories = Arrays.asList(TimeOffRequestType.values());
|
|
||||||
List<TimeOffRequestType> availableCategories = allCategories.stream()
|
|
||||||
.filter(category -> isCategoryAvailable(employeeRequests, category))
|
|
||||||
.filter(category -> isCategoryAllowedByGender(category, employee.getGender()))
|
|
||||||
.filter(category -> shouldIncludeVacationGestionActual(employeeRequests, category))
|
|
||||||
.filter(category -> shouldIncludeVacationGestionAnterior(employeeRequests, category))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
categoryComboBox.setItems(availableCategories);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private boolean shouldIncludeVacationGestionActual(final List<TimeOffRequest> employeeRequests,
|
|
||||||
final TimeOffRequestType category) {
|
|
||||||
if (category != TimeOffRequestType.VACACION_GESTION_ACTUAL) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return employeeRequests.stream()
|
|
||||||
.anyMatch(request -> request.getCategory() == TimeOffRequestType.VACACION_GESTION_ANTERIOR
|
|
||||||
&& request.getDaysBalance() == 0
|
|
||||||
&& request.getState() == TimeOffRequestStatus.TOMADO);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean shouldIncludeVacationGestionAnterior(final List<TimeOffRequest> employeeRequests,
|
|
||||||
final TimeOffRequestType category) {
|
|
||||||
if (category != TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return employeeRequests.stream()
|
|
||||||
.noneMatch(request -> request.getCategory() == TimeOffRequestType.VACACION_GESTION_ANTERIOR
|
|
||||||
&& request.getDaysBalance() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onCategoryChange(final TimeOffRequestType selectedCategory) {
|
|
||||||
if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ACTUAL
|
|
||||||
|| selectedCategory == TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
|
|
||||||
startDatePicker.setEnabled(true);
|
|
||||||
endDatePicker.setEnabled(true);
|
|
||||||
} else {
|
|
||||||
startDatePicker.setEnabled(true);
|
|
||||||
endDatePicker.setEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isCategoryAvailable(final List<TimeOffRequest> employeeRequests,
|
|
||||||
final TimeOffRequestType category) {
|
|
||||||
if (category == TimeOffRequestType.CUMPLEAÑOS && employee.getBirthday() == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TimeOffRequest> requestsByCategory = employeeRequests.stream()
|
|
||||||
.filter(request -> request.getCategory() == category)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
if (requestsByCategory.isEmpty()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeOffRequest latestRequest = requestsByCategory.stream()
|
|
||||||
.max(Comparator.comparing(TimeOffRequest::getStartDate))
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
boolean isSpecialCategory = category == TimeOffRequestType.PERMISOS_DE_SALUD
|
|
||||||
|| category == TimeOffRequestType.VACACION_GESTION_ACTUAL
|
|
||||||
|| category == TimeOffRequestType.VACACION_GESTION_ANTERIOR;
|
|
||||||
|
|
||||||
if (isSpecialCategory) {
|
|
||||||
return (latestRequest.getState() == TimeOffRequestStatus.TOMADO
|
|
||||||
&& latestRequest.getDaysBalance() > 0)
|
|
||||||
|| latestRequest.getState() == TimeOffRequestStatus.RECHAZADO
|
|
||||||
|| (latestRequest.getState() == TimeOffRequestStatus.TOMADO
|
|
||||||
&& latestRequest.getDaysBalance() == 0
|
|
||||||
&& latestRequest.getExpiration().isBefore(LocalDate.now()));
|
|
||||||
} else {
|
|
||||||
return (latestRequest.getState() == TimeOffRequestStatus.TOMADO
|
|
||||||
&& latestRequest.getExpiration().isBefore(LocalDate.now()))
|
|
||||||
|| latestRequest.getState() == TimeOffRequestStatus.RECHAZADO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isCategoryAllowedByGender(final TimeOffRequestType category, final Employee.Gender gender) {
|
|
||||||
if (gender == Employee.Gender.MALE) {
|
|
||||||
return category != TimeOffRequestType.MATERNIDAD
|
|
||||||
&& category != TimeOffRequestType.DIA_DE_LA_MADRE
|
|
||||||
&& category != TimeOffRequestType.DIA_DE_LA_MUJER_INTERNACIONAL
|
|
||||||
&& category != TimeOffRequestType.DIA_DE_LA_MUJER_NACIONAL;
|
|
||||||
} else {
|
|
||||||
return category != TimeOffRequestType.DIA_DEL_PADRE
|
|
||||||
&& category != TimeOffRequestType.PATERNIDAD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleCategorySelection(final TimeOffRequestType selectedCategory) {
|
|
||||||
if (selectedCategory != null) {
|
|
||||||
updateAvailableDays(selectedCategory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateAvailableDays(final TimeOffRequestType selectedCategory) {
|
|
||||||
timeoff = timeOffService.findVacationByCategory(selectedCategory);
|
|
||||||
UUID employeeId = employeeComboBox.getValue().getId();
|
|
||||||
List<TimeOffRequest> requests = requestService.findByEmployeeAndCategory(employeeId, selectedCategory);
|
|
||||||
|
|
||||||
if (timeoff != null) {
|
|
||||||
TimeOffRequest requestWithBalance = requests.stream()
|
|
||||||
.filter(request -> request.getDaysBalance() > 0
|
|
||||||
&& request.getState() != TimeOffRequestStatus.VENCIDO
|
|
||||||
&& request.getState() != TimeOffRequestStatus.RECHAZADO)
|
|
||||||
.max(Comparator.comparing(TimeOffRequest::getStartDate))
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
if (requestWithBalance != null) {
|
|
||||||
if (requestWithBalance.getState() == TimeOffRequestStatus.TOMADO
|
|
||||||
&& requestWithBalance.getDaysBalance() > 0) {
|
|
||||||
availableDaysField.setValue(requestWithBalance.getDaysBalance());
|
|
||||||
} else {
|
|
||||||
availableDaysField.setValue(timeoff.getDuration());
|
|
||||||
}
|
|
||||||
} else if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ACTUAL
|
|
||||||
|| selectedCategory == TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
|
|
||||||
LocalDate dateOfEntry = employeeComboBox.getValue().getDateOfEntry();
|
|
||||||
LocalDate currentDate = LocalDate.now();
|
|
||||||
long yearsOfService = ChronoUnit.YEARS.between(dateOfEntry, currentDate);
|
|
||||||
|
|
||||||
if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
|
|
||||||
yearsOfService -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (yearsOfService > 10) {
|
|
||||||
availableDaysField.setValue(30.0);
|
|
||||||
} else if (yearsOfService > 5) {
|
|
||||||
availableDaysField.setValue(20.0);
|
|
||||||
} else if (yearsOfService > 1) {
|
|
||||||
availableDaysField.setValue(15.0);
|
|
||||||
} else {
|
|
||||||
availableDaysField.setValue(0.0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
availableDaysField.setValue(timeoff.getDuration());
|
|
||||||
}
|
|
||||||
setDatePickerLimits(timeoff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setDatePickerLimits(final TimeOff timeoff) {
|
|
||||||
LocalDate startDate;
|
|
||||||
endDate = null;
|
|
||||||
|
|
||||||
UUID employeeId = employee.getId();
|
|
||||||
List<TimeOffRequest> previousRequests
|
|
||||||
= requestService.findByEmployeeAndCategory(employeeId, timeoff.getCategory());
|
|
||||||
|
|
||||||
int startYear = calculateStartYear(previousRequests);
|
|
||||||
|
|
||||||
startDate = determineStartDate(timeoff, startYear);
|
|
||||||
|
|
||||||
if (startDate.isBefore(LocalDate.now())) {
|
|
||||||
startDate = determineStartDate(timeoff, startYear + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startDate != null) {
|
|
||||||
if (timeoff.getExpiration() != null) {
|
|
||||||
endDate = startDate.plusDays(timeoff.getExpiration().intValue() - 1);
|
|
||||||
} else {
|
|
||||||
endDate = LocalDate.of(startDate.getYear(), 12, 31);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
startDate = LocalDate.now();
|
|
||||||
}
|
|
||||||
|
|
||||||
setPickerValues(timeoff, startDate);
|
|
||||||
setPickerLimits(startDate, endDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int calculateStartYear(final List<TimeOffRequest> previousRequests) {
|
|
||||||
if (previousRequests.isEmpty()) {
|
|
||||||
return LocalDate.now().getYear();
|
|
||||||
}
|
|
||||||
|
|
||||||
int lastRequestYear = previousRequests.stream()
|
|
||||||
.max(Comparator.comparing(TimeOffRequest::getStartDate))
|
|
||||||
.map(request -> request.getStartDate().getYear())
|
|
||||||
.orElse(LocalDate.now().getYear());
|
|
||||||
|
|
||||||
if (previousRequests.getLast().getState() != TimeOffRequestStatus.RECHAZADO) {
|
|
||||||
lastRequestYear = lastRequestYear + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int currentYear = LocalDate.now().getYear();
|
|
||||||
return Math.max(lastRequestYear, currentYear);
|
|
||||||
}
|
|
||||||
|
|
||||||
private LocalDate determineStartDate(final TimeOff timeoff, final int startYear) {
|
|
||||||
if (timeoff.getCategory() == TimeOffRequestType.CUMPLEAÑOS && employee.getBirthday() != null) {
|
|
||||||
return LocalDate.of(startYear, employee.getBirthday().getMonth(), employee.getBirthday().getDayOfMonth());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeoff.getDate() != null) {
|
|
||||||
return LocalDate.of(startYear, timeoff.getDate().getMonthValue(), timeoff.getDate().getDayOfMonth());
|
|
||||||
}
|
|
||||||
|
|
||||||
return LocalDate.now();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setPickerValues(final TimeOff timeoff, final LocalDate startDate) {
|
|
||||||
startDatePicker.setValue(startDate);
|
|
||||||
|
|
||||||
if ((timeoff.getDuration() != null && timeoff.getDuration() == 0.5)
|
|
||||||
|| timeoff.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD
|
|
||||||
|| timeoff.getCategory() == TimeOffRequestType.CUMPLEAÑOS) {
|
|
||||||
|
|
||||||
endDatePicker.setValue(startDate);
|
|
||||||
} else {
|
|
||||||
int durationDays = (timeoff.getDuration() != null ? timeoff.getDuration().intValue() - 1 : 0);
|
|
||||||
endDatePicker.setValue(startDate.plusDays(durationDays));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setPickerLimits(final LocalDate startDate, final LocalDate endDate) {
|
|
||||||
startDatePicker.setMin(startDate);
|
|
||||||
startDatePicker.setMax(endDate);
|
|
||||||
endDatePicker.setMin(startDate);
|
|
||||||
endDatePicker.setMax(endDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDatePickerMinValues() {
|
|
||||||
LocalDate startDate = startDatePicker.getValue();
|
|
||||||
if (availableDaysField.getValue() != null) {
|
|
||||||
if (availableDaysField.getValue() == 0.5) {
|
|
||||||
endDatePicker.setValue(startDate.plusDays(0));
|
|
||||||
} else {
|
|
||||||
endDatePicker.setValue(startDate.plusDays(availableDaysField.getValue().intValue() - 1));
|
|
||||||
}
|
|
||||||
calculateDays();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calculateDays() {
|
|
||||||
LocalDate startDate = startDatePicker.getValue();
|
|
||||||
LocalDate endDate = endDatePicker.getValue();
|
|
||||||
Double availableDays = availableDaysField.getValue();
|
|
||||||
|
|
||||||
if (areDatesValid(startDate, endDate)) {
|
|
||||||
long workDays = countWorkDaysBetween(startDate, endDate);
|
|
||||||
|
|
||||||
daysToBeTakenField.setValue((double) workDays);
|
|
||||||
|
|
||||||
balanceDaysField.setValue(availableDaysField.getValue() - workDays);
|
|
||||||
|
|
||||||
|
|
||||||
double daysToBeTaken = calculateDaysBetween(startDate, endDate);
|
|
||||||
setDaysToBeTakenField(daysToBeTaken);
|
|
||||||
|
|
||||||
double balanceDays = calculateBalanceDays(availableDays, daysToBeTakenField.getValue());
|
|
||||||
balanceDaysField.setValue(balanceDays);
|
|
||||||
|
|
||||||
if (balanceDays < 0.0) {
|
|
||||||
clearFields();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daysToBeTakenField.getValue() > 10
|
|
||||||
&& (categoryComboBox.getValue() == TimeOffRequestType.VACACION_GESTION_ANTERIOR
|
|
||||||
|| categoryComboBox.getValue() == TimeOffRequestType.VACACION_GESTION_ACTUAL)) {
|
|
||||||
clearFields();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean areDatesValid(final LocalDate startDate, final LocalDate endDate) {
|
|
||||||
return startDate != null && endDate != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long countWorkDaysBetween(final LocalDate startDate, final LocalDate endDate) {
|
|
||||||
return startDate.datesUntil(endDate.plusDays(1))
|
|
||||||
.filter(date -> date.getDayOfWeek() != DayOfWeek.SATURDAY && date.getDayOfWeek() != DayOfWeek.SUNDAY)
|
|
||||||
.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
private double calculateDaysBetween(final LocalDate startDate, final LocalDate endDate) {
|
|
||||||
return startDate.datesUntil(endDate.plusDays(1))
|
|
||||||
.filter(date -> {
|
|
||||||
DayOfWeek day = date.getDayOfWeek();
|
|
||||||
return day != DayOfWeek.SATURDAY && day != DayOfWeek.SUNDAY;
|
|
||||||
})
|
|
||||||
.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setDaysToBeTakenField(final double daysToBeTaken) {
|
|
||||||
if (timeoff.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD
|
|
||||||
|| timeoff.getCategory() == TimeOffRequestType.CUMPLEAÑOS
|
|
||||||
|| timeoff.getCategory() == TimeOffRequestType.DIA_DEL_PADRE
|
|
||||||
|| timeoff.getCategory() == TimeOffRequestType.DIA_DE_LA_MADRE
|
|
||||||
|| timeoff.getCategory() == TimeOffRequestType.DIA_DE_LA_MUJER_INTERNACIONAL
|
|
||||||
|| timeoff.getCategory() == TimeOffRequestType.DIA_DE_LA_MUJER_NACIONAL) {
|
|
||||||
daysToBeTakenField.setValue(0.5);
|
|
||||||
} else {
|
|
||||||
daysToBeTakenField.setValue(daysToBeTaken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double calculateBalanceDays(final double availableDays, final double daysToBeTaken) {
|
|
||||||
return availableDays - daysToBeTaken;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearFields() {
|
|
||||||
daysToBeTakenField.clear();
|
|
||||||
balanceDaysField.clear();
|
|
||||||
endDatePicker.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureButtons() {
|
|
||||||
saveButton = new Button("Guardar", event -> saveRequest());
|
|
||||||
closeButton = new Button("Salir", event -> closeForm());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupFormLayout() {
|
|
||||||
add(
|
|
||||||
new H3("Añadir solicitud de vacaciones"),
|
|
||||||
employeeComboBox,
|
|
||||||
categoryComboBox,
|
|
||||||
availableDaysField,
|
|
||||||
startDatePicker,
|
|
||||||
endDatePicker,
|
|
||||||
daysToBeTakenField,
|
|
||||||
balanceDaysField,
|
|
||||||
new HorizontalLayout(saveButton, closeButton)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveRequest() {
|
|
||||||
if (!binder.validate().isOk()) {
|
|
||||||
Notification.show("Rellene correctamente todos los campos obligatorios.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!validateForm()) {
|
|
||||||
Notification.show("Por favor, complete los campos antes de guardar");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeOffRequest request = prepareRequest();
|
|
||||||
|
|
||||||
if (request.getCategory() == TimeOffRequestType.VACACION_GESTION_ACTUAL) {
|
|
||||||
handleVacationRequest(request);
|
|
||||||
} else {
|
|
||||||
handleExistingRequests(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
long differentDays = ChronoUnit.DAYS.between(LocalDate.now(), request.getStartDate());
|
|
||||||
if (differentDays >= -15 && differentDays <= 90) {
|
|
||||||
requestService.saveTimeOffRequest(request);
|
|
||||||
Notification.show("Solicitud guardada correctamente.");
|
|
||||||
closeForm();
|
|
||||||
} else {
|
|
||||||
Notification.show(
|
|
||||||
"La fecha de inicio debe encontrarse dentro del rango de 15 días a 3 meses de anticipación."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private TimeOffRequest prepareRequest() {
|
|
||||||
TimeOffRequest request = binder.getBean();
|
|
||||||
request.setStartDate(startDatePicker.getValue());
|
|
||||||
request.setAvailableDays(availableDaysField.getValue());
|
|
||||||
request.setExpiration(endDate != null ? endDate : endDatePicker.getValue());
|
|
||||||
request.setState(TimeOffRequestStatus.SOLICITADO);
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleExistingRequests(final TimeOffRequest request) {
|
|
||||||
List<TimeOffRequest> existingRequests =
|
|
||||||
requestService.findByEmployeeAndCategory(employee.getId(), request.getCategory());
|
|
||||||
|
|
||||||
int maxRequests = request.getCategory() != TimeOffRequestType.PERMISOS_DE_SALUD
|
|
||||||
&& !request.getCategory().name().startsWith("VACACION")
|
|
||||||
&& request.getCategory() != TimeOffRequestType.CUMPLEAÑOS
|
|
||||||
? 2 : 1;
|
|
||||||
|
|
||||||
if (existingRequests.size() >= maxRequests) {
|
|
||||||
existingRequests.stream()
|
|
||||||
.min(Comparator.comparing(TimeOffRequest::getStartDate))
|
|
||||||
.ifPresent(oldestRequest -> requestService.deleteTimeOffRequest(oldestRequest.getId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleVacationRequest(final TimeOffRequest request) {
|
|
||||||
List<TimeOffRequest> existingRequests = requestService.findByEmployeeAndCategory(
|
|
||||||
employee.getId(),
|
|
||||||
TimeOffRequestType.VACACION_GESTION_ACTUAL
|
|
||||||
);
|
|
||||||
if (!existingRequests.isEmpty()) {
|
|
||||||
TimeOffRequest existingRequest = existingRequests.getFirst();
|
|
||||||
existingRequest.setCategory(TimeOffRequestType.VACACION_GESTION_ANTERIOR);
|
|
||||||
requestService.saveTimeOffRequest(existingRequest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean validateForm() {
|
|
||||||
return employeeComboBox.getValue() != null
|
|
||||||
&& categoryComboBox.getValue() != null
|
|
||||||
&& startDatePicker.getValue() != null
|
|
||||||
&& endDatePicker.getValue() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void closeForm() {
|
|
||||||
getUI().ifPresent(ui -> ui.navigate(TimeOffRequestListView.class));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,508 +0,0 @@
|
|||||||
package com.primefactorsolutions.views.timeoff;
|
|
||||||
|
|
||||||
import com.primefactorsolutions.model.*;
|
|
||||||
import com.primefactorsolutions.service.EmployeeService;
|
|
||||||
import com.primefactorsolutions.service.TeamService;
|
|
||||||
import com.primefactorsolutions.service.TimeOffRequestService;
|
|
||||||
import com.primefactorsolutions.service.TimeOffService;
|
|
||||||
import com.primefactorsolutions.views.BaseView;
|
|
||||||
import com.primefactorsolutions.views.MainLayout;
|
|
||||||
import com.vaadin.flow.component.ClickEvent;
|
|
||||||
import com.vaadin.flow.component.Component;
|
|
||||||
import com.vaadin.flow.component.ComponentEventListener;
|
|
||||||
import com.vaadin.flow.component.UI;
|
|
||||||
import com.vaadin.flow.component.button.Button;
|
|
||||||
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.function.ValueProvider;
|
|
||||||
import com.vaadin.flow.router.PageTitle;
|
|
||||||
import com.vaadin.flow.router.Route;
|
|
||||||
import com.vaadin.flow.server.StreamRegistration;
|
|
||||||
import com.vaadin.flow.server.StreamResource;
|
|
||||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
|
||||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
|
||||||
import jakarta.annotation.security.PermitAll;
|
|
||||||
import org.apache.poi.ss.usermodel.*;
|
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
||||||
import org.springframework.context.annotation.Scope;
|
|
||||||
import org.vaadin.firitin.components.grid.PagingGrid;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UncheckedIOException;
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.Period;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static com.primefactorsolutions.views.Constants.PAGE_SIZE;
|
|
||||||
import static com.primefactorsolutions.views.util.MenuBarUtils.createIconItem;
|
|
||||||
|
|
||||||
@SpringComponent
|
|
||||||
@Scope("prototype")
|
|
||||||
@PageTitle("Requests")
|
|
||||||
@Route(value = "/time-off/requests", layout = MainLayout.class)
|
|
||||||
@PermitAll
|
|
||||||
public class TimeOffRequestListView extends BaseView {
|
|
||||||
|
|
||||||
private final TimeOffRequestService requestService;
|
|
||||||
private final EmployeeService employeeService;
|
|
||||||
private final TeamService teamService;
|
|
||||||
private final TimeOffService timeOffService;
|
|
||||||
private final PagingGrid<Employee> requestGrid = new PagingGrid<>();
|
|
||||||
private ComboBox<Employee> employeeFilter;
|
|
||||||
private ComboBox<Team> teamFilter;
|
|
||||||
private ComboBox<TimeOffRequestType> categoryFilter;
|
|
||||||
private ComboBox<Status> stateFilter;
|
|
||||||
|
|
||||||
public TimeOffRequestListView(
|
|
||||||
final AuthenticationContext authenticationContext,
|
|
||||||
final TimeOffRequestService requestService,
|
|
||||||
final EmployeeService employeeService,
|
|
||||||
final TeamService teamService,
|
|
||||||
final TimeOffService timeOffService) {
|
|
||||||
super(authenticationContext);
|
|
||||||
this.requestService = requestService;
|
|
||||||
this.employeeService = employeeService;
|
|
||||||
this.teamService = teamService;
|
|
||||||
this.timeOffService = timeOffService;
|
|
||||||
initializeView();
|
|
||||||
refreshGeneralRequestGrid(null, null, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeView() {
|
|
||||||
requestService.updateRequestStatuses();
|
|
||||||
|
|
||||||
if (isRoleAdmin()) {
|
|
||||||
final Button downloadButton = new Button("Descargar reporte", event -> downloadReport());
|
|
||||||
getCurrentPageLayout().add(downloadButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
setupFilters();
|
|
||||||
setupRequestGrid();
|
|
||||||
getCurrentPageLayout().add(requestGrid);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupFilters() {
|
|
||||||
final HorizontalLayout hl = new HorizontalLayout();
|
|
||||||
hl.add(createEmployeeFilter());
|
|
||||||
hl.add(createTeamFilter());
|
|
||||||
hl.add(createCategoryFilter());
|
|
||||||
hl.add(createStateFilter());
|
|
||||||
getCurrentPageLayout().add(hl);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupRequestGrid() {
|
|
||||||
requestGrid.addColumn(this::getEmployeeFullName).setHeader("Empleado");
|
|
||||||
requestGrid.addColumn(this::getTeamName).setHeader("Equipo");
|
|
||||||
requestGrid.addColumn(this::getEmployeeStatus).setHeader("Estado del empleado");
|
|
||||||
requestGrid.addColumn(this::getCategory).setHeader("Categoria");
|
|
||||||
requestGrid.addColumn(this::getGeneralTotal).setHeader("Total general");
|
|
||||||
requestGrid.addComponentColumn((ValueProvider<Employee, Component>) employee -> {
|
|
||||||
final MenuBar menuBar = new MenuBar();
|
|
||||||
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
|
|
||||||
final MenuItem view = createIconItem(menuBar, VaadinIcon.EYE, "View");
|
|
||||||
view.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent ->
|
|
||||||
navigateToTimeOffRequestView(employee.getId()));
|
|
||||||
|
|
||||||
return menuBar;
|
|
||||||
});
|
|
||||||
|
|
||||||
requestGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
|
|
||||||
requestGrid.setPageSize(PAGE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshGeneralRequestGrid(final Employee employee,
|
|
||||||
final Team team,
|
|
||||||
final TimeOffRequestType category,
|
|
||||||
final Status state) {
|
|
||||||
requestGrid.setPagingDataProvider((page, pageSize) -> {
|
|
||||||
int start = (int) (page * requestGrid.getPageSize());
|
|
||||||
return fetchFilteredEmployees(start, pageSize, employee, team, category, state);
|
|
||||||
});
|
|
||||||
requestGrid.getDataProvider().refreshAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Employee> fetchFilteredEmployees(final int start,
|
|
||||||
final int pageSize,
|
|
||||||
final Employee employee,
|
|
||||||
final Team team,
|
|
||||||
final TimeOffRequestType category,
|
|
||||||
final Status state) {
|
|
||||||
List<Employee> filteredEmployees = employeeService.findAllEmployees();
|
|
||||||
|
|
||||||
if (employee != null) {
|
|
||||||
filteredEmployees = filteredEmployees.stream()
|
|
||||||
.filter(emp -> emp.getId().equals(employee.getId()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (team != null) {
|
|
||||||
filteredEmployees = filteredEmployees.stream()
|
|
||||||
.filter(emp -> emp.getTeam() != null && emp.getTeam().getId().equals(team.getId()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (category != null) {
|
|
||||||
filteredEmployees = filteredEmployees.stream()
|
|
||||||
.filter(emp -> {
|
|
||||||
Optional<TimeOffRequest> request = requestService
|
|
||||||
.findByEmployeeAndState(emp.getId(), TimeOffRequestStatus.EN_USO);
|
|
||||||
return request.isPresent() && request.get().getCategory() == category;
|
|
||||||
})
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state != null) {
|
|
||||||
filteredEmployees = filteredEmployees.stream()
|
|
||||||
.filter(emp -> {
|
|
||||||
Optional<TimeOffRequest> request = requestService
|
|
||||||
.findByEmployeeAndState(emp.getId(), TimeOffRequestStatus.EN_USO);
|
|
||||||
return state == Status.EN_DESCANSO ? request.isPresent() : request.isEmpty();
|
|
||||||
})
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
int end = Math.min(start + pageSize, filteredEmployees.size());
|
|
||||||
return filteredEmployees.subList(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getEmployeeFullName(final Employee employee) {
|
|
||||||
return employee.getFirstName() + " " + employee.getLastName();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTeamName(final Employee employee) {
|
|
||||||
Team team = employee.getTeam();
|
|
||||||
return team != null ? team.getName() : "Sin asignar";
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTeamLabel(final Team team) {
|
|
||||||
return team.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getEmployeeStatus(final Employee employee) {
|
|
||||||
Optional<TimeOffRequest> activeRequest = requestService
|
|
||||||
.findByEmployeeAndState(employee.getId(), TimeOffRequestStatus.EN_USO);
|
|
||||||
return activeRequest.isPresent() ? "EN_DESCANSO" : "EN_FUNCIONES";
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCategory(final Employee employee) {
|
|
||||||
Optional<TimeOffRequest> activeRequest = requestService
|
|
||||||
.findByEmployeeAndState(employee.getId(), TimeOffRequestStatus.EN_USO);
|
|
||||||
return activeRequest.map(request -> request.getCategory().toString()).orElse("");
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getGeneralTotal(final Employee employee) {
|
|
||||||
List<TimeOffRequest> employeeRequests = requestService.findRequestsByEmployeeId(employee.getId());
|
|
||||||
List<TimeOff> timeOffs = timeOffService.findVacations();
|
|
||||||
|
|
||||||
List<Double> vacationDays = calculateVacationDays(employee);
|
|
||||||
|
|
||||||
double utilizedVacationCurrentDays = vacationDays.get(1);
|
|
||||||
List<TimeOffRequest> vacationCurrentRequests = requestService
|
|
||||||
.findByEmployeeAndCategory(employee.getId(), TimeOffRequestType.VACACION_GESTION_ACTUAL);
|
|
||||||
if (vacationCurrentRequests != null && !vacationCurrentRequests.isEmpty()) {
|
|
||||||
utilizedVacationCurrentDays = vacationCurrentRequests.getLast().getDaysBalance();
|
|
||||||
}
|
|
||||||
double totalVacationCurrentDays = vacationDays.get(1) - (vacationDays.get(1) - utilizedVacationCurrentDays);
|
|
||||||
|
|
||||||
double utilizedVacationPreviousDays = vacationDays.get(0);
|
|
||||||
List<TimeOffRequest> vacationPreviousRequests = requestService
|
|
||||||
.findByEmployeeAndCategory(employee.getId(), TimeOffRequestType.VACACION_GESTION_ANTERIOR);
|
|
||||||
if (vacationPreviousRequests != null && !vacationPreviousRequests.isEmpty()) {
|
|
||||||
utilizedVacationPreviousDays = vacationPreviousRequests.getLast().getDaysBalance();
|
|
||||||
}
|
|
||||||
double totalVacationPreviousDays = vacationDays.getFirst()
|
|
||||||
- (vacationDays.getFirst() - utilizedVacationPreviousDays);
|
|
||||||
|
|
||||||
|
|
||||||
double totalUtilized = calculateTotalUtilized(employeeRequests);
|
|
||||||
double totalVacations = totalVacationCurrentDays + totalVacationPreviousDays;
|
|
||||||
double totalAvailable = calculateTotalAvailable(timeOffs, employeeRequests, employee);
|
|
||||||
|
|
||||||
double generalTotal = totalAvailable + totalVacations - totalUtilized;
|
|
||||||
|
|
||||||
if (employee.getDateOfExit() != null
|
|
||||||
&& (employee.getDateOfExit().isBefore(LocalDate.now())
|
|
||||||
|| employee.getDateOfExit().isEqual(LocalDate.now()))) {
|
|
||||||
generalTotal = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return String.valueOf(generalTotal);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<TimeOffRequestType> getExcludedCategories() {
|
|
||||||
return Set.of(
|
|
||||||
TimeOffRequestType.MATERNIDAD,
|
|
||||||
TimeOffRequestType.PATERNIDAD,
|
|
||||||
TimeOffRequestType.MATRIMONIO,
|
|
||||||
TimeOffRequestType.DUELO_1ER_GRADO,
|
|
||||||
TimeOffRequestType.DUELO_2ER_GRADO,
|
|
||||||
TimeOffRequestType.DIA_DEL_PADRE,
|
|
||||||
TimeOffRequestType.DIA_DE_LA_MADRE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<TimeOffRequestType> getGenderSpecificExclusions() {
|
|
||||||
return Set.of(
|
|
||||||
TimeOffRequestType.DIA_DE_LA_MUJER_INTERNACIONAL,
|
|
||||||
TimeOffRequestType.DIA_DE_LA_MUJER_NACIONAL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private double calculateTotalUtilized(final List<TimeOffRequest> employeeRequests) {
|
|
||||||
int currentYear = LocalDate.now().getYear();
|
|
||||||
return employeeRequests.stream()
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.filter(request -> request.getState() == TimeOffRequestStatus.APROBADO
|
|
||||||
|| request.getState() == TimeOffRequestStatus.TOMADO)
|
|
||||||
.filter(request -> request.getCategory() != TimeOffRequestType.PERMISOS_DE_SALUD)
|
|
||||||
.filter(request -> request.getCategory() != TimeOffRequestType.VACACION_GESTION_ACTUAL)
|
|
||||||
.filter(request -> request.getCategory() != TimeOffRequestType.VACACION_GESTION_ANTERIOR)
|
|
||||||
.filter(request -> request.getStartDate() != null && (
|
|
||||||
request.getStartDate().getYear() == currentYear
|
|
||||||
|| (request.getCategory().name().startsWith("VACACION")
|
|
||||||
&& request.getStartDate().getYear() == currentYear - 1)
|
|
||||||
))
|
|
||||||
.mapToDouble(request -> request.getDaysToBeTake() != null ? request.getDaysToBeTake() : 0.0)
|
|
||||||
.sum();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Double> calculateVacationDays(final Employee employee) {
|
|
||||||
List<Double> vacationDays = new ArrayList<>();
|
|
||||||
|
|
||||||
if (employee.getDateOfEntry() != null) {
|
|
||||||
LocalDate entryDate = employee.getDateOfEntry();
|
|
||||||
LocalDate today = LocalDate.now();
|
|
||||||
|
|
||||||
boolean hasAnniversaryPassed = entryDate.getMonthValue() < today.getMonthValue()
|
|
||||||
|| (entryDate.getMonthValue() == today.getMonthValue() && entryDate.getDayOfMonth()
|
|
||||||
<= today.getDayOfMonth());
|
|
||||||
|
|
||||||
LocalDate previousVacationYearDate;
|
|
||||||
LocalDate currentVacationYearDate;
|
|
||||||
|
|
||||||
if (hasAnniversaryPassed) {
|
|
||||||
previousVacationYearDate = LocalDate.of(
|
|
||||||
today.getYear() - 1,
|
|
||||||
entryDate.getMonth(),
|
|
||||||
entryDate.getDayOfMonth()
|
|
||||||
);
|
|
||||||
currentVacationYearDate = LocalDate.of(
|
|
||||||
today.getYear(),
|
|
||||||
entryDate.getMonth(),
|
|
||||||
entryDate.getDayOfMonth()
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
previousVacationYearDate = LocalDate.of(
|
|
||||||
today.getYear() - 2,
|
|
||||||
entryDate.getMonth(),
|
|
||||||
entryDate.getDayOfMonth()
|
|
||||||
);
|
|
||||||
currentVacationYearDate = LocalDate.of(
|
|
||||||
today.getYear() - 1,
|
|
||||||
entryDate.getMonth(),
|
|
||||||
entryDate.getDayOfMonth()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
vacationDays.add(calculateVacationDaysSinceEntry(entryDate, previousVacationYearDate));
|
|
||||||
vacationDays.add(calculateVacationDaysSinceEntry(entryDate, currentVacationYearDate));
|
|
||||||
} else {
|
|
||||||
vacationDays.add(0.0);
|
|
||||||
vacationDays.add(0.0);
|
|
||||||
}
|
|
||||||
return vacationDays;
|
|
||||||
}
|
|
||||||
|
|
||||||
private double calculateTotalAvailable(final List<TimeOff> timeOffs, final List<TimeOffRequest> employeeRequests,
|
|
||||||
final Employee employee) {
|
|
||||||
Set<TimeOffRequestType> excludedCategories = getExcludedCategories();
|
|
||||||
Set<TimeOffRequestType> genderSpecificExclusions = getGenderSpecificExclusions();
|
|
||||||
Set<TimeOffRequestType> employeeRequestCategories = employeeRequests.stream()
|
|
||||||
.map(TimeOffRequest::getCategory)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
|
|
||||||
double healthLicence = 2;
|
|
||||||
List<TimeOffRequest> healthRequests = requestService
|
|
||||||
.findByEmployeeAndCategory(employee.getId(), TimeOffRequestType.PERMISOS_DE_SALUD);
|
|
||||||
if (healthRequests != null && !healthRequests.isEmpty()) {
|
|
||||||
healthLicence = healthRequests.getLast().getDaysBalance();
|
|
||||||
}
|
|
||||||
|
|
||||||
double totalAvailable = timeOffs.stream()
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.filter(vacation -> vacation.getCategory() != TimeOffRequestType.PERMISOS_DE_SALUD)
|
|
||||||
.filter(vacation -> shouldIncludeVacation(
|
|
||||||
vacation,
|
|
||||||
excludedCategories,
|
|
||||||
genderSpecificExclusions,
|
|
||||||
employee, employeeRequestCategories
|
|
||||||
))
|
|
||||||
.mapToDouble(vacation -> vacation.getDuration() != null ? vacation.getDuration() : 0.0)
|
|
||||||
.sum();
|
|
||||||
|
|
||||||
return totalAvailable + healthLicence;
|
|
||||||
}
|
|
||||||
|
|
||||||
private double calculateVacationDaysSinceEntry(final LocalDate dateOfEntry, final LocalDate date) {
|
|
||||||
int yearsOfService = dateOfEntry != null ? Period.between(dateOfEntry, date).getYears() : 0;
|
|
||||||
if (yearsOfService > 10) {
|
|
||||||
return 30;
|
|
||||||
}
|
|
||||||
if (yearsOfService > 5) {
|
|
||||||
return 20;
|
|
||||||
}
|
|
||||||
if (yearsOfService > 1) {
|
|
||||||
return 15;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean shouldIncludeVacation(final TimeOff timeoff,
|
|
||||||
final Set<TimeOffRequestType> excludedCategories,
|
|
||||||
final Set<TimeOffRequestType> genderSpecificExclusions,
|
|
||||||
final Employee employee,
|
|
||||||
final Set<TimeOffRequestType> employeeRequestCategories) {
|
|
||||||
if (excludedCategories.contains(timeoff.getCategory())
|
|
||||||
&& !employeeRequestCategories.contains(timeoff.getCategory())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isFemale(employee) || !genderSpecificExclusions.contains(timeoff.getCategory());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isFemale(final Employee employee) {
|
|
||||||
return employee.getGender() == Employee.Gender.FEMALE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ComboBox<Employee> createEmployeeFilter() {
|
|
||||||
employeeFilter = new ComboBox<>("Empleado");
|
|
||||||
|
|
||||||
final List<Employee> employees = new ArrayList<>(employeeService.findAllEmployees());
|
|
||||||
employeeFilter.setPlaceholder("TODOS");
|
|
||||||
employeeFilter.setClearButtonVisible(true);
|
|
||||||
employeeFilter.setItems(employees);
|
|
||||||
employeeFilter.setItemLabelGenerator(this::getEmployeeFullName);
|
|
||||||
employeeFilter.addValueChangeListener(event ->
|
|
||||||
refreshGeneralRequestGrid(
|
|
||||||
event.getValue(),
|
|
||||||
teamFilter.getValue(),
|
|
||||||
categoryFilter.getValue(),
|
|
||||||
stateFilter.getValue()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return employeeFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ComboBox<Team> createTeamFilter() {
|
|
||||||
teamFilter = new ComboBox<>("Equipo");
|
|
||||||
teamFilter.setPlaceholder("TODOS");
|
|
||||||
teamFilter.setClearButtonVisible(true);
|
|
||||||
final List<Team> teams = new ArrayList<>(teamService.findAllTeams());
|
|
||||||
teamFilter.setItems(teams);
|
|
||||||
teamFilter.setItemLabelGenerator(this::getTeamLabel);
|
|
||||||
teamFilter.addValueChangeListener(event ->
|
|
||||||
refreshGeneralRequestGrid(
|
|
||||||
employeeFilter.getValue(),
|
|
||||||
event.getValue(),
|
|
||||||
categoryFilter.getValue(),
|
|
||||||
stateFilter.getValue()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return teamFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ComboBox<TimeOffRequestType> createCategoryFilter() {
|
|
||||||
categoryFilter = new ComboBox<>("Category");
|
|
||||||
categoryFilter.setClearButtonVisible(true);
|
|
||||||
categoryFilter.setPlaceholder("TODOS");
|
|
||||||
categoryFilter.setItems(TimeOffRequestType.values());
|
|
||||||
categoryFilter.addValueChangeListener(event ->
|
|
||||||
refreshGeneralRequestGrid(
|
|
||||||
employeeFilter.getValue(),
|
|
||||||
teamFilter.getValue(),
|
|
||||||
event.getValue(),
|
|
||||||
stateFilter.getValue()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return categoryFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ComboBox<Status> createStateFilter() {
|
|
||||||
stateFilter = new ComboBox<>("Estado del empleado");
|
|
||||||
stateFilter.setPlaceholder("TODOS");
|
|
||||||
stateFilter.setClearButtonVisible(true);
|
|
||||||
stateFilter.setItems(Status.values());
|
|
||||||
stateFilter.addValueChangeListener(event ->
|
|
||||||
refreshGeneralRequestGrid(
|
|
||||||
employeeFilter.getValue(),
|
|
||||||
teamFilter.getValue(),
|
|
||||||
categoryFilter.getValue(),
|
|
||||||
event.getValue()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return stateFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum Status {
|
|
||||||
EN_DESCANSO,
|
|
||||||
EN_FUNCIONES
|
|
||||||
}
|
|
||||||
|
|
||||||
private void navigateToTimeOffRequestView(final UUID idEmployee) {
|
|
||||||
getUI().ifPresent(ui -> ui.navigate(TimeOffRequestsByEmployeeView.class, idEmployee.toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private ByteArrayInputStream generateExcelReport(final List<Employee> employees) {
|
|
||||||
try (Workbook workbook = new XSSFWorkbook()) {
|
|
||||||
Sheet sheet = workbook.createSheet("REPORTE_GENERAL_DE_VACACIONES");
|
|
||||||
Row headerRow = sheet.createRow(0);
|
|
||||||
|
|
||||||
String[] headers = {"Empleado", "Equipo", "Estado", "Total Horas"};
|
|
||||||
for (int i = 0; i < headers.length; i++) {
|
|
||||||
Cell cell = headerRow.createCell(i);
|
|
||||||
cell.setCellValue(headers[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rowIndex = 1;
|
|
||||||
for (Employee employee : employees) {
|
|
||||||
Row row = sheet.createRow(rowIndex++);
|
|
||||||
row.createCell(0).setCellValue(getEmployeeFullName(employee));
|
|
||||||
row.createCell(1).setCellValue(getTeamName(employee));
|
|
||||||
row.createCell(2).setCellValue(getEmployeeStatus(employee));
|
|
||||||
row.createCell(3).setCellValue(getGeneralTotal(employee));
|
|
||||||
}
|
|
||||||
|
|
||||||
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
|
||||||
workbook.write(out);
|
|
||||||
return new ByteArrayInputStream(out.toByteArray());
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new UncheckedIOException("Error al generar el archivo Excel", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private StreamResource generateGeneralVacationReport() {
|
|
||||||
List<Employee> employees = employeeService.findAllEmployees();
|
|
||||||
ByteArrayInputStream excelStream = generateExcelReport(employees);
|
|
||||||
return new StreamResource("reporte_general_de_vacaciones_" + LocalDate.now() + ".xlsx",
|
|
||||||
() -> excelStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void downloadReport() {
|
|
||||||
StreamResource resource = generateGeneralVacationReport();
|
|
||||||
getUI().ifPresent(ui -> openDocumentStream(resource, ui));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void openDocumentStream(final StreamResource resource, final UI ui) {
|
|
||||||
StreamRegistration registration = ui.getSession().getResourceRegistry().registerResource(resource);
|
|
||||||
ui.getPage().open(registration.getResourceUri().toString());
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,112 +3,515 @@ 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.TimeOffService;
|
||||||
|
import com.primefactorsolutions.views.BaseEntityForm;
|
||||||
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.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.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;
|
||||||
|
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||||
import jakarta.annotation.security.PermitAll;
|
import jakarta.annotation.security.PermitAll;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.vaadin.firitin.form.BeanValidationForm;
|
|
||||||
|
|
||||||
|
import java.time.DayOfWeek;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
import static com.primefactorsolutions.views.util.ComponentUtils.withFullWidth;
|
||||||
|
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
@PermitAll
|
@PermitAll
|
||||||
@Scope("prototype")
|
@Scope("prototype")
|
||||||
@PageTitle("Request")
|
@PageTitle("Request")
|
||||||
@Route(value = "/requests/:requestId?/:action?", layout = MainLayout.class)
|
@Route(value = "/requests/:requestId?/:action?", layout = MainLayout.class)
|
||||||
public class TimeOffRequestView extends BeanValidationForm<TimeOffRequest> implements HasUrlParameter<String> {
|
public class TimeOffRequestView extends BaseEntityForm<TimeOffRequest> implements HasUrlParameter<String> {
|
||||||
|
|
||||||
private final ComboBox<TimeOffRequestStatus> state = new ComboBox<>("Estado de la solicitud");
|
private final ComboBox<TimeOffRequestType> category = withFullWidth(new ComboBox<>("Categoría"));
|
||||||
private final DatePicker expiration = new DatePicker("Vencimiento");
|
private final ComboBox<TimeOffRequestStatus> state = withFullWidth(new ComboBox<>("Estado de la solicitud"));
|
||||||
private final DatePicker startDate = new DatePicker("Fecha de inicio");
|
private final DatePicker expiration = withFullWidth(new DatePicker("Vencimiento"));
|
||||||
private final DatePicker endDate = new DatePicker("Fecha de fin");
|
private final DatePicker startDate = withFullWidth(new DatePicker("Fecha de inicio"));
|
||||||
private final NumberField availableDays = new NumberField("Días disponibles");
|
private final DatePicker endDate = withFullWidth(new DatePicker("Fecha de fin"));
|
||||||
private final NumberField daysToBeTake = new NumberField("Días a tomar");
|
private final NumberField daysToBeTake = withFullWidth(new NumberField("Días a tomar"));
|
||||||
|
private final NumberField daysBalance = withFullWidth(new NumberField("Días disponibles"));
|
||||||
|
|
||||||
private final TimeOffRequestService requestService;
|
private final TimeOffService timeOffService;
|
||||||
|
private final TimeOffRequestService timeOffRequestService;
|
||||||
private final EmployeeService employeeService;
|
private final EmployeeService employeeService;
|
||||||
private TimeOffRequest request;
|
|
||||||
private Employee employee;
|
private Employee employee;
|
||||||
|
|
||||||
public TimeOffRequestView(final TimeOffRequestService requestService,
|
public TimeOffRequestView(final AuthenticationContext authenticationContext,
|
||||||
|
final TimeOffRequestService timeOffRequestService,
|
||||||
|
final TimeOffService timeOffService,
|
||||||
final EmployeeService employeeService) {
|
final EmployeeService employeeService) {
|
||||||
super(TimeOffRequest.class);
|
super(authenticationContext, TimeOffRequest.class);
|
||||||
this.requestService = requestService;
|
this.timeOffService = timeOffService;
|
||||||
|
this.timeOffRequestService = timeOffRequestService;
|
||||||
this.employeeService = employeeService;
|
this.employeeService = employeeService;
|
||||||
state.setItems(List.of(TimeOffRequestStatus.values()));
|
state.setItems(List.of(TimeOffRequestStatus.values()));
|
||||||
|
|
||||||
this.setSavedHandler(this::saveRequest);
|
this.setSavedHandler(this::saveRequest);
|
||||||
|
|
||||||
|
initView();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initView() {
|
||||||
|
category.addValueChangeListener(event -> {
|
||||||
|
onCategoryChange(event.getValue());
|
||||||
|
handleCategorySelection(event.getValue());
|
||||||
|
});
|
||||||
|
startDate.addValueChangeListener(event -> {
|
||||||
|
LocalDate selectedDate = event.getValue();
|
||||||
|
if (selectedDate != null && (selectedDate.getDayOfWeek().getValue() == 6
|
||||||
|
|| selectedDate.getDayOfWeek().getValue() == 7)) {
|
||||||
|
startDate.setValue(selectedDate.minusDays(1));
|
||||||
|
}
|
||||||
|
updateDatePickerMinValues();
|
||||||
|
});
|
||||||
|
endDate.addValueChangeListener(event -> {
|
||||||
|
if (endDate.getValue() != null) {
|
||||||
|
endDate.setMin(endDate.getValue());
|
||||||
|
}
|
||||||
|
final LocalDate selectedDate = event.getValue();
|
||||||
|
|
||||||
|
if (selectedDate != null && (selectedDate.getDayOfWeek().getValue() == 6
|
||||||
|
|| selectedDate.getDayOfWeek().getValue() == 7)) {
|
||||||
|
endDate.setValue(selectedDate.minusDays(1));
|
||||||
|
}
|
||||||
|
calculateDays();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setParameter(final BeforeEvent beforeEvent, final String action) {
|
public void setParameter(final BeforeEvent beforeEvent, final String action) {
|
||||||
final RouteParameters params = beforeEvent.getRouteParameters();
|
final RouteParameters params = beforeEvent.getRouteParameters();
|
||||||
final String requestIdString = params.get("requestId").orElse(null);
|
final String requestIdString = params.get("requestId").orElse(null);
|
||||||
|
final UUID employeeId = getEmployeeId().get();
|
||||||
|
employee = employeeService.getEmployee(employeeId);
|
||||||
|
filterCategories(employee);
|
||||||
|
|
||||||
if ("new".equals(action)) {
|
if ("new".equals(action)) {
|
||||||
setEntityWithEnabledSave(new TimeOffRequest());
|
setEntityWithEnabledSave(new TimeOffRequest());
|
||||||
} else {
|
} else {
|
||||||
assert requestIdString != null;
|
assert requestIdString != null;
|
||||||
UUID requestId = UUID.fromString(requestIdString);
|
UUID requestId = UUID.fromString(requestIdString);
|
||||||
request = requestService.findTimeOffRequest(requestId);
|
TimeOffRequest timeOffRequest = timeOffRequestService.findTimeOffRequest(requestId);
|
||||||
UUID employeeId = request.getEmployee().getId();
|
|
||||||
employee = employeeService.getEmployee(employeeId);
|
if ("edit".equals(action)) {
|
||||||
setEntity(request);
|
setEntityWithEnabledSave(timeOffRequest);
|
||||||
configureViewOrEditAction(action);
|
setFieldsReadOnly(false);
|
||||||
|
} else if ("view".equals(action)) {
|
||||||
|
setEntity(timeOffRequest);
|
||||||
|
setFieldsReadOnly(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Component> getFormComponents() {
|
protected List<Component> getFormComponents() {
|
||||||
return List.of(
|
return List.of(
|
||||||
createEmployeeHeader(),
|
category,
|
||||||
createTeamHeader(),
|
|
||||||
createCategoryHeader(),
|
|
||||||
state,
|
state,
|
||||||
expiration,
|
expiration,
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
availableDays,
|
daysBalance,
|
||||||
daysToBeTake
|
daysToBeTake
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void filterCategories(final Employee employee) {
|
||||||
|
category.clear();
|
||||||
|
List<TimeOffRequest> employeeRequests = timeOffRequestService.findRequestsByEmployeeId(employee.getId());
|
||||||
|
List<TimeOffRequestType> allCategories = Arrays.asList(TimeOffRequestType.values());
|
||||||
|
List<TimeOffRequestType> availableCategories = allCategories.stream()
|
||||||
|
.filter(category -> isCategoryAvailable(employeeRequests, category))
|
||||||
|
.filter(category -> isCategoryAllowedByGender(category, employee.getGender()))
|
||||||
|
.filter(category -> shouldIncludeVacationGestionActual(employeeRequests, category))
|
||||||
|
.filter(category -> shouldIncludeVacationGestionAnterior(employeeRequests, category))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
category.setItems(availableCategories);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldIncludeVacationGestionActual(final List<TimeOffRequest> employeeRequests,
|
||||||
|
final TimeOffRequestType category) {
|
||||||
|
if (category != TimeOffRequestType.VACACION_GESTION_ACTUAL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return employeeRequests.stream()
|
||||||
|
.anyMatch(request -> request.getCategory() == TimeOffRequestType.VACACION_GESTION_ANTERIOR
|
||||||
|
&& request.getDaysBalance() == 0
|
||||||
|
&& request.getState() == TimeOffRequestStatus.TOMADO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldIncludeVacationGestionAnterior(final List<TimeOffRequest> employeeRequests,
|
||||||
|
final TimeOffRequestType category) {
|
||||||
|
if (category != TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return employeeRequests.stream()
|
||||||
|
.noneMatch(request -> request.getCategory() == TimeOffRequestType.VACACION_GESTION_ANTERIOR
|
||||||
|
&& request.getDaysBalance() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onCategoryChange(final TimeOffRequestType selectedCategory) {
|
||||||
|
if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ACTUAL
|
||||||
|
|| selectedCategory == TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
|
||||||
|
startDate.setEnabled(true);
|
||||||
|
endDate.setEnabled(true);
|
||||||
|
} else {
|
||||||
|
startDate.setEnabled(true);
|
||||||
|
endDate.setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isCategoryAvailable(final List<TimeOffRequest> employeeRequests,
|
||||||
|
final TimeOffRequestType category) {
|
||||||
|
if (category == TimeOffRequestType.CUMPLEAÑOS && employee.getBirthday() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TimeOffRequest> requestsByCategory = employeeRequests.stream()
|
||||||
|
.filter(request -> request.getCategory() == category)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (requestsByCategory.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeOffRequest latestRequest = requestsByCategory.stream()
|
||||||
|
.max(Comparator.comparing(TimeOffRequest::getStartDate))
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
boolean isSpecialCategory = category == TimeOffRequestType.PERMISOS_DE_SALUD
|
||||||
|
|| category == TimeOffRequestType.VACACION_GESTION_ACTUAL
|
||||||
|
|| category == TimeOffRequestType.VACACION_GESTION_ANTERIOR;
|
||||||
|
|
||||||
|
if (isSpecialCategory) {
|
||||||
|
return (latestRequest.getState() == TimeOffRequestStatus.TOMADO
|
||||||
|
&& latestRequest.getDaysBalance() > 0)
|
||||||
|
|| latestRequest.getState() == TimeOffRequestStatus.RECHAZADO
|
||||||
|
|| (latestRequest.getState() == TimeOffRequestStatus.TOMADO
|
||||||
|
&& latestRequest.getDaysBalance() == 0
|
||||||
|
&& latestRequest.getExpiration().isBefore(LocalDate.now()));
|
||||||
|
} else {
|
||||||
|
return (latestRequest.getState() == TimeOffRequestStatus.TOMADO
|
||||||
|
&& latestRequest.getExpiration().isBefore(LocalDate.now()))
|
||||||
|
|| latestRequest.getState() == TimeOffRequestStatus.RECHAZADO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isCategoryAllowedByGender(final TimeOffRequestType category, final Employee.Gender gender) {
|
||||||
|
if (gender == Employee.Gender.MALE) {
|
||||||
|
return category != TimeOffRequestType.MATERNIDAD
|
||||||
|
&& category != TimeOffRequestType.DIA_DE_LA_MADRE
|
||||||
|
&& category != TimeOffRequestType.DIA_DE_LA_MUJER_INTERNACIONAL
|
||||||
|
&& category != TimeOffRequestType.DIA_DE_LA_MUJER_NACIONAL;
|
||||||
|
} else {
|
||||||
|
return category != TimeOffRequestType.DIA_DEL_PADRE
|
||||||
|
&& category != TimeOffRequestType.PATERNIDAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleCategorySelection(final TimeOffRequestType selectedCategory) {
|
||||||
|
if (selectedCategory != null) {
|
||||||
|
updateAvailableDays(selectedCategory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateAvailableDays(final TimeOffRequestType selectedCategory) {
|
||||||
|
final TimeOff timeoff = timeOffService.findVacationByCategory(selectedCategory);
|
||||||
|
final List<TimeOffRequest> requests =
|
||||||
|
timeOffRequestService.findByEmployeeAndCategory(employee.getId(), selectedCategory);
|
||||||
|
|
||||||
|
final TimeOffRequest requestWithBalance = requests.stream()
|
||||||
|
.filter(request -> request.getDaysBalance() > 0
|
||||||
|
&& request.getState() != TimeOffRequestStatus.VENCIDO
|
||||||
|
&& request.getState() != TimeOffRequestStatus.RECHAZADO)
|
||||||
|
.max(Comparator.comparing(TimeOffRequest::getStartDate))
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (requestWithBalance != null) {
|
||||||
|
if (requestWithBalance.getState() == TimeOffRequestStatus.TOMADO
|
||||||
|
&& requestWithBalance.getDaysBalance() > 0) {
|
||||||
|
daysBalance.setValue(requestWithBalance.getDaysBalance());
|
||||||
|
} else {
|
||||||
|
daysBalance.setValue(timeoff.getDuration());
|
||||||
|
}
|
||||||
|
} else if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ACTUAL
|
||||||
|
|| selectedCategory == TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
|
||||||
|
final LocalDate dateOfEntry = employee.getDateOfEntry();
|
||||||
|
final LocalDate currentDate = LocalDate.now();
|
||||||
|
long yearsOfService = ChronoUnit.YEARS.between(dateOfEntry, currentDate);
|
||||||
|
|
||||||
|
if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
|
||||||
|
yearsOfService -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yearsOfService > 10) {
|
||||||
|
daysBalance.setValue(30.0);
|
||||||
|
} else if (yearsOfService > 5) {
|
||||||
|
daysBalance.setValue(20.0);
|
||||||
|
} else if (yearsOfService > 1) {
|
||||||
|
daysBalance.setValue(15.0);
|
||||||
|
} else {
|
||||||
|
daysBalance.setValue(0.0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
daysBalance.setValue(timeoff.getDuration());
|
||||||
|
}
|
||||||
|
|
||||||
|
setDatePickerLimits(timeoff);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDatePickerLimits(final TimeOff timeoff) {
|
||||||
|
LocalDate startDateValue;
|
||||||
|
LocalDate endDateValue = null;
|
||||||
|
|
||||||
|
final UUID employeeId = employee.getId();
|
||||||
|
final List<TimeOffRequest> previousRequests
|
||||||
|
= timeOffRequestService.findByEmployeeAndCategory(employeeId, timeoff.getCategory());
|
||||||
|
|
||||||
|
final int startYear = calculateStartYear(previousRequests);
|
||||||
|
|
||||||
|
startDateValue = determineStartDate(timeoff, startYear);
|
||||||
|
|
||||||
|
if (startDateValue.isBefore(LocalDate.now())) {
|
||||||
|
startDateValue = determineStartDate(timeoff, startYear + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startDateValue != null) {
|
||||||
|
if (timeoff.getExpiration() != null) {
|
||||||
|
endDateValue = startDateValue.plusDays(timeoff.getExpiration().intValue() - 1);
|
||||||
|
} else {
|
||||||
|
endDateValue = LocalDate.of(startDateValue.getYear(), 12, 31);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
startDateValue = LocalDate.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
setPickerValues(timeoff, startDateValue);
|
||||||
|
setPickerLimits(startDateValue, endDateValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int calculateStartYear(final List<TimeOffRequest> previousRequests) {
|
||||||
|
if (previousRequests.isEmpty()) {
|
||||||
|
return LocalDate.now().getYear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int lastRequestYear = previousRequests.stream()
|
||||||
|
.max(Comparator.comparing(TimeOffRequest::getStartDate))
|
||||||
|
.map(request -> request.getStartDate().getYear())
|
||||||
|
.orElse(LocalDate.now().getYear());
|
||||||
|
|
||||||
|
if (previousRequests.getLast().getState() != TimeOffRequestStatus.RECHAZADO) {
|
||||||
|
lastRequestYear = lastRequestYear + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int currentYear = LocalDate.now().getYear();
|
||||||
|
return Math.max(lastRequestYear, currentYear);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalDate determineStartDate(final TimeOff timeoff, final int startYear) {
|
||||||
|
if (timeoff.getCategory() == TimeOffRequestType.CUMPLEAÑOS && employee.getBirthday() != null) {
|
||||||
|
return LocalDate.of(startYear, employee.getBirthday().getMonth(), employee.getBirthday().getDayOfMonth());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeoff.getDate() != null) {
|
||||||
|
return LocalDate.of(startYear, timeoff.getDate().getMonthValue(), timeoff.getDate().getDayOfMonth());
|
||||||
|
}
|
||||||
|
|
||||||
|
return LocalDate.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPickerValues(final TimeOff timeoff, final LocalDate startDateValue) {
|
||||||
|
startDate.setValue(startDateValue);
|
||||||
|
|
||||||
|
if ((timeoff.getDuration() != null && timeoff.getDuration() == 0.5)
|
||||||
|
|| timeoff.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD
|
||||||
|
|| timeoff.getCategory() == TimeOffRequestType.CUMPLEAÑOS) {
|
||||||
|
|
||||||
|
endDate.setValue(startDateValue);
|
||||||
|
} else {
|
||||||
|
int durationDays = (timeoff.getDuration() != null ? timeoff.getDuration().intValue() - 1 : 0);
|
||||||
|
endDate.setValue(startDateValue.plusDays(durationDays));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPickerLimits(final LocalDate startDateValue, final LocalDate endDateValue) {
|
||||||
|
startDate.setMin(startDateValue);
|
||||||
|
startDate.setMax(endDateValue);
|
||||||
|
endDate.setMin(startDateValue);
|
||||||
|
endDate.setMax(endDateValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDatePickerMinValues() {
|
||||||
|
LocalDate startDateValue = startDate.getValue();
|
||||||
|
if (daysBalance.getValue() != null) {
|
||||||
|
if (daysBalance.getValue() == 0.5) {
|
||||||
|
endDate.setValue(startDateValue.plusDays(0));
|
||||||
|
} else {
|
||||||
|
endDate.setValue(startDateValue.plusDays(daysBalance.getValue().intValue() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateDays();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calculateDays() {
|
||||||
|
LocalDate startDateValue = startDate.getValue();
|
||||||
|
LocalDate endDateValue = endDate.getValue();
|
||||||
|
Double availableDaysValue = daysBalance.getValue();
|
||||||
|
|
||||||
|
if (areDatesValid(startDateValue, endDateValue)) {
|
||||||
|
long workDays = countWorkDaysBetween(startDateValue, endDateValue);
|
||||||
|
|
||||||
|
daysToBeTake.setValue((double) workDays);
|
||||||
|
daysBalance.setValue(daysBalance.getValue() - workDays);
|
||||||
|
|
||||||
|
double daysToBeTaken = calculateDaysBetween(startDateValue, endDateValue);
|
||||||
|
setDaysToBeTakenField(daysToBeTaken);
|
||||||
|
|
||||||
|
double balanceDays = calculateBalanceDays(availableDaysValue, daysToBeTake.getValue());
|
||||||
|
daysBalance.setValue(balanceDays);
|
||||||
|
|
||||||
|
if (balanceDays < 0.0) {
|
||||||
|
clearFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (daysToBeTake.getValue() > 10
|
||||||
|
&& (category.getValue() == TimeOffRequestType.VACACION_GESTION_ANTERIOR
|
||||||
|
|| category.getValue() == TimeOffRequestType.VACACION_GESTION_ACTUAL)) {
|
||||||
|
clearFields();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearFields() {
|
||||||
|
daysToBeTake.clear();
|
||||||
|
daysBalance.clear();
|
||||||
|
endDate.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean areDatesValid(final LocalDate startDate, final LocalDate endDate) {
|
||||||
|
return startDate != null && endDate != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long countWorkDaysBetween(final LocalDate startDate, final LocalDate endDate) {
|
||||||
|
return startDate.datesUntil(endDate.plusDays(1))
|
||||||
|
.filter(date -> date.getDayOfWeek() != DayOfWeek.SATURDAY && date.getDayOfWeek() != DayOfWeek.SUNDAY)
|
||||||
|
.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
private double calculateDaysBetween(final LocalDate startDate, final LocalDate endDate) {
|
||||||
|
return startDate.datesUntil(endDate.plusDays(1))
|
||||||
|
.filter(date -> {
|
||||||
|
DayOfWeek day = date.getDayOfWeek();
|
||||||
|
return day != DayOfWeek.SATURDAY && day != DayOfWeek.SUNDAY;
|
||||||
|
})
|
||||||
|
.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDaysToBeTakenField(final double daysToBeTaken) {
|
||||||
|
final TimeOffRequest timeOffRequest = getEntity();
|
||||||
|
|
||||||
|
if (timeOffRequest.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD
|
||||||
|
|| timeOffRequest.getCategory() == TimeOffRequestType.CUMPLEAÑOS
|
||||||
|
|| timeOffRequest.getCategory() == TimeOffRequestType.DIA_DEL_PADRE
|
||||||
|
|| timeOffRequest.getCategory() == TimeOffRequestType.DIA_DE_LA_MADRE
|
||||||
|
|| timeOffRequest.getCategory() == TimeOffRequestType.DIA_DE_LA_MUJER_INTERNACIONAL
|
||||||
|
|| timeOffRequest.getCategory() == TimeOffRequestType.DIA_DE_LA_MUJER_NACIONAL) {
|
||||||
|
daysToBeTake.setValue(0.5);
|
||||||
|
} else {
|
||||||
|
daysToBeTake.setValue(daysToBeTaken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private double calculateBalanceDays(final double availableDays, final double daysToBeTaken) {
|
||||||
|
return availableDays - daysToBeTaken;
|
||||||
|
}
|
||||||
|
|
||||||
private void setFieldsReadOnly(final boolean option) {
|
private void setFieldsReadOnly(final boolean option) {
|
||||||
state.setReadOnly(option);
|
state.setReadOnly(option);
|
||||||
expiration.setReadOnly(option);
|
expiration.setReadOnly(option);
|
||||||
startDate.setReadOnly(option);
|
startDate.setReadOnly(option);
|
||||||
endDate.setReadOnly(option);
|
endDate.setReadOnly(option);
|
||||||
availableDays.setReadOnly(option);
|
daysBalance.setReadOnly(option);
|
||||||
daysToBeTake.setReadOnly(option);
|
daysToBeTake.setReadOnly(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveRequest(final TimeOffRequest request) {
|
private void saveRequest(final TimeOffRequest request) {
|
||||||
if (isFormValid()) {
|
if (!isFormValid()) {
|
||||||
setRequestFieldValues(request);
|
Notification.show("Por favor, complete los campos antes de guardar");
|
||||||
requestService.saveTimeOffRequest(request);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareRequest(request);
|
||||||
|
|
||||||
|
if (request.getCategory() == TimeOffRequestType.VACACION_GESTION_ACTUAL) {
|
||||||
|
handleVacationRequest(request);
|
||||||
|
} else {
|
||||||
|
handleExistingRequests(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
long differentDays = ChronoUnit.DAYS.between(LocalDate.now(), request.getStartDate());
|
||||||
|
if (differentDays >= -15 && differentDays <= 90) {
|
||||||
|
timeOffRequestService.saveTimeOffRequest(request);
|
||||||
|
Notification.show("Solicitud guardada correctamente.");
|
||||||
closeForm();
|
closeForm();
|
||||||
|
} else {
|
||||||
|
Notification.show(
|
||||||
|
"La fecha de inicio debe encontrarse dentro del rango de 15 días a 3 meses de anticipación."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setRequestFieldValues(final TimeOffRequest request) {
|
private void prepareRequest(final TimeOffRequest request) {
|
||||||
request.setState(state.getValue());
|
|
||||||
request.setExpiration(expiration.getValue());
|
|
||||||
request.setStartDate(startDate.getValue());
|
request.setStartDate(startDate.getValue());
|
||||||
request.setEndDate(endDate.getValue());
|
request.setAvailableDays(daysBalance.getValue());
|
||||||
request.setAvailableDays(availableDays.getValue());
|
request.setExpiration(endDate.getValue());
|
||||||
request.setDaysToBeTake(daysToBeTake.getValue());
|
request.setState(TimeOffRequestStatus.SOLICITADO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleExistingRequests(final TimeOffRequest request) {
|
||||||
|
final List<TimeOffRequest> existingRequests =
|
||||||
|
timeOffRequestService.findByEmployeeAndCategory(employee.getId(), request.getCategory());
|
||||||
|
|
||||||
|
int maxRequests = request.getCategory() != TimeOffRequestType.PERMISOS_DE_SALUD
|
||||||
|
&& !request.getCategory().name().startsWith("VACACION")
|
||||||
|
&& request.getCategory() != TimeOffRequestType.CUMPLEAÑOS
|
||||||
|
? 2 : 1;
|
||||||
|
|
||||||
|
if (existingRequests.size() >= maxRequests) {
|
||||||
|
existingRequests.stream()
|
||||||
|
.min(Comparator.comparing(TimeOffRequest::getStartDate))
|
||||||
|
.ifPresent(oldestRequest -> timeOffRequestService.deleteTimeOffRequest(oldestRequest.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleVacationRequest(final TimeOffRequest request) {
|
||||||
|
final List<TimeOffRequest> existingRequests = timeOffRequestService.findByEmployeeAndCategory(
|
||||||
|
employee.getId(),
|
||||||
|
TimeOffRequestType.VACACION_GESTION_ACTUAL
|
||||||
|
);
|
||||||
|
if (!existingRequests.isEmpty()) {
|
||||||
|
TimeOffRequest existingRequest = existingRequests.getFirst();
|
||||||
|
existingRequest.setCategory(TimeOffRequestType.VACACION_GESTION_ANTERIOR);
|
||||||
|
timeOffRequestService.saveTimeOffRequest(existingRequest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeForm() {
|
private void closeForm() {
|
||||||
getUI().ifPresent(ui -> ui.navigate(TimeOffRequestsByEmployeeView.class, employee.getId().toString()));
|
getUI().ifPresent(ui -> ui.navigate(TimeOffRequestsListView.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFormValid() {
|
private boolean isFormValid() {
|
||||||
@ -116,27 +519,7 @@ public class TimeOffRequestView extends BeanValidationForm<TimeOffRequest> imple
|
|||||||
&& expiration.getValue() != null
|
&& expiration.getValue() != null
|
||||||
&& startDate.getValue() != null
|
&& startDate.getValue() != null
|
||||||
&& endDate.getValue() != null
|
&& endDate.getValue() != null
|
||||||
&& availableDays.getValue() != null
|
&& daysBalance.getValue() != null
|
||||||
&& daysToBeTake.getValue() != null;
|
&& daysToBeTake.getValue() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureViewOrEditAction(final String action) {
|
|
||||||
if ("edit".equals(action) && !request.getId().toString().isEmpty()) {
|
|
||||||
setFieldsReadOnly(false);
|
|
||||||
} else if ("view".equals(action) && !request.getId().toString().isEmpty()) {
|
|
||||||
setFieldsReadOnly(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private H3 createEmployeeHeader() {
|
|
||||||
return new H3("Empleado: " + employee.getFirstName() + " " + employee.getLastName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private H3 createTeamHeader() {
|
|
||||||
return new H3("Equipo: " + employee.getTeam().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private H3 createCategoryHeader() {
|
|
||||||
return new H3("Categoría: " + request.getCategory());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import com.vaadin.flow.component.Component;
|
|||||||
import com.vaadin.flow.component.ComponentEventListener;
|
import com.vaadin.flow.component.ComponentEventListener;
|
||||||
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.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,36 +47,43 @@ import static com.primefactorsolutions.views.Constants.PAGE_SIZE;
|
|||||||
|
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
@Scope("prototype")
|
@Scope("prototype")
|
||||||
@PageTitle("Pending Requests")
|
@PageTitle("Time-Off Requests")
|
||||||
@Route(value = "/time-off/requests/pending", layout = MainLayout.class)
|
@Route(value = "/time-off/requests", layout = MainLayout.class)
|
||||||
@PermitAll
|
@PermitAll
|
||||||
public class TimeOffPendingRequestsListView extends BaseView {
|
public class TimeOffRequestsListView 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 PagingGrid<TimeOffRequest> pendingRequestsGrid = new PagingGrid<>();
|
private final PagingGrid<TimeOffRequest> requestsGrid = new PagingGrid<>();
|
||||||
private ComboBox<Employee> employeeFilter;
|
private ComboBox<Employee> employeeFilter;
|
||||||
private ComboBox<Team> teamFilter;
|
private ComboBox<Team> teamFilter;
|
||||||
private ComboBox<TimeOffRequestType> categoryFilter;
|
private ComboBox<TimeOffRequestType> categoryFilter;
|
||||||
|
|
||||||
public TimeOffPendingRequestsListView(final AuthenticationContext authenticationContext,
|
public TimeOffRequestsListView(final AuthenticationContext authenticationContext,
|
||||||
final TimeOffRequestService requestService,
|
final TimeOffRequestService requestService,
|
||||||
final EmployeeService employeeService,
|
final EmployeeService employeeService,
|
||||||
final TeamService teamService) {
|
final TeamService teamService) {
|
||||||
super(authenticationContext);
|
super(authenticationContext);
|
||||||
this.requestService = requestService;
|
this.requestService = requestService;
|
||||||
this.employeeService = employeeService;
|
this.employeeService = employeeService;
|
||||||
this.teamService = teamService;
|
this.teamService = teamService;
|
||||||
initializeView();
|
initializeView();
|
||||||
refreshGeneralPendingRequestsGrid(null, null, null);
|
refreshGeneralRequestsGrid(null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeView() {
|
private void initializeView() {
|
||||||
Button downloadButton = new Button("Descargar reporte de rechazos", event -> downloadReport());
|
final Button newRequestButton = new Button("Crear nueva peticion", event -> navigateToAddNew());
|
||||||
getCurrentPageLayout().add(downloadButton);
|
newRequestButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
|
final Button downloadReportButton = new Button("Descargar reporte de rechazos", event -> downloadReport());
|
||||||
|
final HorizontalLayout hl = new HorizontalLayout(newRequestButton, downloadReportButton);
|
||||||
|
getCurrentPageLayout().add(hl);
|
||||||
setupFilters();
|
setupFilters();
|
||||||
setupPendingRequestsGrid();
|
setupRequestsGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void navigateToAddNew() {
|
||||||
|
getUI().ifPresent(ui -> ui.navigate(TimeOffRequestView.class, "new"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupFilters() {
|
private void setupFilters() {
|
||||||
@ -87,11 +95,11 @@ public class TimeOffPendingRequestsListView extends BaseView {
|
|||||||
getCurrentPageLayout().add(hl);
|
getCurrentPageLayout().add(hl);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupPendingRequestsGrid() {
|
private void setupRequestsGrid() {
|
||||||
pendingRequestsGrid.addColumn(this::getEmployeeFullName).setHeader("Empleado");
|
requestsGrid.addColumn(this::getEmployeeFullName).setHeader("Empleado");
|
||||||
pendingRequestsGrid.addColumn(this::getTeamName).setHeader("Equipo");
|
requestsGrid.addColumn(this::getTeamName).setHeader("Equipo");
|
||||||
pendingRequestsGrid.addColumn(this::getCategory).setHeader("Categoría");
|
requestsGrid.addColumn(this::getCategory).setHeader("Categoría");
|
||||||
pendingRequestsGrid.addComponentColumn((ValueProvider<TimeOffRequest, Component>) timeOffRequest -> {
|
requestsGrid.addComponentColumn((ValueProvider<TimeOffRequest, Component>) timeOffRequest -> {
|
||||||
final MenuBar menuBar = new MenuBar();
|
final MenuBar menuBar = new MenuBar();
|
||||||
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
|
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
|
||||||
final MenuItem approveItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.CHECK, "Aprobar");
|
final MenuItem approveItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.CHECK, "Aprobar");
|
||||||
@ -103,58 +111,58 @@ public class TimeOffPendingRequestsListView extends BaseView {
|
|||||||
return menuBar;
|
return menuBar;
|
||||||
});
|
});
|
||||||
|
|
||||||
pendingRequestsGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
|
requestsGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
|
||||||
pendingRequestsGrid.setPageSize(PAGE_SIZE);
|
requestsGrid.setPageSize(PAGE_SIZE);
|
||||||
|
|
||||||
getCurrentPageLayout().add(pendingRequestsGrid);
|
getCurrentPageLayout().add(requestsGrid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void actionForRequest(final UUID selectedRequestId, final TimeOffRequestStatus status) {
|
private void actionForRequest(final UUID selectedRequestId, final TimeOffRequestStatus status) {
|
||||||
TimeOffRequest request = requestService.findTimeOffRequest(selectedRequestId);
|
TimeOffRequest request = requestService.findTimeOffRequest(selectedRequestId);
|
||||||
request.setState(status);
|
request.setState(status);
|
||||||
requestService.saveTimeOffRequest(request);
|
requestService.saveTimeOffRequest(request);
|
||||||
refreshGeneralPendingRequestsGrid(null, null, null);
|
refreshGeneralRequestsGrid(null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshGeneralPendingRequestsGrid(final Employee employee,
|
private void refreshGeneralRequestsGrid(final Employee employee,
|
||||||
final Team team,
|
final Team team,
|
||||||
final TimeOffRequestType category) {
|
final TimeOffRequestType category) {
|
||||||
pendingRequestsGrid.setPagingDataProvider((page, pageSize) -> {
|
requestsGrid.setPagingDataProvider((page, pageSize) -> {
|
||||||
int start = (int) (page * pendingRequestsGrid.getPageSize());
|
int start = (int) (page * requestsGrid.getPageSize());
|
||||||
return fetchFilteredPendingRequests(start, pageSize, employee, team, category);
|
return fetchFilteredRequests(start, pageSize, employee, team, category);
|
||||||
});
|
});
|
||||||
pendingRequestsGrid.getDataProvider().refreshAll();
|
requestsGrid.getDataProvider().refreshAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<TimeOffRequest> fetchFilteredPendingRequests(final int start,
|
private List<TimeOffRequest> fetchFilteredRequests(final int start,
|
||||||
final int pageSize,
|
final int pageSize,
|
||||||
final Employee employee,
|
final Employee employee,
|
||||||
final Team team,
|
final Team team,
|
||||||
final TimeOffRequestType category) {
|
final TimeOffRequestType category) {
|
||||||
List<TimeOffRequest> filteredPendingRequests
|
List<TimeOffRequest> filteredRequests
|
||||||
= requestService.findRequestsByState(TimeOffRequestStatus.SOLICITADO);
|
= requestService.findAllTimeOffRequests();
|
||||||
|
|
||||||
if (employee != null) {
|
if (employee != null) {
|
||||||
filteredPendingRequests = filteredPendingRequests.stream()
|
filteredRequests = filteredRequests.stream()
|
||||||
.filter(emp -> emp.getEmployee().getId().equals(employee.getId()))
|
.filter(emp -> emp.getEmployee().getId().equals(employee.getId()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (team != null) {
|
if (team != null) {
|
||||||
filteredPendingRequests = filteredPendingRequests.stream()
|
filteredRequests = filteredRequests.stream()
|
||||||
.filter(emp -> emp.getEmployee().getTeam() != null
|
.filter(emp -> emp.getEmployee().getTeam() != null
|
||||||
&& emp.getEmployee().getTeam().getId().equals(team.getId()))
|
&& emp.getEmployee().getTeam().getId().equals(team.getId()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (category != null) {
|
if (category != null) {
|
||||||
filteredPendingRequests = filteredPendingRequests.stream()
|
filteredRequests = filteredRequests.stream()
|
||||||
.filter(emp -> emp.getCategory().equals(category))
|
.filter(emp -> emp.getCategory().equals(category))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
int end = Math.min(start + pageSize, filteredPendingRequests.size());
|
int end = Math.min(start + pageSize, filteredRequests.size());
|
||||||
return filteredPendingRequests.subList(start, end);
|
return filteredRequests.subList(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getEmployeeFullName(final TimeOffRequest request) {
|
private String getEmployeeFullName(final TimeOffRequest request) {
|
||||||
@ -163,8 +171,7 @@ public class TimeOffPendingRequestsListView extends BaseView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getEmployeeFullNameLabel(final Employee employee) {
|
private String getEmployeeFullNameLabel(final Employee employee) {
|
||||||
return "TODOS".equals(employee.getFirstName())
|
return employee.getFirstName() + " " + employee.getLastName();
|
||||||
? "TODOS" : employee.getFirstName() + " " + employee.getLastName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTeamName(final TimeOffRequest request) {
|
private String getTeamName(final TimeOffRequest request) {
|
||||||
@ -173,7 +180,7 @@ public class TimeOffPendingRequestsListView extends BaseView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getTeamLabel(final Team team) {
|
private String getTeamLabel(final Team team) {
|
||||||
return "TODOS".equals(team.getName()) ? "TODOS" : team.getName();
|
return team.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getCategory(final TimeOffRequest request) {
|
private String getCategory(final TimeOffRequest request) {
|
||||||
@ -183,13 +190,13 @@ public class TimeOffPendingRequestsListView extends BaseView {
|
|||||||
private ComboBox<Employee> createEmployeeFilter() {
|
private ComboBox<Employee> createEmployeeFilter() {
|
||||||
employeeFilter = new ComboBox<>("Empleado");
|
employeeFilter = new ComboBox<>("Empleado");
|
||||||
employeeFilter.setClearButtonVisible(true);
|
employeeFilter.setClearButtonVisible(true);
|
||||||
employeeFilter.setPlaceholder("TODOS");
|
employeeFilter.setPlaceholder("Seleccionar ...");
|
||||||
final List<Employee> employees = new ArrayList<>(employeeService.findAllEmployees());
|
final List<Employee> employees = new ArrayList<>(employeeService.findAllEmployees());
|
||||||
|
|
||||||
employeeFilter.setItems(employees);
|
employeeFilter.setItems(employees);
|
||||||
employeeFilter.setItemLabelGenerator(this::getEmployeeFullNameLabel);
|
employeeFilter.setItemLabelGenerator(this::getEmployeeFullNameLabel);
|
||||||
employeeFilter.addValueChangeListener(event ->
|
employeeFilter.addValueChangeListener(event ->
|
||||||
refreshGeneralPendingRequestsGrid(
|
refreshGeneralRequestsGrid(
|
||||||
event.getValue(),
|
event.getValue(),
|
||||||
teamFilter.getValue(),
|
teamFilter.getValue(),
|
||||||
categoryFilter.getValue()
|
categoryFilter.getValue()
|
||||||
@ -201,12 +208,12 @@ public class TimeOffPendingRequestsListView extends BaseView {
|
|||||||
private ComboBox<Team> createTeamFilter() {
|
private ComboBox<Team> createTeamFilter() {
|
||||||
teamFilter = new ComboBox<>("Equipo");
|
teamFilter = new ComboBox<>("Equipo");
|
||||||
teamFilter.setClearButtonVisible(true);
|
teamFilter.setClearButtonVisible(true);
|
||||||
teamFilter.setPlaceholder("TODOS");
|
teamFilter.setPlaceholder("Seleccionar ...");
|
||||||
final List<Team> teams = new ArrayList<>(teamService.findAllTeams());
|
final List<Team> teams = new ArrayList<>(teamService.findAllTeams());
|
||||||
teamFilter.setItems(teams);
|
teamFilter.setItems(teams);
|
||||||
teamFilter.setItemLabelGenerator(this::getTeamLabel);
|
teamFilter.setItemLabelGenerator(this::getTeamLabel);
|
||||||
teamFilter.addValueChangeListener(event ->
|
teamFilter.addValueChangeListener(event ->
|
||||||
refreshGeneralPendingRequestsGrid(
|
refreshGeneralRequestsGrid(
|
||||||
employeeFilter.getValue(),
|
employeeFilter.getValue(),
|
||||||
event.getValue(),
|
event.getValue(),
|
||||||
categoryFilter.getValue()
|
categoryFilter.getValue()
|
||||||
@ -217,11 +224,11 @@ public class TimeOffPendingRequestsListView extends BaseView {
|
|||||||
|
|
||||||
private ComboBox<TimeOffRequestType> createCategoryFilter() {
|
private ComboBox<TimeOffRequestType> createCategoryFilter() {
|
||||||
categoryFilter = new ComboBox<>("Categoría");
|
categoryFilter = new ComboBox<>("Categoría");
|
||||||
categoryFilter.setPlaceholder("TODOS");
|
categoryFilter.setPlaceholder("Seleccionar ...");
|
||||||
categoryFilter.setClearButtonVisible(true);
|
categoryFilter.setClearButtonVisible(true);
|
||||||
categoryFilter.setItems(TimeOffRequestType.values());
|
categoryFilter.setItems(TimeOffRequestType.values());
|
||||||
categoryFilter.addValueChangeListener(event ->
|
categoryFilter.addValueChangeListener(event ->
|
||||||
refreshGeneralPendingRequestsGrid(
|
refreshGeneralRequestsGrid(
|
||||||
employeeFilter.getValue(),
|
employeeFilter.getValue(),
|
||||||
teamFilter.getValue(),
|
teamFilter.getValue(),
|
||||||
event.getValue()
|
event.getValue()
|
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@ import com.primefactorsolutions.model.Team;
|
|||||||
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;
|
||||||
|
import com.primefactorsolutions.views.BaseEntityForm;
|
||||||
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.textfield.NumberField;
|
import com.vaadin.flow.component.textfield.NumberField;
|
||||||
@ -13,10 +14,10 @@ import com.vaadin.flow.component.textfield.TextField;
|
|||||||
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;
|
||||||
|
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||||
import jakarta.annotation.security.PermitAll;
|
import jakarta.annotation.security.PermitAll;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.vaadin.firitin.components.datepicker.VDatePicker;
|
import org.vaadin.firitin.components.datepicker.VDatePicker;
|
||||||
import org.vaadin.firitin.form.BeanValidationForm;
|
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.YearMonth;
|
import java.time.YearMonth;
|
||||||
@ -25,13 +26,12 @@ import java.util.List;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
@PermitAll
|
@PermitAll
|
||||||
@Scope("prototype")
|
@Scope("prototype")
|
||||||
@PageTitle("Horas Trabajadas")
|
@PageTitle("Horas Trabajadas")
|
||||||
@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 BaseEntityForm<TimesheetEntry> implements HasUrlParameter<String> {
|
||||||
private final ComboBox<Team> team = new ComboBox<>("Equipo");
|
private final ComboBox<Team> team = new ComboBox<>("Equipo");
|
||||||
private final ComboBox<Employee> employee = new ComboBox<>("Empleado");
|
private final ComboBox<Employee> employee = new ComboBox<>("Empleado");
|
||||||
private final ComboBox<String> task = new ComboBox<>("Tarea");
|
private final ComboBox<String> task = new ComboBox<>("Tarea");
|
||||||
@ -45,10 +45,11 @@ public class TimesheetEntryView extends BeanValidationForm<TimesheetEntry> imple
|
|||||||
|
|
||||||
private TimesheetEntry timesheetEntry;
|
private TimesheetEntry timesheetEntry;
|
||||||
|
|
||||||
public TimesheetEntryView(final TimesheetService timesheetService,
|
public TimesheetEntryView(final AuthenticationContext authenticationContext,
|
||||||
|
final TimesheetService timesheetService,
|
||||||
final EmployeeService employeeService,
|
final EmployeeService employeeService,
|
||||||
final TeamService teamService) {
|
final TeamService teamService) {
|
||||||
super(TimesheetEntry.class);
|
super(authenticationContext, TimesheetEntry.class);
|
||||||
this.timesheetService = timesheetService;
|
this.timesheetService = timesheetService;
|
||||||
this.employeeService = employeeService;
|
this.employeeService = employeeService;
|
||||||
this.teamService = teamService;
|
this.teamService = teamService;
|
||||||
|
@ -176,7 +176,7 @@ public class TimesheetListView extends BaseView {
|
|||||||
|
|
||||||
private ComboBox<Employee> createEmployeeFilter() {
|
private ComboBox<Employee> createEmployeeFilter() {
|
||||||
employeeFilter = new ComboBox<>("Empleado");
|
employeeFilter = new ComboBox<>("Empleado");
|
||||||
employeeFilter.setPlaceholder("Seleccionar empleado ...");
|
employeeFilter.setPlaceholder("Seleccionar ...");
|
||||||
employeeFilter.setClearButtonVisible(true);
|
employeeFilter.setClearButtonVisible(true);
|
||||||
|
|
||||||
List<Employee> employees = new ArrayList<>(employeeService.findAllEmployees());
|
List<Employee> employees = new ArrayList<>(employeeService.findAllEmployees());
|
||||||
@ -214,7 +214,7 @@ 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("Seleccionar equipo ...");
|
teamFilter.setPlaceholder("Seleccionar ...");
|
||||||
teamFilter.setClearButtonVisible(true);
|
teamFilter.setClearButtonVisible(true);
|
||||||
teamFilter.setItems(teams);
|
teamFilter.setItems(teams);
|
||||||
teamFilter.setItemLabelGenerator(this::getTeamLabel);
|
teamFilter.setItemLabelGenerator(this::getTeamLabel);
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.primefactorsolutions.views.util;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.HasSize;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
|
public class ComponentUtils {
|
||||||
|
|
||||||
|
public static <T extends HasSize> T withFullWidth(final T component) {
|
||||||
|
component.setWidthFull();
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user