Compare commits

..

No commits in common. "b5427c309fd3b44a3bf10c978afa1f1ebc49fcaf" and "48e06fef1f9291ac79d1846e6d259acbfcccbbd1" have entirely different histories.

17 changed files with 315 additions and 558 deletions

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

@ -4,7 +4,7 @@
"type": "module", "type": "module",
"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",
@ -19,29 +19,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"
@ -49,7 +50,7 @@
"vaadin": { "vaadin": {
"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",
@ -64,34 +65,35 @@
"@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"
}, },
"hash": "1a0f17d48b329307b5862bc57499307d1b89f7d89260121c2b7189f76957c436" "hash": "2dc40a4f634ae025081ca2239cba00b14a35fe94ab78ac0a4dd3023d882081d5"
}, },
"overrides": { "overrides": {
"@vaadin/bundles": "$@vaadin/bundles", "@vaadin/bundles": "$@vaadin/bundles",

28
pom.xml
View File

@ -265,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

@ -3,14 +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,
SOLICITADO,
EN_REVISION,
COMPLETADO, COMPLETADO,
CANCELADO, CANCELADO,
VENCIDO
} }

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

@ -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

@ -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() {
@ -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

@ -113,7 +113,7 @@ public class PendingRequestsListView extends Main {
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()

View File

@ -23,7 +23,9 @@ import org.vaadin.firitin.components.grid.PagingGrid;
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;
@SpringComponent @SpringComponent
@ -52,7 +54,6 @@ public class RequestEmployeeView extends Div implements HasUrlParameter<String>
} }
private void initializeView() { private void initializeView() {
requestService.updateRequestStatuses();
setupFilters(); setupFilters();
setupGrid(); setupGrid();
add(requestGrid, createActionButtons(), createSummaryLayout()); add(requestGrid, createActionButtons(), createSummaryLayout());
@ -105,98 +106,29 @@ public class RequestEmployeeView extends Div implements HasUrlParameter<String>
}); });
} }
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)
.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 = 2;
List<TimeOffRequest> healthRequests = requestService
.findByEmployeeAndCategory(employeeId, TimeOffRequestType.PERMISOS_DE_SALUD);
if (healthRequests != null && !healthRequests.isEmpty()) {
healthLicence = healthRequests.getLast().getDaysBalance();
}
double totalFixedAndMovableHolidays = calculateHolidayDays(vacations);
double totalPersonalDays = calculatePersonalDays(vacations, isMale);
List<Double> vacationDays = calculateVacationDays(employee);
double utilizedVacationCurrentDays = vacationDays.get(1);
List<TimeOffRequest> vacationCurrentRequests = requestService
.findByEmployeeAndCategory(employeeId, TimeOffRequestType.VACACION_GESTION_ACTUAL);
if (vacationCurrentRequests != null && !vacationCurrentRequests.isEmpty()) {
utilizedVacationCurrentDays = vacationCurrentRequests.getLast().getDaysBalance();
}
double totalVacationCurrentDays = vacationDays.get(1) - (vacationDays.get(1) - utilizedVacationCurrentDays);
double utilizedVacationPreviousDays = vacationDays.get(0);
List<TimeOffRequest> vacationPreviousRequests = requestService
.findByEmployeeAndCategory(employeeId, TimeOffRequestType.VACACION_GESTION_ANTERIOR);
if (vacationPreviousRequests != null && !vacationPreviousRequests.isEmpty()) {
utilizedVacationPreviousDays = vacationPreviousRequests.getLast().getDaysBalance();
}
double totalVacationPreviousDays = vacationDays.getFirst()
- (vacationDays.getFirst() - utilizedVacationPreviousDays);
double utilizedFixedAndMovableHolidays = calculateHolidayUtilizedDays(currentYear);
double utilizedPersonalDays = calculatePersonalDaysUtilized(isMale, currentYear);
double remainingHolidayDays = totalFixedAndMovableHolidays - utilizedFixedAndMovableHolidays;
double remainingPersonalDays = (totalPersonalDays - utilizedPersonalDays) + healthLicence;
double remainingVacationDays = totalVacationCurrentDays + totalVacationPreviousDays;
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 calculateHolidayDays(final List<Vacation> vacations) { private double calculateVacationDays(final Employee employee) {
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();
@ -232,47 +164,11 @@ public class RequestEmployeeView extends Div implements HasUrlParameter<String>
); );
} }
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(this::verificationIsHoliday)
.filter(req -> req.getState() == TimeOffRequestStatus.APROBADO)
.filter(req -> req.getState() == TimeOffRequestStatus.EN_USO)
.filter(req -> req.getState() == TimeOffRequestStatus.TOMADO)
.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.APROBADO)
.filter(req -> req.getState() == TimeOffRequestStatus.EN_USO)
.filter(req -> req.getState() == TimeOffRequestStatus.TOMADO)
.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) {
@ -340,9 +236,7 @@ public class RequestEmployeeView extends Div implements HasUrlParameter<String>
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))
@ -357,58 +251,6 @@ public class RequestEmployeeView extends Div implements HasUrlParameter<String>
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();
}
@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);

View File

@ -63,7 +63,6 @@ public class RequestRegisterView extends VerticalLayout {
} }
private void initializeView() { private void initializeView() {
requestService.updateRequestStatuses();
configureFormFields(); configureFormFields();
configureButtons(); configureButtons();
configureBinder(); configureBinder();
@ -85,6 +84,8 @@ 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 -> {
@ -135,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 {
@ -190,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;
} }
} }
@ -230,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());
@ -289,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();
} }
@ -312,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();
} }
@ -340,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);
@ -381,7 +330,7 @@ public class RequestRegisterView extends VerticalLayout {
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(); clearFields();
} }
} }
@ -396,12 +345,7 @@ public class RequestRegisterView extends VerticalLayout {
} }
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);
@ -466,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;
} }
@ -474,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

@ -57,7 +57,6 @@ public class RequestsListView extends Main {
} }
private void initializeView() { private void initializeView() {
requestService.updateRequestStatuses();
setupFilters(); setupFilters();
setupRequestGrid(); setupRequestGrid();
add(requestGrid); add(requestGrid);
@ -164,29 +163,8 @@ public class RequestsListView extends Main {
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;
@ -213,24 +191,13 @@ public class RequestsListView extends Main {
} }
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.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();
@ -266,13 +233,11 @@ public class RequestsListView extends Main {
); );
} }
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,
@ -283,16 +248,8 @@ public class RequestsListView extends Main {
.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,
@ -301,8 +258,6 @@ public class RequestsListView extends Main {
)) ))
.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) {

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,26 +68,26 @@ 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);