diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..e18faf5
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..63e9001
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..712ab9d
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..d917c34
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..cb28b0e
Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..5f0536e
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/Evidencias Poatman/Actualizar.png b/Evidencias Poatman/Actualizar.png
new file mode 100644
index 0000000..426fca6
Binary files /dev/null and b/Evidencias Poatman/Actualizar.png differ
diff --git a/Evidencias Poatman/Crear.png b/Evidencias Poatman/Crear.png
new file mode 100644
index 0000000..03cfdcf
Binary files /dev/null and b/Evidencias Poatman/Crear.png differ
diff --git a/Evidencias Poatman/Eliminar.png b/Evidencias Poatman/Eliminar.png
new file mode 100644
index 0000000..9b4ae95
Binary files /dev/null and b/Evidencias Poatman/Eliminar.png differ
diff --git a/Evidencias Poatman/Evidencia_BD.png b/Evidencias Poatman/Evidencia_BD.png
new file mode 100644
index 0000000..0e2ac70
Binary files /dev/null and b/Evidencias Poatman/Evidencia_BD.png differ
diff --git a/Evidencias Poatman/Listar por Id.png b/Evidencias Poatman/Listar por Id.png
new file mode 100644
index 0000000..8c0a580
Binary files /dev/null and b/Evidencias Poatman/Listar por Id.png differ
diff --git a/Evidencias Poatman/Listar todo.png b/Evidencias Poatman/Listar todo.png
new file mode 100644
index 0000000..e211256
Binary files /dev/null and b/Evidencias Poatman/Listar todo.png differ
diff --git a/README.md b/README.md
index 0ef43ea..fb5b552 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,123 @@
-# tesffullstack
+# API REST — `test-full-stack-orozco`
+
+**Autor:** Aaron Orozco
+**Stack:** Java 17 · Spring Boot 3.2 · Spring Data JPA · Maven · PostgreSQL 17
+**Base URL:** `http://localhost:8080`
+
+## Contexto
+
+API REST para gestión de personas (CRUD) sobre PostgreSQL.
+El proyecto mantiene un contrato de respuesta uniforme y actualmente usa una arquitectura por capas:
+- `controller` para exponer endpoints
+- `service` / `serviceImpl` para lógica de negocio
+- `repository` para acceso a datos
+
+## Contrato de respuesta
+
+Todas las operaciones responden con:
+
+| Campo | Tipo | Descripción |
+|-------|------|-------------|
+| `status` | boolean | Resultado de la operación |
+| `msg` | string | Mensaje descriptivo |
+| `data` | array \| null | Registros devueltos o `null` en eliminación/error |
+
+Ejemplo:
+
+```json
+{
+ "status": true,
+ "msg": "Persona encontrada",
+ "data": [
+ {
+ "id": 1,
+ "nombre": "Aaron",
+ "apellido": "Orozco",
+ "fechaNacimiento": "1995-06-15",
+ "puesto": "Desarrollador Full Stack",
+ "sueldo": 45000.00
+ }
+ ]
+}
+```
+
+## Endpoints vigentes
+
+| Método | Ruta | Descripción |
+|--------|------|-------------|
+| `GET` | `/api/persons/findAll` | Listado completo |
+| `GET` | `/api/persons/findById/{id}` | Consulta por identificador |
+| `POST` | `/api/persons/create` | Registro de persona |
+| `PUT` | `/api/persons/update/{id}` | Actualización |
+| `DELETE` | `/api/persons/delete/{id}` | Eliminación |
+
+## Persistencia y configuración
+
+`src/main/resources/application.properties`:
+
+| Parámetro | Valor |
+|-----------|-------|
+| JDBC URL | `jdbc:postgresql://localhost:5432/orozco_bd` |
+| Usuario | `conexion` |
+| Driver | `org.postgresql.Driver` |
+| Dialecto | `org.hibernate.dialect.PostgreSQLDialect` |
+| Hibernate DDL | `none` |
+
+La entidad `Person` mapea la tabla `person`, incluyendo la columna `"fechaNacimiento"` (respetando mayúsculas/minúsculas de PostgreSQL).
+
+## Estructura del proyecto
+
+```
+src/
+├── main/java/com/orozco/testfullstack/
+│ ├── controller/PersonController.java
+│ ├── service/PersonService.java
+│ ├── service/impl/PersonServiceImpl.java
+│ ├── repository/PersonRepository.java
+│ └── model/Person.java, ApiResponse.java
+└── test/java/com/orozco/testfullstack/
+ ├── controller/PersonControllerTest.java
+ ├── service/impl/PersonServiceImplTest.java
+ └── model/ApiResponseTest.java
+```
+
+## Pruebas
+
+| Clase | Cobertura |
+|-------|-----------|
+| `PersonControllerTest` | Contrato HTTP del controlador con `@WebMvcTest` |
+| `PersonServiceImplTest` | Lógica de negocio con `Mockito` |
+| `ApiResponseTest` | Fábrica de respuestas `ok` / `error` |
+
+Ejecución:
+
+```bash
+mvnw.cmd test
+```
+
+## Evidencia (Postman)
+
+### GET por id
+`GET /api/persons/findById/1`
+
+
+
+### GET listado
+`GET /api/persons/findAll`
+
+
+
+### POST crear
+`POST /api/persons/create`
+
+
+
+### PUT actualizar
+`PUT /api/persons/update/4`
+
+
+
+### DELETE eliminar
+`DELETE /api/persons/delete/4`
+
+
diff --git a/bd/README.md b/bd/README.md
deleted file mode 100644
index 0ad162f..0000000
--- a/bd/README.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# Requerimientos
-
-- MySQL instalado en su sistema. Desarrollado con Ver 8.0.31 for Win64 on x86_64 (MySQL Community Server - GPL).
-- Acceso de administrador a MySQL.
-
-# Despliegue y Ejecución
-
-1. Clonar este repositorio:
- ```
- git clone https://github.com/usuario/repositorio.git
- ```
-
-2. Iniciar sesión en MySQL como usuario root:
- ```
- mysql -u root -p
- ```
-
-3. Cargar el script de creación de la base de datos:
- ```
- source ruta_del_script_creacion_bd.sql
- ```
- Ejemplo: `D:\SRC\GitHub\tonysoft2018\tesffullstack\bd\script_creacion_bd.sql`
-
-4. Cambiar a la base de datos recién creada:
- ```
- USE bd_garcia;
- ```
-
-5. Ejecutar la consulta para verificar los datos en la tabla person:
- ```
- SELECT * FROM person;
- ```
-
-6. Crear un nuevo usuario para la conexión del backend y otorgarle privilegios:
- ```
- CREATE USER 'conexion'@'localhost' IDENTIFIED BY 'Wk2!rT8s@6w';
- GRANT ALL PRIVILEGES ON bd_garcia.* TO 'conexion'@'localhost';
- FLUSH PRIVILEGES;
- ```
-
-7. Salir de MySQL:
- ```
- exit;
- ```
\ No newline at end of file
diff --git a/bd/script_creacion_bd.sql b/bd/script_creacion_bd.sql
deleted file mode 100644
index 89a9fbc..0000000
--- a/bd/script_creacion_bd.sql
+++ /dev/null
@@ -1,12 +0,0 @@
-CREATE DATABASE IF NOT EXISTS bd_garcia;
-
-USE bd_garcia;
-
-CREATE TABLE IF NOT EXISTS person (
- id INT AUTO_INCREMENT PRIMARY KEY,
- nombre VARCHAR(255),
- apellido VARCHAR(255),
- fechaNacimiento DATE,
- puesto VARCHAR(255),
- sueldo DECIMAL(10, 2)
-);
diff --git a/mvnw b/mvnw
new file mode 100644
index 0000000..66df285
--- /dev/null
+++ b/mvnw
@@ -0,0 +1,308 @@
+#!/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
+#
+# https://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.2.0
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+ else
+ JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=$(java-config --jre-home)
+ fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+ JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="$(which javac)"
+ if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=$(which readlink)
+ if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+ if $darwin ; then
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+ else
+ javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+ fi
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=$(cd "$wdir/.." || exit 1; pwd)
+ fi
+ # end of workaround
+ done
+ printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ # Remove \r in case we run on Windows within Git Bash
+ # and check out the repository with auto CRLF management
+ # enabled. Otherwise, we may read lines that are delimited with
+ # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+ # splitting rules.
+ tr -s '\r\n' ' ' < "$1"
+ fi
+}
+
+log() {
+ if [ "$MVNW_VERBOSE" = true ]; then
+ printf '%s\n' "$1"
+ fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+ log "Found $wrapperJarPath"
+else
+ log "Couldn't find $wrapperJarPath, downloading it ..."
+
+ if [ -n "$MVNW_REPOURL" ]; then
+ wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ else
+ wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ fi
+ while IFS="=" read -r key value; do
+ # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+ safeValue=$(echo "$value" | tr -d '\r')
+ case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+ esac
+ done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+ log "Downloading from: $wrapperUrl"
+
+ if $cygwin; then
+ wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+ fi
+
+ if command -v wget > /dev/null; then
+ log "Found wget ... using wget"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ log "Found curl ... using curl"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ else
+ curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ fi
+ else
+ log "Falling back to using Java to download"
+ javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaSource=$(cygpath --path --windows "$javaSource")
+ javaClass=$(cygpath --path --windows "$javaClass")
+ fi
+ if [ -e "$javaSource" ]; then
+ if [ ! -e "$javaClass" ]; then
+ log " - Compiling MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/javac" "$javaSource")
+ fi
+ if [ -e "$javaClass" ]; then
+ log " - Running MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+ case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+ esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+ wrapperSha256Result=false
+ if command -v sha256sum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ elif command -v shasum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+ echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+ exit 1
+ fi
+ if [ $wrapperSha256Result = false ]; then
+ echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+ echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+ echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
new file mode 100644
index 0000000..95ba6f5
--- /dev/null
+++ b/mvnw.cmd
@@ -0,0 +1,205 @@
+@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 https://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.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %WRAPPER_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+ powershell -Command "&{"^
+ "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+ "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+ " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+ " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+ " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+ " exit 1;"^
+ "}"^
+ "}"
+ if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..347e44b
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,53 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.5
+
+
+
+ com.orozco
+ test-full-stack
+ 0.0.1-SNAPSHOT
+ test-full-stack
+ API REST - prueba tecnica full stack Orozco
+
+
+ 17
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.postgresql
+ postgresql
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/sql/bd_orozco.sql b/sql/bd_orozco.sql
new file mode 100644
index 0000000..bf1d7af
--- /dev/null
+++ b/sql/bd_orozco.sql
@@ -0,0 +1,32 @@
+-- Base de datos y permisos (ejecutar como usuario postgres)
+CREATE DATABASE bd_orozco;
+
+CREATE USER conexion WITH PASSWORD 'Aaron.2026';
+
+GRANT ALL PRIVILEGES ON DATABASE bd_orozco TO conexion;
+
+-- Conectarse a bd_orozco antes de ejecutar lo siguiente:
+-- psql -U postgres -d bd_orozco
+
+GRANT ALL ON SCHEMA public TO conexion;
+ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO conexion;
+ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO conexion;
+
+-- Tabla person (alineada a com.orozco.testfullstack.model.Person)
+CREATE TABLE IF NOT EXISTS person (
+ id BIGSERIAL PRIMARY KEY,
+ nombre VARCHAR(100) NOT NULL,
+ apellido VARCHAR(100) NOT NULL,
+ "fechaNacimiento" DATE NOT NULL,
+ puesto VARCHAR(150) NOT NULL,
+ sueldo NUMERIC(12, 2) NOT NULL
+);
+
+GRANT ALL PRIVILEGES ON TABLE person TO conexion;
+GRANT USAGE, SELECT ON SEQUENCE person_id_seq TO conexion;
+
+-- Datos de ejemplo
+INSERT INTO person (nombre, apellido, "fechaNacimiento", puesto, sueldo)
+VALUES
+ ('Aaron', 'Orozco', '1995-06-15', 'Desarrollador Full Stack', 45000.00),
+ ('Ana', 'Ruiz', '1992-08-10', 'QA', 32000.00);
diff --git a/sql/create_person_table.sql b/sql/create_person_table.sql
new file mode 100644
index 0000000..5f35a7b
--- /dev/null
+++ b/sql/create_person_table.sql
@@ -0,0 +1,21 @@
+GRANT ALL ON SCHEMA public TO conexion;
+ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO conexion;
+ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO conexion;
+
+CREATE TABLE IF NOT EXISTS person (
+ id BIGSERIAL PRIMARY KEY,
+ nombre VARCHAR(100) NOT NULL,
+ apellido VARCHAR(100) NOT NULL,
+ "fechaNacimiento" DATE NOT NULL,
+ puesto VARCHAR(150) NOT NULL,
+ sueldo NUMERIC(12, 2) NOT NULL
+);
+
+GRANT ALL PRIVILEGES ON TABLE person TO conexion;
+GRANT USAGE, SELECT ON SEQUENCE person_id_seq TO conexion;
+
+INSERT INTO person (nombre, apellido, "fechaNacimiento", puesto, sueldo)
+VALUES
+ ('Aaron', 'Orozco', '1995-06-15', 'Desarrollador Full Stack', 45000.00),
+ ('Ana', 'Ruiz', '1992-08-10', 'QA', 32000.00)
+ON CONFLICT DO NOTHING;
diff --git a/sql/grant_conexion.sql b/sql/grant_conexion.sql
new file mode 100644
index 0000000..bfc44cc
--- /dev/null
+++ b/sql/grant_conexion.sql
@@ -0,0 +1,6 @@
+-- Ejecutar en DBeaver conectado como postgres, base de datos postgres
+
+GRANT ALL PRIVILEGES ON TABLE person TO conexion;
+GRANT USAGE, SELECT ON SEQUENCE person_id_seq TO conexion;
+
+-- Si tambien usas orozco_bd, conectate a esa base y ejecuta lo mismo ahi.
diff --git a/sql/orozco_bd.sql b/sql/orozco_bd.sql
new file mode 100644
index 0000000..54c81e2
--- /dev/null
+++ b/sql/orozco_bd.sql
@@ -0,0 +1,41 @@
+-- ============================================================
+-- PASO 1: Ejecutar conectado como postgres a la BD "postgres"
+-- ============================================================
+
+CREATE DATABASE orozco_bd;
+
+DO $$
+BEGIN
+ IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'conexion') THEN
+ CREATE USER conexion WITH PASSWORD 'Aaron.2026';
+ END IF;
+END
+$$;
+
+GRANT ALL PRIVILEGES ON DATABASE orozco_bd TO conexion;
+
+-- ============================================================
+-- PASO 2: Cambiar conexion a la BD "orozco_bd" y ejecutar esto
+-- ============================================================
+
+GRANT ALL ON SCHEMA public TO conexion;
+ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO conexion;
+ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO conexion;
+
+CREATE TABLE IF NOT EXISTS person (
+ id BIGSERIAL PRIMARY KEY,
+ nombre VARCHAR(100) NOT NULL,
+ apellido VARCHAR(100) NOT NULL,
+ "fechaNacimiento" DATE NOT NULL,
+ puesto VARCHAR(150) NOT NULL,
+ sueldo NUMERIC(12, 2) NOT NULL
+);
+
+GRANT ALL PRIVILEGES ON TABLE person TO conexion;
+GRANT USAGE, SELECT ON SEQUENCE person_id_seq TO conexion;
+
+INSERT INTO person (nombre, apellido, "fechaNacimiento", puesto, sueldo)
+VALUES
+ ('Aaron', 'Orozco', '1995-06-15', 'Desarrollador Full Stack', 45000.00),
+ ('Ana', 'Ruiz', '1992-08-10', 'QA', 32000.00)
+ON CONFLICT DO NOTHING;
diff --git a/src/main/java/com/orozco/testfullstack/TestFullStackApplication.java b/src/main/java/com/orozco/testfullstack/TestFullStackApplication.java
new file mode 100644
index 0000000..95448c6
--- /dev/null
+++ b/src/main/java/com/orozco/testfullstack/TestFullStackApplication.java
@@ -0,0 +1,12 @@
+package com.orozco.testfullstack;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class TestFullStackApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(TestFullStackApplication.class, args);
+ }
+}
diff --git a/src/main/java/com/orozco/testfullstack/controller/PersonController.java b/src/main/java/com/orozco/testfullstack/controller/PersonController.java
new file mode 100644
index 0000000..4b262b5
--- /dev/null
+++ b/src/main/java/com/orozco/testfullstack/controller/PersonController.java
@@ -0,0 +1,54 @@
+package com.orozco.testfullstack.controller;
+
+import com.orozco.testfullstack.model.ApiResponse;
+import com.orozco.testfullstack.model.Person;
+import com.orozco.testfullstack.service.PersonService;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/api/persons")
+@CrossOrigin(origins = "http://localhost:4200")
+public class PersonController {
+
+ private final PersonService personService;
+
+ public PersonController(PersonService personService) {
+ this.personService = personService;
+ }
+
+ @GetMapping("/findAll")
+ public ApiResponse findAll() {
+ return personService.findAll();
+ }
+
+ @GetMapping("/findById/{id}")
+ public ApiResponse findById(@PathVariable Long id) {
+ return personService.findById(id);
+ }
+
+ @PostMapping("/create")
+ @ResponseStatus(HttpStatus.CREATED)
+ public ApiResponse create(@RequestBody Person person) {
+ return personService.create(person);
+ }
+
+ @PutMapping("/update/{id}")
+ public ApiResponse update(@PathVariable Long id, @RequestBody Person person) {
+ return personService.update(id, person);
+ }
+
+ @DeleteMapping("/delete/{id}")
+ public ApiResponse delete(@PathVariable Long id) {
+ return personService.delete(id);
+ }
+}
diff --git a/src/main/java/com/orozco/testfullstack/model/ApiResponse.java b/src/main/java/com/orozco/testfullstack/model/ApiResponse.java
new file mode 100644
index 0000000..d8e83ac
--- /dev/null
+++ b/src/main/java/com/orozco/testfullstack/model/ApiResponse.java
@@ -0,0 +1,27 @@
+package com.orozco.testfullstack.model;
+
+import java.util.List;
+
+public class ApiResponse {
+
+ public boolean status;
+ public String msg;
+ public List data;
+
+ public ApiResponse() {
+ }
+
+ public ApiResponse(boolean status, String msg, List data) {
+ this.status = status;
+ this.msg = msg;
+ this.data = data;
+ }
+
+ public static ApiResponse ok(String msg, List data) {
+ return new ApiResponse<>(true, msg, data);
+ }
+
+ public static ApiResponse error(String msg) {
+ return new ApiResponse<>(false, msg, null);
+ }
+}
diff --git a/src/main/java/com/orozco/testfullstack/model/Person.java b/src/main/java/com/orozco/testfullstack/model/Person.java
new file mode 100644
index 0000000..1d26a63
--- /dev/null
+++ b/src/main/java/com/orozco/testfullstack/model/Person.java
@@ -0,0 +1,77 @@
+package com.orozco.testfullstack.model;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Entity
+@Table(name = "person")
+public class Person {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ private String nombre;
+ private String apellido;
+
+ @Column(name = "fechaNacimiento")
+ private LocalDate fechaNacimiento;
+
+ private String puesto;
+ private BigDecimal sueldo;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getNombre() {
+ return nombre;
+ }
+
+ public void setNombre(String nombre) {
+ this.nombre = nombre;
+ }
+
+ public String getApellido() {
+ return apellido;
+ }
+
+ public void setApellido(String apellido) {
+ this.apellido = apellido;
+ }
+
+ public LocalDate getFechaNacimiento() {
+ return fechaNacimiento;
+ }
+
+ public void setFechaNacimiento(LocalDate fechaNacimiento) {
+ this.fechaNacimiento = fechaNacimiento;
+ }
+
+ public String getPuesto() {
+ return puesto;
+ }
+
+ public void setPuesto(String puesto) {
+ this.puesto = puesto;
+ }
+
+ public BigDecimal getSueldo() {
+ return sueldo;
+ }
+
+ public void setSueldo(BigDecimal sueldo) {
+ this.sueldo = sueldo;
+ }
+}
diff --git a/src/main/java/com/orozco/testfullstack/repository/PersonRepository.java b/src/main/java/com/orozco/testfullstack/repository/PersonRepository.java
new file mode 100644
index 0000000..d6472aa
--- /dev/null
+++ b/src/main/java/com/orozco/testfullstack/repository/PersonRepository.java
@@ -0,0 +1,7 @@
+package com.orozco.testfullstack.repository;
+
+import com.orozco.testfullstack.model.Person;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface PersonRepository extends JpaRepository {
+}
diff --git a/src/main/java/com/orozco/testfullstack/service/PersonService.java b/src/main/java/com/orozco/testfullstack/service/PersonService.java
new file mode 100644
index 0000000..809735e
--- /dev/null
+++ b/src/main/java/com/orozco/testfullstack/service/PersonService.java
@@ -0,0 +1,17 @@
+package com.orozco.testfullstack.service;
+
+import com.orozco.testfullstack.model.ApiResponse;
+import com.orozco.testfullstack.model.Person;
+
+public interface PersonService {
+
+ ApiResponse findAll();
+
+ ApiResponse findById(Long id);
+
+ ApiResponse create(Person person);
+
+ ApiResponse update(Long id, Person person);
+
+ ApiResponse delete(Long id);
+}
diff --git a/src/main/java/com/orozco/testfullstack/service/impl/PersonServiceImpl.java b/src/main/java/com/orozco/testfullstack/service/impl/PersonServiceImpl.java
new file mode 100644
index 0000000..fb0cbd9
--- /dev/null
+++ b/src/main/java/com/orozco/testfullstack/service/impl/PersonServiceImpl.java
@@ -0,0 +1,63 @@
+package com.orozco.testfullstack.service.impl;
+
+import com.orozco.testfullstack.model.ApiResponse;
+import com.orozco.testfullstack.model.Person;
+import com.orozco.testfullstack.repository.PersonRepository;
+import com.orozco.testfullstack.service.PersonService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class PersonServiceImpl implements PersonService {
+
+ private final PersonRepository personRepository;
+
+ public PersonServiceImpl(PersonRepository personRepository) {
+ this.personRepository = personRepository;
+ }
+
+ @Override
+ public ApiResponse findAll() {
+ List persons = personRepository.findAll();
+ return ApiResponse.ok("Personas obtenidas correctamente", persons);
+ }
+
+ @Override
+ public ApiResponse findById(Long id) {
+ return personRepository.findById(id)
+ .map(person -> ApiResponse.ok("Persona encontrada", List.of(person)))
+ .orElse(ApiResponse.error("Persona no encontrada con id: " + id));
+ }
+
+ @Override
+ public ApiResponse create(Person person) {
+ Person saved = personRepository.save(person);
+ return ApiResponse.ok("Persona creada correctamente", List.of(saved));
+ }
+
+ @Override
+ public ApiResponse update(Long id, Person person) {
+ return personRepository.findById(id)
+ .map(existing -> {
+ existing.setNombre(person.getNombre());
+ existing.setApellido(person.getApellido());
+ existing.setFechaNacimiento(person.getFechaNacimiento());
+ existing.setPuesto(person.getPuesto());
+ existing.setSueldo(person.getSueldo());
+ Person updated = personRepository.save(existing);
+ return ApiResponse.ok("Persona actualizada correctamente", List.of(updated));
+ })
+ .orElse(ApiResponse.error("Persona no encontrada con id: " + id));
+ }
+
+ @Override
+ public ApiResponse delete(Long id) {
+ return personRepository.findById(id)
+ .map(person -> {
+ personRepository.delete(person);
+ return ApiResponse.ok("Persona eliminada correctamente", null);
+ })
+ .orElseGet(() -> ApiResponse.error("Persona no encontrada con id: " + id));
+ }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..bcd4a90
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,14 @@
+spring.application.name=test-full-stack-orozco
+
+spring.datasource.url=jdbc:postgresql://localhost:5432/orozco_bd
+spring.datasource.username=conexion
+spring.datasource.password=Aaron.2026
+spring.datasource.driver-class-name=org.postgresql.Driver
+
+spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
+spring.jpa.hibernate.ddl-auto=none
+spring.jpa.show-sql=false
+spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
+spring.jpa.properties.hibernate.globally_quoted_identifiers=true
+
+server.port=8080
diff --git a/src/test/java/com/orozco/testfullstack/controller/PersonControllerTest.java b/src/test/java/com/orozco/testfullstack/controller/PersonControllerTest.java
new file mode 100644
index 0000000..905037e
--- /dev/null
+++ b/src/test/java/com/orozco/testfullstack/controller/PersonControllerTest.java
@@ -0,0 +1,190 @@
+package com.orozco.testfullstack.controller;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.orozco.testfullstack.model.ApiResponse;
+import com.orozco.testfullstack.model.Person;
+import com.orozco.testfullstack.service.PersonService;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@WebMvcTest(PersonController.class)
+class PersonControllerTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Autowired
+ private ObjectMapper objectMapper;
+
+ @MockBean
+ private PersonService personService;
+
+ private Person samplePerson;
+
+ @BeforeEach
+ void setUp() {
+ samplePerson = new Person();
+ samplePerson.setId(1L);
+ samplePerson.setNombre("Cristian");
+ samplePerson.setApellido("Orozco");
+ samplePerson.setFechaNacimiento(LocalDate.of(1995, 6, 15));
+ samplePerson.setPuesto("Desarrollador Full Stack");
+ samplePerson.setSueldo(new BigDecimal("45000.00"));
+ }
+
+ @Test
+ void findAll_returnsPersonList() throws Exception {
+ when(personService.findAll())
+ .thenReturn(ApiResponse.ok("Personas obtenidas correctamente", List.of(samplePerson)));
+
+ mockMvc.perform(get("/api/persons/findAll"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.status").value(true))
+ .andExpect(jsonPath("$.msg").value("Personas obtenidas correctamente"))
+ .andExpect(jsonPath("$.data.length()").value(1))
+ .andExpect(jsonPath("$.data[0].nombre").value("Cristian"));
+ }
+
+ @Test
+ void findById_whenExists_returnsPerson() throws Exception {
+ when(personService.findById(1L))
+ .thenReturn(ApiResponse.ok("Persona encontrada", List.of(samplePerson)));
+
+ mockMvc.perform(get("/api/persons/findById/1"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.status").value(true))
+ .andExpect(jsonPath("$.msg").value("Persona encontrada"))
+ .andExpect(jsonPath("$.data[0].id").value(1));
+ }
+
+ @Test
+ void findById_whenNotFound_returnsError() throws Exception {
+ when(personService.findById(99L))
+ .thenReturn(ApiResponse.error("Persona no encontrada con id: 99"));
+
+ mockMvc.perform(get("/api/persons/findById/99"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.status").value(false))
+ .andExpect(jsonPath("$.msg").value("Persona no encontrada con id: 99"))
+ .andExpect(jsonPath("$.data").doesNotExist());
+ }
+
+ @Test
+ void create_persistsAndReturnsCreated() throws Exception {
+ Person request = new Person();
+ request.setNombre("Ana");
+ request.setApellido("Ruiz");
+ request.setFechaNacimiento(LocalDate.of(1992, 8, 10));
+ request.setPuesto("QA");
+ request.setSueldo(new BigDecimal("32000.00"));
+
+ Person saved = new Person();
+ saved.setId(2L);
+ saved.setNombre(request.getNombre());
+ saved.setApellido(request.getApellido());
+ saved.setFechaNacimiento(request.getFechaNacimiento());
+ saved.setPuesto(request.getPuesto());
+ saved.setSueldo(request.getSueldo());
+
+ when(personService.create(any(Person.class)))
+ .thenReturn(ApiResponse.ok("Persona creada correctamente", List.of(saved)));
+
+ mockMvc.perform(post("/api/persons/create")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(request)))
+ .andExpect(status().isCreated())
+ .andExpect(jsonPath("$.status").value(true))
+ .andExpect(jsonPath("$.msg").value("Persona creada correctamente"))
+ .andExpect(jsonPath("$.data[0].id").value(2))
+ .andExpect(jsonPath("$.data[0].nombre").value("Ana"));
+ }
+
+ @Test
+ void update_whenExists_updatesFields() throws Exception {
+ Person request = new Person();
+ request.setNombre("Cristian");
+ request.setApellido("Orozco Martinez");
+ request.setFechaNacimiento(LocalDate.of(1995, 6, 15));
+ request.setPuesto("Full Stack");
+ request.setSueldo(new BigDecimal("52000.00"));
+
+ Person updated = new Person();
+ updated.setId(1L);
+ updated.setNombre(request.getNombre());
+ updated.setApellido(request.getApellido());
+ updated.setFechaNacimiento(request.getFechaNacimiento());
+ updated.setPuesto(request.getPuesto());
+ updated.setSueldo(request.getSueldo());
+
+ when(personService.update(eq(1L), any(Person.class)))
+ .thenReturn(ApiResponse.ok("Persona actualizada correctamente", List.of(updated)));
+
+ mockMvc.perform(put("/api/persons/update/1")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(request)))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.status").value(true))
+ .andExpect(jsonPath("$.msg").value("Persona actualizada correctamente"))
+ .andExpect(jsonPath("$.data[0].apellido").value("Orozco Martinez"));
+ }
+
+ @Test
+ void update_whenNotFound_returnsError() throws Exception {
+ Person request = new Person();
+ request.setNombre("Test");
+
+ when(personService.update(eq(99L), any(Person.class)))
+ .thenReturn(ApiResponse.error("Persona no encontrada con id: 99"));
+
+ mockMvc.perform(put("/api/persons/update/99")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(request)))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.status").value(false))
+ .andExpect(jsonPath("$.msg").value("Persona no encontrada con id: 99"));
+ }
+
+ @Test
+ void delete_whenExists_removesPerson() throws Exception {
+ when(personService.delete(1L))
+ .thenReturn(ApiResponse.ok("Persona eliminada correctamente", null));
+
+ mockMvc.perform(delete("/api/persons/delete/1"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.status").value(true))
+ .andExpect(jsonPath("$.msg").value("Persona eliminada correctamente"));
+
+ verify(personService).delete(1L);
+ }
+
+ @Test
+ void delete_whenNotFound_returnsError() throws Exception {
+ when(personService.delete(99L))
+ .thenReturn(ApiResponse.error("Persona no encontrada con id: 99"));
+
+ mockMvc.perform(delete("/api/persons/delete/99"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.status").value(false))
+ .andExpect(jsonPath("$.msg").value("Persona no encontrada con id: 99"));
+ }
+}
diff --git a/src/test/java/com/orozco/testfullstack/model/ApiResponseTest.java b/src/test/java/com/orozco/testfullstack/model/ApiResponseTest.java
new file mode 100644
index 0000000..c8cf0f6
--- /dev/null
+++ b/src/test/java/com/orozco/testfullstack/model/ApiResponseTest.java
@@ -0,0 +1,36 @@
+package com.orozco.testfullstack.model;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class ApiResponseTest {
+
+ @Test
+ void ok_buildsSuccessResponse() {
+ Person person = new Person();
+ person.setId(1L);
+ person.setNombre("Cristian");
+
+ ApiResponse response = ApiResponse.ok("Operacion exitosa", List.of(person));
+
+ assertTrue(response.status);
+ assertEquals("Operacion exitosa", response.msg);
+ assertEquals(1, response.data.size());
+ assertEquals("Cristian", response.data.get(0).getNombre());
+ }
+
+ @Test
+ void error_buildsFailureResponse() {
+ ApiResponse response = ApiResponse.error("Recurso no encontrado");
+
+ assertFalse(response.status);
+ assertEquals("Recurso no encontrado", response.msg);
+ assertNull(response.data);
+ }
+}
diff --git a/src/test/java/com/orozco/testfullstack/service/impl/PersonServiceImplTest.java b/src/test/java/com/orozco/testfullstack/service/impl/PersonServiceImplTest.java
new file mode 100644
index 0000000..0fb838a
--- /dev/null
+++ b/src/test/java/com/orozco/testfullstack/service/impl/PersonServiceImplTest.java
@@ -0,0 +1,174 @@
+package com.orozco.testfullstack.service.impl;
+
+import com.orozco.testfullstack.model.ApiResponse;
+import com.orozco.testfullstack.model.Person;
+import com.orozco.testfullstack.repository.PersonRepository;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class PersonServiceImplTest {
+
+ @Mock
+ private PersonRepository personRepository;
+
+ @InjectMocks
+ private PersonServiceImpl personService;
+
+ private Person samplePerson;
+
+ @BeforeEach
+ void setUp() {
+ samplePerson = new Person();
+ samplePerson.setId(1L);
+ samplePerson.setNombre("Cristian");
+ samplePerson.setApellido("Orozco");
+ samplePerson.setFechaNacimiento(LocalDate.of(1995, 6, 15));
+ samplePerson.setPuesto("Desarrollador Full Stack");
+ samplePerson.setSueldo(new BigDecimal("45000.00"));
+ }
+
+ @Test
+ void findAll_returnsPersonList() {
+ when(personRepository.findAll()).thenReturn(List.of(samplePerson));
+
+ ApiResponse response = personService.findAll();
+
+ assertTrue(response.status);
+ assertEquals("Personas obtenidas correctamente", response.msg);
+ assertEquals(1, response.data.size());
+ assertEquals("Cristian", response.data.get(0).getNombre());
+ verify(personRepository).findAll();
+ }
+
+ @Test
+ void findById_whenExists_returnsPerson() {
+ when(personRepository.findById(1L)).thenReturn(Optional.of(samplePerson));
+
+ ApiResponse response = personService.findById(1L);
+
+ assertTrue(response.status);
+ assertEquals("Persona encontrada", response.msg);
+ assertEquals(1L, response.data.get(0).getId());
+ verify(personRepository).findById(1L);
+ }
+
+ @Test
+ void findById_whenNotFound_returnsError() {
+ when(personRepository.findById(99L)).thenReturn(Optional.empty());
+
+ ApiResponse response = personService.findById(99L);
+
+ assertFalse(response.status);
+ assertEquals("Persona no encontrada con id: 99", response.msg);
+ assertNull(response.data);
+ }
+
+ @Test
+ void create_persistsAndReturnsCreated() {
+ Person request = new Person();
+ request.setNombre("Ana");
+ request.setApellido("Ruiz");
+ request.setFechaNacimiento(LocalDate.of(1992, 8, 10));
+ request.setPuesto("QA");
+ request.setSueldo(new BigDecimal("32000.00"));
+
+ Person saved = new Person();
+ saved.setId(2L);
+ saved.setNombre(request.getNombre());
+ saved.setApellido(request.getApellido());
+ saved.setFechaNacimiento(request.getFechaNacimiento());
+ saved.setPuesto(request.getPuesto());
+ saved.setSueldo(request.getSueldo());
+
+ when(personRepository.save(request)).thenReturn(saved);
+
+ ApiResponse response = personService.create(request);
+
+ assertTrue(response.status);
+ assertEquals("Persona creada correctamente", response.msg);
+ assertEquals(2L, response.data.get(0).getId());
+ assertEquals("Ana", response.data.get(0).getNombre());
+ verify(personRepository).save(request);
+ }
+
+ @Test
+ void update_whenExists_updatesFields() {
+ Person request = new Person();
+ request.setNombre("Cristian");
+ request.setApellido("Orozco Martinez");
+ request.setFechaNacimiento(LocalDate.of(1995, 6, 15));
+ request.setPuesto("Full Stack");
+ request.setSueldo(new BigDecimal("52000.00"));
+
+ when(personRepository.findById(1L)).thenReturn(Optional.of(samplePerson));
+ when(personRepository.save(any(Person.class))).thenAnswer(invocation -> invocation.getArgument(0));
+
+ ApiResponse response = personService.update(1L, request);
+
+ assertTrue(response.status);
+ assertEquals("Persona actualizada correctamente", response.msg);
+ assertEquals("Orozco Martinez", response.data.get(0).getApellido());
+ assertEquals(new BigDecimal("52000.00"), response.data.get(0).getSueldo());
+ verify(personRepository).findById(1L);
+ verify(personRepository).save(samplePerson);
+ }
+
+ @Test
+ void update_whenNotFound_returnsError() {
+ Person request = new Person();
+ request.setNombre("Test");
+
+ when(personRepository.findById(99L)).thenReturn(Optional.empty());
+
+ ApiResponse response = personService.update(99L, request);
+
+ assertFalse(response.status);
+ assertEquals("Persona no encontrada con id: 99", response.msg);
+ assertNull(response.data);
+ verify(personRepository, never()).save(any());
+ }
+
+ @Test
+ void delete_whenExists_removesPerson() {
+ when(personRepository.findById(1L)).thenReturn(Optional.of(samplePerson));
+
+ ApiResponse response = personService.delete(1L);
+
+ assertTrue(response.status);
+ assertEquals("Persona eliminada correctamente", response.msg);
+ assertNull(response.data);
+ verify(personRepository).findById(1L);
+ verify(personRepository).delete(samplePerson);
+ }
+
+ @Test
+ void delete_whenNotFound_returnsError() {
+ when(personRepository.findById(99L)).thenReturn(Optional.empty());
+
+ ApiResponse response = personService.delete(99L);
+
+ assertFalse(response.status);
+ assertEquals("Persona no encontrada con id: 99", response.msg);
+ assertNull(response.data);
+ verify(personRepository, never()).delete(any());
+ }
+}
diff --git a/target/classes/application.properties b/target/classes/application.properties
new file mode 100644
index 0000000..bcd4a90
--- /dev/null
+++ b/target/classes/application.properties
@@ -0,0 +1,14 @@
+spring.application.name=test-full-stack-orozco
+
+spring.datasource.url=jdbc:postgresql://localhost:5432/orozco_bd
+spring.datasource.username=conexion
+spring.datasource.password=Aaron.2026
+spring.datasource.driver-class-name=org.postgresql.Driver
+
+spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
+spring.jpa.hibernate.ddl-auto=none
+spring.jpa.show-sql=false
+spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
+spring.jpa.properties.hibernate.globally_quoted_identifiers=true
+
+server.port=8080
diff --git a/target/classes/com/orozco/testfullstack/TestFullStackApplication.class b/target/classes/com/orozco/testfullstack/TestFullStackApplication.class
new file mode 100644
index 0000000..a46c28a
Binary files /dev/null and b/target/classes/com/orozco/testfullstack/TestFullStackApplication.class differ
diff --git a/target/classes/com/orozco/testfullstack/controller/PersonController.class b/target/classes/com/orozco/testfullstack/controller/PersonController.class
new file mode 100644
index 0000000..ad13bb0
Binary files /dev/null and b/target/classes/com/orozco/testfullstack/controller/PersonController.class differ
diff --git a/target/classes/com/orozco/testfullstack/model/ApiResponse.class b/target/classes/com/orozco/testfullstack/model/ApiResponse.class
new file mode 100644
index 0000000..64899bc
Binary files /dev/null and b/target/classes/com/orozco/testfullstack/model/ApiResponse.class differ
diff --git a/target/classes/com/orozco/testfullstack/model/Person.class b/target/classes/com/orozco/testfullstack/model/Person.class
new file mode 100644
index 0000000..5561030
Binary files /dev/null and b/target/classes/com/orozco/testfullstack/model/Person.class differ
diff --git a/target/classes/com/orozco/testfullstack/repository/PersonRepository.class b/target/classes/com/orozco/testfullstack/repository/PersonRepository.class
new file mode 100644
index 0000000..96a7f0a
Binary files /dev/null and b/target/classes/com/orozco/testfullstack/repository/PersonRepository.class differ
diff --git a/target/classes/com/orozco/testfullstack/service/PersonService.class b/target/classes/com/orozco/testfullstack/service/PersonService.class
new file mode 100644
index 0000000..3c0189e
Binary files /dev/null and b/target/classes/com/orozco/testfullstack/service/PersonService.class differ
diff --git a/target/classes/com/orozco/testfullstack/service/impl/PersonServiceImpl.class b/target/classes/com/orozco/testfullstack/service/impl/PersonServiceImpl.class
new file mode 100644
index 0000000..f183493
Binary files /dev/null and b/target/classes/com/orozco/testfullstack/service/impl/PersonServiceImpl.class differ
diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties
new file mode 100644
index 0000000..dfe3d35
--- /dev/null
+++ b/target/maven-archiver/pom.properties
@@ -0,0 +1,3 @@
+artifactId=test-full-stack
+groupId=com.orozco
+version=0.0.1-SNAPSHOT
diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
new file mode 100644
index 0000000..5d130b8
--- /dev/null
+++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
@@ -0,0 +1,7 @@
+com\orozco\testfullstack\service\impl\PersonServiceImpl.class
+com\orozco\testfullstack\TestFullStackApplication.class
+com\orozco\testfullstack\controller\PersonController.class
+com\orozco\testfullstack\repository\PersonRepository.class
+com\orozco\testfullstack\model\ApiResponse.class
+com\orozco\testfullstack\service\PersonService.class
+com\orozco\testfullstack\model\Person.class
diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
new file mode 100644
index 0000000..8d155f4
--- /dev/null
+++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
@@ -0,0 +1,7 @@
+C:\Users\aogonzalez1\OneDrive - Stefanini\Documentos\Prueba tecnica stefanini\tesffullstack\src\main\java\com\orozco\testfullstack\service\PersonService.java
+C:\Users\aogonzalez1\OneDrive - Stefanini\Documentos\Prueba tecnica stefanini\tesffullstack\src\main\java\com\orozco\testfullstack\model\ApiResponse.java
+C:\Users\aogonzalez1\OneDrive - Stefanini\Documentos\Prueba tecnica stefanini\tesffullstack\src\main\java\com\orozco\testfullstack\controller\PersonController.java
+C:\Users\aogonzalez1\OneDrive - Stefanini\Documentos\Prueba tecnica stefanini\tesffullstack\src\main\java\com\orozco\testfullstack\repository\PersonRepository.java
+C:\Users\aogonzalez1\OneDrive - Stefanini\Documentos\Prueba tecnica stefanini\tesffullstack\src\main\java\com\orozco\testfullstack\TestFullStackApplication.java
+C:\Users\aogonzalez1\OneDrive - Stefanini\Documentos\Prueba tecnica stefanini\tesffullstack\src\main\java\com\orozco\testfullstack\model\Person.java
+C:\Users\aogonzalez1\OneDrive - Stefanini\Documentos\Prueba tecnica stefanini\tesffullstack\src\main\java\com\orozco\testfullstack\service\impl\PersonServiceImpl.java
diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
new file mode 100644
index 0000000..07a56b2
--- /dev/null
+++ b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
@@ -0,0 +1,3 @@
+com\orozco\testfullstack\service\impl\PersonServiceImplTest.class
+com\orozco\testfullstack\controller\PersonControllerTest.class
+com\orozco\testfullstack\model\ApiResponseTest.class
diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst
new file mode 100644
index 0000000..86d8ffc
--- /dev/null
+++ b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst
@@ -0,0 +1,3 @@
+C:\Users\aogonzalez1\OneDrive - Stefanini\Documentos\Prueba tecnica stefanini\tesffullstack\src\test\java\com\orozco\testfullstack\service\impl\PersonServiceImplTest.java
+C:\Users\aogonzalez1\OneDrive - Stefanini\Documentos\Prueba tecnica stefanini\tesffullstack\src\test\java\com\orozco\testfullstack\controller\PersonControllerTest.java
+C:\Users\aogonzalez1\OneDrive - Stefanini\Documentos\Prueba tecnica stefanini\tesffullstack\src\test\java\com\orozco\testfullstack\model\ApiResponseTest.java
diff --git a/target/surefire-reports/TEST-com.orozco.testfullstack.controller.PersonControllerTest.xml b/target/surefire-reports/TEST-com.orozco.testfullstack.controller.PersonControllerTest.xml
new file mode 100644
index 0000000..eafe1b4
--- /dev/null
+++ b/target/surefire-reports/TEST-com.orozco.testfullstack.controller.PersonControllerTest.xml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/target/surefire-reports/TEST-com.orozco.testfullstack.model.ApiResponseTest.xml b/target/surefire-reports/TEST-com.orozco.testfullstack.model.ApiResponseTest.xml
new file mode 100644
index 0000000..05c1fdc
--- /dev/null
+++ b/target/surefire-reports/TEST-com.orozco.testfullstack.model.ApiResponseTest.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/target/surefire-reports/TEST-com.orozco.testfullstack.service.impl.PersonServiceImplTest.xml b/target/surefire-reports/TEST-com.orozco.testfullstack.service.impl.PersonServiceImplTest.xml
new file mode 100644
index 0000000..361081d
--- /dev/null
+++ b/target/surefire-reports/TEST-com.orozco.testfullstack.service.impl.PersonServiceImplTest.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/target/surefire-reports/com.orozco.testfullstack.controller.PersonControllerTest.txt b/target/surefire-reports/com.orozco.testfullstack.controller.PersonControllerTest.txt
new file mode 100644
index 0000000..a54cf9e
--- /dev/null
+++ b/target/surefire-reports/com.orozco.testfullstack.controller.PersonControllerTest.txt
@@ -0,0 +1,4 @@
+-------------------------------------------------------------------------------
+Test set: com.orozco.testfullstack.controller.PersonControllerTest
+-------------------------------------------------------------------------------
+Tests run: 8, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 5.185 s -- in com.orozco.testfullstack.controller.PersonControllerTest
diff --git a/target/surefire-reports/com.orozco.testfullstack.model.ApiResponseTest.txt b/target/surefire-reports/com.orozco.testfullstack.model.ApiResponseTest.txt
new file mode 100644
index 0000000..aa94339
--- /dev/null
+++ b/target/surefire-reports/com.orozco.testfullstack.model.ApiResponseTest.txt
@@ -0,0 +1,4 @@
+-------------------------------------------------------------------------------
+Test set: com.orozco.testfullstack.model.ApiResponseTest
+-------------------------------------------------------------------------------
+Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.033 s -- in com.orozco.testfullstack.model.ApiResponseTest
diff --git a/target/surefire-reports/com.orozco.testfullstack.service.impl.PersonServiceImplTest.txt b/target/surefire-reports/com.orozco.testfullstack.service.impl.PersonServiceImplTest.txt
new file mode 100644
index 0000000..60c4020
--- /dev/null
+++ b/target/surefire-reports/com.orozco.testfullstack.service.impl.PersonServiceImplTest.txt
@@ -0,0 +1,4 @@
+-------------------------------------------------------------------------------
+Test set: com.orozco.testfullstack.service.impl.PersonServiceImplTest
+-------------------------------------------------------------------------------
+Tests run: 8, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.314 s -- in com.orozco.testfullstack.service.impl.PersonServiceImplTest
diff --git a/target/test-classes/com/orozco/testfullstack/controller/PersonControllerTest.class b/target/test-classes/com/orozco/testfullstack/controller/PersonControllerTest.class
new file mode 100644
index 0000000..665a346
Binary files /dev/null and b/target/test-classes/com/orozco/testfullstack/controller/PersonControllerTest.class differ
diff --git a/target/test-classes/com/orozco/testfullstack/model/ApiResponseTest.class b/target/test-classes/com/orozco/testfullstack/model/ApiResponseTest.class
new file mode 100644
index 0000000..9eae376
Binary files /dev/null and b/target/test-classes/com/orozco/testfullstack/model/ApiResponseTest.class differ
diff --git a/target/test-classes/com/orozco/testfullstack/service/impl/PersonServiceImplTest.class b/target/test-classes/com/orozco/testfullstack/service/impl/PersonServiceImplTest.class
new file mode 100644
index 0000000..88c5935
Binary files /dev/null and b/target/test-classes/com/orozco/testfullstack/service/impl/PersonServiceImplTest.class differ
diff --git a/target/test-full-stack-0.0.1-SNAPSHOT.jar b/target/test-full-stack-0.0.1-SNAPSHOT.jar
new file mode 100644
index 0000000..f295690
Binary files /dev/null and b/target/test-full-stack-0.0.1-SNAPSHOT.jar differ
diff --git a/target/test-full-stack-0.0.1-SNAPSHOT.jar.original b/target/test-full-stack-0.0.1-SNAPSHOT.jar.original
new file mode 100644
index 0000000..a7efdd8
Binary files /dev/null and b/target/test-full-stack-0.0.1-SNAPSHOT.jar.original differ