Favoritos - bootcamp-uchile-2026/grupo-2-backend GitHub Wiki

Favoritos

La funcionalidad Favoritos permitirá que un usuario de BuenOrigen guarde productos de su interés para consultarlos posteriormente.

Podrá utilizarse desde distintas secciones de la aplicación, como:

  • Búsqueda de Productos.
  • Página de Inicio.
  • Detalle de Producto.
  • Listados del catálogo.
  • Página de Favoritos.

Desde la perspectiva Backend, esta funcionalidad consiste en mantener una relación entre un usuario y los productos que dicho usuario ha marcado como favoritos.


Objetivo

Permitir que Frontend y Mobile puedan:

  • Consultar los productos favoritos del usuario.
  • Agregar productos a favoritos.
  • Eliminar productos de favoritos.
  • Mantener una lista independiente para cada usuario.

Estado

Pendiente de implementación

Actualmente se encuentran definidos conceptualmente:

FavoritosModule
FavoritosService
Endpoints
ProductoFavoritoDto
Reglas iniciales de negocio

Sin embargo, todavía no se encuentran implementados:

FavoritosController
FavoritosService
Almacenamiento de favoritos
Relación Usuario - Producto
Identificación del usuario autenticado

Dominio

Favoritos

Módulo Propuesto

FavoritosModule

Service Propuesto

FavoritosService

Conceptualmente:

FavoritosModule
      |
      v
FavoritosController
      |
      v
FavoritosService
      |
      v
Favoritos del Usuario

Responsabilidad Backend

Cuando la funcionalidad sea implementada, el Backend deberá:

  • Identificar al usuario que realiza la solicitud.
  • Consultar los productos favoritos pertenecientes a ese usuario.
  • Verificar que un producto exista antes de agregarlo.
  • Evitar que un mismo producto sea agregado dos veces por el mismo usuario.
  • Permitir eliminar un producto de favoritos.
  • Impedir que un usuario modifique los favoritos de otro usuario.
  • Mantener la relación entre Usuario y Producto.
  • Entregar únicamente la información necesaria para representar los productos favoritos.
  • Evitar modificar o eliminar el producto original del catálogo al eliminarlo de favoritos.

Contratos de API

Actualmente se han identificado tres operaciones principales.


Consultar Favoritos

Endpoint

GET /favoritos

Objetivo

Obtener los productos guardados como favoritos por el usuario autenticado.

DTO de salida

ProductoFavoritoDto[]

Página relacionada:

DTOs

Conceptualmente:

GET /favoritos
      |
      v
Identificar usuario
      |
      v
Obtener favoritos
      |
      v
Consultar productos
      |
      v
ProductoFavoritoDto[]

Agregar Producto a Favoritos

Endpoint

POST /favoritos/:productoId

Ejemplo:

POST /favoritos/25

Parámetro de Ruta

productoId

Tipo esperado:

number

Objetivo

Agregar un producto determinado a la lista de favoritos del usuario autenticado.

Actualmente no se ha definido un DTO de entrada porque el producto puede identificarse directamente mediante:

productoId

incluido en la URL.

Conceptualmente:

POST /favoritos/25
        |
        v
Identificar usuario
        |
        v
¿Existe producto 25?
        |
    +---+---+
    |       |
   Sí       No
    |       |
    v       v
¿Ya está?  Error
    |
 +--+--+
 |     |
No     Sí
 |     |
 v     v
Agregar No duplicar

Eliminar Producto de Favoritos

Endpoint

DELETE /favoritos/:productoId

Ejemplo:

DELETE /favoritos/25

Parámetro de Ruta

productoId

Objetivo

Eliminar la relación entre el usuario autenticado y un producto determinado.

Esta operación no elimina el producto del catálogo.

Conceptualmente:

DELETE /favoritos/25
        |
        v
Favorito Usuario - Producto
        |
        v
Eliminar relación

y no:

DELETE Producto 25

Relación entre Usuario y Producto

Favoritos representa una relación entre dos dominios:

Usuario

y:

Producto

Conceptualmente:

Usuario
   |
   | guarda
   v
Favorito
   |
   | referencia
   v
Producto

Un usuario puede tener múltiples productos favoritos:

Usuario
   |
   +---- Producto 1
   |
   +---- Producto 7
   |
   +---- Producto 25

Al mismo tiempo, un producto puede encontrarse en los favoritos de distintos usuarios.

