importacion de app de github KevinOlarte1(User)
This commit is contained in:
commit
4121c7b930
|
|
@ -0,0 +1,11 @@
|
|||
#Database configuration
|
||||
SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/resident
|
||||
SPRING_DATASOURCE_USERNAME=
|
||||
SPRING_DATASOURCE_PASSWORD=
|
||||
|
||||
#JWT secret Key
|
||||
JWT_SECRET_KEY=VGhpcyBpcyBhIHZlcnkgc2VjdXJlIHNlY3JldCBrZXkgZm9yIEpXVC4uLg==
|
||||
|
||||
#Mail properties
|
||||
SUPPORT_EMAIL=ktrabajo870@gmail.com
|
||||
APP_PASSWORD=bhqu vpzu oxuy lntp
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
/mvnw text eol=lf
|
||||
*.cmd text eol=crlf
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# 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=only-script
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Proyecto Fundación Residencia Benissa
|
||||
|
||||
### Parte Backend de la aplicación, API REST.
|
||||
|
|
@ -0,0 +1,259 @@
|
|||
#!/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
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
|
||||
# MVNW_REPOURL - repo url base for downloading maven distribution
|
||||
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
|
||||
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
set -euf
|
||||
[ "${MVNW_VERBOSE-}" != debug ] || set -x
|
||||
|
||||
# OS specific support.
|
||||
native_path() { printf %s\\n "$1"; }
|
||||
case "$(uname)" in
|
||||
CYGWIN* | MINGW*)
|
||||
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
|
||||
native_path() { cygpath --path --windows "$1"; }
|
||||
;;
|
||||
esac
|
||||
|
||||
# set JAVACMD and JAVACCMD
|
||||
set_java_home() {
|
||||
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
|
||||
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"
|
||||
JAVACCMD="$JAVA_HOME/jre/sh/javac"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
JAVACCMD="$JAVA_HOME/bin/javac"
|
||||
|
||||
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
|
||||
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
|
||||
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
JAVACMD="$(
|
||||
'set' +e
|
||||
'unset' -f command 2>/dev/null
|
||||
'command' -v java
|
||||
)" || :
|
||||
JAVACCMD="$(
|
||||
'set' +e
|
||||
'unset' -f command 2>/dev/null
|
||||
'command' -v javac
|
||||
)" || :
|
||||
|
||||
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
|
||||
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# hash string like Java String::hashCode
|
||||
hash_string() {
|
||||
str="${1:-}" h=0
|
||||
while [ -n "$str" ]; do
|
||||
char="${str%"${str#?}"}"
|
||||
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
|
||||
str="${str#?}"
|
||||
done
|
||||
printf %x\\n $h
|
||||
}
|
||||
|
||||
verbose() { :; }
|
||||
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
|
||||
|
||||
die() {
|
||||
printf %s\\n "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
trim() {
|
||||
# MWRAPPER-139:
|
||||
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
|
||||
# Needed for removing poorly interpreted newline sequences when running in more
|
||||
# exotic environments such as mingw bash on Windows.
|
||||
printf "%s" "${1}" | tr -d '[:space:]'
|
||||
}
|
||||
|
||||
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
|
||||
while IFS="=" read -r key value; do
|
||||
case "${key-}" in
|
||||
distributionUrl) distributionUrl=$(trim "${value-}") ;;
|
||||
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
|
||||
esac
|
||||
done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
|
||||
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
|
||||
|
||||
case "${distributionUrl##*/}" in
|
||||
maven-mvnd-*bin.*)
|
||||
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
|
||||
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
|
||||
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
|
||||
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
|
||||
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
|
||||
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
|
||||
*)
|
||||
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
|
||||
distributionPlatform=linux-amd64
|
||||
;;
|
||||
esac
|
||||
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
|
||||
;;
|
||||
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
|
||||
*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
|
||||
esac
|
||||
|
||||
# apply MVNW_REPOURL and calculate MAVEN_HOME
|
||||
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
|
||||
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
|
||||
distributionUrlName="${distributionUrl##*/}"
|
||||
distributionUrlNameMain="${distributionUrlName%.*}"
|
||||
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
|
||||
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
|
||||
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
|
||||
|
||||
exec_maven() {
|
||||
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
|
||||
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
|
||||
}
|
||||
|
||||
if [ -d "$MAVEN_HOME" ]; then
|
||||
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
|
||||
exec_maven "$@"
|
||||
fi
|
||||
|
||||
case "${distributionUrl-}" in
|
||||
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
|
||||
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
|
||||
esac
|
||||
|
||||
# prepare tmp dir
|
||||
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
|
||||
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
|
||||
trap clean HUP INT TERM EXIT
|
||||
else
|
||||
die "cannot create temp dir"
|
||||
fi
|
||||
|
||||
mkdir -p -- "${MAVEN_HOME%/*}"
|
||||
|
||||
# Download and Install Apache Maven
|
||||
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
|
||||
verbose "Downloading from: $distributionUrl"
|
||||
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||
|
||||
# select .zip or .tar.gz
|
||||
if ! command -v unzip >/dev/null; then
|
||||
distributionUrl="${distributionUrl%.zip}.tar.gz"
|
||||
distributionUrlName="${distributionUrl##*/}"
|
||||
fi
|
||||
|
||||
# verbose opt
|
||||
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
|
||||
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
|
||||
|
||||
# normalize http auth
|
||||
case "${MVNW_PASSWORD:+has-password}" in
|
||||
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
|
||||
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
|
||||
esac
|
||||
|
||||
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
|
||||
verbose "Found wget ... using wget"
|
||||
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
|
||||
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
|
||||
verbose "Found curl ... using curl"
|
||||
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
|
||||
elif set_java_home; then
|
||||
verbose "Falling back to use Java to download"
|
||||
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
|
||||
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||
cat >"$javaSource" <<-END
|
||||
public class Downloader extends java.net.Authenticator
|
||||
{
|
||||
protected java.net.PasswordAuthentication getPasswordAuthentication()
|
||||
{
|
||||
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
|
||||
}
|
||||
public static void main( String[] args ) throws Exception
|
||||
{
|
||||
setDefault( new Downloader() );
|
||||
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
|
||||
}
|
||||
}
|
||||
END
|
||||
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
|
||||
verbose " - Compiling Downloader.java ..."
|
||||
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
|
||||
verbose " - Running Downloader.java ..."
|
||||
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
|
||||
fi
|
||||
|
||||
# If specified, validate the SHA-256 sum of the Maven distribution zip file
|
||||
if [ -n "${distributionSha256Sum-}" ]; then
|
||||
distributionSha256Result=false
|
||||
if [ "$MVN_CMD" = mvnd.sh ]; then
|
||||
echo "Checksum validation is not supported for maven-mvnd." >&2
|
||||
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
|
||||
exit 1
|
||||
elif command -v sha256sum >/dev/null; then
|
||||
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
|
||||
distributionSha256Result=true
|
||||
fi
|
||||
elif command -v shasum >/dev/null; then
|
||||
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
|
||||
distributionSha256Result=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 'distributionSha256Sum' from your maven-wrapper.properties." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ $distributionSha256Result = false ]; then
|
||||
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
|
||||
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# unzip and move
|
||||
if command -v unzip >/dev/null; then
|
||||
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
|
||||
else
|
||||
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
|
||||
fi
|
||||
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
|
||||
mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
|
||||
|
||||
clean || :
|
||||
exec_maven "$@"
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
<# : batch portion
|
||||
@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 Optional ENV vars
|
||||
@REM MVNW_REPOURL - repo url base for downloading maven distribution
|
||||
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
|
||||
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
|
||||
@SET __MVNW_CMD__=
|
||||
@SET __MVNW_ERROR__=
|
||||
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
|
||||
@SET PSModulePath=
|
||||
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
|
||||
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
|
||||
)
|
||||
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
|
||||
@SET __MVNW_PSMODULEP_SAVE=
|
||||
@SET __MVNW_ARG0_NAME__=
|
||||
@SET MVNW_USERNAME=
|
||||
@SET MVNW_PASSWORD=
|
||||
@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
|
||||
@echo Cannot start maven from wrapper >&2 && exit /b 1
|
||||
@GOTO :EOF
|
||||
: end batch / begin powershell #>
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
if ($env:MVNW_VERBOSE -eq "true") {
|
||||
$VerbosePreference = "Continue"
|
||||
}
|
||||
|
||||
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
|
||||
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
|
||||
if (!$distributionUrl) {
|
||||
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
|
||||
}
|
||||
|
||||
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
|
||||
"maven-mvnd-*" {
|
||||
$USE_MVND = $true
|
||||
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
|
||||
$MVN_CMD = "mvnd.cmd"
|
||||
break
|
||||
}
|
||||
default {
|
||||
$USE_MVND = $false
|
||||
$MVN_CMD = $script -replace '^mvnw','mvn'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
# apply MVNW_REPOURL and calculate MAVEN_HOME
|
||||
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
|
||||
if ($env:MVNW_REPOURL) {
|
||||
$MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
|
||||
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
|
||||
}
|
||||
$distributionUrlName = $distributionUrl -replace '^.*/',''
|
||||
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
|
||||
$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
|
||||
if ($env:MAVEN_USER_HOME) {
|
||||
$MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
|
||||
}
|
||||
$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
|
||||
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
|
||||
|
||||
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
|
||||
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
|
||||
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
|
||||
exit $?
|
||||
}
|
||||
|
||||
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
|
||||
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
|
||||
}
|
||||
|
||||
# prepare tmp dir
|
||||
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
|
||||
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
|
||||
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
|
||||
trap {
|
||||
if ($TMP_DOWNLOAD_DIR.Exists) {
|
||||
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
|
||||
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
|
||||
}
|
||||
}
|
||||
|
||||
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
|
||||
|
||||
# Download and Install Apache Maven
|
||||
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
|
||||
Write-Verbose "Downloading from: $distributionUrl"
|
||||
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||
|
||||
$webclient = New-Object System.Net.WebClient
|
||||
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
|
||||
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
|
||||
}
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
|
||||
|
||||
# If specified, validate the SHA-256 sum of the Maven distribution zip file
|
||||
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
|
||||
if ($distributionSha256Sum) {
|
||||
if ($USE_MVND) {
|
||||
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
|
||||
}
|
||||
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
|
||||
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
|
||||
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
|
||||
}
|
||||
}
|
||||
|
||||
# unzip and move
|
||||
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
|
||||
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
|
||||
try {
|
||||
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
|
||||
} catch {
|
||||
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
|
||||
Write-Error "fail to move MAVEN_HOME"
|
||||
}
|
||||
} finally {
|
||||
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
|
||||
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
|
||||
}
|
||||
|
||||
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
<?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>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.4.4</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.kevinolarte</groupId>
|
||||
<artifactId>resibenissa</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>resibenissa</name>
|
||||
<description>Demo project for Spring Boot</description>
|
||||
<url/>
|
||||
<licenses>
|
||||
<license/>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer/>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection/>
|
||||
<developerConnection/>
|
||||
<tag/>
|
||||
<url/>
|
||||
</scm>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mail</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
<version>0.11.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>0.11.5</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<version>0.11.5</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.librepdf</groupId>
|
||||
<artifactId>openpdf</artifactId>
|
||||
<version>1.3.30</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.datafaker</groupId>
|
||||
<artifactId>datafaker</artifactId>
|
||||
<version>2.1.0</version> <!-- Puedes cambiar por la última disponible -->
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.kevinolarte.resibenissa;
|
||||
|
||||
public class LogContext {
|
||||
private static final ThreadLocal<Long> currentLogId = new ThreadLocal<>();
|
||||
|
||||
public static void setCurrentLogId(Long id) {
|
||||
currentLogId.set(id);
|
||||
}
|
||||
|
||||
public static Long getCurrentLogId() {
|
||||
return currentLogId.get();
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
currentLogId.remove();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.kevinolarte.resibenissa;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class ResibenissaApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ResibenissaApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package com.kevinolarte.resibenissa.config;
|
||||
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.repositories.UserRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
|
||||
/**
|
||||
* Configuración de seguridad de la aplicación.
|
||||
* <p>
|
||||
* Define los beans necesarios para la autenticación de usuarios,
|
||||
* incluyendo el codificador de contraseñas, el proveedor de autenticación
|
||||
* y el servicio de obtención de detalles de usuario.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
public class AplicationConfiguration {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
|
||||
/**
|
||||
* Devuelve un UserDetailsService que busca usuarios por email en la base de datos.
|
||||
*
|
||||
* @return Implementación de UserDetailsService personalizada.
|
||||
* @throws UsernameNotFoundException si el usuario no existe.
|
||||
*/
|
||||
@Bean
|
||||
UserDetailsService userDetailsService(){
|
||||
return email -> {
|
||||
User user = userRepository.findByEmail(email);
|
||||
if(user == null){
|
||||
throw new ResiException(ApiErrorCode.USUARIO_INVALIDO);
|
||||
}
|
||||
if (user.isBaja()){
|
||||
throw new ResiException(ApiErrorCode.USUARIO_BAJA);
|
||||
}
|
||||
return user;
|
||||
};
|
||||
}
|
||||
@Bean
|
||||
BCryptPasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(AuthenticationConfiguration config)throws Exception {
|
||||
return config.getAuthenticationManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un bean de {@link AuthenticationProvider} personalizado que usa
|
||||
* el {@link UserDetailsService} y el codificador de contraseñas definidos.
|
||||
*
|
||||
* @return el proveedor de autenticación configurado.
|
||||
*/
|
||||
@Bean
|
||||
AuthenticationProvider authenticationProvider() {
|
||||
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
|
||||
|
||||
authProvider.setUserDetailsService(userDetailsService());
|
||||
authProvider.setPasswordEncoder(passwordEncoder());
|
||||
|
||||
return authProvider;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package com.kevinolarte.resibenissa.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
/**
|
||||
* Clase de configuración que contiene valores por defecto utilizados en la aplicación.
|
||||
* <p>
|
||||
* Estos valores suelen emplearse para inicializar entidades, usuarios de sistema, o
|
||||
* como fallback en lógica que requiere datos por omisión.
|
||||
* </p>
|
||||
*
|
||||
* <p><b>Nota:</b> Estas constantes no deberían modificarse dinámicamente durante la ejecución.</p>
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
public class Conf {
|
||||
public static final Long idResidenciaDefault = 1L;
|
||||
public static final Long idUsuarioDefault = 1L;
|
||||
public static final String emailDefault = "default@default.com";
|
||||
public static final String PATH_PUBLIC_AUTH= "/auth/";
|
||||
public static final String PATH_PUBLIC_SWAGGER = "/swagger-ui/";
|
||||
public static final String PATH_PUBLIC_RESI_GET = "/resi/getAll";
|
||||
public static final String PATH_PUBLIC_RESI_CONTROLLER = "/public/";
|
||||
|
||||
@Value("${upload.dir}")
|
||||
public static String imageResource;
|
||||
public static final String imageDefault = "defaultPerfil.png";
|
||||
|
||||
public static final int POS_ESTADO_ABIERTO = 0;
|
||||
public static final int POS_ESTADO_CERRADO = 1;
|
||||
public static final int POS_ESTADO_EN_CURSO = 2;
|
||||
public static final int POS_ESTADO_FINALIZADA = 3;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.kevinolarte.resibenissa.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* Configuración global de CORS para permitir acceso desde el frontend.
|
||||
* Esto permite que navegadores puedan hacer peticiones a la API desde dominios distintos.
|
||||
*/
|
||||
@Configuration
|
||||
public class CorsConfig {
|
||||
|
||||
@Bean
|
||||
public WebMvcConfigurer corsConfigurer() {
|
||||
return new WebMvcConfigurer() {
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOrigins(
|
||||
"http://localhost:5500",
|
||||
"http://127.0.0.1:5500"
|
||||
)
|
||||
.allowedMethods("*")
|
||||
.allowedHeaders("*")
|
||||
.allowCredentials(false);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package com.kevinolarte.resibenissa.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Configuración del servicio de envío de correos electrónicos.
|
||||
* <p>
|
||||
* Esta clase define un {@link JavaMailSender} que se configura automáticamente
|
||||
* con los datos definidos en el archivo {@code application.properties} o {@code application.yml}.
|
||||
* Utiliza los servidores de Gmail como proveedor SMTP.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Las credenciales y configuraciones sensibles se inyectan desde las propiedades:
|
||||
* <ul>
|
||||
* <li><code>spring.mail.username</code></li>
|
||||
* <li><code>spring.mail.password</code></li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* @return Bean de {@link JavaMailSender} listo para ser inyectado y utilizado en servicios.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Configuration
|
||||
public class EmailConfiguration {
|
||||
@Value("${spring.mail.username}")
|
||||
private String username;
|
||||
|
||||
@Value("${spring.mail.password}")
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Crea e inicializa el {@link JavaMailSender} con configuración para SMTP (Gmail).
|
||||
*
|
||||
* @return Instancia de {@link JavaMailSender} configurada.
|
||||
*/
|
||||
@Bean
|
||||
public JavaMailSender javaMailSender() {
|
||||
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
|
||||
mailSender.setHost("smtp.gmail.com");
|
||||
mailSender.setPort(587);
|
||||
mailSender.setUsername(username);
|
||||
mailSender.setPassword(password);
|
||||
|
||||
Properties props = mailSender.getJavaMailProperties();
|
||||
props.put("mail.transport.protocol", "smtp");
|
||||
props.put("mail.smtp.auth", "true");
|
||||
props.put("mail.smtp.starttls.enable", "true");
|
||||
props.put("mail.debug", "true");
|
||||
|
||||
return mailSender;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
package com.kevinolarte.resibenissa.config;
|
||||
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.JwtService;
|
||||
import com.kevinolarte.resibenissa.services.LoggerService;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Filtro de autenticación que intercepta todas las peticiones HTTP y verifica si contienen
|
||||
* un token JWT válido en la cabecera {@code Authorization}.
|
||||
* <p>
|
||||
* Si el token es válido, autentica al usuario y lo registra en el {@link SecurityContextHolder}.
|
||||
* En caso de error, delega la excepción al {@link HandlerExceptionResolver} para devolver
|
||||
* una respuesta estructurada.
|
||||
* </p>
|
||||
*
|
||||
* Este filtro se ejecuta una sola vez por petición, al extender de {@link OncePerRequestFilter}.
|
||||
*
|
||||
* @author Kevin
|
||||
*/
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
private final JwtService jwtService;
|
||||
private final UserDetailsService userDetailsService;
|
||||
private final HandlerExceptionResolver handlerExceptionResolver;
|
||||
private final LoggerService loggerService;
|
||||
|
||||
|
||||
/**
|
||||
* Lógica principal del filtro. Verifica si la petición contiene un token JWT válido
|
||||
* y, si es así, autentica al usuario en el contexto de seguridad de Spring.
|
||||
*
|
||||
* @param request Petición HTTP entrante.
|
||||
* @param response Respuesta HTTP saliente.
|
||||
* @param filterChain Cadena de filtros que se continúa tras el procesamiento.
|
||||
* @throws ServletException si ocurre un error en el filtro.
|
||||
* @throws IOException si ocurre un error de entrada/salida.
|
||||
*/
|
||||
@Override
|
||||
protected void doFilterInternal(
|
||||
@NonNull HttpServletRequest request,
|
||||
@NonNull HttpServletResponse response,
|
||||
@NonNull FilterChain filterChain) throws ServletException, IOException {
|
||||
final String authHeader = request.getHeader("Authorization");
|
||||
String endpoint = request.getRequestURI();
|
||||
String metodo = request.getMethod();
|
||||
|
||||
|
||||
// Aquí puedes añadir más lógica para determinar el usuario autenticado
|
||||
String descripcion = "Acceso a endpoint";
|
||||
|
||||
loggerService.registrarLog(endpoint, metodo, descripcion);
|
||||
|
||||
|
||||
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
|
||||
handlerExceptionResolver.resolveException(
|
||||
request,
|
||||
response,
|
||||
null,
|
||||
new ApiException(new ResiException(ApiErrorCode.ENDPOINT_PROTEGIDO), "Falta el token de autorización.")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final String jwt = authHeader.substring(7);
|
||||
final String userEmail = jwtService.extrtractEmail(jwt);
|
||||
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
if (userEmail != null && authentication == null) {
|
||||
UserDetails userDetails = this.userDetailsService.loadUserByUsername(userEmail);
|
||||
|
||||
if (jwtService.isTokenValid(jwt, userDetails)) {
|
||||
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
|
||||
userDetails,
|
||||
null,
|
||||
userDetails.getAuthorities()
|
||||
);
|
||||
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authToken);
|
||||
}
|
||||
}
|
||||
|
||||
String uri = request.getRequestURI();
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (uri.startsWith("/admin/resi") && auth != null && auth.isAuthenticated()) {
|
||||
boolean isAdmin = auth.getAuthorities().stream()
|
||||
.anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"));
|
||||
|
||||
if (!isAdmin) {
|
||||
handlerExceptionResolver.resolveException(
|
||||
request,
|
||||
response,
|
||||
null,
|
||||
new ApiException(new ResiException(ApiErrorCode.ENDPOINT_PROTEGIDO), "Falta el token de autorización.")
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
} catch(Exception e){
|
||||
handlerExceptionResolver.resolveException(request, response, null, new ApiException(new ResiException(ApiErrorCode.ENDPOINT_PROTEGIDO), e.getMessage()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean shouldNotFilter(HttpServletRequest request) {
|
||||
String path = request.getRequestURI();
|
||||
System.out.println("URI: " + path);
|
||||
return path.startsWith(Conf.PATH_PUBLIC_SWAGGER)
|
||||
|| path.startsWith(Conf.PATH_PUBLIC_AUTH)
|
||||
|| path.startsWith(Conf.PATH_PUBLIC_RESI_GET)
|
||||
|| path.startsWith(Conf.PATH_PUBLIC_RESI_CONTROLLER);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package com.kevinolarte.resibenissa.config;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Clase de configuración de seguridad para la API.
|
||||
* <p>
|
||||
* Define la cadena de filtros de seguridad, política de sesiones,
|
||||
* rutas públicas y configuración CORS para permitir solicitudes seguras desde el frontend.
|
||||
* </p>
|
||||
*
|
||||
* Esta configuración se basa en JWT y es stateless (sin sesiones de servidor).
|
||||
*
|
||||
* @author Kevin
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@AllArgsConstructor
|
||||
public class SecurityConfiguration {
|
||||
|
||||
private final AuthenticationProvider authenticationProvider;
|
||||
private final JwtAuthenticationFilter jwtAuthenticationFilter;
|
||||
|
||||
|
||||
/**
|
||||
* Configura la cadena de filtros de seguridad para la aplicación.
|
||||
* <p>
|
||||
* - Desactiva CSRF.<br>
|
||||
* - Permite acceso libre a rutas que comienzan con {@code /auth/**}.<br>
|
||||
* - Requiere autenticación para cualquier otra petición.<br>
|
||||
* - Aplica política de sesión stateless (usada con JWT).<br>
|
||||
* - Agrega el filtro personalizado para validar JWT antes de {@link UsernamePasswordAuthenticationFilter}.
|
||||
* </p>
|
||||
*
|
||||
* @param http Objeto {@link HttpSecurity} para construir la configuración.
|
||||
* @return Cadena de filtros de seguridad {@link SecurityFilterChain} configurada.
|
||||
* @throws Exception Si ocurre un error en la construcción de la cadena.
|
||||
*/
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.authorizeHttpRequests(authorize -> authorize
|
||||
|
||||
.requestMatchers(Conf.PATH_PUBLIC_AUTH + "**").permitAll()
|
||||
.requestMatchers(Conf.PATH_PUBLIC_SWAGGER + "**").permitAll()
|
||||
.requestMatchers(Conf.PATH_PUBLIC_RESI_CONTROLLER + "**").permitAll()
|
||||
.requestMatchers(Conf.PATH_PUBLIC_RESI_GET).permitAll()
|
||||
|
||||
|
||||
|
||||
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.sessionManagement(session -> session
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.authenticationProvider(authenticationProvider)
|
||||
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CorsConfigurationSource corsConfigurationSource(){
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.setAllowedOrigins(List.of("http://localhost:8080"));
|
||||
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
|
||||
configuration.setAllowedHeaders(List.of("Authorization","Content-Type"));
|
||||
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
return source;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
package com.kevinolarte.resibenissa.config;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.moduloOrgSalida.EventoSalidaDto;
|
||||
import com.kevinolarte.resibenissa.dto.in.moduloOrgSalida.ParticipanteDto;
|
||||
import com.kevinolarte.resibenissa.dto.in.modulojuego.RegistroJuegoDto;
|
||||
import com.kevinolarte.resibenissa.enums.Role;
|
||||
import com.kevinolarte.resibenissa.enums.moduloOrgSalida.EstadoSalida;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.Dificultad;
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
import com.kevinolarte.resibenissa.models.Residente;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.models.moduloOrgSalida.EventoSalida;
|
||||
import com.kevinolarte.resibenissa.models.moduloOrgSalida.Participante;
|
||||
import com.kevinolarte.resibenissa.models.moduloWallet.Wallet;
|
||||
import com.kevinolarte.resibenissa.models.modulojuego.Juego;
|
||||
import com.kevinolarte.resibenissa.models.modulojuego.RegistroJuego;
|
||||
import com.kevinolarte.resibenissa.repositories.ResidenciaRepository;
|
||||
import com.kevinolarte.resibenissa.repositories.ResidenteRepository;
|
||||
import com.kevinolarte.resibenissa.repositories.UserRepository;
|
||||
import com.kevinolarte.resibenissa.repositories.moduloOrgSalida.EventoSalidaRepository;
|
||||
import com.kevinolarte.resibenissa.repositories.moduloOrgSalida.ParticipanteRepository;
|
||||
import com.kevinolarte.resibenissa.repositories.moduloWallet.WalletRepository;
|
||||
import com.kevinolarte.resibenissa.repositories.modulojuego.JuegoRepository;
|
||||
import com.kevinolarte.resibenissa.repositories.modulojuego.RegistroJuegoRepository;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.datafaker.Faker;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class StartupDataLoader {
|
||||
|
||||
private final ResidenciaRepository residenciaRepository;
|
||||
private final UserRepository userRepository;
|
||||
private final ResidenteRepository residenteRepository;
|
||||
private final JuegoRepository juegoRepository;
|
||||
private final RegistroJuegoRepository registroJuegoRepository;
|
||||
private final EventoSalidaRepository eventoSalidaRepository;
|
||||
private final ParticipanteRepository participanteRepository;
|
||||
private final BCryptPasswordEncoder passwordEncoder;
|
||||
private final WalletRepository walletRepository;
|
||||
private final Faker faker = new Faker();
|
||||
private final Set<String> dniGenerados = new HashSet<>();
|
||||
private final Set<String> emailsGenerados = new HashSet<>();
|
||||
private final Random random = new Random();
|
||||
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
Residencia residenciaAdmin = residenciaRepository.save(new Residencia("Residencia Admin", "resiAdmin@gmail.com"));
|
||||
User user = new User("Kevin", "olarte", "dafault@gmail.com", passwordEncoder.encode("default"), Role.ADMIN);
|
||||
user.setResidencia(residenciaAdmin);
|
||||
user.setEnabled(true);
|
||||
user = userRepository.save(user);
|
||||
// Cargar datos de prueba al iniciar la aplicación
|
||||
cargarDatosPrueba();
|
||||
cargarJuegosPrueba();
|
||||
cargarRegistrosJuegosPrueba();
|
||||
cargarEventosSalidaPrueba();
|
||||
|
||||
}
|
||||
|
||||
public void cargarRegistrosJuegosPrueba() {
|
||||
List<Residente> residentes = residenteRepository.findAll();
|
||||
List<Juego> juegos = juegoRepository.findAll();
|
||||
List<User> user = userRepository.findAll();
|
||||
if (residentes.isEmpty() || juegos.isEmpty()) {
|
||||
System.out.println("⚠️ No hay residentes o juegos cargados en la base de datos.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Residente residente : residentes) {
|
||||
for (int i = 0; i < 7; i++) {
|
||||
RegistroJuego registro = new RegistroJuego();
|
||||
registro.setResidente(residente);
|
||||
registro.setJuego(juegos.get(random.nextInt(juegos.size())));
|
||||
registro.setFecha(LocalDateTime.now().minusDays(random.nextInt(30)));
|
||||
registro.setNum(random.nextInt(10)); // Fallos entre 0 y 9
|
||||
registro.setDuracion(30 + random.nextDouble() * 90); // Entre 30 y 120 segundos
|
||||
registro.setDificultad(Dificultad.values()[random.nextInt(Dificultad.values().length)]);
|
||||
registro.setObservacion("Prueba generada automáticamente");
|
||||
registro.setUsuario(user.get(0));
|
||||
registroJuegoRepository.save(registro);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cargarJuegosPrueba() {
|
||||
Juego juego1 = new Juego("Seguir la línea");
|
||||
Juego juego2 = new Juego("Memory");
|
||||
Juego juego3 = new Juego("Bongo");
|
||||
|
||||
juegoRepository.save(juego1);
|
||||
juegoRepository.save(juego2);
|
||||
juegoRepository.save(juego3);
|
||||
}
|
||||
|
||||
public void cargarEventosSalidaPrueba() {
|
||||
List<Residencia> residencias = residenciaRepository.findAll();
|
||||
|
||||
for (Residencia residencia : residencias) {
|
||||
// 1 evento esta mañana
|
||||
eventoSalidaRepository.save(crearEvento(residencia, LocalDateTime.now().with(LocalTime.of(10, 0))));
|
||||
|
||||
// 2 eventos pasado mañana
|
||||
eventoSalidaRepository.save(crearEvento(residencia, LocalDateTime.now().plusDays(2).with(LocalTime.of(9 + random.nextInt(3), 0))));
|
||||
eventoSalidaRepository.save(crearEvento(residencia, LocalDateTime.now().plusDays(2).with(LocalTime.of(14 + random.nextInt(3), 0))));
|
||||
|
||||
// 2 eventos la semana que viene
|
||||
eventoSalidaRepository.save(crearEvento(residencia, LocalDateTime.now().plusDays(7).with(LocalTime.of(10, 0))));
|
||||
eventoSalidaRepository.save(crearEvento(residencia, LocalDateTime.now().plusDays(8).with(LocalTime.of(17, 30))));
|
||||
}
|
||||
}
|
||||
|
||||
private EventoSalida crearEvento(Residencia residencia, LocalDateTime fecha) {
|
||||
EventoSalida evento = new EventoSalida();
|
||||
evento.setNombre(faker.funnyName().name());
|
||||
evento.setDescripcion(faker.lorem().sentence(10));
|
||||
evento.setFechaInicio(fecha);
|
||||
evento.setEstado(EstadoSalida.ABIERTO); // Ajusta si usas otro valor por defecto
|
||||
evento.setResidencia(residencia);
|
||||
return evento;
|
||||
}
|
||||
|
||||
public void cargarDatosPrueba() {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
String ciudad = faker.address().cityName().replaceAll("[^A-Za-z]", "");
|
||||
String emailResidencia = generarEmailUnico("residencia" + ciudad.toLowerCase());
|
||||
|
||||
Residencia residencia = new Residencia();
|
||||
residencia.setNombre("Residencia " + ciudad);
|
||||
residencia.setEmail(emailResidencia);
|
||||
residenciaRepository.save(residencia);
|
||||
User user = new User();
|
||||
user.setNombre("Admin " + ciudad);
|
||||
user.setApellido("Administrador " + ciudad);
|
||||
user.setEnabled(true);
|
||||
user.setEmail("admin@" + ciudad.toLowerCase() + ".com");
|
||||
user.setPassword(passwordEncoder.encode("admin123"));
|
||||
user.setResidencia(residencia);
|
||||
user.setRole(Role.NORMAL);
|
||||
userRepository.save(user);
|
||||
|
||||
|
||||
for (int j = 0; j < 30; j++) {
|
||||
String nombre = faker.name().firstName();
|
||||
String apellido = faker.name().lastName();
|
||||
LocalDate nacimiento = faker.date().birthday(65, 95).toLocalDateTime().toLocalDate();
|
||||
String dni = generarDniUnico();
|
||||
String familiar1 = generarEmailUnico(faker.name().firstName());
|
||||
String familiar2 = null;
|
||||
|
||||
Residente residente = new Residente(nombre, apellido, nacimiento, dni, familiar1, familiar2);
|
||||
residente.setResidencia(residencia);
|
||||
residenteRepository.save(residente);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private String generarDniUnico() {
|
||||
String dni;
|
||||
do {
|
||||
// DNI español típico: 8 números + letra final (omitimos la letra final para cumplir tu validador de 8)
|
||||
dni = String.format("%08d", faker.number().numberBetween(10000000, 99999999));
|
||||
} while (!dniGenerados.add(dni));
|
||||
return dni;
|
||||
}
|
||||
|
||||
|
||||
private String generarEmailUnico(String base) {
|
||||
String email;
|
||||
int intento = 0;
|
||||
do {
|
||||
email = base + (intento == 0 ? "" : intento) + "@resisuite.com";
|
||||
intento++;
|
||||
} while (!emailsGenerados.add(email));
|
||||
return email;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.kevinolarte.resibenissa.config;
|
||||
|
||||
import com.kevinolarte.resibenissa.config.interceptor.ControllerLoggerInterceptor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
private final ControllerLoggerInterceptor controllerLoggerInterceptor;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(controllerLoggerInterceptor)
|
||||
.addPathPatterns("/**"); // Intercepta todos los endpoints
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package com.kevinolarte.resibenissa.config.interceptor;
|
||||
|
||||
import com.kevinolarte.resibenissa.LogContext;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.LoggerService;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class ControllerLoggerInterceptor implements HandlerInterceptor {
|
||||
|
||||
private final LoggerService loggerService;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
if (!(handler instanceof HandlerMethod)) return true;
|
||||
|
||||
String endpoint = request.getRequestURI();
|
||||
String metodo = request.getMethod();
|
||||
|
||||
|
||||
// Aquí puedes añadir más lógica para determinar el usuario autenticado
|
||||
String descripcion = "Acceso a endpoint";
|
||||
|
||||
loggerService.registrarLog(endpoint, metodo, descripcion);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||
System.out.println("Interceptor afterCompletion called");
|
||||
LogContext.clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
package com.kevinolarte.resibenissa.controllers;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.auth.LoginUserDto;
|
||||
import com.kevinolarte.resibenissa.dto.in.auth.RegisterUserDto;
|
||||
import com.kevinolarte.resibenissa.dto.in.auth.VerifyUserDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.UserResponseDto;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.dto.out.LoginResponseDto;
|
||||
import com.kevinolarte.resibenissa.services.AuthenticationService;
|
||||
import com.kevinolarte.resibenissa.services.JwtService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* Controlador REST para la creacion de usuarios
|
||||
* <p>
|
||||
* Expone endpoints relacionados con el registro, inicio de sesión,
|
||||
* verificación de cuenta por correo y reenvío de códigos de verificación.
|
||||
* </p>
|
||||
*
|
||||
* Todas las rutas están bajo el prefijo <code>/auth</code>.
|
||||
*
|
||||
* @author Kevin
|
||||
*/
|
||||
@RequestMapping("/auth")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class AuthenticationController {
|
||||
private final JwtService jwtService;
|
||||
private final AuthenticationService authenticationService;
|
||||
|
||||
|
||||
/**
|
||||
* Registra un nuevo usuario en el sistema.
|
||||
* <p>
|
||||
* El usuario creado se guarda con estado "no activado" hasta que complete
|
||||
* el proceso de verificación vía código enviado al correo.
|
||||
* </p>
|
||||
*
|
||||
* @param registerUserDto Datos necesarios para registrar al usuario.
|
||||
* @return {@link ResponseEntity} con los datos del usuario registrado.
|
||||
*/
|
||||
@PostMapping("/signup")
|
||||
public ResponseEntity<UserResponseDto> register(@RequestBody RegisterUserDto registerUserDto){
|
||||
UserResponseDto user;
|
||||
try{
|
||||
user = authenticationService.singUp(registerUserDto);
|
||||
} catch (ResiException e){
|
||||
throw new ApiException(e, e.getMessage());
|
||||
}catch (Exception e){
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(user);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Autentica a un usuario existente y devuelve un token JWT válido.
|
||||
*
|
||||
* @param loginUserDto DTO con email y contraseña.
|
||||
* @return {@link ResponseEntity} con el token JWT y su tiempo de expiración.
|
||||
*/
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<LoginResponseDto> authenticate(@RequestBody LoginUserDto loginUserDto){
|
||||
LoginResponseDto loginResponse;
|
||||
try{
|
||||
User userauthentication = authenticationService.authenticate(loginUserDto);
|
||||
String token = jwtService.generateToken(userauthentication);
|
||||
loginResponse = new LoginResponseDto(
|
||||
token,
|
||||
jwtService.getExpirationTime(),
|
||||
userauthentication
|
||||
);
|
||||
}catch (ResiException e){
|
||||
throw new ApiException(e, e.getMessage());
|
||||
}catch (Exception e){
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(loginResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifica un usuario usando el código enviado por correo.
|
||||
*
|
||||
* @param verifyUserDto DTO con email y código de verificación.
|
||||
* @return {@link ResponseEntity} con mensaje de éxito.
|
||||
*/
|
||||
@PostMapping("/verify")
|
||||
public ResponseEntity<String> verifyUser(@RequestBody VerifyUserDto verifyUserDto){
|
||||
try{
|
||||
authenticationService.verifyUser(verifyUserDto);
|
||||
}catch (ResiException e){
|
||||
throw new ApiException(e, e.getMessage());
|
||||
}catch (Exception e){
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
|
||||
return ResponseEntity.ok("AcountVerfied");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reenvía un nuevo código de verificación al correo indicado.
|
||||
*
|
||||
* @param email Dirección de correo del usuario.
|
||||
* @return {@link ResponseEntity} con mensaje de confirmación.
|
||||
*/
|
||||
@PostMapping("/resend")
|
||||
public ResponseEntity<String> resendVerificationCode(@RequestParam String email ){
|
||||
try{
|
||||
authenticationService.resendVerificationCode(email);
|
||||
}catch (ResiException e){
|
||||
throw new ApiException(e, e.getMessage());
|
||||
}catch (Exception e){
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok("Verification Code Resent");
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package com.kevinolarte.resibenissa.controllers;
|
||||
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.services.JwtService;
|
||||
import com.kevinolarte.resibenissa.services.moduloOrgSalida.ParticipanteService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* Controlador REST para manejar operaciones públicas relacionadas con participantes en eventos.
|
||||
* Permite confirmar o denegar permisos de participantes en eventos de una residencia.
|
||||
* <P>
|
||||
* URL Base: {@code /public}
|
||||
* @author Kevin Olarte
|
||||
*
|
||||
*/
|
||||
@RequestMapping("/public")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class PublicController {
|
||||
|
||||
private final JwtService jwtService;
|
||||
private final ParticipanteService participanteService;
|
||||
|
||||
/**
|
||||
* Endpoint para confirmar el permiso de un participante en un evento.
|
||||
* @param token Token JWT que contiene la información del participante, evento y residencia.
|
||||
* @return ResponseEntity con un mensaje de éxito o error.
|
||||
*/
|
||||
@GetMapping("/allowParticipante")
|
||||
public ResponseEntity<String> confirmarPermiso(@RequestParam String token) {
|
||||
try {
|
||||
Long idParticipante = Long.parseLong(jwtService.extractClaim(token, claims -> claims.get("idParticipante").toString()));
|
||||
Long idEvento = Long.parseLong(jwtService.extractClaim(token, claims -> claims.get("idEvento").toString()));
|
||||
Long idResidencia = Long.parseLong(jwtService.extractClaim(token, claims -> claims.get("idResidencia").toString()));
|
||||
|
||||
participanteService.allow(idResidencia, idEvento, idParticipante);
|
||||
return ResponseEntity.ok("✅ Permiso registrado correctamente.");
|
||||
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
}catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.ENDPOINT_PROTEGIDO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint para confirmar la denegación de un participante en un evento.
|
||||
* @param token Token JWT que contiene la información del participante, evento y residencia.
|
||||
* @return ResponseEntity con un mensaje de éxito o error.
|
||||
*/
|
||||
@GetMapping("/denyParticipante")
|
||||
public ResponseEntity<String> confirmarDenegacion(@RequestParam String token) {
|
||||
try {
|
||||
|
||||
Long idParticipante = Long.parseLong(jwtService.extractClaim(token, claims -> claims.get("idParticipante").toString()));
|
||||
Long idEvento = Long.parseLong(jwtService.extractClaim(token, claims -> claims.get("idEvento").toString()));
|
||||
Long idResidencia = Long.parseLong(jwtService.extractClaim(token, claims -> claims.get("idResidencia").toString()));
|
||||
participanteService.deny(idResidencia, idEvento, idParticipante);
|
||||
return ResponseEntity.ok("✅ Denegación registrada correctamente.");
|
||||
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
}catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.ENDPOINT_PROTEGIDO), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,308 @@
|
|||
package com.kevinolarte.resibenissa.controllers.moduloOrgSalida.evento;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.moduloOrgSalida.EventoSalidaDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.moduloOrgSalida.EventoSalidaResponseDto;
|
||||
import com.kevinolarte.resibenissa.enums.moduloOrgSalida.EstadoSalida;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.moduloOrgSalida.EventoSalidaService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controlador REST para gestionar los eventos de salida de una residencia.
|
||||
* <p>
|
||||
* Permite crear, actualizar, eliminar, consultar y listar eventos de salida
|
||||
* asociados a una residencia específica.
|
||||
* </p>
|
||||
*
|
||||
* URL base: /admin/resi
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/admin/resi")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class EventoSalidaAdminController {
|
||||
|
||||
public final EventoSalidaService eventoSalidaService;
|
||||
|
||||
|
||||
/**
|
||||
* Crea un nuevo evento de salida en una residencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia donde se creará el evento de salida.
|
||||
* @param input DTO que contiene los datos del evento de salida a crear.
|
||||
* @return {@link ResponseEntity} con el evento de salida creado.ç
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PostMapping("/{idResidencia}/evento/add")
|
||||
public ResponseEntity<EventoSalidaResponseDto> add(
|
||||
@PathVariable Long idResidencia,
|
||||
@RequestBody EventoSalidaDto input) {
|
||||
try {
|
||||
return ResponseEntity.status(HttpStatus.CREATED)
|
||||
.body(eventoSalidaService.add(input, idResidencia));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene los datos de un evento de salida específico.
|
||||
*
|
||||
* @param idResidencia ID de la residencia a la que pertenece el evento de salida.
|
||||
* @param idEventoSalida ID del evento de salida a consultar.
|
||||
* @return {@link ResponseEntity} con los datos del evento de salida encontrado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/{idResidencia}/evento/{idEventoSalida}/get")
|
||||
public ResponseEntity<EventoSalidaResponseDto> getEventoSalida(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEventoSalida) {
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.get(idEventoSalida, idResidencia));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene una lista de eventos de salida con filtros dinámicos.
|
||||
*
|
||||
* @param idResidencia ID de la residencia (obligatorio)
|
||||
* @param fecha Fecha exacta del evento
|
||||
* @param minFecha Fecha mínima del evento (rango)
|
||||
* @param maxFecha Fecha máxima del evento (rango)
|
||||
* @param estado Estado del evento (PENDIENTE, REALIZADA, CANCELADA...)
|
||||
* @param idResidente Filtra eventos que contengan al residente con este ID
|
||||
* @param idParticipante Filtra eventos que contengan al participante con este ID
|
||||
* @param minRH Mínimo número de participantes con recursos humanos
|
||||
* @param maxRH Máximo número de participantes con recursos humanos
|
||||
* @param minRM Mínimo número de participantes con recursos materiales
|
||||
* @param maxRM Máximo número de participantes con recursos materiales
|
||||
* @return Lista de eventos de salida que cumplen los filtros
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/{idResidencia}/evento/getAll")
|
||||
public ResponseEntity<List<EventoSalidaResponseDto>> getAllEventosSalida(
|
||||
@PathVariable Long idResidencia,
|
||||
@RequestParam(required = false) LocalDate fecha,
|
||||
@RequestParam(required = false) LocalDate minFecha,
|
||||
@RequestParam(required = false) LocalDate maxFecha,
|
||||
@RequestParam(required = false) EstadoSalida estado,
|
||||
@RequestParam(required = false) Long idResidente,
|
||||
@RequestParam(required = false) Long idParticipante,
|
||||
@RequestParam(required = false) Integer minRH,
|
||||
@RequestParam(required = false) Integer maxRH,
|
||||
@RequestParam(required = false) Integer minRM,
|
||||
@RequestParam(required = false) Integer maxRM) {
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.getAll(
|
||||
idResidencia, fecha, minFecha, maxFecha, estado,
|
||||
idResidente, idParticipante, minRH, maxRH, minRM, maxRM));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de eventos de salida con filtros dinámicos.
|
||||
*
|
||||
* @param fecha Fecha exacta del evento
|
||||
* @param minFecha Fecha mínima del evento (rango)
|
||||
* @param maxFecha Fecha máxima del evento (rango)
|
||||
* @param estado Estado del evento (PENDIENTE, REALIZADA, CANCELADA...)
|
||||
* @param idResidente Filtra eventos que contengan al residente con este ID
|
||||
* @param idParticipante Filtra eventos que contengan al participante con este ID
|
||||
* @param minRH Mínimo número de participantes con recursos humanos
|
||||
* @param maxRH Máximo número de participantes con recursos humanos
|
||||
* @param minRM Mínimo número de participantes con recursos materiales
|
||||
* @param maxRM Máximo número de participantes con recursos materiales
|
||||
* @return Lista de eventos de salida que cumplen los filtros
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/evento/getAll")
|
||||
public ResponseEntity<List<EventoSalidaResponseDto>> getAllEventosSalidaSinResidencia(
|
||||
@RequestParam(required = false) LocalDate fecha,
|
||||
@RequestParam(required = false) LocalDate minFecha,
|
||||
@RequestParam(required = false) LocalDate maxFecha,
|
||||
@RequestParam(required = false) EstadoSalida estado,
|
||||
@RequestParam(required = false) Long idResidente,
|
||||
@RequestParam(required = false) Long idParticipante,
|
||||
@RequestParam(required = false) Integer minRH,
|
||||
@RequestParam(required = false) Integer maxRH,
|
||||
@RequestParam(required = false) Integer minRM,
|
||||
@RequestParam(required = false) Integer maxRM) {
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.getAll(
|
||||
fecha, minFecha, maxFecha, estado,
|
||||
idResidente, idParticipante, minRH, maxRH, minRM, maxRM));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Elimina un evento de salida de una residencia.
|
||||
* <p>
|
||||
* La eliminación incluye también a todos los participantes asociados al evento.
|
||||
* </p>
|
||||
*
|
||||
* @param idResidencia ID de la residencia a la que pertenece el evento de salida.
|
||||
* @param idEventoSalida ID del evento de salida a eliminar.
|
||||
* @return {@link ResponseEntity} sin contenido si la eliminación fue exitosa.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@DeleteMapping("/{idResidencia}/evento/{idEventoSalida}/delete")
|
||||
public ResponseEntity<Void> delete(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEventoSalida) {
|
||||
try {
|
||||
eventoSalidaService.delete(idEventoSalida, idResidencia);
|
||||
return ResponseEntity.noContent().build();
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cambia el nombre de un evento de salida.
|
||||
*
|
||||
* @param idResidencia ID de la residencia a la que pertenece el evento de salida.
|
||||
* @param idEventoSalida ID del evento de salida a actualizar.
|
||||
* @param nombre Nuevo nombre del evento de salida.
|
||||
* @return {@link ResponseEntity} con el evento de salida actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idResidencia}/evento/{idEventoSalida}/changeNombre")
|
||||
public ResponseEntity<EventoSalidaResponseDto> changeNombre(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEventoSalida,
|
||||
@RequestParam String nombre) {
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.changeNombre(idEventoSalida, nombre, idResidencia));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cambia la descripción de un evento de salida.
|
||||
*
|
||||
* @param idResidencia ID de la residencia a la que pertenece el evento de salida.
|
||||
* @param idEventoSalida ID del evento de salida a actualizar.
|
||||
* @param descripcion Nueva descripción del evento de salida.
|
||||
* @return {@link ResponseEntity} con el evento de salida actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idResidencia}/evento/{idEventoSalida}/changeDescripcion")
|
||||
public ResponseEntity<EventoSalidaResponseDto> changeDescripcion(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEventoSalida,
|
||||
@RequestParam String descripcion) {
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.changeDescripcion(idEventoSalida, descripcion, idResidencia));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cambia la fecha de un evento de salida.
|
||||
*
|
||||
* @param idResidencia ID de la residencia a la que pertenece el evento de salida.
|
||||
* @param idEventoSalida ID del evento de salida a actualizar.
|
||||
* @param fecha Nueva fecha del evento de salida.
|
||||
* @return {@link ResponseEntity} con el evento de salida actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idResidencia}/evento/{idEventoSalida}/changeFecha")
|
||||
public ResponseEntity<EventoSalidaResponseDto> changeFecha(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEventoSalida,
|
||||
@RequestParam LocalDateTime fecha) {
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.changeFecha(idEventoSalida, fecha, idResidencia));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cambia el estado de un evento de salida.
|
||||
*
|
||||
* @param idResidencia ID de la residencia a la que pertenece el evento de salida.
|
||||
* @param idEventoSalida ID del evento de salida a actualizar.
|
||||
* @param estado Nuevo estado del evento de salida.
|
||||
* @return {@link ResponseEntity} con el evento de salida actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idResidencia}/evento/{idEventoSalida}/changeEstado")
|
||||
public ResponseEntity<EventoSalidaResponseDto> changeEstado(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEventoSalida,
|
||||
@RequestParam EstadoSalida estado) {
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.changeEstado(idEventoSalida, estado, idResidencia));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualiza los datos de un evento de salida.
|
||||
*
|
||||
* @param idResidencia ID de la residencia a la que pertenece el evento de salida.
|
||||
* @param idEventoSalida ID del evento de salida a actualizar.
|
||||
* @param input DTO con los nuevos datos del evento de salida.
|
||||
* @return {@link ResponseEntity} con el evento de salida actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idResidencia}/evento/{idEventoSalida}/update")
|
||||
public ResponseEntity<EventoSalidaResponseDto> update(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEventoSalida,
|
||||
@RequestBody EventoSalidaDto input) {
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.update(input, idResidencia, idEventoSalida));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
package com.kevinolarte.resibenissa.controllers.moduloOrgSalida.evento;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.moduloOrgSalida.EventoSalidaDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.moduloOrgSalida.EventoSalidaResponseDto;
|
||||
import com.kevinolarte.resibenissa.enums.moduloOrgSalida.EstadoSalida;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.moduloOrgSalida.EventoSalidaService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controlador REST para gestionar los eventos de salida de una residencia.
|
||||
* <p>
|
||||
* Permite crear, actualizar, eliminar, consultar y listar eventos de salida
|
||||
* asociados a una residencia específica.
|
||||
* </p>
|
||||
*
|
||||
* URL base: /resi/evento
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/resi/evento")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class EventoSalidaController {
|
||||
|
||||
private final EventoSalidaService eventoSalidaService;
|
||||
|
||||
|
||||
/**
|
||||
* Crea un nuevo evento de salida en una residencia.
|
||||
*
|
||||
* @param input DTO que contiene los datos del evento de salida a crear.
|
||||
* @return {@link ResponseEntity} con el evento de salida creado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public ResponseEntity<EventoSalidaResponseDto> add(@RequestBody EventoSalidaDto input) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
return ResponseEntity.status(HttpStatus.CREATED)
|
||||
.body(eventoSalidaService.add(input, currentUser.getResidencia().getId()));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene los datos de un evento de salida específico.
|
||||
*
|
||||
* @param idEventoSalida ID del evento de salida a consultar.
|
||||
* @return {@link ResponseEntity} con los datos del evento de salida encontrado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/{idEventoSalida}/get")
|
||||
public ResponseEntity<EventoSalidaResponseDto> getEventoSalida(@PathVariable Long idEventoSalida) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.get(idEventoSalida, currentUser.getResidencia().getId()));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de eventos de salida filtrados por varios parámetros.
|
||||
*
|
||||
* @param fecha Fecha específica del evento de salida.
|
||||
* @param minFecha Fecha mínima del evento de salida.
|
||||
* @param maxFecha Fecha máxima del evento de salida.
|
||||
* @param estado Estado del evento de salida.
|
||||
* @param idResidente ID del residente asociado al evento de salida.
|
||||
* @param idParticipante ID del participante asociado al evento de salida.
|
||||
* @param minRH Mínimo rango horario del evento de salida.
|
||||
* @param maxRH Máximo rango horario del evento de salida.
|
||||
* @param minRM Mínimo rango de minutos del evento de salida.
|
||||
* @param maxRM Máximo rango de minutos del evento de salida.
|
||||
* @return {@link ResponseEntity} con la lista de eventos de salida encontrados.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/getAll")
|
||||
public ResponseEntity<List<EventoSalidaResponseDto>> getAllEventosSalida(
|
||||
@RequestParam(required = false) LocalDate fecha,
|
||||
@RequestParam(required = false) LocalDate minFecha,
|
||||
@RequestParam(required = false) LocalDate maxFecha,
|
||||
@RequestParam(required = false) EstadoSalida estado,
|
||||
@RequestParam(required = false) Long idResidente,
|
||||
@RequestParam(required = false) Long idParticipante,
|
||||
@RequestParam(required = false) Integer minRH,
|
||||
@RequestParam(required = false) Integer maxRH,
|
||||
@RequestParam(required = false) Integer minRM,
|
||||
@RequestParam(required = false) Integer maxRM) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.getAll(
|
||||
currentUser.getResidencia().getId(),
|
||||
fecha, minFecha, maxFecha, estado,
|
||||
idResidente, idParticipante, minRH, maxRH, minRM, maxRM));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Elimina un evento de salida de una residencia.
|
||||
* <p>
|
||||
* La eliminación incluye también a todos los participantes asociados al evento.
|
||||
* </p>
|
||||
*
|
||||
* @param idEventoSalida ID del evento de salida a eliminar.
|
||||
* @return {@link ResponseEntity} con estado NO_CONTENT si la eliminación fue exitosa.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@DeleteMapping("/{idEventoSalida}/delete")
|
||||
public ResponseEntity<Void> delete(@PathVariable Long idEventoSalida) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
eventoSalidaService.delete(idEventoSalida, currentUser.getResidencia().getId());
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cambia el nombre de un evento de salida.
|
||||
*
|
||||
* @param idEventoSalida ID del evento de salida a actualizar.
|
||||
* @param nombre Nuevo nombre del evento de salida.
|
||||
* @return {@link ResponseEntity} con el evento de salida actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idEventoSalida}/changeNombre")
|
||||
public ResponseEntity<EventoSalidaResponseDto> changeNombre(
|
||||
@PathVariable Long idEventoSalida,
|
||||
@RequestParam String nombre) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.changeNombre(idEventoSalida, nombre, currentUser.getResidencia().getId()));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cambia la descripción de un evento de salida.
|
||||
*
|
||||
* @param idEventoSalida ID del evento de salida a actualizar.
|
||||
* @param descripcion Nueva descripción del evento de salida.
|
||||
* @return {@link ResponseEntity} con el evento de salida actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idEventoSalida}/changeDescripcion")
|
||||
public ResponseEntity<EventoSalidaResponseDto> changeDescripcion(
|
||||
@PathVariable Long idEventoSalida,
|
||||
@RequestParam String descripcion) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.changeDescripcion(idEventoSalida, descripcion, currentUser.getResidencia().getId()));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cambia la fecha de un evento de salida.
|
||||
*
|
||||
* @param idEventoSalida ID del evento de salida a actualizar.
|
||||
* @param fecha Nueva fecha del evento de salida.
|
||||
* @return {@link ResponseEntity} con el evento de salida actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idEventoSalida}/ChangeFecha")
|
||||
public ResponseEntity<EventoSalidaResponseDto> changeFecha(
|
||||
@PathVariable Long idEventoSalida,
|
||||
@RequestParam LocalDateTime fecha) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.changeFecha(idEventoSalida, fecha, currentUser.getResidencia().getId()));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cambia el estado de un evento de salida.
|
||||
*
|
||||
* @param idEventoSalida ID del evento de salida a actualizar.
|
||||
* @param estado Nuevo estado del evento de salida.
|
||||
* @return {@link ResponseEntity} con el evento de salida actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idEventoSalida}/changeEstado")
|
||||
public ResponseEntity<EventoSalidaResponseDto> changeEstado(
|
||||
@PathVariable Long idEventoSalida,
|
||||
@RequestParam EstadoSalida estado) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.changeEstado(idEventoSalida, estado, currentUser.getResidencia().getId()));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualiza los datos de un evento de salida.
|
||||
*
|
||||
* @param idEventoSalida ID del evento de salida a actualizar.
|
||||
* @param input DTO con los nuevos datos del evento de salida.
|
||||
* @return {@link ResponseEntity} con el evento de salida actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idEventoSalida}/update")
|
||||
public ResponseEntity<EventoSalidaResponseDto> update(
|
||||
@PathVariable Long idEventoSalida,
|
||||
@RequestBody EventoSalidaDto input) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
return ResponseEntity.ok(eventoSalidaService.update(input, currentUser.getResidencia().getId(), idEventoSalida));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,297 @@
|
|||
package com.kevinolarte.resibenissa.controllers.moduloOrgSalida.participante;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.moduloOrgSalida.ParticipanteDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.moduloOrgSalida.ParticipanteResponseDto;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.moduloOrgSalida.ParticipanteService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controlador REST para gestionar los participantes de un evento de salida en una residencia.
|
||||
* <p>
|
||||
* Permite agregar, consultar, actualizar, eliminar y listar participantes asociados
|
||||
* a un evento específico dentro de una residencia.
|
||||
* </p>
|
||||
*
|
||||
* URL Base: {@code /admin/resi/{idResidencia}/evento/{idEvento}/participante}
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/admin/resi/{idResidencia}/evento/{idEvento}/participante")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class ParticipanteAdminController {
|
||||
|
||||
private final ParticipanteService participanteService;
|
||||
|
||||
/**
|
||||
* Registra un nuevo participante en un evento de salida.
|
||||
*
|
||||
* @param idResidencia ID de la residencia donde se registra el participante.
|
||||
* @param idEvento ID del evento de salida al que se registra el participante.
|
||||
* @param participanteDto DTO con los datos del participante a registrar.
|
||||
* @return {@link ResponseEntity} con el participante creado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public ResponseEntity<ParticipanteResponseDto> add(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEvento,
|
||||
@RequestBody ParticipanteDto participanteDto) {
|
||||
try {
|
||||
return ResponseEntity.status(HttpStatus.CREATED)
|
||||
.body(participanteService.add(participanteDto, idEvento, idResidencia));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene los datos de un participante específico en un evento de salida.
|
||||
*
|
||||
* @param idResidencia ID de la residencia donde se encuentra el evento.
|
||||
* @param idEvento ID del evento de salida al que pertenece el participante.
|
||||
* @param idParticipante ID del participante a consultar.
|
||||
* @return {@link ResponseEntity} con los datos del participante encontrado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("{idParticipante}/get")
|
||||
public ResponseEntity<ParticipanteResponseDto> get(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante) {
|
||||
try {
|
||||
return ResponseEntity.ok(participanteService.get(idResidencia, idEvento, idParticipante));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene una lista de todos los participantes de un evento de salida, con opciones de filtrado.
|
||||
*
|
||||
* @param idResidencia ID de la residencia donde se encuentra el evento.
|
||||
* @param idEvento ID del evento de salida del que se obtienen los participantes.
|
||||
* @param idResidente ID del residente (opcional) para filtrar por residente específico.
|
||||
* @param rM Recurso material (opcional) para filtrar por recurso material.
|
||||
* @param rH Recurso humano (opcional) para filtrar por recurso humano.
|
||||
* @param minEdad Edad mínima del participante (opcional).
|
||||
* @param maxEdad Edad máxima del participante (opcional).
|
||||
* @param preOpinion Filtra por participantes con opinión previa (opcional).
|
||||
* @param postOpinion Filtra por participantes con opinión posterior (opcional).
|
||||
* @param asistenciPermitida Filtra por participantes con asistencia permitida (opcional).
|
||||
* @return {@link ResponseEntity} con la lista de participantes encontrados.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/getAll")
|
||||
public ResponseEntity<List<ParticipanteResponseDto>> getAllParticipantes(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEvento,
|
||||
@RequestParam(required = false) Long idResidente,
|
||||
@RequestParam(required = false) Boolean rM,
|
||||
@RequestParam(required = false) Boolean rH,
|
||||
@RequestParam(required = false) Integer minEdad,
|
||||
@RequestParam(required = false) Integer maxEdad,
|
||||
@RequestParam(required = false) Boolean preOpinion,
|
||||
@RequestParam(required = false) Boolean postOpinion,
|
||||
@RequestParam(required = false) Boolean asistenciPermitida) {
|
||||
try {
|
||||
List<ParticipanteResponseDto> result = participanteService.getAll(
|
||||
idResidencia, idEvento, idResidente, rM, rH, minEdad, maxEdad, preOpinion, postOpinion, asistenciPermitida
|
||||
);
|
||||
return ResponseEntity.ok(result);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Elimina un participante de un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante a eliminar.
|
||||
* @param idResidencia ID de la residencia donde se encuentra el evento.
|
||||
* @param idEvento ID del evento de salida del que se elimina el participante.
|
||||
* @return {@link ResponseEntity} con el estado de la operación.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@DeleteMapping("/{idParticipante}/delete")
|
||||
public ResponseEntity<Void> deleteParticipante(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante) {
|
||||
try {
|
||||
participanteService.deleteParticipante(idResidencia, idEvento, idParticipante);
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualiza los datos de un participante existente en un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante a actualizar.
|
||||
* @param idResidencia ID de la residencia donde se encuentra el evento.
|
||||
* @param idEvento ID del evento de salida al que pertenece el participante.
|
||||
* @param participanteDto DTO con los nuevos datos del participante.
|
||||
* @return {@link ResponseEntity} con el participante actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idParticipante}/update")
|
||||
public ResponseEntity<ParticipanteResponseDto> update(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante,
|
||||
@RequestBody ParticipanteDto participanteDto) {
|
||||
try {
|
||||
return ResponseEntity.ok(participanteService.update(participanteDto, idResidencia, idEvento, idParticipante));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Añade una opinión previa de un participante en un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante al que se le añade la opinión.
|
||||
* @param preOpinion Opinión previa del participante.
|
||||
* @return {@link ResponseEntity} con el participante actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idParticipante}/addPreOpinion")
|
||||
public ResponseEntity<ParticipanteResponseDto> addPreOpinion(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante,
|
||||
@RequestParam String preOpinion) {
|
||||
try {
|
||||
return ResponseEntity.ok(participanteService.addPreOpinion(idResidencia, idEvento, idParticipante, preOpinion));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Agrega una opinión posterior a la participación de un residente en un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante al que se le agregará la opinión.
|
||||
* @param idResidencia ID de la residencia donde se encuentra el evento.
|
||||
* @param idEvento ID del evento de salida al que pertenece el participante.
|
||||
* @param postOpinion Opinión posterior a la participación.
|
||||
* @return {@link ResponseEntity} con el participante actualizado.
|
||||
*/
|
||||
@PatchMapping("/{idParticipante}/addPostOpinion")
|
||||
public ResponseEntity<ParticipanteResponseDto> addPostOpinion(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante,
|
||||
@RequestParam String postOpinion) {
|
||||
try {
|
||||
return ResponseEntity.ok(participanteService.addPostOpinion(idResidencia, idEvento, idParticipante, postOpinion));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cambia los recursos asignados a un participante en un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante a actualizar.
|
||||
* @param idResidencia ID de la residencia donde se encuentra el evento.
|
||||
* @param idEvento ID del evento de salida al que pertenece el participante.
|
||||
* @param rH Recurso humano (opcional).
|
||||
* @param rM Recurso material (opcional).
|
||||
* @return {@link ResponseEntity} con el participante actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idParticipante}/changeRecursos")
|
||||
public ResponseEntity<ParticipanteResponseDto> changeRecursos(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante,
|
||||
@RequestParam(required = false) Boolean rH,
|
||||
@RequestParam(required = false) Boolean rM) {
|
||||
try {
|
||||
return ResponseEntity.ok(participanteService.changeRecursos(idResidencia, idEvento, idParticipante, rH, rM));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Acepta la participación un participante en un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante a aceptar.
|
||||
* @param idResidencia ID de la residencia donde se encuentra el evento.
|
||||
* @param idEvento ID del evento de salida al que pertenece el participante.
|
||||
* @return {@link ResponseEntity} con el participante aceptado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PostMapping("/{idParticipante}/allow")
|
||||
public ResponseEntity<ParticipanteResponseDto> allow(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante) {
|
||||
try {
|
||||
return ResponseEntity.ok(participanteService.allow(idResidencia, idEvento, idParticipante));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deniega la participación de un residente en un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante a denegar.
|
||||
* @param idResidencia ID de la residencia donde se encuentra el evento.
|
||||
* @param idEvento ID del evento de salida al que pertenece el participante.
|
||||
* @return {@link ResponseEntity} con el participante actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PostMapping("/{idParticipante}/deny")
|
||||
public ResponseEntity<ParticipanteResponseDto> deny(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante) {
|
||||
try {
|
||||
return ResponseEntity.ok(participanteService.deny(idResidencia, idEvento, idParticipante));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
package com.kevinolarte.resibenissa.controllers.moduloOrgSalida.participante;
|
||||
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.moduloOrgSalida.ParticipanteDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.moduloOrgSalida.ParticipanteResponseDto;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.EmailService;
|
||||
import com.kevinolarte.resibenissa.services.moduloOrgSalida.ParticipanteService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controlador REST para gestionar los participantes de un evento de salida en una residencia.
|
||||
* <p>
|
||||
* Permite agregar, consultar, actualizar, eliminar y listar participantes asociados
|
||||
* a un evento específico dentro de una residencia.
|
||||
* </p>
|
||||
* URL base: /resi/evento/{idEvento}/participante
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/resi/evento/{idEvento}/participante")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class ParticipanteController {
|
||||
|
||||
private final ParticipanteService participanteService;
|
||||
private final EmailService emailService;
|
||||
|
||||
/**
|
||||
* Registra un nuevo participante en un evento de salida.
|
||||
*
|
||||
* @param participanteDto DTO con los datos del participante a registrar.
|
||||
* @return {@link ResponseEntity} con el participante creado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public ResponseEntity<ParticipanteResponseDto> add(@PathVariable Long idEvento,
|
||||
@RequestBody ParticipanteDto participanteDto) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
ParticipanteResponseDto dto = participanteService.add(participanteDto, idEvento, currentUser.getResidencia().getId());
|
||||
emailService.sendNotificationParticipante(dto);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(dto);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene los datos de un participante específico en un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante a consultar.
|
||||
* @return {@link ResponseEntity} con los datos del participante encontrado.
|
||||
*/
|
||||
@GetMapping("{idParticipante}/get")
|
||||
public ResponseEntity<ParticipanteResponseDto> get(@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
|
||||
return ResponseEntity.ok(participanteService.get(currentUser.getResidencia().getId(), idEvento, idParticipante));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene todos los participantes de un evento de salida, con filtros opcionales.
|
||||
*
|
||||
* @param idEvento ID del evento del que se obtienen los participantes.
|
||||
* @param idResidente ID del residente (opcional).
|
||||
* @param rM Recurso material (opcional).
|
||||
* @param rH Recurso humano (opcional).
|
||||
* @param minEdad Edad mínima del participante (opcional).
|
||||
* @param maxEdad Edad máxima del participante (opcional).
|
||||
* @param preOpinion Si se filtran por opinión previa (opcional).
|
||||
* @param postOpinion Si se filtran por opinión posterior (opcional).
|
||||
* @param asistenciPermitida Si se filtran por asistencia permitida (opcional).
|
||||
* @return {@link ResponseEntity} con la lista de participantes filtrados.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/getAll")
|
||||
public ResponseEntity<List<ParticipanteResponseDto>> getAllParticipantes(
|
||||
@PathVariable Long idEvento,
|
||||
@RequestParam(required = false) Long idResidente,
|
||||
@RequestParam(required = false) Boolean rM,
|
||||
@RequestParam(required = false) Boolean rH,
|
||||
@RequestParam(required = false) Integer minEdad,
|
||||
@RequestParam(required = false) Integer maxEdad,
|
||||
@RequestParam(required = false) Boolean preOpinion,
|
||||
@RequestParam(required = false) Boolean postOpinion,
|
||||
@RequestParam(required = false) Boolean asistenciPermitida) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
return ResponseEntity.ok(participanteService.getAll(currentUser.getResidencia().getId(), idEvento, idResidente, rM, rH, minEdad, maxEdad, preOpinion, postOpinion, asistenciPermitida));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Elimina un participante de un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante a eliminar.
|
||||
* @return {@link ResponseEntity} sin contenido si la eliminación fue exitosa.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@DeleteMapping("/{idParticipante}/delete")
|
||||
public ResponseEntity<Void> deleteParticipante(@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
participanteService.deleteParticipante(currentUser.getResidencia().getId(), idEvento, idParticipante);
|
||||
return ResponseEntity.noContent().build();
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Añade una opinión previa de un participante en un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante al que se le añade la opinión.
|
||||
* @param preOpinion Opinión previa del participante.
|
||||
* @return {@link ResponseEntity} con el participante actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idParticipante}/addPreOpinion")
|
||||
public ResponseEntity<ParticipanteResponseDto> addPreOpinion(@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante,
|
||||
@RequestParam String preOpinion) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
|
||||
return ResponseEntity.ok(participanteService.addPreOpinion(currentUser.getResidencia().getId(), idEvento, idParticipante, preOpinion));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Agrega una opinión posterior a la participación de un residente en un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante al que se le agregará la opinión.
|
||||
* @param postOpinion Opinión posterior a la participación.
|
||||
* @return {@link ResponseEntity} con el participante actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idParticipante}/addPostOpinion")
|
||||
public ResponseEntity<ParticipanteResponseDto> addPostOpinion(@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante,
|
||||
@RequestParam String postOpinion) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
|
||||
return ResponseEntity.ok(participanteService.addPostOpinion(currentUser.getResidencia().getId(), idEvento, idParticipante, postOpinion));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cambia los recursos asignados a un participante en un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante a actualizar.
|
||||
* @param rH Recurso humano (opcional).
|
||||
* @param rM Recurso material (opcional).
|
||||
* @return {@link ResponseEntity} con el participante actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idParticipante}/changeRecursos")
|
||||
public ResponseEntity<ParticipanteResponseDto> changeRecursos(@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante,
|
||||
@RequestParam(required = false) Boolean rH,
|
||||
@RequestParam(required = false) Boolean rM) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
|
||||
return ResponseEntity.ok(participanteService.changeRecursos(currentUser.getResidencia().getId(), idEvento, idParticipante, rH, rM));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Acepta la participación un participante en un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante a aceptar.
|
||||
* @return {@link ResponseEntity} con el participante aceptado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PostMapping("/{idParticipante}/allow")
|
||||
public ResponseEntity<ParticipanteResponseDto> allow(@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
return ResponseEntity.ok(participanteService.allow(currentUser.getResidencia().getId(), idEvento, idParticipante));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deniega la participación de un residente en un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante a denegar.
|
||||
* @return {@link ResponseEntity} con el participante actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PostMapping("/{idParticipante}/deny")
|
||||
public ResponseEntity<ParticipanteResponseDto> deny(@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
|
||||
return ResponseEntity.ok(participanteService.deny(currentUser.getResidencia().getId(), idEvento, idParticipante));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualiza los datos de un participante existente en un evento de salida.
|
||||
*
|
||||
* @param idParticipante ID del participante a actualizar.
|
||||
* @param participanteDto DTO con los nuevos datos del participante.
|
||||
* @return {@link ResponseEntity} con el participante actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idParticipante}/update")
|
||||
public ResponseEntity<ParticipanteResponseDto> update(@PathVariable Long idEvento,
|
||||
@PathVariable Long idParticipante,
|
||||
@RequestBody ParticipanteDto participanteDto) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
|
||||
return ResponseEntity.ok(participanteService.update(participanteDto, currentUser.getResidencia().getId(), idEvento, idParticipante));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
package com.kevinolarte.resibenissa.controllers.moduloWallet;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.modeloWallet.MovimientoRequestDTO;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.moduloWallet.WalletService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/admin/resi/{idResidencia}/resi/{idResidente}/wallet")
|
||||
@AllArgsConstructor
|
||||
public class WalletAdminController {
|
||||
|
||||
private final WalletService walletService;
|
||||
|
||||
@GetMapping("/informe")
|
||||
public ResponseEntity<byte[]> getInforme(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idResidente) {
|
||||
|
||||
try{
|
||||
byte[] pdf = walletService.getInforme(idResidencia, idResidente);
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=informe_wallet_" + idResidente + ".pdf")
|
||||
.contentType(MediaType.APPLICATION_PDF)
|
||||
.body(pdf);
|
||||
}catch (ResiException e){
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
@PostMapping("/deposit")
|
||||
public ResponseEntity<String> deposit(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idResidente,
|
||||
@RequestBody MovimientoRequestDTO input) {
|
||||
|
||||
try {
|
||||
walletService.deposit(idResidencia, idResidente, input);
|
||||
return ResponseEntity.ok("Deposit successful");
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/retire")
|
||||
public ResponseEntity<String> retire(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idResidente,
|
||||
@RequestBody MovimientoRequestDTO input) {
|
||||
|
||||
|
||||
try {
|
||||
walletService.retire(idResidencia, idResidente, input);
|
||||
return ResponseEntity.ok("Retire successful");
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/getSaldo")
|
||||
public ResponseEntity<Double> getSaldo(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idResidente) {
|
||||
|
||||
try {
|
||||
Double saldo = walletService.getSaldo(idResidencia, idResidente);
|
||||
return ResponseEntity.ok(saldo);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
package com.kevinolarte.resibenissa.controllers.moduloWallet;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.modeloWallet.MovimientoRequestDTO;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.moduloWallet.WalletService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
@RequestMapping("/resi/resident/{idResidente}/wallet")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class WalletController {
|
||||
private final WalletService walletService;
|
||||
|
||||
@GetMapping("/informe")
|
||||
public ResponseEntity<byte[]> getInforme(
|
||||
@PathVariable Long idResidente) {
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
|
||||
try{
|
||||
byte[] pdf = walletService.getInforme(currentUser.getResidencia().getId(), idResidente);
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=informe_wallet_" + currentUser.getId() + ".pdf")
|
||||
.contentType(MediaType.APPLICATION_PDF)
|
||||
.body(pdf);
|
||||
}catch (ResiException e){
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/deposit")
|
||||
public ResponseEntity<String> deposit(
|
||||
@PathVariable Long idResidente,
|
||||
@RequestBody MovimientoRequestDTO input) {
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
try {
|
||||
walletService.deposit(currentUser.getResidencia().getId(), idResidente, input);
|
||||
return ResponseEntity.ok("Deposit successful");
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/retire")
|
||||
public ResponseEntity<String> retire(
|
||||
@PathVariable Long idResidente,
|
||||
@RequestBody MovimientoRequestDTO input) {
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
try {
|
||||
walletService.retire(currentUser.getResidencia().getId(), idResidente, input);
|
||||
return ResponseEntity.ok("Retire successful");
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/getSaldo")
|
||||
public ResponseEntity<Double> getSaldo(
|
||||
@PathVariable Long idResidente) {
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
try {
|
||||
Double saldo = walletService.getSaldo(currentUser.getResidencia().getId(), idResidente);
|
||||
return ResponseEntity.ok(saldo);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
package com.kevinolarte.resibenissa.controllers.modulojuego.juego;
|
||||
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.modulojuego.JuegoDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.modulojuego.JuegoResponseDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.Dificultad;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.TipoAgrupacion;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.repositories.modulojuego.RegistroJuegoRepository;
|
||||
import com.kevinolarte.resibenissa.services.modulojuego.JuegoService;
|
||||
import com.kevinolarte.resibenissa.services.modulojuego.RegistroJuegoService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controlador REST que gestiona las operaciones relacionadas con los juegos en una residencia.
|
||||
* <p>
|
||||
* Permite registrar, consultar, listar, actualizar y eliminar juegos asociados a una residencia.
|
||||
* </p>
|
||||
*
|
||||
* Ruta base: <b>/admin/resi/juego</b>
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/admin/resi/juego")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class JuegoAdminController {
|
||||
private final JuegoService juegoService;
|
||||
private final RegistroJuegoRepository registroJuegoRepository;
|
||||
private final RegistroJuegoService registroJuegoService;
|
||||
|
||||
/**
|
||||
* Registra un nuevo juego asociado a una residencia.
|
||||
*
|
||||
* @param juegoDto Datos del juego a registrar.
|
||||
* @return {@link ResponseEntity} con los datos del juego creado y estado 201 CREATED.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public ResponseEntity<JuegoResponseDto> add(@RequestBody JuegoDto juegoDto) {
|
||||
try {
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(juegoService.save(juegoDto));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene los datos de un juego específico en una residencia.
|
||||
* @param idJuego ID del juego a consultar.
|
||||
* @return {@link ResponseEntity} con los datos del juego solicitado y estado 200 OK.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/{idJuego}/get")
|
||||
public ResponseEntity<JuegoResponseDto> get(@PathVariable Long idJuego) {
|
||||
try {
|
||||
return ResponseEntity.ok(juegoService.get(idJuego));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de todos los juegos registrados en una residencia.
|
||||
*
|
||||
* @param nombreJuego Nombre del juego para filtrar (opcional).
|
||||
* @param maxRegistros Indica si se debe limitar la cantidad de registros devueltos (opcional).
|
||||
* @return {@link ResponseEntity} con la lista de juegos y estado 200 OK.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/getAll")
|
||||
public ResponseEntity<?> getAll(
|
||||
@RequestParam(required = false) String nombreJuego,
|
||||
@RequestParam(required = false) Boolean maxRegistros) {
|
||||
try {
|
||||
return ResponseEntity.ok(juegoService.getAll(nombreJuego, maxRegistros));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Elimina un juego de una residencia si no tiene referencias dependientes.
|
||||
*
|
||||
* @param idJuego ID del juego a eliminar.
|
||||
* @return {@link ResponseEntity} con estado 204 NO CONTENT si la eliminación es exitosa.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud o si el juego no puede ser eliminado.
|
||||
*/
|
||||
@DeleteMapping("/{idJuego}/delete")
|
||||
public ResponseEntity<Void> delete(@PathVariable Long idJuego) {
|
||||
try {
|
||||
juegoService.delete(idJuego);
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO),e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualiza los datos de un juego ya registrado en una residencia.
|
||||
*
|
||||
* @param idJuego ID del juego a actualizar.
|
||||
* @param juegoDto Datos nuevos del juego.
|
||||
* @return {@link ResponseEntity} con los datos del juego actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud o si el juego no puede ser actualizado.
|
||||
*/
|
||||
@PatchMapping("/{idJuego}/update")
|
||||
public ResponseEntity<JuegoResponseDto> update(
|
||||
@PathVariable Long idJuego,
|
||||
@RequestBody JuegoDto juegoDto) {
|
||||
try {
|
||||
return ResponseEntity.ok(juegoService.update(idJuego, juegoDto));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e,e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO),e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
package com.kevinolarte.resibenissa.controllers.modulojuego.juego;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.out.modulojuego.JuegoResponseDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.Dificultad;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.TipoAgrupacion;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.modulojuego.JuegoService;
|
||||
import com.kevinolarte.resibenissa.services.modulojuego.RegistroJuegoService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Controlador REST que gestiona las operaciones relacionadas con los juegos en una residencia.
|
||||
* <p>
|
||||
* Permite registrar, consultar, listar, actualizar y eliminar juegos asociados a una residencia.
|
||||
* </p>
|
||||
*
|
||||
* Ruta base: <b>/resi/juego</b>
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/resi/juego")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class JuegoController {
|
||||
private final JuegoService juegoService;
|
||||
private final RegistroJuegoService registroJuegoService;
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene los datos de un juego específico dentro de una residencia.
|
||||
*
|
||||
* @param idJuego ID del juego a consultar.
|
||||
* @return {@link ResponseEntity} con los datos del juego solicitado.
|
||||
* @throws ResiException si ocurre un error al obtener el juego.
|
||||
*/
|
||||
@GetMapping("/{idJuego}/get")
|
||||
public ResponseEntity<JuegoResponseDto> get(
|
||||
@PathVariable Long idJuego) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
JuegoResponseDto juego;
|
||||
try {
|
||||
juego = juegoService.get(idJuego);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(juego);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de juegos de una residencia, con filtros opcionales por nombre y cantidad máxima.
|
||||
*
|
||||
* @param nombreJuego Filtro por nombre del juego (opcional).
|
||||
* @param maxRegistros Si es {@code true}, limita los resultados a un número máximo (definido en servicio).
|
||||
* @return {@link ResponseEntity} con la lista de juegos.
|
||||
* @throws ApiException si ocurre un error al obtener los juegos.g
|
||||
*/
|
||||
@GetMapping("/getAll")
|
||||
public ResponseEntity<List<JuegoResponseDto>> getAll(
|
||||
@RequestParam(required = false) String nombreJuego,
|
||||
@RequestParam(required = false) Boolean maxRegistros) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
List<JuegoResponseDto> juegos;
|
||||
try {
|
||||
juegos = juegoService.getAll(nombreJuego, maxRegistros);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(juegos);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,352 @@
|
|||
package com.kevinolarte.resibenissa.controllers.modulojuego.registroJuego;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.modulojuego.RegistroJuegoDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO;
|
||||
import com.kevinolarte.resibenissa.dto.out.modulojuego.RegistroJuegoResponseDto;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.Dificultad;
|
||||
import com.kevinolarte.resibenissa.enums.Filtrado.RegistroJuegoFiltrado;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.TipoAgrupacion;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.modulojuego.RegistroJuegoService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.print.attribute.standard.Media;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controlador REST para gestionar los registros de juegos jugados por los residentes.
|
||||
* <p>
|
||||
* Permite agregar nuevos registros, consultar estadísticas con múltiples filtros,
|
||||
* actualizar observaciones y eliminar registros específicos.
|
||||
* </p>
|
||||
* <p>
|
||||
* URL base: <code>admin/resi</code>.
|
||||
* </p>
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/admin/resi")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class RegistroJuegoAdminController {
|
||||
|
||||
private final RegistroJuegoService registroJuegoService;
|
||||
|
||||
/**
|
||||
* Crea un nuevo registro de juego para un residente en una residencia y juego específicos.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idJuego ID del juego.
|
||||
* @param registroJuegoDto Datos del registro a guardar.
|
||||
* @return El registro de juego creado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PostMapping("{idResidencia}/registro/add")
|
||||
public ResponseEntity<RegistroJuegoResponseDto> add(
|
||||
@PathVariable Long idResidencia,
|
||||
@RequestParam Long idJuego,
|
||||
@RequestBody RegistroJuegoDto registroJuegoDto) {
|
||||
try {
|
||||
RegistroJuegoResponseDto registroJuego = registroJuegoService.add(idResidencia, idJuego, registroJuegoDto);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(registroJuego);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene un registro de juego específico mediante su ID.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idRegistroJuego ID del registro de juego.
|
||||
* @return El registro de juego solicitado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/{idResidencia}/registro/{idRegistroJuego}/get")
|
||||
public ResponseEntity<RegistroJuegoResponseDto> get(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idRegistroJuego) {
|
||||
try {
|
||||
return ResponseEntity.ok(registroJuegoService.get(idResidencia, idRegistroJuego));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de registros de juego filtrados por varios parámetros.
|
||||
* @param idJuego ID del juego.
|
||||
* @param dificultad Dificultad del juego (opcional).
|
||||
* @param edad Edad del residente (opcional).
|
||||
* @param minEdad Edad mínima del residente (opcional).
|
||||
* @param maxEdad Edad máxima del residente (opcional).
|
||||
* @param idResidente ID del residente (opcional).
|
||||
* @param fecha Fecha del registro (opcional).
|
||||
* @param minFecha Fecha mínima del registro (opcional).
|
||||
* @param maxFecha Fecha máxima del registro (opcional).
|
||||
* @param promedio true si se desea obtener el promedio de los registros, false en caso contrario.
|
||||
* @param masPromedio true si se desea obtener los registros con puntajes superiores al promedio, false en caso contrario.
|
||||
* @param menosPromedio true si se desea obtener los registros con puntajes inferiores al promedio, false en caso contrario.
|
||||
* @return Lista de registros de juego filtrados.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/registro/getAll")
|
||||
public ResponseEntity<List<RegistroJuegoResponseDto>> getAll(
|
||||
@RequestParam(required = false) Long idJuego,
|
||||
@RequestParam(required = false) Dificultad dificultad,
|
||||
@RequestParam(required = false) Integer edad,
|
||||
@RequestParam(required = false) Integer minEdad,
|
||||
@RequestParam(required = false) Integer maxEdad,
|
||||
@RequestParam(required = false) Long idResidente,
|
||||
@RequestParam(required = false) LocalDate fecha,
|
||||
@RequestParam(required = false) LocalDate minFecha,
|
||||
@RequestParam(required = false) LocalDate maxFecha,
|
||||
@RequestParam(required = false) boolean promedio,
|
||||
@RequestParam(required = false) boolean masPromedio,
|
||||
@RequestParam(required = false) boolean menosPromedio,
|
||||
@RequestParam(required = false) RegistroJuegoFiltrado filtrado,
|
||||
@RequestParam(required = false) Boolean comentado) {
|
||||
try {
|
||||
return ResponseEntity.ok(registroJuegoService.getAll(
|
||||
idJuego, dificultad, edad, minEdad, maxEdad,
|
||||
idResidente, fecha, minFecha, maxFecha,
|
||||
promedio, masPromedio, menosPromedio,
|
||||
filtrado, comentado));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de registros de juego filtrados por varios parámetros de una residencia especifica
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idJuego ID del juego.
|
||||
* @param dificultad Dificultad del juego (opcional).
|
||||
* @param edad Edad del residente (opcional).
|
||||
* @param minEdad Edad mínima del residente (opcional).
|
||||
* @param maxEdad Edad máxima del residente (opcional).
|
||||
* @param idResidente ID del residente (opcional).
|
||||
* @param fecha Fecha del registro (opcional).
|
||||
* @param minFecha Fecha mínima del registro (opcional).
|
||||
* @param maxFecha Fecha máxima del registro (opcional).
|
||||
* @param promedio true si se desea obtener el promedio de los registros, false en caso contrario.
|
||||
* @param masPromedio true si se desea obtener los registros con puntajes superiores al promedio, false en caso contrario.
|
||||
* @param menosPromedio true si se desea obtener los registros con puntajes inferiores al promedio, false en caso contrario.
|
||||
* @return Lista de registros de juego filtrados.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/{idResidencia}/registro/getAll")
|
||||
public ResponseEntity<List<RegistroJuegoResponseDto>> getAll(
|
||||
@PathVariable Long idResidencia,
|
||||
@RequestParam(required = false) Long idJuego,
|
||||
@RequestParam(required = false) Dificultad dificultad,
|
||||
@RequestParam(required = false) Integer edad,
|
||||
@RequestParam(required = false) Integer minEdad,
|
||||
@RequestParam(required = false) Integer maxEdad,
|
||||
@RequestParam(required = false) Long idResidente,
|
||||
@RequestParam(required = false) LocalDate fecha,
|
||||
@RequestParam(required = false) LocalDate minFecha,
|
||||
@RequestParam(required = false) LocalDate maxFecha,
|
||||
@RequestParam(required = false) boolean promedio,
|
||||
@RequestParam(required = false) boolean masPromedio,
|
||||
@RequestParam(required = false) boolean menosPromedio,
|
||||
@RequestParam(required = false) RegistroJuegoFiltrado filtrado,
|
||||
@RequestParam(required = false) Boolean comentado) {
|
||||
try {
|
||||
return ResponseEntity.ok(registroJuegoService.getAll(
|
||||
idResidencia, idJuego, dificultad, edad, minEdad, maxEdad,
|
||||
idResidente, fecha, minFecha, maxFecha,
|
||||
promedio, masPromedio, menosPromedio,
|
||||
filtrado, comentado));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualiza un registro de juego existente añadiendo o modificando una observación.
|
||||
*
|
||||
* @param idResidencia ID de la residencia donde se encuentra el registro.
|
||||
* @param idRegistroJuego ID del registro a actualizar.
|
||||
* @param registroJuegoDto DTO con los nuevos datos (principalmente observación).
|
||||
* @return Registro de juego actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idResidencia}/registro/{idRegistroJuego}/addComment")
|
||||
public ResponseEntity<RegistroJuegoResponseDto> update(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idRegistroJuego,
|
||||
@RequestBody RegistroJuegoDto registroJuegoDto) {
|
||||
try {
|
||||
return ResponseEntity.ok(registroJuegoService.update(idResidencia, idRegistroJuego, registroJuegoDto));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Elimina un registro de juego específico.
|
||||
*
|
||||
* @param idResidencia ID de la residencia donde se encuentra el registro.
|
||||
* @param idRegistroJuego ID del registro a eliminar.
|
||||
* @return Respuesta sin contenido si la eliminación fue exitosa.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@DeleteMapping("/{idResidencia}/registro/{idRegistroJuego}/delete")
|
||||
public ResponseEntity<Void> delete(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idRegistroJuego) {
|
||||
try {
|
||||
registroJuegoService.delete(idResidencia, idRegistroJuego);
|
||||
return ResponseEntity.noContent().build();
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/{idResidencia}/registro/media-duracion")
|
||||
public ResponseEntity<List<MediaRegistroDTO>> getMediaDuracionPorResidencia(
|
||||
@PathVariable Long idResidencia,
|
||||
@RequestParam(required = false, defaultValue = "DIARIO") TipoAgrupacion tipo,
|
||||
@RequestParam(required = false) Dificultad dificultad,
|
||||
@RequestParam(required = false) Long idJuego) {
|
||||
|
||||
|
||||
try{
|
||||
List<MediaRegistroDTO> medias = registroJuegoService.getMediaDuracionPorResidencia(idResidencia, tipo, dificultad, idJuego);
|
||||
return ResponseEntity.ok(medias);
|
||||
}catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/{idResidencia}/registro/media-num")
|
||||
public ResponseEntity<List<MediaRegistroDTO>> getMediaErroresPorResidencia(
|
||||
@PathVariable Long idResidencia,
|
||||
@RequestParam(required = false, defaultValue = "DIARIO") TipoAgrupacion tipo,
|
||||
@RequestParam(required = false) Dificultad dificultad,
|
||||
@RequestParam(required = false) Long idJuego) {
|
||||
|
||||
|
||||
try {
|
||||
List<MediaRegistroDTO> medias = registroJuegoService.getMediaErroresPorResidencia(idResidencia, tipo, dificultad, idJuego);
|
||||
return ResponseEntity.ok(medias);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("{idResidencia}/registro/resident/{idResidente}/media-duracion")
|
||||
public ResponseEntity<List<MediaRegistroDTO>> getMediaDuracionPorResidente(@PathVariable Long idResidencia,
|
||||
@PathVariable Long idResidente,
|
||||
@RequestParam(required = false, defaultValue = "DIARIO") TipoAgrupacion tipo,
|
||||
@RequestParam(required = false) Dificultad dificultad,
|
||||
@RequestParam(required = false) Long idJuego) {
|
||||
try {
|
||||
List<MediaRegistroDTO> medias = registroJuegoService.getMediaDuracion(idResidencia, idResidente, tipo, dificultad, idJuego);
|
||||
return ResponseEntity.ok(medias);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("{idResidencia}/registro/resident/{idResidente}/media-num")
|
||||
public ResponseEntity<List<MediaRegistroDTO>> getMediaNumPorResidente(@PathVariable Long idResidencia,
|
||||
@PathVariable Long idResidente,
|
||||
@RequestParam(required = false, defaultValue = "DIARIO") TipoAgrupacion tipo,
|
||||
@RequestParam(required = false) Dificultad dificultad,
|
||||
@RequestParam(required = false) Long idJuego) {
|
||||
try {
|
||||
List<MediaRegistroDTO> medias = registroJuegoService.getMediaErrores(idResidencia, idResidente, tipo, dificultad, idJuego);
|
||||
return ResponseEntity.ok(medias);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint global que calcula el promedio de duración de los registros de juego
|
||||
* agrupados por día, mes o año, para todos los registros del sistema.
|
||||
*
|
||||
* <p>
|
||||
* Permite filtrar opcionalmente por:
|
||||
* <ul>
|
||||
* <li><b>Dificultad</b> del juego (FACIL, MEDIO, DIFICIL)</li>
|
||||
* <li><b>ID del juego</b> específico</li>
|
||||
* </ul>
|
||||
* Si no se proporciona ningún filtro, se devolverá la media de duración de todos los juegos y dificultades del sistema.
|
||||
* </p>
|
||||
*
|
||||
* @param tipo Tipo de agrupación temporal: DIARIO (por defecto), MENSUAL o ANUAL.
|
||||
* @param dificultad Nivel de dificultad del juego a filtrar (opcional).
|
||||
* @param idJuego ID del juego a filtrar (opcional).
|
||||
* @return Lista de {@link MediaRegistroDTO} que contienen el agrupamiento temporal (día, mes o año),
|
||||
* el promedio de duración y el número de registros correspondientes.
|
||||
*/
|
||||
@GetMapping("/registro/media-duracion")
|
||||
public ResponseEntity<List<MediaRegistroDTO>> getMediaDuracionPorResidencia(
|
||||
@RequestParam(required = false, defaultValue = "DIARIO") TipoAgrupacion tipo,
|
||||
@RequestParam(required = false) Dificultad dificultad,
|
||||
@RequestParam(required = false) Long idJuego) {
|
||||
|
||||
|
||||
try{
|
||||
List<MediaRegistroDTO> medias = registroJuegoService.getMediaDuracionGlobal(tipo, dificultad, idJuego);
|
||||
return ResponseEntity.ok(medias);
|
||||
}catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@GetMapping("/registro/media-num")
|
||||
public ResponseEntity<List<MediaRegistroDTO>> getMediaErroresPorResidencia(
|
||||
@RequestParam(required = false, defaultValue = "DIARIO") TipoAgrupacion tipo,
|
||||
@RequestParam(required = false) Dificultad dificultad,
|
||||
@RequestParam(required = false) Long idJuego) {
|
||||
|
||||
|
||||
try {
|
||||
List<MediaRegistroDTO> medias = registroJuegoService.getMediaErroresGlobal(tipo, dificultad, idJuego);
|
||||
return ResponseEntity.ok(medias);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
package com.kevinolarte.resibenissa.controllers.modulojuego.registroJuego;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.modulojuego.RegistroJuegoDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO;
|
||||
import com.kevinolarte.resibenissa.dto.out.modulojuego.RegistroJuegoResponseDto;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.Dificultad;
|
||||
import com.kevinolarte.resibenissa.enums.Filtrado.RegistroJuegoFiltrado;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.TipoAgrupacion;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.modulojuego.RegistroJuegoService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controlador REST para gestionar los registros de juegos jugados por los residentes.
|
||||
* <p>
|
||||
* Permite agregar nuevos registros, consultar estadísticas con múltiples filtros,
|
||||
* actualizar observaciones y eliminar registros específicos.
|
||||
* </p>
|
||||
* <p>
|
||||
* Todas las rutas expuestas están bajo el prefijo <code>/resi/registro</code>.
|
||||
* </p>
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/resi/registro")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class RegistroJuegoController {
|
||||
|
||||
private final RegistroJuegoService registroJuegoService;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Crea un nuevo registro de juego para un residente en una residencia y juego específicos.
|
||||
*
|
||||
* @param idJuego ID del juego.
|
||||
* @param registroJuegoDto Datos del registro a guardar.
|
||||
* @return El registro de juego creado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PostMapping("/juego/{idJuego}/add")
|
||||
public ResponseEntity<RegistroJuegoResponseDto> add(
|
||||
@PathVariable Long idJuego,
|
||||
@RequestBody RegistroJuegoDto registroJuegoDto) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
registroJuegoDto.setIdUsuario(currentUser.getId());
|
||||
RegistroJuegoResponseDto registroJuego = registroJuegoService.add(currentUser.getResidencia().getId(), idJuego, registroJuegoDto);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(registroJuego);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene un registro de juego específico mediante su ID.
|
||||
*
|
||||
*@param idRegistroJuego ID del registro de juego.
|
||||
* @return El registro de juego solicitado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/{idRegistroJuego}/get")
|
||||
public ResponseEntity<RegistroJuegoResponseDto> get(@PathVariable Long idRegistroJuego) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
return ResponseEntity.ok(registroJuegoService.get(currentUser.getResidencia().getId(), idRegistroJuego));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de registros de juego filtrados por varios parámetros.
|
||||
* @param idJuego ID del juego.
|
||||
* @param edad Edad del residente (opcional).
|
||||
* @param minEdad Edad mínima del residente (opcional).
|
||||
* @param maxEdad Edad máxima del residente (opcional).
|
||||
* @param idResidente ID del residente (opcional).
|
||||
* @param fecha Fecha del registro (opcional).
|
||||
* @param minFecha Fecha mínima del registro (opcional).
|
||||
* @param maxFecha Fecha máxima del registro (opcional).
|
||||
* @param promedio true si se desea obtener el promedio de los registros, false en caso contrario.
|
||||
* @param masPromedio true si se desea obtener los registros con puntajes superiores al promedio, false en caso contrario.
|
||||
* @param menosPromedio true si se desea obtener los registros con puntajes inferiores al promedio, false en caso contrario.
|
||||
* @param dificultad Dificultad del juego (opcional).
|
||||
* @return Lista de registros de juego filtrados.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@GetMapping("/getAll")
|
||||
public ResponseEntity<List<RegistroJuegoResponseDto>> getAll(
|
||||
@RequestParam(required = false) Long idJuego,
|
||||
@RequestParam(required = false) Long idResidente,
|
||||
@RequestParam(required = false) Integer edad,
|
||||
@RequestParam(required = false) Integer minEdad,
|
||||
@RequestParam(required = false) Integer maxEdad,
|
||||
@RequestParam(required = false) LocalDate fecha,
|
||||
@RequestParam(required = false) LocalDate minFecha,
|
||||
@RequestParam(required = false) LocalDate maxFecha,
|
||||
@RequestParam(required = false) boolean promedio,
|
||||
@RequestParam(required = false) boolean masPromedio,
|
||||
@RequestParam(required = false) boolean menosPromedio,
|
||||
@RequestParam(required = false) RegistroJuegoFiltrado filtrado,
|
||||
@RequestParam(required = false) Dificultad dificultad,
|
||||
@RequestParam(required = false) Boolean comentado) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
return ResponseEntity.ok(
|
||||
registroJuegoService.getAll(
|
||||
currentUser.getResidencia().getId(),
|
||||
idJuego, dificultad, edad, minEdad, maxEdad,
|
||||
idResidente, fecha, minFecha, maxFecha,
|
||||
promedio, masPromedio, menosPromedio, filtrado, comentado
|
||||
)
|
||||
);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Actualiza un registro de juego existente añadiendo o modificando una observación.
|
||||
*
|
||||
* @param idRegistroJuego ID del registro a actualizar.
|
||||
* @param registroJuegoDto DTO con los nuevos datos (principalmente observación).
|
||||
* @return Registro de juego actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PatchMapping("/{idRegistroJuego}/addComment")
|
||||
public ResponseEntity<RegistroJuegoResponseDto> update(
|
||||
@PathVariable Long idRegistroJuego,
|
||||
@RequestBody RegistroJuegoDto registroJuegoDto) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
return ResponseEntity.ok(registroJuegoService.update(currentUser.getResidencia().getId(), idRegistroJuego, registroJuegoDto));
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Elimina un registro de juego específico.
|
||||
*
|
||||
* @param idRegistroJuego ID del registro a eliminar.
|
||||
* @return Respuesta sin contenido si la eliminación fue exitosa.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@DeleteMapping("/{idRegistroJuego}/delete")
|
||||
public ResponseEntity<Void> delete(@PathVariable Long idRegistroJuego) {
|
||||
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
try {
|
||||
registroJuegoService.delete(currentUser.getResidencia().getId(), idRegistroJuego);
|
||||
return ResponseEntity.noContent().build();
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/media-duracion")
|
||||
public ResponseEntity<List<MediaRegistroDTO>> getMediaDuracionPorResidencia(
|
||||
@RequestParam(required = false, defaultValue = "DIARIO") TipoAgrupacion tipo,
|
||||
@RequestParam(required = false) Dificultad dificultad,
|
||||
@RequestParam(required = false) Long idJuego) {
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
|
||||
try{
|
||||
List<MediaRegistroDTO> medias = registroJuegoService.getMediaDuracionPorResidencia(currentUser.getResidencia().getId(), tipo, dificultad, idJuego);
|
||||
return ResponseEntity.ok(medias);
|
||||
}catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/media-num")
|
||||
public ResponseEntity<List<MediaRegistroDTO>> getMediaErroresPorResidencia(
|
||||
@RequestParam(required = false, defaultValue = "DIARIO") TipoAgrupacion tipo,
|
||||
@RequestParam(required = false) Dificultad dificultad,
|
||||
@RequestParam(required = false) Long idJuego) {
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
|
||||
try {
|
||||
List<MediaRegistroDTO> medias = registroJuegoService.getMediaErroresPorResidencia(currentUser.getResidencia().getId(), tipo, dificultad, idJuego);
|
||||
return ResponseEntity.ok(medias);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/resident/{idResidente}/media-duracion")
|
||||
public ResponseEntity<List<MediaRegistroDTO>> getMediaDuracion(
|
||||
@PathVariable Long idResidente,
|
||||
@RequestParam(required = false, defaultValue = "DIARIO") TipoAgrupacion tipo,
|
||||
@RequestParam(required = false) Dificultad dificultad,
|
||||
@RequestParam(required = false) Long idJuego) {
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
|
||||
List<MediaRegistroDTO> medias;
|
||||
try {
|
||||
medias = registroJuegoService.getMediaDuracion(currentUser.getResidencia().getId(), idResidente, tipo, dificultad, idJuego);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(medias);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
package com.kevinolarte.resibenissa.controllers.residencia;
|
||||
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.ResidenciaDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.ResidenciaPublicResponseDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.ResidenciaResponseDto;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
import com.kevinolarte.resibenissa.services.ResidenciaService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controlador que expone endpoints REST para gestionar entidades {@link Residencia}.
|
||||
* <p>
|
||||
* Permite crear nuevas residencias, obtenerlas por ID y eliminarlas.
|
||||
* </p>
|
||||
*
|
||||
* URL Base: {@code /admin/resi}
|
||||
*
|
||||
* Autor: Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/admin/resi/")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class ResidenciaAdminController {
|
||||
|
||||
private final ResidenciaService residenciaService;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Crea una nueva residencia.
|
||||
*
|
||||
* @param residenciaDto DTO con los datos de la residencia a crear.
|
||||
* @return {@link ResponseEntity} con estado {@code 201 Created} y el DTO de la residencia creada.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud.
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public ResponseEntity<ResidenciaResponseDto> add(
|
||||
@RequestBody ResidenciaDto residenciaDto) {
|
||||
ResidenciaResponseDto residencia;
|
||||
try {
|
||||
residencia = residenciaService.add(residenciaDto);
|
||||
} catch (ResiException e) {
|
||||
// Manejo de excepciones específicas de la aplicación
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
// Manejo de excepciones genéricas
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(residencia);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una residencia por su ID.
|
||||
*
|
||||
* @param idResidencia ID de la residencia a recuperar.
|
||||
* @return {@link ResponseEntity} con estado {@code 200 OK} y el DTO de la residencia encontrada.
|
||||
*/
|
||||
@GetMapping("/{idResidencia}/get")
|
||||
public ResponseEntity<ResidenciaResponseDto> get(
|
||||
@PathVariable Long idResidencia) {
|
||||
ResidenciaResponseDto residencia;
|
||||
try {
|
||||
residencia = residenciaService.get(idResidencia);
|
||||
} catch (ResiException e) {
|
||||
// Manejo de excepciones específicas de la aplicación
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
// Manejo de excepciones genéricas
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residencia);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene todas las residencias.
|
||||
*
|
||||
* @return {@link ResponseEntity} con estado {@code 200 OK} y una lista de DTOs de residencias.
|
||||
* @throws ApiException si ocurre un error al intentar obtener las residencias.
|
||||
*/
|
||||
@GetMapping("/getAll")
|
||||
public ResponseEntity<List<ResidenciaPublicResponseDto>> getAll() {
|
||||
List<ResidenciaPublicResponseDto> residencias;
|
||||
try {
|
||||
residencias = residenciaService.getAll();
|
||||
} catch (Exception e) {
|
||||
// Manejo de excepciones genéricas
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residencias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene todos los que estan de baja
|
||||
* @return {@link ResponseEntity} con estado {@code 200 OK} y una lista de DTOs de residencias.
|
||||
* @throws ApiException si ocurre un error al intentar obtener las residencias.
|
||||
*/
|
||||
@GetMapping("/getAll/baja")
|
||||
public ResponseEntity<List<ResidenciaPublicResponseDto>> getAllBaja() {
|
||||
List<ResidenciaPublicResponseDto> residencias;
|
||||
try {
|
||||
residencias = residenciaService.getAllBaja();
|
||||
} catch (Exception e) {
|
||||
// Manejo de excepciones genéricas
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residencias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Elimina una residencia por su ID.
|
||||
*
|
||||
* @return {@link ResponseEntity} con estado {@code 204 No Content} si la eliminación fue exitosa.
|
||||
* @param idResidencia ID de la residencia a eliminar.
|
||||
* @throws ApiException si ocurre un error al intentar eliminar la residencia.
|
||||
*/
|
||||
@DeleteMapping("/{idResidencia}/delete")
|
||||
public ResponseEntity<Void> remove(
|
||||
@PathVariable Long idResidencia) {
|
||||
try {
|
||||
residenciaService.deleteFisico(idResidencia);
|
||||
}catch (ResiException e) {
|
||||
// Manejo de excepciones específicas de la aplicación
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
// Manejo de excepciones genéricas
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Elimina una residencia de forma lógica. Dandolo de baja.
|
||||
*
|
||||
* @return {@link ResponseEntity} con estado {@code 204 No Content} si la eliminación fue exitosa.
|
||||
* @param idResidencia ID de la residencia a dar de baja.
|
||||
* @throws ApiException si ocurre un error al intentar eliminar la residencia.
|
||||
*/
|
||||
@PatchMapping("/{idResidencia}/baja")
|
||||
public ResponseEntity<Void> baja(
|
||||
@PathVariable Long idResidencia) {
|
||||
try {
|
||||
residenciaService.deleteLogico(idResidencia);
|
||||
}catch (ResiException e) {
|
||||
// Manejo de excepciones específicas de la aplicación
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
// Manejo de excepciones genéricas
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
package com.kevinolarte.resibenissa.controllers.residencia;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.ResidenciaDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.ResidenciaPublicResponseDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.ResidenciaResponseDto;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.ResidenciaService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controlador que expone endpoints REST para gestionar entidades {@link Residencia}.
|
||||
* <p>
|
||||
* Permite crear nuevas residencias, obtenerlas por ID y eliminarlas.
|
||||
* </p>
|
||||
*
|
||||
* URL Base: {@code /resi}
|
||||
*
|
||||
* Autor: Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/resi")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class ResidenciaController {
|
||||
|
||||
private final ResidenciaService residenciaService;
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene una residencia por su ID.
|
||||
*
|
||||
* @return {@link ResponseEntity} con estado {@code 200 OK} y el DTO de la residencia encontrada.
|
||||
* @throws ResiException si ocurre un error al obtener la residencia.
|
||||
*/
|
||||
@GetMapping("/get")
|
||||
public ResponseEntity<ResidenciaResponseDto> get() {
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
ResidenciaResponseDto residencia;
|
||||
try{
|
||||
residencia = residenciaService.get(currentUser.getResidencia().getId());
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residencia);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene todas las residencias.
|
||||
*
|
||||
* @return {@link ResponseEntity} con estado {@code 200 OK} y una lista de DTOs de residencias.
|
||||
* @throws ApiException si ocurre un error al obtener las residencias.
|
||||
*/
|
||||
@GetMapping("/getAll")
|
||||
public ResponseEntity<List<ResidenciaPublicResponseDto>> getAll() {
|
||||
List<ResidenciaPublicResponseDto> residencias;
|
||||
try{
|
||||
residencias = residenciaService.getAll();
|
||||
}catch (Exception e){
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residencias);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,315 @@
|
|||
package com.kevinolarte.resibenissa.controllers.residente;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.ResidenteDto;
|
||||
import com.kevinolarte.resibenissa.dto.in.moduloReporting.EmailRequestDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.ResidenteResponseDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO;
|
||||
import com.kevinolarte.resibenissa.enums.Filtrado.ResidenteFiltrado;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.Dificultad;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.TipoAgrupacion;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.ResidenteService;
|
||||
import com.kevinolarte.resibenissa.services.modulojuego.RegistroJuegoService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controlador REST para la administración de residentes dentro de una residencia.
|
||||
* <p>
|
||||
* Permite registrar, consultar, actualizar, eliminar y listar residentes
|
||||
* aplicando filtros opcionales, tanto a nivel de una residencia específica como global.
|
||||
* </p>
|
||||
*
|
||||
* URL base: {@code /admin/resi}
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/admin/resi/")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class ResidenteAdminController {
|
||||
private final ResidenteService residenteService;
|
||||
private final RegistroJuegoService registroJuegoService;
|
||||
|
||||
|
||||
/**
|
||||
* Registra un nuevo residente dentro de una residencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param residenteDto DTO con los datos del residente a crear.
|
||||
* @return {@link ResponseEntity} con estado {@code 201 Created} y el residente creado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud, como campos obligatorios faltantes
|
||||
*/
|
||||
@PostMapping("/{idResidencia}/resident/add")
|
||||
public ResponseEntity<ResidenteResponseDto> add(
|
||||
@PathVariable Long idResidencia,
|
||||
@RequestBody ResidenteDto residenteDto){
|
||||
ResidenteResponseDto residenteResponseDto;
|
||||
try{
|
||||
residenteResponseDto = residenteService.add(idResidencia, residenteDto);
|
||||
}catch (ResiException e){
|
||||
throw new ApiException(e, e.getMessage());
|
||||
}catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(residenteResponseDto);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene los detalles de un residente específico dentro de una residencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idResidente ID del residente.
|
||||
* @return {@link ResponseEntity} con estado {@code 200 OK} y los datos del residente.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud, como campos obligatorios faltantes
|
||||
*/
|
||||
@GetMapping("/{idResidencia}/resident/{idResidente}/get")
|
||||
public ResponseEntity<ResidenteResponseDto> get(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idResidente) {
|
||||
|
||||
ResidenteResponseDto residenteResponseDto;
|
||||
try {
|
||||
residenteResponseDto = residenteService.get(idResidencia, idResidente);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residenteResponseDto);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Lista todos los residentes de una residencia, aplicando filtros opcionales.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param fechaNacimiento Fecha exacta de nacimiento.
|
||||
* @param minFNac Fecha mínima de nacimiento.
|
||||
* @param maxFNac Fecha máxima de nacimiento.
|
||||
* @param maxAge Edad máxima.
|
||||
* @param minAge Edad mínima.
|
||||
* @param idJuego ID de juego asociado (opcional).
|
||||
* @param idEvento ID de evento asociado (opcional).
|
||||
* @return {@link ResponseEntity} con la lista de residentes filtrados.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud, como campos obligatorios faltantes
|
||||
*/
|
||||
@GetMapping("/{idResidencia}/resident/getAll")
|
||||
public ResponseEntity<List<ResidenteResponseDto>> getAll(
|
||||
@PathVariable Long idResidencia,
|
||||
@RequestParam(required = false) LocalDate fechaNacimiento,
|
||||
@RequestParam(required = false) LocalDate minFNac,
|
||||
@RequestParam(required = false) LocalDate maxFNac,
|
||||
@RequestParam(required = false) Integer maxAge,
|
||||
@RequestParam(required = false) Integer minAge,
|
||||
@RequestParam(required = false) Long idJuego,
|
||||
@RequestParam(required = false) Long idEvento,
|
||||
@RequestParam(required = false)ResidenteFiltrado filtrado) {
|
||||
|
||||
List<ResidenteResponseDto> residentes;
|
||||
try {
|
||||
residentes = residenteService.getAll(idResidencia, fechaNacimiento, minFNac, maxFNac, maxAge, minAge, idJuego, idEvento, filtrado);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residentes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lista todos los residentes en el sistema, sin filtrar por residencia.
|
||||
*
|
||||
* @param fechaNacimiento Fecha exacta de nacimiento.
|
||||
* @param minFNac Fecha mínima de nacimiento.
|
||||
* @param maxFNac Fecha máxima de nacimiento.
|
||||
* @param maxAge Edad máxima.
|
||||
* @param minAge Edad mínima.
|
||||
* @param idJuego ID de juego asociado (opcional).
|
||||
* @param idEvento ID de evento asociado (opcional).
|
||||
* @return {@link ResponseEntity} con la lista global de residentes filtrados.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud, como campos obligatorios faltantes
|
||||
*/
|
||||
@GetMapping("/resident/getAll")
|
||||
public ResponseEntity<List<ResidenteResponseDto>> getAll(
|
||||
@RequestParam(required = false) LocalDate fechaNacimiento,
|
||||
@RequestParam(required = false) LocalDate minFNac,
|
||||
@RequestParam(required = false) LocalDate maxFNac,
|
||||
@RequestParam(required = false) Integer maxAge,
|
||||
@RequestParam(required = false) Integer minAge,
|
||||
@RequestParam(required = false) Long idJuego,
|
||||
@RequestParam(required = false) Long idEvento,
|
||||
@RequestParam(required = false) ResidenteFiltrado filtrado) {
|
||||
List<ResidenteResponseDto> residentes;
|
||||
try {
|
||||
residentes = residenteService.getAll(fechaNacimiento, minFNac, maxFNac, maxAge, minAge, idJuego, idEvento, filtrado);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residentes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lista todos los residentes dados de baja dentro de una residencia, filtrando opcionalmente por fecha.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param fecha Fecha exacta de baja (opcional).
|
||||
* @param minFecha Fecha mínima de baja (opcional).
|
||||
* @param maxFecha Fecha máxima de baja (opcional).
|
||||
* @return {@link ResponseEntity} con la lista de residentes dados de baja.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud, como campos obligatorios faltantes
|
||||
*/
|
||||
@GetMapping("/{idResidencia}/resident/getAll/bajas")
|
||||
public ResponseEntity<List<ResidenteResponseDto>> getAllBajas(
|
||||
@PathVariable Long idResidencia,
|
||||
@RequestParam(required = false) LocalDate fecha,
|
||||
@RequestParam(required = false) LocalDate minFecha,
|
||||
@RequestParam(required = false) LocalDate maxFecha){
|
||||
List<ResidenteResponseDto> residentes;
|
||||
try{
|
||||
residentes = residenteService.getAllBajas(idResidencia, fecha, minFecha, maxFecha);
|
||||
}catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residentes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lista todos los residentes dados de baja del sistema (sin filtro de residencia).
|
||||
*
|
||||
* @param fecha Fecha exacta de baja (opcional).
|
||||
* @param minFecha Fecha mínima de baja (opcional).
|
||||
* @param maxFecha Fecha máxima de baja (opcional).
|
||||
* @return {@link ResponseEntity} con la lista global de residentes dados de baja.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud, como campos obligatorios faltantes
|
||||
*/
|
||||
@GetMapping("/resident/getAll/bajas")
|
||||
public ResponseEntity<List<ResidenteResponseDto>> getAllBajas(
|
||||
@RequestParam(required = false) LocalDate fecha,
|
||||
@RequestParam(required = false) LocalDate minFecha,
|
||||
@RequestParam(required = false) LocalDate maxFecha){
|
||||
List<ResidenteResponseDto> residentes;
|
||||
try {
|
||||
residentes = residenteService.getAllBajas(fecha, minFecha, maxFecha);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residentes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Elimina físicamente un residente de una residencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idResidente ID del residente.
|
||||
* @return {@link ResponseEntity} con estado {@code 204 No Content} si la eliminación fue exitosa.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud, como campos obligatorios faltantes
|
||||
*/
|
||||
@DeleteMapping("/{idResidencia}/resident/{idResidente}/delete")
|
||||
public ResponseEntity<Void> delete(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idResidente) {
|
||||
|
||||
try{
|
||||
residenteService.deleteFisico(idResidencia,idResidente);
|
||||
}catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Marca lógicamente como dado de baja a un residente (sin eliminarlo físicamente).
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idResidente ID del residente.
|
||||
* @return {@link ResponseEntity} con estado {@code 204 No Content} si se realizó correctamente.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud, como campos obligatorios faltantes
|
||||
*/
|
||||
@PatchMapping("{idResidencia}/resident/{idResidente}/baja")
|
||||
public ResponseEntity<Void> deleteLogico(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idResidente) {
|
||||
try{
|
||||
residenteService.deleteLogico(idResidencia,idResidente);
|
||||
|
||||
}catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualiza parcialmente los datos de un residente dentro de una residencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idResidente ID del residente a actualizar.
|
||||
* @param residenteDto DTO con los datos a actualizar.
|
||||
* @return {@link ResponseEntity} con estado {@code 200 OK} y el residente actualizado.
|
||||
* @throws ApiException si ocurre un error al procesar la solicitud, como campos obligatorios faltantes
|
||||
*/
|
||||
@PatchMapping("{idResidencia}/resident/{idResidente}/update")
|
||||
public ResponseEntity<ResidenteResponseDto> update(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idResidente,
|
||||
@RequestBody ResidenteDto residenteDto) {
|
||||
ResidenteResponseDto residenteResponseDto;
|
||||
try {
|
||||
residenteResponseDto = residenteService.update(idResidencia, idResidente, residenteDto);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residenteResponseDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Envía un correo electrónico a un familiar de un residente.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idResidente ID del residente.
|
||||
* @param emailRequestDto DTO con los datos del correo a enviar.
|
||||
* @return {@link ResponseEntity} con estado {@code 204 No Content} si el envío fue exitoso.
|
||||
*/
|
||||
@PostMapping("/{idResidencia}/resident/{idResidente}/sendEmailFamily")
|
||||
public ResponseEntity<Void> sendEmailFamily(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idResidente,
|
||||
@RequestBody EmailRequestDto emailRequestDto) {
|
||||
try{
|
||||
residenteService.sendEmailFamiliar(idResidencia, idResidente, emailRequestDto);
|
||||
|
||||
}catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
package com.kevinolarte.resibenissa.controllers.residente;
|
||||
|
||||
import com.kevinolarte.resibenissa.config.Conf;
|
||||
import com.kevinolarte.resibenissa.dto.in.ResidenteDto;
|
||||
import com.kevinolarte.resibenissa.dto.in.moduloReporting.EmailRequestDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.ResidenteResponseDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO;
|
||||
import com.kevinolarte.resibenissa.enums.Filtrado.ResidenteFiltrado;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.Dificultad;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.TipoAgrupacion;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.ResidenteService;
|
||||
import com.kevinolarte.resibenissa.services.modulojuego.RegistroJuegoService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Controlador REST que gestiona las operaciones relacionadas con los residentes de una residencia.
|
||||
* <p>
|
||||
* Permite registrar, consultar, actualizar, listar y dar de baja residentes.
|
||||
* Todas las operaciones se contextualizan dentro de la residencia del usuario autenticado.
|
||||
* </p>
|
||||
*
|
||||
* URL base: {@code /resi/resident}
|
||||
*
|
||||
* Autor: Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/resi/resident")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class ResidenteController {
|
||||
|
||||
private final ResidenteService residenteService;
|
||||
private final RegistroJuegoService registroJuegoService;
|
||||
|
||||
|
||||
/**
|
||||
* Registra un nuevo residente en la residencia del usuario autenticado.
|
||||
*
|
||||
* @param residenteDto DTO con los datos del nuevo residente.
|
||||
* @return {@link ResponseEntity} con estado {@code 201 Created} y el residente creado.
|
||||
* @throws ApiException si ocurre un error durante el proceso de registro.
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public ResponseEntity<ResidenteResponseDto> add(
|
||||
@RequestBody ResidenteDto residenteDto){
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
|
||||
ResidenteResponseDto residenteResponseDto;
|
||||
try {
|
||||
residenteResponseDto = residenteService.add(currentUser.getResidencia().getId(), residenteDto);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(residenteResponseDto);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene los detalles de un residente específico perteneciente a la misma residencia que el usuario autenticado.
|
||||
*
|
||||
* @param idResidente ID del residente.
|
||||
* @return {@link ResponseEntity} con estado {@code 200 OK} y el residente encontrado.
|
||||
* @throws ApiException si ocurre un error al intentar obtener el residente.
|
||||
*/
|
||||
@GetMapping("/{idResidente}/get")
|
||||
public ResponseEntity<ResidenteResponseDto> get(
|
||||
@PathVariable Long idResidente) {
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
|
||||
ResidenteResponseDto residenteResponseDto;
|
||||
try {
|
||||
residenteResponseDto = residenteService.get(currentUser.getResidencia().getId(), idResidente);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residenteResponseDto);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lista todos los residentes de la residencia del usuario autenticado, con múltiples filtros opcionales.
|
||||
*
|
||||
* @param fechaNacimiento Fecha exacta de nacimiento.
|
||||
* @param minFNac Fecha mínima de nacimiento.
|
||||
* @param maxFNac Fecha máxima de nacimiento.
|
||||
* @param maxAge Edad máxima.
|
||||
* @param minAge Edad mínima.
|
||||
* @param idJuego ID de juego asociado (opcional).
|
||||
* @param idEvento ID de evento asociado (opcional).
|
||||
* @return {@link ResponseEntity} con la lista de residentes filtrados.
|
||||
* @throws ApiException si ocurre un error al intentar obtener los residentes.
|
||||
*/
|
||||
@GetMapping("/getAll")
|
||||
public ResponseEntity<List<ResidenteResponseDto>> getAll(
|
||||
@RequestParam(required = false) LocalDate fechaNacimiento,
|
||||
@RequestParam(required = false) LocalDate minFNac,
|
||||
@RequestParam(required = false) LocalDate maxFNac,
|
||||
@RequestParam(required = false) Integer maxAge,
|
||||
@RequestParam(required = false) Integer minAge,
|
||||
@RequestParam(required = false) Long idJuego,
|
||||
@RequestParam(required = false) Long idEvento,
|
||||
@RequestParam(required = false)ResidenteFiltrado filtrado) {
|
||||
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
|
||||
List<ResidenteResponseDto> residentes;
|
||||
try{
|
||||
residentes = residenteService.getAll(currentUser.getResidencia().getId(),fechaNacimiento, minFNac, maxFNac, maxAge, minAge, idJuego, idEvento, filtrado);
|
||||
}catch (ResiException e){
|
||||
throw new ApiException(e, currentUser);
|
||||
}catch (Exception e){
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residentes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lista todos los residentes dados de baja en la residencia del usuario autenticado,
|
||||
* con posibilidad de filtrar por fechas.
|
||||
*
|
||||
* @param fecha Fecha exacta de baja (opcional).
|
||||
* @param minFecha Fecha mínima de baja (opcional).
|
||||
* @param maxFecha Fecha máxima de baja (opcional).
|
||||
* @return {@link ResponseEntity} con la lista de residentes dados de baja.
|
||||
* @throws ApiException si ocurre un error al intentar obtener los residentes dados de baja.
|
||||
*/
|
||||
@GetMapping("/getAll/bajas")
|
||||
public ResponseEntity<List<ResidenteResponseDto>> getAllBajas(
|
||||
@RequestParam(required = false) LocalDate fecha,
|
||||
@RequestParam(required = false) LocalDate minFecha,
|
||||
@RequestParam(required = false) LocalDate maxFecha){
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
List<ResidenteResponseDto> residentesBajas;
|
||||
try {
|
||||
residentesBajas = residenteService.getAllBajas(currentUser.getResidencia().getId(),fecha, minFecha, maxFecha);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residentesBajas);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marca lógicamente como dado de baja a un residente (no lo elimina físicamente).
|
||||
*
|
||||
* @param idResidente ID del residente a dar de baja.
|
||||
* @return {@link ResponseEntity} con estado {@code 204 No Content} si se realizó correctamente.
|
||||
* @throws ApiException si ocurre un error al intentar dar de baja al residente.
|
||||
*/
|
||||
@PatchMapping("/{idResidente}/baja")
|
||||
public ResponseEntity<Void> deleteLogico(
|
||||
@PathVariable Long idResidente) {
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
try{
|
||||
residenteService.deleteLogico(currentUser.getResidencia().getId(),idResidente);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Actualiza parcialmente los datos de un residente específico.
|
||||
*
|
||||
* @param idResidente ID del residente a actualizar.
|
||||
* @param residenteDto DTO con los nuevos datos del residente.
|
||||
* @return {@link ResponseEntity} con estado {@code 200 OK} y el residente actualizado.
|
||||
* @throws ApiException si ocurre un error al intentar actualizar el residente.
|
||||
*/
|
||||
@PatchMapping("/{idResidente}/update")
|
||||
public ResponseEntity<ResidenteResponseDto> update(
|
||||
@PathVariable Long idResidente,
|
||||
@RequestBody ResidenteDto residenteDto) {
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
ResidenteResponseDto residenteResponseDto;
|
||||
try {
|
||||
residenteResponseDto = residenteService.update(currentUser.getResidencia().getId(), idResidente, residenteDto);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO),currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(residenteResponseDto);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Envía un correo electrónico a un familiar de un residente específico.
|
||||
*
|
||||
* @param idResidente ID del residente.
|
||||
* @param emailRequestDto DTO con los detalles del correo electrónico.
|
||||
* @return {@link ResponseEntity} con estado {@code 204 No Content} si se envió correctamente.
|
||||
*/
|
||||
@PostMapping("/{idResidente}/sendEmailFamily")
|
||||
public ResponseEntity<Void> sendEmailFamily(
|
||||
@PathVariable Long idResidente,
|
||||
@RequestBody EmailRequestDto emailRequestDto) {
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
try{
|
||||
residenteService.sendEmailFamiliar(currentUser.getResidencia().getId(), idResidente, emailRequestDto);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Descarga la imagen por defecto del usuario.
|
||||
*
|
||||
* @return Recurso de imagen por defecto como archivo adjunto.
|
||||
*/
|
||||
@GetMapping("/defualtImage")
|
||||
public ResponseEntity<Resource> downloadImage(){
|
||||
Resource resource = residenteService.getImage(Conf.imageDefault);
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,342 @@
|
|||
package com.kevinolarte.resibenissa.controllers.user;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.UserDto;
|
||||
import com.kevinolarte.resibenissa.dto.in.auth.ChangePasswordUserDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.UserResponseDto;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.services.UserService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controlador REST para la administración de usuarios dentro de una residencia.
|
||||
*
|
||||
* Proporciona operaciones para registrar, consultar, actualizar, desactivar
|
||||
* y eliminar usuarios. Admite filtros por estado, juego asociado y fecha de baja.
|
||||
*
|
||||
* URL base: {@code /admin/resi}
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/admin/resi")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class UserAdminController {
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
|
||||
/**
|
||||
* Registra un nuevo usuario en una residencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param userDto Datos del usuario a registrar.
|
||||
* @return Usuario creado.
|
||||
* @throws ApiException si ocurre un error durante el registro.
|
||||
*/
|
||||
@PostMapping("{idResidencia}/user/add")
|
||||
public ResponseEntity<UserResponseDto> addUser(
|
||||
@PathVariable Long idResidencia,
|
||||
@RequestBody UserDto userDto) {
|
||||
|
||||
UserResponseDto user;
|
||||
|
||||
try {
|
||||
user = userService.add(idResidencia, userDto);
|
||||
}catch (ResiException e){
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(user);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene un usuario por su ID dentro de una residencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idUser ID del usuario.
|
||||
* @return Datos del usuario.
|
||||
* @throws ApiException si ocurre un error al intentar obtener el usuario.
|
||||
*/
|
||||
@GetMapping("{idResidencia}/user/{idUser}/get")
|
||||
public ResponseEntity<UserResponseDto> get(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idUser) {
|
||||
UserResponseDto user;
|
||||
try {
|
||||
user = userService.get(idResidencia, idUser);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(user);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene un usuario por su email dentro de una residencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param email Email del usuario.
|
||||
* @return Datos del usuario.
|
||||
* @throws ApiException si ocurre un error al intentar obtener el usuario.
|
||||
*/
|
||||
@GetMapping("/{idResidencia}/user/get")
|
||||
public ResponseEntity<UserResponseDto> get(
|
||||
@PathVariable Long idResidencia,
|
||||
@RequestParam(required = true) String email) {
|
||||
|
||||
UserResponseDto user;
|
||||
try {
|
||||
user = userService.get(idResidencia, email);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(user);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene una lista de usuarios filtrada por estado y/o juego dentro de una residencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param enabled Filtro por estado habilitado (opcional).
|
||||
* @param idJuego Filtro por ID de juego (opcional).
|
||||
* @return Lista de usuarios.
|
||||
* @throws ApiException si ocurre un error al intentar obtener los usuarios.
|
||||
*/
|
||||
@GetMapping("{idResidencia}/user/getAll")
|
||||
public ResponseEntity<List<UserResponseDto>> getAll(
|
||||
@PathVariable Long idResidencia,
|
||||
@RequestParam(required = false) Boolean enabled,
|
||||
@RequestParam(required = false) Long idJuego) {
|
||||
|
||||
List<UserResponseDto> user;
|
||||
try {
|
||||
user = userService.getAll(idResidencia, enabled, idJuego);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(user);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene todos los usuarios, con filtros por estado y/o juego (sin filtrar por residencia).
|
||||
*
|
||||
* @param enabled Filtro por estado habilitado (opcional).
|
||||
* @param idJuego Filtro por ID de juego (opcional).
|
||||
* @return Lista de usuarios.
|
||||
* @throws ApiException si ocurre un error al intentar obtener los usuarios.
|
||||
*/
|
||||
@GetMapping("/user/getAll")
|
||||
public ResponseEntity<List<UserResponseDto>> getAll(
|
||||
@RequestParam(required = false) Boolean enabled,
|
||||
@RequestParam(required = false) Long idJuego) {
|
||||
|
||||
List<UserResponseDto> user;
|
||||
try {
|
||||
user = userService.getAll(enabled, idJuego);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(user);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de usuarios dados de baja en una residencia, con filtros de fecha.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param fecha Fecha exacta de baja (opcional).
|
||||
* @param minFecha Fecha mínima de baja (opcional).
|
||||
* @param maxFecha Fecha máxima de baja (opcional).
|
||||
* @return Lista de usuarios dados de baja.
|
||||
* @throws ApiException si ocurre un error al intentar obtener los usuarios dados de baja.
|
||||
*/
|
||||
@GetMapping("{idResidencia}/user/getAll/bajas")
|
||||
public ResponseEntity<List<UserResponseDto>> getAllBajas(
|
||||
@PathVariable Long idResidencia,
|
||||
@RequestParam(required = false)LocalDate fecha,
|
||||
@RequestParam(required = false) LocalDate minFecha,
|
||||
@RequestParam(required = false) LocalDate maxFecha){
|
||||
|
||||
List<UserResponseDto> user;
|
||||
try {
|
||||
user = userService.getAllBajas(idResidencia, fecha, minFecha, maxFecha);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(user);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene todos los usuarios dados de baja (sin filtrar por residencia).
|
||||
*
|
||||
* @param fecha Fecha exacta de baja (opcional).
|
||||
* @param minFecha Fecha mínima de baja (opcional).
|
||||
* @param maxFecha Fecha máxima de baja (opcional).
|
||||
* @return Lista de usuarios dados de baja.
|
||||
* @throws ApiException si ocurre un error al intentar obtener los usuarios dados de baja.
|
||||
*/
|
||||
@GetMapping("/user/getAll/bajas")
|
||||
public ResponseEntity<List<UserResponseDto>> getAllBajas(
|
||||
@RequestParam(required = false)LocalDate fecha,
|
||||
@RequestParam(required = false) LocalDate minFecha,
|
||||
@RequestParam(required = false) LocalDate maxFecha){
|
||||
|
||||
List<UserResponseDto> user;
|
||||
try {
|
||||
user = userService.getAllBajas(fecha, minFecha, maxFecha);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(user);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Elimina físicamente un usuario de una residencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idUser ID del usuario.
|
||||
* @return HTTP 204 si se elimina correctamente.
|
||||
* @throws ApiException si ocurre un error al intentar eliminar el usuario.
|
||||
*/
|
||||
@DeleteMapping("/{idResidencia}/user/{idUser}/delete")
|
||||
public ResponseEntity<Void> delete(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idUser) {
|
||||
try{
|
||||
userService.deleteFisico(idResidencia,idUser);
|
||||
|
||||
}catch (ResiException e){
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Elimina las referencias del usuario a registros dependientes (sin eliminar el usuario).
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idUser ID del usuario.
|
||||
* @return HTTP 204 si se eliminan correctamente las referencias.
|
||||
* @throws ApiException si ocurre un error al intentar eliminar las referencias.
|
||||
*/
|
||||
@DeleteMapping("/{idResidencia}/{idUser}/delete/referencies")
|
||||
public ResponseEntity<Void> deleteReferencies(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idUser) {
|
||||
|
||||
try{
|
||||
userService.deleteReferencies(idResidencia, idUser);
|
||||
}catch (ResiException e){
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualiza los datos de un usuario.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idUser ID del usuario.
|
||||
* @param userDto Nuevos datos del usuario.
|
||||
* @return Usuario actualizado.
|
||||
* @throws ApiException si ocurre un error al intentar actualizar el usuario.
|
||||
*/
|
||||
@PatchMapping("/{idResidencia}/user/{idUser}/update")
|
||||
public ResponseEntity<UserResponseDto> update(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idUser,
|
||||
@RequestBody UserDto userDto) {
|
||||
|
||||
UserResponseDto user;
|
||||
try {
|
||||
user = userService.update(idResidencia, idUser, userDto);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cambia la contraseña de un usuario validando la anterior.
|
||||
*
|
||||
* @param idResidencia ID de la residencia a la que pertenece el usuario.
|
||||
* @param idUser ID del usuario.
|
||||
* @param changePasswordUserDto DTO con la contraseña actual y la nueva.
|
||||
* @return {@link ResponseEntity} con los datos del usuario tras el cambio.
|
||||
* * @throws ApiException si ocurre un error al intentar cambiar la contraseña.
|
||||
*/
|
||||
@PatchMapping("/{idResidencia}/user/{idUser}/update/changePassword")
|
||||
public ResponseEntity<UserResponseDto> changePassword(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idUser,
|
||||
@RequestBody ChangePasswordUserDto changePasswordUserDto) {
|
||||
|
||||
UserResponseDto userResponseDto;
|
||||
try {
|
||||
userResponseDto = userService.updatePassword(idResidencia, idUser, changePasswordUserDto);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(userResponseDto);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Marca un usuario como dado de baja (borrado lógico).
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idUser ID del usuario.
|
||||
* @return HTTP 204 si se desactiva correctamente.
|
||||
* @throws ApiException si ocurre un error al intentar dar de baja al usuario.
|
||||
*/
|
||||
@PatchMapping("/{idResidencia}/user/{idUser}/baja")
|
||||
public ResponseEntity<Void> baja(
|
||||
@PathVariable Long idResidencia,
|
||||
@PathVariable Long idUser) {
|
||||
try{
|
||||
userService.deleteLogico(idResidencia, idUser);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), e.getMessage());
|
||||
}
|
||||
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
package com.kevinolarte.resibenissa.controllers.user;
|
||||
|
||||
import com.kevinolarte.resibenissa.config.Conf;
|
||||
import com.kevinolarte.resibenissa.dto.in.UserDto;
|
||||
import com.kevinolarte.resibenissa.dto.in.auth.ChangePasswordUserDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.UserResponseDto;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiException;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.services.UserService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Controlador REST para gestionar las operaciones relacionadas con los usuarios.
|
||||
* Expone endpoints para obtener, actualizar y dar de baja usuarios dentro de una residencia.
|
||||
* <p>
|
||||
* URL Base: {@code /resi/user}
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@RequestMapping("/resi/user")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class UserController {
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene la información del usuario actualmente autenticado.
|
||||
*
|
||||
* @return DTO con los datos del usuario autenticado.
|
||||
*/
|
||||
@GetMapping("/me")
|
||||
public ResponseEntity<UserResponseDto> getMe() {
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
|
||||
return ResponseEntity.ok(new UserResponseDto(currentUser));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene la información de un usuario específico por su ID, perteneciente a la misma residencia del usuario autenticado.
|
||||
*
|
||||
* @param idUser ID del usuario a consultar.
|
||||
* @return DTO con los datos del usuario.
|
||||
* @throws ApiException si ocurre un error al intentar obtener el usuario.
|
||||
*/
|
||||
@GetMapping("/{idUser}/get")
|
||||
public ResponseEntity<UserResponseDto> get(
|
||||
@PathVariable Long idUser) {
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
UserResponseDto userResponseDto;
|
||||
try{
|
||||
userResponseDto = userService.get(currentUser.getResidencia().getId(), idUser);
|
||||
}catch (ResiException e){
|
||||
throw new ApiException(e, currentUser);
|
||||
}
|
||||
return ResponseEntity.ok(userResponseDto);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene todos los usuarios filtrando opcionalmente por si están habilitados y
|
||||
* por ID de juego que han registrado partidas.
|
||||
*
|
||||
* @param enabled Filtro opcional para usuarios habilitados.
|
||||
* @param idJuego Filtro opcional por ID de juego.
|
||||
* @return Lista de DTOs con los datos de los usuarios.
|
||||
* @throws ApiException si ocurre un error al intentar obtener los usuarios.
|
||||
*/
|
||||
@GetMapping("/getAll")
|
||||
public ResponseEntity<List<UserResponseDto>> getAll(
|
||||
@RequestParam(required = false) Boolean enabled,
|
||||
@RequestParam(required = false) Long idJuego) {
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
List<UserResponseDto> userResponseDtos;
|
||||
try {
|
||||
userResponseDtos = userService.getAll(currentUser.getResidencia().getId(), enabled, idJuego);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
}catch (Exception e){
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(userResponseDtos);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene todos los usuarios dados de baja, filtrando opcionalmente por fechas.
|
||||
*
|
||||
* @param fecha Fecha exacta de baja.
|
||||
* @param minFecha Fecha mínima de baja.
|
||||
* @param maxFecha Fecha máxima de baja.
|
||||
* @return Lista de usuarios dados de baja en el rango indicado.
|
||||
* @throws ApiException si ocurre un error al intentar obtener los usuarios dados de baja.
|
||||
*/
|
||||
@GetMapping("/getAll/bajas")
|
||||
public ResponseEntity<List<UserResponseDto>> getAllBajas(
|
||||
@RequestParam(required = false) LocalDate fecha,
|
||||
@RequestParam(required = false) LocalDate minFecha,
|
||||
@RequestParam(required = false) LocalDate maxFecha){
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
List<UserResponseDto> userResponseDtos;
|
||||
try {
|
||||
userResponseDtos = userService.getAllBajas(currentUser.getResidencia().getId(), fecha, minFecha, maxFecha);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
}catch (Exception e){
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(userResponseDtos);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Descarga la imagen por defecto del usuario.
|
||||
*
|
||||
* @return Recurso de imagen por defecto como archivo adjunto.
|
||||
*/
|
||||
@GetMapping("/defualtImage")
|
||||
public ResponseEntity<Resource> downloadImage(){
|
||||
Resource resource = userService.getImage(Conf.imageDefault);
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualiza los datos personales del usuario autenticado.
|
||||
*
|
||||
* @param userDto Objeto DTO con los nuevos datos del usuario.
|
||||
* @return DTO actualizado con la información del usuario.
|
||||
* @throws ApiException si ocurre un error al intentar actualizar los datos del usuario.
|
||||
*/
|
||||
@PatchMapping("/update")
|
||||
public ResponseEntity<UserResponseDto> update(
|
||||
@RequestBody UserDto userDto) {
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
UserResponseDto userResponseDto;
|
||||
try {
|
||||
userResponseDto = userService.update(currentUser.getResidencia().getId(), currentUser.getId(), userDto);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
}catch (Exception e){
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(userResponseDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cambia la contraseña del usuario autenticado.
|
||||
*
|
||||
* @param changePasswordUserDto DTO con la contraseña antigua y la nueva.
|
||||
* @return DTO actualizado del usuario tras el cambio de contraseña.
|
||||
* @throws ApiException si ocurre un error al intentar cambiar la contraseña.
|
||||
*/
|
||||
@PatchMapping("/update/changePassword")
|
||||
public ResponseEntity<UserResponseDto> changePassword(
|
||||
@RequestBody ChangePasswordUserDto changePasswordUserDto) {
|
||||
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
UserResponseDto userResponseDto;
|
||||
try {
|
||||
userResponseDto = userService.updatePassword(currentUser.getResidencia().getId(), currentUser.getId(), changePasswordUserDto);
|
||||
} catch (ResiException e) {
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e){
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(userResponseDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marca lógicamente como dado de baja al usuario.
|
||||
*
|
||||
* @return Respuesta sin contenido (HTTP 204) si se realiza correctamente.
|
||||
* @throws ApiException si ocurre un error al intentar dar de baja al usuario.
|
||||
*/
|
||||
@PatchMapping("/baja")
|
||||
public ResponseEntity<Void> baja() {
|
||||
System.out.println("baja");
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) auth.getPrincipal();
|
||||
try {
|
||||
userService.deleteLogico(currentUser.getResidencia().getId(), currentUser.getId());
|
||||
}catch (ResiException e){
|
||||
throw new ApiException(e, currentUser);
|
||||
} catch (Exception e){
|
||||
throw new ApiException(new ResiException(ApiErrorCode.PROBLEMA_INTERNO), currentUser, e.getMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.kevinolarte.resibenissa.dto.in;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Objeto de transferencia de datos (DTO) utilizado para crear o actualizar una residencia.
|
||||
* <p>
|
||||
* Contiene los datos básicos necesarios para registrar una residencia en el sistema,
|
||||
* como su nombre y correo electrónico de contacto.
|
||||
* <p>
|
||||
* No contiene lógica de negocio ni persistencia.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class ResidenciaDto {
|
||||
|
||||
private String nombre;
|
||||
private String email;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package com.kevinolarte.resibenissa.dto.in;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* Objeto de transferencia de datos (DTO) utilizado para crear o actualizar residentes.
|
||||
* <p>
|
||||
* Contiene los datos personales básicos necesarios para registrar un residente
|
||||
* y asociarlo a una residencia existente.
|
||||
* <p>
|
||||
* No contiene lógica de negocio ni anotaciones de persistencia.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class ResidenteDto {
|
||||
|
||||
private String nombre;
|
||||
private String apellido;
|
||||
|
||||
private LocalDate fechaNacimiento;
|
||||
private String documentoIdentidad;
|
||||
private String familiar1;
|
||||
private String familiar2;
|
||||
private Integer year;
|
||||
private Integer month;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.kevinolarte.resibenissa.dto.in;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Objeto de transferencia de datos (DTO) utilizado para crear o actualizar usuarios.
|
||||
* <p>
|
||||
* Contiene los campos necesarios para registrar un nuevo usuario en el sistema.
|
||||
* No debe contener lógica de negocio ni anotaciones de persistencia.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class UserDto {
|
||||
private String nombre;
|
||||
private String apellido;
|
||||
private String email;
|
||||
private String password;
|
||||
private Long idResidencia;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.kevinolarte.resibenissa.dto.in.auth;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class ChangePasswordUserDto {
|
||||
private String oldPassword;
|
||||
private String newPassword;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.kevinolarte.resibenissa.dto.in.auth;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Objeto de transferecia de datos (DTO) utilizado para logearse y obtener el token de un usario activado anteriormente.
|
||||
* <p>
|
||||
* Este DTO permite obtener acceso a los demas endPoint porque se usara para crear un token. A partir de los parametros que tiene.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class LoginUserDto {
|
||||
|
||||
private String email;
|
||||
private String password;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.kevinolarte.resibenissa.dto.in.auth;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Objecto de transferencia de datos (DTO) utilizado para registrar por primera vez un usuaario.
|
||||
* <p>
|
||||
* Este DTO permite asociar un nuevo usuario a una residencia especifica,
|
||||
* enviando unicamente los siguentes parametros.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class RegisterUserDto {
|
||||
|
||||
private String nombre;
|
||||
private String apellido;
|
||||
private String email;
|
||||
private String password;
|
||||
private Long idResidencia;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.kevinolarte.resibenissa.dto.in.auth;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Objecto de transferencia de datos (DTO) utilizado para verificar el usuario creado anteriormente
|
||||
* <p>
|
||||
* Este DTO permite actibar el usuario creado anteriormete, con solo pasando
|
||||
* los siguientes parametros.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class VerifyUserDto {
|
||||
private String email;
|
||||
private String verificationCode;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.kevinolarte.resibenissa.dto.in.modeloWallet;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class MovimientoRequestDTO {
|
||||
private double cantidad;
|
||||
private String concepto; // opcional, se puede usar "Depósito manual" por defecto si es null
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.kevinolarte.resibenissa.dto.in.moduloOrgSalida;
|
||||
|
||||
import com.kevinolarte.resibenissa.enums.moduloOrgSalida.EstadoSalida;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* DTO para representar un evento de salida.
|
||||
*<p>
|
||||
* Esta clase contiene información básica sobre un evento de salida, incluyendo su ID,
|
||||
* nombre, descripción, fecha y estado.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class EventoSalidaDto {
|
||||
private String nombre;
|
||||
private String descripcion;
|
||||
private LocalDateTime fecha;
|
||||
private EstadoSalida estado;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.kevinolarte.resibenissa.dto.in.moduloOrgSalida;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Objeto de transferencia de datos (DTO) utilizado para representar la asistencia de un residente a una salida.
|
||||
*
|
||||
* <p>
|
||||
* Esta clase encapsula la información necesaria para identificar al residente y el evento de salida
|
||||
* al que asistió, así como su estado de asistencia.
|
||||
* </p>
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class ParticipanteDto {
|
||||
private Long idResidente;
|
||||
private Boolean recursosHumanos;
|
||||
private Boolean recursosMateriales;
|
||||
private String preOpinion;
|
||||
private String postOpinion;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.kevinolarte.resibenissa.dto.in.moduloReporting;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class EmailRequestDto {
|
||||
private String subject;
|
||||
private String body;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.kevinolarte.resibenissa.dto.in.modulojuego;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Objeto de transferencia de datos (DTO) utilizado para crear o actualizar un juego.
|
||||
* <p>
|
||||
* Este DTO permite asociar un nuevo juego a una residencia específica,
|
||||
* enviando únicamente el nombre del juego y el ID de la residencia.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class JuegoDto {
|
||||
private String nombre;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.kevinolarte.resibenissa.dto.in.modulojuego;
|
||||
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.Dificultad;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Objeto de transferencia de datos (DTO) utilizado para registrar una partida de juego
|
||||
* realizada por un residente en una residencia específica.
|
||||
* <p>
|
||||
* Incluye los datos mínimos necesarios para asociar el registro con el juego y la residencia,
|
||||
* así como la información del desempeño durante la sesión.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class RegistroJuegoDto {
|
||||
|
||||
private Long idJuego;
|
||||
private Long idResidente;
|
||||
private Long idUsuario;
|
||||
private Integer num;
|
||||
private Double duracion;
|
||||
private Dificultad dificultad;
|
||||
private String observacion;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RegistroJuegoDto{" +
|
||||
"idJuego=" + idJuego +
|
||||
", idResidente=" + idResidente +
|
||||
", idUsuario=" + idUsuario +
|
||||
", fallos=" + num +
|
||||
", duracion=" + duracion +
|
||||
", dificultad=" + dificultad +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.kevinolarte.resibenissa.dto.out;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* DTO de salida utilizado como respuesta al iniciar sesión.
|
||||
* <p>
|
||||
* Contiene el token JWT generado para el usuario autenticado, así como el tiempo
|
||||
* de expiración en milisegundos, indicando cuánto tiempo es válido el token.
|
||||
* </p>
|
||||
*
|
||||
* Este DTO es devuelto por el endpoint de autenticación {@code /auth/login}.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class LoginResponseDto {
|
||||
private String token;
|
||||
private Long expiresIn;
|
||||
private Long idUser;
|
||||
private Long idResidencia;
|
||||
|
||||
public LoginResponseDto(String token, long expiresIn, User user) {
|
||||
this.token = token;
|
||||
this.expiresIn = expiresIn;
|
||||
this.idUser = user.getId();
|
||||
this.idResidencia = user.getResidencia().getId();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.kevinolarte.resibenissa.dto.out;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
|
||||
public class ResidenciaPublicResponseDto {
|
||||
public Long id;
|
||||
public String nombre;
|
||||
public String email;
|
||||
|
||||
public ResidenciaPublicResponseDto(Residencia residencia) {
|
||||
this.id = residencia.getId();
|
||||
this.nombre = residencia.getNombre();
|
||||
this.email = residencia.getEmail();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package com.kevinolarte.resibenissa.dto.out;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
import com.kevinolarte.resibenissa.models.Residente;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
/**
|
||||
* DTO de salida que representa la información pública de una residencia.
|
||||
* <p>
|
||||
* Esta clase se utiliza para enviar al cliente los datos esenciales de una residencia,
|
||||
* incluyendo su nombre, email y los identificadores de usuarios y residentes asociados.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Se construye a partir de una instancia de {@link Residencia}, mapeando únicamente los IDs
|
||||
* de las relaciones con usuarios y residentes para evitar sobrecarga de datos en la respuesta.
|
||||
* </p>
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class ResidenciaResponseDto {
|
||||
private Long id;
|
||||
private String nombre;
|
||||
private String email;
|
||||
private List<Long> usuarios;
|
||||
private List<Long> residentes;
|
||||
|
||||
public ResidenciaResponseDto(Residencia residencia) {
|
||||
this.id = residencia.getId();
|
||||
this.nombre = residencia.getNombre();
|
||||
this.email = residencia.getEmail();
|
||||
|
||||
this.usuarios = residencia.getUsuarios()
|
||||
.stream()
|
||||
.map(User::getId)
|
||||
.toList();
|
||||
|
||||
this.residentes = residencia.getResidentes()
|
||||
.stream()
|
||||
.map(Residente::getId)
|
||||
.toList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package com.kevinolarte.resibenissa.dto.out;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.Residente;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* DTO de salida que representa los datos públicos de un residente.
|
||||
* <p>
|
||||
* Esta clase se utiliza para enviar al cliente información relevante sobre
|
||||
* un residente sin exponer detalles internos del modelo ni relaciones sensibles.
|
||||
* </p>
|
||||
*
|
||||
* Contiene campos como el ID, nombre completo, fecha de nacimiento y la residencia asociada.
|
||||
*
|
||||
* @author Kevin Olate
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class ResidenteResponseDto {
|
||||
private Long id;
|
||||
private String nombre;
|
||||
private String apellido;
|
||||
private LocalDate fechaNacimiento;
|
||||
private String documentoIdentidad;
|
||||
private String familiar1;
|
||||
private String familiar2;
|
||||
private Long idResidencia;
|
||||
private Boolean baja;
|
||||
|
||||
public ResidenteResponseDto(Residente residente) {
|
||||
this.id = residente.getId();
|
||||
this.nombre = residente.getNombre();
|
||||
this.apellido = residente.getApellido();
|
||||
this.fechaNacimiento = residente.getFechaNacimiento();
|
||||
this.idResidencia = residente.getResidencia().getId();
|
||||
this.documentoIdentidad = residente.getDocuemntoIdentidad();
|
||||
this.baja = residente.isBaja();
|
||||
this.familiar1 = residente.getFamiliar1();
|
||||
this.familiar2 = residente.getFamiliar2();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.kevinolarte.resibenissa.dto.out;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* DTO de salida para representar los datos públicos de un usuario del sistema.
|
||||
* <p>
|
||||
* Esta clase se utiliza para devolver información básica del usuario en las respuestas
|
||||
* de la API, sin incluir detalles sensibles como contraseñas o tokens de autenticación.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Contiene datos como el ID del usuario, nombre, email, estado de activación y la residencia asociada.
|
||||
* </p>
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class UserResponseDto {
|
||||
private Long id;
|
||||
private String nombre;
|
||||
private String apellido;
|
||||
private String email;
|
||||
private String verificationCode;
|
||||
private boolean enabled;
|
||||
|
||||
private Long idResidencia;
|
||||
private String fotoPerfil;
|
||||
private boolean baja;
|
||||
|
||||
|
||||
public UserResponseDto(User user) {
|
||||
this.id = user.getId();
|
||||
this.nombre = user.getNombre();
|
||||
this.apellido = user.getApellido();
|
||||
this.email = user.getEmail();
|
||||
this.enabled = user.isEnabled();
|
||||
this.idResidencia = user.getResidencia().getId();
|
||||
this.fotoPerfil = user.getFotoPerfil();
|
||||
this.verificationCode = user.getVerificationCode();
|
||||
this.baja = user.isBaja();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package com.kevinolarte.resibenissa.dto.out.moduloOrgSalida;
|
||||
|
||||
import com.kevinolarte.resibenissa.enums.moduloOrgSalida.EstadoSalida;
|
||||
import com.kevinolarte.resibenissa.models.moduloOrgSalida.EventoSalida;
|
||||
import com.kevinolarte.resibenissa.models.moduloOrgSalida.Participante;
|
||||
import jdk.jfr.Event;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* DTO de salida que representa los datos públicos de un evento de salida.
|
||||
* <p>
|
||||
* Esta clase se utiliza para enviar al cliente información relevante sobre
|
||||
* un evento de salida sin exponer detalles internos del modelo ni relaciones sensibles.
|
||||
* </p>
|
||||
*
|
||||
* Contiene campos como el ID, nombre, descripción, fecha de inicio, estado y lista de participantes.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class EventoSalidaResponseDto {
|
||||
private Long id;
|
||||
private String nombre;
|
||||
private String descripcion;
|
||||
private LocalDateTime fechaInicio;
|
||||
private EstadoSalida estado;
|
||||
private List<Long> participantes;
|
||||
private Long idResidencia;
|
||||
|
||||
public EventoSalidaResponseDto(EventoSalida e) {
|
||||
this.id = e.getId();
|
||||
this.nombre = e.getNombre();
|
||||
this.descripcion = e.getDescripcion();
|
||||
this.fechaInicio = e.getFechaInicio();
|
||||
this.estado = e.getEstado();
|
||||
this.participantes = e.getParticipantes().stream()
|
||||
.map(Participante::getId)
|
||||
.toList();
|
||||
this.idResidencia = e.getResidencia().getId();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.kevinolarte.resibenissa.dto.out.moduloOrgSalida;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.kevinolarte.resibenissa.models.moduloOrgSalida.Participante;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/*
|
||||
* Objeto de transferencia de datos (DTO) utilizado para representar la respuesta de un participante en un evento de salida.
|
||||
* <p>
|
||||
* Este DTO contiene información sobre el participante, incluyendo su ID, el ID del residente, el ID del evento de salida,
|
||||
* si asistió al evento y sus opiniones antes y después del evento.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class ParticipanteResponseDto {
|
||||
private Long id;
|
||||
private Long idResidente;
|
||||
private Long idEvento;
|
||||
private boolean recursosHumanos;
|
||||
private boolean recursosMateriales;
|
||||
private boolean asistenciaPermitida;
|
||||
private String preOpinion;
|
||||
private String postOpinion;
|
||||
|
||||
@JsonIgnore
|
||||
private Long idResidencia;
|
||||
@JsonIgnore
|
||||
private String familiar1;
|
||||
@JsonIgnore
|
||||
private String familiar2;
|
||||
|
||||
public ParticipanteResponseDto(Participante participante) {
|
||||
this.id = participante.getId();
|
||||
this.idResidente = participante.getResidente().getId();
|
||||
this.idEvento = participante.getEvento().getId();
|
||||
this.recursosHumanos = participante.isRecursosHumanos();
|
||||
this.recursosMateriales = participante.isRecursosMateriales();
|
||||
this.preOpinion = participante.getPreOpinion();
|
||||
this.postOpinion = participante.getPostOpinion();
|
||||
this.asistenciaPermitida = participante.isAsistenciaPermitida();
|
||||
this.idResidencia = participante.getResidente().getResidencia().getId();
|
||||
this.familiar1 = participante.getResidente().getFamiliar1();
|
||||
this.familiar2 = participante.getResidente().getFamiliar2();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.kevinolarte.resibenissa.dto.out.modulojuego;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.modulojuego.Juego;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* DTO de salida que representa los datos públicos de un juego registrado.
|
||||
* <p>
|
||||
* Esta clase es utilizada para enviar al cliente información sobre un juego,
|
||||
* como su identificador, nombre y la residencia a la que pertenece.
|
||||
* </p>
|
||||
*
|
||||
* Se construye a partir de una entidad {@link Juego}.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class JuegoResponseDto {
|
||||
private Long id;
|
||||
private String nombre;
|
||||
|
||||
public JuegoResponseDto(Juego juego){
|
||||
this.id = juego.getId();
|
||||
this.nombre = juego.getNombre();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.kevinolarte.resibenissa.dto.out.modulojuego;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class MediaRegistroDTO {
|
||||
private String agrupacion;
|
||||
private Double promedio;
|
||||
private Long total;
|
||||
|
||||
|
||||
public MediaRegistroDTO(String agrupacion, Double promedio, Long total) {
|
||||
this.agrupacion = agrupacion;
|
||||
this.promedio = promedio;
|
||||
this.total = total;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.kevinolarte.resibenissa.dto.out.modulojuego;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.modulojuego.RegistroJuego;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.Dificultad;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* DTO de salida que representa un registro del uso de un juego por parte de un residente.
|
||||
* <p>
|
||||
* Este DTO se utiliza para enviar al cliente información sobre una sesión de juego,
|
||||
* incluyendo detalles como duración, dificultad, número de errores y fecha de ejecución.
|
||||
* También identifica al residente, al juego y al usuario (trabajador) que registró la partida.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Si el usuario asociado a la partida es nulo, el campo {@code idUsario} se establece en {@code null}.
|
||||
* </p>
|
||||
*
|
||||
* @author Kevin Olarte.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class RegistroJuegoResponseDto {
|
||||
|
||||
private Long id;
|
||||
private Long idResidente;
|
||||
private Long idJuego;
|
||||
private Long idUsuario;
|
||||
private Integer num;
|
||||
private Double duracion;
|
||||
private Dificultad dificultad;
|
||||
private LocalDateTime fecha;
|
||||
private String observacion;
|
||||
|
||||
public RegistroJuegoResponseDto(RegistroJuego registroJuego) {
|
||||
this.id = registroJuego.getId();
|
||||
this.idResidente = registroJuego.getResidente().getId();
|
||||
this.idJuego = registroJuego.getJuego().getId();
|
||||
this.idUsuario = registroJuego.getUsuario() == null? null : registroJuego.getUsuario().getId();
|
||||
this.num = registroJuego.getNum();
|
||||
this.duracion = registroJuego.getDuracion();
|
||||
this.dificultad = registroJuego.getDificultad();
|
||||
this.fecha = registroJuego.getFecha();
|
||||
this.observacion = registroJuego.getObservacion() == null ? null : registroJuego.getObservacion();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.kevinolarte.resibenissa.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum CategoriaLog {
|
||||
DEBUG_INSERT(3L), DEBUG_UPDATE(4L), DEBUG_DELETE(5L), DEBUG_SELECT(6L),
|
||||
ERROR_INSERT(7L), ERROR_UPDATE(8L), ERROR_DELETE(9L), ERROR_SELECT(10L);
|
||||
private final Long valor;
|
||||
CategoriaLog(Long valor) {
|
||||
this.valor = valor;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.kevinolarte.resibenissa.enums.Filtrado;
|
||||
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
public enum RegistroJuegoFiltrado {
|
||||
FECHA_ASC("fecha", Sort.Direction.ASC),
|
||||
FECHA_DESC("fecha", Sort.Direction.DESC),
|
||||
NUM_ASC("num", Sort.Direction.ASC),
|
||||
NUM_DESC("num", Sort.Direction.DESC),
|
||||
DURACION_ASC("duracion", Sort.Direction.ASC),
|
||||
DURACION_DESC("duracion", Sort.Direction.DESC);
|
||||
|
||||
private final String campo;
|
||||
private final Sort.Direction direccion;
|
||||
|
||||
RegistroJuegoFiltrado(String campo, Sort.Direction direccion) {
|
||||
this.campo = campo;
|
||||
this.direccion = direccion;
|
||||
}
|
||||
|
||||
public Sort toSort() {
|
||||
return Sort.by(direccion, campo);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.kevinolarte.resibenissa.enums.Filtrado;
|
||||
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
public enum ResidenteFiltrado {
|
||||
FECHA_NAC_ASC("fechaNacimiento", Sort.Direction.ASC),
|
||||
FECHA_NAC_DESC("fechaNacimiento", Sort.Direction.DESC),
|
||||
NOMBRE_ASC("nombre", Sort.Direction.ASC),
|
||||
NOMBRE_DESC("nombre", Sort.Direction.DESC),
|
||||
APELLIDO_ASC("apellido", Sort.Direction.ASC),
|
||||
APELLIDO_DESC("apellido", Sort.Direction.DESC);
|
||||
|
||||
private final String campo;
|
||||
private final Sort.Direction direccion;
|
||||
|
||||
ResidenteFiltrado(String campo, Sort.Direction direccion) {
|
||||
this.campo = campo;
|
||||
this.direccion = direccion;
|
||||
}
|
||||
|
||||
public Sort toSort() {
|
||||
return Sort.by(direccion, campo);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package com.kevinolarte.resibenissa.enums;
|
||||
|
||||
public enum Role {
|
||||
ADMIN, NORMAL, SENDER;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.kevinolarte.resibenissa.enums.moduloOrgSalida;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Enumeración que representa los posibles estados de una salida.
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
public enum EstadoSalida {
|
||||
ABIERTO(0), CERRADO(1), EN_CURSO(2), FINALIZADA(3);
|
||||
|
||||
|
||||
private final int estado;
|
||||
|
||||
EstadoSalida(int estado) {
|
||||
this.estado = estado;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.kevinolarte.resibenissa.enums.moduloWallet;
|
||||
|
||||
public enum TipoMovimiento {
|
||||
IN, OUT;
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.kevinolarte.resibenissa.enums.modulojuego;
|
||||
|
||||
/**
|
||||
* Enum que representa la dificultad de una partida.
|
||||
* <p>
|
||||
* La interpretación de la dificultad depende del tipo de juego:
|
||||
* <ul>
|
||||
* <li>En juegos tipo A, determina el modo de juego (p. ej. memoria, parejas, secuencia).</li>
|
||||
* <li>En juegos tipo B, define la complejidad de las reglas (p. ej. número de cartas, tiempo disponible).</li>
|
||||
* </ul>
|
||||
* Es responsabilidad del juego interpretar estos valores adecuadamente.
|
||||
*
|
||||
* author Kevin Olarte
|
||||
*/
|
||||
public enum Dificultad {
|
||||
DIFICULTAD1, DIFICULTAD2, DIFICULTAD3;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.kevinolarte.resibenissa.enums.modulojuego;
|
||||
|
||||
public enum TipoAgrupacion {
|
||||
DIARIO,
|
||||
MENSUAL,
|
||||
ANUAL;
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package com.kevinolarte.resibenissa.exceptions;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
/**
|
||||
* Enumeración que define los distintos códigos de error personalizados utilizados en la API.
|
||||
* <p>
|
||||
* Cada valor del enum representa un tipo específico de error que puede ocurrir en la lógica
|
||||
* de negocio de la aplicación. Cada error contiene:
|
||||
* <ul>
|
||||
* <li>Un código numérico interno único para facilitar el rastreo.</li>
|
||||
* <li>Un mensaje amigable que puede mostrarse al usuario.</li>
|
||||
* <li>Un {@link HttpStatus} que será devuelto como código HTTP en la respuesta.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Esta clase se utiliza junto a {@link ResiException} para lanzar errores consistentes.</p>
|
||||
*
|
||||
* @see ResiException
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
public enum ApiErrorCode {
|
||||
|
||||
CAMPOS_OBLIGATORIOS(1001, "Faltan campos obligatorios", HttpStatus.BAD_REQUEST),
|
||||
CORREO_INVALIDO(1002, "Email invalid", HttpStatus.NOT_ACCEPTABLE),
|
||||
CORREO_DUPLICADO(1003, "Email ya existente", HttpStatus.CONFLICT),
|
||||
NOMBRE_DUPLICADO(1004, "Nombre ya existente", HttpStatus.CONFLICT),
|
||||
FECHA_INVALIDO(1005, "Fecha invalida", HttpStatus.NOT_ACCEPTABLE),
|
||||
RESIDENCIA_INVALIDO(1006, "Residencia invalida", HttpStatus.NOT_FOUND),
|
||||
VALORES_NEGATIVOS(1007,"No puede ser negativos los valores", HttpStatus.NOT_ACCEPTABLE),
|
||||
JUEGO_INVALIDO(1008, "Juego invalido", HttpStatus.NOT_FOUND),
|
||||
RESIDENTE_INVALIDO(1009, "Residente invalido", HttpStatus.NOT_FOUND),
|
||||
USUARIO_INVALIDO(1010, "Usuario invalido", HttpStatus.NOT_FOUND),
|
||||
CONFLICTO_REFERENCIAS(1011, "Problemas con las referencias de las entidades, no corresponden a las mismas", HttpStatus.CONFLICT),
|
||||
REGISTRO_JUEGO_INVALIDO(1012,"Registro juego invalido" , HttpStatus.NOT_FOUND ),
|
||||
REFERENCIAS_DEPENDIENTES(1013, "Esta entidad tiene referencias asociadas que dependen de el", HttpStatus.CONFLICT),
|
||||
USER_EXIST(1014, "Usuario ya existente" , HttpStatus.CONFLICT ),
|
||||
USER_NO_ACTIVADO(1015,"Usuario no activado" , HttpStatus.NOT_ACCEPTABLE ),
|
||||
CODIGO_EXPIRADO(1016,"El codigo de verificacion a caducado" , HttpStatus.GONE ),
|
||||
CODIGO_INVALIDO(1017,"El codigo de verificacion no es valdio" , HttpStatus.NOT_ACCEPTABLE ),
|
||||
USER_YA_ACTIVADO(1018,"El usuario ya activado" , HttpStatus.CONFLICT ),
|
||||
ERROR_MAIL_SENDER(1019,"Error enviando el correo" , HttpStatus.BAD_REQUEST ),
|
||||
ENDPOINT_PROTEGIDO(1020, "Tiene que tener permiso para acceder aqui", HttpStatus.METHOD_NOT_ALLOWED),
|
||||
PROBLEMAS_CON_FILE(1021,"A surgido un problema con la imagen" , HttpStatus.INTERNAL_SERVER_ERROR ),
|
||||
PARTICIPANTE_YA_REGISTRADO(1022,"Este residente ya participa en otro evento ese mismo dia" ,HttpStatus.NOT_ACCEPTABLE),
|
||||
EVENTO_SALIDA_INVALIDO(1023,"EventoSalida invalida" ,HttpStatus.NOT_FOUND),
|
||||
EVENTO_SALIDA_NO_DISPONIBLE(1024, "No se puede hacer nada con este evento ciertos problemas", HttpStatus.BAD_REQUEST),
|
||||
PARTICIPANTE_INVALIDO(1025, "Participante invalido" , HttpStatus.NOT_FOUND),
|
||||
PARTICIPANTE_INMUTABLE(1026, "No se puede hacer esta operacion con el participante porque ahora mismo es inmutable", HttpStatus.NOT_ACCEPTABLE),
|
||||
DOCUMENTO_INVALIDO(1027,"El docuemnto de identidad no tiene el formato correcto" ,HttpStatus.NOT_ACCEPTABLE),
|
||||
DOCUMENTO_DUPLICADO(1028,"El docuemnto de identidad debe ser unico" ,HttpStatus.CONFLICT ),
|
||||
CONTRASENA_INCORRECTA(1029,"Contraseña no valida" , HttpStatus.NOT_ACCEPTABLE ),
|
||||
RESIDENTE_BAJA(1028, "Este residente ya esta dado de baja", HttpStatus.NOT_ACCEPTABLE ),
|
||||
RANGO_EDAD_INVALIDO(1029, "Rango de edad inadecuado" , HttpStatus.NOT_ACCEPTABLE ),
|
||||
USUARIO_BAJA(1030, "Usuario dado de baja", HttpStatus.NOT_ACCEPTABLE),
|
||||
RESIDENCIA_BAJA(1031, "Residencia dado de baja", HttpStatus.NOT_ACCEPTABLE),
|
||||
ESTADO_INVALIDO(1032, "Este estado no se puede cambiar por el otro, sigue la secuencia.",HttpStatus.NOT_ACCEPTABLE),
|
||||
PROBLEMA_INTERNO(5000, "Error interno del servidor", HttpStatus.INTERNAL_SERVER_ERROR),
|
||||
WALLET_NO_ENCONTRADA(1033,"Wallet no encontrada" , HttpStatus.NOT_FOUND ),
|
||||
MONTO_INVALIDO(1034,"El monto seleccionado no es valido" , HttpStatus.NOT_ACCEPTABLE ),
|
||||
SALDO_INSUFICIENTE(1035, "No tiene suficiente saldo", HttpStatus.NOT_ACCEPTABLE);
|
||||
|
||||
|
||||
private final int code;
|
||||
private final String message;
|
||||
private final HttpStatus httpStatus;
|
||||
|
||||
ApiErrorCode(int code, String message, HttpStatus httpStatus) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.httpStatus = httpStatus;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.kevinolarte.resibenissa.exceptions;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ApiException extends RuntimeException {
|
||||
private ResiException resiException;
|
||||
private String mensaje;
|
||||
|
||||
public ApiException(ResiException resiException, User user) {
|
||||
super(resiException.getMessage());
|
||||
this.resiException = resiException;
|
||||
this.mensaje = resiException.getMessage() + " - Usuario: " + user.getUsername();
|
||||
}
|
||||
public ApiException(ResiException resiException, User user, String mensaje) {
|
||||
super(resiException.getMessage());
|
||||
this.resiException = resiException;
|
||||
this.mensaje = mensaje + " - Usuario: " + user.getUsername();
|
||||
}
|
||||
|
||||
public ApiException(ResiException resiException, String mensaje) {
|
||||
super(resiException.getMessage());
|
||||
this.resiException = resiException;
|
||||
this.mensaje = mensaje;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.kevinolarte.resibenissa.exceptions;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* DTO de salida que representa la respuesta de error estándar en la API.
|
||||
* <p>
|
||||
* Esta clase encapsula toda la información relevante cuando ocurre una {@link ResiException}
|
||||
* y se desea devolver una respuesta estructurada al cliente.
|
||||
* </p>
|
||||
*
|
||||
* Contiene:
|
||||
* <ul>
|
||||
* <li>Mensaje de error amigable.</li>
|
||||
* <li>Código de error interno (definido en {@link ApiErrorCode}).</li>
|
||||
* <li>Estado HTTP correspondiente.</li>
|
||||
* <li>Fecha y hora del error.</li>
|
||||
* </ul>
|
||||
*
|
||||
* Este DTO es ideal para ser devuelto por un {@code @ControllerAdvice}.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class ErrorResponseDto {
|
||||
|
||||
private String mensaje;
|
||||
|
||||
private int codigo; // Código del enum
|
||||
|
||||
private int status; // Código HTTP
|
||||
|
||||
private String timestamp;
|
||||
|
||||
public ErrorResponseDto(ResiException ex) {
|
||||
this.mensaje = ex.getErrorCode().getMessage();
|
||||
this.codigo = ex.getErrorCode().getCode();
|
||||
this.status = ex.getHttpStatus().value();
|
||||
this.timestamp = LocalDateTime.now().toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.kevinolarte.resibenissa.exceptions;
|
||||
|
||||
import com.kevinolarte.resibenissa.services.LoggerService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
/**
|
||||
* Manejador global de excepciones para la API REST.
|
||||
* <p>
|
||||
* Captura y transforma excepciones de tipo {@link ResiException} en una respuesta estructurada
|
||||
* de tipo {@link ErrorResponseDto}, con el código, mensaje y estado HTTP correspondiente.
|
||||
* </p>
|
||||
*
|
||||
* Esta clase garantiza respuestas consistentes en todos los endpoints ante errores controlados.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
@AllArgsConstructor
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
private LoggerService loggerService;
|
||||
/**
|
||||
* Maneja cualquier excepción de tipo {@link ResiException} lanzada en los controladores.
|
||||
*
|
||||
* @param ex Excepción personalizada que contiene el código de error y estado HTTP.
|
||||
* @return {@link ResponseEntity} con el cuerpo {@link ErrorResponseDto} y el código HTTP correspondiente.
|
||||
*/
|
||||
@ExceptionHandler(ApiException.class)
|
||||
public ResponseEntity<ErrorResponseDto> handleApiException(ApiException ex) {
|
||||
loggerService.registrarLogError(ex.getMensaje());
|
||||
ErrorResponseDto error =
|
||||
new ErrorResponseDto(ex.getResiException());
|
||||
return ResponseEntity.status(ex.getResiException().getHttpStatus()).body(error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package com.kevinolarte.resibenissa.exceptions;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
/**
|
||||
* Excepción personalizada para representar errores controlados en la lógica de negocio de la aplicación.
|
||||
* <p>
|
||||
* Esta excepción encapsula un {@link ApiErrorCode}, el cual contiene:
|
||||
* <ul>
|
||||
* <li>Un mensaje de error legible.</li>
|
||||
* <li>Un código HTTP asociado.</li>
|
||||
* <li>Un código interno único para identificar el tipo de error.</li>
|
||||
* </ul>
|
||||
*
|
||||
* Al lanzar esta excepción, los controladores o filtros pueden capturarla y devolver una respuesta estructurada
|
||||
* al cliente con la información correspondiente.
|
||||
*
|
||||
* @see ApiErrorCode
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Getter
|
||||
public class ResiException extends RuntimeException{
|
||||
|
||||
private final ApiErrorCode errorCode;
|
||||
|
||||
public ResiException(ApiErrorCode errorCode) {
|
||||
super(errorCode.getMessage());
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public int getStatusCode() {
|
||||
return errorCode.getHttpStatus().value();
|
||||
}
|
||||
|
||||
public HttpStatus getHttpStatus() {
|
||||
return errorCode.getHttpStatus();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package com.kevinolarte.resibenissa.models;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Modelo que representa un registro de acción en el sistema.
|
||||
* <p>
|
||||
* Esta clase almacena información sobre acciones realizadas por los usuarios,
|
||||
* incluyendo el nombre de la acción, una descripción, el correo del usuario que la realizó,ç
|
||||
* y la fecha de la acción.
|
||||
* <p>
|
||||
* @Author Kevin Olarte
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "logger")
|
||||
@Getter
|
||||
@Setter
|
||||
public class Logger {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String endpoint;
|
||||
private String metodo;
|
||||
|
||||
@Column(length = 1000)
|
||||
private String descripcion;
|
||||
private LocalDateTime fecha;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "id_padre")
|
||||
private Logger padre;
|
||||
|
||||
@OneToMany(mappedBy = "padre", cascade = CascadeType.ALL)
|
||||
private List<Logger> hijos = new ArrayList<>();
|
||||
|
||||
// Constructores
|
||||
public Logger() {}
|
||||
|
||||
public Logger(String endpoint, String metodo, String descripcion) {
|
||||
this.endpoint = endpoint;
|
||||
this.metodo = metodo;
|
||||
this.descripcion = descripcion;
|
||||
this.fecha = LocalDateTime.now();
|
||||
}
|
||||
|
||||
// Getters y setters
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
package com.kevinolarte.resibenissa.models;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.moduloOrgSalida.EventoSalida;
|
||||
import com.kevinolarte.resibenissa.models.modulojuego.Juego;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
|
||||
/**
|
||||
* Entidad que representa una residencia en la base de datos.
|
||||
* <p>
|
||||
* Cada residencia tiene un identificador, un nombre único y un correo electrónico.
|
||||
* Está relacionada con múltiples usuarios del sistema (como cuidadores o administradores),
|
||||
* así como con los residentes (personas mayores) que viven en ella.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "residencias")
|
||||
@Getter
|
||||
@Setter
|
||||
public class Residencia {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* Nombre de la residencia. Debe ser único.
|
||||
*/
|
||||
@Column(nullable = false, unique = true)
|
||||
private String nombre;
|
||||
|
||||
/**
|
||||
* Correo electrónico de contacto de la residencia. También debe ser único.
|
||||
*/
|
||||
@Column(unique = true, nullable = false)
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* Usuarios asociados a esta residencia (por ejemplo, personal que la gestiona).
|
||||
* Relación uno a muchos.
|
||||
*/
|
||||
@OneToMany(mappedBy = "residencia", cascade = CascadeType.ALL)
|
||||
@JsonIgnore
|
||||
private Set<User> usuarios = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* Residentes (personas mayores) que viven en esta residencia.
|
||||
* Relación uno a muchos.
|
||||
*/
|
||||
@OneToMany(mappedBy = "residencia", cascade = CascadeType.ALL)
|
||||
@JsonIgnore
|
||||
private Set<Residente> residentes = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* Eventos que tienen implementados en esta residencia
|
||||
* Relacion uno a muchos
|
||||
*/
|
||||
@OneToMany(mappedBy = "residencia", cascade = CascadeType.ALL)
|
||||
@JsonIgnore
|
||||
private Set<EventoSalida> eventos = new LinkedHashSet<>();
|
||||
|
||||
private boolean baja;
|
||||
private LocalDateTime fechaBaja;
|
||||
|
||||
|
||||
|
||||
public Residencia(String nombre, String email) {
|
||||
this.nombre = nombre;
|
||||
this.email = email;
|
||||
this.baja = false;
|
||||
|
||||
}
|
||||
|
||||
public Residencia() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
package com.kevinolarte.resibenissa.models;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.kevinolarte.resibenissa.models.moduloOrgSalida.Participante;
|
||||
import com.kevinolarte.resibenissa.models.moduloWallet.Wallet;
|
||||
import com.kevinolarte.resibenissa.models.modulojuego.RegistroJuego;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Entidad que representa a un residente (persona mayor) de una residencia.
|
||||
* <p>
|
||||
* A diferencia de {@link User}, los residentes no se autentican en el sistema.
|
||||
* Esta clase almacena datos personales y permite vincular al residente con su residencia,
|
||||
* así como con registros de actividades (como juegos, entrenos, etc).
|
||||
* <p>
|
||||
* Esta entidad es gestionada por usuarios autenticados del sistema.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "residentes")
|
||||
@Getter
|
||||
@Setter
|
||||
public class Residente {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String nombre;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String apellido;
|
||||
|
||||
@Column(name = "fecha_nacimiento",nullable = false)
|
||||
private LocalDate fechaNacimiento;
|
||||
|
||||
/**
|
||||
* documento de identidad del residente.
|
||||
* DNI o NIE.
|
||||
*/
|
||||
@Column(name = "documento_identidad", nullable = false, unique = true)
|
||||
private String docuemntoIdentidad;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String familiar1;
|
||||
|
||||
private String familiar2;
|
||||
|
||||
/**
|
||||
* Relación con la residencia donde vive este residente.
|
||||
* Múltiples residentes pueden estar en una misma residencia.
|
||||
*/
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fk_residencia", nullable = false)
|
||||
private Residencia residencia;
|
||||
|
||||
/**
|
||||
* Registros de juegos realizados por este residente.
|
||||
* Relación uno a muchos.
|
||||
*/
|
||||
@OneToMany(mappedBy = "residente", cascade = CascadeType.REMOVE)
|
||||
@JsonIgnore
|
||||
private Set<RegistroJuego> registros = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* Conjunto de veces que participa el resudente a las excuirsiones.
|
||||
*/
|
||||
@OneToMany(mappedBy = "residente", cascade = CascadeType.ALL)
|
||||
@JsonIgnore
|
||||
private Set<Participante> participantes = new LinkedHashSet<>();
|
||||
|
||||
@OneToOne(mappedBy = "residente", cascade = CascadeType.ALL)
|
||||
@JsonIgnore
|
||||
private Wallet wallet;
|
||||
|
||||
private boolean baja;
|
||||
private LocalDateTime fechaBaja;
|
||||
|
||||
public Residente(String nombre, String apellido, LocalDate fechaNacimiento, String documentoIdentidad, String familiar1, String familiar2) {
|
||||
this.nombre = nombre;
|
||||
this.apellido = apellido;
|
||||
this.fechaNacimiento = fechaNacimiento;
|
||||
this.docuemntoIdentidad = documentoIdentidad;
|
||||
this.baja = false;
|
||||
this.familiar1 = familiar1;
|
||||
this.familiar2 = familiar2;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public Residente(){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
package com.kevinolarte.resibenissa.models;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.kevinolarte.resibenissa.enums.Role;
|
||||
import com.kevinolarte.resibenissa.models.modulojuego.RegistroJuego;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Entidad que representa un usuario del sistema.
|
||||
* <p>
|
||||
* Implementa la interfaz {@link UserDetails} de Spring Security para integrarse
|
||||
* con el sistema de autenticación.
|
||||
* Cada usuario está asociado a una residencia.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "usuarios")
|
||||
@Setter
|
||||
@Getter
|
||||
public class User implements UserDetails {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String nombre;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String apellido;
|
||||
|
||||
/**
|
||||
* Correo electrónico del usuario, usado como username para iniciar sesión.
|
||||
* Debe ser único en el sistema.
|
||||
*/
|
||||
@Column(nullable = false, unique = true)
|
||||
private String email;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Código de verificación utilizado en el proceso de activación de la cuenta.
|
||||
*/
|
||||
@Column(name = "verification_code")
|
||||
private String verificationCode;
|
||||
|
||||
/**
|
||||
* Fecha y hora de expiración del código de verificación.
|
||||
*/
|
||||
@Column(name = "verification_expiration")
|
||||
private LocalDateTime verificationExpiration;
|
||||
|
||||
/**
|
||||
* Indica si el usuario está habilitado para acceder al sistema.
|
||||
*/
|
||||
private boolean enabled;
|
||||
|
||||
/**
|
||||
* Ruta de la foto de perfil.
|
||||
*/
|
||||
@Column(name = "foto_perfil")
|
||||
private String fotoPerfil;
|
||||
|
||||
/**
|
||||
* Roles o permisos del usuario. En este caso no se están usando, se devuelve una lista vacía.
|
||||
*/
|
||||
@JsonIgnore
|
||||
private boolean accountNonExpired;
|
||||
@JsonIgnore
|
||||
private boolean credentialsNonExpired;
|
||||
@JsonIgnore
|
||||
private boolean accountNonLocked;
|
||||
|
||||
/**
|
||||
* Relación con la residencia a la que pertenece el usuario.
|
||||
* Varios usuarios pueden estar asociados a la misma residencia.
|
||||
*/
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fk_residencia", nullable = false)
|
||||
@JsonIgnore
|
||||
private Residencia residencia;
|
||||
|
||||
private boolean baja;
|
||||
private LocalDateTime fechaBaja;
|
||||
|
||||
/**
|
||||
* Relacion con los registros de los juegos que son los que se encargan de asignar el jugador.
|
||||
* Para llevar un mayor control.
|
||||
* <p>
|
||||
* Este ususario puede tener varios registros.
|
||||
*/
|
||||
@OneToMany(mappedBy = "usuario")
|
||||
@JsonIgnore
|
||||
private Set<RegistroJuego> registroJuegos = new LinkedHashSet<>();
|
||||
|
||||
private Role role;
|
||||
|
||||
public User() {
|
||||
|
||||
}
|
||||
public User(String nombre, String apellido, String email, String password){
|
||||
this.nombre = nombre;
|
||||
this.apellido = apellido;
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
this.baja = false;
|
||||
this.role = Role.NORMAL;
|
||||
|
||||
}
|
||||
public User(String nombre, String apellido, String email, String password, Role role){
|
||||
this.nombre = nombre;
|
||||
this.apellido = apellido;
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
this.baja = false;
|
||||
this.role = role;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
if (role != null) {
|
||||
return List.of(new SimpleGrantedAuthority("ROLE_" + role));
|
||||
}
|
||||
return List.of();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword(){
|
||||
return this.password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.email; // el correo es usado como nombre de usuario
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "User{" +
|
||||
"nombre='" + nombre + '\'' +
|
||||
", id=" + id +
|
||||
", email='" + email + '\'' +
|
||||
", apellido='" + apellido + '\'' +
|
||||
", password='" + password + '\'' +
|
||||
", residencia=" + residencia.getId() +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package com.kevinolarte.resibenissa.models.moduloOrgSalida;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.kevinolarte.resibenissa.dto.in.moduloOrgSalida.EventoSalidaDto;
|
||||
import com.kevinolarte.resibenissa.enums.moduloOrgSalida.EstadoSalida;
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Representa un evento de salida organizado en el sistema.
|
||||
* <p>
|
||||
* Cada salida contiene información sobre su nombre, descripción, fecha de inicio y estado.
|
||||
* También mantiene una lista de residentes que participan en ella.
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
|
||||
@Entity
|
||||
@Table(name = "eventos")
|
||||
@Getter
|
||||
@Setter
|
||||
public class EventoSalida {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
|
||||
/**
|
||||
* Nombre del evento de salida.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private String nombre;
|
||||
|
||||
/**
|
||||
* Descripción del evento, explicando de qué trata o qué actividades incluye.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private String descripcion;
|
||||
|
||||
/**
|
||||
* Fecha en la que se realizará el evento de salida.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime fechaInicio;
|
||||
|
||||
/**
|
||||
* Estado actual del evento de salida.
|
||||
* <p>
|
||||
* Puede ser uno de los valores definidos en el enum {@link EstadoSalida}, como por ejemplo: PENDIENTE, REALIZADA, CANCELADA.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private EstadoSalida estado;
|
||||
|
||||
|
||||
/**
|
||||
* Conjunto de participantes que asisten a esta salida.
|
||||
* <p>
|
||||
* Relación uno-a-muchos con {@link Participante}, donde esta salida es la referencia inversa.
|
||||
* <p>
|
||||
* Se ignora en la serialización JSON para evitar bucles y sobrecarga de datos innecesarios.
|
||||
*/
|
||||
@OneToMany(mappedBy = "evento", cascade = CascadeType.REMOVE)
|
||||
@JsonIgnore
|
||||
private Set<Participante> participantes = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* Relación con la residencia donde pueden tener varias salidas.
|
||||
* Múltiples Eventos pueden estar en una misma residencia.
|
||||
*/
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fk_residencia")
|
||||
private Residencia residencia;
|
||||
|
||||
public EventoSalida(EventoSalidaDto e) {
|
||||
this.nombre = e.getNombre();
|
||||
this.descripcion = e.getDescripcion();
|
||||
this.fechaInicio = e.getFecha();
|
||||
this.estado = EstadoSalida.ABIERTO;
|
||||
}
|
||||
public EventoSalida() {}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
package com.kevinolarte.resibenissa.models.moduloOrgSalida;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.kevinolarte.resibenissa.dto.in.moduloOrgSalida.ParticipanteDto;
|
||||
import com.kevinolarte.resibenissa.models.Residente;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Representa la participación de un residente en un evento de salida.
|
||||
* <p>
|
||||
* Esta entidad contiene información sobre el residente que participa, la salida a la que asiste
|
||||
* y otros datos como si necesita ayuda y sus opiniones antes y después del evento.
|
||||
* <p>
|
||||
* Se asegura que no pueda existir más de un participante con la misma combinación
|
||||
* de {@code fk_salida} y {@code fk_residente}, garantizando que un residente no se registre
|
||||
* dos veces en la misma salida.
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(
|
||||
name = "participantes",
|
||||
uniqueConstraints = {
|
||||
@UniqueConstraint(columnNames = {"fk_evento", "fk_residente"})
|
||||
}
|
||||
)
|
||||
public class Participante {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* Evento de salida en el que participa el residente.
|
||||
* <p>
|
||||
* Relación muchos-a-uno con {@link EventoSalida}.
|
||||
* Esta relación es ignorada en la serialización JSON para evitar bucles.
|
||||
*/
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fk_evento", nullable = false)
|
||||
@JsonIgnore
|
||||
private EventoSalida evento;
|
||||
|
||||
/**
|
||||
* Residente que participa en la salida.
|
||||
* <p>
|
||||
* Relación muchos-a-uno con {@link Residente}.
|
||||
* Esta relación es ignorada en la serialización JSON para evitar bucles.
|
||||
*/
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fk_residente", nullable = false)
|
||||
@JsonIgnore
|
||||
private Residente residente;
|
||||
|
||||
/**
|
||||
* Indica si el residente requiere ayuda durante la salida.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private boolean recursosHumanos;
|
||||
|
||||
@Column(nullable = false)
|
||||
private boolean recursosMateriales;
|
||||
|
||||
private boolean asistenciaPermitida;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Opinión del residente antes de asistir a la salida (opcional).
|
||||
*/
|
||||
private String preOpinion;
|
||||
|
||||
|
||||
/**
|
||||
* Opinión del residente después de asistir a la salida (opcional).
|
||||
*/
|
||||
private String postOpinion;
|
||||
|
||||
|
||||
private boolean baja;
|
||||
private LocalDateTime fechaBaja;
|
||||
|
||||
|
||||
public Participante() {
|
||||
this.recursosHumanos = false;
|
||||
this.recursosMateriales = false;
|
||||
this.preOpinion = "";
|
||||
this.postOpinion = "";
|
||||
this.baja = false;
|
||||
this.asistenciaPermitida = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.kevinolarte.resibenissa.models.moduloWallet;
|
||||
|
||||
import com.kevinolarte.resibenissa.enums.moduloWallet.TipoMovimiento;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Setter
|
||||
@Getter
|
||||
public class MovimientoWallet {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fk_wallet", nullable = false)
|
||||
private Wallet wallet;
|
||||
|
||||
private Double cantidad;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private TipoMovimiento tipo; // IN / OUT
|
||||
|
||||
private String concepto;
|
||||
|
||||
private LocalDateTime fecha;
|
||||
|
||||
public MovimientoWallet() {
|
||||
// Constructor por defecto
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.kevinolarte.resibenissa.models.moduloWallet;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.Residente;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
public class Wallet {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name = "fk_residente", unique = true)
|
||||
private Residente residente;
|
||||
|
||||
private Double saldoTotal;
|
||||
|
||||
@OneToMany(mappedBy = "wallet", cascade = CascadeType.ALL)
|
||||
private Set<MovimientoWallet> movimientos = new LinkedHashSet<>();
|
||||
public Wallet() {
|
||||
this.saldoTotal = 0.0;
|
||||
this.movimientos = new LinkedHashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Wallet{" +
|
||||
"id=" + id +
|
||||
", residente=" + residente +
|
||||
", saldoTotal=" + saldoTotal +
|
||||
", movimientos=" + movimientos +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package com.kevinolarte.resibenissa.models.modulojuego;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Entidad que representa un juego disponible en una residencia.
|
||||
* <p>
|
||||
* Cada juego tiene un nombre único dentro de su residencia.
|
||||
* Está asociado a múltiples registros que indican cuándo y cómo fue jugado por los residentes.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Entity
|
||||
@Table(
|
||||
name = "juegos"
|
||||
|
||||
)
|
||||
@Getter
|
||||
@Setter
|
||||
public class Juego {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* Nombre del juego. Debe ser único dentro de cada residencia.
|
||||
*/
|
||||
@Column(nullable = false, unique = true)
|
||||
private String nombre;
|
||||
|
||||
|
||||
/**
|
||||
* Registros de uso de este juego por parte de residentes.
|
||||
*/
|
||||
@OneToMany(mappedBy = "juego", cascade = CascadeType.REMOVE)
|
||||
@JsonIgnore
|
||||
private Set<RegistroJuego> registro = new LinkedHashSet<>();
|
||||
|
||||
public Juego(String nombre){
|
||||
this.nombre = nombre;
|
||||
}
|
||||
public Juego(){}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Juego{" +
|
||||
"id=" + id +
|
||||
", nombre='" + nombre + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
package com.kevinolarte.resibenissa.models.modulojuego;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.modulojuego.RegistroJuegoDto;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.Dificultad;
|
||||
import com.kevinolarte.resibenissa.models.Residente;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Entidad que representa un registro del uso de un juego por parte de un residente.
|
||||
* <p>
|
||||
* Cada vez que un residente juega, se guarda un registro con la fecha, la duración
|
||||
* del juego y el número de fallos cometidos.
|
||||
* Este historial puede ser usado para analizar la evolución cognitiva o motriz del residente.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "registros_juegos")
|
||||
@Getter
|
||||
@Setter
|
||||
public class RegistroJuego {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* Residente que ha jugado.
|
||||
*/
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "fk_residente")
|
||||
private Residente residente;
|
||||
|
||||
/**
|
||||
* Juego que fue utilizado.
|
||||
*/
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "fk_juego")
|
||||
private Juego juego;
|
||||
|
||||
/**
|
||||
* Trabajador que registra la partida.
|
||||
*/
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fk_usuario")
|
||||
private User usuario;
|
||||
|
||||
/**
|
||||
* Fecha en la que se jugó.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime fecha;
|
||||
|
||||
/**
|
||||
* Número de fallos cometidos por el residente durante el juego.
|
||||
*/
|
||||
private Integer num;
|
||||
|
||||
/**
|
||||
* Duración del juego en segundos (o minutos, según convención del sistema).
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private Double duracion;
|
||||
|
||||
private Dificultad dificultad;
|
||||
private String observacion;
|
||||
|
||||
public RegistroJuego(RegistroJuegoDto input) {
|
||||
this.num = input.getNum();
|
||||
this.duracion = input.getDuracion();
|
||||
this.fecha = LocalDateTime.now();
|
||||
this.dificultad = input.getDificultad();
|
||||
this.observacion = "";
|
||||
}
|
||||
public RegistroJuego(RegistroJuegoDto input, LocalDateTime fecha) {
|
||||
this.num = input.getNum();
|
||||
this.duracion = input.getDuracion();
|
||||
this.fecha = fecha;
|
||||
this.dificultad = input.getDificultad();
|
||||
this.observacion = "";
|
||||
}
|
||||
|
||||
public RegistroJuego() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.kevinolarte.resibenissa.repositories;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.Logger;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface LoggerRepository extends JpaRepository<Logger, Long> {
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package com.kevinolarte.resibenissa.repositories;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Repositorio para acceder y gestionar entidades {@link Residencia}.
|
||||
* <p>
|
||||
* Proporciona métodos personalizados para buscar residencias por nombre o correo electrónico,
|
||||
* además de los métodos estándar de {@link JpaRepository}.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Repository
|
||||
public interface ResidenciaRepository extends JpaRepository<Residencia, Long> {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Busca una residencia por su correo electrónico.
|
||||
*
|
||||
* @param email Correo electrónico de la residencia.
|
||||
* @return Un Optional con la residencia si se encuentra.
|
||||
*/
|
||||
Optional<Residencia> findByEmail(String email);
|
||||
|
||||
/**
|
||||
* Busca una residencia por su nombre.
|
||||
*
|
||||
* @param nombre Nombre de la residencia.
|
||||
* @return Un Optional con la residencia si se encuentra.
|
||||
*/
|
||||
Optional<Residencia> findByNombre(String nombre);
|
||||
|
||||
/**
|
||||
* Busca residencias que estén marcadas como dadas de baja.
|
||||
*
|
||||
* @return Lista de residencias que tienen el campo baja en true.
|
||||
*/
|
||||
List<Residencia> findByBajaTrue();
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package com.kevinolarte.resibenissa.repositories;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
import com.kevinolarte.resibenissa.models.Residente;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Repositorio para acceder y gestionar entidades {@link Residente}.
|
||||
* <p>
|
||||
* Permite realizar operaciones CRUD y buscar residentes por su residencia.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Repository
|
||||
public interface ResidenteRepository extends JpaRepository<Residente, Long>, JpaSpecificationExecutor<Residente>{
|
||||
|
||||
|
||||
/**
|
||||
* Busca residentes por su documento de identidad.
|
||||
* @param docuemntoIdentidad Documento de identidad del residente.
|
||||
* @return residente que coincide con el documento de identidad proporcionado.
|
||||
*/
|
||||
Residente findByDocuemntoIdentidad(String docuemntoIdentidad);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package com.kevinolarte.resibenissa.repositories;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Repositorio para gestionar entidades {@link User}.
|
||||
* <p>
|
||||
* Proporciona métodos personalizados para buscar usuarios por correo electrónico
|
||||
* o por la residencia a la que pertenecen, además de los métodos básicos de {@link JpaRepository}.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Repository
|
||||
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
|
||||
|
||||
/**
|
||||
* Busca un usuario por su correo electrónico.
|
||||
*
|
||||
* @param email Correo electrónico del usuario a buscar.
|
||||
* @return Usuario encontrado o {@code null} si no existe.
|
||||
*/
|
||||
User findByEmail(String email);
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.kevinolarte.resibenissa.repositories.moduloOrgSalida;
|
||||
|
||||
import com.kevinolarte.resibenissa.enums.moduloOrgSalida.EstadoSalida;
|
||||
import com.kevinolarte.resibenissa.models.moduloOrgSalida.EventoSalida;
|
||||
import jakarta.transaction.Transactional;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import java.time.LocalDate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface EventoSalidaRepository extends JpaRepository<EventoSalida, Long>, JpaSpecificationExecutor<EventoSalida> {
|
||||
|
||||
/**
|
||||
* Exsite un nombre igual en la misma residencia
|
||||
*/
|
||||
boolean existsByNombreAndResidenciaId(String nombre, Long residenciaId);
|
||||
|
||||
/**
|
||||
* Elimina todos los eventos de salida asociados a una residencia.
|
||||
* @param idResidencia ID de la residencia cuyos eventos de salida
|
||||
*/
|
||||
@Modifying
|
||||
@Transactional
|
||||
@Query("DELETE FROM EventoSalida p WHERE p.residencia.id = :idResidencia")
|
||||
void deleteAllByResidenciaId(@Param("idResidencia") Long idResidencia);
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene el evento de salida por su nombre y id de residencia perteneciente.
|
||||
* @param nombre Nombre del evento de salida a buscar.
|
||||
* @param residenciaId ID de la residencia a la que pertenece el evento de salida.
|
||||
* @return EventoSalida si se encuentra, null en caso contrario.
|
||||
*/
|
||||
EventoSalida findByNombreAndResidencia_Id(String nombre, Long residenciaId);
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package com.kevinolarte.resibenissa.repositories.moduloOrgSalida;
|
||||
|
||||
|
||||
import com.kevinolarte.resibenissa.models.Residente;
|
||||
import com.kevinolarte.resibenissa.models.moduloOrgSalida.EventoSalida;
|
||||
import com.kevinolarte.resibenissa.models.moduloOrgSalida.Participante;
|
||||
import jakarta.transaction.Transactional;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface ParticipanteRepository extends JpaRepository<Participante, Long>, JpaSpecificationExecutor<Participante> {
|
||||
|
||||
/**
|
||||
* Verifica si un residente esta inscrito el otro evento a partir del idEvento
|
||||
* @param idResidente ID del residente
|
||||
* @param idEvento ID del evento actual
|
||||
* @return true si el residente está inscrito en otro evento el mismo día, false en caso contrario
|
||||
*/
|
||||
@Query("""
|
||||
SELECT COUNT(p) > 0
|
||||
FROM Participante p
|
||||
WHERE p.residente.id = :idResidente
|
||||
AND p.evento.fechaInicio = (
|
||||
SELECT s.fechaInicio
|
||||
FROM EventoSalida s
|
||||
WHERE s.id = :idEvento
|
||||
)
|
||||
AND p.evento.id <> :idEvento
|
||||
""")
|
||||
boolean existsByResidenteInOtherEventoSameDay(
|
||||
@Param("idResidente") Long idResidente,
|
||||
@Param("idEvento") Long idEvento
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Verifica si un residente está inscrito en un evento específico.
|
||||
*
|
||||
* @param idResidente ID del residente.
|
||||
* @param idEvento ID del evento.
|
||||
* @return true si el residente está inscrito en el evento, false en caso contrario.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT COUNT(p) > 0
|
||||
FROM Participante p
|
||||
WHERE p.residente.id = :idResidente
|
||||
AND p.evento.id = :idEvento
|
||||
AND p.baja = false
|
||||
""")
|
||||
boolean isResidenteInscritoEnEvento(Long idResidente, Long idEvento);
|
||||
|
||||
/**
|
||||
* Elimina todos los participantes asociados a una residencia específica.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
*/
|
||||
@Modifying
|
||||
@Transactional
|
||||
@Query("DELETE FROM Participante p WHERE p.residente.residencia.id = :idResidencia")
|
||||
void deleteAllByResidenciaId(@Param("idResidencia") Long idResidencia);
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.kevinolarte.resibenissa.repositories.moduloWallet;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.moduloWallet.MovimientoWallet;
|
||||
import com.kevinolarte.resibenissa.models.moduloWallet.Wallet;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface MovimientoWalletRepository extends JpaRepository<MovimientoWallet, Long> {
|
||||
List<MovimientoWallet> findByWallet(Wallet wallet);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.kevinolarte.resibenissa.repositories.moduloWallet;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.moduloWallet.Wallet;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface WalletRepository extends JpaRepository<Wallet, Long> {
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.kevinolarte.resibenissa.repositories.modulojuego;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
import com.kevinolarte.resibenissa.models.modulojuego.Juego;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Repositorio para acceder y gestionar entidades de tipo {@link Juego}.
|
||||
* <p>
|
||||
* Extiende {@link JpaRepository} para aprovechar métodos CRUD y de paginación,
|
||||
* y define métodos personalizados para búsquedas por nombre y residencia.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Repository
|
||||
public interface JuegoRepository extends JpaRepository<Juego, Long> {
|
||||
|
||||
|
||||
/**
|
||||
* Busca si existe juegos por su nombre, ignorando mayúsculas y minúsculas.
|
||||
* @param nombre Nombre del juego a buscar.
|
||||
* @return Lista de juegos que coinciden con el nombre dado.
|
||||
*/
|
||||
boolean existsByNombreIgnoreCase(String nombre);
|
||||
|
||||
/**
|
||||
* Busca juegos cuyo nombre contenga una cadena específica, ignorando mayúsculas y minúsculas.
|
||||
* @param nombre Cadena a buscar en el nombre del juego.
|
||||
* @return Lista de juegos que contienen la cadena en su nombre.
|
||||
*/
|
||||
List<Juego> findByNombreContainingIgnoreCase(String nombre);
|
||||
}
|
||||
|
|
@ -0,0 +1,647 @@
|
|||
package com.kevinolarte.resibenissa.repositories.modulojuego;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO;
|
||||
import com.kevinolarte.resibenissa.enums.modulojuego.Dificultad;
|
||||
import com.kevinolarte.resibenissa.models.modulojuego.Juego;
|
||||
import com.kevinolarte.resibenissa.models.modulojuego.RegistroJuego;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Repositorio para acceder y gestionar registros de juegos ({@link RegistroJuego}).
|
||||
* <p>
|
||||
* Permite obtener estadísticas o historiales de juegos filtrando por residencia,
|
||||
* por juego, por residente o por fecha.
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Repository
|
||||
public interface RegistroJuegoRepository extends JpaRepository<RegistroJuego, Long>, JpaSpecificationExecutor<RegistroJuego> {
|
||||
|
||||
|
||||
/**
|
||||
* Calcula el promedio diario de duración de los registros de juego de un residente específico.
|
||||
*
|
||||
* <p>
|
||||
* Se agrupan los registros por día (formato YYYY-MM-DD), y se calcula la duración media y el total de registros
|
||||
* por cada día. Permite filtrar por dificultad y por un juego concreto (ambos opcionales).
|
||||
* </p>
|
||||
*
|
||||
* @param idResidente ID del residente a analizar.
|
||||
* @param dificultad Nivel de dificultad a filtrar (opcional, puede ser {@code null}).
|
||||
* @param idJuego ID del juego a filtrar (opcional, puede ser {@code null} para incluir todos).
|
||||
* @return Lista de {@link MediaRegistroDTO} con fecha (día), duración media y cantidad de registros por día.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM-DD'), AVG(r.duracion), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.residente.id = :idResidente
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionDiaria(@Param("idResidente") Long idResidente,
|
||||
@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
|
||||
/**
|
||||
* Calcula el promedio mensual de duración de los registros de juego de un residente específico.
|
||||
*
|
||||
* <p>
|
||||
* Agrupa por mes (formato YYYY-MM), mostrando duración media y número de registros por cada mes.
|
||||
* Se puede filtrar por dificultad y juego (ambos opcionales).
|
||||
* </p>
|
||||
*
|
||||
* @param idResidente ID del residente.
|
||||
* @param dificultad Dificultad del juego (opcional).
|
||||
* @param idJuego ID del juego a filtrar (opcional, puede ser {@code null} para todos los juegos).
|
||||
* @return Lista de {@link MediaRegistroDTO} con la media mensual de duración y el total de registros.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM'), AVG(r.duracion), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.residente.id = :idResidente
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionMensual(@Param("idResidente") Long idResidente,
|
||||
@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
|
||||
/**
|
||||
* Calcula el promedio anual de duración de los registros de juego de un residente específico.
|
||||
*
|
||||
* <p>
|
||||
* Agrupa por año (YYYY) y devuelve la duración media y el total de registros de cada año.
|
||||
* Se puede aplicar filtro por dificultad y juego.
|
||||
* </p>
|
||||
*
|
||||
* @param idResidente ID del residente cuyos registros se agrupan.
|
||||
* @param dificultad Dificultad del juego (opcional).
|
||||
* @param idJuego ID del juego a filtrar (opcional, puede ser {@code null}).
|
||||
* @return Lista de {@link MediaRegistroDTO} con año, duración media y conteo de registros por año.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(CAST(EXTRACT(YEAR FROM r.fecha) AS string), AVG(r.duracion), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.residente.id = :idResidente
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY EXTRACT(YEAR FROM r.fecha)
|
||||
ORDER BY EXTRACT(YEAR FROM r.fecha)
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionAnual(@Param("idResidente") Long idResidente,
|
||||
@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Calcula el promedio diario de errores cometidos por un residente específico.
|
||||
*
|
||||
* <p>
|
||||
* Agrupa los registros por día (formato YYYY-MM-DD), y calcula el promedio de errores (`num`)
|
||||
* y el total de registros por día. Permite filtrar por dificultad y juego de forma opcional.
|
||||
* </p>
|
||||
*
|
||||
* @param idResidente ID del residente a analizar.
|
||||
* @param dificultad Nivel de dificultad del juego (opcional).
|
||||
* @param idJuego ID del juego a filtrar (opcional, {@code null} para incluir todos).
|
||||
* @return Lista de {@link MediaRegistroDTO} con fecha (día), promedio de errores y número total de registros por día.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM-DD'), AVG(r.num), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.residente.id = :idResidente
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresDiario(@Param("idResidente") Long idResidente,
|
||||
@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
|
||||
/**
|
||||
* Calcula el promedio mensual de errores cometidos por un residente específico.
|
||||
*
|
||||
* <p>
|
||||
* Agrupa por mes (formato YYYY-MM), y devuelve el promedio de errores (`num`)
|
||||
* junto con el total de registros por cada mes. Se puede filtrar por dificultad y juego.
|
||||
* </p>
|
||||
*
|
||||
* @param idResidente ID del residente.
|
||||
* @param dificultad Dificultad del juego (opcional).
|
||||
* @param idJuego ID del juego a filtrar (opcional, {@code null} para incluir todos).
|
||||
* @return Lista de {@link MediaRegistroDTO} con promedio mensual de errores y conteo de registros.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM'), AVG(r.num), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.residente.id = :idResidente
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresMensual(@Param("idResidente") Long idResidente,
|
||||
@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
|
||||
/**
|
||||
* Calcula el promedio anual de errores cometidos por un residente específico.
|
||||
*
|
||||
* <p>
|
||||
* Agrupa por año (YYYY), devolviendo el promedio de errores (`num`)
|
||||
* y el total de registros por cada año. Admite filtros opcionales por dificultad y juego.
|
||||
* </p>
|
||||
*
|
||||
* @param idResidente ID del residente cuyos registros se analizarán.
|
||||
* @param dificultad Nivel de dificultad (opcional).
|
||||
* @param idJuego ID del juego (opcional, {@code null} para todos los juegos).
|
||||
* @return Lista de {@link MediaRegistroDTO} con año, promedio de errores y total de registros por año.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(CAST(EXTRACT(YEAR FROM r.fecha) AS string), AVG(r.num), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.residente.id = :idResidente
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY EXTRACT(YEAR FROM r.fecha)
|
||||
ORDER BY EXTRACT(YEAR FROM r.fecha)
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresAnual(@Param("idResidente") Long idResidente,
|
||||
@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Calcula el promedio mensual de duración de los juegos jugados por todos los residentes
|
||||
* de una residencia, con opción de filtrar por dificultad.
|
||||
*
|
||||
* @param idResidencia ID de la residencia cuyos residentes serán considerados.
|
||||
* @param dificultad Dificultad específica a filtrar (puede ser null para ignorar el filtro).
|
||||
* @param idJuego ID del juego a filtrar (puede ser null para ignorar el filtro).
|
||||
* @return Lista de {@link MediaRegistroDTO} donde cada elemento representa un mes y su promedio de duración.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM'), AVG(r.duracion), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.residente.residencia.id = :idResidencia
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionResidenciaMensual(@Param("idResidencia") Long idResidencia,
|
||||
@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
/**
|
||||
* Calcula el promedio anual de duración de los juegos jugados por todos los residentes
|
||||
* de una residencia, con opción de filtrar por dificultad.
|
||||
*
|
||||
* @param idResidencia ID de la residencia cuyos residentes serán considerados.
|
||||
* @param dificultad Dificultad específica a filtrar (puede ser null para ignorar el filtro).
|
||||
* @param idJuego ID del juego a filtrar (puede ser null para ignorar el filtro).
|
||||
* @return Lista de {@link MediaRegistroDTO} donde cada elemento representa un año y su promedio de duración.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(CAST(EXTRACT(YEAR FROM r.fecha) AS string), AVG(r.duracion), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.residente.residencia.id = :idResidencia
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY EXTRACT(YEAR FROM r.fecha)
|
||||
ORDER BY EXTRACT(YEAR FROM r.fecha)
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionResidenciaAnual(@Param("idResidencia") Long idResidencia,
|
||||
@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
/**
|
||||
* Calcula el promedio diario de errores cometidos en los juegos por todos los residentes
|
||||
* de una residencia específica, con opción de filtrar por dificultad.
|
||||
*
|
||||
* @param idResidencia ID de la residencia cuyos residentes se van a considerar.
|
||||
* @param dificultad Dificultad de los juegos a filtrar (si es null, se consideran todas las dificultades).
|
||||
* @param idJuego ID del juego a filtrar (puede ser null para ignorar el filtro).
|
||||
* @return Lista de {@link MediaRegistroDTO} donde cada elemento representa un día y el promedio de errores cometidos.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM-DD'), AVG(r.num), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.residente.residencia.id = :idResidencia
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresResidenciaDiaria(@Param("idResidencia") Long idResidencia,
|
||||
@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
/**
|
||||
* Calcula el promedio diario de duración de los juegos jugados por todos los residentes
|
||||
* de una residencia, con opción de filtrar por dificultad.
|
||||
*
|
||||
* @param idResidencia ID de la residencia cuyos residentes serán considerados.
|
||||
* @param idJuego ID del juego a filtrar (puede ser null para ignorar el filtro).
|
||||
* @param dificultad Dificultad específica a filtrar (puede ser null para ignorar el filtro).
|
||||
* @return Lista de {@link MediaRegistroDTO} donde cada elemento representa un día y su promedio de duración.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM-DD'), AVG(r.duracion), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.residente.residencia.id = :idResidencia
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionResidenciaDiaria(@Param("idResidencia") Long idResidencia,
|
||||
@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
/**
|
||||
* Calcula el promedio mensual de errores cometidos en los juegos por todos los residentes
|
||||
* de una residencia específica, con opción de filtrar por dificultad.
|
||||
*
|
||||
* @param idResidencia ID de la residencia cuyos residentes se van a considerar.
|
||||
* @param dificultad Dificultad de los juegos a filtrar (si es null, se consideran todas las dificultades).
|
||||
* @param idJuego ID del juego a filtrar (puede ser null para ignorar el filtro).
|
||||
* @return Lista de {@link MediaRegistroDTO} donde cada elemento representa un mes y el promedio de errores cometidos.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM'), AVG(r.num), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.residente.residencia.id = :idResidencia
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresResidenciaMensual(@Param("idResidencia") Long idResidencia,
|
||||
@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
/**
|
||||
* Calcula el promedio anual de errores cometidos en los juegos por todos los residentes
|
||||
* de una residencia específica, con opción de filtrar por dificultad.
|
||||
*
|
||||
* @param idResidencia ID de la residencia cuyos residentes se van a considerar.
|
||||
* @param dificultad Dificultad de los juegos a filtrar (si es null, se consideran todas las dificultades).
|
||||
* @param idJuego ID del juego a filtrar (puede ser null para ignorar el filtro).
|
||||
* @return Lista de {@link MediaRegistroDTO} donde cada elemento representa un año y el promedio de errores cometidos.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(CAST(EXTRACT(YEAR FROM r.fecha) AS string), AVG(r.num), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.residente.residencia.id = :idResidencia
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY EXTRACT(YEAR FROM r.fecha)
|
||||
ORDER BY EXTRACT(YEAR FROM r.fecha)
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresResidenciaAnual(@Param("idResidencia") Long idResidencia,
|
||||
@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
|
||||
/**
|
||||
* Calcula el promedio diario de errores a nivel global,
|
||||
* con posibilidad de filtrar por dificultad y juego.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(
|
||||
TO_CHAR(r.fecha, 'YYYY-MM-DD'),
|
||||
AVG(r.num),
|
||||
COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresGlobalDiaria(@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
|
||||
/**
|
||||
* Calcula el promedio mensual de errores a nivel global,
|
||||
* con posibilidad de filtrar por dificultad y juego.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(
|
||||
TO_CHAR(r.fecha, 'YYYY-MM'),
|
||||
AVG(r.num),
|
||||
COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresGlobalMensual(@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
/**
|
||||
* Calcula el promedio anual de errores a nivel global,
|
||||
* con posibilidad de filtrar por dificultad y juego.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(
|
||||
CAST(EXTRACT(YEAR FROM r.fecha) AS string),
|
||||
AVG(r.num),
|
||||
COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY EXTRACT(YEAR FROM r.fecha)
|
||||
ORDER BY EXTRACT(YEAR FROM r.fecha)
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresGlobalAnual(@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
|
||||
/**
|
||||
* Calcula la media diaria de duración de juegos a nivel global,
|
||||
* con posibilidad de filtrar por dificultad y juego.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(
|
||||
TO_CHAR(r.fecha, 'YYYY-MM-DD'),
|
||||
AVG(r.duracion),
|
||||
COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionGlobalDiaria(@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
/**
|
||||
* Calcula la media mensual de duración de juegos a nivel global,
|
||||
* con posibilidad de filtrar por dificultad y juego.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(
|
||||
TO_CHAR(r.fecha, 'YYYY-MM'),
|
||||
AVG(r.duracion),
|
||||
COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionGlobalMensual(@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
|
||||
/**
|
||||
* Calcula la media anual de duración de juegos a nivel global,
|
||||
* con posibilidad de filtrar por dificultad y juego.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(
|
||||
CAST(EXTRACT(YEAR FROM r.fecha) AS string),
|
||||
AVG(r.duracion),
|
||||
COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
AND (:idJuego IS NULL OR r.juego.id = :idJuego)
|
||||
GROUP BY EXTRACT(YEAR FROM r.fecha)
|
||||
ORDER BY EXTRACT(YEAR FROM r.fecha)
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionGlobalAnual(@Param("dificultad") Dificultad dificultad,
|
||||
@Param("idJuego") Long idJuego);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Calcula el promedio diario de errores en los juegos jugados por todos los residentes para un juego específico.
|
||||
*
|
||||
* @param idJuego ID del juego a analizar.
|
||||
* @param dificultad Dificultad a filtrar (puede ser null para incluir todas).
|
||||
* @return Lista de {@link MediaRegistroDTO} agrupada por día.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM-DD'), AVG(r.num), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.juego.id = :idJuego AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresPorJuegoDiaria(@Param("idJuego") Long idJuego,
|
||||
@Param("dificultad") Dificultad dificultad);
|
||||
|
||||
/**
|
||||
* Calcula el promedio mensual de errores para un juego específico.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM'), AVG(r.num), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.juego.id = :idJuego AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresPorJuegoMensual(@Param("idJuego") Long idJuego,
|
||||
@Param("dificultad") Dificultad dificultad);
|
||||
|
||||
/**
|
||||
* Calcula el promedio anual de errores para un juego específico.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(CAST(EXTRACT(YEAR FROM r.fecha) AS string), AVG(r.num), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.juego.id = :idJuego AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
GROUP BY EXTRACT(YEAR FROM r.fecha)
|
||||
ORDER BY EXTRACT(YEAR FROM r.fecha)
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresPorJuegoAnual(@Param("idJuego") Long idJuego,
|
||||
@Param("dificultad") Dificultad dificultad);
|
||||
|
||||
/**
|
||||
* Calcula el promedio diario de duración de un juego específico.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM-DD'), AVG(r.duracion),COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.juego.id = :idJuego AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionPorJuegoDiaria(@Param("idJuego") Long idJuego,
|
||||
@Param("dificultad") Dificultad dificultad);
|
||||
|
||||
/**
|
||||
* Calcula el promedio mensual de duración de un juego específico.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM'), AVG(r.duracion), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.juego.id = :idJuego AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionPorJuegoMensual(@Param("idJuego") Long idJuego,
|
||||
@Param("dificultad") Dificultad dificultad);
|
||||
|
||||
/**
|
||||
* Calcula el promedio anual de duración de un juego específico.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(CAST(EXTRACT(YEAR FROM r.fecha) AS string), AVG(r.duracion), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.juego.id = :idJuego AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
GROUP BY EXTRACT(YEAR FROM r.fecha)
|
||||
ORDER BY EXTRACT(YEAR FROM r.fecha)
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionPorJuegoAnual(@Param("idJuego") Long idJuego,
|
||||
@Param("dificultad") Dificultad dificultad);
|
||||
|
||||
|
||||
/**
|
||||
* Calcula el promedio diario de duración del juego especificado,
|
||||
* considerando únicamente los registros pertenecientes a los residentes de una residencia específica.
|
||||
*
|
||||
* @param idJuego ID del juego cuyos registros se analizarán.
|
||||
* @param idResidencia ID de la residencia cuyos residentes serán tenidos en cuenta.
|
||||
* @param dificultad Nivel de dificultad a filtrar (opcional, puede ser null para incluir todas).
|
||||
* @return Lista de {@link MediaRegistroDTO} donde cada entrada representa un día con el promedio de duración.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM-DD'), AVG(r.duracion),COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.juego.id = :idJuego AND r.residente.residencia.id = :idResidencia
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionPorJuegoYResidenciaDiaria(@Param("idJuego") Long idJuego,
|
||||
@Param("idResidencia") Long idResidencia,
|
||||
@Param("dificultad") Dificultad dificultad);
|
||||
|
||||
/**
|
||||
* Calcula el promedio mensual de duración del juego especificado,
|
||||
* considerando únicamente los registros pertenecientes a los residentes de una residencia específica.
|
||||
*
|
||||
* @param idJuego ID del juego cuyos registros se analizarán.
|
||||
* @param idResidencia ID de la residencia cuyos residentes serán tenidos en cuenta.
|
||||
* @param dificultad Nivel de dificultad a filtrar (opcional, puede ser null para incluir todas).
|
||||
* @return Lista de {@link MediaRegistroDTO} donde cada entrada representa un mes con el promedio de duración.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM'), AVG(r.duracion), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.juego.id = :idJuego AND r.residente.residencia.id = :idResidencia
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionPorJuegoYResidenciaMensual(@Param("idJuego") Long idJuego,
|
||||
@Param("idResidencia") Long idResidencia,
|
||||
@Param("dificultad") Dificultad dificultad);
|
||||
|
||||
/**
|
||||
* Calcula el promedio anual de duración del juego especificado,
|
||||
* considerando únicamente los registros pertenecientes a los residentes de una residencia específica.
|
||||
*
|
||||
* @param idJuego ID del juego cuyos registros se analizarán.
|
||||
* @param idResidencia ID de la residencia cuyos residentes serán tenidos en cuenta.
|
||||
* @param dificultad Nivel de dificultad a filtrar (opcional, puede ser null para incluir todas).
|
||||
* @return Lista de {@link MediaRegistroDTO} donde cada entrada representa un año con el promedio de duración.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(CAST(EXTRACT(YEAR FROM r.fecha) AS string), AVG(r.duracion), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.juego.id = :idJuego AND r.residente.residencia.id = :idResidencia
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
GROUP BY EXTRACT(YEAR FROM r.fecha)
|
||||
ORDER BY EXTRACT(YEAR FROM r.fecha)
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaDuracionPorJuegoYResidenciaAnual(@Param("idJuego") Long idJuego,
|
||||
@Param("idResidencia") Long idResidencia,
|
||||
@Param("dificultad") Dificultad dificultad);
|
||||
|
||||
|
||||
/**
|
||||
* Calcula el promedio diario de errores del juego especificado,
|
||||
* considerando únicamente los registros pertenecientes a los residentes de una residencia específica.
|
||||
*
|
||||
* @param idJuego ID del juego cuyos registros se analizarán.
|
||||
* @param idResidencia ID de la residencia cuyos residentes serán tenidos en cuenta.
|
||||
* @param dificultad Nivel de dificultad a filtrar (opcional, puede ser null para incluir todas).
|
||||
* @return Lista de {@link MediaRegistroDTO} donde cada entrada representa un día con el promedio de errores.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM-DD'), AVG(r.num), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.juego.id = :idJuego AND r.residente.residencia.id = :idResidencia
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM-DD')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresPorJuegoYResidenciaDiaria(@Param("idJuego") Long idJuego,
|
||||
@Param("idResidencia") Long idResidencia,
|
||||
@Param("dificultad") Dificultad dificultad);
|
||||
|
||||
/**
|
||||
* Calcula el promedio mensual de errores del juego especificado,
|
||||
* considerando únicamente los registros pertenecientes a los residentes de una residencia específica.
|
||||
*
|
||||
* @param idJuego ID del juego cuyos registros se analizarán.
|
||||
* @param idResidencia ID de la residencia cuyos residentes serán tenidos en cuenta.
|
||||
* @param dificultad Nivel de dificultad a filtrar (opcional, puede ser null para incluir todas).
|
||||
* @return Lista de {@link MediaRegistroDTO} donde cada entrada representa un mes con el promedio de errores.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(TO_CHAR(r.fecha, 'YYYY-MM'), AVG(r.num), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.juego.id = :idJuego AND r.residente.residencia.id = :idResidencia
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
GROUP BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
ORDER BY TO_CHAR(r.fecha, 'YYYY-MM')
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresPorJuegoYResidenciaMensual(@Param("idJuego") Long idJuego,
|
||||
@Param("idResidencia") Long idResidencia,
|
||||
@Param("dificultad") Dificultad dificultad);
|
||||
|
||||
/**
|
||||
* Calcula el promedio anual de errores del juego especificado,
|
||||
* considerando únicamente los registros pertenecientes a los residentes de una residencia específica.
|
||||
*
|
||||
* @param idJuego ID del juego cuyos registros se analizarán.
|
||||
* @param idResidencia ID de la residencia cuyos residentes serán tenidos en cuenta.
|
||||
* @param dificultad Nivel de dificultad a filtrar (opcional, puede ser null para incluir todas).
|
||||
* @return Lista de {@link MediaRegistroDTO} donde cada entrada representa un año con el promedio de errores.
|
||||
*/
|
||||
@Query("""
|
||||
SELECT new com.kevinolarte.resibenissa.dto.out.modulojuego.MediaRegistroDTO(CAST(EXTRACT(YEAR FROM r.fecha) AS string), AVG(r.num), COUNT(r))
|
||||
FROM RegistroJuego r
|
||||
WHERE r.juego.id = :idJuego AND r.residente.residencia.id = :idResidencia
|
||||
AND (:dificultad IS NULL OR r.dificultad = :dificultad)
|
||||
GROUP BY EXTRACT(YEAR FROM r.fecha)
|
||||
ORDER BY EXTRACT(YEAR FROM r.fecha)
|
||||
""")
|
||||
List<MediaRegistroDTO> getMediaErroresPorJuegoYResidenciaAnual(@Param("idJuego") Long idJuego,
|
||||
@Param("idResidencia") Long idResidencia,
|
||||
@Param("dificultad") Dificultad dificultad);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
package com.kevinolarte.resibenissa.services;
|
||||
|
||||
|
||||
import com.kevinolarte.resibenissa.config.Conf;
|
||||
import com.kevinolarte.resibenissa.dto.in.auth.LoginUserDto;
|
||||
import com.kevinolarte.resibenissa.dto.in.auth.RegisterUserDto;
|
||||
import com.kevinolarte.resibenissa.dto.in.auth.VerifyUserDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.UserResponseDto;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.repositories.UserRepository;
|
||||
import jakarta.mail.MessagingException;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Servicio encargado de gestionar la autenticación y verificación de usuarios.
|
||||
* <p>
|
||||
* Incluye el registro de nuevos usuarios, generación y envío de códigos de verificación por correo electrónico,
|
||||
* autenticación mediante email y contraseña, y validación del código de activación.
|
||||
* </p>
|
||||
*
|
||||
* Este servicio utiliza:
|
||||
* <ul>
|
||||
* <li>{@link PasswordEncoder} para cifrar contraseñas.</li>
|
||||
* <li>{@link AuthenticationManager} para autenticación en Spring Security.</li>
|
||||
* <li>{@link EmailService} para el envío de correos electrónicos.</li>
|
||||
* <li>{@link ResidenciaService} para validar residencias al registrar usuarios.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class AuthenticationService {
|
||||
private final UserRepository userRepository;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final EmailService emailService;
|
||||
private final ResidenciaService residenciaService;
|
||||
|
||||
/**
|
||||
* Registra un nuevo usuario si no existe previamente.
|
||||
* <p>
|
||||
* Genera un código de verificación y lo envía por correo electrónico.
|
||||
* El usuario se crea con estado desactivado hasta completar la verificación.
|
||||
* </p>
|
||||
*
|
||||
* @param input DTO con los datos del usuario a registrar.
|
||||
* @return DTO con los datos del usuario creado.
|
||||
* @throws ResiException si el email es inválido, ya existe, o la residencia no es válida.
|
||||
*/
|
||||
public UserResponseDto singUp(RegisterUserDto input){
|
||||
if (input.getEmail() == null || input.getEmail().trim().isEmpty() || input.getPassword() == null || input.getPassword().trim().isEmpty()
|
||||
|| input.getIdResidencia() == null || input.getNombre() == null || input.getNombre().trim().isEmpty() || input.getApellido() == null || input.getApellido().trim().isEmpty()){
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
|
||||
input.setEmail(input.getEmail().trim().toLowerCase());
|
||||
if (!EmailService.isEmailValid(input.getEmail())){
|
||||
throw new ResiException(ApiErrorCode.CORREO_INVALIDO);
|
||||
}
|
||||
|
||||
//Miramos si ese usuario y residencia existen
|
||||
User userTest = userRepository.findByEmail(input.getEmail());
|
||||
Residencia residenciaTest = residenciaService.getResidencia(input.getIdResidencia());
|
||||
if(userTest != null){
|
||||
if (userTest.isBaja())
|
||||
throw new ResiException(ApiErrorCode.USUARIO_BAJA);
|
||||
throw new ResiException(ApiErrorCode.USER_EXIST);
|
||||
}
|
||||
|
||||
if (residenciaTest.isBaja())
|
||||
throw new ResiException(ApiErrorCode.RESIDENCIA_BAJA);
|
||||
|
||||
User user = new User(input.getNombre(), input.getApellido(),input.getEmail(), passwordEncoder.encode(input.getPassword()));
|
||||
user.setVerificationCode(generateVerificationCode());
|
||||
System.out.println(user.getVerificationCode());
|
||||
user.setVerificationExpiration(LocalDateTime.now().plusMinutes(15));
|
||||
user.setEnabled(false);
|
||||
sendVerificationEmail(user);
|
||||
user.setResidencia(residenciaTest);
|
||||
user.setFotoPerfil("/uploads/" + Conf.imageDefault);
|
||||
User savedUser = userRepository.save(user);
|
||||
|
||||
return new UserResponseDto(savedUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Autentica un usuario existente mediante email y contraseña.
|
||||
*
|
||||
* @param input DTO con credenciales de acceso.
|
||||
* @return El objeto {@link User} autenticado.
|
||||
* @throws ResiException si el usuario no existe o no está activado.
|
||||
*/
|
||||
public User authenticate(LoginUserDto input){
|
||||
if (input.getEmail() == null || input.getEmail().trim().isEmpty() || input.getPassword() == null || input.getPassword().trim().isEmpty()){
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
input.setEmail(input.getEmail().trim().toLowerCase());
|
||||
if (!EmailService.isEmailValid(input.getEmail())){
|
||||
throw new ResiException(ApiErrorCode.CORREO_INVALIDO);
|
||||
}
|
||||
|
||||
//Ver si ese usuario existe o no
|
||||
User user = userRepository.findByEmail(input.getEmail());
|
||||
|
||||
if (user == null){
|
||||
throw new ResiException(ApiErrorCode.USUARIO_INVALIDO);
|
||||
}
|
||||
|
||||
//Ver si esta activado
|
||||
if(!user.isEnabled()){
|
||||
throw new ResiException(ApiErrorCode.USER_NO_ACTIVADO);
|
||||
}
|
||||
//Ver si esta de baja
|
||||
if(user.isBaja()){
|
||||
throw new ResiException(ApiErrorCode.USUARIO_BAJA);
|
||||
}
|
||||
|
||||
//Autehnticamos
|
||||
try{
|
||||
authenticationManager.authenticate(
|
||||
new UsernamePasswordAuthenticationToken(
|
||||
input.getEmail(),
|
||||
input.getPassword()
|
||||
)
|
||||
);
|
||||
}catch (AuthenticationException e){
|
||||
throw new ResiException(ApiErrorCode.CONTRASENA_INCORRECTA);
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifica el código enviado por correo y activa la cuenta del usuario.
|
||||
*
|
||||
* @param input DTO que contiene el email y el código de verificación.
|
||||
* @throws ResiException si el código está expirado, es inválido, o el usuario no existe.
|
||||
*/
|
||||
public void verifyUser(VerifyUserDto input){
|
||||
if (input.getEmail() == null || input.getEmail().trim().isEmpty() || input.getVerificationCode() == null || input.getVerificationCode().trim().isEmpty()){
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
User user = userRepository.findByEmail(input.getEmail());
|
||||
if(user != null){
|
||||
|
||||
if (user.isBaja()) {
|
||||
throw new ResiException(ApiErrorCode.USUARIO_BAJA);
|
||||
}
|
||||
if (user.isEnabled()) {
|
||||
throw new ResiException(ApiErrorCode.USER_YA_ACTIVADO);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(user.getVerificationExpiration().isBefore(LocalDateTime.now())){
|
||||
throw new ResiException(ApiErrorCode.CODIGO_EXPIRADO);
|
||||
}
|
||||
if (user.getVerificationCode().equals(input.getVerificationCode())){
|
||||
user.setEnabled(true);
|
||||
user.setVerificationCode(null);
|
||||
user.setVerificationExpiration(null);
|
||||
userRepository.save(user); //CUIDADO!!!
|
||||
}else{
|
||||
throw new ResiException(ApiErrorCode.CODIGO_INVALIDO);
|
||||
}
|
||||
}
|
||||
else{
|
||||
throw new ResiException(ApiErrorCode.USUARIO_INVALIDO);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reenvía un nuevo código de verificación por correo si el usuario aún no está activado.
|
||||
*
|
||||
* @param email Dirección de correo del usuario.
|
||||
* @throws ResiException si el usuario no existe o ya está activado.
|
||||
*/
|
||||
public void resendVerificationCode(String email){
|
||||
if (email == null || email.trim().isEmpty()){
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
email = email.trim().toLowerCase();
|
||||
if (!EmailService.isEmailValid(email)){
|
||||
throw new ResiException(ApiErrorCode.CORREO_INVALIDO);
|
||||
}
|
||||
User user = userRepository.findByEmail(email);
|
||||
|
||||
if(user != null){
|
||||
if (user.isBaja()) {
|
||||
throw new ResiException(ApiErrorCode.USUARIO_BAJA);
|
||||
}
|
||||
if (user.isEnabled()){
|
||||
throw new ResiException(ApiErrorCode.USER_YA_ACTIVADO);
|
||||
}
|
||||
user.setVerificationCode(generateVerificationCode());
|
||||
user.setVerificationExpiration(LocalDateTime.now().plusHours(1));
|
||||
sendVerificationEmail(user);
|
||||
userRepository.save(user);
|
||||
}
|
||||
else{
|
||||
throw new ResiException(ApiErrorCode.USUARIO_INVALIDO);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Genera un código de verificación de 6 dígitos.
|
||||
*
|
||||
* @return Código de verificación como String.
|
||||
*/
|
||||
public String generateVerificationCode(){
|
||||
Random random = new Random();
|
||||
int code = random.nextInt(900000) + 100000;
|
||||
return String.valueOf(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Envía un correo con el código de verificación al usuario.
|
||||
*
|
||||
* @param user Usuario al que se le enviará el correo.
|
||||
* @throws ResiException si ocurre un error al enviar el correo.
|
||||
*/
|
||||
public void sendVerificationEmail(User user){
|
||||
String subject = "Account verification";
|
||||
String verificationCode = user.getVerificationCode();
|
||||
String htmlMessage = "<html>"
|
||||
+ "<body style=\"font-family: Arial, sans-serif;\">"
|
||||
+ "<div style=\"background-color: #f5f5f5; padding: 20px;\">"
|
||||
+ "<h2 style=\"color: #333;\">Welcome to our app!</h2>"
|
||||
+ "<p style=\"font-size: 16px;\">Please enter the verification code below to continue:</p>"
|
||||
+ "<div style=\"background-color: #fff; padding: 20px; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.1);\">"
|
||||
+ "<h3 style=\"color: #333;\">Verification Code:</h3>"
|
||||
+ "<p style=\"font-size: 18px; font-weight: bold; color: #007bff;\">" + verificationCode + "</p>"
|
||||
+ "</div>"
|
||||
+ "</div>"
|
||||
+ "</body>"
|
||||
+ "</html>";
|
||||
try{
|
||||
emailService.sendEmail(user.getEmail(), subject, htmlMessage);
|
||||
}catch (MessagingException e){
|
||||
throw new ResiException(ApiErrorCode.ERROR_MAIL_SENDER);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
package com.kevinolarte.resibenissa.services;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.out.moduloOrgSalida.ParticipanteResponseDto;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.Residente;
|
||||
import com.kevinolarte.resibenissa.repositories.ResidenteRepository;
|
||||
import jakarta.mail.MessagingException;
|
||||
import jakarta.mail.internet.MimeMessage;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Servicio encargado del envío de correos electrónicos dentro de la aplicación.
|
||||
* <p>
|
||||
* Este servicio utiliza {@link JavaMailSender} para construir y enviar correos
|
||||
* en formato HTML. También incluye una utilidad para validar la estructura de
|
||||
* direcciones de correo electrónico.
|
||||
* </p>
|
||||
*
|
||||
* Requiere configuración previa en {@code application.properties} o {@code application.yml}
|
||||
* con los datos del servidor SMTP (por ejemplo, Gmail).
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class EmailService {
|
||||
|
||||
private final ResidenteRepository residenteRepository;
|
||||
private JavaMailSender mailSender;
|
||||
private JwtService jwtService;
|
||||
|
||||
/**
|
||||
* Verifica si una dirección de correo electrónico tiene un formato válido.
|
||||
* <p>
|
||||
* La validación se realiza mediante una expresión regular que comprueba la estructura estándar de emails.
|
||||
* </p>
|
||||
*
|
||||
* @param email Dirección de correo electrónico a validar.
|
||||
* @return {@code true} si el formato del email es válido, {@code false} en caso contrario.
|
||||
*/
|
||||
public static boolean isEmailValid(String email) {
|
||||
String emailRegex = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
|
||||
return email != null && email.matches(emailRegex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Envía un correo electrónico de verificación en formato HTML.
|
||||
* <p>
|
||||
* Construye el mensaje a partir de los parámetros recibidos y lo envía utilizando el {@link JavaMailSender}.
|
||||
* </p>
|
||||
*
|
||||
* @param to Dirección de correo del destinatario.
|
||||
* @param subject Asunto del correo.
|
||||
* @param text Cuerpo del mensaje en formato HTML.
|
||||
* @throws MessagingException si ocurre un error al crear o enviar el mensaje.
|
||||
*/
|
||||
public void sendEmail(String to, String subject, String text) throws MessagingException {
|
||||
|
||||
MimeMessage message = mailSender.createMimeMessage();
|
||||
|
||||
|
||||
MimeMessageHelper helper = new MimeMessageHelper(message, true);
|
||||
|
||||
helper.setTo(to);
|
||||
helper.setSubject(subject);
|
||||
helper.setText(text, true);
|
||||
|
||||
mailSender.send(message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Envía una notificación por correo electrónico a los familiares de un participante
|
||||
* para solicitar permiso para una excursión.
|
||||
* <p>
|
||||
* Genera un token JWT con información del participante y construye URLs para permitir o rechazar la solicitud.
|
||||
* Reemplaza los placeholders en una plantilla HTML y envía el correo a los familiares.
|
||||
* </p>
|
||||
*
|
||||
* @param participanteDto DTO que contiene la información del participante.
|
||||
*/
|
||||
public void sendNotificationParticipante(ParticipanteResponseDto participanteDto) {
|
||||
try {
|
||||
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.put("idParticipante", participanteDto.getId());
|
||||
claims.put("idEvento", participanteDto.getIdEvento());
|
||||
claims.put("idResidencia", participanteDto.getIdResidencia());
|
||||
|
||||
String token = jwtService.generateTokenConExpiracionCustomClaims(claims, Duration.ofMinutes(30));
|
||||
System.out.println("Token: " + token);
|
||||
// Construir URLs
|
||||
String urlPermitir = "http://localhost:8080/public/allowParticipante?token=" + token;
|
||||
String urlRechazar = "http://localhost:8080/public/denyParticipante?token=" + token;
|
||||
|
||||
// Leer la plantilla HTML desde resources/templates
|
||||
Path htmlPath = Paths.get("src/main/resources/templates/permiso-excursion.html");
|
||||
String html = Files.readString(htmlPath);
|
||||
Residente residente = residenteRepository.findById(participanteDto.getIdResidente())
|
||||
.orElseThrow(() -> new ResiException(ApiErrorCode.RESIDENTE_INVALIDO));
|
||||
|
||||
// Reemplazar los placeholders
|
||||
html = html.replace("{{nombreFamiliar}}", "Familiar")
|
||||
.replace("{{nombreResidente}}", "Residente " + residente.getNombre() + " " + residente.getApellido())
|
||||
.replace("{{nombreExcursion}}", "Excursión especial")
|
||||
.replace("{{fecha}}", LocalDate.now().plusDays(7).toString()) // ejemplo de fecha
|
||||
.replace("{{urlPermitir}}", urlPermitir)
|
||||
.replace("{{urlRechazar}}", urlRechazar);
|
||||
|
||||
|
||||
sendEmail(participanteDto.getFamiliar1(), "Permiso para excursión", html);
|
||||
if (participanteDto.getFamiliar2() != null) {
|
||||
sendEmail(participanteDto.getFamiliar2(), "Permiso para excursión", html);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new ResiException(ApiErrorCode.ERROR_MAIL_SENDER);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
package com.kevinolarte.resibenissa.services;
|
||||
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.io.Decoders;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.security.Key;
|
||||
import java.time.Duration;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Servicio encargado de la generación, validación y extracción de información de tokens JWT.
|
||||
* <p>
|
||||
* Utiliza la clave secreta configurada en las propiedades de la aplicación y respeta el tiempo
|
||||
* de expiración establecido para los tokens. Este servicio también añade el email como un claim
|
||||
* adicional en los tokens generados.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* El campo {@code sub} del token corresponde al {@code username}, pero en esta aplicación se trabaja principalmente con {@code email}.
|
||||
* </p>
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Service
|
||||
public class JwtService {
|
||||
@Value("${security.jwt.secret-key}")
|
||||
private String secretKey;
|
||||
|
||||
@Value("${security.jwt.expiration-time}")
|
||||
private long jwtExpiration;
|
||||
|
||||
/**
|
||||
* Extrae el nombre de usuario (username/subject) del token JWT.
|
||||
*
|
||||
* @param token Token JWT.
|
||||
* @return Nombre de usuario extraído del token.
|
||||
*/
|
||||
public String extractUsername(String token) {
|
||||
return extractClaim(token, Claims::getSubject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrae un claim personalizado del token, utilizando una función de resolución.
|
||||
*
|
||||
* @param token Token JWT.
|
||||
* @param claimsResolver Función que define qué claim se desea extraer.
|
||||
* @return Valor del claim.
|
||||
* @param <T> Tipo del claim.
|
||||
*/
|
||||
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver){
|
||||
final Claims claims = extractAllClaims(token);
|
||||
return claimsResolver.apply(claims);
|
||||
}
|
||||
|
||||
/**
|
||||
* Genera un token JWT para un usuario, sin claims adicionales.
|
||||
*
|
||||
* @param userDetails Usuario autenticado.
|
||||
* @return Token JWT generado.
|
||||
*/
|
||||
public String generateToken(UserDetails userDetails) {
|
||||
|
||||
return generateToken(new HashMap<>(), userDetails);
|
||||
}
|
||||
|
||||
/**
|
||||
* Genera un token JWT con claims personalizados y el correo del usuario.
|
||||
*
|
||||
* @param extraClaims Claims adicionales a incluir en el token.
|
||||
* @param userDetails Usuario autenticado.
|
||||
* @return Token JWT generado.
|
||||
*/
|
||||
public String generateToken(Map<String, Object> extraClaims, UserDetails userDetails) {
|
||||
|
||||
if (userDetails instanceof User user) {
|
||||
extraClaims.put("email", user.getEmail());
|
||||
}
|
||||
return buildToken(extraClaims, userDetails, jwtExpiration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Genera un token JWT con claims personalizados y una duración específica.
|
||||
*
|
||||
* @param extraClaims Claims adicionales a incluir en el token.
|
||||
* @param duration Duración del token.
|
||||
* @return Token JWT generado.
|
||||
*/
|
||||
public String generateTokenConExpiracionCustomClaims(Map<String, Object> extraClaims, Duration duration) {
|
||||
return Jwts.builder()
|
||||
.setClaims(extraClaims)
|
||||
.setIssuedAt(new Date(System.currentTimeMillis()))
|
||||
.setExpiration(new Date(System.currentTimeMillis() + duration.toMillis()))
|
||||
.signWith(getSingKey(), SignatureAlgorithm.HS256)
|
||||
.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* Devuelve el tiempo de expiración configurado para los tokens (en milisegundos).
|
||||
*
|
||||
* @return Tiempo de expiración en milisegundos.
|
||||
*/
|
||||
public long getExpirationTime() {
|
||||
return this.jwtExpiration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construye el token JWT firmándolo con la clave secreta.
|
||||
*
|
||||
* @param extraClaims Claims adicionales.
|
||||
* @param userDetails Datos del usuario.
|
||||
* @param expirationTime Tiempo de expiración en milisegundos.
|
||||
* @return Token JWT generado.
|
||||
*/
|
||||
private String buildToken(
|
||||
Map<String, Object> extraClaims,
|
||||
UserDetails userDetails,
|
||||
long expirationTime) {
|
||||
|
||||
return Jwts
|
||||
.builder()
|
||||
.setClaims(extraClaims)
|
||||
.setSubject(userDetails.getUsername())
|
||||
.setIssuedAt(new Date(System.currentTimeMillis()))
|
||||
.setExpiration(new Date(System.currentTimeMillis() + expirationTime))
|
||||
.signWith(getSingKey(), SignatureAlgorithm.HS256)
|
||||
.compact();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrae el claim personalizado {@code email} del token.
|
||||
*
|
||||
* @param token Token JWT.
|
||||
* @return Email del usuario.
|
||||
*/
|
||||
public String extrtractEmail(String token) {
|
||||
//Del extra claim que pusimos.
|
||||
return extractAllClaims(token).get("email", String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifica si un token es válido para un usuario dado.
|
||||
*
|
||||
* @param token Token JWT.
|
||||
* @param userDetails Usuario autenticado.
|
||||
* @return {@code true} si el token es válido y no ha expirado.
|
||||
*/
|
||||
public boolean isTokenValid(String token, UserDetails userDetails) {
|
||||
|
||||
final String username = extractUsername(token);
|
||||
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifica si el token ya ha expirado.
|
||||
*
|
||||
* @param token Token JWT.
|
||||
* @return {@code true} si el token está expirado.
|
||||
*/
|
||||
private boolean isTokenExpired(String token) {
|
||||
return extractExpiration(token).before(new Date());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extrae la fecha de expiración del token.
|
||||
*
|
||||
* @param token Token JWT.
|
||||
* @return Fecha de expiración.
|
||||
*/
|
||||
private Date extractExpiration(String token) {
|
||||
return extractClaim(token, Claims::getExpiration);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extrae todos los claims del token.
|
||||
*
|
||||
* @param token Token JWT.
|
||||
* @return Todos los claims contenidos en el token.
|
||||
*/
|
||||
private Claims extractAllClaims(String token) {
|
||||
return Jwts
|
||||
.parserBuilder()
|
||||
.setSigningKey(getSingKey())
|
||||
.build()
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene la clave secreta firmada a partir del string base64 en la configuración.
|
||||
*
|
||||
* @return Clave HMAC SHA válida para firmar/verificar JWT.
|
||||
*/
|
||||
private Key getSingKey() {
|
||||
byte[] keyBytes = Decoders.BASE64.decode(secretKey);
|
||||
return Keys.hmacShaKeyFor(keyBytes);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package com.kevinolarte.resibenissa.services;
|
||||
|
||||
import com.kevinolarte.resibenissa.LogContext;
|
||||
import com.kevinolarte.resibenissa.enums.CategoriaLog;
|
||||
import com.kevinolarte.resibenissa.models.Logger;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.repositories.LoggerRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.java.Log;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Service
|
||||
public class LoggerService {
|
||||
|
||||
private final LoggerRepository loggerRepository;
|
||||
|
||||
public LoggerService(LoggerRepository loggerRepository) {
|
||||
this.loggerRepository = loggerRepository;
|
||||
}
|
||||
|
||||
public void registrarLog(String endpoint, String metodo, String descripcion) {
|
||||
Logger log = new Logger(
|
||||
endpoint,
|
||||
metodo,
|
||||
descripcion
|
||||
);
|
||||
Logger saved = loggerRepository.save(log);
|
||||
LogContext.setCurrentLogId(saved.getId());
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void registrarLogError(String descripcion) {
|
||||
Logger log = new Logger(null, null, descripcion);
|
||||
|
||||
Long logId = LogContext.getCurrentLogId();
|
||||
if (logId != null) {
|
||||
loggerRepository.findById(logId).ifPresent(log::setPadre);
|
||||
}
|
||||
|
||||
loggerRepository.save(log);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
package com.kevinolarte.resibenissa.services;
|
||||
|
||||
import com.kevinolarte.resibenissa.dto.in.ResidenciaDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.ResidenciaPublicResponseDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.ResidenciaResponseDto;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
import com.kevinolarte.resibenissa.repositories.ResidenciaRepository;
|
||||
import com.kevinolarte.resibenissa.repositories.ResidenteRepository;
|
||||
import com.kevinolarte.resibenissa.repositories.moduloOrgSalida.EventoSalidaRepository;
|
||||
import com.kevinolarte.resibenissa.repositories.moduloOrgSalida.ParticipanteRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Servicio que gestiona la lógica de negocio relacionada con entidades {@link Residencia}.
|
||||
* <p>
|
||||
* Permite crear, obtener, buscar por ID y eliminar residencias.
|
||||
* </p>
|
||||
*
|
||||
* @author : Kevin Olarte
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class ResidenciaService {
|
||||
|
||||
private final ResidenciaRepository residenciaRepository;
|
||||
private final BCryptPasswordEncoder passwordEncoder;
|
||||
private final ResidenteRepository residenteRepository;
|
||||
private final ParticipanteRepository participanteRepository;
|
||||
private final EventoSalidaRepository eventoSalidaRepository;
|
||||
|
||||
|
||||
/**
|
||||
* Crea una nueva residencia en el sistema a partir de los datos recibidos.
|
||||
* <p>
|
||||
* Valida que el nombre y correo no estén vacíos, que el correo tenga un formato válido,
|
||||
* y que tanto el nombre como el correo no estén ya registrados.
|
||||
* </p>
|
||||
*
|
||||
* @param input DTO que contiene el nombre y correo de la residencia.
|
||||
* @return {@link ResidenciaResponseDto} de la residencia creada.
|
||||
* @throws ResiException en caso de errores de validación o duplicados.
|
||||
*/
|
||||
public ResidenciaResponseDto add(ResidenciaDto input) throws RuntimeException{
|
||||
if (input.getNombre() == null || input.getEmail() == null
|
||||
|| input.getNombre().trim().isEmpty() || input.getEmail().trim().isEmpty()){
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
|
||||
// Validar formato del correo electrónico
|
||||
input.setEmail(input.getEmail().toLowerCase().trim());
|
||||
if (!EmailService.isEmailValid(input.getEmail())){
|
||||
throw new ResiException(ApiErrorCode.CORREO_INVALIDO);
|
||||
}
|
||||
|
||||
// Comprobar si ya existe una residencia con ese correo o nombre
|
||||
Optional<Residencia> residenciaTmp = residenciaRepository.findByEmail(input.getEmail());
|
||||
Optional<Residencia> residenciaTmp2 = residenciaRepository.findByNombre(input.getNombre());
|
||||
if(residenciaTmp.isPresent()){
|
||||
throw new ResiException(ApiErrorCode.CORREO_DUPLICADO);
|
||||
}
|
||||
if(residenciaTmp2.isPresent()){
|
||||
throw new ResiException(ApiErrorCode.NOMBRE_DUPLICADO);
|
||||
}
|
||||
|
||||
Residencia residencia = new Residencia(input.getNombre(), input.getEmail());
|
||||
return new ResidenciaResponseDto(residenciaRepository.save(residencia));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene una residencia a partir de su ID validando su existencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia a recuperar.
|
||||
* @return {@link ResidenciaResponseDto} de la residencia encontrada.
|
||||
* @throws ResiException si el ID es nulo o no existe una residencia con ese ID.
|
||||
*/
|
||||
public ResidenciaResponseDto get(Long idResidencia) {
|
||||
Residencia resi;
|
||||
|
||||
// Comprobar si el ID de residencia es nulo
|
||||
if (idResidencia == null)
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
else
|
||||
resi = residenciaRepository.findById(idResidencia)
|
||||
.orElseThrow(() -> new ResiException(ApiErrorCode.RESIDENCIA_INVALIDO));
|
||||
|
||||
|
||||
return new ResidenciaResponseDto(resi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de todas las residencias en el sistema. con solo el nombre , correo e id.
|
||||
* @return Lista de residencias públicas.
|
||||
*/
|
||||
public List<ResidenciaPublicResponseDto> getAll() {
|
||||
return residenciaRepository.findAll()
|
||||
.stream().map(ResidenciaPublicResponseDto::new)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de todas las residencias que están marcadas como inactivas (baja).
|
||||
* @return Lista de residencias inactivas.
|
||||
*/
|
||||
public List<ResidenciaPublicResponseDto> getAllBaja() {
|
||||
return residenciaRepository.findByBajaTrue().stream().map(ResidenciaPublicResponseDto::new).toList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Elimina una residencia a partir de su ID.
|
||||
* <p>
|
||||
* Si no se encuentra la residencia, lanza una excepción.
|
||||
* </p>
|
||||
*
|
||||
* @param idResidencia ID de la residencia a eliminar.
|
||||
* @throws ResiException si no se encuentra la residencia especificada.
|
||||
*/
|
||||
public void deleteFisico(Long idResidencia) {
|
||||
Residencia residenciaTmp = residenciaRepository.findById(idResidencia).orElse(null);
|
||||
|
||||
if(residenciaTmp == null){
|
||||
throw new ResiException(ApiErrorCode.RESIDENCIA_INVALIDO);
|
||||
}
|
||||
|
||||
residenciaRepository.delete(residenciaTmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Elimina una residencia de forma lógica, marcando su estado como inactivo.
|
||||
* @param id ID de la residencia a eliminar.
|
||||
* @throws ResiException si no se encuentra la residencia.
|
||||
*/
|
||||
public void deleteLogico(Long id) {
|
||||
Residencia residencia = residenciaRepository.findById(id).orElse(null);
|
||||
if (residencia == null) {
|
||||
throw new ResiException(ApiErrorCode.RESIDENCIA_INVALIDO);
|
||||
}
|
||||
|
||||
residencia.setBaja(true);
|
||||
residencia.setFechaBaja(LocalDateTime.now());
|
||||
residencia.setEmail(passwordEncoder.encode(residencia.getEmail()));
|
||||
|
||||
// Cambiar el estado de los residentes a inactivos
|
||||
residencia.getResidentes().forEach(residente -> {
|
||||
ResidenteService.darBajaUser(residente, passwordEncoder);
|
||||
residenteRepository.save(residente);
|
||||
});
|
||||
// Cambiar el estado de los usuarios a inactivos
|
||||
residencia.getUsuarios().forEach(usuario -> {
|
||||
usuario.setBaja(true);
|
||||
usuario.setFechaBaja(LocalDateTime.now());
|
||||
usuario.setPassword(passwordEncoder.encode(usuario.getPassword()));
|
||||
});
|
||||
|
||||
participanteRepository.deleteAllByResidenciaId(residencia.getId());
|
||||
eventoSalidaRepository.deleteAllByResidenciaId(residencia.getId());
|
||||
|
||||
|
||||
|
||||
residenciaRepository.save(residencia);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Busca una residencia por su ID.
|
||||
*
|
||||
* @param id ID de la residencia.
|
||||
* @return {@link Residencia} encontrada.
|
||||
* @throws ResiException si no se encuentra la residencia.
|
||||
*/
|
||||
public Residencia getResidencia(Long id){
|
||||
return residenciaRepository.findById(id).orElseThrow(() -> new ResiException(ApiErrorCode.RESIDENCIA_INVALIDO));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,440 @@
|
|||
package com.kevinolarte.resibenissa.services;
|
||||
|
||||
|
||||
import com.kevinolarte.resibenissa.config.Conf;
|
||||
import com.kevinolarte.resibenissa.dto.in.ResidenteDto;
|
||||
import com.kevinolarte.resibenissa.dto.in.moduloReporting.EmailRequestDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.ResidenteResponseDto;
|
||||
import com.kevinolarte.resibenissa.enums.Filtrado.ResidenteFiltrado;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
import com.kevinolarte.resibenissa.models.Residente;
|
||||
import com.kevinolarte.resibenissa.models.moduloWallet.Wallet;
|
||||
import com.kevinolarte.resibenissa.repositories.ResidenteRepository;
|
||||
import com.kevinolarte.resibenissa.repositories.moduloOrgSalida.ParticipanteRepository;
|
||||
import com.kevinolarte.resibenissa.repositories.moduloWallet.WalletRepository;
|
||||
import com.kevinolarte.resibenissa.services.moduloWallet.WalletService;
|
||||
import com.kevinolarte.resibenissa.specifications.ResidenteSpecification;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Servicio encargado de gestionar la lógica de negocio relacionada con los residentes.
|
||||
* <p>
|
||||
* Permite registrar, consultar, actualizar y eliminar residentes asociados a residencias.
|
||||
* También permite aplicar filtros básicos sobre los residentes.
|
||||
* </p>
|
||||
*
|
||||
* @author : Kevin Olarte
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class ResidenteService {
|
||||
private final ResidenteRepository residenteRepository;
|
||||
private final ResidenciaService residenciaService;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final ParticipanteRepository participanteRepository;
|
||||
private final EmailService emailService;
|
||||
private final WalletRepository walletRepository;
|
||||
|
||||
/**
|
||||
* Registra un nuevo residente asociado a una residencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param input DTO con los datos del residente.
|
||||
* @return DTO del residente creado.
|
||||
* @throws ResiException en caso de datos inválidos o duplicidad de documento.
|
||||
*/
|
||||
public ResidenteResponseDto add(Long idResidencia, ResidenteDto input) throws ResiException {
|
||||
if (input.getNombre() == null || input.getApellido() == null || input.getFechaNacimiento() == null || input.getDocumentoIdentidad() == null ||
|
||||
input.getNombre().trim().isEmpty() || input.getApellido().trim().isEmpty() || input.getDocumentoIdentidad().trim().isEmpty() || idResidencia == null ||
|
||||
input.getFamiliar1() == null || input.getFamiliar1().trim().isEmpty()) {
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
|
||||
// Validar el formato del documento de identidad
|
||||
input.setDocumentoIdentidad(input.getDocumentoIdentidad().trim().toUpperCase());
|
||||
if (input.getDocumentoIdentidad().length() != 8) {
|
||||
throw new ResiException(ApiErrorCode.DOCUMENTO_INVALIDO);
|
||||
}
|
||||
|
||||
//Validar correo familiar 1
|
||||
if (!EmailService.isEmailValid(input.getFamiliar1().toLowerCase().trim())){
|
||||
throw new ResiException(ApiErrorCode.CORREO_INVALIDO);
|
||||
}
|
||||
//Validar correo familiar 2
|
||||
if (input.getFamiliar2() != null && !input.getFamiliar2().trim().isEmpty())
|
||||
if (!EmailService.isEmailValid(input.getFamiliar2().toLowerCase().trim()))
|
||||
throw new ResiException(ApiErrorCode.CORREO_INVALIDO);
|
||||
|
||||
|
||||
|
||||
// Validar que la fecha de nacimiento no sea futura
|
||||
if (input.getFechaNacimiento().isAfter(LocalDate.now())) {
|
||||
throw new ResiException(ApiErrorCode.FECHA_INVALIDO);
|
||||
}
|
||||
|
||||
// Validar que la residencia existe
|
||||
Residencia residencia = residenciaService.getResidencia(idResidencia);
|
||||
|
||||
// Validar que no existe otro residente con el mismo documento de identidad en cualquier residencia
|
||||
Residente residenteDup = residenteRepository.findByDocuemntoIdentidad(input.getDocumentoIdentidad());
|
||||
if (residenteDup != null) {
|
||||
throw new ResiException(ApiErrorCode.DOCUMENTO_DUPLICADO);
|
||||
}
|
||||
|
||||
// Crear el nuevo residente
|
||||
Residente residente = new Residente(input.getNombre(), input.getApellido(), input.getFechaNacimiento(), input.getDocumentoIdentidad(), input.getFamiliar1(), input.getFamiliar2());
|
||||
residente.setResidencia(residencia);
|
||||
Residente residenteSaved = residenteRepository.save(residente);
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.setResidente(residenteSaved);
|
||||
wallet = walletRepository.save(wallet);
|
||||
System.out.println(wallet);
|
||||
residenteSaved.setWallet(wallet);
|
||||
|
||||
|
||||
return new ResidenteResponseDto(residenteRepository.save(residenteSaved));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene un residente asegurando su pertenencia a una residencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idResidente ID del residente.
|
||||
* @return DTO del residente encontrado.
|
||||
* @throws ResiException si el residente no existe o no pertenece a la residencia.
|
||||
*/
|
||||
public ResidenteResponseDto get(Long idResidencia, Long idResidente) {
|
||||
|
||||
Residente residenteTmp = getResidente(idResidencia, idResidente);
|
||||
|
||||
return new ResidenteResponseDto(residenteTmp);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene todos los residentes de todas residencias con filtros opcionales.
|
||||
* @param fechaNacimiento Fecha exacta de nacimiento (opcional).
|
||||
* @param minFNac Fecha mínima de nacimiento (opcional).
|
||||
* @param maxFNac Fecha máxima de nacimiento (opcional).
|
||||
* @param maxAge Edad máxima (opcional).
|
||||
* @param minAge Edad mínima (opcional).
|
||||
* @param idJuego ID de juego asociado (opcional).
|
||||
* @param idEvento ID de evento asociado (opcional).
|
||||
* @return Lista de residentes filtrados.
|
||||
* @throws ResiException si la residencia no existe.
|
||||
*/
|
||||
public List<ResidenteResponseDto> getAll(LocalDate fechaNacimiento, LocalDate minFNac, LocalDate maxFNac, Integer maxAge, Integer minAge, Long idJuego, Long idEvento, ResidenteFiltrado filtrado) {
|
||||
|
||||
|
||||
|
||||
Specification<Residente> spec = ResidenteSpecification.withFilters(null, fechaNacimiento, minFNac, maxFNac, maxAge, minAge, idJuego, idEvento);
|
||||
|
||||
Sort sort = (filtrado != null) ? filtrado.toSort() : Sort.by(Sort.Direction.ASC, "apellido");
|
||||
List<Residente> residentes = residenteRepository.findAll(spec, sort);
|
||||
|
||||
|
||||
return residentes.stream().map(ResidenteResponseDto::new).collect(Collectors.toList());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene todos los residentes de una residencia con filtros opcionales.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param fechaNacimiento Fecha exacta de nacimiento (opcional).
|
||||
* @param minFNac Fecha mínima de nacimiento (opcional).
|
||||
* @param maxFNac Fecha máxima de nacimiento (opcional).
|
||||
* @param maxAge Edad máxima (opcional).
|
||||
* @param minAge Edad mínima (opcional).
|
||||
* @param idJuego ID de juego asociado (opcional).
|
||||
* @param idEvento ID de evento asociado (opcional).
|
||||
* @return Lista de residentes filtrados.
|
||||
* @throws ResiException si la residencia no existe o el ID es nulo.
|
||||
*/
|
||||
public List<ResidenteResponseDto> getAll(Long idResidencia, LocalDate fechaNacimiento, LocalDate minFNac, LocalDate maxFNac, Integer maxAge, Integer minAge, Long idJuego, Long idEvento, ResidenteFiltrado filtrado) {
|
||||
if (idResidencia == null) {
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
// Validar que la residencia existe
|
||||
Residencia residencia = residenciaService.getResidencia(idResidencia);
|
||||
|
||||
Specification<Residente> spec = ResidenteSpecification.withFilters(idResidencia, fechaNacimiento, minFNac, maxFNac, maxAge, minAge, idJuego, idEvento);
|
||||
|
||||
Sort sort = (filtrado != null) ? filtrado.toSort() : Sort.by(Sort.Direction.ASC, "apellido");
|
||||
List<Residente> residentes = residenteRepository.findAll(spec, sort);
|
||||
|
||||
|
||||
return residentes.stream().map(ResidenteResponseDto::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene todos los residentes dados de baja en una residencia, con filtros de fecha.
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param fecha Fecha exacta de baja (opcional).
|
||||
* @param minFecha Fecha mínima de baja (opcional).
|
||||
* @param maxFecha Fecha máxima de baja (opcional).
|
||||
* @return Lista de residentes dados de baja.
|
||||
* @throws ResiException si la residencia no existe o el ID es nulo.
|
||||
*/
|
||||
public List<ResidenteResponseDto> getAllBajas(Long idResidencia, LocalDate fecha, LocalDate minFecha, LocalDate maxFecha) {
|
||||
if (idResidencia == null){
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
|
||||
List<Residente> lista = residenteRepository.findAll(ResidenteSpecification.withFiltersBaja(fecha, minFecha, maxFecha, idResidencia));
|
||||
|
||||
return lista.stream().map(ResidenteResponseDto::new).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene todos los residentes dados de baja en el sistema, sin filtrar por residencia.
|
||||
* @param fecha Fecha exacta de baja (opcional).
|
||||
* @param minFecha Fecha mínima de baja (opcional).
|
||||
* @param maxFecha Fecha máxima de baja (opcional).
|
||||
* @return Lista de residentes dados de baja.
|
||||
* @throws ResiException si la residencia no existe o el ID es nulo.
|
||||
*/
|
||||
public List<ResidenteResponseDto> getAllBajas( LocalDate fecha, LocalDate minFecha, LocalDate maxFecha) {
|
||||
List<Residente> lista = residenteRepository.findAll(ResidenteSpecification.withFiltersBaja(fecha, minFecha, maxFecha, null));
|
||||
|
||||
return lista.stream().map(ResidenteResponseDto::new).toList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Elimina un residente asegurando su pertenencia a una residencia.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idResidente ID del residente.
|
||||
* @throws ResiException si no existe el residente o no pertenece a la residencia.
|
||||
*/
|
||||
public void deleteFisico(Long idResidencia, Long idResidente) {
|
||||
Residente residenteTmp = getResidente(idResidencia, idResidente);
|
||||
// Eliminar el residente
|
||||
residenteRepository.delete(residenteTmp);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Elimina un residente de forma lógica, marcándolo como dado de baja.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idResidente ID del residente.
|
||||
* @throws ResiException si el residente no existe o ya está dado de baja.
|
||||
*/
|
||||
public void deleteLogico(Long idResidencia, Long idResidente) {
|
||||
// Validar que el residente existe
|
||||
Residente residenteUpdatable = getResidente(idResidencia, idResidente);
|
||||
|
||||
//Dar de baja al residente
|
||||
if (residenteUpdatable.isBaja())
|
||||
throw new ResiException(ApiErrorCode.RESIDENTE_BAJA);
|
||||
|
||||
darBajaUser(residenteUpdatable, passwordEncoder);
|
||||
participanteRepository.deleteAll(residenteUpdatable.getParticipantes());
|
||||
residenteRepository.save(residenteUpdatable);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Actualiza los datos de un residente.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idResidente ID del residente.
|
||||
* @param input DTO con los nuevos datos a actualizar.
|
||||
* @return DTO del residente actualizado.
|
||||
* @throws ResiException si los datos son inválidos o se detecta duplicidad de documento.
|
||||
*/
|
||||
public ResidenteResponseDto update(Long idResidencia, Long idResidente, ResidenteDto input) {
|
||||
if (idResidencia == null || idResidente == null) {
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
// Validar que el residente existe
|
||||
Residente residenteUpdatable = getResidente(idResidencia, idResidente);
|
||||
|
||||
//Comprobar si el residente ya se ha dado de baja
|
||||
if (residenteUpdatable.isBaja()) {
|
||||
throw new ResiException(ApiErrorCode.RESIDENTE_BAJA);
|
||||
}
|
||||
|
||||
//Si ha añadido algun campo en el input para actualizar
|
||||
if (input != null) {
|
||||
// Validar el formato del documento de identidad
|
||||
if (input.getDocumentoIdentidad() != null) {
|
||||
input.setDocumentoIdentidad(input.getDocumentoIdentidad().trim().toUpperCase());
|
||||
if (input.getDocumentoIdentidad().length() != 8) {
|
||||
throw new ResiException(ApiErrorCode.DOCUMENTO_INVALIDO);
|
||||
}
|
||||
|
||||
// Comprobar si ya existe otro residente con el mismo documento de identidad
|
||||
Residente residenteDup = residenteRepository.findByDocuemntoIdentidad(input.getDocumentoIdentidad());
|
||||
if (residenteDup != null) {
|
||||
if (!Objects.equals(residenteDup.getId(), idResidente)) {
|
||||
throw new ResiException(ApiErrorCode.DOCUMENTO_DUPLICADO);
|
||||
}
|
||||
|
||||
} else
|
||||
residenteUpdatable.setDocuemntoIdentidad(input.getDocumentoIdentidad());
|
||||
}
|
||||
if (input.getFechaNacimiento() != null) {
|
||||
// Validar que la fecha de nacimiento no sea futura
|
||||
if (input.getFechaNacimiento().isAfter(LocalDate.now())) {
|
||||
throw new ResiException(ApiErrorCode.FECHA_INVALIDO);
|
||||
}
|
||||
residenteUpdatable.setFechaNacimiento(input.getFechaNacimiento());
|
||||
}
|
||||
if (input.getNombre() != null && !input.getNombre().trim().isEmpty()) {
|
||||
residenteUpdatable.setNombre(input.getNombre());
|
||||
}
|
||||
if (input.getApellido() != null && !input.getApellido().trim().isEmpty()) {
|
||||
residenteUpdatable.setApellido(input.getApellido());
|
||||
}
|
||||
if (input.getFamiliar1() != null && !input.getFamiliar1().trim().isEmpty()) {
|
||||
//Validar correo familiar 1
|
||||
if (!EmailService.isEmailValid(input.getFamiliar1().toLowerCase().trim())) {
|
||||
throw new ResiException(ApiErrorCode.CORREO_INVALIDO);
|
||||
}
|
||||
residenteUpdatable.setFamiliar1(input.getFamiliar1());
|
||||
}
|
||||
if (input.getFamiliar2() != null && !input.getFamiliar2().trim().isEmpty()) {
|
||||
//Validar correo familiar 2
|
||||
if (!EmailService.isEmailValid(input.getFamiliar2().toLowerCase().trim())) {
|
||||
throw new ResiException(ApiErrorCode.CORREO_INVALIDO);
|
||||
}
|
||||
residenteUpdatable.setFamiliar2(input.getFamiliar2());
|
||||
}
|
||||
// Guardar los cambios
|
||||
residenteUpdatable = residenteRepository.save(residenteUpdatable);
|
||||
}
|
||||
return new ResidenteResponseDto(residenteUpdatable);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Envía un correo electrónico a los familiares de un residente.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idResidente ID del residente.
|
||||
* @param input DTO con el asunto y cuerpo del correo.
|
||||
* @throws ResiException si el residente no existe o no tiene familiares asociados.
|
||||
*/
|
||||
public void sendEmailFamiliar(Long idResidencia, Long idResidente, EmailRequestDto input) {
|
||||
|
||||
// Validar que el residente existe
|
||||
Residente residenteTmp = getResidente(idResidencia, idResidente);
|
||||
|
||||
if (input == null || input.getSubject() == null || input.getBody() == null ||
|
||||
input.getSubject().trim().isEmpty() || input.getBody().trim().isEmpty()) {
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
//Enviar correo al familiar
|
||||
try{
|
||||
emailService.sendEmail(residenteTmp.getFamiliar1(), input.getSubject(), input.getBody());
|
||||
if(residenteTmp.getFamiliar2() != null)
|
||||
emailService.sendEmail(residenteTmp.getFamiliar2(), input.getSubject(), input.getBody());
|
||||
}catch (Exception e){
|
||||
throw new ResiException(ApiErrorCode.ERROR_MAIL_SENDER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Marca un residente como dado de baja.
|
||||
* @param residenteUpdatable Residente a actualizar.
|
||||
* @param passwordEncoder Codificador de contraseñas.
|
||||
*
|
||||
*/
|
||||
public static void darBajaUser(Residente residenteUpdatable, PasswordEncoder passwordEncoder) {
|
||||
residenteUpdatable.setBaja(true);
|
||||
residenteUpdatable.setFechaBaja(LocalDateTime.now());
|
||||
residenteUpdatable.setDocuemntoIdentidad(passwordEncoder.encode(residenteUpdatable.getDocuemntoIdentidad()));
|
||||
residenteUpdatable.setFamiliar1(passwordEncoder.encode(residenteUpdatable.getFamiliar1()));
|
||||
if (residenteUpdatable.getFamiliar2() != null && !residenteUpdatable.getFamiliar2().trim().isEmpty())
|
||||
residenteUpdatable.setFamiliar2(passwordEncoder.encode(residenteUpdatable.getFamiliar2()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene un residente y valida que pertenece a la residencia especificada.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idResidente ID del residente.
|
||||
* @return Residente encontrado.
|
||||
* @throws ResiException si no existe o no pertenece a la residencia.
|
||||
*/
|
||||
public Residente getResidente(Long idResidencia, Long idResidente) {
|
||||
if (idResidencia == null || idResidente == null) {
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
|
||||
// Validar que el residente existe
|
||||
Residente residenteTmp = residenteRepository.findById(idResidente).orElse(null);
|
||||
if (residenteTmp == null) {
|
||||
throw new ResiException(ApiErrorCode.RESIDENTE_INVALIDO);
|
||||
}
|
||||
//Comrpobar que el residente pertenece a la residencia
|
||||
if (!Objects.equals(residenteTmp.getResidencia().getId(), idResidencia)) {
|
||||
throw new ResiException(ApiErrorCode.RESIDENTE_INVALIDO);
|
||||
}
|
||||
return residenteTmp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene una imagen como recurso desde el sistema de archivos.
|
||||
* @param filename Nombre del archivo solicitado (actualmente no se utiliza, se carga siempre la imagen por defecto).
|
||||
* @return {@link Resource} que representa la imagen cargada desde el sistema de archivos.
|
||||
* @throws ResiException si el archivo no existe o no puede accederse.
|
||||
*/
|
||||
public Resource getImage(String filename) {
|
||||
|
||||
Path filePath = Paths.get("src/main/resources/static/uploads").resolve(Conf.imageDefault).normalize();
|
||||
Resource resource;
|
||||
try{
|
||||
resource = new UrlResource(filePath.toUri());
|
||||
if (!resource.exists()) {
|
||||
throw new ResiException(ApiErrorCode.PROBLEMAS_CON_FILE);
|
||||
}
|
||||
}catch (Exception e){
|
||||
throw new ResiException(ApiErrorCode.PROBLEMAS_CON_FILE);
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,416 @@
|
|||
package com.kevinolarte.resibenissa.services;
|
||||
|
||||
import com.kevinolarte.resibenissa.config.Conf;
|
||||
import com.kevinolarte.resibenissa.dto.in.UserDto;
|
||||
import com.kevinolarte.resibenissa.dto.in.auth.ChangePasswordUserDto;
|
||||
import com.kevinolarte.resibenissa.dto.out.UserResponseDto;
|
||||
import com.kevinolarte.resibenissa.exceptions.ApiErrorCode;
|
||||
import com.kevinolarte.resibenissa.exceptions.ResiException;
|
||||
import com.kevinolarte.resibenissa.models.Residencia;
|
||||
import com.kevinolarte.resibenissa.models.modulojuego.RegistroJuego;
|
||||
import com.kevinolarte.resibenissa.models.User;
|
||||
import com.kevinolarte.resibenissa.repositories.UserRepository;
|
||||
import com.kevinolarte.resibenissa.specifications.UserSpecification;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Servicio que gestiona la lógica relacionada con los usuarios del sistema.
|
||||
* <p>
|
||||
* Permite registrar, consultar, actualizar, eliminar y dar de baja usuarios,
|
||||
* así como aplicar filtros personalizados en las búsquedas.
|
||||
* </p>
|
||||
*
|
||||
* @author Kevin Olarte
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class UserService {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
private final ResidenciaService residenciaService;
|
||||
private final BCryptPasswordEncoder passwordEncoder;
|
||||
|
||||
/**
|
||||
* Guarda un nuevo usuario en la base de datos.
|
||||
* @param idResidencia ID de la residencia a la que pertenece el usuario.
|
||||
* @param input Datos del usuario a guardar.
|
||||
* @return DTO con los datos del usuario guardado.
|
||||
* @throws ResiException si los datos son inválidos o el usuario ya existe.
|
||||
*/
|
||||
public UserResponseDto add(Long idResidencia, UserDto input) {
|
||||
if (input.getEmail() == null || input.getEmail().trim().isEmpty() || input.getPassword() == null || input.getPassword().trim().isEmpty()
|
||||
|| input.getIdResidencia() == null || input.getNombre() == null || input.getNombre().trim().isEmpty() || input.getApellido() == null || input.getApellido().trim().isEmpty()){
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
|
||||
input.setEmail(input.getEmail().trim().toLowerCase());
|
||||
if (!EmailService.isEmailValid(input.getEmail())){
|
||||
throw new ResiException(ApiErrorCode.CORREO_INVALIDO);
|
||||
}
|
||||
|
||||
//Miramos si ese usuario y residencia existen
|
||||
User userTest = userRepository.findByEmail(input.getEmail());
|
||||
Residencia residenciaTest = residenciaService.getResidencia(input.getIdResidencia());
|
||||
if(userTest != null){
|
||||
if (userTest.isBaja())
|
||||
throw new ResiException(ApiErrorCode.USUARIO_BAJA);
|
||||
throw new ResiException(ApiErrorCode.USER_EXIST);
|
||||
}
|
||||
|
||||
if (residenciaTest.isBaja())
|
||||
throw new ResiException(ApiErrorCode.RESIDENCIA_BAJA);
|
||||
|
||||
User user = new User(input.getNombre(), input.getApellido(),input.getEmail(), passwordEncoder.encode(input.getPassword()));
|
||||
user.setResidencia(residenciaTest);
|
||||
//TODO: VERIFICACION CON CODIGO PERO FASE DESAROLLOO, AUN NO.
|
||||
user.setEnabled(true);
|
||||
user.setFotoPerfil("/uploads/" + Conf.imageDefault);
|
||||
User savedUser = userRepository.save(user);
|
||||
return new UserResponseDto(savedUser);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene un usuario por su ID dentro de una residencia específica.
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idUser ID del usuario.
|
||||
* @return DTO con los datos del usuario.
|
||||
* @throws ResiException si el ID de residencia o usuario es nulo, o si el usuario no pertenece a la residencia.
|
||||
*/
|
||||
public UserResponseDto get(Long idResidencia, Long idUser) {
|
||||
User userTmp = getUsuario(idResidencia, idUser);
|
||||
// Si todo es correcto, devolver el usuario
|
||||
return new UserResponseDto(userTmp);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene un usuario por su email dentro de una residencia específica.
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param email Email del usuario.
|
||||
* @return DTO con los datos del usuario.
|
||||
* @throws ResiException si el ID de residencia o email es nulo, o si el usuario no pertenece a la residencia.
|
||||
*/
|
||||
public UserResponseDto get(Long idResidencia, String email){
|
||||
if (idResidencia == null || email == null){
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
|
||||
//Validar si existe ese usuario
|
||||
User user = userRepository.findByEmail(email);
|
||||
if (user == null){
|
||||
throw new ResiException(ApiErrorCode.USUARIO_INVALIDO);
|
||||
}
|
||||
|
||||
//Validar si pertenece a esa residencia
|
||||
if (user.getResidencia() == null || !user.getResidencia().getId().equals(idResidencia)) {
|
||||
throw new ResiException(ApiErrorCode.USUARIO_INVALIDO);
|
||||
}
|
||||
|
||||
// Si todo es correcto, devolver el usuario
|
||||
return new UserResponseDto(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una imagen como recurso desde el sistema de archivos.
|
||||
* @param filename Nombre del archivo solicitado (actualmente no se utiliza, se carga siempre la imagen por defecto).
|
||||
* @return {@link Resource} que representa la imagen cargada desde el sistema de archivos.
|
||||
* @throws ResiException si el archivo no existe o no puede accederse.
|
||||
*/
|
||||
public Resource getImage(String filename) {
|
||||
|
||||
Path filePath = Paths.get("src/main/resources/static/uploads").resolve(Conf.imageDefault).normalize();
|
||||
Resource resource;
|
||||
try{
|
||||
resource = new UrlResource(filePath.toUri());
|
||||
if (!resource.exists()) {
|
||||
throw new ResiException(ApiErrorCode.PROBLEMAS_CON_FILE);
|
||||
}
|
||||
}catch (Exception e){
|
||||
throw new ResiException(ApiErrorCode.PROBLEMAS_CON_FILE);
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de todos los usuarios asociados a una residencia con filtros opcionales.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param enabled Estado habilitado para filtrar (opcional).
|
||||
* @param idJuego ID del juego para filtrar (opcional).
|
||||
* @return Lista de usuarios que cumplen con los filtros aplicados.
|
||||
* @throws ResiException si la residencia no existe o el ID es nulo.
|
||||
*/
|
||||
public List<UserResponseDto> getAll(Long idResidencia, Boolean enabled, Long idJuego){
|
||||
if (idResidencia == null){
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
|
||||
List<User> list = userRepository.findAll(UserSpecification.withFilters(enabled,idResidencia, idJuego));
|
||||
|
||||
return list.stream().map(UserResponseDto::new).toList();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de todos los usuarios con filtros opcionales.
|
||||
*
|
||||
* @param enabled Estado habilitado para filtrar (opcional).
|
||||
* @param idJuego ID del juego para filtrar (opcional).
|
||||
* @return Lista de usuarios que cumplen con los filtros aplicados.
|
||||
* @throws ResiException si la residencia no existe o el ID es nulo.
|
||||
*/
|
||||
public List<UserResponseDto> getAll(Boolean enabled, Long idJuego) {
|
||||
|
||||
List<User> list = userRepository.findAll(UserSpecification.withFilters(enabled,null, idJuego));
|
||||
|
||||
return list.stream().map(UserResponseDto::new).toList();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de usuarios dados de baja en una residencia específica.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @return Lista de usuarios dados de baja en la residencia.
|
||||
* @throws ResiException si la residencia no existe o el ID es nulo.
|
||||
*/
|
||||
public List<UserResponseDto> getAllBajas(Long idResidencia, LocalDate fecha, LocalDate minFecha, LocalDate maxFecha) {
|
||||
if (idResidencia == null) throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
|
||||
List<User> list = userRepository.findAll(UserSpecification.withFiltersBaja(fecha,minFecha, maxFecha, idResidencia));
|
||||
|
||||
|
||||
return list.stream().map(UserResponseDto::new).toList();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene una lista de usuarios dados de baja.
|
||||
*
|
||||
* @param fecha Fecha exacta de baja (opcional).
|
||||
* @param minFecha Fecha mínima de baja (opcional).
|
||||
* @param maxFecha Fecha máxima de baja (opcional).
|
||||
* @return Lista de usuarios dados de baja en la residencia.
|
||||
* @throws ResiException si la residencia no existe o el ID es nulo.
|
||||
*/
|
||||
public List<UserResponseDto> getAllBajas(LocalDate fecha, LocalDate minFecha, LocalDate maxFecha) {
|
||||
|
||||
List<User> list = userRepository.findAll(UserSpecification.withFiltersBaja(fecha,minFecha, maxFecha, null));
|
||||
|
||||
return list.stream().map(UserResponseDto::new).toList();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Elimina físicamente un usuario si no tiene registros dependientes.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idUser ID del usuario.
|
||||
* @throws ResiException si el usuario tiene registros de juego asociados.
|
||||
*/
|
||||
public void deleteFisico(Long idResidencia, Long idUser) {
|
||||
User userTmp = getUsuario(idResidencia, idUser);
|
||||
|
||||
// Comprobar juegos asociados
|
||||
if (userTmp.getRegistroJuegos() != null && !userTmp.getRegistroJuegos().isEmpty()){
|
||||
throw new ResiException(ApiErrorCode.REFERENCIAS_DEPENDIENTES);
|
||||
}
|
||||
|
||||
userRepository.delete(userTmp);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Marca lógicamente como dado de baja a un usuario.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idUser ID del usuario.
|
||||
* @throws ResiException si el usuario no existe, no pertenece a la residencia o ya está dado de baja.
|
||||
*/
|
||||
public void deleteLogico(Long idResidencia, Long idUser) {
|
||||
if (idResidencia == null || idUser == null){
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
//Verificamos si existe el usuario
|
||||
User user = userRepository.findById(idUser).orElse(null);
|
||||
if (user == null){
|
||||
throw new ResiException(ApiErrorCode.USUARIO_INVALIDO);
|
||||
}
|
||||
//Validamos si pertenece a la residencia
|
||||
if (!user.getResidencia().getId().equals(idResidencia)){
|
||||
throw new ResiException(ApiErrorCode.USUARIO_INVALIDO);
|
||||
}
|
||||
|
||||
//Validamos si el usuario ya esta de baja
|
||||
if (user.isBaja()){
|
||||
throw new ResiException(ApiErrorCode.USUARIO_BAJA);
|
||||
}
|
||||
|
||||
//Dar de baja
|
||||
user.setBaja(true);
|
||||
user.setEmail(passwordEncoder.encode(user.getEmail()));
|
||||
user.setFechaBaja(LocalDateTime.now());
|
||||
userRepository.save(user);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Desvincula registros de juego del usuario sin eliminar al usuario.
|
||||
*
|
||||
* @param idResidencia ID de la residencia del usuario.
|
||||
* @param idUser ID del usuario al que se le eliminarán las referencias.
|
||||
* @throws ResiException en caso de error
|
||||
*
|
||||
*/
|
||||
public void deleteReferencies(Long idResidencia, Long idUser) {
|
||||
if (idResidencia == null || idUser == null) {
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
User userTmp = userRepository.findById(idUser)
|
||||
.orElseThrow(() -> new ResiException(ApiErrorCode.USUARIO_INVALIDO));
|
||||
//Validar si pertenece a esa residencia
|
||||
if (!userTmp.getResidencia().getId().equals(idResidencia)) {
|
||||
throw new ResiException(ApiErrorCode.USUARIO_INVALIDO);
|
||||
}
|
||||
// Desvincular el usuario de todos los registros de juego
|
||||
for(RegistroJuego reg : userTmp.getRegistroJuegos()){
|
||||
reg.setUsuario(null);
|
||||
}
|
||||
userTmp.setRegistroJuegos(new LinkedHashSet<>());
|
||||
userRepository.save(userTmp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Actualiza los datos de un usuario existente.
|
||||
* <p>
|
||||
* Este método permite modificar nombre, apellido y correo electrónico del usuario,
|
||||
* con validaciones para cada uno. El correo debe ser válido y no estar ya registrado.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idUser ID del usuario a actualizar.
|
||||
* @param input Datos nuevos del usuario.
|
||||
* @return DTO con los datos del usuario actualizado.
|
||||
* @throws ResiException si los datos son inválidos o el usuario no pertenece a la residencia.
|
||||
*/
|
||||
public UserResponseDto update(Long idResidencia, Long idUser, UserDto input) {
|
||||
User userTmp = getUsuario(idResidencia, idUser);
|
||||
//Comprobar si elm usuario esta de baja
|
||||
if (userTmp.isBaja()) {
|
||||
throw new ResiException(ApiErrorCode.USUARIO_BAJA);
|
||||
}
|
||||
|
||||
if (input != null){
|
||||
//Validar si el nombre es valido
|
||||
if (input.getNombre() != null && !input.getNombre().isEmpty()) {
|
||||
userTmp.setNombre(input.getNombre().trim());
|
||||
}
|
||||
//Validar si el apellido es valido
|
||||
if (input.getApellido() != null && !input.getApellido().isEmpty()) {
|
||||
userTmp.setApellido(input.getApellido().trim());
|
||||
}
|
||||
//
|
||||
//Validar si el email es valido
|
||||
input.setEmail(input.getEmail().trim().toLowerCase());
|
||||
if (EmailService.isEmailValid(input.getEmail())) {
|
||||
//Validar si el email ya existe
|
||||
if (userRepository.findByEmail(input.getEmail()) != null) {
|
||||
throw new ResiException(ApiErrorCode.CORREO_DUPLICADO);
|
||||
}
|
||||
userTmp.setEmail(input.getEmail());
|
||||
} else {
|
||||
throw new ResiException(ApiErrorCode.CORREO_INVALIDO);
|
||||
}
|
||||
|
||||
}
|
||||
return new UserResponseDto(userRepository.save(userTmp));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cambia la contraseña de un usuario, validando su contraseña actual.
|
||||
*
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idUser ID del usuario.
|
||||
* @param input Objeto con la contraseña actual y la nueva.
|
||||
* @return DTO con los datos del usuario actualizado.
|
||||
* @throws ResiException si los datos son inválidos o la contraseña actual no coincide.
|
||||
*/
|
||||
public UserResponseDto updatePassword(Long idResidencia, Long idUser, ChangePasswordUserDto input) {
|
||||
if (idResidencia == null || idUser == null || input == null ||
|
||||
input.getOldPassword() == null || input.getNewPassword() == null) {
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
//Validar si existe ese usuario
|
||||
User userTmp = userRepository.findById(idUser)
|
||||
.orElseThrow(() -> new ResiException(ApiErrorCode.USUARIO_INVALIDO));
|
||||
//Validar si pertenece a esa residencia
|
||||
if (!userTmp.getResidencia().getId().equals(idResidencia)) {
|
||||
throw new ResiException(ApiErrorCode.USUARIO_INVALIDO);
|
||||
}
|
||||
//Comprobar si elm usuario esta de baja
|
||||
if (userTmp.isBaja()) {
|
||||
throw new ResiException(ApiErrorCode.USUARIO_BAJA);
|
||||
}
|
||||
//Validar si la contraseña es correcta
|
||||
if (!passwordEncoder.matches(input.getOldPassword(), userTmp.getPassword())) {
|
||||
throw new ResiException(ApiErrorCode.CONTRASENA_INCORRECTA); // Asegúrate de definir este código si no existe
|
||||
}
|
||||
|
||||
userTmp.setPassword(passwordEncoder.encode(input.getNewPassword()));
|
||||
|
||||
return new UserResponseDto(userRepository.save(userTmp));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Obtiene un usuario por su ID y valida que pertenezca a la residencia indicada.
|
||||
* @param idResidencia ID de la residencia.
|
||||
* @param idUsuario ID del usuario.
|
||||
* @return DTO del usuario solicitado.
|
||||
* @throws ResiException si el ID es nulo, el usuario no existe o no pertenece a la residencia.
|
||||
*/
|
||||
public User getUsuario(Long idResidencia, Long idUsuario) {
|
||||
if (idResidencia == null || idUsuario == null) {
|
||||
throw new ResiException(ApiErrorCode.CAMPOS_OBLIGATORIOS);
|
||||
}
|
||||
//validar si existe ese usuario
|
||||
User userTmp = userRepository.findById(idUsuario)
|
||||
.orElseThrow(() -> new ResiException(ApiErrorCode.USUARIO_INVALIDO));
|
||||
|
||||
//Validar si pertenece a esa residencia
|
||||
if (userTmp.getResidencia() == null || !userTmp.getResidencia().getId().equals(idResidencia)) {
|
||||
throw new ResiException(ApiErrorCode.USUARIO_INVALIDO);
|
||||
}
|
||||
return userTmp;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue