UNPKG

tuain-bpm-lib

Version:

Servicio de gestión de manejo de procesos de la plataforma Tuain

200 lines (191 loc) 8.58 kB
const { collections: { execution: { processes: processColl }, }, // schemas: { execution: instanceSchemas }, dbQueries: { execution: { process: processQueries }, }, process: { elements: { task: TASK, gateway: GATEWAY, event: EVENT }, eventTypes: { start: START }, }, } = require('../../../config'); const modErrs = { newProcessInstance: { notStartEvent: ['01', 'No se encontró definición del evento de inicialización start'], missingRequiredVariable: ['02', 'Variable requerida para iniciar el proceso no se encuentra'], }, findInstance: { notFound: ['01', 'No se encontró proceso con la información dada'], completed: ['02', 'Instancia del proceso completada'], }, }; async function saveNewInstance(inputUsers, inputGroups, subject = null) { const procCol = this.rwPool.collection(processColl); const processVarNames = Object.keys(this.processDefinition?.variables); const processAttrNames = Object.keys(this.processDefinition?.attributes); const userRoles = this.processDefinition?.userRoles; const groupRoles = Object.keys(this.processDefinition?.groupRoles ?? {}); const newInstanceData = { ecosystem: this._ecosystem, name: this.name, creation: new Date(), subject, completed: false, variables: {}, attributes: {}, users: {}, groups: {}, }; for (let index = 0; index < processVarNames.length; index++) { const processVarName = processVarNames[index]; newInstanceData.variables[processVarName] = null; } for (let index = 0; index < processAttrNames.length; index++) { const processAttrName = processAttrNames[index]; const attribute = this.processDefinition?.attributes?.[processAttrName]; newInstanceData.attributes[processAttrName] = attribute.value; } for (let index = 0; index < userRoles.length; index++) { const roleName = userRoles[index]; newInstanceData.users[roleName] = inputUsers[roleName] ?? null; } for (let index = 0; index < groupRoles.length; index++) { const roleName = groupRoles[index]; newInstanceData.groups[roleName] = inputGroups[roleName] ?? null; } let message = `[BPM] Nueva instancia del proceso ${this.name} con ${JSON.stringify(newInstanceData, null, 2)}`; this.logger.log({ level: 'silly', label: 'processInstance', action: 'saveInstanceDB', message }); const actionResult = await procCol.insertOne(newInstanceData); const procId = actionResult?.insertedId.toString(); if (!procId) { message = `[BPM] No fue posible la creación de una nueva instancia del proceso ${this.name}`; this.logger.log({ level: 'error', label: 'processInstance', action: 'saveInstanceDB', message }); const errorObj = this.errorObj.get(modErrs.newProcessInstance.saveFailure); return [errorObj, null]; } message = `[BPM] Creación de una nueva instancia del proceso ${this.name} con id ${procId}`; this.logger.log({ level: 'info', label: 'processInstance', action: 'saveInstanceDB', message }); return [null, procId]; } async function newInstance(inputVars, users, groups, subject = null) { let message; const startEvent = Object.values(this.processDefinition?.events).find((value) => value.type === START); if (!startEvent) { message = `[BPM] : No se tiene evento inicial para el proceso ${this.name}`; this.logger.log({ level: 'error', label: 'processInstance', action: 'newInstance', message }); const errorObj = this.errMgr.get(modErrs.newProcessInstance.notStartEvent, message); return [errorObj, null]; } const [saveErr, procId] = await this.saveNewInstance(users, groups, subject); if (saveErr) { return [saveErr, null]; } message = `[BPM] : Se dispara evento inicial de la instancia ${procId} del proceso ${this.name}`; this.logger.log({ level: 'info', label: 'processInstance', action: 'newInstance', message }); this.triggerBoundaryEvent(procId, START, inputVars); return [null, procId]; } async function findInstance(inputVars, subject) { const procCol = this.rwPool.collection(processColl); const findInstanceQuery = { ecosystem: this._ecosystem, name: this.name, variables: {}, }; subject && Object.assign(findInstanceQuery, { subject }); const inputVarNames = Object.keys(inputVars); for (let index = 0; index < inputVarNames.length; index++) { const inputVarName = inputVarNames[index]; findInstanceQuery.variables[inputVarName] = inputVars[inputVarName]; } const foundInstance = await procCol.findOne(findInstanceQuery); if (!foundInstance) { const errorObj = this.errMgr.get(modErrs.findInstance.notFound); return [errorObj, null]; } return [null, { procId: foundInstance._id }]; } async function updateBasicInfoInstance(reqData) { const { procId } = reqData; let message; const procCol = this.rwPool.collection(processColl); const procDetail = await procCol.findOne(processQueries.findProcess(procId)); if (!procDetail) { const errorDetail = `Instancia ${procId} del proceso ${this.name} no existe`; const errorObj = this.errMgr.get(modErrs.updateProc.notFound, errorDetail); return [errorObj, null]; } const updateData = { ...reqData }; delete updateData.procId; const actionResult = await procCol.updateOne(...processQueries.updateProc(procId, updateData)); const result = actionResult?.result?.nModified > 0; if (!result) { message = `[BPM] : No se pudo efectuar modificación de la instancia de proceso ${procId}`; this.logger.log({ level: 'silly', label: 'processInstance', action: 'updateProcInstanceDB', message }); } return [null, { result }]; } async function goToNode(procId, name, type, originType, originName, originId) { let message = `[BPM] : Iniciar ${type} ${name} en proceso ${this.name}/${procId} desde ${originName}/${originType}:${originId}`; this.logger.log({ level: 'silly', label: 'processInstance', action: 'goToNode', message }); let newNodeId; const origin = { id: originId, type: originType, name: originName }; const procCol = this.rwPool.collection(processColl); const procDetail = await procCol.findOne(processQueries.findProcess(procId)); if (!procDetail) { message = `[BPM] : Instancia ${procId} del proceso ${this.name} no encontrada`; this.logger.log({ level: 'error', label: 'processInstance', action: 'goToNode', message }); const errorObj = this.errMgr.get(modErrs.findInstance.notFound, message); return [errorObj, null]; } if (procDetail.completed === true) { message = `[BPM] : Instancia ${procId} del proceso ${this.name} ha sido completada`; this.logger.log({ level: 'error', label: 'processInstance', action: 'goToNode', message }); const errorObj = this.errMgr.get(modErrs.findInstance.completed, message); return [errorObj, null]; } if (type === TASK) { const [errorTask, taskId] = await this.startNewTask(procId, name, origin); if (errorTask) { message = `[BPM] : No fue posible iniciar la tarea ${name} desde ${originName} para el proceso ${this.name}:${procId}`; this.logger.log({ level: 'error', label: 'processInstance', action: 'goToNode', message }); return [errorTask, null]; } newNodeId = taskId; } else if (type === GATEWAY) { const [errorGateway, gatewayId] = await this.startNewGateway(procId, name, origin); if (errorGateway) { message = `[BPM] : No fue posible iniciar el gateway ${name} desde ${originName} para el proceso ${this.name}:${procId}`; this.logger.log({ level: 'error', label: 'processInstance', action: 'goToNode', message }); return [errorGateway, null]; } newNodeId = gatewayId; } else if (type === EVENT) { /** Aqui es donde se debe diferenciar un evento de temporizador de cualquier otro evento!!!! */ const [errorTimer, eventId] = await this.triggerEvent(procId, name, {}); if (errorTimer) { message = `[BPM] : No fue posible disparar el evento ${name} desde ${originName} para el proceso ${this.name}:${procId}`; this.logger.log({ level: 'error', label: 'processInstance', action: 'goToNode', message }); return [errorTimer, null]; } newNodeId = eventId; } if (originType === TASK) { this.updateTaskNextNode(procId, originId, newNodeId, type, name); } else if (originType === GATEWAY) { this.updateGatewayNextNode(procId, originId, newNodeId, type, name); } return [null, newNodeId]; } module.exports = { methods: { saveNewInstance, newInstance, findInstance, updateBasicInfoInstance, goToNode, }, errors: modErrs, };