ADD project from GitLab Banesco
This commit is contained in:
parent
bb342e3c79
commit
4549f45f58
@ -1,3 +1,3 @@
|
||||
# BIAN-Quarkus
|
||||
|
||||
Repositorio de APIs BIAN implementadas con Quarkus
|
||||
Repositorio de APIs BIAN de consulta de productos. Con implementación del mock para la consulta de TDD.
|
||||
5
bus-evaluate-customer-product/.dockerignore
Normal file
5
bus-evaluate-customer-product/.dockerignore
Normal file
@ -0,0 +1,5 @@
|
||||
*
|
||||
!target/*-runner
|
||||
!target/*-runner.jar
|
||||
!target/lib/*
|
||||
!target/quarkus-app/*
|
||||
45
bus-evaluate-customer-product/.gitignore
vendored
Normal file
45
bus-evaluate-customer-product/.gitignore
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
#Maven
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
release.properties
|
||||
.flattened-pom.xml
|
||||
|
||||
# Eclipse
|
||||
.project
|
||||
.classpath
|
||||
.settings/
|
||||
bin/
|
||||
|
||||
# IntelliJ
|
||||
.idea
|
||||
*.ipr
|
||||
*.iml
|
||||
*.iws
|
||||
|
||||
# NetBeans
|
||||
nb-configuration.xml
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode
|
||||
.factorypath
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
|
||||
# Vim
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# patch
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
# Local environment
|
||||
.env
|
||||
|
||||
# Plugin directory
|
||||
/.quarkus/cli/plugins/
|
||||
# TLS Certificates
|
||||
.certs/
|
||||
1
bus-evaluate-customer-product/.mvn/wrapper/.gitignore
vendored
Normal file
1
bus-evaluate-customer-product/.mvn/wrapper/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
maven-wrapper.jar
|
||||
93
bus-evaluate-customer-product/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
93
bus-evaluate-customer-product/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.Authenticator;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public final class MavenWrapperDownloader {
|
||||
private static final String WRAPPER_VERSION = "3.3.2";
|
||||
|
||||
private static final boolean VERBOSE = Boolean.parseBoolean(System.getenv("MVNW_VERBOSE"));
|
||||
|
||||
public static void main(String[] args) {
|
||||
log("Apache Maven Wrapper Downloader " + WRAPPER_VERSION);
|
||||
|
||||
if (args.length != 2) {
|
||||
System.err.println(" - ERROR wrapperUrl or wrapperJarPath parameter missing");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
log(" - Downloader started");
|
||||
final URL wrapperUrl = URI.create(args[0]).toURL();
|
||||
final String jarPath = args[1].replace("..", ""); // Sanitize path
|
||||
final Path wrapperJarPath = Paths.get(jarPath).toAbsolutePath().normalize();
|
||||
downloadFileFromURL(wrapperUrl, wrapperJarPath);
|
||||
log("Done");
|
||||
} catch (IOException e) {
|
||||
System.err.println("- Error downloading: " + e.getMessage());
|
||||
if (VERBOSE) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void downloadFileFromURL(URL wrapperUrl, Path wrapperJarPath)
|
||||
throws IOException {
|
||||
log(" - Downloading to: " + wrapperJarPath);
|
||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
|
||||
final String username = System.getenv("MVNW_USERNAME");
|
||||
final char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
|
||||
Authenticator.setDefault(new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, password);
|
||||
}
|
||||
});
|
||||
}
|
||||
Path temp = wrapperJarPath
|
||||
.getParent()
|
||||
.resolve(wrapperJarPath.getFileName() + "."
|
||||
+ Long.toUnsignedString(ThreadLocalRandom.current().nextLong()) + ".tmp");
|
||||
try (InputStream inStream = wrapperUrl.openStream()) {
|
||||
Files.copy(inStream, temp, StandardCopyOption.REPLACE_EXISTING);
|
||||
Files.move(temp, wrapperJarPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
} finally {
|
||||
Files.deleteIfExists(temp);
|
||||
}
|
||||
log(" - Downloader complete");
|
||||
}
|
||||
|
||||
private static void log(String msg) {
|
||||
if (VERBOSE) {
|
||||
System.out.println(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
20
bus-evaluate-customer-product/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
20
bus-evaluate-customer-product/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
# 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.
|
||||
wrapperVersion=3.3.2
|
||||
distributionType=source
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar
|
||||
10
bus-evaluate-customer-product/CHANGELOG.md
Normal file
10
bus-evaluate-customer-product/CHANGELOG.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Changelog
|
||||
|
||||
Todos los cambios notables en este proyecto se documentarán en este archivo.
|
||||
|
||||
El formato se basa en [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
y este proyecto se adhiere a [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## v1.0.0 - UNRELEASED
|
||||
### Updated
|
||||
- Migración completada a Quarkus 3.25.3
|
||||
61
bus-evaluate-customer-product/README.md
Normal file
61
bus-evaluate-customer-product/README.md
Normal file
@ -0,0 +1,61 @@
|
||||
# bus-evaluate-customer-product
|
||||
|
||||
This project uses Quarkus, the Supersonic Subatomic Java Framework.
|
||||
|
||||
If you want to learn more about Quarkus, please visit its website: <https://quarkus.io/>.
|
||||
|
||||
## Running the application in dev mode
|
||||
|
||||
You can run your application in dev mode that enables live coding using:
|
||||
|
||||
```shell script
|
||||
./mvnw quarkus:dev
|
||||
```
|
||||
|
||||
> **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at <http://localhost:8080/q/dev/>.
|
||||
|
||||
## Packaging and running the application
|
||||
|
||||
The application can be packaged using:
|
||||
|
||||
```shell script
|
||||
./mvnw package
|
||||
```
|
||||
|
||||
It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory.
|
||||
Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/quarkus-app/lib/` directory.
|
||||
|
||||
The application is now runnable using `java -jar target/quarkus-app/quarkus-run.jar`.
|
||||
|
||||
If you want to build an _über-jar_, execute the following command:
|
||||
|
||||
```shell script
|
||||
./mvnw package -Dquarkus.package.jar.type=uber-jar
|
||||
```
|
||||
|
||||
The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`.
|
||||
|
||||
## Creating a native executable
|
||||
|
||||
You can create a native executable using:
|
||||
|
||||
```shell script
|
||||
./mvnw package -Dnative
|
||||
```
|
||||
|
||||
Or, if you don't have GraalVM installed, you can run the native executable build in a container using:
|
||||
|
||||
```shell script
|
||||
./mvnw package -Dnative -Dquarkus.native.container-build=true
|
||||
```
|
||||
|
||||
You can then execute your native executable with: `./target/bus-evaluate-customer-product-1.0.0-runner`
|
||||
|
||||
If you want to learn more about building native executables, please consult <https://quarkus.io/guides/maven-tooling>.
|
||||
|
||||
## Related Guides
|
||||
|
||||
- Hibernate Validator ([guide](https://quarkus.io/guides/validation)): Validate object properties (field, getter) and method parameters for your beans (REST, CDI, Jakarta Persistence)
|
||||
- REST Jackson ([guide](https://quarkus.io/guides/rest#json-serialisation)): Jackson serialization support for Quarkus REST. This extension is not compatible with the quarkus-resteasy extension, or any of the extensions that depend on it
|
||||
- YAML Configuration ([guide](https://quarkus.io/guides/config-yaml)): Use YAML to configure your Quarkus application
|
||||
- SmallRye Health ([guide](https://quarkus.io/guides/smallrye-health)): Monitor service health
|
||||
2
bus-evaluate-customer-product/TASKS.md
Normal file
2
bus-evaluate-customer-product/TASKS.md
Normal file
@ -0,0 +1,2 @@
|
||||
- user login de spring tiene respuesta diferente a la hecha en quarkus (migracion cargo en cuenta)
|
||||
- Condicionar que el postgres guarde en cache
|
||||
332
bus-evaluate-customer-product/mvnw
vendored
Normal file
332
bus-evaluate-customer-product/mvnw
vendored
Normal file
@ -0,0 +1,332 @@
|
||||
#!/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.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Apache Maven Wrapper startup batch script, version 3.3.2
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# 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
|
||||
JAVA_HOME="$(/usr/libexec/java_home)"
|
||||
export JAVA_HOME
|
||||
else
|
||||
JAVA_HOME="/Library/Java/Home"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -r /etc/gentoo-release ]; then
|
||||
JAVA_HOME=$(java-config --jre-home)
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin; then
|
||||
[ -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 "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] \
|
||||
&& JAVA_HOME="$(
|
||||
cd "$JAVA_HOME" || (
|
||||
echo "cannot cd into $JAVA_HOME." >&2
|
||||
exit 1
|
||||
)
|
||||
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 2>/dev/null
|
||||
\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." >&2
|
||||
fi
|
||||
|
||||
# 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" >&2
|
||||
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/.." || exit 1
|
||||
pwd
|
||||
)
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
printf '%s' "$(
|
||||
cd "$basedir" || exit 1
|
||||
pwd
|
||||
)"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
# Remove \r in case we run on Windows within Git Bash
|
||||
# and check out the repository with auto CRLF management
|
||||
# enabled. Otherwise, we may read lines that are delimited with
|
||||
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
|
||||
# splitting rules.
|
||||
tr -s '\r\n' ' ' <"$1"
|
||||
fi
|
||||
}
|
||||
|
||||
log() {
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
printf '%s\n' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
export MAVEN_PROJECTBASEDIR
|
||||
log "$MAVEN_PROJECTBASEDIR"
|
||||
|
||||
##########################################################################################
|
||||
# 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.
|
||||
##########################################################################################
|
||||
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if [ -r "$wrapperJarPath" ]; then
|
||||
log "Found $wrapperJarPath"
|
||||
else
|
||||
log "Couldn't find $wrapperJarPath, downloading it ..."
|
||||
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
|
||||
else
|
||||
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
|
||||
fi
|
||||
while IFS="=" read -r key value; do
|
||||
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
|
||||
safeValue=$(echo "$value" | tr -d '\r')
|
||||
case "$key" in wrapperUrl)
|
||||
wrapperUrl="$safeValue"
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
log "Downloading from: $wrapperUrl"
|
||||
|
||||
if $cygwin; then
|
||||
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
|
||||
fi
|
||||
|
||||
if command -v wget >/dev/null; then
|
||||
log "Found wget ... using wget"
|
||||
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
else
|
||||
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl >/dev/null; then
|
||||
log "Found curl ... using curl"
|
||||
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||
else
|
||||
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
else
|
||||
log "Falling back to using Java to download"
|
||||
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaSource=$(cygpath --path --windows "$javaSource")
|
||||
javaClass=$(cygpath --path --windows "$javaClass")
|
||||
fi
|
||||
if [ -e "$javaSource" ]; then
|
||||
if [ ! -e "$javaClass" ]; then
|
||||
log " - Compiling MavenWrapperDownloader.java ..."
|
||||
("$JAVA_HOME/bin/javac" "$javaSource")
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
log " - Running MavenWrapperDownloader.java ..."
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
|
||||
wrapperSha256Sum=""
|
||||
while IFS="=" read -r key value; do
|
||||
case "$key" in wrapperSha256Sum)
|
||||
wrapperSha256Sum=$value
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ -n "$wrapperSha256Sum" ]; then
|
||||
wrapperSha256Result=false
|
||||
if command -v sha256sum >/dev/null; then
|
||||
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c >/dev/null 2>&1; then
|
||||
wrapperSha256Result=true
|
||||
fi
|
||||
elif command -v shasum >/dev/null; then
|
||||
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c >/dev/null 2>&1; then
|
||||
wrapperSha256Result=true
|
||||
fi
|
||||
else
|
||||
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
|
||||
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ $wrapperSha256Result = false ]; then
|
||||
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
|
||||
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
|
||||
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
|
||||
exit 1
|
||||
fi
|
||||
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 "$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
|
||||
|
||||
# shellcheck disable=SC2086 # safe args
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
$MAVEN_DEBUG_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||
206
bus-evaluate-customer-product/mvnw.cmd
vendored
Normal file
206
bus-evaluate-customer-product/mvnw.cmd
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
@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 Apache Maven Wrapper startup batch script, version 3.3.2
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@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. >&2
|
||||
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. >&2
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo. >&2
|
||||
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. >&2
|
||||
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 WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
|
||||
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET WRAPPER_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 WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %WRAPPER_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('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
|
||||
SET WRAPPER_SHA_256_SUM=""
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
|
||||
)
|
||||
IF NOT %WRAPPER_SHA_256_SUM%=="" (
|
||||
powershell -Command "&{"^
|
||||
"Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash;"^
|
||||
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
|
||||
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
|
||||
" Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
|
||||
" Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
|
||||
" Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
|
||||
" exit 1;"^
|
||||
"}"^
|
||||
"}"
|
||||
if ERRORLEVEL 1 goto error
|
||||
)
|
||||
|
||||
@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%
|
||||
226
bus-evaluate-customer-product/pom.xml
Normal file
226
bus-evaluate-customer-product/pom.xml
Normal file
@ -0,0 +1,226 @@
|
||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.banesco</groupId>
|
||||
<artifactId>bus-evaluate-customer-product</artifactId>
|
||||
<name>bus-evaluate-customer-product</name>
|
||||
<description>API REST Customer Product (consulta de cuentas) BUS</description>
|
||||
<version>1.0.0</version>
|
||||
|
||||
<properties>
|
||||
<compiler-plugin.version>3.14.0</compiler-plugin.version>
|
||||
<maven.compiler.release>17</maven.compiler.release>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
|
||||
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
|
||||
<quarkus.platform.version>3.25.3</quarkus.platform.version>
|
||||
<skipITs>true</skipITs>
|
||||
<quarkus.main-class>com.banesco.Main</quarkus.main-class>
|
||||
<surefire-plugin.version>3.5.3</surefire-plugin.version>
|
||||
<cxf.version>4.0.4</cxf.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${quarkus.platform.group-id}</groupId>
|
||||
<artifactId>${quarkus.platform.artifact-id}</artifactId>
|
||||
<version>${quarkus.platform.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.banesco</groupId>
|
||||
<artifactId>commons</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-rest-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-rest-client-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-config-yaml</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-arc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.38</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-redis-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-redis-cache</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkiverse.cxf</groupId>
|
||||
<artifactId>quarkus-cxf</artifactId>
|
||||
<version>3.15.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-smallrye-openapi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-swagger-ui</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-smallrye-health</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-hibernate-validator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- postgresql -->
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-jdbc-postgresql</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>${quarkus.platform.group-id}</groupId>
|
||||
<artifactId>quarkus-maven-plugin</artifactId>
|
||||
<version>${quarkus.platform.version}</version>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
<goal>generate-code</goal>
|
||||
<goal>generate-code-tests</goal>
|
||||
<goal>native-image-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.cxf</groupId>
|
||||
<artifactId>cxf-codegen-plugin</artifactId>
|
||||
<version>${cxf.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>generate-sources</id>
|
||||
<phase>generate-sources</phase>
|
||||
<configuration>
|
||||
<sourceRoot>${project.build.directory}/generated-sources/cxf</sourceRoot>
|
||||
<wsdlOptions>
|
||||
<wsdlOption>
|
||||
<wsdl>${project.basedir}/src/main/resources/wsdl/PruebaService.wsdl</wsdl>
|
||||
<extraargs>
|
||||
<extraarg>-client</extraarg>
|
||||
<extraarg>-verbose</extraarg>
|
||||
</extraargs>
|
||||
</wsdlOption>
|
||||
</wsdlOptions>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>wsdl2java</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<parameters>true</parameters>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
<maven.home>${maven.home}</maven.home>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>${surefire-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
<maven.home>${maven.home}</maven.home>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-source</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>add-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>${project.build.directory}/generated-sources/cxf</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>native</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>native</name>
|
||||
</property>
|
||||
</activation>
|
||||
<properties>
|
||||
<skipITs>false</skipITs>
|
||||
<quarkus.native.enabled>true</quarkus.native.enabled>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
12
bus-evaluate-customer-product/scripts/native/Dockerfile
Normal file
12
bus-evaluate-customer-product/scripts/native/Dockerfile
Normal file
@ -0,0 +1,12 @@
|
||||
FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0
|
||||
RUN mkdir -p /work
|
||||
ENV TZ="America/Caracas"
|
||||
ENV LANGUAGE='en_US:en'
|
||||
VOLUME /tmp
|
||||
COPY /file/*-runner /work/busCustomerAccounts
|
||||
RUN chmod -R 775 /work
|
||||
RUN ls -ltra /work/
|
||||
EXPOSE 8080
|
||||
WORKDIR /work/
|
||||
|
||||
ENTRYPOINT ["./busCustomerAccounts", "-Dquarkus.http.host=0.0.0.0"]
|
||||
Binary file not shown.
98
bus-evaluate-customer-product/src/main/docker/Dockerfile.jvm
Normal file
98
bus-evaluate-customer-product/src/main/docker/Dockerfile.jvm
Normal file
@ -0,0 +1,98 @@
|
||||
####
|
||||
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
|
||||
#
|
||||
# Before building the container image run:
|
||||
#
|
||||
# ./mvnw package
|
||||
#
|
||||
# Then, build the image with:
|
||||
#
|
||||
# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/pub-get-accounts-client-jvm .
|
||||
#
|
||||
# Then run the container using:
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/pub-get-accounts-client-jvm
|
||||
#
|
||||
# If you want to include the debug port into your docker image
|
||||
# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005.
|
||||
# Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005
|
||||
# when running the container
|
||||
#
|
||||
# Then run the container using :
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/pub-get-accounts-client-jvm
|
||||
#
|
||||
# This image uses the `run-java.sh` script to run the application.
|
||||
# This scripts computes the command line to execute your Java application, and
|
||||
# includes memory/GC tuning.
|
||||
# You can configure the behavior using the following environment properties:
|
||||
# - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") - Be aware that this will override
|
||||
# the default JVM options, use `JAVA_OPTS_APPEND` to append options
|
||||
# - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options
|
||||
# in JAVA_OPTS (example: "-Dsome.property=foo")
|
||||
# - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is
|
||||
# used to calculate a default maximal heap memory based on a containers restriction.
|
||||
# If used in a container without any memory constraints for the container then this
|
||||
# option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio
|
||||
# of the container available memory as set here. The default is `50` which means 50%
|
||||
# of the available memory is used as an upper boundary. You can skip this mechanism by
|
||||
# setting this value to `0` in which case no `-Xmx` option is added.
|
||||
# - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This
|
||||
# is used to calculate a default initial heap memory based on the maximum heap memory.
|
||||
# If used in a container without any memory constraints for the container then this
|
||||
# option has no effect. If there is a memory constraint then `-Xms` is set to a ratio
|
||||
# of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx`
|
||||
# is used as the initial heap size. You can skip this mechanism by setting this value
|
||||
# to `0` in which case no `-Xms` option is added (example: "25")
|
||||
# - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS.
|
||||
# This is used to calculate the maximum value of the initial heap memory. If used in
|
||||
# a container without any memory constraints for the container then this option has
|
||||
# no effect. If there is a memory constraint then `-Xms` is limited to the value set
|
||||
# here. The default is 4096MB which means the calculated value of `-Xms` never will
|
||||
# be greater than 4096MB. The value of this variable is expressed in MB (example: "4096")
|
||||
# - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output
|
||||
# when things are happening. This option, if set to true, will set
|
||||
# `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true").
|
||||
# - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example:
|
||||
# true").
|
||||
# - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787").
|
||||
# - CONTAINER_CORE_LIMIT: A calculated core limit as described in
|
||||
# https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2")
|
||||
# - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024").
|
||||
# - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion.
|
||||
# (example: "20")
|
||||
# - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking.
|
||||
# (example: "40")
|
||||
# - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection.
|
||||
# (example: "4")
|
||||
# - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus
|
||||
# previous GC times. (example: "90")
|
||||
# - GC_METASPACE_SIZE: The initial metaspace size. (example: "20")
|
||||
# - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100")
|
||||
# - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should
|
||||
# contain the necessary JRE command-line options to specify the required GC, which
|
||||
# will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC).
|
||||
# - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080")
|
||||
# - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080")
|
||||
# - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be
|
||||
# accessed directly. (example: "foo.example.com,bar.example.com")
|
||||
#
|
||||
###
|
||||
FROM registry.access.redhat.com/ubi9/openjdk-17:1.23
|
||||
|
||||
ENV LANGUAGE='en_US:en'
|
||||
|
||||
|
||||
# We make four distinct layers so if there are application changes the library layers can be re-used
|
||||
COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/
|
||||
COPY --chown=185 target/quarkus-app/*.jar /deployments/
|
||||
COPY --chown=185 target/quarkus-app/app/ /deployments/app/
|
||||
COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/
|
||||
|
||||
EXPOSE 8080
|
||||
USER 185
|
||||
ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
|
||||
ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
|
||||
|
||||
ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ]
|
||||
|
||||
@ -0,0 +1,94 @@
|
||||
####
|
||||
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
|
||||
#
|
||||
# Before building the container image run:
|
||||
#
|
||||
# ./mvnw package -Dquarkus.package.jar.type=legacy-jar
|
||||
#
|
||||
# Then, build the image with:
|
||||
#
|
||||
# docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/pub-get-accounts-client-legacy-jar .
|
||||
#
|
||||
# Then run the container using:
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/pub-get-accounts-client-legacy-jar
|
||||
#
|
||||
# If you want to include the debug port into your docker image
|
||||
# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005.
|
||||
# Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005
|
||||
# when running the container
|
||||
#
|
||||
# Then run the container using :
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/pub-get-accounts-client-legacy-jar
|
||||
#
|
||||
# This image uses the `run-java.sh` script to run the application.
|
||||
# This scripts computes the command line to execute your Java application, and
|
||||
# includes memory/GC tuning.
|
||||
# You can configure the behavior using the following environment properties:
|
||||
# - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") - Be aware that this will override
|
||||
# the default JVM options, use `JAVA_OPTS_APPEND` to append options
|
||||
# - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options
|
||||
# in JAVA_OPTS (example: "-Dsome.property=foo")
|
||||
# - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is
|
||||
# used to calculate a default maximal heap memory based on a containers restriction.
|
||||
# If used in a container without any memory constraints for the container then this
|
||||
# option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio
|
||||
# of the container available memory as set here. The default is `50` which means 50%
|
||||
# of the available memory is used as an upper boundary. You can skip this mechanism by
|
||||
# setting this value to `0` in which case no `-Xmx` option is added.
|
||||
# - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This
|
||||
# is used to calculate a default initial heap memory based on the maximum heap memory.
|
||||
# If used in a container without any memory constraints for the container then this
|
||||
# option has no effect. If there is a memory constraint then `-Xms` is set to a ratio
|
||||
# of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx`
|
||||
# is used as the initial heap size. You can skip this mechanism by setting this value
|
||||
# to `0` in which case no `-Xms` option is added (example: "25")
|
||||
# - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS.
|
||||
# This is used to calculate the maximum value of the initial heap memory. If used in
|
||||
# a container without any memory constraints for the container then this option has
|
||||
# no effect. If there is a memory constraint then `-Xms` is limited to the value set
|
||||
# here. The default is 4096MB which means the calculated value of `-Xms` never will
|
||||
# be greater than 4096MB. The value of this variable is expressed in MB (example: "4096")
|
||||
# - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output
|
||||
# when things are happening. This option, if set to true, will set
|
||||
# `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true").
|
||||
# - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example:
|
||||
# true").
|
||||
# - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787").
|
||||
# - CONTAINER_CORE_LIMIT: A calculated core limit as described in
|
||||
# https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2")
|
||||
# - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024").
|
||||
# - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion.
|
||||
# (example: "20")
|
||||
# - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking.
|
||||
# (example: "40")
|
||||
# - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection.
|
||||
# (example: "4")
|
||||
# - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus
|
||||
# previous GC times. (example: "90")
|
||||
# - GC_METASPACE_SIZE: The initial metaspace size. (example: "20")
|
||||
# - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100")
|
||||
# - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should
|
||||
# contain the necessary JRE command-line options to specify the required GC, which
|
||||
# will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC).
|
||||
# - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080")
|
||||
# - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080")
|
||||
# - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be
|
||||
# accessed directly. (example: "foo.example.com,bar.example.com")
|
||||
#
|
||||
###
|
||||
FROM registry.access.redhat.com/ubi9/openjdk-17:1.23
|
||||
|
||||
ENV LANGUAGE='en_US:en'
|
||||
|
||||
|
||||
COPY target/lib/* /deployments/lib/
|
||||
COPY target/*-runner.jar /deployments/quarkus-run.jar
|
||||
|
||||
EXPOSE 8080
|
||||
USER 185
|
||||
ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
|
||||
ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
|
||||
|
||||
ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ]
|
||||
@ -0,0 +1,29 @@
|
||||
####
|
||||
# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode.
|
||||
#
|
||||
# Before building the container image run:
|
||||
#
|
||||
# ./mvnw package -Dnative
|
||||
#
|
||||
# Then, build the image with:
|
||||
#
|
||||
# docker build -f src/main/docker/Dockerfile.native -t quarkus/pub-get-accounts-client .
|
||||
#
|
||||
# Then run the container using:
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/pub-get-accounts-client
|
||||
#
|
||||
# The ` registry.access.redhat.com/ubi9/ubi-minimal:9.6` base image is based on UBI 9.
|
||||
# To use UBI 8, switch to `quay.io/ubi8/ubi-minimal:8.10`.
|
||||
###
|
||||
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.6
|
||||
WORKDIR /work/
|
||||
RUN chown 1001 /work \
|
||||
&& chmod "g+rwX" /work \
|
||||
&& chown 1001:root /work
|
||||
COPY --chown=1001:root --chmod=0755 target/*-runner /work/application
|
||||
|
||||
EXPOSE 8080
|
||||
USER 1001
|
||||
|
||||
ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
|
||||
@ -0,0 +1,32 @@
|
||||
####
|
||||
# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode.
|
||||
# It uses a micro base image, tuned for Quarkus native executables.
|
||||
# It reduces the size of the resulting container image.
|
||||
# Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image.
|
||||
#
|
||||
# Before building the container image run:
|
||||
#
|
||||
# ./mvnw package -Dnative
|
||||
#
|
||||
# Then, build the image with:
|
||||
#
|
||||
# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/pub-get-accounts-client .
|
||||
#
|
||||
# Then run the container using:
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/pub-get-accounts-client
|
||||
#
|
||||
# The `quay.io/quarkus/ubi9-quarkus-micro-image:2.0` base image is based on UBI 9.
|
||||
# To use UBI 8, switch to `quay.io/quarkus/quarkus-micro-image:2.0`.
|
||||
###
|
||||
FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0
|
||||
WORKDIR /work/
|
||||
RUN chown 1001 /work \
|
||||
&& chmod "g+rwX" /work \
|
||||
&& chown 1001:root /work
|
||||
COPY --chown=1001:root --chmod=0755 target/*-runner /work/application
|
||||
|
||||
EXPOSE 8080
|
||||
USER 1001
|
||||
|
||||
ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
|
||||
12
bus-evaluate-customer-product/src/main/java/Main.java
Normal file
12
bus-evaluate-customer-product/src/main/java/Main.java
Normal file
@ -0,0 +1,12 @@
|
||||
import io.quarkus.runtime.Quarkus;
|
||||
import io.quarkus.runtime.annotations.QuarkusMain;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@QuarkusMain
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
log.info("Running bus-evaluate-customer-product...");
|
||||
Quarkus.run(args);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package application.exception;
|
||||
|
||||
public class GatewayServiceException extends RuntimeException {
|
||||
public GatewayServiceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public GatewayServiceException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package application.exception;
|
||||
|
||||
public class InvalidTokenException extends RuntimeException {
|
||||
public InvalidTokenException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package application.exception;
|
||||
|
||||
public class ServiceCommunicationException extends GatewayServiceException {
|
||||
public ServiceCommunicationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package application.factory;
|
||||
|
||||
import application.port.input.command.RegisterSecurityCommand;
|
||||
import domain.dto.response.StatusResponse;
|
||||
import domain.model.AccountClientContext;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class SecurityTraceFactory {
|
||||
|
||||
public RegisterSecurityCommand createCommandFromContext(AccountClientContext context, StatusResponse statusResponse) {
|
||||
var request = context.getRequest();
|
||||
var customerReference = request.getCustomerPositionState().getCustomerReference();
|
||||
var device = request.getDevice();
|
||||
|
||||
long durationInMillis = System.currentTimeMillis() - context.getStartExecution();
|
||||
|
||||
return RegisterSecurityCommand.builder()
|
||||
.login(context.getUsername())
|
||||
.fecHor(Timestamp.valueOf(LocalDateTime.now()))
|
||||
.nacCli(customerReference.getCustomerIdType())
|
||||
.cedRifCli(Integer.valueOf(customerReference.getCustomerId()))
|
||||
.tipoRespuesta(Integer.valueOf(statusResponse.getStatusCode()))
|
||||
.msgRespuesta(statusResponse.getMessage())
|
||||
.codFintech(context.getFintechId())
|
||||
.tiempoRespuesta((int) durationInMillis)
|
||||
.tipoDispositivo(device.getDeviceType())
|
||||
.desDispositivo(device.getDeviceDescription())
|
||||
.ipCli(device.getDeviceIp())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package application.helper;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
public class CustomerHelper {
|
||||
/**
|
||||
* Construye de forma segura un ID de cliente a partir de su tipo y número.
|
||||
*
|
||||
* @param idType El tipo de identificación (ej. "V", "J").
|
||||
* @param idNumber El número de identificación.
|
||||
* @return Un {@link Optional} con el ID concatenado si ambos parámetros son válidos (no nulos ni vacíos),
|
||||
* o un {@code Optional.empty()} en caso contrario.
|
||||
*/
|
||||
public static Optional<String> buildCustomerId(String idType, String idNumber) {
|
||||
return Optional.ofNullable(idType)
|
||||
.filter(type -> !type.isBlank())
|
||||
.flatMap(type -> Optional.ofNullable(idNumber)
|
||||
.filter(number -> !number.isBlank())
|
||||
.map(number -> type + number));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
package application.helper;
|
||||
|
||||
import domain.dto.response.CustomerPositionStateResponse;
|
||||
import domain.dto.response.CustomerResponse;
|
||||
import domain.dto.response.StatusResponse;
|
||||
import domain.model.BankingProduct;
|
||||
import domain.model.ErrorCode;
|
||||
import infrastructure.service.StatusDescriptionResolver;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApplicationScoped
|
||||
public class ResponseHelper {
|
||||
|
||||
private final StatusDescriptionResolver statusDescriptionResolver;
|
||||
|
||||
public ResponseHelper(StatusDescriptionResolver statusDescriptionResolver) {
|
||||
this.statusDescriptionResolver = statusDescriptionResolver;
|
||||
}
|
||||
|
||||
public Response buildErrorResponse(String errorCodeKey, String requestId) {
|
||||
var errorCode = statusDescriptionResolver.getCode(errorCodeKey);
|
||||
return this.buildErrorResponse(errorCode, requestId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construye una respuesta de error estandarizada de forma genérica.
|
||||
* @param errorCode Objeto con el código de error interno.
|
||||
* @return Un objeto Response estándar de JAX-RS.
|
||||
*/
|
||||
public Response buildErrorResponse(ErrorCode errorCode, String requestId) {
|
||||
|
||||
var statusResponse = StatusResponse.builder()
|
||||
.status(errorCode.status())
|
||||
.statusCode(errorCode.statusCode())
|
||||
.message(errorCode.description())
|
||||
.traceId(requestId)
|
||||
.build();
|
||||
|
||||
var response = new CustomerResponse(statusResponse);
|
||||
|
||||
int httpStatus = errorCode.getHttpStatusCode();
|
||||
|
||||
return Response.status(httpStatus)
|
||||
.entity(response)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construye una respuesta de éxito (200) CON DATOS.
|
||||
* @param customerAccounts La lista de productos (el cuerpo de la respuesta).
|
||||
* @param successCode El ErrorCode "200" (para los detalles del status).
|
||||
* @param requestId El ID de traza.
|
||||
* @return Un objeto Response estándar de JAX-RS.
|
||||
*/
|
||||
public Response buildSuccessResponse(List<BankingProduct> customerAccounts, ErrorCode successCode, String requestId) {
|
||||
|
||||
var status = StatusResponse.builder()
|
||||
.status(successCode.status())
|
||||
.statusCode(successCode.statusCode())
|
||||
.message(successCode.description())
|
||||
.traceId(requestId)
|
||||
.build();
|
||||
|
||||
var accounts = CustomerPositionStateResponse.builder()
|
||||
.bankingProducts(customerAccounts)
|
||||
.record(customerAccounts.size())
|
||||
.build();
|
||||
|
||||
var response = new CustomerResponse(status, accounts);
|
||||
|
||||
return Response.status(successCode.getHttpStatusCode())
|
||||
.entity(response)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package application.port.input;
|
||||
|
||||
import domain.entity.AppConfiguration;
|
||||
|
||||
public interface IAppConfig {
|
||||
AppConfiguration execute(String appName);
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package application.port.input;
|
||||
|
||||
import application.port.input.command.CustomerAccountCommand;
|
||||
import domain.entity.AppConfiguration;
|
||||
import domain.model.AccountClientContext;
|
||||
import domain.model.BankingProduct;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ICustomerProduct {
|
||||
// TODO: mejorar
|
||||
List<BankingProduct> execute(CustomerAccountCommand command, AccountClientContext context, AppConfiguration appConfig, String otp, Boolean isCacheable, String requestId);
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package application.port.input;
|
||||
|
||||
import application.port.input.command.EncodeValueCommand;
|
||||
|
||||
public interface IEncodeValue {
|
||||
String execute(EncodeValueCommand command, String requestId);
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package application.port.input;
|
||||
|
||||
import application.port.input.command.RegisterSecurityCommand;
|
||||
|
||||
public interface IRegisterSecurity {
|
||||
void execute(RegisterSecurityCommand command, String requestId);
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package application.port.input;
|
||||
|
||||
import application.port.input.command.ServiceStatusCommand;
|
||||
|
||||
public interface IServiceStatus {
|
||||
Boolean execute(ServiceStatusCommand command, String requestId);
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package application.port.input;
|
||||
|
||||
import application.port.input.command.UserLoginCommand;
|
||||
import domain.model.UserLogin;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Puerto de entrada para el caso de uso de login de usuario (API privada)
|
||||
*/
|
||||
public interface IUserLogin {
|
||||
Optional<UserLogin> execute(UserLoginCommand command, String requestId);
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package application.port.input;
|
||||
|
||||
import application.port.input.command.ValidateOtpCommand;
|
||||
|
||||
public interface IValidateOtp {
|
||||
Boolean isValidOtp(ValidateOtpCommand command, String requestId);
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package application.port.input;
|
||||
|
||||
import application.port.input.command.ValidateProfileCommand;
|
||||
|
||||
public interface IValidateProfile {
|
||||
Boolean execute(ValidateProfileCommand command, String requestId);
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package application.port.input.command;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public class CustomerAccountCommand {
|
||||
String rif;
|
||||
String bankCode;
|
||||
String currencyCode;
|
||||
String status;
|
||||
String statusMe;
|
||||
String productCv;
|
||||
String product;
|
||||
String channel;
|
||||
String service;
|
||||
String operator;
|
||||
String phone;
|
||||
String affiliationStatus;
|
||||
String counterpartyAccount;
|
||||
String holder;
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package application.port.input.command;
|
||||
|
||||
public record EncodeValueCommand(
|
||||
String sApp
|
||||
) {}
|
||||
@ -0,0 +1,39 @@
|
||||
package application.port.input.command;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public class RegisterSecurityCommand {
|
||||
String login;
|
||||
Date fecHor;
|
||||
String nacCli;
|
||||
Integer cedRifCli;
|
||||
String tipoProductoCli;
|
||||
String tipoProductoBen;
|
||||
String productoCli;
|
||||
String codEmpresa;
|
||||
String nacBen;
|
||||
Integer cedBen;
|
||||
String nombreBen;
|
||||
String productoBen;
|
||||
Double monto;
|
||||
String referencia;
|
||||
String nroDePago;
|
||||
String desPago;
|
||||
String objeto;
|
||||
Integer tipoRespuesta;
|
||||
String msgRespuesta;
|
||||
Integer tiempoRespuesta;
|
||||
String codFintech;
|
||||
String cedRifFintech;
|
||||
String tipoDispositivo;
|
||||
String desDispositivo;
|
||||
String ipCli;
|
||||
String sp;
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package application.port.input.command;
|
||||
|
||||
import domain.model.BankService;
|
||||
|
||||
public record ServiceStatusCommand(
|
||||
String applicationId,
|
||||
String transactionId,
|
||||
BankService bankService
|
||||
) { }
|
||||
@ -0,0 +1,14 @@
|
||||
package application.port.input.command;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
|
||||
/**
|
||||
* Contiene los datos entradas para el caso de uso de login de usuario
|
||||
* @param customerId
|
||||
* @param customerIdType
|
||||
*/
|
||||
@RegisterForReflection
|
||||
public record UserLoginCommand(
|
||||
String customerId,
|
||||
String customerIdType
|
||||
) { }
|
||||
@ -0,0 +1,11 @@
|
||||
package application.port.input.command;
|
||||
|
||||
public record ValidateOtpCommand(
|
||||
String otpToken,
|
||||
String appOrigen,
|
||||
String login,
|
||||
String ipAddress,
|
||||
String canal,
|
||||
String servicio,
|
||||
String domain
|
||||
) { }
|
||||
@ -0,0 +1,10 @@
|
||||
package application.port.input.command;
|
||||
|
||||
/**
|
||||
* Contiene los datos de entrada para el caso de uso de validate profile
|
||||
*/
|
||||
public record ValidateProfileCommand(
|
||||
String customerId,
|
||||
String ipAddress,
|
||||
String hash
|
||||
) {}
|
||||
@ -0,0 +1,5 @@
|
||||
package application.port.output;
|
||||
|
||||
public interface IAppConfigRepository {
|
||||
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package application.port.output;
|
||||
|
||||
public interface IMaintenanceCheckPort {
|
||||
Boolean isUnderMaintenance(String requestId);
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package application.port.output;
|
||||
|
||||
import application.exception.GatewayServiceException;
|
||||
import application.port.input.IRegisterSecurity;
|
||||
import application.port.input.command.RegisterSecurityCommand;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.repository.IRegisterSecurityPort;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class RegisterSecurityUseCase implements IRegisterSecurity {
|
||||
|
||||
private final IRegisterSecurityPort registerSecurityPort;
|
||||
|
||||
@Inject
|
||||
public RegisterSecurityUseCase(IRegisterSecurityPort registerSecurityPort) {
|
||||
this.registerSecurityPort = registerSecurityPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(RegisterSecurityCommand command, String requestId) {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Iniciando caso de uso: Registrar traza de seguridad"));
|
||||
try {
|
||||
registerSecurityPort.writeTrace(command, requestId);
|
||||
} catch (GatewayServiceException ex) {
|
||||
log.error(LoggerHelper.buildError(requestId, "Fallo la comunicacion con el servicio de register security"));
|
||||
throw ex;
|
||||
} finally {
|
||||
log.debug(LoggerHelper.buildInfoPrivateResponse(requestId, "Finalizado caso de uso: Registrar traza de seguridad"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package application.service;
|
||||
|
||||
import com.banesco.common.domain.model.redis.UserAccountRedis;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import com.banesco.common.infraestructure.repository.UserAccountRedisRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class AccountService {
|
||||
|
||||
@Inject
|
||||
UserAccountRedisRepository userAccountRedisRepository;
|
||||
|
||||
/**
|
||||
* Guarda una lista de cuentas en la caché de Redis y establece un tiempo de expiración (TTL).
|
||||
*
|
||||
* @param requestId ID de la solicitud para trazabilidad en los logs.
|
||||
* @param id El identificador único del cliente para la clave del hash.
|
||||
* @param sid El identificador de sesión para la clave del índice.
|
||||
* @param accounts La lista de cuentas a guardar.
|
||||
* @param ttlInSeconds El tiempo de vida (en segundos) para las claves en caché.
|
||||
*/
|
||||
public void saveAccounts(String requestId, String id, String sid, List<UserAccountRedis> accounts, long ttlInSeconds) {
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Iniciando guardado en Redis para el sid", sid));
|
||||
if (accounts == null || accounts.isEmpty()) {
|
||||
log.warn(LoggerHelper.buildInfoPrivateRequest(requestId, "Se intento guardar una lista de cuentas vacia o nula. No se realiza la operacion."));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
userAccountRedisRepository.saveOrUpdate(sid, accounts);
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Guardado exitoso en Redis para el sid", sid));
|
||||
} catch (Exception ex) {
|
||||
log.error(LoggerHelper.buildError(requestId, String.format("Error al intentar guardar en Redis para el sid %s. %s", sid, ex.getMessage())));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
package application.service;
|
||||
|
||||
import application.port.input.IValidateOtp;
|
||||
import application.port.input.command.ValidateOtpCommand;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import infrastructure.config.DomainConfig;
|
||||
import infrastructure.config.OtpConfig;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class OtpValidationService {
|
||||
|
||||
private final IValidateOtp validateOtpUseCase;
|
||||
private final OtpConfig otpConfig;
|
||||
private final DomainConfig domainConfig;
|
||||
|
||||
@Inject
|
||||
public OtpValidationService(
|
||||
IValidateOtp validateOtpUseCase,
|
||||
OtpConfig otpConfig,
|
||||
DomainConfig domainConfig
|
||||
) {
|
||||
this.validateOtpUseCase = validateOtpUseCase;
|
||||
this.otpConfig = otpConfig;
|
||||
this.domainConfig = domainConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Punto de entrada principal para validar un OTP.
|
||||
*
|
||||
* @return {@code true} si el OTP es válido, de lo contrario {@code false}.
|
||||
*/
|
||||
public boolean isOtpValid(
|
||||
String otpToken,
|
||||
String originApp,
|
||||
String login,
|
||||
String ipAddress,
|
||||
String requestId
|
||||
) {
|
||||
return validateOtpFromApiService(otpToken, originApp, login, ipAddress, requestId);
|
||||
}
|
||||
|
||||
private boolean validateOtpFromApiService(
|
||||
String otpToken,
|
||||
String originApp,
|
||||
String login,
|
||||
String ipAddress,
|
||||
String requestId
|
||||
) {
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Validando OTP usando servicio externo"));
|
||||
|
||||
var otpCommand = new ValidateOtpCommand(
|
||||
otpToken,
|
||||
originApp,
|
||||
login,
|
||||
ipAddress,
|
||||
otpConfig.channel(),
|
||||
otpConfig.servicio(),
|
||||
domainConfig.payment()
|
||||
);
|
||||
|
||||
return validateOtpUseCase.isValidOtp(otpCommand, requestId);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package application.service;
|
||||
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import com.banesco.common.infraestructure.repository.PostgresRedisRepository;
|
||||
import domain.entity.AppConfiguration;
|
||||
import infrastructure.mapper.PostgresMapper;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class PostgresConfigService {
|
||||
|
||||
@Inject
|
||||
PostgresRedisRepository postgresRedisRepository;
|
||||
|
||||
/**
|
||||
* Recibe una entidad AppConfiguration de la lógica de negocio y la mapea
|
||||
* a un CustomerAccountPostgresConfig del "commons" para guardarla en Redis.
|
||||
*/
|
||||
public void savePostgresConfig(String configName, AppConfiguration appConfigItem, long ttlInSeconds, String requestId) {
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Iniciando guardado de configuracion postgres en Redis", appConfigItem.toString()));
|
||||
|
||||
try {
|
||||
var commonConfigToSave = PostgresMapper.mapToCommon(appConfigItem);
|
||||
postgresRedisRepository.save(configName, commonConfigToSave, ttlInSeconds);
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Guardado exitoso en Redis. Clave: " + configName));
|
||||
} catch (Exception ex) {
|
||||
log.error(LoggerHelper.buildError(requestId, "Error al intentar guardar configuracion de postgres en Redis"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca una configuración en Redis por su nombre (clave).
|
||||
*
|
||||
* @param configName La clave de Redis (ej: el appId).
|
||||
* @param requestId El ID de la traza para logging.
|
||||
* @return Un Optional con la entidad AppConfiguration si se encuentra en caché.
|
||||
*/
|
||||
public Optional<AppConfiguration> findByName(String configName, String requestId) {
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Buscando configuracion en Redis. Clave: " + configName));
|
||||
try {
|
||||
var commonConfigOpt = postgresRedisRepository.findByName(configName);
|
||||
|
||||
if (commonConfigOpt.isEmpty()) {
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Cache miss para clave: " + configName));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Cache hit para clave: " + configName));
|
||||
|
||||
return Optional.of(PostgresMapper.mapToApp(commonConfigOpt.get()));
|
||||
|
||||
} catch (Exception ex) {
|
||||
log.error(LoggerHelper.buildError(requestId, "Error al intentar leer configuracion de postgres en Redis"), ex);
|
||||
// Si hay error en Redis, es mejor tratarlo como un "cache miss" (no encontrado)
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
package application.usecase;
|
||||
|
||||
import application.exception.GatewayServiceException;
|
||||
import application.port.input.ICustomerProduct;
|
||||
import application.port.input.command.CustomerAccountCommand;
|
||||
import application.service.AccountService;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.entity.AppConfiguration;
|
||||
import domain.model.AccountClientContext;
|
||||
import domain.model.BankingProduct;
|
||||
import domain.repository.ICustomerProductPort;
|
||||
import infrastructure.mapper.BankingProductMapper;
|
||||
import infrastructure.mapper.CacheMapper;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class CustomerProductUseCase implements ICustomerProduct {
|
||||
|
||||
private final ICustomerProductPort customerProductPort;
|
||||
private final AccountService accountService;
|
||||
|
||||
@ConfigProperty(name = "app.redis.expiration")
|
||||
long cacheTtl;
|
||||
|
||||
@Inject
|
||||
public CustomerProductUseCase(
|
||||
ICustomerProductPort customerProductPort,
|
||||
AccountService accountService
|
||||
) {
|
||||
this.customerProductPort = customerProductPort;
|
||||
this.accountService = accountService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BankingProduct> execute(CustomerAccountCommand command, AccountClientContext context, AppConfiguration appConfig, String otp, Boolean isCacheable, String requestId) {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Iniciando caso de uso: api-get-db2-accounts-client-v2"));
|
||||
try {
|
||||
|
||||
var customerAccountsFromService = customerProductPort.execute(command, requestId);
|
||||
|
||||
// Si el servicio no devuelve nada, no hay nada que guardar ni devolver.
|
||||
if (customerAccountsFromService == null || customerAccountsFromService.isEmpty()) {
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "El servicio principal no devolvio cuentas para requestId {}", requestId));
|
||||
return List.of();
|
||||
}
|
||||
|
||||
var bankingProducts = BankingProductMapper.fromCustomerAccountList(customerAccountsFromService, appConfig.isEncryptionData());
|
||||
|
||||
if(isCacheable) {
|
||||
var accountsToCache = CacheMapper.toUserAccountRedisList(
|
||||
customerAccountsFromService,
|
||||
context.getRedisKey(),
|
||||
context.getFinalCustomerId(),
|
||||
otp
|
||||
);
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(
|
||||
requestId, String.format("Guardando %s cuentas en cache", accountsToCache.size())
|
||||
));
|
||||
|
||||
accountService.saveAccounts(
|
||||
requestId,
|
||||
context.getFinalCustomerId(),
|
||||
context.getRedisKey(),
|
||||
accountsToCache,
|
||||
cacheTtl
|
||||
);
|
||||
}
|
||||
return bankingProducts;
|
||||
} catch (GatewayServiceException ex) {
|
||||
log.error(LoggerHelper.buildError(requestId, "Fallo la comunicacion con el servicio de api-get-db2-accounts-client-v2"));
|
||||
throw ex;
|
||||
} finally {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Finalizado caso de uso: api-get-db2-accounts-client-v2"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package application.usecase;
|
||||
|
||||
import application.exception.GatewayServiceException;
|
||||
import application.port.input.IEncodeValue;
|
||||
import application.port.input.command.EncodeValueCommand;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.repository.IEncodeValuePort;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class EncodeValueUseCase implements IEncodeValue {
|
||||
|
||||
private final IEncodeValuePort encodeValuePort;
|
||||
|
||||
@Inject
|
||||
public EncodeValueUseCase(IEncodeValuePort encodeValuePort) {
|
||||
this.encodeValuePort = encodeValuePort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(EncodeValueCommand command, String requestId) {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Iniciando caso de uso: Encode Value"));
|
||||
try {
|
||||
return encodeValuePort.execute(command, requestId);
|
||||
} catch (GatewayServiceException ex) {
|
||||
log.error(LoggerHelper.buildError(requestId, "Fallo la comunicacion con el servicio de Encode Value: " + ex.getMessage()));
|
||||
throw ex;
|
||||
} finally {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Finalizado caso de uso: Encode Value"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package application.usecase;
|
||||
|
||||
import application.port.input.IAppConfig;
|
||||
import domain.entity.AppConfiguration;
|
||||
import domain.repository.AppConfigRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class GetAppConfigUseCase implements IAppConfig {
|
||||
|
||||
private final AppConfigRepository appConfigRepository;
|
||||
|
||||
@Inject
|
||||
public GetAppConfigUseCase(AppConfigRepository appConfigRepository) {
|
||||
this.appConfigRepository = appConfigRepository;
|
||||
}
|
||||
|
||||
public AppConfiguration execute(String appName) {
|
||||
|
||||
return appConfigRepository.findConfigByAppName(appName)
|
||||
.orElseThrow(() -> new NotFoundException("Configuracion no encontrada para la app: " + appName));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package application.usecase;
|
||||
|
||||
import application.exception.GatewayServiceException;
|
||||
import application.port.input.IServiceStatus;
|
||||
import application.port.input.command.ServiceStatusCommand;
|
||||
import application.port.output.IMaintenanceCheckPort;
|
||||
import com.banesco.common.infraestructure.helpers.JsonHelper;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.repository.IStatusPort;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class ServiceStatusUseCase implements IServiceStatus {
|
||||
|
||||
private static final String INACTIVE_STATUS = "I";
|
||||
|
||||
private final IStatusPort statusApiPort;
|
||||
private final IMaintenanceCheckPort maintenancePort;
|
||||
|
||||
@Inject
|
||||
public ServiceStatusUseCase(
|
||||
IStatusPort statusApiService,
|
||||
IMaintenanceCheckPort maintenancePort
|
||||
) {
|
||||
this.statusApiPort = statusApiService;
|
||||
this.maintenancePort = maintenancePort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determina el estado de disponibilidad de un servicio, devolviendo true si está activo y false si no lo está.
|
||||
*
|
||||
* @param command El objeto de comando que contiene los datos necesarios para la consulta, como el ID de aplicación y transacción.
|
||||
* @param requestId Un identificador único de la solicitud, utilizado principalmente para la trazabilidad en los logs.
|
||||
* @return {@code true} si el servicio se considera activo; {@code false} si está inactivo, en mantenimiento o si la verificación falló.
|
||||
*/
|
||||
@Override
|
||||
public Boolean execute(ServiceStatusCommand command, String requestId) {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Iniciando caso de uso: Service Status"));
|
||||
|
||||
// Si no estamos en ventana de mantenimiento, el servicio está activo.
|
||||
if(!maintenancePort.isUnderMaintenance(requestId)) {
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "No estamos en ventana de mantenimiento. Servicio ACTIVO"));
|
||||
return true;
|
||||
}
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "En ventana de mantenimiento, consultando estado remoto..."));
|
||||
|
||||
try {
|
||||
// Si estamos en horario de validacion, consultamos el estado remoto.
|
||||
var remoteStatus = statusApiPort.getServiceStatus(command, requestId);
|
||||
|
||||
var isActive = remoteStatus != null && !INACTIVE_STATUS.equalsIgnoreCase(remoteStatus.getStatus());
|
||||
|
||||
if (isActive) {
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "El servicio externo confirmo estado ACTIVO"));
|
||||
} else {
|
||||
log.warn(LoggerHelper.buildInfoPrivateRequest(requestId, "El servicio externo esta nulo o en estado INACTIVO"));
|
||||
}
|
||||
return isActive;
|
||||
} catch (GatewayServiceException ex) {
|
||||
log.error(LoggerHelper.buildError(requestId, "Fallo la comunicacion con el servicio de service status"));
|
||||
throw ex;
|
||||
} finally {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Finalizado caso de uso: Service Status"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package application.usecase;
|
||||
|
||||
import application.exception.GatewayServiceException;
|
||||
import application.port.input.IUserLogin;
|
||||
import application.port.input.command.UserLoginCommand;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.model.UserLogin;
|
||||
import domain.repository.IUserLoginPort;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class UserLoginUseCase implements IUserLogin {
|
||||
|
||||
private final IUserLoginPort userLoginApiPort;
|
||||
|
||||
public UserLoginUseCase(IUserLoginPort userLoginApiPort) {
|
||||
this.userLoginApiPort = userLoginApiPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Orquesta la ejecución del caso de uso de login de usuario
|
||||
* Encapsula la lógica de negocio, incluyendo la generación de códigos de referencia
|
||||
* y el manejo de fallos de comunicación con el servicio externo.
|
||||
* @param command El comando con los datos de entrada para el login.
|
||||
* @param requestId El ID de la solicitud para trazabilidad.
|
||||
* @return Un {@link Optional} con el objeto {@link UserLogin} si el login fue exitoso,
|
||||
* o un {@code Optional.empty()} si falló por cualquier motivo.
|
||||
*/
|
||||
@Override
|
||||
public Optional<UserLogin> execute(UserLoginCommand command, String requestId) {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Iniciando caso de uso: User Login"));
|
||||
try {
|
||||
var result = userLoginApiPort.execute(command, requestId);
|
||||
|
||||
if(result == null) {
|
||||
log.error(LoggerHelper.buildError(requestId, " El login no fue exitoso segun la respuesta del servicio"));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
log.debug(LoggerHelper.buildInfoPrivateResponse(requestId, "Finalizado caso de uso: User Login"));
|
||||
return Optional.of(result);
|
||||
} catch (GatewayServiceException ex) {
|
||||
log.error(LoggerHelper.buildError(requestId, "Fallo la comunicacion con el servicio de User Login"));
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
package application.usecase;
|
||||
|
||||
import application.exception.GatewayServiceException;
|
||||
import application.exception.InvalidTokenException;
|
||||
import application.port.input.IValidateOtp;
|
||||
import application.port.input.command.ValidateOtpCommand;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.repository.IOtpPort;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jboss.resteasy.reactive.RestResponse;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class ValidateOtpUseCase implements IValidateOtp {
|
||||
|
||||
private final IOtpPort otpApiPort;
|
||||
|
||||
@Inject
|
||||
public ValidateOtpUseCase(IOtpPort otpApiService) {
|
||||
this.otpApiPort = otpApiService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Orquesta la validación de un token OTP.
|
||||
* Encapsula la lógica de negocio para determinar si un OTP es válido,
|
||||
* manejando también los fallos de comunicación con el servicio externo.
|
||||
*
|
||||
* @param command El comando con los datos necesarios para validar el OTP.
|
||||
* @param requestId El ID de la solicitud para trazabilidad.
|
||||
* @return {@code true} si el servicio externo responde con un status HTTP 200 (OK),
|
||||
* {@code false} en cualquier otro caso (respuesta de error o fallo de comunicación).
|
||||
*/
|
||||
@Override
|
||||
public Boolean isValidOtp(ValidateOtpCommand command, String requestId) {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Iniciando caso de uso: Validate OTP"));
|
||||
|
||||
try {
|
||||
var apiResponse = otpApiPort.validateOtp(command, requestId);
|
||||
var isValid = apiResponse.getStatus() == RestResponse.Status.OK.getStatusCode();
|
||||
|
||||
log.info("Validacion de OTP para requestId {}. Resultado: {}. Codigo de estado recibido: {}",
|
||||
requestId, isValid, apiResponse.getStatus());
|
||||
|
||||
return isValid;
|
||||
} catch(InvalidTokenException ex) {
|
||||
return false;
|
||||
} catch(GatewayServiceException ex) {
|
||||
log.error(LoggerHelper.buildError(requestId, "Fallo la comunicacion con el servicio de validate otp"));
|
||||
throw ex;
|
||||
} finally {
|
||||
log.debug(LoggerHelper.buildInfoPrivateResponse(requestId, "Finalizado caso de uso: Validate OTP"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package application.usecase;
|
||||
|
||||
import application.exception.GatewayServiceException;
|
||||
import application.port.input.IValidateProfile;
|
||||
import application.port.input.command.ValidateProfileCommand;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.model.ClientProfile;
|
||||
import domain.repository.IValidateProfilePort;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class ValidateProfileUseCase implements IValidateProfile {
|
||||
|
||||
private final IValidateProfilePort validateProfilePort;
|
||||
|
||||
@Inject
|
||||
public ValidateProfileUseCase(IValidateProfilePort validateProfilePort) {
|
||||
this.validateProfilePort = validateProfilePort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Orquesta la validación del perfil de un cliente.
|
||||
* Determina si un perfil es válido según la respuesta de un servicio externo,
|
||||
* navegando de forma segura a través de una estructura de datos anidada.
|
||||
*
|
||||
* @param command El comando con los datos de entrada para la validación.
|
||||
* @param requestId El ID de la solicitud para trazabilidad.
|
||||
* @return {@code true} si el perfil es válido (status = 0), {@code false} en cualquier otro caso.
|
||||
*/
|
||||
@Override
|
||||
public Boolean execute(ValidateProfileCommand command, String requestId) {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Iniciando caso de uso: Validate Profile"));
|
||||
try {
|
||||
var result = validateProfilePort.execute(command, requestId);
|
||||
|
||||
// La validación completa se realiza en una única cadena funcional y segura.
|
||||
var isValidProfile = Optional.ofNullable(result)
|
||||
.filter(profile -> !profile.getHasError())
|
||||
.flatMap(this::extractStatusFromData)
|
||||
.map(status -> status == 0)
|
||||
.orElse(false);
|
||||
|
||||
log.info("{} - Validacion de perfil completada ¿Es valido?: {}", requestId, isValidProfile);
|
||||
return isValidProfile;
|
||||
|
||||
} catch (GatewayServiceException ex) {
|
||||
log.error(LoggerHelper.buildError(requestId, "Fallo la comunicacion con el servicio de Validate Profile"));
|
||||
throw ex;
|
||||
} finally {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Finalizado caso de uso: Validate Profile"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper privado para navegar de forma segura la estructura de Mapas anidada
|
||||
* y extraer el valor de 'stausu'.
|
||||
*
|
||||
* @param profile El objeto ClientProfile que contiene los datos.
|
||||
* @return Un Optional<Integer> con el valor de 'stausu' si se encuentra.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Optional<Integer> extractStatusFromData(ClientProfile profile) {
|
||||
return Optional.ofNullable(profile.getData())
|
||||
.filter(Map.class::isInstance).map(m -> (Map<String, Object>) m)
|
||||
.map(data -> data.get("banesco"))
|
||||
.filter(Map.class::isInstance).map(m -> (Map<String, Object>) m)
|
||||
.map(banesco -> banesco.get("respuesta"))
|
||||
.filter(Map.class::isInstance).map(m -> (Map<String, Object>) m)
|
||||
.map(res -> res.get("respuesta"))
|
||||
.filter(Map.class::isInstance).map(m -> (Map<String, Object>) m)
|
||||
.map(respuesta -> respuesta.get("stausu"))
|
||||
.filter(Integer.class::isInstance)
|
||||
.map(Integer.class::cast);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package domain.dto.request;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class CustomerRequest {
|
||||
|
||||
@Valid
|
||||
@NotNull(message = "VDE01")
|
||||
private CustomerPositionState customerPositionState;
|
||||
|
||||
@Valid
|
||||
@NotNull(message = "VDE01")
|
||||
private Device device;
|
||||
|
||||
private TokenAssignmentInstance tokenAssignmentInstance;
|
||||
|
||||
@Data
|
||||
public static class CustomerPositionState {
|
||||
private CustomerReference customerReference;
|
||||
|
||||
@Data
|
||||
public static class CustomerReference {
|
||||
|
||||
/**
|
||||
* Valida que sea una única letra del conjunto [V, E, P, G, J].
|
||||
*/
|
||||
private String customerIdType;
|
||||
|
||||
/**
|
||||
* Valida que sea numérico con un máximo de 9 dígitos.
|
||||
*/
|
||||
private String customerId;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Device {
|
||||
private String deviceType;
|
||||
private String deviceDescription;
|
||||
private String deviceIp;
|
||||
private String deviceSessionReference;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class TokenAssignmentInstance {
|
||||
private String tokenIdentificationCode;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package domain.dto.response;
|
||||
|
||||
import domain.model.BankingProduct;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public class CustomerPositionStateResponse {
|
||||
int record;
|
||||
List<BankingProduct> bankingProducts;
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package domain.dto.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@RegisterForReflection
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class CustomerResponse {
|
||||
StatusResponse statusResponse;
|
||||
CustomerPositionStateResponse customerPositionState;
|
||||
|
||||
public CustomerResponse(StatusResponse statusResponse, CustomerPositionStateResponse customerPositionState) {
|
||||
this.statusResponse = statusResponse;
|
||||
this.customerPositionState = customerPositionState;
|
||||
}
|
||||
|
||||
public CustomerResponse(StatusResponse statusResponse) {
|
||||
this.statusResponse = statusResponse;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package domain.dto.response;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public class StatusResponse {
|
||||
String status;
|
||||
String statusCode;
|
||||
String message;
|
||||
String traceId;
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package domain.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import domain.model.Configuration;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@RegisterForReflection
|
||||
public class AppConfiguration {
|
||||
|
||||
@JsonIgnore
|
||||
private Long appId;
|
||||
|
||||
private String appName;
|
||||
|
||||
private String apiName;
|
||||
|
||||
private String type;
|
||||
|
||||
private String event;
|
||||
|
||||
private boolean encryptionData;
|
||||
|
||||
private Configuration configuration;
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package domain.entity;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@RegisterForReflection
|
||||
public class ConfigItem {
|
||||
boolean cacheable;
|
||||
String bankCode;
|
||||
String currencyCode;
|
||||
String status;
|
||||
String statusMe;
|
||||
String productCv;
|
||||
String product;
|
||||
String channel;
|
||||
String service;
|
||||
String operator;
|
||||
String phone;
|
||||
String affiliationStatus;
|
||||
String counterpartyAccount;
|
||||
String holder;
|
||||
String codProduct;
|
||||
String statusOperation;
|
||||
String statusRestriction;
|
||||
String statusOperationRestriction;
|
||||
|
||||
public ConfigItem() {}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package domain.model;
|
||||
|
||||
import domain.dto.request.CustomerRequest;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Data
|
||||
@RegisterForReflection
|
||||
public class AccountClientContext {
|
||||
// Datos de entrada
|
||||
final long startExecution;
|
||||
final String requestId;
|
||||
final CustomerRequest request;
|
||||
final String appId, fintechId, finalCustomerId, redisKey;
|
||||
String username;
|
||||
|
||||
Optional<ErrorCode> finalError = Optional.empty();
|
||||
|
||||
public AccountClientContext(long startExecution, String requestId, CustomerRequest request, String... headers) {
|
||||
var customer = request.getCustomerPositionState().getCustomerReference();
|
||||
var sid = request.getDevice().getDeviceSessionReference();
|
||||
|
||||
this.startExecution = startExecution;
|
||||
this.requestId = requestId;
|
||||
this.request = request;
|
||||
|
||||
this.appId = headers[0];
|
||||
this.fintechId = headers[1];
|
||||
this.finalCustomerId = customer.getCustomerIdType().concat(customer.getCustomerId());
|
||||
|
||||
this.username = Optional.ofNullable(headers[2]).orElse(this.finalCustomerId);
|
||||
|
||||
this.redisKey = Optional.ofNullable(sid)
|
||||
.filter(s -> !s.isBlank())
|
||||
.map(s -> this.finalCustomerId + sid)
|
||||
.orElse(this.finalCustomerId);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package domain.model;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
|
||||
@RegisterForReflection
|
||||
public record BankService(
|
||||
String bankCode,
|
||||
String serviceCode,
|
||||
String eventCode
|
||||
) {}
|
||||
@ -0,0 +1,17 @@
|
||||
package domain.model;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public class BankingProduct {
|
||||
String productNumber;
|
||||
String productType;
|
||||
BigDecimal balance;
|
||||
String currency;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package domain.model;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public class ClientProfile {
|
||||
Boolean hasError;
|
||||
String errorMessage;
|
||||
String errorCode;
|
||||
Object data;
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package domain.model;
|
||||
|
||||
import domain.entity.ConfigItem;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@RegisterForReflection
|
||||
public class Configuration {
|
||||
private Map<String, Boolean> validationRules;
|
||||
private Map<String, String> aliases;
|
||||
private Map<String, ConfigItem> configuration;
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package domain.model;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public class CustomerAccount {
|
||||
String banco;
|
||||
String cuenta;
|
||||
String producto;
|
||||
String descProd;
|
||||
String claseCta;
|
||||
String tipoCta;
|
||||
String moneda;
|
||||
BigDecimal saldoDisponible;
|
||||
String estatus;
|
||||
String statusMe;
|
||||
String titular;
|
||||
BigDecimal maximumPerDay;
|
||||
BigDecimal maximumPerTransaction;
|
||||
BigDecimal maximumPerMonth;
|
||||
BigDecimal maximumMonthlyFee;
|
||||
BigDecimal minimumPerTransaction;
|
||||
String operator;
|
||||
String phone;
|
||||
String channel;
|
||||
String service;
|
||||
String affiliationStatus;
|
||||
String codeError;
|
||||
String descError;
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package domain.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
|
||||
/**
|
||||
* Representa un código de error de la aplicación.
|
||||
*/
|
||||
@RegisterForReflection
|
||||
public record ErrorCode(
|
||||
@JsonProperty("backend_code") String backendCode,
|
||||
@JsonProperty("http_code") String httpCode,
|
||||
@JsonProperty("status_code") String statusCode,
|
||||
@JsonProperty("description") String description,
|
||||
@JsonProperty("status") String status
|
||||
) {
|
||||
/**
|
||||
* Convierte de forma segura el 'httpCode' a un código de estado HTTP numérico.
|
||||
* @return El código de estado HTTP como un entero.
|
||||
*/
|
||||
public int getHttpStatusCode() {
|
||||
try {
|
||||
return Integer.parseInt(this.httpCode);
|
||||
} catch (NumberFormatException e) {
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package domain.model;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
|
||||
@RegisterForReflection
|
||||
public record FoundAccountInfo(
|
||||
String clearAccount,
|
||||
String username,
|
||||
String otp,
|
||||
String accountType
|
||||
) {}
|
||||
@ -0,0 +1,15 @@
|
||||
package domain.model;
|
||||
|
||||
import com.banesco.xmlns.enterpriseobjects.msgrshdr.MsgRsHdr;
|
||||
import infrastructure.client.otp.dto.response.Status;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public class Otp {
|
||||
MsgRsHdr msgRsHdr;
|
||||
Status status;
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package domain.model;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public class ServiceStatus {
|
||||
String status;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package domain.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public record UserLogin(
|
||||
String usernameBol,
|
||||
String usernameBOLE,
|
||||
String idNumber
|
||||
) { }
|
||||
@ -0,0 +1,9 @@
|
||||
package domain.repository;
|
||||
|
||||
import domain.entity.AppConfiguration;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface AppConfigRepository {
|
||||
Optional<AppConfiguration> findConfigByAppName(String appName);
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package domain.repository;
|
||||
|
||||
import application.port.input.command.CustomerAccountCommand;
|
||||
import domain.model.CustomerAccount;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ICustomerProductPort {
|
||||
List<CustomerAccount> execute(CustomerAccountCommand command, String requestId);
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package domain.repository;
|
||||
|
||||
import application.port.input.command.EncodeValueCommand;
|
||||
|
||||
public interface IEncodeValuePort {
|
||||
String execute(EncodeValueCommand command, String requestId);
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package domain.repository;
|
||||
|
||||
import application.port.input.command.ValidateOtpCommand;
|
||||
import org.jboss.resteasy.reactive.RestResponse;
|
||||
|
||||
public interface IOtpPort {
|
||||
RestResponse<Void> validateOtp(ValidateOtpCommand command, String requestId);
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package domain.repository;
|
||||
|
||||
import application.port.input.command.RegisterSecurityCommand;
|
||||
|
||||
public interface IRegisterSecurityPort {
|
||||
void writeTrace(RegisterSecurityCommand request, String requestId);
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package domain.repository;
|
||||
|
||||
import application.port.input.command.ServiceStatusCommand;
|
||||
import domain.model.ServiceStatus;
|
||||
|
||||
public interface IStatusPort {
|
||||
ServiceStatus getServiceStatus(ServiceStatusCommand query, String requestId);
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package domain.repository;
|
||||
|
||||
import application.port.input.command.UserLoginCommand;
|
||||
import domain.model.UserLogin;
|
||||
|
||||
public interface IUserLoginPort {
|
||||
UserLogin execute(
|
||||
UserLoginCommand command,
|
||||
String requestId
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package domain.repository;
|
||||
|
||||
import application.port.input.command.ValidateProfileCommand;
|
||||
import domain.model.ClientProfile;
|
||||
|
||||
public interface IValidateProfilePort {
|
||||
ClientProfile execute(ValidateProfileCommand command, String requestId);
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
package infrastructure.adapter.input.rest;
|
||||
|
||||
import application.helper.ResponseHelper;
|
||||
import application.port.input.IAppConfig;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.dto.response.CustomerResponse;
|
||||
import domain.entity.AppConfiguration;
|
||||
import infrastructure.context.TraceIdContext;
|
||||
import infrastructure.service.StatusDescriptionResolver;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.microprofile.openapi.annotations.Operation;
|
||||
import org.eclipse.microprofile.openapi.annotations.enums.ParameterIn;
|
||||
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Content;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.ExampleObject;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
|
||||
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
|
||||
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
|
||||
import org.jboss.resteasy.reactive.RestPath;
|
||||
|
||||
@Slf4j
|
||||
@Path("/customer")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class AppConfigResource {
|
||||
|
||||
// --- CASOS DE USO Y SERVICIOS ---
|
||||
private final IAppConfig appConfigUseCase;
|
||||
|
||||
// --- DEPENDENCIAS ADICIONALES ---
|
||||
private final ResponseHelper responseHelper;
|
||||
private final TraceIdContext traceIdContext;
|
||||
|
||||
public AppConfigResource(
|
||||
IAppConfig appConfigUseCase,
|
||||
ResponseHelper responseHelper,
|
||||
TraceIdContext traceIdContext,
|
||||
StatusDescriptionResolver statusDescriptionResolver
|
||||
) {
|
||||
this.appConfigUseCase = appConfigUseCase;
|
||||
this.responseHelper = responseHelper;
|
||||
this.traceIdContext = traceIdContext;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/config/{appName}")
|
||||
@Operation(
|
||||
summary = "Obtener Configuración de Aplicación",
|
||||
description = "Obtiene la configuración JSON completa para un 'appName' (appId) específico. Este endpoint se usa para testing o recarga manual."
|
||||
)
|
||||
@Parameter(
|
||||
name = "appName",
|
||||
in = ParameterIn.PATH,
|
||||
description = "El 'appName' (appId) que se usará para buscar la configuración.",
|
||||
required = true,
|
||||
schema = @Schema(type = SchemaType.STRING),
|
||||
example = "abc123"
|
||||
)
|
||||
@APIResponses(value = {
|
||||
@APIResponse(
|
||||
responseCode = "200",
|
||||
description = "Configuración encontrada.",
|
||||
content = @Content(
|
||||
mediaType = MediaType.APPLICATION_JSON,
|
||||
schema = @Schema(implementation = AppConfiguration.class),
|
||||
examples = {
|
||||
@ExampleObject(
|
||||
name = "Configuración encontrada",
|
||||
externalValue = "/openapi-examples/response/app-config.json"
|
||||
)
|
||||
}
|
||||
)
|
||||
),
|
||||
@APIResponse(
|
||||
responseCode = "400",
|
||||
description = "Configuración no encontrada. El 'appName' no existe en la base de datos.",
|
||||
content = @Content(
|
||||
mediaType = MediaType.APPLICATION_JSON,
|
||||
schema = @Schema(implementation = CustomerResponse.class),
|
||||
examples = {
|
||||
@ExampleObject(
|
||||
name = "Configuración no encontrada",
|
||||
summary = "VRN_CONFIG_NOT_FOUND",
|
||||
externalValue = "/openapi-examples/response/config-not-found.json"
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
})
|
||||
public Response getConfig(@RestPath String appName) {
|
||||
final var requestId = traceIdContext.getTraceId();
|
||||
|
||||
try {
|
||||
var config = appConfigUseCase.execute(appName);
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Configuracion encontrada para appName: " + appName));
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Configuracion: " + config));
|
||||
|
||||
return Response.ok(config).build();
|
||||
|
||||
} catch (NotFoundException ex) {
|
||||
log.warn(LoggerHelper.buildError(requestId, "Configuracion no encontrada (VRN_CONFIG_NOT_FOUND) para appName: " + appName));
|
||||
return responseHelper.buildErrorResponse("VRN_CONFIG_NOT_FOUND", requestId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,540 @@
|
||||
package infrastructure.adapter.input.rest;
|
||||
|
||||
import application.factory.SecurityTraceFactory;
|
||||
import application.helper.ResponseHelper;
|
||||
import application.port.input.*;
|
||||
import application.port.input.command.*;
|
||||
import application.service.OtpValidationService;
|
||||
import application.service.PostgresConfigService;
|
||||
import com.banesco.common.infraestructure.helpers.JsonHelper;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.dto.request.CustomerRequest;
|
||||
import domain.dto.response.CustomerResponse;
|
||||
import domain.dto.response.StatusResponse;
|
||||
import domain.entity.AppConfiguration;
|
||||
import domain.entity.ConfigItem;
|
||||
import domain.model.AccountClientContext;
|
||||
import domain.model.BankService;
|
||||
import domain.model.ErrorCode;
|
||||
import domain.model.UserLogin;
|
||||
import infrastructure.config.AvailabilityBolConfig;
|
||||
import infrastructure.context.TraceIdContext;
|
||||
import infrastructure.service.StatusDescriptionResolver;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.ws.rs.HeaderParam;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.eclipse.microprofile.openapi.annotations.Operation;
|
||||
import org.eclipse.microprofile.openapi.annotations.enums.ParameterIn;
|
||||
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Content;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.ExampleObject;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
|
||||
import org.eclipse.microprofile.openapi.annotations.parameters.Parameters;
|
||||
import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;
|
||||
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
|
||||
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
@Path("/customer")
|
||||
public class CustomerResource {
|
||||
|
||||
@ConfigProperty(name = "app.redis.expiration")
|
||||
long cacheTtl;
|
||||
|
||||
// --- DEPENDENCIAS INYECTADAS ---
|
||||
private final TraceIdContext traceIdContext;
|
||||
private final ResponseHelper responseHelper;
|
||||
private final SecurityTraceFactory securityTraceFactory;
|
||||
private final StatusDescriptionResolver statusDescriptionResolver;
|
||||
|
||||
// --- CONFIGURACIONES ---
|
||||
private final AvailabilityBolConfig bolConfig;
|
||||
|
||||
// --- CASOS DE USO Y SERVICIOS ---
|
||||
private final IAppConfig appConfigUseCase;
|
||||
private final IServiceStatus serviceStatusUseCase;
|
||||
private final IUserLogin userLoginUseCase;
|
||||
private final IValidateProfile validateProfileUseCase;
|
||||
private final IEncodeValue encodeValueUseCase;
|
||||
private final ICustomerProduct customerProductUseCase;
|
||||
private final IRegisterSecurity registerSecurityUseCase;
|
||||
private final OtpValidationService otpValidationService;
|
||||
private final PostgresConfigService postgresConfigService;
|
||||
|
||||
public CustomerResource(
|
||||
TraceIdContext traceIdContext,
|
||||
ResponseHelper responseHelper,
|
||||
SecurityTraceFactory securityTraceFactory,
|
||||
AvailabilityBolConfig bolConfig,
|
||||
StatusDescriptionResolver statusDescriptionResolver,
|
||||
IAppConfig appConfigUseCase,
|
||||
IServiceStatus serviceStatusUseCase,
|
||||
IUserLogin userLoginUseCase,
|
||||
IValidateProfile validateProfileUseCase,
|
||||
IEncodeValue encodeValueUseCase,
|
||||
ICustomerProduct customerProductUseCase,
|
||||
IRegisterSecurity registerSecurityUseCase,
|
||||
OtpValidationService otpValidationService,
|
||||
PostgresConfigService postgresConfigService
|
||||
) {
|
||||
this.traceIdContext = traceIdContext;
|
||||
this.responseHelper = responseHelper;
|
||||
this.securityTraceFactory = securityTraceFactory;
|
||||
this.bolConfig = bolConfig;
|
||||
this.statusDescriptionResolver = statusDescriptionResolver;
|
||||
this.appConfigUseCase = appConfigUseCase;
|
||||
this.serviceStatusUseCase = serviceStatusUseCase;
|
||||
this.userLoginUseCase = userLoginUseCase;
|
||||
this.validateProfileUseCase = validateProfileUseCase;
|
||||
this.encodeValueUseCase = encodeValueUseCase;
|
||||
this.customerProductUseCase = customerProductUseCase;
|
||||
this.registerSecurityUseCase = registerSecurityUseCase;
|
||||
this.otpValidationService = otpValidationService;
|
||||
this.postgresConfigService = postgresConfigService;
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/position/evaluate")
|
||||
@Operation(
|
||||
summary = "Consulta de cuentas",
|
||||
description = "Orquesta el flujo de validaciones (estatus de servicio, perfil, OTP, etc.) y, si son exitosas, consulta los productos del cliente."
|
||||
)
|
||||
@Parameters({
|
||||
@Parameter(
|
||||
name = "requestId",
|
||||
in = ParameterIn.HEADER,
|
||||
description = "Identificador de la solicitud para la trazabilidad. Si se omite, se genera uno automático.",
|
||||
schema = @Schema(type = SchemaType.STRING),
|
||||
example = "7WCnvznd0CPrBZ0jF4af"
|
||||
),
|
||||
@Parameter(
|
||||
name = "appId",
|
||||
in = ParameterIn.HEADER,
|
||||
description = "Identificador de la aplicación cliente para cargar una configuración de header específica. Si se omite, se usa la configuración por defecto.",
|
||||
schema = @Schema(type = SchemaType.STRING),
|
||||
example = "abc123"
|
||||
)
|
||||
})
|
||||
@RequestBody(
|
||||
description = "Cuerpo de la solicitud con los datos necesarios para consultar las cuentas.",
|
||||
content = @Content(mediaType = MediaType.APPLICATION_JSON, schema =
|
||||
@Schema(implementation = CustomerRequest.class),
|
||||
examples = {
|
||||
@ExampleObject(
|
||||
name = "Solicitud Estándar",
|
||||
summary = "Ejemplo de solicitud con éxito",
|
||||
externalValue = "/openapi-examples/request/customer-product-success.json"
|
||||
),
|
||||
@ExampleObject(
|
||||
name = "Solicitud con Token",
|
||||
summary = "Ejemplo de solicitud con token (éxito)",
|
||||
externalValue = "/openapi-examples/request/customer-product-token-success.json"
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
@APIResponses(value = {
|
||||
@APIResponse(
|
||||
responseCode = "200",
|
||||
description = "Operación Exitosa. Devuelve la lista de productos del cliente.",
|
||||
content = @Content(
|
||||
mediaType = MediaType.APPLICATION_JSON,
|
||||
schema = @Schema(implementation = CustomerResponse.class),
|
||||
examples = {
|
||||
@ExampleObject(
|
||||
name = "Cuentas Enmascaradas",
|
||||
summary = "Respuesta exitosa (Enmascaramiento activo)",
|
||||
description = "La configuración de la app indica que 'encryptionData' es true.",
|
||||
externalValue = "/openapi-examples/response/customer-product-response.json"
|
||||
),
|
||||
@ExampleObject(
|
||||
name = "Cuentas Reales",
|
||||
summary = "Respuesta exitosa (Sin enmascaramiento)",
|
||||
description = "La configuración de la app indica que 'encryptionData' es false.",
|
||||
externalValue = "/openapi-examples/response/customer-product-response-unmasked.json"
|
||||
),
|
||||
@ExampleObject(
|
||||
name = "Sin Resultados",
|
||||
summary = "Respuesta exitosa (Cliente sin productos)",
|
||||
description = "La consulta se completó, pero el cliente no tiene productos que coincidan.",
|
||||
externalValue = "/openapi-examples/response/customer-product-without-results.json"
|
||||
)
|
||||
}
|
||||
)
|
||||
),
|
||||
@APIResponse(
|
||||
responseCode = "401",
|
||||
description = "Error de Autorización o Perfil. El perfil del cliente no es válido o falló una validación de seguridad.",
|
||||
content = @Content(
|
||||
mediaType = MediaType.APPLICATION_JSON,
|
||||
schema = @Schema(implementation = StatusResponse.class),
|
||||
examples = {
|
||||
@ExampleObject(
|
||||
name = "Perfil Inválido",
|
||||
summary = "VRN01 - Perfil no válido",
|
||||
externalValue = "/openapi-examples/response/invalid-profile.json"
|
||||
)
|
||||
}
|
||||
)
|
||||
),
|
||||
@APIResponse(
|
||||
responseCode = "400",
|
||||
description = "Datos de entrada inválidos, como un token OTP incorrecto o una configuración de app no encontrada.",
|
||||
content = @Content(
|
||||
mediaType = MediaType.APPLICATION_JSON,
|
||||
schema = @Schema(implementation = StatusResponse.class),
|
||||
examples = {
|
||||
@ExampleObject(
|
||||
name = "Token Inválido",
|
||||
summary = "VRN07 - OTP Inválido",
|
||||
externalValue = "/openapi-examples/response/invalid-token.json"
|
||||
),
|
||||
@ExampleObject(
|
||||
name = "Configuración no encontrada",
|
||||
summary = "VRN_CONFIG_NOT_FOUND",
|
||||
externalValue = "/openapi-examples/response/config-not-found.json"
|
||||
)
|
||||
}
|
||||
)
|
||||
),
|
||||
@APIResponse(
|
||||
responseCode = "404",
|
||||
description = "Recurso no encontrado. Puede ser un usuario BOL, un login vacío.",
|
||||
content = @Content(
|
||||
mediaType = MediaType.APPLICATION_JSON,
|
||||
schema = @Schema(implementation = CustomerResponse.class),
|
||||
examples = {
|
||||
@ExampleObject(
|
||||
name = "Usuario no existe",
|
||||
summary = "AUTH02 - Usuario no existe",
|
||||
externalValue = "/openapi-examples/response/user-bol-not-exist.json"
|
||||
),
|
||||
@ExampleObject(
|
||||
name = "Usuario vacío",
|
||||
summary = "AUTH01 - Login vacío",
|
||||
externalValue = "/openapi-examples/response/user-not-exist.json"
|
||||
),
|
||||
}
|
||||
)
|
||||
),
|
||||
@APIResponse(
|
||||
responseCode = "409",
|
||||
description = "CONFLICTO.",
|
||||
content = @Content(
|
||||
mediaType = MediaType.APPLICATION_JSON,
|
||||
schema = @Schema(implementation = StatusResponse.class),
|
||||
examples = {
|
||||
@ExampleObject(
|
||||
name = "Conflicto",
|
||||
summary = "Conflicto (revisar)",
|
||||
externalValue = "/openapi-examples/response/conflict.json"
|
||||
)
|
||||
}
|
||||
)
|
||||
),
|
||||
@APIResponse(
|
||||
responseCode = "500",
|
||||
description = "Uso Interno. Ocurrio un error inesperado.",
|
||||
content = @Content(
|
||||
mediaType = MediaType.APPLICATION_JSON,
|
||||
schema = @Schema(implementation = StatusResponse.class),
|
||||
examples = {
|
||||
@ExampleObject(
|
||||
name = "Uso Interno",
|
||||
summary = "Uso Interno (revisar)",
|
||||
externalValue = "/openapi-examples/response/internal-use.json"
|
||||
)
|
||||
}
|
||||
)
|
||||
),
|
||||
@APIResponse(
|
||||
responseCode = "503",
|
||||
description = "Servicio no disponible. Ocurrió un error con una dependencia interna o el servicio está en mantenimiento.",
|
||||
content = @Content(
|
||||
mediaType = MediaType.APPLICATION_JSON,
|
||||
schema = @Schema(implementation = StatusResponse.class),
|
||||
examples = {
|
||||
@ExampleObject(
|
||||
name = "Mantenimiento",
|
||||
summary = "VRN04 - Servicio en mantenimiento",
|
||||
externalValue = "/openapi-examples/response/service-unavailable.json"
|
||||
),
|
||||
@ExampleObject(
|
||||
name = "Error de Dependencia",
|
||||
summary = "Error de CI",
|
||||
externalValue = "/openapi-examples/response/customer-product-rest-client-error.json"
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
})
|
||||
public Response getCustomerProducts(
|
||||
@HeaderParam("appId") String appId,
|
||||
@HeaderParam("customerReferenceFintechId") String customerReferenceFintechId,
|
||||
@HeaderParam("customerReferenceUser") String customerReferenceUser,
|
||||
@Valid @NotNull(message = "VDE01") CustomerRequest request
|
||||
) {
|
||||
final var requestId = traceIdContext.getTraceId();
|
||||
final long startExecution = System.currentTimeMillis();
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, JsonHelper.getJsonFromObject(request)));
|
||||
|
||||
var context = new AccountClientContext(startExecution, requestId, request,
|
||||
appId, customerReferenceFintechId, customerReferenceUser
|
||||
);
|
||||
|
||||
var appConfigurationOpt = getPgConfig(context, requestId);
|
||||
|
||||
if (appConfigurationOpt.isEmpty()) {
|
||||
var error = statusDescriptionResolver.getCode("VRN_CONFIG_NOT_FOUND");
|
||||
return responseHelper.buildErrorResponse(error, requestId);
|
||||
}
|
||||
|
||||
var appConfiguration = appConfigurationOpt.get();
|
||||
|
||||
var validationRules = appConfiguration.getConfiguration().getValidationRules();
|
||||
var validationErrorOpt = runValidationPipeline(context, validationRules, requestId);
|
||||
|
||||
Response finalResponse;
|
||||
if (validationErrorOpt.isPresent()) {
|
||||
context.setFinalError(validationErrorOpt);
|
||||
finalResponse = responseHelper.buildErrorResponse(validationErrorOpt.get(), requestId);
|
||||
} else {
|
||||
var configItem = findSpecificConfigItem(appConfiguration, context, requestId);
|
||||
|
||||
if (configItem == null) {
|
||||
log.error(LoggerHelper.buildError(requestId, "FATAL: No se encontro un ConfigItem (ni especifico ni 'all')"));
|
||||
var error = statusDescriptionResolver.getCode("VRN_ITEM_NOT_FOUND");
|
||||
return responseHelper.buildErrorResponse(error, requestId);
|
||||
}
|
||||
|
||||
var otp = Optional.ofNullable(request.getTokenAssignmentInstance())
|
||||
.map(CustomerRequest.TokenAssignmentInstance::getTokenIdentificationCode)
|
||||
.filter(otpCode -> !otpCode.isEmpty())
|
||||
.orElse(null);
|
||||
|
||||
finalResponse = getUserAccounts(context, appConfiguration, configItem, otp, requestId);
|
||||
}
|
||||
|
||||
var fullResponse = (CustomerResponse) finalResponse.getEntity();
|
||||
|
||||
var statusRegister = fullResponse.getStatusResponse();
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Ejecutando tareas finales (traza de seguridad)"));
|
||||
var securityCommand = securityTraceFactory.createCommandFromContext(context, statusRegister);
|
||||
registerSecurityUseCase.execute(securityCommand, context.getRequestId());
|
||||
|
||||
return finalResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ejecuta la secuencia de validaciones. Si alguna falla, devuelve la respuesta de error.
|
||||
* Si todas pasan, devuelve un Optional vacío.
|
||||
*/
|
||||
@SuppressWarnings("t")
|
||||
private Optional<ErrorCode> runValidationPipeline(AccountClientContext context, Map<String, Boolean> validationRules, String requestId) {
|
||||
var data = context.getRequest();
|
||||
var device = data.getDevice();
|
||||
var customerReference = data.getCustomerPositionState().getCustomerReference();
|
||||
var tokenInstance = data.getTokenAssignmentInstance();
|
||||
|
||||
if (shouldRun(validationRules, "serviceStatus")) {
|
||||
if (!isServiceActive(context.getRequestId())) {
|
||||
return Optional.of(statusDescriptionResolver.getCode("VRN04"));
|
||||
}
|
||||
}
|
||||
|
||||
// Primero intenta obtener el usuario del contexto
|
||||
var userOpt = Optional.ofNullable(context.getUsername())
|
||||
.filter(u -> !u.isBlank())
|
||||
.map(u -> UserLogin.builder()
|
||||
.usernameBol(u)
|
||||
.idNumber(customerReference.getCustomerId())
|
||||
.build());
|
||||
|
||||
// Si no está en el contexto Y la regla dice que se debe ejecutar, búscalo en la API
|
||||
if (shouldRun(validationRules, "getUserLogin")) {
|
||||
userOpt = getUserLogin(context.getRequestId(), customerReference.getCustomerId(), customerReference.getCustomerIdType());
|
||||
|
||||
if (userOpt.isEmpty() ) {
|
||||
log.info(LoggerHelper.buildInfoPrivateResponse(requestId, "No se pudo obtener el usuario ni desde el contexto ni desde la API"));
|
||||
return Optional.of(statusDescriptionResolver.getCode("VRN19"));
|
||||
}
|
||||
|
||||
// Si viene vacio el usernameBol ""
|
||||
if(userOpt.get().usernameBol().isBlank()) {
|
||||
log.info(LoggerHelper.buildInfoPrivateResponse(requestId, "No se pudo obtener el usernameBol"));
|
||||
return Optional.of(statusDescriptionResolver.getCode("VRN20"));
|
||||
}
|
||||
|
||||
context.setUsername(userOpt.get().usernameBol());
|
||||
}
|
||||
|
||||
String hash = ""; // Inicializar
|
||||
if (shouldRun(validationRules, "encodeValue")) {
|
||||
hash = encodeUsername(context.getUsername(), requestId);
|
||||
}
|
||||
|
||||
if (shouldRun(validationRules, "validateOtp")) {
|
||||
if(!tokenInstance.getTokenIdentificationCode().isEmpty()) {
|
||||
var isOtpValid = otpValidationService.isOtpValid(
|
||||
tokenInstance.getTokenIdentificationCode(),
|
||||
context.getFintechId(),
|
||||
context.getUsername(),
|
||||
device.getDeviceIp(),
|
||||
requestId
|
||||
);
|
||||
if (!isOtpValid) {
|
||||
return Optional.of(statusDescriptionResolver.getCode("VRN07"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldRun(validationRules, "validateProfile")) {
|
||||
var command = new ValidateProfileCommand(
|
||||
device.getDeviceSessionReference() == null || device.getDeviceSessionReference().isBlank() ? context.getFinalCustomerId() + device.getDeviceSessionReference() : context.getFinalCustomerId(),
|
||||
device.getDeviceIp(),
|
||||
hash
|
||||
);
|
||||
var isValidProfile = validateProfileUseCase.execute(command, requestId);
|
||||
|
||||
if(!isValidProfile) {
|
||||
log.info(LoggerHelper.buildInfoPrivateResponse(requestId, "FALLO LA VALIDACION DEL CLIENTE EN TRANSACT"));
|
||||
return Optional.of(statusDescriptionResolver.getCode("VRN01"));
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
|
||||
}
|
||||
|
||||
// --- MÉTODOS PRIVADOS DE ORQUESTACIÓN ---
|
||||
private boolean isServiceActive(String requestId) {
|
||||
var bankService = new BankService(bolConfig.codBan(), bolConfig.codEve(), bolConfig.codServ());
|
||||
var command = new ServiceStatusCommand(requestId, requestId, bankService);
|
||||
return serviceStatusUseCase.execute(command, requestId);
|
||||
}
|
||||
|
||||
private Optional<UserLogin> getUserLogin(String requestId, String... params) {
|
||||
var command = new UserLoginCommand(
|
||||
params[0],
|
||||
params[1]
|
||||
);
|
||||
|
||||
return userLoginUseCase.execute(command, requestId);
|
||||
}
|
||||
|
||||
private String encodeUsername(String username, String requestId) {
|
||||
var command = new EncodeValueCommand(username);
|
||||
return encodeValueUseCase.execute(command, requestId);
|
||||
}
|
||||
|
||||
private Optional<AppConfiguration> getPgConfig(AccountClientContext context, String requestId) {
|
||||
var configKey = context.getAppId();
|
||||
|
||||
var cachedConfig = postgresConfigService.findByName(configKey, requestId);
|
||||
if (cachedConfig.isPresent()) {
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Configuracion obtenida desde CACHE"));
|
||||
return cachedConfig;
|
||||
}
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Configuracion no encontrada en cache, buscando en BD..."));
|
||||
|
||||
AppConfiguration appConfiguration;
|
||||
try {
|
||||
appConfiguration = appConfigUseCase.execute(configKey);
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateResponse(requestId, "Configuracion obtenida desde BD"));
|
||||
} catch (NotFoundException ex) {
|
||||
log.error(LoggerHelper.buildError(requestId, "FATAL: No se encontro AppConfiguration para appId: " + configKey), ex);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
postgresConfigService.savePostgresConfig(configKey, appConfiguration, cacheTtl, requestId);
|
||||
return Optional.of(appConfiguration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrae el ConfigItem específico de la AppConfiguration basado en el contexto.
|
||||
* Cae a "all" si no se encuentra uno específico.
|
||||
*/
|
||||
private ConfigItem findSpecificConfigItem(AppConfiguration appConfiguration, AccountClientContext context, String requestId) {
|
||||
var data = context.getRequest().getCustomerPositionState().getCustomerReference();
|
||||
var postgresConfig = appConfiguration.getConfiguration();
|
||||
|
||||
var aliases = postgresConfig.getAliases();
|
||||
var configMap = postgresConfig.getConfiguration();
|
||||
|
||||
// Usamos el appId del contexto como prefijo de la clave
|
||||
var literal = data.getCustomerIdType();
|
||||
var finalLiteral = aliases.getOrDefault(literal, literal);
|
||||
var specificKey = context.getAppId() + "_" + finalLiteral;
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Buscando ConfigItem con KEY: " + specificKey));
|
||||
|
||||
ConfigItem config;
|
||||
if (configMap.containsKey(specificKey)) {
|
||||
config = configMap.get(specificKey);
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Configuracion encontrada (Especifica): " + specificKey));
|
||||
} else {
|
||||
config = configMap.get("all");
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Configuracion encontrada (General): all"));
|
||||
}
|
||||
|
||||
return config; // Puede ser null si "all" tampoco existe
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper para verificar de forma segura si una regla debe ejecutarse.
|
||||
* Por defecto, si una regla no está en el mapa, SÍ se ejecuta (falla seguro).
|
||||
*/
|
||||
private boolean shouldRun(Map<String, Boolean> rules, String ruleName) {
|
||||
if (rules == null) {
|
||||
// Si no hay mapa, orquesta completo
|
||||
return true;
|
||||
}
|
||||
return rules.getOrDefault(ruleName, true);
|
||||
}
|
||||
|
||||
|
||||
private Response getUserAccounts(AccountClientContext context, AppConfiguration appConfig, ConfigItem configItem, String otp, String requestId) {
|
||||
|
||||
var customerAccountCommand = CustomerAccountCommand.builder()
|
||||
.rif(context.getFinalCustomerId())
|
||||
.bankCode(configItem.getBankCode())
|
||||
.currencyCode(configItem.getCurrencyCode())
|
||||
.status(configItem.getStatus())
|
||||
.statusMe(configItem.getStatusMe())
|
||||
.productCv(configItem.getProductCv())
|
||||
.product(configItem.getProduct())
|
||||
.channel(configItem.getChannel())
|
||||
.service(configItem.getService())
|
||||
.operator(configItem.getOperator())
|
||||
.phone(configItem.getPhone())
|
||||
.affiliationStatus(configItem.getAffiliationStatus())
|
||||
.counterpartyAccount(configItem.getCounterpartyAccount())
|
||||
.holder(configItem.getHolder())
|
||||
.build();
|
||||
|
||||
var products = customerProductUseCase.execute(customerAccountCommand, context, appConfig, otp, configItem.isCacheable(), requestId);
|
||||
|
||||
return responseHelper.buildSuccessResponse(
|
||||
products.stream().toList(),
|
||||
products.isEmpty() ?
|
||||
statusDescriptionResolver.getCode("204") :
|
||||
statusDescriptionResolver.getCode("200"),
|
||||
requestId
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package infrastructure.adapter.output;
|
||||
|
||||
import application.port.output.IMaintenanceCheckPort;
|
||||
import com.banesco.common.infraestructure.utils.MaintenanceUtil;
|
||||
import infrastructure.config.AccountAvailabilityConfig;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class MaintenanceCheckAdapter implements IMaintenanceCheckPort {
|
||||
|
||||
private final AccountAvailabilityConfig availabilityConfig;
|
||||
|
||||
@Inject
|
||||
MaintenanceCheckAdapter(AccountAvailabilityConfig paymentAvailabilityConfig) {
|
||||
this.availabilityConfig = paymentAvailabilityConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isUnderMaintenance(String requestId) {
|
||||
return MaintenanceUtil.isDateInRange(requestId, availabilityConfig.begin(), availabilityConfig.finish());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
package infrastructure.adapter.output.persistence;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import domain.entity.AppConfiguration;
|
||||
import domain.model.Configuration;
|
||||
import domain.repository.AppConfigRepository;
|
||||
import io.agroal.api.AgroalDataSource;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.Optional;
|
||||
|
||||
@ApplicationScoped
|
||||
public class AppConfigRepositoryAdapter implements AppConfigRepository {
|
||||
|
||||
@Inject
|
||||
AgroalDataSource dataSource;
|
||||
|
||||
@Inject
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
public Optional<AppConfiguration> findConfigByAppName(String appName) {
|
||||
String sql = "SELECT * FROM get_application_config(?)";
|
||||
|
||||
try (var conn = dataSource.getConnection();
|
||||
var ps = conn.prepareStatement(sql)) {
|
||||
|
||||
ps.setString(1, appName);
|
||||
|
||||
try (var rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
var config = new AppConfiguration();
|
||||
|
||||
config.setAppId(rs.getLong("id_appconfig"));
|
||||
config.setAppName(rs.getString("app_name"));
|
||||
config.setApiName(rs.getString("api_name"));
|
||||
config.setType(rs.getString("type"));
|
||||
config.setEvent(rs.getString("event"));
|
||||
config.setEncryptionData(rs.getBoolean("encryption_data"));
|
||||
var jsonString = rs.getString("configuration");
|
||||
if (jsonString != null) {
|
||||
config.setConfiguration(objectMapper.readValue(jsonString, Configuration.class));
|
||||
}
|
||||
|
||||
return Optional.of(config);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error al llamar a get_application_config", e);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package infrastructure.client.accounts.adapter;
|
||||
|
||||
import application.exception.GatewayServiceException;
|
||||
import application.port.input.command.CustomerAccountCommand;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.model.CustomerAccount;
|
||||
import domain.repository.ICustomerProductPort;
|
||||
import infrastructure.client.accounts.api.CustomerAccountClient;
|
||||
import infrastructure.mapper.CustomerAccountMapper;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class CustomerProductAdapter implements ICustomerProductPort {
|
||||
|
||||
private final CustomerAccountClient client;
|
||||
|
||||
public CustomerProductAdapter(@RestClient CustomerAccountClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CustomerAccount> execute(CustomerAccountCommand command, String requestId) {
|
||||
try {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Adaptador: Mapeando Command a DTO para api-get-db2-accounts-client-v2"));
|
||||
var request = CustomerAccountMapper.toRequestDto(command);
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Llamando al servicio de api-get-db2-accounts-client-v2", request));
|
||||
|
||||
var response = client.readCustomerProducts(requestId, request);
|
||||
log.info(LoggerHelper.buildInfoPrivateResponse(requestId, "Respuesta del servicio de api-get-db2-accounts-client-v2", response));
|
||||
|
||||
// Validación de contrato: asegura que la respuesta no sea nula o inválida.
|
||||
if (response == null) {
|
||||
log.warn(LoggerHelper.buildError(requestId, "Respuesta invalida o nula del servicio de api-get-db2-accounts-client-v2"));
|
||||
throw new GatewayServiceException("Respuesta invalida del servicio externo de api-get-db2-accounts-client-v2");
|
||||
}
|
||||
|
||||
return CustomerAccountMapper.toEntityList(response);
|
||||
} catch (WebApplicationException ex) {
|
||||
var errorResponse = ex.getResponse();
|
||||
var status = errorResponse.getStatus();
|
||||
String errorDetails;
|
||||
|
||||
// Verifica si el Content-Type es HTML
|
||||
if (errorResponse.getMediaType() != null && errorResponse.getMediaType().toString().contains("text/html")) {
|
||||
errorDetails = "Se recibio una respuesta HTML no esperada del servicio.";
|
||||
log.error(LoggerHelper.buildError(requestId,
|
||||
String.format("Error HTTP %s del servicio de api-get-db2-accounts-client-v2 %s", status, errorDetails)));
|
||||
} else {
|
||||
// Si no es HTML, probablemente es un error JSON que sí queremos ver.
|
||||
var errorBody = errorResponse.readEntity(String.class);
|
||||
|
||||
// Aun así, es buena idea truncarlo por si es muy largo
|
||||
errorDetails = errorBody.substring(0, Math.min(errorBody.length(), 1000));
|
||||
log.error(LoggerHelper.buildError(requestId,
|
||||
String.format("Error HTTP no manejado del servicio de api-get-db2-accounts-client-v2 Status: %s. Body: %s", status, errorDetails)));
|
||||
}
|
||||
|
||||
throw new GatewayServiceException("Error en el servicio de api-get-db2-accounts-client-v2: " + errorDetails);
|
||||
} catch (RuntimeException ex) {
|
||||
// Captura errores de más bajo nivel (red, timeouts, host desconocido, etc.).
|
||||
log.error(LoggerHelper.buildError(
|
||||
requestId,
|
||||
String.format("Error de comunicacion con el servicio de api-get-db2-accounts-client-v2: %s", ex.getMessage())
|
||||
));
|
||||
// Traduce el error técnico a una excepción de la aplicación.
|
||||
throw new GatewayServiceException("No se pudo comunicar con el servicio externo de api-get-db2-accounts-client-v2");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package infrastructure.client.accounts.api;
|
||||
|
||||
import infrastructure.client.accounts.dto.request.CustomerAccountRequest;
|
||||
import infrastructure.client.accounts.dto.respone.CustomerAccountResponse;
|
||||
import infrastructure.interceptor.LoggingFilter;
|
||||
import jakarta.ws.rs.HeaderParam;
|
||||
import jakarta.ws.rs.POST;
|
||||
import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
@RegisterRestClient(configKey = "customer-accounts")
|
||||
@RegisterProvider(LoggingFilter.class)
|
||||
public interface CustomerAccountClient {
|
||||
@POST
|
||||
@ClientHeaderParam(name = "appId", value = "${app.appId}")
|
||||
CustomerAccountResponse readCustomerProducts(
|
||||
@HeaderParam("requestId") String requestId,
|
||||
CustomerAccountRequest request
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package infrastructure.client.accounts.dto.request;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public class CustomerAccountRequest {
|
||||
String rif;
|
||||
String bankCode;
|
||||
String currencyCode;
|
||||
String status;
|
||||
String statusMe;
|
||||
String productCv;
|
||||
String product;
|
||||
String channel;
|
||||
String service;
|
||||
String operator;
|
||||
String phone;
|
||||
String affiliationStatus;
|
||||
String counterpartyAccount;
|
||||
String holder;
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package infrastructure.client.accounts.dto.respone;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public class CustomerAccountResponse {
|
||||
List<CustomerAccount> data;
|
||||
int record;
|
||||
|
||||
@Value
|
||||
@RegisterForReflection
|
||||
public static class CustomerAccount {
|
||||
String banco;
|
||||
String cuenta;
|
||||
String producto;
|
||||
String descProd;
|
||||
String claseCta;
|
||||
String tipoCta;
|
||||
String moneda;
|
||||
BigDecimal saldoDisponible;
|
||||
String estatus;
|
||||
String statusMe;
|
||||
String titular;
|
||||
BigDecimal maximumPerDay;
|
||||
BigDecimal maximumPerTransaction;
|
||||
BigDecimal maximumPerMonth;
|
||||
BigDecimal maximumMonthlyFee;
|
||||
BigDecimal minimumPerTransaction;
|
||||
String operator;
|
||||
String phone;
|
||||
String channel;
|
||||
String service;
|
||||
String affiliationStatus;
|
||||
String codeError;
|
||||
String descError;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package infrastructure.client.encodevalue.adapter;
|
||||
|
||||
import application.exception.GatewayServiceException;
|
||||
import application.exception.ServiceCommunicationException;
|
||||
import application.port.input.command.EncodeValueCommand;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.repository.IEncodeValuePort;
|
||||
import infrastructure.client.encodevalue.api.EncodeValueClient;
|
||||
import infrastructure.mapper.EncodeValueMapper;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class EncodeValueAdapter implements IEncodeValuePort {
|
||||
|
||||
private final EncodeValueClient client;
|
||||
|
||||
public EncodeValueAdapter(@RestClient EncodeValueClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute( EncodeValueCommand command, String requestId) {
|
||||
try {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Adaptador: Mapeando Command a DTO para Encode Value"));
|
||||
var requestDto = EncodeValueMapper.toRequestDto(command);
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Llamando al servicio de encode value", requestDto));
|
||||
var response = client.encodeValue(requestId, requestDto);
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateResponse(requestId, "Respuesta del servicio de encode value", response));
|
||||
|
||||
// Validación de contrato: asegura que la respuesta no sea nula o inválida.
|
||||
if (response == null) {
|
||||
log.warn(LoggerHelper.buildError(requestId, "Respuesta invalida o nula del servicio de encode value"));
|
||||
throw new GatewayServiceException("Respuesta invalida del servicio externo de encode value");
|
||||
}
|
||||
|
||||
return EncodeValueMapper.toResponseDto(response);
|
||||
|
||||
} catch (WebApplicationException ex) {
|
||||
var errorResponse = ex.getResponse();
|
||||
var status = errorResponse.getStatus();
|
||||
String errorDetails;
|
||||
|
||||
// Verifica si el Content-Type es HTML
|
||||
if (errorResponse.getMediaType() != null && errorResponse.getMediaType().toString().contains("text/html")) {
|
||||
errorDetails = "Se recibio una respuesta HTML no esperada del servicio.";
|
||||
log.error(LoggerHelper.buildError(requestId,
|
||||
String.format("Error HTTP %s del servicio de encode value. %s", status, errorDetails)));
|
||||
} else {
|
||||
// Si no es HTML, probablemente es un error JSON que sí queremos ver.
|
||||
var errorBody = errorResponse.readEntity(String.class);
|
||||
// Aun así, es buena idea truncarlo por si es muy largo
|
||||
errorDetails = errorBody.substring(0, Math.min(errorBody.length(), 1000));
|
||||
log.error(LoggerHelper.buildError(requestId,
|
||||
String.format("Error HTTP no manejado del servicio de encode value. Status: %s. Body: %s", status, errorDetails)));
|
||||
}
|
||||
|
||||
throw new GatewayServiceException("Error en el servicio de encode value: " + errorDetails);
|
||||
} catch (RuntimeException ex) {
|
||||
// Captura errores de más bajo nivel (red, timeouts, host desconocido, etc.).
|
||||
log.error(LoggerHelper.buildError(
|
||||
requestId,
|
||||
String.format("Error de comunicacion con el servicio de encode value: %s", ex)
|
||||
));
|
||||
|
||||
throw new ServiceCommunicationException("No se pudo comunicar con el servicio externo de encode value", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package infrastructure.client.encodevalue.api;
|
||||
|
||||
import infrastructure.interceptor.LoggingFilter;
|
||||
import jakarta.ws.rs.HeaderParam;
|
||||
import jakarta.ws.rs.POST;
|
||||
import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import org.tempuri.Prueba;
|
||||
import org.tempuri.PruebaResponse;
|
||||
|
||||
@RegisterRestClient(configKey = "encode-value")
|
||||
@RegisterProvider(LoggingFilter.class)
|
||||
public interface EncodeValueClient {
|
||||
@POST
|
||||
@ClientHeaderParam(name = "appId", value = "${app.appId}")
|
||||
PruebaResponse encodeValue(
|
||||
@HeaderParam("requestId") String requestId,
|
||||
Prueba request
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
package infrastructure.client.otp.adapter;
|
||||
|
||||
import application.exception.GatewayServiceException;
|
||||
import application.exception.InvalidTokenException;
|
||||
import application.port.input.command.ValidateOtpCommand;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.repository.IOtpPort;
|
||||
import infrastructure.client.otp.api.OtpClient;
|
||||
import infrastructure.mapper.OtpMapper;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import org.jboss.resteasy.reactive.RestResponse;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class OtpAdapter implements IOtpPort {
|
||||
|
||||
private final OtpClient client;
|
||||
|
||||
@Inject
|
||||
public OtpAdapter(@RestClient OtpClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementa la comunicación con la API externa para validar un OTP.
|
||||
* Se encarga de mapear el DTO, llamar al cliente REST y TRADUCIR errores
|
||||
* técnicos (de red) o respuestas HTTP inesperadas en excepciones de la aplicación.
|
||||
*
|
||||
* @param command El comando de dominio con los datos de validación.
|
||||
* @param requestId El ID de la solicitud para trazabilidad.
|
||||
* @return Un objeto {@link RestResponse} que contiene la respuesta HTTP completa de la API.
|
||||
* @throws GatewayServiceException si ocurre un error de red o la API responde con un error 5xx.
|
||||
*/
|
||||
@Override
|
||||
public RestResponse<Void> validateOtp(ValidateOtpCommand command, String requestId) {
|
||||
try {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Adaptador: Mapeando Command a DTO para la API privada de validate otp"));
|
||||
var requestDto = OtpMapper.toRequestDto(command);
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Llamando al servicio de validate otp", requestDto));
|
||||
|
||||
var response = client.validateOtp(
|
||||
requestId,
|
||||
requestDto.getOtpToken(),
|
||||
requestDto.getAppOrigen(),
|
||||
requestDto.getLogin(),
|
||||
requestDto.getIpAddress(),
|
||||
requestDto.getCanal(),
|
||||
requestDto.getServicio()
|
||||
);
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateResponse(requestId, "Respuesta del servicio de otp", response.getStatus()));
|
||||
|
||||
return response;
|
||||
} catch(WebApplicationException ex) {
|
||||
var errorResponse = ex.getResponse();
|
||||
var status = errorResponse.getStatus();
|
||||
String errorDetails;
|
||||
|
||||
// OTP inválido (respuesta de la privada)
|
||||
if(status == 403) {
|
||||
log.error(LoggerHelper.buildError(requestId, String.format("token %s invalido, respuesta HTTP API privada de otp: %s", command.otpToken(), status)));
|
||||
throw new InvalidTokenException("Token inválido");
|
||||
}
|
||||
|
||||
// Verifica si el Content-Type es HTML
|
||||
if (errorResponse.getMediaType() != null && errorResponse.getMediaType().toString().contains("text/html")) {
|
||||
errorDetails = "Se recibio una respuesta HTML no esperada del servicio.";
|
||||
log.error(LoggerHelper.buildError(requestId,
|
||||
String.format("Error HTTP %s del servicio de otp. %s", status, errorDetails)));
|
||||
} else {
|
||||
// Si no es HTML, probablemente es un error JSON que sí queremos ver.
|
||||
var errorBody = errorResponse.readEntity(String.class);
|
||||
|
||||
// Se trunca por si es el error es muy largo
|
||||
errorDetails = errorBody.substring(0, Math.min(errorBody.length(), 1000));
|
||||
log.error(LoggerHelper.buildError(requestId,
|
||||
String.format("Error HTTP no manejado del servicio de otp. Status: %s. Body: %s", status, errorDetails)));
|
||||
}
|
||||
|
||||
throw new GatewayServiceException("Error en el servicio de otp: " + errorDetails);
|
||||
} catch(RuntimeException ex) {
|
||||
// Error de red (Timeout, no se puede conectar, etc.)
|
||||
log.error(LoggerHelper.buildError(requestId, String.format("Error de comunicacion con el servicio de otp %s", ex)));
|
||||
throw new GatewayServiceException("No se pudo comunicar con el servicio externo de otp.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package infrastructure.client.otp.api;
|
||||
|
||||
import infrastructure.interceptor.LoggingFilter;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.HeaderParam;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
import org.jboss.resteasy.reactive.RestResponse;
|
||||
|
||||
@RegisterRestClient(configKey = "otp")
|
||||
@RegisterProvider(LoggingFilter.class)
|
||||
public interface OtpClient {
|
||||
@GET
|
||||
@ClientHeaderParam(name = "appId", value = "${app.appId}")
|
||||
@Path("/{otpToken}/{appOrigen}/{login}/{ipAddress}/{canal}/{servicio}")
|
||||
RestResponse<Void> validateOtp(
|
||||
@HeaderParam("requestId") String requestId,
|
||||
@PathParam("otpToken") String otpToken,
|
||||
@PathParam("appOrigen") String appOrigen,
|
||||
@PathParam("login") String login,
|
||||
@PathParam("ipAddress") String ipAddress,
|
||||
@PathParam("canal") String canal,
|
||||
@PathParam("servicio") String servicio
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package infrastructure.client.otp.dto.request;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public class ValidateOtpRequest {
|
||||
// MsgRqHdr msgRqHdr;
|
||||
String otpToken;
|
||||
String appOrigen;
|
||||
String login;
|
||||
String ipAddress;
|
||||
String canal;
|
||||
String servicio;
|
||||
// String domain;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package infrastructure.client.otp.dto.response;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
public class AditionalStatus {
|
||||
String statusType;
|
||||
String statusCode;
|
||||
String statusDesc;
|
||||
String validationType;
|
||||
String severity;
|
||||
String lineNumber;
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package infrastructure.client.otp.dto.response;
|
||||
|
||||
import com.banesco.xmlns.enterpriseobjects.status.AdditionalStatus;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Value;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
@Value
|
||||
@RegisterForReflection
|
||||
public class Status {
|
||||
String statusType;
|
||||
String statusCode;
|
||||
String statusDesc;
|
||||
String applicationName;
|
||||
BigInteger lineNumber;
|
||||
List<AdditionalStatus> additionalStatus;
|
||||
String severity;
|
||||
String statusInd;
|
||||
String logId;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package infrastructure.client.otp.dto.response;
|
||||
|
||||
import com.banesco.xmlns.enterpriseobjects.msgrshdr.MsgRsHdr;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public class ValidateOtpResponse {
|
||||
MsgRsHdr msgRsHdr;
|
||||
Status status;
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
package infrastructure.client.registersecurity.adapter;
|
||||
|
||||
import application.port.input.command.RegisterSecurityCommand;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.repository.IRegisterSecurityPort;
|
||||
import infrastructure.client.registersecurity.api.RegisterSecurityClient;
|
||||
import infrastructure.mapper.RegisterSecurityMapper;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class RegisterSecurityAdapter implements IRegisterSecurityPort {
|
||||
|
||||
private final RegisterSecurityClient client;
|
||||
private final RegisterSecurityMapper mapper;
|
||||
|
||||
@Inject
|
||||
public RegisterSecurityAdapter(
|
||||
@RestClient RegisterSecurityClient client,
|
||||
RegisterSecurityMapper mapper
|
||||
) {
|
||||
this.client = client;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTrace(RegisterSecurityCommand command, String requestId) {
|
||||
try {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Adaptador: Mapeando Command a DTO para register security"));
|
||||
var requestDto = mapper.toRequestDto(command);
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Llamando al servicio de register security (asincrono)", requestDto));
|
||||
|
||||
client.registerSecurity(requestId, requestDto)
|
||||
.subscribe().with(
|
||||
// 1. Callback de ÉXITO (sin cambios)
|
||||
response -> log.info(LoggerHelper.buildInfoPrivateResponse(
|
||||
requestId,
|
||||
String.format("Traza de seguridad registrada. Status: %s", response.getStatus())
|
||||
)),
|
||||
|
||||
// 2. Callback de FALLO (con la nueva lógica detallada)
|
||||
failure -> handleFailure(failure, requestId)
|
||||
);
|
||||
|
||||
} catch (Exception e) {
|
||||
// Este bloque captura errores síncronos (ej. en el mapeo)
|
||||
log.error(LoggerHelper.buildError(
|
||||
requestId,
|
||||
String.format("Error al preparar la llamada para registrar la traza de seguridad: %s", e.getMessage())
|
||||
), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Centralizar y detallar el manejo de errores asíncronos.
|
||||
*
|
||||
* @param failure La excepción ocurrida.
|
||||
* @param requestId El ID de la traza.
|
||||
*/
|
||||
private void handleFailure(Throwable failure, String requestId) {
|
||||
if (failure instanceof WebApplicationException ex) {
|
||||
// Lógica para errores HTTP (4xx, 5xx) - Equivalente al primer catch
|
||||
var errorResponse = ex.getResponse();
|
||||
var status = errorResponse.getStatus();
|
||||
String errorDetails;
|
||||
|
||||
if (errorResponse.getMediaType() != null && errorResponse.getMediaType().toString().contains("text/html")) {
|
||||
errorDetails = "Se recibio una respuesta HTML no esperada del servicio.";
|
||||
log.error(LoggerHelper.buildError(requestId,
|
||||
String.format("Error HTTP %s del servicio de register security. %s", status, errorDetails)));
|
||||
} else {
|
||||
var errorBody = errorResponse.readEntity(String.class);
|
||||
errorDetails = errorBody.substring(0, Math.min(errorBody.length(), 1000));
|
||||
log.error(LoggerHelper.buildError(requestId,
|
||||
String.format("Error HTTP no manejado del servicio de register security. Status: %s. Body: %s", status, errorDetails)));
|
||||
}
|
||||
} else {
|
||||
// Lógica para otros errores (red, timeout, etc.) - Equivalente al segundo catch
|
||||
log.error(LoggerHelper.buildError(
|
||||
requestId,
|
||||
String.format("Error de comunicacion con el servicio de register security: %s", failure.getMessage())
|
||||
), failure);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package infrastructure.client.registersecurity.api;
|
||||
|
||||
import infrastructure.client.registersecurity.dto.request.RegisterSecurityRequest;
|
||||
import infrastructure.interceptor.LoggingFilter;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.ws.rs.HeaderParam;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
@RegisterRestClient(configKey = "register-security")
|
||||
@RegisterProvider(LoggingFilter.class)
|
||||
public interface RegisterSecurityClient {
|
||||
@POST
|
||||
Uni<Response> registerSecurity(
|
||||
@HeaderParam("requestId") String requestId,
|
||||
RegisterSecurityRequest request
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package infrastructure.client.registersecurity.dto.request;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@RegisterForReflection
|
||||
public record RegisterSecurityRequest (
|
||||
String codBan,
|
||||
String codMon,
|
||||
String codEve,
|
||||
String codEve2,
|
||||
String login,
|
||||
Date fecHor,
|
||||
String nacCli,
|
||||
Integer cedRifCli,
|
||||
String tipoProductoCli,
|
||||
String tipoProductoBen,
|
||||
String productoCli,
|
||||
String codEmpresa,
|
||||
String nacBen,
|
||||
Integer cedBen,
|
||||
String nombreBen,
|
||||
String productoBen,
|
||||
Double monto,
|
||||
String referencia,
|
||||
String nroDePago,
|
||||
String desPago,
|
||||
String objeto,
|
||||
Integer tipoRespuesta,
|
||||
String msgRespuesta,
|
||||
Integer tiempoRespuesta,
|
||||
String codFintech,
|
||||
String cedRifFintech,
|
||||
String tipoDispositivo,
|
||||
String desDispositivo,
|
||||
String ipCli,
|
||||
String sp
|
||||
) {}
|
||||
@ -0,0 +1,86 @@
|
||||
package infrastructure.client.servicestatus.adapter;
|
||||
|
||||
import application.exception.GatewayServiceException;
|
||||
import application.exception.ServiceCommunicationException;
|
||||
import application.port.input.command.ServiceStatusCommand;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.model.ServiceStatus;
|
||||
import domain.repository.IStatusPort;
|
||||
import infrastructure.client.servicestatus.api.ServiceStatusClient;
|
||||
import infrastructure.mapper.ServiceStatusMapper;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class ServiceStatusAdapter implements IStatusPort {
|
||||
|
||||
private final ServiceStatusClient client;
|
||||
|
||||
@Inject
|
||||
public ServiceStatusAdapter(@RestClient ServiceStatusClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementa la comunicación con la API externa para obtener el estado de un servicio.
|
||||
*
|
||||
* @param command El comando de dominio con los datos de la consulta.
|
||||
* @param requestId El ID de la solicitud para trazabilidad.
|
||||
* @return Un objeto {@link ServiceStatus} con el estado del servicio.
|
||||
* @throws GatewayServiceException si el servicio externo no es accesible, devuelve un error,
|
||||
* o la respuesta tiene un formato inesperado.
|
||||
*/
|
||||
@Override
|
||||
public ServiceStatus getServiceStatus(ServiceStatusCommand command, String requestId) {
|
||||
try {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Adaptador: Mapeando Command a DTO para Service Status"));
|
||||
var requestDto = ServiceStatusMapper.toRequestDto(command);
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Llamando al servicio de service status", requestDto));
|
||||
var response = client.getServiceStatus(requestId, requestDto);
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateResponse(requestId, "Respuesta del servicio de service status", response));
|
||||
|
||||
// Validación de contrato: asegura que la respuesta no sea nula o inválida.
|
||||
if (response == null || response.getStatus() == null) {
|
||||
log.warn(LoggerHelper.buildError(requestId, "Respuesta invalida o nula del servicio de service status."));
|
||||
throw new GatewayServiceException("Respuesta invalida del servicio externo de estado.");
|
||||
}
|
||||
|
||||
return ServiceStatusMapper.toEntity(response);
|
||||
|
||||
} catch (WebApplicationException ex) {
|
||||
var errorResponse = ex.getResponse();
|
||||
var status = errorResponse.getStatus();
|
||||
String errorDetails;
|
||||
|
||||
// Verifica si el Content-Type es HTML
|
||||
if (errorResponse.getMediaType() != null && errorResponse.getMediaType().toString().contains("text/html")) {
|
||||
errorDetails = "Se recibio una respuesta HTML no esperada del servicio.";
|
||||
log.error(LoggerHelper.buildError(requestId,
|
||||
String.format("Error HTTP %s del servicio de service status. %s", status, errorDetails)));
|
||||
} else {
|
||||
// Si no es HTML, probablemente es un error JSON que sí queremos ver.
|
||||
var errorBody = errorResponse.readEntity(String.class);
|
||||
// Aun así, es buena idea truncarlo por si es muy largo
|
||||
errorDetails = errorBody.substring(0, Math.min(errorBody.length(), 1000));
|
||||
log.error(LoggerHelper.buildError(requestId,
|
||||
String.format("Error HTTP no manejado del servicio de service status. Status: %s. Body: %s", status, errorDetails)));
|
||||
}
|
||||
|
||||
throw new GatewayServiceException("Error en el servicio de service status: " + errorDetails);
|
||||
} catch (RuntimeException ex) {
|
||||
// Captura errores de más bajo nivel (red, timeouts, host desconocido, etc.).
|
||||
log.error(LoggerHelper.buildError(
|
||||
requestId,
|
||||
String.format("Error de comunicacion con el servicio de estado: %s", ex.getMessage())
|
||||
));
|
||||
|
||||
throw new ServiceCommunicationException("No se pudo comunicar con el servicio externo de service status", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package infrastructure.client.servicestatus.api;
|
||||
|
||||
import com.banesco.common.infraestructure.web.dto.request.ServiceStatusRequest;
|
||||
import com.banesco.common.infraestructure.web.dto.response.ServiceStatusResponse;
|
||||
import infrastructure.interceptor.LoggingFilter;
|
||||
import jakarta.ws.rs.HeaderParam;
|
||||
import jakarta.ws.rs.POST;
|
||||
import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
@RegisterRestClient(configKey = "get-service-status")
|
||||
@RegisterProvider(LoggingFilter.class)
|
||||
public interface ServiceStatusClient {
|
||||
@POST
|
||||
@ClientHeaderParam(name = "appId", value = "${app.appId}")
|
||||
ServiceStatusResponse getServiceStatus(
|
||||
@HeaderParam("requestId") String requestId,
|
||||
ServiceStatusRequest request
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package infrastructure.client.userlogin.adapter;
|
||||
|
||||
import application.exception.GatewayServiceException;
|
||||
import application.exception.ServiceCommunicationException;
|
||||
import application.port.input.command.UserLoginCommand;
|
||||
import com.banesco.common.infraestructure.helpers.LoggerHelper;
|
||||
import domain.model.UserLogin;
|
||||
import domain.repository.IUserLoginPort;
|
||||
import infrastructure.client.userlogin.api.UserLoginClient;
|
||||
import infrastructure.mapper.UserLoginMapper;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class UserLoginAdapter implements IUserLoginPort {
|
||||
|
||||
private final UserLoginClient client;
|
||||
private final UserLoginMapper mapper;
|
||||
|
||||
public UserLoginAdapter(
|
||||
@RestClient UserLoginClient client,
|
||||
UserLoginMapper mapper
|
||||
) {
|
||||
this.client = client;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserLogin execute(UserLoginCommand command, String requestId) {
|
||||
try {
|
||||
log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Adaptador: Mapeando Command a DTO para la API privada de user login"));
|
||||
var requestDto = mapper.toRequestDto(command, requestId);
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "Llamando al servicio de user login", requestDto));
|
||||
var response = client.getUserLogin(requestId, requestDto);
|
||||
|
||||
log.info(LoggerHelper.buildInfoPrivateResponse(requestId, "Respuesta del servicio de user login", response));
|
||||
|
||||
if (response == null) {
|
||||
log.warn(LoggerHelper.buildError(requestId, "Respuesta invalida o nula del servicio de user login."));
|
||||
throw new GatewayServiceException("La respuesta del servicio de user login fue nula.");
|
||||
}
|
||||
|
||||
return UserLoginMapper.toEntity(response);
|
||||
} catch (WebApplicationException ex) {
|
||||
var errorResponse = ex.getResponse();
|
||||
var status = errorResponse.getStatus();
|
||||
String errorDetails;
|
||||
|
||||
// Verifica si el Content-Type es HTML
|
||||
if (errorResponse.getMediaType() != null && errorResponse.getMediaType().toString().contains("text/html")) {
|
||||
errorDetails = "Se recibio una respuesta HTML no esperada del servicio.";
|
||||
log.error(LoggerHelper.buildError(requestId,
|
||||
String.format("Error HTTP %s del servicio de user login. %s", status, errorDetails)));
|
||||
} else {
|
||||
// Si no es HTML, probablemente es un error JSON que sí queremos ver.
|
||||
var errorBody = errorResponse.readEntity(String.class);
|
||||
// Aun así, es buena idea truncarlo por si es muy largo
|
||||
errorDetails = errorBody.substring(0, Math.min(errorBody.length(), 1000));
|
||||
log.error(LoggerHelper.buildError(requestId,
|
||||
String.format("Error HTTP no manejado del servicio de user login. Status: %s. Body: %s", status, errorDetails)));
|
||||
}
|
||||
|
||||
throw new GatewayServiceException("Error en el servicio de user login: " + errorDetails);
|
||||
} catch (RuntimeException ex) {
|
||||
// Error de red (Timeout, no se puede conectar, etc.)
|
||||
log.error(LoggerHelper.buildError(requestId, String.format("Error de comunicacion con el servicio de user login %s", ex)));
|
||||
|
||||
throw new ServiceCommunicationException("No se pudo comunicar con el servicio externo de user login", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user