'use strict'; /** * * * @author Mai * @date 2018/4/25 * @version */ const Service = require('egg').Service; const paramConst = require('../const/template_param'); const nodeConst = require('../const/template_node'); module.exports = app => { class Match extends Service { /** * 初始化匹配所需变量 * @param {Array|Object} bills - 导入的清单数据 * @private */ _init(bills) { this.bills = bills instanceof Array ? bills : [bills]; this.fixedBills = this.bills.filter(function (b) { return b.n_id < 100; }); this.nodes = []; this.indexes = []; this.params = []; } /** * 获取指标模板数据 * @param {Number} templateId - 指标模板Id * @returns {Promise} * @private */ async _getTemplateData (templateId) { this.templateNodes = await this.ctx.service.templateNode.getAllDataByCondition({ template_id: templateId }); this.templateIndexes = await this.ctx.service.templateIndex.getAllDataByCondition({ template_id: templateId }); this.templateParams = await this.ctx.service.templateParam.getAllDataByCondition({ template_id: templateId }); } /** * 检查code是否满足匹配规则rule * @param {String} code - 匹配编号 * @param {String} rule - 匹配规则 * @returns {boolean} * @private */ _matchCode(code, rule) { const codeParts = code.split('-'); const ruleParts = rule.split('-'); const numReg = /(^[0-9]+$)/; if (codeParts.length !== ruleParts.length) { return false; } for (let i = 0, iLen = codeParts.length; i < iLen; i++) { if (numReg.test(ruleParts[i]) && ruleParts[i] !== codeParts[i]) { return false; } } return true; } /** * 过滤符合指标节点node匹配规则的清单 * 已经匹配过的清单不再匹配 * * @param {Object} node - 指标节点 * @private */ _filterBills (node) { const self = this; return this.bills.filter(function (b) { if (!b.match_node) { if (node.match_type === nodeConst.matchType.code) { return self._matchCode(b.code, node.match_key); } else { return node.match_key === b.name; } } else { return false; } }) } /** * 根据指标参数取值类别,从清单取值 * * @param {Object} param - 指标参数 * @param {Object} bills - 清单节点 * @returns {number} * @private */ _getNodeBillsValue(param, bills) { switch (param.match_num) { case paramConst.matchNum.quantity: return bills.quantity; case paramConst.matchNum.total_price: return bills.total_price; case paramConst.matchNum.dgn_quantity1: return bills.dgn_quantity1; case paramConst.matchNum.dgn_quantity2: return bills.dgn_quantity2; } } /** * 获取指标参数取值(固定Id匹配) * @param {Object} param - 指标参数 * @returns {*} * @private */ _getFixedIdParamValue(param) { for (const b of this.fixedBills) { if (b.n_id == param.match_key) { return this._getNodeBillsValue(param, b); } } return undefined; } /** * 获取指标参数取值(编号匹配) * @param param * @param nodeBills * @returns {*} * @private */ _getCodeParamValue(param) { for (const b of this.bills) { if (this._matchCode(b.code, param.match_key)) { return this._getNodeBillsValue(param, b); } } return undefined; } /** * 获取指标参数取值 * @param {Object} param - 指标参数 * @param {Object} nodeBills - 指标参数 所属 指标节点,绑定的 清单 * @returns {*} * @private */ _getParamValue(param, nodeBills) { switch (param.match_type) { case paramConst.matchType.fixed_id: return this._getFixedIdParamValue(param); case paramConst.matchType.node_default: return this._getNodeBillsValue(param, nodeBills); case paramConst.matchType.code: return this._getCodeParamValue(param); // to do 匹配属性 default: return undefined; } } /** * 同步指标节点下的全部指标参数 * @param {Number} nodeId * @private */ _syncNodeParam(nodeId, nodeBills) { const nodeParams = this.templateParams.filter(function (p) { return p.node_id === nodeId; }); for (const np of nodeParams) { const newParam = { node_id: nodeId, lib_id: nodeBills.lib_id, param_id: this.params.length + 1, source_id: np.param_id, code: np.code, name: np.name, match_type: np.match_type, match_key: np.match_key, match_num: np.match_num, } newParam.match_value = this._getParamValue(newParam, nodeBills); newParam.calc_value = newParam.match_value; this.params.push(newParam); } } /** * 同步指标节点下的全部指标 * @param {Number} nodeId * @private */ _syncNodeIndex(node) { const nodeIndexes = this.templateIndexes.filter(function (i) { return i.node_id === node.source_id; }); for (const ni of nodeIndexes) { const newIndex = { node_id: node.node_id, lib_id: node.lib_id, index_id: this.indexes.length + 1, source_id: ni.index_id, code: ni.code, name: ni.name, unit1: ni.unit1, unit2: ni.unit2, rule: ni.rule, calc_rule: ni.calc_rule, parse_rule: ni.parse_rule, index_type: ni.index_type, } this.indexes.push(newIndex); } } /** * 匹配指标节点 * @param node * @private */ _matchNode(node) { if (!node) { return; } const matchedBills = this._filterBills(node); for (const mb of matchedBills) { const newNode = { node_id: this.nodes.length + 1, lib_id: mb.lib_id, source_id: node.node_id, code: node.code, name: node.name, match_type: node.match_type, match_key: node.match_key, bills_id: mb.n_id, } this.nodes.push(newNode); this._syncNodeParam(newNode.source_id, mb); this._syncNodeIndex(newNode); mb.match_node = newNode.node_id; } } /** * * @param bills * @returns {Promise} */ async matchBills (bills) { this._init(bills); // 获取指标模板全部数据 await this._getTemplateData(1); // 同步全局指标参数 this._syncNodeParam(0, this.bills[0]); // 遍历模板中所有指标节点,匹配清单 for (const node of this.templateNodes) { this._matchNode(node); } // 计算全部指标节点 const globalParams = this.params.filter(function (p) { return p.node_id === 0; }); for (const node of this.nodes) { const nodeParams = this.params.filter(function (p) { return p.node_id === node.node_id; }); const nodeIndexes = this.indexes.filter(function (i) { return i.node_id === node.node_id; }); this.ctx.service.indexCalc.calculate(nodeIndexes, globalParams, nodeParams); } } }; return Match; }