chenshilong 6 vuotta sitten
vanhempi
commit
696d46bb95

+ 2 - 1
modules/all_models/bills.js

@@ -70,7 +70,8 @@ let billsSchema = new Schema({
     remark:String,
     remark:String,
     engineeringContent:String,//工程内容
     engineeringContent:String,//工程内容
     serviceContent:String,//服务内容
     serviceContent:String,//服务内容
-    claimVisa:String//签证及索赔依据
+    claimVisa:String,//签证及索赔依据
+    calcFlag: {type: Number}    // 叶子清单的计算类型。末定义:按定额计算。1:用户输入金额。2:用户输入单价。3:用户输入设计单价。
 });
 });
 
 
 mongoose.model("bills", billsSchema);
 mongoose.model("bills", billsSchema);

+ 78 - 109
web/building_saas/main/js/models/calc_program.js

@@ -198,7 +198,7 @@ let calcTools = {
         if (!feeObj) return;
         if (!feeObj) return;
         if (feeObj.fieldName == '') return;
         if (feeObj.fieldName == '') return;
 
 
-        // 初始化前先拦截末定义的情况
+        // 初始化前先拦截属性末定义、又要给该属性赋0的情况
         if (!treeNode.data.feesIndex || !treeNode.data.feesIndex[feeObj.fieldName]){
         if (!treeNode.data.feesIndex || !treeNode.data.feesIndex[feeObj.fieldName]){
             if (feeObj.unitFee == 0 && feeObj.totalFee == 0) return;
             if (feeObj.unitFee == 0 && feeObj.totalFee == 0) return;
         }
         }
@@ -851,6 +851,12 @@ let calcTools = {
     },
     },
     inBase(baseName, kindName){
     inBase(baseName, kindName){
         return rationCalcBasesNameKinds[kindName].includes(baseName);
         return rationCalcBasesNameKinds[kindName].includes(baseName);
+    },
+    isBudgetProject(){
+        return projectObj.project.property.valuationType == 'bill';
+    },
+    isBillProject(){
+        return projectObj.project.property.valuationType == 'ration';
     }
     }
 };
 };
 
 
