fix vacations

This commit is contained in:
alex 2025-01-04 15:01:43 -05:00
parent 6e87c1795c
commit 368b176892
11 changed files with 129 additions and 123 deletions

View File

@ -1,7 +1,11 @@
package com.primefactorsolutions.model;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.ColumnDefault;
import java.time.Instant;
import java.util.UUID;
@MappedSuperclass
@ -9,22 +13,18 @@ public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Getter
@Setter
private UUID id;
@Version
@Getter
private int version;
public UUID getId() {
return id;
}
public void setId(final UUID id) {
this.id = id;
}
public int getVersion() {
return version;
}
@Getter
@ColumnDefault("NOW()")
private Instant created;
@ColumnDefault("NOW()")
@Getter
private Instant updated;
@Override
public int hashCode() {
@ -44,4 +44,14 @@ public abstract class BaseEntity {
}
return super.equals(that);
}
@PrePersist
public void updateCreated() {
this.created = Instant.now();
}
@PreUpdate
public void updateUpdated() {
this.updated = Instant.now();
}
}

View File

@ -0,0 +1,4 @@
package com.primefactorsolutions.model;
public record Certification(String title, Integer year) {
}

View File

@ -1,9 +1,12 @@
package com.primefactorsolutions.model;
import com.google.common.collect.Lists;
import io.hypersistence.utils.hibernate.type.json.JsonType;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import lombok.*;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.Type;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
@ -11,6 +14,7 @@ import org.springframework.security.core.userdetails.UserDetails;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Collection;
import java.util.List;
@Data
@Entity
@ -41,9 +45,9 @@ public class Employee extends BaseEntity implements UserDetails {
@Email(message = "El correo personal no tiene un formato válido")
private String personalEmail;
@Pattern(regexp = "^[0-9]+$", message = "El número de teléfono debe contener solo números")
private String phoneNumberProfesional;
private String phoneNumberProfessional;
@Email(message = "El correo profesional no tiene un formato válido")
private String profesionalEmail;
private String professionalEmail;
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El cargo solo debe contener letras")
private String position;
@ -64,25 +68,21 @@ public class Employee extends BaseEntity implements UserDetails {
@Pattern(regexp = "^[a-zA-Z0-9]+$", message = "El CI debe contener solo letras y números")
private String ci;
private String issuedIn;
private String pTitle1;
private String pTitle2;
private String pTitle3;
private String pStudy1;
private String pStudy2;
private String pStudy3;
private String certification1;
private String certification2;
private String certification3;
private String certification4;
@Type(JsonType.class)
@Column(columnDefinition = "json")
@ColumnDefault("JSON_ARRAY()")
private List<Certification> educationTitles = Lists.newArrayList();
@Type(JsonType.class)
@Column(columnDefinition = "json")
@ColumnDefault("JSON_ARRAY()")
private List<Certification> certifications = Lists.newArrayList();
private String recognition;
private String achievements;
private String language1;
private String language1Level;
private String language2;
private String language2Level;
@Type(JsonType.class)
@Column(columnDefinition = "json")
@ColumnDefault("JSON_ARRAY()")
private List<Language> languages = Lists.newArrayList();
@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")

View File

@ -0,0 +1,4 @@
package com.primefactorsolutions.model;
public record Language(String name, Proficiency proficiency) {
}

View File

@ -0,0 +1,7 @@
package com.primefactorsolutions.model;
public enum Proficiency {
BASIC,
ADVANCED,
FLUENT
}

View File

@ -10,6 +10,7 @@ import java.util.Optional;
import java.util.UUID;
public interface TimeOffRequestRepository extends JpaRepository<TimeOffRequest, UUID> {
List<TimeOffRequest> findByOrderByUpdatedDesc();
List<TimeOffRequest> findByEmployeeId(UUID idEmployee);
Optional<TimeOffRequest> findByEmployeeIdAndState(UUID employeeId, TimeOffRequestStatus state);
List<TimeOffRequest> findByEmployeeIdAndCategory(UUID employeeId, TimeOffRequestType category);

View File

@ -221,7 +221,7 @@ public class ReportService {
employee.getMaritalStatus().toString(), String.valueOf(employee.getNumberOfChildren()),
employee.getCi(),
employee.getIssuedIn(), employee.getPhoneNumber(), employee.getPersonalEmail(),
employee.getPhoneNumberProfesional(), employee.getProfesionalEmail(), employee.getEmergencyCName(),
employee.getPhoneNumberProfessional(), employee.getProfessionalEmail(), employee.getEmergencyCName(),
employee.getEmergencyCAddress(), employee.getEmergencyCPhone(), employee.getEmergencyCEmail(),
employee.getCod(), employee.getPosition(), employee.getTeam().getName(), employee.getLeadManager(),
employee.getDateOfEntry().toString(), employee.getDateOfExit() != null ? employee.getDateOfExit()

View File

@ -32,7 +32,7 @@ public class TimeOffRequestService {
}
public List<TimeOffRequest> findAllTimeOffRequests() {
return timeOffRequestRepository.findAll();
return timeOffRequestRepository.findByOrderByUpdatedDesc();
}
public TimeOffRequest findTimeOffRequest(final UUID id) {

View File

@ -36,6 +36,7 @@ import jakarta.annotation.security.PermitAll;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.vaadin.firitin.components.datepicker.VDatePicker;
import org.vaadin.firitin.fields.ElementCollectionField;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@ -74,7 +75,7 @@ public class EmployeeView extends BaseEntityForm<Employee> implements HasUrlPara
private final TextField issuedIn = createTextField("Lugar de Expedicion", 10, false);
private final TextField phoneNumber = createTextField("Teléfono", 8, false);
private final EmailField personalEmail = createEmailField("E-mail");
private final TextField phoneNumberProfesional = createTextField("Teléfono Laboral", 8, false);
private final TextField phoneNumberProfessional = createTextField("Teléfono Laboral", 8, false);
private final TextField emergencyCName = createTextField("Nombres y Apellidos de Contacto", 50, false);
private final TextField emergencyCAddress = createTextField("Dirección de Contacto", 50, false);
private final TextField emergencyCPhone = createTextField("Teléfono de Contacto", 8, false);
@ -82,22 +83,11 @@ public class EmployeeView extends BaseEntityForm<Employee> implements HasUrlPara
private final MemoryBuffer buffer = new MemoryBuffer();
private final Upload upload = new Upload(buffer);
private final Image profileImagePreview = new Image();
private final TextField pTitle1 = createTextField("Título 1", 30, false);
private final TextField pTitle2 = createTextField("Título 2", 30, false);
private final TextField pTitle3 = createTextField("Título 3", 30, false);
private final TextField pStudy1 = createTextField("Estudio 1", 30, false);
private final TextField pStudy2 = createTextField("Estudio 2", 30, false);
private final TextField pStudy3 = createTextField("Estudio 3", 30, false);
private final TextField certification1 = createTextField("Certificación 1", 30, false);
private final TextField certification2 = createTextField("Certificación 2", 30, false);
private final TextField certification3 = createTextField("Certificación 3", 30, false);
private final TextField certification4 = createTextField("Certificación 4", 30, false);
private final ElementCollectionField<Certification> educationTitles = new ElementCollectionField<>(Certification.class);
private final ElementCollectionField<Certification> certifications = new ElementCollectionField<>(Certification.class);
private final TextField recognition = createTextField("Reconocimientos", 30, false);
private final TextField achievements = createTextField("Logros Profesionales", 30, false);
private final TextField language1 = createTextField("Idioma 1", 30, false);
private final TextField language1Level = createTextField("Nivel de Idioma", 30, false);
private final TextField language2 = createTextField("Idioma 2", 30, false);
private final TextField language2Level = createTextField("Nivel de Idioma", 30, false);
private final ElementCollectionField<Language> languages = new ElementCollectionField<>(Language.class);
private final TextField cod = createTextField("Codigo de Empleado", 20, false);
private final TextField position = createTextField("Cargo", 30, false);
private final ComboBox<Team> team = new ComboBox<>("Equipo");
@ -218,22 +208,8 @@ public class EmployeeView extends BaseEntityForm<Employee> implements HasUrlPara
makeUpperCase(emergencyCAddress);
makeUpperCase(ci);
makeUpperCase(issuedIn);
makeUpperCase(pTitle1);
makeUpperCase(pTitle2);
makeUpperCase(pTitle3);
makeUpperCase(pStudy1);
makeUpperCase(pStudy2);
makeUpperCase(pStudy3);
makeUpperCase(certification1);
makeUpperCase(certification2);
makeUpperCase(certification3);
makeUpperCase(certification4);
makeUpperCase(recognition);
makeUpperCase(achievements);
makeUpperCase(language1);
makeUpperCase(language1Level);
makeUpperCase(language2);
makeUpperCase(language2Level);
makeUpperCase(cod);
makeUpperCase(leadManager);
makeUpperCase(seniority);
@ -566,7 +542,7 @@ public class EmployeeView extends BaseEntityForm<Employee> implements HasUrlPara
numberOfChildren.setReadOnly(true);
phoneNumber.setReadOnly(true);
personalEmail.setReadOnly(true);
phoneNumberProfesional.setReadOnly(true);
phoneNumberProfessional.setReadOnly(true);
position.setReadOnly(true);
team.setReadOnly(true);
emergencyCName.setReadOnly(true);
@ -579,22 +555,11 @@ public class EmployeeView extends BaseEntityForm<Employee> implements HasUrlPara
status.setReadOnly(true);
ci.setReadOnly(true);
issuedIn.setReadOnly(true);
pTitle1.setReadOnly(true);
pTitle2.setReadOnly(true);
pTitle3.setReadOnly(true);
pStudy1.setReadOnly(true);
pStudy2.setReadOnly(true);
pStudy3.setReadOnly(true);
certification1.setReadOnly(true);
certification2.setReadOnly(true);
certification3.setReadOnly(true);
certification4.setReadOnly(true);
educationTitles.setReadOnly(true);
certifications.setReadOnly(true);
recognition.setReadOnly(true);
achievements.setReadOnly(true);
language1.setReadOnly(true);
language1Level.setReadOnly(true);
language2.setReadOnly(true);
language2Level.setReadOnly(true);
languages.setReadOnly(true);
cod.setReadOnly(true);
leadManager.setReadOnly(true);
dateOfEntry.setReadOnly(true);
@ -627,7 +592,7 @@ public class EmployeeView extends BaseEntityForm<Employee> implements HasUrlPara
numberOfChildren.setReadOnly(false);
phoneNumber.setReadOnly(false);
personalEmail.setReadOnly(false);
phoneNumberProfesional.setReadOnly(false);
phoneNumberProfessional.setReadOnly(false);
position.setReadOnly(false);
team.setReadOnly(false);
emergencyCName.setReadOnly(false);
@ -640,22 +605,11 @@ public class EmployeeView extends BaseEntityForm<Employee> implements HasUrlPara
status.setReadOnly(false);
ci.setReadOnly(false);
issuedIn.setReadOnly(false);
pTitle1.setReadOnly(false);
pTitle2.setReadOnly(false);
pTitle3.setReadOnly(false);
pStudy1.setReadOnly(false);
pStudy2.setReadOnly(false);
pStudy3.setReadOnly(false);
certification1.setReadOnly(false);
certification2.setReadOnly(false);
certification3.setReadOnly(false);
certification4.setReadOnly(false);
educationTitles.setReadOnly(false);
certifications.setReadOnly(false);
recognition.setReadOnly(false);
achievements.setReadOnly(false);
language1.setReadOnly(false);
language1Level.setReadOnly(false);
language2.setReadOnly(false);
language2Level.setReadOnly(false);
languages.setReadOnly(false);
cod.setReadOnly(false);
leadManager.setReadOnly(false);
dateOfEntry.setReadOnly(false);
@ -700,7 +654,7 @@ public class EmployeeView extends BaseEntityForm<Employee> implements HasUrlPara
numberOfChildren,
phoneNumber,
personalEmail,
phoneNumberProfesional,
phoneNumberProfessional,
contEmerg,
emergencyCName,
emergencyCAddress,
@ -708,25 +662,14 @@ public class EmployeeView extends BaseEntityForm<Employee> implements HasUrlPara
emergencyCEmail,
infProf,
titulos,
pTitle1,
pTitle2,
pTitle3,
pStudy1,
pStudy2,
pStudy3,
educationTitles,
certif,
certification1,
certification2,
certification3,
certification4,
certifications,
logros,
recognition,
achievements,
idioma,
language1,
language1Level,
language2,
language2Level,
languages,
infoAdm,
cod,
position,

View File

@ -96,7 +96,7 @@ public class EmployeesListView extends BaseView {
row.createCell(4).setCellValue(employee.getGender() != null ? employee.getGender().toString() : "");
row.createCell(5).setCellValue(employee.getBirthday() != null ? employee.getBirthday()
.toString() : "");
row.createCell(6).setCellValue(employee.getAge() != null ? employee.getAge().toString() : "");
row.createCell(6).setCellValue(employee.getAge() != null ? employee.getAge() : "");
row.createCell(7).setCellValue(employee.getBirthCity() != null ? employee.getBirthCity() : "");
row.createCell(8).setCellValue(employee.getResidenceAddress() != null ? employee
.getResidenceAddress() : "");
@ -104,16 +104,16 @@ public class EmployeesListView extends BaseView {
row.createCell(10).setCellValue(employee.getMaritalStatus() != null ? employee.getMaritalStatus()
.toString() : "");
row.createCell(11).setCellValue(employee.getNumberOfChildren() != null ? employee
.getNumberOfChildren().toString() : "");
.getNumberOfChildren() : "");
row.createCell(12).setCellValue(employee.getCi() != null ? employee.getCi() : "");
row.createCell(13).setCellValue(employee.getIssuedIn() != null ? employee.getIssuedIn() : "");
row.createCell(14).setCellValue(employee.getPhoneNumber() != null ? employee.getPhoneNumber() : "");
row.createCell(15).setCellValue(employee.getPersonalEmail() != null ? employee
.getPersonalEmail() : "");
row.createCell(16).setCellValue(employee.getPhoneNumberProfesional() != null ? employee
.getPhoneNumberProfesional() : "");
row.createCell(17).setCellValue(employee.getProfesionalEmail() != null ? employee
.getProfesionalEmail() : "");
row.createCell(16).setCellValue(employee.getPhoneNumberProfessional() != null ? employee
.getPhoneNumberProfessional() : "");
row.createCell(17).setCellValue(employee.getProfessionalEmail() != null ? employee
.getProfessionalEmail() : "");
row.createCell(18).setCellValue(employee.getCod() != null ? employee.getCod() : "");
row.createCell(19).setCellValue(employee.getPosition() != null ? employee.getPosition() : "");
row.createCell(20).setCellValue(employee.getTeam() != null ? employee.getTeam().getName() : "");

View File

@ -40,6 +40,9 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
@ -59,6 +62,7 @@ public class TimeOffRequestsListView extends BaseView {
private final ComboBox<Employee> employeeFilter = new ComboBox<>("Empleado");
private final ComboBox<Team> teamFilter = new ComboBox<>("Equipo");
private final ComboBox<TimeOffRequestType> categoryFilter = new ComboBox<>("Categoría");
private final ComboBox<TimeOffRequestStatus> stateFilter = new ComboBox<>("Estado");
public TimeOffRequestsListView(final AuthenticationContext authenticationContext,
final TimeOffRequestService requestService,
@ -69,7 +73,8 @@ public class TimeOffRequestsListView extends BaseView {
this.employeeService = employeeService;
this.teamService = teamService;
initializeView();
refreshGeneralRequestsGrid(employeeFilter.getValue(), teamFilter.getValue(), categoryFilter.getValue());
refreshGeneralRequestsGrid(employeeFilter.getValue(), teamFilter.getValue(), categoryFilter.getValue(),
stateFilter.getValue());
}
private void initializeView() {
@ -97,6 +102,7 @@ public class TimeOffRequestsListView extends BaseView {
hl.add(createEmployeeFilter());
hl.add(createTeamFilter());
hl.add(createCategoryFilter());
hl.add(createStateFilter());
getCurrentPageLayout().add(hl);
}
@ -107,6 +113,7 @@ public class TimeOffRequestsListView extends BaseView {
requestsGrid.addColumn(this::getCategory).setHeader("Categoría");
requestsGrid.addColumn(this::getDates).setHeader("Dias");
requestsGrid.addColumn(this::getState).setHeader("Estado");
requestsGrid.addColumn(this::getUpdated).setHeader("Fecha Actualizacion");
requestsGrid.addComponentColumn((ValueProvider<TimeOffRequest, Component>) timeOffRequest -> {
final MenuBar menuBar = new MenuBar();
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
@ -129,15 +136,16 @@ public class TimeOffRequestsListView extends BaseView {
TimeOffRequest request = requestService.findTimeOffRequest(selectedRequestId);
request.setState(status);
requestService.saveTimeOffRequest(request);
refreshGeneralRequestsGrid(null, null, null);
refreshGeneralRequestsGrid(null, null, null, null);
}
private void refreshGeneralRequestsGrid(final Employee employee,
final Team team,
final TimeOffRequestType category) {
final TimeOffRequestType category,
final TimeOffRequestStatus timeOffRequestStatus) {
requestsGrid.setPagingDataProvider((page, pageSize) -> {
int start = (int) (page * requestsGrid.getPageSize());
return fetchFilteredRequests(start, pageSize, employee, team, category);
return fetchFilteredRequests(start, pageSize, employee, team, category, timeOffRequestStatus);
});
requestsGrid.getDataProvider().refreshAll();
}
@ -146,9 +154,9 @@ public class TimeOffRequestsListView extends BaseView {
final int pageSize,
final Employee employee,
final Team team,
final TimeOffRequestType category) {
List<TimeOffRequest> filteredRequests
= requestService.findAllTimeOffRequests();
final TimeOffRequestType category,
final TimeOffRequestStatus timeOffRequestStatus) {
List<TimeOffRequest> filteredRequests = requestService.findAllTimeOffRequests();
if (employee != null) {
filteredRequests = filteredRequests.stream()
@ -169,6 +177,12 @@ public class TimeOffRequestsListView extends BaseView {
.collect(Collectors.toList());
}
if (timeOffRequestStatus != null) {
filteredRequests = filteredRequests.stream()
.filter(emp -> emp.getState().equals(timeOffRequestStatus))
.collect(Collectors.toList());
}
int end = Math.min(start + pageSize, filteredRequests.size());
return filteredRequests.subList(start, end);
}
@ -203,6 +217,10 @@ public class TimeOffRequestsListView extends BaseView {
return request.getState().name();
}
private String getUpdated(final TimeOffRequest request) {
return DateTimeFormatter.ofPattern("yyyy/dd/MM hh:mm").format(request.getUpdated().atOffset(ZoneOffset.ofHours(-5)));
}
private ComboBox<Employee> createEmployeeFilter() {
employeeFilter.setClearButtonVisible(true);
employeeFilter.setPlaceholder("Seleccionar ...");
@ -222,7 +240,8 @@ public class TimeOffRequestsListView extends BaseView {
refreshGeneralRequestsGrid(
event.getValue(),
teamFilter.getValue(),
categoryFilter.getValue()
categoryFilter.getValue(),
stateFilter.getValue()
)
);
return employeeFilter;
@ -238,7 +257,8 @@ public class TimeOffRequestsListView extends BaseView {
refreshGeneralRequestsGrid(
employeeFilter.getValue(),
event.getValue(),
categoryFilter.getValue()
categoryFilter.getValue(),
stateFilter.getValue()
)
);
return teamFilter;
@ -252,12 +272,29 @@ public class TimeOffRequestsListView extends BaseView {
refreshGeneralRequestsGrid(
employeeFilter.getValue(),
teamFilter.getValue(),
event.getValue()
event.getValue(),
stateFilter.getValue()
)
);
return categoryFilter;
}
private ComboBox<TimeOffRequestStatus> createStateFilter() {
stateFilter.setPlaceholder("Seleccionar ...");
stateFilter.setClearButtonVisible(true);
stateFilter.setItems(TimeOffRequestStatus.values());
stateFilter.addValueChangeListener(event ->
refreshGeneralRequestsGrid(
employeeFilter.getValue(),
teamFilter.getValue(),
categoryFilter.getValue(),
event.getValue()
)
);
return stateFilter;
}
private void downloadReport() {
StreamResource resource = generateGeneralVacationReport();
getUI().ifPresent(ui -> openDocumentStream(resource, ui));