En-desarrollo #65
@ -1,6 +1,8 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@ -17,30 +19,45 @@
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Employee extends BaseEntity implements UserDetails {
|
||||
|
||||
private String username;
|
||||
@NotNull(message = "El nombre no puede estar vacío")
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El nombre solo debe contener letras")
|
||||
private String firstName;
|
||||
@NotNull(message = "El apellido no puede estar vacío")
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El apellido solo debe contener letras")
|
||||
private String lastName;
|
||||
private LocalDate birthday;
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "La ciudad de nacimiento solo debe contener letras")
|
||||
private String birthCity;
|
||||
private String age;
|
||||
|
||||
@Size(max = 100, message = "La dirección de residencia no debe exceder 100 caracteres")
|
||||
private String residenceAddress;
|
||||
@Size(max = 100, message = "La dirección local no debe exceder 100 caracteres")
|
||||
private String localAddress;
|
||||
@Pattern(regexp = "^[0-9]+$", message = "El número de teléfono debe contener solo números")
|
||||
private String phoneNumber;
|
||||
@Email(message = "El correo personal no tiene un formato válido")
|
||||
private String personalEmail;
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El cargo solo debe contener letras")
|
||||
private String position;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "team_id", nullable = false)
|
||||
private Team team;
|
||||
@Size(max = 100, message = "El nombre de contacto de emergencia no debe exceder 100 caracteres")
|
||||
private String emergencyCName;
|
||||
@Size(max = 100, message = "La dirección de contacto de emergencia no debe exceder 100 caracteres")
|
||||
private String emergencyCAddress;
|
||||
@Pattern(regexp = "^[0-9]+$", message = "El teléfono de contacto de emergencia debe contener solo números")
|
||||
private String emergencyCPhone;
|
||||
@Email(message = "El correo de contacto de emergencia no tiene un formato válido")
|
||||
private String emergencyCEmail;
|
||||
@Pattern(regexp = "^[0-9]+$", message = "La cantidad de hijos debe contener solo números")
|
||||
private String numberOfChildren;
|
||||
|
||||
@Pattern(regexp = "^[0-9]+$", message = "El CI debe contener solo números")
|
||||
private String ci;
|
||||
private String issuedIn;
|
||||
|
||||
@Size(max = 100, message = "El título no debe exceder 100 caracteres")
|
||||
private String pTitle1;
|
||||
private String pTitle2;
|
||||
private String pTitle3;
|
||||
@ -53,29 +70,36 @@
|
||||
private String certification2;
|
||||
private String certification3;
|
||||
private String certification4;
|
||||
|
||||
@Size(max = 255, message = "El reconocimiento no debe exceder 255 caracteres")
|
||||
private String recognition;
|
||||
@Size(max = 500, message = "Los logros no deben exceder 500 caracteres")
|
||||
private String achievements;
|
||||
|
||||
private String language;
|
||||
private String languageLevel;
|
||||
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "El código debe contener solo letras y números")
|
||||
private String cod;
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El lead manager solo debe contener letras")
|
||||
private String leadManager;
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El proyecto solo debe contener letras")
|
||||
private String project;
|
||||
|
||||
private LocalDate dateOfEntry;
|
||||
private LocalDate dateOfExit;
|
||||
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El tipo de contrato solo debe contener letras")
|
||||
private String contractType;
|
||||
@Pattern(regexp = "^[0-9]+$", message = "La antigüedad debe contener solo números")
|
||||
private String seniority;
|
||||
@Pattern(regexp = "^[0-9]+(\\.[0-9]{1,2})?$", message = "El salario debe ser un número con hasta dos decimales")
|
||||
private String salary;
|
||||
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El nombre del banco solo debe contener letras")
|
||||
private String bankName;
|
||||
@Pattern(regexp = "^[0-9]+$", message = "El número de cuenta debe contener solo números")
|
||||
private String accountNumber;
|
||||
|
||||
private String gpss;
|
||||
private String sss;
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "Los derechohabientes solo deben contener letras")
|
||||
private String beneficiaries;
|
||||
|
||||
@Column(columnDefinition = "TEXT")
|
||||
@ -122,26 +146,22 @@
|
||||
ACTIVE,
|
||||
INACTIVE
|
||||
}
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private MaritalStatus maritalStatus;
|
||||
|
||||
public enum MaritalStatus {
|
||||
SINGLE,
|
||||
MARRIED,
|
||||
WIDOWED,
|
||||
DIVORCED
|
||||
}
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Gender gender;
|
||||
|
||||
public enum Gender {
|
||||
MALE,
|
||||
FEMALE
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
|
||||
return status;
|
||||
}
|
||||
public void setStatus(final Status status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import com.primefactorsolutions.model.Team;
|
||||
import com.primefactorsolutions.model.*;
|
||||
import com.primefactorsolutions.service.EmployeeService;
|
||||
import com.primefactorsolutions.service.ReportService;
|
||||
import com.primefactorsolutions.service.TeamService;
|
||||
import com.primefactorsolutions.service.TimeOffRequestService;
|
||||
import com.vaadin.componentfactory.pdfviewer.PdfViewer;
|
||||
import com.vaadin.flow.component.ClickEvent;
|
||||
import com.vaadin.flow.component.Component;
|
||||
@ -24,6 +24,9 @@ import com.vaadin.flow.component.textfield.EmailField;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.component.upload.Upload;
|
||||
import com.vaadin.flow.component.upload.receivers.MemoryBuffer;
|
||||
import com.vaadin.flow.data.binder.Result;
|
||||
import com.vaadin.flow.data.binder.ValueContext;
|
||||
import com.vaadin.flow.data.converter.Converter;
|
||||
import com.vaadin.flow.data.value.ValueChangeMode;
|
||||
import com.vaadin.flow.router.*;
|
||||
import com.vaadin.flow.server.StreamResource;
|
||||
@ -36,6 +39,8 @@ import org.vaadin.firitin.form.BeanValidationForm;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@ -49,8 +54,10 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
|
||||
|
||||
private final EmployeeService employeeService;
|
||||
private final ReportService reportService;
|
||||
private final TimeOffRequestService requestService;
|
||||
private final TeamService teamService;
|
||||
|
||||
|
||||
// TODO: campo usado para registrar al empleado en LDAP. Este campo podria estar en otro form eventualmente.
|
||||
private final TextField username = createTextField("Username: ", 30, true);
|
||||
private final TextField firstName = createTextField("Nombres: ", 30, true);
|
||||
@ -140,10 +147,12 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
|
||||
|
||||
public EmployeeView(final EmployeeService employeeService,
|
||||
final ReportService reportService,
|
||||
final TeamService teamService) {
|
||||
final TeamService teamService,
|
||||
final TimeOffRequestService requestService) {
|
||||
super(Employee.class);
|
||||
this.employeeService = employeeService;
|
||||
this.reportService = reportService;
|
||||
this.requestService = requestService;
|
||||
this.teamService = teamService;
|
||||
saveButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
|
||||
@ -156,12 +165,18 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
|
||||
phoneNumber.addValueChangeListener(e -> validatePhoneNumber(phoneNumber, e.getValue()));
|
||||
emergencyCPhone.setValueChangeMode(ValueChangeMode.EAGER);
|
||||
emergencyCPhone.addValueChangeListener(e -> validatePhoneNumber(emergencyCPhone, e.getValue()));
|
||||
|
||||
firstName.setValueChangeMode(ValueChangeMode.EAGER);
|
||||
firstName.addValueChangeListener(e -> validateNameField(firstName, e.getValue()));
|
||||
lastName.setValueChangeMode(ValueChangeMode.EAGER);
|
||||
lastName.addValueChangeListener(e -> validateNameField(lastName, e.getValue()));
|
||||
createTeamComboBox();
|
||||
|
||||
configureUpload();
|
||||
saveButton.setVisible(true);
|
||||
editButton.setVisible(true);
|
||||
reportButton.setVisible(true);
|
||||
birthday.addValueChangeListener(event -> calculateAge());
|
||||
createTeamComboBox();
|
||||
|
||||
reportButton.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
||||
var employee = getEntity();
|
||||
@ -174,6 +189,15 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
|
||||
initDialog();
|
||||
}
|
||||
|
||||
private void validateNameField(TextField textField, String value) {
|
||||
if (!value.matches("^[a-zA-ZáéíóúÁÉÍÓÚñÑ\\s]*$")) {
|
||||
textField.setInvalid(true);
|
||||
textField.setErrorMessage("Este campo solo debe contener letras.");
|
||||
} else {
|
||||
textField.setInvalid(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateAge() {
|
||||
if (birthday.getValue() != null) {
|
||||
int currentYear = java.time.LocalDate.now().getYear();
|
||||
@ -244,7 +268,7 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
|
||||
ComboBox<Employee.Status> comboBox = new ComboBox<>("Estado");
|
||||
comboBox.setItems(Employee.Status.values());
|
||||
comboBox.setItemLabelGenerator(Employee.Status::name);
|
||||
comboBox.setRequiredIndicatorVisible(true); // Indicador de campo requerido
|
||||
comboBox.setRequiredIndicatorVisible(true);
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
@ -276,6 +300,14 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
|
||||
team.setWidthFull();
|
||||
}
|
||||
|
||||
private <T> ComboBox<T> createComboBox(final String label, final T[] items) {
|
||||
ComboBox<T> comboBox = new ComboBox<>(label);
|
||||
comboBox.setItems(items);
|
||||
comboBox.setItemLabelGenerator(Object::toString);
|
||||
comboBox.setWidthFull();
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private ComboBox<Employee.Gender> createGenderComboBox() {
|
||||
ComboBox<Employee.Gender> comboBox = new ComboBox<>("Genero");
|
||||
comboBox.setItems(Employee.Gender.values());
|
||||
@ -288,12 +320,33 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
|
||||
return !firstName.isEmpty() && !lastName.isEmpty() && status.getValue() != null;
|
||||
}
|
||||
|
||||
private void setVacationDuration(Employee employee, TimeOffRequest request, LocalDate referenceDate) {
|
||||
double yearsOfService = ChronoUnit.YEARS.between(employee.getDateOfEntry(), referenceDate);
|
||||
request.setAvailableDays(calculateAvailableDays(yearsOfService));
|
||||
}
|
||||
|
||||
private double calculateAvailableDays(double yearsOfService) {
|
||||
if (yearsOfService > 10) {
|
||||
return 30.0;
|
||||
} else if (yearsOfService > 5) {
|
||||
return 20.0;
|
||||
} else if (yearsOfService > 1) {
|
||||
return 15.0;
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private void saveEmployee() {
|
||||
if (validateForm()) {
|
||||
Employee employee = getEntity();
|
||||
employee.setStatus(status.getValue());
|
||||
employee.setAge(age.getValue());
|
||||
|
||||
if (employee.getDateOfEntry() != null) {
|
||||
processTimeOffRequests(employee);
|
||||
}
|
||||
|
||||
employeeService.createOrUpdate(employee);
|
||||
Notification.show(NOTIFICATION_SAVE_SUCCESS);
|
||||
getUI().ifPresent(ui -> ui.navigate(EmployeesListView.class));
|
||||
@ -302,13 +355,60 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
|
||||
}
|
||||
}
|
||||
|
||||
private void processTimeOffRequests(Employee employee) {
|
||||
if (hasTimeOffRequests(employee)) {
|
||||
updateExistingTimeOffRequests(employee);
|
||||
} else {
|
||||
createAndSaveTimeOffRequests(employee);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasTimeOffRequests(Employee employee) {
|
||||
return !requestService.findByEmployeeAndCategory(employee.getId(), TimeOffRequestType.VACACION_GESTION_ACTUAL).isEmpty() ||
|
||||
!requestService.findByEmployeeAndCategory(employee.getId(), TimeOffRequestType.VACACION_GESTION_ANTERIOR).isEmpty();
|
||||
}
|
||||
|
||||
private void updateExistingTimeOffRequests(Employee employee) {
|
||||
updateTimeOffRequest(employee, TimeOffRequestType.VACACION_GESTION_ANTERIOR, -1, 729);
|
||||
updateTimeOffRequest(employee, TimeOffRequestType.VACACION_GESTION_ACTUAL, 0, 1094);
|
||||
}
|
||||
|
||||
private void updateTimeOffRequest(Employee employee, TimeOffRequestType category, int yearOffset, int daysToAdd) {
|
||||
List<TimeOffRequest> requests = requestService.findByEmployeeAndCategory(employee.getId(), category);
|
||||
if (!requests.isEmpty()) {
|
||||
TimeOffRequest request = requests.getLast();
|
||||
LocalDate newBaseDate = LocalDate.of(LocalDate.now().getYear() + yearOffset, employee.getDateOfEntry().getMonth(), employee.getDateOfEntry().getDayOfMonth());
|
||||
request.setExpiration(newBaseDate.plusDays(daysToAdd));
|
||||
setVacationDuration(employee, request, newBaseDate);
|
||||
requestService.saveTimeOffRequest(request);
|
||||
}
|
||||
}
|
||||
|
||||
private void createAndSaveTimeOffRequests(Employee employee) {
|
||||
requestService.saveTimeOffRequest(createTimeOffRequest(employee, TimeOffRequestType.VACACION_GESTION_ANTERIOR, -1, 729));
|
||||
requestService.saveTimeOffRequest(createTimeOffRequest(employee, TimeOffRequestType.VACACION_GESTION_ACTUAL, 0, 1094));
|
||||
}
|
||||
|
||||
private TimeOffRequest createTimeOffRequest(Employee employee, TimeOffRequestType category, int yearOffset, int daysToAdd) {
|
||||
LocalDate baseDate = LocalDate.of(LocalDate.now().getYear() + yearOffset, employee.getDateOfEntry().getMonth(), employee.getDateOfEntry().getDayOfMonth());
|
||||
LocalDate expirationDate = baseDate.plusDays(daysToAdd);
|
||||
|
||||
TimeOffRequest request = new TimeOffRequest();
|
||||
request.setCategory(category);
|
||||
request.setState(TimeOffRequestStatus.APROBADO);
|
||||
request.setEmployee(employee);
|
||||
request.setExpiration(expirationDate);
|
||||
setVacationDuration(employee, request, baseDate);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
private void enableEditMode() {
|
||||
setFieldsEditable();
|
||||
saveButton.setVisible(true);
|
||||
editButton.setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setParameter(final BeforeEvent beforeEvent, final String action) {
|
||||
final RouteParameters params = beforeEvent.getRouteParameters();
|
||||
@ -323,7 +423,6 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
|
||||
UUID employeeId = UUID.fromString(s);
|
||||
var employee = employeeService.getEmployee(employeeId);
|
||||
setEntityWithEnabledSave(employee);
|
||||
team.setValue(employee.getTeam());
|
||||
|
||||
if ("edit".equals(action) && !s.isEmpty()) {
|
||||
saveButton.setVisible(true);
|
||||
@ -491,4 +590,3 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user