Vacaciones #64

Merged
jesus.pelaez merged 11 commits from Vacaciones into En-desarrollo 2024-11-04 04:25:22 +00:00
2 changed files with 175 additions and 128 deletions
Showing only changes of commit 4421c6fe45 - Show all commits

View File

@ -87,9 +87,7 @@ public class RequestEmployeeView extends Div implements HasUrlParameter<String>
"state", "state",
"startDate", "startDate",
"endDate", "endDate",
"daysToBeTake", "daysToBeTake");
"daysBalance"
);
requestGrid.setAllRowsVisible(true); requestGrid.setAllRowsVisible(true);
requestGrid.asSingleSelect().addValueChangeListener(event -> { requestGrid.asSingleSelect().addValueChangeListener(event -> {
TimeOffRequest selectedRequest = event.getValue(); TimeOffRequest selectedRequest = event.getValue();

View File

@ -32,13 +32,13 @@ import java.util.UUID;
@Route(value = "/requests/new", layout = MainLayout.class) @Route(value = "/requests/new", layout = MainLayout.class)
public class RequestRegisterView extends VerticalLayout { public class RequestRegisterView extends VerticalLayout {
private final ComboBox<Employee> employeeComboBox = new ComboBox<>("Employee"); private final ComboBox<Employee> employeeComboBox = new ComboBox<>("Empleado");
private final ComboBox<TimeOffRequestType> categoryComboBox = new ComboBox<>("Category"); private final ComboBox<TimeOffRequestType> categoryComboBox = new ComboBox<>("Categoría");
private final NumberField availableDaysField = new NumberField("Available Days"); private final NumberField availableDaysField = new NumberField("Días disponibles");
private final DatePicker startDatePicker = new DatePicker("Start Date"); private final DatePicker startDatePicker = new DatePicker("Fecha de inicio");
private final DatePicker endDatePicker = new DatePicker("End Date"); private final DatePicker endDatePicker = new DatePicker("Fecha final");
private final NumberField daysToBeTakenField = new NumberField("Days To Be Taken"); private final NumberField daysToBeTakenField = new NumberField("Días a tomar");
private final NumberField balanceDaysField = new NumberField("Balance Days"); private final NumberField balanceDaysField = new NumberField("Días de saldo");
private final TimeOffRequestService requestService; private final TimeOffRequestService requestService;
private final EmployeeService employeeService; private final EmployeeService employeeService;
@ -59,11 +59,24 @@ public class RequestRegisterView extends VerticalLayout {
this.employeeService = employeeService; this.employeeService = employeeService;
this.vacationService = vacationService; this.vacationService = vacationService;
this.binder = new Binder<>(TimeOffRequest.class); this.binder = new Binder<>(TimeOffRequest.class);
initializeView();
}
private void initializeView() {
configureFormFields(); configureFormFields();
configureButtons(); configureButtons();
configureBinder(); configureBinder();
setupFormLayout(); 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() { private void configureFormFields() {
@ -71,66 +84,74 @@ public class RequestRegisterView extends VerticalLayout {
employeeComboBox.setItemLabelGenerator(emp -> emp.getFirstName() + " " + emp.getLastName()); employeeComboBox.setItemLabelGenerator(emp -> emp.getFirstName() + " " + emp.getLastName());
employeeComboBox.addValueChangeListener(event -> { employeeComboBox.addValueChangeListener(event -> {
employee = event.getValue(); employee = event.getValue();
handleEmployeeSelection(employee); System.out.println("Clearing form..." + employee);
handleEmployeeSelection(event.getValue());
});
categoryComboBox.addValueChangeListener(event -> {
onCategoryChange(event.getValue());
handleCategorySelection(event.getValue());
}); });
categoryComboBox.setEnabled(false);
startDatePicker.setEnabled(false);
endDatePicker.setEnabled(false);
categoryComboBox.addValueChangeListener(event -> handleCategorySelection(event.getValue()));
startDatePicker.addValueChangeListener(event -> updateDatePickerMinValues()); startDatePicker.addValueChangeListener(event -> updateDatePickerMinValues());
endDatePicker.addValueChangeListener(event -> calculateDays()); endDatePicker.addValueChangeListener(event -> calculateDays());
availableDaysField.setReadOnly(true);
daysToBeTakenField.setReadOnly(true);
balanceDaysField.setReadOnly(true);
} }
private void configureBinder() { private void configureBinder() {
binder.forField(employeeComboBox) binder.forField(employeeComboBox)
.asRequired("Employee is required")
.bind(TimeOffRequest::getEmployee, TimeOffRequest::setEmployee); .bind(TimeOffRequest::getEmployee, TimeOffRequest::setEmployee);
binder.forField(categoryComboBox) binder.forField(categoryComboBox)
.asRequired("Category is required")
.bind(TimeOffRequest::getCategory, TimeOffRequest::setCategory); .bind(TimeOffRequest::getCategory, TimeOffRequest::setCategory);
binder.forField(availableDaysField) binder.forField(availableDaysField)
.bind(TimeOffRequest::getAvailableDays, TimeOffRequest::setAvailableDays); .bind(TimeOffRequest::getAvailableDays, TimeOffRequest::setAvailableDays);
binder.forField(startDatePicker) binder.forField(startDatePicker)
.asRequired("Start date is required")
.bind(TimeOffRequest::getStartDate, TimeOffRequest::setStartDate); .bind(TimeOffRequest::getStartDate, TimeOffRequest::setStartDate);
binder.forField(endDatePicker) binder.forField(endDatePicker)
.asRequired("End date is required")
.bind(TimeOffRequest::getEndDate, TimeOffRequest::setEndDate); .bind(TimeOffRequest::getEndDate, TimeOffRequest::setEndDate);
binder.forField(daysToBeTakenField) binder.forField(daysToBeTakenField)
.bind(TimeOffRequest::getDaysToBeTake, TimeOffRequest::setDaysToBeTake); .bind(TimeOffRequest::getDaysToBeTake, TimeOffRequest::setDaysToBeTake);
binder.forField(balanceDaysField) binder.forField(balanceDaysField)
.bind(TimeOffRequest::getDaysBalance, TimeOffRequest::setDaysBalance); .bind(TimeOffRequest::getDaysBalance, TimeOffRequest::setDaysBalance);
binder.setBean(new TimeOffRequest()); binder.setBean(new TimeOffRequest());
} }
private void handleEmployeeSelection(final Employee selectedEmployee) { private void handleEmployeeSelection(final Employee selectedEmployee) {
clearForm();
if (selectedEmployee != null) { if (selectedEmployee != null) {
categoryComboBox.clear();
availableDaysField.clear();
startDatePicker.clear();
endDatePicker.clear();
daysToBeTakenField.clear();
balanceDaysField.clear();
categoryComboBox.setEnabled(true); categoryComboBox.setEnabled(true);
startDatePicker.setEnabled(false);
endDatePicker.setEnabled(false);
filterCategories(selectedEmployee); filterCategories(selectedEmployee);
} }
} }
private void filterCategories(final Employee employee) { private void filterCategories(final Employee employee) {
categoryComboBox.clear();
List<TimeOffRequest> employeeRequests = requestService.findRequestsByEmployeeId(employee.getId()); List<TimeOffRequest> employeeRequests = requestService.findRequestsByEmployeeId(employee.getId());
List<TimeOffRequestType> allCategories = Arrays.asList(TimeOffRequestType.values()); List<TimeOffRequestType> allCategories = Arrays.asList(TimeOffRequestType.values());
List<TimeOffRequestType> availableCategories = allCategories.stream() List<TimeOffRequestType> availableCategories = allCategories.stream()
.filter(category -> isCategoryAvailable(employeeRequests, category)) .filter(category -> isCategoryAvailable(employeeRequests, category))
.filter(category -> isCategoryAllowedByGender(category, employee.getGender())) .filter(category -> isCategoryAllowedByGender(category, employee.getGender()))
.filter(category -> category != TimeOffRequestType.VACACION_GESTION_ANTERIOR && category != TimeOffRequestType.TODOS)
.toList(); .toList();
categoryComboBox.setItems(availableCategories); categoryComboBox.setItems(availableCategories);
} }
private void onCategoryChange(final TimeOffRequestType selectedCategory) {
if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ACTUAL) {
startDatePicker.setEnabled(true);
endDatePicker.setEnabled(true);
} else {
startDatePicker.setEnabled(true);
endDatePicker.setEnabled(false);
}
}
private boolean isCategoryAvailable(final List<TimeOffRequest> employeeRequests, private boolean isCategoryAvailable(final List<TimeOffRequest> employeeRequests,
final TimeOffRequestType category) { final TimeOffRequestType category) {
List<TimeOffRequest> requestsByCategory = employeeRequests.stream() List<TimeOffRequest> requestsByCategory = employeeRequests.stream()
@ -170,7 +191,6 @@ public class RequestRegisterView extends VerticalLayout {
private void handleCategorySelection(final TimeOffRequestType selectedCategory) { private void handleCategorySelection(final TimeOffRequestType selectedCategory) {
if (selectedCategory != null) { if (selectedCategory != null) {
updateAvailableDays(selectedCategory); updateAvailableDays(selectedCategory);
startDatePicker.setEnabled(true);
} }
} }
@ -215,48 +235,52 @@ public class RequestRegisterView extends VerticalLayout {
endDate = null; endDate = null;
UUID employeeId = employee.getId(); UUID employeeId = employee.getId();
List<TimeOffRequest> previousRequests List<TimeOffRequest> previousRequests = requestService.findByEmployeeAndCategory(employeeId, vacation.getCategory());
= requestService.findByEmployeeAndCategory(employeeId, vacation.getCategory());
int startYear; int startYear = calculateStartYear(previousRequests);
if (previousRequests.isEmpty()) {
startYear = LocalDate.now().getYear();
} else {
int lastRequestYear = previousRequests.stream()
.max(Comparator.comparing(TimeOffRequest::getStartDate))
.map(request -> request.getStartDate().getYear())
.orElse(LocalDate.now().getYear());
int proposedYear = lastRequestYear + 1; startDate = determineStartDate(vacation, startYear);
int currentYear = LocalDate.now().getYear(); if (startDate != null) {
if (proposedYear < currentYear) {
startYear = currentYear;
} else {
startYear = proposedYear;
}
}
if (vacation.getMonthOfYear() != null && vacation.getDayOfMonth() != null) {
startDate = LocalDate.of(
startYear,
vacation.getMonthOfYear().intValue(),
vacation.getDayOfMonth().intValue());
endDate = startDate.plusDays(vacation.getExpiration().intValue() - 1); endDate = startDate.plusDays(vacation.getExpiration().intValue() - 1);
} else { } else {
if (vacation.getCategory() == TimeOffRequestType.CUMPLEAÑOS && employee.getBirthday() != null) { startDate = LocalDate.now();
startDate = LocalDate.of(
startYear,
employee.getBirthday().getMonth(),
employee.getBirthday().getDayOfMonth());
endDate = startDate.plusDays(vacation.getExpiration().intValue() - 1);
} else if (vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD) {
startDate = LocalDate.now();
endDate = LocalDate.of(startYear, 12, 31);
} else {
startDate = LocalDate.now();
}
} }
setPickerValues(vacation, 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());
int currentYear = LocalDate.now().getYear();
return Math.max(lastRequestYear + 1, currentYear);
}
private LocalDate determineStartDate(final Vacation vacation, final int startYear) {
if (vacation.getMonthOfYear() != null && vacation.getDayOfMonth() != null) {
return LocalDate.of(startYear, vacation.getMonthOfYear().intValue(), vacation.getDayOfMonth().intValue());
}
if (vacation.getCategory() == TimeOffRequestType.CUMPLEAÑOS && employee.getBirthday() != null) {
return LocalDate.of(startYear, employee.getBirthday().getMonth(), employee.getBirthday().getDayOfMonth());
}
if (vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD) {
return LocalDate.now();
}
return LocalDate.now();
}
private void setPickerValues(final Vacation vacation, final LocalDate startDate) {
startDatePicker.setValue(startDate); startDatePicker.setValue(startDate);
if ((vacation.getDuration() != null && vacation.getDuration() == 0.5) if ((vacation.getDuration() != null && vacation.getDuration() == 0.5)
@ -266,22 +290,25 @@ public class RequestRegisterView extends VerticalLayout {
int durationDays = (vacation.getDuration() != null ? vacation.getDuration().intValue() - 1 : 0); int durationDays = (vacation.getDuration() != null ? vacation.getDuration().intValue() - 1 : 0);
endDatePicker.setValue(startDate.plusDays(durationDays)); endDatePicker.setValue(startDate.plusDays(durationDays));
} }
}
private void setPickerLimits(final LocalDate startDate, final LocalDate endDate) {
startDatePicker.setMin(startDate); startDatePicker.setMin(startDate);
startDatePicker.setMax(endDate); startDatePicker.setMax(endDate);
endDatePicker.setMin(startDate); endDatePicker.setMin(startDate);
endDatePicker.setMax(endDate); endDatePicker.setMax(endDate);
} }
private void updateDatePickerMinValues() { private void updateDatePickerMinValues() {
LocalDate startDate = startDatePicker.getValue(); LocalDate startDate = startDatePicker.getValue();
if (vacation.getDuration() == 0.5) { if (availableDaysField.getValue() != null) {
endDatePicker.setValue(startDate.plusDays(0)); if (availableDaysField.getValue() == 0.5) {
} else { endDatePicker.setValue(startDate.plusDays(0));
endDatePicker.setValue(startDate.plusDays(vacation.getDuration().intValue() - 1)); } else {
endDatePicker.setValue(startDate.plusDays(availableDaysField.getValue().intValue() - 1));
}
calculateDays();
} }
calculateDays();
} }
private void calculateDays() { private void calculateDays() {
@ -289,26 +316,53 @@ public class RequestRegisterView extends VerticalLayout {
LocalDate endDate = endDatePicker.getValue(); LocalDate endDate = endDatePicker.getValue();
Double availableDays = availableDaysField.getValue(); Double availableDays = availableDaysField.getValue();
if (startDate != null && endDate != null) { if (areDatesValid(startDate, endDate)) {
double daysToBeTaken = java.time.temporal.ChronoUnit.DAYS.between(startDate, endDate) + 1; double daysToBeTaken = calculateDaysBetween(startDate, endDate);
if (vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD || vacation.getDuration() == 0.5) { setDaysToBeTakenField(daysToBeTaken);
daysToBeTakenField.setValue(0.5);
} else { double balanceDays = calculateBalanceDays(availableDays, daysToBeTakenField.getValue());
daysToBeTakenField.setValue(daysToBeTaken);
}
double balanceDays = availableDays - daysToBeTakenField.getValue();
balanceDaysField.setValue(balanceDays); balanceDaysField.setValue(balanceDays);
if (balanceDays < 0) {
clearFields();
}
} }
} }
private boolean areDatesValid(final LocalDate startDate, final LocalDate endDate) {
return startDate != null && endDate != null;
}
private double calculateDaysBetween(final LocalDate startDate, final LocalDate endDate) {
return java.time.temporal.ChronoUnit.DAYS.between(startDate, endDate) + 1;
}
private void setDaysToBeTakenField(final double daysToBeTaken) {
if (vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD) {
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() { private void configureButtons() {
saveButton = new Button("Save", event -> saveRequest()); saveButton = new Button("Guardar", event -> saveRequest());
closeButton = new Button("Close", event -> closeForm()); closeButton = new Button("Salir", event -> closeForm());
} }
private void setupFormLayout() { private void setupFormLayout() {
add( add(
new H3("Add Vacation Request"), new H3("Añadir solicitud de vacaciones"),
employeeComboBox, employeeComboBox,
categoryComboBox, categoryComboBox,
availableDaysField, availableDaysField,
@ -321,59 +375,54 @@ public class RequestRegisterView extends VerticalLayout {
} }
private void saveRequest() { private void saveRequest() {
if (binder.validate().isOk()) { if (!binder.validate().isOk()) {
TimeOffRequest request = binder.getBean(); Notification.show("Rellene correctamente todos los campos obligatorios.");
request.setStartDate(startDatePicker.getValue()); return;
request.setAvailableDays(availableDaysField.getValue()); }
if (endDate == null) {
request.setExpiration(endDatePicker.getValue());
} else {
request.setExpiration(endDate);
}
request.setState(TimeOffRequestStatus.SOLICITADO);
List<TimeOffRequest> existingRequests = if (!validateForm()) {
requestService.findByEmployeeAndCategory(employee.getId(), request.getCategory()); Notification.show("Por favor, complete los campos antes de guardar");
return;
}
int maxRequests = request.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD ? 4 : 2; TimeOffRequest request = prepareRequest();
handleExistingRequests(request);
requestService.saveTimeOffRequest(request);
if (existingRequests.size() >= maxRequests) { Notification.show("Solicitud guardada correctamente.");
existingRequests.stream() closeForm();
.min(Comparator.comparing(TimeOffRequest::getStartDate)) }
.ifPresent(oldestRequest -> requestService.deleteTimeOffRequest(oldestRequest.getId()));
}
requestService.saveTimeOffRequest(request); private TimeOffRequest prepareRequest() {
Notification.show("Request saved successfully."); TimeOffRequest request = binder.getBean();
closeForm(); request.setStartDate(startDatePicker.getValue());
} else { request.setAvailableDays(availableDaysField.getValue());
Notification.show("Please fill all required fields correctly."); request.setExpiration(endDate != null ? endDate : endDatePicker.getValue());
request.setState(TimeOffRequestStatus.PENDIENTE);
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 ? 4 : 2;
if (existingRequests.size() >= maxRequests) {
existingRequests.stream()
.min(Comparator.comparing(TimeOffRequest::getStartDate))
.ifPresent(oldestRequest -> requestService.deleteTimeOffRequest(oldestRequest.getId()));
} }
} }
private void updateBalanceForCategory(final TimeOffRequest newRequest) { private boolean validateForm() {
List<TimeOffRequest> requests = requestService.findByEmployeeAndCategory( return employeeComboBox.getValue() != null
newRequest.getEmployee().getId(), newRequest.getCategory()); && categoryComboBox.getValue() != null
&& startDatePicker.getValue() != null
if (vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD && endDatePicker.getValue() != null;
&& vacation.getCategory() == TimeOffRequestType.VACACION_GESTION_ACTUAL) {
for (TimeOffRequest request : requests) {
double newBalance = request.getDaysBalance() - newRequest.getDaysToBeTake();
request.setDaysBalance(newBalance);
requestService.saveTimeOffRequest(request);
}
}
} }
private void closeForm() { private void closeForm() {
getUI().ifPresent(ui -> ui.navigate(RequestsListView.class)); getUI().ifPresent(ui -> ui.navigate(RequestsListView.class));
} }
private void clearForm() {
availableDaysField.clear();
startDatePicker.clear();
endDatePicker.clear();
daysToBeTakenField.clear();
balanceDaysField.clear();
}
} }