From 69e378a623cda363ae0fae9cdd71fa1791eea2ce Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Wed, 20 Nov 2024 09:15:17 -0400 Subject: [PATCH 01/10] Remover estados de solicitud (COMPLETADO, CANCELADO, EN_REVISION) --- .../com/primefactorsolutions/model/TimeOffRequestStatus.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/primefactorsolutions/model/TimeOffRequestStatus.java b/src/main/java/com/primefactorsolutions/model/TimeOffRequestStatus.java index 6f0a2d0..3c8d1e2 100644 --- a/src/main/java/com/primefactorsolutions/model/TimeOffRequestStatus.java +++ b/src/main/java/com/primefactorsolutions/model/TimeOffRequestStatus.java @@ -10,7 +10,4 @@ public enum TimeOffRequestStatus { VENCIDO, SOLICITADO, - EN_REVISION, - COMPLETADO, - CANCELADO, } From b55d919439723dc5b600e0ea4a693f8b4191b5f0 Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Wed, 20 Nov 2024 09:55:58 -0400 Subject: [PATCH 02/10] Excluir sabado y domingo cuando se solicita una vacacion --- package.json | 60 ++++++++++--------- .../views/RequestRegisterView.java | 43 +++++++++++-- .../views/RequestsListView.java | 4 +- 3 files changed, 70 insertions(+), 37 deletions(-) diff --git a/package.json b/package.json index 3395e11..209a580 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java b/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java index 4d56f10..af03693 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java @@ -19,6 +19,7 @@ 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; @@ -91,8 +92,20 @@ public class RequestRegisterView extends VerticalLayout { onCategoryChange(event.getValue()); handleCategorySelection(event.getValue()); }); - startDatePicker.addValueChangeListener(event -> updateDatePickerMinValues()); - endDatePicker.addValueChangeListener(event -> calculateDays()); + 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 -> { + LocalDate selectedDate = event.getValue(); + if (selectedDate != null && (selectedDate.getDayOfWeek().getValue() == 6 || selectedDate.getDayOfWeek().getValue() == 7)) { + startDatePicker.setValue(selectedDate.minusDays(1)); + } + calculateDays(); + }); } private void configureBinder() { @@ -167,7 +180,7 @@ public class RequestRegisterView extends VerticalLayout { private void onCategoryChange(final TimeOffRequestType selectedCategory) { if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ACTUAL - || selectedCategory == TimeOffRequestType.VACACION_GESTION_ANTERIOR) { + || selectedCategory == TimeOffRequestType.VACACION_GESTION_ANTERIOR) { startDatePicker.setEnabled(true); endDatePicker.setEnabled(true); } else { @@ -199,8 +212,8 @@ public class RequestRegisterView extends VerticalLayout { && latestRequest.getDaysBalance() > 0) || latestRequest.getState() == TimeOffRequestStatus.RECHAZADO || (latestRequest.getState() == TimeOffRequestStatus.TOMADO - && latestRequest.getDaysBalance() == 0 - && latestRequest.getExpiration().isBefore(LocalDate.now())); + && latestRequest.getDaysBalance() == 0 + && latestRequest.getExpiration().isBefore(LocalDate.now())); } else { return (latestRequest.getState() == TimeOffRequestStatus.TOMADO && latestRequest.getExpiration().isBefore(LocalDate.now())) @@ -375,6 +388,13 @@ public class RequestRegisterView extends VerticalLayout { 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); @@ -391,8 +411,19 @@ public class RequestRegisterView extends VerticalLayout { return startDate != null && endDate != null; } + private long countWorkDaysBetween(LocalDate startDate, 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 java.time.temporal.ChronoUnit.DAYS.between(startDate, endDate) + 1; + 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) { diff --git a/src/main/java/com/primefactorsolutions/views/RequestsListView.java b/src/main/java/com/primefactorsolutions/views/RequestsListView.java index 12b1715..503092a 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestsListView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestsListView.java @@ -159,7 +159,7 @@ public class RequestsListView extends BaseView { private String getEmployeeStatus(final Employee employee) { Optional activeRequest = requestService .findByEmployeeAndState(employee.getId(), TimeOffRequestStatus.EN_USO); - return activeRequest.isPresent() ? "EN_DESCANSO" : "ACTIVO"; + return activeRequest.isPresent() ? "EN_DESCANSO" : "EN_FUNCIONES"; } private String getGeneralTotal(final Employee employee) { @@ -388,7 +388,7 @@ public class RequestsListView extends BaseView { private enum Status { TODOS, EN_DESCANSO, - ACTIVO + EN_FUNCIONES } private Employee createAllEmployeesOption() { From 5287f4087882ea8a09bc613758e5096f047ba96e Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Wed, 20 Nov 2024 10:07:53 -0400 Subject: [PATCH 03/10] =?UTF-8?q?Agregar=20condicion=20para=20tomar=20dia?= =?UTF-8?q?=20libre=20por=20cumplea=C3=B1os?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/primefactorsolutions/views/RequestRegisterView.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java b/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java index af03693..eb24c27 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java @@ -191,6 +191,10 @@ public class RequestRegisterView extends VerticalLayout { private boolean isCategoryAvailable(final List employeeRequests, final TimeOffRequestType category) { + if (category == TimeOffRequestType.CUMPLEAÑOS && employee.getBirthday() == null) { + return false; + } + List requestsByCategory = employeeRequests.stream() .filter(request -> request.getCategory() == category) .toList(); From d18f591df0b528fed3b77ffe796de07085cec464 Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Wed, 20 Nov 2024 10:33:11 -0400 Subject: [PATCH 04/10] Limitar a 10 dias maximo para tomar vacaciones por gestion --- .../views/RequestRegisterView.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java b/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java index eb24c27..e32feba 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java @@ -100,9 +100,12 @@ public class RequestRegisterView extends VerticalLayout { 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)) { - startDatePicker.setValue(selectedDate.minusDays(1)); + endDatePicker.setValue(selectedDate.minusDays(1)); } calculateDays(); }); @@ -408,6 +411,12 @@ public class RequestRegisterView extends VerticalLayout { if (balanceDays < 0.0) { clearFields(); } + + if (daysToBeTakenField.getValue() > 10 + && (categoryComboBox.getValue() == TimeOffRequestType.VACACION_GESTION_ANTERIOR + || categoryComboBox.getValue() == TimeOffRequestType.VACACION_GESTION_ACTUAL)) { + clearFields(); + } } } From 17bd54a3f4bb4bad157aaa540ab9a327a2f2d763 Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Thu, 21 Nov 2024 18:22:46 -0400 Subject: [PATCH 05/10] No descontar dias si la solicitud de vacacion no fue aprobada. --- .../com/primefactorsolutions/views/RequestEmployeeView.java | 4 ++-- .../java/com/primefactorsolutions/views/RequestsListView.java | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java b/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java index 5e8c437..dabdd23 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java @@ -246,7 +246,7 @@ public class RequestEmployeeView extends Div implements HasUrlParameter private double calculateHolidayUtilizedDays(final int year) { return requests.stream() .filter(this::verificationIsHoliday) - .filter(req -> req.getState() == TimeOffRequestStatus.TOMADO) + .filter(req -> req.getState() == TimeOffRequestStatus.TOMADO || req.getState() == TimeOffRequestStatus.APROBADO) .filter(req -> getStartDateYear(req) == year) .mapToDouble(TimeOffRequest::getDaysToBeTake) .sum(); @@ -255,7 +255,7 @@ public class RequestEmployeeView extends Div implements HasUrlParameter private double calculatePersonalDaysUtilized(final boolean isMale, final int year) { return requests.stream() .filter(req -> !verificationIsHoliday(req)) - .filter(req -> req.getState() == TimeOffRequestStatus.TOMADO) + .filter(req -> req.getState() == TimeOffRequestStatus.TOMADO || req.getState() == TimeOffRequestStatus.APROBADO) .filter(req -> !getStandardExclusions().contains(req.getCategory())) .filter(req -> !(isMale && getMaleSpecificExclusions().contains(req.getCategory()))) .filter(req -> !req.getCategory().name().startsWith("VACACION")) diff --git a/src/main/java/com/primefactorsolutions/views/RequestsListView.java b/src/main/java/com/primefactorsolutions/views/RequestsListView.java index 503092a..c6c4704 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestsListView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestsListView.java @@ -217,6 +217,7 @@ public class RequestsListView extends BaseView { 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) From bf3fadbae37ef4523cb03275dbc1ed200fac6703 Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Thu, 21 Nov 2024 18:52:08 -0400 Subject: [PATCH 06/10] No permitir solicitudes de vacaciones con anticimacion de 3 meses maximo a 15 dias minimo. --- .../views/RequestRegisterView.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java b/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java index e32feba..9b0c562 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java @@ -500,9 +500,14 @@ public class RequestRegisterView extends VerticalLayout { handleExistingRequests(request); } - requestService.saveTimeOffRequest(request); - Notification.show("Solicitud guardada correctamente."); - closeForm(); + 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() { From e72bca0d394d6224f9205ab46be01eca23fdd3a1 Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Fri, 22 Nov 2024 23:42:18 -0400 Subject: [PATCH 07/10] Traducir modulo documentos --- .../model/DocumentType.java | 61 +++++++++---------- .../views/DocumentView.java | 24 ++++---- .../views/DocumentsListView.java | 21 ++++--- .../views/RequestEmployeeView.java | 6 +- .../views/RequestRegisterView.java | 12 ++-- .../views/RequestsListView.java | 3 +- 6 files changed, 68 insertions(+), 59 deletions(-) diff --git a/src/main/java/com/primefactorsolutions/model/DocumentType.java b/src/main/java/com/primefactorsolutions/model/DocumentType.java index 96c8ce3..10251fc 100644 --- a/src/main/java/com/primefactorsolutions/model/DocumentType.java +++ b/src/main/java/com/primefactorsolutions/model/DocumentType.java @@ -1,36 +1,35 @@ package com.primefactorsolutions.model; public enum DocumentType { - All, - ID_CARD, - PAY_STUB, - PAY_SLIPS, - EMPLOYMENT_CONTRACT, - WORK_CERTIFICATES, + TODOS, + CARNET_DE_IDENTIDAD, + RECIBOS_DE_PAGO, + CONTRATO_DE_TRABAJO, + CERTIFICADO_DE_TRABAJO, NDA, - MEMORANDUMS, - CONTRACT_APPROVAL_MTEPS, - BACKGROUND_CHECK_CERTIFICATE, - PRE_EMPLOYMENT_EVALUATION, - INSURANCE_REGISTRATION_FORM, - INSURANCE_CANCELLATION_FORM, - PROFESSIONAL_DEGREE_1, - PROFESSIONAL_CERTIFICATE_1, - PROFESSIONAL_DEGREE_2, - PROFESSIONAL_CERTIFICATE_2, - PROFESSIONAL_DEGREE_3, - PROFESSIONAL_CERTIFICATE_3, - GENERAL_LABOR_REGULATIONS, - REMOTE_WORK_GUIDELINES, - SAFETY_REGULATIONS, - HUMAN_RESOURCES_GUIDELINES, - ADMINISTRATION_FUNCTIONS_MANUAL, - ENGINEERING_FUNCTIONS_MANUAL, - GENERAL_LABOR_LAW, - SUPREME_DECREE, - REGULATORY_RESOLUTION, - COMPLEMENTARY_REGULATION, - HEALTH_SAFETY_LAW, - INTERNSHIP_RULES, - OTHER + MEMORÁNDUMS, + APROBACIÓN_DE_CONTRATO_MTEPS, + CERTIFICADO_DE_ANTECEDENTES, + EVALUACIÓN_PRE_EMPLEO, + FORMULARIO_DE_INSCRIPCIÓN_AL_SEGURO, + FORMULARIO_DE_CANCELACIÓN_DE_SEGURO, + TÍTULO_PROFESIONAL_1, + CERTIFICACIÓN_PROFESIONAL_1, + TÍTULO_PROFESIONAL_2, + CERTIFICACIÓN_PROFECIONAL_2, + TÍTULO_PROFESIONAL_3, + CERTIFICACIÓN_PROFECIONAL_3, + NORMATIVA_LABORAL_GENERAL, + NORMAS_DE_TRABAJO_REMOTO, + NORMAS_DE_SEGURIDAD, + INSTRUCTIVOS_DE_RECURSOS_HUMANOS, + MANUAL_DE_FUNCIONES_DE_ADMINISTRACIÓN, + MANUAL_DE_FUNCIONES_DE_INGENIERÍA, + LEY_GENERAL_DEL_TRABAJO, + DECRETOS_SUPREMOS, + RESOLUCIONES_O_DISPOSICIONES_REGLAMENTARIAS, + NORMATIVA_COMPLEMENTARIA, + LEY_GRAL_DE_HIGIENE_SALUD_SEGURIDAD_OCUPACIONAL_Y_BIENESTAR, + NORMATIVA_REGLAMENTARIA_PARA_DESARROLLO_DE_PASANTÍAS, + OTROS } diff --git a/src/main/java/com/primefactorsolutions/views/DocumentView.java b/src/main/java/com/primefactorsolutions/views/DocumentView.java index 49c44a3..b1bbad9 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentView.java @@ -39,9 +39,9 @@ import java.io.InputStream; @PageTitle("Document") @Route(value = "/documents/:documentId?/:action?", layout = MainLayout.class) public class DocumentView extends BeanValidationForm implements HasUrlParameter { - private final TextField fileName = new TextField("Document Name"); - private final ComboBox documentType = new ComboBox<>("Document Type"); - private final ComboBox employeeComboBox = new ComboBox<>("Employee"); + private final TextField fileName = new TextField("Nombre del documento"); + private final ComboBox documentType = new ComboBox<>("Tipo de documento"); + private final ComboBox employeeComboBox = new ComboBox<>("Empleado"); private final MemoryBuffer buffer = new MemoryBuffer(); private final Upload uploadButton = new Upload(buffer); private final DocumentService documentService; @@ -68,19 +68,19 @@ public class DocumentView extends BeanValidationForm implements HasUrl } protected Button createSaveButton() { - saveButton = new Button("Save"); + saveButton = new Button("Guardar"); saveButton.addClickListener(event -> saveDocument()); return saveButton; } protected Button createCloseButton() { - Button closeButton = new Button("Close"); + Button closeButton = new Button("Salir"); closeButton.addClickListener(event -> closeForm()); return closeButton; } protected Button createViewDocumentButton() { - viewDocumentButton = new Button("View Document"); + viewDocumentButton = new Button("Ver documento"); viewDocumentButton.setEnabled(false); viewDocumentButton.addClickListener(event -> viewDocument()); return viewDocumentButton; @@ -130,7 +130,7 @@ public class DocumentView extends BeanValidationForm implements HasUrl ui.getPage().open(registration.getResourceUri().toString()); }); } catch (IOException e) { - Notification.show("Error reading file."); + Notification.show("Error al leer el archivo."); } } @@ -148,10 +148,10 @@ public class DocumentView extends BeanValidationForm implements HasUrl setDocumentCreator(document); documentService.saveDocument(document); - Notification.show("File saved successfully."); + Notification.show("Archivo guardado correctamente."); clearForm(); } else { - Notification.show("Save failed: Please complete all fields and upload a file."); + Notification.show("Error al guardar: Por favor, complete todos los campos y cargue un archivo."); } } @@ -179,7 +179,7 @@ public class DocumentView extends BeanValidationForm implements HasUrl try { return buffer.getInputStream().readAllBytes(); } catch (IOException e) { - Notification.show("Error reading file data."); + Notification.show("Error al leer los datos del archivo."); return new byte[0]; } } @@ -220,13 +220,13 @@ public class DocumentView extends BeanValidationForm implements HasUrl uploadButton.setAcceptedFileTypes(".pdf"); uploadButton.addSucceededListener(event -> { fileUploaded = true; - Notification.show("File uploaded successfully."); + Notification.show("Archivo cargado correctamente."); viewDocumentButton.setEnabled(true); updateSaveButtonState(); }); uploadButton.getElement().addEventListener("file-remove", event -> { fileUploaded = false; - Notification.show("File removed."); + Notification.show("Archivo eliminado."); viewDocumentButton.setEnabled(false); updateSaveButtonState(); }); diff --git a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java index 39803d0..b6cbb47 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java @@ -47,7 +47,7 @@ public class DocumentsListView extends BaseView { } private void initializeView() { - getCurrentPageLayout().add(createActionButton("Add Document", this::navigateToAddDocumentView)); + getCurrentPageLayout().add(createActionButton("Añadir documento", this::navigateToAddDocumentView)); final HorizontalLayout hl = new HorizontalLayout(); hl.add(createDocumentTypeFilter()); @@ -61,7 +61,10 @@ public class DocumentsListView extends BaseView { private void configureDocumentGrid() { documentGrid.setColumns("fileName", "documentType", "creator"); - documentGrid.addComponentColumn(this::createEmployeeSpan).setHeader("Employee"); + documentGrid.getColumnByKey("fileName").setHeader("Nombre archivo"); + documentGrid.getColumnByKey("documentType").setHeader("Tipo"); + documentGrid.getColumnByKey("creator").setHeader("Creador"); + documentGrid.addComponentColumn(this::createEmployeeSpan).setHeader("Empleado"); addActionColumns(); configurePagination(); } @@ -73,9 +76,9 @@ public class DocumentsListView extends BaseView { } private void addActionColumns() { - addDocumentActionColumn("View", this::navigateToDocumentView); - addDocumentActionColumn("Edit", this::navigateToEditDocumentView); - addDocumentActionColumn("Download", this::downloadDocument); + addDocumentActionColumn("Ver", this::navigateToDocumentView); + addDocumentActionColumn("Editar", this::navigateToEditDocumentView); + addDocumentActionColumn("Descargar", this::downloadDocument); } private void addDocumentActionColumn(final String label, final DocumentActionHandler handler) { @@ -89,7 +92,7 @@ public class DocumentsListView extends BaseView { } private ComboBox createDocumentTypeFilter() { - documentTypeFilter = new ComboBox<>("Document Type"); + documentTypeFilter = new ComboBox<>("Tipo de documento"); documentTypeFilter.setItems(DocumentType.values()); documentTypeFilter.setValue(DocumentType.values()[0]); documentTypeFilter.addValueChangeListener(event -> { @@ -99,7 +102,7 @@ public class DocumentsListView extends BaseView { } private ComboBox createEmployeeFilter() { - employeeFilter = new ComboBox<>("Employee"); + employeeFilter = new ComboBox<>("Empleado"); List employees = employeeService.findAllEmployees(); employees.addFirst(createAllEmployeesOption()); employeeFilter.setItems(employees); @@ -113,12 +116,12 @@ public class DocumentsListView extends BaseView { private Employee createAllEmployeesOption() { Employee allEmployeesOption = new Employee(); - allEmployeesOption.setFirstName("All"); + allEmployeesOption.setFirstName("TODOS"); return allEmployeesOption; } private String getEmployeeLabel(final Employee employee) { - return employee.getFirstName().equals("All") ? "All" : employee.getFirstName() + " " + employee.getLastName(); + return employee.getFirstName().equals("TODOS") ? "TODOS" : employee.getFirstName() + " " + employee.getLastName(); } private void navigateToEditDocumentView(final Document document) { diff --git a/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java b/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java index dabdd23..d3cdd16 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java @@ -246,7 +246,8 @@ public class RequestEmployeeView extends Div implements HasUrlParameter private double calculateHolidayUtilizedDays(final int year) { return requests.stream() .filter(this::verificationIsHoliday) - .filter(req -> req.getState() == TimeOffRequestStatus.TOMADO || req.getState() == TimeOffRequestStatus.APROBADO) + .filter(req -> req.getState() == TimeOffRequestStatus.TOMADO + || req.getState() == TimeOffRequestStatus.APROBADO) .filter(req -> getStartDateYear(req) == year) .mapToDouble(TimeOffRequest::getDaysToBeTake) .sum(); @@ -255,7 +256,8 @@ public class RequestEmployeeView extends Div implements HasUrlParameter private double calculatePersonalDaysUtilized(final boolean isMale, final int year) { return requests.stream() .filter(req -> !verificationIsHoliday(req)) - .filter(req -> req.getState() == TimeOffRequestStatus.TOMADO || req.getState() == TimeOffRequestStatus.APROBADO) + .filter(req -> req.getState() == TimeOffRequestStatus.TOMADO + || req.getState() == TimeOffRequestStatus.APROBADO) .filter(req -> !getStandardExclusions().contains(req.getCategory())) .filter(req -> !(isMale && getMaleSpecificExclusions().contains(req.getCategory()))) .filter(req -> !req.getCategory().name().startsWith("VACACION")) diff --git a/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java b/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java index 9b0c562..4f5ae22 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestRegisterView.java @@ -94,7 +94,8 @@ public class RequestRegisterView extends VerticalLayout { }); startDatePicker.addValueChangeListener(event -> { LocalDate selectedDate = event.getValue(); - if (selectedDate != null && (selectedDate.getDayOfWeek().getValue() == 6 || selectedDate.getDayOfWeek().getValue() == 7)) { + if (selectedDate != null && (selectedDate.getDayOfWeek().getValue() == 6 + || selectedDate.getDayOfWeek().getValue() == 7)) { startDatePicker.setValue(selectedDate.minusDays(1)); } updateDatePickerMinValues(); @@ -104,7 +105,8 @@ public class RequestRegisterView extends VerticalLayout { endDatePicker.setMin(startDatePicker.getValue()); } LocalDate selectedDate = event.getValue(); - if (selectedDate != null && (selectedDate.getDayOfWeek().getValue() == 6 || selectedDate.getDayOfWeek().getValue() == 7)) { + if (selectedDate != null && (selectedDate.getDayOfWeek().getValue() == 6 + || selectedDate.getDayOfWeek().getValue() == 7)) { endDatePicker.setValue(selectedDate.minusDays(1)); } calculateDays(); @@ -424,7 +426,7 @@ public class RequestRegisterView extends VerticalLayout { return startDate != null && endDate != null; } - private long countWorkDaysBetween(LocalDate startDate, LocalDate endDate) { + 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(); @@ -506,7 +508,9 @@ public class RequestRegisterView extends VerticalLayout { 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."); + Notification.show( + "La fecha de inicio debe encontrarse dentro del rango de 15 días a 3 meses de anticipación." + ); } } diff --git a/src/main/java/com/primefactorsolutions/views/RequestsListView.java b/src/main/java/com/primefactorsolutions/views/RequestsListView.java index c6c4704..ffacc1e 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestsListView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestsListView.java @@ -217,7 +217,8 @@ public class RequestsListView extends BaseView { int currentYear = LocalDate.now().getYear(); return employeeRequests.stream() .filter(Objects::nonNull) - .filter(request -> request.getState() == TimeOffRequestStatus.APROBADO || request.getState() == TimeOffRequestStatus.TOMADO) + .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) From ebb9bc888b77c17185df56ca9994031713a42d77 Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Sat, 23 Nov 2024 13:42:50 -0400 Subject: [PATCH 08/10] Descontar a cero las vacaciones cuando llegue la fecha de salida --- .../views/DocumentsListView.java | 3 +- .../views/RequestEmployeeView.java | 110 +++++++++++++----- .../views/RequestsListView.java | 7 ++ 3 files changed, 92 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java index b6cbb47..6e247fb 100644 --- a/src/main/java/com/primefactorsolutions/views/DocumentsListView.java +++ b/src/main/java/com/primefactorsolutions/views/DocumentsListView.java @@ -121,7 +121,8 @@ public class DocumentsListView extends BaseView { } private String getEmployeeLabel(final Employee employee) { - return employee.getFirstName().equals("TODOS") ? "TODOS" : employee.getFirstName() + " " + employee.getLastName(); + return employee.getFirstName().equals("TODOS") + ? "TODOS" : employee.getFirstName() + " " + employee.getLastName(); } private void navigateToEditDocumentView(final Document document) { diff --git a/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java b/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java index d3cdd16..d97cbcd 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java @@ -130,43 +130,47 @@ public class RequestEmployeeView extends Div implements HasUrlParameter Employee employee = employeeService.getEmployee(employeeId); boolean isMale = employee.getGender() == Employee.Gender.MALE; int currentYear = LocalDate.now().getYear(); + LocalDate currentDate = LocalDate.now(); List vacations = vacationService.findVacations(); - double healthLicence = 2; - List healthRequests = requestService - .findByEmployeeAndCategory(employeeId, TimeOffRequestType.PERMISOS_DE_SALUD); - if (healthRequests != null && !healthRequests.isEmpty()) { - healthLicence = healthRequests.getLast().getDaysBalance(); - } + double healthLicence = getHealthLicence(employeeId); double totalFixedAndMovableHolidays = calculateHolidayDays(vacations); double totalPersonalDays = calculatePersonalDays(vacations, isMale); List vacationDays = calculateVacationDays(employee); - double utilizedVacationCurrentDays = vacationDays.get(1); - List vacationCurrentRequests = requestService - .findByEmployeeAndCategory(employeeId, 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 vacationPreviousRequests = requestService - .findByEmployeeAndCategory(employeeId, TimeOffRequestType.VACACION_GESTION_ANTERIOR); - if (vacationPreviousRequests != null && !vacationPreviousRequests.isEmpty()) { - utilizedVacationPreviousDays = vacationPreviousRequests.getLast().getDaysBalance(); - } - double totalVacationPreviousDays = vacationDays.getFirst() - - (vacationDays.getFirst() - utilizedVacationPreviousDays); + double totalVacationCurrentDays = calculateUtilizedVacationDays( + vacationDays.get(1), + TimeOffRequestType.VACACION_GESTION_ACTUAL + ); + double totalVacationPreviousDays = calculateUtilizedVacationDays( + vacationDays.get(0), + TimeOffRequestType.VACACION_GESTION_ANTERIOR + ); double utilizedFixedAndMovableHolidays = calculateHolidayUtilizedDays(currentYear); double utilizedPersonalDays = calculatePersonalDaysUtilized(isMale, currentYear); - double remainingHolidayDays = totalFixedAndMovableHolidays - utilizedFixedAndMovableHolidays; - double remainingPersonalDays = (totalPersonalDays - utilizedPersonalDays) + healthLicence; - double remainingVacationDays = totalVacationCurrentDays + totalVacationPreviousDays; + double remainingHolidayDays = calculateRemainingHolidayDays( + totalFixedAndMovableHolidays, + utilizedFixedAndMovableHolidays, + employee.getDateOfExit(), + currentDate + ); + double remainingPersonalDays = calculateRemainingPersonalDays( + totalPersonalDays, + utilizedPersonalDays, + healthLicence, + employee.getDateOfExit(), + currentDate + ); + double remainingVacationDays = calculateRemainingVacationDays( + totalVacationCurrentDays, + totalVacationPreviousDays, + employee.getDateOfExit(), + currentDate + ); double totalAvailableDays = remainingHolidayDays + remainingPersonalDays + remainingVacationDays; @@ -178,6 +182,51 @@ public class RequestEmployeeView extends Div implements HasUrlParameter ); } + private double getHealthLicence(final UUID employeeId) { + List healthRequests = requestService + .findByEmployeeAndCategory(employeeId, TimeOffRequestType.PERMISOS_DE_SALUD); + return healthRequests != null && !healthRequests.isEmpty() ? healthRequests.getLast().getDaysBalance() : 2; + } + + private double calculateUtilizedVacationDays(final double vacationDays, final TimeOffRequestType requestType) { + List vacationRequests = requestService.findByEmployeeAndCategory(employeeId, requestType); + if (vacationRequests != null && !vacationRequests.isEmpty()) { + return vacationRequests.getLast().getDaysBalance(); + } + return vacationDays; + } + + private double calculateRemainingVacationDays(final double totalVacationCurrentDays, + final double totalVacationPreviousDays, + final LocalDate exitDate, + final LocalDate currentDate) { + if (exitDate == null || exitDate.isAfter(currentDate)) { + return totalVacationCurrentDays + totalVacationPreviousDays; + } + return 0; + } + + private double calculateRemainingHolidayDays(final double totalFixedAndMovableHolidays, + final double utilizedFixedAndMovableHolidays, + final LocalDate exitDate, + final LocalDate currentDate) { + if (exitDate == null || exitDate.isAfter(currentDate)) { + return totalFixedAndMovableHolidays - utilizedFixedAndMovableHolidays; + } + return 0; + } + + private double calculateRemainingPersonalDays(final double totalPersonalDays, + final double utilizedPersonalDays, + final double healthLicence, + final LocalDate exitDate, + final LocalDate currentDate) { + if (exitDate == null || exitDate.isAfter(currentDate)) { + return (totalPersonalDays - utilizedPersonalDays) + healthLicence; + } + return 0; + } + private double calculateHolidayDays(final List vacations) { return vacations.stream() .filter(req -> req.getType() != Vacation.Type.OTHER) @@ -413,13 +462,20 @@ public class RequestEmployeeView extends Div implements HasUrlParameter employeeId = UUID.fromString(parameter); Employee employee = employeeService.getEmployee(employeeId); requests = requestService.findRequestsByEmployeeId(employeeId); - setViewTitle(employee.getFirstName() + " " + employee.getLastName(), employee.getTeam().getName()); + setViewTitle( + employee.getFirstName() + " " + employee.getLastName(), + employee.getTeam().getName(), + employee.getDateOfExit() + ); requestGrid.setItems(requests); initializeView(); } - private void setViewTitle(final String employeeName, final String employeeTeam) { + private void setViewTitle(final String employeeName, final String employeeTeam, final LocalDate dateOfExit) { addComponentAsFirst(new H3("Nombre del empleado: " + employeeName)); addComponentAtIndex(1, new H3("Equipo: " + employeeTeam)); + if (dateOfExit != null) { + addComponentAtIndex(2, new H3("Descontado a cero en fecha " + dateOfExit + " por pago de finiquito.")); + } } } diff --git a/src/main/java/com/primefactorsolutions/views/RequestsListView.java b/src/main/java/com/primefactorsolutions/views/RequestsListView.java index ffacc1e..864e0da 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestsListView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestsListView.java @@ -191,6 +191,13 @@ public class RequestsListView extends BaseView { double totalAvailable = calculateTotalAvailable(vacations, 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); } From 2206bf234267e05d7f142c487b5981ab8621720a Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Sat, 23 Nov 2024 14:55:12 -0400 Subject: [PATCH 09/10] Descargar reporte general de vacaciones en excel. --- Reporte_Vacaciones.xlsx | Bin 0 -> 4181 bytes .../views/RequestsListView.java | 66 +++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 Reporte_Vacaciones.xlsx diff --git a/Reporte_Vacaciones.xlsx b/Reporte_Vacaciones.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..8ce8134d9c64dbcc7b5e2998c2636aa3375c88d2 GIT binary patch literal 4181 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 H0KmThbjG&X literal 0 HcmV?d00001 diff --git a/src/main/java/com/primefactorsolutions/views/RequestsListView.java b/src/main/java/com/primefactorsolutions/views/RequestsListView.java index 864e0da..cb54b03 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestsListView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestsListView.java @@ -5,19 +5,33 @@ import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.TeamService; import com.primefactorsolutions.service.TimeOffRequestService; import com.primefactorsolutions.service.VacationService; +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.dialog.Dialog; +import com.vaadin.flow.component.html.Anchor; +import com.vaadin.flow.component.html.Span; import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; 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 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.DayOfWeek; import java.time.LocalDate; import java.time.Period; +import java.time.temporal.WeekFields; import java.util.*; import java.util.stream.Collectors; @@ -67,7 +81,6 @@ public class RequestsListView extends BaseView { hl.add(createEmployeeFilter()); hl.add(createTeamFilter()); hl.add(createStateFilter()); - getCurrentPageLayout().add(hl); } @@ -95,8 +108,9 @@ public class RequestsListView extends BaseView { Notification.show("Seleccione una solicitud.", 3000, Notification.Position.MIDDLE); } }); + Button downloadButton = new Button("Descargar reporte", event -> downloadReport()); Button closeButton = new Button("Salir", event -> navigateToMainView()); - return new HorizontalLayout(viewButton, closeButton); + return new HorizontalLayout(viewButton, downloadButton, closeButton); } private void refreshGeneralRequestGrid(final Employee employee, @@ -419,4 +433,52 @@ public class RequestsListView extends BaseView { private void navigateToTimeOffRequestView(final UUID idEmployee) { getUI().ifPresent(ui -> ui.navigate("requests/" + idEmployee.toString())); } + + private ByteArrayInputStream generateExcelReport(List employees) { + try (Workbook workbook = new XSSFWorkbook()) { + Sheet sheet = workbook.createSheet("Reporte Horas Trabajadas"); + Row headerRow = sheet.createRow(0); + + String[] headers = {"Nombre", "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 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()); + } } \ No newline at end of file From a6e9407d733ebee4d15eb3b40a7bd6eb8b9ddbdc Mon Sep 17 00:00:00 2001 From: ricardo051199 Date: Sat, 23 Nov 2024 21:16:21 -0400 Subject: [PATCH 10/10] Descargar reporte de vacaciones personal en pdf. --- .../views/RequestEmployeeView.java | 153 +++++++++++++++++- .../views/RequestsListView.java | 13 +- 2 files changed, 155 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java b/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java index d97cbcd..0e27062 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestEmployeeView.java @@ -4,6 +4,7 @@ import com.primefactorsolutions.model.*; import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.TimeOffRequestService; import com.primefactorsolutions.service.VacationService; +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.html.Div; @@ -16,11 +17,21 @@ import com.vaadin.flow.router.BeforeEvent; import com.vaadin.flow.router.HasUrlParameter; 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 jakarta.annotation.security.PermitAll; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageContentStream; +import org.apache.pdfbox.pdmodel.font.PDType1Font; 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.*; @@ -345,9 +356,10 @@ public class RequestEmployeeView extends Div implements HasUrlParameter private HorizontalLayout createActionButtons() { Button viewButton = createButton("Ver", () -> navigateToViewRequest(request)); Button editButton = createButton("Editar", () -> navigateToEditRequest(request)); + Button downloadButton = new Button("Descargar reporte", event -> downloadReport()); Button closeButton = new Button("Salir", event -> navigateToRequestsListView()); - return new HorizontalLayout(viewButton, editButton, closeButton); + return new HorizontalLayout(viewButton, editButton, downloadButton, closeButton); } private Button createButton(final String caption, final Runnable action) { @@ -457,6 +469,145 @@ public class RequestEmployeeView extends Div implements HasUrlParameter return existingRequest.isEmpty(); } + private String getDateString(final LocalDate date) { + return (date != null) ? date.toString() : ""; + } + + private ByteArrayInputStream generatePdfReport() { + try (PDDocument document = new PDDocument(); ByteArrayOutputStream out = new ByteArrayOutputStream()) { + PDPage page = new PDPage(); + document.addPage(page); + Employee employee = employeeService.getEmployee(employeeId); + + PDPageContentStream contentStream = null; + try { + contentStream = new PDPageContentStream(document, page); + + contentStream.setFont(PDType1Font.TIMES_BOLD, 18); + contentStream.beginText(); + contentStream.newLineAtOffset(200, 750); + contentStream.showText("Reporte de Vacaciones"); + contentStream.endText(); + + contentStream.setFont(PDType1Font.TIMES_ROMAN, 14); + contentStream.beginText(); + contentStream.newLineAtOffset(50, 700); + contentStream.showText("Empleado: " + employee.getFirstName() + " " + employee.getLastName()); + contentStream.newLineAtOffset(0, -15); + contentStream.showText("Equipo: " + employee.getTeam().getName()); + contentStream.endText(); + + float tableTopY = 650; + float margin = 50; + float cellHeight = 20; + String[] headers = {"Categoría", "Estado", "Fecha de Inicio", "Fecha de Fin", "Días a Tomar"}; + int columns = headers.length; + + float[] columnWidths = new float[columns]; + for (int i = 0; i < columns; i++) { + columnWidths[i] = getMaxColumnWidth(headers[i], requests, i); + } + + contentStream.setFont(PDType1Font.TIMES_BOLD, 10); + float currentX = margin; + for (int i = 0; i < columns; i++) { + contentStream.addRect(currentX, tableTopY, columnWidths[i], -cellHeight); + contentStream.beginText(); + contentStream.newLineAtOffset(currentX + 5, tableTopY - 15); + contentStream.showText(headers[i]); + contentStream.endText(); + currentX += columnWidths[i]; + } + contentStream.stroke(); + + contentStream.setFont(PDType1Font.TIMES_ROMAN, 10); + float currentY = tableTopY - cellHeight; + for (TimeOffRequest request : requests) { + String startDate = getDateString(request.getStartDate()); + String endDate = getDateString(request.getEndDate()); + + String[] rowData = { + request.getCategory().name() != null ? request.getCategory().name() : "", + request.getState().name() != null ? request.getState().name() : "", + startDate, + endDate, + String.valueOf(request.getDaysToBeTake() != null ? request.getDaysToBeTake() : 0) + }; + + currentX = margin; + for (int i = 0; i < columns; i++) { + contentStream.addRect(currentX, currentY, columnWidths[i], -cellHeight); + contentStream.beginText(); + contentStream.newLineAtOffset(currentX + 5, currentY - 15); + contentStream.showText(rowData[i]); + contentStream.endText(); + currentX += columnWidths[i]; + } + contentStream.stroke(); + currentY -= cellHeight; + + if (currentY < 50) { + contentStream.close(); + page = new PDPage(); + document.addPage(page); + contentStream = new PDPageContentStream(document, page); + currentY = 750; + } + } + } finally { + if (contentStream != null) { + contentStream.close(); + } + } + document.save(out); + return new ByteArrayInputStream(out.toByteArray()); + } catch (IOException e) { + throw new UncheckedIOException("Error al generar el reporte", e); + } + } + + private float getMaxColumnWidth(final String header, final List requests, final int columnIndex) { + float maxWidth = header.length(); + for (TimeOffRequest request : requests) { + String value = switch (columnIndex) { + case 0 -> request.getCategory().name(); + case 1 -> request.getState().name(); + case 2 -> getDateString(request.getStartDate()); + case 3 -> getDateString(request.getEndDate()); + case 4 -> String.valueOf(request.getDaysToBeTake()); + default -> ""; + }; + if (value != null) { + maxWidth = Math.max(maxWidth, value.length()); + } + } + return maxWidth * 7; + } + + private StreamResource generateVacationReport() { + Employee employee = employeeService.getEmployee(employeeId); + String fileName = String.format("%s_%s-reporte_de_vacaciones_%s.pdf", + employee.getFirstName(), + employee.getLastName(), + LocalDate.now()); + + ByteArrayInputStream pdfStream = generatePdfReport(); + + return new StreamResource(fileName, () -> pdfStream) + .setContentType("application/pdf") + .setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); + } + + private void downloadReport() { + StreamResource resource = generateVacationReport(); + 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()); + } + @Override public void setParameter(final BeforeEvent event, final String parameter) { employeeId = UUID.fromString(parameter); diff --git a/src/main/java/com/primefactorsolutions/views/RequestsListView.java b/src/main/java/com/primefactorsolutions/views/RequestsListView.java index cb54b03..c911edc 100644 --- a/src/main/java/com/primefactorsolutions/views/RequestsListView.java +++ b/src/main/java/com/primefactorsolutions/views/RequestsListView.java @@ -8,9 +8,6 @@ import com.primefactorsolutions.service.VacationService; 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.dialog.Dialog; -import com.vaadin.flow.component.html.Anchor; -import com.vaadin.flow.component.html.Span; import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.router.PageTitle; @@ -28,10 +25,8 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UncheckedIOException; -import java.time.DayOfWeek; import java.time.LocalDate; import java.time.Period; -import java.time.temporal.WeekFields; import java.util.*; import java.util.stream.Collectors; @@ -434,12 +429,12 @@ public class RequestsListView extends BaseView { getUI().ifPresent(ui -> ui.navigate("requests/" + idEmployee.toString())); } - private ByteArrayInputStream generateExcelReport(List employees) { + private ByteArrayInputStream generateExcelReport(final List employees) { try (Workbook workbook = new XSSFWorkbook()) { - Sheet sheet = workbook.createSheet("Reporte Horas Trabajadas"); + Sheet sheet = workbook.createSheet("REPORTE_GENERAL_DE_VACACIONES"); Row headerRow = sheet.createRow(0); - String[] headers = {"Nombre", "Equipo", "Estado", "Total Horas"}; + String[] headers = {"Empleado", "Equipo", "Estado", "Total Horas"}; for (int i = 0; i < headers.length; i++) { Cell cell = headerRow.createCell(i); cell.setCellValue(headers[i]); @@ -465,9 +460,7 @@ public class RequestsListView extends BaseView { private StreamResource generateGeneralVacationReport() { List employees = employeeService.findAllEmployees(); - ByteArrayInputStream excelStream = generateExcelReport(employees); - return new StreamResource("reporte_general_de_vacaciones_" + LocalDate.now() + ".xlsx", () -> excelStream); }