diff --git a/.env.sample b/.env.sample
new file mode 100644
index 0000000000000000000000000000000000000000..d774fd3d29b324b76ba5b57bc2cbca24fe266dcc
--- /dev/null
+++ b/.env.sample
@@ -0,0 +1,5 @@
+DATABASE_NAME=kata_db
+
+FLYWAY_URL=jdbc:postgresql://localhost:5432/kata_db
+FLYWAY_USER=admin
+FLYWAY_PASSWORD=admin
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..400ea5a4893ad001545b866599a317e28b86c41d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,36 @@
+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/
+
+.mvn
+.env
\ No newline at end of file
diff --git a/README.md b/README.md
index ef5293924f74641f6b5e6a7f530b6ea7b1081ec0..5967ba803f46c5764787eed12c9a1ed08704c246 100644
--- a/README.md
+++ b/README.md
@@ -1,93 +1,99 @@
-# kataagregio
+# kata Agregio
 
+Api for the management of energy park and the creation of offers in order to sell energy to a market.
 
+This api expose multiple endpoints to handle the CRUD operations on the parks and the offers.
+
+- Create a park
+- Get parks
+- Create an offer
+- Get offers
 
 ## Getting started
 
-To make it easy for you to get started with GitLab, here's a list of recommended next steps.
+This application need a database to Run . All the setup is already done in the docker-compose file.
+To start the database you can run the following command:
 
-Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
+```bash
+docker-compose up
+```
 
-## Add your files
+Don't forget to replace the .env.sample file with a .env file with the correct values.
+Here is an example of the .env file:
 
-- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
-- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
+```.dotenv
+DATABASE_NAME=kata_db
 
-```
-cd existing_repo
-git remote add origin https://gitlab.takima.io/rgalmier/kataagregio.git
-git branch -M main
-git push -uf origin main
-```
+FLYWAY_URL=jdbc:postgresql://localhost:5432/kata_db
+FLYWAY_USER=admin
+FLYWAY_PASSWORD=admin
+  ```
 
-## Integrate with your tools
+Database name is the name of the database that will be created in the postgres instance.
+
+Flyway url is the url of the database, the user and the password are the credentials to connect to the database.
+
+To run the application you can run it on an Ide or use the following command:
+
+```bash
+./mvnw spring-boot:run
+```
 
