'use strict'; /** * * 清单汇总 * * @author Mai * @date * @version */ const mergeChar = ';'; const Ledger = require('./ledger'); const gclGatherModel = class { /** * 构造函数 * * @param {Object} ctx - egg 全局变量 */ constructor(ctx) { this.ctx = ctx; this._ = ctx.helper._; // mainData this.billsTree = new Ledger.billsTree(this.ctx, { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1, keys: ['id', 'tender_id', 'ledger_id'] }); this.pos = new Ledger.pos({ id: 'id', ledgerId: 'lid', order: 'order' }); } /** * 根据node新增工程量清单 * * @param {Object}} node * @returns {Object} */ newGclNode(node) { const gcl = { id: this.gclList.length + 1, b_code: node.b_code, name: node.name, unit: node.unit, unit_price: node.unit_price, leafXmjs: [], }; this.gclList.push(gcl); return gcl; } /** * 获取node对应的工程量清单 * * @param {Object} node * @returns {Object} */ getGclNode(node) { const helper = this.ctx.helper; const gcl = this.gclList.find(function (g) { return g.b_code === node.b_code && (g.name || node.name ? g.name === node.name : true) && (g.unit || node.unit ? g.unit === node.unit : true) && helper.checkZero(helper.sub(g.unit_price, node.unit_price)); }); if (gcl) { return gcl; } else { return this.newGclNode(node); } } /** * 检查 text 是否是Peg * e.g. K123+000(true) Kab+123(false) K123.234+234(false) K12+324.234(true) * * @param text * @returns {*} * @constructor */ CheckPeg(text) { const pegReg = /[a-zA-Z]*[kK][0-9]+[++][0-9]{3}([.][0-9]+)?/; return pegReg.test(text); } /** * 基于node向上查找桩号节点(特别的,对于路基工程等,桩号节点应该在计量单元中) * * @param {Object} node - 清单树节点 */ getPegNode(node) { if (node) { if (this.CheckPeg(node.name)) { return node; } else { const parent = this.billsTree.getParent(node); return parent ? this.getPegNode(parent) : null; } } } /** * 获取节点的第N层父节点 * * @param node - 节点(检索起点) * @param level - 第N层 * @returns {*} */ getNodeByLevel(node, level) { let cur = node; while (cur && cur.level > level) { cur = this.billsTree.getParent(cur); } return cur; } /** * 获取 单位工程 * * @param xmj - 计量单元(最底层项目节) * @returns {string} */ getDwgc(peg, xmj) { if (peg) { return peg.name; } else { const node = this.getNodeByLevel(xmj, 2); return node ? node.name : ''; } } /** * 获取 分部工程 * * @param peg - 桩号节点 * @param xmj - 计量单元(最底层项目节) * @returns {string} */ getFbgc(peg, xmj) { if (peg && peg.id !== xmj.id) { const node = this.getNodeByLevel(xmj, peg.level + 1); return node ? node.name : ''; } else { const node = this.getNodeByLevel(xmj, 3); return node ? node.name : ''; } } /** * 获取 分项工程 * * @param peg - 桩号节点 * @param xmj - 计量单元(最底层项目节) * @returns {string} */ getFxgc (peg, xmj) { if (!peg) { const node = this.getNodeByLevel(xmj, 4); return node ? node.name : ''; } else if (peg.id === xmj.id) { if (xmj.level > 4) { let value = ''; for (let level = 4; level < xmj.level; level++) { const node = this.getNodeByLevel(xmj, level); value = value === '' ? node.name : value + mergeChar + node.name; } return value; } else { return ''; } } else { if (peg.level + 2 < xmj.level) { let value = ''; for (let level = peg.level + 2; level < xmj.level; level++) { const node = this.getNodeByLevel(xmj, level); value = value === '' ? node.name : value + mergeChar + node.name; } return value; } else { return ''; } } } /** * 生成缓存数据(缓存仅为了不用每次都运算分部工程等) * * @param {Object}} leafXmj - 清单树节点 * @returns {Object} 最底层项目节缓存数据 */ newCacheLeafXmj(leafXmj) { const peg = this.getPegNode(leafXmj); const cacheLX = { id: leafXmj.id, code: leafXmj.code, jldy: leafXmj.name, fbgc: this.getFbgc(peg, leafXmj), fxgc: this.getFxgc(peg, leafXmj), dwgc: this.getDwgc(peg, leafXmj), drawing_code: leafXmj.drawing_code, }; this.leafXmjs.push(cacheLX); return cacheLX; } /** * 获取缓存数据(有缓存则直接读取,无则生成缓存) * * @param {Object} leafXmj - 最底层项目节 * @returns {Object} 最底层项目缓存数据 */ getCacheLeafXmj(leafXmj) { const cacheLX = this.leafXmjs.find(lx => { return lx.id === leafXmj.id; }); if (!cacheLX) { return this.newCacheLeafXmj(leafXmj); } else { return cacheLX; } } /** * 汇总工程量清单数据 * * @param {Object} node 最底层工程量清单树节点 * @param {*} leafXmj node所属的最底层项目节 */ loadGatherGclNode(node, leafXmj) { const helper = this.ctx.helper; const gcl = this.getGclNode(node); for (const prop in node) { if (prop === 'quantity' || prop === 'total_price' || prop.indexOf('qty') >= 0 || prop.indexOf('tp') >= 0) { gcl[prop] = this.ctx.helper.add(gcl[prop], node[prop]); } } const cacheLeafXmj = this.getCacheLeafXmj(leafXmj); const posRange = this.pos.getLedgerPos(node.id); const loadLeafXmj = function (detail, calcSource) { const dx = helper._.assign({}, cacheLeafXmj); dx.gcl_id = gcl.id; dx.org_gcl_id = node.id; if (detail.name !== node.name) { dx.bwmx = detail.name; dx.mx_id = detail.id; } if (detail.drawing_code) { dx.drawing_code = detail.drawing_code; } for (const prop in calcSource) { if (prop === 'quantity' || prop.indexOf('qty') > 0) dx[prop] = calcSource[prop]; } gcl.leafXmjs.push(dx); }; if (posRange && posRange.length > 0) { for (const pr of posRange) { loadLeafXmj(pr, pr); } } else { loadLeafXmj(leafXmj, node); } } /** * 递归生成工程量清单汇总数据 * * @param {Array} nodes 清单子节点 * @param {Object} leafXmj 最底层项目节 */ recursiveGatherGclData(nodes, leafXmj) { for (const node of nodes) { if (node.b_code) { if (node.children.length > 0) { this.recursiveGatherGclData(node.children, leafXmj); } else { this.loadGatherGclNode(node, leafXmj); } } else if (node.children.length > 0) { this.recursiveGatherGclData(node.children, node); } } } gatherDealBillsData(deal) { if (deal && deal.length > 0) { for (const node of deal) { node.b_code = node.code; const gcl = this.getGclNode(node); if (!node.quantity || !node.unit_price) continue; gcl.deal_bills_qty = node.quantity; gcl.deal_bills_tp = node.total_price; } } } convertResultData() { this.leafXmjs = []; for (const gcl of this.gclList) { if (gcl.leafXmjs.length === 0) return; for (const lx of gcl.leafXmjs) { this.leafXmjs.push(lx); } } } /** * 汇总 * * @param {Array} bills 清单数据 * @param {Array} pos 计量单元数据 */ gather(bills, pos, deal) { const helper = this.ctx.helper; this.billsTree.loadDatas(bills); this.pos.loadDatas(pos); this.gclList = []; this.leafXmjs = []; this.recursiveGatherGclData(this.billsTree.children, null); this.gatherDealBillsData(deal); this.gclList.sort(function (a, b) { return helper.compareCode(a.b_code, b.b_code); }); this.convertResultData(); return [this.gclList, this.leafXmjs]; } gatherObj(bills, pos, deal) { const helper = this.ctx.helper; this.billsTree = bills; this.pos = pos; this.gclList = []; this.leafXmjs = []; this.recursiveGatherGclData(this.billsTree.children, null); this.gatherDealBillsData(deal); this.gclList.sort(function (a, b) { return helper.compareCode(a.b_code, b.b_code); }); this.convertResultData(); return [this.gclList, this.leafXmjs]; } }; module.exports = { gclGather: gclGatherModel, };