|
@@ -27,18 +27,26 @@ let calcTools = {
|
|
|
treeNode.source.children.length > 0
|
|
|
);
|
|
|
},
|
|
|
+ // 最底层的清单,即叶子清单:⑴下面挂有定额 ⑵下面不挂定额。
|
|
|
isLeafBill: function (treeNode) {
|
|
|
- // 下面挂有定额的清单也是叶子清单
|
|
|
return (
|
|
|
this.isBill(treeNode) &&
|
|
|
treeNode.source.children &&
|
|
|
treeNode.source.children.length === 0
|
|
|
);
|
|
|
},
|
|
|
+ // 叶子清单有定额
|
|
|
+ isLeafBillHasRation: function (treeNode) {
|
|
|
+ return this.isLeafBill(treeNode) && (treeNode.children.length > 0);
|
|
|
+ },
|
|
|
+ // 最底层结点:如 ⑴无定额的叶子清单 ⑵定额。
|
|
|
isLeafNode: function (treeNode) {
|
|
|
- // 最底层结点,如定额等。
|
|
|
return treeNode.children.length === 0;
|
|
|
},
|
|
|
+ // 父清单也可以有锁定标志,但这个是给子结点批量设置用的,所以光判断这个不靠谱。
|
|
|
+ isLockPriceBill: function (treeNode) {
|
|
|
+ return this.isLeafBill(treeNode) && treeNode.data.lockUnitPrice;
|
|
|
+ },
|
|
|
isBill_DXFY: function (treeNode) {
|
|
|
return this.isBill(treeNode) && treeNode.data.type == billType.DXFY;
|
|
|
},
|
|
@@ -54,12 +62,12 @@ let calcTools = {
|
|
|
isBill_BX: function (treeNode) {
|
|
|
return this.isBill(treeNode) && treeNode.data.type == billType.BX;
|
|
|
},
|
|
|
- // 用户手工输入单价或金额的清单。叶子清单(且无定额无公式 或 有锁定单价)
|
|
|
+ // 用户手工输入单价,叶子清单、无定额、无公式。
|
|
|
isCustomBill: function (treeNode) {
|
|
|
- return this.isLeafBill(treeNode) && ((treeNode.children.length === 0 && !treeNode.data.calcBase) || treeNode.data.lockUnitPrice);
|
|
|
+ return this.isLeafBill(treeNode) && (treeNode.children.length === 0) && (!treeNode.data.calcBase);
|
|
|
},
|
|
|
+ // 无效的、影响正常计算的行(无意义的空行、没有金额的行等)
|
|
|
isInvalidNode: function (treeNode) {
|
|
|
- // 无效的、影响正常计算的行(无意义的空行、没有金额的行等)
|
|
|
return !(
|
|
|
treeNode.data &&
|
|
|
treeNode.data.feesIndex &&
|
|
@@ -972,28 +980,26 @@ let calcTools = {
|
|
|
return sum;
|
|
|
},
|
|
|
getCalcType: function (treeNode) {
|
|
|
- if (this.isRationCategory(treeNode)) {
|
|
|
- return treeNodeCalcType.ctRationCalcProgram;
|
|
|
- } else if (this.isCustomBill(treeNode)) {
|
|
|
- return treeNodeCalcType.ctCustom;
|
|
|
- } else if (this.isLeafBill(treeNode)) {
|
|
|
- if (treeNode.data.lockUnitPrice) // 叶子清单锁定单价(有定额或无定额)
|
|
|
- return treeNodeCalcType.ctLockUnitPrice
|
|
|
- else 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 {
|
|
|
+ if (this.isRationCategory(treeNode))
|
|
|
return treeNodeCalcType.ctRationCalcProgram;
|
|
|
+
|
|
|
+ if (this.isParentBill(treeNode)) // 父清单:汇总子清单的费用类别
|
|
|
+ return treeNodeCalcType.ctGatherBillsFees;
|
|
|
+
|
|
|
+ if (this.isLeafBill(treeNode)) {
|
|
|
+ if (this.isLockPriceBill(treeNode)) return treeNodeCalcType.ctLockPrice; // 叶子清单锁定单价(有定额或无定额)
|
|
|
+
|
|
|
+ if (this.isLeafBillHasRation(treeNode)) {
|
|
|
+ // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算。(汇总清单所有定额的工料机)
|
|
|
+ if (projectObj.project.property.billsCalcMode === leafBillGetFeeType.billsPrice)
|
|
|
+ return treeNodeCalcType.ctBillCalcProgram
|
|
|
+ // 前三种计算模式下的叶子清单:汇总定额的计算程序的费用类别
|
|
|
+ else return treeNodeCalcType.ctGatherRationsFees;
|
|
|
+ };
|
|
|
+
|
|
|
+ if (this.isCustomBill(treeNode)) return treeNodeCalcType.ctCustom;
|
|
|
+
|
|
|
+ return treeNodeCalcType.ctCalcBaseValue; // 公式计算
|
|
|
}
|
|
|
},
|
|
|
cutNodeForSave(treeNode) {
|
|
@@ -2121,23 +2127,30 @@ class CalcProgram {
|
|
|
|
|
|
treeNode.calcType = calcTools.getCalcType(treeNode);
|
|
|
|
|
|
- // 父清单汇总子清单的费用类别
|
|
|
- if (treeNode.calcType == treeNodeCalcType.ctGatherBillsFees)
|
|
|
- me.innerCalcBill(treeNode, 2)
|
|
|
- // 叶子清单:汇总定额的费用类别
|
|
|
- else if (treeNode.calcType == treeNodeCalcType.ctGatherRationsFees)
|
|
|
- me.innerCalcBill(treeNode, 1)
|
|
|
- // 叶子清单:锁定单价
|
|
|
- else if (treeNode.calcType == treeNodeCalcType.ctLockUnitPrice)
|
|
|
- me.innerCalcBill(treeNode, 4)
|
|
|
- // 叶子清单:公式计算
|
|
|
- else if (treeNode.calcType == treeNodeCalcType.ctCalcBaseValue)
|
|
|
- me.innerCalcBillExpr(treeNode)
|
|
|
- // 叶子清单:手工修改单价或金额。
|
|
|
- else if (treeNode.calcType == treeNodeCalcType.ctCustom)
|
|
|
- me.innerCalcBillCustom(treeNode);
|
|
|
- // 定额:计算程序
|
|
|
- else me.innerCalcRation(treeNode, tenderType);
|
|
|
+ switch (treeNode.calcType) {
|
|
|
+ case treeNodeCalcType.ctRationCalcProgram: // 定额:计算程序
|
|
|
+ me.innerCalcRation(treeNode, tenderType);
|
|
|
+ break;
|
|
|
+ case treeNodeCalcType.ctGatherBillsFees: // 父清单:汇总子清单的费用类别
|
|
|
+ me.innerCalcBill(treeNode, 2);
|
|
|
+ break;
|
|
|
+ case treeNodeCalcType.ctGatherRationsFees: // 叶子清单:汇总定额的费用类别
|
|
|
+ me.innerCalcBill(treeNode, 1);
|
|
|
+ break;
|
|
|
+ case treeNodeCalcType.ctCalcBaseValue: // 叶子清单:公式计算
|
|
|
+ me.innerCalcBillExpr(treeNode);
|
|
|
+ break;
|
|
|
+ case treeNodeCalcType.ctCustom: // 叶子清单:⑴手工修改单价。
|
|
|
+ me.innerCalcBillCustom(treeNode);
|
|
|
+ break;
|
|
|
+ case treeNodeCalcType.ctLockPrice: // 叶子清单:⑵锁定单价、强制修改单价(有定额也可改清单单价,定额与清单计算关系打断,但定额分摊清单的金额并逼近)。
|
|
|
+ // let oldTotalFee = parseFloatPlus(treeNode.data.feesIndex.common.totalFee);
|
|
|
+ me.innerCalcBillCustom(treeNode);
|
|
|
+ // if (calcTools.isLeafBillHasRation(treeNode)) { 有坑暂停,改基础数据影响很深很广,重构再做。
|
|
|
+ // me.distributeToRations(treeNode, oldTotalFee); // 分摊计算定额。这里方法提取出来,是防止逻辑上循环计算。
|
|
|
+ // }
|
|
|
+ break;
|
|
|
+ };
|
|
|
|
|
|
if (!calcTools.isTotalCostBill(treeNode))
|
|
|
// 已在上面的分支中计算过
|
|
@@ -2353,7 +2366,7 @@ class CalcProgram {
|
|
|
me.deleteUselessFees(treeNode, ["rationCommon"]);
|
|
|
|
|
|
// 2017-09-27 需求改了,除了第 1 、 2.2部分以外,都可以手工修改综合单价、综合合价并参与计算
|
|
|
- // 2021-09-14 增加强制修改综合单价功能,所以“除了第 1 、 2.2部分以外,...” 这里的业务取消。
|
|
|
+ // 2021-09-14 需求变更,为简化逻辑,“除了第 1 、 2.2部分以外,...” 这里的业务不必保留。增加强制修改综合单价功能。
|
|
|
// if (calcTools.canCalcToTalFeeByOwn(treeNode)) {
|
|
|
if (treeNode.data.feesIndex && treeNode.data.feesIndex.common) {
|
|
|
let ftObj = { fieldName: "common" };
|
|
@@ -2526,6 +2539,7 @@ class CalcProgram {
|
|
|
// 计算父结点
|
|
|
if (calcParents) {
|
|
|
let curNode = treeNode.parent;
|
|
|
+ if (calcTools.isLockPriceBill(curNode)) curNode = undefined;
|
|
|
while (curNode) {
|
|
|
me.innerCalc(curNode, changedNodes, tender);
|
|
|
curNode = curNode.parent;
|
|
@@ -2609,6 +2623,7 @@ class CalcProgram {
|
|
|
for (let ration of rationNodes) {
|
|
|
me.innerCalc(ration, allChangedNodes, tender);
|
|
|
let leafBill = ration.parent;
|
|
|
+ if (calcTools.isLockPriceBill(leafBill)) leafBill = undefined; // 这里必须打断,否则有循环计算(父变要分摊到子,子变又汇总到父)
|
|
|
if (leafBill && leafBills.indexOf(leafBill) < 0) leafBills.push(leafBill);
|
|
|
}
|
|
|
|
|
@@ -3003,6 +3018,18 @@ class CalcProgram {
|
|
|
this.distributeTargetTotalFee(treeNode.nextSibling);
|
|
|
}
|
|
|
|
|
|
+ // 强制修改叶子清单的综合单价,
|
|
|
+ distributeToRations(treeNode, oldTotlalFee){
|
|
|
+ for (let child of treeNode.children){
|
|
|
+ let newT = (treeNode.data.feesIndex.common.totalFee * child.data.feesIndex.common.totalFee / oldTotlalFee).toDecimal(decimalObj.ration.totalPrice);
|
|
|
+ let newQ = (newT / child.data.feesIndex.common.totalFee).toDecimal(decimalObj.ration.quantity);
|
|
|
+ child.data.quantity = newQ;
|
|
|
+ child.data.feesIndex.common.totalFee = (newQ * child.data.feesIndex.common.unitFee).toDecimal(decimalObj.ration.totalPrice);
|
|
|
+ child.changed = true;
|
|
|
+ this.innerCalcRation(child);
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
// 反向调价逼近
|
|
|
reverseTenderApproach(callback, tender) {
|
|
|
let me = this;
|