-- [ ] [Set up project integrations](https://gitlab.takima.io/rgalmier/kataagregio/-/settings/integrations)
+The application will be available on the following url: http://localhost:8081
 
-## Collaborate with your team
+### Stack
+- Java 21 last LTS
+- Spring Boot framework web 
+- Hibernate
+- Postgres
+- Docker
 
-- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
-- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
-- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
-- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
-- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
+## What is done
 
-## Test and Deploy
+#### Application
 
-Use the built-in continuous integration in GitLab.
+Controllers for the parks and the offers with the following endpoints:
 
-- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
-- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
-- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
-- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
-- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
+- POST /parks
+- GET /parks
+- POST /offers
+- GET /offers
 
-***
+Services and Repository for the parks offers and the timeBlocks
 
-# Editing this README
+Dto and Mapper for creation endpoints
 
-When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
+Use of Springboot validation for the creation of an offer
 
-## Suggestions for a good README
+#### Exceptions
 
-Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
+ControllerAdvice to handle the validation of the request
 
-## Name
-Choose a self-explaining name for your project.
+#### Tests
 
-## Description
-Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
+Unit tests for Validator
+Integration tests for the création of an offer
 
-## Badges
-On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
+## What is left to be done
 
-## Visuals
-Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
+Pagination for the get parks and get offers endpoints
 
-## Installation
-Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
+Add a new endpoint to get the origin of the energy park
 
-## Usage
-Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
+#### Dto
 
-## Support
-Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
+Use Dto for request and response of creation of parks
+Use Dto for the response of creation of offers
 
-## Roadmap
-If you have ideas for releases in the future, it is a good idea to list them in the README.
+#### Validation
 
-## Contributing
-State if you are open to contributions and what your requirements are for accepting them.
+Add validation for the creation of parks and offers with the creation of associated exceptions
 
-For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
 
-You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
+#### Database
 
-## Authors and acknowledgment
-Show your appreciation to those who have contributed to the project.
+Need to do indexes on the relevant columns in order to improve the performance of the application
 
-## License
-For open source projects, say how it is licensed.
+#### Tests
 
-## Project status
-If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
+Need to add more tests for the application to have an optimal coverage
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fb2ff0d35c6e8855591286121c548747e2a025bb
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,29 @@
+version: "3.9"
+services:
+  db:
+    image: postgres:14-alpine
+    container_name: ${DATABASE_NAME}
+    restart: unless-stopped
+    networks:
+      - db-net
+    environment:
+      - POSTGRES_PASSWORD=${FLYWAY_PASSWORD}
+      - POSTGRES_USER=${FLYWAY_USER}
+      - POSTGRES_DB=${DATABASE_NAME}
+    ports:
+      - "5432:5432"
+    volumes:
+      - db-kata-data:/var/lib/postgresql/data
+    healthcheck:
+      test:
+        [
+          "CMD-SHELL",
+          "sh -c 'pg_isready -U ${FLYWAY_USER} -d ${DATABASE_NAME}'",
+        ]
+      interval: 10s
+      timeout: 3s
+      retries: 3
+networks:
+  db-net:
+volumes:
+  db-kata-data:
\ No newline at end of file
diff --git a/mvnw b/mvnw
new file mode 100755
index 0000000000000000000000000000000000000000..19529ddf8c6eaa08c5c75ff80652d21ce4b72f8c
--- /dev/null
+++ b/mvnw
@@ -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 "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
new file mode 100644
index 0000000000000000000000000000000000000000..249bdf3822221aa612d1da2605316cabd7b07e50
--- /dev/null
+++ b/mvnw.cmd
@@ -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"
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6d462dc340a85928e924d557834cd3b54feaeea3
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         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.3.3</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>takima.test</groupId>
+    <artifactId>kataAgregio</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>kata Agregio</name>
+    <description>Api for the management of energy park and the creation of offers in order to sell energy</description>
+    <url/>
+    <properties>
+        <java.version>21</java.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.flywaydb</groupId>
+            <artifactId>flyway-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.flywaydb</groupId>
+            <artifactId>flyway-database-postgresql</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-testcontainers</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.testcontainers</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.testcontainers</groupId>
+            <artifactId>postgresql</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/src/main/java/takima/test/kataagregio/KataAgregioApplication.java b/src/main/java/takima/test/kataagregio/KataAgregioApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..58f1674589ac42ce844723fe9d60f04f2bbbddf7
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/KataAgregioApplication.java
@@ -0,0 +1,13 @@
+package takima.test.kataagregio;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class KataAgregioApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(KataAgregioApplication.class, args);
+    }
+
+}
diff --git a/src/main/java/takima/test/kataagregio/exeption/CommonExceptionHandler.java b/src/main/java/takima/test/kataagregio/exeption/CommonExceptionHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..f1180175f5fa6a276ed053bcb810778dfa6a0cd3
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/exeption/CommonExceptionHandler.java
@@ -0,0 +1,17 @@
+package takima.test.kataagregio.exeption;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+@ControllerAdvice
+public class CommonExceptionHandler {
+
+    @ExceptionHandler({InvalidTimeInterval.class})
+    public ResponseEntity<String> handleInvalidTimeInterval(InvalidTimeInterval e) {
+        return ResponseEntity
+                .status(HttpStatus.BAD_REQUEST)
+                .body(e.getMessage());
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/exeption/InvalidTimeInterval.java b/src/main/java/takima/test/kataagregio/exeption/InvalidTimeInterval.java
new file mode 100644
index 0000000000000000000000000000000000000000..6d44b8dafdeffa870b3a498184b055d3d44dc786
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/exeption/InvalidTimeInterval.java
@@ -0,0 +1,7 @@
+package takima.test.kataagregio.exeption;
+
+public class InvalidTimeInterval extends RuntimeException {
+    public InvalidTimeInterval(String message) {
+        super(message);
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/model/Market.java b/src/main/java/takima/test/kataagregio/model/Market.java
new file mode 100644
index 0000000000000000000000000000000000000000..208948b12e9c05fb3b97e63e7b78e1a5a59d8504
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/model/Market.java
@@ -0,0 +1,7 @@
+package takima.test.kataagregio.model;
+
+public enum Market {
+    PRIMARY,
+    SECONDARY,
+    FAST,
+}
diff --git a/src/main/java/takima/test/kataagregio/model/Offer.java b/src/main/java/takima/test/kataagregio/model/Offer.java
new file mode 100644
index 0000000000000000000000000000000000000000..f02c27f89573f11cd59fe1fa3a805b95c3576670
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/model/Offer.java
@@ -0,0 +1,64 @@
+package takima.test.kataagregio.model;
+
+import jakarta.persistence.*;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+
+@Entity
+public class Offer {
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    private UUID id;
+
+    @Enumerated(EnumType.STRING)
+    private Market market;
+
+    @OneToMany(mappedBy = "offer")
+    private List<TimeBlock> timeBlocks;
+
+    public UUID getId() {
+        return id;
+    }
+
+    public Market getMarket() {
+        return market;
+    }
+
+    public Offer setMarket(Market market) {
+        this.market = market;
+        return this;
+    }
+
+    public List<TimeBlock> getTimeBlocks() {
+        return timeBlocks;
+    }
+
+    public Offer setTimeBlocks(List<TimeBlock> timeBlocks) {
+        this.timeBlocks = timeBlocks;
+        return this;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Offer offer = (Offer) o;
+        return Objects.equals(id, offer.id) && market == offer.market;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, market);
+    }
+
+    @Override
+    public String toString() {
+        return "Offer{" +
+                "id=" + id +
+                ", market=" + market +
+                ", timeBlocks=" + timeBlocks +
+                '}';
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/model/Park.java b/src/main/java/takima/test/kataagregio/model/Park.java
new file mode 100644
index 0000000000000000000000000000000000000000..c537ab0988fc8eb8447f8ebc258b46629199fb15
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/model/Park.java
@@ -0,0 +1,81 @@
+package takima.test.kataagregio.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.*;
+
+import java.util.Objects;
+import java.util.UUID;
+
+@Entity
+public class Park {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    private UUID id;
+
+    @Enumerated(EnumType.STRING)
+    private ParkType type;
+    private double capacity; // MW for block of 3 Hours
+
+    @JsonIgnore
+    @ManyToOne
+    private TimeBlock timeBlock;
+
+    public UUID getId() {
+        return id;
+    }
+
+    public Park setId(UUID id) {
+        this.id = id;
+        return this;
+    }
+
+    public ParkType getType() {
+        return type;
+    }
+
+    public Park setType(ParkType type) {
+        this.type = type;
+        return this;
+    }
+
+    public double getCapacity() {
+        return capacity;
+    }
+
+    public Park setCapacity(double capacity) {
+        this.capacity = capacity;
+        return this;
+    }
+
+    public TimeBlock getTimeBlock() {
+        return timeBlock;
+    }
+
+    public Park setTimeBlock(TimeBlock timeBlock) {
+        this.timeBlock = timeBlock;
+        return this;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Park park = (Park) o;
+        return Double.compare(capacity, park.capacity) == 0 && Objects.equals(id, park.id) && type == park.type;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, type, capacity);
+    }
+
+    @Override
+    public String toString() {
+        return "Park{" +
+                "id=" + id +
+                ", type=" + type +
+                ", capacity=" + capacity +
+                '}';
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/model/ParkType.java b/src/main/java/takima/test/kataagregio/model/ParkType.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8e73ed669a5e1720bff98411fddacfef589f2c2
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/model/ParkType.java
@@ -0,0 +1,5 @@
+package takima.test.kataagregio.model;
+
+public enum ParkType {
+    SOLAR, WIND, HYDRO,
+}
diff --git a/src/main/java/takima/test/kataagregio/model/TimeBlock.java b/src/main/java/takima/test/kataagregio/model/TimeBlock.java
new file mode 100644
index 0000000000000000000000000000000000000000..d530e603573d28512af1d12de598eb22bec875b2
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/model/TimeBlock.java
@@ -0,0 +1,111 @@
+package takima.test.kataagregio.model;
+
+import jakarta.persistence.*;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+
+@Entity
+public class TimeBlock {
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    private UUID id;
+
+    private double amountMw;
+    private double minimumPrice;
+    private Instant startTime;
+    private Instant endTime;
+
+    @ManyToOne
+    private Offer offer;
+
+    @OneToMany(mappedBy = "timeBlock")
+    private List<Park> parks;
+
+    public UUID getId() {
+        return id;
+    }
+
+    public TimeBlock setId(UUID id) {
+        this.id = id;
+        return this;
+    }
+
+    public double getAmountMw() {
+        return amountMw;
+    }
+
+    public TimeBlock setAmountMw(double amoutMw) {
+        this.amountMw = amoutMw;
+        return this;
+    }
+
+    public double getMinimumPrice() {
+        return minimumPrice;
+    }
+
+    public TimeBlock setMinimumPrice(double minimumPrice) {
+        this.minimumPrice = minimumPrice;
+        return this;
+    }
+
+    public Offer getOffer() {
+        return offer;
+    }
+
+    public TimeBlock setOffer(Offer offer) {
+        this.offer = offer;
+        return this;
+    }
+
+    public List<Park> getParks() {
+        return parks;
+    }
+
+    public TimeBlock setParks(List<Park> parks) {
+        this.parks = parks;
+        return this;
+    }
+
+    public Instant getEndTime() {
+        return endTime;
+    }
+
+    public TimeBlock setEndTime(Instant endTime) {
+        this.endTime = endTime;
+        return this;
+    }
+
+    public Instant getStartTime() {
+        return startTime;
+    }
+
+    public TimeBlock setStartTime(Instant startTime) {
+        this.startTime = startTime;
+        return this;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        TimeBlock timeBlock = (TimeBlock) o;
+        return Double.compare(amountMw, timeBlock.amountMw) == 0 && Double.compare(minimumPrice, timeBlock.minimumPrice) == 0 && Objects.equals(id, timeBlock.id);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, amountMw, minimumPrice);
+    }
+
+    @Override
+    public String toString() {
+        return "TimeBlock{" +
+                "id=" + id +
+                ", amoutMw=" + amountMw +
+                ", minimumPrice=" + minimumPrice +
+                '}';
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/persistance/OfferDao.java b/src/main/java/takima/test/kataagregio/persistance/OfferDao.java
new file mode 100644
index 0000000000000000000000000000000000000000..beeed01e34c38ca16816b2f6b2fb518249b5dfe2
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/persistance/OfferDao.java
@@ -0,0 +1,13 @@
+package takima.test.kataagregio.persistance;
+
+import takima.test.kataagregio.model.Offer;
+
+import java.util.List;
+
+public interface OfferDao {
+
+    Offer save(Offer offer);
+
+    List<Offer> getAllOffers();
+
+}
diff --git a/src/main/java/takima/test/kataagregio/persistance/ParkDao.java b/src/main/java/takima/test/kataagregio/persistance/ParkDao.java
new file mode 100644
index 0000000000000000000000000000000000000000..9eddd8edb743280cc3659761abfc994ff46d5e0e
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/persistance/ParkDao.java
@@ -0,0 +1,14 @@
+package takima.test.kataagregio.persistance;
+
+import takima.test.kataagregio.model.Park;
+
+import java.util.List;
+import java.util.UUID;
+
+public interface ParkDao {
+    Park save(Park park);
+
+    List<Park> findAll();
+
+    List<Park> findAllById(Iterable<UUID> parkIds);
+}
diff --git a/src/main/java/takima/test/kataagregio/persistance/TimeBlockDao.java b/src/main/java/takima/test/kataagregio/persistance/TimeBlockDao.java
new file mode 100644
index 0000000000000000000000000000000000000000..d8dab0751d4b453be33ea4ba97bdbe2ac1bed78f
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/persistance/TimeBlockDao.java
@@ -0,0 +1,8 @@
+package takima.test.kataagregio.persistance;
+
+import takima.test.kataagregio.model.TimeBlock;
+
+public interface TimeBlockDao {
+
+    TimeBlock save(TimeBlock timeBlock);
+}
diff --git a/src/main/java/takima/test/kataagregio/persistance/impl/OfferDaoImpl.java b/src/main/java/takima/test/kataagregio/persistance/impl/OfferDaoImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..91ae171b28baa1f5cdce49f083793a0a394f175c
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/persistance/impl/OfferDaoImpl.java
@@ -0,0 +1,23 @@
+package takima.test.kataagregio.persistance.impl;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+import takima.test.kataagregio.model.Offer;
+import takima.test.kataagregio.persistance.OfferDao;
+
+import java.util.List;
+import java.util.UUID;
+
+@Repository
+public interface OfferDaoImpl extends JpaRepository<Offer, UUID>, JpaSpecificationExecutor<Offer>, OfferDao {
+
+    @Query(value = """
+            SELECT o
+            FROM Offer o
+            JOIN fetch o.timeBlocks tb
+            """)
+    List<Offer> getAllOffers();
+
+}
diff --git a/src/main/java/takima/test/kataagregio/persistance/impl/ParkDaoImpl.java b/src/main/java/takima/test/kataagregio/persistance/impl/ParkDaoImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..d741ab06f83422cafa75f0c5f493777b62bc1d61
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/persistance/impl/ParkDaoImpl.java
@@ -0,0 +1,14 @@
+package takima.test.kataagregio.persistance.impl;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.stereotype.Repository;
+import takima.test.kataagregio.model.Park;
+import takima.test.kataagregio.persistance.ParkDao;
+
+import java.util.UUID;
+
+@Repository
+public interface ParkDaoImpl extends JpaRepository<Park, UUID>, JpaSpecificationExecutor<Park>, ParkDao {
+
+}
diff --git a/src/main/java/takima/test/kataagregio/persistance/impl/TimeBlockDaoImpl.java b/src/main/java/takima/test/kataagregio/persistance/impl/TimeBlockDaoImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..44adee1866d0676d69fb1e10adb932911f159431
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/persistance/impl/TimeBlockDaoImpl.java
@@ -0,0 +1,13 @@
+package takima.test.kataagregio.persistance.impl;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.stereotype.Repository;
+import takima.test.kataagregio.model.TimeBlock;
+import takima.test.kataagregio.persistance.TimeBlockDao;
+
+import java.util.UUID;
+
+@Repository
+public interface TimeBlockDaoImpl extends JpaRepository<TimeBlock, UUID>, JpaSpecificationExecutor<TimeBlock>, TimeBlockDao {
+}
diff --git a/src/main/java/takima/test/kataagregio/presentation/OfferController.java b/src/main/java/takima/test/kataagregio/presentation/OfferController.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b37abff41d7e58a930fa8a777bf24b2f9832dce
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/presentation/OfferController.java
@@ -0,0 +1,39 @@
+package takima.test.kataagregio.presentation;
+
+import jakarta.validation.Valid;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import takima.test.kataagregio.model.Offer;
+import takima.test.kataagregio.presentation.dto.OfferDto;
+import takima.test.kataagregio.service.OfferService;
+import takima.test.kataagregio.utils.mapper.OfferDtoMapper;
+
+import java.util.List;
+
+import static org.springframework.http.HttpStatus.CREATED;
+
+@RestController
+@RequestMapping("api/offers")
+public class OfferController {
+
+    private final OfferService offerService;
+    private final OfferDtoMapper offerDtoMapper;
+
+    public OfferController(OfferService offerService, OfferDtoMapper offerRequestDto) {
+        this.offerService = offerService;
+        this.offerDtoMapper = offerRequestDto;
+    }
+
+    @PostMapping
+    @ResponseStatus(CREATED)
+    public Offer createOffer(@Valid @RequestBody OfferDto offerDto) {
+        Offer offer = offerDtoMapper.fromDto(offerDto);
+        return offerService.createOffer(offer);
+    }
+
+    @GetMapping
+    public List<OfferDto> getAllOffers() {
+        List<Offer> allOffers = offerService.getAllOffers();
+        return offerDtoMapper.toDtoList(allOffers);
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/presentation/ParkController.java b/src/main/java/takima/test/kataagregio/presentation/ParkController.java
new file mode 100644
index 0000000000000000000000000000000000000000..cfbaf40e6a290c1a6f8b837c512b65d3b6d07cf4
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/presentation/ParkController.java
@@ -0,0 +1,36 @@
+package takima.test.kataagregio.presentation;
+
+import org.springframework.web.bind.annotation.*;
+import takima.test.kataagregio.model.Park;
+import takima.test.kataagregio.presentation.dto.ParkDto;
+import takima.test.kataagregio.service.ParkService;
+import takima.test.kataagregio.utils.mapper.ParkDtoMapper;
+
+import java.util.List;
+
+import static org.springframework.http.HttpStatus.CREATED;
+
+@RestController
+@RequestMapping("api/parks")
+public class ParkController {
+
+    private final ParkService parkService;
+    private final ParkDtoMapper parkDtoMapper;
+
+    public ParkController(ParkService parkService, ParkDtoMapper parkDtoMapper) {
+        this.parkService = parkService;
+        this.parkDtoMapper = parkDtoMapper;
+    }
+
+    @PostMapping
+    @ResponseStatus(CREATED)
+    public Park createPark(@RequestBody Park park) {
+        return parkService.createPark(park);
+    }
+
+    @GetMapping
+    public List<ParkDto> getAllParks() {
+        List<Park> allParks = parkService.getAllParks();
+        return parkDtoMapper.toDtoList(allParks);
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/presentation/dto/OfferDto.java b/src/main/java/takima/test/kataagregio/presentation/dto/OfferDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..bad4b0f2d108b85b05dfe0f787c5fdbb7a457065
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/presentation/dto/OfferDto.java
@@ -0,0 +1,27 @@
+package takima.test.kataagregio.presentation.dto;
+
+
+import java.util.List;
+
+public class OfferDto {
+    private String market;
+    private List<TimeBlockDto> timeBlocksdto;
+
+    public List<TimeBlockDto> getTimeBlocksdto() {
+        return timeBlocksdto;
+    }
+
+    public OfferDto setTimeBlocksdto(List<TimeBlockDto> timeBlocksdto) {
+        this.timeBlocksdto = timeBlocksdto;
+        return this;
+    }
+
+    public String getMarket() {
+        return market;
+    }
+
+    public OfferDto setMarket(String market) {
+        this.market = market;
+        return this;
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/presentation/dto/ParkDto.java b/src/main/java/takima/test/kataagregio/presentation/dto/ParkDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..f88fb1106fbe70bdf9de8c3239c23b3551f7a848
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/presentation/dto/ParkDto.java
@@ -0,0 +1,38 @@
+package takima.test.kataagregio.presentation.dto;
+
+import takima.test.kataagregio.model.ParkType;
+
+import java.util.UUID;
+
+public class ParkDto {
+    private UUID id;
+    private ParkType type;
+    private double capacity;
+
+    public UUID getId() {
+        return id;
+    }
+
+    public ParkDto setId(UUID id) {
+        this.id = id;
+        return this;
+    }
+
+    public ParkType getType() {
+        return type;
+    }
+
+    public ParkDto setType(ParkType type) {
+        this.type = type;
+        return this;
+    }
+
+    public double getCapacity() {
+        return capacity;
+    }
+
+    public ParkDto setCapacity(double capacity) {
+        this.capacity = capacity;
+        return this;
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/presentation/dto/TimeBlockDto.java b/src/main/java/takima/test/kataagregio/presentation/dto/TimeBlockDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed67c663bc64690ec36122eb80c7accaab579cb3
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/presentation/dto/TimeBlockDto.java
@@ -0,0 +1,61 @@
+package takima.test.kataagregio.presentation.dto;
+
+import jakarta.validation.constraints.NotNull;
+
+import java.time.Instant;
+import java.util.List;
+
+public class TimeBlockDto {
+    private double amountMw;
+    private double minimumPrice;
+    @NotNull
+    private Instant startTime;
+    @NotNull
+    private Instant endTime;
+    private List<ParkDto> parks;
+
+    public double getAmountMw() {
+        return amountMw;
+    }
+
+    public TimeBlockDto setAmountMw(double amountMw) {
+        this.amountMw = amountMw;
+        return this;
+    }
+
+    public double getMinimumPrice() {
+        return minimumPrice;
+    }
+
+    public TimeBlockDto setMinimumPrice(double minimumPrice) {
+        this.minimumPrice = minimumPrice;
+        return this;
+    }
+
+    public Instant getStartTime() {
+        return startTime;
+    }
+
+    public TimeBlockDto setStartTime(Instant startTime) {
+        this.startTime = startTime;
+        return this;
+    }
+
+    public Instant getEndTime() {
+        return endTime;
+    }
+
+    public TimeBlockDto setEndTime(Instant endTime) {
+        this.endTime = endTime;
+        return this;
+    }
+
+    public List<ParkDto> getParks() {
+        return parks;
+    }
+
+    public TimeBlockDto setParks(List<ParkDto> parks) {
+        this.parks = parks;
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/takima/test/kataagregio/service/OfferService.java b/src/main/java/takima/test/kataagregio/service/OfferService.java
new file mode 100644
index 0000000000000000000000000000000000000000..49afcb2fb70f9a9461bb6e6272486a3e7e4bd269
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/service/OfferService.java
@@ -0,0 +1,11 @@
+package takima.test.kataagregio.service;
+
+import takima.test.kataagregio.model.Offer;
+
+import java.util.List;
+
+public interface OfferService {
+    Offer createOffer(Offer offer);
+
+    List<Offer> getAllOffers();
+}
diff --git a/src/main/java/takima/test/kataagregio/service/ParkService.java b/src/main/java/takima/test/kataagregio/service/ParkService.java
new file mode 100644
index 0000000000000000000000000000000000000000..a04b6363388240b5cb7404c24f8fb28a006f9156
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/service/ParkService.java
@@ -0,0 +1,15 @@
+package takima.test.kataagregio.service;
+
+import takima.test.kataagregio.model.Park;
+
+import java.util.List;
+import java.util.UUID;
+
+public interface ParkService {
+    Park createPark(Park park);
+
+    List<Park> getAllParks();
+
+    List<Park> getParks(List<UUID> parkIds);
+
+}
diff --git a/src/main/java/takima/test/kataagregio/service/TimeBlockService.java b/src/main/java/takima/test/kataagregio/service/TimeBlockService.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb816455783033aad60c20ffb3937b3fd4c42053
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/service/TimeBlockService.java
@@ -0,0 +1,11 @@
+package takima.test.kataagregio.service;
+
+import takima.test.kataagregio.model.TimeBlock;
+
+import java.util.List;
+
+public interface TimeBlockService {
+
+    List<TimeBlock> createTimeBlocks(List<TimeBlock> timeBlocks);
+
+}
diff --git a/src/main/java/takima/test/kataagregio/service/TimeBlockValidator.java b/src/main/java/takima/test/kataagregio/service/TimeBlockValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..a162f2c7963abfc9e872565a6620b9ecb0a32ecd
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/service/TimeBlockValidator.java
@@ -0,0 +1,9 @@
+package takima.test.kataagregio.service;
+
+import takima.test.kataagregio.model.TimeBlock;
+
+public interface TimeBlockValidator {
+
+    void assertTimePeriod(TimeBlock timeBlock);
+
+}
diff --git a/src/main/java/takima/test/kataagregio/service/impl/OfferServiceImpl.java b/src/main/java/takima/test/kataagregio/service/impl/OfferServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f0918635905a0b3979af02951450b11c305c0be
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/service/impl/OfferServiceImpl.java
@@ -0,0 +1,42 @@
+package takima.test.kataagregio.service.impl;
+
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import takima.test.kataagregio.model.Offer;
+import takima.test.kataagregio.model.TimeBlock;
+import takima.test.kataagregio.persistance.OfferDao;
+import takima.test.kataagregio.persistance.impl.OfferDaoImpl;
+import takima.test.kataagregio.service.OfferService;
+import takima.test.kataagregio.service.TimeBlockService;
+
+import java.util.List;
+
+
+@Service
+@Transactional(readOnly = true)
+public class OfferServiceImpl implements OfferService {
+
+    private final OfferDao offerDao;
+    private final TimeBlockService timeBlockService;
+
+    public OfferServiceImpl(OfferDaoImpl offerDao, TimeBlockService timeBlockService) {
+        this.offerDao = offerDao;
+        this.timeBlockService = timeBlockService;
+    }
+
+    @Override
+    @Transactional
+    public Offer createOffer(Offer offer) {
+        offerDao.save(offer);
+        offer.getTimeBlocks().forEach(timeBlock -> timeBlock.setOffer(offer));
+
+        List<TimeBlock> timeBlocks = timeBlockService.createTimeBlocks(offer.getTimeBlocks());
+        offer.setTimeBlocks(timeBlocks);
+        return offer;
+    }
+
+    @Override
+    public List<Offer> getAllOffers() {
+        return offerDao.getAllOffers();
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/service/impl/ParkServiceImpl.java b/src/main/java/takima/test/kataagregio/service/impl/ParkServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..5ef6442cde2445a0665654cc5fc72b1f202afaa0
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/service/impl/ParkServiceImpl.java
@@ -0,0 +1,37 @@
+package takima.test.kataagregio.service.impl;
+
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import takima.test.kataagregio.model.Park;
+import takima.test.kataagregio.persistance.ParkDao;
+import takima.test.kataagregio.persistance.impl.ParkDaoImpl;
+import takima.test.kataagregio.service.ParkService;
+
+import java.util.List;
+import java.util.UUID;
+
+@Service
+@Transactional(readOnly = true)
+public class ParkServiceImpl implements ParkService {
+    private final ParkDao parkDao;
+
+    public ParkServiceImpl(ParkDaoImpl parkDao) {
+        this.parkDao = parkDao;
+    }
+
+    @Override
+    @Transactional
+    public Park createPark(Park park) {
+        return parkDao.save(park);
+    }
+
+    @Override
+    public List<Park> getAllParks() {
+        return parkDao.findAll();
+    }
+
+
+    public List<Park> getParks(List<UUID> parkIds) {
+        return parkDao.findAllById(parkIds);
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/service/impl/TimeBlockServiceImpl.java b/src/main/java/takima/test/kataagregio/service/impl/TimeBlockServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7fbc8e9342604fc134e8f1d0fafb17786cda58b
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/service/impl/TimeBlockServiceImpl.java
@@ -0,0 +1,51 @@
+package takima.test.kataagregio.service.impl;
+
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import takima.test.kataagregio.model.Park;
+import takima.test.kataagregio.model.TimeBlock;
+import takima.test.kataagregio.persistance.TimeBlockDao;
+import takima.test.kataagregio.persistance.impl.TimeBlockDaoImpl;
+import takima.test.kataagregio.service.ParkService;
+import takima.test.kataagregio.service.TimeBlockService;
+import takima.test.kataagregio.service.TimeBlockValidator;
+
+import java.util.List;
+import java.util.UUID;
+
+@Service
+@Transactional(readOnly = true)
+public class TimeBlockServiceImpl implements TimeBlockService {
+
+    private final TimeBlockDao timeBlockDao;
+    private final TimeBlockValidator timeBlockValidator;
+    private final ParkService parkService;
+
+    public TimeBlockServiceImpl(TimeBlockDaoImpl timeBlockDao, TimeBlockValidator timeBlockValidator, ParkService parkService) {
+        this.timeBlockDao = timeBlockDao;
+        this.timeBlockValidator = timeBlockValidator;
+        this.parkService = parkService;
+    }
+
+    @Override
+    @Transactional
+    public List<TimeBlock> createTimeBlocks(List<TimeBlock> timeBlocks) {
+
+        assertTimePeriodValid(timeBlocks);
+        timeBlocks.forEach(timeBlock -> {
+            timeBlockDao.save(timeBlock);
+            updateParks(timeBlock);
+        });
+        return timeBlocks;
+    }
+
+    private void updateParks(TimeBlock timeBlock) {
+        List<UUID> parkIds = timeBlock.getParks().stream().map(Park::getId).toList();
+        List<Park> parks = parkService.getParks(parkIds);
+        parks.forEach(park -> park.setTimeBlock(timeBlock));
+    }
+
+    private void assertTimePeriodValid(List<TimeBlock> timeBlocks) {
+        timeBlocks.forEach(timeBlockValidator::assertTimePeriod);
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/service/impl/TimeBlockValidatorImpl.java b/src/main/java/takima/test/kataagregio/service/impl/TimeBlockValidatorImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..d2a854a3adc4a399b3b1c37905a993f9332dd453
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/service/impl/TimeBlockValidatorImpl.java
@@ -0,0 +1,18 @@
+package takima.test.kataagregio.service.impl;
+
+import org.springframework.stereotype.Service;
+import takima.test.kataagregio.exeption.InvalidTimeInterval;
+import takima.test.kataagregio.model.TimeBlock;
+import takima.test.kataagregio.service.TimeBlockValidator;
+
+@Service
+public class TimeBlockValidatorImpl implements TimeBlockValidator {
+
+    public static final String START_TIME_MUST_BE_BEFORE_END_TIME = "Start time must be before end time";
+
+    public void assertTimePeriod(TimeBlock timeBlock) {
+        if (timeBlock.getStartTime().isAfter(timeBlock.getEndTime())) {
+            throw new InvalidTimeInterval(START_TIME_MUST_BE_BEFORE_END_TIME);
+        }
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/utils/mapper/OfferDtoMapper.java b/src/main/java/takima/test/kataagregio/utils/mapper/OfferDtoMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..a66b1ff49fc24616a2e3c9725ecf0ffe6a12cdc0
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/utils/mapper/OfferDtoMapper.java
@@ -0,0 +1,49 @@
+package takima.test.kataagregio.utils.mapper;
+
+import org.springframework.stereotype.Component;
+import takima.test.kataagregio.model.Market;
+import takima.test.kataagregio.model.Offer;
+import takima.test.kataagregio.model.TimeBlock;
+import takima.test.kataagregio.presentation.dto.OfferDto;
+import takima.test.kataagregio.presentation.dto.TimeBlockDto;
+
+import java.util.List;
+
+@Component
+public class OfferDtoMapper {
+    private final TimeBlockDtoMapper timeBlockDtoMapper;
+
+    public OfferDtoMapper(takima.test.kataagregio.utils.mapper.TimeBlockDtoMapper timeBlockDtoMapper) {
+        this.timeBlockDtoMapper = timeBlockDtoMapper;
+    }
+
+    public Offer fromDto(OfferDto dto) {
+        takima.test.kataagregio.model.Offer offer = new takima.test.kataagregio.model.Offer();
+        offer.setMarket(Market.valueOf(dto.getMarket()));
+
+        List<TimeBlock> timeBlocks = dto.getTimeBlocksdto().stream()
+                .map(timeBlockDtoMapper::fromDto)
+                .toList();
+        offer.setTimeBlocks(timeBlocks);
+
+        return offer;
+    }
+
+    public OfferDto toDto(Offer offer) {
+        OfferDto dto = new OfferDto();
+        dto.setMarket(offer.getMarket().name());
+
+        List<TimeBlockDto> timeBlockDtos = offer.getTimeBlocks().stream()
+                .map(timeBlockDtoMapper::toDto)
+                .toList();
+        dto.setTimeBlocksdto(timeBlockDtos);
+
+        return dto;
+    }
+
+    public List<OfferDto> toDtoList(List<Offer> offers) {
+        return offers.stream()
+                .map(this::toDto)
+                .toList();
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/takima/test/kataagregio/utils/mapper/ParkDtoMapper.java b/src/main/java/takima/test/kataagregio/utils/mapper/ParkDtoMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..832f7d9e02ca5c2dc4a491ddb16cc93dfca4fac8
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/utils/mapper/ParkDtoMapper.java
@@ -0,0 +1,35 @@
+package takima.test.kataagregio.utils.mapper;
+
+import org.springframework.stereotype.Component;
+import takima.test.kataagregio.model.Park;
+import takima.test.kataagregio.presentation.dto.ParkDto;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+public class ParkDtoMapper {
+
+    public Park fromDto(ParkDto dto) {
+        Park park = new Park();
+        park.setId(dto.getId());
+        park.setType(dto.getType());
+        park.setCapacity(dto.getCapacity());
+        return park;
+    }
+
+    public ParkDto toDto(Park park) {
+        ParkDto dto = new ParkDto();
+        dto.setId(park.getId());
+        dto.setType(park.getType());
+        dto.setCapacity(park.getCapacity());
+        return dto;
+    }
+
+    public List<ParkDto> toDtoList(List<Park> parks) {
+        return parks.stream()
+                .map(this::toDto)
+                .collect(Collectors.toList());
+
+    }
+}
diff --git a/src/main/java/takima/test/kataagregio/utils/mapper/TimeBlockDtoMapper.java b/src/main/java/takima/test/kataagregio/utils/mapper/TimeBlockDtoMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8511c14d565206e6b5d37caf6d75a30f5ccfbfc
--- /dev/null
+++ b/src/main/java/takima/test/kataagregio/utils/mapper/TimeBlockDtoMapper.java
@@ -0,0 +1,38 @@
+package takima.test.kataagregio.utils.mapper;
+
+import org.springframework.stereotype.Component;
+import takima.test.kataagregio.model.TimeBlock;
+import takima.test.kataagregio.presentation.dto.TimeBlockDto;
+
+import java.util.stream.Collectors;
+
+@Component
+public class TimeBlockDtoMapper {
+    private final ParkDtoMapper parkDtoMapper;
+
+    public TimeBlockDtoMapper(ParkDtoMapper parkDtoMapper) {
+        this.parkDtoMapper = parkDtoMapper;
+    }
+
+    public TimeBlock fromDto(TimeBlockDto dto) {
+        TimeBlock timeBlock = new TimeBlock();
+        timeBlock.setAmountMw(dto.getAmountMw());
+        timeBlock.setMinimumPrice(dto.getMinimumPrice());
+        timeBlock.setStartTime(dto.getStartTime());
+        timeBlock.setEndTime(dto.getEndTime());
+        timeBlock.setEndTime(dto.getEndTime());
+        timeBlock.setParks(dto.getParks().stream()
+                .map(parkDtoMapper::fromDto)
+                .collect(Collectors.toList()));
+        return timeBlock;
+    }
+
+    public TimeBlockDto toDto(TimeBlock timeBlock) {
+        TimeBlockDto dto = new TimeBlockDto();
+        dto.setAmountMw(timeBlock.getAmountMw());
+        dto.setMinimumPrice(timeBlock.getMinimumPrice());
+        dto.setStartTime(timeBlock.getStartTime());
+        dto.setEndTime(timeBlock.getEndTime());
+        return dto;
+    }
+}
\ No newline at end of file
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e47b2fee6b5bf0f8be01363b9c45abb9e03405bf
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,23 @@
+spring:
+  flyway:
+    enabled: true
+    baseline-on-migrate: true
+  datasource:
+    url: jdbc:postgresql://localhost:5432/kata_db
+    username: admin
+    password: admin
+  config:
+    import: optional:file:../.env[.properties]
+  jpa:
+    open-in-view: false
+    hibernate:
+      ddl-auto: validate
+    database-platform: org.hibernate.dialect.PostgreSQLDialect
+  application:
+    name: kataAgregio
+
+server:
+  port: 8081
+logging:
+  level:
+    root: info
\ No newline at end of file
diff --git a/src/main/resources/db/migration/V1__Create_Offer_Plant_TimeBlock_Tables_With_Relationships.sql b/src/main/resources/db/migration/V1__Create_Offer_Plant_TimeBlock_Tables_With_Relationships.sql
new file mode 100644
index 0000000000000000000000000000000000000000..f9e3eaaecb9c9697e79d5fb9dff201016b047150
--- /dev/null
+++ b/src/main/resources/db/migration/V1__Create_Offer_Plant_TimeBlock_Tables_With_Relationships.sql
@@ -0,0 +1,32 @@
+CREATE TABLE offer
+(
+    id     UUID NOT NULL,
+    market VARCHAR(255),
+    CONSTRAINT pk_offer PRIMARY KEY (id)
+);
+
+CREATE TABLE park
+(
+    id            UUID             NOT NULL,
+    type          VARCHAR(255),
+    capacity      DOUBLE PRECISION NOT NULL,
+    time_block_id UUID,
+    CONSTRAINT pk_park PRIMARY KEY (id)
+);
+
+CREATE TABLE time_block
+(
+    id            UUID             NOT NULL,
+    amount_mw     DOUBLE PRECISION NOT NULL,
+    minimum_price DOUBLE PRECISION NOT NULL,
+    start_time    TIMESTAMP WITHOUT TIME ZONE,
+    end_time      TIMESTAMP WITHOUT TIME ZONE,
+    offer_id      UUID,
+    CONSTRAINT pk_timeblock PRIMARY KEY (id)
+);
+
+ALTER TABLE park
+    ADD CONSTRAINT FK_PARK_ON_TIMEBLOCK FOREIGN KEY (time_block_id) REFERENCES time_block (id);
+
+ALTER TABLE time_block
+    ADD CONSTRAINT FK_TIMEBLOCK_ON_OFFER FOREIGN KEY (offer_id) REFERENCES offer (id);
\ No newline at end of file
diff --git a/src/main/resources/db/migration/V2__Fill_Tables.sql b/src/main/resources/db/migration/V2__Fill_Tables.sql
new file mode 100644
index 0000000000000000000000000000000000000000..6aedc42696d58973e97798141577b9d94cb1fe2e
--- /dev/null
+++ b/src/main/resources/db/migration/V2__Fill_Tables.sql
@@ -0,0 +1,7 @@
+INSERT INTO park (id, type, capacity, time_block_id)
+VALUES ('4f7b6d1d-268a-4d8b-b447-cfc0db7a15e7', 'SOLAR', 100.5, null),
+       ('8c3fa2fc-5d60-43e1-ba40-14ec42047d2e', 'WIND', 200.0, null)
+-- INSERT INTO timeblock (id, amout_mw, minimum_price, offer_id)
+-- VALUES (7cc8eede-ec79-415a-bed9-a00923210f90, 150.0, 45.5, (SELECT id FROM offer WHERE market = 'Solar Market')),
+--        (357411d2-38a3-44f2-8b50-6c7ebc58d210, 250.0, 50.0, (SELECT id FROM offer WHERE market = 'Wind Market'));
+
diff --git a/src/test/java/takima/test/kataagregio/service/impl/OfferServiceITest.java b/src/test/java/takima/test/kataagregio/service/impl/OfferServiceITest.java
new file mode 100644
index 0000000000000000000000000000000000000000..fdec62d8f1efb104ceea184d85a0ffd9791804ae
--- /dev/null
+++ b/src/test/java/takima/test/kataagregio/service/impl/OfferServiceITest.java
@@ -0,0 +1,59 @@
+package takima.test.kataagregio.service.impl;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.jdbc.Sql;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import takima.test.kataagregio.model.Market;
+import takima.test.kataagregio.model.Offer;
+import takima.test.kataagregio.model.Park;
+import takima.test.kataagregio.model.TimeBlock;
+import takima.test.kataagregio.persistance.OfferDao;
+import takima.test.kataagregio.service.OfferService;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.UUID;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@SpringBootTest
+@Testcontainers
+@Sql(scripts = {"/db/migration/clean_data.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
+class OfferServiceITest {
+
+    @Autowired
+    private OfferService offerService;
+
+    @Autowired
+    private OfferDao offerDao;
+
+    @Test
+    void createOffer() {
+        UUID uuid = UUID.randomUUID();
+        Park park = new Park();
+        park.setId(uuid);
+
+        TimeBlock timeBlock = new TimeBlock();
+        timeBlock.setAmountMw(100);
+        timeBlock.setMinimumPrice(10);
+        timeBlock.setStartTime(Instant.parse("2023-09-23T10:00:00Z"));
+        timeBlock.setEndTime(Instant.parse("2023-09-23T12:00:00Z"));
+        timeBlock.setParks(List.of(park));
+
+        Offer offer = new Offer();
+        offer.setMarket(Market.PRIMARY);
+        offer.setTimeBlocks(List.of(timeBlock));
+
+        Offer createdOffer = offerService.createOffer(offer);
+
+        List<Offer> allOffers = offerDao.getAllOffers();
+        assertThat(createdOffer).isNotNull();
+        assertThat(allOffers).hasSize(1);
+        assertThat(allOffers.getFirst().getMarket()).isEqualTo(Market.PRIMARY);
+        assertThat(allOffers.getFirst().getTimeBlocks()).hasSize(1);
+        assertThat(allOffers.getFirst().getTimeBlocks().getFirst().getAmountMw()).isEqualTo(100);
+
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/takima/test/kataagregio/service/impl/TimeBlockValidatorImplTest.java b/src/test/java/takima/test/kataagregio/service/impl/TimeBlockValidatorImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc429bef41240fad41e1ef7b3370e2ad7b951133
--- /dev/null
+++ b/src/test/java/takima/test/kataagregio/service/impl/TimeBlockValidatorImplTest.java
@@ -0,0 +1,41 @@
+package takima.test.kataagregio.service.impl;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.junit.jupiter.MockitoExtension;
+import takima.test.kataagregio.exeption.InvalidTimeInterval;
+import takima.test.kataagregio.model.TimeBlock;
+
+import java.time.Instant;
+
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+@ExtendWith(MockitoExtension.class)
+class TimeBlockValidatorImplTest {
+
+    @InjectMocks
+    private TimeBlockValidatorImpl timeBlockValidator;
+
+    @Test
+    void testAssertTimePeriod_happy_case() {
+        TimeBlock timeBlock = new TimeBlock();
+        timeBlock.setStartTime(Instant.parse("2023-09-23T10:00:00Z"));
+        timeBlock.setEndTime(Instant.parse("2023-09-23T12:00:00Z"));
+
+        assertThatCode(() -> timeBlockValidator.assertTimePeriod(timeBlock))
+                .doesNotThrowAnyException();
+    }
+
+    @Test
+    void testAssertTimePeriod_invalid_if_end_date_before_start_date() {
+        TimeBlock timeBlock = new TimeBlock();
+        timeBlock.setStartTime(Instant.parse("2023-09-23T12:00:00Z"));
+        timeBlock.setEndTime(Instant.parse("2023-09-23T10:00:00Z"));
+
+        assertThatThrownBy(() -> timeBlockValidator.assertTimePeriod(timeBlock))
+                .isInstanceOf(InvalidTimeInterval.class)
+                .hasMessage("Start time must be before end time");
+    }
+}
diff --git a/src/test/resources/db/migration/clean_data.sql b/src/test/resources/db/migration/clean_data.sql
new file mode 100644
index 0000000000000000000000000000000000000000..ecfa2d62bebc4f7a63f0ee36921cb5594a7b4915
--- /dev/null
+++ b/src/test/resources/db/migration/clean_data.sql
@@ -0,0 +1,3 @@
+TRUNCATE TABLE offer CASCADE;
+TRUNCATE TABLE park CASCADE;
+TRUNCATE TABLE time_block CASCADE;
\ No newline at end of file