Merge pull request 'arreglar-funcionalidad' (#84) from arreglar-funcionalidad into main
All checks were successful
Builder / Build-Project (push) Successful in 2m45s

Reviewed-on: #84
This commit is contained in:
alex 2024-11-28 02:52:21 +00:00
commit 116f094eb2
9 changed files with 221 additions and 41 deletions

View File

@ -4,7 +4,7 @@
"type": "module",
"dependencies": {
"@f0rce/ace-widget": "1.0.2",
"@polymer/polymer": "3.5.1",
"@polymer/polymer": "3.5.2",
"@vaadin-component-factory/vcf-pdf-viewer": "2.0.1",
"@vaadin/bundles": "24.5.1",
"@vaadin/common-frontend": "0.0.19",
@ -19,29 +19,30 @@
"@vaadin/vaadin-usage-statistics": "2.1.3",
"construct-style-sheets-polyfill": "3.1.0",
"date-fns": "2.29.3",
"lit": "3.1.4",
"lit": "3.2.1",
"print-js": "1.6.0",
"proj4": "2.12.1",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-router-dom": "6.23.1"
"react-router-dom": "6.26.2"
},
"devDependencies": {
"@babel/preset-react": "7.24.7",
"@rollup/plugin-replace": "5.0.7",
"@rollup/pluginutils": "5.1.0",
"@types/react": "18.3.3",
"@types/react-dom": "18.3.0",
"@vitejs/plugin-react": "4.3.1",
"async": "3.2.5",
"glob": "10.4.1",
"@babel/preset-react": "7.25.7",
"@preact/signals-react-transform": "0.4.0",
"@rollup/plugin-replace": "6.0.1",
"@rollup/pluginutils": "5.1.2",
"@types/react": "18.3.11",
"@types/react-dom": "18.3.1",
"@vitejs/plugin-react": "4.3.3",
"async": "3.2.6",
"glob": "10.4.5",
"rollup-plugin-brotli": "3.1.0",
"rollup-plugin-visualizer": "5.12.0",
"strip-css-comments": "5.0.0",
"transform-ast": "2.4.4",
"typescript": "5.4.5",
"vite": "5.3.3",
"vite-plugin-checker": "0.6.4",
"typescript": "5.6.3",
"vite": "5.4.9",
"vite-plugin-checker": "0.8.0",
"workbox-build": "7.1.1",
"workbox-core": "7.1.0",
"workbox-precaching": "7.1.0"
@ -49,7 +50,7 @@
"vaadin": {
"dependencies": {
"@f0rce/ace-widget": "1.0.2",
"@polymer/polymer": "3.5.1",
"@polymer/polymer": "3.5.2",
"@vaadin-component-factory/vcf-pdf-viewer": "2.0.1",
"@vaadin/bundles": "24.5.1",
"@vaadin/common-frontend": "0.0.19",
@ -64,34 +65,35 @@
"@vaadin/vaadin-usage-statistics": "2.1.3",
"construct-style-sheets-polyfill": "3.1.0",
"date-fns": "2.29.3",
"lit": "3.1.4",
"lit": "3.2.1",
"print-js": "1.6.0",
"proj4": "2.12.1",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-router-dom": "6.23.1"
"react-router-dom": "6.26.2"
},
"devDependencies": {
"@babel/preset-react": "7.24.7",
"@rollup/plugin-replace": "5.0.7",
"@rollup/pluginutils": "5.1.0",
"@types/react": "18.3.3",
"@types/react-dom": "18.3.0",
"@vitejs/plugin-react": "4.3.1",
"async": "3.2.5",
"glob": "10.4.1",
"@babel/preset-react": "7.25.7",
"@preact/signals-react-transform": "0.4.0",
"@rollup/plugin-replace": "6.0.1",
"@rollup/pluginutils": "5.1.2",
"@types/react": "18.3.11",
"@types/react-dom": "18.3.1",
"@vitejs/plugin-react": "4.3.3",
"async": "3.2.6",
"glob": "10.4.5",
"rollup-plugin-brotli": "3.1.0",
"rollup-plugin-visualizer": "5.12.0",
"strip-css-comments": "5.0.0",
"transform-ast": "2.4.4",
"typescript": "5.4.5",
"vite": "5.3.3",
"vite-plugin-checker": "0.6.4",
"typescript": "5.6.3",
"vite": "5.4.9",
"vite-plugin-checker": "0.8.0",
"workbox-build": "7.1.1",
"workbox-core": "7.1.0",
"workbox-precaching": "7.1.0"
},
"hash": "1a0f17d48b329307b5862bc57499307d1b89f7d89260121c2b7189f76957c436"
"hash": "2dc40a4f634ae025081ca2239cba00b14a35fe94ab78ac0a4dd3023d882081d5"
},
"overrides": {
"@vaadin/bundles": "$@vaadin/bundles",

View File

@ -27,6 +27,7 @@ public class Employee extends BaseEntity implements UserDetails {
@NotNull(message = "El apellido no puede estar vacío")
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El apellido solo debe contener letras")
private String lastName;
@MinAge(18)
private LocalDate birthday;
@Pattern(regexp = "^[a-zA-Z ,]+$", message = "La ciudad de nacimiento solo debe contener letras, espacios o comas")
private String birthCity;
@ -101,6 +102,7 @@ public class Employee extends BaseEntity implements UserDetails {
private String bankName;
@Pattern(regexp = "^[0-9]+$", message = "El número de cuenta debe contener solo números")
private String accountNumber;
private String customContractType;
private String gpss;
private String sss;
@ -113,6 +115,10 @@ public class Employee extends BaseEntity implements UserDetails {
@Enumerated(EnumType.STRING)
private Status status;
public void setCustomContractType(final String customContractType) {
this.customContractType = customContractType;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Lists.newArrayList();
@ -180,7 +186,7 @@ public class Employee extends BaseEntity implements UserDetails {
CONTRATO_PLAZO_FIJO,
CONSULTORIA_INTERNA,
CONSULTORIA_EXTERNA,
MIXTO,
CONTRATO_MIXTO,
OTROS
}

View File

@ -0,0 +1,17 @@
package com.primefactorsolutions.model;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;
@Documented
@Constraint(validatedBy = MinAgeValidator.class)
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface MinAge {
String message() default "El empleado debe ser mayor de {value} años";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int value();
}

View File

@ -0,0 +1,24 @@
package com.primefactorsolutions.model;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class MinAgeValidator implements ConstraintValidator<MinAge, LocalDate> {
private int minAge;
@Override
public void initialize(final MinAge constraintAnnotation) {
this.minAge = constraintAnnotation.value();
}
@Override
public boolean isValid(final LocalDate birthday, final ConstraintValidatorContext context) {
if (birthday == null) {
return true;
}
return ChronoUnit.YEARS.between(birthday, LocalDate.now()) >= minAge;
}
}

View File

@ -11,5 +11,6 @@ public interface EmployeeRepository extends JpaRepository<Employee, UUID> {
Optional<Employee> findByUsername(String username);
Optional<Employee> findByPersonalEmail(String personalEmail);
List<Employee> findAllByTeamId(UUID teamId);
//Optional<Employee> findByTeamIdAndLeadManagerTrue(UUID teamId);
List<Employee> findByTeamName(String teamName);
}

View File

@ -55,7 +55,6 @@ public class EmployeeService {
Optional<Employee> leadManager = teamMembers.stream()
.filter(e -> Strings.isNullOrEmpty(e.getLeadManager()))
.findFirst();
return leadManager.map(employee -> employee.getFirstName() + " " + employee.getLastName())
.orElse("No asignado");
}

View File

@ -15,9 +15,7 @@ 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.dialog.Dialog;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.H3;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.component.html.*;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
@ -106,10 +104,11 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
private final VDatePicker dateOfEntry = new VDatePicker("Fecha de Ingreso");
private final VDatePicker dateOfExit = new VDatePicker("Fecha de Retiro");
private final ComboBox<Employee.ContractType> contractType = createContractTypeComboBox();
private final TextField customContractType = createCustomContractTypeField();
private final TextField seniority = createTextField("Antiguedad", 30, false);
private final TextField salaryTotal = createTextField("Salario Total", 10, false);
private final TextField salaryBasic = createTextField("Salario Basico", 10, false);
private final TextField antiguedad = createTextField("Descuento por Antiguedad", 10, false);
private final TextField antiguedad = createTextField("Bono de Antiguedad", 10, false);
private final TextField bonoProfesional = createTextField("Bono Profesional", 30, false);
private final TextField bankName = createTextField("Banco", 30, false);
private final TextField accountNumber = createTextField("Nro. de Cuenta", 30, false);
@ -124,11 +123,12 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
private static final String PHONE_NUMBER_ERROR_MESSAGE = "El teléfono debe contener solo números.";
private final Button saveButton = new Button(SAVE_BUTTON_TEXT, e -> saveEmployee());
private final Button editButton = new Button(EDIT_BUTTON_TEXT, e -> enableEditMode());
private final Button reportButton = new Button("Generar Ficha");
private final Button reportButton = new Button("Generar Ficha de Contratación");
private final Dialog dialog = new Dialog();
private final PdfViewer pdfViewer = new PdfViewer();
private final H2 infoPer = new H2("Información Personal");
private final H3 infoGenr = new H3("Información General");
private final H5 imagenSub = new H5("Insertar una imagen .jpg:");
private final H3 contEmerg = new H3("Contacto de Emergencia");
private final H2 infProf = new H2("Información Profesional");
private final H3 titulos = new H3("Titulos Profesionales y Estudios Realizados");
@ -178,7 +178,17 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
editButton.setVisible(true);
reportButton.setVisible(true);
birthday.addValueChangeListener(event -> calculateAge());
birthday.setMax(java.time.LocalDate.now().minusYears(18));
birthday.setMin(LocalDate.now().minusYears(100));
birthday.setMax(LocalDate.now().minusYears(18));
birthday.addValueChangeListener(event -> {
LocalDate selectedDate = event.getValue();
if (selectedDate != null && ChronoUnit.YEARS.between(selectedDate, LocalDate.now()) < 18) {
birthday.setInvalid(true);
birthday.setErrorMessage("El empleado debe ser mayor o tener 18 años");
} else {
birthday.setInvalid(false);
}
});
salaryTotal.addValueChangeListener(event -> calculateSalaryTotal());
dateOfEntry.addValueChangeListener(event -> calculateSeniority());
dateOfExit.addValueChangeListener(event -> {
@ -373,10 +383,30 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
comboBox.setItemLabelGenerator(Employee.ContractType::name);
comboBox.setRequiredIndicatorVisible(true);
comboBox.setWidth("300px");
comboBox.setMinWidth("200px");
comboBox.addValueChangeListener(event -> handleContractTypeChange(event.getValue()));
return comboBox;
}
private TextField createCustomContractTypeField() {
TextField textField = new TextField("Especificar Tipo de Contrato");
textField.setPlaceholder("Ingrese el tipo de contrato...");
textField.setVisible(false);
textField.setWidth("300px");
return textField;
}
private void handleContractTypeChange(final Employee.ContractType selectedType) {
if (selectedType == Employee.ContractType.OTROS) {
customContractType.setVisible(true);
customContractType.setRequired(true);
} else {
customContractType.setVisible(false);
customContractType.clear();
customContractType.setRequired(false);
}
}
private VerticalLayout createContentLayout() {
VerticalLayout contentLayout = new VerticalLayout();
contentLayout.setWidth("100%");
@ -454,6 +484,12 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
employee.setBonoProfesional(bonoProfesional.getValue());
employee.setAntiguedad(antiguedad.getValue());
employee.setSalarytotal((salaryTotal.getValue()));
employee.setContractType(contractType.getValue());
if (contractType.getValue() == Employee.ContractType.OTROS) {
employee.setCustomContractType(customContractType.getValue());
} else {
employee.setCustomContractType(null);
}
employeeService.createOrUpdate(employee);
Notification.show(NOTIFICATION_SAVE_SUCCESS);
getUI().ifPresent(ui -> ui.navigate(EmployeesListView.class));
@ -478,7 +514,7 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
editButton.setVisible(false);
setFieldsEditable();
upload.setVisible(true);
salaryTotal.setValue(String.valueOf(true));
salaryTotal.setValue(String.valueOf(0.0));
} else {
UUID employeeId = UUID.fromString(s);
var employee = employeeService.getEmployee(employeeId);
@ -565,6 +601,7 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
dateOfEntry.setReadOnly(true);
dateOfExit.setReadOnly(true);
contractType.setReadOnly(true);
customContractType.setReadOnly(true);
seniority.setReadOnly(true);
salaryTotal.setReadOnly(true);
salaryBasic.setReadOnly(true);
@ -627,6 +664,7 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
dateOfEntry.setReadOnly(false);
dateOfExit.setReadOnly(false);
contractType.setReadOnly(false);
customContractType.setReadOnly(false);
seniority.setReadOnly(false);
salaryTotal.setReadOnly(false);
salaryBasic.setReadOnly(false);
@ -646,6 +684,7 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
username,
infoPer,
infoGenr,
imagenSub,
upload, profileImagePreview,
firstName, lastName,
gender, status,
@ -661,7 +700,7 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
idioma, language1, language1Level, language2, language2Level,
infoAdm,
cod, position, team, leadManager,
infoCont, dateOfEntry, dateOfExit, contractType, seniority,
infoCont, dateOfEntry, dateOfExit, seniority, contractType, customContractType,
salaryBasic, bonoProfesional, antiguedad, salaryTotal,
datBanc, bankName, accountNumber,
datGest, gpss, sss, beneficiarie1, beneficiarie2,

View File

@ -3,15 +3,22 @@ package com.primefactorsolutions.views;
import com.primefactorsolutions.model.Employee;
import com.primefactorsolutions.service.EmployeeService;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Anchor;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.StreamResource;
import com.vaadin.flow.spring.annotation.SpringComponent;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.vaadin.firitin.components.grid.PagingGrid;
import com.vaadin.flow.component.grid.GridSortOrder;
import com.vaadin.flow.data.provider.SortDirection;
import jakarta.annotation.security.PermitAll;
import org.springframework.context.annotation.Scope;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
@SpringComponent
@ -33,9 +40,92 @@ public class EmployeesListView extends BaseView {
private void setupView() {
configureTable();
getCurrentPageLayout().add(createAddEmployeeButton());
getCurrentPageLayout().add(createExportButton());
getCurrentPageLayout().add(table);
}
private Button createExportButton() {
StreamResource excelResource = new StreamResource("employees.xlsx", this::generateExcel);
Anchor downloadLink = new Anchor(excelResource, "Export Employees");
downloadLink.getElement().setAttribute("download", true); // Forzar descarga
return new Button("Exportar como Excel", e -> getCurrentPageLayout().add(downloadLink));
}
private ByteArrayInputStream generateExcel() {
List<Employee> employees = employeeService.findAllEmployees();
try (Workbook workbook = new XSSFWorkbook(); ByteArrayOutputStream out = new ByteArrayOutputStream()) {
Sheet sheet = workbook.createSheet("Employees");
Row headerRow = sheet.createRow(0);
String[] headers = {
"ID", "Nombres", "Apellidos", "Status", "Genero", "Fecha de Nacimiento", "Edad",
"Ciudad y Pais de Nacimiento", "Dirección de Residencia", "Departamento y Provincia de Residencia",
"Marital Status",
"Numero de Hijos", "CI", "Expedido en", "Teléfono", "E-mail",
"Teléfono Laboral", "E-mail Laboral", "Codigo de Empleado", "Cargo",
"Equipo", "Lead/Manager", "Fecha de Ingreso", "Fecha de Retiro", "Tipo de Contrato",
"Otro Tipo de Contrato", "Antiguedad", "Salario Total"
};
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
CellStyle style = workbook.createCellStyle();
Font font = workbook.createFont();
font.setBold(true);
style.setFont(font);
cell.setCellStyle(style);
}
int rowIndex = 1;
for (Employee employee : employees) {
Row row = sheet.createRow(rowIndex++);
row.createCell(0).setCellValue(employee.getId().toString());
row.createCell(1).setCellValue(employee.getFirstName());
row.createCell(2).setCellValue(employee.getLastName());
row.createCell(3).setCellValue(employee.getStatus().toString());
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(7).setCellValue(employee.getBirthCity() != null ? employee.getBirthCity() : "");
row.createCell(8).setCellValue(employee.getResidenceAddress() != null ? employee
.getResidenceAddress() : "");
row.createCell(9).setCellValue(employee.getLocalAddress() != null ? employee.getLocalAddress() : "");
row.createCell(10).setCellValue(employee.getMaritalStatus() != null ? employee.getMaritalStatus()
.toString() : "");
row.createCell(11).setCellValue(employee.getNumberOfChildren() != null ? employee
.getNumberOfChildren().toString() : "");
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(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() : "");
row.createCell(21).setCellValue(employee.getLeadManager() != null ? employee.getLeadManager() : "");
row.createCell(22).setCellValue(employee.getDateOfEntry() != null ? employee.getDateOfEntry()
.toString() : "");
row.createCell(23).setCellValue(employee.getDateOfExit() != null ? employee.getDateOfExit()
.toString() : "");
row.createCell(24).setCellValue(employee.getContractType() != null ? employee.getContractType()
.toString() : "");
row.createCell(25).setCellValue(employee.getCustomContractType() != null ? employee
.getCustomContractType() : "");
row.createCell(26).setCellValue(employee.getSeniority() != null ? employee.getSeniority() : "");
row.createCell(27).setCellValue(employee.getSalarytotal() != null ? employee.getSalarytotal() : "");
}
workbook.write(out);
return new ByteArrayInputStream(out.toByteArray());
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private void configureTable() {
table.setColumns("firstName", "lastName", "status");
addEditButtonColumn("View", this::navigateToEmployeeView);
@ -54,6 +144,7 @@ public class EmployeesListView extends BaseView {
}
private Button createAddEmployeeButton() {
return createButton("Add Employee", this::navigateToAddEmployeeView);
}
@ -66,6 +157,7 @@ public class EmployeesListView extends BaseView {
}
private void navigateToAddEmployeeView() {
getUI().ifPresent(ui -> ui.navigate(EmployeeView.class, "new"));
}

View File

@ -133,7 +133,7 @@ public class HoursWorkedView extends BeanValidationForm<HoursWorked> implements
}
protected Button createCloseButton() {
Button closeButton = new Button("Cerrar");
Button closeButton = new Button("Cancelar");
closeButton.addClickListener(event -> closeForm());
return closeButton;
}