Productos - bootcamp-uchile-2026/grupo-4-backend GitHub Wiki
Productos
Servicio encargado de gestionar los productos disponibles en el ecommerce.
El servicio permite consultar, crear, actualizar y eliminar productos, además de realizar búsquedas mediante filtros y consultar los productos más vendidos.
Endpoints
- GET /productos - Obtener lista de productos con filtros opcionales
- GET /productos/top-ventas - Obtener productos más vendidos
- GET /productos/{id} - Obtener producto por ID
- POST /productos - Crear producto
- PATCH /productos/{id} - Actualizar producto
- DELETE /productos/{id} - Eliminar producto
Modelo
Producto
Representa un producto disponible en el catálogo del ecommerce.
| Campo | Tipo | Descripción |
|---|---|---|
| id | number | Identificador único del producto |
| nombre | string | Nombre del producto |
| descripcion | string | Descripción del producto |
| ingredientes | string | Ingredientes del producto |
| valorNutricional | string | Información nutricional |
| categoriaId | number | Identificador de la categoría |
| proveedorId | number | Identificador del proveedor |
| precio | number | Precio del producto |
| fechaVencimiento | Date | Fecha de vencimiento |
| descuento | number | Porcentaje de descuento |
| precioDescuento | number | Precio final con descuento |
| imagen | string | URL de la imagen |
| tipoConservacion | TipoConservacion | Tipo de conservación requerido |
| valoracion | number | Valoración promedio del producto |
| favorito | boolean | Indica si el producto está marcado como favorito |
Enumeraciones
TipoConservacion
Define las condiciones de conservación requeridas por el producto.
Valores disponibles:
- Ambiente
- Refrigerado
- Congelado
enum TipoConservacion {
AMBIENTE = 'Ambiente',
REFRIGERADO = 'Refrigerado',
CONGELADO = 'Congelado',
}
DTOs
CreateProductoDto
DTO utilizado para crear un nuevo producto. Los campos opcionales pueden omitirse en la solicitud.
Validaciones definidas: nombre, descripción e ingredientes deben ser textos no vacíos ni compuestos solo por espacios; categoriaId y proveedorId deben ser enteros mayores o iguales a 1; precio debe ser un entero mayor o igual a 0; descuento, si se proporciona, debe ser un entero entre 0 y 100; fechaVencimiento, si se proporciona, debe ser una fecha válida; imagen, si se proporciona, debe ser una URL válida; tipoConservacion debe pertenecer a la enumeración correspondiente.
Campos
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
| nombre | string | Sí | Nombre del producto |
| descripcion | string | Sí | Descripción del producto |
| ingredientes | string | Sí | Ingredientes del producto |
| valorNutricional | string | No | Información nutricional |
| categoriaId | number | Sí | ID de la categoría |
| proveedorId | number | Sí | ID del proveedor |
| precio | number | Sí | Precio del producto |
| fechaVencimiento | Date | No | Fecha de vencimiento |
| descuento | number | No | Porcentaje de descuento |
| imagen | string | No | URL de la imagen |
| tipoConservacion | TipoConservacion | Sí | Tipo de conservación |
Ejemplo de Request Body
{
"nombre": "Mermelada de frutilla",
"descripcion": "Mermelada artesanal elaborada con frutillas.",
"ingredientes": "Frutillas, azúcar, jugo de limón",
"valorNutricional": "250 kcal por 100g",
"categoriaId": 1,
"proveedorId": 1,
"precio": 5990,
"fechaVencimiento": "2026-12-31",
"descuento": 10,
"imagen": "https://ejemplo.com/mermelada.jpg",
"tipoConservacion": "Refrigerado"
}
UpdateProductoDto
DTO utilizado para actualizar parcialmente un producto existente.
Hereda todos los campos de CreateProductoDto, pero todos son opcionales.
Esto permite modificar solamente los campos necesarios.
Ejemplo de Request Body
{
"precio": 6490,
"descuento": 15
}
ProductoQueryDto
DTO utilizado para definir los parámetros opcionales de búsqueda de productos. categoriaId y proveedorId deben ser enteros mayores o iguales a 1; precioMin y precioMax deben ser enteros mayores o iguales a 0; tipoConservacion debe corresponder a un valor del enum; tieneDescuento acepta true o false; nombre debe ser texto y no contener exclusivamente espacios.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
| nombre | string | No | Busca productos cuyo nombre contenga el texto indicado |
| categoriaId | number | No | Filtra por categoría |
| proveedorId | number | No | Filtra por proveedor |
| precioMin | number | No | Precio mínimo |
| precioMax | number | No | Precio máximo |
| tipoConservacion | TipoConservacion | No | Filtra por tipo de conservación |
| tieneDescuento | boolean | No | Filtra productos que tienen descuento |
ProductoResponseDto
DTO utilizado para representar la respuesta de los endpoints de Productos.
{
"id": 1,
"nombre": "Mermelada de frutilla",
"descripcion": "Mermelada artesanal elaborada con frutillas de la zona central.",
"ingredientes": "Frutillas, azúcar, jugo de limón",
"valorNutricional": "Energía: 250 kcal por 100g",
"categoriaId": 1,
"proveedorId": 1,
"precio": 5990,
"fechaVencimiento": "2026-12-31",
"descuento": 10,
"precioDescuento": 5391,
"imagen": "https://ejemplo.com/mermelada-frutilla.jpg",
"tipoConservacion": "Ambiente",
"valoracion": 4.8,
"favorito": false
}
Endpoints detallados
GET /productos
Obtiene una lista de productos aplicando filtros opcionales.
Query Parameters
Todos los parámetros son opcionales.
- ?nombre=Mermelada
- &categoriaId=1
- &proveedorId=1
- &precioMin=3000
- &precioMax=10000
- &tipoConservacion=Refrigerado
- &tieneDescuento=true
Ejemplo de solicitud
GET /productos?nombre=Mermelada&categoriaId=1&precioMax=10000
Response — 200 OK
[
{
"id": 1,
"nombre": "Mermelada de frutilla",
"descripcion": "Mermelada artesanal elaborada con frutillas de la zona central.",
"ingredientes": "Frutillas, azúcar, jugo de limón",
"valorNutricional": "Energía: 250 kcal por 100g",
"categoriaId": 1,
"proveedorId": 1,
"precio": 5990,
"fechaVencimiento": "2026-12-31",
"descuento": 10,
"precioDescuento": 5391,
"imagen": "https://ejemplo.com/mermelada-frutilla.jpg",
"tipoConservacion": "Ambiente",
"valoracion": 4.8,
"favorito": false
}
]
Response — 400 Bad Request
Se produce cuando los parámetros de búsqueda no son válidos.
{
"statusCode": 400,
"message": "Los parámetros de búsqueda no son válidos."
}
GET /productos/top-ventas
Obtiene los productos con mayor cantidad de ventas.
Query Parameters
| Parámetro | Tipo | Requerido | Valor por defecto | Descripción |
|---|---|---|---|---|
| limite | number | No | 5 | Cantidad máxima de productos a retornar (valor previsto mayor a 0) |
Ejemplo de solicitud
GET /productos/top-ventas?limite=10
Si no se especifica limite, se utiliza el valor 5. El parámetro se convierte a entero; los valores no enteros producen un error de validación.
Response — 200 OK
[
{
"id": 1,
"nombre": "Mermelada de frutilla",
"descripcion": "Mermelada artesanal elaborada con frutillas de la zona central.",
"ingredientes": "Frutillas, azúcar, jugo de limón",
"valorNutricional": "Energía: 250 kcal por 100g",
"categoriaId": 1,
"proveedorId": 1,
"precio": 5990,
"fechaVencimiento": "2026-12-31",
"descuento": 10,
"precioDescuento": 5391,
"imagen": "https://ejemplo.com/mermelada-frutilla.jpg",
"tipoConservacion": "Ambiente",
"valoracion": 4.8,
"favorito": false
}
]
Response — 400 Bad Request
El límite indicado no es válido.
{
"statusCode": 400,
"message": "El límite indicado no es válido."
}
GET /productos/{id}
Obtiene un producto específico mediante su identificador.
Path Parameters
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
| id | number | Sí | Identificador único del producto |
Ejemplo de solicitud
GET /productos/1
Response — 200 OK
{
"id": 1,
"nombre": "Mermelada de frutilla",
"descripcion": "Mermelada artesanal elaborada con frutillas de la zona central.",
"ingredientes": "Frutillas, azúcar, jugo de limón",
"valorNutricional": "Energía: 250 kcal por 100g",
"categoriaId": 1,
"proveedorId": 1,
"precio": 5990,
"fechaVencimiento": "2026-12-31",
"descuento": 10,
"precioDescuento": 5391,
"imagen": "https://ejemplo.com/mermelada-frutilla.jpg",
"tipoConservacion": "Ambiente",
"valoracion": 4.8,
"favorito": false
}
Response — 400 Bad Request
El ID proporcionado no es válido.
{
"statusCode": 400,
"message": "El ID del producto no es válido."
}
Response — 404 Not Found
El producto no existe.
{
"statusCode": 404,
"message": "Producto no encontrado."
}
POST /productos
Crea un nuevo producto.
Request Body
Utiliza CreateProductoDto.
{
"nombre": "Mermelada de frutilla",
"descripcion": "Mermelada artesanal elaborada con frutillas.",
"ingredientes": "Frutillas, azúcar, jugo de limón",
"valorNutricional": "250 kcal por 100g",
"categoriaId": 1,
"proveedorId": 1,
"precio": 5990,
"fechaVencimiento": "2026-12-31",
"descuento": 10,
"imagen": "https://ejemplo.com/mermelada.jpg",
"tipoConservacion": "Refrigerado"
}
Response — 201 Created
{
"id": 1,
"nombre": "Mermelada de frutilla",
"descripcion": "Mermelada artesanal elaborada con frutillas.",
"ingredientes": "Frutillas, azúcar, jugo de limón",
"valorNutricional": "250 kcal por 100g",
"categoriaId": 1,
"proveedorId": 1,
"precio": 5990,
"fechaVencimiento": "2026-12-31",
"descuento": 10,
"precioDescuento": 5391,
"imagen": "https://ejemplo.com/mermelada.jpg",
"tipoConservacion": "Refrigerado",
"valoracion": 0,
"favorito": false
}
Response — 400 Bad Request
Los datos enviados no son válidos.
{
"statusCode": 400,
"message": "Los datos del producto no son válidos."
}
Response — 409 Conflict
Ya existe un producto con los datos proporcionados.
{
"statusCode": 409,
"message": "Ya existe un producto con los datos proporcionados."
}
PATCH /productos/{id}
Actualiza parcialmente los datos de un producto existente.
Path Parameters
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
| id | number | Sí | Identificador único del producto |
Request Body
Utiliza UpdateProductoDto. Todos los campos son opcionales.
{
"precio": 6490,
"descuento": 15,
"imagen": "https://ejemplo.com/mermelada-nueva.jpg"
}
Response — 200 OK
{
"id": 1,
"nombre": "Mermelada de frutilla",
"descripcion": "Mermelada artesanal elaborada con frutillas.",
"ingredientes": "Frutillas, azúcar, jugo de limón",
"valorNutricional": "250 kcal por 100g",
"categoriaId": 1,
"proveedorId": 1,
"precio": 6490,
"fechaVencimiento": "2026-12-31",
"descuento": 15,
"precioDescuento": 5516.5,
"imagen": "https://ejemplo.com/mermelada-nueva.jpg",
"tipoConservacion": "Refrigerado",
"valoracion": 4.8,
"favorito": false
}
Response — 400 Bad Request
El ID o los datos enviados no son válidos.
{
"statusCode": 400,
"message": "El ID o los datos del producto no son válidos."
}
Response — 404 Not Found
El producto no existe.
{
"statusCode": 404,
"message": "Producto no encontrado."
}
DELETE /productos/{id}
Elimina un producto mediante su identificador.
Path Parameters
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
| id | number | Sí | Identificador único del producto |
Ejemplo de solicitud
DELETE /productos/1
Response — 204 No Content
El producto fue eliminado correctamente.
No se retorna un cuerpo en la respuesta.
Response — 400 Bad Request
El ID proporcionado no es válido.
{
"statusCode": 400,
"message": "El ID del producto no es válido."
}
Response — 404 Not Found
El producto no existe.
{
"statusCode": 404,
"message": "Producto no encontrado."
}