Compare commits

..

8 Commits

Author SHA1 Message Date
Melina Gutierrez
addba4b70f crear tabla para visuaizar las actividades creadas 2024-11-13 16:08:20 -04:00
Melina Gutierrez
090a4bb67a crear tabla para visuaizar las actividades creadas 2024-11-13 15:57:49 -04:00
Melina Gutierrez
3c626e3c85 Merge remote-tracking branch 'origin/hoursworked' into hoursworked
Some checks failed
PR Builder / Build-PR (pull_request) Failing after 19s
# Conflicts:
#	src/main/java/com/primefactorsolutions/views/HoursWorkedView.java
2024-11-12 20:57:30 -04:00
Melina Gutierrez
e45d0d828f #45-Registro Semanal de Horas Trabajadas corregir duplicados y actividades 2024-11-12 20:55:52 -04:00
Melina Gutierrez
b94ec365c7 #45-Registro Semanal de Horas Trabajadas corregir duplicados 2024-11-12 20:29:21 -04:00
Melina Gutierrez
e2f128c301 #45-Registro Semanal de Horas Trabajadas corregir duplicados 2024-11-12 20:20:35 -04:00
Melina Gutierrez
ebb5454b29 #45-Registro Semanal de Horas Trabajadas corregir duplicados 2024-11-12 07:00:43 -04:00
Melina Gutierrez
dee4bcaf3b #45-Registro Semanal de Horas Trabajadas corregir duplicados
Some checks failed
PR Builder / Build-PR (pull_request) Failing after 23s
2024-11-12 07:00:06 -04:00
50 changed files with 1590 additions and 2191 deletions

View File

@ -1,14 +0,0 @@
name: PR Builder
run-name: ${{ gitea.actor }} building PR
on: [pull_request]
jobs:
Build-PR:
runs-on: ubuntu-22.04
steps:
- run: echo "The job was automatically triggered by a ${{ gitea.event_name }} event on branch ${{ gitea.head_ref }} and ref is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
- name: Build PR
if: gitea.base_ref == 'main'
run: |
git clone --single-branch --branch "${{ gitea.head_ref }}" https://git.primefactorsolutions.com/PFS/pfs-intra.git && cd pfs-intra && ./mvnw clean package -Pproduction
- run: echo "This job's status is ${{ job.status }}."

View File

@ -1,16 +0,0 @@
name: Builder
run-name: ${{ gitea.actor }} building
on:
push:
branches:
- main
jobs:
Build-Project:
runs-on: ubuntu-22.04
steps:
- run: echo "The job was automatically triggered by a ${{ gitea.event_name }} event on branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
- name: Build package
run: |
git clone --single-branch --branch main https://git.primefactorsolutions.com/PFS/pfs-intra.git && cd pfs-intra && ./mvnw clean package -Pproduction && unlink /home/ubuntu/pfs-intra/app.jar && cp target/*.jar /home/ubuntu/pfs-intra/app.jar && sudo systemctl restart pfs-intra
- run: echo "This job's status is ${{ job.status }}."

View File

