tuain-ecosystem-lib
Version:
Servicio de gestión mensajería instantanea de la plataforma Tuain
1,099 lines (1,043 loc) • 60 kB
JavaScript
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);