From 663ba4ee8663969af1672a507ffd64689f9e7712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Fri, 6 Jun 2025 03:45:52 -0600 Subject: [PATCH 01/19] Feat: Implementar funcionalidad para actualizar productos y variantes --- .../actualizarProducto.controller.js | 179 ++++++++++++++++++ .../repositorioActualizarOpcion.js | 43 +++++ .../repositorioActualizarProducto.js | 63 ++++++ .../repositorioActualizarProductoImagen.js | 41 ++++ .../repositorioActualizarVariante.js | 37 ++++ .../repositorioActualizarVarianteImagen.js | 45 +++++ .../actualizarProducto.routes.js | 20 ++ Productos/Rutas/indexProductos.routes.js | 3 + Utilidades/Constantes/rutas.js | 1 + 9 files changed, 432 insertions(+) create mode 100644 Productos/Controladores/actualizarProducto.controller.js create mode 100644 Productos/Datos/Repositorios/repositorioActualizarOpcion.js create mode 100644 Productos/Datos/Repositorios/repositorioActualizarProducto.js create mode 100644 Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js create mode 100644 Productos/Datos/Repositorios/repositorioActualizarVariante.js create mode 100644 Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js create mode 100644 Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js diff --git a/Productos/Controladores/actualizarProducto.controller.js b/Productos/Controladores/actualizarProducto.controller.js new file mode 100644 index 0000000..0843048 --- /dev/null +++ b/Productos/Controladores/actualizarProducto.controller.js @@ -0,0 +1,179 @@ +//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26 +const multer = require('multer'); +const enviarS3 = require('@altertex/util/ser/enviarS3'); +const MENSAJES_PRODUCTOS = require('@altertex/util/const/mensajesProductos'); +const validarProducto = require('@altertex/util/vali/validarProducto'); +const validarVariante = require('@altertex/util/vali/validarVariante'); +const validarOpciones = require('@altertex/util/vali/validarOpciones'); +const repositorioActualizarProducto = require('@altertex/pro/repos/repositorioActualizarProducto'); +const repositorioProductoImagen = require('@altertex/pro/repos/repositorioProductoImagen'); +const repositorioActualizarVariante = require('@altertex/pro/repos/repositorioActualizarVariante'); +const repositorioVarianteImagen = require('@altertex/pro/repos/repositorioVarianteImagen'); +const repositorioActualizarOpcion = require('@altertex/pro/repos/repositorioActualizarOpcion'); +const db = require('@altertex/util/bd/db'); +const upload = multer({ storage: multer.memoryStorage() }); + +exports.actualizarProducto = [ + upload.fields([ + { name: 'imagenProducto', maxCount: 1 }, + { name: 'imagenesVariante', maxCount: 100 }, + ]), + + async (req, res) => { + const idCliente = parseInt(req.user.clienteSeleccionado); + const producto = JSON.parse(req.body.producto); + const variantes = JSON.parse(req.body.variantes); + const mapaImagenes = JSON.parse(req.body.mapaImagenes); + const imagenProducto = req.files.imagenProducto ? req.files.imagenProducto[0] : null; + const imagenesVariante = req.files.imagenesVariante || []; + let conexion = null; + + // prettier-ignore + if ( + !idCliente + || !mapaImagenes + || !producto + || !Array.isArray(variantes) + || variantes.length === 0 + || !imagenProducto + || !imagenesVariante + ) { + return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({ + mensaje: MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.mensaje, + }); + } + + const errorProducto = validarProducto(producto); + if (errorProducto) { + return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({ + mensaje: errorProducto.error, + }); + } + + if (imagenesVariante.length !== mapaImagenes.length) { + return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({ + mensaje: 'La cantidad de imágenes no coincide con el mapa de imágenes', + }); + } + + try { + conexion = await db.getConnection(); + await conexion.beginTransaction(); + + const idProducto = await repositorioActualizarProducto.actualizarProducto( + idCliente, + producto + ); + if (!idProducto) { + throw new Error('Error al actualizar producto'); + } + + const varianteIdMap = {}; + const variantesPromises = variantes.map(async (variante) => { + const errorVariante = validarVariante({ + nombreVariante: variante.nombreVariante, + descripcion: variante.descripcion, + }); + if (errorVariante) { + throw new Error(errorVariante.error); + } + + const idVariante = await repositorioActualizarVariante.actualizarVariante( + idProducto, + variante + ); + if (!idVariante) { + throw new Error('Error al actualizar variante'); + } + + varianteIdMap[variante.identificador] = { + id: idVariante, + nombre: variante.nombreVariante, + }; + + const errorOpciones = validarOpciones(variante.opciones); + if (errorOpciones) { + throw new Error(errorOpciones.error); + } + + await repositorioActualizarOpcion.actualizarOpcion(idVariante, variante.opciones); + }); + + await Promise.all(variantesPromises); + + const urlImagenProductoPromise = imagenProducto + ? enviarS3({ + Bucket: process.env.AWS_BUCKET_NAME, + Key: `productos/${imagenProducto.originalname}`, + Body: imagenProducto.buffer, + ContentType: imagenProducto.mimetype, + }) + : Promise.resolve(null); + + // prettier-ignore + const urlImagenVariantePromises = imagenesVariante.map((imagenVariante) => + enviarS3({ + Bucket: process.env.AWS_BUCKET_NAME, + Key: `productos/${imagenVariante.originalname}`, + Body: imagenVariante.buffer, + ContentType: imagenVariante.mimetype, + })); + + const [urlImagenProducto, ...urlImagenVariantes] = await Promise.all([ + urlImagenProductoPromise, + ...urlImagenVariantePromises, + ]); + + if ((imagenProducto && !urlImagenProducto) || urlImagenVariantes.includes(null)) { + throw new Error('Error al subir imágenes al servidor'); + } + + if (imagenProducto) { + await repositorioProductoImagen.actualizarImagen( + idProducto, + imagenProducto.originalname, + producto.nombreComun + ); + } + + const imagenesVariantePromises = imagenesVariante.map(async (imagen, index) => { + const { idVariante: tempIdVariante } = mapaImagenes[index]; + const varianteInfo = varianteIdMap[tempIdVariante]; + + if (!varianteInfo) { + throw new Error(`Variante con ID temporal ${tempIdVariante} no encontrada`); + } + + await repositorioVarianteImagen.actualizarImagen( + varianteInfo.id, + imagen.originalname, + varianteInfo.nombre + ); + }); + + await Promise.all(imagenesVariantePromises); + + await conexion.commit(); + return res.status(200).json({ mensaje: 'Producto actualizado correctamente' }); + } catch (error) { + if (conexion) await conexion.rollback(); + + let errorMensaje = MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_PRODUCTO; + + if (error.message.includes('Error al subir imágenes al servidor')) { + errorMensaje = MENSAJES_PRODUCTOS.ERROR_ENVIAR_IMAGENES_S3; + } else if (error.message.includes('Error al actualizar variante')) { + errorMensaje = MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_VARIANTE; + } else if (error.message.includes('Error al asociar imagen con variante')) { + errorMensaje = MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_IMAGEN_VARIANTE; + } + + return res.status(errorMensaje.codigo).json({ + mensaje: errorMensaje.mensaje, + error: error.message, + }); + } finally { + if (conexion) conexion.release(); + } + }, +]; diff --git a/Productos/Datos/Repositorios/repositorioActualizarOpcion.js b/Productos/Datos/Repositorios/repositorioActualizarOpcion.js new file mode 100644 index 0000000..5626da0 --- /dev/null +++ b/Productos/Datos/Repositorios/repositorioActualizarOpcion.js @@ -0,0 +1,43 @@ +//RF29 Actualiza Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF29 +const db = require('@altertex/util/bd/db'); +const consultas = require('@altertex/util/const/consultasOpciones'); + +/** + * Actualiza una o varias opciones relacionadas con una variante. + * + * @async + * @function crearOpcion + * @param {number} idVariante - ID de la variante a la que se le agregarán las opciones. + * @param {Array} opciones - Un arreglo con los objetos de opciones que se desean agregar. + * @returns {Promise} - Una promesa que se resuelve cuando todas las opciones se crean exitosamente. + */ +exports.actualizarOpcion = async (idVariante, opciones) => { + const conexion = await db.getConnection(); + + try { + await conexion.beginTransaction(); + + for (const opcion of opciones) { + const params = [ + idVariante, + opcion.cantidad, + opcion.valorOpcion, + opcion.SKUautomatico, + opcion.SKUcomercial, + opcion.costoAdicional, + opcion.descuento, + opcion.estado, + ]; + + await conexion.query(consultas.ACTUALIZAR, params); + } + + await conexion.commit(); + } catch (error) { + await conexion.rollback(); + console.error('Error al actualizar opciones:', error); + throw error; + } finally { + if (conexion) conexion.release(); + } +}; diff --git a/Productos/Datos/Repositorios/repositorioActualizarProducto.js b/Productos/Datos/Repositorios/repositorioActualizarProducto.js new file mode 100644 index 0000000..ebea5ae --- /dev/null +++ b/Productos/Datos/Repositorios/repositorioActualizarProducto.js @@ -0,0 +1,63 @@ +//RF29 Actualiza Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF29 +const db = require('@altertex/util/bd/db'); +const consultas = require('@altertex/util/const/consultasProductos'); + +/** + * Actualiza un producto en la base de datos. + * + * Esta función ejecuta una consulta SQL para actualizar un producto en la base de datos, + * utilizando los parámetros proporcionados. Devuelve el ID del producto actualizado + * en caso de éxito, o un array vacío si ocurre algún error durante la operación. + * + * @param {number} clienteSeleccionado - ID del cliente para el cual se está creando el producto. + * @param {object} producto - Objeto que contiene la información del producto. + * @param {number} producto.idProveedor - ID del proveedor asociado al producto. + * @param {string} producto.nombreComun - Nombre común del producto. + * @param {string} producto.nombreComercial - Nombre comercial del producto. + * @param {string} producto.descripcion - Descripción del producto. + * @param {string} producto.marca - Marca del producto. + * @param {string} producto.modelo - Modelo del producto. + * @param {string} producto.tipoProducto - Tipo del producto. + * @param {number} producto.precioPuntos - Precio en puntos del producto. + * @param {number} producto.precioCliente - Precio para el cliente del producto. + * @param {number} producto.precioVenta - Precio de venta del producto. + * @param {number} producto.costo - Costo de producción del producto. + * @param {number} producto.impuesto - Impuesto aplicado al producto. + * @param {number} producto.descuento - Descuento aplicado al producto. + * @param {string} producto.estado - Estado del producto (activo/inactivo). + * @param {boolean} producto.envio - Indica si el producto es apto para envío. + * + * @returns {number|Array} El ID del producto recién creado en caso de éxito, o un array vacío en caso de error. + */ +exports.actualizarProducto = async (clienteSeleccionado, producto) => { + const conexion = await db.getConnection(); + + try { + const [resultados] = await conexion.query(consultas.ACTUALIZAR, [ + clienteSeleccionado, + producto.idProveedor, + producto.nombreComun, + producto.nombreComercial, + producto.descripcion, + producto.marca, + producto.modelo, + producto.tipoProducto, + producto.precioPuntos, + producto.precioCliente, + producto.precioVenta, + producto.costo, + producto.impuesto, + producto.descuento, + producto.estado, + producto.envio, + ]); + + const idProducto = resultados.insertId; + return idProducto; + } catch (error) { + console.error('Error al actualizar producto:', error); + return []; + } finally { + if (conexion) conexion.release(); + } +}; diff --git a/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js b/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js new file mode 100644 index 0000000..2db9cdd --- /dev/null +++ b/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js @@ -0,0 +1,41 @@ +// RF29 Actualiza Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF29 +const db = require('@altertex/util/bd/db'); +const consultasProductos = require('@altertex/util/const/consultasProductos'); +const consultasImagenes = require('@altertex/util/const/consultasImagenes'); + +/** + * Actualiza la imagen de un producto existente en la base de datos. + * Esta función realiza dos operaciones en una transacción: + * - Actualiza la imagen en la tabla de imágenes. + * - Actualiza la relación entre la imagen y el producto correspondiente. + * @param {number} idProducto - ID del producto al que se asociará la imagen. + * @param {number} idImagen - ID de la imagen que se actualizará. + * @param {string} urlImagenProducto - Nueva URL o ruta de la imagen del producto almacenada. + * @param {string} nombreComun - Nuevo nombre común o descriptivo asociado al producto. + * @returns {Promise} El resultado de la actualización de la imagen (incluyendo `affectedRows`) si es exitoso, o un arreglo vacío en caso de error. + */ + +exports.actualizarProductoImagen = async (idProducto, idImagen, urlImagenProducto, nombreComun) => { + const parametrosImagen = [urlImagenProducto, nombreComun, idImagen]; + const conexion = await db.getConnection(); + + try { + await conexion.beginTransaction(); + + // Actualizar la imagen en la tabla de imágenes + const [resultadoImagen] = await conexion.query(consultasImagenes.ACTUALIZAR, parametrosImagen); + + // Actualizar la relación entre la imagen y el producto + const parametrosRelacion = [idImagen, idProducto]; + await conexion.query(consultasProductos.ACTUALIZAR_IMAGEN_PRODUCTO, parametrosRelacion); + + await conexion.commit(); + return resultadoImagen; + } catch (error) { + console.error('Error al actualizar o asociar la imagen:', error); + await conexion.rollback(); + return []; + } finally { + if (conexion) conexion.release(); + } +}; diff --git a/Productos/Datos/Repositorios/repositorioActualizarVariante.js b/Productos/Datos/Repositorios/repositorioActualizarVariante.js new file mode 100644 index 0000000..e14be0c --- /dev/null +++ b/Productos/Datos/Repositorios/repositorioActualizarVariante.js @@ -0,0 +1,37 @@ +// RF29 Actualiza Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF29 +const db = require('@altertex/util/bd/db'); +const consultas = require('@altertex/util/const/consultasVariantes'); + +/** + * Actualiza una variante para un producto en la base de datos. + * + * Esta función ejecuta una consulta SQL para actualizar una variante asociada a un producto, + * utilizando los parámetros proporcionados. Devuelve el ID de la variante actualizada + * en caso de éxito, o un array vacío si ocurre algún error durante la operación. + * + * @param {number} idProducto - ID del producto al que se le va a agregar la variante. + * @param {object} variante - Objeto que contiene la información de la variante. + * @param {string} variante.nombreVariante - Nombre de la variante (por ejemplo, color, tamaño). + * @param {string} variante.descripcion - Descripción de la variante. + * + * @returns {number|Array} El ID de la variante recién creada en caso de éxito, o un array vacío en caso de error. + */ +exports.actualizarVariante = async (idProducto, variante) => { + const conexion = await db.getConnection(); + + try { + const [resultados] = await conexion.query(consultas.ACTUALIZAR, [ + idProducto, + variante.nombreVariante, + variante.descripcion, + ]); + + const idVariante = resultados.insertId; + return idVariante; + } catch (error) { + console.error('Error al actualizar variante:', error); + return []; + } finally { + if (conexion) conexion.release(); + } +}; diff --git a/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js b/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js new file mode 100644 index 0000000..756424b --- /dev/null +++ b/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js @@ -0,0 +1,45 @@ +//RF29 Actualizar Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF29 +const db = require('@altertex/util/bd/db'); +const consultasVariantes = require('@altertex/util/const/consultasVariantes'); +const consultasImagenes = require('@altertex/util/const/consultasImagenes'); + +/** + * Actualiza la imagen de una variante existente en la base de datos. + * Esta función realiza dos operaciones en una transacción: + * - Actualiza la imagen en la tabla de imágenes. + * - Actualiza la relación entre la imagen y la variante correspondiente. + * @param {number} idVariante - ID de la variante a la que se asociará la imagen. + * @param {number} idImagen - ID de la imagen que se actualizará. + * @param {string} urlImagenVariante - Nueva URL o ruta de la imagen de la variante almacenada. + * @param {string} nombreVariante - Nuevo nombre de la variante asociado a la imagen. + * @returns {Promise} El resultado de la actualización de la imagen (incluyendo `affectedRows`) si es exitoso, o un arreglo vacío en caso de error. + */ +exports.actualizarVarianteImagen = async ( + idVariante, + idImagen, + urlImagenVariante, + nombreVariante +) => { + const parametrosImagen = [urlImagenVariante, nombreVariante, idImagen]; + const conexion = await db.getConnection(); + + try { + await conexion.beginTransaction(); + + // Actualizar la imagen en la tabla de imágenes + const [resultadoImagen] = await conexion.query(consultasImagenes.ACTUALIZAR, parametrosImagen); + + // Actualizar la relación entre la imagen y la variante + const parametrosRelacion = [idImagen, idVariante]; + await conexion.query(consultasVariantes.ACTUALIZAR_IMAGEN_VARIANTE, parametrosRelacion); + + await conexion.commit(); + return resultadoImagen; + } catch (error) { + console.error('Error al actualizar o asociar la imagen:', error); + await conexion.rollback(); + return []; + } finally { + if (conexion) conexion.release(); + } +}; diff --git a/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js b/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js new file mode 100644 index 0000000..48ee496 --- /dev/null +++ b/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js @@ -0,0 +1,20 @@ +//RF27 Consulta Lista de Productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF27 +const express = require('express'); +const ruteador = express.Router(); +const controlador = require('@altertex/pro/ctrl/actualizarProductos.controller'); +const revisarApiKey = require('@altertex/util/inter/revisarApiKey'); +const autorizarToken = require('@altertex/util/inter/autorizarToken'); +const verificarPermisos = require('@altertex/util/inter/verificarPermisos'); +const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones'); +const PERMISOS = require('@altertex/util/const/permisos'); +const RUTAS = require('@altertex/util/const/rutas'); + +ruteador.post( + RUTAS.PRODUCTOS.ACTUALIZAR, + revisarApiKey, + autorizarToken, + limitePeticionesDiarias(PERMISOS.ACTUALIZAR_PRODUCTO), + controlador.actualizarProducto +); + +module.exports = ruteador; diff --git a/Productos/Rutas/indexProductos.routes.js b/Productos/Rutas/indexProductos.routes.js index 678cf01..4e20604 100644 --- a/Productos/Rutas/indexProductos.routes.js +++ b/Productos/Rutas/indexProductos.routes.js @@ -5,6 +5,7 @@ const rutaEliminar = require('@altertex/pro/rutasInd/eliminarProducto.routes'); const rutaCrearProducto = require('@altertex/pro/rutasInd/crearProducto.routes'); const rutasLeerProducto = require('@altertex/pro/rutasInd/leerProductos.routes'); const rutasExportarProductos = require('@altertex/pro/rutasInd/exportarProductos.routes'); +const rutasActualizarProducto = require('@altertex/pro/rutasInd/actualizarProducto.routes'); const RUTAS = require('@altertex/util/const/rutas'); @@ -18,5 +19,7 @@ ruteador.use(RUTAS.PRODUCTOS.BASE, rutaEliminar); ruteador.use(RUTAS.PRODUCTOS.BASE, rutasLeerProducto); // RF[58] Exportar Productos - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF58] ruteador.use(RUTAS.PRODUCTOS.BASE, rutasExportarProductos); +// RF[29] Actualizar Producto - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF29] +ruteador.use(RUTAS.PRODUCTOS.BASE, rutasActualizarProducto); module.exports = ruteador; diff --git a/Utilidades/Constantes/rutas.js b/Utilidades/Constantes/rutas.js index e6c4575..7f0c2fd 100644 --- a/Utilidades/Constantes/rutas.js +++ b/Utilidades/Constantes/rutas.js @@ -42,6 +42,7 @@ module.exports = { ELIMINAR_PRODUCTO: '/eliminar', LEER: '/leer-producto', EXPORTAR_PRODUCTOS: '/exportar-productos', + ACTUALIZAR: '/actualizar', }, PROVEEDORES: { BASE: '/proveedores', From 745752561e81fa6c3d50b3ef54278c72a9be1ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Fri, 6 Jun 2025 04:19:51 -0600 Subject: [PATCH 02/19] =?UTF-8?q?Feat:=20AGREGU=C3=89=20LA=20NUEVAS=20QUER?= =?UTF-8?q?YS=20PARA=20PRODUCTO,=20VARIANTE=20Y=20OPCION=20E=20IMAGENES?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Utilidades/Constantes/consultasImagenes.js | 7 +++++++ Utilidades/Constantes/consultasOpciones.js | 5 +++++ Utilidades/Constantes/consultasProductos.js | 12 ++++++++++++ Utilidades/Constantes/consultasVariantes.js | 12 ++++++++++++ 4 files changed, 36 insertions(+) diff --git a/Utilidades/Constantes/consultasImagenes.js b/Utilidades/Constantes/consultasImagenes.js index 0c559a6..16ee6a6 100644 --- a/Utilidades/Constantes/consultasImagenes.js +++ b/Utilidades/Constantes/consultasImagenes.js @@ -1,6 +1,13 @@ +const { ACTUALIZAR } = require('./consultasEmpleados'); + module.exports = { CREAR: ` INSERT INTO imagen(urlImagen, tipoImagen, textoAlternativo) VALUES (?, ?, ?); `, + ACTUALIZAR: ` + UPDATE imagen + SET urlImagen = ?, tipoImagen = ?, textoAlternativo = ? + WHERE idImagen = ?; + `, }; diff --git a/Utilidades/Constantes/consultasOpciones.js b/Utilidades/Constantes/consultasOpciones.js index 825ebfe..ac41ac9 100644 --- a/Utilidades/Constantes/consultasOpciones.js +++ b/Utilidades/Constantes/consultasOpciones.js @@ -3,4 +3,9 @@ module.exports = { INSERT INTO opcion (idVariante, cantidad, valorOpcion, SKUautomatico, SKUcomercial, costoAdicional, descuento, estado) VALUES (?, ?, ?, ?, ?, ?, ?, ?); `, + ACTUALIZAR: ` + UPDATE opcion + SET idVariante = ?, cantidad = ?, valorOpcion = ?, SKUcomercial = ?, costoAdicional = ?, descuento = ?, estado = ? + WHERE idOpcion = ?; + `, }; diff --git a/Utilidades/Constantes/consultasProductos.js b/Utilidades/Constantes/consultasProductos.js index b0c2d54..341a216 100644 --- a/Utilidades/Constantes/consultasProductos.js +++ b/Utilidades/Constantes/consultasProductos.js @@ -1,4 +1,16 @@ module.exports = { + ACTUALIZAR: ` + UPDATE producto + SET idProveedor = ?, nombreComun = ?, nombreComercial = ?, descripcion = ?, + marca = ?, modelo = ?, tipoProducto = ?, precioPuntos = ?, precioCliente = ?, + precioVenta = ?, costo = ?, impuesto = ?, descuento = ?, estado = ?, envio = ? + WHERE idProducto = ?; + `, + ACTUALIZAR_IMAGEN_PRODUCTO: ` + UPDATE imagen_producto + SET idImagen = ? + WHERE idProducto = ?; + `, OBTENER_LISTA: ` SELECT p.idProducto, p.nombreComun, p.precioVenta, p.estado, i.urlImagen FROM producto p diff --git a/Utilidades/Constantes/consultasVariantes.js b/Utilidades/Constantes/consultasVariantes.js index b9ebc21..062e812 100644 --- a/Utilidades/Constantes/consultasVariantes.js +++ b/Utilidades/Constantes/consultasVariantes.js @@ -1,3 +1,5 @@ +const { ACTUALIZAR } = require('./consultasProductos'); + module.exports = { CREAR: ` INSERT INTO variante (idProducto, nombreVariante, descripcion) @@ -7,4 +9,14 @@ module.exports = { INSERT INTO imagen_variante (idImagen, idVariante) VALUES (?, ?); `, + ACTUALIZAR: ` + UPDATE variante + SET idProducto = ?, nombreVariante = ?, descripcion = ? + WHERE idVariante = ?; + `, + ACTUALIZAR_IMAGEN_VARIANTE: ` + UPDATE imagen_variante + SET idImagen = ? + WHERE idVariante = ?; + `, }; From 7d097a4c213c601b89f622e600a1e70b1e61f27a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Fri, 6 Jun 2025 04:23:58 -0600 Subject: [PATCH 03/19] =?UTF-8?q?Feat:=20Agregar=20mensajes=20de=20respues?= =?UTF-8?q?ta=20para=20la=20actualizaci=C3=B3n=20de=20productos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Utilidades/Constantes/mensajesProductos.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Utilidades/Constantes/mensajesProductos.js b/Utilidades/Constantes/mensajesProductos.js index 7f71397..28db914 100644 --- a/Utilidades/Constantes/mensajesProductos.js +++ b/Utilidades/Constantes/mensajesProductos.js @@ -8,6 +8,10 @@ module.exports = { codigo: 200, mensaje: 'Producto creado correctamente.', }, + ACTUALIZACION_EXITOSA: { + codigo: 200, + mensaje: 'Producto actualizado exitosamente.', + }, // 204 - No Content SIN_RESULTADOS: { @@ -28,6 +32,11 @@ module.exports = { codigo: 400, mensaje: 'Los valores de límite u offset deben ser números positivos.', }, + ERROR_PARAMETROS_ACTUALIZACION: { + codigo: 400, + mensaje: + 'Los parámetros proporcionados para la actualización no son válidos o están incompletos.', + }, // 403 - Forbidden PERMISO_DENEGADO: { @@ -35,6 +44,12 @@ module.exports = { mensaje: 'No tiene permiso para consultar productos de este cliente.', }, + // 404 - Not Found + PRODUCTO_NO_ENCONTRADO_ACTUALIZACION: { + codigo: 404, + mensaje: 'El producto que intenta actualizar no existe.', + }, + // 500 - Internal Server Error ERROR_CONSULTAR_PRODUCTOS: { codigo: 500, @@ -63,6 +78,10 @@ module.exports = { mensaje: 'Ocurrió un error al asociar la imagen con la variante. Verifique los datos de las imágenes de variantes.', }, + ERROR_ACTUALIZAR_PRODUCTO: { + codigo: 500, + mensaje: 'Ocurrió un error al actualizar el producto. Por favor, intente nuevamente más tarde.', + }, // 200 - OK RESPUESTA_ELIMINAR_PRODUCTO_EXITOSA: { From bf6d634f217c2b20e239a47aa1903300650abbb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Fri, 6 Jun 2025 04:52:01 -0600 Subject: [PATCH 04/19] =?UTF-8?q?Feat:=20Mejorar=20manejo=20de=20errores?= =?UTF-8?q?=20y=20mensajes=20en=20la=20actualizaci=C3=B3n=20de=20productos?= =?UTF-8?q?=20y=20variantes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../actualizarProducto.controller.js | 32 ++++++++++--------- .../repositorioActualizarProducto.js | 1 - .../repositorioActualizarVariante.js | 1 - .../repositorioActualizarVarianteImagen.js | 1 - 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Productos/Controladores/actualizarProducto.controller.js b/Productos/Controladores/actualizarProducto.controller.js index 0843048..79115cc 100644 --- a/Productos/Controladores/actualizarProducto.controller.js +++ b/Productos/Controladores/actualizarProducto.controller.js @@ -45,14 +45,14 @@ exports.actualizarProducto = [ const errorProducto = validarProducto(producto); if (errorProducto) { - return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({ - mensaje: errorProducto.error, + return res.status(MENSAJES_PRODUCTOS.ERROR_PARAMETROS_ACTUALIZACION.codigo).json({ + mensaje: MENSAJES_PRODUCTOS.ERROR_PARAMETROS_ACTUALIZACION.mensaje, }); } if (imagenesVariante.length !== mapaImagenes.length) { - return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({ - mensaje: 'La cantidad de imágenes no coincide con el mapa de imágenes', + return res.status(MENSAJES_PRODUCTOS.LIMITE_OFFSET_INVALIDOS.codigo).json({ + mensaje: MENSAJES_PRODUCTOS.LIMITE_OFFSET_INVALIDOS.mensaje, }); } @@ -65,7 +65,7 @@ exports.actualizarProducto = [ producto ); if (!idProducto) { - throw new Error('Error al actualizar producto'); + throw new Error(MENSAJES_PRODUCTOS.PRODUCTO_NO_ENCONTRADO_ACTUALIZACION.mensaje); } const varianteIdMap = {}; @@ -75,7 +75,7 @@ exports.actualizarProducto = [ descripcion: variante.descripcion, }); if (errorVariante) { - throw new Error(errorVariante.error); + throw new Error(MENSAJES_PRODUCTOS.ERROR_PARAMETROS_ACTUALIZACION.mensaje); } const idVariante = await repositorioActualizarVariante.actualizarVariante( @@ -83,7 +83,7 @@ exports.actualizarProducto = [ variante ); if (!idVariante) { - throw new Error('Error al actualizar variante'); + throw new Error(MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_PRODUCTO.mensaje); } varianteIdMap[variante.identificador] = { @@ -93,7 +93,7 @@ exports.actualizarProducto = [ const errorOpciones = validarOpciones(variante.opciones); if (errorOpciones) { - throw new Error(errorOpciones.error); + throw new Error(MENSAJES_PRODUCTOS.ERROR_PARAMETROS_ACTUALIZACION.mensaje); } await repositorioActualizarOpcion.actualizarOpcion(idVariante, variante.opciones); @@ -125,7 +125,7 @@ exports.actualizarProducto = [ ]); if ((imagenProducto && !urlImagenProducto) || urlImagenVariantes.includes(null)) { - throw new Error('Error al subir imágenes al servidor'); + throw new Error(MENSAJES_PRODUCTOS.ERROR_ENVIAR_IMAGENES_S3.mensaje); } if (imagenProducto) { @@ -141,7 +141,7 @@ exports.actualizarProducto = [ const varianteInfo = varianteIdMap[tempIdVariante]; if (!varianteInfo) { - throw new Error(`Variante con ID temporal ${tempIdVariante} no encontrada`); + throw new Error(MENSAJES_PRODUCTOS.PRODUCTO_NO_ENCONTRADO.mensaje); } await repositorioVarianteImagen.actualizarImagen( @@ -154,18 +154,20 @@ exports.actualizarProducto = [ await Promise.all(imagenesVariantePromises); await conexion.commit(); - return res.status(200).json({ mensaje: 'Producto actualizado correctamente' }); + return res.status(MENSAJES_PRODUCTOS.ACTUALIZACION_EXITOSA.codigo).json({ + mensaje: MENSAJES_PRODUCTOS.ACTUALIZACION_EXITOSA.mensaje, + }); } catch (error) { if (conexion) await conexion.rollback(); let errorMensaje = MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_PRODUCTO; - if (error.message.includes('Error al subir imágenes al servidor')) { + if (error.message.includes(MENSAJES_PRODUCTOS.ERROR_ENVIAR_IMAGENES_S3.mensaje)) { errorMensaje = MENSAJES_PRODUCTOS.ERROR_ENVIAR_IMAGENES_S3; - } else if (error.message.includes('Error al actualizar variante')) { + } else if (error.message.includes(MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_VARIANTE.mensaje)) { errorMensaje = MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_VARIANTE; - } else if (error.message.includes('Error al asociar imagen con variante')) { - errorMensaje = MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_IMAGEN_VARIANTE; + } else if (error.message.includes(MENSAJES_PRODUCTOS.ERROR_CREAR_IMAGEN_VARIANTE.mensaje)) { + errorMensaje = MENSAJES_PRODUCTOS.ERROR_CREAR_IMAGEN_VARIANTE; } return res.status(errorMensaje.codigo).json({ diff --git a/Productos/Datos/Repositorios/repositorioActualizarProducto.js b/Productos/Datos/Repositorios/repositorioActualizarProducto.js index ebea5ae..59ff0fe 100644 --- a/Productos/Datos/Repositorios/repositorioActualizarProducto.js +++ b/Productos/Datos/Repositorios/repositorioActualizarProducto.js @@ -55,7 +55,6 @@ exports.actualizarProducto = async (clienteSeleccionado, producto) => { const idProducto = resultados.insertId; return idProducto; } catch (error) { - console.error('Error al actualizar producto:', error); return []; } finally { if (conexion) conexion.release(); diff --git a/Productos/Datos/Repositorios/repositorioActualizarVariante.js b/Productos/Datos/Repositorios/repositorioActualizarVariante.js index e14be0c..297f3a1 100644 --- a/Productos/Datos/Repositorios/repositorioActualizarVariante.js +++ b/Productos/Datos/Repositorios/repositorioActualizarVariante.js @@ -29,7 +29,6 @@ exports.actualizarVariante = async (idProducto, variante) => { const idVariante = resultados.insertId; return idVariante; } catch (error) { - console.error('Error al actualizar variante:', error); return []; } finally { if (conexion) conexion.release(); diff --git a/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js b/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js index 756424b..d1ab253 100644 --- a/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js +++ b/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js @@ -36,7 +36,6 @@ exports.actualizarVarianteImagen = async ( await conexion.commit(); return resultadoImagen; } catch (error) { - console.error('Error al actualizar o asociar la imagen:', error); await conexion.rollback(); return []; } finally { From 9c7e5e861f075af91a5c6721e650d2afd168a5eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Fri, 6 Jun 2025 04:56:47 -0600 Subject: [PATCH 05/19] =?UTF-8?q?Feat:=20Agregar=20manejo=20de=20errores?= =?UTF-8?q?=20en=20la=20actualizaci=C3=B3n=20de=20productos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Productos/Datos/Repositorios/repositorioActualizarProducto.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Productos/Datos/Repositorios/repositorioActualizarProducto.js b/Productos/Datos/Repositorios/repositorioActualizarProducto.js index 59ff0fe..653fd85 100644 --- a/Productos/Datos/Repositorios/repositorioActualizarProducto.js +++ b/Productos/Datos/Repositorios/repositorioActualizarProducto.js @@ -55,6 +55,7 @@ exports.actualizarProducto = async (clienteSeleccionado, producto) => { const idProducto = resultados.insertId; return idProducto; } catch (error) { + console.error('Error al actualizar el producto:', error); return []; } finally { if (conexion) conexion.release(); From b2fe224fb22d8932a8ebf70e441baa0f11385fb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Fri, 6 Jun 2025 05:22:08 -0600 Subject: [PATCH 06/19] =?UTF-8?q?Feat:=20Agregar=20documentaci=C3=B3n=20Sw?= =?UTF-8?q?agger=20para=20la=20actualizaci=C3=B3n=20de=20productos=20y=20m?= =?UTF-8?q?ejorar=20manejo=20de=20errores=20en=20la=20actualizaci=C3=B3n?= =?UTF-8?q?=20de=20variantes=20e=20im=C3=A1genes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repositorioActualizarProductoImagen.js | 11 +++ .../repositorioActualizarVariante.js | 1 + .../repositorioActualizarVarianteImagen.js | 1 + .../actualizarProducto.routes.js | 93 ++++++++++++++++++- 4 files changed, 104 insertions(+), 2 deletions(-) diff --git a/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js b/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js index 2db9cdd..1f9db25 100644 --- a/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js +++ b/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js @@ -15,7 +15,18 @@ const consultasImagenes = require('@altertex/util/const/consultasImagenes'); * @returns {Promise} El resultado de la actualización de la imagen (incluyendo `affectedRows`) si es exitoso, o un arreglo vacío en caso de error. */ +/** + * + * @param idProducto + * @param idImagen + * @param urlImagenProducto + * @param nombreComun + */ exports.actualizarProductoImagen = async (idProducto, idImagen, urlImagenProducto, nombreComun) => { + /** + * Parámetros para actualizar la imagen en la tabla de imágenes. + * @type {Array} Contiene la URL de la imagen, el nombre común, y el ID de la imagen. + */ const parametrosImagen = [urlImagenProducto, nombreComun, idImagen]; const conexion = await db.getConnection(); diff --git a/Productos/Datos/Repositorios/repositorioActualizarVariante.js b/Productos/Datos/Repositorios/repositorioActualizarVariante.js index 297f3a1..3700628 100644 --- a/Productos/Datos/Repositorios/repositorioActualizarVariante.js +++ b/Productos/Datos/Repositorios/repositorioActualizarVariante.js @@ -29,6 +29,7 @@ exports.actualizarVariante = async (idProducto, variante) => { const idVariante = resultados.insertId; return idVariante; } catch (error) { + console.error('Error al actualizar la variante:', error); return []; } finally { if (conexion) conexion.release(); diff --git a/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js b/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js index d1ab253..6573f76 100644 --- a/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js +++ b/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js @@ -36,6 +36,7 @@ exports.actualizarVarianteImagen = async ( await conexion.commit(); return resultadoImagen; } catch (error) { + console.error('Error al actualizar o asociar la imagen de la variante:', error); await conexion.rollback(); return []; } finally { diff --git a/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js b/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js index 48ee496..b461ea0 100644 --- a/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js +++ b/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js @@ -9,11 +9,100 @@ const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones') const PERMISOS = require('@altertex/util/const/permisos'); const RUTAS = require('@altertex/util/const/rutas'); +/** + * @swagger + * /api/productos/actualizar: + * post: + * summary: Actualizar un producto existente + * tags: [Productos] + * security: + * - ApiKeyAuth: [] + * - BearerAuth: [] + * consumes: + * - application/json + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - idProducto + * - producto + * properties: + * idProducto: + * type: integer + * description: ID del producto a actualizar + * example: 123 + * producto: + * type: object + * description: Información actualizada del producto + * properties: + * nombreComun: + * type: string + * example: Camisa casual actualizada + * descripcion: + * type: string + * example: Camisa de algodón actualizada + * precioCliente: + * type: number + * format: float + * example: 55.99 + * estado: + * type: integer + * example: 1 + * responses: + * 200: + * description: Producto actualizado correctamente + * content: + * application/json: + * schema: + * type: object + * properties: + * mensaje: + * type: string + * example: Producto actualizado correctamente + * 400: + * description: Error en los parámetros proporcionados + * content: + * application/json: + * schema: + * type: object + * properties: + * mensaje: + * type: string + * example: Los parámetros proporcionados no son válidos + * 401: + * description: No autorizado, token inválido o falta de permisos + * content: + * application/json: + * schema: + * type: object + * properties: + * mensaje: + * type: string + * example: No tiene permisos para realizar esta acción + * 500: + * description: Error interno del servidor + * content: + * application/json: + * schema: + * type: object + * properties: + * mensaje: + * type: string + * example: Error al actualizar producto + * error: + * type: string + * example: Detalles del error + */ + ruteador.post( RUTAS.PRODUCTOS.ACTUALIZAR, - revisarApiKey, + revisarApiKey(), autorizarToken, - limitePeticionesDiarias(PERMISOS.ACTUALIZAR_PRODUCTO), + limitePeticionesDiarias, + verificarPermisos(PERMISOS.ACTUALIZAR_PRODUCTO), controlador.actualizarProducto ); From 1524d711cab4bf910930fa487f64b70b899d4643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Fri, 6 Jun 2025 05:23:13 -0600 Subject: [PATCH 07/19] =?UTF-8?q?Refactor:=20Simplificar=20la=20documentac?= =?UTF-8?q?i=C3=B3n=20de=20la=20funci=C3=B3n=20actualizarProductoImagen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repositorios/repositorioActualizarProductoImagen.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js b/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js index 1f9db25..dca8226 100644 --- a/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js +++ b/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js @@ -8,20 +8,13 @@ const consultasImagenes = require('@altertex/util/const/consultasImagenes'); * Esta función realiza dos operaciones en una transacción: * - Actualiza la imagen en la tabla de imágenes. * - Actualiza la relación entre la imagen y el producto correspondiente. + * * @param {number} idProducto - ID del producto al que se asociará la imagen. * @param {number} idImagen - ID de la imagen que se actualizará. * @param {string} urlImagenProducto - Nueva URL o ruta de la imagen del producto almacenada. * @param {string} nombreComun - Nuevo nombre común o descriptivo asociado al producto. * @returns {Promise} El resultado de la actualización de la imagen (incluyendo `affectedRows`) si es exitoso, o un arreglo vacío en caso de error. */ - -/** - * - * @param idProducto - * @param idImagen - * @param urlImagenProducto - * @param nombreComun - */ exports.actualizarProductoImagen = async (idProducto, idImagen, urlImagenProducto, nombreComun) => { /** * Parámetros para actualizar la imagen en la tabla de imágenes. From eea6fd9cc1a598f447ea5656a68b287cc340082a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Fri, 6 Jun 2025 05:24:24 -0600 Subject: [PATCH 08/19] Refactor: Eliminar importaciones innecesarias en consultasImagenes y consultasVariantes --- Utilidades/Constantes/consultasImagenes.js | 2 -- Utilidades/Constantes/consultasVariantes.js | 2 -- 2 files changed, 4 deletions(-) diff --git a/Utilidades/Constantes/consultasImagenes.js b/Utilidades/Constantes/consultasImagenes.js index 16ee6a6..0c3b8f0 100644 --- a/Utilidades/Constantes/consultasImagenes.js +++ b/Utilidades/Constantes/consultasImagenes.js @@ -1,5 +1,3 @@ -const { ACTUALIZAR } = require('./consultasEmpleados'); - module.exports = { CREAR: ` INSERT INTO imagen(urlImagen, tipoImagen, textoAlternativo) diff --git a/Utilidades/Constantes/consultasVariantes.js b/Utilidades/Constantes/consultasVariantes.js index 062e812..b7288c9 100644 --- a/Utilidades/Constantes/consultasVariantes.js +++ b/Utilidades/Constantes/consultasVariantes.js @@ -1,5 +1,3 @@ -const { ACTUALIZAR } = require('./consultasProductos'); - module.exports = { CREAR: ` INSERT INTO variante (idProducto, nombreVariante, descripcion) From b0774d3c3791f90c1ed4ea0360fcefb5a6c42094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Fri, 6 Jun 2025 05:32:22 -0600 Subject: [PATCH 09/19] =?UTF-8?q?Fix:=20Corregir=20la=20importaci=C3=B3n?= =?UTF-8?q?=20del=20controlador=20en=20actualizarProducto.routes.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js b/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js index b461ea0..d195354 100644 --- a/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js +++ b/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js @@ -1,7 +1,7 @@ //RF27 Consulta Lista de Productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF27 const express = require('express'); const ruteador = express.Router(); -const controlador = require('@altertex/pro/ctrl/actualizarProductos.controller'); +const controlador = require('@altertex/pro/ctrl/actualizarProducto.controller'); const revisarApiKey = require('@altertex/util/inter/revisarApiKey'); const autorizarToken = require('@altertex/util/inter/autorizarToken'); const verificarPermisos = require('@altertex/util/inter/verificarPermisos'); From 2029906e55dee7dbb5c81b3742d506386253ebb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Fri, 6 Jun 2025 08:52:08 -0600 Subject: [PATCH 10/19] =?UTF-8?q?Refactor:=20Mejorar=20la=20l=C3=B3gica=20?= =?UTF-8?q?de=20actualizaci=C3=B3n=20de=20productos=20y=20manejo=20de=20er?= =?UTF-8?q?rores=20(necesita=20idCliente=20pero=20creo=20jala)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../actualizarProducto.controller.js | 226 +++++++----------- 1 file changed, 91 insertions(+), 135 deletions(-) diff --git a/Productos/Controladores/actualizarProducto.controller.js b/Productos/Controladores/actualizarProducto.controller.js index 79115cc..47fe39f 100644 --- a/Productos/Controladores/actualizarProducto.controller.js +++ b/Productos/Controladores/actualizarProducto.controller.js @@ -20,162 +20,118 @@ exports.actualizarProducto = [ ]), async (req, res) => { + console.log('Iniciando actualización de producto...'); const idCliente = parseInt(req.user.clienteSeleccionado); - const producto = JSON.parse(req.body.producto); - const variantes = JSON.parse(req.body.variantes); - const mapaImagenes = JSON.parse(req.body.mapaImagenes); - const imagenProducto = req.files.imagenProducto ? req.files.imagenProducto[0] : null; - const imagenesVariante = req.files.imagenesVariante || []; - let conexion = null; + const idProducto = parseInt(req.body.idProducto); - // prettier-ignore - if ( - !idCliente - || !mapaImagenes - || !producto - || !Array.isArray(variantes) - || variantes.length === 0 - || !imagenProducto - || !imagenesVariante - ) { - return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({ - mensaje: MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.mensaje, - }); + // Validar idCliente e idProducto + if (isNaN(idCliente)) { + console.error('El idCliente es inválido:', req.user.clienteSeleccionado); + return res.status(400).json({ mensaje: 'El idCliente es inválido.' }); } - - const errorProducto = validarProducto(producto); - if (errorProducto) { - return res.status(MENSAJES_PRODUCTOS.ERROR_PARAMETROS_ACTUALIZACION.codigo).json({ - mensaje: MENSAJES_PRODUCTOS.ERROR_PARAMETROS_ACTUALIZACION.mensaje, - }); + if (isNaN(idProducto)) { + console.error('El idProducto es inválido:', req.body.idProducto); + return res.status(400).json({ mensaje: 'El idProducto es inválido.' }); } - if (imagenesVariante.length !== mapaImagenes.length) { - return res.status(MENSAJES_PRODUCTOS.LIMITE_OFFSET_INVALIDOS.codigo).json({ - mensaje: MENSAJES_PRODUCTOS.LIMITE_OFFSET_INVALIDOS.mensaje, - }); - } + console.log('idCliente:', idCliente); + console.log('idProducto:', idProducto); + + const producto = req.body.producto || null; + const variantes = req.body.variantes || []; + const mapaImagenes = req.body.mapaImagenes || []; + const imagenProducto = req.files && req.files.imagenProducto ? req.files.imagenProducto[0] : null; + const imagenesVariante = req.files && req.files.imagenesVariante ? req.files.imagenesVariante : []; + let conexion = null; try { + console.log('Obteniendo conexión a la base de datos...'); conexion = await db.getConnection(); await conexion.beginTransaction(); + console.log('Conexión establecida y transacción iniciada.'); - const idProducto = await repositorioActualizarProducto.actualizarProducto( - idCliente, - producto + // Obtener los valores actuales del producto + console.log('Obteniendo valores actuales del producto...'); + const [productoActual] = await conexion.query( + `SELECT * FROM producto WHERE idProducto = ? AND idCliente = ?`, + [idProducto, idCliente] ); - if (!idProducto) { - throw new Error(MENSAJES_PRODUCTOS.PRODUCTO_NO_ENCONTRADO_ACTUALIZACION.mensaje); - } - - const varianteIdMap = {}; - const variantesPromises = variantes.map(async (variante) => { - const errorVariante = validarVariante({ - nombreVariante: variante.nombreVariante, - descripcion: variante.descripcion, - }); - if (errorVariante) { - throw new Error(MENSAJES_PRODUCTOS.ERROR_PARAMETROS_ACTUALIZACION.mensaje); - } - - const idVariante = await repositorioActualizarVariante.actualizarVariante( - idProducto, - variante - ); - if (!idVariante) { - throw new Error(MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_PRODUCTO.mensaje); - } - - varianteIdMap[variante.identificador] = { - id: idVariante, - nombre: variante.nombreVariante, - }; - - const errorOpciones = validarOpciones(variante.opciones); - if (errorOpciones) { - throw new Error(MENSAJES_PRODUCTOS.ERROR_PARAMETROS_ACTUALIZACION.mensaje); - } - - await repositorioActualizarOpcion.actualizarOpcion(idVariante, variante.opciones); - }); - - await Promise.all(variantesPromises); - - const urlImagenProductoPromise = imagenProducto - ? enviarS3({ - Bucket: process.env.AWS_BUCKET_NAME, - Key: `productos/${imagenProducto.originalname}`, - Body: imagenProducto.buffer, - ContentType: imagenProducto.mimetype, - }) - : Promise.resolve(null); - - // prettier-ignore - const urlImagenVariantePromises = imagenesVariante.map((imagenVariante) => - enviarS3({ - Bucket: process.env.AWS_BUCKET_NAME, - Key: `productos/${imagenVariante.originalname}`, - Body: imagenVariante.buffer, - ContentType: imagenVariante.mimetype, - })); - - const [urlImagenProducto, ...urlImagenVariantes] = await Promise.all([ - urlImagenProductoPromise, - ...urlImagenVariantePromises, - ]); - - if ((imagenProducto && !urlImagenProducto) || urlImagenVariantes.includes(null)) { - throw new Error(MENSAJES_PRODUCTOS.ERROR_ENVIAR_IMAGENES_S3.mensaje); + if (productoActual.length === 0) { + throw new Error('El producto no existe o no pertenece al cliente.'); } - - if (imagenProducto) { - await repositorioProductoImagen.actualizarImagen( + const valoresActualesProducto = productoActual[0]; + console.log('Valores actuales del producto:', valoresActualesProducto); + + // Combinar los valores actuales con los nuevos datos enviados + const datosProducto = { + idProveedor: producto?.idProveedor || valoresActualesProducto.idProveedor, + nombreComun: producto?.nombreComun || valoresActualesProducto.nombreComun, + nombreComercial: producto?.nombreComercial || valoresActualesProducto.nombreComercial, + descripcion: producto?.descripcion || valoresActualesProducto.descripcion, + marca: producto?.marca || valoresActualesProducto.marca, + modelo: producto?.modelo || valoresActualesProducto.modelo, + tipoProducto: producto?.tipoProducto || valoresActualesProducto.tipoProducto, + precioPuntos: producto?.precioPuntos || valoresActualesProducto.precioPuntos, + precioCliente: producto?.precioCliente || valoresActualesProducto.precioCliente, + precioVenta: producto?.precioVenta || valoresActualesProducto.precioVenta, + costo: producto?.costo || valoresActualesProducto.costo, + impuesto: producto?.impuesto || valoresActualesProducto.impuesto, + descuento: producto?.descuento || valoresActualesProducto.descuento, + estado: producto?.estado || valoresActualesProducto.estado, + envio: producto?.envio || valoresActualesProducto.envio, + }; + + console.log('Datos combinados del producto para actualizar:', datosProducto); + + // Actualizar producto + console.log('Actualizando producto...'); + await conexion.query( + `UPDATE producto + SET + idProveedor = ?, nombreComun = ?, nombreComercial = ?, descripcion = ?, + marca = ?, modelo = ?, tipoProducto = ?, precioPuntos = ?, precioCliente = ?, + precioVenta = ?, costo = ?, impuesto = ?, descuento = ?, estado = ?, envio = ? + WHERE idProducto = ? AND idCliente = ?`, + [ + datosProducto.idProveedor, + datosProducto.nombreComun, + datosProducto.nombreComercial, + datosProducto.descripcion, + datosProducto.marca, + datosProducto.modelo, + datosProducto.tipoProducto, + datosProducto.precioPuntos, + datosProducto.precioCliente, + datosProducto.precioVenta, + datosProducto.costo, + datosProducto.impuesto, + datosProducto.descuento, + datosProducto.estado, + datosProducto.envio, idProducto, - imagenProducto.originalname, - producto.nombreComun - ); - } - - const imagenesVariantePromises = imagenesVariante.map(async (imagen, index) => { - const { idVariante: tempIdVariante } = mapaImagenes[index]; - const varianteInfo = varianteIdMap[tempIdVariante]; - - if (!varianteInfo) { - throw new Error(MENSAJES_PRODUCTOS.PRODUCTO_NO_ENCONTRADO.mensaje); - } - - await repositorioVarianteImagen.actualizarImagen( - varianteInfo.id, - imagen.originalname, - varianteInfo.nombre - ); - }); - - await Promise.all(imagenesVariantePromises); + idCliente, + ] + ); + console.log('Producto actualizado.'); await conexion.commit(); - return res.status(MENSAJES_PRODUCTOS.ACTUALIZACION_EXITOSA.codigo).json({ - mensaje: MENSAJES_PRODUCTOS.ACTUALIZACION_EXITOSA.mensaje, + console.log('Transacción confirmada.'); + return res.status(200).json({ + mensaje: 'Producto actualizado correctamente.', }); } catch (error) { + console.error('Error durante la actualización:', error.message); if (conexion) await conexion.rollback(); - - let errorMensaje = MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_PRODUCTO; - - if (error.message.includes(MENSAJES_PRODUCTOS.ERROR_ENVIAR_IMAGENES_S3.mensaje)) { - errorMensaje = MENSAJES_PRODUCTOS.ERROR_ENVIAR_IMAGENES_S3; - } else if (error.message.includes(MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_VARIANTE.mensaje)) { - errorMensaje = MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_VARIANTE; - } else if (error.message.includes(MENSAJES_PRODUCTOS.ERROR_CREAR_IMAGEN_VARIANTE.mensaje)) { - errorMensaje = MENSAJES_PRODUCTOS.ERROR_CREAR_IMAGEN_VARIANTE; - } - - return res.status(errorMensaje.codigo).json({ - mensaje: errorMensaje.mensaje, + console.log('Transacción revertida.'); + return res.status(500).json({ + mensaje: 'Error al actualizar el producto.', error: error.message, }); } finally { - if (conexion) conexion.release(); + if (conexion) { + conexion.release(); + console.log('Conexión liberada.'); + } } }, ]; From 2fc353fdf55add6cee2cd6fd2b2ff8dd6a651e6c Mon Sep 17 00:00:00 2001 From: Hiram <147564077+Hiram10tec@users.noreply.github.com> Date: Fri, 6 Jun 2025 20:04:10 -0600 Subject: [PATCH 11/19] Feature actualizar producto --- .../actualizarProducto.controller.js | 260 +++++++++++------- .../repositorioActualizarOpcion.js | 43 --- .../repositorioActualizarProducto.js | 87 ++---- .../repositorioActualizarProductoImagen.js | 45 --- .../repositorioActualizarVariante.js | 37 --- .../repositorioActualizarVarianteImagen.js | 45 --- .../actualizarProducto.routes.js | 177 +++++++++--- Productos/Rutas/indexProductos.routes.js | 1 - Utilidades/Constantes/consultasProductos.js | 38 ++- .../Validaciones/validarProducto.js | 16 +- 10 files changed, 363 insertions(+), 386 deletions(-) delete mode 100644 Productos/Datos/Repositorios/repositorioActualizarOpcion.js delete mode 100644 Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js delete mode 100644 Productos/Datos/Repositorios/repositorioActualizarVariante.js delete mode 100644 Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js diff --git a/Productos/Controladores/actualizarProducto.controller.js b/Productos/Controladores/actualizarProducto.controller.js index 47fe39f..ccbf2c5 100644 --- a/Productos/Controladores/actualizarProducto.controller.js +++ b/Productos/Controladores/actualizarProducto.controller.js @@ -1,137 +1,183 @@ -//RF26 Crea Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF26 +// RF29 Actualizar Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF29 const multer = require('multer'); -const enviarS3 = require('@altertex/util/ser/enviarS3'); -const MENSAJES_PRODUCTOS = require('@altertex/util/const/mensajesProductos'); +const upload = multer({ storage: multer.memoryStorage() }); const validarProducto = require('@altertex/util/vali/validarProducto'); -const validarVariante = require('@altertex/util/vali/validarVariante'); -const validarOpciones = require('@altertex/util/vali/validarOpciones'); const repositorioActualizarProducto = require('@altertex/pro/repos/repositorioActualizarProducto'); +const repositorioCrearOpcion = require('@altertex/pro/repos/repositorioCrearOpcion'); +const repositorioCrearVariante = require('@altertex/pro/repos/repositorioCrearVariante'); const repositorioProductoImagen = require('@altertex/pro/repos/repositorioProductoImagen'); -const repositorioActualizarVariante = require('@altertex/pro/repos/repositorioActualizarVariante'); const repositorioVarianteImagen = require('@altertex/pro/repos/repositorioVarianteImagen'); -const repositorioActualizarOpcion = require('@altertex/pro/repos/repositorioActualizarOpcion'); +const validarVariante = require('@altertex/util/vali/validarVariante'); +const validarOpciones = require('@altertex/util/vali/validarOpciones'); +const enviarS3 = require('@altertex/util/ser/enviarS3'); +const MENSAJES_PRODUCTOS = require('@altertex/util/const/mensajesProductos'); const db = require('@altertex/util/bd/db'); -const upload = multer({ storage: multer.memoryStorage() }); +/** + * Controlador para actualizar un producto existente. + * + * @param {Express.Request} req - Objeto de solicitud HTTP. + * @param {Express.Response} res - Objeto de respuesta HTTP. + * @returns {Promise} Respuesta HTTP con el estado de la operación. + */ exports.actualizarProducto = [ upload.fields([ { name: 'imagenProducto', maxCount: 1 }, - { name: 'imagenesVariante', maxCount: 100 }, + { name: 'imagenesVariante', maxCount: 100 } ]), async (req, res) => { - console.log('Iniciando actualización de producto...'); - const idCliente = parseInt(req.user.clienteSeleccionado); - const idProducto = parseInt(req.body.idProducto); - - // Validar idCliente e idProducto - if (isNaN(idCliente)) { - console.error('El idCliente es inválido:', req.user.clienteSeleccionado); - return res.status(400).json({ mensaje: 'El idCliente es inválido.' }); - } - if (isNaN(idProducto)) { - console.error('El idProducto es inválido:', req.body.idProducto); - return res.status(400).json({ mensaje: 'El idProducto es inválido.' }); - } + let conexion; + + try { + // Extracción y parsing de datos + const { idProducto } = req.body; + const producto = JSON.parse(req.body.producto); + const variantes = JSON.parse(req.body.variantes); + const mapaImagenes = JSON.parse(req.body.mapaImagenes); + const imagenProducto = req.files.imagenProducto ? req.files.imagenProducto[0] : null; + const imagenesVariante = req.files.imagenesVariante || []; - console.log('idCliente:', idCliente); - console.log('idProducto:', idProducto); + // Validaciones iniciales + if (!idProducto || isNaN(parseInt(idProducto)) || !producto) { + return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({ + mensaje: MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.mensaje, + }); + } - const producto = req.body.producto || null; - const variantes = req.body.variantes || []; - const mapaImagenes = req.body.mapaImagenes || []; - const imagenProducto = req.files && req.files.imagenProducto ? req.files.imagenProducto[0] : null; - const imagenesVariante = req.files && req.files.imagenesVariante ? req.files.imagenesVariante : []; - let conexion = null; + // Validación del producto + const productoParaValidar = { ...producto }; + delete productoParaValidar.idProveedor; + const errorValidacion = validarProducto(productoParaValidar); + if (errorValidacion) { + return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({ + mensaje: errorValidacion.error, + }); + } - try { - console.log('Obteniendo conexión a la base de datos...'); + // Iniciar transacción de base de datos conexion = await db.getConnection(); await conexion.beginTransaction(); - console.log('Conexión establecida y transacción iniciada.'); - // Obtener los valores actuales del producto - console.log('Obteniendo valores actuales del producto...'); - const [productoActual] = await conexion.query( - `SELECT * FROM producto WHERE idProducto = ? AND idCliente = ?`, - [idProducto, idCliente] + // Actualizar producto + const actualizado = await repositorioActualizarProducto.actualizarProducto(idProducto, producto); + if (!actualizado) { + await conexion.rollback(); + return res.status(MENSAJES_PRODUCTOS.PRODUCTO_NO_ENCONTRADO_ACTUALIZACION.codigo).json({ + mensaje: MENSAJES_PRODUCTOS.PRODUCTO_NO_ENCONTRADO_ACTUALIZACION.mensaje, + }); + } + + // Procesar variantes + const varianteIdMap = {}; + const variantesPromises = variantes.map(async (variante) => { + // Validar variante + const errorVariante = validarVariante({ + nombreVariante: variante.nombreVariante, + descripcion: variante.descripcion, + }); + if (errorVariante) { + throw new Error(errorVariante.error); + } + + // Crear variante + const idVariante = await repositorioCrearVariante.crearVariante(idProducto, variante); + if (!idVariante) { + throw new Error('Error al crear variante'); + } + + // Mapear ID de variante + varianteIdMap[variante.identificador] = { + id: idVariante, + nombre: variante.nombreVariante, + }; + + // Validar y crear opciones + const errorOpciones = validarOpciones(variante.opciones); + if (errorOpciones) { + throw new Error(errorOpciones.error); + } + + await repositorioCrearOpcion.crearOpcion(idVariante, variante.opciones); + }); + + await Promise.all(variantesPromises); + await conexion.commit(); + conexion.release(); + + // Procesar imágenes en S3 + const urlImagenProductoPromise = imagenProducto + ? enviarS3({ + Bucket: process.env.AWS_BUCKET_NAME, + Key: `productos/${imagenProducto.originalname}`, + Body: imagenProducto.buffer, + ContentType: imagenProducto.mimetype, + }) + : Promise.resolve(null); + + const urlImagenVariantePromises = imagenesVariante.map((imagenVariante) => + enviarS3({ + Bucket: process.env.AWS_BUCKET_NAME, + Key: `productos/${imagenVariante.originalname}`, + Body: imagenVariante.buffer, + ContentType: imagenVariante.mimetype, + }) ); - if (productoActual.length === 0) { - throw new Error('El producto no existe o no pertenece al cliente.'); + + const [urlImagenProducto, ...urlImagenVariantes] = await Promise.all([ + urlImagenProductoPromise, + ...urlImagenVariantePromises, + ]); + + // Verificar que las imágenes se subieron correctamente + if ((imagenProducto && !urlImagenProducto) || urlImagenVariantes.includes(null)) { + throw new Error('Error al subir imágenes al servidor'); } - const valoresActualesProducto = productoActual[0]; - console.log('Valores actuales del producto:', valoresActualesProducto); - - // Combinar los valores actuales con los nuevos datos enviados - const datosProducto = { - idProveedor: producto?.idProveedor || valoresActualesProducto.idProveedor, - nombreComun: producto?.nombreComun || valoresActualesProducto.nombreComun, - nombreComercial: producto?.nombreComercial || valoresActualesProducto.nombreComercial, - descripcion: producto?.descripcion || valoresActualesProducto.descripcion, - marca: producto?.marca || valoresActualesProducto.marca, - modelo: producto?.modelo || valoresActualesProducto.modelo, - tipoProducto: producto?.tipoProducto || valoresActualesProducto.tipoProducto, - precioPuntos: producto?.precioPuntos || valoresActualesProducto.precioPuntos, - precioCliente: producto?.precioCliente || valoresActualesProducto.precioCliente, - precioVenta: producto?.precioVenta || valoresActualesProducto.precioVenta, - costo: producto?.costo || valoresActualesProducto.costo, - impuesto: producto?.impuesto || valoresActualesProducto.impuesto, - descuento: producto?.descuento || valoresActualesProducto.descuento, - estado: producto?.estado || valoresActualesProducto.estado, - envio: producto?.envio || valoresActualesProducto.envio, - }; - - console.log('Datos combinados del producto para actualizar:', datosProducto); - // Actualizar producto - console.log('Actualizando producto...'); - await conexion.query( - `UPDATE producto - SET - idProveedor = ?, nombreComun = ?, nombreComercial = ?, descripcion = ?, - marca = ?, modelo = ?, tipoProducto = ?, precioPuntos = ?, precioCliente = ?, - precioVenta = ?, costo = ?, impuesto = ?, descuento = ?, estado = ?, envio = ? - WHERE idProducto = ? AND idCliente = ?`, - [ - datosProducto.idProveedor, - datosProducto.nombreComun, - datosProducto.nombreComercial, - datosProducto.descripcion, - datosProducto.marca, - datosProducto.modelo, - datosProducto.tipoProducto, - datosProducto.precioPuntos, - datosProducto.precioCliente, - datosProducto.precioVenta, - datosProducto.costo, - datosProducto.impuesto, - datosProducto.descuento, - datosProducto.estado, - datosProducto.envio, + // Guardar imagen del producto en base de datos + if (imagenProducto) { + await repositorioProductoImagen.crearImagen( idProducto, - idCliente, - ] - ); - console.log('Producto actualizado.'); + imagenProducto.originalname, + producto.nombreComun + ); + } - await conexion.commit(); - console.log('Transacción confirmada.'); - return res.status(200).json({ - mensaje: 'Producto actualizado correctamente.', + // Guardar imágenes de variantes en base de datos + const imagenesVariantePromises = imagenesVariante.map(async (imagen, index) => { + const { idVariante: tempIdVariante } = mapaImagenes[index]; + const varianteInfo = varianteIdMap[tempIdVariante]; + + if (!varianteInfo) { + throw new Error(`Variante con ID temporal ${tempIdVariante} no encontrada`); + } + + await repositorioVarianteImagen.crearImagen( + varianteInfo.id, + imagen.originalname, + varianteInfo.nombre + ); }); - } catch (error) { - console.error('Error durante la actualización:', error.message); - if (conexion) await conexion.rollback(); - console.log('Transacción revertida.'); - return res.status(500).json({ - mensaje: 'Error al actualizar el producto.', - error: error.message, + + await Promise.all(imagenesVariantePromises); + + // Respuesta exitosa + return res.status(MENSAJES_PRODUCTOS.ACTUALIZACION_EXITOSA.codigo).json({ + mensaje: MENSAJES_PRODUCTOS.ACTUALIZACION_EXITOSA.mensaje, }); - } finally { + + } catch (error) { + // Manejo de errores if (conexion) { + await conexion.rollback(); conexion.release(); - console.log('Conexión liberada.'); } + + console.error('Error al actualizar producto extendido:', error); + return res.status(MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_PRODUCTO.codigo).json({ + mensaje: MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_PRODUCTO.mensaje, + error: error.message, + }); } - }, -]; + } +]; \ No newline at end of file diff --git a/Productos/Datos/Repositorios/repositorioActualizarOpcion.js b/Productos/Datos/Repositorios/repositorioActualizarOpcion.js deleted file mode 100644 index 5626da0..0000000 --- a/Productos/Datos/Repositorios/repositorioActualizarOpcion.js +++ /dev/null @@ -1,43 +0,0 @@ -//RF29 Actualiza Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF29 -const db = require('@altertex/util/bd/db'); -const consultas = require('@altertex/util/const/consultasOpciones'); - -/** - * Actualiza una o varias opciones relacionadas con una variante. - * - * @async - * @function crearOpcion - * @param {number} idVariante - ID de la variante a la que se le agregarán las opciones. - * @param {Array} opciones - Un arreglo con los objetos de opciones que se desean agregar. - * @returns {Promise} - Una promesa que se resuelve cuando todas las opciones se crean exitosamente. - */ -exports.actualizarOpcion = async (idVariante, opciones) => { - const conexion = await db.getConnection(); - - try { - await conexion.beginTransaction(); - - for (const opcion of opciones) { - const params = [ - idVariante, - opcion.cantidad, - opcion.valorOpcion, - opcion.SKUautomatico, - opcion.SKUcomercial, - opcion.costoAdicional, - opcion.descuento, - opcion.estado, - ]; - - await conexion.query(consultas.ACTUALIZAR, params); - } - - await conexion.commit(); - } catch (error) { - await conexion.rollback(); - console.error('Error al actualizar opciones:', error); - throw error; - } finally { - if (conexion) conexion.release(); - } -}; diff --git a/Productos/Datos/Repositorios/repositorioActualizarProducto.js b/Productos/Datos/Repositorios/repositorioActualizarProducto.js index 653fd85..2c94097 100644 --- a/Productos/Datos/Repositorios/repositorioActualizarProducto.js +++ b/Productos/Datos/Repositorios/repositorioActualizarProducto.js @@ -1,63 +1,36 @@ -//RF29 Actualiza Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF29 -const db = require('@altertex/util/bd/db'); +const correrQuery = require('@altertex/util/ser/correrQuery'); const consultas = require('@altertex/util/const/consultasProductos'); /** - * Actualiza un producto en la base de datos. + * Actualiza un producto existente en la base de datos. * - * Esta función ejecuta una consulta SQL para actualizar un producto en la base de datos, - * utilizando los parámetros proporcionados. Devuelve el ID del producto actualizado - * en caso de éxito, o un array vacío si ocurre algún error durante la operación. - * - * @param {number} clienteSeleccionado - ID del cliente para el cual se está creando el producto. - * @param {object} producto - Objeto que contiene la información del producto. - * @param {number} producto.idProveedor - ID del proveedor asociado al producto. - * @param {string} producto.nombreComun - Nombre común del producto. - * @param {string} producto.nombreComercial - Nombre comercial del producto. - * @param {string} producto.descripcion - Descripción del producto. - * @param {string} producto.marca - Marca del producto. - * @param {string} producto.modelo - Modelo del producto. - * @param {string} producto.tipoProducto - Tipo del producto. - * @param {number} producto.precioPuntos - Precio en puntos del producto. - * @param {number} producto.precioCliente - Precio para el cliente del producto. - * @param {number} producto.precioVenta - Precio de venta del producto. - * @param {number} producto.costo - Costo de producción del producto. - * @param {number} producto.impuesto - Impuesto aplicado al producto. - * @param {number} producto.descuento - Descuento aplicado al producto. - * @param {string} producto.estado - Estado del producto (activo/inactivo). - * @param {boolean} producto.envio - Indica si el producto es apto para envío. - * - * @returns {number|Array} El ID del producto recién creado en caso de éxito, o un array vacío en caso de error. + * @param {number} idProducto - ID del producto a actualizar. + * @param {object} producto - Objeto con la nueva información del producto. + * @returns {Promise} Verdadero si se actualizó correctamente. */ -exports.actualizarProducto = async (clienteSeleccionado, producto) => { - const conexion = await db.getConnection(); - - try { - const [resultados] = await conexion.query(consultas.ACTUALIZAR, [ - clienteSeleccionado, - producto.idProveedor, - producto.nombreComun, - producto.nombreComercial, - producto.descripcion, - producto.marca, - producto.modelo, - producto.tipoProducto, - producto.precioPuntos, - producto.precioCliente, - producto.precioVenta, - producto.costo, - producto.impuesto, - producto.descuento, - producto.estado, - producto.envio, - ]); +exports.actualizarProducto = async (idProducto, producto) => { + const params = [ + producto.nombreComun, + producto.nombreComercial, + producto.descripcion, + producto.marca, + producto.modelo, + producto.tipoProducto, + producto.precioPuntos, + producto.precioCliente, + producto.precioVenta, + producto.costo, + producto.impuesto, + producto.descuento, + producto.estado, + producto.envio, + idProducto, + ]; - const idProducto = resultados.insertId; - return idProducto; - } catch (error) { - console.error('Error al actualizar el producto:', error); - return []; - } finally { - if (conexion) conexion.release(); - } -}; + const resultado = await correrQuery(consultas.ACTUALIZAR, params); + await correrQuery(consultas.ELIMINAR_OPCIONES, [idProducto]); + await correrQuery(consultas.ELIMINAR_VARIANTES, [idProducto]); + await correrQuery(consultas.ELIMINAR_IMAGEN_PRODUCTO, [idProducto]); + await correrQuery(consultas.ELIMINAR_IMAGEN_VARIANTES, [idProducto]); + return resultado.affectedRows > 0; +}; \ No newline at end of file diff --git a/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js b/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js deleted file mode 100644 index dca8226..0000000 --- a/Productos/Datos/Repositorios/repositorioActualizarProductoImagen.js +++ /dev/null @@ -1,45 +0,0 @@ -// RF29 Actualiza Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF29 -const db = require('@altertex/util/bd/db'); -const consultasProductos = require('@altertex/util/const/consultasProductos'); -const consultasImagenes = require('@altertex/util/const/consultasImagenes'); - -/** - * Actualiza la imagen de un producto existente en la base de datos. - * Esta función realiza dos operaciones en una transacción: - * - Actualiza la imagen en la tabla de imágenes. - * - Actualiza la relación entre la imagen y el producto correspondiente. - * - * @param {number} idProducto - ID del producto al que se asociará la imagen. - * @param {number} idImagen - ID de la imagen que se actualizará. - * @param {string} urlImagenProducto - Nueva URL o ruta de la imagen del producto almacenada. - * @param {string} nombreComun - Nuevo nombre común o descriptivo asociado al producto. - * @returns {Promise} El resultado de la actualización de la imagen (incluyendo `affectedRows`) si es exitoso, o un arreglo vacío en caso de error. - */ -exports.actualizarProductoImagen = async (idProducto, idImagen, urlImagenProducto, nombreComun) => { - /** - * Parámetros para actualizar la imagen en la tabla de imágenes. - * @type {Array} Contiene la URL de la imagen, el nombre común, y el ID de la imagen. - */ - const parametrosImagen = [urlImagenProducto, nombreComun, idImagen]; - const conexion = await db.getConnection(); - - try { - await conexion.beginTransaction(); - - // Actualizar la imagen en la tabla de imágenes - const [resultadoImagen] = await conexion.query(consultasImagenes.ACTUALIZAR, parametrosImagen); - - // Actualizar la relación entre la imagen y el producto - const parametrosRelacion = [idImagen, idProducto]; - await conexion.query(consultasProductos.ACTUALIZAR_IMAGEN_PRODUCTO, parametrosRelacion); - - await conexion.commit(); - return resultadoImagen; - } catch (error) { - console.error('Error al actualizar o asociar la imagen:', error); - await conexion.rollback(); - return []; - } finally { - if (conexion) conexion.release(); - } -}; diff --git a/Productos/Datos/Repositorios/repositorioActualizarVariante.js b/Productos/Datos/Repositorios/repositorioActualizarVariante.js deleted file mode 100644 index 3700628..0000000 --- a/Productos/Datos/Repositorios/repositorioActualizarVariante.js +++ /dev/null @@ -1,37 +0,0 @@ -// RF29 Actualiza Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF29 -const db = require('@altertex/util/bd/db'); -const consultas = require('@altertex/util/const/consultasVariantes'); - -/** - * Actualiza una variante para un producto en la base de datos. - * - * Esta función ejecuta una consulta SQL para actualizar una variante asociada a un producto, - * utilizando los parámetros proporcionados. Devuelve el ID de la variante actualizada - * en caso de éxito, o un array vacío si ocurre algún error durante la operación. - * - * @param {number} idProducto - ID del producto al que se le va a agregar la variante. - * @param {object} variante - Objeto que contiene la información de la variante. - * @param {string} variante.nombreVariante - Nombre de la variante (por ejemplo, color, tamaño). - * @param {string} variante.descripcion - Descripción de la variante. - * - * @returns {number|Array} El ID de la variante recién creada en caso de éxito, o un array vacío en caso de error. - */ -exports.actualizarVariante = async (idProducto, variante) => { - const conexion = await db.getConnection(); - - try { - const [resultados] = await conexion.query(consultas.ACTUALIZAR, [ - idProducto, - variante.nombreVariante, - variante.descripcion, - ]); - - const idVariante = resultados.insertId; - return idVariante; - } catch (error) { - console.error('Error al actualizar la variante:', error); - return []; - } finally { - if (conexion) conexion.release(); - } -}; diff --git a/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js b/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js deleted file mode 100644 index 6573f76..0000000 --- a/Productos/Datos/Repositorios/repositorioActualizarVarianteImagen.js +++ /dev/null @@ -1,45 +0,0 @@ -//RF29 Actualizar Producto - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF29 -const db = require('@altertex/util/bd/db'); -const consultasVariantes = require('@altertex/util/const/consultasVariantes'); -const consultasImagenes = require('@altertex/util/const/consultasImagenes'); - -/** - * Actualiza la imagen de una variante existente en la base de datos. - * Esta función realiza dos operaciones en una transacción: - * - Actualiza la imagen en la tabla de imágenes. - * - Actualiza la relación entre la imagen y la variante correspondiente. - * @param {number} idVariante - ID de la variante a la que se asociará la imagen. - * @param {number} idImagen - ID de la imagen que se actualizará. - * @param {string} urlImagenVariante - Nueva URL o ruta de la imagen de la variante almacenada. - * @param {string} nombreVariante - Nuevo nombre de la variante asociado a la imagen. - * @returns {Promise} El resultado de la actualización de la imagen (incluyendo `affectedRows`) si es exitoso, o un arreglo vacío en caso de error. - */ -exports.actualizarVarianteImagen = async ( - idVariante, - idImagen, - urlImagenVariante, - nombreVariante -) => { - const parametrosImagen = [urlImagenVariante, nombreVariante, idImagen]; - const conexion = await db.getConnection(); - - try { - await conexion.beginTransaction(); - - // Actualizar la imagen en la tabla de imágenes - const [resultadoImagen] = await conexion.query(consultasImagenes.ACTUALIZAR, parametrosImagen); - - // Actualizar la relación entre la imagen y la variante - const parametrosRelacion = [idImagen, idVariante]; - await conexion.query(consultasVariantes.ACTUALIZAR_IMAGEN_VARIANTE, parametrosRelacion); - - await conexion.commit(); - return resultadoImagen; - } catch (error) { - console.error('Error al actualizar o asociar la imagen de la variante:', error); - await conexion.rollback(); - return []; - } finally { - if (conexion) conexion.release(); - } -}; diff --git a/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js b/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js index d195354..207fd86 100644 --- a/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js +++ b/Productos/Rutas/RutasIndividuales/actualizarProducto.routes.js @@ -1,4 +1,3 @@ -//RF27 Consulta Lista de Productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF27 const express = require('express'); const ruteador = express.Router(); const controlador = require('@altertex/pro/ctrl/actualizarProducto.controller'); @@ -6,54 +5,64 @@ const revisarApiKey = require('@altertex/util/inter/revisarApiKey'); const autorizarToken = require('@altertex/util/inter/autorizarToken'); const verificarPermisos = require('@altertex/util/inter/verificarPermisos'); const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones'); +const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar'); const PERMISOS = require('@altertex/util/const/permisos'); const RUTAS = require('@altertex/util/const/rutas'); /** * @swagger - * /api/productos/actualizar: + * /productos/actualizar: * post: + * tags: + * - Productos * summary: Actualizar un producto existente - * tags: [Productos] + * description: | + * Permite actualizar un producto existente con sus variantes, opciones e imágenes. + * Requiere autenticación, permisos específicos y está sujeto a límites de peticiones diarias. * security: * - ApiKeyAuth: [] * - BearerAuth: [] - * consumes: - * - application/json * requestBody: * required: true * content: - * application/json: + * multipart/form-data: * schema: * type: object * required: * - idProducto * - producto + * - variantes + * - mapaImagenes * properties: * idProducto: - * type: integer - * description: ID del producto a actualizar - * example: 123 + * type: string + * description: ID único del producto a actualizar + * example: "123" * producto: - * type: object - * description: Información actualizada del producto - * properties: - * nombreComun: - * type: string - * example: Camisa casual actualizada - * descripcion: - * type: string - * example: Camisa de algodón actualizada - * precioCliente: - * type: number - * format: float - * example: 55.99 - * estado: - * type: integer - * example: 1 + * type: string + * description: Objeto JSON stringificado con los datos del producto + * example: '{"nombreComun":"Camiseta Básica","descripcion":"Camiseta 100% algodón","precio":25.99,"categoria":"Ropa","marca":"AlterTex"}' + * variantes: + * type: string + * description: Array JSON stringificado con las variantes del producto + * example: '[{"identificador":"var1","nombreVariante":"Talla M","descripcion":"Talla mediana","opciones":{"color":"azul","talla":"M"}}]' + * mapaImagenes: + * type: string + * description: Array JSON stringificado que mapea imágenes con variantes + * example: '[{"idVariante":"var1","indiceImagen":0}]' + * imagenProducto: + * type: string + * format: binary + * description: Imagen principal del producto (opcional) + * imagenesVariante: + * type: array + * items: + * type: string + * format: binary + * description: Imágenes de las variantes del producto (máximo 100) * responses: * 200: - * description: Producto actualizado correctamente + * description: Producto actualizado exitosamente * content: * application/json: * schema: @@ -61,9 +70,9 @@ const RUTAS = require('@altertex/util/const/rutas'); * properties: * mensaje: * type: string - * example: Producto actualizado correctamente + * example: "Producto actualizado exitosamente" * 400: - * description: Error en los parámetros proporcionados + * description: Parámetros inválidos o error de validación * content: * application/json: * schema: @@ -71,9 +80,19 @@ const RUTAS = require('@altertex/util/const/rutas'); * properties: * mensaje: * type: string - * example: Los parámetros proporcionados no son válidos + * example: "Los parámetros proporcionados son inválidos" * 401: - * description: No autorizado, token inválido o falta de permisos + * description: No autorizado - Token inválido o faltante + * content: + * application/json: + * schema: + * type: object + * properties: + * mensaje: + * type: string + * example: "Token de acceso inválido" + * 403: + * description: Permisos insuficientes * content: * application/json: * schema: @@ -81,7 +100,27 @@ const RUTAS = require('@altertex/util/const/rutas'); * properties: * mensaje: * type: string - * example: No tiene permisos para realizar esta acción + * example: "No tienes permisos para actualizar productos" + * 404: + * description: Producto no encontrado + * content: + * application/json: + * schema: + * type: object + * properties: + * mensaje: + * type: string + * example: "Producto no encontrado para actualización" + * 429: + * description: Límite de peticiones diarias excedido + * content: + * application/json: + * schema: + * type: object + * properties: + * mensaje: + * type: string + * example: "Límite de peticiones diarias excedido" * 500: * description: Error interno del servidor * content: @@ -91,19 +130,89 @@ const RUTAS = require('@altertex/util/const/rutas'); * properties: * mensaje: * type: string - * example: Error al actualizar producto + * example: "Error interno al actualizar el producto" * error: * type: string - * example: Detalles del error + * example: "Descripción detallada del error" + * + * components: + * securitySchemes: + * ApiKeyAuth: + * type: apiKey + * in: header + * name: X-API-Key + * description: API Key requerida para acceder al endpoint + * BearerAuth: + * type: http + * scheme: bearer + * bearerFormat: JWT + * description: Token JWT para autenticación de usuario + * schemas: + * ProductoBase: + * type: object + * properties: + * nombreComun: + * type: string + * description: Nombre común del producto + * example: "Camiseta Básica" + * descripcion: + * type: string + * description: Descripción detallada del producto + * example: "Camiseta 100% algodón, cómoda y duradera" + * precio: + * type: number + * format: float + * description: Precio del producto + * example: 25.99 + * categoria: + * type: string + * description: Categoría del producto + * example: "Ropa" + * marca: + * type: string + * description: Marca del producto + * example: "AlterTex" + * VarianteProducto: + * type: object + * properties: + * identificador: + * type: string + * description: Identificador único temporal de la variante + * example: "var1" + * nombreVariante: + * type: string + * description: Nombre de la variante + * example: "Talla M - Color Azul" + * descripcion: + * type: string + * description: Descripción de la variante + * example: "Talla mediana en color azul" + * opciones: + * type: object + * description: Opciones específicas de la variante + * example: {"color": "azul", "talla": "M"} + * MapaImagen: + * type: object + * properties: + * idVariante: + * type: string + * description: ID temporal de la variante asociada a la imagen + * example: "var1" + * indiceImagen: + * type: integer + * description: Índice de la imagen en el array de imágenes + * example: 0 */ + ruteador.post( RUTAS.PRODUCTOS.ACTUALIZAR, revisarApiKey(), autorizarToken, limitePeticionesDiarias, + validarYSanitizar, verificarPermisos(PERMISOS.ACTUALIZAR_PRODUCTO), controlador.actualizarProducto ); -module.exports = ruteador; +module.exports = ruteador; \ No newline at end of file diff --git a/Productos/Rutas/indexProductos.routes.js b/Productos/Rutas/indexProductos.routes.js index 4e20604..076d273 100644 --- a/Productos/Rutas/indexProductos.routes.js +++ b/Productos/Rutas/indexProductos.routes.js @@ -6,7 +6,6 @@ const rutaCrearProducto = require('@altertex/pro/rutasInd/crearProducto.routes') const rutasLeerProducto = require('@altertex/pro/rutasInd/leerProductos.routes'); const rutasExportarProductos = require('@altertex/pro/rutasInd/exportarProductos.routes'); const rutasActualizarProducto = require('@altertex/pro/rutasInd/actualizarProducto.routes'); - const RUTAS = require('@altertex/util/const/rutas'); //RF27 Consulta Lista de Productos - https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF27 diff --git a/Utilidades/Constantes/consultasProductos.js b/Utilidades/Constantes/consultasProductos.js index 341a216..e3279dd 100644 --- a/Utilidades/Constantes/consultasProductos.js +++ b/Utilidades/Constantes/consultasProductos.js @@ -1,15 +1,32 @@ module.exports = { - ACTUALIZAR: ` - UPDATE producto - SET idProveedor = ?, nombreComun = ?, nombreComercial = ?, descripcion = ?, - marca = ?, modelo = ?, tipoProducto = ?, precioPuntos = ?, precioCliente = ?, - precioVenta = ?, costo = ?, impuesto = ?, descuento = ?, estado = ?, envio = ? - WHERE idProducto = ?; + ACTUALIZAR:` + UPDATE producto + SET nombreComun = ?, nombreComercial = ?, descripcion = ?, + marca = ?, modelo = ?, tipoProducto = ?, precioPuntos = ?, precioCliente = ?, + precioVenta = ?, costo = ?, impuesto = ?, descuento = ?, estado = ?, envio = ? + WHERE idProducto = ?; `, - ACTUALIZAR_IMAGEN_PRODUCTO: ` - UPDATE imagen_producto - SET idImagen = ? - WHERE idProducto = ?; + + ELIMINAR_OPCIONES: ` + DELETE opcion + FROM opcion + INNER JOIN variante ON opcion.idVariante = variante.idVariante + WHERE variante.idProducto = ?; + `, + + ELIMINAR_VARIANTES: ` + DELETE FROM variante + WHERE idProducto = ?; + `, + ELIMINAR_IMAGEN_PRODUCTO: ` + DELETE FROM imagen_producto + WHERE idProducto = ?; + `, + ELIMINAR_IMAGEN_VARIANTES: ` + DELETE imagen_variante + FROM imagen_variante + INNER JOIN variante ON imagen_variante.idVariante = variante.idVariante + WHERE variante.idProducto = ?; `, OBTENER_LISTA: ` SELECT p.idProducto, p.nombreComun, p.precioVenta, p.estado, i.urlImagen @@ -61,6 +78,7 @@ module.exports = { 'descripcion', v.descripcion, 'opciones', (SELECT JSON_ARRAYAGG( JSON_OBJECT( + 'idOpcion', o.idOpcion, 'cantidad', o.cantidad, 'valorOpcion', o.valorOpcion, diff --git a/Utilidades/Intermediarios/Validaciones/validarProducto.js b/Utilidades/Intermediarios/Validaciones/validarProducto.js index 5738d07..b38dcc1 100644 --- a/Utilidades/Intermediarios/Validaciones/validarProducto.js +++ b/Utilidades/Intermediarios/Validaciones/validarProducto.js @@ -46,13 +46,15 @@ */ // prettier-ignore module.exports = (producto) => { - if ( - producto.idProveedor !== null - && (typeof producto.idProveedor !== 'number' - || producto.idProveedor <= 0 - || !Number.isInteger(producto.idProveedor)) - ) { - return { error: 'idProveedor debe ser un número entero positivo o NULL.' }; + if ('idProveedor' in producto) { + if ( + producto.idProveedor !== null + && (typeof producto.idProveedor !== 'number' + || producto.idProveedor <= 0 + || !Number.isInteger(producto.idProveedor)) + ) { + return { error: 'idProveedor debe ser un número entero positivo o NULL.' }; + } } if ( From 32ba180e08055566476bfe6d7a35cb9863107505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Fri, 6 Jun 2025 20:10:48 -0600 Subject: [PATCH 12/19] Feat: Add product description to product queries --- Utilidades/Constantes/consultasProductos.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Utilidades/Constantes/consultasProductos.js b/Utilidades/Constantes/consultasProductos.js index 341a216..c9c97cc 100644 --- a/Utilidades/Constantes/consultasProductos.js +++ b/Utilidades/Constantes/consultasProductos.js @@ -53,6 +53,7 @@ module.exports = { 'descuento', p.descuento, 'estado', p.estado, 'envio', p.envio, + 'descripcion', p.descripcion, 'nombreProveedor', pr.nombreCompania, 'variantes', (SELECT JSON_ARRAYAGG( JSON_OBJECT( From 8c56bc030f0ae7c8e204d9953fa34bcd16e45b01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Mon, 9 Jun 2025 17:45:38 -0600 Subject: [PATCH 13/19] Refactor: ver si hay errores con cosole logs --- .../actualizarProducto.controller.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Productos/Controladores/actualizarProducto.controller.js b/Productos/Controladores/actualizarProducto.controller.js index ccbf2c5..840782e 100644 --- a/Productos/Controladores/actualizarProducto.controller.js +++ b/Productos/Controladores/actualizarProducto.controller.js @@ -23,19 +23,22 @@ const db = require('@altertex/util/bd/db'); exports.actualizarProducto = [ upload.fields([ { name: 'imagenProducto', maxCount: 1 }, - { name: 'imagenesVariante', maxCount: 100 } + { name: 'imagenesVariante', maxCount: 100 }, ]), async (req, res) => { let conexion; - + try { + console.log(req.body); + console.log(req.files); // Extracción y parsing de datos const { idProducto } = req.body; const producto = JSON.parse(req.body.producto); const variantes = JSON.parse(req.body.variantes); const mapaImagenes = JSON.parse(req.body.mapaImagenes); const imagenProducto = req.files.imagenProducto ? req.files.imagenProducto[0] : null; + console.log('imagen producto: ', imagenProducto); const imagenesVariante = req.files.imagenesVariante || []; // Validaciones iniciales @@ -60,7 +63,10 @@ exports.actualizarProducto = [ await conexion.beginTransaction(); // Actualizar producto - const actualizado = await repositorioActualizarProducto.actualizarProducto(idProducto, producto); + const actualizado = await repositorioActualizarProducto.actualizarProducto( + idProducto, + producto + ); if (!actualizado) { await conexion.rollback(); return res.status(MENSAJES_PRODUCTOS.PRODUCTO_NO_ENCONTRADO_ACTUALIZACION.codigo).json({ @@ -165,19 +171,18 @@ exports.actualizarProducto = [ return res.status(MENSAJES_PRODUCTOS.ACTUALIZACION_EXITOSA.codigo).json({ mensaje: MENSAJES_PRODUCTOS.ACTUALIZACION_EXITOSA.mensaje, }); - } catch (error) { // Manejo de errores if (conexion) { await conexion.rollback(); conexion.release(); } - + console.error('Error al actualizar producto extendido:', error); return res.status(MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_PRODUCTO.codigo).json({ mensaje: MENSAJES_PRODUCTOS.ERROR_ACTUALIZAR_PRODUCTO.mensaje, error: error.message, }); } - } -]; \ No newline at end of file + }, +]; From ead432f5664f9e836c2ac3bf848d1390526540c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Thu, 12 Jun 2025 15:26:59 -0600 Subject: [PATCH 14/19] =?UTF-8?q?feat:=20editar=20producto=20sin=20tener?= =?UTF-8?q?=20que=20volver=20a=20subir=20todas=20las=20im=C3=A1genes=20del?= =?UTF-8?q?=20producto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../actualizarProducto.controller.js | 143 ++++++++++-------- ...epositorioActualizarProductoSinImagenes.js | 38 +++++ .../repositorioObtenerImagenesProducto.js | 0 3 files changed, 120 insertions(+), 61 deletions(-) create mode 100644 Productos/Datos/Repositorios/repositorioActualizarProductoSinImagenes.js create mode 100644 Productos/Datos/Repositorios/repositorioObtenerImagenesProducto.js diff --git a/Productos/Controladores/actualizarProducto.controller.js b/Productos/Controladores/actualizarProducto.controller.js index 840782e..a3a3658 100644 --- a/Productos/Controladores/actualizarProducto.controller.js +++ b/Productos/Controladores/actualizarProducto.controller.js @@ -3,10 +3,12 @@ const multer = require('multer'); const upload = multer({ storage: multer.memoryStorage() }); const validarProducto = require('@altertex/util/vali/validarProducto'); const repositorioActualizarProducto = require('@altertex/pro/repos/repositorioActualizarProducto'); +const repositorioActualizarProductoSinImagenes = require('@altertex/pro/repos/repositorioActualizarProductoSinImagenes'); const repositorioCrearOpcion = require('@altertex/pro/repos/repositorioCrearOpcion'); const repositorioCrearVariante = require('@altertex/pro/repos/repositorioCrearVariante'); const repositorioProductoImagen = require('@altertex/pro/repos/repositorioProductoImagen'); const repositorioVarianteImagen = require('@altertex/pro/repos/repositorioVarianteImagen'); +const repositorioObtenerImagenes = require('@altertex/pro/repos/repositorioObtenerImagenesProducto'); const validarVariante = require('@altertex/util/vali/validarVariante'); const validarOpciones = require('@altertex/util/vali/validarOpciones'); const enviarS3 = require('@altertex/util/ser/enviarS3'); @@ -46,9 +48,7 @@ exports.actualizarProducto = [ return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({ mensaje: MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.mensaje, }); - } - - // Validación del producto + } // Validación del producto const productoParaValidar = { ...producto }; delete productoParaValidar.idProveedor; const errorValidacion = validarProducto(productoParaValidar); @@ -58,15 +58,22 @@ exports.actualizarProducto = [ }); } + // Comprobar si hay nuevas imágenes + const tieneNuevasImagenes = + !!imagenProducto || (imagenesVariante && imagenesVariante.length > 0); + // Iniciar transacción de base de datos conexion = await db.getConnection(); await conexion.beginTransaction(); - // Actualizar producto - const actualizado = await repositorioActualizarProducto.actualizarProducto( - idProducto, - producto - ); + // Actualizar producto - elegir el repositorio adecuado según si hay o no nuevas imágenes + // Si no hay imágenes nuevas, usamos el repositorio que no elimina imágenes existentes + const actualizado = tieneNuevasImagenes + ? await repositorioActualizarProducto.actualizarProducto(idProducto, producto) + : await repositorioActualizarProductoSinImagenes.actualizarProductoSinImagenes( + idProducto, + producto + ); if (!actualizado) { await conexion.rollback(); return res.status(MENSAJES_PRODUCTOS.PRODUCTO_NO_ENCONTRADO_ACTUALIZACION.codigo).json({ @@ -109,68 +116,82 @@ exports.actualizarProducto = [ await Promise.all(variantesPromises); await conexion.commit(); - conexion.release(); - - // Procesar imágenes en S3 - const urlImagenProductoPromise = imagenProducto - ? enviarS3({ + conexion.release(); // Procesar imágenes en S3 solo si hay nuevas imágenes + if (tieneNuevasImagenes) { + const urlImagenProductoPromise = imagenProducto + ? enviarS3({ + Bucket: process.env.AWS_BUCKET_NAME, + Key: `productos/${imagenProducto.originalname}`, + Body: imagenProducto.buffer, + ContentType: imagenProducto.mimetype, + }) + : Promise.resolve(null); + + const urlImagenVariantePromises = imagenesVariante.map((imagenVariante) => + enviarS3({ Bucket: process.env.AWS_BUCKET_NAME, - Key: `productos/${imagenProducto.originalname}`, - Body: imagenProducto.buffer, - ContentType: imagenProducto.mimetype, + Key: `productos/${imagenVariante.originalname}`, + Body: imagenVariante.buffer, + ContentType: imagenVariante.mimetype, }) - : Promise.resolve(null); - - const urlImagenVariantePromises = imagenesVariante.map((imagenVariante) => - enviarS3({ - Bucket: process.env.AWS_BUCKET_NAME, - Key: `productos/${imagenVariante.originalname}`, - Body: imagenVariante.buffer, - ContentType: imagenVariante.mimetype, - }) - ); - - const [urlImagenProducto, ...urlImagenVariantes] = await Promise.all([ - urlImagenProductoPromise, - ...urlImagenVariantePromises, - ]); - - // Verificar que las imágenes se subieron correctamente - if ((imagenProducto && !urlImagenProducto) || urlImagenVariantes.includes(null)) { - throw new Error('Error al subir imágenes al servidor'); - } - - // Guardar imagen del producto en base de datos - if (imagenProducto) { - await repositorioProductoImagen.crearImagen( - idProducto, - imagenProducto.originalname, - producto.nombreComun ); - } - - // Guardar imágenes de variantes en base de datos - const imagenesVariantePromises = imagenesVariante.map(async (imagen, index) => { - const { idVariante: tempIdVariante } = mapaImagenes[index]; - const varianteInfo = varianteIdMap[tempIdVariante]; - if (!varianteInfo) { - throw new Error(`Variante con ID temporal ${tempIdVariante} no encontrada`); + const [urlImagenProducto, ...urlImagenVariantes] = await Promise.all([ + urlImagenProductoPromise, + ...urlImagenVariantePromises, + ]); + + // Verificar que las imágenes se subieron correctamente (solo si hay imágenes nuevas) + if ( + (imagenProducto && !urlImagenProducto) || + (imagenesVariante.length > 0 && urlImagenVariantes.includes(null)) + ) { + throw new Error('Error al subir imágenes al servidor'); + } + } // Guardar imágenes solo si hay nuevas + if (tieneNuevasImagenes) { + // Guardar imagen del producto en base de datos + if (imagenProducto) { + await repositorioProductoImagen.crearImagen( + idProducto, + imagenProducto.originalname, + producto.nombreComun + ); } - await repositorioVarianteImagen.crearImagen( - varianteInfo.id, - imagen.originalname, - varianteInfo.nombre - ); - }); + // Guardar imágenes de variantes en base de datos + if (imagenesVariante.length > 0) { + const imagenesVariantePromises = imagenesVariante.map(async (imagen, index) => { + const { idVariante: tempIdVariante } = mapaImagenes[index]; + const varianteInfo = varianteIdMap[tempIdVariante]; - await Promise.all(imagenesVariantePromises); + if (!varianteInfo) { + throw new Error(`Variante con ID temporal ${tempIdVariante} no encontrada`); + } - // Respuesta exitosa - return res.status(MENSAJES_PRODUCTOS.ACTUALIZACION_EXITOSA.codigo).json({ + await repositorioVarianteImagen.crearImagen( + varianteInfo.id, + imagen.originalname, + varianteInfo.nombre + ); + }); + + await Promise.all(imagenesVariantePromises); + } + } // Construir la respuesta de éxito + const respuesta = { mensaje: MENSAJES_PRODUCTOS.ACTUALIZACION_EXITOSA.mensaje, - }); + actualizacionImagenes: tieneNuevasImagenes, + }; + + // Obtener las imágenes actuales del producto solo si se subieron nuevas imágenes + if (tieneNuevasImagenes) { + const imagenes = await repositorioObtenerImagenes.obtenerImagenesProducto(idProducto); + respuesta.imagenes = imagenes; + } + + // Respuesta exitosa + return res.status(MENSAJES_PRODUCTOS.ACTUALIZACION_EXITOSA.codigo).json(respuesta); } catch (error) { // Manejo de errores if (conexion) { diff --git a/Productos/Datos/Repositorios/repositorioActualizarProductoSinImagenes.js b/Productos/Datos/Repositorios/repositorioActualizarProductoSinImagenes.js new file mode 100644 index 0000000..38b8c5f --- /dev/null +++ b/Productos/Datos/Repositorios/repositorioActualizarProductoSinImagenes.js @@ -0,0 +1,38 @@ +const correrQuery = require('@altertex/util/ser/correrQuery'); +const consultas = require('@altertex/util/const/consultasProductos'); + +/** + * Actualiza un producto existente en la base de datos sin afectar las imágenes. + * + * Esta función es una versión modificada de actualizarProducto que no elimina las imágenes existentes, + * permitiendo actualizar solo la información del producto y las variantes/opciones. + * + * @param {number} idProducto - ID del producto a actualizar. + * @param {object} producto - Objeto con la nueva información del producto. + * @returns {Promise} Verdadero si se actualizó correctamente. + */ +exports.actualizarProductoSinImagenes = async (idProducto, producto) => { + const params = [ + producto.nombreComun, + producto.nombreComercial, + producto.descripcion, + producto.marca, + producto.modelo, + producto.tipoProducto, + producto.precioPuntos, + producto.precioCliente, + producto.precioVenta, + producto.costo, + producto.impuesto, + producto.descuento, + producto.estado, + producto.envio, + idProducto, + ]; + + const resultado = await correrQuery(consultas.ACTUALIZAR, params); + // Eliminar opciones y variantes pero no las imágenes + await correrQuery(consultas.ELIMINAR_OPCIONES, [idProducto]); + await correrQuery(consultas.ELIMINAR_VARIANTES, [idProducto]); + return resultado.affectedRows > 0; +}; diff --git a/Productos/Datos/Repositorios/repositorioObtenerImagenesProducto.js b/Productos/Datos/Repositorios/repositorioObtenerImagenesProducto.js new file mode 100644 index 0000000..e69de29 From bf9471f047d38dcee96e84ca8568548de651730e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Thu, 12 Jun 2025 15:27:51 -0600 Subject: [PATCH 15/19] =?UTF-8?q?feat:=20implementar=20funci=C3=B3n=20para?= =?UTF-8?q?=20obtener=20im=C3=A1genes=20de=20productos=20por=20ID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repositorioObtenerImagenesProducto.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Productos/Datos/Repositorios/repositorioObtenerImagenesProducto.js b/Productos/Datos/Repositorios/repositorioObtenerImagenesProducto.js index e69de29..11e5261 100644 --- a/Productos/Datos/Repositorios/repositorioObtenerImagenesProducto.js +++ b/Productos/Datos/Repositorios/repositorioObtenerImagenesProducto.js @@ -0,0 +1,24 @@ +// Repositorio para obtener imágenes de productos +const correrQuery = require('@altertex/util/ser/correrQuery'); +const consultas = require('@altertex/util/const/consultasProductos'); + +/** + * Obtiene todas las imágenes asociadas a un producto específico. + * + * @async + * @function obtenerImagenesProducto + * @param {number|string} idProducto - ID del producto del cual se quieren obtener las imágenes. + * @returns {Promise} Lista de imágenes asociadas al producto. + */ +exports.obtenerImagenesProducto = async (idProducto) => { + try { + // Usar la consulta existente para obtener imágenes por ID + const query = consultas.OBTENER_IMAGENES_POR_IDS.replace('(?)', '?'); + const imagenes = await correrQuery(query, [idProducto]); + + return imagenes || []; + } catch (error) { + console.error('Error al obtener imágenes del producto:', error); + return []; + } +}; From f3a3186a039807edce751b050f66fdfe61c81de1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Thu, 12 Jun 2025 15:38:16 -0600 Subject: [PATCH 16/19] =?UTF-8?q?refactor:=20mejorar=20la=20estructura=20d?= =?UTF-8?q?e=20c=C3=B3digo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controladores/actualizarProducto.controller.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/Productos/Controladores/actualizarProducto.controller.js b/Productos/Controladores/actualizarProducto.controller.js index a3a3658..fa2f290 100644 --- a/Productos/Controladores/actualizarProducto.controller.js +++ b/Productos/Controladores/actualizarProducto.controller.js @@ -56,17 +56,13 @@ exports.actualizarProducto = [ return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({ mensaje: errorValidacion.error, }); - } - - // Comprobar si hay nuevas imágenes + } // Comprobar si hay nuevas imágenes const tieneNuevasImagenes = !!imagenProducto || (imagenesVariante && imagenesVariante.length > 0); // Iniciar transacción de base de datos conexion = await db.getConnection(); - await conexion.beginTransaction(); - - // Actualizar producto - elegir el repositorio adecuado según si hay o no nuevas imágenes + await conexion.beginTransaction(); // Actualizar producto - elegir el repositorio adecuado según si hay o no nuevas imágenes // Si no hay imágenes nuevas, usamos el repositorio que no elimina imágenes existentes const actualizado = tieneNuevasImagenes ? await repositorioActualizarProducto.actualizarProducto(idProducto, producto) @@ -139,9 +135,7 @@ exports.actualizarProducto = [ const [urlImagenProducto, ...urlImagenVariantes] = await Promise.all([ urlImagenProductoPromise, ...urlImagenVariantePromises, - ]); - - // Verificar que las imágenes se subieron correctamente (solo si hay imágenes nuevas) + ]); // Verificar que las imágenes se subieron correctamente (solo si hay imágenes nuevas) if ( (imagenProducto && !urlImagenProducto) || (imagenesVariante.length > 0 && urlImagenVariantes.includes(null)) From 88db0ba23a8e9dd3d3ea265d82e13a6fe7e1f636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Thu, 12 Jun 2025 15:47:59 -0600 Subject: [PATCH 17/19] =?UTF-8?q?refactor:=20mejorar=20la=20legibilidad=20?= =?UTF-8?q?y=20estructura=20del=20c=C3=B3digo=20en=20el=20controlador=20de?= =?UTF-8?q?=20actualizaci=C3=B3n=20de=20productos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../actualizarProducto.controller.js | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Productos/Controladores/actualizarProducto.controller.js b/Productos/Controladores/actualizarProducto.controller.js index fa2f290..3bd7be9 100644 --- a/Productos/Controladores/actualizarProducto.controller.js +++ b/Productos/Controladores/actualizarProducto.controller.js @@ -22,6 +22,7 @@ const db = require('@altertex/util/bd/db'); * @param {Express.Response} res - Objeto de respuesta HTTP. * @returns {Promise} Respuesta HTTP con el estado de la operación. */ +// prettier-ignore exports.actualizarProducto = [ upload.fields([ { name: 'imagenProducto', maxCount: 1 }, @@ -56,20 +57,18 @@ exports.actualizarProducto = [ return res.status(MENSAJES_PRODUCTOS.PARAMETROS_INVALIDOS.codigo).json({ mensaje: errorValidacion.error, }); - } // Comprobar si hay nuevas imágenes - const tieneNuevasImagenes = - !!imagenProducto || (imagenesVariante && imagenesVariante.length > 0); + } // Comprobar si hay nuevas imágenes + const tieneNuevasImagenes = !!imagenProducto + || (imagenesVariante && imagenesVariante.length > 0); // Iniciar transacción de base de datos conexion = await db.getConnection(); - await conexion.beginTransaction(); // Actualizar producto - elegir el repositorio adecuado según si hay o no nuevas imágenes - // Si no hay imágenes nuevas, usamos el repositorio que no elimina imágenes existentes + await conexion.beginTransaction(); + // Actualizar producto - elegir el repositorio adecuado según si hay o no nuevas imágenes + // Si no hay imágenes nuevas, usamos el repositorio que no elimina imágenes existentes const actualizado = tieneNuevasImagenes ? await repositorioActualizarProducto.actualizarProducto(idProducto, producto) - : await repositorioActualizarProductoSinImagenes.actualizarProductoSinImagenes( - idProducto, - producto - ); + : await repositorioActualizarProductoSinImagenes.actualizarProductoSinImagenes(idProducto, producto); if (!actualizado) { await conexion.rollback(); return res.status(MENSAJES_PRODUCTOS.PRODUCTO_NO_ENCONTRADO_ACTUALIZACION.codigo).json({ @@ -135,10 +134,11 @@ exports.actualizarProducto = [ const [urlImagenProducto, ...urlImagenVariantes] = await Promise.all([ urlImagenProductoPromise, ...urlImagenVariantePromises, - ]); // Verificar que las imágenes se subieron correctamente (solo si hay imágenes nuevas) + ]); + // Verificar que las imágenes se subieron correctamente (solo si hay imágenes nuevas) if ( - (imagenProducto && !urlImagenProducto) || - (imagenesVariante.length > 0 && urlImagenVariantes.includes(null)) + (imagenProducto && !urlImagenProducto) + || (imagenesVariante.length > 0 && urlImagenVariantes.includes(null)) ) { throw new Error('Error al subir imágenes al servidor'); } From b9ea417b38cc6c79445b3fb963d43d0e4d882192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Thu, 12 Jun 2025 15:52:00 -0600 Subject: [PATCH 18/19] =?UTF-8?q?refactor:=20simplificar=20la=20carga=20de?= =?UTF-8?q?=20im=C3=A1genes=20en=20el=20controlador=20de=20actualizaci?= =?UTF-8?q?=C3=B3n=20de=20productos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Productos/Controladores/actualizarProducto.controller.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Productos/Controladores/actualizarProducto.controller.js b/Productos/Controladores/actualizarProducto.controller.js index 3bd7be9..0a95cf6 100644 --- a/Productos/Controladores/actualizarProducto.controller.js +++ b/Productos/Controladores/actualizarProducto.controller.js @@ -128,8 +128,7 @@ exports.actualizarProducto = [ Key: `productos/${imagenVariante.originalname}`, Body: imagenVariante.buffer, ContentType: imagenVariante.mimetype, - }) - ); + })); const [urlImagenProducto, ...urlImagenVariantes] = await Promise.all([ urlImagenProductoPromise, From d914535faffbc948d5a493657d50f560eb2921e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Antonio=20Ben=C3=ADtez=20De=20La=20Portilla?= Date: Thu, 12 Jun 2025 17:31:05 -0600 Subject: [PATCH 19/19] refactor: unificar estilo de comillas y mejorar formato en rutas de productos --- .../consultarSistema.routes.js | 17 ++++++++--------- .../Controladores/leerProducto.controller.js | 2 +- .../RutasIndividuales/leerProductos.routes.js | 11 +++++++++-- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Clientes/Rutas/RutasIndividuales/consultarSistema.routes.js b/Clientes/Rutas/RutasIndividuales/consultarSistema.routes.js index 304c0c1..5284953 100644 --- a/Clientes/Rutas/RutasIndividuales/consultarSistema.routes.js +++ b/Clientes/Rutas/RutasIndividuales/consultarSistema.routes.js @@ -1,14 +1,13 @@ -const express = require("express"); +const express = require('express'); const ruteador = express.Router(); -const controlador = require("@altertex/cli/ctrl/consultarSistema.controller"); -const revisarApiKey = require("@altertex/util/inter/revisarApiKey"); -const autorizarToken = require("@altertex/util/inter/autorizarToken"); -const verificarPermisos = require("@altertex/util/inter/verificarPermisos"); +const controlador = require('@altertex/cli/ctrl/consultarSistema.controller'); +const revisarApiKey = require('@altertex/util/inter/revisarApiKey'); +const autorizarToken = require('@altertex/util/inter/autorizarToken'); +const verificarPermisos = require('@altertex/util/inter/verificarPermisos'); const limitePeticionesDiarias = require('@altertex/util/inter/limitePeticiones'); - -const PERMISOS = require("@altertex/util/const/permisos"); -const RUTAS = require("@altertex/util/const/rutas"); +const PERMISOS = require('@altertex/util/const/permisos'); +const RUTAS = require('@altertex/util/const/rutas'); /** * @swagger @@ -63,7 +62,7 @@ ruteador.post( RUTAS.CLIENTES.CONSULTAR_SISTEMA, revisarApiKey(), autorizarToken, - limitePeticionesDiarias, + limitePeticionesDiarias, verificarPermisos(PERMISOS.CONSULTAR_SISTEMA_ADMINISTRATIVO), controlador.consultarSistema ); diff --git a/Productos/Controladores/leerProducto.controller.js b/Productos/Controladores/leerProducto.controller.js index 5303e6f..752bd30 100644 --- a/Productos/Controladores/leerProducto.controller.js +++ b/Productos/Controladores/leerProducto.controller.js @@ -35,4 +35,4 @@ exports.leerProducto = async (req, res) => { } catch (error) { return res.status(MENSAJES.ERROR_LEER_PRODUCTO.codigo).json({ mensaje: error.message }); } -}; \ No newline at end of file +}; diff --git a/Productos/Rutas/RutasIndividuales/leerProductos.routes.js b/Productos/Rutas/RutasIndividuales/leerProductos.routes.js index d11e442..1eeca7a 100644 --- a/Productos/Rutas/RutasIndividuales/leerProductos.routes.js +++ b/Productos/Rutas/RutasIndividuales/leerProductos.routes.js @@ -9,6 +9,13 @@ const validarYSanitizar = require('@altertex/util/inter/validarYSanitizar'); const controlador = require('@altertex/pro/ctrl/leerProducto.controller'); // RF[28] Leer producto - [https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF28] -ruteador.get(RUTAS.PRODUCTOS.LEER, revisarApiKey(), autorizarToken, verificarPermisos(PERMISOS.LEER_PRODUCTO), validarYSanitizar, controlador.leerProducto); +ruteador.get( + RUTAS.PRODUCTOS.LEER, + revisarApiKey(), + autorizarToken, + verificarPermisos(PERMISOS.LEER_PRODUCTO), + validarYSanitizar, + controlador.leerProducto +); -module.exports = ruteador; \ No newline at end of file +module.exports = ruteador;