Por lo tanto, conceptualmente existe una relación:

Usuario N -------- N Producto

gestionada mediante Favoritos.


Representación Conceptual de la Relación

Una posible representación interna podría ser:

export class Favorito {
  usuarioId: number;
  productoId: number;
}

Por ejemplo:

usuarioId = 3
productoId = 25

significa:

El usuario 3
ha agregado
el producto 25
a sus favoritos

Esta estructura es conceptual y podrá ajustarse cuando se implemente el dominio Usuarios y la persistencia definitiva.


ProductoFavoritoDto

La consulta de favoritos utiliza actualmente el contrato definido:

ProductoFavoritoDto

con la estructura:

export class ProductoFavoritoDto {
  id: number;
  marca: string;
  nombre: string;
  precio: number;
  imagenUrl: string;
}

La respuesta de:

GET /favoritos

será:

ProductoFavoritoDto[]

Ejemplo de Respuesta

[
  {
    "id": 25,
    "marca": "EcoHome",
    "nombre": "Bolsa Reutilizable de Algodón",
    "precio": 5990,
    "imagenUrl": "https://ejemplo.cl/imagenes/bolsa-algodon.jpg"
  },
  {
    "id": 31,
    "marca": "Naturaleza Viva",
    "nombre": "Shampoo Sólido",
    "precio": 6990,
    "imagenUrl": "https://ejemplo.cl/imagenes/shampoo-solido.jpg"
  }
]

Usuario sin Favoritos

Si el usuario no posee productos favoritos, la operación:

GET /favoritos

deberá devolver:

[]

con:

200 OK

Esto no deberá considerarse un error.

Conceptualmente:

Usuario existe
      |
      v
Buscar favoritos
      |
      v
0 favoritos
      |
      v
[]
      |
      v
200 OK

Reglas de Negocio

La funcionalidad deberá considerar inicialmente las siguientes reglas.

Producto Existente

Antes de agregar un favorito:

POST /favoritos/:productoId

el Backend deberá verificar que el producto exista.

Conceptualmente:

productoId
    |
    v
ProductosService
    |
    v
¿Existe producto?
    |
 +--+--+
 |     |
Sí     No
 |     |
 v     v
Continuar Error

Evitar Favoritos Duplicados

Un usuario no deberá mantener dos relaciones iguales con el mismo producto.

Por ejemplo:

Usuario 3
+
Producto 25

deberá existir como máximo una vez.

No debería producirse:

usuarioId: 3, productoId: 25
usuarioId: 3, productoId: 25
usuarioId: 3, productoId: 25

Favoritos Independientes por Usuario

Cada usuario deberá administrar únicamente sus propios favoritos.

Por ejemplo:

Usuario 1
├── Producto 5
└── Producto 8

Usuario 2
├── Producto 5
└── Producto 20

El hecho de que ambos usuarios tengan:

Producto 5

como favorito es válido.

Lo que debe evitarse es que:

Usuario 1

pueda eliminar o modificar directamente los favoritos pertenecientes a:

Usuario 2

Eliminación de un Favorito

Eliminar un favorito deberá eliminar solamente la relación:

Usuario - Producto

No deberá modificar:

Producto
stock
precio
catálogo
información del producto

Conceptualmente:

ANTES

Usuario
   |
   v
Favorito
   |
   v
Producto 25


DELETE /favoritos/25


DESPUÉS

Usuario

Producto 25
continúa existiendo

Identificación del Usuario

Esta es actualmente la principal dependencia pendiente para implementar Favoritos.

Los endpoints propuestos son:

GET /favoritos

POST /favoritos/:productoId

DELETE /favoritos/:productoId

pero ninguno contiene:

usuarioId

en la URL.

Esto es intencional si el usuario es identificado mediante autenticación.

Conceptualmente:

Request
   |
   +--> Token / Sesión
   |
   v
Usuario autenticado
   |
   v
Favoritos de ese usuario

Por ejemplo:

GET /favoritos

debería significar:

Obtener MIS favoritos

y no:

Obtener los favoritos de todos los usuarios

Dependencia con Autenticación

Antes de implementar completamente Favoritos deberá definirse cómo se obtiene el usuario autenticado.

Conceptualmente:

Usuario inicia sesión
        |
        v
Autenticación
        |
        v
Usuario identificado
        |
        +-------------------+
        |                   |
        v                   v
   Favoritos             Carrito