@ -1,118 +0,0 @@
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.*;
import java.net.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is
* provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl
* property to use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH = ".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH = ".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download
* url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a
// custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if (mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if (mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if (!outputFile.getParentFile().exists()) {
if (!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

Binary file not shown.

View File

@ -1,18 +0,0 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar

Binary file not shown.

270
package-lock.json generated
View File

@ -8,7 +8,7 @@
"license": "UNLICENSED", "license": "UNLICENSED",
"dependencies": { "dependencies": {
"@f0rce/ace-widget": "1.0.2", "@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-component-factory/vcf-pdf-viewer": "2.0.1",
"@vaadin/bundles": "24.5.1", "@vaadin/bundles": "24.5.1",
"@vaadin/common-frontend": "0.0.19", "@vaadin/common-frontend": "0.0.19",
@ -23,29 +23,30 @@
"@vaadin/vaadin-usage-statistics": "2.1.3", "@vaadin/vaadin-usage-statistics": "2.1.3",
"construct-style-sheets-polyfill": "3.1.0", "construct-style-sheets-polyfill": "3.1.0",
"date-fns": "2.29.3", "date-fns": "2.29.3",
"lit": "3.1.4", "lit": "3.2.1",
"print-js": "1.6.0", "print-js": "1.6.0",
"proj4": "2.12.1", "proj4": "2.12.1",
"react": "18.3.1", "react": "18.3.1",
"react-dom": "18.3.1", "react-dom": "18.3.1",
"react-router-dom": "6.23.1" "react-router-dom": "6.26.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/preset-react": "7.24.7", "@babel/preset-react": "7.25.7",
"@rollup/plugin-replace": "5.0.7", "@preact/signals-react-transform": "0.4.0",
"@rollup/pluginutils": "5.1.0", "@rollup/plugin-replace": "6.0.1",
"@types/react": "18.3.3", "@rollup/pluginutils": "5.1.2",
"@types/react-dom": "18.3.0", "@types/react": "18.3.11",
"@vitejs/plugin-react": "4.3.1", "@types/react-dom": "18.3.1",
"async": "3.2.5", "@vitejs/plugin-react": "4.3.3",
"glob": "10.4.1", "async": "3.2.6",
"glob": "10.4.5",
"rollup-plugin-brotli": "3.1.0", "rollup-plugin-brotli": "3.1.0",
"rollup-plugin-visualizer": "5.12.0", "rollup-plugin-visualizer": "5.12.0",
"strip-css-comments": "5.0.0", "strip-css-comments": "5.0.0",
"transform-ast": "2.4.4", "transform-ast": "2.4.4",
"typescript": "5.4.5", "typescript": "5.6.3",
"vite": "5.3.3", "vite": "5.4.9",
"vite-plugin-checker": "0.6.4", "vite-plugin-checker": "0.8.0",
"workbox-build": "7.1.1", "workbox-build": "7.1.1",
"workbox-core": "7.1.0", "workbox-core": "7.1.0",
"workbox-precaching": "7.1.0" "workbox-precaching": "7.1.0"
@ -1809,17 +1810,18 @@
} }
}, },
"node_modules/@babel/preset-react": { "node_modules/@babel/preset-react": {
"version": "7.24.7", "version": "7.25.7",
"resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.25.7.tgz",
"integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", "integrity": "sha512-GjV0/mUEEXpi1U5ZgDprMRRgajGMRW3G5FjMr5KLKD8nT2fTG8+h/klV3+6Dm5739QE+K5+2e91qFKAYI3pmRg==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-plugin-utils": "^7.25.7",
"@babel/helper-validator-option": "^7.24.7", "@babel/helper-validator-option": "^7.25.7",
"@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.25.7",
"@babel/plugin-transform-react-jsx": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.7",
"@babel/plugin-transform-react-jsx-development": "^7.24.7", "@babel/plugin-transform-react-jsx-development": "^7.25.7",
"@babel/plugin-transform-react-pure-annotations": "^7.24.7" "@babel/plugin-transform-react-pure-annotations": "^7.25.7"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@ -2465,17 +2467,70 @@
} }
}, },
"node_modules/@polymer/polymer": { "node_modules/@polymer/polymer": {
"version": "3.5.1", "version": "3.5.2",
"resolved": "https://registry.npmjs.org/@polymer/polymer/-/polymer-3.5.1.tgz", "resolved": "https://registry.npmjs.org/@polymer/polymer/-/polymer-3.5.2.tgz",
"integrity": "sha512-JlAHuy+1qIC6hL1ojEUfIVD58fzTpJAoCxFwV5yr0mYTXV1H8bz5zy0+rC963Cgr9iNXQ4T9ncSjC2fkF9BQfw==", "integrity": "sha512-fWwImY/UH4bb2534DVSaX+Azs2yKg8slkMBHOyGeU2kKx7Xmxp6Lee0jP8p6B3d7c1gFUPB2Z976dTUtX81pQA==",
"license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"@webcomponents/shadycss": "^1.9.1" "@webcomponents/shadycss": "^1.9.1"
} }
}, },
"node_modules/@preact/signals-core": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.8.0.tgz",
"integrity": "sha512-OBvUsRZqNmjzCZXWLxkZfhcgT+Fk8DDcT/8vD6a1xhDemodyy87UJRJfASMuSD8FaAIeGgGm85ydXhm7lr4fyA==",
"dev": true,
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
}
},
"node_modules/@preact/signals-react": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@preact/signals-react/-/signals-react-2.2.0.tgz",
"integrity": "sha512-EPYlhXqqcOUxz2gTQGt4rtK6X7Jr04517DcJVZ4I5a7Gxy39haK24uFeVWtiU/tnEReRFcxpQN6poYra1jf68A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@preact/signals-core": "^1.7.0",
"use-sync-external-store": "^1.2.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
},
"peerDependencies": {
"react": "^16.14.0 || 17.x || 18.x"
}
},
"node_modules/@preact/signals-react-transform": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@preact/signals-react-transform/-/signals-react-transform-0.4.0.tgz",
"integrity": "sha512-ZH8u5VrFPMmxggjAr7Rl9OLi3yvyDGi4lGQulftkszuiJB15jVy/MMraIfNvWKf2RfjtHLvp3K6Jk19xO/j7Tw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-module-imports": "^7.22.5",
"@babel/helper-plugin-utils": "^7.22.5",
"@preact/signals-react": "^2.1.0",
"debug": "^4.3.4",
"use-sync-external-store": "^1.2.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
},
"peerDependencies": {
"@babel/core": "^7.0.0",
"react": "^16.14.0 || 17.x || 18.x"
}
},
"node_modules/@remix-run/router": { "node_modules/@remix-run/router": {
"version": "1.16.1", "version": "1.19.2",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.2.tgz",
"integrity": "sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==", "integrity": "sha512-baiMx18+IMuD1yyvOGaHM9QrVUPGGG0jC+z+IPHnRJWUAUvaKuWKyE8gjDj2rzv3sz9zOGoRSPgeBVHRhZnBlA==",
"license": "MIT",
"engines": { "engines": {
"node": ">=14.0.0" "node": ">=14.0.0"
} }
@ -2506,10 +2561,11 @@
} }
}, },
"node_modules/@rollup/plugin-replace": { "node_modules/@rollup/plugin-replace": {
"version": "5.0.7", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.7.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-6.0.1.tgz",
"integrity": "sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ==", "integrity": "sha512-2sPh9b73dj5IxuMmDAsQWVFT7mR+yoHweBaXG2W/R8vQ+IWZlnaI7BR7J6EguVQUp1hd8Z7XuozpDjEKQAAC2Q==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@rollup/pluginutils": "^5.0.1", "@rollup/pluginutils": "^5.0.1",
"magic-string": "^0.30.3" "magic-string": "^0.30.3"
@ -2549,10 +2605,11 @@
} }
}, },
"node_modules/@rollup/pluginutils": { "node_modules/@rollup/pluginutils": {
"version": "5.1.0", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz",
"integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", "integrity": "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@types/estree": "^1.0.0", "@types/estree": "^1.0.0",
"estree-walker": "^2.0.2", "estree-walker": "^2.0.2",
@ -2929,19 +2986,21 @@
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
}, },
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "18.3.3", "version": "18.3.11",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz",
"integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@types/prop-types": "*", "@types/prop-types": "*",
"csstype": "^3.0.2" "csstype": "^3.0.2"
} }
}, },
"node_modules/@types/react-dom": { "node_modules/@types/react-dom": {
"version": "18.3.0", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==",
"devOptional": true, "devOptional": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@types/react": "*" "@types/react": "*"
} }
@ -4440,14 +4499,15 @@
} }
}, },
"node_modules/@vitejs/plugin-react": { "node_modules/@vitejs/plugin-react": {
"version": "4.3.1", "version": "4.3.3",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.3.tgz",
"integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==", "integrity": "sha512-NooDe9GpHGqNns1i8XDERg0Vsg5SSYRhRxxyTGogUdkdNt47jal+fbuYi+Yfq6pzRCKXyoPcWisfxE6RIM3GKA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/core": "^7.24.5", "@babel/core": "^7.25.2",
"@babel/plugin-transform-react-jsx-self": "^7.24.5", "@babel/plugin-transform-react-jsx-self": "^7.24.7",
"@babel/plugin-transform-react-jsx-source": "^7.24.1", "@babel/plugin-transform-react-jsx-source": "^7.24.7",
"@types/babel__core": "^7.20.5", "@types/babel__core": "^7.20.5",
"react-refresh": "^0.14.2" "react-refresh": "^0.14.2"
}, },
@ -4624,10 +4684,11 @@
} }
}, },
"node_modules/async": { "node_modules/async": {
"version": "3.2.5", "version": "3.2.6",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
"integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
"dev": true "dev": true,
"license": "MIT"
}, },
"node_modules/at-least-node": { "node_modules/at-least-node": {
"version": "1.0.0", "version": "1.0.0",
@ -6053,23 +6114,22 @@
} }
}, },
"node_modules/glob": { "node_modules/glob": {
"version": "10.4.1", "version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"dev": true, "dev": true,
"license": "ISC",
"dependencies": { "dependencies": {
"foreground-child": "^3.1.0", "foreground-child": "^3.1.0",
"jackspeak": "^3.1.2", "jackspeak": "^3.1.2",
"minimatch": "^9.0.4", "minimatch": "^9.0.4",
"minipass": "^7.1.2", "minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1" "path-scurry": "^1.11.1"
}, },
"bin": { "bin": {
"glob": "dist/esm/bin.mjs" "glob": "dist/esm/bin.mjs"
}, },
"engines": {
"node": ">=16 || 14 >=14.18"
},
"funding": { "funding": {
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
@ -7012,13 +7072,14 @@
"peer": true "peer": true
}, },
"node_modules/lit": { "node_modules/lit": {
"version": "3.1.4", "version": "3.2.1",
"resolved": "https://registry.npmjs.org/lit/-/lit-3.1.4.tgz", "resolved": "https://registry.npmjs.org/lit/-/lit-3.2.1.tgz",
"integrity": "sha512-q6qKnKXHy2g1kjBaNfcoLlgbI3+aSOZ9Q4tiGa9bGYXq5RBXxkVTqTIVmP2VWMp29L4GyvCFm8ZQ2o56eUAMyA==", "integrity": "sha512-1BBa1E/z0O9ye5fZprPtdqnc0BFzxIxTTOO/tQFmyC/hj1O3jL4TfmLBw0WEwjAokdLwpclkvGgDJwTIh0/22w==",
"license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"@lit/reactive-element": "^2.0.4", "@lit/reactive-element": "^2.0.4",
"lit-element": "^4.0.4", "lit-element": "^4.1.0",
"lit-html": "^3.1.2" "lit-html": "^3.2.0"
} }
}, },
"node_modules/lit-element": { "node_modules/lit-element": {
@ -7568,6 +7629,13 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"dev": true,
"license": "BlueOak-1.0.0"
},
"node_modules/pako": { "node_modules/pako": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
@ -7870,11 +7938,12 @@
} }
}, },
"node_modules/react-router": { "node_modules/react-router": {
"version": "6.23.1", "version": "6.26.2",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.1.tgz", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.2.tgz",
"integrity": "sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==", "integrity": "sha512-tvN1iuT03kHgOFnLPfLJ8V95eijteveqdOSk+srqfePtQvqCExB8eHOYnlilbOcyJyKnYkr1vJvf7YqotAJu1A==",
"license": "MIT",
"dependencies": { "dependencies": {
"@remix-run/router": "1.16.1" "@remix-run/router": "1.19.2"
}, },
"engines": { "engines": {
"node": ">=14.0.0" "node": ">=14.0.0"
@ -7884,12 +7953,13 @@
} }
}, },
"node_modules/react-router-dom": { "node_modules/react-router-dom": {
"version": "6.23.1", "version": "6.26.2",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.23.1.tgz", "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.2.tgz",
"integrity": "sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==", "integrity": "sha512-z7YkaEW0Dy35T3/QKPYB1LjMK2R1fxnHO8kWpUMTBdfVzZrWOiY9a7CtN8HqdWtDUWd5FY6Dl8HFsqVwH4uOtQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@remix-run/router": "1.16.1", "@remix-run/router": "1.19.2",
"react-router": "6.23.1" "react-router": "6.26.2"
}, },
"engines": { "engines": {
"node": ">=14.0.0" "node": ">=14.0.0"
@ -9045,10 +9115,11 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.4.5", "version": "5.6.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
"dev": true, "dev": true,
"license": "Apache-2.0",
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@ -9183,6 +9254,16 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/use-sync-external-store": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
"integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/validate-npm-package-license": { "node_modules/validate-npm-package-license": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@ -9196,14 +9277,15 @@
} }
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "5.3.3", "version": "5.4.9",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.3.3.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.9.tgz",
"integrity": "sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==", "integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"esbuild": "^0.21.3", "esbuild": "^0.21.3",
"postcss": "^8.4.39", "postcss": "^8.4.43",
"rollup": "^4.13.0" "rollup": "^4.20.0"
}, },
"bin": { "bin": {
"vite": "bin/vite.js" "vite": "bin/vite.js"
@ -9222,6 +9304,7 @@
"less": "*", "less": "*",
"lightningcss": "^1.21.0", "lightningcss": "^1.21.0",
"sass": "*", "sass": "*",
"sass-embedded": "*",
"stylus": "*", "stylus": "*",
"sugarss": "*", "sugarss": "*",
"terser": "^5.4.0" "terser": "^5.4.0"
@ -9239,6 +9322,9 @@
"sass": { "sass": {
"optional": true "optional": true
}, },
"sass-embedded": {
"optional": true
},
"stylus": { "stylus": {
"optional": true "optional": true
}, },
@ -9251,10 +9337,11 @@
} }
}, },
"node_modules/vite-plugin-checker": { "node_modules/vite-plugin-checker": {
"version": "0.6.4", "version": "0.8.0",
"resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.6.4.tgz", "resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.8.0.tgz",
"integrity": "sha512-2zKHH5oxr+ye43nReRbC2fny1nyARwhxdm0uNYp/ERy4YvU9iZpNOsueoi/luXw5gnpqRSvjcEPxXbS153O2wA==", "integrity": "sha512-UA5uzOGm97UvZRTdZHiQVYFnd86AVn8EVaD4L3PoVzxH+IZSfaAw14WGFwX9QS23UW3lV/5bVKZn6l0w+q9P0g==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.12.13", "@babel/code-frame": "^7.12.13",
"ansi-escapes": "^4.3.0", "ansi-escapes": "^4.3.0",
@ -9264,7 +9351,6 @@
"fast-glob": "^3.2.7", "fast-glob": "^3.2.7",
"fs-extra": "^11.1.0", "fs-extra": "^11.1.0",
"npm-run-path": "^4.0.1", "npm-run-path": "^4.0.1",
"semver": "^7.5.0",
"strip-ansi": "^6.0.0", "strip-ansi": "^6.0.0",
"tiny-invariant": "^1.1.0", "tiny-invariant": "^1.1.0",
"vscode-languageclient": "^7.0.0", "vscode-languageclient": "^7.0.0",
@ -9276,6 +9362,7 @@
"node": ">=14.16" "node": ">=14.16"
}, },
"peerDependencies": { "peerDependencies": {
"@biomejs/biome": ">=1.7",
"eslint": ">=7", "eslint": ">=7",
"meow": "^9.0.0", "meow": "^9.0.0",
"optionator": "^0.9.1", "optionator": "^0.9.1",
@ -9284,9 +9371,12 @@
"vite": ">=2.0.0", "vite": ">=2.0.0",
"vls": "*", "vls": "*",
"vti": "*", "vti": "*",
"vue-tsc": ">=1.3.9" "vue-tsc": "~2.1.6"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"@biomejs/biome": {
"optional": true
},
"eslint": { "eslint": {
"optional": true "optional": true
}, },
@ -9380,18 +9470,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/vite-plugin-checker/node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/vite-plugin-checker/node_modules/strip-ansi": { "node_modules/vite-plugin-checker/node_modules/strip-ansi": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",

View File

@ -28,6 +28,7 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/preset-react": "7.24.7", "@babel/preset-react": "7.24.7",
"@preact/signals-react-transform": "0.4.0",
"@rollup/plugin-replace": "5.0.7", "@rollup/plugin-replace": "5.0.7",
"@rollup/pluginutils": "5.1.0", "@rollup/pluginutils": "5.1.0",
"@types/react": "18.3.3", "@types/react": "18.3.3",
@ -73,6 +74,7 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/preset-react": "7.24.7", "@babel/preset-react": "7.24.7",
"@preact/signals-react-transform": "0.4.0",
"@rollup/plugin-replace": "5.0.7", "@rollup/plugin-replace": "5.0.7",
"@rollup/pluginutils": "5.1.0", "@rollup/pluginutils": "5.1.0",
"@types/react": "18.3.3", "@types/react": "18.3.3",
@ -91,7 +93,7 @@
"workbox-core": "7.1.0", "workbox-core": "7.1.0",
"workbox-precaching": "7.1.0" "workbox-precaching": "7.1.0"
}, },
"hash": "1a0f17d48b329307b5862bc57499307d1b89f7d89260121c2b7189f76957c436" "hash": "2dc40a4f634ae025081ca2239cba00b14a35fe94ab78ac0a4dd3023d882081d5"
}, },
"overrides": { "overrides": {
"@vaadin/bundles": "$@vaadin/bundles", "@vaadin/bundles": "$@vaadin/bundles",

33
pom.xml
View File

@ -120,11 +120,6 @@
<artifactId>commons-beanutils</artifactId> <artifactId>commons-beanutils</artifactId>
<version>1.9.4</version> <version>1.9.4</version>
</dependency> </dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.17.0</version>
</dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId> <artifactId>jackson-core</artifactId>
@ -270,39 +265,11 @@
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>3.3.1</version> <version>3.3.1</version>
</dependency> </dependency>
<dependency>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
<version>9.0.1</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<defaultGoal>spring-boot:run</defaultGoal> <defaultGoal>spring-boot:run</defaultGoal>
<plugins> <plugins>
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
<version>9.0.1</version>
<executions>
<execution>
<id>get-the-git-infos</id>
<goals>
<goal>revision</goal>
</goals>
<phase>initialize</phase>
</execution>
</executions>
<configuration>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
<includeOnlyProperties>
<includeOnlyProperty>^git.build.(time|version)$</includeOnlyProperty>
<includeOnlyProperty>^git.commit.id.(abbrev|full)$</includeOnlyProperty>
</includeOnlyProperties>
<commitIdGenerationMode>full</commitIdGenerationMode>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId> <artifactId>maven-checkstyle-plugin</artifactId>

Binary file not shown.

View File

@ -4,6 +4,7 @@ import com.vaadin.flow.component.page.AppShellConfigurator;
import com.vaadin.flow.theme.Theme; import com.vaadin.flow.theme.Theme;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
/** /**
* The entry point of the Spring Boot application. * The entry point of the Spring Boot application.
* *

View File

@ -1,19 +0,0 @@
package com.primefactorsolutions.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;
@Configuration
public class PropertiesConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
final PropertySourcesPlaceholderConfigurer propsConfig = new PropertySourcesPlaceholderConfigurer();
propsConfig.setLocation(new ClassPathResource("git.properties"));
propsConfig.setIgnoreResourceNotFound(true);
propsConfig.setIgnoreUnresolvablePlaceholders(true);
return propsConfig;
}
}

View File

@ -0,0 +1,200 @@
package com.primefactorsolutions.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.util.UUID;
@Entity
public class Actividad extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
private String nombre;
private double lunes;
private double martes;
private double miercoles;
private double jueves;
private double viernes;
private double sabado;
private double domingo;
private String tarea;
private double horas;
public Actividad() { }
public Actividad(final Builder builder) {
this.nombre = builder.nombre;
this.lunes = builder.lunes;
this.martes = builder.martes;
this.miercoles = builder.miercoles;
this.jueves = builder.jueves;
this.viernes = builder.viernes;
this.sabado = builder.sabado;
this.domingo = builder.domingo;
this.tarea = builder.tarea;
this.horas = builder.horas;
}
public String setNombre(final String nombre) {
this.nombre = nombre;
return nombre;
}
public String getNombre() {
return nombre;
}
public void setLunes(final double lunes) {
this.lunes = lunes;
return;
}
public void setMartes(final double martes) {
this.martes = martes;
return;
}
public void setMiercoles(final double miercoles) {
this.miercoles = miercoles;
return;
}
public void setJueves(final double jueves) {
this.jueves = jueves;
return;
}
public void setViernes(final double viernes) {
this.viernes = viernes;
return;
}
public void setSabado(final double sabado) {
this.sabado = sabado;
return;
}
public void setDomingo(final double domingo) {
this.domingo = domingo;
return;
}
public void setTarea(final String tarea) {
this.tarea = tarea;
return;
}
public void setHoras(final double horas) {
this.horas = horas;
return;
}
public double getLunes() {
return lunes;
}
public double getMartes() {
return martes;
}
public double getMiercoles() {
return miercoles;
}
public double getJueves() {
return jueves;
}
public double getViernes() {
return viernes;
}
public double getSabado() {
return sabado;
}
public double getDomingo() {
return domingo;
}
public String getTarea() { // Cambié aquí también
return tarea;
}
public double getHoras() {
return horas;
}
// Builder para crear instancias de Actividad
public static class Builder {
private String nombre;
private double lunes;
private double martes;
private double miercoles;
private double jueves;
private double viernes;
private double sabado;
private double domingo;
private String tarea; // Cambié 'tarea' por 'descripcion'
private double horas;
public Builder tarea(final String tarea, final double horas) {
this.tarea = tarea;
this.horas = horas;
return this;
}
public Builder tarea(final String tarea) {
this.tarea = tarea;
return this;
}
public Builder nombre(final String nombre) {
this.nombre = nombre;
return this;
}
public Builder lunes(final double horas) {
this.lunes = horas;
return this;
}
public Builder martes(final double horas) {
this.martes = horas;
return this;
}
public Builder miercoles(final double horas) {
this.miercoles = horas;
return this;
}
public Builder jueves(final double horas) {
this.jueves = horas;
return this;
}
public Builder viernes(final double horas) {
this.viernes = horas;
return this;
}
public Builder sabado(final double horas) {
this.sabado = horas;
return this;
}
public Builder domingo(final double horas) {
this.domingo = horas;
return this;
}
public Actividad build() {
return new Actividad(this);
}
}
}

View File

@ -0,0 +1,81 @@
package com.primefactorsolutions.model;
import jakarta.persistence.*;
import java.time.LocalDate;
import java.util.UUID;
@Entity
@Table(name = "Actividades_hours")
public class ActividadesHours {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
@ManyToOne
@JoinColumn(name = "employee_id", nullable = false)
private Employee employee;
@ManyToOne
@JoinColumn(name = "actividad_id", nullable = false)
private Actividad actividad;
@Column(nullable = false)
private double totalHours;
@Column(nullable = false)
private int weekNumber;
@Column(nullable = false)
private LocalDate fecha;
// Getters y Setters
public UUID getId() {
return id;
}
public void setId(final UUID id) {
this.id = id;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(final Employee employee) {
this.employee = employee;
}
public Actividad getActividad() {
return actividad;
}
public void setActividad(final Actividad actividad) {
this.actividad = actividad;
}
public double getTotalHours() {
return totalHours;
}
public void setTotalHours(final double totalHours) {
this.totalHours = totalHours;
}
public int getWeekNumber() {
return weekNumber;
}
public void setWeekNumber(final int weekNumber) {
this.weekNumber = weekNumber;
}
public LocalDate getFecha() {
return fecha;
}
public void setFecha(final LocalDate fecha) {
this.fecha = fecha;
}
}

View File

@ -1,35 +1,36 @@
package com.primefactorsolutions.model; package com.primefactorsolutions.model;
public enum DocumentType { public enum DocumentType {
TODOS, All,
CARNET_DE_IDENTIDAD, ID_CARD,
RECIBOS_DE_PAGO, PAY_STUB,
CONTRATO_DE_TRABAJO, PAY_SLIPS,
CERTIFICADO_DE_TRABAJO, EMPLOYMENT_CONTRACT,
WORK_CERTIFICATES,
NDA, NDA,
MEMORÁNDUMS, MEMORANDUMS,
APROBACIÓN_DE_CONTRATO_MTEPS, CONTRACT_APPROVAL_MTEPS,
CERTIFICADO_DE_ANTECEDENTES, BACKGROUND_CHECK_CERTIFICATE,
EVALUACIÓN_PRE_EMPLEO, PRE_EMPLOYMENT_EVALUATION,
FORMULARIO_DE_INSCRIPCIÓN_AL_SEGURO, INSURANCE_REGISTRATION_FORM,
FORMULARIO_DE_CANCELACIÓN_DE_SEGURO, INSURANCE_CANCELLATION_FORM,
TÍTULO_PROFESIONAL_1, PROFESSIONAL_DEGREE_1,
CERTIFICACIÓN_PROFESIONAL_1, PROFESSIONAL_CERTIFICATE_1,
TÍTULO_PROFESIONAL_2, PROFESSIONAL_DEGREE_2,
CERTIFICACIÓN_PROFECIONAL_2, PROFESSIONAL_CERTIFICATE_2,
TÍTULO_PROFESIONAL_3, PROFESSIONAL_DEGREE_3,
CERTIFICACIÓN_PROFECIONAL_3, PROFESSIONAL_CERTIFICATE_3,
NORMATIVA_LABORAL_GENERAL, GENERAL_LABOR_REGULATIONS,
NORMAS_DE_TRABAJO_REMOTO, REMOTE_WORK_GUIDELINES,
NORMAS_DE_SEGURIDAD, SAFETY_REGULATIONS,
INSTRUCTIVOS_DE_RECURSOS_HUMANOS, HUMAN_RESOURCES_GUIDELINES,
MANUAL_DE_FUNCIONES_DE_ADMINISTRACIÓN, ADMINISTRATION_FUNCTIONS_MANUAL,
MANUAL_DE_FUNCIONES_DE_INGENIERÍA, ENGINEERING_FUNCTIONS_MANUAL,
LEY_GENERAL_DEL_TRABAJO, GENERAL_LABOR_LAW,
DECRETOS_SUPREMOS, SUPREME_DECREE,
RESOLUCIONES_O_DISPOSICIONES_REGLAMENTARIAS, REGULATORY_RESOLUTION,
NORMATIVA_COMPLEMENTARIA, COMPLEMENTARY_REGULATION,
LEY_GRAL_DE_HIGIENE_SALUD_SEGURIDAD_OCUPACIONAL_Y_BIENESTAR, HEALTH_SAFETY_LAW,
NORMATIVA_REGLAMENTARIA_PARA_DESARROLLO_DE_PASANTÍAS, INTERNSHIP_RULES,
OTROS OTHER
} }

View File

@ -28,42 +28,36 @@ public class Employee extends BaseEntity implements UserDetails {
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El apellido solo debe contener letras") @Pattern(regexp = "^[a-zA-Z ]+$", message = "El apellido solo debe contener letras")
private String lastName; private String lastName;
private LocalDate birthday; private LocalDate birthday;
@Pattern(regexp = "^[a-zA-Z ,]+$", message = "La ciudad de nacimiento solo debe contener letras, espacios o comas") @Pattern(regexp = "^[a-zA-Z ]+$", message = "La ciudad de nacimiento solo debe contener letras")
private String birthCity; private String birthCity;
private String age; private String age;
@Size(max = 50, message = "La dirección de residencia no debe exceder 50 caracteres") @Size(max = 100, message = "La dirección de residencia no debe exceder 100 caracteres")
private String residenceAddress; private String residenceAddress;
@Size(max = 30, message = "La dirección local no debe exceder 100 caracteres") @Size(max = 100, message = "La dirección local no debe exceder 100 caracteres")
@Pattern(regexp = "^[a-zA-Z -]+$", message = "La dirección local solo debe contener letras y guion")
private String localAddress; private String localAddress;
@Pattern(regexp = "^[0-9]+$", message = "El número de teléfono debe contener solo números") @Pattern(regexp = "^[0-9]+$", message = "El número de teléfono debe contener solo números")
private String phoneNumber; private String phoneNumber;
@Email(message = "El correo personal no tiene un formato válido") @Email(message = "El correo personal no tiene un formato válido")
private String personalEmail; private String personalEmail;
@Pattern(regexp = "^[0-9]+$", message = "El número de teléfono debe contener solo números")
private String phoneNumberProfesional;
@Email(message = "El correo profesional no tiene un formato válido")
private String profesionalEmail;
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El cargo solo debe contener letras") @Pattern(regexp = "^[a-zA-Z ]+$", message = "El cargo solo debe contener letras")
private String position; private String position;
@ManyToOne @ManyToOne
@JoinColumn(name = "team_id", nullable = false) @JoinColumn(name = "team_id", nullable = false)
private Team team; private Team team;
@Size(max = 100, message = "El nombre de contacto de emergencia no debe exceder 100 caracteres")
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El nombre y apellido de contacto"
+ " de emergencia solo debe contener letras")
private String emergencyCName; private String emergencyCName;
@Size(max = 100, message = "La dirección de contacto de emergencia no debe exceder 100 caracteres")
private String emergencyCAddress; private String emergencyCAddress;
@Pattern(regexp = "^[0-9]+$", message = "El teléfono de contacto de emergencia " @Pattern(regexp = "^[0-9]+$", message = "El teléfono de contacto de emergencia debe contener solo números")
+ " debe contener solo números")
private String emergencyCPhone; private String emergencyCPhone;
@Email(message = "El correo de contacto de emergencia no tiene un formato válido") @Email(message = "El correo de contacto de emergencia no tiene un formato válido")
private String emergencyCEmail; private String emergencyCEmail;
@Pattern(regexp = "^[0-9]+$", message = "La cantidad de hijos debe contener solo números")
private String numberOfChildren; private String numberOfChildren;
@Pattern(regexp = "^[a-zA-Z0-9]+$", message = "El CI debe contener solo letras y números") @Pattern(regexp = "^[0-9]+$", message = "El CI debe contener solo números")
private String ci; private String ci;
private String issuedIn; private String issuedIn;
@Size(max = 100, message = "El título no debe exceder 100 caracteres")
private String pTitle1; private String pTitle1;
private String pTitle2; private String pTitle2;
private String pTitle3; private String pTitle3;
@ -76,27 +70,28 @@ public class Employee extends BaseEntity implements UserDetails {
private String certification2; private String certification2;
private String certification3; private String certification3;
private String certification4; private String certification4;
@Size(max = 255, message = "El reconocimiento no debe exceder 255 caracteres")
private String recognition; private String recognition;
@Size(max = 500, message = "Los logros no deben exceder 500 caracteres")
private String achievements; private String achievements;
private String language1; private String language;
private String language1Level; private String languageLevel;
private String language2;
private String language2Level;
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "El código debe contener solo letras y números") @Pattern(regexp = "^[A-Za-z0-9]+$", message = "El código debe contener solo letras y números")
private String cod; private String cod;
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El lead manager solo debe contener letras") @Pattern(regexp = "^[a-zA-Z ]+$", message = "El lead manager solo debe contener letras")
private String leadManager; private String leadManager;
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El proyecto solo debe contener letras")
private String project;
private LocalDate dateOfEntry; private LocalDate dateOfEntry;
private LocalDate dateOfExit; private LocalDate dateOfExit;
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El tipo de contrato solo debe contener letras")
private String contractType;
@Pattern(regexp = "^[0-9]+$", message = "La antigüedad debe contener solo números")
private String seniority; private String seniority;
@Pattern(regexp = "^[0-9]+(\\.[0-9]{1,2})?$", message = "El salario debe ser un número con hasta dos decimales") @Pattern(regexp = "^[0-9]+(\\.[0-9]{1,2})?$", message = "El salario debe ser un número con hasta dos decimales")
private String salarytotal; private String salary;
private String salaryBasic;
private String bonoProfesional;
private String antiguedad;
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El nombre del banco solo debe contener letras") @Pattern(regexp = "^[a-zA-Z ]+$", message = "El nombre del banco solo debe contener letras")
private String bankName; private String bankName;
@Pattern(regexp = "^[0-9]+$", message = "El número de cuenta debe contener solo números") @Pattern(regexp = "^[0-9]+$", message = "El número de cuenta debe contener solo números")
@ -105,9 +100,8 @@ public class Employee extends BaseEntity implements UserDetails {
private String gpss; private String gpss;
private String sss; private String sss;
@Pattern(regexp = "^[a-zA-Z ]+$", message = "Los derechohabientes solo deben contener letras") @Pattern(regexp = "^[a-zA-Z ]+$", message = "Los derechohabientes solo deben contener letras")
private String beneficiarie1; private String beneficiaries;
@Pattern(regexp = "^[a-zA-Z ]+$", message = "Los derechohabientes solo deben contener letras")
private String beneficiarie2;
@Column(columnDefinition = "TEXT") @Column(columnDefinition = "TEXT")
private String profileImage; private String profileImage;
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
@ -170,20 +164,4 @@ public class Employee extends BaseEntity implements UserDetails {
MALE, MALE,
FEMALE FEMALE
} }
@Enumerated(EnumType.STRING)
private ContractType contractType;
public enum ContractType {
CONTRATO_LABORAL,
CONTRATO_CIVIL_O_SERVICIOS,
CONTRATO_PLAZO_FIJO,
CONSULTORIA_INTERNA,
CONSULTORIA_EXTERNA,
MIXTO,
OTROS
}
@Size(max = 255, message = "El detalle del contrato no debe exceder 255 caracteres")
private String otherContractDetail;
} }

View File

@ -1,57 +1,42 @@
package com.primefactorsolutions.model; package com.primefactorsolutions.model;
import jakarta.persistence.*; import jakarta.persistence.Entity;
import lombok.AllArgsConstructor; import jakarta.persistence.GeneratedValue;
import lombok.Data; import jakarta.persistence.GenerationType;
import lombok.EqualsAndHashCode; import jakarta.persistence.Id;
import lombok.NoArgsConstructor; import jakarta.persistence.ManyToOne;
import jakarta.persistence.CascadeType;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.temporal.WeekFields; import java.time.temporal.WeekFields;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.UUID;
@Data
@Entity @Entity
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class HoursWorked extends BaseEntity { public class HoursWorked extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@ManyToOne @ManyToOne
@JoinColumn(name = "employee_id", nullable = true)
private Employee employee; private Employee employee;
@ManyToOne @ManyToOne(cascade = CascadeType.PERSIST) // Añadimos cascade para que persista la actividad automáticamente
@JoinColumn(name = "team_id", nullable = true) private Actividad actividad;
private Team team;
private int weekNumber; private int weekNumber;
private LocalDate date;
private String actividad;
private double hours;
private double horaspendientes;
private double totalHours; private double totalHours;
private LocalDate fecha;
private String tareaEspecifica; public HoursWorked() { }
public String getTareaEspecifica() { // Getters y Setters
return tareaEspecifica; public UUID getId() {
return id;
} }
public void setTareaEspecifica(final String tareaEspecifica) { public void setId(final UUID id) {
this.tareaEspecifica = tareaEspecifica; this.id = id;
}
public static double calculateTotalHours(final List<HoursWorked> activities) {
return activities.stream()
.mapToDouble(activity -> activity.hours)
.sum();
}
public static double calculatePendingHours(final List<HoursWorked> activities) {
double totalHoursWorked = calculateTotalHours(activities);
return Math.max(0, 40 - totalHoursWorked);
} }
public Employee getEmployee() { public Employee getEmployee() {
@ -62,6 +47,14 @@ public class HoursWorked extends BaseEntity {
this.employee = employee; this.employee = employee;
} }
public Actividad getActividad() {
return actividad;
}
public void setActividad(final Actividad actividad) {
this.actividad = actividad;
}
public int getWeekNumber() { public int getWeekNumber() {
return weekNumber; return weekNumber;
} }
@ -69,58 +62,41 @@ public class HoursWorked extends BaseEntity {
public void setWeekNumber(final int weekNumber) { public void setWeekNumber(final int weekNumber) {
this.weekNumber = weekNumber; this.weekNumber = weekNumber;
} }
public LocalDate getDate() {
return date;
}
public void setDate(final LocalDate date) {
this.date = date;
if (date != null) {
WeekFields weekFields = WeekFields.of(Locale.getDefault());
this.weekNumber = date.get(weekFields.weekOfWeekBasedYear());
}
}
public String getActividad() {
return actividad;
}
public void setActividad(final String actividad) {
this.actividad = actividad;
}
public double getHours() {
return hours;
}
public void setHours(final double hours) {
this.hours = hours;
}
public double getTotalHours() { public double getTotalHours() {
double total = this.getHours(); return totalHours;
return totalHours + total;
} }
public void setTotalHours(final double totalHours) { public void setTotalHours(final double totalHours) {
this.totalHours = totalHours; this.totalHours = totalHours;
} }
public Team getTeam() { public LocalDate getFecha() {
return team; return fecha;
} }
public void setTeam(final Team team) { public void setFecha(final LocalDate fecha) {
this.team = team; this.fecha = fecha;
// Actualiza el número de semana automáticamente al establecer la fecha
if (fecha != null) {
this.weekNumber = calculateWeekNumber(fecha);
}
} }
public double getHoraspendientes() { // Método adicional para calcular el número de semana basado en la fecha
//double horasTrabajadas = this.getTotalHours() + this.getHorasTareasEspecificas(); private int calculateWeekNumber(final LocalDate date) {
return 40; WeekFields weekFields = WeekFields.of(Locale.getDefault());
return date.get(weekFields.weekOfWeekBasedYear());
} }
public void setHoraspendientes(final double horaspendientes) { @Override
this.horaspendientes = horaspendientes; public String toString() {
return "HoursWorked{"
+ "id=" + id
+ ", employee=" + (employee != null ? employee.getFirstName() : "N/A")
+ ", actividad=" + (actividad != null ? actividad.getNombre() : "N/A")
+ ", weekNumber=" + weekNumber
+ ", totalHours=" + totalHours
+ ", fecha=" + fecha + '}';
} }
} }

View File

@ -3,11 +3,13 @@ package com.primefactorsolutions.model;
public enum TimeOffRequestStatus { public enum TimeOffRequestStatus {
TODOS, TODOS,
TOMADO, TOMADO,
SOLICITADO,
APROBADO, APROBADO,
EN_USO, EN_USO,
EN_REVISION,
PENDIENTE, PENDIENTE,
RECHAZADO, RECHAZADO,
VENCIDO, COMPLETADO,
CANCELADO,
SOLICITADO, VENCIDO
} }

View File

@ -14,6 +14,7 @@ public enum TimeOffRequestType {
AÑO_NUEVO_ANDINO, AÑO_NUEVO_ANDINO,
ANIVERSARIO_DEPARTAMENTAL, ANIVERSARIO_DEPARTAMENTAL,
DIA_DE_TODOS_LOS_DIFUNTOS, DIA_DE_TODOS_LOS_DIFUNTOS,
CUMPLEAÑOS, CUMPLEAÑOS,
MATERNIDAD, MATERNIDAD,
PATERNIDAD, PATERNIDAD,

View File

@ -0,0 +1,6 @@
package com.primefactorsolutions.repositories;
import com.primefactorsolutions.model.ActividadesHours;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.UUID;
public interface ActividadesHoursRepository extends JpaRepository<ActividadesHours, UUID> {
}

View File

@ -9,7 +9,9 @@ import java.util.UUID;
public interface EmployeeRepository extends JpaRepository<Employee, UUID> { public interface EmployeeRepository extends JpaRepository<Employee, UUID> {
Optional<Employee> findByUsername(String username); Optional<Employee> findByUsername(String username);
Optional<Employee> findByPersonalEmail(String personalEmail); Optional<Employee> findByPersonalEmail(String personalEmail);
List<Employee> findAllByTeamId(UUID teamId); Optional<Employee> findByTeamIdAndLeadManagerTrue(UUID teamId);
List<Employee> findByTeamName(String teamName); List<Employee> findByTeamName(String teamName);
} }

View File

@ -2,15 +2,11 @@ package com.primefactorsolutions.repositories;
import com.primefactorsolutions.model.HoursWorked; import com.primefactorsolutions.model.HoursWorked;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.time.LocalDate;
import java.util.List; import java.util.List;
import java.util.UUID;
@Repository
public interface HoursWorkedRepository extends JpaRepository<HoursWorked, UUID> { public interface HoursWorkedRepository extends JpaRepository<HoursWorked, Long> {
List<HoursWorked> findByWeekNumber(int weekNumber); List<HoursWorked> findByWeekNumber(int weekNumber);
List<HoursWorked> findByDate(LocalDate date);
List<HoursWorked> findByEmployeeIdAndWeekNumber(UUID employeeId, int weekNumber);
} }

View File

@ -14,5 +14,4 @@ public interface TimeOffRequestRepository extends JpaRepository<TimeOffRequest,
Optional<TimeOffRequest> findByEmployeeIdAndState(UUID employeeId, TimeOffRequestStatus state); Optional<TimeOffRequest> findByEmployeeIdAndState(UUID employeeId, TimeOffRequestStatus state);
List<TimeOffRequest> findByEmployeeIdAndCategory(UUID employeeId, TimeOffRequestType category); List<TimeOffRequest> findByEmployeeIdAndCategory(UUID employeeId, TimeOffRequestType category);
List<TimeOffRequest> findByState(TimeOffRequestStatus state); List<TimeOffRequest> findByState(TimeOffRequestStatus state);
void deleteByEmployeeIdAndCategory(UUID employeeId, TimeOffRequestType category);
} }

View File

@ -1,5 +1,4 @@
package com.primefactorsolutions.service; package com.primefactorsolutions.service;
import com.google.common.base.Strings;
import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.model.Employee;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@ -51,15 +50,11 @@ public class EmployeeService {
public String getTeamLeadName(final UUID teamId) { public String getTeamLeadName(final UUID teamId) {
// Encuentra al empleado con el rol de lead_manager en el equipo especificado // Encuentra al empleado con el rol de lead_manager en el equipo especificado
List<Employee> teamMembers = employeeRepository.findAllByTeamId(teamId); Optional<Employee> leadManager = employeeRepository.findByTeamIdAndLeadManagerTrue(teamId);
Optional<Employee> leadManager = teamMembers.stream()
.filter(e -> Strings.isNullOrEmpty(e.getLeadManager()))
.findFirst();
return leadManager.map(employee -> employee.getFirstName() + " " + employee.getLastName()) return leadManager.map(employee -> employee.getFirstName() + " " + employee.getLastName())
.orElse("No asignado"); .orElse("No asignado");
} }
public List<Employee> findEmployees( public List<Employee> findEmployees(
final int start, final int pageSize, final String sortProperty, final boolean asc) { final int start, final int pageSize, final String sortProperty, final boolean asc) {
List<Employee> employees = employeeRepository.findAll(); List<Employee> employees = employeeRepository.findAll();
@ -131,4 +126,6 @@ public class EmployeeService {
public List<Employee> findEmployeesByTeam(final String teamName) { public List<Employee> findEmployeesByTeam(final String teamName) {
return employeeRepository.findByTeamName(teamName); return employeeRepository.findByTeamName(teamName);
} }
} }

View File

@ -2,12 +2,10 @@ package com.primefactorsolutions.service;
import com.primefactorsolutions.model.HoursWorked; import com.primefactorsolutions.model.HoursWorked;
import com.primefactorsolutions.repositories.HoursWorkedRepository; import com.primefactorsolutions.repositories.HoursWorkedRepository;
import org.apache.commons.beanutils.BeanComparator;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDate; import java.util.List;
import java.util.*;
@Service @Service
public class HoursWorkedService { public class HoursWorkedService {
@ -22,20 +20,6 @@ public class HoursWorkedService {
return hoursWorkedRepository.findAll(); return hoursWorkedRepository.findAll();
} }
public double getTotalHoursWorkedByEmployeeForWeek(final UUID employeeId, final int weekNumber) {
List<HoursWorked> hoursWorkedList = hoursWorkedRepository.findByWeekNumber(weekNumber);
return hoursWorkedList.stream()
.filter(hw -> hw.getEmployee().getId().equals(employeeId))
.mapToDouble(HoursWorked::getTotalHours)
.sum();
}
public HoursWorked findHoursWorked(final UUID id) {
Optional<HoursWorked> hoursWorked = hoursWorkedRepository.findById(id);
HoursWorked hw = hoursWorked.get();
return hw;
}
public HoursWorked saveHoursWorked(final HoursWorked hoursWorked) { public HoursWorked saveHoursWorked(final HoursWorked hoursWorked) {
return hoursWorkedRepository.save(hoursWorked); return hoursWorkedRepository.save(hoursWorked);
} }
@ -44,56 +28,13 @@ public class HoursWorkedService {
return hoursWorkedRepository.save(hoursWorked); return hoursWorkedRepository.save(hoursWorked);
} }
public double getTotalHoursForEmployee(final UUID employeeId, final int weekNumber) { public void deleteHoursWorked(final Long id) {
List<HoursWorked> activities = hoursWorkedRepository.findByEmployeeIdAndWeekNumber(employeeId, weekNumber); hoursWorkedRepository.deleteById(id);
return HoursWorked.calculateTotalHours(activities);
}
public double getPendingHoursForEmployee(final UUID employeeId, final int weekNumber) {
List<HoursWorked> activities = hoursWorkedRepository.findByEmployeeIdAndWeekNumber(employeeId, weekNumber);
return HoursWorked.calculatePendingHours(activities);
} }
public List<HoursWorked> findByWeekNumber(final int weekNumber) { public List<HoursWorked> findByWeekNumber(final int weekNumber) {
return hoursWorkedRepository.findByWeekNumber(weekNumber); return hoursWorkedRepository.findByWeekNumber(weekNumber);
} }
public List<HoursWorked> findByDate(final LocalDate date) {
return hoursWorkedRepository.findByDate(date);
} }
public List<HoursWorked> findByDateAndWeekNumber(final LocalDate date, final int weekNumber) {
return hoursWorkedRepository.findByDate(date);
}
public List<HoursWorked> findHoursWorkeds(
final int start, final int pageSize, final String sortProperty, final boolean asc) {
List<HoursWorked> hoursWorkeds = hoursWorkedRepository.findAll();
int end = Math.min(start + pageSize, hoursWorkeds.size());
hoursWorkeds.sort(new BeanComparator<>(sortProperty));
if (!asc) {
Collections.reverse(hoursWorkeds);
}
return hoursWorkeds.subList(start, end);
}
public List<HoursWorked> findHoursWorkeds(final int start, final int pageSize) {
List<HoursWorked> hoursWorkeds = hoursWorkedRepository.findAll();
int end = Math.min(start + pageSize, hoursWorkeds.size());
return hoursWorkeds.subList(start, end);
}
public HoursWorked getHoursWorked(final UUID id) {
final Optional<HoursWorked> hoursWorked = hoursWorkedRepository.findById(id);
return hoursWorked.get();
}
public List<HoursWorked> findListHoursWorkedEmployee(final UUID employeeId, final int weekNumber) {
return hoursWorkedRepository.findByEmployeeIdAndWeekNumber(employeeId, weekNumber);
}
}

View File

@ -5,7 +5,6 @@ import com.primefactorsolutions.repositories.TimeOffRequestRepository;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.Optional; import java.util.Optional;
@ -19,10 +18,6 @@ public class TimeOffRequestService {
timeOffRequestRepository.save(newTimeOffRequest); timeOffRequestRepository.save(newTimeOffRequest);
} }
public void deleteTimeOffRequestByEmployeeAndCategory(final UUID employeeId, final TimeOffRequestType category) {
timeOffRequestRepository.deleteByEmployeeIdAndCategory(employeeId, category);
}
public void saveAll(final List<TimeOffRequest> requests) { public void saveAll(final List<TimeOffRequest> requests) {
timeOffRequestRepository.saveAll(requests); timeOffRequestRepository.saveAll(requests);
} }
@ -55,34 +50,4 @@ public class TimeOffRequestService {
public List<TimeOffRequest> findByEmployeeAndCategory(final UUID employeeId, final TimeOffRequestType category) { public List<TimeOffRequest> findByEmployeeAndCategory(final UUID employeeId, final TimeOffRequestType category) {
return timeOffRequestRepository.findByEmployeeIdAndCategory(employeeId, category); return timeOffRequestRepository.findByEmployeeIdAndCategory(employeeId, category);
} }
public void updateRequestStatuses() {
List<TimeOffRequest> requests = findAllTimeOffRequests();
LocalDate now = LocalDate.now();
LocalDate startOfYear = LocalDate.of(now.getYear(), 1, 1);
for (TimeOffRequest request : requests) {
if (request.getCategory() == TimeOffRequestType.VACACION_GESTION_ACTUAL && now.isEqual(startOfYear)) {
deleteTimeOffRequestByEmployeeAndCategory(
request.getEmployee().getId(),
TimeOffRequestType.VACACION_GESTION_ANTERIOR
);
request.setCategory(TimeOffRequestType.VACACION_GESTION_ANTERIOR);
}
if (request.getState() == TimeOffRequestStatus.APROBADO
|| request.getState() == TimeOffRequestStatus.EN_USO) {
LocalDate startDate = request.getStartDate();
LocalDate endDate = request.getEndDate();
if (now.isAfter(endDate)) {
request.setState(TimeOffRequestStatus.TOMADO);
} else if (now.isEqual(startDate) || (now.isAfter(startDate) && now.isBefore(endDate))) {
request.setState(TimeOffRequestStatus.EN_USO);
}
}
}
saveAll(requests);
}
} }

View File

@ -8,6 +8,7 @@ import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.confirmdialog.ConfirmDialog; import com.vaadin.flow.component.confirmdialog.ConfirmDialog;
import com.vaadin.flow.component.grid.Grid; import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.data.provider.DataProvider; import com.vaadin.flow.data.provider.DataProvider;
@ -30,13 +31,13 @@ import java.util.stream.Stream;
@PageTitle("Assessments") @PageTitle("Assessments")
@Route(value = "/assessments", layout = MainLayout.class) @Route(value = "/assessments", layout = MainLayout.class)
@PermitAll @PermitAll
public class AssessmentsListView extends BaseView { public class AssessmentsListView extends Main {
public AssessmentsListView(final AssessmentService assessmentService) { public AssessmentsListView(final AssessmentService assessmentService) {
final HorizontalLayout hl = new HorizontalLayout(); final HorizontalLayout hl = new HorizontalLayout();
final Button addAssessment = new Button("Add Assessment"); final Button addAssessment = new Button("Add Assessment");
addAssessment.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> { addAssessment.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
this.getUI().flatMap(ui -> ui.navigate(AssessmentView.class, "new")); this.getUI().get().navigate(AssessmentView.class, "new");
}); });
hl.add(addAssessment); hl.add(addAssessment);
@ -50,7 +51,7 @@ public class AssessmentsListView extends BaseView {
grid.addComponentColumn((ValueProvider<Assessment, Component>) assessment -> { grid.addComponentColumn((ValueProvider<Assessment, Component>) assessment -> {
var result = new Button("Result", event -> var result = new Button("Result", event ->
this.getUI().flatMap(ui -> ui.navigate(SubmissionView.class, assessment.getId().toString())) this.getUI().get().navigate(SubmissionView.class, assessment.getId().toString())
); );
result.setEnabled(assessment.isCompleted()); result.setEnabled(assessment.isCompleted());
@ -94,7 +95,6 @@ public class AssessmentsListView extends BaseView {
return assessmentService.getAssessments().size(); return assessmentService.getAssessments().size();
} }
@SuppressWarnings("unused")
@Override @Override
public Stream<Assessment> fetch(final Query<Assessment, Object> query) { public Stream<Assessment> fetch(final Query<Assessment, Object> query) {
int limit = query.getLimit(); int limit = query.getLimit();
@ -121,7 +121,7 @@ public class AssessmentsListView extends BaseView {
}); });
grid.setAllRowsVisible(true); grid.setAllRowsVisible(true);
getCurrentPageLayout().add(hl, grid); add(hl, grid);
} }
} }

View File

@ -1,16 +0,0 @@
package com.primefactorsolutions.views;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import lombok.Getter;
@Getter
public class BaseView extends Main {
private final VerticalLayout currentPageLayout;
public BaseView() {
currentPageLayout = new VerticalLayout();
add(currentPageLayout);
}
}

View File

@ -6,6 +6,7 @@ import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener; import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.data.provider.DataProvider; import com.vaadin.flow.data.provider.DataProvider;
import com.vaadin.flow.data.provider.DataProviderListener; import com.vaadin.flow.data.provider.DataProviderListener;
@ -26,14 +27,16 @@ import java.util.stream.Stream;
@PageTitle("Candidates") @PageTitle("Candidates")
@Route(value = "/candidates", layout = MainLayout.class) @Route(value = "/candidates", layout = MainLayout.class)
@PermitAll @PermitAll
public class CandidatesListView extends BaseView { public class CandidatesListView extends Main {
private final CandidateService candidateService;
public CandidatesListView(final CandidateService candidateService) { public CandidatesListView(final CandidateService candidateService) {
this.candidateService = candidateService;
final HorizontalLayout hl = new HorizontalLayout(); final HorizontalLayout hl = new HorizontalLayout();
final Button addCandidate = new Button("Add Candidate"); final Button addCandidate = new Button("Add Candidate");
addCandidate.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> { addCandidate.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
this.getUI().flatMap(ui -> ui.navigate(CandidateView.class, "new")); this.getUI().get().navigate(CandidateView.class, "new");
}); });
hl.add(addCandidate); hl.add(addCandidate);
@ -43,7 +46,7 @@ public class CandidatesListView extends BaseView {
grid.addComponentColumn((ValueProvider<Candidate, Component>) candidate -> { grid.addComponentColumn((ValueProvider<Candidate, Component>) candidate -> {
final Button edit = new Button("Edit"); final Button edit = new Button("Edit");
edit.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> edit.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent ->
this.getUI().flatMap(ui -> ui.navigate(CandidateView.class, candidate.getId().toString()))); this.getUI().get().navigate(CandidateView.class, candidate.getId().toString()));
return edit; return edit;
}); });
@ -58,7 +61,6 @@ public class CandidatesListView extends BaseView {
return candidateService.getCandidates().size(); return candidateService.getCandidates().size();
} }
@SuppressWarnings("unused")
@Override @Override
public Stream<Candidate> fetch(final Query<Candidate, Object> query) { public Stream<Candidate> fetch(final Query<Candidate, Object> query) {
int limit = query.getLimit(); int limit = query.getLimit();
@ -83,6 +85,6 @@ public class CandidatesListView extends BaseView {
} }
}); });
getCurrentPageLayout().add(hl, grid); add(hl, grid);
} }
} }

View File

@ -1,5 +0,0 @@
package com.primefactorsolutions.views;
public class Constants {
public static final int PAGE_SIZE = 10;
}

View File

@ -39,9 +39,9 @@ import java.io.InputStream;
@PageTitle("Document") @PageTitle("Document")
@Route(value = "/documents/:documentId?/:action?", layout = MainLayout.class) @Route(value = "/documents/:documentId?/:action?", layout = MainLayout.class)
public class DocumentView extends BeanValidationForm<Document> implements HasUrlParameter<String> { public class DocumentView extends BeanValidationForm<Document> implements HasUrlParameter<String> {
private final TextField fileName = new TextField("Nombre del documento"); private final TextField fileName = new TextField("Document Name");
private final ComboBox<DocumentType> documentType = new ComboBox<>("Tipo de documento"); private final ComboBox<DocumentType> documentType = new ComboBox<>("Document Type");
private final ComboBox<Employee> employeeComboBox = new ComboBox<>("Empleado"); private final ComboBox<Employee> employeeComboBox = new ComboBox<>("Employee");
private final MemoryBuffer buffer = new MemoryBuffer(); private final MemoryBuffer buffer = new MemoryBuffer();
private final Upload uploadButton = new Upload(buffer); private final Upload uploadButton = new Upload(buffer);
private final DocumentService documentService; private final DocumentService documentService;
@ -68,19 +68,19 @@ public class DocumentView extends BeanValidationForm<Document> implements HasUrl
} }
protected Button createSaveButton() { protected Button createSaveButton() {
saveButton = new Button("Guardar"); saveButton = new Button("Save");
saveButton.addClickListener(event -> saveDocument()); saveButton.addClickListener(event -> saveDocument());
return saveButton; return saveButton;
} }
protected Button createCloseButton() { protected Button createCloseButton() {
Button closeButton = new Button("Salir"); Button closeButton = new Button("Close");
closeButton.addClickListener(event -> closeForm()); closeButton.addClickListener(event -> closeForm());
return closeButton; return closeButton;
} }
protected Button createViewDocumentButton() { protected Button createViewDocumentButton() {
viewDocumentButton = new Button("Ver documento"); viewDocumentButton = new Button("View Document");
viewDocumentButton.setEnabled(false); viewDocumentButton.setEnabled(false);
viewDocumentButton.addClickListener(event -> viewDocument()); viewDocumentButton.addClickListener(event -> viewDocument());
return viewDocumentButton; return viewDocumentButton;
@ -130,7 +130,7 @@ public class DocumentView extends BeanValidationForm<Document> implements HasUrl
ui.getPage().open(registration.getResourceUri().toString()); ui.getPage().open(registration.getResourceUri().toString());
}); });
} catch (IOException e) { } catch (IOException e) {
Notification.show("Error al leer el archivo."); Notification.show("Error reading file.");
} }
} }
@ -148,10 +148,10 @@ public class DocumentView extends BeanValidationForm<Document> implements HasUrl
setDocumentCreator(document); setDocumentCreator(document);
documentService.saveDocument(document); documentService.saveDocument(document);
Notification.show("Archivo guardado correctamente."); Notification.show("File saved successfully.");
clearForm(); clearForm();
} else { } else {
Notification.show("Error al guardar: Por favor, complete todos los campos y cargue un archivo."); Notification.show("Save failed: Please complete all fields and upload a file.");
} }
} }
@ -179,7 +179,7 @@ public class DocumentView extends BeanValidationForm<Document> implements HasUrl
try { try {
return buffer.getInputStream().readAllBytes(); return buffer.getInputStream().readAllBytes();
} catch (IOException e) { } catch (IOException e) {
Notification.show("Error al leer los datos del archivo."); Notification.show("Error reading file data.");
return new byte[0]; return new byte[0];
} }
} }
@ -220,13 +220,13 @@ public class DocumentView extends BeanValidationForm<Document> implements HasUrl
uploadButton.setAcceptedFileTypes(".pdf"); uploadButton.setAcceptedFileTypes(".pdf");
uploadButton.addSucceededListener(event -> { uploadButton.addSucceededListener(event -> {
fileUploaded = true; fileUploaded = true;
Notification.show("Archivo cargado correctamente."); Notification.show("File uploaded successfully.");
viewDocumentButton.setEnabled(true); viewDocumentButton.setEnabled(true);
updateSaveButtonState(); updateSaveButtonState();
}); });
uploadButton.getElement().addEventListener("file-remove", event -> { uploadButton.getElement().addEventListener("file-remove", event -> {
fileUploaded = false; fileUploaded = false;
Notification.show("Archivo eliminado."); Notification.show("File removed.");
viewDocumentButton.setEnabled(false); viewDocumentButton.setEnabled(false);
updateSaveButtonState(); updateSaveButtonState();
}); });

View File

@ -5,22 +5,13 @@ import com.primefactorsolutions.model.DocumentType;
import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.model.Employee;
import com.primefactorsolutions.service.DocumentService; import com.primefactorsolutions.service.DocumentService;
import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.views.util.MenuBarUtils;
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.UI; import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.contextmenu.MenuItem;
import com.vaadin.flow.component.grid.GridSortOrder; import com.vaadin.flow.component.grid.GridSortOrder;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.html.Span; import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.menubar.MenuBar;
import com.vaadin.flow.component.menubar.MenuBarVariant;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.data.provider.SortDirection; import com.vaadin.flow.data.provider.SortDirection;
import com.vaadin.flow.function.ValueProvider;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.StreamRegistration; import com.vaadin.flow.server.StreamRegistration;
@ -33,14 +24,13 @@ import org.vaadin.firitin.components.grid.PagingGrid;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.util.List; import java.util.List;
import static com.primefactorsolutions.views.Constants.PAGE_SIZE;
@SpringComponent @SpringComponent
@Scope("prototype") @Scope("prototype")
@PageTitle("Documents") @PageTitle("Documents")
@Route(value = "/documents", layout = MainLayout.class) @Route(value = "/documents", layout = MainLayout.class)
@PermitAll @PermitAll
public class DocumentsListView extends BaseView { public class DocumentsListView extends Main {
private final DocumentService documentService; private final DocumentService documentService;
private final EmployeeService employeeService; private final EmployeeService employeeService;
@ -56,24 +46,16 @@ public class DocumentsListView extends BaseView {
} }
private void initializeView() { private void initializeView() {
getCurrentPageLayout().add(createActionButton("Añadir documento", this::navigateToAddDocumentView));
final HorizontalLayout hl = new HorizontalLayout();
hl.add(createDocumentTypeFilter());
hl.add(createEmployeeFilter());
getCurrentPageLayout().add(hl);
configureDocumentGrid(); configureDocumentGrid();
getCurrentPageLayout().add(documentGrid); add(createActionButton("Add Document", this::navigateToAddDocumentView));
add(createDocumentTypeFilter());
add(createEmployeeFilter());
add(documentGrid);
} }
private void configureDocumentGrid() { private void configureDocumentGrid() {
documentGrid.setColumns("fileName", "documentType", "creator"); documentGrid.setColumns("fileName", "documentType", "creator");
documentGrid.getColumnByKey("fileName").setHeader("Nombre archivo"); documentGrid.addComponentColumn(this::createEmployeeSpan).setHeader("Employee");
documentGrid.getColumnByKey("documentType").setHeader("Tipo");
documentGrid.getColumnByKey("creator").setHeader("Creador");
documentGrid.addComponentColumn(this::createEmployeeSpan).setHeader("Empleado");
addActionColumns(); addActionColumns();
configurePagination(); configurePagination();
} }
@ -85,20 +67,13 @@ public class DocumentsListView extends BaseView {
} }
private void addActionColumns() { private void addActionColumns() {
documentGrid.addComponentColumn((ValueProvider<Document, Component>) document -> { addDocumentActionColumn("View", this::navigateToDocumentView);
final MenuBar menuBar = new MenuBar(); addDocumentActionColumn("Edit", this::navigateToEditDocumentView);
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE); addDocumentActionColumn("Download", this::downloadDocument);
final MenuItem viewItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.EYE, "Ver"); }
viewItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent ->
navigateToDocumentView(document)); private void addDocumentActionColumn(final String label, final DocumentActionHandler handler) {
final MenuItem editItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.PENCIL, "Editar"); documentGrid.addComponentColumn(document -> createActionButton(label, () -> handler.handle(document)));
editItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent ->
navigateToEditDocumentView(document));
final MenuItem downloadItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.DOWNLOAD, "Descargar");
downloadItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent ->
downloadDocument(document));
return menuBar;
});
} }
private Button createActionButton(final String label, final Runnable onClickAction) { private Button createActionButton(final String label, final Runnable onClickAction) {
@ -108,7 +83,7 @@ public class DocumentsListView extends BaseView {
} }
private ComboBox<DocumentType> createDocumentTypeFilter() { private ComboBox<DocumentType> createDocumentTypeFilter() {
documentTypeFilter = new ComboBox<>("Tipo de documento"); documentTypeFilter = new ComboBox<>("Document Type");
documentTypeFilter.setItems(DocumentType.values()); documentTypeFilter.setItems(DocumentType.values());
documentTypeFilter.setValue(DocumentType.values()[0]); documentTypeFilter.setValue(DocumentType.values()[0]);
documentTypeFilter.addValueChangeListener(event -> { documentTypeFilter.addValueChangeListener(event -> {
@ -118,7 +93,7 @@ public class DocumentsListView extends BaseView {
} }
private ComboBox<Employee> createEmployeeFilter() { private ComboBox<Employee> createEmployeeFilter() {
employeeFilter = new ComboBox<>("Empleado"); employeeFilter = new ComboBox<>("Employee");
List<Employee> employees = employeeService.findAllEmployees(); List<Employee> employees = employeeService.findAllEmployees();
employees.addFirst(createAllEmployeesOption()); employees.addFirst(createAllEmployeesOption());
employeeFilter.setItems(employees); employeeFilter.setItems(employees);
@ -132,13 +107,12 @@ public class DocumentsListView extends BaseView {
private Employee createAllEmployeesOption() { private Employee createAllEmployeesOption() {
Employee allEmployeesOption = new Employee(); Employee allEmployeesOption = new Employee();
allEmployeesOption.setFirstName("TODOS"); allEmployeesOption.setFirstName("All");
return allEmployeesOption; return allEmployeesOption;
} }
private String getEmployeeLabel(final Employee employee) { private String getEmployeeLabel(final Employee employee) {
return employee.getFirstName().equals("TODOS") return employee.getFirstName().equals("All") ? "All" : employee.getFirstName() + " " + employee.getLastName();
? "TODOS" : employee.getFirstName() + " " + employee.getLastName();
} }
private void navigateToEditDocumentView(final Document document) { private void navigateToEditDocumentView(final Document document) {
@ -159,7 +133,7 @@ public class DocumentsListView extends BaseView {
private void configurePagination() { private void configurePagination() {
documentGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM); documentGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
documentGrid.setPageSize(PAGE_SIZE); documentGrid.setPageSize(5);
} }
private void updateDocumentGrid(final DocumentType documentType, final Employee employee) { private void updateDocumentGrid(final DocumentType documentType, final Employee employee) {
@ -223,4 +197,9 @@ public class DocumentsListView extends BaseView {
StreamRegistration registration = ui.getSession().getResourceRegistry().registerResource(resource); StreamRegistration registration = ui.getSession().getResourceRegistry().registerResource(resource);
ui.getPage().open(registration.getResourceUri().toString()); ui.getPage().open(registration.getResourceUri().toString());
} }
@FunctionalInterface
private interface DocumentActionHandler {
void handle(Document document);
}
} }

View File

@ -50,10 +50,13 @@ import java.util.UUID;
@PageTitle("Employee") @PageTitle("Employee")
@Route(value = "/employees/:employeeId?/:action?", layout = MainLayout.class) @Route(value = "/employees/:employeeId?/:action?", layout = MainLayout.class)
public class EmployeeView extends BeanValidationForm<Employee> implements HasUrlParameter<String> { public class EmployeeView extends BeanValidationForm<Employee> implements HasUrlParameter<String> {
private final EmployeeService employeeService; private final EmployeeService employeeService;
private final ReportService reportService; private final ReportService reportService;
private final TimeOffRequestService requestService; private final TimeOffRequestService requestService;
private final TeamService teamService; private final TeamService teamService;
// TODO: campo usado para registrar al empleado en LDAP. Este campo podria estar en otro form eventualmente. // TODO: campo usado para registrar al empleado en LDAP. Este campo podria estar en otro form eventualmente.
private final TextField username = createTextField("Username: ", 30, true); private final TextField username = createTextField("Username: ", 30, true);
private final TextField firstName = createTextField("Nombres: ", 30, true); private final TextField firstName = createTextField("Nombres: ", 30, true);
@ -62,27 +65,30 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
private final ComboBox<Employee.Gender> gender = createGenderComboBox(); private final ComboBox<Employee.Gender> gender = createGenderComboBox();
private final VDatePicker birthday = new VDatePicker("Fecha de Nacimiento"); private final VDatePicker birthday = new VDatePicker("Fecha de Nacimiento");
private final TextField age = createTextField("Edad", 3, false); private final TextField age = createTextField("Edad", 3, false);
private final TextField birthCity = createTextField("Ciudad y País de Nacimiento ejemplo: (Ciudad, País) ", private final TextField birthCity = createTextField("Ciudad y País de Nacimiento", 20, false);
30, false);
private final TextField residenceAddress = createTextField("Dirección de Residencia", 50, false); private final TextField residenceAddress = createTextField("Dirección de Residencia", 50, false);
private final TextField localAddress = createTextField("Departamento y Provincia de Residencia " private final TextField localAddress = createTextField("Dep/Provincia de Residencia", 10, false);
+ " ejemplo: (Departamento-Provincia)", 30, false);
private final ComboBox<Employee.MaritalStatus> maritalStatus = createMaritalStatusComboBox(); private final ComboBox<Employee.MaritalStatus> maritalStatus = createMaritalStatusComboBox();
private final TextField numberOfChildren = createTextField("Numero de Hijos", 1, false); private final TextField numberOfChildren = createTextField("Numero de Hijos", 3, false);
private final TextField ci = createTextField("CI", 10, false); private final TextField ci = createTextField("CI", 30, false);
private final TextField issuedIn = createTextField("Expedido en ", 10, false); private final TextField issuedIn = createTextField("Expedido en ", 30, false);
private final TextField phoneNumber = createTextField("Teléfono", 8, false); private final TextField phoneNumber = createTextField("Teléfono", 8, false);
private final EmailField personalEmail = createEmailField("E-mail ejemplo: (ejemplo@gmail.com)"); private final EmailField personalEmail = createEmailField("E-mail");
private final TextField phoneNumberProfesional = createTextField("Teléfono Laboral", 8, false); private final TextField cod = createTextField("Codigo de Empleado", 30, false);
private final EmailField profesionalEmail = createEmailField("E-mail Laboral ejemplo: " private final TextField position = createTextField("Cargo", 30, false);
+ "(ejemplo@primerfactorsolutions.com)"); private final ComboBox<Team> team = new ComboBox<>("Equipo");
private final TextField leadManager = createTextField("Lead/Manager", 30, false);
private final TextField project = createTextField("Proyecto", 30, false);
private final TextField emergencyCName = createTextField("Nombres y Apellidos de Contacto", 50, 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 emergencyCAddress = createTextField("Dirección de Contacto", 50, false);
private final TextField emergencyCPhone = createTextField("Teléfono de Contacto", 8, false); private final TextField emergencyCPhone = createTextField("Teléfono de Contacto", 8, false);
private final EmailField emergencyCEmail = createEmailField("Email de Contacto ejemplo: (ejemplo@gmail.com)"); private final EmailField emergencyCEmail = createEmailField("Email de Contacto");
private final MemoryBuffer buffer = new MemoryBuffer(); private final MemoryBuffer buffer = new MemoryBuffer();
private final Upload upload = new Upload(buffer); private final Upload upload = new Upload(buffer);
private final Image profileImagePreview = new Image(); private final Image profileImagePreview = new Image();
//INFORMACION PROFESIONAL
private final TextField pTitle1 = createTextField("Título 1", 30, false); private final TextField pTitle1 = createTextField("Título 1", 30, false);
private final TextField pTitle2 = createTextField("Título 2", 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 pTitle3 = createTextField("Título 3", 30, false);
@ -95,49 +101,47 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
private final TextField certification4 = createTextField("Certificación 4", 30, false); private final TextField certification4 = createTextField("Certificación 4", 30, false);
private final TextField recognition = createTextField("Reconocimientos", 30, false); private final TextField recognition = createTextField("Reconocimientos", 30, false);
private final TextField achievements = createTextField("Logros Profesionales", 30, false); private final TextField achievements = createTextField("Logros Profesionales", 30, false);
private final TextField language1 = createTextField("Idioma 1", 30, false); private final TextField language = createTextField("Idioma", 30, false);
private final TextField language1Level = createTextField("Nivel de Idioma", 30, false); private final TextField languageLevel = 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); //INFORMACION DE CONTRATACION
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");
private final TextField leadManager = createTextField("Lead/Manager", 30, false);
private final VDatePicker dateOfEntry = new VDatePicker("Fecha de Ingreso"); private final VDatePicker dateOfEntry = new VDatePicker("Fecha de Ingreso");
private final VDatePicker dateOfExit = new VDatePicker("Fecha de Retiro"); private final VDatePicker dateOfExit = new VDatePicker("Fecha de Retiro");
private final ComboBox<Employee.ContractType> contractType = createContractTypeComboBox(); private final TextField contractType = createTextField("Tipo de Contratación", 30, false);
private final TextField seniority = createTextField("Antiguedad", 30, false); private final TextField seniority = createTextField("Antiguedad", 30, false);
private final TextField salaryTotal = createTextField("Salario Total", 10, false); private final TextField salary = createTextField("Salario", 30, false);
private final TextField salaryBasic = createTextField("Salario Basico", 10, false);
private final TextField antiguedad = createTextField("Descuento por Antiguedad", 10, false);
private final TextField bonoProfesional = createTextField("Bono Profesional", 30, false);
private final TextField bankName = createTextField("Banco", 30, false); private final TextField bankName = createTextField("Banco", 30, false);
private final TextField accountNumber = createTextField("Nro. de Cuenta", 30, false); private final TextField accountNumber = createTextField("Nro. de Cuenta", 30, false);
private final TextField gpss = createTextField("Código Único de Asegurado (GPSS)", 30, false); private final TextField gpss = createTextField("Código Único de Asegurado (GPSS)", 30, false);
private final TextField sss = createTextField("Matricula de Asegurado (SSS)", 30, false); private final TextField sss = createTextField("Matricula de Asegurado (SSS)", 30, false);
private final TextField beneficiarie1 = createTextField("Derechohabiente 1", 30, false); private final TextField beneficiaries = createTextField("Derechohabientes", 30, false);
private final TextField beneficiarie2 = createTextField("Derechohabiente 2", 30, false);
private static final String SAVE_BUTTON_TEXT = "Save"; private static final String SAVE_BUTTON_TEXT = "Save";
private static final String EDIT_BUTTON_TEXT = "Edit"; private static final String EDIT_BUTTON_TEXT = "Edit";
private static final String NOTIFICATION_SAVE_SUCCESS = "Employee saved successfully."; private static final String NOTIFICATION_SAVE_SUCCESS = "Employee saved successfully.";
private static final String NOTIFICATION_VALIDATE_ERROR = "Please complete the required fields correctly."; private static final String NOTIFICATION_VALIDATE_ERROR = "Please complete the required fields correctly.";
private static final String PHONE_NUMBER_ERROR_MESSAGE = "El teléfono debe contener solo números."; 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 saveButton = new Button(SAVE_BUTTON_TEXT, e -> saveEmployee());
private final Button editButton = new Button(EDIT_BUTTON_TEXT, e -> enableEditMode()); 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");
private final Dialog dialog = new Dialog(); private final Dialog dialog = new Dialog();
private final PdfViewer pdfViewer = new PdfViewer(); private final PdfViewer pdfViewer = new PdfViewer();
//TITULOS PARA INFORMACION PERSONAL
private final H2 infoPer = new H2("Información Personal"); private final H2 infoPer = new H2("Información Personal");
private final H3 infoGenr = new H3("Información General"); private final H3 infoGenr = new H3("Información General");
private final H3 contEmerg = new H3("Contacto de Emergencia"); private final H3 contEmerg = new H3("Contacto de Emergencia");
//TITULOS PARA INFORMACIÓN PROFESIONAL
private final H2 infProf = new H2("Información Profesional"); private final H2 infProf = new H2("Información Profesional");
private final H3 titulos = new H3("Titulos Profesionales y Estudios Realizados"); private final H3 titulos = new H3("Titulos Profesionales y Estudios Realizados");
private final H3 certif = new H3("Certificaciones Profesionales"); private final H3 certif = new H3("Certificaciones Profesionales");
private final H3 logros = new H3("Otros Logros y Reconocimientos"); private final H3 logros = new H3("Otros Logros y Reconocimientos");
private final H3 idioma = new H3("Dominio de Idiomas"); private final H3 idioma = new H3("Dominio de Idiomas");
//TITULOS PARA INFORMACIÓN ADMINISTRATIVA
private final H2 infoAdm = new H2("Información Administrativa"); private final H2 infoAdm = new H2("Información Administrativa");
private final H3 infoCont = new H3("Información de Contratación"); private final H3 infoCont = new H3("Información de Contratación");
private final H3 datBanc = new H3("Datos Bancarios"); private final H3 datBanc = new H3("Datos Bancados");
private final H3 datGest = new H3("Datos Gestora Pública y Seguro Social"); private final H3 datGest = new H3("Datos Gestora Pública y Seguro Social");
public EmployeeView(final EmployeeService employeeService, public EmployeeView(final EmployeeService employeeService,
@ -150,44 +154,29 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
this.requestService = requestService; this.requestService = requestService;
this.teamService = teamService; this.teamService = teamService;
saveButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); saveButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
configureComponents(); configureComponents();
addClassName("main-layout"); addClassName("main-layout");
} }
private void makeUpperCase(final TextField textField) {
textField.addValueChangeListener(event -> {
String value = event.getValue();
if (value != null) {
textField.setValue(value.toUpperCase());
}
});
}
private void configureComponents() { private void configureComponents() {
phoneNumber.setValueChangeMode(ValueChangeMode.EAGER); phoneNumber.setValueChangeMode(ValueChangeMode.EAGER);
phoneNumber.addValueChangeListener(e -> validatePhoneNumber(phoneNumber, e.getValue())); phoneNumber.addValueChangeListener(e -> validatePhoneNumber(phoneNumber, e.getValue()));
emergencyCPhone.setValueChangeMode(ValueChangeMode.EAGER); emergencyCPhone.setValueChangeMode(ValueChangeMode.EAGER);
emergencyCPhone.addValueChangeListener(e -> validatePhoneNumber(emergencyCPhone, e.getValue())); emergencyCPhone.addValueChangeListener(e -> validatePhoneNumber(emergencyCPhone, e.getValue()));
firstName.setValueChangeMode(ValueChangeMode.EAGER); firstName.setValueChangeMode(ValueChangeMode.EAGER);
firstName.addValueChangeListener(e -> validateNameField(firstName, e.getValue())); firstName.addValueChangeListener(e -> validateNameField(firstName, e.getValue()));
lastName.setValueChangeMode(ValueChangeMode.EAGER); lastName.setValueChangeMode(ValueChangeMode.EAGER);
lastName.addValueChangeListener(e -> validateNameField(lastName, e.getValue())); lastName.addValueChangeListener(e -> validateNameField(lastName, e.getValue()));
createTeamComboBox(); createTeamComboBox();
configureUpload(); configureUpload();
saveButton.setVisible(true); saveButton.setVisible(true);
editButton.setVisible(true); editButton.setVisible(true);
reportButton.setVisible(true); reportButton.setVisible(true);
birthday.addValueChangeListener(event -> calculateAge()); birthday.addValueChangeListener(event -> calculateAge());
birthday.setMax(java.time.LocalDate.now().minusYears(18));
salaryTotal.addValueChangeListener(event -> calculateSalaryTotal());
dateOfEntry.addValueChangeListener(event -> calculateSeniority());
dateOfExit.addValueChangeListener(event -> {
if (event.getValue() != null) {
status.setValue(Employee.Status.INACTIVE);
} else {
status.setValue(Employee.Status.ACTIVE);
}
});
reportButton.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> { reportButton.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
var employee = getEntity(); var employee = getEntity();
byte[] pdfContent = reportService.writeAsPdf("ficha", employee); byte[] pdfContent = reportService.writeAsPdf("ficha", employee);
@ -196,41 +185,6 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
dialog.open(); dialog.open();
}); });
makeUpperCase(firstName);
makeUpperCase(lastName);
makeUpperCase(birthCity);
makeUpperCase(residenceAddress);
makeUpperCase(localAddress);
makeUpperCase(position);
makeUpperCase(emergencyCName);
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);
makeUpperCase(bankName);
makeUpperCase(accountNumber);
makeUpperCase(gpss);
makeUpperCase(sss);
makeUpperCase(beneficiarie1);
makeUpperCase(beneficiarie2);
initDialog(); initDialog();
} }
@ -249,61 +203,10 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
int birthYear = birthday.getValue().getYear(); int birthYear = birthday.getValue().getYear();
int ages = currentYear - birthYear; int ages = currentYear - birthYear;
age.setValue(String.valueOf(ages)); age.setValue(String.valueOf(ages));
birthday.setInvalid(ages < 18);
System.out.println(age); System.out.println(age);
} }
} }
private void calculateSeniority() {
LocalDate entryDate = dateOfEntry.getValue();
LocalDate exitDate = dateOfExit.getValue() != null ? dateOfExit.getValue() : LocalDate.now();
if (entryDate != null) {
long yearsOfService = ChronoUnit.YEARS.between(entryDate, exitDate);
String seniorityValue = yearsOfService + " años ";
seniority.setValue(seniorityValue);
} else {
seniority.setValue("No disponible");
}
}
private void calculateSalaryTotal() {
if (contractType.getValue() == Employee.ContractType.CONTRATO_LABORAL) {
salaryBasic.setVisible(true);
bonoProfesional.setVisible(true);
antiguedad.setVisible(true);
salaryTotal.setVisible(true);
salaryBasic.addValueChangeListener(event -> updateTotalSalary());
bonoProfesional.addValueChangeListener(event -> updateTotalSalary());
antiguedad.addValueChangeListener(event -> updateTotalSalary());
} else {
salaryBasic.setVisible(false);
bonoProfesional.setVisible(false);
antiguedad.setVisible(false);
salaryTotal.setVisible(true);
}
salaryTotal.getValue();
}
private void updateTotalSalary() {
try {
double basic = parseDoubleValue(salaryBasic.getValue());
double bonus = parseDoubleValue(bonoProfesional.getValue());
double seniorityBonus = parseDoubleValue(antiguedad.getValue());
double totalSalary = basic + bonus + seniorityBonus;
salaryTotal.setValue(String.valueOf(totalSalary));
} catch (Exception e) {
salaryTotal.setValue("0.0");
}
}
private double parseDoubleValue(final String value) {
try {
return value != null && !value.isEmpty() ? Double.parseDouble(value) : 0.0;
} catch (NumberFormatException e) {
return 0.0;
}
}
private void configureUpload() { private void configureUpload() {
upload.setAcceptedFileTypes("image/jpeg", "image/png"); upload.setAcceptedFileTypes("image/jpeg", "image/png");
upload.setMaxFileSize(1024 * 1024); upload.setMaxFileSize(1024 * 1024);
@ -312,16 +215,14 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
buffer.getInputStream().transferTo(outputStream); buffer.getInputStream().transferTo(outputStream);
byte[] imageBytes = outputStream.toByteArray(); byte[] imageBytes = outputStream.toByteArray();
String base64Image = Base64.getEncoder().encodeToString(imageBytes); String base64Image = Base64.getEncoder().encodeToString(imageBytes);
getEntity().setProfileImage(base64Image); getEntity().setProfileImage(base64Image);
profileImagePreview.setSrc("data:image/png;base64," + base64Image);
profileImagePreview.setSrc("data:image/jpeg;base64," + base64Image);
profileImagePreview.setMaxWidth("150px"); profileImagePreview.setMaxWidth("150px");
profileImagePreview.setMaxHeight("150px"); profileImagePreview.setMaxHeight("150px");
} catch (IOException e) { } catch (IOException e) {
Notification.show("Error al subir la imagen: " + e.getMessage()); Notification.show("Error al subir la imagen.");
e.printStackTrace();
} catch (Exception e) {
Notification.show("Error en el servidor al procesar la imagen.");
e.printStackTrace();
} }
}); });
} }
@ -337,9 +238,11 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
H2 headline = new H2("Ficha Empleado"); H2 headline = new H2("Ficha Empleado");
headline.getStyle().set("margin", "var(--lumo-space-m) 0 0 0") headline.getStyle().set("margin", "var(--lumo-space-m) 0 0 0")
.set("font-size", "1.5em").set("font-weight", "bold"); .set("font-size", "1.5em").set("font-weight", "bold");
final Button cancelDialogButton = new Button("Close", e -> dialog.close()); final Button cancelDialogButton = new Button("Close", e -> dialog.close());
final HorizontalLayout buttonLayout = new HorizontalLayout(cancelDialogButton); final HorizontalLayout buttonLayout = new HorizontalLayout(cancelDialogButton);
buttonLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.END); buttonLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.END);
final VerticalLayout dialogLayout = new VerticalLayout(headline, pdfViewer, buttonLayout); final VerticalLayout dialogLayout = new VerticalLayout(headline, pdfViewer, buttonLayout);
dialogLayout.getStyle().set("height", "100%"); dialogLayout.getStyle().set("height", "100%");
dialogLayout.getStyle().set("overflow", "hidden"); dialogLayout.getStyle().set("overflow", "hidden");
@ -349,6 +252,7 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
dialogLayout.setAlignItems(FlexComponent.Alignment.STRETCH); dialogLayout.setAlignItems(FlexComponent.Alignment.STRETCH);
dialogLayout.getStyle().set("width", "700px").set("max-width", "100%"); dialogLayout.getStyle().set("width", "700px").set("max-width", "100%");
dialogLayout.getStyle().set("height", "800px").set("max-height", "100%"); dialogLayout.getStyle().set("height", "800px").set("max-height", "100%");
dialog.add(dialogLayout); dialog.add(dialogLayout);
} }
@ -367,16 +271,6 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
return comboBox; return comboBox;
} }
private ComboBox<Employee.ContractType> createContractTypeComboBox() {
ComboBox<Employee.ContractType> comboBox = new ComboBox<>("Tipo de Contrato");
comboBox.setItems(Employee.ContractType.values());
comboBox.setItemLabelGenerator(Employee.ContractType::name);
comboBox.setRequiredIndicatorVisible(true);
comboBox.setWidth("300px");
comboBox.setMinWidth("200px");
return comboBox;
}
private VerticalLayout createContentLayout() { private VerticalLayout createContentLayout() {
VerticalLayout contentLayout = new VerticalLayout(); VerticalLayout contentLayout = new VerticalLayout();
contentLayout.setWidth("100%"); contentLayout.setWidth("100%");
@ -394,7 +288,7 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
private EmailField createEmailField(final String label) { private EmailField createEmailField(final String label) {
EmailField emailField = new EmailField(label); EmailField emailField = new EmailField(label);
emailField.setWidthFull(); emailField.setWidthFull();
emailField.setMaxLength(50); emailField.setMaxLength(30);
return emailField; return emailField;
} }
@ -450,10 +344,7 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
Employee employee = getEntity(); Employee employee = getEntity();
employee.setStatus(status.getValue()); employee.setStatus(status.getValue());
employee.setAge(age.getValue()); employee.setAge(age.getValue());
employee.setSalaryBasic(salaryBasic.getValue());
employee.setBonoProfesional(bonoProfesional.getValue());
employee.setAntiguedad(antiguedad.getValue());
employee.setSalarytotal((salaryTotal.getValue()));
employeeService.createOrUpdate(employee); employeeService.createOrUpdate(employee);
Notification.show(NOTIFICATION_SAVE_SUCCESS); Notification.show(NOTIFICATION_SAVE_SUCCESS);
getUI().ifPresent(ui -> ui.navigate(EmployeesListView.class)); getUI().ifPresent(ui -> ui.navigate(EmployeesListView.class));
@ -472,33 +363,28 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
public void setParameter(final BeforeEvent beforeEvent, final String action) { public void setParameter(final BeforeEvent beforeEvent, final String action) {
final RouteParameters params = beforeEvent.getRouteParameters(); final RouteParameters params = beforeEvent.getRouteParameters();
final String s = params.get("employeeId").orElse(null); final String s = params.get("employeeId").orElse(null);
if ("new".equals(action)) { if ("new".equals(action)) {
setEntityWithEnabledSave(new Employee()); setEntityWithEnabledSave(new Employee());
saveButton.setVisible(true); saveButton.setVisible(true);
editButton.setVisible(false); editButton.setVisible(false);
setFieldsEditable(); setFieldsEditable();
upload.setVisible(true);
salaryTotal.setValue(String.valueOf(true));
} else { } else {
UUID employeeId = UUID.fromString(s); UUID employeeId = UUID.fromString(s);
var employee = employeeService.getEmployee(employeeId); var employee = employeeService.getEmployee(employeeId);
setEntityWithEnabledSave(employee); setEntityWithEnabledSave(employee);
if ("edit".equals(action) && !s.isEmpty()) { if ("edit".equals(action) && !s.isEmpty()) {
saveButton.setVisible(true); saveButton.setVisible(true);
editButton.setVisible(false); editButton.setVisible(false);
status.setValue(employee.getStatus()); status.setValue(employee.getStatus());
setFieldsEditable(); setFieldsEditable();
upload.setVisible(true);
displayProfileImage(employee);
salaryTotal.setValue(employee.getSalarytotal());
} else if ("view".equals(action) && !s.isEmpty()) { } else if ("view".equals(action) && !s.isEmpty()) {
setFieldsReadOnly(); setFieldsReadOnly();
saveButton.setVisible(false); saveButton.setVisible(false);
editButton.setVisible(true); editButton.setVisible(true);
setFieldsReadOnly(); setFieldsReadOnly();
displayProfileImage(employee); displayProfileImage(employee);
upload.setVisible(true);
salaryTotal.setValue(employee.getSalarytotal());
} }
} }
} }
@ -507,17 +393,18 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
if (employee.getProfileImage() != null && !employee.getProfileImage().isEmpty()) { if (employee.getProfileImage() != null && !employee.getProfileImage().isEmpty()) {
profileImagePreview.setSrc("data:image/jpeg;base64," + employee.getProfileImage()); profileImagePreview.setSrc("data:image/jpeg;base64," + employee.getProfileImage());
profileImagePreview.setVisible(true); profileImagePreview.setVisible(true);
profileImagePreview.setMaxWidth("250px"); profileImagePreview.setMaxWidth("150px");
profileImagePreview.setMaxHeight("250px"); profileImagePreview.setMaxHeight("150px");
upload.setVisible(true);
upload.setVisible(false);
} else { } else {
profileImagePreview.setVisible(true); profileImagePreview.setVisible(false);
upload.setVisible(true); upload.setVisible(true);
} }
} }
private void setFieldsReadOnly() { private void setFieldsReadOnly() {
username.setReadOnly(true); username.setReadOnly(false);
firstName.setReadOnly(true); firstName.setReadOnly(true);
lastName.setReadOnly(true); lastName.setReadOnly(true);
status.setReadOnly(true); status.setReadOnly(true);
@ -529,8 +416,6 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
numberOfChildren.setReadOnly(true); numberOfChildren.setReadOnly(true);
phoneNumber.setReadOnly(true); phoneNumber.setReadOnly(true);
personalEmail.setReadOnly(true); personalEmail.setReadOnly(true);
phoneNumberProfesional.setReadOnly(true);
profesionalEmail.setReadOnly(true);
position.setReadOnly(true); position.setReadOnly(true);
team.setReadOnly(true); team.setReadOnly(true);
emergencyCName.setReadOnly(true); emergencyCName.setReadOnly(true);
@ -556,26 +441,21 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
certification4.setReadOnly(true); certification4.setReadOnly(true);
recognition.setReadOnly(true); recognition.setReadOnly(true);
achievements.setReadOnly(true); achievements.setReadOnly(true);
language1.setReadOnly(true); language.setReadOnly(true);
language1Level.setReadOnly(true); languageLevel.setReadOnly(true);
language2.setReadOnly(true);
language2Level.setReadOnly(true);
cod.setReadOnly(true); cod.setReadOnly(true);
leadManager.setReadOnly(true); leadManager.setReadOnly(true);
project.setReadOnly(true);
dateOfEntry.setReadOnly(true); dateOfEntry.setReadOnly(true);
dateOfExit.setReadOnly(true); dateOfExit.setReadOnly(true);
contractType.setReadOnly(true); contractType.setReadOnly(true);
seniority.setReadOnly(true); seniority.setReadOnly(true);
salaryTotal.setReadOnly(true); salary.setReadOnly(true);
salaryBasic.setReadOnly(true);
bonoProfesional.setReadOnly(true);
antiguedad.setReadOnly(true);
bankName.setReadOnly(true); bankName.setReadOnly(true);
accountNumber.setReadOnly(true); accountNumber.setReadOnly(true);
gpss.setReadOnly(true); gpss.setReadOnly(true);
sss.setReadOnly(true); sss.setReadOnly(true);
beneficiarie1.setReadOnly(true); beneficiaries.setReadOnly(true);
beneficiarie2.setReadOnly(true);
} }
private void setFieldsEditable() { private void setFieldsEditable() {
@ -591,8 +471,6 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
numberOfChildren.setReadOnly(false); numberOfChildren.setReadOnly(false);
phoneNumber.setReadOnly(false); phoneNumber.setReadOnly(false);
personalEmail.setReadOnly(false); personalEmail.setReadOnly(false);
phoneNumberProfesional.setReadOnly(false);
profesionalEmail.setReadOnly(false);
position.setReadOnly(false); position.setReadOnly(false);
team.setReadOnly(false); team.setReadOnly(false);
emergencyCName.setReadOnly(false); emergencyCName.setReadOnly(false);
@ -600,7 +478,6 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
emergencyCPhone.setReadOnly(false); emergencyCPhone.setReadOnly(false);
emergencyCEmail.setReadOnly(false); emergencyCEmail.setReadOnly(false);
upload.setVisible(false); upload.setVisible(false);
profileImagePreview.setVisible(true);
age.setReadOnly(false); age.setReadOnly(false);
gender.setReadOnly(false); gender.setReadOnly(false);
status.setReadOnly(false); status.setReadOnly(false);
@ -618,26 +495,21 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
certification4.setReadOnly(false); certification4.setReadOnly(false);
recognition.setReadOnly(false); recognition.setReadOnly(false);
achievements.setReadOnly(false); achievements.setReadOnly(false);
language1.setReadOnly(false); language.setReadOnly(false);
language1Level.setReadOnly(false); languageLevel.setReadOnly(false);
language2.setReadOnly(false);
language2Level.setReadOnly(false);
cod.setReadOnly(false); cod.setReadOnly(false);
leadManager.setReadOnly(false); leadManager.setReadOnly(false);
project.setReadOnly(false);
dateOfEntry.setReadOnly(false); dateOfEntry.setReadOnly(false);
dateOfExit.setReadOnly(false); dateOfExit.setReadOnly(false);
contractType.setReadOnly(false); contractType.setReadOnly(false);
seniority.setReadOnly(false); seniority.setReadOnly(false);
salaryTotal.setReadOnly(false); salary.setReadOnly(false);
salaryBasic.setReadOnly(false);
bonoProfesional.setReadOnly(false);
antiguedad.setReadOnly(false);
bankName.setReadOnly(false); bankName.setReadOnly(false);
accountNumber.setReadOnly(false); accountNumber.setReadOnly(false);
gpss.setReadOnly(false); gpss.setReadOnly(false);
sss.setReadOnly(false); sss.setReadOnly(false);
beneficiarie1.setReadOnly(false); beneficiaries.setReadOnly(false);
beneficiarie2.setReadOnly(false);
} }
@Override @Override
@ -652,19 +524,18 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
birthday, age, birthday, age,
birthCity, residenceAddress, localAddress, birthCity, residenceAddress, localAddress,
maritalStatus, ci, issuedIn, numberOfChildren, maritalStatus, ci, issuedIn, numberOfChildren,
phoneNumber, personalEmail, phoneNumberProfesional, profesionalEmail, phoneNumber, personalEmail,
cod, position, team, leadManager, project,
contEmerg, emergencyCName, emergencyCAddress, emergencyCPhone, emergencyCEmail, contEmerg, emergencyCName, emergencyCAddress, emergencyCPhone, emergencyCEmail,
infProf, infProf,
titulos, pTitle1, pTitle2, pTitle3, pStudy1, pStudy2, pStudy3, titulos, pTitle1, pTitle2, pTitle3, pStudy1, pStudy2, pStudy3,
certif, certification1, certification2, certification3, certification4, certif, certification1, certification2, certification3, certification4,
logros, recognition, achievements, logros, recognition, achievements,
idioma, language1, language1Level, language2, language2Level, idioma, language, languageLevel,
infoAdm, infoAdm,
cod, position, team, leadManager, infoCont, dateOfEntry, dateOfExit, contractType, seniority, salary,
infoCont, dateOfEntry, dateOfExit, contractType, seniority,
salaryBasic, bonoProfesional, antiguedad, salaryTotal,
datBanc, bankName, accountNumber, datBanc, bankName, accountNumber,
datGest, gpss, sss, beneficiarie1, beneficiarie2, datGest, gpss, sss, beneficiaries,
saveButton, editButton, reportButton, dialog saveButton, editButton, reportButton, dialog
); );
} }

View File

@ -3,6 +3,8 @@ package com.primefactorsolutions.views;
import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.model.Employee;
import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.EmployeeService;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.annotation.SpringComponent;
@ -14,12 +16,13 @@ import org.springframework.context.annotation.Scope;
import java.util.List; import java.util.List;
@SpringComponent @SpringComponent
@Scope("prototype") @Scope("prototype")
@PageTitle("Employees") @PageTitle("Employees")
@Route(value = "/employees", layout = MainLayout.class) @Route(value = "/employees", layout = MainLayout.class)
@PermitAll @PermitAll
public class EmployeesListView extends BaseView { public class EmployeesListView extends Main {
private final EmployeeService employeeService; private final EmployeeService employeeService;
private final PagingGrid<Employee> table = new PagingGrid<>(Employee.class); private final PagingGrid<Employee> table = new PagingGrid<>(Employee.class);
@ -31,9 +34,10 @@ public class EmployeesListView extends BaseView {
} }
private void setupView() { private void setupView() {
add(new H2("Employee List"));
configureTable(); configureTable();
getCurrentPageLayout().add(createAddEmployeeButton()); add(createAddEmployeeButton());
getCurrentPageLayout().add(table); add(table);
} }
private void configureTable() { private void configureTable() {
@ -71,7 +75,7 @@ public class EmployeesListView extends BaseView {
private void setupPagingGrid() { private void setupPagingGrid() {
table.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM); table.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
table.setPageSize(Constants.PAGE_SIZE); table.setPageSize(5);
} }
private void refreshGrid() { private void refreshGrid() {

View File

@ -1,279 +0,0 @@
package com.primefactorsolutions.views;
import com.primefactorsolutions.model.Employee;
import com.primefactorsolutions.model.HoursWorked;
import com.primefactorsolutions.model.Team;
import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.service.HoursWorkedService;
import com.primefactorsolutions.service.TeamService;
import com.primefactorsolutions.views.util.MenuBarUtils;
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.contextmenu.MenuItem;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.menubar.MenuBar;
import com.vaadin.flow.component.menubar.MenuBarVariant;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.function.ValueProvider;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent;
import jakarta.annotation.security.PermitAll;
import org.springframework.context.annotation.Scope;
import org.vaadin.firitin.components.grid.PagingGrid;
import java.time.LocalDate;
import java.time.temporal.IsoFields;
import java.util.*;
import java.util.stream.Collectors;
import static com.primefactorsolutions.views.Constants.PAGE_SIZE;
@SpringComponent
@PermitAll
@Scope("prototype")
@PageTitle("Registro de Horas Trabajadas")
@Route(value = "/hours-worked-list", layout = MainLayout.class)
public class HoursWorkedListView extends BaseView {
private final HoursWorkedService hoursWorkedService;
private final EmployeeService employeeService;
private final TeamService teamService;
private final PagingGrid<HoursWorked> hoursWorkedGrid = new PagingGrid<>();
private ComboBox<Employee> employeeFilter;
private ComboBox<Team> teamFilter;
public HoursWorkedListView(final HoursWorkedService hoursWorkedService,
final EmployeeService employeeService,
final TeamService teamService) {
this.hoursWorkedService = hoursWorkedService;
this.employeeService = employeeService;
this.teamService = teamService;
initializeView();
refreshGridListHoursWorked(null, null);
}
private void refreshGridListHoursWorked(final Employee employee,
final Team team) {
hoursWorkedGrid.setPagingDataProvider((page, pageSize) -> {
int start = (int) (page * hoursWorkedGrid.getPageSize());
List<HoursWorked> hoursWorkedList = fetchFilteredHoursWorked(start, pageSize, employee, team);
double totalHours = hoursWorkedList.stream()
.mapToDouble(HoursWorked::getTotalHours)
.sum();
Notification.show("Total de horas trabajadas: " + totalHours,
3000, Notification.Position.BOTTOM_CENTER);
return hoursWorkedList;
});
hoursWorkedGrid.getDataProvider().refreshAll();
}
private List<HoursWorked> fetchFilteredHoursWorked(final int start,
final int pageSize,
final Employee employee,
final Team team) {
List<HoursWorked> filteredHoursWorked = hoursWorkedService.findAll();
if (employee != null && !"TODOS".equals(employee.getFirstName())) {
filteredHoursWorked = filteredHoursWorked.stream()
.filter(hw -> hw.getEmployee().getId().equals(employee.getId()))
.collect(Collectors.toList());
}
if (team != null && !"TODOS".equals(team.getName())) {
filteredHoursWorked = filteredHoursWorked.stream()
.filter(hw -> hw.getEmployee().getTeam() != null
&& hw.getEmployee().getTeam().getId().equals(team.getId()))
.collect(Collectors.toList());
}
for (HoursWorked hoursWorked : filteredHoursWorked) {
if (employee != null && hoursWorked.getEmployee().getId().equals(employee.getId())) {
LocalDate date = hoursWorked.getDate();
int currentWeek = date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
double totalWorkedInSameWeek = filteredHoursWorked.stream()
.filter(hw -> hw.getEmployee().getId().equals(employee.getId())
&&
hw.getDate().get(IsoFields.WEEK_OF_WEEK_BASED_YEAR) == currentWeek)
.mapToDouble(HoursWorked::getHours)
.sum();
double updatedPendingHours = totalWorkedInSameWeek - hoursWorked.getHours();
hoursWorked.setHoraspendientes(updatedPendingHours);
}
}
int end = Math.min(start + pageSize, filteredHoursWorked.size());
return filteredHoursWorked.subList(start, end);
}
private void initializeView() {
getCurrentPageLayout().add(createAddHoursWorked());
setupFilters();
setupListHoursWorkedGrid();
getCurrentPageLayout().add(hoursWorkedGrid);
}
private void setupFilters() {
final HorizontalLayout hl = new HorizontalLayout();
hl.add(createEmployeeFilter());
hl.add(createTeamFilter());
getCurrentPageLayout().add(hl);
}
private void setupListHoursWorkedGrid() {
hoursWorkedGrid.addColumn(hw -> hw.getDate() != null ? hw.getDate().toString() : "")
.setHeader("Fecha")
.setSortable(true);
hoursWorkedGrid.addColumn(HoursWorked::getWeekNumber)
.setHeader("Semana")
.setSortable(true);
hoursWorkedGrid.addColumn(hw -> hw.getEmployee().getFirstName() + " " + hw.getEmployee().getLastName())
.setHeader("Empleado");
hoursWorkedGrid.addColumn(hw -> hw.getEmployee().getTeam() != null ? hw.getEmployee().getTeam()
.getName() : "Sin asignar")
.setHeader("Equipo");
hoursWorkedGrid.addColumn(hw -> {
String actividad = hw.getActividad() != null ? hw.getActividad() : "Sin Actividad";
String tareaEspecifica = hw.getTareaEspecifica() != null ? hw.getTareaEspecifica() : "";
return !tareaEspecifica.isEmpty() ? tareaEspecifica : actividad;
}).setHeader("Actividad");
hoursWorkedGrid.addColumn(hw -> {
if (hw.getTareaEspecifica() != null && !hw.getTareaEspecifica().isEmpty()) {
return calcularHorasPorTareaEspecifica(hw);
} else {
return calcularHorasPorActividadGeneral(hw);
}
}).setHeader("Total Horas").setSortable(true);
hoursWorkedGrid.addColumn(hw -> hw.getHoraspendientes() - calcularTotal(hw)).setHeader("Horas Pendientes")
.setSortable(true);
hoursWorkedGrid.addComponentColumn((ValueProvider<HoursWorked, Component>) hoursWorked -> {
final MenuBar menuBar = new MenuBar();
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
final MenuItem viewItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.EYE, "Ver");
viewItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
navigateToHoursWorkedView(hoursWorked.getEmployee().getId());
});
return menuBar;
});
hoursWorkedGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
hoursWorkedGrid.setPageSize(PAGE_SIZE);
}
private double calcularHorasPorTareaEspecifica(final HoursWorked hoursWorked) {
List<HoursWorked> tareas = hoursWorkedService.findListHoursWorkedEmployee(
hoursWorked.getEmployee().getId(), hoursWorked.getWeekNumber());
return tareas.stream()
.filter(hw -> Objects.equals(hw.getTareaEspecifica(), hoursWorked.getTareaEspecifica()))
.mapToDouble(HoursWorked::getHours)
.sum();
}
private double calcularHorasPorActividadGeneral(final HoursWorked hoursWorked) {
List<HoursWorked> actividades = hoursWorkedService.findListHoursWorkedEmployee(
hoursWorked.getEmployee().getId(), hoursWorked.getWeekNumber());
return actividades.stream()
.filter(hw -> Objects.equals(hw.getActividad(), hoursWorked.getActividad())
&& (hw.getTareaEspecifica() == null || hw.getTareaEspecifica().isEmpty()))
.mapToDouble(HoursWorked::getHours)
.sum();
}
private void navigateToHoursWorkedView(final UUID idEmployee) {
getUI().ifPresent(ui -> ui.navigate("hours-worked-list/" + idEmployee.toString()));
}
private double calcularTotal(final HoursWorked hoursWorked) {
List<HoursWorked> listHoursworkedemploye = hoursWorkedService.findListHoursWorkedEmployee(
hoursWorked.getEmployee().getId(), hoursWorked.getWeekNumber());
return calculateTotalUtilized(listHoursworkedemploye);
}
private double calculateTotalUtilized(final List<HoursWorked> employeeRequests) {
return employeeRequests.stream()
.filter(Objects::nonNull)
.mapToDouble(HoursWorked::getHours)
.sum();
}
private Button createButton(final String label, final Runnable onClickAction) {
final Button button = new Button(label);
button.addClickListener(event -> onClickAction.run());
return button;
}
private Button createAddHoursWorked() {
return createButton("Agregar Actividad", this::navigateToHours);
}
private void navigateToHours() {
getUI().ifPresent(ui -> ui.navigate(HoursWorkedView.class, "new"));
}
private ComboBox<Employee> createEmployeeFilter() {
employeeFilter = new ComboBox<>("Empleado");
final List<Employee> employees = new ArrayList<>(employeeService.findAllEmployees());
employees.addFirst(createAllEmployeesOption());
employeeFilter.setItems(employees);
employeeFilter.setItemLabelGenerator(this::getEmployeeFullName);
employeeFilter.setValue(employees.getFirst());
employeeFilter.addValueChangeListener(event ->
refreshGridListHoursWorked(
event.getValue(),
teamFilter.getValue()
)
);
return employeeFilter;
}
private String getEmployeeFullName(final Employee employee) {
return "TODOS".equals(employee.getFirstName())
? "TODOS" : employee.getFirstName() + " " + employee.getLastName();
}
private ComboBox<Team> createTeamFilter() {
teamFilter = new ComboBox<>("Equipo");
List<Team> teams = new ArrayList<>(teamService.findAllTeams());
teams.addFirst(createAllTeamsOption());
teamFilter.setItems(teams);
teamFilter.setItemLabelGenerator(this::getTeamLabel);
teamFilter.setValue(teams.getFirst());
teamFilter.addValueChangeListener(event ->
refreshGridListHoursWorked(
employeeFilter.getValue(),
event.getValue()
)
);
return teamFilter;
}
private String getTeamLabel(final Team team) {
return team != null && !"TODOS".equals(team.getName()) ? team.getName() : "TODOS";
}
private Employee createAllEmployeesOption() {
Employee allEmployeesOption = new Employee();
allEmployeesOption.setFirstName("TODOS");
return allEmployeesOption;
}
private Team createAllTeamsOption() {
Team allTeamsOption = new Team();
allTeamsOption.setName("TODOS");
return allTeamsOption;
}
}

View File

@ -0,0 +1,161 @@
package com.primefactorsolutions.views;
import com.primefactorsolutions.model.Employee;
import com.primefactorsolutions.model.Actividad;
import com.primefactorsolutions.service.EmployeeService;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent;
import jakarta.annotation.security.PermitAll;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import java.time.LocalDate;
import java.util.List;
@SpringComponent
@PermitAll
@Scope("prototype")
@PageTitle("Hours Worked Month")
@Route(value = "/hours-worked-month/me", layout = MainLayout.class)
public class HoursWorkedMonthView extends VerticalLayout {
private final EmployeeService employeeService;
private final ComboBox<Employee> employeeComboBox = new ComboBox<>("Empleado");
private final ComboBox<String> equipoDropdown = new ComboBox<>("Equipo");
private final Grid<Actividad> grid = new Grid<>(Actividad.class);
private final Label totalCompletadoLabel = new Label();
private final Label horasPendientesLabel = new Label();
private final Label totalAcumuladasLabel = new Label();
private final Label horasAdeudadasLabel = new Label();
private final Button actualizarButton = new Button("Actualizar");
private final Button guardarButton = new Button("Guardar");
private final Button cerrarButton = new Button("Cerrar");
private LocalDate selectedMonth;
@Autowired
public HoursWorkedMonthView(final EmployeeService employeeService) {
this.employeeService = employeeService;
configurarVista();
}
private void configurarVista() {
DatePicker monthPicker = new DatePicker("Selecciona un mes");
monthPicker.setValue(LocalDate.now());
monthPicker.addValueChangeListener(event -> {
selectedMonth = event.getValue().withDayOfMonth(1);
//cargarDatosMes(selectedMonth);
});
equipoDropdown.setItems("Equipo 1", "Equipo 2", "Equipo 3");
equipoDropdown.setWidth("250px");
setEmployeeComboBoxProperties();
configurarGrid();
actualizarButton.addClickListener(event -> actualizarDatos());
guardarButton.addClickListener(event -> guardarActividades());
cerrarButton.addClickListener(event -> closeView());
HorizontalLayout headerLayout = new HorizontalLayout(monthPicker, equipoDropdown, employeeComboBox);
add(
headerLayout, grid, totalCompletadoLabel,
horasPendientesLabel, totalAcumuladasLabel,
horasAdeudadasLabel, actualizarButton,
guardarButton, cerrarButton);
}
private void setEmployeeComboBoxProperties() {
employeeComboBox.setWidth("250px");
employeeComboBox.setPlaceholder("Buscar empleado...");
employeeComboBox.setItems(employeeService.findAllEmployees());
employeeComboBox.setItemLabelGenerator(employee -> employee.getFirstName() + " " + employee.getLastName());
}
private void configurarGrid() {
grid.removeAllColumns();
grid.addColumn(Actividad::getLunes).setHeader("Lunes");
grid.addColumn(Actividad::getMartes).setHeader("Martes");
grid.addColumn(Actividad::getMiercoles).setHeader("Miércoles");
grid.addColumn(Actividad::getJueves).setHeader("Jueves");
grid.addColumn(Actividad::getViernes).setHeader("Viernes");
grid.addColumn(Actividad::getSabado).setHeader("Sábado");
grid.addColumn(Actividad::getDomingo).setHeader("Domingo");
grid.addColumn(this::calcularTotalPorDia).setHeader("Total Semanal").setKey("totalSemanal");
}
// private void cargarDatosMes(final LocalDate month) {
// List<Actividad> actividadesDelMes = obtenerActividadesDelMes(month);
// grid.setItems(actividadesDelMes);
//
// double totalCompletado = calcularTotalCompletado(actividadesDelMes);
// double horasPendientes = calcularHorasPendientes(totalCompletado);
// double totalAcumuladas = 166;
// double horasAdeudadas = 2;
//
// totalCompletadoLabel.setText("Prom. Hrs/Semana Completadas: " + totalCompletado);
// horasPendientesLabel.setText("Prom. Hrs/Semana Pendientes: " + horasPendientes);
// totalAcumuladasLabel.setText("Total Hrs./Mes Acumuladas: " + totalAcumuladas);
// horasAdeudadasLabel.setText("Total Hrs./Mes Adeudadas: " + horasAdeudadas);
// }
// private List<Actividad> obtenerActividadesDelMes(final LocalDate month) {
// LocalDate startOfMonth = month.with(TemporalAdjusters.firstDayOfMonth());
// LocalDate endOfMonth = month.with(TemporalAdjusters.lastDayOfMonth());
//
// List<Actividad> actividadesDelMes = new ArrayList<>();
//
// for (LocalDate date = startOfMonth; date.isBefore(endOfMonth.plusDays(1)); date = date.plusDays(1)) {
// Actividad actividad = new Actividad.Builder()
// .lunes(0)
// .martes(0)
// .miercoles(0)
// .jueves(0)
// .viernes(0)
// .sabado(0)
// .domingo(0)
// .build();
// actividadesDelMes.add(actividad);
// }
//
// return actividadesDelMes;
// }
private double calcularTotalCompletado(final List<Actividad> actividades) {
return actividades.stream()
.mapToDouble(this::calcularTotalPorDia)
.sum();
}
private double calcularTotalPorDia(final Actividad actividad) {
return actividad.getLunes() + actividad.getMartes() + actividad.getMiercoles()
+ actividad.getJueves() + actividad.getViernes() + actividad.getSabado()
+ actividad.getDomingo();
}
private double calcularHorasPendientes(final double totalCompletado) {
return 40 - totalCompletado;
}
private void actualizarDatos() {
Notification.show("Datos actualizados.");
}
private void guardarActividades() {
Notification.show("Actividades guardadas correctamente.");
}
private void closeView() {
getUI().ifPresent(ui -> ui.navigate(""));
}
}

View File

@ -1,295 +1,526 @@
package com.primefactorsolutions.views; package com.primefactorsolutions.views;
import com.primefactorsolutions.model.Actividad;
import com.primefactorsolutions.model.Employee; import com.primefactorsolutions.model.Employee;
import com.primefactorsolutions.model.HoursWorked; import com.primefactorsolutions.model.HoursWorked;
import com.primefactorsolutions.model.Team; import com.primefactorsolutions.repositories.ActividadesHoursRepository;
import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.service.HoursWorkedService; import com.primefactorsolutions.service.HoursWorkedService;
import com.primefactorsolutions.service.TeamService; import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.html.H2; import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.router.*; import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.annotation.SpringComponent;
import jakarta.annotation.security.PermitAll; import jakarta.annotation.security.PermitAll;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import com.vaadin.flow.component.html.Label;
import org.vaadin.firitin.components.datepicker.VDatePicker; import org.vaadin.firitin.components.datepicker.VDatePicker;
import org.vaadin.firitin.form.BeanValidationForm;
import java.time.DayOfWeek;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.YearMonth;
import java.time.temporal.IsoFields; import java.time.temporal.IsoFields;
import java.time.temporal.WeekFields;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.Locale;
@SpringComponent @SpringComponent
@PermitAll @PermitAll
@Scope("prototype") @Scope("prototype")
@PageTitle("Horas Trabajadas") @PageTitle("Horas Trabajadas")
@Route(value = "/hours-worked-list/:hours-workedId?/:action?", layout = MainLayout.class) @Route(value = "/hours-worked/me", layout = MainLayout.class)
public class HoursWorkedView extends BeanValidationForm<HoursWorked> implements HasUrlParameter<String> { public class HoursWorkedView extends VerticalLayout {
private final VDatePicker dateField = new VDatePicker("Fecha"); private final List<Actividad> actividades = new ArrayList<>();
private final ComboBox<Team> teamField = new ComboBox<>("Equipo"); private final List<Actividad> actividadesEspecificas = new ArrayList<>(); // Nueva lista para tareas específicas
private ComboBox<Employee> employeeField; private final Grid<Actividad> grid = new Grid<>(Actividad.class);
private final ComboBox<String> tareasEspecificasDropdown = new ComboBox<>("Tarea Específica"); private final Grid<Actividad> gridActividadesEspecificas = new Grid<>(Actividad.class);
private final TextField tareaEspecificaInput = new TextField("Otra Tarea Específica");
private final TextField horasTareaEspecificaField = new TextField("Horas Tarea Específica"); private final ComboBox<Employee> employeeComboBox = new ComboBox<>("Empleado");
private final TextField activityField = new TextField("Actividad"); private final ComboBox<String> equipoDropdown = new ComboBox<>("Equipo");
private final TextField hoursField = new TextField("Horas"); private VDatePicker fechaPicker = new VDatePicker("Selecciona una fecha");
private final ComboBox<String> tareasEspecificasDropdown = new ComboBox<>("Tareas Específicas");
private final TextField tareaEspecificaInput = new TextField("Especificar Tarea");
private TextField horasTareaInput = crearCampoHora("Horas Tareas");
private LocalDate selectedStartOfWeek;
private int weekNumber;
@Autowired
private final EmployeeService employeeService;
@Autowired
private final HoursWorkedService hoursWorkedService;
@Autowired
private ActividadesHoursRepository actividadesHoursRepository;
private final H2 equipoLabel = new H2("Tareas del Cliente/Equipo"); private final H2 equipoLabel = new H2("Tareas del Cliente/Equipo");
private final H2 empresaLabel = new H2("Tareas de la Empresa"); private final H2 empresaLabel = new H2("Tareas de la Empresa");
private final Label totalCompletadoLabel = new Label(); private final Label totalCompletadoLabel = new Label();
private final Label horasPendientesLabel = new Label();
private final HoursWorkedService hoursWorkedService; public HoursWorkedView(final EmployeeService employeeService,
private final EmployeeService employeeService; final HoursWorkedService hoursWorkedService) {
private final TeamService teamService;
private HoursWorked hoursWorked;
private Employee employee;
private Button saveButton;
public HoursWorkedView(final HoursWorkedService hoursWorkedService,
final EmployeeService employeeService,
final TeamService teamService) {
super(HoursWorked.class);
this.hoursWorkedService = hoursWorkedService;
this.employeeService = employeeService; this.employeeService = employeeService;
this.teamService = teamService; this.hoursWorkedService = hoursWorkedService;
configurarVista();
initializeDateField(); configurarGrid();
initializeTeamField(); configurarGridActividadesEspecificas();
initializeEmployeeField(); cargarDatos();
configureTareasEspecificas(); configurarTareasEspecificas();
} }
@Override private void configurarTareasEspecificas() {
public void setParameter(final BeforeEvent beforeEvent, final String action) { tareasEspecificasDropdown.setItems("Entrevistas", "Reuniones", "Colaboraciones",
final RouteParameters params = beforeEvent.getRouteParameters(); "Aprendizajes", "Proyectos PFS", "Otros");
final String s = params.get("hours-workedId").orElse(null);
if ("new".equals(action)) {
setEntityWithEnabledSave(new HoursWorked());
} else {
UUID hoursWorkedId = UUID.fromString(s);
var hoursWorked = hoursWorkedService.getHoursWorked(hoursWorkedId);
setEntityWithEnabledSave(hoursWorked);
if ("edit".equals(action) && !s.isEmpty()) {
saveButton.setVisible(true);
} else if ("view".equals(action) && !s.isEmpty()) {
saveButton.setVisible(false);
}
}
}
@Override
protected List<Component> getFormComponents() {
return List.of(
dateField,
teamField,
employeeField,
equipoLabel,
activityField,
hoursField,
empresaLabel,
tareasEspecificasDropdown,
tareaEspecificaInput,
horasTareaEspecificaField,
createCloseButton()
);
}
private void configureTareasEspecificas() {
tareasEspecificasDropdown.setItems("Entrevistas", "Reuniones",
"Colaboraciones", "Aprendizajes", "Proyectos PFS",
"Consulta Medica", "Afiliación al Seguro", "Fallas Tecnicas", "Otros");
tareasEspecificasDropdown.setPlaceholder("Selecciona una tarea..."); tareasEspecificasDropdown.setPlaceholder("Selecciona una tarea...");
tareasEspecificasDropdown.addValueChangeListener(event -> { tareasEspecificasDropdown.addValueChangeListener(event -> {
String selected = event.getValue(); String selected = event.getValue();
boolean isOtros = "Otros".equals(selected); // Activa el campo de texto si la opción seleccionada es "Otros"
tareaEspecificaInput.setVisible(isOtros); tareaEspecificaInput.setVisible("Otros".equals(selected));
horasTareaEspecificaField.setVisible(true); if (!"Otros".equals(selected)) {
if (!isOtros) {
tareaEspecificaInput.clear(); tareaEspecificaInput.clear();
horasTareaEspecificaField.clear();
} }
}); });
tareaEspecificaInput.setVisible(false); tareaEspecificaInput.setVisible(false);
horasTareaEspecificaField.setVisible(false);
} }
protected Button createSaveButton() { private void cargarDatos() {
saveButton = new Button("Guardar"); if (selectedStartOfWeek != null && weekNumber > 0) {
saveButton.addClickListener(event -> saveHoursWorked()); List<HoursWorked> listaDeHorasTrabajadas = obtenerDatos();
return saveButton;
for (HoursWorked hours : listaDeHorasTrabajadas) {
LocalDate activityDate = hours.getFecha();
int activityWeek = getWeekOfYear(activityDate);
if (activityWeek == weekNumber) {
Actividad actividad = hours.getActividad();
if (actividad != null) {
DayOfWeek dayOfWeek = activityDate.getDayOfWeek();
agregarOActualizarActividad(actividad, dayOfWeek, hours.getTotalHours());
}
}
} }
protected Button createCloseButton() { grid.setItems(actividades);
Button closeButton = new Button("Cerrar"); gridActividadesEspecificas.setItems(actividadesEspecificas);
closeButton.addClickListener(event -> closeForm()); calcularTotalHoras(listaDeHorasTrabajadas);
return closeButton; }
} }
private void initializeTeamField() { private void setEmployeeComboBoxProperties() {
List<Team> teams = new ArrayList<>(teamService.findAllTeams()); employeeComboBox.setWidth("250px");
teamField.setItems(teamService.findAllTeams()); employeeComboBox.setPlaceholder("Buscar empleado...");
teamField.setItemLabelGenerator(Team::getName); employeeComboBox.setItems(employeeService.findAllEmployees());
teamField.setValue(teams.getFirst()); employeeComboBox.setItemLabelGenerator(employee -> employee.getFirstName()
teamField.addValueChangeListener(event -> { + " " + employee.getLastName());
if (teams != null) { employeeComboBox.setAllowCustomValue(false);
employeeField.getValue(); employeeComboBox.addCustomValueSetListener(event ->
event.getValue(); Notification.show("Selecciona un empleado válido de la lista.")
}
}
); );
}
private ComboBox<Employee> initializeEmployeeField() { employeeComboBox.addValueChangeListener(event -> {
employeeField = new ComboBox<>("Empleado"); Employee selectedEmployee = event.getValue();
List<Employee> employees = new ArrayList<>(employeeService.findAllEmployees()); if (selectedEmployee != null) {
employeeField.setItems(employees); Notification.show("Empleado seleccionado: "
employeeField.setItemLabelGenerator(this::getEmployeeFullName); + selectedEmployee.getFirstName() + " "
employeeField.setValue(employees.getFirst()); + selectedEmployee.getLastName());
return employeeField;
}
private String getEmployeeFullName(final Employee employee) {
return "TODOS".equals(employee.getFirstName())
? "TODOS" : employee.getFirstName() + " " + employee.getLastName();
}
private void initializeDateField() {
LocalDate today = LocalDate.now();
YearMonth currentMonth = YearMonth.of(today.getYear(), today.getMonth());
LocalDate startOfMonth = currentMonth.atDay(1);
LocalDate maxSelectableDate = today;
dateField.setMin(startOfMonth);
dateField.setMax(maxSelectableDate);
dateField.setValue(today);
dateField.addValueChangeListener(event -> {
LocalDate selectedDate = event.getValue();
if (selectedDate != null) {
int weekNumber = selectedDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
Notification.show("Número de la semana: " + weekNumber,
3000, Notification.Position.BOTTOM_CENTER);
if (hoursWorked != null) {
hoursWorked.setWeekNumber(weekNumber);
}
} }
}); });
} }
private void saveHoursWorked() { private int getWeekOfYear(final LocalDate date) {
if (isFormValid()) { return date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
HoursWorked hoursWorked = getEntity(); }
String actividad = activityField.getValue();
String tareaEspecifica = tareasEspecificasDropdown.getValue(); private void configurarVista() {
if (actividad != null && !actividad.isEmpty() && tareaEspecifica != null) { fechaPicker.setMax(LocalDate.now());
Notification.show("Solo puedes elegir una: actividad del proyecto o tarea de la empresa.", fechaPicker.addValueChangeListener(event -> {
3000, Notification.Position.BOTTOM_CENTER); LocalDate selectedDate = event.getValue();
if (selectedDate != null) {
selectedStartOfWeek = getStartOfWeek(selectedDate);
weekNumber = getWeekOfYear(selectedDate);
cargarDatos();
}
});
Button verMesButton = new Button("Ver Mes", event -> {
getUI().ifPresent(ui -> ui.navigate(HoursWorkedMonthView.class));
});
equipoDropdown.setItems("ABC", "DEF", "XYZ");
equipoDropdown.setWidth("250px");
equipoDropdown.addValueChangeListener(event -> {
String selectedEquipo = event.getValue();
if (selectedEquipo != null) {
// Filtra la lista de empleados según el equipo seleccionado
List<Employee> filteredEmployees = employeeService.findEmployeesByTeam(selectedEquipo);
employeeComboBox.setItems(filteredEmployees);
}
});
setEmployeeComboBoxProperties();
HorizontalLayout filtersLayout = new HorizontalLayout(equipoDropdown, employeeComboBox);
filtersLayout.setSpacing(true);
HorizontalLayout actividadFormLayout = configurarFormularioActividades();
HorizontalLayout tareasEspecificasLayout = configurarTareasEspecificasLayout();
Button actualizarButton = new Button("Actualizar Totales", event -> actualizarTotales());
Button guardarButton = new Button("Guardar", event -> guardarActividades());
Button cerrarButton = new Button("Cerrar", event -> this.closeView());
HorizontalLayout buttonsLayout = new HorizontalLayout(actualizarButton, guardarButton,
cerrarButton, verMesButton);
VerticalLayout totalesLayout = new VerticalLayout(totalCompletadoLabel,
horasPendientesLabel);
totalesLayout.setSpacing(true);
totalesLayout.setPadding(true);
add(fechaPicker, filtersLayout, actividadFormLayout,
equipoLabel, grid, empresaLabel, tareasEspecificasLayout,
gridActividadesEspecificas, buttonsLayout, totalesLayout);
}
private void configurarGrid() {
grid.removeAllColumns();
grid.setItems(actividades);
grid.addColumn(Actividad::getNombre).setHeader("Actividad");
grid.addColumn(Actividad::getLunes).setHeader("Lunes");
grid.addColumn(Actividad::getMartes).setHeader("Martes");
grid.addColumn(Actividad::getMiercoles).setHeader("Miércoles");
grid.addColumn(Actividad::getJueves).setHeader("Jueves");
grid.addColumn(Actividad::getViernes).setHeader("Viernes");
grid.addColumn(Actividad::getSabado).setHeader("Sábado");
grid.addColumn(Actividad::getDomingo).setHeader("Domingo");
grid.addColumn(this::calcularTotalPorDia).setHeader("Total Día").setKey("totalDia");
grid.setItems(actividades);
}
private void configurarGridActividadesEspecificas() {
gridActividadesEspecificas.removeAllColumns();
gridActividadesEspecificas.setItems(actividadesEspecificas);
gridActividadesEspecificas.addColumn(Actividad::getTarea).setHeader("Actividad");
gridActividadesEspecificas.addColumn(Actividad::getLunes).setHeader("Lunes");
gridActividadesEspecificas.addColumn(Actividad::getMartes).setHeader("Martes");
gridActividadesEspecificas.addColumn(Actividad::getMiercoles).setHeader("Miércoles");
gridActividadesEspecificas.addColumn(Actividad::getJueves).setHeader("Jueves");
gridActividadesEspecificas.addColumn(Actividad::getViernes).setHeader("Viernes");
gridActividadesEspecificas.addColumn(Actividad::getSabado).setHeader("Sábado");
gridActividadesEspecificas.addColumn(Actividad::getDomingo).setHeader("Domingo");
gridActividadesEspecificas.addColumn(this::calcularTotalPorDia).setHeader("Total Día Específico")
.setKey("totalDiaEspecifico");
}
private HorizontalLayout configurarFormularioActividades() {
TextField actividadNombre = new TextField("Actividad");
actividadNombre.setWidth("200px");
TextField horasInput = crearCampoHora("Horas");
Button agregarActividadButton = new Button("Agregar Actividad", e -> {
try {
LocalDate selectedDate = fechaPicker.getValue();
if (selectedDate == null) {
Notification.show("Por favor, selecciona una fecha.");
return; return;
} }
if (actividad != null && !actividad.isEmpty()) {
int selectedWeekNumber = getWeekOfYear(selectedDate);
if (selectedWeekNumber != weekNumber) {
Notification.show("Solo puedes agregar actividades dentro de la semana actual.");
return;
}
DayOfWeek selectedDay = selectedDate.getDayOfWeek();
Actividad.Builder actividadBuilder = new Actividad.Builder()
.nombre(actividadNombre.getValue());
double horas = parseHoras(horasInput.getValue());
switch (selectedDay) {
case MONDAY -> actividadBuilder.lunes(horas);
case TUESDAY -> actividadBuilder.martes(horas);
case WEDNESDAY -> actividadBuilder.miercoles(horas);
case THURSDAY -> actividadBuilder.jueves(horas);
case FRIDAY -> actividadBuilder.viernes(horas);
case SATURDAY -> actividadBuilder.sabado(horas);
case SUNDAY -> actividadBuilder.domingo(horas);
default -> throw new IllegalArgumentException("Día seleccionado no válido: " + selectedDay);
}
String tareaSeleccionada = tareasEspecificasDropdown.getValue();
double horasTarea = parseHoras(horasTareaInput.getValue());
if (tareaSeleccionada != null && !tareaSeleccionada.isEmpty()) {
actividadBuilder.tarea(tareaSeleccionada).lunes(horasTarea);
Actividad nuevaActividadEspecifica = actividadBuilder.build();
actividadesEspecificas.add(nuevaActividadEspecifica);
gridActividadesEspecificas.setItems(actividadesEspecificas);
} else {
Actividad nuevaActividad = actividadBuilder.build();
actividades.add(nuevaActividad);
grid.setItems(actividades);
}
Actividad nuevaActividad = actividadBuilder.build();
agregarOActualizarActividad(nuevaActividad, selectedDay, horas);
actualizarTotales();
Notification.show("Actividad agregada correctamente");
actividadNombre.clear();
horasInput.clear();
tareasEspecificasDropdown.clear();
horasTareaInput.clear();
} catch (NumberFormatException ex) {
Notification.show("Error: Por favor ingresa números válidos para las horas.");
}
});
return new HorizontalLayout(actividadNombre, horasInput, agregarActividadButton);
}
private void agregarOActualizarActividad(final Actividad nuevaActividad, final DayOfWeek dia, final double horas) {
Actividad actividadExistente = actividades.stream()
.filter(a -> a.getNombre().equals(nuevaActividad.getNombre()))
.findFirst()
.orElse(null);
if (actividadExistente != null) {
// Si la actividad ya existe, actualiza las horas para el día correspondiente
switch (dia) {
case MONDAY -> actividadExistente.setLunes(horas);
case TUESDAY -> actividadExistente.setMartes(horas);
case WEDNESDAY -> actividadExistente.setMiercoles(horas);
case THURSDAY -> actividadExistente.setJueves(horas);
case FRIDAY -> actividadExistente.setViernes(horas);
case SATURDAY -> actividadExistente.setSabado(horas);
case SUNDAY -> actividadExistente.setDomingo(horas);
default -> throw new IllegalArgumentException("Día seleccionado no válido: " + dia);
}
} else {
// Si no existe, se agrega como nueva actividad
switch (dia) {
case MONDAY -> nuevaActividad.setLunes(horas);
case TUESDAY -> nuevaActividad.setMartes(horas);
case WEDNESDAY -> nuevaActividad.setMiercoles(horas);
case THURSDAY -> nuevaActividad.setJueves(horas);
case FRIDAY -> nuevaActividad.setViernes(horas);
case SATURDAY -> nuevaActividad.setSabado(horas);
case SUNDAY -> nuevaActividad.setDomingo(horas);
default -> throw new IllegalArgumentException("Día seleccionado no válido: " + dia);
}
actividades.add(nuevaActividad);
}
// Actualiza el Grid
grid.setItems(actividades);
}
private HorizontalLayout configurarTareasEspecificasLayout() {
Button agregarTareaButton = new Button("Agregar Tarea PFS", e -> {
try {
String tareaSeleccionada = tareasEspecificasDropdown.getValue();
String tareaNombre = "Otros"
.equals(tareaSeleccionada) ? tareaEspecificaInput
.getValue() : tareaSeleccionada;
if (tareaNombre == null || tareaNombre.isEmpty()) {
Notification.show("Por favor, especifica la tarea.");
return;
}
double horasTarea = parseHoras(horasTareaInput.getValue());
if (horasTarea <= 0) {
Notification.show("Por favor, ingresa un número válido para las horas.");
return;
}
if (tareaSeleccionada != null && !tareaSeleccionada.isEmpty() && horasTarea > 0) {
LocalDate selectedDate = fechaPicker.getValue();
if (selectedDate == null) {
Notification.show("Selecciona una fecha para asignar la tarea.");
return;
}
DayOfWeek selectedDay = selectedDate.getDayOfWeek();
Actividad.Builder actividadBuilder = new Actividad.Builder().tarea(tareaNombre);
switch (selectedDay) {
case MONDAY -> actividadBuilder.lunes(horasTarea);
case TUESDAY -> actividadBuilder.martes(horasTarea);
case WEDNESDAY -> actividadBuilder.miercoles(horasTarea);
case THURSDAY -> actividadBuilder.jueves(horasTarea);
case FRIDAY -> actividadBuilder.viernes(horasTarea);
case SATURDAY -> actividadBuilder.sabado(horasTarea);
case SUNDAY -> actividadBuilder.domingo(horasTarea);
default -> throw new IllegalArgumentException("Día seleccionado no válido: " + selectedDay);
}
Actividad nuevaActividadEspecifica = actividadBuilder.build();
actividadesEspecificas.add(nuevaActividadEspecifica);
gridActividadesEspecificas.setItems(actividadesEspecificas);
actualizarTotales();
tareasEspecificasDropdown.clear();
tareaEspecificaInput.clear();
horasTareaInput.clear();
Notification.show("Tarea específica agregada correctamente");
} else {
Notification.show("Selecciona una tarea y asegúrate de ingresar horas válidas.");
}
} catch (NumberFormatException ex) {
Notification.show("Error: Por favor ingresa un número válido para las horas.");
}
});
HorizontalLayout layout = new HorizontalLayout(tareasEspecificasDropdown,
tareaEspecificaInput, horasTareaInput, agregarTareaButton);
layout.setSpacing(true);
return layout;
}
private TextField crearCampoHora(final String placeholder) {
TextField field = new TextField(placeholder);
field.setWidth("80px");
field.setPlaceholder("0.0");
return field;
}
private double parseHoras(final String value) {
if (value == null || value.trim().isEmpty()) {
return 0.0;
}
return Double.parseDouble(value);
}
private LocalDate getStartOfWeek(final LocalDate date) {
WeekFields weekFields = WeekFields.of(Locale.getDefault());
return date.with(weekFields.dayOfWeek(), DayOfWeek.FRIDAY.getValue());
}
private double calcularTotalPorDia(final Actividad actividad) {
return actividad.getLunes() + actividad.getMartes() + actividad.getMiercoles()
+ actividad.getJueves() + actividad.getViernes() + actividad.getSabado() + actividad.getDomingo();
}
private void actualizarTotales() {
double totalActividadesGenerales = actividades.stream()
.mapToDouble(this::calcularTotalPorDia)
.sum();
double totalActividadesEspecificas = actividadesEspecificas.stream()
.mapToDouble(this::calcularTotalPorDia)
.sum();
double totalFinal = totalActividadesGenerales + totalActividadesEspecificas;
double horasPendientes = 40 - totalFinal;
totalCompletadoLabel.setText("Total Hrs/Semana Completadas: " + totalFinal);
horasPendientesLabel.setText("Horas Pendientes: " + horasPendientes);
}
private void guardarActividades() {
Employee selectedEmployee = employeeComboBox.getValue();
String selectedEquipo = equipoDropdown.getValue();
if (selectedEmployee == null || selectedEquipo == null) {
Notification.show("Por favor selecciona un equipo y un empleado.");
return;
}
// Verificar que hay actividades para guardar
if (actividades.isEmpty()) {
Notification.show("No hay actividades para guardar.");
return;
}
// Sumar el total de horas para la semana
double totalHorasSemana = actividades.stream()
.mapToDouble(this::calcularTotalPorDia)
.sum();
// Crear un objeto HoursWorked por cada actividad
List<HoursWorked> savedHoursWorked = new ArrayList<>(); // Para almacenar los objetos guardados
// Recorrer todas las actividades y guardar un registro para cada una
for (Actividad actividad : actividades) {
HoursWorked hoursWorked = new HoursWorked();
hoursWorked.setEmployee(selectedEmployee);
hoursWorked.setWeekNumber(weekNumber);
hoursWorked.setTotalHours(totalHorasSemana);
// Asignar cada actividad individualmente
hoursWorked.setActividad(actividad); hoursWorked.setActividad(actividad);
} else if (tareaEspecifica != null) { hoursWorked.setFecha(LocalDate.now()); // Establecer la fecha actual o la seleccionada si es otra
if ("Otros".equals(tareaEspecifica)) {
// Validar que se ingresó una tarea específica en el campo de texto
String tareaEspecificaInputValue = tareaEspecificaInput.getValue();
if (tareaEspecificaInputValue == null || tareaEspecificaInputValue.isEmpty()) {
Notification.show("Por favor, ingresa una tarea específica.",
3000, Notification.Position.BOTTOM_CENTER);
return;
}
hoursWorked.setTareaEspecifica(tareaEspecificaInputValue);
} else {
hoursWorked.setTareaEspecifica(tareaEspecifica);
}
} else {
Notification.show("Por favor, selecciona una actividad o tarea para guardar.",
3000, Notification.Position.BOTTOM_CENTER);
return;
}
setFieldValues(hoursWorked);
hoursWorkedService.save(hoursWorked);
Notification.show("Horas trabajadas guardadas correctamente.",
3000, Notification.Position.BOTTOM_CENTER);
closeForm();
}
}
// Mostrar información de la actividad para depuración
System.out.println("Guardando actividad: " + actividad.getNombre()
+ " con " + totalHorasSemana + " horas.");
private void setFieldValues(final HoursWorked hoursWorked) {
hoursWorked.setDate(dateField.getValue());
hoursWorked.setTeam(teamField.getValue());
hoursWorked.setEmployee(employeeField.getValue());
hoursWorked.setActividad(activityField.getValue());
try { try {
double hours = Double.parseDouble(hoursField.getValue()); // Guardar en el servicio
hoursWorked.setHours(hours); hoursWorkedService.saveHoursWorked(hoursWorked);
} catch (NumberFormatException e) { savedHoursWorked.add(hoursWorked); // Agregar a la lista de registros guardados
Notification.show("Por favor, ingrese un número válido para las horas."); Notification.show("Actividad guardada correctamente: " + actividad.getNombre());
} } catch (Exception e) {
if ("Otros".equals(tareasEspecificasDropdown.getValue())) { Notification.show("Error al guardar la actividad: " + actividad.getNombre()
hoursWorked.setActividad(tareaEspecificaInput.getValue()); + " - " + e.getMessage());
try {
double horasEspecifica = Double.parseDouble(horasTareaEspecificaField.getValue());
hoursWorked.setHours(horasEspecifica);
double totalHoras = hoursWorked.getHours() + horasEspecifica;
hoursWorked.setTotalHours(totalHoras);
} catch (NumberFormatException e) {
Notification.show("Por favor, ingrese un número válido para las horas de la tarea específica.");
}
}
}
private void closeForm() {
if (hoursWorked != null) {
getUI().ifPresent(ui -> ui.navigate("hours-worked-list/" + hoursWorked.getId().toString()));
} else {
getUI().ifPresent(ui -> ui.navigate("hours-worked-list"));
} }
} }
private boolean isFormValid() { // Mostrar los registros guardados
boolean isTareaEspecificaValida = "Otros".equals(tareasEspecificasDropdown.getValue()) savedHoursWorked.forEach(hw -> System.out.println("Horas trabajadas guardadas: " + hw));
? !tareaEspecificaInput.isEmpty()
: tareasEspecificasDropdown.getValue() != null; // Crear el Grid
boolean isActividadValida = !activityField.isEmpty(); Grid<HoursWorked> grid = new Grid<>();
boolean isSoloUnaOpcionElegida = (isActividadValida && tareasEspecificasDropdown.isEmpty())
|| (!isActividadValida && isTareaEspecificaValida); // Configurar columnas para mostrar la información deseada
return dateField.getValue() != null grid.addColumn(hw -> hw.getEmployee().getFirstName()).setHeader("Empleado");
&& teamField.getValue() != null grid.addColumn(hw -> hw.getEmployee().getId()).setHeader("ID Empleado");
&& employeeField.getValue() != null grid.addColumn(hw -> hw.getActividad().getNombre()).setHeader("Actividad");
&& isSoloUnaOpcionElegida; grid.addColumn(hw -> hw.getTotalHours()).setHeader("Horas Trabajadas");
grid.addColumn(hw -> hw.getWeekNumber()).setHeader("Número de Semana");
grid.addColumn(hw -> hw.getFecha().toString()).setHeader("Fecha");
// Llenar el Grid con los datos de savedHoursWorked
grid.setItems(savedHoursWorked);
// Agregar el Grid a la vista
add(grid);
} }
private void configureViewOrEditAction(final String action) {
if ("edit".equals(action) && hoursWorked != null) {
setFieldsReadOnly(false); private double calcularTotalHoras(final List<HoursWorked> listaDeHorasTrabajadas) {
} else if ("view".equals(action) && hoursWorked != null) { return listaDeHorasTrabajadas.stream()
setFieldsReadOnly(true); .mapToDouble(HoursWorked::getTotalHours)
saveButton.setEnabled(false); .sum();
}
} }
private void setFieldsReadOnly(final boolean readOnly) { private List<HoursWorked> obtenerDatos() {
dateField.setReadOnly(readOnly); return new ArrayList<>();
teamField.setReadOnly(readOnly); }
employeeField.setReadOnly(readOnly);
activityField.setReadOnly(readOnly); private void closeView() {
getUI().ifPresent(ui -> ui.navigate(HoursWorkedView.class));
} }
} }

View File

@ -13,7 +13,6 @@ import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.auth.AnonymousAllowed; import com.vaadin.flow.server.auth.AnonymousAllowed;
@SuppressWarnings("unused")
@Route("init-account") @Route("init-account")
@PageTitle("PFS Intra") @PageTitle("PFS Intra")
@AnonymousAllowed @AnonymousAllowed

View File

@ -2,7 +2,6 @@ package com.primefactorsolutions.views;
import com.vaadin.flow.component.html.Anchor; import com.vaadin.flow.component.html.Anchor;
import com.vaadin.flow.component.html.H1; import com.vaadin.flow.component.html.H1;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.login.LoginForm; import com.vaadin.flow.component.login.LoginForm;
import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.BeforeEnterEvent; import com.vaadin.flow.router.BeforeEnterEvent;
@ -10,9 +9,6 @@ import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.auth.AnonymousAllowed; import com.vaadin.flow.server.auth.AnonymousAllowed;
import com.vaadin.flow.theme.lumo.LumoUtility;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@Route("login") @Route("login")
@PageTitle("PFS Intra") @PageTitle("PFS Intra")
@ -21,7 +17,7 @@ public class LoginView extends VerticalLayout implements BeforeEnterObserver {
private final LoginForm login = new LoginForm(); private final LoginForm login = new LoginForm();
public LoginView(@Autowired @Value("${git.commit.id.abbrev}") final String commitId) { public LoginView() {
addClassName("login-view"); addClassName("login-view");
setSizeFull(); setSizeFull();
setAlignItems(Alignment.CENTER); setAlignItems(Alignment.CENTER);
@ -33,10 +29,6 @@ public class LoginView extends VerticalLayout implements BeforeEnterObserver {
add(new H1("PFS Intra")); add(new H1("PFS Intra"));
add(login); add(login);
add(new Anchor("/password-recovery", "Reset password?")); add(new Anchor("/password-recovery", "Reset password?"));
final Span version = new Span(String.format("v.%s", commitId));
version.addClassName(LumoUtility.FontSize.XSMALL);
add(version);
} }
@Override @Override

View File

@ -22,8 +22,6 @@ import com.vaadin.flow.component.sidenav.SideNavItem;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.spring.security.AuthenticationContext; import com.vaadin.flow.spring.security.AuthenticationContext;
import com.vaadin.flow.theme.lumo.LumoUtility; import com.vaadin.flow.theme.lumo.LumoUtility;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.vaadin.lineawesome.LineAwesomeIcon; import org.vaadin.lineawesome.LineAwesomeIcon;
@ -37,11 +35,10 @@ public class MainLayout extends AppLayout {
private H1 viewTitle; private H1 viewTitle;
public MainLayout(final AuthenticationContext authContext, public MainLayout(final AuthenticationContext authContext) {
@Autowired @Value("${git.commit.id.abbrev}") final String commitId) {
this.authContext = authContext; this.authContext = authContext;
setPrimarySection(Section.DRAWER); setPrimarySection(Section.DRAWER);
addDrawerContent(commitId); addDrawerContent();
addHeaderContent(); addHeaderContent();
} }
@ -115,12 +112,12 @@ public class MainLayout extends AppLayout {
return icon; return icon;
} }
private void addDrawerContent(final String commitId) { private void addDrawerContent() {
final Span appName = new Span("pfs-intra"); final Span appName = new Span("pfs-intra");
appName.addClassNames(LumoUtility.FontWeight.SEMIBOLD, LumoUtility.FontSize.LARGE); appName.addClassNames(LumoUtility.FontWeight.SEMIBOLD, LumoUtility.FontSize.LARGE);
final Header header = new Header(appName); final Header header = new Header(appName);
final Scroller scroller = new Scroller(createNavigation()); final Scroller scroller = new Scroller(createNavigation());
addToDrawer(header, scroller, createFooter(commitId)); addToDrawer(header, scroller, createFooter());
} }
private SideNav createNavigation() { private SideNav createNavigation() {
@ -153,7 +150,7 @@ public class MainLayout extends AppLayout {
LineAwesomeIcon.LIST_ALT.create())); LineAwesomeIcon.LIST_ALT.create()));
SideNavItem timesheet = new SideNavItem("My Timesheet", TimesheetView.class, SideNavItem timesheet = new SideNavItem("My Timesheet", TimesheetView.class,
LineAwesomeIcon.HOURGLASS_START_SOLID.create()); LineAwesomeIcon.HOURGLASS_START_SOLID.create());
timesheet.addItem(new SideNavItem("Registro de Horas Trabajadas", HoursWorkedListView.class, timesheet.addItem(new SideNavItem("Horas Trabajadas", HoursWorkedView.class,
LineAwesomeIcon.ID_CARD_SOLID.create())); LineAwesomeIcon.ID_CARD_SOLID.create()));
timesheet.addItem(new SideNavItem("Reporte Horas Trabajadas", ReporteView.class, timesheet.addItem(new SideNavItem("Reporte Horas Trabajadas", ReporteView.class,
LineAwesomeIcon.ID_CARD_SOLID.create())); LineAwesomeIcon.ID_CARD_SOLID.create()));
@ -172,8 +169,8 @@ public class MainLayout extends AppLayout {
return nav; return nav;
} }
private Footer createFooter(final String commitId) { private Footer createFooter() {
return new Footer(new Text(String.format("v.%s", commitId))); return new Footer();
} }
@Override @Override

View File

@ -1,17 +1,50 @@
package com.primefactorsolutions.views; package com.primefactorsolutions.views;
import com.primefactorsolutions.model.TimeOffRequest;
import com.primefactorsolutions.model.TimeOffRequestStatus;
import com.primefactorsolutions.service.TimeOffRequestService;
import com.vaadin.flow.component.Text; import com.vaadin.flow.component.Text;
import com.vaadin.flow.component.html.Main; import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import jakarta.annotation.security.PermitAll; import jakarta.annotation.security.PermitAll;
import java.time.LocalDate;
import java.util.List;
@PageTitle("Home") @PageTitle("Home")
@Route(value = "", layout = MainLayout.class) @Route(value = "", layout = MainLayout.class)
@PermitAll @PermitAll
public class MainView extends Main { public class MainView extends Main {
public MainView() { private final TimeOffRequestService requestService;
public MainView(final TimeOffRequestService requestService) {
this.requestService = requestService;
add(new Text("Welcome")); add(new Text("Welcome"));
updateRequestStatuses();
}
private void updateRequestStatuses() {
List<TimeOffRequest> requests = requestService.findAllTimeOffRequests();
LocalDate now = LocalDate.now();
for (TimeOffRequest request : requests) {
if (request.getState() == TimeOffRequestStatus.APROBADO) {
LocalDate expirationDate = request.getExpiration();
LocalDate startDate = request.getStartDate();
LocalDate endDate = request.getEndDate();
if (now.isAfter(expirationDate)) {
request.setState(TimeOffRequestStatus.VENCIDO);
} else if (now.isAfter(endDate) && now.isBefore(expirationDate)) {
request.setState(TimeOffRequestStatus.TOMADO);
} else if (now.isEqual(startDate) || now.isAfter(startDate) && now.isBefore(endDate)) {
request.setState(TimeOffRequestStatus.EN_USO);
}
}
}
requestService.saveAll(requests);
} }
} }

View File

@ -4,17 +4,11 @@ import com.primefactorsolutions.model.*;
import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.service.TeamService; import com.primefactorsolutions.service.TeamService;
import com.primefactorsolutions.service.TimeOffRequestService; import com.primefactorsolutions.service.TimeOffRequestService;
import com.primefactorsolutions.views.util.MenuBarUtils; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.contextmenu.MenuItem; import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.menubar.MenuBar;
import com.vaadin.flow.component.menubar.MenuBarVariant;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.function.ValueProvider;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.annotation.SpringComponent;
@ -25,23 +19,24 @@ import org.vaadin.firitin.components.grid.PagingGrid;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.primefactorsolutions.views.Constants.PAGE_SIZE;
@SpringComponent @SpringComponent
@Scope("prototype") @Scope("prototype")
@PageTitle("PendingRequests") @PageTitle("PendingRequests")
@Route(value = "/pending-requests", layout = MainLayout.class) @Route(value = "/pending-requests", layout = MainLayout.class)
@PermitAll @PermitAll
public class PendingRequestsListView extends BaseView { public class PendingRequestsListView extends Main {
private final TimeOffRequestService requestService; private final TimeOffRequestService requestService;
private final EmployeeService employeeService; private final EmployeeService employeeService;
private final TeamService teamService; private final TeamService teamService;
private final PagingGrid<TimeOffRequest> pendingRequestsGrid = new PagingGrid<>(); private final PagingGrid<TimeOffRequest> pendingRequestsGrid = new PagingGrid<>();
private List<Employee> employees = Collections.emptyList();
private ComboBox<Employee> employeeFilter; private ComboBox<Employee> employeeFilter;
private ComboBox<Team> teamFilter; private ComboBox<Team> teamFilter;
private ComboBox<TimeOffRequestType> categoryFilter; private ComboBox<TimeOffRequestType> categoryFilter;
private UUID selectedRequestId;
public PendingRequestsListView(final TimeOffRequestService requestService, public PendingRequestsListView(final TimeOffRequestService requestService,
final EmployeeService employeeService, final EmployeeService employeeService,
@ -49,6 +44,7 @@ public class PendingRequestsListView extends BaseView {
this.requestService = requestService; this.requestService = requestService;
this.employeeService = employeeService; this.employeeService = employeeService;
this.teamService = teamService; this.teamService = teamService;
this.employees = employeeService.findAllEmployees();
initializeView(); initializeView();
refreshGeneralPendingRequestsGrid(null, null, null); refreshGeneralPendingRequestsGrid(null, null, null);
} }
@ -56,46 +52,49 @@ public class PendingRequestsListView extends BaseView {
private void initializeView() { private void initializeView() {
setupFilters(); setupFilters();
setupPendingRequestsGrid(); setupPendingRequestsGrid();
add(pendingRequestsGrid);
add(createActionButtons());
} }
private void setupFilters() { private void setupFilters() {
final HorizontalLayout hl = new HorizontalLayout(); add(createEmployeeFilter());
hl.add(createEmployeeFilter()); add(createTeamFilter());
hl.add(createTeamFilter()); add(createCategoryFilter());
hl.add(createCategoryFilter());
getCurrentPageLayout().add(hl);
} }
private void setupPendingRequestsGrid() { private void setupPendingRequestsGrid() {
pendingRequestsGrid.addColumn(this::getEmployeeFullName).setHeader("Empleado"); pendingRequestsGrid.addColumn(this::getEmployeeFullName).setHeader("Empleado");
pendingRequestsGrid.addColumn(this::getTeamName).setHeader("Equipo"); pendingRequestsGrid.addColumn(this::getTeamName).setHeader("Equipo");
pendingRequestsGrid.addColumn(this::getCategory).setHeader("Categoría"); pendingRequestsGrid.addColumn(this::getCategory).setHeader("Categoría");
pendingRequestsGrid.addComponentColumn((ValueProvider<TimeOffRequest, Component>) timeOffRequest -> {
final MenuBar menuBar = new MenuBar();
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
final MenuItem approveItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.CHECK, "Aprobar");
approveItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
actionForRequest(timeOffRequest.getId(), TimeOffRequestStatus.APROBADO);
});
final MenuItem rejectItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.BAN, "Rechazar");
rejectItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
actionForRequest(timeOffRequest.getId(), TimeOffRequestStatus.RECHAZADO);
});
return menuBar;
});
pendingRequestsGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM); pendingRequestsGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
pendingRequestsGrid.setPageSize(PAGE_SIZE); pendingRequestsGrid.setPageSize(5);
pendingRequestsGrid.asSingleSelect().addValueChangeListener(event -> {
getCurrentPageLayout().add(pendingRequestsGrid); TimeOffRequest selectedRequest = event.getValue();
if (selectedRequest != null) {
selectedRequestId = selectedRequest.getId();
}
});
} }
private void actionForRequest(final UUID selectedRequestId, final TimeOffRequestStatus status) { private HorizontalLayout createActionButtons() {
Button approveButton = createActionButton("Aprobar", TimeOffRequestStatus.APROBADO);
Button rejectButton = createActionButton("Rechazar", TimeOffRequestStatus.RECHAZADO);
Button closeButton = new Button("Salir", event -> navigateToMainView());
return new HorizontalLayout(approveButton, rejectButton, closeButton);
}
private Button createActionButton(final String caption, final TimeOffRequestStatus status) {
return new Button(caption, event -> {
if (selectedRequestId != null) {
TimeOffRequest request = requestService.findTimeOffRequest(selectedRequestId); TimeOffRequest request = requestService.findTimeOffRequest(selectedRequestId);
request.setState(status); request.setState(status);
requestService.saveTimeOffRequest(request); requestService.saveTimeOffRequest(request);
refreshGeneralPendingRequestsGrid(null, null, null); refreshGeneralPendingRequestsGrid(null, null, null);
} else {
Notification.show("Seleccione una solicitud.", 3000, Notification.Position.MIDDLE);
}
});
} }
private void refreshGeneralPendingRequestsGrid(final Employee employee, private void refreshGeneralPendingRequestsGrid(final Employee employee,
@ -114,7 +113,7 @@ public class PendingRequestsListView extends BaseView {
final Team team, final Team team,
final TimeOffRequestType category) { final TimeOffRequestType category) {
List<TimeOffRequest> filteredPendingRequests List<TimeOffRequest> filteredPendingRequests
= requestService.findRequestsByState(TimeOffRequestStatus.SOLICITADO); = requestService.findRequestsByState(TimeOffRequestStatus.PENDIENTE);
if (employee != null && !"TODOS".equals(employee.getFirstName())) { if (employee != null && !"TODOS".equals(employee.getFirstName())) {
filteredPendingRequests = filteredPendingRequests.stream() filteredPendingRequests = filteredPendingRequests.stream()
@ -221,4 +220,8 @@ public class PendingRequestsListView extends BaseView {
allTeamsOption.setName("TODOS"); allTeamsOption.setName("TODOS");
return allTeamsOption; return allTeamsOption;
} }
private void navigateToMainView() {
getUI().ifPresent(ui -> ui.navigate(MainView.class));
}
} }

View File

@ -6,6 +6,7 @@ import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener; import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.data.provider.DataProvider; import com.vaadin.flow.data.provider.DataProvider;
import com.vaadin.flow.data.provider.DataProviderListener; import com.vaadin.flow.data.provider.DataProviderListener;
@ -26,14 +27,17 @@ import java.util.stream.Stream;
@PageTitle("Questions") @PageTitle("Questions")
@Route(value = "/questions", layout = MainLayout.class) @Route(value = "/questions", layout = MainLayout.class)
@PermitAll @PermitAll
public class QuestionsListView extends BaseView { public class QuestionsListView extends Main {
private final QuestionService questionService;
public QuestionsListView(final QuestionService questionService) { public QuestionsListView(final QuestionService questionService) {
this.questionService = questionService;
final HorizontalLayout hl = new HorizontalLayout(); final HorizontalLayout hl = new HorizontalLayout();
final Button addQuestion = new Button("Add Question"); final Button addQuestion = new Button("Add Question");
addQuestion.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> addQuestion.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
this.getUI().flatMap(ui -> ui.navigate(QuestionView.class, "new"))); this.getUI().get().navigate(QuestionView.class, "new");
});
hl.add(addQuestion); hl.add(addQuestion);
final VGrid<Question> grid = new VGrid<>(Question.class); final VGrid<Question> grid = new VGrid<>(Question.class);
@ -41,7 +45,7 @@ public class QuestionsListView extends BaseView {
grid.addComponentColumn((ValueProvider<Question, Component>) question -> { grid.addComponentColumn((ValueProvider<Question, Component>) question -> {
final Button edit = new Button("Edit"); final Button edit = new Button("Edit");
edit.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> edit.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent ->
this.getUI().flatMap(ui -> ui.navigate(QuestionView.class, question.getId().toString()))); this.getUI().get().navigate(QuestionView.class, question.getId().toString()));
return edit; return edit;
}); });
grid.setDataProvider(new DataProvider<>() { grid.setDataProvider(new DataProvider<>() {
@ -55,7 +59,6 @@ public class QuestionsListView extends BaseView {
return questionService.getQuestions().size(); return questionService.getQuestions().size();
} }
@SuppressWarnings("unused")
@Override @Override
public Stream<Question> fetch(final Query<Question, Object> query) { public Stream<Question> fetch(final Query<Question, Object> query) {
int limit = query.getLimit(); int limit = query.getLimit();
@ -81,6 +84,6 @@ public class QuestionsListView extends BaseView {
}); });
grid.setAllRowsVisible(true); grid.setAllRowsVisible(true);
getCurrentPageLayout().add(hl, grid); add(hl, grid);
} }
} }

View File

@ -35,7 +35,7 @@ import java.util.stream.Collectors;
@PermitAll @PermitAll
@Route(value = "/reportes", layout = MainLayout.class) @Route(value = "/reportes", layout = MainLayout.class)
@PageTitle("Reporte de Horas Trabajadas") @PageTitle("Reporte de Horas Trabajadas")
public class ReporteView extends BaseView { public class ReporteView extends VerticalLayout {
private final EmployeeService employeeService; private final EmployeeService employeeService;
private final HoursWorkedService hoursWorkedService; private final HoursWorkedService hoursWorkedService;
@ -51,7 +51,7 @@ public class ReporteView extends BaseView {
private final Span semanaInfoSpan = new Span(); private final Span semanaInfoSpan = new Span();
// Obtener el año actual // Obtener el año actual
private final int currentYear = LocalDate.now().getYear(); private int currentYear = LocalDate.now().getYear();
@Autowired @Autowired
public ReporteView(final HoursWorkedService hoursWorkedService, public ReporteView(final HoursWorkedService hoursWorkedService,
@ -63,7 +63,7 @@ public class ReporteView extends BaseView {
this.employeeService = employeeService; this.employeeService = employeeService;
H2 title = new H2("Reporte de Horas Trabajadas"); H2 title = new H2("Reporte de Horas Trabajadas");
getCurrentPageLayout().add(title); add(title);
List<Team> teams = teamService.findAllTeams(); List<Team> teams = teamService.findAllTeams();
equipoComboBox.setItems(teams); equipoComboBox.setItems(teams);
@ -80,20 +80,21 @@ public class ReporteView extends BaseView {
Button reportButton = new Button("Generar Reporte de Horas Trabajadas", Button reportButton = new Button("Generar Reporte de Horas Trabajadas",
event -> generateHoursWorkedReport()); event -> generateHoursWorkedReport());
getCurrentPageLayout().add(reportButton); HorizontalLayout filtersLayout = new HorizontalLayout(equipoComboBox, semanaComboBox, reportButton);
add(filtersLayout);
HorizontalLayout filtersLayout = new HorizontalLayout(equipoComboBox, semanaComboBox); // Añadir `headerLayout` al diseño principal para el encabezado dinámico
getCurrentPageLayout().add(filtersLayout); add(headerLayout);
getCurrentPageLayout().add(headerLayout);
updateHeaderLayout(null, null); updateHeaderLayout(null, null);
grid.addColumn(map -> map.get("ID")).setHeader("ID").getElement().getStyle().set("font-weight", "bold");
grid.addColumn(map -> map.get("Employee ID")).setHeader("Employee ID");
grid.addColumn(map -> map.get("Empleado")).setHeader("Empleado"); grid.addColumn(map -> map.get("Empleado")).setHeader("Empleado");
grid.addColumn(map -> map.get("Horas Trabajadas")).setHeader("Horas Trabajadas"); grid.addColumn(map -> map.get("Horas Trabajadas")).setHeader("Horas Trabajadas");
grid.addColumn(map -> map.get("Horas Pendientes")).setHeader("Horas Pendientes"); grid.addColumn(map -> map.get("Horas Pendientes")).setHeader("Horas Pendientes");
grid.addColumn(map -> map.get("Observaciones")).setHeader("Observaciones"); grid.addColumn(map -> map.get("Observaciones")).setHeader("Observaciones");
getCurrentPageLayout().add(grid); add(grid);
} }
private void initializeSemanaComboBox() { private void initializeSemanaComboBox() {
@ -105,11 +106,12 @@ public class ReporteView extends BaseView {
.map(date -> { .map(date -> {
int weekNumber = date.get(WeekFields.of(DayOfWeek.MONDAY, 1) int weekNumber = date.get(WeekFields.of(DayOfWeek.MONDAY, 1)
.weekOfWeekBasedYear()); .weekOfWeekBasedYear());
LocalDate endOfWeek = date.plusDays(6); LocalDate startOfWeek = date;
LocalDate endOfWeek = startOfWeek.plusDays(6);
return String.format("Semana %d: %s - %s", return String.format("Semana %d: %s - %s",
weekNumber, weekNumber,
date.getDayOfMonth() + " de " + date.getMonth() startOfWeek.getDayOfMonth() + " de " + startOfWeek.getMonth()
.getDisplayName(TextStyle.FULL, Locale.getDefault()), .getDisplayName(TextStyle.FULL, Locale.getDefault()),
endOfWeek.getDayOfMonth() + " de " + endOfWeek.getMonth() endOfWeek.getDayOfMonth() + " de " + endOfWeek.getMonth()
.getDisplayName(TextStyle.FULL, Locale.getDefault()) .getDisplayName(TextStyle.FULL, Locale.getDefault())
@ -140,9 +142,7 @@ public class ReporteView extends BaseView {
.getId()) && hw.getWeekNumber() == weekNumber) .getId()) && hw.getWeekNumber() == weekNumber)
.collect(Collectors.toList()); .collect(Collectors.toList());
System.out.println(hoursWorkedList);
if (hoursWorkedList.isEmpty()) { if (hoursWorkedList.isEmpty()) {
Notification.show("No hay horas trabajadas disponibles para generar el reporte.", Notification.show("No hay horas trabajadas disponibles para generar el reporte.",
3000, Notification.Position.MIDDLE); 3000, Notification.Position.MIDDLE);
return; return;
@ -170,8 +170,15 @@ public class ReporteView extends BaseView {
headerLayout.removeAll(); headerLayout.removeAll();
if (team != null && dateInWeek != null) { if (team != null && dateInWeek != null) {
LocalDate startOfWeek = dateInWeek.with(DayOfWeek.FRIDAY);
LocalDate endOfWeek = dateInWeek.with(DayOfWeek.THURSDAY);
int weekNumber = getWeekOfYear(dateInWeek); int weekNumber = getWeekOfYear(dateInWeek);
String formattedStartDate = startOfWeek.getDayOfMonth() + " de "
+ startOfWeek.getMonth().getDisplayName(TextStyle.FULL, Locale.getDefault());
String formattedEndDate = endOfWeek.getDayOfMonth() + " de "
+ endOfWeek.getMonth().getDisplayName(TextStyle.FULL, Locale.getDefault());
headerLayout.add(new Span("Informe " headerLayout.add(new Span("Informe "
+ String.format("%03d", weekNumber) + "/" + currentYear) {{ + String.format("%03d", weekNumber) + "/" + currentYear) {{
getStyle().set("font-size", "24px"); getStyle().set("font-size", "24px");
@ -199,7 +206,7 @@ public class ReporteView extends BaseView {
private void generateExcelDownloadLink(final List<Map<String, Object>> data, final int weekNumber) { private void generateExcelDownloadLink(final List<Map<String, Object>> data, final int weekNumber) {
try { try {
List<String> headers = List.of("Empleado", List<String> headers = List.of("ID", "Employee ID", "Empleado",
"Horas Trabajadas", "Horas Pendientes", "Observaciones"); "Horas Trabajadas", "Horas Pendientes", "Observaciones");
String selectedTeam = equipoComboBox.getValue().getName(); String selectedTeam = equipoComboBox.getValue().getName();
byte[] excelBytes = reportService.writeAsExcel( byte[] excelBytes = reportService.writeAsExcel(
@ -210,7 +217,7 @@ public class ReporteView extends BaseView {
if (downloadLink == null) { if (downloadLink == null) {
downloadLink = new Anchor(excelResource, "Descargar Reporte en Excel"); downloadLink = new Anchor(excelResource, "Descargar Reporte en Excel");
downloadLink.getElement().setAttribute("download", true); downloadLink.getElement().setAttribute("download", true);
getCurrentPageLayout().add(downloadLink); add(downloadLink);
} else { } else {
downloadLink.setHref(excelResource); downloadLink.setHref(excelResource);
} }

View File

@ -4,54 +4,36 @@ import com.primefactorsolutions.model.*;
import com.primefactorsolutions.service.EmployeeService; import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.service.TimeOffRequestService; import com.primefactorsolutions.service.TimeOffRequestService;
import com.primefactorsolutions.service.VacationService; import com.primefactorsolutions.service.VacationService;
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.contextmenu.MenuItem; import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.H3; import com.vaadin.flow.component.html.H3;
import com.vaadin.flow.component.html.Span; import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.menubar.MenuBar;
import com.vaadin.flow.component.menubar.MenuBarVariant;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.function.ValueProvider;
import com.vaadin.flow.router.BeforeEvent; import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.HasUrlParameter; import com.vaadin.flow.router.HasUrlParameter;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; 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 com.vaadin.flow.spring.annotation.SpringComponent;
import jakarta.annotation.security.PermitAll; 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.springframework.context.annotation.Scope;
import org.vaadin.firitin.components.grid.PagingGrid; 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.LocalDate;
import java.time.Period; import java.time.Period;
import java.util.*; import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.primefactorsolutions.views.Constants.PAGE_SIZE;
import static com.primefactorsolutions.views.util.MenuBarUtils.createIconItem;
@SpringComponent @SpringComponent
@PermitAll @PermitAll
@Scope("prototype") @Scope("prototype")
@PageTitle("Employee Request") @PageTitle("RequestEmployee")
@Route(value = "/requests", layout = MainLayout.class) @Route(value = "/requests", layout = MainLayout.class)
public class RequestEmployeeView extends BaseView implements HasUrlParameter<String> { public class RequestEmployeeView extends Div implements HasUrlParameter<String> {
private final TimeOffRequestService requestService; private final TimeOffRequestService requestService;
private final EmployeeService employeeService; private final EmployeeService employeeService;
@ -61,6 +43,7 @@ public class RequestEmployeeView extends BaseView implements HasUrlParameter<Str
private ComboBox<TimeOffRequestType> categoryFilter; private ComboBox<TimeOffRequestType> categoryFilter;
private ComboBox<TimeOffRequestStatus> stateFilter; private ComboBox<TimeOffRequestStatus> stateFilter;
private UUID employeeId; private UUID employeeId;
private TimeOffRequest request;
public RequestEmployeeView(final TimeOffRequestService requestService, public RequestEmployeeView(final TimeOffRequestService requestService,
final EmployeeService employeeService, final EmployeeService employeeService,
@ -71,20 +54,16 @@ public class RequestEmployeeView extends BaseView implements HasUrlParameter<Str
} }
private void initializeView() { private void initializeView() {
requestService.updateRequestStatuses();
Button downloadButton = new Button("Descargar reporte", event -> downloadReport());
getCurrentPageLayout().add(downloadButton);
setupFilters(); setupFilters();
setupGrid(); setupGrid();
getCurrentPageLayout().add(requestGrid, new H3("Balance"), createSummaryLayout()); add(requestGrid, createActionButtons(), createSummaryLayout());
refreshRequestGrid(null, null); refreshRequestGrid(null, null);
} }
private void setupFilters() { private void setupFilters() {
categoryFilter = createCategoryFilter(); categoryFilter = createCategoryFilter();
stateFilter = createStateFilter(); stateFilter = createStateFilter();
HorizontalLayout hl = new HorizontalLayout(categoryFilter, stateFilter); add(categoryFilter, stateFilter);
getCurrentPageLayout().add(hl);
} }
private ComboBox<TimeOffRequestType> createCategoryFilter() { private ComboBox<TimeOffRequestType> createCategoryFilter() {
@ -116,163 +95,40 @@ public class RequestEmployeeView extends BaseView implements HasUrlParameter<Str
requestGrid.getColumnByKey("startDate").setHeader("Fecha de Inicio"); requestGrid.getColumnByKey("startDate").setHeader("Fecha de Inicio");
requestGrid.getColumnByKey("endDate").setHeader("Fecha de Fin"); requestGrid.getColumnByKey("endDate").setHeader("Fecha de Fin");
requestGrid.getColumnByKey("daysToBeTake").setHeader("Días a Tomar"); requestGrid.getColumnByKey("daysToBeTake").setHeader("Días a Tomar");
requestGrid.addComponentColumn((ValueProvider<TimeOffRequest, Component>) timeOffRequest -> {
final MenuBar menuBar = new MenuBar();
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
final MenuItem view = createIconItem(menuBar, VaadinIcon.EYE, "View");
view.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent ->
navigateToViewRequest(timeOffRequest));
final MenuItem edit = createIconItem(menuBar, VaadinIcon.PENCIL, "Edit");
edit.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent ->
navigateToEditRequest(timeOffRequest));
return menuBar;
});
requestGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM); requestGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
requestGrid.setPageSize(PAGE_SIZE); requestGrid.setPageSize(5);
requestGrid.asSingleSelect().addValueChangeListener(event -> {
TimeOffRequest selectedRequest = event.getValue();
if (selectedRequest != null) {
request = selectedRequest;
} }
});
private Set<TimeOffRequestType> getStandardExclusions() {
return Set.of(
TimeOffRequestType.MATERNIDAD,
TimeOffRequestType.PATERNIDAD,
TimeOffRequestType.MATRIMONIO,
TimeOffRequestType.DUELO_1ER_GRADO,
TimeOffRequestType.DUELO_2ER_GRADO,
TimeOffRequestType.DIA_DEL_PADRE,
TimeOffRequestType.DIA_DE_LA_MADRE
);
}
private Set<TimeOffRequestType> getMaleSpecificExclusions() {
return Set.of(
TimeOffRequestType.DIA_DE_LA_MUJER_INTERNACIONAL,
TimeOffRequestType.DIA_DE_LA_MUJER_NACIONAL
);
} }
private VerticalLayout createSummaryLayout() { private VerticalLayout createSummaryLayout() {
Employee employee = employeeService.getEmployee(employeeId); double totalHoliday = requests.stream()
boolean isMale = employee.getGender() == Employee.Gender.MALE; .filter(this::verificationIsHoliday)
int currentYear = LocalDate.now().getYear(); .mapToDouble(TimeOffRequest::getAvailableDays)
LocalDate currentDate = LocalDate.now(); .sum();
double totalVacations = calculateVacationDays(employeeService.getEmployee(employeeId));
double totalPersonalDays = requests.stream()
.filter(req -> !verificationIsHoliday(req))
.filter(req -> !req.getCategory().name().startsWith("VACACION"))
.mapToDouble(TimeOffRequest::getAvailableDays)
.sum();
List<Vacation> vacations = vacationService.findVacations(); double totalAvailableDays = totalHoliday + totalVacations + totalPersonalDays;
double healthLicence = getHealthLicence(employeeId);
double totalFixedAndMovableHolidays = calculateHolidayDays(vacations);
double totalPersonalDays = calculatePersonalDays(vacations, isMale);
List<Double> vacationDays = calculateVacationDays(employee);
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 = 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;
return new VerticalLayout( return new VerticalLayout(
new Span("Total feriados fijos y movibles: " + remainingHolidayDays), new Span("Total feriados: " + totalHoliday),
new Span("Total días libres personales: " + remainingPersonalDays), new Span("Total vacaciones: " + totalVacations),
new Span("Total vacaciones pendientes de uso: " + remainingVacationDays), new Span("Total días personales: " + totalPersonalDays),
new Span("TOTAL GENERAL DE DÍAS DISPONIBLES: " + totalAvailableDays) new Span("Total general: " + totalAvailableDays)
); );
} }
private double getHealthLicence(final UUID employeeId) { private double calculateVacationDays(final Employee employee) {
List<TimeOffRequest> 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<TimeOffRequest> 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<Vacation> vacations) {
return vacations.stream()
.filter(req -> req.getType() != Vacation.Type.OTHER)
.mapToDouble(Vacation::getDuration)
.sum();
}
private double calculatePersonalDays(final List<Vacation> vacations, final boolean isMale) {
return vacations.stream()
.filter(req -> req.getType() == Vacation.Type.OTHER)
.filter(req -> !getStandardExclusions().contains(req.getCategory()))
.filter(req -> !(isMale && getMaleSpecificExclusions().contains(req.getCategory())))
.filter(req -> !req.getCategory().name().startsWith("VACACION"))
.filter(req -> req.getCategory() != TimeOffRequestType.PERMISOS_DE_SALUD)
.mapToDouble(Vacation::getDuration)
.sum();
}
private List<Double> calculateVacationDays(final Employee employee) {
List<Double> vacationDays = new ArrayList<>();
if (employee.getDateOfEntry() != null) { if (employee.getDateOfEntry() != null) {
LocalDate entryDate = employee.getDateOfEntry(); LocalDate entryDate = employee.getDateOfEntry();
LocalDate today = LocalDate.now(); LocalDate today = LocalDate.now();
@ -308,44 +164,11 @@ public class RequestEmployeeView extends BaseView implements HasUrlParameter<Str
); );
} }
vacationDays.add(calculateVacationDaysSinceEntry(entryDate, previousVacationYearDate)); return calculateVacationDaysSinceEntry(entryDate, previousVacationYearDate)
vacationDays.add(calculateVacationDaysSinceEntry(entryDate, currentVacationYearDate)); + calculateVacationDaysSinceEntry(entryDate, currentVacationYearDate);
} else { } else {
vacationDays.add(0.0); return 0.0;
vacationDays.add(0.0);
} }
return vacationDays;
}
private double calculateHolidayUtilizedDays(final int year) {
return requests.stream()
.filter(this::verificationIsHoliday)
.filter(req -> req.getState() == TimeOffRequestStatus.TOMADO
|| req.getState() == TimeOffRequestStatus.APROBADO)
.filter(req -> getStartDateYear(req) == year)
.mapToDouble(TimeOffRequest::getDaysToBeTake)
.sum();
}
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 -> !getStandardExclusions().contains(req.getCategory()))
.filter(req -> !(isMale && getMaleSpecificExclusions().contains(req.getCategory())))
.filter(req -> !req.getCategory().name().startsWith("VACACION"))
.filter(req -> req.getCategory() != TimeOffRequestType.PERMISOS_DE_SALUD)
.filter(req -> getStartDateYear(req) == year)
.mapToDouble(TimeOffRequest::getDaysToBeTake)
.sum();
}
private int getStartDateYear(final TimeOffRequest request) {
if (request.getStartDate() != null) {
return request.getStartDate().getYear();
}
return 0;
} }
private double calculateVacationDaysSinceEntry(final LocalDate dateOfEntry, final LocalDate date) { private double calculateVacationDaysSinceEntry(final LocalDate dateOfEntry, final LocalDate date) {
@ -367,6 +190,28 @@ public class RequestEmployeeView extends BaseView implements HasUrlParameter<Str
return vacation.getType() != Vacation.Type.OTHER; return vacation.getType() != Vacation.Type.OTHER;
} }
private HorizontalLayout createActionButtons() {
Button viewButton = createButton("Ver", () -> navigateToViewRequest(request));
Button editButton = createButton("Editar", () -> navigateToEditRequest(request));
Button closeButton = new Button("Salir", event -> navigateToRequestsListView());
return new HorizontalLayout(viewButton, editButton, closeButton);
}
private Button createButton(final String caption, final Runnable action) {
return new Button(caption, event -> {
if (request != null) {
action.run();
} else {
Notification.show("Seleccione una solicitud.", 3000, Notification.Position.MIDDLE);
}
});
}
private void navigateToRequestsListView() {
getUI().ifPresent(ui -> ui.navigate(RequestsListView.class));
}
private void navigateToEditRequest(final TimeOffRequest request) { private void navigateToEditRequest(final TimeOffRequest request) {
navigateToRequestView(request, "edit"); navigateToRequestView(request, "edit");
} }
@ -391,9 +236,7 @@ public class RequestEmployeeView extends BaseView implements HasUrlParameter<Str
final int pageSize, final int pageSize,
final TimeOffRequestType category, final TimeOffRequestType category,
final TimeOffRequestStatus state) { final TimeOffRequestStatus state) {
requests = requestService.findRequestsByEmployeeId(employeeId); requests = requestService.findRequestsByEmployeeId(employeeId);
generateRequests();
if (category != null && !"TODOS".equals(category.name())) { if (category != null && !"TODOS".equals(category.name())) {
requests = requests.stream() requests = requests.stream()
.filter(req -> req.getCategory().equals(category)) .filter(req -> req.getCategory().equals(category))
@ -408,216 +251,18 @@ public class RequestEmployeeView extends BaseView implements HasUrlParameter<Str
return requests.subList(start, end); return requests.subList(start, end);
} }
public void generateRequests() {
boolean isMale = isEmployeeMale();
for (TimeOffRequestType type : TimeOffRequestType.values()) {
if (shouldIncludeRequest(type) && isValidRequestType(type, isMale)) {
TimeOffRequest request = createRequest(type);
if (isVacationExpired(request)) {
request.setState(TimeOffRequestStatus.VENCIDO);
} else {
request.setState(TimeOffRequestStatus.PENDIENTE);
}
requests.add(request);
}
}
}
private boolean isEmployeeMale() {
return employeeService.getEmployee(employeeId).getGender() == Employee.Gender.MALE;
}
private boolean isValidRequestType(final TimeOffRequestType type, final boolean isMale) {
return !getStandardExclusions().contains(type)
&& !(isMale && getMaleSpecificExclusions().contains(type))
&& type != TimeOffRequestType.TODOS;
}
private TimeOffRequest createRequest(final TimeOffRequestType type) {
TimeOffRequest request = new TimeOffRequest();
request.setCategory(type);
return request;
}
private boolean isVacationExpired(final TimeOffRequest request) {
Vacation vacation = vacationService.findVacationByCategory(request.getCategory());
if (vacation != null && vacation.getMonthOfYear() != null && vacation.getDayOfMonth() != null) {
int vacationMonth = vacation.getMonthOfYear();
int vacationDay = vacation.getDayOfMonth();
int currentMonth = LocalDate.now().getMonthValue();
int currentDay = LocalDate.now().getDayOfMonth();
return vacationMonth < currentMonth || (vacationMonth == currentMonth && vacationDay < currentDay);
}
return false;
}
private boolean shouldIncludeRequest(final TimeOffRequestType type) {
List<TimeOffRequest> existingRequest = requestService.findByEmployeeAndCategory(employeeId, type);
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<TimeOffRequest> 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 @Override
public void setParameter(final BeforeEvent event, final String parameter) { public void setParameter(final BeforeEvent event, final String parameter) {
employeeId = UUID.fromString(parameter); employeeId = UUID.fromString(parameter);
Employee employee = employeeService.getEmployee(employeeId); Employee employee = employeeService.getEmployee(employeeId);
requests = requestService.findRequestsByEmployeeId(employeeId); requests = requestService.findRequestsByEmployeeId(employeeId);
setViewTitle( setViewTitle(employee.getFirstName() + " " + employee.getLastName(), employee.getTeam().getName());
employee.getFirstName() + " " + employee.getLastName(),
employee.getTeam().getName(),
employee.getDateOfExit()
);
requestGrid.setItems(requests); requestGrid.setItems(requests);
initializeView(); initializeView();
} }
private void setViewTitle(final String employeeName, final String employeeTeam, final LocalDate dateOfExit) { private void setViewTitle(final String employeeName, final String employeeTeam) {
addComponentAsFirst(new H3("Nombre del empleado: " + employeeName)); addComponentAsFirst(new H3("Nombre del empleado: " + employeeName));
addComponentAtIndex(1, new H3("Equipo: " + employeeTeam)); addComponentAtIndex(1, new H3("Equipo: " + employeeTeam));
if (dateOfExit != null) {
addComponentAtIndex(2, new H3("Descontado a cero en fecha " + dateOfExit + " por pago de finiquito."));
}
} }
} }

View File

@ -19,7 +19,6 @@ import jakarta.annotation.security.PermitAll;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.DayOfWeek;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
@ -64,7 +63,6 @@ public class RequestRegisterView extends VerticalLayout {
} }
private void initializeView() { private void initializeView() {
requestService.updateRequestStatuses();
configureFormFields(); configureFormFields();
configureButtons(); configureButtons();
configureBinder(); configureBinder();
@ -86,31 +84,16 @@ public class RequestRegisterView extends VerticalLayout {
employeeComboBox.setItemLabelGenerator(emp -> emp.getFirstName() + " " + emp.getLastName()); employeeComboBox.setItemLabelGenerator(emp -> emp.getFirstName() + " " + emp.getLastName());
employeeComboBox.addValueChangeListener(event -> { employeeComboBox.addValueChangeListener(event -> {
employee = event.getValue(); employee = event.getValue();
System.out.println("Clearing form..." + employee);
handleEmployeeSelection(event.getValue()); handleEmployeeSelection(event.getValue());
}); });
categoryComboBox.addValueChangeListener(event -> { categoryComboBox.addValueChangeListener(event -> {
onCategoryChange(event.getValue()); onCategoryChange(event.getValue());
handleCategorySelection(event.getValue()); handleCategorySelection(event.getValue());
}); });
startDatePicker.addValueChangeListener(event -> { startDatePicker.addValueChangeListener(event -> updateDatePickerMinValues());
LocalDate selectedDate = event.getValue(); endDatePicker.addValueChangeListener(event -> calculateDays());
if (selectedDate != null && (selectedDate.getDayOfWeek().getValue() == 6
|| selectedDate.getDayOfWeek().getValue() == 7)) {
startDatePicker.setValue(selectedDate.minusDays(1));
}
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)) {
endDatePicker.setValue(selectedDate.minusDays(1));
}
calculateDays();
});
} }
private void configureBinder() { private void configureBinder() {
@ -153,39 +136,15 @@ public class RequestRegisterView extends VerticalLayout {
List<TimeOffRequestType> availableCategories = allCategories.stream() List<TimeOffRequestType> availableCategories = allCategories.stream()
.filter(category -> isCategoryAvailable(employeeRequests, category)) .filter(category -> isCategoryAvailable(employeeRequests, category))
.filter(category -> isCategoryAllowedByGender(category, employee.getGender())) .filter(category -> isCategoryAllowedByGender(category, employee.getGender()))
.filter(category -> category != TimeOffRequestType.TODOS) .filter(category -> category != TimeOffRequestType.VACACION_GESTION_ANTERIOR
.filter(category -> shouldIncludeVacationGestionActual(employeeRequests, category)) && category != TimeOffRequestType.TODOS)
.filter(category -> shouldIncludeVacationGestionAnterior(employeeRequests, category))
.toList(); .toList();
categoryComboBox.setItems(availableCategories); categoryComboBox.setItems(availableCategories);
} }
private boolean shouldIncludeVacationGestionActual(final List<TimeOffRequest> employeeRequests,
final TimeOffRequestType category) {
if (category != TimeOffRequestType.VACACION_GESTION_ACTUAL) {
return true;
}
return employeeRequests.stream()
.anyMatch(request -> request.getCategory() == TimeOffRequestType.VACACION_GESTION_ANTERIOR
&& request.getDaysBalance() == 0
&& request.getState() == TimeOffRequestStatus.TOMADO);
}
private boolean shouldIncludeVacationGestionAnterior(final List<TimeOffRequest> employeeRequests,
final TimeOffRequestType category) {
if (category != TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
return true;
}
return employeeRequests.stream()
.noneMatch(request -> request.getCategory() == TimeOffRequestType.VACACION_GESTION_ANTERIOR
&& request.getDaysBalance() == 0);
}
private void onCategoryChange(final TimeOffRequestType selectedCategory) { private void onCategoryChange(final TimeOffRequestType selectedCategory) {
if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ACTUAL if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ACTUAL) {
|| selectedCategory == TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
startDatePicker.setEnabled(true); startDatePicker.setEnabled(true);
endDatePicker.setEnabled(true); endDatePicker.setEnabled(true);
} else { } else {
@ -196,10 +155,6 @@ public class RequestRegisterView extends VerticalLayout {
private boolean isCategoryAvailable(final List<TimeOffRequest> employeeRequests, private boolean isCategoryAvailable(final List<TimeOffRequest> employeeRequests,
final TimeOffRequestType category) { final TimeOffRequestType category) {
if (category == TimeOffRequestType.CUMPLEAÑOS && employee.getBirthday() == null) {
return false;
}
List<TimeOffRequest> requestsByCategory = employeeRequests.stream() List<TimeOffRequest> requestsByCategory = employeeRequests.stream()
.filter(request -> request.getCategory() == category) .filter(request -> request.getCategory() == category)
.toList(); .toList();
@ -212,21 +167,13 @@ public class RequestRegisterView extends VerticalLayout {
.max(Comparator.comparing(TimeOffRequest::getStartDate)) .max(Comparator.comparing(TimeOffRequest::getStartDate))
.orElse(null); .orElse(null);
boolean isSpecialCategory = category == TimeOffRequestType.PERMISOS_DE_SALUD if (category == TimeOffRequestType.PERMISOS_DE_SALUD
|| category == TimeOffRequestType.VACACION_GESTION_ACTUAL || category == TimeOffRequestType.VACACION_GESTION_ACTUAL
|| category == TimeOffRequestType.VACACION_GESTION_ANTERIOR; || category == TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
return latestRequest.getState() == TimeOffRequestStatus.VENCIDO
if (isSpecialCategory) { || (latestRequest.getState() == TimeOffRequestStatus.TOMADO && latestRequest.getDaysBalance() > 0);
return (latestRequest.getState() == TimeOffRequestStatus.TOMADO
&& latestRequest.getDaysBalance() > 0)
|| latestRequest.getState() == TimeOffRequestStatus.RECHAZADO
|| (latestRequest.getState() == TimeOffRequestStatus.TOMADO
&& latestRequest.getDaysBalance() == 0
&& latestRequest.getExpiration().isBefore(LocalDate.now()));
} else { } else {
return (latestRequest.getState() == TimeOffRequestStatus.TOMADO return latestRequest.getState() == TimeOffRequestStatus.VENCIDO;
&& latestRequest.getExpiration().isBefore(LocalDate.now()))
|| latestRequest.getState() == TimeOffRequestStatus.RECHAZADO;
} }
} }
@ -252,40 +199,30 @@ public class RequestRegisterView extends VerticalLayout {
vacation = vacationService.findVacationByCategory(selectedCategory); vacation = vacationService.findVacationByCategory(selectedCategory);
UUID employeeId = employeeComboBox.getValue().getId(); UUID employeeId = employeeComboBox.getValue().getId();
List<TimeOffRequest> requests = requestService.findByEmployeeAndCategory(employeeId, selectedCategory); List<TimeOffRequest> requests = requestService.findByEmployeeAndCategory(employeeId, selectedCategory);
if (vacation != null) { if (vacation != null) {
TimeOffRequest requestWithBalance = requests.stream() TimeOffRequest requestWithBalance = requests.stream()
.filter(request -> request.getDaysBalance() > 0 .filter(request -> request.getDaysBalance() > 0
&& request.getState() != TimeOffRequestStatus.VENCIDO && request.getState() != TimeOffRequestStatus.VENCIDO)
&& request.getState() != TimeOffRequestStatus.RECHAZADO)
.max(Comparator.comparing(TimeOffRequest::getStartDate)) .max(Comparator.comparing(TimeOffRequest::getStartDate))
.orElse(null); .orElse(null);
if (requestWithBalance != null) { if (requestWithBalance != null) {
if (requestWithBalance.getState() == TimeOffRequestStatus.TOMADO if (requestWithBalance.getState() == TimeOffRequestStatus.TOMADO) {
&& requestWithBalance.getDaysBalance() > 0) {
availableDaysField.setValue(requestWithBalance.getDaysBalance()); availableDaysField.setValue(requestWithBalance.getDaysBalance());
} else { } else if (requestWithBalance.getState() == TimeOffRequestStatus.VENCIDO) {
availableDaysField.setValue(vacation.getDuration()); availableDaysField.setValue(vacation.getDuration());
} }
} else if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ACTUAL } else if (vacation.getCategory() == TimeOffRequestType.VACACION_GESTION_ACTUAL) {
|| selectedCategory == TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
LocalDate dateOfEntry = employeeComboBox.getValue().getDateOfEntry(); LocalDate dateOfEntry = employeeComboBox.getValue().getDateOfEntry();
LocalDate currentDate = LocalDate.now(); LocalDate currentDate = LocalDate.now();
long yearsOfService = ChronoUnit.YEARS.between(dateOfEntry, currentDate); long yearsOfService = ChronoUnit.YEARS.between(dateOfEntry, currentDate);
if (selectedCategory == TimeOffRequestType.VACACION_GESTION_ANTERIOR) {
yearsOfService -= 1;
}
if (yearsOfService > 10) { if (yearsOfService > 10) {
availableDaysField.setValue(30.0); availableDaysField.setValue((double) 30);
} else if (yearsOfService > 5) { } else if (yearsOfService > 5) {
availableDaysField.setValue(20.0); availableDaysField.setValue((double) 20);
} else if (yearsOfService > 1) { } else if (yearsOfService > 1) {
availableDaysField.setValue(15.0); availableDaysField.setValue((double) 15);
} else { } else {
availableDaysField.setValue(0.0); availableDaysField.setValue((double) 0);
} }
} else { } else {
availableDaysField.setValue(vacation.getDuration()); availableDaysField.setValue(vacation.getDuration());
@ -311,11 +248,7 @@ public class RequestRegisterView extends VerticalLayout {
} }
if (startDate != null) { if (startDate != null) {
if (vacation.getExpiration() != null) {
endDate = startDate.plusDays(vacation.getExpiration().intValue() - 1); endDate = startDate.plusDays(vacation.getExpiration().intValue() - 1);
} else {
endDate = LocalDate.of(startDate.getYear(), 12, 31);
}
} else { } else {
startDate = LocalDate.now(); startDate = LocalDate.now();
} }
@ -334,23 +267,19 @@ public class RequestRegisterView extends VerticalLayout {
.map(request -> request.getStartDate().getYear()) .map(request -> request.getStartDate().getYear())
.orElse(LocalDate.now().getYear()); .orElse(LocalDate.now().getYear());
if (previousRequests.getLast().getState() != TimeOffRequestStatus.RECHAZADO) {
lastRequestYear = lastRequestYear + 1;
}
int currentYear = LocalDate.now().getYear(); int currentYear = LocalDate.now().getYear();
return Math.max(lastRequestYear, currentYear); return Math.max(lastRequestYear + 1, currentYear);
} }
private LocalDate determineStartDate(final Vacation vacation, final int startYear) { private LocalDate determineStartDate(final Vacation vacation, final int startYear) {
if (vacation.getCategory() == TimeOffRequestType.CUMPLEAÑOS && employee.getBirthday() != null) {
return LocalDate.of(startYear, employee.getBirthday().getMonth(), employee.getBirthday().getDayOfMonth());
}
if (vacation.getMonthOfYear() != null && vacation.getDayOfMonth() != null) { if (vacation.getMonthOfYear() != null && vacation.getDayOfMonth() != null) {
return LocalDate.of(startYear, vacation.getMonthOfYear().intValue(), vacation.getDayOfMonth().intValue()); return LocalDate.of(startYear, vacation.getMonthOfYear().intValue(), vacation.getDayOfMonth().intValue());
} }
if (vacation.getCategory() == TimeOffRequestType.CUMPLEAÑOS && employee.getBirthday() != null) {
return LocalDate.of(startYear, employee.getBirthday().getMonth(), employee.getBirthday().getDayOfMonth());
}
if (vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD) { if (vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD) {
return LocalDate.now(); return LocalDate.now();
} }
@ -362,9 +291,7 @@ public class RequestRegisterView extends VerticalLayout {
startDatePicker.setValue(startDate); startDatePicker.setValue(startDate);
if ((vacation.getDuration() != null && vacation.getDuration() == 0.5) if ((vacation.getDuration() != null && vacation.getDuration() == 0.5)
|| vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD || vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD) {
|| vacation.getCategory() == TimeOffRequestType.CUMPLEAÑOS) {
endDatePicker.setValue(startDate); endDatePicker.setValue(startDate);
} else { } else {
int durationDays = (vacation.getDuration() != null ? vacation.getDuration().intValue() - 1 : 0); int durationDays = (vacation.getDuration() != null ? vacation.getDuration().intValue() - 1 : 0);
@ -397,26 +324,13 @@ public class RequestRegisterView extends VerticalLayout {
Double availableDays = availableDaysField.getValue(); Double availableDays = availableDaysField.getValue();
if (areDatesValid(startDate, endDate)) { if (areDatesValid(startDate, endDate)) {
long workDays = countWorkDaysBetween(startDate, endDate);
daysToBeTakenField.setValue((double) workDays);
balanceDaysField.setValue(availableDaysField.getValue() - workDays);
double daysToBeTaken = calculateDaysBetween(startDate, endDate); double daysToBeTaken = calculateDaysBetween(startDate, endDate);
setDaysToBeTakenField(daysToBeTaken); setDaysToBeTakenField(daysToBeTaken);
double balanceDays = calculateBalanceDays(availableDays, daysToBeTakenField.getValue()); double balanceDays = calculateBalanceDays(availableDays, daysToBeTakenField.getValue());
balanceDaysField.setValue(balanceDays); balanceDaysField.setValue(balanceDays);
if (balanceDays < 0.0) { if (balanceDays < 0) {
clearFields();
}
if (daysToBeTakenField.getValue() > 10
&& (categoryComboBox.getValue() == TimeOffRequestType.VACACION_GESTION_ANTERIOR
|| categoryComboBox.getValue() == TimeOffRequestType.VACACION_GESTION_ACTUAL)) {
clearFields(); clearFields();
} }
} }
@ -426,28 +340,12 @@ public class RequestRegisterView extends VerticalLayout {
return startDate != null && endDate != null; return startDate != null && endDate != null;
} }
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();
}
private double calculateDaysBetween(final LocalDate startDate, final LocalDate endDate) { private double calculateDaysBetween(final LocalDate startDate, final LocalDate endDate) {
return startDate.datesUntil(endDate.plusDays(1)) return java.time.temporal.ChronoUnit.DAYS.between(startDate, endDate) + 1;
.filter(date -> {
DayOfWeek day = date.getDayOfWeek();
return day != DayOfWeek.SATURDAY && day != DayOfWeek.SUNDAY;
})
.count();
} }
private void setDaysToBeTakenField(final double daysToBeTaken) { private void setDaysToBeTakenField(final double daysToBeTaken) {
if (vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD if (vacation.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD) {
|| vacation.getCategory() == TimeOffRequestType.CUMPLEAÑOS
|| vacation.getCategory() == TimeOffRequestType.DIA_DEL_PADRE
|| vacation.getCategory() == TimeOffRequestType.DIA_DE_LA_MADRE
|| vacation.getCategory() == TimeOffRequestType.DIA_DE_LA_MUJER_INTERNACIONAL
|| vacation.getCategory() == TimeOffRequestType.DIA_DE_LA_MUJER_NACIONAL) {
daysToBeTakenField.setValue(0.5); daysToBeTakenField.setValue(0.5);
} else { } else {
daysToBeTakenField.setValue(daysToBeTaken); daysToBeTakenField.setValue(daysToBeTaken);
@ -502,16 +400,9 @@ public class RequestRegisterView extends VerticalLayout {
handleExistingRequests(request); handleExistingRequests(request);
} }
long differentDays = ChronoUnit.DAYS.between(LocalDate.now(), request.getStartDate());
if (differentDays >= -15 && differentDays <= 90) {
requestService.saveTimeOffRequest(request); requestService.saveTimeOffRequest(request);
Notification.show("Solicitud guardada correctamente."); Notification.show("Solicitud guardada correctamente.");
closeForm(); 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() { private TimeOffRequest prepareRequest() {
@ -519,7 +410,7 @@ public class RequestRegisterView extends VerticalLayout {
request.setStartDate(startDatePicker.getValue()); request.setStartDate(startDatePicker.getValue());
request.setAvailableDays(availableDaysField.getValue()); request.setAvailableDays(availableDaysField.getValue());
request.setExpiration(endDate != null ? endDate : endDatePicker.getValue()); request.setExpiration(endDate != null ? endDate : endDatePicker.getValue());
request.setState(TimeOffRequestStatus.SOLICITADO); request.setState(TimeOffRequestStatus.PENDIENTE);
return request; return request;
} }
@ -527,10 +418,7 @@ public class RequestRegisterView extends VerticalLayout {
List<TimeOffRequest> existingRequests = List<TimeOffRequest> existingRequests =
requestService.findByEmployeeAndCategory(employee.getId(), request.getCategory()); requestService.findByEmployeeAndCategory(employee.getId(), request.getCategory());
int maxRequests = request.getCategory() != TimeOffRequestType.PERMISOS_DE_SALUD int maxRequests = request.getCategory() == TimeOffRequestType.PERMISOS_DE_SALUD ? 4 : 2;
&& !request.getCategory().name().startsWith("VACACION")
&& request.getCategory() != TimeOffRequestType.CUMPLEAÑOS
? 2 : 1;
if (existingRequests.size() >= maxRequests) { if (existingRequests.size() >= maxRequests) {
existingRequests.stream() existingRequests.stream()

View File

@ -5,47 +5,29 @@ import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.service.TeamService; import com.primefactorsolutions.service.TeamService;
import com.primefactorsolutions.service.TimeOffRequestService; import com.primefactorsolutions.service.TimeOffRequestService;
import com.primefactorsolutions.service.VacationService; import com.primefactorsolutions.service.VacationService;
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.contextmenu.MenuItem; import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.menubar.MenuBar;
import com.vaadin.flow.component.menubar.MenuBarVariant;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.function.ValueProvider;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; 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 com.vaadin.flow.spring.annotation.SpringComponent;
import jakarta.annotation.security.PermitAll; 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.springframework.context.annotation.Scope;
import org.vaadin.firitin.components.grid.PagingGrid; 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.LocalDate;
import java.time.Period; import java.time.Period;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.primefactorsolutions.views.Constants.PAGE_SIZE;
import static com.primefactorsolutions.views.util.MenuBarUtils.createIconItem;
@SpringComponent @SpringComponent
@Scope("prototype") @Scope("prototype")
@PageTitle("Requests") @PageTitle("Requests")
@Route(value = "/requests", layout = MainLayout.class) @Route(value = "/requests", layout = MainLayout.class)
@PermitAll @PermitAll
public class RequestsListView extends BaseView { public class RequestsListView extends Main {
private final TimeOffRequestService requestService; private final TimeOffRequestService requestService;
private final EmployeeService employeeService; private final EmployeeService employeeService;
@ -53,9 +35,13 @@ public class RequestsListView extends BaseView {
private final VacationService vacationService; private final VacationService vacationService;
private final PagingGrid<Employee> requestGrid = new PagingGrid<>(); private final PagingGrid<Employee> requestGrid = new PagingGrid<>();
private List<Employee> employees = Collections.emptyList();
private ComboBox<Employee> employeeFilter; private ComboBox<Employee> employeeFilter;
private ComboBox<Team> teamFilter; private ComboBox<Team> teamFilter;
private ComboBox<TimeOffRequestType> categoryFilter;
private ComboBox<Status> stateFilter; private ComboBox<Status> stateFilter;
private UUID selectedEmployeeId;
public RequestsListView(final TimeOffRequestService requestService, public RequestsListView(final TimeOffRequestService requestService,
final EmployeeService employeeService, final EmployeeService employeeService,
@ -65,25 +51,22 @@ public class RequestsListView extends BaseView {
this.employeeService = employeeService; this.employeeService = employeeService;
this.teamService = teamService; this.teamService = teamService;
this.vacationService = vacationService; this.vacationService = vacationService;
this.employees = employeeService.findAllEmployees();
initializeView(); initializeView();
refreshGeneralRequestGrid(null, null, null); refreshGeneralRequestGrid(null, null, null);
} }
private void initializeView() { private void initializeView() {
requestService.updateRequestStatuses();
Button downloadButton = new Button("Descargar reporte", event -> downloadReport());
getCurrentPageLayout().add(downloadButton);
setupFilters(); setupFilters();
setupRequestGrid(); setupRequestGrid();
getCurrentPageLayout().add(requestGrid); add(requestGrid);
add(createActionButtons());
} }
private void setupFilters() { private void setupFilters() {
final HorizontalLayout hl = new HorizontalLayout(); add(createEmployeeFilter());
hl.add(createEmployeeFilter()); add(createTeamFilter());
hl.add(createTeamFilter()); add(createStateFilter());
hl.add(createStateFilter());
getCurrentPageLayout().add(hl);
} }
private void setupRequestGrid() { private void setupRequestGrid() {
@ -91,18 +74,27 @@ public class RequestsListView extends BaseView {
requestGrid.addColumn(this::getTeamName).setHeader("Equipo"); requestGrid.addColumn(this::getTeamName).setHeader("Equipo");
requestGrid.addColumn(this::getEmployeeStatus).setHeader("Estado del empleado"); requestGrid.addColumn(this::getEmployeeStatus).setHeader("Estado del empleado");
requestGrid.addColumn(this::getGeneralTotal).setHeader("Total general"); requestGrid.addColumn(this::getGeneralTotal).setHeader("Total general");
requestGrid.addComponentColumn((ValueProvider<Employee, Component>) employee -> {
final MenuBar menuBar = new MenuBar();
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
final MenuItem view = createIconItem(menuBar, VaadinIcon.EYE, "View");
view.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent ->
navigateToTimeOffRequestView(employee.getId()));
return menuBar;
});
requestGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM); requestGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
requestGrid.setPageSize(PAGE_SIZE); requestGrid.setPageSize(5);
requestGrid.asSingleSelect().addValueChangeListener(event -> {
Employee selectedRequest = event.getValue();
if (selectedRequest != null) {
selectedEmployeeId = selectedRequest.getId();
}
});
}
private HorizontalLayout createActionButtons() {
Button viewButton = new Button("Ver", event -> {
if (selectedEmployeeId != null) {
navigateToTimeOffRequestView(selectedEmployeeId);
} else {
Notification.show("Seleccione una solicitud.", 3000, Notification.Position.MIDDLE);
}
});
Button closeButton = new Button("Salir", event -> navigateToMainView());
return new HorizontalLayout(viewButton, closeButton);
} }
private void refreshGeneralRequestGrid(final Employee employee, private void refreshGeneralRequestGrid(final Employee employee,
@ -165,45 +157,17 @@ public class RequestsListView extends BaseView {
private String getEmployeeStatus(final Employee employee) { private String getEmployeeStatus(final Employee employee) {
Optional<TimeOffRequest> activeRequest = requestService Optional<TimeOffRequest> activeRequest = requestService
.findByEmployeeAndState(employee.getId(), TimeOffRequestStatus.EN_USO); .findByEmployeeAndState(employee.getId(), TimeOffRequestStatus.EN_USO);
return activeRequest.isPresent() ? "EN_DESCANSO" : "EN_FUNCIONES"; return activeRequest.isPresent() ? "EN_DESCANSO" : "ACTIVO";
} }
private String getGeneralTotal(final Employee employee) { private String getGeneralTotal(final Employee employee) {
List<TimeOffRequest> employeeRequests = requestService.findRequestsByEmployeeId(employee.getId()); List<TimeOffRequest> employeeRequests = requestService.findRequestsByEmployeeId(employee.getId());
List<Vacation> vacations = vacationService.findVacations(); List<Vacation> vacations = vacationService.findVacations();
List<Double> vacationDays = calculateVacationDays(employee);
double utilizedVacationCurrentDays = vacationDays.get(1);
List<TimeOffRequest> vacationCurrentRequests = requestService
.findByEmployeeAndCategory(employee.getId(), 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<TimeOffRequest> vacationPreviousRequests = requestService
.findByEmployeeAndCategory(employee.getId(), TimeOffRequestType.VACACION_GESTION_ANTERIOR);
if (vacationPreviousRequests != null && !vacationPreviousRequests.isEmpty()) {
utilizedVacationPreviousDays = vacationPreviousRequests.getLast().getDaysBalance();
}
double totalVacationPreviousDays = vacationDays.getFirst()
- (vacationDays.getFirst() - utilizedVacationPreviousDays);
double totalUtilized = calculateTotalUtilized(employeeRequests); double totalUtilized = calculateTotalUtilized(employeeRequests);
double totalVacations = totalVacationCurrentDays + totalVacationPreviousDays; double totalVacations = calculateVacationDays(employee);
double totalAvailable = calculateTotalAvailable(vacations, employeeRequests, employee); double totalAvailable = calculateTotalAvailable(vacations, employeeRequests, employee);
double generalTotal = totalAvailable + totalVacations - totalUtilized; 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); return String.valueOf(generalTotal);
} }
@ -227,26 +191,13 @@ public class RequestsListView extends BaseView {
} }
private double calculateTotalUtilized(final List<TimeOffRequest> employeeRequests) { private double calculateTotalUtilized(final List<TimeOffRequest> employeeRequests) {
int currentYear = LocalDate.now().getYear();
return employeeRequests.stream() return employeeRequests.stream()
.filter(Objects::nonNull) .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)
.filter(request -> request.getStartDate() != null && (
request.getStartDate().getYear() == currentYear
|| (request.getCategory().name().startsWith("VACACION")
&& request.getStartDate().getYear() == currentYear - 1)
))
.mapToDouble(request -> request.getDaysToBeTake() != null ? request.getDaysToBeTake() : 0.0) .mapToDouble(request -> request.getDaysToBeTake() != null ? request.getDaysToBeTake() : 0.0)
.sum(); .sum();
} }
private List<Double> calculateVacationDays(final Employee employee) { private double calculateVacationDays(final Employee employee) {
List<Double> vacationDays = new ArrayList<>();
if (employee.getDateOfEntry() != null) { if (employee.getDateOfEntry() != null) {
LocalDate entryDate = employee.getDateOfEntry(); LocalDate entryDate = employee.getDateOfEntry();
LocalDate today = LocalDate.now(); LocalDate today = LocalDate.now();
@ -282,13 +233,11 @@ public class RequestsListView extends BaseView {
); );
} }
vacationDays.add(calculateVacationDaysSinceEntry(entryDate, previousVacationYearDate)); return calculateVacationDaysSinceEntry(entryDate, previousVacationYearDate)
vacationDays.add(calculateVacationDaysSinceEntry(entryDate, currentVacationYearDate)); + calculateVacationDaysSinceEntry(entryDate, currentVacationYearDate);
} else { } else {
vacationDays.add(0.0); return 0.0;
vacationDays.add(0.0);
} }
return vacationDays;
} }
private double calculateTotalAvailable(final List<Vacation> vacations, final List<TimeOffRequest> employeeRequests, private double calculateTotalAvailable(final List<Vacation> vacations, final List<TimeOffRequest> employeeRequests,
@ -299,16 +248,8 @@ public class RequestsListView extends BaseView {
.map(TimeOffRequest::getCategory) .map(TimeOffRequest::getCategory)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
double healthLicence = 2; return vacations.stream()
List<TimeOffRequest> healthRequests = requestService
.findByEmployeeAndCategory(employee.getId(), TimeOffRequestType.PERMISOS_DE_SALUD);
if (healthRequests != null && !healthRequests.isEmpty()) {
healthLicence = healthRequests.getLast().getDaysBalance();
}
double totalAvailable = vacations.stream()
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(vacation -> vacation.getCategory() != TimeOffRequestType.PERMISOS_DE_SALUD)
.filter(vacation -> shouldIncludeVacation( .filter(vacation -> shouldIncludeVacation(
vacation, vacation,
excludedCategories, excludedCategories,
@ -317,8 +258,6 @@ public class RequestsListView extends BaseView {
)) ))
.mapToDouble(vacation -> vacation.getDuration() != null ? vacation.getDuration() : 0.0) .mapToDouble(vacation -> vacation.getDuration() != null ? vacation.getDuration() : 0.0)
.sum(); .sum();
return totalAvailable + healthLicence;
} }
private double calculateVacationDaysSinceEntry(final LocalDate dateOfEntry, final LocalDate date) { private double calculateVacationDaysSinceEntry(final LocalDate dateOfEntry, final LocalDate date) {
@ -344,8 +283,10 @@ public class RequestsListView extends BaseView {
&& !employeeRequestCategories.contains(vacation.getCategory())) { && !employeeRequestCategories.contains(vacation.getCategory())) {
return false; return false;
} }
if (!isFemale(employee) && genderSpecificExclusions.contains(vacation.getCategory())) {
return isFemale(employee) || !genderSpecificExclusions.contains(vacation.getCategory()); return false;
}
return true;
} }
private boolean isFemale(final Employee employee) { private boolean isFemale(final Employee employee) {
@ -403,7 +344,7 @@ public class RequestsListView extends BaseView {
private enum Status { private enum Status {
TODOS, TODOS,
EN_DESCANSO, EN_DESCANSO,
EN_FUNCIONES ACTIVO
} }
private Employee createAllEmployeesOption() { private Employee createAllEmployeesOption() {
@ -425,50 +366,4 @@ public class RequestsListView extends BaseView {
private void navigateToTimeOffRequestView(final UUID idEmployee) { private void navigateToTimeOffRequestView(final UUID idEmployee) {
getUI().ifPresent(ui -> ui.navigate("requests/" + idEmployee.toString())); getUI().ifPresent(ui -> ui.navigate("requests/" + idEmployee.toString()));
} }
private ByteArrayInputStream generateExcelReport(final List<Employee> employees) {
try (Workbook workbook = new XSSFWorkbook()) {
Sheet sheet = workbook.createSheet("REPORTE_GENERAL_DE_VACACIONES");
Row headerRow = sheet.createRow(0);
String[] headers = {"Empleado", "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<Employee> 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());
}
} }

View File

@ -1,19 +0,0 @@
package com.primefactorsolutions.views.util;
import com.vaadin.flow.component.contextmenu.MenuItem;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.menubar.MenuBar;
import lombok.experimental.UtilityClass;
@UtilityClass
public class MenuBarUtils {
public static MenuItem createIconItem(final MenuBar menu, final VaadinIcon iconName, final String ariaLabel) {
final Icon icon = new Icon(iconName);
final MenuItem item = menu.addItem(icon);
item.setAriaLabel(ariaLabel);
return item;
}
}

View File

@ -32,7 +32,7 @@ INSERT INTO vacation (id, version, category, month_of_year, day_of_month, durati
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400b', 1, 'DIA_DE_TODOS_LOS_DIFUNTOS', 11, 2, 1, 30, 'MOVABLE'); INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400b', 1, 'DIA_DE_TODOS_LOS_DIFUNTOS', 11, 2, 1, 30, 'MOVABLE');
INSERT INTO vacation (id, version, category, month_of_year, day_of_month, duration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400c', 1, 'CUMPLEAÑOS', 12, 31, 0.5, 'OTHER'); INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400c', 1, 'CUMPLEAÑOS', 0.5, 365, 'OTHER');
INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400d', 1, 'MATERNIDAD', 90, 90, 'OTHER'); INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400d', 1, 'MATERNIDAD', 90, 90, 'OTHER');
INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400e', 1, 'PATERNIDAD', 3, 3, 'OTHER'); INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400e', 1, 'PATERNIDAD', 3, 3, 'OTHER');
INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400f', 1, 'MATRIMONIO', 3, 3, 'OTHER'); INSERT INTO vacation (id, version, category, duration, expiration, type) VALUES ('c23e4567-e89b-12d3-a456-42661417400f', 1, 'MATRIMONIO', 3, 3, 'OTHER');
@ -68,25 +68,25 @@ insert into employee (id, version, username, first_name, last_name, status, team
insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('9d6f12ba-e341-4e7a-b8a6-cab0982bd8c1', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'PATERNIDAD', 'APROBADO', 3, '2024-10-03', '2024-10-01', '2024-10-03', 3, 0); values ('9d6f12ba-e341-4e7a-b8a6-cab0982bd8c1', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'PATERNIDAD', 'VENCIDO', 3, '2024-10-03', '2024-10-01', '2024-10-03', 3, 0);
insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('9a6f12ba-e111-4e7a-b8a6-caa0982bd8a1', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'AÑO_NUEVO', 'APROBADO', 1, '2024-01-01', '2024-01-01', '2024-01-01', 1, 0); values ('9a6f12ba-e111-4e7a-b8a6-caa0982bd8a1', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'AÑO_NUEVO', 'VENCIDO', 1, '2024-01-01', '2024-01-01', '2024-01-01', 1, 0);
insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('9b6f12ba-e222-4e7a-b8a6-caa0982bd8b2', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'LUNES_CARNAVAL', 'APROBADO', 1, '2025-02-12', '2025-02-12', '2025-02-12', 1, 0); values ('9b6f12ba-e222-4e7a-b8a6-caa0982bd8b2', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'LUNES_CARNAVAL', 'APROBADO', 1, '2025-02-12', '2025-02-12', '2025-02-12', 1, 0);
insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('9c6f12ba-e333-4e7a-b8a6-caa0982bd8c3', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'MARTES_CARNAVAL', 'SOLICITADO', 1, '2025-02-13', '2025-02-13', '2025-02-13', 1, 0); values ('9c6f12ba-e333-4e7a-b8a6-caa0982bd8c3', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'MARTES_CARNAVAL', 'EN_REVISION', 1, '2025-02-13', '2025-02-13', '2025-02-13', 1, 0);
insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('9d6f12ba-e444-4e7a-b8a6-caa0982bd8d4', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'VIERNES_SANTO', 'APROBADO', 1, '2024-03-29', '2024-03-29', '2024-03-29', 1, 0); values ('9d6f12ba-e444-4e7a-b8a6-caa0982bd8d4', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'VIERNES_SANTO', 'APROBADO', 1, '2024-03-29', '2024-03-29', '2024-03-29', 1, 0);
insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('9e6f12ba-e555-4e7a-b8a6-caa0982bd8e5', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'VACACION_GESTION_ANTERIOR', 'APROBADO', 20, '2024-11-01', '2022-11-01', '2022-11-30', 20, 0); values ('9e6f12ba-e555-4e7a-b8a6-caa0982bd8e5', 1, '5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 'VACACION_GESTION_ACTUAL', 'APROBADO', 30, '2024-11-01', '2022-11-01', '2022-11-30', 30, 0);
insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('8c653f2a-f9a3-4d67-b3b6-12ad98fe0983', 1, 'f6ab3c6d-7078-45f6-9b22-4e37637bfec6', 'DIA_DEL_TRABAJADOR', 'APROBADO', 1, '2024-05-01', '2024-05-01', '2024-05-01', 1, 0); values ('8c653f2a-f9a3-4d67-b3b6-12ad98fe0983', 1, 'f6ab3c6d-7078-45f6-9b22-4e37637bfec6', 'DIA_DEL_TRABAJADOR', 'APROBADO', 1, '2024-05-01', '2024-05-01', '2024-05-01', 1, 0);
insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('fb9d9d75-b2ab-4ea4-b8b3-0a8f89e5c123', 1, '2e2293b1-3f9a-4f3d-abc8-32639b0a5e15', 'DIA_DE_LA_INDEPENDENCIA', 'APROBADO', 1, '2024-08-06', '2024-08-06', '2024-08-06', 1, 0); values ('fb9d9d75-b2ab-4ea4-b8b3-0a8f89e5c123', 1, '2e2293b1-3f9a-4f3d-abc8-32639b0a5e15', 'DIA_DE_LA_INDEPENDENCIA', 'APROBADO', 1, '2024-08-06', '2024-08-06', '2024-08-06', 1, 0);
insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('6fdc47a8-127b-41c4-8d12-7fc12098ab12', 1, 'b2436b82-7b9f-4f0d-9463-f2c3173a45c3', 'DIA_DE_TODOS_LOS_DIFUNTOS', 'SOLICITADO', 1, '2025-12-01', '2025-11-02', '2025-11-02', 1, 0); values ('6fdc47a8-127b-41c4-8d12-7fc12098ab12', 1, 'b2436b82-7b9f-4f0d-9463-f2c3173a45c3', 'DIA_DE_TODOS_LOS_DIFUNTOS', 'PENDIENTE', 1, '2025-12-01', '2025-11-02', '2025-11-02', 1, 0);
insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('12ec8b74-983d-4a17-b67e-134f45ae904c', 1, '5c1a7b82-832d-4f24-8377-54b77b91b6a8', 'AÑO_NUEVO', 'SOLICITADO', 1, '2025-01-01', '2025-01-01', '2025-01-01', 1, 0); values ('12ec8b74-983d-4a17-b67e-134f45ae904c', 1, '5c1a7b82-832d-4f24-8377-54b77b91b6a8', 'AÑO_NUEVO', 'PENDIENTE', 1, '2025-01-01', '2025-01-01', '2025-01-01', 1, 0);
insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance) insert into time_off_request (id, version, employee_id, category, state, available_days, expiration, start_date, end_date, days_to_be_take, days_balance)
values ('89bc4b2a-943f-487c-a9f3-bacf78145e67', 1, 'cba3efb7-32bc-44be-9fdc-fc5e4f211254', 'LUNES_CARNAVAL', 'APROBADO', 1, '2024-02-12', '2024-02-12', '2024-02-12', 1, 0); values ('89bc4b2a-943f-487c-a9f3-bacf78145e67', 1, 'cba3efb7-32bc-44be-9fdc-fc5e4f211254', 'LUNES_CARNAVAL', 'APROBADO', 1, '2024-02-12', '2024-02-12', '2024-02-12', 1, 0);