@@ -1594,44 +1600,41 @@ class CalcProgram {
 
 
     // 只计算treeNode自身。changedArr: 外部传来的一个数组,专门存储发生变动的节点。
     // 只计算treeNode自身。changedArr: 外部传来的一个数组,专门存储发生变动的节点。
     innerCalc(treeNode, changedArr, tender){
     innerCalc(treeNode, changedArr, tender){
+        if (treeNode.sourceType === ModuleNames.ration_glj) return;             // 仅用作树节点显示的工料机不能参与计算。
+
+        // 不能直接删除该属性,否则无法冲掉库中已存储的值。下同。
+        function deleteProperties (treeNode, propNamesArr){
+            for (let pn of propNamesArr){
+                if (treeNode.data[pn]){
+                    treeNode.data[pn] = null;
+                    treeNode.changed = true;
+                }
+            };
+        };
+        /*删掉多余的费用。例如:从其它计算方式(有很多费)切换到公式计算方式(只需要common费),多出来的费要删除。
+        reserveArr 值取自:情况①遍历treeNode的计算规则,取有绑定的字段名。这些字段名以外的fee是因旧计算多出来的,需要删除。没有绑定的
+        费用类别,不要同步到清单,也需要删除。*/
+        function deleteUselessFees(treeNode, reserveArr){
+            treeNode.data.fees = _.filter(treeNode.data.fees, function (item) {
+                if(!reserveArr.includes(item.fieldName)){
+                    delete treeNode.data.feesIndex[item.fieldName];
+                    treeNode.changed = true;
+                    return false;
+                }
+                return true;
+            });
+        };
+
         let me = this;
         let me = this;
-        me.setUpdateDataToNode(treeNode);//先更新要计算的节点信息
-        if(!treeNode.temData) treeNode.temData = _.cloneDeep(treeNode.data); //有可能会有多次计算,只有第一次才保存原始数据,用来对于更新。
-        // 仅用作树节点显示的工料机不能参与计算。
-        if (treeNode.sourceType === ModuleNames.ration_glj) return;
-        treeNode.calcType = calcTools.getCalcType(treeNode);
+        me.setUpdateDataToNode(treeNode);                                       // 先更新要计算的节点信息
+        if(!treeNode.temData) treeNode.temData = _.cloneDeep(treeNode.data);    // 有可能会有多次计算,只有第一次才保存原始数据,用来对于更新。
+
+
         let nQ = calcTools.uiNodeQty(treeNode);
         let nQ = calcTools.uiNodeQty(treeNode);
         let nTQ = calcTools.uiNodeTenderQty(treeNode);
         let nTQ = calcTools.uiNodeTenderQty(treeNode);
+        treeNode.calcType = calcTools.getCalcType(treeNode);
 
 
-        /*删掉多余的费用。例如:从其它计算方式(有很多费)切换到公式计算方式(只需要common费),多出来的费要删除。
-        fieldNameArr 值取自:遍历treeNode的计算规则,取有绑定的字段名。这些字段名以外的fee是因旧计算多出来的,需要删除。 */
-        function deleteUselessFees(treeNode, fieldNameArr){
-            if (fieldNameArr){   // 用于计算程序没有绑定的费用类别,不要同步到清单,而清单因为以前计算过该类别又有值,需删除。如切换取费类别,旧费要清掉。
-                treeNode.data.fees = _.filter(treeNode.data.fees, function (item) {
-                    if(!fieldNameArr.includes(item.fieldName)){
-                        delete treeNode.data.feesIndex[item.fieldName];
-                        treeNode.changed = true;
-                        return false;
-                    }
-                    return true;
-                });
-            }
-            else{   // 总造价清单只留common, estimate两个费用类别。其它公式清单只留common。
-                let reserveArr = calcTools.isTotalCostBill(treeNode)? ['common', 'estimate']:['common'];
-                if (treeNode.data.fees && treeNode.data.fees.length > 0){
-                    treeNode.data.fees = _.filter(treeNode.data.fees, function (item) {
-                        if(!reserveArr.includes(item.fieldName)){
-                            delete treeNode.data.feesIndex[item.fieldName];
-                            treeNode.changed = true;
-                            return false;
-                        }
-                        return true;
-                    });
-                };
-            };
-        };
-
-        // 父清单汇总子项(子清单或定额)的费用类别
+        // 父清单汇总子清单的费用类别、叶子清单汇总定额的费用类别
         if (treeNode.calcType == treeNodeCalcType.ctGatherBillsFees || treeNode.calcType == treeNodeCalcType.ctGatherRationsFees){
         if (treeNode.calcType == treeNodeCalcType.ctGatherBillsFees || treeNode.calcType == treeNodeCalcType.ctGatherRationsFees){
             treeNode.data.programID = null;
             treeNode.data.programID = null;
             calcTools.initFees(treeNode);
             calcTools.initFees(treeNode);
@@ -1704,43 +1707,51 @@ class CalcProgram {
             };
             };
             treeNode.data.calcTemplate = {"calcItems": rst};
             treeNode.data.calcTemplate = {"calcItems": rst};
         }
         }
-        // 叶子清单无子结点、无公式计算(啥都没有时)
-        else if (treeNode.calcType == treeNodeCalcType.ctNull){
+        // 叶子清单:公式计算
+        else if (treeNode.calcType == treeNodeCalcType.ctCalcBaseValue){
             delete treeNode.data.gljList;
             delete treeNode.data.gljList;
-
-            // 不能直接删除该属性,否则无法冲掉库中已存储的值。下同。
-            if (treeNode.data.calcBase){
-                treeNode.data.calcBase = null;
-                treeNode.changed = true;
-            }
-
-            if (treeNode.data.calcBaseValue){
-                treeNode.data.calcBaseValue = null;
-                treeNode.changed = true;
-            }
-
-            if (treeNode.data.tenderCalcBaseValue){
-                treeNode.data.tenderCalcBaseValue = null;
-                treeNode.changed = true;
-            }
-
-            if (treeNode.data.programID) {
-                treeNode.data.programID = null;
-                treeNode.changed = true;
+            deleteProperties(treeNode, ['programID']);
+            deleteUselessFees(treeNode, ['common', 'rationCommon']);
+            let tf = treeNode.data.calcBaseValue ? treeNode.data.calcBaseValue : 0;
+            let ttf = treeNode.data.tenderCalcBaseValue ? treeNode.data.tenderCalcBaseValue : 0;
+            let q = nQ ? nQ : 1;
+            let tq = nTQ ? nTQ : 1;
+            let uf = (tf / q).toDecimal(decimalObj.bills.unitPrice);
+            let tuf = (ttf / tq).toDecimal(decimalObj.bills.unitPrice);
+            if (calcTools.isBillProject()){
+                tf = (uf * q).toDecimal(decimalObj.bills.totalPrice);
+                ttf = (tuf * q).toDecimal(decimalObj.bills.totalPrice);
             };
             };
+            calcTools.checkFeeField(treeNode, {'fieldName': 'common', 'unitFee': uf, 'totalFee': tf, 'tenderUnitFee': tuf, 'tenderTotalFee': ttf});
+            //第一部分建安费下,使用基数计算的清单,定额建安费应=金额
+            if (cbTools.getBelongFlagList(treeNode).includes(fixedFlag.CONSTRUCTION_INSTALL_FEE))
+                calcTools.checkFeeField(treeNode, {'fieldName': 'rationCommon', 'unitFee': uf, 'totalFee': tf, 'tenderUnitFee': tuf, 'tenderTotalFee': ttf});
+
+            // 总造价清单还要做单项工程、建设项目的四大项金额汇总
+            // if (calcTools.isTotalCostBill(treeNode)){
+            //     // 公式叶子清单没有暂估费,但总造价清单除外。
+            //     calcTools.estimateFee(treeNode);
+            //     calcTools.initSummaryFee(treeNode);
+            //     treeNode.data.summaryFees.totalFee = tf;
+            //     treeNode.data.summaryFees.estimateFee = calcTools.getFee(treeNode, 'estimate.totalFee');
+            // }
+            treeNode.data.calcTemplate = {"calcItems": []};
+        }
+        // 叶子清单:无定额、无公式计算(什么都没有时),手工修改单价或金额。
+        else if (treeNode.calcType == treeNodeCalcType.ctNull){
+            delete treeNode.data.gljList;
+            deleteProperties(treeNode, ['calcBase', 'calcBaseValue', 'tenderCalcBaseValue', 'programID']);
 
 
-            // 叶子清单在没有公式的情况下可以手工修改综合单价并参与计算。
             if (treeNode.data.feesIndex && treeNode.data.feesIndex.common){
             if (treeNode.data.feesIndex && treeNode.data.feesIndex.common){
                 let uf, tf;
                 let uf, tf;
                 let ftObj = {fieldName: 'common'};
                 let ftObj = {fieldName: 'common'};
-                if (!treeNode.modifyFlag) return;    // 没有改过单价、数量、金额,则不计算,保留上次的计算结果。
 
 
-                if (treeNode.modifyFlag == 2){    // 修改了清单单价:以单价为准,算金额
+                if (treeNode.data.calcFlag == treeNodeCalcFlag.customUnitPrice){    // 修改了清单单价:以单价为准,算金额
                     uf = parseFloatPlus(treeNode.data.feesIndex.common.unitFee);
                     uf = parseFloatPlus(treeNode.data.feesIndex.common.unitFee);
                     if (nQ == 0) nQ = 1;
                     if (nQ == 0) nQ = 1;
                     tf = (uf * nQ).toDecimal(decimalObj.bills.totalPrice);
                     tf = (uf * nQ).toDecimal(decimalObj.bills.totalPrice);
                 }
                 }
-                else if (treeNode.modifyFlag == 3 || treeNode.modifyFlag == 1){  // 修改了清单金额:以金额为准,算单价。修改了清单数量也一样
+                else if (treeNode.data.calcFlag == treeNodeCalcFlag.customTotalPrice){  // 修改了清单金额:以金额为准,算单价。修改了清单数量也一样
                     tf = parseFloatPlus(treeNode.data.feesIndex.common.totalFee);
                     tf = parseFloatPlus(treeNode.data.feesIndex.common.totalFee);
                     uf = nQ ? (tf / nQ) : tf;        // 如果工程量为0或空,综合合单直接填到综合单价
                     uf = nQ ? (tf / nQ) : tf;        // 如果工程量为0或空,综合合单直接填到综合单价
                     uf = uf.toDecimal(decimalObj.bills.unitPrice);
                     uf = uf.toDecimal(decimalObj.bills.unitPrice);
@@ -1754,60 +1765,20 @@ class CalcProgram {
                 ftObj.totalFee = tf;
                 ftObj.totalFee = tf;
                 calcTools.checkFeeField(treeNode, ftObj);
                 calcTools.checkFeeField(treeNode, ftObj);
 
 
-                if (treeNode.modifyFlag == 2 || treeNode.modifyFlag == 3){
+                // 数量、金额时,同步定额建安费
+                if (treeNode.data.calcFlag == treeNodeCalcFlag.customUnitPrice || treeNode.data.calcFlag == treeNodeCalcFlag.customTotalPrice){
                     let ftObj2 = {
                     let ftObj2 = {
                         fieldName: 'rationCommon',
                         fieldName: 'rationCommon',
                         unitFee: uf,
                         unitFee: uf,
                         totalFee: tf
                         totalFee: tf
                     };
                     };
                     calcTools.checkFeeField(treeNode, ftObj2);
                     calcTools.checkFeeField(treeNode, ftObj2);
-                }
-            }
-
-            treeNode.data.calcTemplate = {"calcItems": []};
-        }
-        // 叶子清单公式计算
-        else if (treeNode.calcType == treeNodeCalcType.ctCalcBaseValue){
-            delete treeNode.data.gljList;
-
-            if (treeNode.data.programID) {
-                treeNode.data.programID = null;
-                treeNode.changed = true;
-            }
-            let f = 100;
-            if (treeNode.data.feeRate || treeNode.data.feeRate == 0)
-                f = treeNode.data.feeRate;
-            let b = treeNode.data.calcBaseValue ? treeNode.data.calcBaseValue : 0;
-            let tb = treeNode.data.tenderCalcBaseValue ? treeNode.data.tenderCalcBaseValue : 0;
-            let q = nQ ? nQ : 1;
-            let tq = nTQ ? nTQ : 1;
-            let uf = (b * f * 0.01 / q).toDecimal(decimalObj.bills.unitPrice);
-            let tuf = (tb * f * 0.01 / tq).toDecimal(decimalObj.bills.unitPrice);
-            let tf = (me.project.property.billsCalcMode === leafBillGetFeeType.rationPrice) ? (b * f / 100) : (uf * q);
-            tf = tf.toDecimal(decimalObj.bills.totalPrice);
-            let ttf = (me.project.property.billsCalcMode === leafBillGetFeeType.rationPrice) ? (tb * f / 100) : (tuf * tq);
-            ttf = ttf.toDecimal(decimalObj.bills.totalPrice);
-            deleteUselessFees(treeNode);
-            calcTools.checkFeeField(treeNode, {'fieldName': 'common', 'unitFee': uf, 'totalFee': tf, 'tenderUnitFee': tuf, 'tenderTotalFee': ttf});
-            //第一部分建安费下,使用基数计算的清单,定额建安费应=金额
-            if (cbTools.getBelongFlagList(treeNode).includes(fixedFlag.CONSTRUCTION_INSTALL_FEE)) {
-                calcTools.checkFeeField(treeNode, {'fieldName': 'rationCommon', 'unitFee': uf, 'totalFee': tf, 'tenderUnitFee': tuf, 'tenderTotalFee': ttf});
-            }
-
-            // 总造价清单还要做单项工程、建设项目的四大项金额汇总
-            if (calcTools.isTotalCostBill(treeNode)){
-                // 公式叶子清单没有暂估费,但总造价清单除外。
-                calcTools.estimateFee(treeNode);
-                calcTools.initSummaryFee(treeNode);
-                treeNode.data.summaryFees.totalFee = tf;
-                treeNode.data.summaryFees.estimateFee = calcTools.getFee(treeNode, 'estimate.totalFee');
-                // treeNode.data.summaryFees.safetyFee = calcTools.getFee(calcTools.getNodeByFlag(fixedFlag.SAFETY_CONSTRUCTION), 'common.totalFee');
-                // treeNode.data.summaryFees.chargeFee = calcTools.getFee(calcTools.getNodeByFlag(fixedFlag.CHARGE), 'common.totalFee');
+                };
             }
             }
 
 
             treeNode.data.calcTemplate = {"calcItems": []};
             treeNode.data.calcTemplate = {"calcItems": []};
         }
         }
-        // 定额或叶子清单自己的计算程序计算
+        // 定额:计算程序
         else{
         else{
             let fnArr = [];
             let fnArr = [];
             calcTools.getGLJList(treeNode, true);
             calcTools.getGLJList(treeNode, true);
@@ -1865,9 +1836,8 @@ class CalcProgram {
             };
             };
         };
         };
 
 
-        if (!calcTools.isTotalCostBill(treeNode))  // 已在上面的分支中计算过
-            calcTools.estimateFee(treeNode);
-
+        // if (!calcTools.isTotalCostBill(treeNode))  // 已在上面的分支中计算过
+        //     calcTools.estimateFee(treeNode);
         if (treeNode.changed && !changedArr.includes(treeNode)) changedArr.push(treeNode);
         if (treeNode.changed && !changedArr.includes(treeNode)) changedArr.push(treeNode);
     };
     };
 
 
@@ -1911,7 +1881,6 @@ class CalcProgram {
             for (let node of treeNodes){
             for (let node of treeNodes){
                 delete node.changed;
                 delete node.changed;
                 delete node.temData;
                 delete node.temData;
-                if (node.modifyFlag) delete node.modifyFlag;
                 node.updateData = {};
                 node.updateData = {};
             };
             };
             if(callback){
             if(callback){

+ 7 - 0
web/building_saas/main/js/models/main_consts.js

@@ -84,6 +84,13 @@ const treeNodeCalcType = {
     // ctCommonUnitFee: 6       // 树结点的手工输入综合单价的方式已废弃,现综合单价只读,引入市场单价。
     // ctCommonUnitFee: 6       // 树结点的手工输入综合单价的方式已废弃,现综合单价只读,引入市场单价。
 };
 };
 
 
+const treeNodeCalcFlag = {      // 主要用于清单。建筑的清单类型计算逻辑不能用公路。这里引入公路的计算Flag
+    customTotalPrice: 1,        // 用户直接输入金额
+    customUnitPrice: 2,         // 用户直接输入单价,金额是根据用户输入的单价算来的
+    customDesignPrice: 3        // 用户直接输入设计单价,金额是根据用户输入的设计单价算来的
+    // 末定义情况、0             // 金额是由定额计算的来的
+};
+
 const tenderTypes = {
 const tenderTypes = {
   ttCalc: 1,                // 正向调价
   ttCalc: 1,                // 正向调价
   ttReverseRation: 2,       // 反向调价-调子目
   ttReverseRation: 2,       // 反向调价-调子目

+ 2 - 3
web/building_saas/main/js/views/project_view.js

@@ -475,7 +475,6 @@ var projectObj = {
                 fieldName === 'calcBase' ||
                 fieldName === 'calcBase' ||
                 fieldName === 'programID' || fieldName === 'subType' || fieldName === 'isSubcontract'){
                 fieldName === 'programID' || fieldName === 'subType' || fieldName === 'isSubcontract'){
                 if (fieldName === 'quantity') {
                 if (fieldName === 'quantity') {
-                    node.modifyFlag = 1;
                     quantityEditObj.checkingAndUpdate(editingText,node);
                     quantityEditObj.checkingAndUpdate(editingText,node);
                     return;
                     return;
                 }
                 }
@@ -495,12 +494,12 @@ var projectObj = {
                                 fieldName = 'marketUnitFee';
                                 fieldName = 'marketUnitFee';
                             }
                             }
                             else if (node.sourceType == ModuleNames.bills){
                             else if (node.sourceType == ModuleNames.bills){
-                                node.modifyFlag = 2;
+                                node.updateData.calcFlag = treeNodeCalcFlag.customUnitPrice;
                             }
                             }
                         }
                         }
                         else if(fieldName === 'feesIndex.common.totalFee'){
                         else if(fieldName === 'feesIndex.common.totalFee'){
                             value = scMathUtil.roundForObj(value, getDecimal("totalPrice", node));
                             value = scMathUtil.roundForObj(value, getDecimal("totalPrice", node));
-                            node.modifyFlag = 3;
+                            node.updateData.calcFlag = treeNodeCalcFlag.customTotalPrice;
                         }
                         }
                     // }
                     // }
                 }
                 }