Por esta razón, Favoritos se encuentra relacionado con:

Autenticación

y:

Perfil de Usuario


Posible Flujo Futuro

Una vez implementada la autenticación, una solicitud podría funcionar conceptualmente así:

GET /favoritos
      |
      v
Request autenticada
      |
      v
Obtener usuarioId
      |
      v
FavoritosService
      |
      v
Buscar relaciones del usuario
      |
      v
Obtener productos
      |
      v
ProductoFavoritoDto[]

Relación con ProductosService

Favoritos necesitará consultar información perteneciente al dominio Productos.

Por ejemplo:

POST /favoritos/25
        |
        v
FavoritosService
        |
        | verificar producto
        v
ProductosService

También al consultar favoritos:

Favoritos
    |
    | productoId
    v
Productos
    |
    v
ProductoFavoritoDto

Por lo tanto, al implementar esta funcionalidad podrá evaluarse reutilizar:

ProductosService

en lugar de duplicar información del catálogo.


Manejo de Errores Propuesto

Los códigos definitivos deberán establecerse durante la implementación.

Como criterio inicial podrán considerarse:

Código Situación
200 OK Favoritos obtenidos correctamente
200 OK con [] El usuario no posee favoritos
201 Created Producto agregado correctamente a favoritos
400 Bad Request Parámetro incorrecto o intento de duplicar una relación, según la regla definitiva
401 Unauthorized Usuario no autenticado
404 Not Found Producto solicitado no existe
204 No Content Favorito eliminado correctamente, si se adopta este contrato

Los códigos exactos deberán confirmarse al momento de implementar los endpoints y documentarse posteriormente en Swagger y Endpoints.


Documentación Swagger

Cuando se implemente la funcionalidad deberán documentarse las operaciones mediante decoradores como:

@ApiTags()
@ApiOperation()
@ApiParam()
@ApiOkResponse()
@ApiCreatedResponse()
@ApiNotFoundResponse()
@ApiUnauthorizedResponse()

según corresponda.

El parámetro:

productoId

deberá documentarse como:

Number

y la respuesta de:

GET /favoritos

como:

ProductoFavoritoDto[]

Flujo General

Conceptualmente:

Frontend / Mobile
        |
        v
Usuario autenticado
        |
        v
FavoritosController
        |
        v
FavoritosService
        |
        +-------------------------+
        |                         |
        v                         v
Usuario                     ProductosService
        |                         |
        v                         v
Relaciones favoritas        Productos
        |                         |
        +------------+------------+
                     |
                     v
            ProductoFavoritoDto[]

Relación con el Header

Desde el Header, el usuario podrá acceder a su lista de favoritos.

Header
   |
   v
Favoritos
   |
   v
GET /favoritos
   |
   v
Productos Favoritos

Desde otras páginas podrá:

Producto
   |
   +--> POST /favoritos/:productoId
   |
   └--> DELETE /favoritos/:productoId

Estado de los Componentes

Elemento Estado
Funcionalidad identificada Definida
Dominio Favoritos Identificado
FavoritosModule Pendiente
FavoritosController Pendiente
FavoritosService Pendiente
GET /favoritos Pendiente
POST /favoritos/:productoId Pendiente
DELETE /favoritos/:productoId Pendiente
ProductoFavoritoDto Definido
Relación Usuario - Producto Diseño conceptual
Identificación del usuario Pendiente de Autenticación
Persistencia Pendiente

Decisiones Pendientes

Antes de implementar completamente Favoritos se deberá definir principalmente:

1. Cómo se autenticará el usuario.

2. Cómo obtendrá FavoritosService
   la identidad del usuario.

3. Cómo se almacenará la relación:
   Usuario - Producto.

4. Qué respuesta tendrá POST
   cuando el producto ya sea favorito.

5. Qué respuesta tendrá DELETE
   cuando el producto no esté en favoritos.

6. Qué mecanismo de persistencia
   utilizará la aplicación.

Estas decisiones deberán resolverse junto con el diseño de Usuarios y Autenticación.


Relación con la Arquitectura

La funcionalidad pertenecerá al dominio:

Favoritos

y conceptualmente utilizará:

FavoritosModule
      |
      v
FavoritosController
      |
      v
FavoritosService
      |
      +--> Usuario autenticado
      |
      +--> ProductosService
      |
      v
ProductoFavoritoDto[]

Páginas relacionadas: