diff --git a/README.md b/README.md
index 3e441c9..087c608 100644
--- a/README.md
+++ b/README.md
@@ -1,78 +1,129 @@
-
-
-# LAB | SpringBoot REST API
-
-### Instructions
-
-1. Fork this repo.
-2. Clone your fork to your local machine.
-3. Solve the challenges.
-
-
-## Deliverables
-
-- Upon completion, add your solution to git.
-- Then commit to git and push to your repo on GitHub.
-- Make a pull request and paste the pull request link in the submission field in the Student Portal.
-
-## Tasks
-
-1. Create a Spring Boot application using Spring Initializr with the following dependencies:
- - Spring Web
- - Spring Boot DevTools
- - Spring Boot Starter Validation
-
-2. Create a `Product` class with the following validated properties:
- - name (not blank, min length 3)
- - price (positive number)
- - category (not blank)
- - quantity (positive number)
-
-3. Create a `ProductService` class that manages a List of Products and has methods to:
- - Add a new product
- - Get all products
- - Get product by name
- - Update product
- - Delete product
- - Get products by category
- - Get products by price range
-
-4. Create a `ProductController` class that:
- - Uses constructor injection for the ProductService
- - Requires an "API-Key" header for all requests (value: "123456")
- - Has the following endpoints:
- * POST `/products` - Create new product
- * GET `/products` - Get all products
- * GET `/products/{name}` - Get product by name
- * PUT `/products/{name}` - Update product
- * DELETE `/products/{name}` - Delete product
- * GET `/products/category/{category}` - Get products by category
- * GET `/products/price?min={min}&max={max}` - Get products by price range
-
-5. Create a global exception handler that handles:
- - Validation errors (return proper error messages)
- - Missing API-Key header
- - Product not found
- - Invalid price range
-
-6. Create a `Customer` class with the following validated properties:
- - name (not blank)
- - email (valid email format)
- - age (minimum 18)
- - address (not blank)
-
-7. Create a `CustomerController` with endpoints to:
- - Create new customer (with validation)
- - Get all customers
- - Get customer by email
- - Update customer
- - Delete customer
-
-**Remember**:
-- Use proper package structure
-- Use constructor injection instead of @Autowired
-- Test all endpoints using Postman
-- Include appropriate error handling
-- Use meaningful variable and method names
-- Return appropriate HTTP status codes
-- Include validation messages in responses
+# Spring Boot REST API Lab 05 Final
+
+Aplicacion REST desarrollada con Spring Boot para gestionar productos y clientes en memoria.
+
+## Tecnologias
+
+- Java 17
+- Spring Boot 3.3.5
+- Spring Web
+- Spring Boot DevTools
+- Spring Boot Starter Validation
+- Maven
+
+## Requisitos
+
+- API-Key obligatoria en todas las peticiones: `123456`
+- Datos validados en productos y clientes
+- Manejo global de errores con respuestas JSON
+
+## Estructura
+
+- `model`: clases `Product` y `Customer`
+- `service`: logica de negocio en memoria
+- `controller`: endpoints REST
+- `config`: interceptor de API key
+- `exception`: excepciones personalizadas y handler global
+
+## Endpoints
+
+### Products
+
+- `POST /products`
+- `GET /products`
+- `GET /products/{name}`
+- `PUT /products/{name}`
+- `DELETE /products/{name}`
+- `GET /products/category/{category}`
+- `GET /products/price?min={min}&max={max}`
+
+### Customers
+
+- `POST /customers`
+- `GET /customers`
+- `GET /customers/{email}`
+- `PUT /customers/{email}`
+- `DELETE /customers/{email}`
+
+## Ejemplo de headers
+
+```http
+API-Key: 123456
+Content-Type: application/json
+```
+
+## Ejemplo de payloads
+
+### Product
+
+```json
+{
+ "name": "Laptop",
+ "price": 1200,
+ "category": "Tech",
+ "quantity": 5
+}
+```
+
+### Customer
+
+```json
+{
+ "name": "Ana",
+ "email": "ana@example.com",
+ "age": 30,
+ "address": "Madrid"
+}
+```
+
+## Ejecutar el proyecto
+
+```bash
+mvn spring-boot:run
+```
+
+La API queda disponible en:
+
+```text
+http://localhost:8080
+```
+
+## Ejecutar tests
+
+```bash
+mvn test
+```
+
+## Validaciones implementadas
+
+### Product
+
+- `name`: obligatorio, minimo 3 caracteres
+- `price`: numero positivo
+- `category`: obligatoria
+- `quantity`: numero positivo
+
+### Customer
+
+- `name`: obligatorio
+- `email`: formato valido
+- `age`: minimo 18
+- `address`: obligatoria
+
+## Manejo de errores
+
+La API devuelve respuestas con codigo HTTP adecuado para:
+
+- errores de validacion
+- API-Key ausente
+- API-Key invalida
+- producto no encontrado
+- cliente no encontrado
+- rango de precios invalido
+- parametros faltantes o con tipo invalido
+
+## Verificacion realizada
+
+- La aplicacion compila correctamente
+- Los tests pasan correctamente
+- Se verificaron endpoints clave en `localhost:8080`
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..16a3da6
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,54 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.3.5
+
+
+
+ org.example
+ springboot-rest-api-lab05final
+ 0.0.1-SNAPSHOT
+ springboot-rest-api-lab05final
+ Spring Boot REST API lab solution
+
+
+ 17
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/src/main/java/org/example/ProductApiApplication.java b/src/main/java/org/example/ProductApiApplication.java
new file mode 100644
index 0000000..394f553
--- /dev/null
+++ b/src/main/java/org/example/ProductApiApplication.java
@@ -0,0 +1,12 @@
+package org.example;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ProductApiApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ProductApiApplication.class, args);
+ }
+}
diff --git a/src/main/java/org/example/config/ApiKeyInterceptor.java b/src/main/java/org/example/config/ApiKeyInterceptor.java
new file mode 100644
index 0000000..ef05d71
--- /dev/null
+++ b/src/main/java/org/example/config/ApiKeyInterceptor.java
@@ -0,0 +1,28 @@
+package org.example.config;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+@Component
+public class ApiKeyInterceptor implements HandlerInterceptor {
+
+ private static final String API_KEY_HEADER = "API-Key";
+ private static final String EXPECTED_API_KEY = "123456";
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
+ String apiKey = request.getHeader(API_KEY_HEADER);
+
+ if (apiKey == null || apiKey.isBlank()) {
+ throw new MissingApiKeyException("Falta el header API-Key");
+ }
+
+ if (!EXPECTED_API_KEY.equals(apiKey)) {
+ throw new InvalidApiKeyException("API-Key invalida");
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/org/example/config/InvalidApiKeyException.java b/src/main/java/org/example/config/InvalidApiKeyException.java
new file mode 100644
index 0000000..a6885d0
--- /dev/null
+++ b/src/main/java/org/example/config/InvalidApiKeyException.java
@@ -0,0 +1,8 @@
+package org.example.config;
+
+public class InvalidApiKeyException extends RuntimeException {
+
+ public InvalidApiKeyException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/org/example/config/MissingApiKeyException.java b/src/main/java/org/example/config/MissingApiKeyException.java
new file mode 100644
index 0000000..2e92a17
--- /dev/null
+++ b/src/main/java/org/example/config/MissingApiKeyException.java
@@ -0,0 +1,8 @@
+package org.example.config;
+
+public class MissingApiKeyException extends RuntimeException {
+
+ public MissingApiKeyException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/org/example/config/WebConfig.java b/src/main/java/org/example/config/WebConfig.java
new file mode 100644
index 0000000..4897e6d
--- /dev/null
+++ b/src/main/java/org/example/config/WebConfig.java
@@ -0,0 +1,20 @@
+package org.example.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+ private final ApiKeyInterceptor apiKeyInterceptor;
+
+ public WebConfig(ApiKeyInterceptor apiKeyInterceptor) {
+ this.apiKeyInterceptor = apiKeyInterceptor;
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(apiKeyInterceptor);
+ }
+}
diff --git a/src/main/java/org/example/controller/CustomerController.java b/src/main/java/org/example/controller/CustomerController.java
new file mode 100644
index 0000000..0ede271
--- /dev/null
+++ b/src/main/java/org/example/controller/CustomerController.java
@@ -0,0 +1,55 @@
+package org.example.controller;
+
+import jakarta.validation.Valid;
+import org.example.model.Customer;
+import org.example.service.CustomerService;
+import org.springframework.http.HttpStatus;
+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;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/customers")
+public class CustomerController {
+
+ private final CustomerService customerService;
+
+ public CustomerController(CustomerService customerService) {
+ this.customerService = customerService;
+ }
+
+ @PostMapping
+ @ResponseStatus(HttpStatus.CREATED)
+ public Customer createCustomer(@Valid @RequestBody Customer customer) {
+ return customerService.createCustomer(customer);
+ }
+
+ @GetMapping
+ public List getAllCustomers() {
+ return customerService.getAllCustomers();
+ }
+
+ @GetMapping("/{email}")
+ public Customer getCustomerByEmail(@PathVariable String email) {
+ return customerService.getCustomerByEmail(email);
+ }
+
+ @PutMapping("/{email}")
+ public Customer updateCustomer(@PathVariable String email, @Valid @RequestBody Customer customer) {
+ return customerService.updateCustomer(email, customer);
+ }
+
+ @DeleteMapping("/{email}")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ public void deleteCustomer(@PathVariable String email) {
+ customerService.deleteCustomer(email);
+ }
+}
diff --git a/src/main/java/org/example/controller/ProductController.java b/src/main/java/org/example/controller/ProductController.java
new file mode 100644
index 0000000..15aad3a
--- /dev/null
+++ b/src/main/java/org/example/controller/ProductController.java
@@ -0,0 +1,66 @@
+package org.example.controller;
+
+import jakarta.validation.Valid;
+import org.example.model.Product;
+import org.example.service.ProductService;
+import org.springframework.http.HttpStatus;
+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.RequestParam;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/products")
+public class ProductController {
+
+ private final ProductService productService;
+
+ public ProductController(ProductService productService) {
+ this.productService = productService;
+ }
+
+ @PostMapping
+ @ResponseStatus(HttpStatus.CREATED)
+ public Product createProduct(@Valid @RequestBody Product product) {
+ return productService.addProduct(product);
+ }
+
+ @GetMapping
+ public List getAllProducts() {
+ return productService.getAllProducts();
+ }
+
+ @GetMapping("/{name}")
+ public Product getProductByName(@PathVariable String name) {
+ return productService.getProductByName(name);
+ }
+
+ @PutMapping("/{name}")
+ public Product updateProduct(@PathVariable String name, @Valid @RequestBody Product product) {
+ return productService.updateProduct(name, product);
+ }
+
+ @DeleteMapping("/{name}")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ public void deleteProduct(@PathVariable String name) {
+ productService.deleteProduct(name);
+ }
+
+ @GetMapping("/category/{category}")
+ public List getProductsByCategory(@PathVariable String category) {
+ return productService.getProductsByCategory(category);
+ }
+
+ @GetMapping("/price")
+ public List getProductsByPriceRange(@RequestParam double min, @RequestParam double max) {
+ return productService.getProductsByPriceRange(min, max);
+ }
+}
diff --git a/src/main/java/org/example/exception/CustomerNotFoundException.java b/src/main/java/org/example/exception/CustomerNotFoundException.java
new file mode 100644
index 0000000..c3eb0ab
--- /dev/null
+++ b/src/main/java/org/example/exception/CustomerNotFoundException.java
@@ -0,0 +1,8 @@
+package org.example.exception;
+
+public class CustomerNotFoundException extends RuntimeException {
+
+ public CustomerNotFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/org/example/exception/GlobalExceptionHandler.java b/src/main/java/org/example/exception/GlobalExceptionHandler.java
new file mode 100644
index 0000000..a2f695b
--- /dev/null
+++ b/src/main/java/org/example/exception/GlobalExceptionHandler.java
@@ -0,0 +1,85 @@
+package org.example.exception;
+
+import org.example.config.InvalidApiKeyException;
+import org.example.config.MissingApiKeyException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.FieldError;
+import org.springframework.web.bind.MissingRequestHeaderException;
+import org.springframework.web.bind.MissingServletRequestParameterException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
+
+import java.time.LocalDateTime;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public ResponseEntity