Browse Source

强制修改综合单价.

chenshilong 3 years ago
parent
commit
79ec56bd04

+ 71 - 44
web/building_saas/main/js/models/calc_program.js

@@ -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;

+ 3 - 3
web/building_saas/main/js/models/main_consts.js

@@ -83,9 +83,9 @@ const treeNodeCalcType = {
     ctBillCalcProgram: 2,       // 汇总清单下所有定额的工料机
     ctGatherRationsFees: 3,     // 汇总定额的各个费
     ctGatherBillsFees: 4,       // 汇总清单的各个费
-    ctCalcBaseValue: 5,
-    ctCustom: 6,
-    ctLockUnitPrice: 7         // 锁定单价
+    ctCalcBaseValue: 5,         // 金额是公式
+    ctCustom: 6,                // 手工输入单价
+    ctLockPrice: 7              // 锁定单价
 };
 
 const tenderTypes = {

+ 2 - 2
web/building_saas/main/js/models/quantity_detail.js

@@ -771,7 +771,7 @@ var quantity_detail = {
                 /*project.calcProgram.calcNodesAndSave(needUpdateChildren, function () {
                     project.projectGLJ.loadData();
                 });*/
-                project.calcProgram.calcNodesAndSave(needUpdateChildren,async function () {
+                project.calcProgram.calcNodesAndSave([...needUpdateChildren, node], async function () {
                     project.projectGLJ.calcQuantity();
                     await OVER_HEIGHT.reCalcOverHeightFee();
                     await itemIncreaseFeeObj.calcItemIncreaseFeeByNodes(needUpdateChildren);
@@ -856,4 +856,4 @@ var quantity_detail = {
         return new quantity_detail(project);
     }
 
-};
+};

+ 4 - 12
web/building_saas/main/js/views/main_tree_col.js

@@ -123,21 +123,13 @@ let MainTreeCol = {
             let Bills =projectObj.project.Bills;
             if(node.sourceType == ModuleNames.bills){//针对清单、分项部分
                 // 强制修改综合单价模式:可修改单价
-                if (projectObj.project.property?.tenderSetting?.calcPriceOption == 'priceBase_unitPrice'){
-                    if (calcTools.isLeafBill(node)) return false;
-                }
-
+                if (calcTools.isLockPriceBill(node)) return false;
                 // 属于标题清单,只读
-                if (calcTools.isTitleBills(node)) {
-                    return true;
-                }
+                if (calcTools.isTitleBills(node)) return true;
                 // 当前属于不可通过自身数据计算合价的部分,单价只读
-                if (Bills.cantCalcToTalFeeByOwn(node)) {
-                    return true;
-                }
-
+                if (Bills.cantCalcToTalFeeByOwn(node)) return true;
                 // 不属于分部分项、施工技术措施项目的部分,如果不是叶子清单,或有基数计算/定额/量价/人材机 只读
-                if(!calcTools.isLeafBill(node)||calcTools.isCalcBaseBill(node)||node.children.length > 0)return true;
+                if (!calcTools.isLeafBill(node) || calcTools.isCalcBaseBill(node) || node.children.length > 0) return true;
             }
             //当前是定额,综合单价只读。 2018-11-15
             if(MainTreeCol.readOnly.ration(node)) return true;