|
@@ -8,6 +8,8 @@
|
|
|
* @version
|
|
|
*/
|
|
|
|
|
|
+const math = require('mathjs');
|
|
|
+const standard = require('../const/standard');
|
|
|
const changeSort = {
|
|
|
name: '变更令排序',
|
|
|
hint: '默认的变更令排序,同时对变更令,变更清单进行排序\n' +
|
|
@@ -19,8 +21,9 @@ const changeSort = {
|
|
|
* @param ctx - context常量
|
|
|
* @param data - 全部数据源{Array}
|
|
|
* @param fieldsKey - 计算字段
|
|
|
+ * @param options - 计算设置
|
|
|
*/
|
|
|
- fun: function(ctx, data, fieldsKey) {
|
|
|
+ fun: function(ctx, data, fieldsKey, options) {
|
|
|
if (!data.change) return;
|
|
|
// 变更令排序
|
|
|
data.change.sort(function (a, b) {
|
|
@@ -51,7 +54,7 @@ const gatherGcl = {
|
|
|
' 树结构-层级(level), 树结构-同层排序(order), 树结构-完整路径(full_path),\n' +
|
|
|
' 图册号(drawing_code), 备注(memo), 节点类型(node_type), 总额计量(is_tp)\n' +
|
|
|
'3. 如需汇总"未计入清单章节项",请勾选"章节编号(chapter)"字段\n',
|
|
|
- fun: function (ctx, data, fieldsKey) {
|
|
|
+ fun: function (ctx, data, fieldsKey, options) {
|
|
|
const gatherFields = function(gcl, data, fields) {
|
|
|
for (const f of fields) {
|
|
|
if (data[f]) {
|
|
@@ -124,7 +127,7 @@ const sortGcl = {
|
|
|
'特别的,如有"未计入清单章节项": \n' +
|
|
|
' 1. 默认"未计入清单章节项"排列在最后\n' +
|
|
|
' 2. 如须"未计入清单章节项"排在100章之后,请在清单编号字段后,依次勾选"章节编号(chapter)", "名称(name)"\n',
|
|
|
- fun: function (ctx, data, fieldsKey) {
|
|
|
+ fun: function (ctx, data, fieldsKey, options) {
|
|
|
if (fieldsKey.length !== 1 && fieldsKey.length !== 3) return;
|
|
|
const code = fieldsKey[0].field;
|
|
|
const chapter = fieldsKey.length > 1 ? fieldsKey[1].field : '';
|
|
@@ -161,46 +164,148 @@ const gatherChapter = {
|
|
|
'e.g.2 要对mem_stage_bills_compare汇总,须勾选mem_stage_bills_compare下的"清单编号(b_code)", "树结构-是否子项((is_leaf)"字段\n' +
|
|
|
'结果:\n' +
|
|
|
'汇总结果可参照 清单汇总--章节合计,但是不过滤1000-1300章数据',
|
|
|
- fun: function (ctx, data, fieldsKey) {
|
|
|
- if (!data.tender_info || !data.tender_info.chapter) return;
|
|
|
- if (!fieldsKey && fieldsKey.length < 0) return;
|
|
|
+ defaultSetting: {
|
|
|
+ count: 9,
|
|
|
+ unChapter: {
|
|
|
+ name: '未计入清单章节合计',
|
|
|
+ order: 1,
|
|
|
+ },
|
|
|
+ gclSum: {
|
|
|
+ name: '清单小计',
|
|
|
+ order: 2,
|
|
|
+ },
|
|
|
+ unGcl: {
|
|
|
+ name: '非清单项费用',
|
|
|
+ order: 3,
|
|
|
+ },
|
|
|
+ sum: {
|
|
|
+ name: '合计',
|
|
|
+ order: 4,
|
|
|
+ }
|
|
|
+ },
|
|
|
+ customSetting1: {
|
|
|
+ count: 7,
|
|
|
+ gclSum: {
|
|
|
+ name: '第100章至700章清单合计',
|
|
|
+ order: 1,
|
|
|
+ },
|
|
|
+ custom: [
|
|
|
+ {name: '已包含在清单合计中的材料、工程设备、专业工程暂估价', order: 2},
|
|
|
+ {name: '清单合计减去材料、工程设备、专业工程暂估价(即8-9=10)', order_calc: 'o1-o2', order: 3},
|
|
|
+ {name: '计日工合计', node_type: '计日工', order: 4},
|
|
|
+ {name: '暂列金额(不含计日工总额)(即10×暂列金额比列)', node_type: '暂列金额', order: 5},
|
|
|
+ {name: '投标报价、台账价(8+11+12)=13', order_calc: 'o1+o4+o5', order: 6},
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ _getCalcChapter: function (chapter, options) {
|
|
|
+ const gclChapter = [], otherChapter = [], customChapter = [];
|
|
|
|
|
|
- const getCalcChapter = function (chapter) {
|
|
|
- const gclChapter = [], otherChapter = [];
|
|
|
- let serialNo = 1;
|
|
|
- for (const c of chapter) {
|
|
|
- const cc = { code: c.code, name: c.name, cType: 1 };
|
|
|
- cc.serialNo = serialNo++;
|
|
|
- cc.filter = '^' + c.code.substr(0, c.code.length - 2) + '[0-9]{2}-';
|
|
|
- gclChapter.push(cc);
|
|
|
- }
|
|
|
- gclChapter.push({ name: '未计入章节清单合计', cType: 21, serialNo: serialNo++, });
|
|
|
- otherChapter.push({ name: '清单小计(A)', cType: 11, serialNo: serialNo++ });
|
|
|
- otherChapter.push({ name: '非清单项费用(B)', cType: 31, serialNo: serialNo++ });
|
|
|
- otherChapter.push({ name: '合计(C=A+B)', cType: 41, serialNo: serialNo });
|
|
|
- return [gclChapter, otherChapter];
|
|
|
- };
|
|
|
- const getGclChapter = function (chapter, data) {
|
|
|
- for (const c of chapter) {
|
|
|
- if (c.filter) {
|
|
|
- const reg = new RegExp(c.filter);
|
|
|
- if (reg.test(data.b_code)) {
|
|
|
- return c;
|
|
|
- }
|
|
|
+ let serialNo = 1;
|
|
|
+ for (const c of chapter) {
|
|
|
+ const cc = { code: c.code, name: c.name, cType: 1 };
|
|
|
+ cc.serialNo = serialNo++;
|
|
|
+ cc.filter = '^' + c.code.substr(0, c.code.length - 2) + '[0-9]{2}-';
|
|
|
+ gclChapter.push(cc);
|
|
|
+
|
|
|
+ if (serialNo > options.count) break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (options.unChapter) {
|
|
|
+ gclChapter.push({ name: options.unChapter.name, cType: 21, serialNo: serialNo + options.unChapter.order, order: options.unChapter.order });
|
|
|
+ }
|
|
|
+ if (options.gclSum) {
|
|
|
+ otherChapter.push({ name: options.gclSum.name, cType: 11, serialNo: serialNo + options.gclSum.order, order: options.gclSum.order });
|
|
|
+ }
|
|
|
+ if (options.unGcl) {
|
|
|
+ otherChapter.push({ name: options.unGcl.name, cType: 31, serialNo: serialNo + options.unGcl.order, order: options.unGcl.order });
|
|
|
+ }
|
|
|
+ if (options.sum) {
|
|
|
+ otherChapter.push({ name: options.sum.name , cType: 41, serialNo: serialNo + options.sum.order, order: options.sum.order });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (options.custom && options.custom instanceof Array) {
|
|
|
+ for (const c of options.custom) {
|
|
|
+ const cc = {
|
|
|
+ name: c.name, serialNo: serialNo + c.order,
|
|
|
+ order_calc: c.order_calc,
|
|
|
+ cType: 5, order: c.order,
|
|
|
+ };
|
|
|
+ if (c.node_type && c.node_type !== '') {
|
|
|
+ const nodeType = standard.nodeType.find(function (x) {return x.text === c.node_type});
|
|
|
+ cc.node_type = nodeType.value;
|
|
|
} else {
|
|
|
+ cc.node_type = -1;
|
|
|
+ }
|
|
|
+ customChapter.push(cc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return [gclChapter, otherChapter, customChapter];
|
|
|
+ },
|
|
|
+ _getGclChapter: function (chapter, data) {
|
|
|
+ for (const c of chapter) {
|
|
|
+ if (c.filter) {
|
|
|
+ const reg = new RegExp(c.filter);
|
|
|
+ if (reg.test(data.b_code)) {
|
|
|
return c;
|
|
|
}
|
|
|
+ } else {
|
|
|
+ return c;
|
|
|
}
|
|
|
- };
|
|
|
- const gatherData = function(chapter, data) {
|
|
|
+ }
|
|
|
+ },
|
|
|
+ _checkFilter: function (fullPath, filter) {
|
|
|
+ for (const f of filter) {
|
|
|
+ if (fullPath.indexOf(f + '-') === 0 || fullPath === f) return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ },
|
|
|
+ _orderCalc: function (ctx, chapter, fields) {
|
|
|
+ const orderMatch = new RegExp('o[0-9]+', 'igm');
|
|
|
+ for (const c of chapter) {
|
|
|
+ if (c.order_calc && c.order_calc !== '') {
|
|
|
+ console.log(c.order_calc);
|
|
|
+ const matchs = c.order_calc.match(orderMatch);
|
|
|
+ const calcMatch = [];
|
|
|
+ for (const m of matchs) {
|
|
|
+ const order = m.substring(1, m.length);
|
|
|
+ console.log(order);
|
|
|
+ const orderChapter = chapter.find(function (x) {return x.order == order});
|
|
|
+ console.log(orderChapter);
|
|
|
+ if (orderChapter) {
|
|
|
+ calcMatch.push({match: m, value: orderChapter})
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log(calcMatch);
|
|
|
+ for (const f of fields) {
|
|
|
+ let expr = c.order_calc;
|
|
|
+ for (const m of calcMatch) {
|
|
|
+ expr = expr.replace(m.match, m.value[f] ? m.value[f] : 0);
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ c[f] = ctx.helper.round(math.eval(expr), 6);
|
|
|
+ } catch(err) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fun: function (ctx, data, fieldsKey, options) {
|
|
|
+ if (!data.tender_info || !data.tender_info.chapter) return;
|
|
|
+ if (!fieldsKey && fieldsKey.length < 0) return;
|
|
|
+
|
|
|
+ const calcFields = [];
|
|
|
+ const gatherData = function (chapter, data) {
|
|
|
+ if (!chapter) return;
|
|
|
+
|
|
|
for (const f in data) {
|
|
|
if (data[f] && (f.indexOf('tp') >= 0 || f === 'total_price')) {
|
|
|
chapter[f] = ctx.helper.add(chapter[f], data[f]);
|
|
|
+ if (calcFields.indexOf(f) === -1) calcFields.push(f);
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- const [gclChapter, otherChapter] = getCalcChapter(data.tender_info.chapter);
|
|
|
+ const [gclChapter, otherChapter, customChapter] = this._getCalcChapter(data.tender_info.chapter, options ? options : this.defaultSetting);
|
|
|
const fields = ctx.helper._.map(fieldsKey, 'field');
|
|
|
const needFields = ['b_code', 'is_leaf'];
|
|
|
for (const nf of needFields) {
|
|
@@ -208,24 +313,36 @@ const gatherChapter = {
|
|
|
}
|
|
|
const sourceData = data[fieldsKey[0].table];
|
|
|
if (!sourceData) return;
|
|
|
+ const filter = [];
|
|
|
for (const d of sourceData) {
|
|
|
- if (!d.is_leaf) continue;
|
|
|
+ for (const c of customChapter) {
|
|
|
+ if (c.node_type && c.node_type > 0 && c.node_type === d.node_type) {
|
|
|
+ gatherData(c, d);
|
|
|
+ filter.push(d.full_path);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!d.is_leaf || this._checkFilter(d.full_path, filter)) continue;
|
|
|
|
|
|
for (const c of otherChapter) {
|
|
|
if (c.cType === 41) {
|
|
|
gatherData(c, d);
|
|
|
} else if (c.cType === 31 && (!d.b_code || d.b_code === '')) {
|
|
|
- gatherData(c, d, fields);
|
|
|
+ gatherData(c, d);
|
|
|
} else if (c.cType === 11 && (d.b_code)) {
|
|
|
- gatherData(c, d, fields);
|
|
|
+ gatherData(c, d);
|
|
|
}
|
|
|
}
|
|
|
if (d.b_code) {
|
|
|
- const c = getGclChapter(gclChapter, d);
|
|
|
- gatherData(c, d, fields);
|
|
|
+ const c = this._getGclChapter(gclChapter, d);
|
|
|
+ gatherData(c, d);
|
|
|
}
|
|
|
}
|
|
|
- data[fieldsKey[0].table] = gclChapter.concat(otherChapter);
|
|
|
+ const chapter = gclChapter.concat(otherChapter).concat(customChapter);
|
|
|
+ this._orderCalc(ctx, chapter, calcFields);
|
|
|
+ chapter.sort(function (a, b) {return a.serialNo - b.serialNo});
|
|
|
+
|
|
|
+ data[fieldsKey[0].table] = chapter;
|
|
|
},
|
|
|
};
|
|
|
|