/products/register
🔐 Requiere autenticación JWT previa.
POST /api/products/register
multipart/form-data
. Valida que los campos sean correctos, maneja la carga a Cloudinary y controla errores, incluyendo duplicados.verificarAutenticacion
verificarAutenticacion
: Verifica el token JWT.upload.single('image')
: Maneja la carga del archivo usando Multer.imageRequired
: Verifica si hay un campo image
en la solicitud.createProductValidator
: Valida los campos del cuerpo.validateRequest
: Maneja errores de validación.processImage
: Sube imagen a Cloudinary y guarda la URL en req.imageUrl
.Tipo: multipart/form-data
Campo | Tipo | Requerido | Descripción |
---|---|---|---|
id | number | ✅ | Identificador único del producto. |
product_name | string | ✅ | Nombre del producto. |
measure | string | ✅ | Unidad de medida. |
price | number | ✅ | Precio del producto (no negativo). |
stock | number | ✅ | Cantidad disponible (no negativa). |
image | file | ❌ | Imagen del producto (opcional). |
{
"status": "success",
"code": "PRODUCT_CREATED",
"msg": "Producto creado correctamente.",
"data": {
"id": 1,
"product_name": "Ejemplo",
"measure": "kg",
"price": 25.5,
"stock": 10,
"imgUrl": "https://cloudinary.com/... (o string vacío)"
},
"info": {
"imageAction": "Subida" // o "Ninguna"
}
}
{
"status": "error",
"code": "MISSING_FIELD", // o "VALIDATION_ERROR", "INVALID_FORMAT"
"msg": "Campos requeridos: id, product_name, measure, price, stock.",
"errors": [/* Detalles si aplica */]
}
{
"status": "error",
"code": "AUTH_ERROR",
"msg": "Acceso no autorizado. Se requiere token válido."
}
{
"status": "error",
"code": "RESOURCE_ALREADY_EXISTS",
"msg": "El producto con ID 1 ya existe.",
"info": {
"duplicateProductId": 1,
"imageAction": "Eliminada (Duplicado)",
"imageStatus": "Imagen subida eliminada correctamente."
}
}
{
"status": "error",
"code": "SERVER_ERROR",
"msg": "Ha ocurrido un error inesperado al crear el producto. Intente de nuevo más tarde.",
"info": {
"detail": "Error al guardar en base de datos.",
"imageAction": "Eliminada (Error Creación)",
"imageStatus": "Imagen subida fue eliminada correctamente."
}
}
curl --location --request POST 'https://back-prima-s-a.onrender.com/api/products/register/' \
--header 'User-Agent: insomnia/11.0.0' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY3NjI0ZjkwNzY2OWM5MDZjYTM0YThkZSIsInJvbCI6ImFkbWluIiwiaWF0IjoxNzQyOTMxNzg3LCJleHAiOjE3NDI5NjA1ODd9.nwBdY2DmiTAjEYfxGukAQHJkbrsLHqMosjmOSgzfbR4' \
--header 'Content-Type: multipart/form-data' \
--form 'id="44444"' \
--form 'product_name="APPLE"' \
--form 'measure="Unit"' \
--form 'price="0.50"' \
--form 'stock="100"' \
--form 'image=@""'
{"message":"Producto creado correctamente","product":{"id":"44444","product_name":"APPLE","measure":"Unit","price":"0.50","stock":"100","imgUrl":"https://res.cloudinary.com/dyoyatqoz/image/upload/v1742931815/cvommtn1ldj5ky9cslyp.png"}}