| @ -0,0 +1,22 @@ | |||
| /target/ | |||
| .idea/ | |||
| .vscode/ | |||
| .settings | |||
| .project | |||
| .classpath | |||
| *.iml | |||
| .DS_Store | |||
| # The following files are generated/updated by vaadin-maven-plugin | |||
| node_modules/ | |||
| src/main/frontend/generated/ | |||
| pnpmfile.js | |||
| vite.generated.ts | |||
| # Browser drivers for local integration tests | |||
| drivers/ | |||
| # Error screenshots generated by TestBench for failed integration tests | |||
| error-screenshots/ | |||
| webpack.generated.js | |||
| /bin/ | |||
| @ -0,0 +1,118 @@ | |||
| /* | |||
| * 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(); | |||
| } | |||
| } | |||
| @ -0,0 +1,18 @@ | |||
| # 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 | |||
| @ -0,0 +1,24 @@ | |||
| This is free and unencumbered software released into the public domain. | |||
| Anyone is free to copy, modify, publish, use, compile, sell, or | |||
| distribute this software, either in source code form or as a compiled | |||
| binary, for any purpose, commercial or non-commercial, and by any | |||
| means. | |||
| In jurisdictions that recognize copyright laws, the author or authors | |||
| of this software dedicate any and all copyright interest in the | |||
| software to the public domain. We make this dedication for the benefit | |||
| of the public at large and to the detriment of our heirs and | |||
| successors. We intend this dedication to be an overt act of | |||
| relinquishment in perpetuity of all present and future rights to this | |||
| software under copyright law. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR | |||
| OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |||
| ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |||
| OTHER DEALINGS IN THE SOFTWARE. | |||
| For more information, please refer to <http://unlicense.org> | |||
| @ -0,0 +1,45 @@ | |||
| # Sistema de Mantenimiento | |||
| This project can be used as a starting point to create your own Vaadin application with Spring Boot. | |||
| It contains all the necessary configuration and some placeholder files to get you started. | |||
| ## Running the application | |||
| The project is a standard Maven project. To run it from the command line, | |||
| type `mvnw` (Windows), or `./mvnw` (Mac & Linux), then open | |||
| http://localhost:8080 in your browser. | |||
| You can also import the project to your IDE of choice as you would with any | |||
| Maven project. Read more on [how to import Vaadin projects to different IDEs](https://vaadin.com/docs/latest/guide/step-by-step/importing) (Eclipse, IntelliJ IDEA, NetBeans, and VS Code). | |||
| ## Deploying to Production | |||
| To create a production build, call `mvnw clean package -Pproduction` (Windows), | |||
| or `./mvnw clean package -Pproduction` (Mac & Linux). | |||
| This will build a JAR file with all the dependencies and front-end resources, | |||
| ready to be deployed. The file can be found in the `target` folder after the build completes. | |||
| Once the JAR file is built, you can run it using | |||
| `java -jar target/sistema-mantenimiento-1.0-SNAPSHOT.jar` | |||
| ## Project structure | |||
| - `MainLayout.java` in `src/main/java` contains the navigation setup (i.e., the | |||
| side/top bar and the main menu). This setup uses | |||
| [App Layout](https://vaadin.com/docs/components/app-layout). | |||
| - `views` package in `src/main/java` contains the server-side Java views of your application. | |||
| - `views` folder in `src/main/frontend` contains the client-side JavaScript views of your application. | |||
| - `themes` folder in `src/main/frontend` contains the custom CSS styles. | |||
| ## Useful links | |||
| - Read the documentation at [vaadin.com/docs](https://vaadin.com/docs). | |||
| - Follow the tutorial at [vaadin.com/docs/latest/tutorial/overview](https://vaadin.com/docs/latest/tutorial/overview). | |||
| - Create new projects at [start.vaadin.com](https://start.vaadin.com/). | |||
| - Search UI components and their usage examples at [vaadin.com/docs/latest/components](https://vaadin.com/docs/latest/components). | |||
| - View use case applications that demonstrate Vaadin capabilities at [vaadin.com/examples-and-demos](https://vaadin.com/examples-and-demos). | |||
| - Build any UI without custom CSS by discovering Vaadin's set of [CSS utility classes](https://vaadin.com/docs/styling/lumo/utility-classes). | |||
| - Find a collection of solutions to common use cases at [cookbook.vaadin.com](https://cookbook.vaadin.com/). | |||
| - Find add-ons at [vaadin.com/directory](https://vaadin.com/directory). | |||
| - Ask questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/vaadin) or join our [Discord channel](https://discord.gg/MYFq5RTbBn). | |||
| - Report issues, create pull requests in [GitHub](https://github.com/vaadin). | |||
| @ -0,0 +1,316 @@ | |||
| #!/bin/sh | |||
| # ---------------------------------------------------------------------------- | |||
| # 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. | |||
| # ---------------------------------------------------------------------------- | |||
| # ---------------------------------------------------------------------------- | |||
| # Maven Start Up Batch script | |||
| # | |||
| # Required ENV vars: | |||
| # ------------------ | |||
| # JAVA_HOME - location of a JDK home dir | |||
| # | |||
| # Optional ENV vars | |||
| # ----------------- | |||
| # M2_HOME - location of maven2's installed home dir | |||
| # MAVEN_OPTS - parameters passed to the Java VM when running Maven | |||
| # e.g. to debug Maven itself, use | |||
| # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 | |||
| # MAVEN_SKIP_RC - flag to disable loading of mavenrc files | |||
| # ---------------------------------------------------------------------------- | |||
| if [ -z "$MAVEN_SKIP_RC" ] ; then | |||
| if [ -f /usr/local/etc/mavenrc ] ; then | |||
| . /usr/local/etc/mavenrc | |||
| fi | |||
| if [ -f /etc/mavenrc ] ; then | |||
| . /etc/mavenrc | |||
| fi | |||
| if [ -f "$HOME/.mavenrc" ] ; then | |||
| . "$HOME/.mavenrc" | |||
| fi | |||
| fi | |||
| # OS specific support. $var _must_ be set to either true or false. | |||
| cygwin=false; | |||
| darwin=false; | |||
| mingw=false | |||
| case "`uname`" in | |||
| CYGWIN*) cygwin=true ;; | |||
| MINGW*) mingw=true;; | |||
| Darwin*) darwin=true | |||
| # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home | |||
| # See https://developer.apple.com/library/mac/qa/qa1170/_index.html | |||
| if [ -z "$JAVA_HOME" ]; then | |||
| if [ -x "/usr/libexec/java_home" ]; then | |||
| export JAVA_HOME="`/usr/libexec/java_home`" | |||
| else | |||
| export JAVA_HOME="/Library/Java/Home" | |||
| fi | |||
| fi | |||
| ;; | |||
| esac | |||
| if [ -z "$JAVA_HOME" ] ; then | |||
| if [ -r /etc/gentoo-release ] ; then | |||
| JAVA_HOME=`java-config --jre-home` | |||
| fi | |||
| fi | |||
| if [ -z "$M2_HOME" ] ; then | |||
| ## resolve links - $0 may be a link to maven's home | |||
| PRG="$0" | |||
| # need this for relative symlinks | |||
| while [ -h "$PRG" ] ; do | |||
| ls=`ls -ld "$PRG"` | |||
| link=`expr "$ls" : '.*-> \(.*\)$'` | |||
| if expr "$link" : '/.*' > /dev/null; then | |||
| PRG="$link" | |||
| else | |||
| PRG="`dirname "$PRG"`/$link" | |||
| fi | |||
| done | |||
| saveddir=`pwd` | |||
| M2_HOME=`dirname "$PRG"`/.. | |||
| # make it fully qualified | |||
| M2_HOME=`cd "$M2_HOME" && pwd` | |||
| cd "$saveddir" | |||
| # echo Using m2 at $M2_HOME | |||
| fi | |||
| # For Cygwin, ensure paths are in UNIX format before anything is touched | |||
| if $cygwin ; then | |||
| [ -n "$M2_HOME" ] && | |||
| M2_HOME=`cygpath --unix "$M2_HOME"` | |||
| [ -n "$JAVA_HOME" ] && | |||
| JAVA_HOME=`cygpath --unix "$JAVA_HOME"` | |||
| [ -n "$CLASSPATH" ] && | |||
| CLASSPATH=`cygpath --path --unix "$CLASSPATH"` | |||
| fi | |||
| # For Mingw, ensure paths are in UNIX format before anything is touched | |||
| if $mingw ; then | |||
| [ -n "$M2_HOME" ] && | |||
| M2_HOME="`(cd "$M2_HOME"; pwd)`" | |||
| [ -n "$JAVA_HOME" ] && | |||
| JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" | |||
| fi | |||
| if [ -z "$JAVA_HOME" ]; then | |||
| javaExecutable="`which javac`" | |||
| if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then | |||
| # readlink(1) is not available as standard on Solaris 10. | |||
| readLink=`which readlink` | |||
| if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then | |||
| if $darwin ; then | |||
| javaHome="`dirname \"$javaExecutable\"`" | |||
| javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" | |||
| else | |||
| javaExecutable="`readlink -f \"$javaExecutable\"`" | |||
| fi | |||
| javaHome="`dirname \"$javaExecutable\"`" | |||
| javaHome=`expr "$javaHome" : '\(.*\)/bin'` | |||
| JAVA_HOME="$javaHome" | |||
| export JAVA_HOME | |||
| fi | |||
| fi | |||
| fi | |||
| if [ -z "$JAVACMD" ] ; then | |||
| if [ -n "$JAVA_HOME" ] ; then | |||
| if [ -x "$JAVA_HOME/jre/sh/java" ] ; then | |||
| # IBM's JDK on AIX uses strange locations for the executables | |||
| JAVACMD="$JAVA_HOME/jre/sh/java" | |||
| else | |||
| JAVACMD="$JAVA_HOME/bin/java" | |||
| fi | |||
| else | |||
| JAVACMD="`\\unset -f command; \\command -v java`" | |||
| fi | |||
| fi | |||
| if [ ! -x "$JAVACMD" ] ; then | |||
| echo "Error: JAVA_HOME is not defined correctly." >&2 | |||
| echo " We cannot execute $JAVACMD" >&2 | |||
| exit 1 | |||
| fi | |||
| if [ -z "$JAVA_HOME" ] ; then | |||
| echo "Warning: JAVA_HOME environment variable is not set." | |||
| fi | |||
| CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher | |||
| # traverses directory structure from process work directory to filesystem root | |||
| # first directory with .mvn subdirectory is considered project base directory | |||
| find_maven_basedir() { | |||
| if [ -z "$1" ] | |||
| then | |||
| echo "Path not specified to find_maven_basedir" | |||
| return 1 | |||
| fi | |||
| basedir="$1" | |||
| wdir="$1" | |||
| while [ "$wdir" != '/' ] ; do | |||
| if [ -d "$wdir"/.mvn ] ; then | |||
| basedir=$wdir | |||
| break | |||
| fi | |||
| # workaround for JBEAP-8937 (on Solaris 10/Sparc) | |||
| if [ -d "${wdir}" ]; then | |||
| wdir=`cd "$wdir/.."; pwd` | |||
| fi | |||
| # end of workaround | |||
| done | |||
| echo "${basedir}" | |||
| } | |||
| # concatenates all lines of a file | |||
| concat_lines() { | |||
| if [ -f "$1" ]; then | |||
| echo "$(tr -s '\n' ' ' < "$1")" | |||
| fi | |||
| } | |||
| BASE_DIR=`find_maven_basedir "$(pwd)"` | |||
| if [ -z "$BASE_DIR" ]; then | |||
| exit 1; | |||
| fi | |||
| ########################################################################################## | |||
| # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central | |||
| # This allows using the maven wrapper in projects that prohibit checking in binary data. | |||
| ########################################################################################## | |||
| if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then | |||
| if [ "$MVNW_VERBOSE" = true ]; then | |||
| echo "Found .mvn/wrapper/maven-wrapper.jar" | |||
| fi | |||
| else | |||
| if [ "$MVNW_VERBOSE" = true ]; then | |||
| echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." | |||
| fi | |||
| if [ -n "$MVNW_REPOURL" ]; then | |||
| jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" | |||
| else | |||
| jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" | |||
| fi | |||
| while IFS="=" read key value; do | |||
| case "$key" in (wrapperUrl) jarUrl="$value"; break ;; | |||
| esac | |||
| done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" | |||
| if [ "$MVNW_VERBOSE" = true ]; then | |||
| echo "Downloading from: $jarUrl" | |||
| fi | |||
| wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" | |||
| if $cygwin; then | |||
| wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` | |||
| fi | |||
| if command -v wget > /dev/null; then | |||
| if [ "$MVNW_VERBOSE" = true ]; then | |||
| echo "Found wget ... using wget" | |||
| fi | |||
| if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then | |||
| wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" | |||
| else | |||
| wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" | |||
| fi | |||
| elif command -v curl > /dev/null; then | |||
| if [ "$MVNW_VERBOSE" = true ]; then | |||
| echo "Found curl ... using curl" | |||
| fi | |||
| if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then | |||
| curl -o "$wrapperJarPath" "$jarUrl" -f | |||
| else | |||
| curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f | |||
| fi | |||
| else | |||
| if [ "$MVNW_VERBOSE" = true ]; then | |||
| echo "Falling back to using Java to download" | |||
| fi | |||
| javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" | |||
| # For Cygwin, switch paths to Windows format before running javac | |||
| if $cygwin; then | |||
| javaClass=`cygpath --path --windows "$javaClass"` | |||
| fi | |||
| if [ -e "$javaClass" ]; then | |||
| if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then | |||
| if [ "$MVNW_VERBOSE" = true ]; then | |||
| echo " - Compiling MavenWrapperDownloader.java ..." | |||
| fi | |||
| # Compiling the Java class | |||
| ("$JAVA_HOME/bin/javac" "$javaClass") | |||
| fi | |||
| if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then | |||
| # Running the downloader | |||
| if [ "$MVNW_VERBOSE" = true ]; then | |||
| echo " - Running MavenWrapperDownloader.java ..." | |||
| fi | |||
| ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") | |||
| fi | |||
| fi | |||
| fi | |||
| fi | |||
| ########################################################################################## | |||
| # End of extension | |||
| ########################################################################################## | |||
| export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} | |||
| if [ "$MVNW_VERBOSE" = true ]; then | |||
| echo $MAVEN_PROJECTBASEDIR | |||
| fi | |||
| MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" | |||
| # For Cygwin, switch paths to Windows format before running java | |||
| if $cygwin; then | |||
| [ -n "$M2_HOME" ] && | |||
| M2_HOME=`cygpath --path --windows "$M2_HOME"` | |||
| [ -n "$JAVA_HOME" ] && | |||
| JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` | |||
| [ -n "$CLASSPATH" ] && | |||
| CLASSPATH=`cygpath --path --windows "$CLASSPATH"` | |||
| [ -n "$MAVEN_PROJECTBASEDIR" ] && | |||
| MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` | |||
| fi | |||
| # Provide a "standardized" way to retrieve the CLI args that will | |||
| # work with both Windows and non-Windows executions. | |||
| MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" | |||
| export MAVEN_CMD_LINE_ARGS | |||
| WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain | |||
| exec "$JAVACMD" \ | |||
| $MAVEN_OPTS \ | |||
| $MAVEN_DEBUG_OPTS \ | |||
| -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ | |||
| "-Dmaven.home=${M2_HOME}" \ | |||
| "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ | |||
| ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" | |||
| @ -0,0 +1,188 @@ | |||
| @REM ---------------------------------------------------------------------------- | |||
| @REM Licensed to the Apache Software Foundation (ASF) under one | |||
| @REM or more contributor license agreements. See the NOTICE file | |||
| @REM distributed with this work for additional information | |||
| @REM regarding copyright ownership. The ASF licenses this file | |||
| @REM to you under the Apache License, Version 2.0 (the | |||
| @REM "License"); you may not use this file except in compliance | |||
| @REM with the License. You may obtain a copy of the License at | |||
| @REM | |||
| @REM http://www.apache.org/licenses/LICENSE-2.0 | |||
| @REM | |||
| @REM Unless required by applicable law or agreed to in writing, | |||
| @REM software distributed under the License is distributed on an | |||
| @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |||
| @REM KIND, either express or implied. See the License for the | |||
| @REM specific language governing permissions and limitations | |||
| @REM under the License. | |||
| @REM ---------------------------------------------------------------------------- | |||
| @REM ---------------------------------------------------------------------------- | |||
| @REM Maven Start Up Batch script | |||
| @REM | |||
| @REM Required ENV vars: | |||
| @REM JAVA_HOME - location of a JDK home dir | |||
| @REM | |||
| @REM Optional ENV vars | |||
| @REM M2_HOME - location of maven2's installed home dir | |||
| @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands | |||
| @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending | |||
| @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven | |||
| @REM e.g. to debug Maven itself, use | |||
| @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 | |||
| @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files | |||
| @REM ---------------------------------------------------------------------------- | |||
| @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' | |||
| @echo off | |||
| @REM set title of command window | |||
| title %0 | |||
| @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' | |||
| @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% | |||
| @REM set %HOME% to equivalent of $HOME | |||
| if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") | |||
| @REM Execute a user defined script before this one | |||
| if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre | |||
| @REM check for pre script, once with legacy .bat ending and once with .cmd ending | |||
| if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* | |||
| if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* | |||
| :skipRcPre | |||
| @setlocal | |||
| set ERROR_CODE=0 | |||
| @REM To isolate internal variables from possible post scripts, we use another setlocal | |||
| @setlocal | |||
| @REM ==== START VALIDATION ==== | |||
| if not "%JAVA_HOME%" == "" goto OkJHome | |||
| echo. | |||
| echo Error: JAVA_HOME not found in your environment. >&2 | |||
| echo Please set the JAVA_HOME variable in your environment to match the >&2 | |||
| echo location of your Java installation. >&2 | |||
| echo. | |||
| goto error | |||
| :OkJHome | |||
| if exist "%JAVA_HOME%\bin\java.exe" goto init | |||
| echo. | |||
| echo Error: JAVA_HOME is set to an invalid directory. >&2 | |||
| echo JAVA_HOME = "%JAVA_HOME%" >&2 | |||
| echo Please set the JAVA_HOME variable in your environment to match the >&2 | |||
| echo location of your Java installation. >&2 | |||
| echo. | |||
| goto error | |||
| @REM ==== END VALIDATION ==== | |||
| :init | |||
| @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". | |||
| @REM Fallback to current working directory if not found. | |||
| set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% | |||
| IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir | |||
| set EXEC_DIR=%CD% | |||
| set WDIR=%EXEC_DIR% | |||
| :findBaseDir | |||
| IF EXIST "%WDIR%"\.mvn goto baseDirFound | |||
| cd .. | |||
| IF "%WDIR%"=="%CD%" goto baseDirNotFound | |||
| set WDIR=%CD% | |||
| goto findBaseDir | |||
| :baseDirFound | |||
| set MAVEN_PROJECTBASEDIR=%WDIR% | |||
| cd "%EXEC_DIR%" | |||
| goto endDetectBaseDir | |||
| :baseDirNotFound | |||
| set MAVEN_PROJECTBASEDIR=%EXEC_DIR% | |||
| cd "%EXEC_DIR%" | |||
| :endDetectBaseDir | |||
| IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig | |||
| @setlocal EnableExtensions EnableDelayedExpansion | |||
| for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a | |||
| @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% | |||
| :endReadAdditionalConfig | |||
| SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" | |||
| set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" | |||
| set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain | |||
| set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" | |||
| FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( | |||
| IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B | |||
| ) | |||
| @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central | |||
| @REM This allows using the maven wrapper in projects that prohibit checking in binary data. | |||
| if exist %WRAPPER_JAR% ( | |||
| if "%MVNW_VERBOSE%" == "true" ( | |||
| echo Found %WRAPPER_JAR% | |||
| ) | |||
| ) else ( | |||
| if not "%MVNW_REPOURL%" == "" ( | |||
| SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" | |||
| ) | |||
| if "%MVNW_VERBOSE%" == "true" ( | |||
| echo Couldn't find %WRAPPER_JAR%, downloading it ... | |||
| echo Downloading from: %DOWNLOAD_URL% | |||
| ) | |||
| powershell -Command "&{"^ | |||
| "$webclient = new-object System.Net.WebClient;"^ | |||
| "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ | |||
| "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ | |||
| "}"^ | |||
| "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ | |||
| "}" | |||
| if "%MVNW_VERBOSE%" == "true" ( | |||
| echo Finished downloading %WRAPPER_JAR% | |||
| ) | |||
| ) | |||
| @REM End of extension | |||
| @REM Provide a "standardized" way to retrieve the CLI args that will | |||
| @REM work with both Windows and non-Windows executions. | |||
| set MAVEN_CMD_LINE_ARGS=%* | |||
| %MAVEN_JAVA_EXE% ^ | |||
| %JVM_CONFIG_MAVEN_PROPS% ^ | |||
| %MAVEN_OPTS% ^ | |||
| %MAVEN_DEBUG_OPTS% ^ | |||
| -classpath %WRAPPER_JAR% ^ | |||
| "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ | |||
| %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* | |||
| if ERRORLEVEL 1 goto error | |||
| goto end | |||
| :error | |||
| set ERROR_CODE=1 | |||
| :end | |||
| @endlocal & set ERROR_CODE=%ERROR_CODE% | |||
| if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost | |||
| @REM check for post script, once with legacy .bat ending and once with .cmd ending | |||
| if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" | |||
| if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" | |||
| :skipRcPost | |||
| @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' | |||
| if "%MAVEN_BATCH_PAUSE%"=="on" pause | |||
| if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% | |||
| cmd /C exit /B %ERROR_CODE% | |||
| @ -0,0 +1,113 @@ | |||
| { | |||
| "name": "no-name", | |||
| "license": "UNLICENSED", | |||
| "type": "module", | |||
| "dependencies": { | |||
| "@polymer/polymer": "3.5.2", | |||
| "@vaadin/bundles": "24.5.5", | |||
| "@vaadin/common-frontend": "0.0.19", | |||
| "@vaadin/polymer-legacy-adapter": "24.5.5", | |||
| "@vaadin/react-components": "24.5.5", | |||
| "@vaadin/react-components-pro": "24.5.5", | |||
| "@vaadin/vaadin-development-mode-detector": "2.0.7", | |||
| "@vaadin/vaadin-lumo-styles": "24.5.5", | |||
| "@vaadin/vaadin-material-styles": "24.5.5", | |||
| "@vaadin/vaadin-themable-mixin": "24.5.5", | |||
| "@vaadin/vaadin-usage-statistics": "2.1.3", | |||
| "construct-style-sheets-polyfill": "3.1.0", | |||
| "date-fns": "2.29.3", | |||
| "lit": "3.2.1", | |||
| "proj4": "2.12.1", | |||
| "react": "18.3.1", | |||
| "react-dom": "18.3.1", | |||
| "react-router-dom": "6.28.0", | |||
| "signature_pad": "4.1.5" | |||
| }, | |||
| "devDependencies": { | |||
| "@babel/preset-react": "7.26.3", | |||
| "@preact/signals-react-transform": "0.4.0", | |||
| "@rollup/plugin-replace": "6.0.1", | |||
| "@rollup/pluginutils": "5.1.3", | |||
| "@types/react": "18.3.13", | |||
| "@types/react-dom": "18.3.1", | |||
| "@vitejs/plugin-react": "4.3.3", | |||
| "async": "3.2.6", | |||
| "glob": "10.4.5", | |||
| "rollup-plugin-brotli": "3.1.0", | |||
| "rollup-plugin-visualizer": "5.12.0", | |||
| "strip-css-comments": "5.0.0", | |||
| "transform-ast": "2.4.4", | |||
| "typescript": "5.6.3", | |||
| "vite": "5.4.11", | |||
| "vite-plugin-checker": "0.8.0", | |||
| "workbox-build": "7.3.0", | |||
| "workbox-core": "7.3.0", | |||
| "workbox-precaching": "7.3.0" | |||
| }, | |||
| "vaadin": { | |||
| "dependencies": { | |||
| "@polymer/polymer": "3.5.2", | |||
| "@vaadin/bundles": "24.5.5", | |||
| "@vaadin/common-frontend": "0.0.19", | |||
| "@vaadin/polymer-legacy-adapter": "24.5.5", | |||
| "@vaadin/react-components": "24.5.5", | |||
| "@vaadin/react-components-pro": "24.5.5", | |||
| "@vaadin/vaadin-development-mode-detector": "2.0.7", | |||
| "@vaadin/vaadin-lumo-styles": "24.5.5", | |||
| "@vaadin/vaadin-material-styles": "24.5.5", | |||
| "@vaadin/vaadin-themable-mixin": "24.5.5", | |||
| "@vaadin/vaadin-usage-statistics": "2.1.3", | |||
| "construct-style-sheets-polyfill": "3.1.0", | |||
| "date-fns": "2.29.3", | |||
| "lit": "3.2.1", | |||
| "proj4": "2.12.1", | |||
| "react": "18.3.1", | |||
| "react-dom": "18.3.1", | |||
| "react-router-dom": "6.28.0", | |||
| "signature_pad": "4.1.5" | |||
| }, | |||
| "devDependencies": { | |||
| "@babel/preset-react": "7.26.3", | |||
| "@preact/signals-react-transform": "0.4.0", | |||
| "@rollup/plugin-replace": "6.0.1", | |||
| "@rollup/pluginutils": "5.1.3", | |||
| "@types/react": "18.3.13", | |||
| "@types/react-dom": "18.3.1", | |||
| "@vitejs/plugin-react": "4.3.3", | |||
| "async": "3.2.6", | |||
| "glob": "10.4.5", | |||
| "rollup-plugin-brotli": "3.1.0", | |||
| "rollup-plugin-visualizer": "5.12.0", | |||
| "strip-css-comments": "5.0.0", | |||
| "transform-ast": "2.4.4", | |||
| "typescript": "5.6.3", | |||
| "vite": "5.4.11", | |||
| "vite-plugin-checker": "0.8.0", | |||
| "workbox-build": "7.3.0", | |||
| "workbox-core": "7.3.0", | |||
| "workbox-precaching": "7.3.0" | |||
| }, | |||
| "hash": "6126bd412c2a8696938f50edd1abae217c30c0119a0496af47b9d6ba1762921f" | |||
| }, | |||
| "overrides": { | |||
| "@vaadin/bundles": "$@vaadin/bundles", | |||
| "@vaadin/polymer-legacy-adapter": "$@vaadin/polymer-legacy-adapter", | |||
| "@vaadin/vaadin-development-mode-detector": "$@vaadin/vaadin-development-mode-detector", | |||
| "@vaadin/vaadin-usage-statistics": "$@vaadin/vaadin-usage-statistics", | |||
| "@vaadin/react-components": "$@vaadin/react-components", | |||
| "@vaadin/react-components-pro": "$@vaadin/react-components-pro", | |||
| "@vaadin/common-frontend": "$@vaadin/common-frontend", | |||
| "react-dom": "$react-dom", | |||
| "construct-style-sheets-polyfill": "$construct-style-sheets-polyfill", | |||
| "react-router-dom": "$react-router-dom", | |||
| "lit": "$lit", | |||
| "@polymer/polymer": "$@polymer/polymer", | |||
| "react": "$react", | |||
| "date-fns": "$date-fns", | |||
| "proj4": "$proj4", | |||
| "@vaadin/vaadin-themable-mixin": "$@vaadin/vaadin-themable-mixin", | |||
| "@vaadin/vaadin-lumo-styles": "$@vaadin/vaadin-lumo-styles", | |||
| "@vaadin/vaadin-material-styles": "$@vaadin/vaadin-material-styles", | |||
| "signature_pad": "$signature_pad" | |||
| } | |||
| } | |||
| @ -0,0 +1,295 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | |||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <!-- Project from https://start.vaadin.com/project/d0aaac74-a0be-4584-96f9-8bc2489b2c80 --> | |||
| <groupId>mx.gob.jumapacelaya</groupId> | |||
| <artifactId>sistema-mantenimiento</artifactId> | |||
| <name>sistema-mantenimiento</name> | |||
| <version>1.0-SNAPSHOT</version> | |||
| <packaging>jar</packaging> | |||
| <properties> | |||
| <java.version>17</java.version> | |||
| <vaadin.version>24.5.8</vaadin.version> | |||
| </properties> | |||
| <parent> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-starter-parent</artifactId> | |||
| <version>3.2.8</version> | |||
| </parent> | |||
| <repositories> | |||
| <repository> | |||
| <id>central</id> | |||
| <url>https://repo.maven.apache.org/maven2</url> | |||
| <releases> | |||
| <enabled>true</enabled> | |||
| </releases> | |||
| <snapshots> | |||
| <enabled>false</enabled> | |||
| </snapshots> | |||
| </repository> | |||
| <repository> | |||
| <id>Vaadin Directory</id> | |||
| <url>https://maven.vaadin.com/vaadin-addons</url> | |||
| <snapshots> | |||
| <enabled>false</enabled> | |||
| </snapshots> | |||
| </repository> | |||
| <repository> | |||
| <id>oracle-public</id> | |||
| <url>https://maven.oracle.com/public</url> | |||
| </repository> | |||
| </repositories> | |||
| <dependencyManagement> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>com.vaadin</groupId> | |||
| <artifactId>vaadin-bom</artifactId> | |||
| <version>${vaadin.version}</version> | |||
| <type>pom</type> | |||
| <scope>import</scope> | |||
| </dependency> | |||
| </dependencies> | |||
| </dependencyManagement> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>com.vaadin</groupId> | |||
| <!-- Replace artifactId with vaadin-core to use only free components --> | |||
| <artifactId>vaadin</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.vaadin</groupId> | |||
| <artifactId>vaadin-spring-boot-starter</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.parttio</groupId> | |||
| <artifactId>line-awesome</artifactId> | |||
| <version>2.0.0</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.h2database</groupId> | |||
| <artifactId>h2</artifactId> | |||
| <scope>runtime</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <!-- Dependencia para utilizar JDBC en la Base de Datos --> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-starter-jdbc</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <!-- Conector a base de datos Oracle--> | |||
| <groupId>com.oracle.database.jdbc</groupId> | |||
| <artifactId>ojdbc8</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>mysql</groupId> | |||
| <artifactId>mysql-connector-java</artifactId> | |||
| <version>8.0.33</version> | |||
| </dependency> | |||
| <dependency> | |||
| <!-- Dependencia para poder enviar correos --> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-starter-mail</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-starter-security</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-starter-validation</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-devtools</artifactId> | |||
| <optional>true</optional> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.springframework.security</groupId> | |||
| <artifactId>spring-security-ldap</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-starter-test</artifactId> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-starter-data-ldap</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.springframework.ldap</groupId> | |||
| <artifactId>spring-ldap-core</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.vaadin</groupId> | |||
| <artifactId>vaadin-testbench-junit5</artifactId> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>de.f0rce.signaturepad</groupId> | |||
| <artifactId>signature-widget</artifactId> | |||
| <version>3.1.0</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.apache.poi</groupId> | |||
| <artifactId>poi-ooxml</artifactId> | |||
| <version>5.2.0</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>commons-io</groupId> | |||
| <artifactId>commons-io</artifactId> | |||
| <version>2.16.1</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>net.sf.jasperreports</groupId> | |||
| <artifactId>jasperreports</artifactId> | |||
| <version>7.0.3</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>net.sf.jasperreports</groupId> | |||
| <artifactId>jasperreports-pdf</artifactId> | |||
| <version>7.0.3</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.google.code.gson</groupId> | |||
| <artifactId>gson</artifactId> | |||
| </dependency> | |||
| </dependencies> | |||
| <build> | |||
| <defaultGoal>spring-boot:run</defaultGoal> | |||
| <plugins> | |||
| <plugin> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-maven-plugin</artifactId> | |||
| </plugin> | |||
| <plugin> | |||
| <groupId>com.vaadin</groupId> | |||
| <artifactId>vaadin-maven-plugin</artifactId> | |||
| <version>${vaadin.version}</version> | |||
| <executions> | |||
| <execution> | |||
| <goals> | |||
| <goal>prepare-frontend</goal> | |||
| </goals> | |||
| </execution> | |||
| </executions> | |||
| </plugin> | |||
| </plugins> | |||
| </build> | |||
| <profiles> | |||
| <profile> | |||
| <!-- Production mode is activated using -Pproduction --> | |||
| <id>production</id> | |||
| <dependencies> | |||
| <!-- Exclude development dependencies from production --> | |||
| <dependency> | |||
| <groupId>com.vaadin</groupId> | |||
| <artifactId>vaadin-core</artifactId> | |||
| <exclusions> | |||
| <exclusion> | |||
| <groupId>com.vaadin</groupId> | |||
| <artifactId>vaadin-dev</artifactId> | |||
| </exclusion> | |||
| </exclusions> | |||
| </dependency> | |||
| </dependencies> | |||
| <build> | |||
| <plugins> | |||
| <plugin> | |||
| <groupId>com.vaadin</groupId> | |||
| <artifactId>vaadin-maven-plugin</artifactId> | |||
| <version>${vaadin.version}</version> | |||
| <executions> | |||
| <execution> | |||
| <goals> | |||
| <goal>build-frontend</goal> | |||
| </goals> | |||
| <phase>compile</phase> | |||
| </execution> | |||
| </executions> | |||
| </plugin> | |||
| </plugins> | |||
| </build> | |||
| </profile> | |||
| <profile> | |||
| <id>it</id> | |||
| <build> | |||
| <plugins> | |||
| <plugin> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-maven-plugin</artifactId> | |||
| <executions> | |||
| <execution> | |||
| <id>start-spring-boot</id> | |||
| <phase>pre-integration-test</phase> | |||
| <goals> | |||
| <goal>start</goal> | |||
| </goals> | |||
| </execution> | |||
| <execution> | |||
| <id>stop-spring-boot</id> | |||
| <phase>post-integration-test</phase> | |||
| <goals> | |||
| <goal>stop</goal> | |||
| </goals> | |||
| </execution> | |||
| </executions> | |||
| </plugin> | |||
| <!-- Runs the integration tests (*IT) after the server is started --> | |||
| <plugin> | |||
| <groupId>org.apache.maven.plugins</groupId> | |||
| <artifactId>maven-failsafe-plugin</artifactId> | |||
| <executions> | |||
| <execution> | |||
| <goals> | |||
| <goal>integration-test</goal> | |||
| <goal>verify</goal> | |||
| </goals> | |||
| </execution> | |||
| </executions> | |||
| <configuration> | |||
| <trimStackTrace>false</trimStackTrace> | |||
| <enableAssertions>true</enableAssertions> | |||
| </configuration> | |||
| </plugin> | |||
| </plugins> | |||
| </build> | |||
| </profile> | |||
| </profiles> | |||
| </project> | |||
| @ -0,0 +1,32 @@ | |||
| This directory is automatically generated by Vaadin and contains the pre-compiled | |||
| frontend files/resources for your project (frontend development bundle). | |||
| It should be added to Version Control System and committed, so that other developers | |||
| do not have to compile it again. | |||
| Frontend development bundle is automatically updated when needed: | |||
| - an npm/pnpm package is added with @NpmPackage or directly into package.json | |||
| - CSS, JavaScript or TypeScript files are added with @CssImport, @JsModule or @JavaScript | |||
| - Vaadin add-on with front-end customizations is added | |||
| - Custom theme imports/assets added into 'theme.json' file | |||
| - Exported web component is added. | |||
| If your project development needs a hot deployment of the frontend changes, | |||
| you can switch Flow to use Vite development server (default in Vaadin 23.3 and earlier versions): | |||
| - set `vaadin.frontend.hotdeploy=true` in `application.properties` | |||
| - configure `vaadin-maven-plugin`: | |||
| ``` | |||
| <configuration> | |||
| <frontendHotdeploy>true</frontendHotdeploy> | |||
| </configuration> | |||
| ``` | |||
| - configure `jetty-maven-plugin`: | |||
| ``` | |||
| <configuration> | |||
| <systemProperties> | |||
| <vaadin.frontend.hotdeploy>true</vaadin.frontend.hotdeploy> | |||
| </systemProperties> | |||
| </configuration> | |||
| ``` | |||
| Read more [about Vaadin development mode](https://vaadin.com/docs/next/flow/configuration/development-mode#precompiled-bundle). | |||
| @ -0,0 +1,23 @@ | |||
| <!DOCTYPE html> | |||
| <!-- | |||
| This file is auto-generated by Vaadin. | |||
| --> | |||
| <html> | |||
| <head> | |||
| <meta charset="UTF-8" /> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |||
| <style> | |||
| body, #outlet { | |||
| height: 100vh; | |||
| width: 100%; | |||
| margin: 0; | |||
| } | |||
| </style> | |||
| <!-- index.ts is included here automatically (either by the dev server or during the build) --> | |||
| </head> | |||
| <body> | |||
| <!-- This outlet div is where the views are rendered --> | |||
| <div id="outlet"></div> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,20 @@ | |||
| vaadin-scroller[slot="drawer"] { | |||
| padding: var(--lumo-space-s); | |||
| } | |||
| vaadin-side-nav-item vaadin-icon { | |||
| padding: 0; | |||
| } | |||
| [slot="drawer"]:is(header, footer) { | |||
| display: flex; | |||
| align-items: center; | |||
| gap: var(--lumo-space-s); | |||
| padding: var(--lumo-space-s) var(--lumo-space-m); | |||
| min-height: var(--lumo-size-xl); | |||
| box-sizing: border-box; | |||
| } | |||
| [slot="drawer"]:is(header, footer):is(:empty) { | |||
| display: none; | |||
| } | |||
| @ -0,0 +1,294 @@ | |||
| @import url('./main-layout.css'); | |||
| /* ----------- Estilos para el MainLayout.java ----------- */ | |||
| /* Estilos para el DrawerToggle*/ | |||
| .drawer-toggle { | |||
| background-color: #bc955b; | |||
| } | |||
| /* Estilos para el encabezado */ | |||
| .header-content { | |||
| height: 64px; | |||
| display: flex; | |||
| align-items: center; | |||
| width: 100%; | |||
| } | |||
| /* Estilo para el boton de cerrar sesion */ | |||
| .logout-button { | |||
| margin-right: 30px; | |||
| } | |||
| /* Estilos para el drawer */ | |||
| .drawer-logo { | |||
| width: 300px; | |||
| } | |||
| /* Estilos para el fondo de la aplicacion */ | |||
| .app-layout { | |||
| background-image: url('/images/bckgndNvo.png'); | |||
| background-size: cover; | |||
| background-position: center; | |||
| background-repeat: no-repeat; | |||
| } | |||
| /* ------------------ FIN -------------------------------------- */ | |||
| /* | |||
| /* | |||
| */ | |||
| /*!--------------------- Estilos para MantenimientosView.java ------------------- */ | |||
| /* Estilo para el fondo del header */ | |||
| .plan-anual-header { | |||
| background-color: #a02142; | |||
| padding: 0; | |||
| } | |||
| /* Estilo para el titulo */ | |||
| .plan-anual-titulo { | |||
| text-align: center; | |||
| font-size: 24px; | |||
| color: #ddc9a3; | |||
| } | |||
| /* Estilo para el subtitulo */ | |||
| .plan-anual-titulo1 { | |||
| text-align: center; | |||
| font-size: 18px; | |||
| color: #ddc9a3; | |||
| } | |||
| /* Estilo para el campo de texto nomenclatura */ | |||
| .nomenclatura-txt { | |||
| margin-top: 15px; | |||
| margin-right: 15px; | |||
| } | |||
| /* Estilo para el logo CELAYA */ | |||
| .celaya-logo { | |||
| width: 100px; | |||
| margin-left: 15px; | |||
| margin-top: 15px; | |||
| } | |||
| /* ------------------------ FIN -------------------------- */ | |||
| /* | |||
| /* | |||
| */ | |||
| /* --------------- Estilos para la vista de ActDiaria.java -------------- */ | |||
| /* Estilo para el header */ | |||
| .act-diaria-header { | |||
| background-color: #3E8BEA; | |||
| padding: 10px; | |||
| } | |||
| /* Estilo para el titulo */ | |||
| .act-diaria-titulo { | |||
| color: white; | |||
| font-size: 24px; | |||
| text-align: center; | |||
| } | |||
| /* Estilo para el grid */ | |||
| .act-diaria-grid { | |||
| margin-top: 20px; | |||
| } | |||
| /* ---------------------------- FIN------------------------ */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* Estilos especificos para el TextField, TextArea y Fecha*/ | |||
| vaadin-text-field::part(label), vaadin-text-area::part(label), vaadin-date-picker::part(label) { | |||
| color: #691b31; /* Color de la etiqueta */ | |||
| } | |||
| vaadin-text-field::part(input-field), vaadin-text-area::part(input-field), vaadin-password-field::part(input-field), | |||
| vaadin-number-field::part(input-field), vaadin-date-picker::part(input-field) { | |||
| border: 1px solid #691b31; /* Color del borde */ | |||
| color: #691b31; /* Color del texto */ | |||
| } | |||
| vaadin-month-calendar::part(date) { | |||
| color: #691b31; /* Color para los dias del calendario */ | |||
| } | |||
| vaadin-month-calendar::part(date):hover /* Estilos para cuando se posiciona el puntero sobre el dia */{ | |||
| background-color: #a02142; | |||
| opacity: 50%; | |||
| border-radius: 5px; | |||
| } | |||
| vaadin-month-calendar::part(date focused) { | |||
| background-color: #ddc9a3; /* Color de la fecha seleccionada */ | |||
| } | |||
| vaadin-date-picker-overlay-content > vaadin-button, vaadin-date-picker-year::part(year-number) { | |||
| color: #691b31; | |||
| } | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* Estilos específicos para el Upload */ | |||
| vaadin-upload > vaadin-button { | |||
| color: #691b31; | |||
| } | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* Estilos específicos para el ComboBox */ | |||
| vaadin-combo-box::part(input-field) { | |||
| background-color: #ddc9a3; /* Color de fondo */ | |||
| color: #691b31; /* Color del texto */ | |||
| border: 1px solid #691b31; /* Color del borde */ | |||
| } | |||
| vaadin-combo-box::part(label) { | |||
| color: #691b31; /* Color de las etiquetas */ | |||
| } | |||
| vaadin-combo-box::part(dropdown) { | |||
| background-color: rgba(221, 201, 163, 1); /* Color del fondo del dropdown */ | |||
| } | |||
| vaadin-combo-box-item::part(checkmark)::before, vaadin-combo-box-item:hover | |||
| { | |||
| color: #691b31; | |||
| } | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) INDICADOR DE CARGA DE LA APLICACION (*)(*) (*)(*) */ | |||
| .v-loading-indicator { /* Cambiar el color de la barra de carga que sale cuando la aplicacion esta cargando */ | |||
| background: #691b31 !important; | |||
| } | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) ESTILOS PARA LA SIDEBAR (*)(*) (*)(*) */ | |||
| vaadin-side-nav-item[aria-current="page"]::part(content) { | |||
| color: #691b31; /* Color de texto seleccionado */ | |||
| } | |||
| vaadin-side-nav-item:hover::part(content) { | |||
| background-color: #ddc9a3; /* Color de fondo al hacer hover*/ | |||
| fill-opacity: 50%; | |||
| border-radius: 5px; | |||
| } | |||
| vaadin-side-nav-item::part(content) { | |||
| color: #a02142; /* Color del texto deseado */ | |||
| } | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /*Estilos especificos para el Grid */ | |||
| vaadin-grid::part(selected-row-cell) { | |||
| background-color: #ddc9a3; | |||
| opacity: 100%; | |||
| } | |||
| vaadin-grid::part(selected-row) { | |||
| color: #691b31; | |||
| font-weight: bold; | |||
| } | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /*Estilos especificos para los botones */ | |||
| vaadin-button[theme~="primary"] { | |||
| background-color: #691b31; | |||
| } | |||
| vaadin-button:not([theme]) { | |||
| color: #a02142; | |||
| } | |||
| vaadin-button[theme~="tertiary-inline"], vaadin-button[theme~="icon"] { | |||
| color: #a02142; | |||
| } | |||
| /* Estilos para el theme personalizado 'subir-archivo' */ | |||
| vaadin-button[theme~="subir-archivo"] { | |||
| background-color: #691b31; | |||
| color: #ffffff; | |||
| } | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /*Estilos especificos para los CheckBox y RadioButtons */ | |||
| vaadin-checkbox[checked]::part(checkbox) { | |||
| background-color: #691b31; /* Cambia el color del CheckBox */ | |||
| } | |||
| vaadin-checkbox-group::part(label), vaadin-radio-group::part(label) { | |||
| color: #691b31; | |||
| } | |||
| vaadin-radio-button[checked]::part(radio) { | |||
| background-color: #691b31; | |||
| } | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) */ | |||
| /* Estilo especificos para el login form */ | |||
| vaadin-login-form.special, vaadin-login-form.special::part(container) { | |||
| background-color: rgba(105, 27, 49, 0.8); | |||
| border-radius: 30px; | |||
| } | |||
| vaadin-login-form-wrapper { | |||
| background-color: rgba(221, 201, 163, 1); | |||
| border-radius: 30px; | |||
| } | |||
| /*letras de los label*/ | |||
| vaadin-login-form-wrapper ::part(label) { | |||
| color: #6f7271; | |||
| /*transform: scale(1.2);*/ | |||
| } | |||
| vaadin-login-form vaadin-button[theme~="submit"] { | |||
| background-color: #691b31; | |||
| } | |||
| vaadin-login-form-wrapper::part(form-title) { | |||
| color: #691b31; | |||
| } | |||
| vaadin-login-form-wrapper::part(error-message) { | |||
| color: #a02142; | |||
| } | |||
| vaadin-popover-overlay::part(overlay) { | |||
| border-radius: 12px; | |||
| box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); | |||
| } | |||
| @media (max-width: 900px) { | |||
| .v-horizontallayout { | |||
| flex-direction: column !important; | |||
| align-items: stretch !important; | |||
| } | |||
| .mantenimiento-text-field, | |||
| .mantenimiento-combo, | |||
| vaadin-text-field, | |||
| vaadin-combo-box { | |||
| min-width: 0; | |||
| width: 100% !important; | |||
| box-sizing: border-box; | |||
| } | |||
| } | |||
| @ -0,0 +1,3 @@ | |||
| { | |||
| "lumoImports" : [ "typography", "color", "spacing", "badge", "utility" ] | |||
| } | |||
| @ -0,0 +1,28 @@ | |||
| package mx.gob.jumapacelaya; | |||
| import com.vaadin.flow.component.page.AppShellConfigurator; | |||
| import com.vaadin.flow.server.PWA; | |||
| import com.vaadin.flow.theme.Theme; | |||
| import mx.gob.jumapacelaya.services.DatabaseService; | |||
| import org.springframework.boot.SpringApplication; | |||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
| import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; | |||
| import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration; | |||
| /** | |||
| * The entry point of the Spring Boot application. | |||
| * | |||
| * Use the @PWA annotation make the application installable on phones, tablets | |||
| * and some desktop browsers. | |||
| * | |||
| */ | |||
| @SpringBootApplication | |||
| @Theme(value = "sistema-mantenimiento") | |||
| @PWA(name = "Aplicacion de Mantenimiento de Equipo de Computo", shortName = "Mantenimiento de Computo", iconPath = "icons/icon.png") | |||
| public class Application implements AppShellConfigurator { | |||
| public static void main(String[] args) { | |||
| SpringApplication.run(Application.class, args); | |||
| } | |||
| } | |||
| @ -0,0 +1,337 @@ | |||
| package mx.gob.jumapacelaya.api; | |||
| import com.google.gson.*; | |||
| import mx.gob.jumapacelaya.models.RedmineUser; | |||
| import mx.gob.jumapacelaya.models.Ticket; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Component; | |||
| import java.io.IOException; | |||
| import java.net.URI; | |||
| import java.net.http.HttpClient; | |||
| import java.net.http.HttpRequest; | |||
| import java.net.http.HttpResponse; | |||
| import java.time.LocalDate; | |||
| import java.time.format.DateTimeFormatter; | |||
| import java.time.format.DateTimeParseException; | |||
| import java.util.ArrayList; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| @Component | |||
| public class RedmineClient { | |||
| private static final int PAGE_SIZE = 25; | |||
| static String REDMINE_URL; | |||
| static String API_KEY; | |||
| public static final Gson GSON = new Gson(); | |||
| public RedmineClient(@Value("${redmine.url}") String redmineUrl, @Value("${redmine.api_key}") String apiKey) { | |||
| REDMINE_URL = redmineUrl; | |||
| API_KEY = apiKey; | |||
| } | |||
| //AQUI OBTENGO LOS TICKETS DESDE REDMINE | |||
| public List<Ticket> getTickets(RedmineUser user, boolean includeClosed) { | |||
| List<Ticket> tickets = new ArrayList<>(); | |||
| HttpClient client = HttpClient.newHttpClient(); | |||
| int offset = 0; | |||
| // Si includeClose es true, incluira todos los tikets si no, incluira solo los que estan abiertos | |||
| String statusFilter = includeClosed ? "&status_id=*" : "&status_id=open"; | |||
| while (true) { | |||
| HttpRequest request = HttpRequest.newBuilder() | |||
| .uri(URI.create(REDMINE_URL + "/issues.json?key=" + user.getKey() + statusFilter + "&offset=" + offset)) | |||
| .header("Content-Type", "application/json") | |||
| .build(); | |||
| try { | |||
| HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); | |||
| if (response.statusCode() == 200) { | |||
| String responseBody = response.body(); | |||
| List<Ticket> pageTickets = parseTickets(responseBody); | |||
| tickets.addAll(pageTickets); | |||
| if (pageTickets.size() < PAGE_SIZE) { | |||
| break; | |||
| } | |||
| offset += PAGE_SIZE; | |||
| } else { | |||
| System.err.println("Error en la respuesta: " + response.statusCode()); | |||
| break; | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| break; | |||
| } | |||
| } | |||
| System.out.println("Total tickets obtenidos: " + tickets.size()); | |||
| return tickets; | |||
| } | |||
| //AQUI OBTENGO LOS TICKETS DESDE REDMINE | |||
| public List<Ticket> getTicketsAuthor(RedmineUser user, boolean includeClosed) { | |||
| List<Ticket> tickets = new ArrayList<>(); | |||
| HttpClient client = HttpClient.newHttpClient(); | |||
| int offset = 0; | |||
| // Si includeClose es true, incluira todos los tikets si no, incluira solo los que estan abiertos | |||
| String statusFilter = includeClosed ? "&status_id=*" : "&status_id=open"; | |||
| while (true) { | |||
| HttpRequest request = HttpRequest.newBuilder() | |||
| .uri(URI.create(REDMINE_URL + "/issues.json?key=" + user.getKey() + "&author_id=" + user.getId() + statusFilter + "&offset=" + offset)) | |||
| .header("Content-Type", "application/json") | |||
| .build(); | |||
| try { | |||
| HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); | |||
| if (response.statusCode() == 200) { | |||
| String responseBody = response.body(); | |||
| List<Ticket> pageTickets = parseTickets(responseBody); | |||
| tickets.addAll(pageTickets); | |||
| if (pageTickets.size() < PAGE_SIZE) { | |||
| break; | |||
| } | |||
| offset += PAGE_SIZE; | |||
| } else { | |||
| System.err.println("Error en la respuesta: " + response.statusCode()); | |||
| break; | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| break; | |||
| } | |||
| } | |||
| System.out.println("Total tickets obtenidos: " + tickets.size()); | |||
| return tickets; | |||
| } | |||
| // Aquí se parsean todos los tickets que existen y se les da un formato con los campos a mostrarse | |||
| private List<Ticket> parseTickets(String json) { | |||
| List<Ticket> tickets = new ArrayList<>(); | |||
| try { | |||
| JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject(); | |||
| JsonArray issues = jsonObject.getAsJsonArray("issues"); | |||
| if (issues != null) { | |||
| for (JsonElement issueElement : issues) { | |||
| JsonObject issue = issueElement.getAsJsonObject(); | |||
| // Verifica y obtiene el ID | |||
| int id = issue.has("id") && !issue.get("id").isJsonNull() ? issue.get("id").getAsInt() : 0; | |||
| // Verifica y obtiene el subject | |||
| String subject = issue.has("subject") && !issue.get("subject").isJsonNull() ? issue.get("subject").getAsString() : ""; | |||
| // Verifica y obtiene la descripción | |||
| String description = issue.has("description") && !issue.get("description").isJsonNull() ? issue.get("description").getAsString() : ""; | |||
| // Verifica y obtiene el status | |||
| String status = "Unknown"; | |||
| if (issue.has("status") && !issue.get("status").isJsonNull()) { | |||
| JsonObject statusObject = issue.getAsJsonObject("status"); | |||
| if (statusObject.has("name") && !statusObject.get("name").isJsonNull()) { | |||
| status = statusObject.get("name").getAsString(); | |||
| } | |||
| } | |||
| // Verifica y obtiene la fecha de creación | |||
| String dateString = issue.has("created_on") && !issue.get("created_on").isJsonNull() ? issue.get("created_on").getAsString() : ""; | |||
| LocalDate dateCreate = null; | |||
| if (!dateString.isEmpty()) { | |||
| try { | |||
| DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME; | |||
| dateCreate = LocalDate.parse(dateString, formatter); | |||
| } catch (DateTimeParseException e) { | |||
| System.err.println("Error al parsear la fecha: " + dateString); | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| // Verifica y obtiene la fecha de cierre | |||
| String closeDateString = issue.has("closed_on") && !issue.get("closed_on").isJsonNull() ? issue.get("closed_on").getAsString() : ""; | |||
| LocalDate dateClose = null; | |||
| if (!closeDateString.isEmpty()) { | |||
| try { | |||
| DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME; | |||
| dateClose = LocalDate.parse(closeDateString, formatter); | |||
| } catch (DateTimeParseException e) { | |||
| System.err.println("Error al parsear la fecha de cierre: " + closeDateString); | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| //Verifica y obtiene el ID del tipo de ticket | |||
| Integer trackerId = null; | |||
| if (issue.has("tracker") && !issue.get("tracker").isJsonNull()) { | |||
| JsonObject trackerObject = issue.getAsJsonObject("tracker"); | |||
| if (trackerObject.has("id") && !trackerObject.get("id").isJsonNull()) { | |||
| trackerId = trackerObject.get("id").getAsInt(); | |||
| } | |||
| } | |||
| // Agrega el ticket a la lista | |||
| tickets.add(new Ticket(id, subject, description, status, | |||
| dateCreate != null ? dateCreate.toString() : "", | |||
| dateClose != null ? dateClose.toString() : "", | |||
| trackerId, "Tipo Desconocido")); | |||
| } | |||
| } else { | |||
| System.out.println("La respuesta JSON no contiene la clave 'issues'"); | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| System.out.println("Ocurrió un error al parsear los tickets: " + e.getMessage()); | |||
| } | |||
| return tickets; | |||
| } | |||
| public RedmineUser getMyAccount(String username) { | |||
| HttpRequest request = HttpRequest.newBuilder() | |||
| .uri(URI.create(REDMINE_URL + "/my/account.json")) | |||
| .header("Content-Type", "application/json") | |||
| .header("X-Redmine-Switch-User", username) | |||
| .header("X-Redmine-API-Key", API_KEY) | |||
| .GET() | |||
| .build(); | |||
| try { | |||
| HttpClient client = HttpClient.newHttpClient(); | |||
| HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); | |||
| JsonObject jsonObject = JsonParser.parseString(response.body()).getAsJsonObject(); | |||
| JsonObject userJson = jsonObject.get("user").getAsJsonObject(); | |||
| RedmineUser user = new RedmineUser(); | |||
| user.setId(userJson.get("id").getAsInt()); | |||
| user.setLogin(userJson.get("login").getAsString()); | |||
| user.setFirstname(userJson.get("firstname").getAsString()); | |||
| user.setLastname(userJson.get("lastname").getAsString()); | |||
| user.setMail(userJson.get("mail").getAsString()); | |||
| user.setKey(userJson.get("api_key").getAsString()); | |||
| return user; | |||
| //return response.body(); | |||
| } catch (IOException | InterruptedException e) { | |||
| e.printStackTrace(); | |||
| return null; | |||
| } | |||
| } | |||
| public static RedmineUser createRedmineUser(String username, String firstname, String lastname, String mail) { | |||
| HttpClient client = HttpClient.newHttpClient(); | |||
| Map<String, Object> user = new HashMap<>(); | |||
| user.put("login", username); | |||
| user.put("firstname", firstname); | |||
| user.put("lastname", lastname); | |||
| user.put("mail", mail); | |||
| user.put("auth_source_id", "1"); | |||
| Map<String, Object> payload = new HashMap<>(); | |||
| payload.put("user", user); | |||
| String jsonPayload = new Gson().toJson(payload); | |||
| HttpRequest request = HttpRequest.newBuilder() | |||
| .uri(URI.create(REDMINE_URL + "/users.json")) | |||
| .header("Content-Type", "application/json") | |||
| .header("X-Redmine-API-Key", API_KEY) | |||
| .POST(HttpRequest.BodyPublishers.ofString(jsonPayload)) | |||
| .build(); | |||
| try { | |||
| HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); | |||
| JsonObject jsonObject = JsonParser.parseString(response.body()).getAsJsonObject(); | |||
| JsonObject userJson = jsonObject.get("user").getAsJsonObject(); | |||
| RedmineUser newUser = new RedmineUser(); | |||
| newUser.setId(userJson.get("id").getAsInt()); | |||
| newUser.setLogin(userJson.get("login").getAsString()); | |||
| newUser.setFirstname(userJson.get("firstname").getAsString()); | |||
| newUser.setLastname(userJson.get("lastname").getAsString()); | |||
| newUser.setMail(userJson.get("mail").getAsString()); | |||
| return newUser; | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| return null; | |||
| } | |||
| } | |||
| //AQUI OBTENGO A LOS USUARIOS | |||
| //Se devuelven en formato Json | |||
| public RedmineUser getUserByUsername(String username) { | |||
| HttpClient client = HttpClient.newHttpClient(); | |||
| HttpRequest request = HttpRequest.newBuilder() | |||
| .uri(URI.create(REDMINE_URL + "/users.json?name=" + username )) | |||
| .header("Content-Type", "application/json") | |||
| .header("X-Redmine-API-Key", API_KEY) | |||
| .build(); | |||
| try { | |||
| HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); | |||
| if (response.statusCode() == 200) { | |||
| String responseBody = response.body(); | |||
| System.out.println("Datos del usuario " + responseBody); | |||
| return parseUser(responseBody); | |||
| } else { | |||
| System.err.println("Error en la respuesta: " + response.statusCode()); | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return null; | |||
| } | |||
| //Aqui se parsean a los usuarios y se les da un formato con los campos a mostrarse | |||
| private RedmineUser parseUser(String json) { | |||
| JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject(); | |||
| JsonObject userJson = jsonObject.getAsJsonArray("users").get(0).getAsJsonObject(); | |||
| RedmineUser user = new RedmineUser(); | |||
| user.setId(userJson.get("id").getAsInt()); | |||
| user.setLogin(userJson.get("login").getAsString()); | |||
| user.setFirstname(userJson.get("firstname").getAsString()); | |||
| user.setLastname(userJson.get("lastname").getAsString()); | |||
| user.setMail(userJson.get("mail").getAsString()); | |||
| //user.setKey(userJson.get("key").getAsString()); | |||
| return user; | |||
| } | |||
| /*Este metodo sirve para actualizar el estatus de los tickets | |||
| en este caso se actualiza al estatus TERMINADO */ | |||
| public void closeTicket(int ticketId, RedmineUser user) throws IOException, InterruptedException { | |||
| int closedStatusId = 5; //este es el ID del estado TERMINADO, se debe poner el id a según corresponda | |||
| Map<String, Object> payload = new HashMap<>(); | |||
| Map<String, Object> issue = new HashMap<>(); | |||
| issue.put("status_id", closedStatusId); | |||
| payload.put("issue", issue); | |||
| String jsonPayload = GSON.toJson(payload); | |||
| HttpRequest request = HttpRequest.newBuilder() | |||
| .uri(URI.create(REDMINE_URL + "/issues/" + ticketId + ".json?key=" + user.getKey())) | |||
| .header("Content-Type", "application/json") | |||
| .PUT(HttpRequest.BodyPublishers.ofString(jsonPayload)) | |||
| .build(); | |||
| HttpClient client = HttpClient.newHttpClient(); | |||
| HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); | |||
| if (response.statusCode() == 204) { | |||
| String responseBody = response.body(); | |||
| System.out.println("Ticket " + ticketId + " cerrado correctamente."); | |||
| } else { | |||
| System.err.println("Error al cerrar el ticket: " + response.statusCode()); | |||
| System.err.println(response.body()); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1 @@ | |||
| package mx.gob.jumapacelaya.api; | |||
| @ -0,0 +1,13 @@ | |||
| package mx.gob.jumapacelaya.api; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Component; | |||
| @Component | |||
| public class ServerProperties { | |||
| @Value("${redmine.url}") | |||
| public String REDMINE_URL; | |||
| @Value("${redmine.api_key}") | |||
| public String API_KEY; | |||
| } | |||
| @ -0,0 +1,94 @@ | |||
| package mx.gob.jumapacelaya.controller; | |||
| import com.vaadin.flow.spring.security.VaadinWebSecurity; | |||
| import mx.gob.jumapacelaya.ui.login.LoginView; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.http.HttpMethod; | |||
| import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; | |||
| import org.springframework.security.config.annotation.web.builders.HttpSecurity; | |||
| import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | |||
| import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider; | |||
| import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | |||
| import org.springframework.ldap.core.support.LdapContextSource; | |||
| @EnableWebSecurity | |||
| @Configuration | |||
| public class SecurityConfiguration extends VaadinWebSecurity { | |||
| @Override | |||
| protected void configure(HttpSecurity http) throws Exception { | |||
| http.authorizeHttpRequests(auth -> auth | |||
| .requestMatchers( | |||
| AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/icons/*.png"), | |||
| AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/images/*.png") | |||
| ).permitAll() | |||
| .requestMatchers( | |||
| AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/login*") | |||
| ).permitAll() | |||
| ); | |||
| super.configure(http); | |||
| setLoginView(http, LoginView.class); | |||
| } | |||
| // !Esta es la real autenticacion con ldap | |||
| @Autowired | |||
| public void configure(AuthenticationManagerBuilder auth) throws Exception { | |||
| ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider("JUMAPACELAYA.GOB.MX", "ldap://172.16.0.1"); | |||
| provider.setConvertSubErrorCodesToExceptions(true); | |||
| provider.setUseAuthenticationRequestCredentials(true); | |||
| auth.authenticationProvider(provider); | |||
| } | |||
| // !Autenticacion local solo para que lo vea el departamento de calidad | |||
| /*@Autowired | |||
| public void configure(AuthenticationManagerBuilder auth) throws Exception { | |||
| // Configura la autenticación en memoria con un usuario local | |||
| auth.inMemoryAuthentication() | |||
| .withUser("admin") | |||
| .password("{noop}admin") // {noop} indica que la contraseña no está cifrada (solo para pruebas) | |||
| .roles("ADMIN") | |||
| .and() | |||
| .withUser("jlermal") | |||
| .password("{noop}Temporal1") | |||
| .roles("USER") | |||
| .and() | |||
| .withUser("mramirezg") | |||
| .password("{noop}Temporal1") | |||
| .roles("ADMIN"); | |||
| }*/ | |||
| @Value("${spring.ldap.urls}") | |||
| private String ldapUrls; | |||
| @Value("${spring.ldap.base}") | |||
| private String ldapBase; | |||
| @Value("${spring.ldap.password}") | |||
| private String ldapPassword; | |||
| @Bean | |||
| public LdapContextSource ldapContextSource() { | |||
| LdapContextSource contextSource = new LdapContextSource(); | |||
| contextSource.setUrl(ldapUrls); | |||
| contextSource.setBase(ldapBase); | |||
| contextSource.setUserDn("administrator"); | |||
| contextSource.setPassword(ldapPassword); | |||
| contextSource.setPooled(true); | |||
| contextSource.setReferral("follow"); | |||
| return contextSource; | |||
| } | |||
| } | |||
| @ -0,0 +1,31 @@ | |||
| package mx.gob.jumapacelaya.datasource; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.beans.factory.annotation.Qualifier; | |||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||
| import org.springframework.boot.jdbc.DataSourceBuilder; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.context.annotation.Primary; | |||
| import org.springframework.jdbc.core.JdbcTemplate; | |||
| import org.springframework.transaction.annotation.EnableTransactionManagement; | |||
| import javax.sql.DataSource; | |||
| @Configuration | |||
| public class MysqlDataSource { | |||
| @Bean(name= "mysqlDB") | |||
| @Primary | |||
| @ConfigurationProperties(prefix = "spring.datasource") | |||
| public DataSource mysqlDataSource() { | |||
| return DataSourceBuilder.create().build(); | |||
| } | |||
| @Bean(name = "mysqlJdbcTemplate") | |||
| @Autowired | |||
| public JdbcTemplate mysqlTemplate(@Qualifier("mysqlDB") DataSource mysqlDB) { | |||
| return new JdbcTemplate(mysqlDB); | |||
| } | |||
| } | |||
| @ -0,0 +1,27 @@ | |||
| package mx.gob.jumapacelaya.datasource; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.beans.factory.annotation.Qualifier; | |||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||
| import org.springframework.boot.jdbc.DataSourceBuilder; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.jdbc.core.JdbcTemplate; | |||
| import javax.sql.DataSource; | |||
| @Configuration | |||
| public class OracleDataSource { | |||
| @Bean(name = "oracleDB") | |||
| @ConfigurationProperties(prefix = "spring.datasource.secondary") | |||
| public DataSource oracleDataSource() { | |||
| return DataSourceBuilder.create().build(); | |||
| } | |||
| @Bean(name = "oracleTemplate") | |||
| @Autowired | |||
| public JdbcTemplate oracleJdbcTemplate(@Qualifier("oracleDB") DataSource oracleDB) { | |||
| return new JdbcTemplate(oracleDB); | |||
| } | |||
| } | |||
| @ -0,0 +1,87 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| import org.springframework.stereotype.Service; | |||
| import java.util.Date; | |||
| public class ActividadDiaria { | |||
| private int numero; | |||
| private String proyecto; | |||
| private String tipo; | |||
| private String estado; | |||
| private String asunto; | |||
| private Date fechaInicial; | |||
| private Date fechaCierre; | |||
| public int getNumero() { | |||
| return numero; | |||
| } | |||
| public void setNumero(int numero) { | |||
| this.numero = numero; | |||
| } | |||
| public String getProyecto() { | |||
| return proyecto; | |||
| } | |||
| public void setProyecto(String proyecto) { | |||
| this.proyecto = proyecto; | |||
| } | |||
| public String getTipo() { | |||
| return tipo; | |||
| } | |||
| public void setTipo(String tipo) { | |||
| this.tipo = tipo; | |||
| } | |||
| public String getEstado() { | |||
| return estado; | |||
| } | |||
| public void setEstado(String estado) { | |||
| this.estado = estado; | |||
| } | |||
| public String getAsunto() { | |||
| return asunto; | |||
| } | |||
| public void setAsunto(String asunto) { | |||
| this.asunto = asunto; | |||
| } | |||
| public Date getFechaInicial() { | |||
| return fechaInicial; | |||
| } | |||
| public void setFechaInicial(Date fechaInicial) { | |||
| this.fechaInicial = fechaInicial; | |||
| } | |||
| public Date getFechaCierre() { | |||
| return fechaCierre; | |||
| } | |||
| public void setFechaCierre(Date fechaCierre) { | |||
| this.fechaCierre = fechaCierre; | |||
| } | |||
| public ActividadDiaria(int numero, String proyecto, String estado, String tipo, String asunto, Date fechaInicial, Date fechaCierre) { | |||
| this.numero = numero; | |||
| this.proyecto = proyecto; | |||
| this.estado = estado; | |||
| this.tipo = tipo; | |||
| this.asunto = asunto; | |||
| this.fechaInicial = fechaInicial; | |||
| this.fechaCierre = fechaCierre; | |||
| } | |||
| public ActividadDiaria() { | |||
| } | |||
| } | |||
| @ -0,0 +1,27 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| public class ActualizacioneSeguridadModel { | |||
| private int actualizacionsegId; | |||
| private String descripcion; | |||
| private String otrasactualizaciones; | |||
| private int mantenimientoId; | |||
| public ActualizacioneSeguridadModel(int actualizacionsegId, String descripcion, String otrasactualizaciones, int mantenimientoId) { | |||
| this.actualizacionsegId = actualizacionsegId; | |||
| this.descripcion = descripcion; | |||
| this.otrasactualizaciones = otrasactualizaciones; | |||
| this.mantenimientoId = mantenimientoId; | |||
| } | |||
| public int getActualizacionsegId() { return actualizacionsegId; } | |||
| public String getDescripcion() { return descripcion; } | |||
| public String getOtrasactualizaciones() { return otrasactualizaciones; } | |||
| public int getMantenimientoId() { return mantenimientoId; } | |||
| public void setActualizacionsegId(int actualizacionsegId) { this.actualizacionsegId = actualizacionsegId; } | |||
| public void setDescripcion(String descripcion) { this.descripcion = descripcion; } | |||
| public void setOtrasactualizaciones(String otrasactualizaciones) { this.otrasactualizaciones = otrasactualizaciones; } | |||
| public void setMantenimientoId(int mantenimientoId) { this.mantenimientoId = mantenimientoId;} | |||
| } | |||
| @ -0,0 +1,84 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| import org.springframework.security.core.GrantedAuthority; | |||
| import org.springframework.security.core.userdetails.UserDetails; | |||
| import java.util.Collection; | |||
| public class CustomUserDetails implements UserDetails { | |||
| private String username; | |||
| private String firstName; | |||
| private String lastName; | |||
| private String email; | |||
| private Collection<? extends GrantedAuthority> authorities; | |||
| private String password; | |||
| public CustomUserDetails(String username, String firstName, String lastName, String email, Collection<? extends GrantedAuthority> authorities, String password) { | |||
| this.username = username; | |||
| this.firstName = firstName; | |||
| this.lastName = lastName; | |||
| this.email = email; | |||
| this.authorities = authorities; | |||
| this.password = password; | |||
| } | |||
| // Getters and setters | |||
| public String getFirstName() { | |||
| return firstName; | |||
| } | |||
| public void setFirstName(String firstName) { | |||
| this.firstName = firstName; | |||
| } | |||
| public String getLastName() { | |||
| return lastName; | |||
| } | |||
| public void setLastName(String lastName) { | |||
| this.lastName = lastName; | |||
| } | |||
| public String getEmail() { | |||
| return email; | |||
| } | |||
| public void setEmail(String email) { | |||
| this.email = email; | |||
| } | |||
| @Override | |||
| public Collection<? extends GrantedAuthority> getAuthorities() { | |||
| return authorities; | |||
| } | |||
| @Override | |||
| public String getPassword() { | |||
| return password; | |||
| } | |||
| @Override | |||
| public String getUsername() { | |||
| return username; | |||
| } | |||
| @Override | |||
| public boolean isAccountNonExpired() { | |||
| return true; | |||
| } | |||
| @Override | |||
| public boolean isAccountNonLocked() { | |||
| return true; | |||
| } | |||
| @Override | |||
| public boolean isCredentialsNonExpired() { | |||
| return true; | |||
| } | |||
| @Override | |||
| public boolean isEnabled() { | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,33 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| public class DepartamentosModel { | |||
| private String departamentoId; | |||
| private String nombre; | |||
| public DepartamentosModel(String departamentoId, String nombre) { | |||
| this.departamentoId = departamentoId; | |||
| this.nombre = nombre; | |||
| } | |||
| public String getDepartamentoId() { | |||
| return departamentoId; | |||
| } | |||
| public void setDepartamentoId(String departamentoId) { | |||
| this.departamentoId = departamentoId; | |||
| } | |||
| public String getNombre() { | |||
| return nombre; | |||
| } | |||
| public void setNombre(String nombre) { | |||
| this.nombre = nombre; | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| return nombre; | |||
| } | |||
| } | |||
| @ -0,0 +1,66 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| import java.time.LocalDate; | |||
| public class DetalleMantenimientoModel { | |||
| private int id; | |||
| private int planAnualId; | |||
| private String tipo; | |||
| private String departamento; | |||
| private String usuario; | |||
| private LocalDate fechaprog; | |||
| private LocalDate fecha; | |||
| private String nombreEquipo; | |||
| private String formaMant; | |||
| private String firmaUser; | |||
| private String firmaSmt; | |||
| private String firmaGcia; | |||
| private String situacion; | |||
| public DetalleMantenimientoModel(int id, int planAnualId, String tipo, String departamento, | |||
| String usuario, LocalDate fechaprog, LocalDate fecha, String nombreEquipo, String formaMant, | |||
| String firmaUser, String firmaSmt, String firmaGcia, String situacion) { | |||
| this.id = id; | |||
| this.planAnualId = planAnualId; | |||
| this.tipo = tipo; | |||
| this.departamento = departamento; | |||
| this.usuario = usuario; | |||
| this.fechaprog = fechaprog; | |||
| this.fecha = fecha; | |||
| this.nombreEquipo = nombreEquipo; | |||
| this.formaMant = formaMant; | |||
| this.firmaUser = firmaUser; | |||
| this.firmaSmt = firmaSmt; | |||
| this.firmaGcia = firmaGcia; | |||
| this.situacion = situacion; | |||
| } | |||
| public int getId() { return id; } | |||
| public int getPlanAnualId() { return planAnualId; } | |||
| public String getTipo() { return tipo; } | |||
| public String getDepartamento() { return departamento; } | |||
| public String getUsuario() { return usuario; } | |||
| public LocalDate getFechaprog() { return fechaprog; } | |||
| public LocalDate getFecha() { return fecha; } | |||
| public String getNombreEquipo() { return nombreEquipo; } | |||
| public String getFormaMant() { return formaMant; } | |||
| public String getFirmaUser() { return firmaUser; } | |||
| public String getFirmaSmt() { return firmaSmt; } | |||
| public String getFirmaGcia() { return firmaGcia; } | |||
| public String getSituacion() { return situacion; } | |||
| public void setId(int id) { this.id = id; } | |||
| public void setPlanAnualId(int planAnualId) { this.planAnualId = planAnualId; } | |||
| public void setTipo(String tipo) { this.tipo = tipo; } | |||
| public void setDepartamento(String departamento) { this.departamento = departamento; } | |||
| public void setUsuario(String usuario) { this.usuario = usuario; } | |||
| public void setFechaprog(LocalDate fechaprog) { this.fechaprog = fechaprog; } | |||
| public void setFecha(LocalDate fecha) { this.fecha = fecha; } | |||
| public void setNombreEquipo(String nombreEquipo) { this.nombreEquipo = nombreEquipo; } | |||
| public void setFormaMant(String formaMant) { this.formaMant = formaMant; } | |||
| public void setFirmaUser(String firmaUser) { this.firmaUser = firmaUser; } | |||
| public void setFirmaSmt(String firmaSmt) { this.firmaSmt = firmaSmt; } | |||
| public void setFirmaGcia(String firmaGcia) { this.firmaGcia = firmaGcia; } | |||
| public void setSituacion(String situacion) { this.situacion = situacion; } | |||
| } | |||
| @ -0,0 +1,35 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| public class HardwareDetalle { | |||
| private int mantenimientoId; | |||
| private int hardwareDetId; | |||
| private String descripcion; | |||
| private String modelo; | |||
| private String numSerie; | |||
| private String placa; | |||
| public HardwareDetalle(int mantenimientoId, int hardwareDetId, String descripcion, | |||
| String modelo, String numSerie, String placa) { | |||
| this.mantenimientoId = mantenimientoId; | |||
| this.hardwareDetId = hardwareDetId; | |||
| this.descripcion = descripcion; | |||
| this.modelo = modelo; | |||
| this.numSerie = numSerie; | |||
| this.placa = placa; | |||
| } | |||
| public int getMantenimientoId() { return mantenimientoId; } | |||
| public int getHardwareDetId() { return hardwareDetId; } | |||
| public String getDescripcion() { return descripcion; } | |||
| public String getModelo() { return modelo; } | |||
| public String getNumSerie() { return numSerie; } | |||
| public String getPlaca() { return placa; } | |||
| public void setMantenimientoId(int mantenimientoId) { this.mantenimientoId = mantenimientoId; } | |||
| public void setHardwareDetId(int hardwareDetId) { this.hardwareDetId = hardwareDetId; } | |||
| public void setDescripcion(String descripcion) { this.descripcion = descripcion; } | |||
| public void setModelo(String modelo) { this.modelo = modelo; } | |||
| public void setNumSerie(String numSerie) { this.numSerie = numSerie; } | |||
| public void setPlaca(String placa) { this.placa = placa; } | |||
| } | |||
| @ -0,0 +1,91 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| import java.time.LocalDate; | |||
| public class MantCorrectivosModel { | |||
| private int mantenimientoId; | |||
| private LocalDate fecha; | |||
| private String tipo; | |||
| private String area; | |||
| private String nombre; | |||
| private String forma; | |||
| private String nomequipo; | |||
| private String reparacion; | |||
| public MantCorrectivosModel(int mantenimientoId, LocalDate fecha, String tipo, | |||
| String area, String nombre, String forma, String nomequipo, String reparacion) { | |||
| this.mantenimientoId = mantenimientoId; | |||
| this.fecha = fecha; | |||
| this.tipo = tipo; | |||
| this.area = area; | |||
| this.nombre = nombre; | |||
| this.forma = forma; | |||
| this.nomequipo = nomequipo; | |||
| this.reparacion = reparacion; | |||
| } | |||
| public int getMantenimientoId() { | |||
| return mantenimientoId; | |||
| } | |||
| public void setMantenimientoId(int mantenimientoId) { | |||
| this.mantenimientoId = mantenimientoId; | |||
| } | |||
| public LocalDate getFecha() { | |||
| return fecha; | |||
| } | |||
| public void setFecha(LocalDate fecha) { | |||
| this.fecha = fecha; | |||
| } | |||
| public String getTipo() { | |||
| return tipo; | |||
| } | |||
| public void setTipo(String tipo) { | |||
| this.tipo = tipo; | |||
| } | |||
| public String getArea() { | |||
| return area; | |||
| } | |||
| public void setArea(String area) { | |||
| this.area = area; | |||
| } | |||
| public String getNombre() { | |||
| return nombre; | |||
| } | |||
| public void setNombre(String nombre) { | |||
| this.nombre = nombre; | |||
| } | |||
| public String getForma() { | |||
| return forma; | |||
| } | |||
| public void setForma(String forma) { | |||
| this.forma = forma; | |||
| } | |||
| public String getNomequipo() { | |||
| return nomequipo; | |||
| } | |||
| public void setNomequipo(String nomequipo) { | |||
| this.nomequipo = nomequipo; | |||
| } | |||
| public String getReparacion() { | |||
| return reparacion; | |||
| } | |||
| public void setReparacion(String reparacion) { | |||
| this.reparacion = reparacion; | |||
| } | |||
| } | |||
| @ -0,0 +1,145 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| import java.time.LocalDate; | |||
| public class PlanAnual { | |||
| private int numero; | |||
| private String nomEquipo; | |||
| private String departamento; | |||
| private boolean monitor; // Cambiado a boolean | |||
| private boolean teclado; // Cambiado a boolean | |||
| private boolean mouse; // Cambiado a boolean | |||
| private boolean regulador; // Cambiado a boolean | |||
| private boolean cpu; // Cambiado a boolean | |||
| private boolean impresora; // Cambiado a boolean | |||
| private boolean miniPrint; // Cambiado a boolean | |||
| private boolean laptop; // Cambiado a boolean | |||
| private boolean escaner; // Cambiado a boolean | |||
| private LocalDate fechaProgramada; | |||
| private LocalDate fechaMantenimiento; | |||
| private String mesplaneado; | |||
| private String smt; | |||
| private String estado; | |||
| private String situacion; | |||
| // Constructor | |||
| public PlanAnual(int numero, String nomEquipo, String departamento, boolean monitor, | |||
| boolean teclado, boolean mouse, boolean regulador, | |||
| boolean cpu, boolean impresora, boolean miniPrint, | |||
| boolean laptop, boolean escaner, LocalDate fechaProgramada, | |||
| LocalDate fechaMantenimiento, String mesplaneado, String smt, String estado, String situacion) { | |||
| this.numero = numero; | |||
| this.nomEquipo = nomEquipo; | |||
| this.departamento = departamento; | |||
| this.monitor = monitor; | |||
| this.teclado = teclado; | |||
| this.mouse = mouse; | |||
| this.regulador = regulador; | |||
| this.cpu = cpu; | |||
| this.impresora = impresora; | |||
| this.miniPrint = miniPrint; | |||
| this.laptop = laptop; | |||
| this.escaner = escaner; | |||
| this.fechaProgramada = fechaProgramada; | |||
| this.fechaMantenimiento = fechaMantenimiento; | |||
| this.mesplaneado = mesplaneado; | |||
| this.smt = smt; | |||
| this.estado = estado; | |||
| this.situacion = situacion; | |||
| } | |||
| // Getters | |||
| public int getNumero() { | |||
| return numero; | |||
| } | |||
| public String getNomEquipo() { | |||
| return nomEquipo; | |||
| } | |||
| public String getDepartamento() { | |||
| return departamento; | |||
| } | |||
| public boolean isMonitor() { | |||
| return monitor; | |||
| } | |||
| public boolean isTeclado() { | |||
| return teclado; | |||
| } | |||
| public boolean isMouse() { | |||
| return mouse; | |||
| } | |||
| public boolean isRegulador() { | |||
| return regulador; | |||
| } | |||
| public boolean isCpu() { | |||
| return cpu; | |||
| } | |||
| public boolean isImpresora() { | |||
| return impresora; | |||
| } | |||
| public boolean isMiniPrint() { | |||
| return miniPrint; | |||
| } | |||
| public boolean isLaptop() { | |||
| return laptop; | |||
| } | |||
| public boolean isEscaner() { | |||
| return escaner; | |||
| } | |||
| public String getSmt() { | |||
| return smt; | |||
| } | |||
| public String getEstado() { | |||
| return estado; | |||
| } | |||
| public void setNumero(int numero) { | |||
| this.numero = numero; | |||
| } | |||
| public LocalDate getFechaMantenimiento() { | |||
| return fechaMantenimiento; | |||
| } | |||
| public void setFechaMantenimiento(LocalDate fechaMantenimiento) { | |||
| this.fechaMantenimiento = fechaMantenimiento; | |||
| } | |||
| public LocalDate getFechaProgramada() { | |||
| return fechaProgramada; | |||
| } | |||
| public void setFechaProgramada(LocalDate fechaProgramada) { | |||
| this.fechaProgramada = fechaProgramada; | |||
| } | |||
| public String getMesplaneado() { | |||
| return mesplaneado; | |||
| } | |||
| public void setMesplaneado(String mesplaneado) { | |||
| this.mesplaneado = mesplaneado; | |||
| } | |||
| public String getSituacion() { | |||
| return situacion; | |||
| } | |||
| public void setSituacion(String situacion) { | |||
| this.situacion = situacion; | |||
| } | |||
| } | |||
| @ -0,0 +1,72 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| public class RedmineUser { | |||
| private int id; | |||
| private String login; | |||
| private String firstname; | |||
| private String lastname; | |||
| private String mail; | |||
| private String key; | |||
| public int getId() { | |||
| return id; | |||
| } | |||
| public void setId(int id) { | |||
| this.id = id; | |||
| } | |||
| public String getLogin() { | |||
| return login; | |||
| } | |||
| public void setLogin(String login) { | |||
| this.login = login; | |||
| } | |||
| public String getFirstname() { | |||
| return firstname; | |||
| } | |||
| public void setFirstname(String firstname) { | |||
| this.firstname = firstname; | |||
| } | |||
| public String getLastname() { | |||
| return lastname; | |||
| } | |||
| public void setLastname(String lastname) { | |||
| this.lastname = lastname; | |||
| } | |||
| public String getMail() { | |||
| return mail; | |||
| } | |||
| public void setMail(String mail) { | |||
| this.mail = mail; | |||
| } | |||
| public String getKey() { | |||
| return key; | |||
| } | |||
| public void setKey(String key) { | |||
| this.key = key; | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| return "RedmineUser{" + | |||
| "id=" + id + | |||
| ", login='" + login + '\'' + | |||
| ", firstname='" + firstname + '\'' + | |||
| ", lastname='" + lastname + '\'' + | |||
| ", mail='" + mail + '\'' + | |||
| ", key='" + key + '\'' + | |||
| '}'; | |||
| } | |||
| } | |||
| @ -0,0 +1 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| @ -0,0 +1,153 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| import java.sql.Date; | |||
| import java.time.LocalDate; | |||
| public class Ticket { | |||
| private final int id; | |||
| private final String subject; | |||
| private final String description; | |||
| private final String status; | |||
| private final LocalDate dateCreate; | |||
| private LocalDate dateClose; | |||
| private User author; | |||
| private Integer trackerId; | |||
| private String type; | |||
| public Ticket(int id, String subject, String description, String status, String dateCreate, String dateClose, Integer trackerId, String type) { | |||
| this.id = id; | |||
| this.subject = subject; | |||
| this.description = description; | |||
| this.status = status; | |||
| // Manejo de la fecha de creación | |||
| if (dateCreate != null && !dateCreate.isEmpty()) { | |||
| this.dateCreate = LocalDate.parse(dateCreate); // Solo se parsea si no está vacío | |||
| } else { | |||
| this.dateCreate = null; // Si está vacío, asignar null | |||
| } | |||
| // Manejo de la fecha de cierre | |||
| if (dateClose != null && !dateClose.isEmpty()) { | |||
| this.dateClose = LocalDate.parse(dateClose); // Solo se parsea si no está vacío | |||
| } else { | |||
| this.dateClose = null; // Si está vacío, asignar null | |||
| } | |||
| this.author = author; | |||
| this.trackerId = trackerId; | |||
| this.type = type; | |||
| } | |||
| public int getId() { | |||
| return id; | |||
| } | |||
| public String getSubject() { | |||
| return subject; | |||
| } | |||
| public String getDescription() { | |||
| return description; | |||
| } | |||
| public String getStatus() { | |||
| return status; | |||
| } | |||
| public User getAuthor() { | |||
| return author; | |||
| } | |||
| public void setAuthor(User author) { | |||
| this.author = author; | |||
| } | |||
| public Date getDateCreate() { | |||
| return java.sql.Date.valueOf(this.dateCreate); | |||
| } | |||
| public Integer getTrackerId() { | |||
| return trackerId; | |||
| } | |||
| public void setTrackerId(Integer tipoId) { | |||
| this.trackerId = tipoId; | |||
| } | |||
| public LocalDate getDateClose() { | |||
| return dateClose; | |||
| } | |||
| public void setDateClose(LocalDate dateClose) { | |||
| this.dateClose = dateClose; | |||
| } | |||
| public void setType(String type) { | |||
| this.type = type; | |||
| } | |||
| public static class User { | |||
| private String username; | |||
| public User(String username) { | |||
| this.username = username; | |||
| } | |||
| public String getUsername() { | |||
| return username; | |||
| } | |||
| public void setUsername(String username) { | |||
| this.username = username; | |||
| } | |||
| } | |||
| public String tiempoEst(Integer trackerId) { | |||
| if (trackerId == null) { | |||
| return "Desconocido"; | |||
| } | |||
| switch (trackerId) { | |||
| case 1,3,4,7: | |||
| return "1-2 dias Max"; | |||
| case 2,12: | |||
| return "2 hrs Max"; | |||
| case 5: | |||
| return "5 dias aprox."; | |||
| case 8,11: | |||
| return "2-6 hrs Max"; | |||
| case 9,10: | |||
| return "2 hrs Max"; | |||
| default: | |||
| return "N/A"; | |||
| } | |||
| } | |||
| public String getType() { | |||
| if (trackerId == null) { | |||
| return "Desconocido"; | |||
| } | |||
| return switch (trackerId) { | |||
| case 5 -> "Acceso/Permiso/Bajas"; | |||
| case 6 -> "Soporte de Software"; | |||
| case 7 -> "Capacitacion de Software"; | |||
| case 8 -> "Configuracion de Software"; | |||
| case 9 -> "Desarrollo de Software"; | |||
| case 10 -> "Digitalizacion GIS"; | |||
| case 11 -> "Documento"; | |||
| case 12 -> "Reporte"; | |||
| case 13 -> "Mantenimiento Correctivo"; | |||
| case 14 -> "Actividad"; | |||
| case 15 -> "Entrega de Consumibles"; | |||
| case 16 -> "Instalacion/Configuracion GIS"; | |||
| //case 17 -> "DDL"; | |||
| //case 18 -> "DCL"; | |||
| //case 19 -> "DML"; | |||
| default -> "N/A"; | |||
| }; | |||
| } | |||
| } | |||
| @ -0,0 +1,34 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| public class TiposHardware { | |||
| private String tipoHardwareId; | |||
| private String nombreHardware; | |||
| public TiposHardware(String tipoHardwareId, String nombreHardware) { | |||
| this.tipoHardwareId = tipoHardwareId; | |||
| this.nombreHardware = nombreHardware; | |||
| } | |||
| public String getTipoHardwareId() { | |||
| return tipoHardwareId; | |||
| } | |||
| public void setTipoHardwareId(String tipoHardwareId) { | |||
| this.tipoHardwareId = tipoHardwareId; | |||
| } | |||
| public String getNombreHardware() { | |||
| return nombreHardware; | |||
| } | |||
| public void setNombreHardware(String nombreHardware) { | |||
| this.nombreHardware = nombreHardware; | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| return nombreHardware; | |||
| } | |||
| } | |||
| @ -0,0 +1,32 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| public class TiposMantenimiento { | |||
| private String tipomantId; | |||
| private String nombre; | |||
| public TiposMantenimiento(String tipomantId, String nombre) { | |||
| this.tipomantId = tipomantId; | |||
| this.nombre = nombre; | |||
| } | |||
| public String getTipomantId() { | |||
| return tipomantId; | |||
| } | |||
| public void setTipomantId(String tipomantId) { | |||
| this.tipomantId = tipomantId; | |||
| } | |||
| public String getNombre() { | |||
| return nombre; | |||
| } | |||
| public void setNombre(String nombre) { | |||
| this.nombre = nombre; | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| return nombre; | |||
| } | |||
| } | |||
| @ -0,0 +1,43 @@ | |||
| package mx.gob.jumapacelaya.models; | |||
| public class Usuario { | |||
| private String empleadoId; | |||
| private String nombre; | |||
| private String email; | |||
| public Usuario(String empleadoId, String nombre, String email) { | |||
| this.empleadoId = empleadoId; | |||
| this.nombre = nombre; | |||
| this.email = email; | |||
| } | |||
| public String getEmpleadoId() { | |||
| return empleadoId; | |||
| } | |||
| public void setEmpleadoId(String empleadoId) { | |||
| this.empleadoId = empleadoId; | |||
| } | |||
| public String getNombre() { | |||
| return nombre; | |||
| } | |||
| public void setNombre(String nombre) { | |||
| this.nombre = nombre; | |||
| } | |||
| public String getEmail() { | |||
| return email; | |||
| } | |||
| public void setEmail(String email) { | |||
| this.email = email; | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| return nombre; | |||
| } | |||
| } | |||
| @ -0,0 +1,899 @@ | |||
| package mx.gob.jumapacelaya.services; | |||
| import mx.gob.jumapacelaya.models.*; | |||
| import oracle.jdbc.OracleConnection; | |||
| import oracle.jdbc.OraclePreparedStatement; | |||
| import oracle.sql.CLOB; | |||
| import org.apache.poi.ss.usermodel.*; | |||
| import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Service; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.io.StringReader; | |||
| import java.security.interfaces.RSAKey; | |||
| import java.sql.*; | |||
| import java.time.LocalDate; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| @Service | |||
| public class DatabaseService { | |||
| @Value("${db.url}") | |||
| private String dbUrl; | |||
| @Value("${db.user}") | |||
| private String dbUser; | |||
| @Value("${db.pass}") | |||
| private String dbPass; | |||
| private Connection getMysqlConnection() throws SQLException { | |||
| return DriverManager.getConnection(dbUrl, dbUser, dbPass); | |||
| } | |||
| /*private Connection getOracleConnection() throws SQLException { | |||
| String url = "jdbc:oracle:thin:@//svradminfinan:1521/admfinpdb.JUMAPACELAYA.GOB.MX"; | |||
| String user = "Finanzas"; | |||
| String pass = "finanzas"; | |||
| return DriverManager.getConnection(url, user, pass); | |||
| }*/ | |||
| // Método para obtener los tipos de mantenimientos | |||
| public List<TiposMantenimiento> getTiposDeMantenimientos() { | |||
| List<TiposMantenimiento> tiposDeMantenimientos = new ArrayList<>(); | |||
| String query = "SELECT tipomantid, nombre FROM TIPOMANT"; | |||
| try (Connection connection = getMysqlConnection(); | |||
| Statement statement = connection.createStatement(); | |||
| ResultSet resultSet = statement.executeQuery(query)) { | |||
| while (resultSet.next()) { | |||
| TiposMantenimiento tipo = new TiposMantenimiento( | |||
| resultSet.getString("tipomantid"), | |||
| resultSet.getString("nombre") | |||
| ); | |||
| tiposDeMantenimientos.add(tipo); | |||
| } | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return tiposDeMantenimientos; | |||
| } | |||
| // Método para obtener las nomenclaturas | |||
| public String getNomenclatura(String tipoMantenimiento) { | |||
| String nomenclatura = ""; | |||
| String query = "SELECT nomenclatura FROM TIPOMANT where TIPOMANTID = ?"; | |||
| try (Connection connection = getMysqlConnection(); | |||
| PreparedStatement preparedStatement = connection.prepareStatement(query)) { | |||
| preparedStatement.setString(1, tipoMantenimiento); | |||
| try (ResultSet resultSet = preparedStatement.executeQuery()) { | |||
| if (resultSet.next()) { | |||
| nomenclatura = resultSet.getString("nomenclatura"); | |||
| } | |||
| } | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| System.err.println("Error al obtener nomenclatura: " + e.getMessage()); | |||
| } | |||
| return nomenclatura; | |||
| } | |||
| /* -------------- Metodo para obtener a los usuarios ---------------- */ | |||
| public List<Usuario> getUsuarios() { | |||
| List<Usuario> usuarios = new ArrayList<>(); | |||
| String query = "SELECT u.* \n" + | |||
| "FROM USUARIOS u"; | |||
| try (Connection connection = getMysqlConnection(); | |||
| Statement statement = connection.createStatement(); | |||
| ResultSet resultSet = statement.executeQuery(query)) { | |||
| while (resultSet.next()) { | |||
| Usuario usuario = new Usuario( | |||
| resultSet.getString("empleadoid"), | |||
| resultSet.getString("nombre"), | |||
| resultSet.getString("email") | |||
| ); | |||
| usuarios.add(usuario); | |||
| } | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return usuarios; | |||
| } | |||
| /* -------------- Metodo para obtener los departamentos ---------------- */ | |||
| public List<DepartamentosModel> getDepartamentos() { | |||
| List<DepartamentosModel> departamentos = new ArrayList<>(); | |||
| String query = "select DEPARTAMENTOID, DESCRIPCION from DEPARTAMENTOS"; | |||
| try (Connection connection = getMysqlConnection(); | |||
| Statement statement = connection.createStatement(); | |||
| ResultSet resultSet = statement.executeQuery(query)) { | |||
| while (resultSet.next()) { | |||
| DepartamentosModel departamentosModel = new DepartamentosModel( | |||
| resultSet.getString("departamentoid"), | |||
| resultSet.getString("descripcion") | |||
| ); | |||
| departamentos.add(departamentosModel); | |||
| } | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return departamentos; | |||
| } | |||
| /* -------------- Metodo para obtener los tipos de hardware ---------------- */ | |||
| public List<TiposHardware> getTiposHardware() { | |||
| List<TiposHardware> tiposHardware = new ArrayList<>(); | |||
| String query = "select TIPOHARDWAREID, DESCRIPCION from TIPOSHARDWARE"; | |||
| try (Connection connection = getMysqlConnection(); | |||
| Statement statement = connection.createStatement(); | |||
| ResultSet resultSet = statement.executeQuery(query)) { | |||
| while (resultSet.next()) { | |||
| TiposHardware tiposHardwareModel = new TiposHardware( | |||
| resultSet.getString("tipohardwareid"), | |||
| resultSet.getString("descripcion") | |||
| ); | |||
| tiposHardware.add(tiposHardwareModel); | |||
| } | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return tiposHardware; | |||
| } | |||
| /* ----------------Obtener el Plan Anual de Mantenimiento ---------------- */ | |||
| public List<PlanAnual> getPlanAnual() { | |||
| List<PlanAnual> planAnualList = new ArrayList<>(); | |||
| String query = "SELECT p.plananualid, p.nomEquipo, p.area,\n" + | |||
| " p.monitor, p.teclado, p.mouse, p.regulador,\n" + | |||
| " p.cpu, p.impresora, p.miniPrint, p.laptop, p.escaner,\n" + | |||
| " p.fechaprog, m.fecha AS fechaMantenimiento,\n" + | |||
| " me.NOMBRE AS MESPLANEADO, p.tecnicosmt, p.estado,\n" + | |||
| " COALESCE(v.SITUACION, 'NO REALIZADO') AS SITUACION\n" + | |||
| " FROM PLANANUAL p\n" + | |||
| " LEFT JOIN MANTENIMIENTOS m ON p.plananualid = m.plananualid\n" + | |||
| " LEFT JOIN MESES me ON p.MESID = me.MESID\n" + | |||
| " LEFT JOIN VW_SITUACION_MANTENIMIENTO v ON v.PLANANUALID = p.PLANANUALID\n" + | |||
| " ORDER BY p.FECHAPROG ASC"; | |||
| try (Connection connection = getMysqlConnection(); | |||
| Statement statement = connection.createStatement(); | |||
| ResultSet resultSet = statement.executeQuery(query)) { | |||
| while (resultSet.next()) { | |||
| PlanAnual planAnual = new PlanAnual( | |||
| resultSet.getInt("plananualid"), | |||
| resultSet.getString("nomEquipo"), | |||
| resultSet.getString("area"), | |||
| resultSet.getBoolean("monitor"), | |||
| resultSet.getBoolean("teclado"), | |||
| resultSet.getBoolean("mouse"), | |||
| resultSet.getBoolean("regulador"), | |||
| resultSet.getBoolean("cpu"), | |||
| resultSet.getBoolean("impresora"), | |||
| resultSet.getBoolean("miniPrint"), | |||
| resultSet.getBoolean("laptop"), | |||
| resultSet.getBoolean("escaner"), | |||
| resultSet.getDate("fechaprog").toLocalDate(), // Cambiado a LocalDate | |||
| resultSet.getDate("fechaMantenimiento") != null ? resultSet.getDate("fechaMantenimiento").toLocalDate() : null, // Cambiado a LocalDate | |||
| resultSet.getString("mesplaneado"), | |||
| resultSet.getString("tecnicosmt"), | |||
| resultSet.getString("estado"), | |||
| resultSet.getString("SITUACION") | |||
| ); | |||
| planAnualList.add(planAnual); | |||
| } | |||
| System.out.println("Registros obtenidos: " + planAnualList.size()); | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return planAnualList; | |||
| } | |||
| /* ----------------Obtener el Plan Anual de Mantenimiento por ID ---------------- */ | |||
| public PlanAnual getPlanAnualPorId(int id) { | |||
| String query = "SELECT p.plananualid, p.nomEquipo, p.area,\n" + | |||
| " p.monitor, p.teclado, p.mouse, p.regulador,\n" + | |||
| " p.cpu, p.impresora, p.miniPrint, p.laptop, p.escaner,\n" + | |||
| " p.fechaprog, m.fecha AS fechaMantenimiento,\n" + | |||
| " me.NOMBRE AS MESPLANEADO, p.tecnicosmt, p.estado,\n" + | |||
| " COALESCE(v.SITUACION, 'NO REALIZADO') AS SITUACION\n" + | |||
| " FROM PLANANUAL p\n" + | |||
| " LEFT JOIN MANTENIMIENTOS m ON p.plananualid = m.plananualid\n" + | |||
| " LEFT JOIN MESES me ON p.MESID = me.MESID\n" + | |||
| " LEFT JOIN VW_SITUACION_MANTENIMIENTO v ON v.PLANANUALID = p.PLANANUALID\n" + | |||
| " where p.plananualid = ?"; | |||
| try (Connection connection = getMysqlConnection(); | |||
| PreparedStatement statement = connection.prepareStatement(query)) { | |||
| statement.setInt(1, id); | |||
| try (ResultSet resultSet = statement.executeQuery()) { | |||
| if (resultSet.next()) { | |||
| return new PlanAnual( | |||
| resultSet.getInt("plananualid"), | |||
| resultSet.getString("nomEquipo"), | |||
| resultSet.getString("area"), | |||
| resultSet.getBoolean("monitor"), | |||
| resultSet.getBoolean("teclado"), | |||
| resultSet.getBoolean("mouse"), | |||
| resultSet.getBoolean("regulador"), | |||
| resultSet.getBoolean("cpu"), | |||
| resultSet.getBoolean("impresora"), | |||
| resultSet.getBoolean("miniPrint"), | |||
| resultSet.getBoolean("laptop"), | |||
| resultSet.getBoolean("escaner"), | |||
| resultSet.getDate("fechaprog").toLocalDate(), // Cambiado a LocalDate | |||
| resultSet.getDate("fechaMantenimiento") != null ? resultSet.getDate("fechaMantenimiento").toLocalDate() : null, // Cambiado a LocalDate | |||
| resultSet.getString("mesplaneado"), | |||
| resultSet.getString("tecnicosmt"), | |||
| resultSet.getString("estado"), | |||
| resultSet.getString("SITUACION") | |||
| ); | |||
| } | |||
| } | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return null; | |||
| } | |||
| /* ----------------Obtener detalles del mantenimiento ---------------- */ | |||
| public DetalleMantenimientoModel getDetalleMantenimientoPorPlanAnualId(int planAnualId) { | |||
| String query = "SELECT\n" + | |||
| " m.MANTENIMIENTOID AS ID,\n" + | |||
| " p.PLANANUALID,\n" + | |||
| " t.NOMBRE AS TIPO,\n" + | |||
| " d.DESCRIPCION AS DEPARTAMENTO,\n" + | |||
| " u.NOMBRE AS USUARIO,\n" + | |||
| " v.FECHAPROG,\n" + | |||
| " v.FECHAREALIZADO,\n" + | |||
| " NOMBREEQUIPO,\n" + | |||
| " FORMAMANT,\n" + | |||
| " FIRMAUSUARIO,\n" + | |||
| " FIRMASMT,\n" + | |||
| " FIRMAGCIA,\n" + | |||
| " v.SITUACION\n" + | |||
| "FROM MANTENIMIENTOS m\n" + | |||
| "INNER JOIN TIPOMANT t ON m.TIPOMANTID = t.TIPOMANTID\n" + | |||
| "INNER JOIN DEPARTAMENTOS d ON m.DEPARTAMENTOID = d.DEPARTAMENTOID\n" + | |||
| "INNER JOIN USUARIOS u ON u.EMPLEADOID = m.EMPLEADOID\n" + | |||
| "INNER JOIN PLANANUAL p ON m.PLANANUALID = p.PLANANUALID\n" + | |||
| "INNER JOIN PLANANUAL pa ON m.PLANANUALID = pa.PLANANUALID\n" + | |||
| "INNER JOIN VW_SITUACION_MANTENIMIENTO v ON v.MANTENIMIENTOID = m.MANTENIMIENTOID\n" + | |||
| "WHERE p.PLANANUALID = ?"; | |||
| try (Connection connection = getMysqlConnection(); | |||
| PreparedStatement statement = connection.prepareStatement(query)) { | |||
| statement.setInt(1, planAnualId); | |||
| try (ResultSet rs = statement.executeQuery()) { | |||
| if (rs.next()) { | |||
| return new DetalleMantenimientoModel( | |||
| rs.getInt("ID"), | |||
| rs.getInt("PLANANUALID"), | |||
| rs.getString("TIPO"), | |||
| rs.getString("DEPARTAMENTO"), | |||
| rs.getString("USUARIO"), | |||
| rs.getDate("FECHAPROG").toLocalDate(), | |||
| rs.getDate("FECHAREALIZADO").toLocalDate(), | |||
| rs.getString("NOMBREEQUIPO"), | |||
| rs.getString("FORMAMANT"), | |||
| rs.getString("FIRMAUSUARIO"), | |||
| rs.getString("FIRMASMT"), | |||
| rs.getString("FIRMAGCIA"), | |||
| rs.getString("SITUACION") | |||
| ); | |||
| } | |||
| } | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return null; | |||
| } | |||
| /* ----------------Obtener detalles del hardaware por ID ---------------- */ | |||
| public List<HardwareDetalle> getHardwaredetallePorMantId(int mantenimientoId) { | |||
| List<HardwareDetalle> detalles = new ArrayList<>(); | |||
| String query = "SELECT h.MANTENIMIENTOID, h.HARDWAREDETID, t.DESCRIPCION, h.MODELO, h.NUMSERIE, h.PLACA\r\n" + // | |||
| "FROM HARDWAREDET h\r\n" + // | |||
| "INNER JOIN TIPOSHARDWARE t ON h.TIPOHARDWAREID = t.TIPOHARDWAREID \r\n" + // | |||
| "WHERE h.MANTENIMIENTOID = ?"; | |||
| try (Connection conn = getMysqlConnection(); | |||
| PreparedStatement stmt = conn.prepareStatement(query)) { | |||
| stmt.setInt(1, mantenimientoId); | |||
| ResultSet rs = stmt.executeQuery(); | |||
| while (rs.next()) { | |||
| HardwareDetalle detalle = new HardwareDetalle( | |||
| rs.getInt("MANTENIMIENTOID"), | |||
| rs.getInt("HARDWAREDETID"), | |||
| rs.getString("DESCRIPCION"), | |||
| rs.getString("MODELO"), | |||
| rs.getString("NUMSERIE"), | |||
| rs.getString("PLACA") | |||
| ); | |||
| detalles.add(detalle); | |||
| } | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return detalles; | |||
| } | |||
| /* ---------------- Obtener las actualizaciones de seguridad ---------------- */ | |||
| public List<ActualizacioneSeguridadModel> getActualizacionesSeg(int mantenimientoId) { | |||
| List<ActualizacioneSeguridadModel> actualizaciones = new ArrayList<>(); | |||
| String query = "SELECT *\r\n" + // | |||
| "FROM ACTUALIZACIONESSEG a\r\n" + // | |||
| "WHERE a.MANTENIMIENTOID = ?"; | |||
| try (Connection conn = getMysqlConnection(); | |||
| PreparedStatement stmt = conn.prepareStatement(query)) { | |||
| stmt.setInt(1, mantenimientoId); | |||
| ResultSet rs = stmt.executeQuery(); | |||
| while (rs.next()) { | |||
| ActualizacioneSeguridadModel actualizacion = new ActualizacioneSeguridadModel( | |||
| rs.getInt("ACTUALIZACIONSEGID"), | |||
| rs.getString("DESCRIPCION"), | |||
| rs.getString("OTRASACTUALIZACIONES"), | |||
| rs.getInt("MANTENIMIENTOID") | |||
| ); | |||
| actualizaciones.add(actualizacion); | |||
| } | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return actualizaciones; | |||
| } | |||
| /* ---------------- Obtener los mantenimientos correctivos ---------------- */ | |||
| public List<MantCorrectivosModel> getMantenimientosCorrectivos(int tipomantId) { | |||
| List<MantCorrectivosModel> mantCorrectivos = new ArrayList<>(); | |||
| String query = "select\n" + | |||
| "\tm.MANTENIMIENTOID,\n" + | |||
| "\tm.FECHA,\n" + | |||
| "\tt.NOMBRE TIPO,\n" + | |||
| "\td.DESCRIPCION AREA,\n" + | |||
| "\tu.NOMBRE,\n" + | |||
| "\tCASE\n" + | |||
| "\t\tWHEN formamant = 'M' then 'MANUAL'\n" + | |||
| "\t\tELSE 'REMOTO'\n" + | |||
| "\tEND as FORMA,\n" + | |||
| "\tm.NOMBREEQUIPO,\n" + | |||
| "\tm.REPARACION\n" + | |||
| "from MANTENIMIENTOS m\n" + | |||
| "inner join TIPOMANT t on t.TIPOMANTID = m.TIPOMANTID\n" + | |||
| "inner join DEPARTAMENTOS d on d.DEPARTAMENTOID = m.DEPARTAMENTOID\n" + | |||
| "inner join USUARIOS u on u.EMPLEADOID = m.EMPLEADOID\n" + | |||
| "where m.TIPOMANTID = ?"; | |||
| try (Connection conn = getMysqlConnection(); | |||
| PreparedStatement statement = conn.prepareStatement(query)) { | |||
| statement.setInt(1, tipomantId); | |||
| try (ResultSet rs = statement.executeQuery()) { | |||
| while (rs.next()) { | |||
| MantCorrectivosModel model = new MantCorrectivosModel( | |||
| rs.getInt("MANTENIMIENTOID"), | |||
| rs.getDate("FECHA").toLocalDate(), | |||
| rs.getString("TIPO"), | |||
| rs.getString("AREA"), | |||
| rs.getString("NOMBRE"), | |||
| rs.getString("FORMA"), | |||
| rs.getString("NOMBREEQUIPO"), | |||
| rs.getString("REPARACION") | |||
| ); | |||
| mantCorrectivos.add(model); | |||
| } | |||
| } | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return mantCorrectivos; | |||
| } | |||
| /*-=iii=<() *-=iii=<() *-=iii=<() *-=iii=<() *-=iii=<() *-=iii=<()*/ | |||
| /*-=iii=<() *-=iii=<() *-=iii=<() *-=iii=<() *-=iii=<()*/ | |||
| /*-=iii=<() *-=iii=<() *-=iii=<() *-=iii=<()*/ | |||
| /*-=iii=<() *-=iii=<() *-=iii=<()*/ | |||
| /*-=iii=<() *-=iii=<()*/ | |||
| /* ( ͡° ͜ʖ ͡°) Metodos para insetar en la BD ( ͡° ͜ʖ ͡°) ( ͡° ͜ʖ ͡°) Metodos para insetar en la BD ( ͡° ͜ʖ ͡°) ( ͡° ͜ʖ ͡°) Metodos para insetar en la BD ( ͡° ͜ʖ ͡°) */ | |||
| // INSERTAR EN TABLA: MANTENIMINETOS | |||
| public int insertarMantenimiento(LocalDate fecha, String tipoMantId, String departamentoId, String empleadoId, | |||
| String formaMant, String equipoId, String userSignatureBase64, | |||
| String smtSignatureBase64, String planAnualId, String justificacion, String reparacion) { | |||
| String query = "INSERT INTO MANTENIMIENTOS (fecha, tipoMantId, departamentoId, empleadoId, formaMant, nombreequipo," + | |||
| " firmaUsuario, firmaSmt, planAnualId, justificacion, reparacion) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; | |||
| String updateStatusQuery = "UPDATE PLANANUAL SET estado = 'REALIZADO' WHERE planAnualId = ?"; | |||
| int nuevoId = -1; | |||
| Connection connection = null; | |||
| try { | |||
| connection = getMysqlConnection(); | |||
| if (connection == null) { | |||
| throw new SQLException("No se pudo establecer la conexion con la base de datos."); | |||
| } | |||
| connection.setAutoCommit(false); | |||
| // Paso 1: primero inserta el mantenimiento | |||
| try (PreparedStatement preparedStatement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) { | |||
| preparedStatement.setDate(1, Date.valueOf(fecha)); | |||
| preparedStatement.setLong(2, Long.parseLong(tipoMantId)); | |||
| preparedStatement.setString(3, departamentoId); | |||
| preparedStatement.setLong(4, Long.parseLong(empleadoId)); | |||
| preparedStatement.setString(5, formaMant); | |||
| preparedStatement.setString(6, equipoId); | |||
| if (userSignatureBase64 != null) { | |||
| preparedStatement.setString(7, userSignatureBase64); | |||
| } else { | |||
| preparedStatement.setNull(7, Types.VARCHAR); | |||
| } | |||
| if (smtSignatureBase64 != null) { | |||
| preparedStatement.setString(8, smtSignatureBase64); | |||
| } else { | |||
| preparedStatement.setNull(8, Types.VARCHAR); | |||
| } | |||
| if (planAnualId != null && !planAnualId.isEmpty()) { | |||
| preparedStatement.setLong(9, Long.parseLong(planAnualId)); | |||
| } else { | |||
| preparedStatement.setNull(9, Types.BIGINT); | |||
| } | |||
| preparedStatement.setString(10, justificacion); | |||
| preparedStatement.setString(11, reparacion); | |||
| preparedStatement.executeUpdate(); | |||
| try (ResultSet rs = preparedStatement.getGeneratedKeys()) { | |||
| if (rs.next()) { | |||
| nuevoId = rs.getInt(1); | |||
| } | |||
| } | |||
| } | |||
| // Paso 2: Si se inserto el mantenimiento, se actualiza el estado en MTTOPROGRAMADOS | |||
| if (nuevoId != -1) { | |||
| try (PreparedStatement updateStatement = connection.prepareStatement(updateStatusQuery)) { | |||
| updateStatement.setString(1, planAnualId); | |||
| updateStatement.executeUpdate(); | |||
| } | |||
| } | |||
| // Confirmar la transaccion si ambos pasos son exitosos | |||
| connection.commit(); | |||
| } catch (SQLException e) { | |||
| System.err.println("Error al insertar mantenimiento: " + e.getMessage()); | |||
| e.printStackTrace(); | |||
| // En caso de error, se hace rollback | |||
| if (connection != null) { | |||
| try { | |||
| connection.rollback(); | |||
| } catch (SQLException rollbackEx) { | |||
| System.err.println("Error al hacer rollback: " + rollbackEx.getMessage()); | |||
| } | |||
| } | |||
| } finally { | |||
| // Cerrar la conexion | |||
| if (connection != null) { | |||
| try { | |||
| connection.close(); | |||
| } catch (SQLException closeEx) { | |||
| System.err.println("Error al cerrar la conexion: " + closeEx.getMessage()); | |||
| } | |||
| } | |||
| } | |||
| return nuevoId; | |||
| } | |||
| /*( •_•)>⌐■-■ (⌐■_■)( •_•)>⌐■-■ (⌐■_■)( •_•)>⌐■-■ (⌐■_■)( •_•)>⌐■-■ (⌐■_■)( •_•)>⌐■-■ (⌐■_■)( •_•)>⌐■-■ (⌐■_■)( •_•)>⌐■-■ (⌐■_■) */ | |||
| /* ˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀ */ | |||
| // INSERTAR EN LA TABLA: HARDWAREDET | |||
| public boolean insertarHardware(String tipoHardwareId, String numSerie, String modelo, String placa, int mantenimientoId) { | |||
| String query = "INSERT INTO HARDWAREDET (tipoHardwareId, numSerie, modelo, placa, mantenimientoId) VALUES (?, ?, ?, ?, ?)"; | |||
| boolean isInserted = false; | |||
| try (Connection connection = getMysqlConnection(); | |||
| PreparedStatement preparedStatement = connection.prepareStatement(query)) { | |||
| preparedStatement.setInt(1, Integer.parseInt(tipoHardwareId)); | |||
| preparedStatement.setString(2, numSerie); | |||
| preparedStatement.setString(3, modelo); | |||
| preparedStatement.setString(4, placa); | |||
| preparedStatement.setInt(5, mantenimientoId); | |||
| int rowsAffected = preparedStatement.executeUpdate(); | |||
| isInserted = rowsAffected > 0; | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return isInserted; | |||
| } | |||
| public int getUltimoMantenimientoId() { | |||
| int ultimoId = -1; | |||
| try (Connection connection = getMysqlConnection()) { | |||
| String query = "SELECT MAX(mantenimientoid) FROM MANTENIMIENTOS"; | |||
| try (PreparedStatement preparedStatement = connection.prepareStatement(query)) { | |||
| ResultSet resultSet = preparedStatement.executeQuery(); | |||
| if (resultSet.next()) { | |||
| ultimoId = resultSet.getInt(1); | |||
| } | |||
| } | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return ultimoId; | |||
| } | |||
| // INSERTAR EN LA TABLA: ACTUALIZACIONESSEG | |||
| public boolean insertActualizacionSeg(String descripcion, String otras, int mantenimientoId) { | |||
| String query = "INSERT INTO ACTUALIZACIONESSEG (descripcion, otrasactualizaciones, mantenimientoid) VALUES (?, ?, ?)"; | |||
| try (Connection connection = getMysqlConnection(); | |||
| PreparedStatement preparedStatement = connection.prepareStatement(query)) { | |||
| preparedStatement.setString(1, descripcion); | |||
| preparedStatement.setString(2, otras); | |||
| preparedStatement.setInt(3, mantenimientoId); | |||
| int rowsInserted = preparedStatement.executeUpdate(); | |||
| return rowsInserted > 0; | |||
| } catch (SQLException e) { | |||
| System.err.println("Error al insertar actualizacionSeg: " + e.getMessage()); | |||
| return false; | |||
| } | |||
| } | |||
| // INSERTAR ARCHIVO EXCEL EN LA TABLA: PLANANUAL | |||
| public void insertarDesdeExcel(InputStream inputStream) { | |||
| String query = "INSERT INTO PLANANUAL (NOMEQUIPO, AREA, MONITOR, TECLADO, MOUSE, " + | |||
| "REGULADOR, CPU, IMPRESORA, MINIPRINT, LAPTOP, ESCANER, FECHAPROG, TECNICOSMT, ESTADO) " + | |||
| "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; | |||
| try (Connection connection = getMysqlConnection(); | |||
| //FileInputStream file = new FileInputStream(rutaArchivoExcel); | |||
| Workbook workbook = new XSSFWorkbook(inputStream)) { | |||
| Sheet sheet = workbook.getSheetAt(0); // Primera hoja del archivo Excel | |||
| for (Row row : sheet) { | |||
| if (row.getRowNum() == 0) continue; // Saltar la primera fila si contiene encabezados | |||
| try { | |||
| // Leer cada celda de la fila según el índice correcto | |||
| String nomequipo = getStringCellValue(row.getCell(0)); // Columna 1 | |||
| String area = getStringCellValue(row.getCell(1)); // Columna 2 | |||
| boolean monitor = getBooleanCellValue(row.getCell(2)); // Columna 3 | |||
| boolean teclado = getBooleanCellValue(row.getCell(3)); // Columna 4 | |||
| boolean mouse = getBooleanCellValue(row.getCell(4)); // Columna 5 | |||
| boolean regulador = getBooleanCellValue(row.getCell(5)); // Columna 6 | |||
| boolean cpu = getBooleanCellValue(row.getCell(6)); // Columna 7 | |||
| boolean impresora = getBooleanCellValue(row.getCell(7)); // Columna 8 | |||
| boolean miniprint = getBooleanCellValue(row.getCell(8)); // Columna 9 | |||
| boolean laptop = getBooleanCellValue(row.getCell(9)); // Columna 10 | |||
| boolean escaner = getBooleanCellValue(row.getCell(10)); // Columna 11 | |||
| // Leer la fecha de la columna correcta | |||
| Date fechaprog = getDateCellValue(row.getCell(11)); // Columna 12 | |||
| String tecnicosmt = getStringCellValue(row.getCell(12)); // Columna 13 | |||
| String estado = getStringCellValue(row.getCell(13)); // Columna 14 | |||
| Date fecharealizado = getDateCellValue(row.getCell(14)); // Columna 15 | |||
| // Insertar datos en la base de datos | |||
| try (PreparedStatement preparedStatement = connection.prepareStatement(query)) { | |||
| preparedStatement.setString(1, nomequipo); | |||
| preparedStatement.setString(2, area); | |||
| preparedStatement.setBoolean(3, monitor); | |||
| preparedStatement.setBoolean(4, teclado); | |||
| preparedStatement.setBoolean(5, mouse); | |||
| preparedStatement.setBoolean(6, regulador); | |||
| preparedStatement.setBoolean(7, cpu); | |||
| preparedStatement.setBoolean(8, impresora); | |||
| preparedStatement.setBoolean(9, miniprint); | |||
| preparedStatement.setBoolean(10, laptop); | |||
| preparedStatement.setBoolean(11, escaner); | |||
| // Manejo de fechas | |||
| if (fechaprog != null) { | |||
| preparedStatement.setDate(12, new java.sql.Date(fechaprog.getTime())); | |||
| } else { | |||
| preparedStatement.setNull(12, java.sql.Types.DATE); // Manejo de valor nulo | |||
| } | |||
| preparedStatement.setString(13, tecnicosmt); | |||
| preparedStatement.setString(14, estado); | |||
| preparedStatement.executeUpdate(); | |||
| } | |||
| } catch (Exception e) { | |||
| System.err.println("Error procesando la fila " + row.getRowNum() + ": " + e.getMessage()); | |||
| } | |||
| } | |||
| System.out.println("Datos insertados desde Excel con éxito en PLANANUAL."); | |||
| } catch (IOException e) { | |||
| System.err.println("Error al leer el archivo Excel: " + e.getMessage()); | |||
| } catch (SQLException e) { | |||
| System.err.println("Error al insertar datos en la BD: " + e.getMessage()); | |||
| } | |||
| } | |||
| // INSERTAR NUEVO EQUIPO INDIVIDUAL EN PLANANUAL | |||
| public void insertarNuevoEquipo(String nomequipo, String area, boolean monitor, boolean teclado, | |||
| boolean mouse, boolean regulador, boolean cpu, boolean impresora, | |||
| boolean miniprint, boolean laptop, boolean escaner, Date fechaprog, | |||
| String tecnicosmt, String estado, Integer mesId) { | |||
| String query = "INSERT INTO PLANANUAL (NOMEQUIPO, AREA, MONITOR, TECLADO,MOUSE, REGULADOR,\n" + | |||
| "CPU, IMPRESORA, MINIPRINT, LAPTOP, ESCANER, FECHAPROG,\n" + | |||
| "TECNICOSMT, ESTADO, MESID)\n" + | |||
| "VALUES (?, ?,\n" + | |||
| "?, ?, ?, ?, ?, ?, ?, ?, ?,\n" + | |||
| "?, ?, ?, ?)"; | |||
| try (Connection conn = getMysqlConnection(); | |||
| PreparedStatement stmt = conn.prepareStatement(query)) { | |||
| stmt.setString(1, nomequipo); | |||
| stmt.setString(2, area); | |||
| stmt.setBoolean(3, monitor); | |||
| stmt.setBoolean(4, teclado); | |||
| stmt.setBoolean(5, mouse); | |||
| stmt.setBoolean(6, regulador); | |||
| stmt.setBoolean(7, cpu); | |||
| stmt.setBoolean(8, impresora); | |||
| stmt.setBoolean(9, miniprint); | |||
| stmt.setBoolean(10, laptop); | |||
| stmt.setBoolean(11, escaner); | |||
| // Manejo de fechas | |||
| if (fechaprog != null) { | |||
| stmt.setDate(12, new java.sql.Date(fechaprog.getTime())); | |||
| } else { | |||
| stmt.setNull(12, java.sql.Types.DATE); // Manejo de valor nulo | |||
| } | |||
| stmt.setString(13, tecnicosmt); | |||
| stmt.setString(14, estado); | |||
| stmt.setInt(15, mesId); | |||
| stmt.executeUpdate(); | |||
| } catch (SQLException e) { | |||
| System.err.println("Error al insertar nuevo equipo en PLANANUAL: " + e.getMessage()); | |||
| } | |||
| } | |||
| // Método auxiliar para obtener un valor de tipo Date de una celda | |||
| private Date getDateCellValue(Cell cell) { | |||
| if (cell != null) { | |||
| switch (cell.getCellType()) { | |||
| case NUMERIC: | |||
| return new Date(cell.getDateCellValue().getTime()); // Retorna la fecha directamente | |||
| case STRING: | |||
| try { | |||
| return Date.valueOf(LocalDate.parse(cell.getStringCellValue().trim())); // Asume formato ISO | |||
| } catch (Exception e) { | |||
| System.err.println("No se puede convertir la cadena a fecha: " + cell.getStringCellValue()); | |||
| } | |||
| break; | |||
| case BLANK: | |||
| return null; // Devuelve null si la celda está vacía | |||
| default: | |||
| System.err.println("Tipo de celda inesperado en la fila " + cell.getRowIndex()); | |||
| break; | |||
| } | |||
| } | |||
| return null; // Retorna null si no se puede obtener una fecha | |||
| } | |||
| // Método auxiliar para obtener un valor de tipo String de una celda | |||
| private String getStringCellValue(Cell cell) { | |||
| if (cell != null) { | |||
| switch (cell.getCellType()) { | |||
| case STRING: | |||
| return cell.getStringCellValue().trim(); | |||
| case NUMERIC: | |||
| return String.valueOf((int) cell.getNumericCellValue()); // Convierte el número a cadena | |||
| default: | |||
| return ""; // Devuelve cadena vacía si la celda no es de tipo STRING o NUMERIC | |||
| } | |||
| } | |||
| return ""; // Devuelve cadena vacía si la celda es nula | |||
| } | |||
| // Método auxiliar para obtener un valor de tipo boolean de una celda | |||
| private boolean getBooleanCellValue(Cell cell) { | |||
| if (cell != null) { | |||
| switch (cell.getCellType()) { | |||
| case NUMERIC: | |||
| return cell.getNumericCellValue() != 0; // Considera 0 como false, cualquier otro número como true | |||
| case BOOLEAN: | |||
| return cell.getBooleanCellValue(); | |||
| case STRING: | |||
| return Boolean.parseBoolean(cell.getStringCellValue().trim()); // Conversión de string a boolean | |||
| default: | |||
| return false; // Valor por defecto | |||
| } | |||
| } | |||
| return false; // Valor por defecto si la celda es nula | |||
| } | |||
| /* ----------------Actualizar los detalles del del mantenimiento por ID ---------------- */ | |||
| public boolean actualizarPlanAnual(int planAnualId, String nombreEquipo) { | |||
| String sql = "UPDATE PLANANUAL SET NOMEQUIPO=? WHERE PLANANUALID=?"; | |||
| try (Connection conn = getMysqlConnection(); | |||
| PreparedStatement stmt = conn.prepareStatement(sql)) { | |||
| stmt.setString(1, nombreEquipo); | |||
| stmt.setInt(2, planAnualId); | |||
| return stmt.executeUpdate() > 0; | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| return false; | |||
| } | |||
| } | |||
| public boolean actualizarMantenimiento(int mantenimientoId, int tipoId, String departamentoId, int empleadoId, LocalDate fechaRealizado, String nombreEquipo, String firmausuario, String firmasmt) { | |||
| String sql = "UPDATE MANTENIMIENTOS SET TIPOMANTID=?, DEPARTAMENTOID=?, EMPLEADOID=?, FECHA=?, NOMBREEQUIPO=?, FIRMAUSUARIO=?, FIRMASMT=? WHERE MANTENIMIENTOID=?"; | |||
| try (Connection conn = getMysqlConnection(); | |||
| PreparedStatement stmt = conn.prepareStatement(sql)) { | |||
| stmt.setInt(1, tipoId); // tipoId es int | |||
| stmt.setString(2, departamentoId); // departamentoId es String | |||
| stmt.setInt(3, empleadoId); // empleadoId es int | |||
| stmt.setDate(4, fechaRealizado != null ? Date.valueOf(fechaRealizado) : null); | |||
| stmt.setString(5, nombreEquipo); | |||
| if (firmausuario != null) { | |||
| stmt.setString(6, firmausuario); | |||
| } else { | |||
| stmt.setNull(6, Types.VARCHAR); | |||
| } | |||
| if (firmasmt != null) { | |||
| stmt.setString(7, firmasmt); | |||
| } else { | |||
| stmt.setNull(7, Types.VARCHAR); | |||
| } | |||
| stmt.setInt(8, mantenimientoId); | |||
| return stmt.executeUpdate() > 0; | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| return false; | |||
| } | |||
| } | |||
| /* ----------------Actualizar los detalles del hardaware por ID ---------------- */ | |||
| public boolean actualizarHardwareDetalle(HardwareDetalle detalle) { | |||
| String sql = "UPDATE HARDWAREDET SET MODELO=?, NUMSERIE=?, PLACA=? WHERE HARDWAREDETID=?"; | |||
| try (Connection conn = getMysqlConnection(); | |||
| PreparedStatement stmt = conn.prepareStatement(sql)) { | |||
| stmt.setString(1, detalle.getModelo()); | |||
| stmt.setString(2, detalle.getNumSerie()); | |||
| stmt.setString(3, detalle.getPlaca()); | |||
| stmt.setInt(4, detalle.getHardwareDetId()); | |||
| return stmt.executeUpdate() > 0; | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| return false; | |||
| } | |||
| } | |||
| /* ----------------Actualizar las actualizaciones de seguridad por ID ---------------- */ | |||
| public boolean actualizarActualizacionSeg(ActualizacioneSeguridadModel actualizacion) { | |||
| String sql = "UPDATE ACTUALIZACIONESSEG SET OTRASACTUALIZACIONES=? WHERE ACTUALIZACIONSEGID=?"; | |||
| try (Connection conn = getMysqlConnection(); | |||
| PreparedStatement stmt = conn.prepareStatement(sql)) { | |||
| stmt.setString(1, actualizacion.getOtrasactualizaciones()); | |||
| stmt.setInt(2, actualizacion.getActualizacionsegId()); | |||
| return stmt.executeUpdate() > 0; | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| return false; | |||
| } | |||
| } | |||
| /* ---------------- Insertar en bitacora ---------------- */ | |||
| public boolean insertarBitacora(int mantenimientoid, String usuarioid, LocalDate fechora, String motivo) { | |||
| String query = "INSERT INTO BITACORACTUALIZACIONES (MANTENIMIENTOID, USUARIOID, FECHORA, MOTIVO) VALUES (?, ?, ?, ?)"; | |||
| try (Connection conn = getMysqlConnection(); | |||
| PreparedStatement stmt = conn.prepareStatement(query)) { | |||
| stmt.setInt(1, mantenimientoid); | |||
| stmt.setString(2, usuarioid); | |||
| stmt.setDate(3, fechora != null ? Date.valueOf(fechora) : null); | |||
| stmt.setString(4, motivo); | |||
| return stmt.executeUpdate() > 0; | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| return false; | |||
| } | |||
| } | |||
| /* ---------------- Insertar en bitacora de eliminacion de equipos ---------------- */ | |||
| public boolean insertarBitacoraEliminacion(int plananualid, String usuarioid, LocalDate fechora, String motivo) { | |||
| String query = "INSERT INTO BITACORAELIMINACIONES (PLANANUALID, USUARIOID, FECHAHORA, MOTIVO) VALUES (?, ?, ?, ?)"; | |||
| try (Connection conn = getMysqlConnection(); | |||
| PreparedStatement stmt = conn.prepareStatement(query)) { | |||
| stmt.setInt(1, plananualid); | |||
| stmt.setString(2, usuarioid); | |||
| stmt.setDate(3, fechora != null ? Date.valueOf(fechora) : null); | |||
| stmt.setString(4, motivo); | |||
| return stmt.executeUpdate() > 0; | |||
| } catch (SQLException e) { | |||
| e.printStackTrace(); | |||
| return false; | |||
| } | |||
| } | |||
| /* ---------------- Eliminar equipo de PLAN ANUAL ---------------- */ | |||
| public void eliminarEquipoPlanAnual(int planAnualId) { | |||
| String sql = "DELETE FROM PLANANUAL WHERE PLANANUALID = ?"; | |||
| try (Connection conn = getMysqlConnection(); | |||
| PreparedStatement stmt = conn.prepareStatement(sql)) { | |||
| stmt.setInt(1, planAnualId); | |||
| int rowsAffected = stmt.executeUpdate(); | |||
| if (rowsAffected > 0) { | |||
| System.out.println(planAnualId + " eliminado correctamente."); | |||
| } else { | |||
| System.out.println("No se encontró el equipo con ID: " + planAnualId); | |||
| } | |||
| } catch (SQLException e) { | |||
| System.err.println("Error al eliminar el equipo de PLANANUAL: " + e.getMessage()); | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,48 @@ | |||
| package mx.gob.jumapacelaya.services; | |||
| import com.vaadin.flow.component.notification.Notification; | |||
| import jakarta.activation.DataSource; | |||
| import jakarta.mail.internet.MimeMessage; | |||
| import jakarta.mail.util.ByteArrayDataSource; | |||
| import mx.gob.jumapacelaya.models.Usuario; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.core.io.ClassPathResource; | |||
| import org.springframework.core.io.InputStreamResource; | |||
| import org.springframework.mail.SimpleMailMessage; | |||
| import org.springframework.mail.javamail.JavaMailSender; | |||
| import org.springframework.mail.javamail.MimeMailMessage; | |||
| import org.springframework.mail.javamail.MimeMessageHelper; | |||
| import org.springframework.stereotype.Service; | |||
| import java.io.File; | |||
| import java.io.InputStream; | |||
| @Service | |||
| public class EmailService { | |||
| @Autowired | |||
| private JavaMailSender mailSender; | |||
| public void enviarCorreo(String destinatario, String asunto, String cuerpo, String imagePath) { | |||
| try { | |||
| MimeMessage mensaje = mailSender.createMimeMessage(); | |||
| MimeMessageHelper helper = new MimeMessageHelper(mensaje, true); | |||
| helper.setTo(destinatario); | |||
| helper.setSubject(asunto); | |||
| helper.setFrom("noreply@jumapacelaya.gob.mx"); | |||
| helper.setText(cuerpo, true); | |||
| ClassPathResource imgResource = new ClassPathResource(imagePath); | |||
| helper.addInline("image_id", imgResource); | |||
| mailSender.send(mensaje); | |||
| System.out.println("Correo enviado con imagen exitosamente"); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| throw new RuntimeException("Error al enviar el correo: " + e.getMessage()); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,46 @@ | |||
| package mx.gob.jumapacelaya.services; | |||
| import mx.gob.jumapacelaya.models.CustomUserDetails; | |||
| import org.springframework.ldap.core.LdapTemplate; | |||
| import org.springframework.ldap.filter.EqualsFilter; | |||
| import org.springframework.stereotype.Service; | |||
| import javax.naming.NamingException; | |||
| import javax.naming.directory.Attributes; | |||
| import javax.naming.directory.SearchControls; | |||
| import java.util.List; | |||
| @Service | |||
| public class LdapService { | |||
| private final LdapTemplate ldapTemplate; | |||
| public LdapService(LdapTemplate ldapTemplate) { | |||
| this.ldapTemplate = ldapTemplate; | |||
| } | |||
| public CustomUserDetails getUserDetails(String username) { | |||
| EqualsFilter filter = new EqualsFilter("sAMAccountName", username); | |||
| SearchControls searchControls = new SearchControls(); | |||
| searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); | |||
| searchControls.setReturningAttributes(new String[]{"givenName", "sn", "mail"}); | |||
| searchControls.setReturningObjFlag(true); | |||
| List<CustomUserDetails> result = ldapTemplate.search("", filter.encode(), searchControls, (Attributes attrs) -> { | |||
| String firstName = getAttribute(attrs, "givenName"); | |||
| String lastName = getAttribute(attrs, "sn"); | |||
| String email = getAttribute(attrs, "mail"); | |||
| return new CustomUserDetails(username, firstName, lastName, email, null, null); // Ajustar los últimos dos parámetros si es necesario | |||
| }); | |||
| return result.isEmpty() ? null : result.get(0); | |||
| } | |||
| private String getAttribute(Attributes attributes, String attributeName) { | |||
| try { | |||
| return attributes.get(attributeName) != null ? attributes.get(attributeName).get().toString(): null; | |||
| } catch (NamingException e) { | |||
| return null; | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,41 @@ | |||
| package mx.gob.jumapacelaya.services; | |||
| import net.sf.jasperreports.engine.JasperExportManager; | |||
| import net.sf.jasperreports.engine.JasperFillManager; | |||
| import net.sf.jasperreports.engine.JasperPrint; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Service; | |||
| import java.io.InputStream; | |||
| import java.sql.Connection; | |||
| import java.sql.DriverManager; | |||
| import java.util.Map; | |||
| @Service | |||
| public class ReportService { | |||
| @Value("${db.url}") | |||
| private String dbUrl; | |||
| @Value("${db.user}") | |||
| private String dbUser; | |||
| @Value("${db.pass}") | |||
| private String dbPass; | |||
| public byte[] generarReporte(String nombreReporte, Map<String, Object> parametros) throws Exception { | |||
| InputStream logo = getClass().getResourceAsStream("/META-INF/resources/images/LOGO_24'27.png"); | |||
| parametros.put("logo", logo); | |||
| InputStream firmaGcia = getClass().getResourceAsStream("/META-INF/resources/images/FirmaGerenteTI.png"); | |||
| parametros.put("firmaGcia", firmaGcia); | |||
| InputStream jasperStream = getClass().getResourceAsStream("/META-INF/resources/reportes/" + nombreReporte + ".jasper"); | |||
| if (jasperStream == null) { | |||
| throw new IllegalArgumentException("No se encontro el archivo del reporte: " + nombreReporte); | |||
| } | |||
| try (Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPass)) { | |||
| JasperPrint jasperPrint = JasperFillManager.fillReport(jasperStream, parametros, conn); | |||
| return JasperExportManager.exportReportToPdf(jasperPrint); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,30 @@ | |||
| package mx.gob.jumapacelaya.services; | |||
| import com.vaadin.flow.spring.security.AuthenticationContext; | |||
| import org.springframework.security.core.Authentication; | |||
| import org.springframework.security.core.context.SecurityContextHolder; | |||
| import org.springframework.stereotype.Component; | |||
| @Component | |||
| public class SecurityService { | |||
| private final AuthenticationContext authenticationContext; | |||
| public SecurityService(AuthenticationContext authenticationContext) { | |||
| this.authenticationContext = authenticationContext; | |||
| } | |||
| public String getAuthenticatedUser() { | |||
| Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | |||
| if (authentication != null) { | |||
| return authentication.getName(); | |||
| } | |||
| return null; | |||
| } | |||
| public void logout() { | |||
| authenticationContext.logout(); | |||
| } | |||
| } | |||
| @ -0,0 +1,89 @@ | |||
| package mx.gob.jumapacelaya.services; | |||
| import com.vaadin.flow.server.VaadinService; | |||
| import mx.gob.jumapacelaya.api.RedmineClient; | |||
| import mx.gob.jumapacelaya.services.SecurityService; | |||
| import mx.gob.jumapacelaya.models.CustomUserDetails; | |||
| import mx.gob.jumapacelaya.models.RedmineUser; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.stereotype.Service; | |||
| @Service | |||
| public class UserService { | |||
| private final SecurityService securityService; | |||
| private final RedmineClient redmineClient; | |||
| private static final Logger logger = LoggerFactory.getLogger(UserService.class); | |||
| private final LdapService ldpaService; | |||
| public UserService(SecurityService securityService, RedmineClient redmineClient, LdapService ldpaService) { | |||
| this.securityService = securityService; | |||
| this.redmineClient = redmineClient; | |||
| this.ldpaService = ldpaService; | |||
| } | |||
| public RedmineUser getAuthenticatedRedmineUser() { | |||
| try { | |||
| String username = securityService.getAuthenticatedUser(); | |||
| logger.info("Usuario autenticado: " + username); | |||
| if (username != null) { | |||
| RedmineUser user = redmineClient.getUserByUsername(username); | |||
| if (user == null) { | |||
| CustomUserDetails userDetails = ldpaService.getUserDetails(username); | |||
| if (userDetails != null) { | |||
| if (userDetails.getEmail() == null || userDetails.getEmail().isEmpty()) { | |||
| logger.error("El usuario: " + username + " no tiene correo electronico."); | |||
| return null; | |||
| } | |||
| RedmineUser newUser = RedmineClient.createRedmineUser( | |||
| username, | |||
| userDetails.getFirstName(), | |||
| userDetails.getLastName(), | |||
| userDetails.getEmail() | |||
| ); | |||
| if (newUser != null) { | |||
| logger.info("Usuario creado en Redmine: " + newUser); | |||
| return newUser; | |||
| } else { | |||
| logger.error("Error al crear el usuario en Redmine"); | |||
| } | |||
| } else { | |||
| logger.error("No se encontraron detalles del usuario en LDAP"); | |||
| } | |||
| } else { | |||
| logger.info("Usuario autenticado en Redmine: " + user); | |||
| } | |||
| return user; | |||
| } | |||
| } catch (Exception e) { | |||
| logger.error("Error al obtener al usuario autenticado en Redmine", e); | |||
| } | |||
| return null; | |||
| } | |||
| public RedmineUser getRedmineUser() { | |||
| RedmineUser userclient = (RedmineUser) VaadinService.getCurrentRequest().getWrappedSession().getAttribute("myaccount"); | |||
| if (userclient == null) { | |||
| RedmineUser user = getAuthenticatedRedmineUser(); | |||
| if (user != null) { | |||
| RedmineUser myAccount = redmineClient.getMyAccount(user.getLogin()); | |||
| if (myAccount != null && !myAccount.getKey().isEmpty()) { | |||
| userclient = myAccount; | |||
| VaadinService.getCurrentRequest().getWrappedSession().setAttribute("myaccount", myAccount); | |||
| } else { | |||
| // Crear un nuevo usuario si no existe | |||
| myAccount = RedmineClient.createRedmineUser(user.getLogin(), user.getFirstname(), user.getLastname(), user.getMail()); | |||
| if (myAccount != null && !myAccount.getKey().isEmpty()) { | |||
| userclient = myAccount; | |||
| VaadinService.getCurrentRequest().getWrappedSession().setAttribute("myaccount", myAccount); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| return userclient; | |||
| } | |||
| } | |||
| @ -0,0 +1,223 @@ | |||
| package mx.gob.jumapacelaya.ui; | |||
| import com.vaadin.flow.component.UI; | |||
| import com.vaadin.flow.component.button.Button; | |||
| import com.vaadin.flow.component.button.ButtonVariant; | |||
| import com.vaadin.flow.component.dependency.CssImport; | |||
| import com.vaadin.flow.component.dialog.Dialog; | |||
| import com.vaadin.flow.component.grid.Grid; | |||
| import com.vaadin.flow.component.grid.GridVariant; | |||
| import com.vaadin.flow.component.html.H3; | |||
| import com.vaadin.flow.component.html.Span; | |||
| import com.vaadin.flow.component.icon.Icon; | |||
| import com.vaadin.flow.component.icon.VaadinIcon; | |||
| import com.vaadin.flow.component.notification.Notification; | |||
| import com.vaadin.flow.component.notification.NotificationVariant; | |||
| import com.vaadin.flow.component.orderedlayout.FlexComponent; | |||
| import com.vaadin.flow.component.orderedlayout.HorizontalLayout; | |||
| import com.vaadin.flow.component.orderedlayout.VerticalLayout; | |||
| import com.vaadin.flow.component.richtexteditor.RichTextEditor; | |||
| import com.vaadin.flow.data.renderer.ComponentRenderer; | |||
| import com.vaadin.flow.router.PageTitle; | |||
| import com.vaadin.flow.router.Route; | |||
| import jakarta.annotation.security.PermitAll; | |||
| import mx.gob.jumapacelaya.api.RedmineClient; | |||
| import mx.gob.jumapacelaya.api.ServerProperties; | |||
| import mx.gob.jumapacelaya.models.ActividadDiaria; | |||
| import mx.gob.jumapacelaya.models.RedmineUser; | |||
| import mx.gob.jumapacelaya.models.Ticket; | |||
| import mx.gob.jumapacelaya.services.LdapService; | |||
| import mx.gob.jumapacelaya.services.UserService; | |||
| import java.io.IOException; | |||
| import java.text.SimpleDateFormat; | |||
| import java.time.LocalDate; | |||
| import java.time.format.DateTimeFormatter; | |||
| import java.util.*; | |||
| @PermitAll | |||
| @PageTitle("Actividades Diarias") | |||
| @Route(value = "actdiaria", layout = MainLayout.class) | |||
| @CssImport("./themes/sistema-mantenimiento/styles.css") | |||
| public class ActDiariaView extends VerticalLayout { | |||
| private final RedmineClient redmineClient; | |||
| private final UserService userService; | |||
| private final Grid<Ticket> grid; | |||
| public ActDiariaView(ServerProperties properties, RedmineClient redmineClient, UserService userService) { | |||
| this.userService = userService; | |||
| this.redmineClient = redmineClient; | |||
| this.grid = new Grid<>(Ticket.class, false); | |||
| // Configuración de columnas del grid | |||
| grid.addColumn(Ticket::getId).setHeader("No.") | |||
| .setAutoWidth(true).setFlexGrow(0).setSortable(true); | |||
| grid.addColumn(Ticket::getType) | |||
| .setHeader("Tipo") | |||
| .setAutoWidth(true); | |||
| grid.addColumn(Ticket::getSubject).setHeader("Asunto") | |||
| .setWidth("25em"); | |||
| grid.addColumn(createStatusRender()).setHeader("Estado"); | |||
| grid.addColumn(ticket -> { | |||
| Date date = ticket.getDateCreate(); | |||
| if (date != null) { | |||
| SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy"); | |||
| return formatter.format(date); | |||
| } else { | |||
| return ""; | |||
| } | |||
| }).setHeader("Fecha creacion").setAutoWidth(true); | |||
| grid.addColumn(ticket -> { | |||
| LocalDate fechaCierre = ticket.getDateClose(); | |||
| if (fechaCierre != null) { | |||
| DateTimeFormatter formatterClose = DateTimeFormatter.ofPattern("dd/MM/yyyy"); | |||
| return fechaCierre.format(formatterClose); | |||
| } else { | |||
| return ""; | |||
| } | |||
| }).setHeader("Fecha cierre").setAutoWidth(true); | |||
| //grid.addColumn(ticket -> ticket.tiempoEst(ticket.getTrackerId())).setHeader("Tiempo estimado de atencion").setAutoWidth(false); | |||
| grid.addComponentColumn(ticket -> { | |||
| Button btnVer = new Button(new Icon(VaadinIcon.EYE)); | |||
| btnVer.addClickListener(event -> showDescription(ticket)); | |||
| btnVer.getStyle().set("color", "#A02142"); | |||
| return btnVer; | |||
| }).setAutoWidth(true); | |||
| grid.addColumn(buttonTicketComponentRenderer()).setAutoWidth(true); | |||
| grid.addThemeVariants(GridVariant.LUMO_WRAP_CELL_CONTENT); | |||
| grid.getStyle().set("opacity", "0.8"); | |||
| grid.setAllRowsVisible(false); | |||
| grid.setSizeFull(); | |||
| // Ajustar tamaño del Grid y Layout | |||
| grid.setSizeFull(); | |||
| setSizeFull(); | |||
| add(grid); | |||
| //expand(grid); | |||
| setMargin(false); | |||
| loadTickets(); | |||
| } | |||
| private void loadTickets() { | |||
| try { | |||
| List<Ticket> tickets = redmineClient.getTickets(userService.getRedmineUser(), true); | |||
| List<Ticket> filteredTickets = tickets.stream() | |||
| .filter(ticket -> ticket.getTrackerId() == 13 || ticket.getTrackerId() == 14) | |||
| .toList(); | |||
| grid.setItems(filteredTickets); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| // Manejo de error al cargar los tickets | |||
| } | |||
| } | |||
| private ComponentRenderer<Span, Ticket> createStatusRender() { | |||
| return new ComponentRenderer<>(ticket -> { | |||
| // Creamos un Span para mostrar el estado | |||
| Span span = new Span(ticket.getStatus()); | |||
| // Estilos basados en el estado del ticket | |||
| switch (ticket.getStatus().toLowerCase()) { | |||
| case "análisis": | |||
| span.getElement().getStyle().set("color","orange"); | |||
| break; | |||
| case "desarrollo": | |||
| span.getElement().getStyle().set("color","blue"); | |||
| break; | |||
| case "rechazada": | |||
| span.getElement().getStyle().set("color","red"); | |||
| break; | |||
| case "cerrada": | |||
| span.getElement().getStyle().set("color","grey"); | |||
| break; | |||
| case "solicitado": | |||
| span.getElement().getStyle().set("color","purple"); | |||
| break; | |||
| case "qa": | |||
| span.getElement().getStyle().set("color","#C21DF2"); | |||
| break; | |||
| default: | |||
| span.getElement().getStyle().set("color","green"); | |||
| break; | |||
| } | |||
| return span; | |||
| }); | |||
| } | |||
| public ComponentRenderer<Button, Ticket> buttonTicketComponentRenderer() { | |||
| return new ComponentRenderer<>(ticket -> { | |||
| Button button = new Button(new Icon(VaadinIcon.EDIT) ); | |||
| button.getStyle().set("color", "#A02142"); | |||
| button.addClickListener(e -> { | |||
| RedmineUser currentUser = userService.getRedmineUser(); | |||
| if (ticket.getTrackerId() == 13) { | |||
| UI.getCurrent().navigate("mantenimiento"); | |||
| } else if (ticket.getTrackerId() == 14) { | |||
| cerrarTicket(ticket, currentUser); | |||
| } else { | |||
| Notification.show("El ticket no es de tipo Mantenimiento o Actividad."); | |||
| } | |||
| }); | |||
| return button; | |||
| }); | |||
| } | |||
| public void cerrarTicket(Ticket ticket, RedmineUser user) { | |||
| try { | |||
| //Llamar al metodo para cambiar el estado del ticket | |||
| redmineClient.closeTicket(ticket.getId(), user); | |||
| Notification.show("El ticket " + ticket.getId() + " se ha cerrado exitosamente.", 3000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_SUCCESS); | |||
| UI.getCurrent().getPage().executeJs("setTimeout(() => { window.location.reload(); }, 3000);"); | |||
| } catch (IOException | InterruptedException e) { | |||
| e.printStackTrace(); | |||
| Notification.show("Error al cerrar el ticket " + ticket.getId()); | |||
| } | |||
| } | |||
| // Metodo para mostrar las descripciones en un componente Dialog | |||
| private void showDescription(Ticket ticket) { | |||
| Dialog dialog = new Dialog(); | |||
| dialog.getElement().setAttribute("arial-label", "Add note"); | |||
| dialog.setMaxHeight("500px"); | |||
| dialog.setMaxWidth("1100px"); | |||
| RichTextEditor textEditor = new RichTextEditor(); | |||
| textEditor.setValue(ticket.getDescription()); | |||
| textEditor.setReadOnly(true); | |||
| Button closeButton = new Button("Cerrar", new Icon(VaadinIcon.CLOSE)); | |||
| closeButton.addThemeVariants(ButtonVariant.LUMO_ERROR); | |||
| closeButton.addClickListener(e -> dialog.close()); | |||
| HorizontalLayout buttonLayout = new HorizontalLayout(closeButton); | |||
| buttonLayout.setWidthFull(); | |||
| buttonLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.END); | |||
| buttonLayout.add(closeButton); | |||
| dialog.add(textEditor, buttonLayout); | |||
| dialog.open(); | |||
| } | |||
| } | |||
| @ -0,0 +1,607 @@ | |||
| package mx.gob.jumapacelaya.ui; | |||
| import java.io.ByteArrayInputStream; | |||
| import java.time.LocalDate; | |||
| import java.time.format.DateTimeFormatter; | |||
| import java.util.Base64; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import com.vaadin.flow.component.UI; | |||
| import com.vaadin.flow.component.html.Anchor; | |||
| import com.vaadin.flow.server.StreamRegistration; | |||
| import com.vaadin.flow.server.StreamResource; | |||
| import mx.gob.jumapacelaya.services.ReportService; | |||
| import org.springframework.security.core.Authentication; | |||
| import org.springframework.security.core.context.SecurityContextHolder; | |||
| import org.vaadin.lineawesome.LineAwesomeIcon; | |||
| import com.vaadin.flow.component.button.Button; | |||
| import com.vaadin.flow.component.combobox.ComboBox; | |||
| import com.vaadin.flow.component.dependency.CssImport; | |||
| import com.vaadin.flow.component.dialog.Dialog; | |||
| import com.vaadin.flow.component.grid.GridVariant; | |||
| import com.vaadin.flow.component.gridpro.GridPro; | |||
| import com.vaadin.flow.component.html.H3; | |||
| import com.vaadin.flow.component.html.Image; | |||
| import com.vaadin.flow.component.html.Span; | |||
| import com.vaadin.flow.component.icon.Icon; | |||
| import com.vaadin.flow.component.icon.VaadinIcon; | |||
| import com.vaadin.flow.component.notification.Notification; | |||
| import com.vaadin.flow.component.notification.NotificationVariant; | |||
| import com.vaadin.flow.component.orderedlayout.HorizontalLayout; | |||
| import com.vaadin.flow.component.orderedlayout.VerticalLayout; | |||
| import com.vaadin.flow.component.textfield.TextField; | |||
| import com.vaadin.flow.router.BeforeEnterEvent; | |||
| import com.vaadin.flow.router.BeforeEnterObserver; | |||
| import com.vaadin.flow.router.PageTitle; | |||
| import com.vaadin.flow.router.Route; | |||
| import de.f0rce.signaturepad.SignaturePad; | |||
| import jakarta.annotation.security.PermitAll; | |||
| import mx.gob.jumapacelaya.models.ActualizacioneSeguridadModel; | |||
| import mx.gob.jumapacelaya.models.DepartamentosModel; | |||
| import mx.gob.jumapacelaya.models.DetalleMantenimientoModel; | |||
| import mx.gob.jumapacelaya.models.HardwareDetalle; | |||
| import mx.gob.jumapacelaya.models.TiposMantenimiento; | |||
| import mx.gob.jumapacelaya.models.Usuario; | |||
| import mx.gob.jumapacelaya.services.DatabaseService; | |||
| import mx.gob.jumapacelaya.services.SecurityService; | |||
| @PageTitle("Detalles del mantenimiento") | |||
| @Route(value = "detalles", layout = MainLayout.class) | |||
| @PermitAll | |||
| @CssImport("./themes/sistema-mantenimiento/styles.css") | |||
| public class DetallesMantView extends VerticalLayout implements BeforeEnterObserver { | |||
| private H3 id; | |||
| private VerticalLayout mainLayout; | |||
| private HorizontalLayout headerLayout; | |||
| private HorizontalLayout layout2; | |||
| private HorizontalLayout layout3; | |||
| private HorizontalLayout botonesLayout; | |||
| private HorizontalLayout fechasLayout; | |||
| private TextField txtId; | |||
| private TextField txtEquipo; | |||
| private ComboBox<TiposMantenimiento> cbTipo; | |||
| private TextField txtFecha; | |||
| private TextField txtFechaProgramada; | |||
| private TextField txtSituacion; | |||
| private ComboBox<Usuario> cbUsuario; | |||
| private ComboBox<DepartamentosModel> cbDepartamento; | |||
| private GridPro<HardwareDetalle> gridHardware; | |||
| private GridPro<ActualizacioneSeguridadModel> gridActualizaciones; | |||
| private Button btnEditar; | |||
| private Button btnEditarFirmas; | |||
| private Button btnImprimirRepo; | |||
| private Button btnCancelar; | |||
| private Button btnGuardar; | |||
| private int planAnualIdActual; | |||
| private int mantenimientoIdActual; | |||
| private Dialog confirmDialog; | |||
| private SignaturePad userSignPad; | |||
| private SignaturePad smtSignPad; | |||
| private SignaturePad gciaSignPad; | |||
| private final HorizontalLayout firmasLAyout = new HorizontalLayout(); | |||
| private Image firmaUsuarioImg; | |||
| private Image firmaSmtImg; | |||
| private Image firmaGciaImg; | |||
| private VerticalLayout userSignLayout; | |||
| private VerticalLayout smtSignLayout; | |||
| private VerticalLayout gciaSignLayout; | |||
| private final SecurityService securityService; | |||
| private final DatabaseService service; | |||
| private final ReportService reportService; | |||
| public DetallesMantView(SecurityService securityService, DatabaseService service, ReportService reportService) { | |||
| this.service = service; | |||
| this.securityService = securityService; | |||
| this.reportService = reportService; | |||
| setPadding(true); | |||
| mainLayout = new VerticalLayout(); | |||
| mainLayout.setHeightFull(); | |||
| mainLayout.getStyle() | |||
| .set("box-shadow","0 4px 8px rgba(0,0,0,0.2)") | |||
| .set("border-radius", "12px") | |||
| .set("background-color", "white") | |||
| .set("padding", "1rem") | |||
| .set("margin", "1rem auto"); | |||
| id = new H3(); | |||
| headerLayout = new HorizontalLayout(); | |||
| headerLayout.setWidthFull(); | |||
| headerLayout.add(id); | |||
| cbTipo = new ComboBox<>("Tipo:"); | |||
| cbTipo.setItems(service.getTiposDeMantenimientos()); | |||
| cbTipo.setItemLabelGenerator(TiposMantenimiento::getNombre); | |||
| cbUsuario = new ComboBox<>("Usuario:"); | |||
| cbUsuario.setItems(service.getUsuarios()); | |||
| cbUsuario.setItemLabelGenerator(Usuario::getNombre); | |||
| cbDepartamento = new ComboBox<>("Area:"); | |||
| cbDepartamento.setItems(service.getDepartamentos()); | |||
| cbDepartamento.setItemLabelGenerator(DepartamentosModel::getNombre); | |||
| layout2 = new HorizontalLayout(); | |||
| layout2.setWidthFull(); | |||
| txtEquipo = new TextField("Equipo:"); | |||
| txtEquipo.setReadOnly(true); | |||
| cbTipo.setReadOnly(true); | |||
| layout2.add(txtEquipo,cbTipo); | |||
| fechasLayout = new HorizontalLayout(); | |||
| fechasLayout.setWidthFull(); | |||
| txtFecha = new TextField("Fecha realización:"); | |||
| txtFechaProgramada = new TextField("Fecha programada:"); | |||
| txtSituacion = new TextField("Situación:"); | |||
| txtFecha.setReadOnly(true); | |||
| txtFechaProgramada.setReadOnly(true); | |||
| txtSituacion.setReadOnly(true); | |||
| fechasLayout.add(txtFechaProgramada,txtFecha,txtSituacion); | |||
| layout3 = new HorizontalLayout(); | |||
| layout3.setWidthFull(); | |||
| cbUsuario.setReadOnly(true); | |||
| cbDepartamento.setReadOnly(true); | |||
| cbUsuario.setWidthFull(); | |||
| cbDepartamento.setWidthFull(); | |||
| layout3.add(cbUsuario,cbDepartamento); | |||
| // Grid que muestra los detalles del hardware | |||
| gridHardware = new GridPro<>(); | |||
| gridHardware.addColumn(item -> item.getDescripcion()) | |||
| .setHeader("Descripción"); | |||
| gridHardware.addEditColumn(HardwareDetalle::getNumSerie) | |||
| .text((item, newValue) -> item.setNumSerie(newValue)) | |||
| .setHeader("No. Serie") | |||
| .setEditorComponent(new TextField()); | |||
| gridHardware.addEditColumn(HardwareDetalle::getModelo) | |||
| .text((item, newValue) -> item.setModelo(newValue)) | |||
| .setHeader("Modelo") | |||
| .setEditorComponent(new TextField()); | |||
| gridHardware.addEditColumn(HardwareDetalle::getPlaca) | |||
| .text((item, newValue) -> item.setPlaca(newValue)) | |||
| .setHeader("Placa") | |||
| .setEditorComponent(new TextField()); | |||
| gridHardware.setWidthFull(); | |||
| gridHardware.setEditOnClick(false); | |||
| gridHardware.setHeight("250px"); | |||
| gridHardware.addThemeVariants(GridVariant.LUMO_ROW_STRIPES); | |||
| // Grid que muestra las actualizaciones de seguridad | |||
| gridActualizaciones = new GridPro<>(); | |||
| gridActualizaciones.addEditColumn(ActualizacioneSeguridadModel::getDescripcion) | |||
| .text((item, newValue) -> item.setDescripcion(newValue)) | |||
| .setHeader("Descripción") | |||
| .setEditorComponent(new TextField()); | |||
| gridActualizaciones.addEditColumn(ActualizacioneSeguridadModel::getOtrasactualizaciones) | |||
| .text((item, newValue) -> item.setOtrasactualizaciones(newValue)) | |||
| .setHeader("Otras Actualizaciones") | |||
| .setEditorComponent(new TextField()); | |||
| gridActualizaciones.setWidthFull(); | |||
| gridActualizaciones.setEditOnClick(false); | |||
| gridActualizaciones.setHeight("200px"); | |||
| gridActualizaciones.addThemeVariants(GridVariant.LUMO_ROW_STRIPES); | |||
| botonesLayout = new HorizontalLayout(); | |||
| botonesLayout.setWidthFull(); | |||
| botonesLayout.setJustifyContentMode(JustifyContentMode.CENTER); | |||
| btnEditar = new Button("Editar", new Icon(VaadinIcon.EDIT)); | |||
| btnImprimirRepo = new Button("Imprimir Reporte", new Icon(VaadinIcon.PRINT)); | |||
| btnEditarFirmas = new Button("Editar firmas", LineAwesomeIcon.SIGNATURE_SOLID.create()); | |||
| btnGuardar = new Button("Guardar", LineAwesomeIcon.SAVE_SOLID.create()); | |||
| btnCancelar = new Button("Cancelar", new Icon(VaadinIcon.CLOSE_CIRCLE_O)); | |||
| botonesLayout.add(btnEditar,btnEditarFirmas,btnImprimirRepo,btnGuardar,btnCancelar); | |||
| btnGuardar.setVisible(false); | |||
| btnGuardar.getStyle().set("background-color", "#008000"); | |||
| btnGuardar.getStyle().set("color", "white"); | |||
| btnCancelar.setVisible(false); | |||
| btnCancelar.getStyle().set("background-color", "red"); | |||
| btnCancelar.getStyle().set("color", "white"); | |||
| btnEditar.addClickListener(e -> { | |||
| txtEquipo.setReadOnly(false); | |||
| cbTipo.setReadOnly(false); | |||
| txtFecha.setReadOnly(false); | |||
| cbUsuario.setReadOnly(false); | |||
| cbDepartamento.setReadOnly(false); | |||
| btnImprimirRepo.setVisible(false); | |||
| btnEditar.setVisible(false); | |||
| btnGuardar.setVisible(true); | |||
| btnCancelar.setVisible(true); | |||
| btnEditarFirmas.setVisible(false); | |||
| gridHardware.setEditOnClick(true); | |||
| gridActualizaciones.setEditOnClick(true); | |||
| }); | |||
| btnEditarFirmas.addClickListener(e -> { | |||
| btnCancelar.setVisible(true); | |||
| btnGuardar.setVisible(true); | |||
| btnEditar.setVisible(false); | |||
| btnImprimirRepo.setVisible(false); | |||
| btnEditarFirmas.setVisible(false); | |||
| if (firmaUsuarioImg != null && firmaUsuarioImg.getParent().isPresent()) { | |||
| userSignLayout.replace(firmaUsuarioImg, userSignPad); | |||
| } | |||
| if (firmaSmtImg != null && firmaSmtImg.getParent().isPresent()) { | |||
| smtSignLayout.replace(firmaSmtImg, smtSignPad); | |||
| } | |||
| }); | |||
| btnCancelar.addClickListener(e -> { | |||
| txtEquipo.setReadOnly(true); | |||
| cbTipo.setReadOnly(true); | |||
| txtFecha.setReadOnly(true); | |||
| cbUsuario.setReadOnly(true); | |||
| cbDepartamento.setReadOnly(true); | |||
| btnImprimirRepo.setVisible(true); | |||
| btnEditar.setVisible(true); | |||
| btnGuardar.setVisible(false); | |||
| btnCancelar.setVisible(false); | |||
| btnEditarFirmas.setVisible(true); | |||
| gridHardware.setEditOnClick(false); | |||
| gridHardware.getEditor().cancel(); | |||
| gridActualizaciones.setEditOnClick(false); | |||
| gridActualizaciones.getEditor().cancel(); | |||
| if (firmaUsuarioImg != null && userSignPad.getParent().isPresent()) { | |||
| userSignLayout.replace(userSignPad, firmaUsuarioImg); | |||
| } | |||
| if (firmaSmtImg != null && smtSignPad.getParent().isPresent()) { | |||
| smtSignLayout.replace(smtSignPad, firmaSmtImg); | |||
| } | |||
| }); | |||
| btnImprimirRepo.addClickListener(e -> { | |||
| try { | |||
| // Prepara los parámetros para el reporte | |||
| Map<String, Object> parametros = new HashMap<>(); | |||
| parametros.put("PLAN_ID", planAnualIdActual); | |||
| // Genera el PDF | |||
| byte[] pdf = reportService.generarReporte("mantenimientoReport", parametros); | |||
| // Se crea el recurso para descarga | |||
| StreamResource resource = new StreamResource("reporte.pdf", () -> new ByteArrayInputStream(pdf)); | |||
| /*Anchor downloadLink = new Anchor(resource, "Descargar Reporte"); | |||
| downloadLink.setTarget("_blank"); | |||
| downloadLink.setId("descargar-reporte-link"); | |||
| add(downloadLink); | |||
| getUI().ifPresent(ui -> | |||
| ui.getPage().executeJs("document.getElementById('descargar-reporte-link').click();") | |||
| );*/ | |||
| StreamRegistration registration = UI.getCurrent().getSession().getResourceRegistry().registerResource(resource); | |||
| UI.getCurrent().getPage().executeJs("window.open('" + registration.getResourceUri().toString() + "','_blank')"); | |||
| } catch (Exception ex) { | |||
| Notification.show("Error al generar el reporte: " + ex.getMessage(), 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| ex.printStackTrace(); | |||
| } | |||
| }); | |||
| // Se dispara el dialogo de confirmacion | |||
| btnGuardar.addClickListener(e -> confirmDialog.open()); | |||
| // Dialogo de confirmación de actualización | |||
| confirmDialog = new Dialog(); | |||
| confirmDialog.setHeaderTitle("Actualizar Mantenimiento"); | |||
| TextField txtJustificacion = new TextField("Justificacion"); | |||
| txtJustificacion.setWidthFull(); | |||
| txtJustificacion.setRequired(true); | |||
| confirmDialog.add( | |||
| new VerticalLayout( | |||
| new Span("¿Estás seguro de que deseas actualizar el mantenimiento?"), | |||
| txtJustificacion | |||
| ) | |||
| ); | |||
| Button btnConfirmar = new Button("Actualizar", event -> { | |||
| String justificacion = txtJustificacion.getValue(); | |||
| if (justificacion.isEmpty()) { | |||
| txtJustificacion.setErrorMessage("Por favor, ingresa una justificación."); | |||
| txtJustificacion.setInvalid(true); | |||
| return; | |||
| } | |||
| txtJustificacion.setInvalid(false); | |||
| confirmDialog.close(); | |||
| Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | |||
| String usuarioId = authentication != null ? authentication.getName().toUpperCase() : "DESCONOCIDO"; | |||
| LocalDate fecha = LocalDate.now(); | |||
| service.insertarBitacora(mantenimientoIdActual, usuarioId, fecha, justificacion); | |||
| realizarActualizacion(); | |||
| txtJustificacion.clear(); | |||
| }); | |||
| Button btnCancelarDialog = new Button("Cancelar", event -> { | |||
| confirmDialog.close(); | |||
| txtEquipo.setReadOnly(true); | |||
| cbTipo.setReadOnly(true); | |||
| txtFecha.setReadOnly(true); | |||
| cbUsuario.setReadOnly(true); | |||
| cbDepartamento.setReadOnly(true); | |||
| btnImprimirRepo.setVisible(true); | |||
| btnEditar.setVisible(true); | |||
| btnGuardar.setVisible(false); | |||
| btnCancelar.setVisible(false); | |||
| gridHardware.setEditOnClick(false); | |||
| gridHardware.getEditor().cancel(); | |||
| if (firmaUsuarioImg != null && userSignPad.getParent().isPresent()) { | |||
| userSignLayout.replace(userSignPad, firmaUsuarioImg); | |||
| } | |||
| if (firmaSmtImg != null && smtSignPad.getParent().isPresent()) { | |||
| smtSignLayout.replace(smtSignPad, firmaSmtImg); | |||
| } | |||
| }); | |||
| HorizontalLayout dialogButtons = new HorizontalLayout(btnConfirmar, btnCancelarDialog); | |||
| confirmDialog.getFooter().add(dialogButtons); | |||
| addSignatureSection(); | |||
| mainLayout.add(headerLayout,layout2,fechasLayout,layout3,gridHardware,gridActualizaciones,firmasLAyout,botonesLayout); | |||
| add(mainLayout); | |||
| } | |||
| private void realizarActualizacion() { | |||
| boolean exito = true; | |||
| // Obtén los objetos seleccionados | |||
| TiposMantenimiento tipoSeleccionado = cbTipo.getValue(); | |||
| Usuario usuarioSeleccionado = cbUsuario.getValue(); | |||
| DepartamentosModel departamentoSeleccionado = cbDepartamento.getValue(); | |||
| int tipoId = tipoSeleccionado != null ? Integer.parseInt(tipoSeleccionado.getTipomantId()) : 0; | |||
| int empleadoId = usuarioSeleccionado != null ? Integer.parseInt(usuarioSeleccionado.getEmpleadoId()) : 0; | |||
| String departamentoId = departamentoSeleccionado != null ? departamentoSeleccionado.getDepartamentoId() : null; | |||
| // Fechas (corrige el campo) | |||
| DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); | |||
| LocalDate fechaProg = !txtFechaProgramada.getValue().isEmpty() ? LocalDate.parse(txtFechaProgramada.getValue(), formatter) : null; | |||
| LocalDate fechaRealizado = !txtFecha.getValue().isEmpty() ? LocalDate.parse(txtFecha.getValue(), formatter) : null; | |||
| // Obtener las firmas como en MantenimientoView | |||
| byte[] userSignatureBytes = userSignPad.getImageBase64(); | |||
| byte[] smtSignatureBytes = smtSignPad.getImageBase64(); | |||
| String userSignatureBase64 = (userSignatureBytes != null) ? Base64.getEncoder().encodeToString(userSignatureBytes) : null; | |||
| String smtSignatureBase64 = (smtSignatureBytes != null) ? Base64.getEncoder().encodeToString(smtSignatureBytes) : null; | |||
| // Si la firma está vacía, conserva la anterior | |||
| if (userSignatureBase64 == null || esFirmaVacia(userSignatureBase64)) { | |||
| userSignatureBase64 = service.getDetalleMantenimientoPorPlanAnualId(planAnualIdActual).getFirmaUser(); | |||
| } | |||
| if (smtSignatureBase64 == null || esFirmaVacia(smtSignatureBase64)) { | |||
| smtSignatureBase64 = service.getDetalleMantenimientoPorPlanAnualId(planAnualIdActual).getFirmaSmt(); | |||
| } | |||
| // ACTUALIZA PLANANUAL (nombre del equipo y fecha programada) | |||
| if (!service.actualizarPlanAnual(planAnualIdActual, txtEquipo.getValue())) { | |||
| exito = false; | |||
| } | |||
| // ACTUALIZA MANTENIMIENTOS (tipo, departamento, usuario, fecha realizado) | |||
| if (!service.actualizarMantenimiento( | |||
| mantenimientoIdActual, | |||
| tipoId, | |||
| departamentoId, | |||
| empleadoId, | |||
| fechaRealizado, | |||
| txtEquipo.getValue(), | |||
| userSignatureBase64, | |||
| smtSignatureBase64 | |||
| )) { | |||
| exito = false; | |||
| } | |||
| // ACTUALIZA HARDWARE (grid) | |||
| for (HardwareDetalle detalle : gridHardware.getListDataView().getItems().toList()) { | |||
| if (!service.actualizarHardwareDetalle(detalle)) { | |||
| exito = false; | |||
| } | |||
| } | |||
| // ACTUALIZA ACTUALIZACIONES DE SEGURIDAD (grid) | |||
| for (ActualizacioneSeguridadModel actualizacion : gridActualizaciones.getListDataView().getItems().toList()) { | |||
| if (!service.actualizarActualizacionSeg(actualizacion)) { | |||
| exito = false; | |||
| } | |||
| } | |||
| if (exito) { | |||
| Notification.show("Registros actualizados correctamente", 3000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_SUCCESS); | |||
| } else { | |||
| Notification.show("Error al actualizar uno o más registros", 3000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| } | |||
| // Opcional: volver a modo solo lectura | |||
| txtEquipo.setReadOnly(true); | |||
| cbTipo.setReadOnly(true); | |||
| txtFecha.setReadOnly(true); | |||
| cbUsuario.setReadOnly(true); | |||
| cbDepartamento.setReadOnly(true); | |||
| btnImprimirRepo.setVisible(true); | |||
| btnEditar.setVisible(true); | |||
| btnEditarFirmas.setVisible(true); | |||
| btnGuardar.setVisible(false); | |||
| btnCancelar.setVisible(false); | |||
| gridHardware.setEditOnClick(false); | |||
| gridHardware.getEditor().cancel(); | |||
| if (firmaUsuarioImg != null && userSignPad.getParent().isPresent()) { | |||
| userSignLayout.replace(userSignPad, firmaUsuarioImg); | |||
| } | |||
| if (firmaSmtImg != null && smtSignPad.getParent().isPresent()) { | |||
| smtSignLayout.replace(smtSignPad, firmaSmtImg); | |||
| } | |||
| } | |||
| // Metodo para verificar si la firma corresponde a una cadena de firma vacia | |||
| private boolean esFirmaVacia(String firmaBase64) { | |||
| String firmaVacia = "iVBORw0KGgoAAAANSUhEUgAAAXkAAAD8CAYAAACSCdTiAAAIbElEQVR4Xu3UAQ0AIAwDQeZfNCPI+Nwc9Lp07rvjCBAgQCApMEY+2atQBAgQ+AJG3iMQIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBBYAuXtOkIWm1QAAAAASUVORK5CYII="; | |||
| return firmaBase64.equals(firmaVacia); | |||
| } | |||
| private void addSignatureSection() { | |||
| // Usa los atributos de clase, no variables locales | |||
| userSignLayout = new VerticalLayout(); | |||
| userSignLayout.setWidthFull(); | |||
| userSignLayout.setAlignItems(Alignment.CENTER); | |||
| userSignPad = new SignaturePad(); | |||
| userSignPad.setHeight("200px"); | |||
| userSignPad.setWidthFull(); | |||
| userSignLayout.add(userSignPad, new Span("Usuario Interno")); | |||
| smtSignLayout = new VerticalLayout(); | |||
| smtSignLayout.setWidthFull(); | |||
| smtSignLayout.setAlignItems(Alignment.CENTER); | |||
| smtSignPad = new SignaturePad(); | |||
| smtSignPad.setHeight("200px"); | |||
| smtSignPad.setWidthFull(); | |||
| smtSignLayout.add(smtSignPad, new Span("Responsable de Soporte")); | |||
| gciaSignLayout = new VerticalLayout(); | |||
| gciaSignLayout.setWidthFull(); | |||
| gciaSignLayout.setAlignItems(Alignment.CENTER); | |||
| gciaSignPad = new SignaturePad(); | |||
| gciaSignPad.setHeight("200px"); | |||
| gciaSignPad.setWidthFull(); | |||
| gciaSignLayout.add(gciaSignPad, new Span("Gcia. de T.I")); | |||
| firmasLAyout.removeAll(); | |||
| firmasLAyout.setWidthFull(); | |||
| firmasLAyout.setSpacing(false); | |||
| firmasLAyout.setJustifyContentMode(JustifyContentMode.CENTER); | |||
| firmasLAyout.add(userSignLayout, smtSignLayout, gciaSignLayout); | |||
| } | |||
| @Override | |||
| public void beforeEnter(BeforeEnterEvent event) { | |||
| String idParam = event.getLocation().getQueryParameters().getParameters().get("id") != null | |||
| ? event.getLocation().getQueryParameters().getParameters().get("id").stream().findFirst().orElse(null) | |||
| : null; | |||
| if (idParam != null) { | |||
| try { | |||
| int planId = Integer.parseInt(idParam); | |||
| DetalleMantenimientoModel detalle = service.getDetalleMantenimientoPorPlanAnualId(planId); | |||
| if (detalle != null) { | |||
| this.planAnualIdActual = detalle.getPlanAnualId(); | |||
| this.mantenimientoIdActual = detalle.getId(); | |||
| id.setText("Plan ID: " + idParam); | |||
| txtEquipo.setValue(String.valueOf(detalle.getNombreEquipo())); | |||
| cbTipo.setValue( | |||
| cbTipo.getListDataView().getItems() | |||
| .filter(t -> t.getNombre().equals(detalle.getTipo())) | |||
| .findFirst().orElse(null) | |||
| ); | |||
| DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); | |||
| String fechaProg = detalle.getFechaprog() != null ? detalle.getFechaprog().format(formatter) : ""; | |||
| String fechaReal = detalle.getFecha() != null ? detalle.getFecha().format(formatter) : ""; | |||
| String situacion = detalle.getSituacion() != null ? detalle.getSituacion() : ""; | |||
| txtFechaProgramada.setValue(fechaProg); | |||
| txtFecha.setValue(fechaReal); | |||
| txtSituacion.setValue(situacion); | |||
| cbUsuario.setValue( | |||
| cbUsuario.getListDataView().getItems() | |||
| .filter(u -> u.getNombre().equals(detalle.getUsuario())) | |||
| .findFirst().orElse(null) | |||
| ); | |||
| cbDepartamento.setValue( | |||
| cbDepartamento.getListDataView().getItems() | |||
| .filter(d -> d.getNombre().equals(detalle.getDepartamento())) | |||
| .findFirst().orElse(null) | |||
| ); | |||
| int mantId = detalle.getId(); | |||
| List<HardwareDetalle> listaHardware = service.getHardwaredetallePorMantId(mantId); | |||
| gridHardware.setItems(listaHardware); | |||
| List<ActualizacioneSeguridadModel> listaActualizaciones = service.getActualizacionesSeg(mantId); | |||
| gridActualizaciones.setItems(listaActualizaciones); | |||
| gridActualizaciones.setVisible(!listaActualizaciones.isEmpty()); | |||
| // --- Mostrar firmas como imagen si existen --- | |||
| // Firma usuario | |||
| if (detalle.getFirmaUser() != null && !detalle.getFirmaUser().isEmpty()) { | |||
| String firmaUser = detalle.getFirmaUser(); | |||
| if (!firmaUser.startsWith("data:image")) { | |||
| firmaUser = "data:image/png;base64," + firmaUser; | |||
| } | |||
| firmaUsuarioImg = new Image(firmaUser, "Firma del usuario"); | |||
| firmaUsuarioImg.setHeight("200px"); | |||
| firmaUsuarioImg.setWidthFull(); | |||
| userSignLayout.replace(userSignPad, firmaUsuarioImg); | |||
| } | |||
| // Firma soporte | |||
| if (detalle.getFirmaSmt() != null && !detalle.getFirmaSmt().isEmpty()) { | |||
| String firmaSmt = detalle.getFirmaSmt(); | |||
| if (!firmaSmt.startsWith("data:image")) { | |||
| firmaSmt = "data:image/png;base64," + firmaSmt; | |||
| } | |||
| firmaSmtImg = new Image(firmaSmt, "Firma del usuario de soporte"); | |||
| firmaSmtImg.setHeight("200px"); | |||
| firmaSmtImg.setWidthFull(); | |||
| smtSignLayout.replace(smtSignPad, firmaSmtImg); | |||
| } | |||
| Image firmaGcia = new Image("images/FirmaGerenteTI.png", "Firma de la Gcia. de T.I"); | |||
| firmaGcia.setHeight("200px"); | |||
| firmaGcia.setWidthFull(); | |||
| gciaSignLayout.replace(gciaSignPad, firmaGcia); | |||
| } else { | |||
| id.setText("No se encontro informacion para el Plan ID: " + planId); | |||
| } | |||
| } catch (NumberFormatException e) { | |||
| id.setText("ID no valido"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,109 @@ | |||
| package mx.gob.jumapacelaya.ui; | |||
| import com.vaadin.flow.component.applayout.AppLayout; | |||
| import com.vaadin.flow.component.applayout.DrawerToggle; | |||
| import com.vaadin.flow.component.button.Button; | |||
| import com.vaadin.flow.component.button.ButtonVariant; | |||
| import com.vaadin.flow.component.dependency.CssImport; | |||
| import com.vaadin.flow.component.html.*; | |||
| import com.vaadin.flow.component.icon.VaadinIcon; | |||
| import com.vaadin.flow.component.orderedlayout.FlexComponent; | |||
| import com.vaadin.flow.component.orderedlayout.HorizontalLayout; | |||
| import com.vaadin.flow.component.orderedlayout.Scroller; | |||
| import com.vaadin.flow.component.orderedlayout.VerticalLayout; | |||
| import com.vaadin.flow.component.sidenav.SideNav; | |||
| import com.vaadin.flow.component.sidenav.SideNavItem; | |||
| import com.vaadin.flow.theme.lumo.LumoUtility; | |||
| import mx.gob.jumapacelaya.services.SecurityService; | |||
| @CssImport("./themes/sistema-mantenimiento/styles.css") | |||
| public class MainLayout extends AppLayout { | |||
| private H2 viewTitle; | |||
| private final SecurityService securityService; | |||
| public MainLayout(SecurityService securityService) { | |||
| this.securityService = securityService; | |||
| this.addClassName("app-layout"); | |||
| setPrimarySection(Section.DRAWER); | |||
| addDrawerContent(); | |||
| addHeaderContent(); | |||
| } | |||
| private void addHeaderContent() { | |||
| DrawerToggle toggle = new DrawerToggle(); | |||
| toggle.setAriaLabel("Menu toggle"); | |||
| toggle.addClassName("drawer-toggle"); | |||
| viewTitle = new H2(); | |||
| viewTitle.addClassNames(LumoUtility.FontSize.LARGE, LumoUtility.Margin.NONE); | |||
| viewTitle.getStyle().set("font-weight", "bold"); | |||
| viewTitle.getStyle().set("color", "#691B31"); | |||
| viewTitle.getStyle().set("font-size", "25px"); | |||
| String u = securityService.getAuthenticatedUser(); | |||
| Span usrNameLabel = new Span(u); | |||
| usrNameLabel.getStyle().set("color", "#691b31"); | |||
| usrNameLabel.getStyle().set("font-weight", "bold"); | |||
| usrNameLabel.getStyle().set("font-size", "20px"); | |||
| Button logoutButton = new Button("Cerrar sesión", VaadinIcon.SIGN_OUT.create(),event -> { | |||
| securityService.logout(); | |||
| }); | |||
| logoutButton.addClassName("logout-button"); | |||
| logoutButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY ,ButtonVariant.LUMO_ERROR); | |||
| HorizontalLayout headerContent = new HorizontalLayout(); | |||
| headerContent.setDefaultVerticalComponentAlignment(FlexComponent.Alignment.CENTER); | |||
| headerContent.addClassName("header-content"); | |||
| headerContent.add(viewTitle); | |||
| headerContent.setFlexGrow(1, viewTitle); | |||
| headerContent.add(usrNameLabel, logoutButton); | |||
| addToNavbar(false, toggle, headerContent); | |||
| } | |||
| private void addDrawerContent() { | |||
| VerticalLayout headerLayout = new VerticalLayout(); | |||
| headerLayout.setPadding(true); | |||
| headerLayout.setSpacing(false); | |||
| headerLayout.setAlignItems(FlexComponent.Alignment.CENTER); | |||
| headerLayout.getStyle().set("background-color", "#DDC9A3"); | |||
| Image imgLogo = new Image("images/LOGO_900X160.png", "Logo"); | |||
| imgLogo.setWidthFull(); | |||
| headerLayout.add(imgLogo); | |||
| Scroller scroller = new Scroller(createNavigation()); | |||
| scroller.getStyle().set("background-color", "#691b31"); | |||
| addToDrawer(headerLayout, scroller, createFooter()); | |||
| } | |||
| private SideNav createNavigation() { | |||
| SideNav nav = new SideNav(); | |||
| nav.addItem(new SideNavItem("Plan Anual", PlanAnualView.class, VaadinIcon.CALENDAR.create())); | |||
| nav.addItem(new SideNavItem("Listado de Actividades", ActDiariaView.class, VaadinIcon.EDIT.create())); | |||
| nav.addItem(new SideNavItem("Mantenimiento Correctivo", MantCorrectivoView.class, VaadinIcon.WRENCH.create())); | |||
| nav.getStyle().set("background-color", "white"); | |||
| nav.getStyle().set("border-radius", "5px"); | |||
| nav.getStyle().set("opacity", "0.9"); | |||
| return nav; | |||
| } | |||
| private Footer createFooter() { | |||
| Footer layout = new Footer(); | |||
| return layout; | |||
| } | |||
| @Override | |||
| protected void afterNavigation() { | |||
| super.afterNavigation(); | |||
| viewTitle.setText("Mantenimiento de Hardware"); | |||
| } | |||
| } | |||
| @ -0,0 +1,693 @@ | |||
| package mx.gob.jumapacelaya.ui; | |||
| import com.vaadin.flow.component.Text; | |||
| import com.vaadin.flow.component.UI; | |||
| import com.vaadin.flow.component.button.Button; | |||
| import com.vaadin.flow.component.button.ButtonVariant; | |||
| import com.vaadin.flow.component.checkbox.CheckboxGroup; | |||
| import com.vaadin.flow.component.combobox.ComboBox; | |||
| import com.vaadin.flow.component.datepicker.DatePicker; | |||
| import com.vaadin.flow.component.dependency.CssImport; | |||
| import com.vaadin.flow.component.dialog.Dialog; | |||
| import com.vaadin.flow.component.formlayout.FormLayout; | |||
| import com.vaadin.flow.component.grid.Grid; | |||
| import com.vaadin.flow.component.grid.GridVariant; | |||
| import com.vaadin.flow.component.html.Image; | |||
| import com.vaadin.flow.component.html.Span; | |||
| import com.vaadin.flow.component.icon.Icon; | |||
| import com.vaadin.flow.component.icon.VaadinIcon; | |||
| import com.vaadin.flow.component.notification.Notification; | |||
| import com.vaadin.flow.component.notification.NotificationVariant; | |||
| import com.vaadin.flow.component.orderedlayout.HorizontalLayout; | |||
| import com.vaadin.flow.component.orderedlayout.VerticalLayout; | |||
| import com.vaadin.flow.component.radiobutton.RadioButtonGroup; | |||
| import com.vaadin.flow.component.textfield.TextArea; | |||
| import com.vaadin.flow.component.textfield.TextField; | |||
| import com.vaadin.flow.data.renderer.ComponentRenderer; | |||
| import com.vaadin.flow.function.ValueProvider; | |||
| import com.vaadin.flow.router.BeforeEnterEvent; | |||
| import com.vaadin.flow.router.BeforeEnterObserver; | |||
| import com.vaadin.flow.router.PageTitle; | |||
| import com.vaadin.flow.router.Route; | |||
| import de.f0rce.signaturepad.SignaturePad; | |||
| import jakarta.annotation.security.PermitAll; | |||
| import mx.gob.jumapacelaya.models.*; | |||
| import mx.gob.jumapacelaya.services.DatabaseService; | |||
| import mx.gob.jumapacelaya.services.EmailService; | |||
| import mx.gob.jumapacelaya.services.SecurityService; | |||
| import mx.gob.jumapacelaya.services.UserService; | |||
| import org.vaadin.lineawesome.LineAwesomeIcon; | |||
| import java.time.LocalDate; | |||
| import java.time.format.DateTimeFormatter; | |||
| import java.util.*; | |||
| @PermitAll | |||
| @PageTitle("Correctivo") | |||
| @Route(value = "correctivo", layout = MainLayout.class) | |||
| @CssImport("./themes/sistema-mantenimiento/styles.css") | |||
| public class MantCorrectivoView extends VerticalLayout { | |||
| private VerticalLayout mainLayout; | |||
| private final SecurityService securityService; | |||
| private final VerticalLayout controlsLayout; | |||
| private final DatabaseService databaseService; | |||
| private final VerticalLayout actualizacionesLayout; | |||
| //private final VerticalLayout etiquetaLayout; | |||
| private final HorizontalLayout firmasLayout; | |||
| private final DatePicker fecha; | |||
| private final ComboBox<TiposMantenimiento> tipoMantt; | |||
| private final ComboBox<DepartamentosModel> area; | |||
| private final ComboBox<Usuario> usuario; | |||
| private final TextField txtNombreEquipo; | |||
| private final UserService userService; | |||
| private final EmailService emailService; | |||
| private RadioButtonGroup<String> formaGroup; | |||
| private CheckboxGroup<String> actualizaciones; | |||
| private final HorizontalLayout botonesLayout; | |||
| private TextArea txtCuales; | |||
| private RadioButtonGroup<String> masActualizacionesGroup; | |||
| private SignaturePad userSignPad; | |||
| private SignaturePad smtSignPad; | |||
| private SignaturePad gciatiSignPad; | |||
| private PlanAnual planAnualActual; | |||
| private LocalDate fechaProgramada; | |||
| private LocalDate fechaSeleccionada; | |||
| private TextArea jsutificacion; | |||
| Span userSignSpan = new Span("Nombre Usuario"); | |||
| private TextArea txtReparacion; | |||
| private HorizontalLayout headerLayout; | |||
| public MantCorrectivoView(UserService userService, SecurityService securityService, EmailService emailService, DatabaseService databaseService) { | |||
| this.databaseService = databaseService; | |||
| this.controlsLayout = new VerticalLayout(); | |||
| this.actualizacionesLayout = new VerticalLayout(); | |||
| //this.etiquetaLayout = new VerticalLayout(); | |||
| this.firmasLayout = new HorizontalLayout(); | |||
| this.botonesLayout = new HorizontalLayout(); | |||
| this.securityService = securityService; | |||
| this.userService = userService; | |||
| this.emailService = emailService; | |||
| headerLayout = new HorizontalLayout(); | |||
| headerLayout.setWidthFull(); | |||
| headerLayout.setMargin(false); | |||
| headerLayout.getStyle() | |||
| .set("box-shadow", "0 4px 8px rgba(0,0,0,0.2)") | |||
| .set("border-radius", "10px") | |||
| .set("background-color", "white") | |||
| .set("padding", "1rem") | |||
| .set("margin", "1rem auto"); | |||
| mainLayout = new VerticalLayout(); | |||
| mainLayout.setHeightFull(); | |||
| mainLayout.setMargin(false); | |||
| mainLayout.getStyle() | |||
| .set("box-shadow", "0 4px 8px rgba(0,0,0,0.2)") | |||
| .set("border-radius", "12px") | |||
| .set("background-color", "white") | |||
| .set("padding", "1rem") | |||
| .set("margin", "1rem auto"); | |||
| TextField nomenclatura = new TextField("Nomenclatura"); | |||
| nomenclatura.setReadOnly(true); | |||
| nomenclatura.addClassName("mantenimiento-text-field"); | |||
| Button btnListado = new Button("Mantenimientos realizados", VaadinIcon.CLIPBOARD_CHECK.create()); | |||
| btnListado.addClickListener(e -> verListadoMantenimientos()); | |||
| fecha = new DatePicker("Fecha:"); | |||
| fecha.setRequired(true); | |||
| fecha.setLocale(new Locale("es", "MX")); | |||
| DatePicker.DatePickerI18n i18n = new DatePicker.DatePickerI18n() | |||
| .setWeekdays(List.of("Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado")) | |||
| .setWeekdaysShort(List.of("Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb")) | |||
| .setMonthNames(List.of("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre")) | |||
| .setFirstDayOfWeek(1) | |||
| .setToday("Hoy") | |||
| .setCancel("Cancelar") | |||
| .setDateFormat("dd/MM/yyyy"); | |||
| fecha.setI18n(i18n); | |||
| tipoMantt = new ComboBox<>("Tipo de Mantenimiento"); | |||
| List<TiposMantenimiento> tiposMantenimiento = databaseService.getTiposDeMantenimientos(); | |||
| tipoMantt.setItems(tiposMantenimiento); | |||
| tipoMantt.addClassName("mantenimiento-combo"); | |||
| // Listener para manejar el cambio en el tipo de mantenimiento | |||
| tipoMantt.addValueChangeListener(e -> { | |||
| TiposMantenimiento tipoSeleccionado = e.getValue(); | |||
| if (tipoSeleccionado != null) { | |||
| String nomenclaturaValue = databaseService.getNomenclatura(tipoSeleccionado.getTipomantId()); | |||
| nomenclatura.setValue(nomenclaturaValue); | |||
| fecha.setValue(LocalDate.now()); | |||
| } | |||
| }); | |||
| HorizontalLayout fechaLayout = new HorizontalLayout(); | |||
| fechaLayout.add(fecha); | |||
| fechaLayout.addAndExpand(new HorizontalLayout()); | |||
| fechaLayout.add(tipoMantt, nomenclatura); | |||
| fechaLayout.setWidthFull(); | |||
| HorizontalLayout departamentoUsuarioLayout = new HorizontalLayout(); | |||
| area = new ComboBox<>("Área o Departamento:"); | |||
| area.setRequired(true); | |||
| List<DepartamentosModel> areas = databaseService.getDepartamentos(); | |||
| area.setItems(areas); | |||
| usuario = new ComboBox<>("Usuario:"); | |||
| List<Usuario> usuarios = databaseService.getUsuarios(); | |||
| usuario.setItems(usuarios); | |||
| usuario.setItemLabelGenerator(Usuario::getNombre); | |||
| usuario.setRequired(true); | |||
| usuario.addValueChangeListener(e -> { | |||
| Usuario usuarioSeleccionado = e.getValue(); | |||
| if (usuarioSeleccionado != null) { | |||
| String empleadoId = usuarioSeleccionado.getEmpleadoId(); | |||
| String nombreUsuario = usuarioSeleccionado.getNombre(); | |||
| //userSignSpan.setText(nombreUsuario); | |||
| } else { | |||
| //userSignSpan.setText("S.M.T Nombre"); | |||
| } | |||
| }); | |||
| txtNombreEquipo = new TextField("Nombre del Equipo:"); | |||
| departamentoUsuarioLayout.add(area, usuario, txtNombreEquipo); | |||
| departamentoUsuarioLayout.setWidthFull(); | |||
| createHardwareSection(databaseService); | |||
| addActualizacionesSection(); | |||
| signLayout(); | |||
| buttons(); | |||
| headerLayout.add(btnListado); | |||
| mainLayout.add(fechaLayout, departamentoUsuarioLayout, controlsLayout, actualizacionesLayout, firmasLayout, botonesLayout); | |||
| add(headerLayout, mainLayout); | |||
| } | |||
| // Metodo para inicializar el formulario de hardware | |||
| private void createHardwareSection(DatabaseService databaseService) { | |||
| HorizontalLayout etiquetaLayout = new HorizontalLayout(); | |||
| Span etiqueta = new Span("Limpieza de Equipo Realizada"); | |||
| Button btnAgregarTipo = new Button(new Icon(VaadinIcon.PLUS)); | |||
| btnAgregarTipo.addThemeVariants(ButtonVariant.LUMO_ICON); | |||
| btnAgregarTipo.setAriaLabel("Agregar Equipo"); | |||
| btnAgregarTipo.addClickListener(e -> { | |||
| addNuevoTipo(); | |||
| }); | |||
| etiquetaLayout.add(etiqueta, btnAgregarTipo); | |||
| controlsLayout.add(etiquetaLayout); | |||
| controlsLayout.setSpacing(false); | |||
| addNuevoTipo(); | |||
| } | |||
| // Método para crear el combo box y campos de texto para eñ hardware en tiempo de ejecución | |||
| private List<HorizontalLayout> hardwareLayouts = new ArrayList<>(); | |||
| private void addNuevoTipo() { | |||
| ComboBox<TiposHardware> tipoHardware = new ComboBox<>(); | |||
| tipoHardware.setPlaceholder("Tipos de Hardware"); | |||
| tipoHardware.setItemLabelGenerator(TiposHardware::getNombreHardware); | |||
| tipoHardware.setItems(databaseService.getTiposHardware()); | |||
| tipoHardware.setSizeFull(); | |||
| TextField noSerie = new TextField(); | |||
| noSerie.setEnabled(false); | |||
| noSerie.setRequired(true); | |||
| noSerie.setPlaceholder("No. de Serie"); | |||
| noSerie.setSizeFull(); | |||
| noSerie.addValueChangeListener(e -> { | |||
| String upperCaseValue = e.getValue().toUpperCase(); | |||
| noSerie.setValue(upperCaseValue); | |||
| }); | |||
| TextField modelo = new TextField(); | |||
| modelo.setEnabled(false); | |||
| modelo.setRequired(true); | |||
| modelo.setPlaceholder("Modelo"); | |||
| modelo.setSizeFull(); | |||
| modelo.addValueChangeListener(event -> { | |||
| String upperCaseValue = event.getValue().toUpperCase(); | |||
| modelo.setValue(upperCaseValue); | |||
| }); | |||
| TextField placa = new TextField(); | |||
| placa.setEnabled(false); | |||
| placa.setRequired(true); | |||
| placa.setPlaceholder("Placa"); | |||
| placa.setSizeFull(); | |||
| // Validacion para que este campo solo acepte numeros | |||
| placa.getElement().executeJs( | |||
| "this.addEventListener('input', function(e) { " + | |||
| " e.target.value = e.target.value.replace(/[^0-9]/g, '');" + // Solo permite dígitos | |||
| "});" | |||
| ); | |||
| tipoHardware.addValueChangeListener(event -> { | |||
| TiposHardware tipoSeleccionado = event.getValue(); | |||
| if (tipoSeleccionado != null) { | |||
| String nombreTipo = tipoSeleccionado.getNombreHardware(); | |||
| if ("TECLADO".equals(nombreTipo)) { | |||
| noSerie.setEnabled(false); | |||
| modelo.setEnabled(false); | |||
| placa.setEnabled(false); | |||
| } else if ("MOUSE".equals(nombreTipo)) { | |||
| noSerie.setEnabled(false); | |||
| modelo.setEnabled(false); | |||
| placa.setEnabled(false); | |||
| } else { | |||
| noSerie.setEnabled(true); | |||
| modelo.setEnabled(true); | |||
| placa.setEnabled(true); | |||
| } | |||
| } else { | |||
| noSerie.setEnabled(false); | |||
| modelo.setEnabled(false); | |||
| placa.setEnabled(false); | |||
| } | |||
| }); | |||
| Button btnEliminar = new Button(new Icon(VaadinIcon.TRASH)); | |||
| btnEliminar.addThemeVariants(ButtonVariant.LUMO_ICON, ButtonVariant.LUMO_ERROR); | |||
| btnEliminar.setAriaLabel("Eliminar Tipo"); | |||
| //Crear nuevo layout horizontal con estos campos | |||
| HorizontalLayout hardwareDetailsLayout = new HorizontalLayout(); | |||
| hardwareDetailsLayout.add(tipoHardware, noSerie, modelo, placa, btnEliminar); | |||
| hardwareDetailsLayout.setWidthFull(); | |||
| hardwareLayouts.add(hardwareDetailsLayout); | |||
| controlsLayout.add(hardwareDetailsLayout); | |||
| //Listener para eliminar el tipo | |||
| btnEliminar.addClickListener(event -> { | |||
| controlsLayout.remove(hardwareDetailsLayout); | |||
| }); | |||
| controlsLayout.add(hardwareDetailsLayout); | |||
| controlsLayout.setSizeFull(); | |||
| } | |||
| private void addActualizacionesSection() { | |||
| VerticalLayout etiquetaLayout = new VerticalLayout(); | |||
| Span Titulo = new Span("Actualizaciones de Seguridad Informatica:"); | |||
| etiquetaLayout.add(Titulo); | |||
| actualizaciones = new CheckboxGroup<>(); | |||
| actualizaciones.setLabel("Actualizaciones Necesarias"); | |||
| actualizaciones.setItems("S.O", "Antivirus", "Firewall"); | |||
| formaGroup = new RadioButtonGroup<>(); | |||
| formaGroup.setLabel("Actividad Realizada de Forma:"); | |||
| formaGroup.setRequired(true); | |||
| formaGroup.setItems("Remota", "Manual"); | |||
| txtCuales = new TextArea(); | |||
| txtCuales.setLabel("¿Cuáles?"); | |||
| txtCuales.setEnabled(false); | |||
| txtCuales.setWidthFull(); | |||
| masActualizacionesGroup = new RadioButtonGroup<>(); | |||
| masActualizacionesGroup.setRequired(true); | |||
| masActualizacionesGroup.setLabel("¿Requiere más actualizaciones?"); | |||
| masActualizacionesGroup.setItems("Si", "No"); | |||
| masActualizacionesGroup.addValueChangeListener(e -> { | |||
| if ("Si".equals(e.getValue())) { | |||
| txtCuales.setEnabled(true); | |||
| txtCuales.setRequired(true); | |||
| txtCuales.clear(); | |||
| } else { | |||
| txtCuales.setEnabled(false); | |||
| txtCuales.setRequired(false); | |||
| txtCuales.clear(); | |||
| } | |||
| }); | |||
| txtReparacion = new TextArea("Reparación Realizada:"); | |||
| txtReparacion.setWidthFull(); | |||
| txtReparacion.setHeight("100px"); | |||
| HorizontalLayout formasLayout = new HorizontalLayout(); | |||
| formasLayout.add(formaGroup, masActualizacionesGroup, txtCuales); | |||
| formasLayout.setSizeFull(); | |||
| actualizacionesLayout.add(Titulo, actualizaciones, formasLayout, txtReparacion); | |||
| actualizacionesLayout.setSpacing(false); | |||
| } | |||
| private void signLayout() { | |||
| VerticalLayout userSignLayout = new VerticalLayout(); | |||
| userSignPad = new SignaturePad(); | |||
| userSignPad.setBackgroundColor("#FFFFFF"); | |||
| userSignPad.setHeight("200px"); | |||
| userSignPad.setPenColor("#000000"); | |||
| userSignPad.getElement().getStyle().set("border", "1px solid black"); | |||
| Span tituloUser = new Span("Usuario Interno"); | |||
| userSignLayout.setSizeFull(); | |||
| userSignLayout.setSpacing(true); | |||
| userSignLayout.setSpacing(false); | |||
| userSignLayout.setAlignItems(Alignment.CENTER); | |||
| userSignLayout.add(userSignPad, userSignSpan, tituloUser); | |||
| VerticalLayout smtSignLayout = new VerticalLayout(); | |||
| smtSignPad = new SignaturePad(); | |||
| smtSignPad.setHeight("200px"); | |||
| smtSignPad.setBackgroundColor("#FFFFFF"); | |||
| smtSignPad.setPenColor("#000000"); | |||
| smtSignPad.getElement().getStyle().set("border", "1px solid black"); | |||
| String u = securityService.getAuthenticatedUser(); | |||
| Span smtSignSpan = new Span(u); | |||
| Span tituloSMT = new Span("Responsable de Soporte"); | |||
| smtSignLayout.setSizeFull(); | |||
| smtSignLayout.setSpacing(true); | |||
| smtSignLayout.setSpacing(false); | |||
| smtSignLayout.setAlignItems(Alignment.CENTER); | |||
| smtSignLayout.add(smtSignPad, smtSignSpan, tituloSMT); | |||
| VerticalLayout gcialSignLayout = new VerticalLayout(); | |||
| Image firmaGcia = new Image("images/FirmaGerenteTI.png", "Firma Gerente de Sistemas"); | |||
| firmaGcia.setHeight("200px"); | |||
| firmaGcia.setWidthFull(); | |||
| Span gciatiSignSpan = new Span("Ing. Javier Patiño Martinez"); | |||
| Span tituloGerente = new Span("Gerente de T.I"); | |||
| gcialSignLayout.setSizeFull(); | |||
| gcialSignLayout.setSpacing(false); | |||
| gcialSignLayout.setAlignItems(Alignment.CENTER); | |||
| gcialSignLayout.add(firmaGcia, gciatiSignSpan, tituloGerente); | |||
| firmasLayout.add(userSignLayout, smtSignLayout, gcialSignLayout); | |||
| firmasLayout.setWidthFull(); | |||
| firmasLayout.setSpacing(false); | |||
| firmasLayout.setJustifyContentMode(JustifyContentMode.CENTER); | |||
| } | |||
| // Metodo para verificar si la firma corresponde a una cadena de firma vacia | |||
| private boolean esFirmaVacia(String firmaBase64) { | |||
| String firmaVacia = "iVBORw0KGgoAAAANSUhEUgAAAXkAAAD8CAYAAACSCdTiAAAIbElEQVR4Xu3UAQ0AIAwDQeZfNCPI+Nwc9Lp07rvjCBAgQCApMEY+2atQBAgQ+AJG3iMQIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBBYAuXtOkIWm1QAAAAASUVORK5CYII="; | |||
| return firmaBase64.equals(firmaVacia); | |||
| } | |||
| private void buttons() { | |||
| VerticalLayout buttonsLayout = new VerticalLayout(); | |||
| Button btnGuardar = new Button("Guardar", LineAwesomeIcon.SAVE.create()); | |||
| btnGuardar.addThemeVariants(ButtonVariant.LUMO_PRIMARY); | |||
| btnGuardar.addThemeVariants(ButtonVariant.LUMO_LARGE); | |||
| btnGuardar.addClickListener(event -> { | |||
| fechaSeleccionada = fecha.getValue(); | |||
| guardarMantenimiento(); | |||
| }); | |||
| buttonsLayout.setSizeFull(); | |||
| buttonsLayout.add(btnGuardar); | |||
| buttonsLayout.setAlignItems(Alignment.CENTER); | |||
| botonesLayout.add(buttonsLayout); | |||
| botonesLayout.setSizeFull(); | |||
| //botonesLayout.setAlignItems(Alignment.CENTER); | |||
| } | |||
| // METODO PARA ENVIAR CORREOS ELECTRONICOS | |||
| private void enviarCorreo() { | |||
| Usuario usuarioSeleccionado = usuario.getValue(); | |||
| if (usuarioSeleccionado != null && usuarioSeleccionado.getEmail() != null) { | |||
| String destinatario = usuarioSeleccionado.getEmail(); | |||
| String asunto = "MANTENIMIENTO DE EQUIPO DE COMPUTO REALIZADO"; | |||
| String cuerpo = "<html>" + | |||
| "<body>" + | |||
| "<img src='cid:image_id'/>" + | |||
| "</body>" + | |||
| "</html>"; | |||
| String imagePath = "META-INF/resources/images/imgCorreo/correoMantt.png"; | |||
| emailService.enviarCorreo(destinatario, asunto, cuerpo, imagePath); | |||
| } else { | |||
| Notification.show("Por favor selecciona un usuario", 4000, Notification.Position.MIDDLE); | |||
| } | |||
| } | |||
| private void guardarMantenimiento() { | |||
| TiposMantenimiento tiposMantenimiento = tipoMantt.getValue(); | |||
| String tipoMantId = tiposMantenimiento != null ? tiposMantenimiento.getTipomantId() : null; | |||
| String justificacionValue = jsutificacion != null ? jsutificacion.getValue() : null; | |||
| String reparacionValue = txtReparacion != null ? txtReparacion.getValue() : null; | |||
| DepartamentosModel departamentoSeleccionado = area.getValue(); | |||
| String departamentoId = departamentoSeleccionado != null ? departamentoSeleccionado.getDepartamentoId().toString() : null; | |||
| Usuario usuarioSeleccionado = usuario.getValue(); | |||
| String empleadoId = usuarioSeleccionado != null ? usuarioSeleccionado.getEmpleadoId().toString() : null; | |||
| String equipoId = txtNombreEquipo.getValue(); | |||
| String formaSeleccionada = formaGroup.getValue(); | |||
| String formaMantt = null; | |||
| if ("Remota".equals(formaSeleccionada)) { | |||
| formaMantt = "R"; | |||
| } else if ("Manual".equals(formaSeleccionada)) { | |||
| formaMantt = "M"; | |||
| } | |||
| // Validación de campos obligatorios | |||
| if (fechaSeleccionada == null || tipoMantId == null || departamentoId == null || empleadoId == null || | |||
| equipoId == null || equipoId.trim().isEmpty() || formaMantt == null) { | |||
| Notification.show("Por favor, completa todos los campos requeridos", 4000, Notification.Position.MIDDLE); | |||
| return; | |||
| } | |||
| byte[] userSignatureBytes = userSignPad.getImageBase64(); | |||
| byte[] smtSignatureBytes = smtSignPad.getImageBase64(); | |||
| //byte[] gciaSignatureBytes = gciatiSignPad.getImageBase64(); | |||
| String userSignatureBase64 = Base64.getEncoder().encodeToString(userSignatureBytes); | |||
| String smtSignatureBase64 = Base64.getEncoder().encodeToString(smtSignatureBytes); | |||
| //String gciaSignatureBase64 = Base64.getEncoder().encodeToString(gciaSignatureBytes); | |||
| if (esFirmaVacia(userSignatureBase64)) userSignatureBase64 = null; | |||
| if (esFirmaVacia(smtSignatureBase64)) smtSignatureBase64 = null; | |||
| //if (esFirmaVacia(gciaSignatureBase64)) gciaSignatureBase64 = null; | |||
| // Validación de campos de hardware | |||
| List<Map<String, String>> detallesHardware = new ArrayList<>(); | |||
| for (HorizontalLayout layout : hardwareLayouts) { | |||
| ComboBox<TiposHardware> tipoHardware = (ComboBox<TiposHardware>) layout.getComponentAt(0); | |||
| TextField noSerie = (TextField) layout.getComponentAt(1); | |||
| TextField modelo = (TextField) layout.getComponentAt(2); | |||
| TextField placa = (TextField) layout.getComponentAt(3); | |||
| TiposHardware tipoSeleccionado = tipoHardware.getValue(); | |||
| if (tipoSeleccionado == null) { | |||
| Notification.show("Por favor, selecciona un tipo de hardware", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_WARNING); | |||
| return; | |||
| } | |||
| boolean esOpcional = Arrays.asList("TECLADO", "MOUSE").contains(tipoSeleccionado.getNombreHardware()); | |||
| String numSerie = noSerie.getValue(); | |||
| String modeloVal = modelo.getValue(); | |||
| String placaVal = placa.getValue(); | |||
| if (!esOpcional && (modeloVal == null || modeloVal.isEmpty() || numSerie == null || numSerie.isEmpty() || placaVal == null || placaVal.isEmpty())) { | |||
| Notification.show("Por favor, completa todos los campos de hardware.", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_WARNING); | |||
| return; | |||
| } | |||
| Map<String, String> hw = new HashMap<>(); | |||
| hw.put("tipoHardwareId", tipoSeleccionado.getTipoHardwareId()); | |||
| hw.put("numSerie", numSerie); | |||
| hw.put("modelo", modeloVal); | |||
| hw.put("placa", placaVal); | |||
| detallesHardware.add(hw); | |||
| } | |||
| Set<String> actualizacionesSeleccionadas = actualizaciones.getSelectedItems(); | |||
| String otrasActualizaciones = null; | |||
| if ("Si".equals(masActualizacionesGroup.getValue())) { | |||
| otrasActualizaciones = txtCuales.getValue(); | |||
| if (otrasActualizaciones == null || otrasActualizaciones.trim().isEmpty()) { | |||
| Notification.show("Especifica las otras actualizaciones", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_WARNING); | |||
| return; | |||
| } | |||
| } | |||
| // Una vez que validamos todos los campos del formulario, procedemos a insertar en BD | |||
| try { | |||
| int isInserted = databaseService.insertarMantenimiento(fechaSeleccionada, tipoMantId, departamentoId, empleadoId, formaMantt, equipoId, userSignatureBase64, smtSignatureBase64, null, justificacionValue, reparacionValue); | |||
| if (isInserted <= 0) { | |||
| Notification.show("Error al guardar el mantenimiento", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| return; | |||
| } | |||
| int mantenimientoId = databaseService.getUltimoMantenimientoId(); | |||
| for (Map<String, String> hw : detallesHardware) { | |||
| boolean ok = databaseService.insertarHardware( | |||
| hw.get("tipoHardwareId"), | |||
| hw.get("numSerie"), | |||
| hw.get("modelo"), | |||
| hw.get("placa"), | |||
| mantenimientoId | |||
| ); | |||
| if (!ok) { | |||
| Notification.show("Error al insertar detalles del hardware: ", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| return; | |||
| } | |||
| } | |||
| for (String act : actualizacionesSeleccionadas) { | |||
| boolean ok = databaseService.insertActualizacionSeg(act, null, mantenimientoId); | |||
| if (!ok) { | |||
| Notification.show("Error al insertar actualización de seguridad", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| return; | |||
| } | |||
| } | |||
| if (otrasActualizaciones != null) { | |||
| boolean ok = databaseService.insertActualizacionSeg("Otras", otrasActualizaciones, mantenimientoId); | |||
| if (!ok) { | |||
| Notification.show("Error al insertar otras actualizaciones", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| return; | |||
| } | |||
| } | |||
| // === EXITO === | |||
| Notification.show("¡Mantenimiento guardado exitosamente!", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_SUCCESS); | |||
| try { | |||
| enviarCorreo(); | |||
| } catch (Exception e) { | |||
| Notification.show("Error al enviar el correo", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| e.printStackTrace(); | |||
| } | |||
| // Limpiar campos | |||
| fecha.clear(); | |||
| tipoMantt.clear(); | |||
| area.clear(); | |||
| usuario.clear(); | |||
| txtNombreEquipo.clear(); | |||
| formaGroup.clear(); | |||
| actualizaciones.clear(); | |||
| masActualizacionesGroup.clear(); | |||
| txtCuales.clear(); | |||
| userSignPad.clear(); | |||
| smtSignPad.clear(); | |||
| //gciatiSignPad.clear(); | |||
| txtReparacion.clear(); | |||
| for (HorizontalLayout layout : hardwareLayouts) { | |||
| ((ComboBox<?>) layout.getComponentAt(0)).clear(); | |||
| ((TextField) layout.getComponentAt(1)).clear(); | |||
| ((TextField) layout.getComponentAt(2)).clear(); | |||
| ((TextField) layout.getComponentAt(3)).clear(); | |||
| } | |||
| UI.getCurrent().navigate("/"); | |||
| } catch (Exception ex) { | |||
| Notification.show("Ocurrio un error inesperado: " + ex.getMessage(), 5000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| ex.printStackTrace(); | |||
| } | |||
| } | |||
| // Muestra un dialogo con el listado de los mantenimientos correctivos realizados | |||
| private void verListadoMantenimientos() { | |||
| Dialog dialog = new Dialog(); | |||
| dialog.setSizeFull(); | |||
| dialog.setCloseOnEsc(true); | |||
| dialog.setCloseOnOutsideClick(true); | |||
| dialog.setHeaderTitle("Listado de Mantenimientos Correctivos"); | |||
| Grid<MantCorrectivosModel> grid = new Grid<>(MantCorrectivosModel.class, false); | |||
| grid.addColumn(MantCorrectivosModel::getMantenimientoId) | |||
| .setHeader("No.").setAutoWidth(true); | |||
| DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); | |||
| grid.addColumn(item -> item.getFecha() != null ? item.getFecha().format(formatter) : "N/A") | |||
| .setHeader("Fecha:").setAutoWidth(true); | |||
| grid.addColumn(MantCorrectivosModel::getTipo) | |||
| .setHeader("Tipo:").setAutoWidth(true); | |||
| grid.addColumn(MantCorrectivosModel::getArea) | |||
| .setHeader("Área:").setAutoWidth(true); | |||
| grid.addColumn(MantCorrectivosModel::getNombre) | |||
| .setHeader("Usuario:").setAutoWidth(true); | |||
| grid.addColumn(MantCorrectivosModel::getForma) | |||
| .setHeader("Forma:").setAutoWidth(true); | |||
| grid.addColumn(MantCorrectivosModel::getNomequipo) | |||
| .setHeader("Equipo:").setAutoWidth(true); | |||
| grid.setItems(databaseService.getMantenimientosCorrectivos(2)); | |||
| grid.setItemDetailsRenderer(ReparacionDetails.createReparacionesDetails()); | |||
| grid.addThemeVariants(GridVariant.LUMO_ROW_STRIPES); | |||
| Button closeButton = new Button("Cerrar", e -> dialog.close()); | |||
| closeButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); | |||
| dialog.add(grid, closeButton); | |||
| dialog.open(); | |||
| } | |||
| private static class ReparacionDetails extends FormLayout { | |||
| private final TextArea txtReparacion = new TextArea("Reparación realizada:"); | |||
| public ReparacionDetails() { | |||
| txtReparacion.setReadOnly(true); | |||
| add(txtReparacion); | |||
| setResponsiveSteps(new ResponsiveStep("0", 1)); | |||
| setColspan(txtReparacion, 1); | |||
| } | |||
| public void setModel(MantCorrectivosModel model) { | |||
| txtReparacion.setValue(model.getReparacion() != null ? model.getReparacion() : ""); | |||
| } | |||
| private static ComponentRenderer<ReparacionDetails, MantCorrectivosModel> createReparacionesDetails() { | |||
| return new ComponentRenderer<>(ReparacionDetails::new, ReparacionDetails::setModel); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,853 @@ | |||
| package mx.gob.jumapacelaya.ui; | |||
| import com.vaadin.flow.component.Component; | |||
| import com.vaadin.flow.component.UI; | |||
| import com.vaadin.flow.component.button.ButtonVariant; | |||
| import com.vaadin.flow.component.checkbox.CheckboxGroup; | |||
| import com.vaadin.flow.component.combobox.ComboBox; | |||
| import com.vaadin.flow.component.datepicker.DatePicker; | |||
| import com.vaadin.flow.component.dependency.CssImport; | |||
| import com.vaadin.flow.component.dialog.Dialog; | |||
| import com.vaadin.flow.component.html.H1; | |||
| import com.vaadin.flow.component.html.H2; | |||
| import com.vaadin.flow.component.html.Image; | |||
| import com.vaadin.flow.component.html.Span; | |||
| import com.vaadin.flow.component.icon.Icon; | |||
| import com.vaadin.flow.component.icon.VaadinIcon; | |||
| import com.vaadin.flow.component.notification.Notification; | |||
| import com.vaadin.flow.component.notification.NotificationVariant; | |||
| import com.vaadin.flow.component.orderedlayout.FlexComponent; | |||
| import com.vaadin.flow.component.orderedlayout.HorizontalLayout; | |||
| import com.vaadin.flow.component.orderedlayout.VerticalLayout; | |||
| import com.vaadin.flow.component.radiobutton.RadioButtonGroup; | |||
| import com.vaadin.flow.component.textfield.NumberField; | |||
| import com.vaadin.flow.component.textfield.TextArea; | |||
| import com.vaadin.flow.component.textfield.TextField; | |||
| import com.vaadin.flow.component.button.Button; | |||
| import com.vaadin.flow.router.BeforeEnterEvent; | |||
| import com.vaadin.flow.router.BeforeEnterObserver; | |||
| import com.vaadin.flow.router.PageTitle; | |||
| import com.vaadin.flow.router.Route; | |||
| import de.f0rce.signaturepad.SignaturePad; | |||
| import jakarta.annotation.security.PermitAll; | |||
| import mx.gob.jumapacelaya.models.*; | |||
| import mx.gob.jumapacelaya.services.DatabaseService; | |||
| import mx.gob.jumapacelaya.services.EmailService; | |||
| import mx.gob.jumapacelaya.services.SecurityService; | |||
| import mx.gob.jumapacelaya.services.UserService; | |||
| import oracle.net.aso.h; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.vaadin.lineawesome.LineAwesomeIcon; | |||
| import java.time.LocalDate; | |||
| import java.util.*; | |||
| @PermitAll | |||
| @PageTitle("Mantenimiento") | |||
| @Route(value = "mantenimiento", layout = MainLayout.class) | |||
| @CssImport("./themes/sistema-mantenimiento/styles.css") | |||
| public class MantenimientoView extends VerticalLayout implements BeforeEnterObserver { | |||
| private final SecurityService securityService; | |||
| private final VerticalLayout controlsLayout; | |||
| private final DatabaseService databaseService; | |||
| private final VerticalLayout actualizacionesLayout; | |||
| private final VerticalLayout etiquetaLayout; | |||
| private final HorizontalLayout firmasLayout; | |||
| private final DatePicker fecha; | |||
| private final TextField txtPlananualID; | |||
| private final ComboBox<TiposMantenimiento> tipoMantt; | |||
| private final ComboBox<DepartamentosModel> area; | |||
| private final ComboBox<Usuario> usuario; | |||
| private final TextField txtNombreEquipo; | |||
| private final UserService userService; | |||
| private final EmailService emailService; | |||
| private RadioButtonGroup<String> formaGroup; | |||
| private CheckboxGroup<String> actualizaciones; | |||
| private final HorizontalLayout botonesLayout; | |||
| private TextArea txtCuales; | |||
| private RadioButtonGroup<String> masActualizacionesGroup; | |||
| private SignaturePad userSignPad; | |||
| private SignaturePad smtSignPad; | |||
| //private SignaturePad gciatiSignPad; | |||
| private PlanAnual planAnualActual; | |||
| private LocalDate fechaProgramada; | |||
| private LocalDate fechaSeleccionada; | |||
| private TextArea jsutificacion; | |||
| private VerticalLayout mainLayout; | |||
| Span userSignSpan = new Span("Nombre Usuario"); | |||
| public MantenimientoView(UserService userService, SecurityService securityService, EmailService emailService, DatabaseService databaseService) { | |||
| this.databaseService = databaseService; | |||
| this.controlsLayout = new VerticalLayout(); | |||
| this.actualizacionesLayout = new VerticalLayout(); | |||
| this.etiquetaLayout = new VerticalLayout(); | |||
| this.firmasLayout = new HorizontalLayout(); | |||
| this.botonesLayout = new HorizontalLayout(); | |||
| this.securityService = securityService; | |||
| this.userService = userService; | |||
| this.emailService = emailService; | |||
| mainLayout = new VerticalLayout(); | |||
| mainLayout.setHeightFull(); | |||
| mainLayout.getStyle() | |||
| .set("box-shadow","0 4px 8px rgba(0,0,0,0.2)") | |||
| .set("border-radius", "12px") | |||
| .set("background-color", "white") | |||
| .set("padding", "1rem") | |||
| .set("margin", "1rem auto"); | |||
| HorizontalLayout fechaLayout = new HorizontalLayout(); | |||
| //Componentes de texto | |||
| TextField nomenclatura = new TextField("Nomenclatura"); | |||
| nomenclatura.setReadOnly(true); | |||
| nomenclatura.addClassName("mantenimiento-text-field"); | |||
| TextArea otras = new TextArea("¿Cuales?"); | |||
| otras.setEnabled(false); | |||
| otras.addClassName("mantenimiento-text-field"); | |||
| //Selector de fecha | |||
| this.fecha = new DatePicker("Fecha"); | |||
| fecha.setRequired(true); | |||
| fecha.setLocale(new Locale("es", "MX")); | |||
| DatePicker.DatePickerI18n i18n = new DatePicker.DatePickerI18n() | |||
| .setWeekdays(List.of("Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado")) | |||
| .setWeekdaysShort(List.of("Dom","Lun","Mar","Mié","Jue","Vie","Sáb")) | |||
| .setMonthNames(List.of("Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre")) | |||
| .setFirstDayOfWeek(1) | |||
| .setToday("Hoy") | |||
| .setCancel("Cancelar") | |||
| .setDateFormat("dd/MM/yyyy"); | |||
| fecha.setI18n(i18n); | |||
| // Campo de texto para el ID de MTTOPROGRAMADO | |||
| this.txtPlananualID = new TextField("Plan Anual ID"); | |||
| txtPlananualID.setReadOnly(true); | |||
| txtPlananualID.addClassName("mantenimiento-text-field"); | |||
| // ComboBox Tipo de Mantenimiento | |||
| this.tipoMantt = new ComboBox<>("Tipo de Mantenimiento"); | |||
| List<TiposMantenimiento> tiposMantenimiento = databaseService.getTiposDeMantenimientos(); | |||
| tipoMantt.setItems(tiposMantenimiento); | |||
| tipoMantt.addClassName("mantenimiento-combo"); | |||
| // Listener para manejar el cambio en el tipo de mantenimiento | |||
| tipoMantt.addValueChangeListener(event -> { | |||
| TiposMantenimiento tipoSeleccionado = event.getValue(); | |||
| if (tipoSeleccionado != null) { | |||
| // Actualizar nomenclatura dependiendo del tipo de mantenimiento | |||
| String nomenclaturaValue = databaseService.getNomenclatura(tipoSeleccionado.getTipomantId()); | |||
| nomenclatura.setValue(nomenclaturaValue); | |||
| // Si el tipo es preventivo se establecerá la fecha automáticamente a la fecha del sistema | |||
| if ("1".equals(tipoSeleccionado.getTipomantId())) { // 1 es para PREVENTIVO | |||
| this.fecha.setValue(LocalDate.now()); | |||
| etiquetaLayout.setVisible(false); | |||
| // Limpiar el layout de correctivo si es necesario | |||
| etiquetaLayout.removeAll(); | |||
| } else if ("2".equals(tipoSeleccionado.getTipomantId())) { // 2 es para CORRECTIVO | |||
| this.fecha.clear(); | |||
| etiquetaLayout.setVisible(true); | |||
| //correctivoLayout(); | |||
| } else { | |||
| // Para otros tipos de mantenimiento | |||
| this.fecha.clear(); | |||
| etiquetaLayout.setVisible(false); | |||
| etiquetaLayout.removeAll(); // Limpia el layout para otros tipos | |||
| } | |||
| } else { | |||
| nomenclatura.clear(); | |||
| this.fecha.clear(); | |||
| etiquetaLayout.setVisible(false); | |||
| etiquetaLayout.removeAll(); // Limpia el layout | |||
| } | |||
| }); | |||
| fechaLayout.add(this.fecha/*, this.txtPlananualID*/); | |||
| fechaLayout.addAndExpand(new HorizontalLayout()); | |||
| fechaLayout.add(tipoMantt, nomenclatura); | |||
| fechaLayout.setWidthFull(); | |||
| HorizontalLayout departamentoLayout = new HorizontalLayout(); | |||
| //ComboBox Area o Departamento | |||
| this.area = new ComboBox<>("Area o Departamento"); | |||
| area.setRequired(true); | |||
| List<DepartamentosModel> areas = databaseService.getDepartamentos(); | |||
| area.setItems(areas); | |||
| this.usuario = new ComboBox<>("Usuario"); | |||
| List<Usuario> usuarios = databaseService.getUsuarios(); | |||
| usuario.setItems(usuarios); | |||
| usuario.setItemLabelGenerator(Usuario::getNombre); | |||
| usuario.setRequired(true); | |||
| usuario.addValueChangeListener(event -> { | |||
| Usuario usuarioSeleccionado = event.getValue(); | |||
| if (usuarioSeleccionado != null) { | |||
| String empleadoId = usuarioSeleccionado.getEmpleadoId(); | |||
| String nombreUsuario = usuarioSeleccionado.getNombre(); | |||
| userSignSpan.setText(nombreUsuario); | |||
| } else { | |||
| userSignSpan.setText("S.M.T Nombre"); | |||
| } | |||
| }); | |||
| // Boton auxiliar para probar el envio de los correos electronicos | |||
| Button btnEnviarCorreo = new Button("Enviar correo de prueba"); | |||
| btnEnviarCorreo.addClickListener(event -> enviarCorreo()); | |||
| this.txtNombreEquipo = new TextField("Nombre del Equipo"); | |||
| txtNombreEquipo.setRequired(true); | |||
| //txtNombreEquipo.setReadOnly(true); | |||
| departamentoLayout.add(area, usuario/*, btnEnviarCorreo*/, txtNombreEquipo); | |||
| departamentoLayout.setWidthFull(); | |||
| createHardwareSection(databaseService); | |||
| addActualizacionesSection(); | |||
| //correctivoLayout(); | |||
| signLayout(); | |||
| buttons(); | |||
| mainLayout.add(fechaLayout, departamentoLayout, controlsLayout, actualizacionesLayout, etiquetaLayout, firmasLayout, botonesLayout); | |||
| add(mainLayout); | |||
| } | |||
| private void createHardwareSection(DatabaseService databaseService) { | |||
| HorizontalLayout etiquetaLayout = new HorizontalLayout(); | |||
| Span etiqueta = new Span("Limpieza de Equipo Realizada"); | |||
| //Boton para agregar otro tipo de hardware | |||
| Button btnAgregarTipo = new Button(new Icon(VaadinIcon.PLUS)); | |||
| btnAgregarTipo.addThemeVariants(ButtonVariant.LUMO_ICON); | |||
| btnAgregarTipo.setAriaLabel("Agregar Tipo"); | |||
| //Listener del boton para agregar mas | |||
| btnAgregarTipo.addClickListener(event -> { | |||
| addNuevoTipo(); | |||
| }); | |||
| etiquetaLayout.add(etiqueta, btnAgregarTipo); | |||
| controlsLayout.add(etiquetaLayout); | |||
| controlsLayout.setSpacing(false); | |||
| addNuevoTipo(); | |||
| } | |||
| //Metodo para agregar un nuevo ComboBox de tipo de hardware y campos de texto | |||
| private List<HorizontalLayout> hardwareLayouts = new ArrayList<>(); | |||
| private void addNuevoTipo() { | |||
| ComboBox<TiposHardware> tipoHardware = new ComboBox<>(); | |||
| tipoHardware.setPlaceholder("Tipo de hardware"); | |||
| tipoHardware.setItemLabelGenerator(TiposHardware::getNombreHardware); | |||
| tipoHardware.setItems(databaseService.getTiposHardware()); | |||
| tipoHardware.setSizeFull(); | |||
| TextField noSerie = new TextField(); | |||
| noSerie.setEnabled(false); | |||
| noSerie.setRequired(true); | |||
| noSerie.setPlaceholder("No. Serie"); | |||
| noSerie.setSizeFull(); | |||
| noSerie.addValueChangeListener(event -> { | |||
| String upperCaseValue = event.getValue().toUpperCase(); | |||
| noSerie.setValue(upperCaseValue); | |||
| }); | |||
| // Validacion para que este campo solo acepte numeros | |||
| /*noSerie.getElement().executeJs( | |||
| "this.addEventListener('input', function(e) { " + | |||
| " e.target.value = e.target.value.replace(/[^0-9]/g, '');" + // Solo permite dígitos | |||
| "});" | |||
| );*/ | |||
| TextField modelo = new TextField(); | |||
| modelo.setEnabled(false); | |||
| modelo.setRequired(true); | |||
| modelo.setPlaceholder("Modelo"); | |||
| modelo.setSizeFull(); | |||
| modelo.addValueChangeListener(event -> { | |||
| String upperCaseValue = event.getValue().toUpperCase(); | |||
| modelo.setValue(upperCaseValue); | |||
| }); | |||
| TextField placa = new TextField(); | |||
| placa.setEnabled(false); | |||
| placa.setRequired(true); | |||
| placa.setPlaceholder("Placa"); | |||
| placa.setSizeFull(); | |||
| // Validacion para que este campo solo acepte numeros | |||
| placa.getElement().executeJs( | |||
| "this.addEventListener('input', function(e) { " + | |||
| " e.target.value = e.target.value.replace(/[^0-9]/g, '');" + // Solo permite dígitos | |||
| "});" | |||
| ); | |||
| tipoHardware.addValueChangeListener(event -> { | |||
| TiposHardware tipoSeleccionado = event.getValue(); | |||
| if (tipoSeleccionado != null) { | |||
| String nombreTipo = tipoSeleccionado.getNombreHardware(); | |||
| if ("TECLADO".equals(nombreTipo)) { | |||
| noSerie.setEnabled(false); | |||
| modelo.setEnabled(false); | |||
| placa.setEnabled(false); | |||
| } else if ("MOUSE".equals(nombreTipo)) { | |||
| noSerie.setEnabled(false); | |||
| modelo.setEnabled(false); | |||
| placa.setEnabled(false); | |||
| } else { | |||
| noSerie.setEnabled(true); | |||
| modelo.setEnabled(true); | |||
| placa.setEnabled(true); | |||
| } | |||
| } else { | |||
| noSerie.setEnabled(false); | |||
| modelo.setEnabled(false); | |||
| placa.setEnabled(false); | |||
| } | |||
| }); | |||
| //Boton para eliminar ese conjunto de hardware | |||
| Button btnEliminar = new Button(new Icon(VaadinIcon.TRASH)); | |||
| btnEliminar.addThemeVariants(ButtonVariant.LUMO_ICON, ButtonVariant.LUMO_ERROR); | |||
| btnEliminar.setAriaLabel("Eliminar Tipo"); | |||
| //Crear nuevo layout horizontal con estos campos | |||
| HorizontalLayout hardwareDetailsLayout = new HorizontalLayout(); | |||
| hardwareDetailsLayout.add(tipoHardware, noSerie, modelo, placa, btnEliminar); | |||
| hardwareDetailsLayout.setWidthFull(); | |||
| hardwareLayouts.add(hardwareDetailsLayout); | |||
| controlsLayout.add(hardwareDetailsLayout); | |||
| //Listener para eliminar el tipo | |||
| btnEliminar.addClickListener(event -> { | |||
| controlsLayout.remove(hardwareDetailsLayout); | |||
| }); | |||
| controlsLayout.add(hardwareDetailsLayout); | |||
| controlsLayout.setSizeFull(); | |||
| } | |||
| private void addActualizacionesSection() { | |||
| VerticalLayout etiquetaLayout = new VerticalLayout(); | |||
| Span Titulo = new Span("Actualizaciones de Seguridad Informatica:"); | |||
| etiquetaLayout.add(Titulo); | |||
| this.actualizaciones = new CheckboxGroup<>(); | |||
| actualizaciones.setLabel("Actualizaciones Necesarias"); | |||
| actualizaciones.setItems("S.O", "Antivirus", "Firewall"); | |||
| this.formaGroup = new RadioButtonGroup<>(); | |||
| formaGroup.setRequired(true); | |||
| formaGroup.setLabel("Actividad Realizada de Forma:"); | |||
| formaGroup.setItems("Remota", "Manual"); | |||
| this.txtCuales = new TextArea(); | |||
| txtCuales.setLabel("¿Cuales?"); | |||
| txtCuales.setEnabled(false); | |||
| txtCuales.setWidthFull(); | |||
| this.masActualizacionesGroup= new RadioButtonGroup<>(); | |||
| masActualizacionesGroup.setRequired(true); | |||
| masActualizacionesGroup.setLabel("¿Requiere Más Actualizaciones?"); | |||
| masActualizacionesGroup.setItems("Si","No"); | |||
| masActualizacionesGroup.addValueChangeListener(event -> { | |||
| if ("Si".equals(event.getValue())) { | |||
| txtCuales.setEnabled(true); | |||
| txtCuales.setRequired(true); | |||
| txtCuales.setMaxHeight("100px"); | |||
| } else { | |||
| txtCuales.setEnabled(false); | |||
| txtCuales.setRequired(false); | |||
| txtCuales.clear(); | |||
| } | |||
| }); | |||
| /*VerticalLayout actualizacionesGroup = new VerticalLayout(); | |||
| actualizacionesGroup.add(actualizaciones);*/ | |||
| HorizontalLayout formasLayout = new HorizontalLayout(); | |||
| formasLayout.add(formaGroup, masActualizacionesGroup, txtCuales); | |||
| formasLayout.setSizeFull(); | |||
| actualizacionesLayout.add(Titulo, actualizaciones, formasLayout); | |||
| actualizacionesLayout.setSpacing(false); | |||
| } | |||
| /* Formulario para cuando el mnatenimiento es de tipo CORRECTIVO */ | |||
| /*private void correctivoLayout() { | |||
| Span Titulo = new Span("Reparación Realizada al Equipo: "); | |||
| // Verificar el ID del tipo de mantenimiento | |||
| TiposMantenimiento tiposMantenimiento = tipoMantt.getValue(); | |||
| if (tiposMantenimiento != null && "2".equals(tiposMantenimiento.getTipomantId())) { // Solo si el tipo es CORRECTIVO | |||
| TextField txtModelo = new TextField(); | |||
| txtModelo.setPlaceholder("Modelo"); | |||
| txtModelo.setWidth("240px"); | |||
| NumberField txtSerie = new NumberField(); | |||
| txtSerie.setPlaceholder("No. Serie"); | |||
| txtSerie.setWidth("240px"); | |||
| TextField txtSoft = new TextField(); | |||
| txtSoft.setPlaceholder("Instalación de Software"); | |||
| txtSoft.setWidth("500px"); | |||
| TextField txtRepHard = new TextField(); | |||
| txtRepHard.setPlaceholder("Reparación de Hardware"); | |||
| txtRepHard.setWidth("500px"); | |||
| TextField txtCamDisp = new TextField(); | |||
| txtCamDisp.setPlaceholder("Cambio de Dispositivo"); | |||
| txtCamDisp.setWidth("500px"); | |||
| HorizontalLayout model = new HorizontalLayout(); | |||
| model.add(txtModelo, txtSerie, txtSoft); | |||
| model.setSizeFull(); | |||
| HorizontalLayout hard = new HorizontalLayout(); | |||
| hard.add(txtRepHard, txtCamDisp); | |||
| hard.setSizeFull(); | |||
| etiquetaLayout.add(Titulo, model, hard); | |||
| etiquetaLayout.setVisible(true); // Asegúrate de que el layout esté visible | |||
| } else { | |||
| etiquetaLayout.setVisible(false); // Ocultar si no es correctivo | |||
| } | |||
| }*/ | |||
| private String emptySignature; | |||
| private void signLayout() { | |||
| VerticalLayout userSignLayout = new VerticalLayout(); | |||
| userSignPad = new SignaturePad(); | |||
| userSignPad.setBackgroundColor("#FFFFFF"); | |||
| userSignPad.setHeight("200px"); | |||
| userSignPad.setPenColor("#000000"); | |||
| userSignPad.getElement().getStyle().set("border", "1px solid black"); | |||
| Span tituloUser = new Span("Usuario Interno"); | |||
| userSignLayout.setSizeFull(); | |||
| userSignLayout.setSpacing(true); | |||
| userSignLayout.setSpacing(false); | |||
| userSignLayout.setAlignItems(Alignment.CENTER); | |||
| userSignLayout.add(userSignPad, userSignSpan, tituloUser); | |||
| VerticalLayout smtSignLayout = new VerticalLayout(); | |||
| smtSignPad = new SignaturePad(); | |||
| smtSignPad.setHeight("200px"); | |||
| smtSignPad.setBackgroundColor("#FFFFFF"); | |||
| smtSignPad.setPenColor("#000000"); | |||
| smtSignPad.getElement().getStyle().set("border", "1px solid black"); | |||
| String u = securityService.getAuthenticatedUser(); | |||
| Span smtSignSpan = new Span(u); | |||
| Span tituloSMT = new Span("Responsable de Soporte"); | |||
| smtSignLayout.setSizeFull(); | |||
| smtSignLayout.setSpacing(true); | |||
| smtSignLayout.setSpacing(false); | |||
| smtSignLayout.setAlignItems(Alignment.CENTER); | |||
| smtSignLayout.add(smtSignPad, smtSignSpan, tituloSMT); | |||
| VerticalLayout gcialSignLayout = new VerticalLayout(); | |||
| Image firmaGcia = new Image("images/FirmaGerenteTI.png", "Firma Gerente de Sistemas"); | |||
| firmaGcia.setHeight("200px"); | |||
| firmaGcia.setWidthFull(); | |||
| Span gciatiSignSpan = new Span("Ing. Javier Patiño Martinez"); | |||
| Span tituloGerente = new Span("Gerente de T.I"); | |||
| gcialSignLayout.setSizeFull(); | |||
| gcialSignLayout.setSpacing(false); | |||
| gcialSignLayout.setAlignItems(Alignment.CENTER); | |||
| gcialSignLayout.add(firmaGcia, gciatiSignSpan, tituloGerente); | |||
| firmasLayout.add(userSignLayout, smtSignLayout, gcialSignLayout); | |||
| firmasLayout.setWidthFull(); | |||
| firmasLayout.setSpacing(false); | |||
| firmasLayout.setJustifyContentMode(JustifyContentMode.CENTER); | |||
| } | |||
| // Metodo para verificar si la firma corresponde a una cadena de firma vacia | |||
| private boolean esFirmaVacia(String firmaBase64) { | |||
| String firmaVacia = "iVBORw0KGgoAAAANSUhEUgAAAXkAAAD8CAYAAACSCdTiAAAIbElEQVR4Xu3UAQ0AIAwDQeZfNCPI+Nwc9Lp07rvjCBAgQCApMEY+2atQBAgQ+AJG3iMQIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBAw8n6AAAECYQEjHy5XNAIECBh5P0CAAIGwgJEPlysaAQIEjLwfIECAQFjAyIfLFY0AAQJG3g8QIEAgLGDkw+WKRoAAASPvBwgQIBAWMPLhckUjQICAkfcDBAgQCAsY+XC5ohEgQMDI+wECBAiEBYx8uFzRCBAgYOT9AAECBMICRj5crmgECBBYAuXtOkIWm1QAAAAASUVORK5CYII="; | |||
| return firmaBase64.equals(firmaVacia); | |||
| } | |||
| private void buttons() { | |||
| VerticalLayout buttonsLayout = new VerticalLayout(); | |||
| Button btnGuardar = new Button("Guardar", LineAwesomeIcon.SAVE.create()); | |||
| btnGuardar.addThemeVariants(ButtonVariant.LUMO_PRIMARY); | |||
| btnGuardar.addThemeVariants(ButtonVariant.LUMO_LARGE); | |||
| btnGuardar.addClickListener(event -> { | |||
| if (planAnualActual == null) { | |||
| Notification.show("No se pudo cargar el Plan Anual. Verifica el ID.", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| } | |||
| if (planAnualActual != null) { | |||
| fechaProgramada = planAnualActual.getFechaProgramada(); | |||
| fechaSeleccionada = fecha.getValue(); | |||
| boolean mismoMes = fechaSeleccionada != null && | |||
| fechaSeleccionada.getMonthValue() == fechaProgramada.getMonthValue() && | |||
| fechaSeleccionada.getYear() == fechaProgramada.getYear(); | |||
| if (!mismoMes) { | |||
| Dialog confirmDialog = new Dialog(); | |||
| Span aviso = new Span("El mantenimiento esta fuera de tiempo, justifique el motivo"); | |||
| jsutificacion = new TextArea(); | |||
| jsutificacion.setSizeFull(); | |||
| Button btnSi = new Button("Guardar",LineAwesomeIcon.SAVE_SOLID.create(), e -> { | |||
| confirmDialog.close(); | |||
| guardarMantenimiento(); | |||
| }); | |||
| btnSi.addThemeVariants(ButtonVariant.LUMO_PRIMARY); | |||
| VerticalLayout layout = new VerticalLayout(aviso, jsutificacion, btnSi); | |||
| layout.setSizeFull(); | |||
| layout.setAlignItems(Alignment.CENTER); | |||
| confirmDialog.add(layout); | |||
| confirmDialog.open(); | |||
| } else { | |||
| guardarMantenimiento(); | |||
| } | |||
| } | |||
| }); | |||
| buttonsLayout.setSizeFull(); | |||
| buttonsLayout.add(btnGuardar); | |||
| buttonsLayout.setAlignItems(Alignment.CENTER); | |||
| botonesLayout.add(buttonsLayout); | |||
| botonesLayout.setSizeFull(); | |||
| //botonesLayout.setAlignItems(Alignment.CENTER); | |||
| } | |||
| // METODO PARA ENVIAR CORREOS ELECTRONICOS | |||
| private void enviarCorreo() { | |||
| Usuario usuarioSeleccionado = usuario.getValue(); | |||
| if (usuarioSeleccionado != null && usuarioSeleccionado.getEmail() != null) { | |||
| String destinatario = usuarioSeleccionado.getEmail(); | |||
| String asunto = "MANTENIMIENTO DE EQUIPO DE COMPUTO REALIZADO"; | |||
| String cuerpo = "<html>" + | |||
| "<body>" + | |||
| "<img src='cid:image_id'/>"+ | |||
| "</body>" + | |||
| "</html>"; | |||
| String imagePath = "META-INF/resources/images/imgCorreo/correoMantt.png"; | |||
| emailService.enviarCorreo(destinatario, asunto, cuerpo, imagePath); | |||
| } else { | |||
| Notification.show("Por favor selecciona un usuario", 4000, Notification.Position.MIDDLE); | |||
| } | |||
| } | |||
| private void guardarMantenimiento() { | |||
| TiposMantenimiento tiposMantenimiento = tipoMantt.getValue(); | |||
| String tipoMantId = tiposMantenimiento != null ? tiposMantenimiento.getTipomantId() : null; | |||
| String planAnualValue = txtPlananualID.getValue(); | |||
| String justificacionValue = jsutificacion != null ? jsutificacion.getValue() : null; | |||
| String reparacionValue = null; | |||
| DepartamentosModel departamentoSeleccionado = area.getValue(); | |||
| String departamentoId = departamentoSeleccionado != null ? departamentoSeleccionado.getDepartamentoId().toString() : null; | |||
| Usuario usuarioSeleccionado = usuario.getValue(); | |||
| String empleadoId = usuarioSeleccionado != null ? usuarioSeleccionado.getEmpleadoId().toString() : null; | |||
| String equipoId = txtNombreEquipo.getValue(); | |||
| String formaSeleccionada = formaGroup.getValue(); | |||
| String formaMantt = null; | |||
| if ("Remota".equals(formaSeleccionada)) { | |||
| formaMantt = "R"; | |||
| } else if ("Manual".equals(formaSeleccionada)) { | |||
| formaMantt = "M"; | |||
| } | |||
| // Validación de campos obligatorios | |||
| if (fechaSeleccionada == null || tipoMantId == null || departamentoId == null || empleadoId == null || | |||
| equipoId == null || equipoId.trim().isEmpty() || formaMantt == null || planAnualValue == null || planAnualValue.trim().isEmpty()) { | |||
| Notification.show("Por favor, completa todos los campos requeridos", 4000, Notification.Position.MIDDLE); | |||
| return; | |||
| } | |||
| byte[] userSignatureBytes = userSignPad.getImageBase64(); | |||
| byte[] smtSignatureBytes = smtSignPad.getImageBase64(); | |||
| //byte[] gciaSignatureBytes = gciatiSignPad.getImageBase64(); | |||
| String userSignatureBase64 = Base64.getEncoder().encodeToString(userSignatureBytes); | |||
| String smtSignatureBase64 = Base64.getEncoder().encodeToString(smtSignatureBytes); | |||
| //String gciaSignatureBase64 = Base64.getEncoder().encodeToString(gciaSignatureBytes); | |||
| if (esFirmaVacia(userSignatureBase64)) userSignatureBase64 = null; | |||
| if (esFirmaVacia(smtSignatureBase64)) smtSignatureBase64 = null; | |||
| //if (esFirmaVacia(gciaSignatureBase64)) gciaSignatureBase64 = null; | |||
| // Validación de campos de hardware | |||
| List<Map<String, String>> detallesHardware = new ArrayList<>(); | |||
| for (HorizontalLayout layout : hardwareLayouts) { | |||
| ComboBox<TiposHardware> tipoHardware = (ComboBox<TiposHardware>) layout.getComponentAt(0); | |||
| TextField noSerie = (TextField) layout.getComponentAt(1); | |||
| TextField modelo = (TextField) layout.getComponentAt(2); | |||
| TextField placa = (TextField) layout.getComponentAt(3); | |||
| TiposHardware tipoSeleccionado = tipoHardware.getValue(); | |||
| if (tipoSeleccionado == null) { | |||
| Notification.show("Por favor, selecciona un tipo de hardware", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_WARNING); | |||
| return; | |||
| } | |||
| boolean esOpcional = Arrays.asList("TECLADO", "MOUSE").contains(tipoSeleccionado.getNombreHardware()); | |||
| String numSerie = noSerie.getValue(); | |||
| String modeloVal = modelo.getValue(); | |||
| String placaVal = placa.getValue(); | |||
| if (!esOpcional && (modeloVal == null || modeloVal.isEmpty() || numSerie == null || numSerie.isEmpty() || placaVal == null || placaVal.isEmpty())) { | |||
| Notification.show("Por favor, completa todos los campos de hardware.", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_WARNING); | |||
| return; | |||
| } | |||
| Map<String, String> hw = new HashMap<>(); | |||
| hw.put("tipoHardwareId", tipoSeleccionado.getTipoHardwareId()); | |||
| hw.put("numSerie", numSerie); | |||
| hw.put("modelo", modeloVal); | |||
| hw.put("placa", placaVal); | |||
| detallesHardware.add(hw); | |||
| } | |||
| Set<String> actualizacionesSeleccionadas = actualizaciones.getSelectedItems(); | |||
| String otrasActualizaciones = null; | |||
| if ("Si".equals(masActualizacionesGroup.getValue())) { | |||
| otrasActualizaciones = txtCuales.getValue(); | |||
| if (otrasActualizaciones == null || otrasActualizaciones.trim().isEmpty()) { | |||
| Notification.show("Especifica las otras actualizaciones", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_WARNING); | |||
| return; | |||
| } | |||
| } | |||
| // Una vez que validamos todos los campos del formulario, procedemos a insertar en BD | |||
| try { | |||
| int isInserted = databaseService.insertarMantenimiento(fechaSeleccionada, tipoMantId, departamentoId, empleadoId, formaMantt, equipoId, userSignatureBase64, smtSignatureBase64, planAnualValue, justificacionValue, reparacionValue); | |||
| if (isInserted <= 0) { | |||
| Notification.show("Error al guardar el mantenimiento", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| return; | |||
| } | |||
| int mantenimientoId = databaseService.getUltimoMantenimientoId(); | |||
| for (Map<String, String> hw : detallesHardware) { | |||
| boolean ok = databaseService.insertarHardware( | |||
| hw.get("tipoHardwareId"), | |||
| hw.get("numSerie"), | |||
| hw.get("modelo"), | |||
| hw.get("placa"), | |||
| mantenimientoId | |||
| ); | |||
| if (!ok) { | |||
| Notification.show("Error al insertar detalles del hardware: ", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| return; | |||
| } | |||
| } | |||
| for (String act : actualizacionesSeleccionadas) { | |||
| boolean ok = databaseService.insertActualizacionSeg(act, null, mantenimientoId); | |||
| if (!ok) { | |||
| Notification.show("Error al insertar actualización de seguridad", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| return; | |||
| } | |||
| } | |||
| if (otrasActualizaciones != null) { | |||
| boolean ok = databaseService.insertActualizacionSeg("Otras", otrasActualizaciones, mantenimientoId); | |||
| if (!ok) { | |||
| Notification.show("Error al insertar otras actualizaciones", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| return; | |||
| } | |||
| } | |||
| // === EXITO === | |||
| Notification.show("¡Mantenimiento guardado exitosamente!", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_SUCCESS); | |||
| try { | |||
| enviarCorreo(); | |||
| } catch (Exception e) { | |||
| Notification.show("Error al enviar el correo", 4000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| e.printStackTrace(); | |||
| } | |||
| // Limpiar campos | |||
| fecha.clear(); | |||
| txtPlananualID.clear(); | |||
| tipoMantt.clear(); | |||
| area.clear(); | |||
| usuario.clear(); | |||
| txtNombreEquipo.clear(); | |||
| formaGroup.clear(); | |||
| actualizaciones.clear(); | |||
| masActualizacionesGroup.clear(); | |||
| txtCuales.clear(); | |||
| userSignPad.clear(); | |||
| smtSignPad.clear(); | |||
| //gciatiSignPad.clear(); | |||
| for (HorizontalLayout layout : hardwareLayouts) { | |||
| ((ComboBox<?>) layout.getComponentAt(0)).clear(); | |||
| ((TextField) layout.getComponentAt(1)).clear(); | |||
| ((TextField) layout.getComponentAt(2)).clear(); | |||
| ((TextField) layout.getComponentAt(3)).clear(); | |||
| } | |||
| UI.getCurrent().navigate("/"); | |||
| } catch (Exception ex) { | |||
| Notification.show("Ocurrio un error inesperado: " + ex.getMessage(), 5000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| ex.printStackTrace(); | |||
| } | |||
| } | |||
| @Override | |||
| public void beforeEnter(BeforeEnterEvent beforeEnterEvent) { | |||
| String fechaParam = beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("fecha") != null | |||
| ? beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("fecha").stream().findFirst().orElse(null) | |||
| : null; | |||
| String tipoParam = beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("tipo") != null | |||
| ? beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("tipo").stream().findFirst().orElse(null) | |||
| : null; | |||
| String idParam = beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("id") != null | |||
| ? beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("id").stream().findFirst().orElse(null) | |||
| : null; | |||
| if (idParam != null) { | |||
| try { | |||
| int id = Integer.parseInt(idParam); | |||
| planAnualActual = databaseService.getPlanAnualPorId(id); | |||
| } catch (NumberFormatException e) { | |||
| planAnualActual = null; | |||
| } | |||
| } | |||
| String equipoParam = beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("nomEquipo") != null | |||
| ? beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("nomEquipo").stream().findFirst().orElse(null) | |||
| : null; | |||
| String deptoParam = beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("departamento") != null | |||
| ? beforeEnterEvent.getLocation().getQueryParameters().getParameters().get("departamento").stream().findFirst().orElse(null) | |||
| : null; | |||
| if (fechaParam != null) { | |||
| try { | |||
| LocalDate fechaActual = LocalDate.parse(fechaParam); | |||
| this.fecha.setValue(fechaActual); // Establece la fecha en el DatePicker | |||
| } catch (Exception e) { | |||
| Notification.show("Error al establecer la fecha: " + e.getMessage(), 3000, Notification.Position.MIDDLE); | |||
| } | |||
| } | |||
| // Cambiamos el valor por el ID | |||
| if ("1".equals(tipoParam)) { // 1 es para PREVENTIVO | |||
| TiposMantenimiento preventivo = tipoMantt.getDataProvider() | |||
| .fetch(new com.vaadin.flow.data.provider.Query<>()) | |||
| .filter(tipo -> "1".equals(tipo.getTipomantId())) | |||
| .findFirst() | |||
| .orElse(null); | |||
| if (preventivo != null) { | |||
| tipoMantt.setValue(preventivo); | |||
| tipoMantt.setReadOnly(true); | |||
| } | |||
| } else if ("2".equals(tipoParam)) { // 2 es para CORRECTIVO | |||
| TiposMantenimiento correctivo = tipoMantt.getDataProvider() | |||
| .fetch(new com.vaadin.flow.data.provider.Query<>()) | |||
| .filter(tipo -> "2".equals(tipo.getTipomantId())) | |||
| .findFirst() | |||
| .orElse(null); | |||
| if (correctivo != null) { | |||
| tipoMantt.setValue(correctivo); | |||
| tipoMantt.setReadOnly(true); | |||
| } | |||
| } | |||
| // Establecemos el ID desde el plan anual | |||
| if (idParam != null) { | |||
| txtPlananualID.setValue(idParam); // Establece el ID en el campo de texto | |||
| } else { | |||
| txtPlananualID.setValue("Sin ID"); // O un valor por defecto si no hay ID | |||
| } | |||
| // Establecemos el valor del campo de texto Nombre de Equipo con el parametro que viene en la url | |||
| if (equipoParam != null) { | |||
| txtNombreEquipo.setValue(equipoParam); | |||
| } else { | |||
| txtNombreEquipo.setValue("Sin nombre"); | |||
| } | |||
| // Establecemos el campo del departamento con el departamento desde el plan anual | |||
| if (deptoParam != null) { | |||
| Optional<DepartamentosModel> departamentoSeleccionado = area.getDataProvider() | |||
| .fetch(new com.vaadin.flow.data.provider.Query<>()) | |||
| .filter(departamento -> departamento.getNombre().equals(deptoParam)) | |||
| .findFirst(); | |||
| if (departamentoSeleccionado.isPresent()) { | |||
| area.setValue(departamentoSeleccionado.get()); | |||
| area.setReadOnly(true); | |||
| } else { | |||
| area.setValue(null); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,950 @@ | |||
| package mx.gob.jumapacelaya.ui; | |||
| import com.vaadin.flow.component.Component; | |||
| import com.vaadin.flow.component.UI; | |||
| import com.vaadin.flow.component.button.Button; | |||
| import com.vaadin.flow.component.button.ButtonVariant; | |||
| import com.vaadin.flow.component.checkbox.Checkbox; | |||
| import com.vaadin.flow.component.checkbox.CheckboxGroup; | |||
| import com.vaadin.flow.component.checkbox.CheckboxGroupVariant; | |||
| import com.vaadin.flow.component.combobox.ComboBox; | |||
| import com.vaadin.flow.component.confirmdialog.ConfirmDialog; | |||
| import com.vaadin.flow.component.datepicker.DatePicker; | |||
| import com.vaadin.flow.component.dependency.CssImport; | |||
| import com.vaadin.flow.component.dialog.Dialog; | |||
| import com.vaadin.flow.component.formlayout.FormLayout; | |||
| import com.vaadin.flow.component.grid.Grid; | |||
| import com.vaadin.flow.component.grid.GridVariant; | |||
| import com.vaadin.flow.component.grid.HeaderRow; | |||
| import com.vaadin.flow.component.grid.contextmenu.GridContextMenu; | |||
| import com.vaadin.flow.component.grid.contextmenu.GridMenuItem; | |||
| import com.vaadin.flow.component.grid.dataview.GridListDataView; | |||
| import com.vaadin.flow.component.html.*; | |||
| import com.vaadin.flow.component.icon.Icon; | |||
| import com.vaadin.flow.component.icon.VaadinIcon; | |||
| import com.vaadin.flow.component.notification.Notification; | |||
| import com.vaadin.flow.component.notification.NotificationVariant; | |||
| import com.vaadin.flow.component.orderedlayout.HorizontalLayout; | |||
| import com.vaadin.flow.component.orderedlayout.VerticalLayout; | |||
| import com.vaadin.flow.component.popover.Popover; | |||
| import com.vaadin.flow.component.popover.PopoverPosition; | |||
| import com.vaadin.flow.component.radiobutton.RadioButtonGroup; | |||
| import com.vaadin.flow.component.textfield.NumberField; | |||
| import com.vaadin.flow.component.textfield.TextField; | |||
| import com.vaadin.flow.component.upload.Upload; | |||
| import com.vaadin.flow.component.upload.receivers.MemoryBuffer; | |||
| import com.vaadin.flow.data.value.ValueChangeMode; | |||
| import com.vaadin.flow.function.ValueProvider; | |||
| import com.vaadin.flow.router.PageTitle; | |||
| import com.vaadin.flow.router.Route; | |||
| import com.vaadin.flow.server.StreamRegistration; | |||
| import com.vaadin.flow.server.StreamResource; | |||
| import jakarta.annotation.security.PermitAll; | |||
| import mx.gob.jumapacelaya.models.PlanAnual; | |||
| import mx.gob.jumapacelaya.services.DatabaseService; | |||
| import mx.gob.jumapacelaya.services.ReportService; | |||
| import net.sf.jasperreports.engine.JasperFillManager; | |||
| import net.sf.jasperreports.engine.JasperPrint; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.apache.poi.ss.usermodel.*; | |||
| import org.springframework.core.env.Environment; | |||
| import org.springframework.security.core.Authentication; | |||
| import org.springframework.security.core.context.SecurityContextHolder; | |||
| import org.vaadin.lineawesome.LineAwesomeIcon; | |||
| import java.io.*; | |||
| import java.lang.reflect.Array; | |||
| import java.sql.Date; | |||
| import java.time.LocalDate; | |||
| import java.time.Year; | |||
| import java.time.format.DateTimeFormatter; | |||
| import java.util.*; | |||
| import java.util.function.Consumer; | |||
| @PermitAll | |||
| @PageTitle("Plan Anual de Mantenimiento") | |||
| @Route(value = "/", layout = MainLayout.class) | |||
| @CssImport("./themes/sistema-mantenimiento/styles.css") | |||
| public class PlanAnualView extends VerticalLayout { | |||
| private final Environment env; | |||
| private final ReportService reportService; | |||
| H4 titulo = new H4(); | |||
| H5 titulo1 = new H5(); | |||
| Button btnInsertar; | |||
| private byte[] fileContent; | |||
| VerticalLayout gridLayout = new VerticalLayout(); | |||
| HorizontalLayout uploadLayout = new HorizontalLayout(); | |||
| HorizontalLayout filtrosLayout = new HorizontalLayout(); | |||
| private final DatabaseService databaseService; | |||
| Grid<PlanAnual> planAnualGrid; | |||
| Button btnColumns; | |||
| Button btnImprimirRpt; | |||
| Button btnAddEquipo; | |||
| HorizontalLayout btnImprimirLayout; | |||
| private Popover reportePopover; | |||
| public PlanAnualView(DatabaseService databaseService, Environment env, ReportService reportService) { | |||
| this.databaseService = databaseService; | |||
| this.env = env; | |||
| this.reportService = reportService; | |||
| setupHeader(); | |||
| Grid<PlanAnual> planAnualGrid = setupGrid(); | |||
| // Notificación de conexión activa | |||
| String perfil = String.join(",", env.getActiveProfiles()); | |||
| String url = env.getProperty("db.url"); | |||
| Notification.show("Conectado a: " + perfil + "\nURL DB: " + url, 5000, Notification.Position.BOTTOM_START); | |||
| // Obtenemos la lista de items y establecemos un GridListDataView para gestionar | |||
| // los datos | |||
| List<PlanAnual> planAnualItems = databaseService.getPlanAnual(); | |||
| GridListDataView<PlanAnual> dataView = planAnualGrid.setItems(planAnualItems); | |||
| // Se crea el filtro para el grid. | |||
| PlanAnualFilter planAnualFilter = new PlanAnualFilter(dataView); | |||
| planAnualFilter.setExcludeRealizado(true); | |||
| HeaderRow headerRow = planAnualGrid.appendHeaderRow(); | |||
| /*headerRow.getCell(planAnualGrid.getColumnByKey("smtColumnKey")) | |||
| .setComponent(createFilterHeader("S.M.T", planAnualFilter::setSmt));*/ | |||
| headerRow.getCell(planAnualGrid.getColumnByKey("equipo")) | |||
| .setComponent(createFilterHeader("Equipo", planAnualFilter::setEquipo)); | |||
| headerRow.getCell(planAnualGrid.getColumnByKey("departamento")) | |||
| .setComponent(createFilterHeader("Departamento", planAnualFilter::setDepartamento)); | |||
| headerRow.getCell(planAnualGrid.getColumnByKey("mesplaneado")) | |||
| .setComponent(createFilterHeader("Mes Planeado", planAnualFilter::setMesPlaneado)); | |||
| // MENU CONTEXTUAL DEL GRID | |||
| PersonContextMenu contextMenu = new PersonContextMenu(planAnualGrid); | |||
| // Componente UPLOAD para subir archivos | |||
| MemoryBuffer buffer = new MemoryBuffer(); | |||
| Upload upload = new Upload(); | |||
| upload.setAcceptedFileTypes(".xls", ".xlsx"); | |||
| upload.setMaxFiles(1); | |||
| upload.setDropLabel(new com.vaadin.flow.component.html.Span("Arrastra un archivo Excel aquí o selecciona uno")); | |||
| upload.addSucceededListener(event -> { | |||
| try { | |||
| // Almacena el contenido del archivo en un arreglo de bytes | |||
| try (InputStream inputStream = buffer.getInputStream(); | |||
| ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { | |||
| inputStream.transferTo(byteArrayOutputStream); | |||
| fileContent = byteArrayOutputStream.toByteArray(); | |||
| } | |||
| // Validación del archivo cargado | |||
| List<String> errores = validarExcel(new ByteArrayInputStream(fileContent)); | |||
| if (!errores.isEmpty()) { | |||
| // Crear notificación con mensaje de error y sin duración | |||
| final Notification ntfError = new Notification(); | |||
| ntfError.setText("Errores en el archivo: " + String.join(", ", errores)); | |||
| ntfError.setDuration(0); // La notificación no se cerrará automáticamente | |||
| ntfError.setPosition(Notification.Position.MIDDLE); | |||
| ntfError.addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| // Texto del mensaje de error | |||
| Span errorMessage = new Span("Errores en el archivo: " + String.join(", ", errores)); | |||
| errorMessage.getStyle().set("margin-right", "10px"); | |||
| // Crear botón de cierre | |||
| final Button closeButton = new Button(new Icon(VaadinIcon.CLOSE)); | |||
| closeButton.addClickListener(e -> ntfError.close()); | |||
| // Agregar el mensaje y el botón de cierre a la notificación | |||
| HorizontalLayout notificationLayout = new HorizontalLayout(errorMessage, closeButton); | |||
| ntfError.add(notificationLayout); | |||
| ntfError.open(); // Abrir la notificación en pantalla | |||
| // Ocultar el botón de insertar si hay errores | |||
| btnInsertar.setVisible(false); | |||
| } else { | |||
| btnInsertar.setVisible(true); | |||
| } | |||
| } catch (IOException e) { | |||
| Notification.show("Error al leer el archivo: " + e.getMessage()) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| } | |||
| }); | |||
| btnInsertar = new Button("Insertar archivo", event -> insertarDatos()); | |||
| btnInsertar.setVisible(false); | |||
| gridLayout.add(btnImprimirLayout,planAnualGrid); | |||
| gridLayout.setSizeFull(); | |||
| uploadLayout.add(upload, btnInsertar); | |||
| toggleLayouts(dataView); | |||
| filtrosLayout.addClassNames("lumo-justify-content-center", "lumo-gap-m", "lumo-padding-s"); | |||
| filtrosLayout.setWidthFull(); | |||
| filtrosLayout.setJustifyContentMode(JustifyContentMode.CENTER); | |||
| Button btnPendientes = new Button("Pendientes", VaadinIcon.CLOCK.create()); | |||
| Button btnRealizados = new Button("Realizados", VaadinIcon.CHECK_CIRCLE.create()); | |||
| btnPendientes.addClassName("selected-tab"); | |||
| btnPendientes.addClickListener(e -> { | |||
| planAnualFilter.setExcludeRealizado(true); | |||
| btnPendientes.addClassName("selected-tab"); | |||
| btnRealizados.removeClassName("selected-tab"); | |||
| }); | |||
| btnRealizados.addClickListener(e -> { | |||
| planAnualFilter.setExcludeRealizado(false); | |||
| btnRealizados.addClassName("selected-tab"); | |||
| btnPendientes.removeClassName("selected-tab"); | |||
| }); | |||
| filtrosLayout.add(btnPendientes, btnRealizados); | |||
| mostrarPopoverReportes(); | |||
| this.setPadding(false); | |||
| this.setMargin(false); | |||
| this.setSpacing(false); | |||
| this.setSizeFull(); | |||
| add(filtrosLayout, gridLayout, uploadLayout); | |||
| } | |||
| private void setupHeader() { | |||
| VerticalLayout headerLayout = new VerticalLayout(); | |||
| headerLayout.addClassName("plan-anual-header"); | |||
| titulo.addClassName("plan-anual-titulo"); | |||
| titulo1.addClassName("plan-anual-titulo1"); | |||
| titulo.setText("Plan Anual de Mantenimiento Preventivo de Equipo de Computo"); | |||
| titulo1.setText(Year.now().toString()); | |||
| TextField nomenclaturaTxt = new TextField(); | |||
| nomenclaturaTxt.setValue("FR01-PA-7.1.3-02"); | |||
| nomenclaturaTxt.setReadOnly(true); | |||
| nomenclaturaTxt.addClassName("nomenclatura-txt"); | |||
| headerLayout.add(titulo, titulo1); | |||
| headerLayout.setAlignItems(Alignment.CENTER); | |||
| add(headerLayout); | |||
| } | |||
| private Grid<PlanAnual> setupGrid() { | |||
| planAnualGrid = new Grid<>(PlanAnual.class, false); | |||
| planAnualGrid.addColumn((ValueProvider<PlanAnual, Integer>) PlanAnual::getNumero) | |||
| .setHeader("No.").setSortable(true).setAutoWidth(true).setFrozen(true); | |||
| // Botón condicional | |||
| planAnualGrid.addComponentColumn(planAnual -> { | |||
| String estado = planAnual.getEstado(); | |||
| Button btn; | |||
| if ("PENDIENTE".equalsIgnoreCase(estado)) { | |||
| btn = new Button(new Icon(VaadinIcon.EDIT)); | |||
| btn.setTooltipText("Realizar mantenimiento"); | |||
| btn.getStyle().set("color", "#A02142"); | |||
| btn.addClickListener(event -> { | |||
| int idPlananual = planAnual.getNumero(); | |||
| LocalDate fechaSistema = LocalDate.now(); | |||
| String nomEquipo = planAnual.getNomEquipo(); | |||
| String departamento = planAnual.getDepartamento(); | |||
| btn.getUI().ifPresent(ui -> ui.navigate( | |||
| "mantenimiento?id=" + idPlananual + | |||
| "&fecha=" + fechaSistema + | |||
| "&tipo=1" + | |||
| "&nomEquipo=" + nomEquipo + | |||
| "&departamento=" + departamento)); | |||
| }); | |||
| } else if ("REALIZADO".equalsIgnoreCase(estado)) { | |||
| btn = new Button(new Icon(VaadinIcon.EYE)); | |||
| btn.setTooltipText("Ver detalles"); | |||
| btn.getStyle().set("color", "#A02142"); | |||
| btn.addClickListener(event -> { | |||
| int idPlananual = planAnual.getNumero(); | |||
| btn.getUI().ifPresent(ui -> ui.navigate( | |||
| "detalles?id=" + idPlananual)); | |||
| }); | |||
| } else { | |||
| btn = new Button("N/A"); | |||
| btn.setEnabled(false); | |||
| } | |||
| return btn; | |||
| }).setAutoWidth(true).setFrozen(true); | |||
| planAnualGrid.addColumn((ValueProvider<PlanAnual, String>) PlanAnual::getNomEquipo) | |||
| .setHeader("Equipo").setAutoWidth(true).setKey("equipo"); | |||
| planAnualGrid.addColumn((ValueProvider<PlanAnual, String>) PlanAnual::getDepartamento) | |||
| .setHeader("Departamento").setAutoWidth(true).setKey("departamento"); | |||
| planAnualGrid.addColumn(planAnual -> { | |||
| String mesPlaneado = planAnual.getMesplaneado(); | |||
| return mesPlaneado != null ? mesPlaneado.toUpperCase() : "N/A"; | |||
| }).setHeader("Mes Planeado").setAutoWidth(true).setKey("mesplaneado"); | |||
| // Fechas formateadas | |||
| planAnualGrid.addColumn(planAnual -> { | |||
| LocalDate fecha = planAnual.getFechaProgramada(); | |||
| return fecha != null ? fecha.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")) : "No programada"; | |||
| }).setHeader("Fecha Programada").setAutoWidth(true).setSortable(true).setKey("fechaProgramada"); | |||
| planAnualGrid.addColumn(planAnual -> { | |||
| LocalDate fecha = planAnual.getFechaMantenimiento(); | |||
| return fecha != null ? fecha.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")) : ""; | |||
| }).setHeader("Fecha Realización").setAutoWidth(true).setSortable(true).setKey("fechaMantenimiento"); | |||
| planAnualGrid.addColumn((ValueProvider<PlanAnual, String>) PlanAnual::getEstado) | |||
| .setHeader("Estado").setAutoWidth(true).setKey("estado"); | |||
| planAnualGrid.addColumn((ValueProvider<PlanAnual, String>) PlanAnual::getSituacion) | |||
| .setHeader("Situación").setAutoWidth(true).setKey("situacion"); | |||
| /*planAnualGrid.addColumn((ValueProvider<PlanAnual, String>) PlanAnual::getSmt) | |||
| .setHeader("S.M.T").setKey("smtColumnKey");*/ | |||
| // Iconos en columnas booleanas | |||
| planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isMonitor())).setHeader("Monitor").setKey("monitor"); | |||
| planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isTeclado())).setHeader("Teclado").setKey("teclado"); | |||
| planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isMouse())).setHeader("Mouse").setKey("mouse"); | |||
| planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isRegulador())).setHeader("Regulador").setKey("regulador"); | |||
| planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isCpu())).setHeader("CPU").setKey("cpu"); | |||
| planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isImpresora())).setHeader("Impresora").setKey("impresora"); | |||
| planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isMiniPrint())).setHeader("MiniPrint").setKey("miniprint"); | |||
| planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isLaptop())).setHeader("Laptop").setKey("laptop"); | |||
| planAnualGrid.addComponentColumn(planAnual -> getIcon(planAnual.isEscaner())).setHeader("Escáner").setKey("escaner"); | |||
| planAnualGrid.addThemeVariants(GridVariant.LUMO_WRAP_CELL_CONTENT); | |||
| planAnualGrid.addThemeVariants(GridVariant.LUMO_ROW_STRIPES); | |||
| btnColumns = new Button(VaadinIcon.GRID_H.create()); | |||
| btnColumns.addThemeVariants(ButtonVariant.LUMO_ICON); | |||
| btnColumns.setAriaLabel("Show/Hide Columns"); | |||
| btnColumns.setTooltipText("Show/Hide Columns"); | |||
| btnImprimirRpt = new Button(VaadinIcon.PRINT.create()); | |||
| btnImprimirRpt.addClickListener(event -> reportePopover.open()); | |||
| btnImprimirRpt.setTooltipText("Imprimir reporte"); | |||
| btnAddEquipo = new Button(VaadinIcon.PLUS.create()); | |||
| btnAddEquipo.addClickListener(event -> addNuevoEquipo()); | |||
| btnAddEquipo.setTooltipText("Agregar nuevo equipo"); | |||
| btnImprimirLayout = new HorizontalLayout(btnColumns, btnImprimirRpt, btnAddEquipo); | |||
| HorizontalLayout columnSelectorLayout = new HorizontalLayout(); | |||
| columnSelectorLayout.setAlignItems(Alignment.END); | |||
| Popover popover = new Popover(); | |||
| popover.setModal(true); | |||
| popover.setBackdropVisible(true); | |||
| popover.setPosition(PopoverPosition.BOTTOM_END); | |||
| popover.setTarget(btnColumns); | |||
| Div heading = new Div("Ver/Ocultar columnas"); | |||
| heading.getStyle().set("font-weight", "600"); | |||
| heading.getStyle().set("padding", "var(--lumo-space-xs)"); | |||
| List<String> columns = List.of("equipo", "departamento", "mesplaneado", "fechaProgramada", | |||
| "fechaMantenimiento", "estado", "situacion", "monitor", "teclado", "mouse", "regulador", | |||
| "cpu", "impresora", "miniprint", "laptop", "escaner"); | |||
| CheckboxGroup<String> chkColumns = new CheckboxGroup<>(); | |||
| chkColumns.addThemeVariants(CheckboxGroupVariant.LUMO_VERTICAL); | |||
| chkColumns.setItems(columns); | |||
| chkColumns.setItemLabelGenerator((item) -> { | |||
| String label = StringUtils | |||
| .join(StringUtils.splitByCharacterTypeCamelCase(item), " "); | |||
| return StringUtils.capitalize(label.toLowerCase()); | |||
| }); | |||
| chkColumns.addValueChangeListener((e) -> { | |||
| columns.forEach((key) -> { | |||
| Grid.Column<?> col = planAnualGrid.getColumnByKey(key); | |||
| if (col != null) { | |||
| col.setVisible(e.getValue().contains(key)); | |||
| } else { | |||
| System.out.println("Columna no encontrada para key: " + key); | |||
| } | |||
| }); | |||
| }); | |||
| Set<String> defaultColumns = Set.of("equipo", "departamento", "mesplaneado", | |||
| "fechaProgramada", "fechaMantenimiento", "estado", "situacion"); | |||
| chkColumns.setValue(defaultColumns); | |||
| popover.add(heading, chkColumns); | |||
| // Cargar datos | |||
| planAnualGrid.setItems(databaseService.getPlanAnual()); | |||
| return planAnualGrid; | |||
| } | |||
| /* | |||
| * (∩ ͡° ͜ʖ ͡°)⊃━☆゚. * SUSTITUIR VALORES BOOLEANOS POR UN ICONO (∩ ͡° ͜ʖ | |||
| * ͡°)⊃━☆゚. * | |||
| */ | |||
| private Icon getIcon(boolean value) { | |||
| if (value) { | |||
| return new Icon(VaadinIcon.CHECK_CIRCLE); | |||
| } else { | |||
| return new Icon(); | |||
| } | |||
| } | |||
| /* | |||
| * (∩ ͡° ͜ʖ ͡°)⊃━☆゚. * METODO PARA VALIDAR QUE EL ARCHIOVO TENGA LA ESTRUCTURA | |||
| * CORRECTA (∩ ͡° ͜ʖ ͡°)⊃━☆゚. * | |||
| */ | |||
| private List<String> validarExcel(InputStream inputStream) throws IOException { | |||
| List<String> errores = new ArrayList<>(); | |||
| Workbook workbook = WorkbookFactory.create(inputStream); | |||
| Sheet sheet = workbook.getSheetAt(0); | |||
| // Lista de nombres de columnas esperados en el encabezado | |||
| List<String> columnas = Arrays.asList("NOMEQUIPO", "DEPARTAMENTO", "MONITOR", "TECLADO", "MOUSE", "REGULADOR", | |||
| "CPU", "IMPRESORA", "MINIPRINT", "LAPTOP", "ESCANER", "FECHAPROG", "TECNICO", "ESTADO"); | |||
| // Obtener la primera fila como encabezado | |||
| Row headerRow = sheet.getRow(0); | |||
| if (headerRow != null) { | |||
| // Validar que cada celda en el encabezado tiene el nombre correcto | |||
| for (int i = 0; i < headerRow.getPhysicalNumberOfCells(); i++) { | |||
| Cell cell = headerRow.getCell(i); | |||
| if (cell != null) { // Verificar si la celda no es null antes de acceder a su valor | |||
| String columnName = cell.getStringCellValue(); | |||
| if (!columnas.contains(columnName)) { | |||
| errores.add("Columna inesperada: " + columnName); | |||
| } | |||
| } else { | |||
| errores.add("Celda vacía en la columna de índice " + i); | |||
| } | |||
| } | |||
| } else { | |||
| errores.add("La hoja no contiene un encabezado en la primera fila."); | |||
| } | |||
| // Verificar si faltan columnas esperadas en el encabezado | |||
| for (String columnName : columnas) { | |||
| boolean found = false; | |||
| if (headerRow != null) { | |||
| for (int i = 0; i < headerRow.getPhysicalNumberOfCells(); i++) { | |||
| Cell cell = headerRow.getCell(i); | |||
| if (cell != null && cell.getStringCellValue().equals(columnName)) { | |||
| found = true; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| if (!found) { | |||
| errores.add("Falta la columna: " + columnName); | |||
| } | |||
| } | |||
| workbook.close(); | |||
| return errores; | |||
| } | |||
| // Valida que haya un archivo cargado en el UPLOAD y si si, llama al metodo para | |||
| // insertar el archivo en la base de datos | |||
| private void insertarDatos() { | |||
| if (fileContent == null) { | |||
| Notification.show("Error: No hay archivo cargado.").addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| return; | |||
| } | |||
| try (InputStream inputStream = new ByteArrayInputStream(fileContent)) { | |||
| databaseService.insertarDesdeExcel(inputStream); | |||
| Notification.show("Archivo insertado correctamente").addThemeVariants(NotificationVariant.LUMO_SUCCESS); | |||
| btnInsertar.setVisible(false); // Ocultar el botón después de la inserción | |||
| } catch (Exception e) { | |||
| Notification.show("Error al insertar el archivo: " + e.getMessage()) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| } | |||
| } | |||
| private static Component createFilterHeader(String labelText, Consumer<String> filterChangeConsumer) { | |||
| TextField textField = new TextField(); | |||
| textField.setPlaceholder("Buscar..."); | |||
| textField.setValueChangeMode(ValueChangeMode.EAGER); | |||
| textField.setClearButtonVisible(true); | |||
| textField.setWidthFull(); | |||
| textField.addValueChangeListener(event -> filterChangeConsumer.accept(event.getValue())); | |||
| VerticalLayout layout = new VerticalLayout(textField); | |||
| layout.setSpacing(false); | |||
| layout.setPadding(false); | |||
| return layout; | |||
| } | |||
| private static class PlanAnualFilter { | |||
| private final GridListDataView<PlanAnual> dataView; | |||
| private String smt; | |||
| private String equipo; | |||
| private String departamento; | |||
| private String mesPlaneado; | |||
| private boolean excludeRealizado = true; | |||
| public PlanAnualFilter(GridListDataView<PlanAnual> dataView) { | |||
| this.dataView = dataView; | |||
| this.dataView.addFilter(this::test); | |||
| } | |||
| public void setSmt(String smt) { | |||
| this.smt = smt; | |||
| this.dataView.refreshAll(); | |||
| } | |||
| public void setEquipo(String equipo) { | |||
| this.equipo = equipo; | |||
| this.dataView.refreshAll(); | |||
| } | |||
| public void setDepartamento(String departamento) { | |||
| this.departamento = departamento; | |||
| this.dataView.refreshAll(); | |||
| } | |||
| public void setMesPlaneado(String mesPlaneado) { | |||
| this.mesPlaneado = mesPlaneado; | |||
| this.dataView.refreshAll(); | |||
| } | |||
| public void setExcludeRealizado(boolean excludeRealizado) { | |||
| this.excludeRealizado = excludeRealizado; | |||
| this.dataView.refreshAll(); | |||
| } | |||
| public boolean test(PlanAnual planAnual) { | |||
| if (planAnual == null) { | |||
| return false; // Avoid NullPointerException | |||
| } | |||
| boolean matchesSmt = matches(planAnual.getSmt(), smt); | |||
| boolean matchesEquipo = matches(planAnual.getNomEquipo(), equipo); | |||
| boolean matchesDepartamento = matches(planAnual.getDepartamento(), departamento); | |||
| boolean matchesMesPlaneado = matches(planAnual.getMesplaneado(), mesPlaneado); | |||
| if (excludeRealizado) { | |||
| // Mostrar solo los pendientes | |||
| return matchesSmt && matchesEquipo && matchesDepartamento && matchesMesPlaneado | |||
| && (planAnual.getEstado() == null || !"REALIZADO".equalsIgnoreCase(planAnual.getEstado())); | |||
| } else { | |||
| // Mostrar solo realizados | |||
| return matchesSmt && matchesEquipo && matchesDepartamento && matchesMesPlaneado | |||
| && "REALIZADO".equalsIgnoreCase(planAnual.getEstado()); | |||
| } | |||
| } | |||
| private boolean matches(String value, String searchTerm) { | |||
| return searchTerm == null || searchTerm.isEmpty() | |||
| || value.toLowerCase().contains(searchTerm.toLowerCase()); | |||
| } | |||
| } | |||
| // Aqui validamos que haya registros en el plan anual y si no hay muestra el | |||
| // upload para cargar un nuevo plan anual | |||
| private void toggleLayouts(GridListDataView<PlanAnual> dataView) { | |||
| boolean hasItems = dataView.getItemCount() > 0; | |||
| gridLayout.setVisible(hasItems); | |||
| uploadLayout.setVisible(!hasItems); | |||
| } | |||
| private void sacarReporte() { | |||
| Dialog dialog = new Dialog(); | |||
| dialog.setHeaderTitle("Seleccione la fecha de inicio y fin"); | |||
| DatePicker.DatePickerI18n i18n = new DatePicker.DatePickerI18n() | |||
| .setWeekdays(List.of("Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sabado")) | |||
| .setWeekdaysShort(List.of("Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb")) | |||
| .setMonthNames(List.of("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre")) | |||
| .setFirstDayOfWeek(1) | |||
| .setToday("Hoy") | |||
| .setCancel("Cancelar") | |||
| .setDateFormat("dd/MM/yyyy"); | |||
| DatePicker fechaInicio = new DatePicker("Fecha de inicio:"); | |||
| fechaInicio.setRequired(true); | |||
| fechaInicio.setI18n(i18n); | |||
| DatePicker fechaFin = new DatePicker("Fecha de fin:"); | |||
| fechaFin.setRequired(true); | |||
| fechaFin.setI18n(i18n); | |||
| Button btnGenerar = new Button("Generar", VaadinIcon.PRINT.create()); | |||
| btnGenerar.addThemeVariants(ButtonVariant.LUMO_PRIMARY); | |||
| btnGenerar.addClickListener(e -> { | |||
| if (fechaInicio.getValue() == null || fechaFin.getValue() == null) { | |||
| Notification.show("Por favor, seleccione ambas fechas.", 3000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| return; | |||
| } | |||
| LocalDate inicio = fechaInicio.getValue(); | |||
| LocalDate fin = fechaFin.getValue(); | |||
| try { | |||
| // Prepara los parámetros para el reporte | |||
| Map<String, Object> parametros = new HashMap<>(); | |||
| parametros.put("FECHAINICIO", java.sql.Date.valueOf(inicio)); | |||
| parametros.put("FECHAFIN", java.sql.Date.valueOf(fin)); | |||
| // Genera el PDF | |||
| byte[] pdf = reportService.generarReporte("mantenimientoFechas", parametros); | |||
| // Creando el recurso de descarga | |||
| StreamResource resource = new StreamResource("reporte.pdf", () -> new ByteArrayInputStream(pdf)); | |||
| /*Anchor downloadLink = new Anchor(resource, "Descargar Reporte"); | |||
| downloadLink.setTarget("_blank"); | |||
| downloadLink.setId("descargar-reporte-link"); | |||
| add(downloadLink); | |||
| getUI().ifPresent(ui -> | |||
| ui.getPage().executeJs("document.getElementById('descargar-reporte-link').click();") | |||
| );*/ | |||
| StreamRegistration registration = UI.getCurrent().getSession().getResourceRegistry().registerResource(resource); | |||
| UI.getCurrent().getPage().executeJs("window.open('" + registration.getResourceUri().toString() + "','_blank')"); | |||
| } catch (Exception ex) { | |||
| Notification.show("Error al genrar el reporte: " + ex.getMessage(), 5000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| ex.printStackTrace(); | |||
| } | |||
| }); | |||
| Button btnCancelar = new Button("Cancelar", VaadinIcon.CLOSE_CIRCLE.create(), e -> dialog.close()); | |||
| dialog.getFooter().add(btnCancelar); | |||
| dialog.getFooter().add(btnGenerar); | |||
| HorizontalLayout fechasLayout = new HorizontalLayout(fechaInicio, fechaFin); | |||
| dialog.add(fechasLayout); | |||
| dialog.open(); | |||
| } | |||
| private void addNuevoEquipo() { | |||
| Dialog dialog = new Dialog(); | |||
| dialog.setHeaderTitle("Agregar nuevo equipo"); | |||
| TextField nombreEquipo = new TextField("Nombre equipo:"); | |||
| TextField area = new TextField("Área:"); | |||
| DatePicker.DatePickerI18n i18n = new DatePicker.DatePickerI18n() | |||
| .setWeekdays(List.of("Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sabado")) | |||
| .setWeekdaysShort(List.of("Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb")) | |||
| .setMonthNames(List.of("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre")) | |||
| .setFirstDayOfWeek(1) | |||
| .setToday("Hoy") | |||
| .setCancel("Cancelar") | |||
| .setDateFormat("dd/MM/yyyy"); | |||
| DatePicker fechaProgramada = new DatePicker("Fecha programada:"); | |||
| fechaProgramada.setI18n(i18n); | |||
| List<String> items = List.of("ENERO", "FEBRERO", "MARZO", "ABRIL", "MAYO", "JUNIO", | |||
| "JULIO", "AGOSTO", "SEPTIEMBRE", "OCTUBRE", "NOVIEMBRE", "DICIEMBRE"); | |||
| ComboBox<String> cmbMes = new ComboBox<>("Mes Planeado:"); | |||
| cmbMes.setItems(items); | |||
| CheckboxGroup<String> group1 = new CheckboxGroup<>(); | |||
| group1.setLabel("Seleccione los componentes del equipo"); | |||
| group1.setItems("MONITOR","TECLADO","MOUSE","REGULADOR"); | |||
| CheckboxGroup<String> group2 = new CheckboxGroup<>(); | |||
| group2.setItems("CPU","IMPRESORA","MINIPRINT","LAPTOP","ESCANER"); | |||
| HorizontalLayout layout1 = new HorizontalLayout(nombreEquipo, area); | |||
| HorizontalLayout layout2 = new HorizontalLayout(fechaProgramada,cmbMes); | |||
| VerticalLayout layout3 = new VerticalLayout(group1,group2); | |||
| layout3.setSpacing(false); | |||
| Button btnGuardar = new Button("Guardar", LineAwesomeIcon.SAVE_SOLID.create()); | |||
| btnGuardar.addThemeVariants(ButtonVariant.LUMO_PRIMARY); | |||
| btnGuardar.addClickListener(e -> { | |||
| if (nombreEquipo.getValue().isEmpty() || area.getValue().isEmpty() || | |||
| fechaProgramada.getValue() == null || cmbMes.getValue() == null) { | |||
| Notification.show("Por favor, complete todos los campos.", 3000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| return; | |||
| } | |||
| final Map<String, Integer> MES_ID_MAP = new HashMap<>(); | |||
| MES_ID_MAP.put("ENERO", 1); | |||
| MES_ID_MAP.put("FEBRERO", 2); | |||
| MES_ID_MAP.put("MARZO", 3); | |||
| MES_ID_MAP.put("ABRIL", 4); | |||
| MES_ID_MAP.put("MAYO", 5); | |||
| MES_ID_MAP.put("JUNIO", 6); | |||
| MES_ID_MAP.put("JULIO", 7); | |||
| MES_ID_MAP.put("AGOSTO", 8); | |||
| MES_ID_MAP.put("SEPTIEMBRE", 9); | |||
| MES_ID_MAP.put("OCTUBRE", 10); | |||
| MES_ID_MAP.put("NOVIEMBRE", 11); | |||
| MES_ID_MAP.put("DICIEMBRE", 12); | |||
| String mesSeleccionado = cmbMes.getValue(); | |||
| Integer mesId = MES_ID_MAP.get(mesSeleccionado); | |||
| if (group1.getValue().isEmpty() && group2.getValue().isEmpty()) { | |||
| Notification.show("Debe seleccionar al menos un componente del equipo.", 3000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| return; | |||
| } | |||
| Set<String> seleccionados = new HashSet<>(); | |||
| seleccionados.addAll(group1.getValue()); | |||
| seleccionados.addAll(group2.getValue()); | |||
| boolean monitor = seleccionados.contains("MONITOR"); | |||
| boolean teclado = seleccionados.contains("TECLADO"); | |||
| boolean mouse = seleccionados.contains("MOUSE"); | |||
| boolean regulador = seleccionados.contains("REGULADOR"); | |||
| boolean cpu = seleccionados.contains("CPU"); | |||
| boolean impresora = seleccionados.contains("IMPRESORA"); | |||
| boolean miniprint = seleccionados.contains("MINIPRINT"); | |||
| boolean laptop = seleccionados.contains("LAPTOP"); | |||
| boolean escaner = seleccionados.contains("ESCANER"); | |||
| databaseService.insertarNuevoEquipo( | |||
| nombreEquipo.getValue().toUpperCase(), | |||
| area.getValue().toUpperCase(), | |||
| monitor, | |||
| teclado, | |||
| mouse, | |||
| regulador, | |||
| cpu, | |||
| impresora, | |||
| miniprint, | |||
| laptop, | |||
| escaner, | |||
| java.sql.Date.valueOf(fechaProgramada.getValue()), | |||
| "", | |||
| "PENDIENTE", | |||
| mesId | |||
| ); | |||
| Notification.show("Equipo agregado correctamente", 3000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_SUCCESS); | |||
| dialog.close(); | |||
| // Recargar el grid para mostrar el nuevo equipo | |||
| planAnualGrid.setItems(databaseService.getPlanAnual()); | |||
| }); | |||
| Button btnCancelar = new Button("Cancelar", VaadinIcon.CLOSE_CIRCLE.create(), e -> dialog.close()); | |||
| dialog.getFooter().add(btnGuardar); | |||
| dialog.getFooter().add(btnCancelar); | |||
| dialog.add(layout1,layout2,layout3); | |||
| dialog.open(); | |||
| } | |||
| private void mostrarPopoverReportes() { | |||
| reportePopover = new Popover(); | |||
| reportePopover.setModal(true); | |||
| reportePopover.setBackdropVisible(true); | |||
| reportePopover.setPosition(PopoverPosition.BOTTOM_END); | |||
| reportePopover.setTarget(btnImprimirRpt); | |||
| Div headding = new Div("Reportes disponibles"); | |||
| headding.getStyle().set("font-weight", "600"); | |||
| headding.getStyle().set("padding", "var(--lumo-space-xs)"); | |||
| VerticalLayout listaRrportes = new VerticalLayout(); | |||
| //listaRrportes.setSpacing(false); | |||
| listaRrportes.setPadding(false); | |||
| Button btnReporteFechas = new Button("Mantenimiento por fechas", VaadinIcon.STAR.create(), e -> { | |||
| reportePopover.close(); | |||
| sacarReporte(); | |||
| }); | |||
| btnReporteFechas.addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE); | |||
| Button btnListadoMant = new Button("Listado de mantenimientos", VaadinIcon.STAR.create(), e -> { | |||
| reportePopover.close(); | |||
| obtenerListadoRpt(); | |||
| }); | |||
| btnListadoMant.addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE); | |||
| listaRrportes.add(btnReporteFechas, btnListadoMant); | |||
| reportePopover.add(headding, listaRrportes); | |||
| } | |||
| private void obtenerListadoRpt() { | |||
| Dialog dialog = new Dialog(); | |||
| dialog.setHeaderTitle("Ingresa el peridodo a consultar"); | |||
| TextField txtMes = new TextField("Mes:"); | |||
| txtMes.setRequired(true); | |||
| NumberField txtAnio = new NumberField("Año:"); | |||
| txtAnio.setRequired(true); | |||
| HorizontalLayout layout = new HorizontalLayout(txtMes, txtAnio); | |||
| Button btnGenerar = new Button("Generar", VaadinIcon.PRINT.create()); | |||
| btnGenerar.addThemeVariants(ButtonVariant.LUMO_PRIMARY); | |||
| btnGenerar.addClickListener(e -> { | |||
| String mes = txtMes.getValue().toUpperCase(); | |||
| Integer anio = txtAnio.getValue() != null ? txtAnio.getValue().intValue() : null; | |||
| if (mes.isEmpty() || anio == null) { | |||
| Notification.show("Por favor, completa todos los campos.", 2000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| return; | |||
| } | |||
| try { | |||
| // Preparando los parámetros para el reporte | |||
| Map<String, Object> parametros = new HashMap<>(); | |||
| parametros.put("pMES", mes); | |||
| parametros.put("pANIO", anio); | |||
| // Generando el PDF | |||
| byte[] pdf = reportService.generarReporte("listadoMantenimientos", parametros); | |||
| // Creando el recurso de descarga | |||
| StreamResource resource = new StreamResource("listado_mantenimientos.pdf", () -> new ByteArrayInputStream(pdf)); | |||
| /*Anchor downloadLink = new Anchor(resource, "Descargar Reporte"); | |||
| downloadLink.setTarget("_blank"); | |||
| downloadLink.setId("descargar-listado-link"); | |||
| add(downloadLink); | |||
| getUI().ifPresent(ui -> | |||
| ui.getPage().executeJs("document.getElementById('descargar-listado-link').click();") | |||
| );*/ | |||
| StreamRegistration registration = UI.getCurrent().getSession().getResourceRegistry().registerResource(resource); | |||
| UI.getCurrent().getPage().executeJs("window.open('" + registration.getResourceUri().toString() + "','_blank')"); | |||
| } catch (Exception ex) { | |||
| Notification.show("Error al generar el reporte: " + ex.getMessage(), 5000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_ERROR); | |||
| ex.printStackTrace(); | |||
| } | |||
| }); | |||
| Button btnCancelar = new Button("Cancelar", VaadinIcon.CLOSE_CIRCLE.create(), e -> dialog.close()); | |||
| dialog.getFooter().add(btnCancelar, btnGenerar); | |||
| dialog.add(layout); | |||
| dialog.open(); | |||
| } | |||
| private class PersonContextMenu extends GridContextMenu<PlanAnual> { | |||
| public PersonContextMenu(Grid<PlanAnual> target) { | |||
| super(target); | |||
| addItem("Realizar", e -> e.getItem().ifPresent(planAnual -> { | |||
| int idPlananual = planAnual.getNumero(); | |||
| LocalDate fechaSistema = LocalDate.now(); | |||
| String nomEquipo = planAnual.getNomEquipo(); | |||
| String departamento = planAnual.getDepartamento(); | |||
| getUI().ifPresent(ui -> ui.navigate( | |||
| "mantenimiento?id=" + idPlananual + | |||
| "&fecha=" + fechaSistema + | |||
| "&tipo=1" + | |||
| "&nomEquipo=" + nomEquipo + | |||
| "&departamento=" + departamento)); | |||
| })); | |||
| addItem("Borrar", e -> e.getItem().ifPresent(planAnual -> { | |||
| eliminarPlanAnual(planAnual); | |||
| })); | |||
| add(new Hr()); | |||
| GridMenuItem<PlanAnual> nomEquipo = addItem("Equipo", | |||
| e -> e.getItem().ifPresent(planAnual -> { | |||
| planAnual.getNomEquipo(); | |||
| })); | |||
| GridMenuItem<PlanAnual> depto = addItem("Departamento", | |||
| e -> e.getItem().ifPresent(planAnual -> { | |||
| planAnual.getDepartamento(); | |||
| })); | |||
| setDynamicContentHandler(planAnual -> { | |||
| if (planAnual == null) | |||
| return false; | |||
| nomEquipo.setText(String.format("Equipo: %s", planAnual.getNomEquipo())); | |||
| depto.setText(String.format("Area: %s", planAnual.getDepartamento())); | |||
| return true; | |||
| }); | |||
| } | |||
| } | |||
| private void eliminarPlanAnual(PlanAnual planAnual) { | |||
| Dialog dialog = new Dialog(); | |||
| dialog.setHeaderTitle("Eliminar Mantenimiento"); | |||
| TextField txtMotivo = new TextField("Justifica el motivo de la eliminación"); | |||
| txtMotivo.setWidthFull(); | |||
| txtMotivo.setRequired(true); | |||
| dialog.add( | |||
| new VerticalLayout( | |||
| new Span("¿Estás seguro de que deseas eliminar el mantenimiento del equipo: " + planAnual.getNomEquipo()), | |||
| txtMotivo | |||
| ) | |||
| ); | |||
| Button btnEliminar = new Button("Eliminar", VaadinIcon.TRASH.create(), event -> { | |||
| String motivo = txtMotivo.getValue(); | |||
| if (motivo.isEmpty()) { | |||
| txtMotivo.setErrorMessage("El motivo es requerido."); | |||
| txtMotivo.setInvalid(true); | |||
| return; | |||
| } | |||
| txtMotivo.setInvalid(false); | |||
| Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | |||
| String usuarioId = authentication != null ? authentication.getName().toUpperCase() : "DESCONOCIDO"; | |||
| LocalDate fecha = LocalDate.now(); | |||
| // Llamar al servicio para insertar la bitácora de eliminación | |||
| databaseService.insertarBitacoraEliminacion(planAnual.getNumero(), usuarioId, fecha, motivo); | |||
| // Llamar al servicio para eliminar el plan anual | |||
| databaseService.eliminarEquipoPlanAnual(planAnual.getNumero()); | |||
| Notification.show("Equipo eliminado correctamente", 3000, Notification.Position.MIDDLE) | |||
| .addThemeVariants(NotificationVariant.LUMO_SUCCESS); | |||
| dialog.close(); | |||
| UI.getCurrent().getPage().executeJs("setTimeout(() => { location.reload(); }, 2000);"); | |||
| }); | |||
| Button btnCancelar = new Button("Cancelar", VaadinIcon.CLOSE_CIRCLE.create(), e -> dialog.close()); | |||
| HorizontalLayout dialogFooter = new HorizontalLayout(btnEliminar, btnCancelar); | |||
| dialog.getFooter().add(dialogFooter); | |||
| dialog.open(); | |||
| } | |||
| } | |||
| @ -0,0 +1,106 @@ | |||
| package mx.gob.jumapacelaya.ui.login; | |||
| import com.vaadin.flow.component.UI; | |||
| import com.vaadin.flow.component.html.Image; | |||
| import com.vaadin.flow.component.login.LoginForm; | |||
| import com.vaadin.flow.component.login.LoginI18n; | |||
| import com.vaadin.flow.component.orderedlayout.HorizontalLayout; | |||
| import com.vaadin.flow.component.orderedlayout.VerticalLayout; | |||
| import com.vaadin.flow.router.BeforeEnterEvent; | |||
| import com.vaadin.flow.router.BeforeEnterObserver; | |||
| import com.vaadin.flow.router.PageTitle; | |||
| import com.vaadin.flow.router.Route; | |||
| import com.vaadin.flow.server.auth.AnonymousAllowed; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| @Route("login") | |||
| @PageTitle("Login") | |||
| @AnonymousAllowed | |||
| public class LoginView extends VerticalLayout implements BeforeEnterObserver { | |||
| private static final Logger log = LoggerFactory.getLogger(LoginView.class); | |||
| private final LoginForm login = new LoginForm(); | |||
| // Usuario local para demostracion | |||
| private final String localUser = "admin"; | |||
| private final String localPassword = "admin"; | |||
| public LoginView(){ | |||
| //Configuracion de la vista | |||
| addClassName("login"); | |||
| setSizeFull(); | |||
| setPadding(false); | |||
| setMargin(false); | |||
| // Crear el layout horizontal | |||
| HorizontalLayout mainLayout = new HorizontalLayout(); | |||
| mainLayout.setSizeFull(); | |||
| mainLayout.setPadding(false); | |||
| mainLayout.setMargin(false); | |||
| // Configuración de i18n para el formulario de login | |||
| LoginI18n i18n = LoginI18n.createDefault(); | |||
| LoginI18n.Form i18nFormulario = i18n.getForm(); | |||
| i18nFormulario.setTitle("Mantenimiento Preventivo y Correctivo"); | |||
| i18nFormulario.setUsername("Usuario"); | |||
| i18nFormulario.setPassword("Contraseña"); | |||
| i18nFormulario.setSubmit("Iniciar sesión"); | |||
| i18n.setForm(i18nFormulario); | |||
| // Configuración de los mensajes de error | |||
| LoginI18n.ErrorMessage i18nError = i18n.getErrorMessage(); | |||
| i18nError.setTitle("Credenciales incorrectas"); | |||
| i18nError.setMessage("Usuario o contraseña incorrectos, verifica tus credenciales"); | |||
| i18n.setErrorMessage(i18nError); | |||
| i18n.setAdditionalInformation("Versión 2.0.0 - © 2024 JUMAPACelaya"); | |||
| // Configuración del formulario de login | |||
| login.setAction("login"); | |||
| login.setForgotPasswordButtonVisible(false); | |||
| login.setI18n(i18n); | |||
| // Crear un contenedor para el formulario | |||
| VerticalLayout loginFormContainer = new VerticalLayout(); | |||
| Image imageLogin = new Image("images/LOGO_24'27.png", "Login"); | |||
| imageLogin.setWidth("300px"); | |||
| loginFormContainer.add(imageLogin); | |||
| loginFormContainer.add(login); | |||
| loginFormContainer.setSizeUndefined(); | |||
| loginFormContainer.setPadding(false); | |||
| loginFormContainer.setMargin(false); | |||
| loginFormContainer.setAlignItems(Alignment.CENTER); | |||
| loginFormContainer.setJustifyContentMode(JustifyContentMode.CENTER); | |||
| loginFormContainer.getElement().getThemeList().add("dark"); | |||
| // Añadir la imagen y el contenedor del formulario al layout principal | |||
| mainLayout.add(loginFormContainer); | |||
| mainLayout.setFlexGrow(1, loginFormContainer); | |||
| mainLayout.setFlexGrow(2); | |||
| // Añadir el layout principal a la vista | |||
| add(mainLayout); | |||
| } | |||
| @Override | |||
| public void beforeEnter(BeforeEnterEvent beforeEnterEvent) { | |||
| if(beforeEnterEvent.getLocation() | |||
| .getQueryParameters() | |||
| .getParameters() | |||
| .containsKey("error")){ | |||
| login.setError(true); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,4 @@ | |||
| #Configuracion de la base de datos | |||
| db.url=jdbc:mysql://localhost:3307/mantenimientosdb | |||
| db.user=mantenimientos | |||
| db.pass=mantenimientos | |||
| @ -0,0 +1,5 @@ | |||
| #Configuracion de la base de datos | |||
| db.url=jdbc:mysql://db:3306/mantenimientosdb | |||
| #db.url=jdbc:oracle:thin:@//SVRAPPS:1521/XEPDB1 | |||
| db.user=mantenimientos | |||
| db.pass=mantenimientos | |||
| @ -0,0 +1,34 @@ | |||
| server.port=${PORT:8080} | |||
| logging.level.org.atmosphere = warn | |||
| spring.profiles.active=dev | |||
| # Launch the default browser when starting the application in development mode | |||
| vaadin.launch-browser=true | |||
| # To improve the performance during development. | |||
| # For more information https://vaadin.com/docs/latest/integrations/spring/configuration#special-configuration-parameters | |||
| vaadin.allowed-packages = com.vaadin,org.vaadin,mx.gob.jumapacelaya, de.f0rce.signaturepad | |||
| spring.jpa.defer-datasource-initialization = true | |||
| #Configuracion LDAP | |||
| spring.ldap.urls=ldap://172.1.0.1:389 | |||
| spring.ldap.base=DC=JUMAPACELAYA,DC=GOB,DC=MX | |||
| spring.ldap.username=administrator | |||
| spring.ldap.password=Dr3na$134%4guA | |||
| ###################PRODUCTIVO#################### | |||
| redmine.url=https://proyman.jumapacelaya.gob.mx/ | |||
| redmine.api_key=69be2a5df9bacce02722f566fdf0731d728a1b86 | |||
| #Conexion al servidor de correo electronico | |||
| spring.mail.host=correo.jumapacelaya.gob.mx | |||
| spring.mail.port=587 | |||
| spring.mail.username=noreply@jumapacelaya.gob.mx | |||
| spring.mail.password=Div#13AJum$17 | |||
| spring.mail.properties.mail.smtp.auth=true | |||
| spring.mail.properties.mail.smtp.starttls.enable=false | |||
| spring.mail.properties.mail.smtp.ssl.trust=correo.jumapacelaya.gob.mx | |||
| @ -0,0 +1,6 @@ | |||
| ____ _ _ _ __ __ _ _ _ _ | |||
| / ___|(_)___| |_ ___ _ __ ___ __ _ __| | ___ | \/ | __ _ _ __ | |_ ___ _ __ (_)_ __ ___ (_) ___ _ __ | |_ ___ | |||
| \___ \| / __| __/ _ \ '_ ` _ \ / _` | / _` |/ _ \ | |\/| |/ _` | '_ \| __/ _ \ '_ \| | '_ ` _ \| |/ _ \ '_ \| __/ _ \ | |||
| ___) | \__ \ || __/ | | | | | (_| | | (_| | __/ | | | | (_| | | | | || __/ | | | | | | | | | | __/ | | | || (_) | | |||
| |____/|_|___/\__\___|_| |_| |_|\__,_| \__,_|\___| |_| |_|\__,_|_| |_|\__\___|_| |_|_|_| |_| |_|_|\___|_| |_|\__\___/ | |||
| @ -0,0 +1,39 @@ | |||
| // This TypeScript configuration file is generated by vaadin-maven-plugin. | |||
| // This is needed for TypeScript compiler to compile your TypeScript code in the project. | |||
| // It is recommended to commit this file to the VCS. | |||
| // You might want to change the configurations to fit your preferences | |||
| // For more information about the configurations, please refer to http://www.typescriptlang.org/docs/handbook/tsconfig-json.html | |||
| { | |||
| "_version": "9.1", | |||
| "compilerOptions": { | |||
| "sourceMap": true, | |||
| "jsx": "react-jsx", | |||
| "inlineSources": true, | |||
| "module": "esNext", | |||
| "target": "es2020", | |||
| "moduleResolution": "bundler", | |||
| "strict": true, | |||
| "skipLibCheck": true, | |||
| "noFallthroughCasesInSwitch": true, | |||
| "noImplicitReturns": true, | |||
| "noImplicitAny": true, | |||
| "noImplicitThis": true, | |||
| "noUnusedLocals": false, | |||
| "noUnusedParameters": false, | |||
| "experimentalDecorators": true, | |||
| "useDefineForClassFields": false, | |||
| "baseUrl": "src/main/frontend", | |||
| "paths": { | |||
| "@vaadin/flow-frontend": ["generated/jar-resources"], | |||
| "@vaadin/flow-frontend/*": ["generated/jar-resources/*"], | |||
| "Frontend/*": ["*"] | |||
| } | |||
| }, | |||
| "include": [ | |||
| "src/main/frontend/**/*", | |||
| "types.d.ts" | |||
| ], | |||
| "exclude": [ | |||
| "src/main/frontend/generated/jar-resources/**" | |||
| ] | |||
| } | |||
| @ -0,0 +1,17 @@ | |||
| // This TypeScript modules definition file is generated by vaadin-maven-plugin. | |||
| // You can not directly import your different static files into TypeScript, | |||
| // This is needed for TypeScript compiler to declare and export as a TypeScript module. | |||
| // It is recommended to commit this file to the VCS. | |||
| // You might want to change the configurations to fit your preferences | |||
| declare module '*.css?inline' { | |||
| import type { CSSResultGroup } from 'lit'; | |||
| const content: CSSResultGroup; | |||
| export default content; | |||
| } | |||
| // Allow any CSS Custom Properties | |||
| declare module 'csstype' { | |||
| interface Properties { | |||
| [index: `--${string}`]: any; | |||
| } | |||
| } | |||
| @ -0,0 +1,9 @@ | |||
| import { UserConfigFn } from 'vite'; | |||
| import { overrideVaadinConfig } from './vite.generated'; | |||
| const customConfig: UserConfigFn = (env) => ({ | |||
| // Here you can add custom Vite parameters | |||
| // https://vitejs.dev/config/ | |||
| }); | |||
| export default overrideVaadinConfig(customConfig); | |||