UNPKG

tuain-ecosystem-lib

Version:

Servicio de gestión mensajería instantanea de la plataforma Tuain

1,099 lines (1,043 loc) 60 kB
const { ObjectId } = require('mongodb'); const { dbQueries: { products: productQueries }, collections: { endpoints: endpointsColl, productProccessors: productProccessorsColl, productFamilies: productFamiliesColl, products: productsColl, subproducts: subproductsColl, enabledProducts: enabledProductsColl, }, } = require('../../config'); const PROD_SEARCH_FIELDS = ['name', 'fullname', 'externalCode']; const ENDPOINT_SEARCH_FIELDS = ['name', 'endpointRoot', 'externalCode']; const FAMILY_SEARCH_FIELDS = ['name', 'description', 'nature']; const modErrs = { createProductProccessor: { alreadyExist: ['01', 'El procesador de productos ya existe'], }, findProcessor: { notFound: ['01', 'El procesador de productos no existe'], }, findEndPoint: { notFound: ['01', 'El endpoint de productos no existe'], }, modifyProcessor: { alreadyActive: ['01', 'El procesador de productos ya está activo'], alreadyInactive: ['02', 'El procesador de productos no está activo'], }, createProductFamily: { alreadyExist: ['01', 'La familia de productos ya existe'], }, findFamily: { notFound: ['01', 'La familia de productos no existe'], hasChildren: ['02', 'Familia de productos contiene subproductos'], }, modifyFamily: { alreadyActive: ['01', 'La familia de productos ya está activo'], alreadyInactive: ['02', 'La familia de productos no está activo'], }, createProduct: { alreadyExist: ['01', 'Producto ya existe'], }, findProduct: { notFound: ['01', 'Producto no existe'], hasChildren: ['02', 'Producto contiene subproductos'], }, modifyProduct: { alreadyActive: ['01', 'Producto ya está activo'], alreadyInactive: ['02', 'Producto no está activo'], }, createSubProduct: { alreadyExist: ['01', 'Subproducto ya existe'], invaidCategory: ['02', 'Categoría invalida'], }, findSubProduct: { notFound: ['01', 'Subproducto no existe'], }, modifySubProduct: { alreadyActive: ['01', 'Subproducto ya está activo'], alreadyInactive: ['02', 'Subproducto no está activo'], }, }; class ProductManager { constructor(getDb, logger, errMgr, options) { this.options = options; this.getDb = getDb; this.logger = logger; this.errMgr = errMgr; this.errMgr.addModuleSet('lib-products', modErrs); } async getProcessors(reqData, constraints = null) { const procCol = this.getDb().collection(productProccessorsColl); const procList = await procCol.find(productQueries.findByAttributes(constraints, PROD_SEARCH_FIELDS)); const processors = procList ? await procList.toArray() : null; if (!processors || processors.length < 1) { const errorObj = this.errMgr.get(modErrs.findProcessor.notFound); return [errorObj, null]; } return [null, { processors }]; } async getProcessor(reqData) { const { proccessorId } = reqData; const procCol = this.getDb().collection(productProccessorsColl); const processor = await procCol.findOne(productQueries.findById(proccessorId)); if (!processor) { const errorObj = this.errMgr.get(modErrs.findProcessor.notFound); return [errorObj, null]; } return [null, processor]; } async createProductProccessor(processorData) { const { name } = processorData; const procCol = this.getDb().collection(productProccessorsColl); const procDetail = await procCol.findOne(productQueries.findByName(name)); if (procDetail) { const errorDetail = `Procesador de productos ${name} ya existe`; const errorObj = this.errMgr.get(modErrs.createProductProccessor.alreadyExist, errorDetail); return [errorObj, null]; } const newProcData = { ...processorData, enabled: false, creation: new Date() }; const actionResult = await procCol.insertOne(newProcData); this.logger.debug(`Creación de un nuevo procesador ${newProcData} con resultado ${actionResult?.insertedId}`); return [null, { envId: actionResult?.insertedId }]; } async updateProductProccessor(reqData) { const { productProcesorId } = reqData; const procCol = this.getDb().collection(productProccessorsColl); const procDetail = await procCol.findOne(productQueries.findById(productProcesorId)); if (!procDetail) { const errorDetail = `Procesador con Id ${productProcesorId} no encontrado`; const errorObj = this.errMgr.get(modErrs.findProcessor.notFound, errorDetail); return [errorObj, null]; } const updateData = { ...reqData }; delete updateData.productProcesorId; const actionResult = await procCol.updateOne( productQueries.findById(productProcesorId), productQueries.updateObj(updateData), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Modificación del procesador ${updateData} con resultado ${result}`); return [null, { result }]; } async activateProductProccessor(reqData) { const { productProcesorId } = reqData; const procCol = this.getDb().collection(productProccessorsColl); const procDetail = await procCol.findOne(productQueries.findById(productProcesorId)); if (!procDetail) { const errorDetail = `Procesador con Id ${productProcesorId} no encontrado`; const errorObj = this.errMgr.get(modErrs.findProcessor.notFound, errorDetail); return [errorObj, null]; } if (procDetail.enabled) { const errorDetail = `Procesador con Id ${productProcesorId} actualmente activo`; const errorObj = this.errMgr.get(modErrs.modifyProcessor.alreadyActive, errorDetail); return [errorObj, null]; } const actionResult = await procCol.updateOne( productQueries.findById(productProcesorId), productQueries.updateObj({ enabled: true }), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Activación del procesador ${productProcesorId} con resultado ${result}`); return [null, { result }]; } async inactivateProductProccessor(reqData) { const { productProcesorId } = reqData; const procCol = this.getDb().collection(productProccessorsColl); const procDetail = await procCol.findOne(productQueries.findById(productProcesorId)); if (!procDetail) { const errorDetail = `Procesador con Id ${productProcesorId} no encontrado`; const errorObj = this.errMgr.get(modErrs.findProcessor.notFound, errorDetail); return [errorObj, null]; } if (!procDetail.enabled) { const errorDetail = `Relación con Id ${productProcesorId} actualmente inactivo`; const errorObj = this.errMgr.get(modErrs.modifyProcessor.alreadyInactive, errorDetail); return [errorObj, null]; } const actionResult = await procCol.updateOne( productQueries.findById(productProcesorId), productQueries.updateObj({ enabled: false }), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Inactivación del procesador ${productProcesorId} con resultado ${result}`); return [null, { result }]; } /** * Familias de productos */ async getProductFamilies(reqData) { const { productFamilyIds, productFamilyName } = reqData; const familyCol = this.getDb().collection(productFamiliesColl); let familyDetail; if (productFamilyIds) { familyDetail = await familyCol.find({ _id: { $in: productFamilyIds.map((item) => ObjectId(item)) } }).toArray(); if (!familyDetail) { const errorDetail = `Familia de productos con Id ${productFamilyIds} no encontrada`; const errorObj = this.errMgr.get(modErrs.findFamily.notFound, errorDetail); return [errorObj, null]; } } else if (productFamilyName) { familyDetail = await familyCol.findOne(productQueries.findByName(productFamilyName)); } else { familyDetail = await familyCol.find().toArray(); } return [null, familyDetail]; } async getProductFamily(reqData) { const { productFamilyId } = reqData; const familyCol = this.getDb().collection(productFamiliesColl); const familyDetail = await familyCol.findOne(productQueries.findById(productFamilyId)); if (!familyDetail) { const errorDetail = `Familia de productos con Id ${productFamilyId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findFamily.notFound, errorDetail); return [errorObj, null]; } return [null, familyDetail]; } async createProductFamily(familyData) { const { name } = familyData; const familyCol = this.getDb().collection(productFamiliesColl); const familyDetail = await familyCol.findOne(productQueries.findByName(name)); if (familyDetail) { const errorDetail = `Familia de productos ${name} ya existe`; const errorObj = this.errMgr.get(modErrs.createProductFamily.alreadyExist, errorDetail); return [errorObj, null]; } const newFamilyData = { ...familyData, enabled: false, creation: new Date() }; const actionResult = await familyCol.insertOne(newFamilyData); this.logger.debug(`Creación de una nueva familia de productos ${newFamilyData} con resultado ${actionResult?.insertedId}`); return [null, { productFamilyId: actionResult?.insertedId }]; } async updateProductFamily(reqData) { const { productFamilyId } = reqData; const familyCol = this.getDb().collection(productFamiliesColl); const familyDetail = await familyCol.findOne(productQueries.findById(productFamilyId)); if (!familyDetail) { const errorDetail = `Familia de productos con Id ${productFamilyId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findFamily.notFound, errorDetail); return [errorObj, null]; } const updateData = { ...reqData }; delete updateData.productFamilyId; const actionResult = await familyCol.updateOne( productQueries.findById(productFamilyId), productQueries.updateObj(updateData), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Modificación de la familia ${updateData} con resultado ${result}`); return [null, { result }]; } async activateProductFamily(reqData) { const { productFamilyId } = reqData; const familyCol = this.getDb().collection(productFamiliesColl); const familyDetail = await familyCol.findOne(productQueries.findById(productFamilyId)); if (!familyDetail) { const errorDetail = `Familia de produtos con Id ${productFamilyId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findFamily.notFound, errorDetail); return [errorObj, null]; } if (familyDetail.enabled) { const errorDetail = `Familia de produtos con Id ${productFamilyId} actualmente activa`; const errorObj = this.errMgr.get(modErrs.modifyFamily.alreadyActive, errorDetail); return [errorObj, null]; } const actionResult = await familyCol.updateOne( productQueries.findById(productFamilyId), productQueries.updateObj({ enabled: true }), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Activación de la familia ${productFamilyId} con resultado ${result}`); return [null, { result }]; } async inactivateProductFamily(reqData) { const { productFamilyId } = reqData; const familyCol = this.getDb().collection(productFamiliesColl); const familyDetail = await familyCol.findOne(productQueries.findById(productFamilyId)); if (!familyDetail) { const errorDetail = `Familia de produtos con Id ${productFamilyId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findFamily.notFound, errorDetail); return [errorObj, null]; } if (!familyDetail.enabled) { const errorDetail = `Familia de produtos con Id ${productFamilyId} actualmente inactiva`; const errorObj = this.errMgr.get(modErrs.modifyFamily.alreadyInactive, errorDetail); return [errorObj, null]; } const actionResult = await familyCol.updateOne( productQueries.findById(productFamilyId), productQueries.updateObj({ enabled: false }), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Inactivación de la familia ${productFamilyId} con resultado ${result}`); return [null, { result }]; } async deleteProductFamily(reqData) { const { productFamilyId } = reqData; const familyCol = this.getDb().collection(productFamiliesColl); const familyDetail = await familyCol.findOne(productQueries.findById(productFamilyId)); if (!familyDetail) { const errorDetail = `Familia de produtos con Id ${productFamilyId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findFamily.notFound, errorDetail); return [errorObj, null]; } if (familyDetail.enabled) { const errorDetail = `Familia de produtos con Id ${productFamilyId} actualmente activa`; const errorObj = this.errMgr.get(modErrs.modifyFamily.alreadyActive, errorDetail); return [errorObj, null]; } const productCol = this.getDb().collection(productsColl); const productCount = await productCol.find(productQueries.findProductByFamily(productFamilyId)).count(); if (productCount > 0) { const errorDetail = `Familia de produtos con Id ${productFamilyId} contiene productos`; const errorObj = this.errMgr.get(modErrs.findFamily.hasChildren, errorDetail); return [errorObj, null]; } const actionResult = await familyCol.deleteOne(productQueries.findById(productFamilyId)); this.logger.debug(`Eliminación de la familia ${productFamilyId} con resultado ${actionResult?.result?.n}`); const result = actionResult?.result?.n > 0; return [null, { result }]; } /** * Productos */ async getProducts(reqData, constraints = null) { const { productFamilyId, productIds, productName } = reqData; const findQuery = {}; if (productIds) { findQuery._id = { $in: productIds.map((item) => ObjectId(item)) }; } if (productFamilyId) { findQuery.productFamilyId = ObjectId(productFamilyId); } if (productName) { findQuery.name = productName; } if (constraints) { Object.assign(findQuery, productQueries.findByAttributes(constraints, FAMILY_SEARCH_FIELDS)); } const procCol = this.getDb().collection(productsColl); const products = await procCol.find(findQuery).toArray(); if (!products || products.length < 1) { const errorObj = this.errMgr.get(modErrs.findProduct.notFound); return [errorObj, null]; } return [null, products]; } async getProduct(reqData) { const { productId, name } = reqData; const procCol = this.getDb().collection(productsColl); let productFound; if (name) { productFound = await procCol.aggregate(productQueries.findProductByName(name)).toArray(); } else { productFound = await procCol.aggregate(productQueries.findProduct(productId)).toArray(); } const [product] = productFound ?? []; if (!product) { const errorObj = this.errMgr.get(modErrs.findProcessor.notFound); return [errorObj, null]; } return [null, product]; } async createProduct(productData) { const { productFamilyId, proccessorId, name } = productData; const productCol = this.getDb().collection(productsColl); const productDetailPrms = productCol.findOne(productQueries.findByName(name)); const familyCol = this.getDb().collection(productFamiliesColl); const familyDetailPrms = familyCol.findOne(productQueries.findById(productFamilyId)); const procCol = this.getDb().collection(productProccessorsColl); const procDetailPrms = procCol.findOne(productQueries.findById(proccessorId)); const [productDetail, familyDetail, procDetail] = await Promise.all([productDetailPrms, familyDetailPrms, procDetailPrms]); if (productDetail) { const errorDetail = `Producto ${name} ya existe`; const errorObj = this.errMgr.get(modErrs.createProduct.alreadyExist, errorDetail); return [errorObj, null]; } if (!familyDetail) { const errorDetail = `Familia de productos ${productFamilyId} no existe`; const errorObj = this.errMgr.get(modErrs.findFamily.notFound, errorDetail); return [errorObj, null]; } if (!procDetail) { const errorDetail = `Procesador de productos ${proccessorId} no existe`; const errorObj = this.errMgr.get(modErrs.findProcessor.notFound, errorDetail); return [errorObj, null]; } const newProdData = { ...productData, enabled: false, creation: new Date() }; const actionResult = await productCol.insertOne(newProdData); this.logger.debug(`Creación de un nuevo producto ${newProdData} con resultado ${actionResult?.insertedId}`); return [null, { productId: actionResult?.insertedId }]; } async addProductCategories(reqData) { const { productId, addProductCategories } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await productCol.updateOne( productQueries.findById(productId), productQueries.addCategories(addProductCategories), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Adición de categorías ${addProductCategories} con resultado ${result}`); return [null, { result }]; } async updateProduct(reqData) { const { productId, name, productFamilyId, proccessorId } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } if (name) { const productWithName = await productCol.findOne(productQueries.findByName(name)); if (productWithName && productId !== productWithName._id.toString()) { const errorDetail = `Producto ${name} ya existe`; const errorObj = this.errMgr.get(modErrs.createProduct.alreadyExist, errorDetail); return [errorObj, null]; } } if (productFamilyId) { const familyCol = this.getDb().collection(productFamiliesColl); const familyDetail = await familyCol.findOne(productQueries.findById(productFamilyId)); if (!familyDetail) { const errorDetail = `Familia de productos ${name} no existe`; const errorObj = this.errMgr.get(modErrs.findFamily.notFound, errorDetail); return [errorObj, null]; } } if (proccessorId) { const procCol = this.getDb().collection(productProccessorsColl); const procDetail = await procCol.findOne(productQueries.findById(proccessorId)); if (!procDetail) { const errorDetail = `Procesador de productos ${name} no existe`; const errorObj = this.errMgr.get(modErrs.findProcessor.notFound, errorDetail); return [errorObj, null]; } } const updateData = { ...reqData }; delete updateData.productId; const actionResult = await productCol.updateOne(productQueries.findById(productId), productQueries.updateObj(updateData)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Modificación del producto ${updateData} con resultado ${result}`); return [null, { result }]; } async addProductSendAttribute(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const attributeFind = name ? productDetail.sendAttributes?.find((item) => item.name === name) : null; if (attributeFind) { const removeObject = { name }; await productCol.updateOne(productQueries.findById(productId), productQueries.removeSendAttribute(removeObject)); } const attribute = { ...reqData }; delete attribute.productId; const actionResult = await productCol.updateOne( productQueries.findById(productId), productQueries.addSendAttribute(attribute), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Adición de atributo de envío ${name} a producto ${productId} con resultado ${result}`); return [null, { result }]; } async deleteProductSendAttribute(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await productCol.updateOne( productQueries.findById(productId), productQueries.removeSendAttribute({ name }), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Se remuve el atributo ${name} con resultado ${result}`); return [null, { result }]; } async addProductReceiveAttribute(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const attributeFind = name ? productDetail.receiveAttributes?.find((item) => item.name === name) : null; if (attributeFind) { const removeObject = { name }; await productCol.updateOne(productQueries.findById(productId), productQueries.removeReceiveAttribute(removeObject)); } const attribute = { ...reqData }; delete attribute.productId; const actionResult = await productCol.updateOne( productQueries.findById(productId), productQueries.addReceiveAttribute(attribute), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Adición de atributo de envío ${name} a producto ${productId} con resultado ${result}`); return [null, { result }]; } async deleteProductReceiveAttribute(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await productCol.updateOne( productQueries.findById(productId), productQueries.removeReceiveAttribute({ name }), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Se remuve el atributo ${name} con resultado ${result}`); return [null, { result }]; } async addProductInputVar(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const inputVarFind = productDetail.inputVars?.find((item) => item.name === name); if (inputVarFind) { await productCol.updateOne(productQueries.findById(productId), productQueries.removeInputVar(name)); } const inputVar = { ...reqData }; delete inputVar.productId; const actionResult = await productCol.updateOne(productQueries.findById(productId), productQueries.addInputVar(inputVar)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Adición de inputVar ${name} con resultado ${result}`); return [null, { result }]; } async deleteProductInputVar(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await productCol.updateOne(productQueries.findById(productId), productQueries.removeInputVar(name)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Se remuve el campo de captura ${name} con resultado ${result}`); return [null, { result }]; } async addProductInputVarOption(reqData) { const { productId, name, option } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await productCol.updateOne(...productQueries.addInputVarOption(productId, name, option)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Se remuve el campo de captura ${name} con resultado ${result}`); return [null, { result }]; } async removeProductInputVarOption(reqData) { const { productId, name, value } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await productCol.updateOne(...productQueries.removeInputVarOption(productId, name, value)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Se remuve el campo de captura ${name} con resultado ${result}`); return [null, { result }]; } async addProductOutputVar(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const outputVarFind = productDetail.outputVars?.find((item) => item.name === name); if (outputVarFind) { await productCol.updateOne(productQueries.findById(productId), productQueries.removeOutputVar(name)); } const outputVar = { ...reqData }; delete outputVar.productId; const actionResult = await productCol.updateOne(productQueries.findById(productId), productQueries.addOutputVar(outputVar)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Adición de inputVar ${name} con resultado ${result}`); return [null, { result }]; } async deleteProductOutputVar(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await productCol.updateOne(productQueries.findById(productId), productQueries.removeOutputVar(name)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Se remuve el campo de captura ${name} con resultado ${result}`); return [null, { result }]; } async addProductStage(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const stageFind = productDetail.stages?.find((item) => item.name === name); if (stageFind) { await productCol.updateOne(productQueries.findById(productId), productQueries.removeStage(name)); } const stage = { ...reqData }; delete stage.productId; const actionResult = await productCol.updateOne(productQueries.findById(productId), productQueries.addStage(stage)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Adición de stage ${name} con resultado ${result}`); return [null, { result }]; } async deleteProductStage(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await productCol.updateOne(productQueries.findById(productId), productQueries.removeStage(name)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Se remuve la etapa ${name} con resultado ${result}`); return [null, { result }]; } async addProductVoucherAttr(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const voucherAttributeFind = productDetail.voucherAttributes?.find((item) => item.name === name); if (voucherAttributeFind) { await productCol.updateOne(productQueries.findById(productId), productQueries.removeVoucherAttribute(name)); } const voucherAttribute = { ...reqData }; delete voucherAttribute.productId; const actionResult = await productCol.updateOne( productQueries.findById(productId), productQueries.addVoucherAttribute(voucherAttribute), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Adición de atributo de comprobante ${name} con resultado ${result}`); return [null, { result }]; } async deleteProductVoucherAttr(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await productCol.updateOne( productQueries.findById(productId), productQueries.removeVoucherAttribute(name), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Se remueve el atributo de comprobante ${name} con resultado ${result}`); return [null, { result }]; } async addProductProperty(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const propertyFind = productDetail.properties?.find((item) => item.name === name); if (propertyFind) { await productCol.updateOne(productQueries.findById(productId), productQueries.removeProperty(name)); } const property = { ...reqData }; delete property.productId; const actionResult = await productCol.updateOne(productQueries.findById(productId), productQueries.addProperty(property)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Adición de propiedad de producto ${name} con resultado ${result}`); return [null, { result }]; } async deleteProductProperty(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await productCol.updateOne(productQueries.findById(productId), productQueries.removeProperty(name)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Se remueve la porpiedad de producto ${name} con resultado ${result}`); return [null, { result }]; } async addProducFlow(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const flowFind = productDetail.flows?.find((item) => item.name === name); if (flowFind) { await productCol.updateOne(productQueries.findById(productId), productQueries.removeFlow(name)); } const flow = { ...reqData }; delete flow.productId; const actionResult = await productCol.updateOne(productQueries.findById(productId), productQueries.addFlow(flow)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Adición de flow ${name} con resultado ${result}`); return [null, { result }]; } async deleteProductFlow(reqData) { const { productId, name } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await productCol.updateOne(productQueries.findById(productId), productQueries.removeFlow(name)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Se remueve el flujo ${name} con resultado ${result}`); return [null, { result }]; } async getEndPoints(reqData, constraints = null) { const endPointCol = this.getDb().collection(endpointsColl); const endPointList = await endPointCol.find(productQueries.findByAttributes(constraints, ENDPOINT_SEARCH_FIELDS)); const endPoints = endPointList ? await endPointList.toArray() : null; if (!endPoints || endPoints.length < 1) { const errorObj = this.errMgr.get(modErrs.findEndPoint.notFound); return [errorObj, null]; } return [null, { endPoints }]; } async activateProduct(reqData) { const { productId } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrado`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } if (productDetail.enabled) { const errorDetail = `Producto con Id ${productId} actualmente activo`; const errorObj = this.errMgr.get(modErrs.modifyProduct.alreadyActive, errorDetail); return [errorObj, null]; } const actionResult = await productCol.updateOne( productQueries.findById(productId), productQueries.updateObj({ enabled: true }), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Activación del producto ${productId} con resultado ${result}`); return [null, { result }]; } async inactivateProduct(reqData) { const { productId } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrado`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } if (!productDetail.enabled) { const errorDetail = `Producto con Id ${productId} actualmente inactivo`; const errorObj = this.errMgr.get(modErrs.modifyProduct.alreadyActive, errorDetail); return [errorObj, null]; } const actionResult = await productCol.updateOne( productQueries.findById(productId), productQueries.updateObj({ enabled: false }), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Inactivación del producto ${productId} con resultado ${result}`); return [null, { result }]; } async deleteProduct(reqData) { const { productId } = reqData; const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrado`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } if (productDetail.enabled) { const errorDetail = `Producto con Id ${productId} actualmente activo`; const errorObj = this.errMgr.get(modErrs.modifyProduct.alreadyActive, errorDetail); return [errorObj, null]; } const subprodCol = this.getDb().collection(subproductsColl); const subprodCount = await subprodCol.find(productQueries.findSubProdByProd(productId)).count(); if (subprodCount > 0) { const errorDetail = `Produto con Id ${productId} contiene sub-productos`; const errorObj = this.errMgr.get(modErrs.findProduct.hasChildren, errorDetail); return [errorObj, null]; } const actionResult = await productCol.deleteOne(productQueries.findById(productId)); this.logger.debug(`Eliminación del producto ${productId} con resultado ${actionResult?.result?.n}`); const result = actionResult?.result?.n > 0; return [null, { result }]; } /** * Sub-Productos */ async createSubproduct(subProdData) { const { productId, name, category } = subProdData; const subprodCol = this.getDb().collection(subproductsColl); const subprodDetail = await subprodCol.findOne(productQueries.findByName(name)); if (subprodDetail) { const errorDetail = `Subproducto ${name} ya existe`; const errorObj = this.errMgr.get(modErrs.createSubProduct.alreadyExist, errorDetail); return [errorObj, null]; } const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrado`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const priodCategory = productDetail.categories?.find((ctg) => ctg === category); if (!priodCategory && category && productDetail?.categories?.length > 0) { const errorDetail = `La categoría ${category} no está dentro de las categorías del producto`; const errorObj = this.errMgr.get(modErrs.createSubProduct.invaidCategory, errorDetail); return [errorObj, null]; } const newSubProdData = { ...subProdData, enabled: false, creation: new Date() }; const actionResult = await subprodCol.insertOne(newSubProdData); this.logger.debug(`Creación de un nuevo subproducto ${newSubProdData} con resultado ${actionResult?.insertedId}`); return [null, { subproductId: actionResult?.insertedId }]; } async getSubproducts(reqData) { const { productId, subproductId, subproductIds, subproductName } = reqData; const findQuery = {}; const subprodCol = this.getDb().collection(subproductsColl); if (productId) { const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrado`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } findQuery.productId = productId; } if (subproductName) { findQuery.name = { $regex: subproductName, $options: 'i' }; } if (subproductId) { findQuery._id = ObjectId(subproductId); } if (subproductIds) { const subIds = subproductIds.map((item) => ObjectId(item)); findQuery._id = { $in: subIds }; } const subproducts = await subprodCol.find(findQuery).toArray(); return [null, subproducts]; } async getSubproduct(reqData) { const { productId, subProductId, name } = reqData; const subprodCol = this.getDb().collection(subproductsColl); let subproduct; if (name) { subproduct = await subprodCol.findOne(productQueries.findByName(name)); } else { subproduct = await subprodCol.findOne(productQueries.findById(subProductId)); } if (!subproduct) { const errorDetail = `Subroducto con ${subProductId ?? name} no encontrado`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const prodId = productId || subproduct?.productId; const productCol = this.getDb().collection(productsColl); const [productDetail] = await productCol.aggregate(productQueries.findProduct(prodId)).toArray(); if (!productDetail) { const errorDetail = `Producto con Id ${prodId} no encontrado`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const { processor, productFamilyId } = productDetail; Object.assign(subproduct, { processor, productFamilyId }); return [null, subproduct]; } async updateSubproduct(reqData) { const { subproductId, productId } = reqData; const subprodCol = this.getDb().collection(subproductsColl); const subprodDetail = await subprodCol.findOne(productQueries.findById(subproductId)); if (!subprodDetail) { const errorDetail = `Subproducto con Id ${subproductId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findSubProduct.notFound, errorDetail); return [errorObj, null]; } if (productId) { const productCol = this.getDb().collection(productsColl); const productDetail = await productCol.findOne(productQueries.findById(productId)); if (!productDetail) { const errorDetail = `Producto con Id ${productId} no encontrado`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } } const updateData = { ...reqData }; delete updateData.subproductId; const actionResult = await subprodCol.updateOne(productQueries.findById(subproductId), productQueries.updateObj(updateData)); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Modificación del subproducto ${updateData} con resultado ${result}`); return [null, { result }]; } async addSubProductProperty(reqData) { const { subproductId, name, value } = reqData; const subproductCol = this.getDb().collection(subproductsColl); const subproductDetail = await subproductCol.findOne(productQueries.findById(subproductId)); if (!subproductDetail) { const errorDetail = `Subproducto con Id ${subproductId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await subproductCol.updateOne( productQueries.findById(subproductId), productQueries.addProperty(name, value), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Adición de la propiedad ${name}/${value} a producto ${subproductId} con resultado ${result}`); return [null, { result }]; } async deleteSubProductProperty(reqData) { const { subproductId, name } = reqData; const subproductCol = this.getDb().collection(subproductsColl); const subproductDetail = await subproductCol.findOne(productQueries.findById(subproductId)); if (!subproductDetail) { const errorDetail = `Subproducto con Id ${subproductId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await subproductCol.updateOne( productQueries.findById(subproductId), productQueries.removeProperty(name), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Se remuve la propiedad ${name} con resultado ${result}`); return [null, { result }]; } async addSubProductSendAttribute(reqData) { const { subproductId, name } = reqData; const subproductCol = this.getDb().collection(subproductsColl); const subproductDetail = await subproductCol.findOne(productQueries.findById(subproductId)); if (!subproductDetail) { const errorDetail = `Subproducto con Id ${subproductId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const attributeFind = name ? subproductDetail.sendAttributes?.find((item) => item.name === name) : null; if (attributeFind) { const removeObject = { name }; await subproductCol.updateOne(productQueries.findById(subproductId), productQueries.removeSendAttribute(removeObject)); } const attribute = { ...reqData }; delete attribute.subproductId; const actionResult = await subproductCol.updateOne( productQueries.findById(subproductId), productQueries.addSendAttribute(attribute), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Adición de atributo de envío ${name} a producto ${subproductId} con resultado ${result}`); return [null, { result }]; } async deleteSubProductSendAttribute(reqData) { const { subproductId, name } = reqData; const subproductCol = this.getDb().collection(subproductsColl); const subproductDetail = await subproductCol.findOne(productQueries.findById(subproductId)); if (!subproductDetail) { const errorDetail = `Subproducto con Id ${subproductId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const actionResult = await subproductCol.updateOne( productQueries.findById(subproductId), productQueries.removeSendAttribute({ name }), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Se remuve el atributo ${name} con resultado ${result}`); return [null, { result }]; } async addSubProductReceiveAttribute(reqData) { const { subproductId, name } = reqData; const subproductCol = this.getDb().collection(subproductsColl); const subproductDetail = await subproductCol.findOne(productQueries.findById(subproductId)); if (!subproductDetail) { const errorDetail = `Subproducto con Id ${subproductId} no encontrada`; const errorObj = this.errMgr.get(modErrs.findProduct.notFound, errorDetail); return [errorObj, null]; } const attributeFind = name ? subproductDetail.receiveAttributes?.find((item) => item.name === name) : null; if (attributeFind) { const removeObject = { name }; await subproductCol.updateOne(productQueries.findById(subproductId), productQueries.removeReceiveAttribute(removeObject)); } const attribute = { ...reqData }; delete attribute.subproductId; const actionResult = await subproductCol.updateOne( productQueries.findById(subproductId), productQueries.addReceiveAttribute(attribute), ); const result = actionResult?.result?.nModified > 0; this.logger.debug(`Adición de atributo de envío ${name} a producto ${subproductId} con resultado ${result}`); return [null, { result }]; } async deleteSubProductReceiveAttribute(reqData) { const { subproductId, name } = reqData; const subproductCol = this.getDb().collection(subproductsColl);