瀏覽代碼

Merge branch 'master' of http://smartcost.f3322.net:3000/SmartCost/YangHuCost

TonyKang 6 年之前
父節點
當前提交
19e1fe33d3

+ 2 - 1
modules/all_models/bills.js

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

+ 110 - 2
modules/fee_rates/facade/fee_rates_facade.js

@@ -15,6 +15,7 @@ let template = require('../controllers/feerate_template');
 let logger = require("../../../logs/log_helper").logger;
 const uuidV1 = require('uuid/v1');
 let EngineeringLibModel = require("../../users/models/engineering_lib_model");
+const scMathUtil = require('../../../public/scMathUtil').getUtil();
 
 module.exports={
     save:save,
@@ -256,19 +257,126 @@ async function changeFeeRateStandard(jdata){
     let newFeeRate = {};
     newFeeRate.ID =uuidV1();
     newFeeRate.rates=template.rates;
+    //2019-02-25新需求,养护切换标准后还要设置旧的值到新的费率文件里
+    let subMap = await getAllSubRatesMap(data.feeRateID);
+    let [IDMap,childrenMap] = setRatesByMap(newFeeRate,subMap,data.decimal);
+    sumParentRate(IDMap,childrenMap,data.decimal);
     await feeRateModel.create(newFeeRate);
     let doc={
         libID:data.newLibID,
         libName:template.libName,
         feeRateID: newFeeRate.ID
     };
-    let deleteInfo = {deleted: true, deleteDateTime: new Date(), deleteBy: data.user_id};
     await feeRateFileModel.findOneAndUpdate({ID:data.feeRateFileID,deleteInfo:null},doc);
-    await feeRateModel.findOneAndUpdate({ID:data.feeRateID},{deleteInfo:deleteInfo});
+    await feeRateModel.deleteOne({ID:data.feeRateID});
     doc.rates=newFeeRate.rates;
     return doc;
 }
 
+async function getAllSubRatesMap(feeRateID){
+    let subMap = {};
+    let feeRate = await feeRateModel.findOne({ID:feeRateID});
+    if(feeRate){
+        let rates = feeRate.rates;
+        for(let r of rates){
+           if(r.subFeeRate){
+               for(let p of r.subFeeRate.recodes){
+                   if(subMap[p.name]) continue;
+                   subMap[p.name] = p;
+               }
+           }
+        }
+    }
+    return subMap;
+}
+
+function sumParentRate(IDMap,childrenMap,decimal){
+    for(let ParentID in  childrenMap){
+        if(IDMap[ParentID] && IDMap[ParentID].sum !== true) continue;
+        let childrenList = childrenMap[ParentID];
+        let total = 0;
+        for(let c of childrenList){
+            let tem = c.rate?c.rate:0;
+            tem = scMathUtil.roundForObj(tem,decimal);
+            total = scMathUtil.roundForObj(tem + total,6);
+        }
+        total = scMathUtil.roundForObj(total,decimal);
+        if(IDMap[ParentID])IDMap[ParentID].rate = total;
+    }
+}
+
+function setRatesByMap(newFeeRate,subMap,decimal){
+    let IDMap ={},childrenMap={};
+    for(let r of newFeeRate.rates){
+        IDMap[r.ID] = r;
+        if(r.subFeeRate){
+            for(let p of r.subFeeRate.recodes){
+                let t_p = subMap[p.name];
+                if(t_p){//找到同名的子项
+                    //获取选中的节点
+                    let selected = _.find(t_p.optionList,{"selected":true});
+                    for(let s of p.optionList){
+                        s.selected = selected && selected.name == s.name?true:false;//设置新费率的选中项
+                    }
+                    if(selected){//如果有选中项,则从valueMap中找出值并设置到rate上// ;
+                        let map = _.find(r.subFeeRate.valueMaps,{ID:selected.name});
+                        if(map){
+                            r.rate = map.value;
+                            setSubValue(p,selected.name);
+                        }
+                    }else if(t_p.editable==true){//在原来的选项中没有选中节点则说明是自已输入的,同时要是可编辑的类型,用内插法算值
+                        let ltRate = null;//
+                        let gtRate = null;
+                        for(let v of r.subFeeRate.valueMaps){
+                            if(parseFloat(v.ID)<parseFloat(t_p.value)){
+                                ltRate = v;
+                            }else if( gtRate==null && parseFloat(v.ID)>parseFloat(t_p.value)){
+                                gtRate = v;
+                            }
+                        }
+                        if(ltRate!=null&&gtRate!=null){//已经找到前后的值了
+                            let step = scMathUtil.roundForObj(gtRate.value - ltRate.value,getDecimal("process"))
+                            let total =  parseFloat(gtRate.ID) - parseFloat(ltRate.ID);
+                            r.rate  =getRateByStep(ltRate.value,total,parseFloat(t_p.value) - parseFloat(ltRate.ID),step,decimal);
+                        }else if(ltRate!=null&&gtRate == null){//说明是超出了选项的最大值
+                            let share = parseFloat(t_p.value) - parseFloat(ltRate.ID);//超出了多少
+                            r.rate  = getRateByStep(ltRate.value,p.step,share,p.amount,decimal)
+                        }else if(gtRate!=null&&ltRate==null){//说明是只有一个选项,且这个选项比输入的值大
+                            let step =  parseFloat(gtRate.value)- 0;
+                            r.rate = getRateByStep(0,gtRate.value,parseFloat(t_p.value),step,decimal)
+                        }
+                        if(r.rate!=undefined && r.rate != null){
+                            p.value = t_p.value;
+                            setSubValue(p,t_p.value);
+                        }
+                    }
+                }
+            }
+        }
+        if(r.ParentID&&r.ParentID!=""){
+            childrenMap[r.ParentID]?childrenMap[r.ParentID].push(r):childrenMap[r.ParentID]=[r];
+        }
+    }
+    return [IDMap,childrenMap]
+}
+
+function getRateByStep(ltValue,total,share,step,decimal) { //min值 ,计算值的总区间, 区间中占比,步长--前端也要用到
+    let p = scMathUtil.roundForObj(share/total,6);
+    let a = scMathUtil.roundForObj(step * p,6) ;
+    return scMathUtil.roundForObj(ltValue + a,decimal)
+}
+
+
+function setSubValue(p,name) {//设置综合理程的树节点的子节点的值
+    if(p.subList && p.subList.length > 0){
+        for(let s of p.subList){
+            s.value = Number(name);
+        }
+    }
+}
+
+
+
 async function newFeeRateFile(userId, updateData){
     if(updateData.property !== null){
         let property = updateData.property;

+ 1 - 1
modules/ration_glj/facade/ration_glj_facade.js

@@ -773,7 +773,7 @@ async  function replaceGLJByData(data,compilation) {
 
 async function replaceMixRatio(g,result,unitFileId){
     let newRecodes=[],deleteList = [];
-    if(gljUtil.isConcreteType(g.type)){//相同类型的才能替换,所以判断一个就好了
+    if(gljUtil.isConcreteType(g.type)||gljUtil.isCommercialConcreteType(g.type)){//混凝土大类,商品混凝土属于相同大类,替换前和替换后只判断一个就好了
         let IDMap = {}, projectGLJMap = {},referenceMap={},concreteList=[],newMap={};
         let projectGljModel = new GLJListModel();
         let rationGLJList = await ration_glj.find({'rationID':g.rationID});

+ 5 - 0
public/gljUtil.js

@@ -18,6 +18,7 @@ module.exports = {
     getAdjustPrice:getAdjustPrice,
     getMainType:getMainType,
     isConcreteType:isConcreteType,
+    isCommercialConcreteType:isCommercialConcreteType,
     getIndex:getIndex,
     sortRationGLJ:sortRationGLJ
 };
@@ -57,6 +58,10 @@ function isConcreteType(type) {
     return gljNodeUtil.isConcreteType(type);
 }
 
+function isCommercialConcreteType(type){
+    return gljNodeUtil.isCommercialConcreteType(type);
+}
+
 function sortRationGLJ(type) {
     return gljNodeUtil.sortRationGLJ(type);
 }

+ 4 - 0
public/web/gljUtil.js

@@ -322,6 +322,10 @@ let gljUtil = {
         let concreteType = [gljUtil.gljType.CONCRETE,gljUtil.gljType.MORTAR,gljUtil.gljType.MIX_RATIO];//混凝土大类:混凝土、砂浆,配合比
         return concreteType.indexOf(type)!=-1
     },
+    isCommercialConcreteType:function (type) {
+        let commercialType = [gljUtil.gljType.COMMERCIAL_CONCRETE,gljUtil.gljType.COMMERCIAL_MORTAR];//商品混凝土、商品砂浆
+        return commercialType.indexOf(type)!=-1
+    },
     hasComposition:function (ration_glj,isRationType) {//判断是否有组成物,有则返回true   现在主材类型的工料机也有可能有组成物。
         let type = isRationType==true? ration_glj.subType:ration_glj.type;
         if(gljUtil.notEditType.indexOf(type)!=-1||type==gljType.MAIN_MATERIAL){

+ 92 - 126
web/building_saas/main/js/models/calc_program.js

@@ -198,7 +198,7 @@ let calcTools = {
         if (!feeObj) return;
         if (feeObj.fieldName == '') return;
 
-        // 初始化前先拦截末定义的情况
+        // 初始化前先拦截属性末定义、又要给该属性赋0的情况
         if (!treeNode.data.feesIndex || !treeNode.data.feesIndex[feeObj.fieldName]){
             if (feeObj.unitFee == 0 && feeObj.totalFee == 0) return;
         }
@@ -851,6 +851,12 @@ let calcTools = {
     },
     inBase(baseName, kindName){
         return rationCalcBasesNameKinds[kindName].includes(baseName);
+    },
+    isBudgetProject(){
+        return projectObj.project.property.valuationType == 'bill';
+    },
+    isBillProject(){
+        return projectObj.project.property.valuationType == 'ration';
     }
 };
 
@@ -1594,44 +1600,40 @@ class CalcProgram {
 
     // 只计算treeNode自身。changedArr: 外部传来的一个数组,专门存储发生变动的节点。
     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;
-        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 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){
             treeNode.data.programID = null;
             calcTools.initFees(treeNode);
@@ -1655,16 +1657,17 @@ class CalcProgram {
                 if (treeNode.calcType == treeNodeCalcType.ctGatherBillsFees){
                     for (let node of nodes) {
                         if (node.data.feesIndex && node.data.feesIndex[ft.type]) {
-                            if (projectObj.project.property.valuationType === 'bill') { // 预算
-                                buf = (buf + parseFloatPlus(node.data.feesIndex[ft.type].unitFee)).toDecimal(decimalObj.process);
-                                btuf = (btuf + parseFloatPlus(node.data.feesIndex[ft.type].tenderUnitFee)).toDecimal(decimalObj.process);
-                            };
                             btf = (btf + parseFloatPlus(node.data.feesIndex[ft.type].totalFee)).toDecimal(decimalObj.process);
                             bttf = (bttf + parseFloatPlus(node.data.feesIndex[ft.type].tenderTotalFee)).toDecimal(decimalObj.process);
+
+                            if (calcTools.isBudgetProject()){
+                                buf = (btf / bq).toDecimal(decimalObj.process);
+                                btuf = (bttf / bq).toDecimal(decimalObj.process);
+                            }
                         };
                     };
                 }
-                else if (treeNode.calcType == treeNodeCalcType.ctGatherRationsFees){     // 这里的算法要配合冷姐姐的神图才能看懂^_^
+                else if (treeNode.calcType == treeNodeCalcType.ctGatherRationsFees){
                     let sum_rtf = 0, sum_rttf = 0;
                     for (let node of nodes) {
                         let ruf = 0, rtuf = 0, rtf = 0, rttf = 0;
@@ -1684,7 +1687,7 @@ class CalcProgram {
                     btf = sum_rtf;
                     bttf = sum_rttf;
 
-                    if (projectObj.project.property.valuationType != 'bill') {  // 招投标项目, 还要反算
+                    if (calcTools.isBillProject()) {  // 招投标项目, 还要反算
                         buf = buf.toDecimal(decimalObj.bills.unitPrice);
                         btuf = btuf.toDecimal(decimalObj.bills.unitPrice);
                         btf = (buf * nQ).toDecimal(decimalObj.bills.totalPrice);
@@ -1704,49 +1707,55 @@ class CalcProgram {
             };
             treeNode.data.calcTemplate = {"calcItems": rst};
         }
-        // 叶子清单无子结点、无公式计算(啥都没有时)
-        else if (treeNode.calcType == treeNodeCalcType.ctNull){
+        // 叶子清单:公式计算
+        else if (treeNode.calcType == treeNodeCalcType.ctCalcBaseValue){
             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){
                 let uf, tf;
                 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);
-                    if (nQ == 0) nQ = 1;
                     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);
-                    uf = nQ ? (tf / nQ) : tf;        // 如果工程量为0或空,综合合单直接填到综合单价
+                    uf = nQ ? (tf / nQ) : tf;        // 如果工程量为0或空,综合单价直接等于综合合
                     uf = uf.toDecimal(decimalObj.bills.unitPrice);
-                    if (projectObj.project.property.valuationType != 'bill') {  // 招投标项目, 还要反算
-                        let nQ2 = nQ ? nQ : 1;
-                        tf = (uf * nQ2).toDecimal(decimalObj.bills.totalPrice);
+                    if (calcTools.isBillProject()) {  // 招投标项目, 还要反算
+                        tf = (uf * nQ).toDecimal(decimalObj.bills.totalPrice);
                     };
                 };
 
@@ -1754,60 +1763,18 @@ class CalcProgram {
                 ftObj.totalFee = tf;
                 calcTools.checkFeeField(treeNode, ftObj);
 
-                if (treeNode.modifyFlag == 2 || treeNode.modifyFlag == 3){
-                    let ftObj2 = {
-                        fieldName: 'rationCommon',
-                        unitFee: uf,
-                        totalFee: tf
-                    };
-                    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');
+                // 数量、金额时,同步定额建安费
+                let ftObj2 = {
+                    fieldName: 'rationCommon',
+                    unitFee: uf,
+                    totalFee: tf
+                };
+                calcTools.checkFeeField(treeNode, ftObj2);
             }
 
             treeNode.data.calcTemplate = {"calcItems": []};
         }
-        // 定额或叶子清单自己的计算程序计算
+        // 定额:计算程序
         else{
             let fnArr = [];
             calcTools.getGLJList(treeNode, true);
@@ -1865,9 +1832,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);
     };
 
@@ -1911,7 +1877,6 @@ class CalcProgram {
             for (let node of treeNodes){
                 delete node.changed;
                 delete node.temData;
-                if (node.modifyFlag) delete node.modifyFlag;
                 node.updateData = {};
             };
             if(callback){
@@ -1993,6 +1958,7 @@ class CalcProgram {
     };
     setUpdateDataToNode(node){//将updateData里面的值设到node.data上,计算结点时才能拿到最新的值
         if(!_.isEmpty(node.updateData)){
+            node.changed = true;
             for(let key in node.updateData){
                 node.data[key] = node.updateData[key];
             }

+ 2 - 1
web/building_saas/main/js/models/fee_rate.js

@@ -337,7 +337,8 @@ var FeeRate = {
                 "newLibID": newVal,
                 "feeRateFileID":feeRate.ID,
                 "feeRateID":feeRate.feeRateID,
-                "user_id":userID
+                "user_id":userID,
+                "decimal":getDecimal("feeRate")
             };
             CommonAjax.post('/feeRates/changeFeeRateStandard', data, function (data) {
                 if (data) {

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

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

+ 8 - 2
web/building_saas/main/js/models/ration.js

@@ -606,6 +606,8 @@ var Ration = {
                     }else {
                         project.projectGLJ.loadData(function () {
                             syncNodeOper(data);
+                            if (newNode.parent.data.calcFlag)        // 删除定额时不用改Flag,反正添加定额时已经改好了。
+                                newNode.parent.updateData.calcFlag = null;
                             project.calcProgram.calcAndSave(newNode,function () {
                                 if(project.Bills.isFBFX(newNode)) { //判断是否属于分部分项工程 ,是的话才需要做计取安装费计算
                                     installationFeeObj.calcInstallationFee();
@@ -685,11 +687,15 @@ var Ration = {
                     newSource = data.ration;
                     newNode.source = newSource;
                     newNode.data = newSource;
-                })
+                });
                 ProjectController.syncDisplayNewNode(sheetController, newNode);
                 if(callback){
                     callback(newNode);
-                }
+                };
+                if (newNode.parent.data.calcFlag) {        // 删除定额时不用改Flag,反正添加定额时已经改好了。
+                    newNode.parent.updateData.calcFlag = null;
+                    project.calcProgram.calcAndSave(newNode.parent);
+                };
                 $.bootstrapLoading.end();
                 return newNode;
             }

+ 2 - 1
web/building_saas/main/js/models/ration_glj.js

@@ -823,6 +823,7 @@ let ration_glj = {
             }
             oldData.GLJID = glj.ID;
             oldData.name = glj.name;
+            oldData.type = glj.gljType;
             oldData.code = glj.code;
             oldData.original_code = glj.code;
             oldData.unit = glj.unit;
@@ -832,7 +833,7 @@ let ration_glj = {
             oldData.marketPrice = glj.basePrice;
             oldData.repositoryId = glj.repositoryId;
             oldData.materialType = glj.materialType;
-            oldData. materialCoe =  glj.materialCoe;
+            oldData.materialCoe =  glj.materialCoe;
             oldData.grossWeightCoe= glj.grossWeightCoe;
             oldData.purchaseStorageRate = glj.purchaseStorageRate;
             oldData.offSiteTransportLossRate = glj.offSiteTransportLossRate;

+ 2 - 4
web/building_saas/main/js/views/fee_rate_view.js

@@ -580,7 +580,7 @@ var feeRateObject={
                              }else {
                                  o.selected = false;
                              }
-                         }else {//没有匹配上的,直接取值就可以
+                         }else {//没有匹配上的,直接取值就可以(这个是为多参数时用的,但是目前来看,不支持多参数,比较麻烦)
                              if(o.selected == true)  valueArray.push(o.name);
                          }
                      }
@@ -599,7 +599,6 @@ var feeRateObject={
                      }else {//没找到,用内插法或步长算值
                          let ltRate = null;//
                          let gtRate = null;
-                         let lastRate = null;
                          temP.value = scMathUtil.roundForObj(value,getDecimal("feeRate")) ;
                          for(let v of valueMaps){
                             if(parseFloat(v.ID)<parseFloat(value)){
@@ -607,7 +606,6 @@ var feeRateObject={
                             }else if( gtRate==null && parseFloat(v.ID)>parseFloat(value)){
                                 gtRate = v;
                             }
-                            lastRate = v;
                          }
                          if(gljUtil.isDef(ltRate)&&gljUtil.isDef(gtRate)){//已经找到前后的值了
                              let step = scMathUtil.roundForObj(gtRate.value - ltRate.value,getDecimal("process"))
@@ -642,7 +640,7 @@ var feeRateObject={
                 $.bootstrapLoading.end();
             })
         }
-        function getRateByStep(ltValue,total,share,step) { //min值 ,计算值的总区间, 区间中占比,步长
+        function getRateByStep(ltValue,total,share,step) { //min值 ,计算值的总区间, 区间中占比,步长--后端重选标准也要用到
             let p = scMathUtil.roundForObj(share/total,getDecimal("process"));
             let a = scMathUtil.roundForObj(step * p,getDecimal("process")) ;
             return scMathUtil.roundForObj(ltValue + a,getDecimal("feeRate"))

+ 1 - 0
web/building_saas/main/js/views/glj_view.js

@@ -723,6 +723,7 @@ var gljOprObj = {
                     ration_gljs[i].shortName =projectObj.project.projectGLJ.getShortNameByID(ration_gljs[i].type);
                     ration_gljs[i].isAdd = glj.unit_price.is_add;
                     ration_gljs[i]=this.setGLJPrice(ration_gljs[i],glj);//设置工料机价格
+                    delete ration_gljs[i].subList; //置空,再设置
                     let connect_index = this.getIndex(glj, gljKeyArray);
                     if (needRatio==true&&mixRatioMap.hasOwnProperty(connect_index)) {
                         let mixRatios = this.getMixRationShowDatas(mixRatioMap[connect_index], projectGljs);

+ 4 - 5
web/building_saas/main/js/views/project_view.js

@@ -475,7 +475,6 @@ var projectObj = {
                 fieldName === 'calcBase' ||
                 fieldName === 'programID' || fieldName === 'subType' || fieldName === 'isSubcontract'){
                 if (fieldName === 'quantity') {
-                    node.modifyFlag = 1;
                     quantityEditObj.checkingAndUpdate(editingText,node);
                     return;
                 }
@@ -495,12 +494,12 @@ var projectObj = {
                                 fieldName = 'marketUnitFee';
                             }
                             else if (node.sourceType == ModuleNames.bills){
-                                node.modifyFlag = 2;
+                                node.updateData.calcFlag = treeNodeCalcFlag.customUnitPrice;
                             }
                         }
                         else if(fieldName === 'feesIndex.common.totalFee'){
                             value = scMathUtil.roundForObj(value, getDecimal("totalPrice", node));
-                            node.modifyFlag = 3;
+                            node.updateData.calcFlag = treeNodeCalcFlag.customTotalPrice;
                         }
                     // }
                 }
@@ -1992,7 +1991,7 @@ $("body").on("click",  function(e) {
     }
 });
 
-$('#insert').click(function () {
+/*$('#insert').click(function () {
     var controller = projectObj.mainController, project = projectObj.project;
     var selected = controller.tree.selected;
 
@@ -2001,7 +2000,7 @@ $('#insert').click(function () {
     } else if (selected.sourceType === project.Ration.getSourceType()) {
         ProjectController.addRation(project, controller, selected.data.type);
     };
-});
+});*/
 
 $('#delete').click(function () {
     let project = projectObj.project;

二進制
web/dest/css/img/login-bgp.jpg