|
@@ -6,7 +6,8 @@
|
|
|
* 用到费率的规则必须有feeRateID属性,当有该属性时,会自动显示费率值。
|
|
|
*/
|
|
|
|
|
|
-/*let defaultBillTemplate = {
|
|
|
+/* 新版GLD 取消了默认清单模板,所以这里废弃。先留着,预防不时之需。
|
|
|
+let defaultBillTemplate = {
|
|
|
ID: 15,
|
|
|
name: "清单公式",
|
|
|
calcItems: [
|
|
@@ -430,26 +431,74 @@ let treeNodeTools = {
|
|
|
return nodes;
|
|
|
},
|
|
|
|
|
|
- isRation: function(treeNode){
|
|
|
- return treeNode.sourceType === ModuleNames.ration && treeNode.data.type === rationType.ration;
|
|
|
+ isBill: function(treeNode){
|
|
|
+ return treeNode.sourceType === ModuleNames.bills;
|
|
|
},
|
|
|
-
|
|
|
isLeafBill: function(treeNode){
|
|
|
- return treeNode.sourceType === projectObj.project.Bills.getSourceType() &&
|
|
|
+ return treeNode.sourceType === ModuleNames.bills &&
|
|
|
treeNode.source.children &&
|
|
|
treeNode.source.children.length === 0;
|
|
|
},
|
|
|
-
|
|
|
isNullBill: function (treeNode) {
|
|
|
return this.isLeafBill(treeNode) && (treeNode.children.length === 0) && (!treeNode.data.calcBase);
|
|
|
},
|
|
|
|
|
|
+ isRationCategory: function(treeNode){
|
|
|
+ return treeNode.sourceType === ModuleNames.ration;
|
|
|
+ },
|
|
|
+ isRation: function(treeNode){
|
|
|
+ return treeNode.sourceType === ModuleNames.ration && treeNode.data.type === rationType.ration;
|
|
|
+ },
|
|
|
isVolumePrice: function (treeNode) {
|
|
|
return treeNode.sourceType === ModuleNames.ration && treeNode.data.type === rationType.volumePrice;
|
|
|
},
|
|
|
-
|
|
|
isGljRation: function (treeNode) {
|
|
|
return treeNode.sourceType === ModuleNames.ration && treeNode.data.type === rationType.gljRation;
|
|
|
+ },
|
|
|
+
|
|
|
+ initFeeField(treeNode, fieldName){
|
|
|
+ if (!treeNode.data.fees) {
|
|
|
+ treeNode.data.fees = [];
|
|
|
+ treeNode.data.feesIndex = {};
|
|
|
+ };
|
|
|
+ if (!treeNode.data.feesIndex[fieldName]) {
|
|
|
+ let fee = {
|
|
|
+ 'fieldName': fieldName,
|
|
|
+ 'unitFee': 0,
|
|
|
+ 'totalFee': 0,
|
|
|
+ 'tenderUnitFee': 0,
|
|
|
+ 'tenderTotalFee': 0
|
|
|
+ };
|
|
|
+ treeNode.data.fees.push(fee);
|
|
|
+ treeNode.data.feesIndex[fieldName] = fee;
|
|
|
+ };
|
|
|
+ },
|
|
|
+
|
|
|
+ getCalcType(treeNode) {
|
|
|
+ if (this.isRationCategory(treeNode)){
|
|
|
+ return treeNodeCalcType.ctRationCalcProgram;
|
|
|
+ }
|
|
|
+ else if (this.isNullBill(treeNode)){
|
|
|
+ return treeNodeCalcType.ctCommonUnitFee;
|
|
|
+ }
|
|
|
+ else if (this.isLeafBill(treeNode)) {
|
|
|
+ if (treeNode.children && treeNode.children.length > 0){
|
|
|
+ // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算。(汇总清单所有定额的工料机)
|
|
|
+ if (projectObj.project.property.billsCalcMode === leafBillGetFeeType.billsPrice)
|
|
|
+ return treeNodeCalcType.ctBillCalcProgram;
|
|
|
+ else // 前三种计算模式下的叶子清单:汇总定额的计算程序的费用类别
|
|
|
+ return treeNodeCalcType.ctGatherRationsFees;
|
|
|
+ }
|
|
|
+ else{ // 公式计算
|
|
|
+ return treeNodeCalcType.ctCalcBaseValue;
|
|
|
+ };
|
|
|
+ }
|
|
|
+ else if (this.isBill(treeNode)) { // 父清单:汇总子清单的费用类别
|
|
|
+ return treeNodeCalcType.ctGatherBillsFees;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return treeNodeCalcType.ctRationCalcProgram;
|
|
|
+ };
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -463,18 +512,18 @@ class CalcProgram {
|
|
|
|
|
|
getSourceType () {
|
|
|
return ModuleNames.calc_program;
|
|
|
- };
|
|
|
+ }; // 兼容Project框架方法
|
|
|
|
|
|
loadData (datas) {
|
|
|
this.datas = datas;
|
|
|
this.compileAllTemps();
|
|
|
- };
|
|
|
+ }; // 兼容Project框架方法
|
|
|
|
|
|
doAfterUpdate (err, data) {
|
|
|
if(!err){
|
|
|
$.bootstrapLoading.end();
|
|
|
}
|
|
|
- };
|
|
|
+ }; // 兼容Project框架方法
|
|
|
|
|
|
// 经测试,全部编译一次耗时0.003~0.004秒。耗时基本忽略不计。
|
|
|
compileAllTemps(){
|
|
@@ -648,28 +697,14 @@ class CalcProgram {
|
|
|
};
|
|
|
};
|
|
|
|
|
|
- initFeeField(treeNode, fieldName){
|
|
|
- if (!treeNode.data.fees) {
|
|
|
- treeNode.data.fees = [];
|
|
|
- treeNode.data.feesIndex = {};
|
|
|
- };
|
|
|
- if (!treeNode.data.feesIndex[fieldName]) {
|
|
|
- let fee = {
|
|
|
- 'fieldName': fieldName,
|
|
|
- 'unitFee': 0,
|
|
|
- 'totalFee': 0,
|
|
|
- 'tenderUnitFee': 0,
|
|
|
- 'tenderTotalFee': 0
|
|
|
- };
|
|
|
- treeNode.data.fees.push(fee);
|
|
|
- treeNode.data.feesIndex[fieldName] = fee;
|
|
|
- };
|
|
|
- };
|
|
|
-
|
|
|
// 仅内部调用。注意:外部不能直接使用,因为这里传入的树节点必须有一定的初始化。
|
|
|
- InnerCalc(treeNode){
|
|
|
+ innerCalc(treeNode){
|
|
|
let me = this;
|
|
|
- let project = me.project;
|
|
|
+ // 仅用作树节点显示的工料机不能参与计算。
|
|
|
+ if (treeNode.sourceType === me.project.ration_glj.getSourceType()) return;
|
|
|
+
|
|
|
+ treeNode.calcType = treeNodeTools.getCalcType(treeNode);
|
|
|
+ // if (treeNode.calcType == treeNodeCalcType.ctCalcBaseValue) return;
|
|
|
|
|
|
function initFees(treeNode){
|
|
|
if (!treeNode.data.fees) {
|
|
@@ -711,12 +746,13 @@ class CalcProgram {
|
|
|
return ['labour', 'material', 'machine', 'mainMaterial', 'equipment'].indexOf(type) > -1;
|
|
|
};
|
|
|
|
|
|
- // 汇总定额或子清单的费用类别
|
|
|
- if (treeNode.calcType == treeNodeCalcType.ctGatherRationsFees || treeNode.calcType == treeNodeCalcType.ctGatherBillsFees){
|
|
|
+ // 父清单汇总子项(定额或子清单)的费用类别
|
|
|
+ if (treeNode.calcType == treeNodeCalcType.ctGatherRationsFees ||
|
|
|
+ treeNode.calcType == treeNodeCalcType.ctGatherBillsFees){
|
|
|
treeNode.data.programID = null;
|
|
|
initFees(treeNode);
|
|
|
|
|
|
- let objsArr = (treeNode.calcType == treeNodeCalcType.ctGatherRationsFees) ? project.Ration.getRationsByNode(treeNode) : treeNode.children;
|
|
|
+ let objsArr = (treeNode.calcType == treeNodeCalcType.ctGatherRationsFees) ? me.project.Ration.getRationsByNode(treeNode) : treeNode.children;
|
|
|
let rst = [];
|
|
|
for (let ft of cpFeeTypes) {
|
|
|
let ftObj = {};
|
|
@@ -798,7 +834,7 @@ class CalcProgram {
|
|
|
|
|
|
delete treeNode.data.fees; // 直接删掉再新增,不用一个个费判断更新,效率更高。
|
|
|
delete treeNode.data.feesIndex;
|
|
|
- me.initFeeField(treeNode, 'common');
|
|
|
+ treeNodeTools.initFeeField(treeNode, 'common');
|
|
|
treeNode.data.feesIndex.common.unitFee = uf.toDecimal(decimalObj.bills.unitPrice);
|
|
|
treeNode.data.feesIndex.common.totalFee = tf.toDecimal(decimalObj.bills.totalPrice);
|
|
|
treeNode.data.feesIndex.common.tenderUnitFee = tuf.toDecimal(decimalObj.bills.unitPrice);
|
|
@@ -806,13 +842,12 @@ class CalcProgram {
|
|
|
treeNode.changed = true;
|
|
|
treeNode.data.calcTemplate = {"calcItems": []};
|
|
|
}
|
|
|
- // 叶子清单的计算基数计算
|
|
|
+ // 叶子清单公式计算
|
|
|
else if (treeNode.calcType == treeNodeCalcType.ctCalcBaseValue){
|
|
|
delete treeNode.data.gljList;
|
|
|
if (treeNode.data.programID) treeNode.data.programID = null;
|
|
|
|
|
|
let f = treeNode.data.feeRate ? treeNode.data.feeRate : 100;
|
|
|
- // let q = treeNode.data.quantity ? treeNode.data.quantity : 0;
|
|
|
if (!treeNode.data.quantity) treeNode.data.quantity = 1;
|
|
|
let q = treeNode.data.quantity;
|
|
|
let b = treeNode.data.calcBaseValue ? treeNode.data.calcBaseValue : 0;
|
|
@@ -823,7 +858,7 @@ class CalcProgram {
|
|
|
|
|
|
delete treeNode.data.fees; // 直接删掉再新增,不用一个个费判断更新,效率更高。
|
|
|
delete treeNode.data.feesIndex;
|
|
|
- me.initFeeField(treeNode, 'common');
|
|
|
+ treeNodeTools.initFeeField(treeNode, 'common');
|
|
|
treeNode.data.feesIndex.common.unitFee = uf;
|
|
|
treeNode.data.feesIndex.common.totalFee = tf;
|
|
|
treeNode.data.feesIndex.common.tenderUnitFee = tuf;
|
|
@@ -831,7 +866,7 @@ class CalcProgram {
|
|
|
treeNode.changed = true;
|
|
|
treeNode.data.calcTemplate = {"calcItems": []};
|
|
|
}
|
|
|
- // 定额或清单自己的计算程序计算
|
|
|
+ // 定额或叶子清单自己的计算程序计算
|
|
|
else{
|
|
|
if (treeNode.calcType == treeNodeCalcType.ctRationCalcProgram) {
|
|
|
if (treeNode.data.type == rationType.volumePrice){
|
|
@@ -852,10 +887,9 @@ class CalcProgram {
|
|
|
};
|
|
|
}
|
|
|
else if (treeNode.calcType == treeNodeCalcType.ctBillCalcProgram) {
|
|
|
- let rations = project.Ration.getBillsSortRation(treeNode.source.getID());
|
|
|
- treeNode.data.gljList = project.ration_glj.getGatherGljArrByRations(rations);
|
|
|
+ let rations = me.project.Ration.getBillsSortRation(treeNode.source.getID());
|
|
|
+ treeNode.data.gljList = me.project.ration_glj.getGatherGljArrByRations(rations);
|
|
|
|
|
|
- // if (treeNode.data.programID == undefined || treeNode.data.programID == defaultBillTemplate.ID){
|
|
|
if (treeNode.data.programID == undefined){
|
|
|
treeNode.data.programID = projectInfoObj.projectInfo.property.engineering;
|
|
|
}
|
|
@@ -891,40 +925,60 @@ class CalcProgram {
|
|
|
};
|
|
|
};
|
|
|
|
|
|
+ /*// 计算公式结点(叶子清单的计算基数计算)。仅内部调用。注意:外部不能直接使用,因为这里传入的树节点必须有一定的初始化。
|
|
|
+ innerCalcFormula(treeNode){
|
|
|
+ treeNode.calcType = treeNodeTools.getCalcType(treeNode);
|
|
|
+ if (treeNode.calcType != treeNodeCalcType.ctCalcBaseValue) return;
|
|
|
+
|
|
|
+ let me = this;
|
|
|
+ delete treeNode.data.gljList;
|
|
|
+ if (treeNode.data.programID) treeNode.data.programID = null;
|
|
|
+
|
|
|
+ let f = treeNode.data.feeRate ? treeNode.data.feeRate : 100;
|
|
|
+ if (!treeNode.data.quantity) treeNode.data.quantity = 1;
|
|
|
+ let q = treeNode.data.quantity;
|
|
|
+ let b = treeNode.data.calcBaseValue ? treeNode.data.calcBaseValue : 0;
|
|
|
+ let uf = (b * f * q / 100).toDecimal(decimalObj.bills.unitPrice);
|
|
|
+ let tuf = uf;
|
|
|
+ let tf = (me.project.property.billsCalcMode === leafBillGetFeeType.rationPrice) ? (b * f / 100).toDecimal(decimalObj.bills.totalPrice) : (uf * q).toDecimal(decimalObj.bills.totalPrice);
|
|
|
+ let ttf = tf;
|
|
|
+
|
|
|
+ delete treeNode.data.fees; // 直接删掉再新增,不用一个个费判断更新,效率更高。
|
|
|
+ delete treeNode.data.feesIndex;
|
|
|
+ treeNodeTools.initFeeField(treeNode, 'common');
|
|
|
+ treeNode.data.feesIndex.common.unitFee = uf;
|
|
|
+ treeNode.data.feesIndex.common.totalFee = tf;
|
|
|
+ treeNode.data.feesIndex.common.tenderUnitFee = tuf;
|
|
|
+ treeNode.data.feesIndex.common.tenderTotalFee = ttf;
|
|
|
+ treeNode.changed = true;
|
|
|
+ treeNode.data.calcTemplate = {"calcItems": []};
|
|
|
+ };*/
|
|
|
+
|
|
|
// 计算本节点(默认同时递归计算所有父节点,可选)
|
|
|
calculate(treeNode, calcParents = true){
|
|
|
let me = this;
|
|
|
- if (treeNode.sourceType === me.project.ration_glj.getSourceType()) return; // 仅用作树节点显示的工料机不能参与计算。
|
|
|
- let isRation = treeNode.sourceType === me.project.Ration.getSourceType();
|
|
|
- let isBill = treeNode.sourceType === me.project.Bills.getSourceType();
|
|
|
+ let changedNodes = [];
|
|
|
|
|
|
- if (isRation){
|
|
|
- treeNode.calcType = treeNodeCalcType.ctRationCalcProgram;
|
|
|
- }
|
|
|
- else if (treeNodeTools.isNullBill(treeNode)){
|
|
|
- treeNode.calcType = treeNodeCalcType.ctCommonUnitFee;
|
|
|
- }
|
|
|
- else if (treeNodeTools.isLeafBill(treeNode)) {
|
|
|
- if (treeNode.children && treeNode.children.length > 0){
|
|
|
- // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算。(汇总清单所有定额的工料机)
|
|
|
- if (me.project.property.billsCalcMode === leafBillGetFeeType.billsPrice)
|
|
|
- treeNode.calcType = treeNodeCalcType.ctBillCalcProgram;
|
|
|
- else // 前三种计算模式下的叶子清单:汇总定额的计算程序的费用类别
|
|
|
- treeNode.calcType = treeNodeCalcType.ctGatherRationsFees;
|
|
|
- }
|
|
|
- else{ // 公式计算
|
|
|
- treeNode.calcType = treeNodeCalcType.ctCalcBaseValue;
|
|
|
- };
|
|
|
- }
|
|
|
- else if (isBill) // 父清单:汇总子清单的费用类别
|
|
|
- treeNode.calcType = treeNodeCalcType.ctGatherBillsFees;
|
|
|
+ me.innerCalc(treeNode);
|
|
|
|
|
|
- me.InnerCalc(treeNode);
|
|
|
+ if (treeNode.changed) {
|
|
|
+ if (!changedNodes.includes(treeNode)) changedNodes.push(treeNode);
|
|
|
+
|
|
|
+ // 计算父结点
|
|
|
+ if (calcParents){
|
|
|
+ let curNode = treeNode.parent;
|
|
|
+ while (curNode){
|
|
|
+ me.innerCalc(curNode);
|
|
|
+ if (curNode.changed && !changedNodes.includes(curNode)) changedNodes.push(curNode);
|
|
|
+ curNode = curNode.parent;
|
|
|
+ };
|
|
|
+ };
|
|
|
|
|
|
- // 计算所有父结点
|
|
|
- if (treeNode.changed && calcParents && treeNode.parent) {
|
|
|
- me.calculate(treeNode.parent);
|
|
|
+ // 父结点算完,再算所有的公式结点(必须先算完父结点,再算公式结点)
|
|
|
+ me.calcFormulaNodes(changedNodes);
|
|
|
};
|
|
|
+
|
|
|
+ return changedNodes;
|
|
|
};
|
|
|
|
|
|
// 存储、刷新本节点(默认存储刷新所有父节点,可选)
|
|
@@ -1016,20 +1070,32 @@ class CalcProgram {
|
|
|
return changedNodes;
|
|
|
};
|
|
|
|
|
|
- // 计算全部公式项
|
|
|
- calcFormulaNodes(){
|
|
|
- let nodes = treeNodeTools.getFormulaNodes();
|
|
|
- if (nodes.length == 0) return;
|
|
|
- for (let node of nodes){
|
|
|
- this.calcFormulaNode(node);
|
|
|
+ // 计算全部公式项。 (参数意义:将通过本方法后发生改变的节点存入changedNodesArr中)
|
|
|
+ calcFormulaNodes(changedNodesArr){
|
|
|
+ let me = this;
|
|
|
+ let formulaNodes = treeNodeTools.getFormulaNodes();
|
|
|
+ if (formulaNodes.length == 0) return;
|
|
|
+ for (let formulaNode of formulaNodes){
|
|
|
+ formulaNode.data.userCalcBase = formulaNode.data.calcBase; // 这句不该出现,projectObj.project.calcBase中要改进。
|
|
|
+ projectObj.project.calcBase.calculate(formulaNode, true);
|
|
|
+ if (projectObj.project.calcBase.success){
|
|
|
+ // 计算公式结点
|
|
|
+ me.innerCalc(formulaNode);
|
|
|
+ if (formulaNode.changed && !changedNodesArr.includes(formulaNode)) changedNodesArr.push(formulaNode);
|
|
|
+
|
|
|
+ // 计算父结点
|
|
|
+ if (formulaNode.changed){
|
|
|
+ let curNode = formulaNode.parent;
|
|
|
+ while (curNode){
|
|
|
+ me.innerCalc(curNode);
|
|
|
+ if (curNode.changed && !changedNodesArr.includes(curNode)) changedNodesArr.push(curNode);
|
|
|
+ curNode = curNode.parent;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ };
|
|
|
};
|
|
|
};
|
|
|
|
|
|
- // 计算公式项。(它一定是叶子结点,它的父结点一定没有公式)
|
|
|
- calcFormulaNode(treeNode){
|
|
|
- // do
|
|
|
- };
|
|
|
-
|
|
|
// 计算叶子清单下的所有子结点(如定额、量价、工料机定额等), 并计算自身和所有父结点。最后打包存储。
|
|
|
calcLeafAndSave(treeNode){
|
|
|
let me = this;
|
|
@@ -1074,4 +1140,11 @@ class CalcProgram {
|
|
|
me.saveNodes(changedNodes);
|
|
|
};
|
|
|
|
|
|
+ // 计算并保存指定的一个树节点。修改一个树节点,实际上要计算和保存的是一批树结点:层层父结点、被其它结点(的公式)引用的公式结点。
|
|
|
+ // 这个方法实际上封装了calculate()和saveNodes()两个方法,方便外部调用,少写一点代码。
|
|
|
+ calcAndSave(treeNode){
|
|
|
+ let changedNodes = this.calculate(treeNode);
|
|
|
+ this.saveNodes(changedNodes);
|
|
|
+ };
|
|
|
+
|
|
|
}
|