소스 검색

调价同步

chenshilong 5 년 전
부모
커밋
42d4acd465

+ 15 - 1
modules/main/models/bills.js

@@ -35,9 +35,23 @@ class billsModel extends baseModel {
     getQuery(projectID){
         return {'$or': [{projectID: projectID, deleteInfo: null}, {projectID: projectID, 'deleteInfo.deleted': {$in: [null, false]}}]}
     }
-     getData (projectID, callback) {
+     getData (projectID, callback, isReport = false) {
         this.model.find(this.getQuery(projectID), '-_id', function(err, datas){
             if (!err) {
+                if (isReport){
+                    for (let i = 0; i < datas.length; i++) {
+                       let fees = datas[i]._doc.fees;
+                       if (fees){
+                           for (let i = 0; i < fees.length; i++) {
+                               let doc = fees[i]._doc;
+                               if (doc){
+                                   if (doc.tenderTotalFee) doc.totalFee = doc.tenderTotalFee;
+                                   if (doc.tenderUnitFee) doc.unitFee = doc.tenderUnitFee;
+                               }
+                           }
+                       }
+                    }
+                };
                 callback(0, projectConsts.BILLS, datas);
             } else {
                 callback(1, projectConsts.BILLS, null);

+ 1 - 1
modules/main/models/project.js

@@ -138,7 +138,7 @@ Project.prototype.getFilterData = function (projectID, filter, callback) {
             if (moduleMap[moduleName]) {
                 moduleMap[moduleName].getData(projectID, function (err, name, data) {
                     cb(err, {'moduleName': name, 'data': data})
-                });
+                }, true);     // 所有报表只显示调价后的数据,这里传入一个标记true,子方法会将调价后的值赋给调价前的字段,这样报表可以不用动。
             } else if (moduleName === projectConsts.PROJECTGLJ) {
                 try {
                     if (isNaN(projectID) || projectID <= 0) {

+ 15 - 1
modules/main/models/ration.js

@@ -19,9 +19,23 @@ class rationModel extends baseModel {
     getQuery(projectID){
         return {'$or': [{projectID: projectID, deleteInfo: null}, {projectID: projectID, 'deleteInfo.deleted': {$in: [null, false]}}]}
     }
-    getData (projectID, callback) {
+    getData (projectID, callback, isReport = false) {
         ration.find(this.getQuery(projectID), '-_id', function(err, datas){
             if (!err) {
+                if (isReport){
+                    for (let i = 0; i < datas.length; i++) {
+                        let fees = datas[i]._doc.fees;
+                        if (fees){
+                            for (let i = 0; i < fees.length; i++) {
+                                let doc = fees[i]._doc;
+                                if (doc){
+                                    if (doc.tenderTotalFee) doc.totalFee = doc.tenderTotalFee;
+                                    if (doc.tenderUnitFee) doc.unitFee = doc.tenderUnitFee;
+                                }
+                            }
+                        }
+                    }
+                };
                 callback(0, projectConsts.RATION, datas);
             } else {
                 callback(1, '', null);

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

@@ -49,6 +49,7 @@ let logger = require("../../../logs/log_helper").logger;
 import stdgljutil  from "../../../public/cache/std_glj_type_util";
 import EngineeringLibModel from "../../users/models/engineering_lib_model";
 import GljDao from "../../complementary_glj_lib/models/gljModel";
+import gljType from "../../common/const/glj_type_const.js";
 const complementaryGljModel = mongoose.model('complementary_glj_lib');
 const stdGljModel = mongoose.model('std_glj_lib_gljList');
 const gljClassModel = mongoose.model('std_glj_lib_gljClass');
@@ -905,11 +906,61 @@ async function testError() {
     throw  new Error('test Error');
 }
 
-function getData(projectID, callback) {
+function getData(projectID, callback, isReport) {
+    function findRation(rations, ID) {
+        let ration = rations.find(function getElement(element) {
+            return element.ID == ID;
+        });
+        return ration._doc;
+    };
+
     ration_glj.find({'projectID': projectID}, (err, datas) => {
         if (err) {
             callback(1, '', null);
         } else {
+            if (isReport) {
+                ration.find({'projectID': projectID}, ['ID', 'code', 'name', 'quantityCoe', 'quantity', 'rationQuantityCoe'],
+                    function cbData(err, rations) {
+                        if (!err) {
+                            for (let i = 0; i < datas.length; i++) {
+                                let glj = datas[i]._doc;
+                                let ration = findRation(rations, glj.rationID);
+                                let coe = 1;
+                                if (ration && ration.quantityCoe){
+                                    if ([gljType.LABOUR].includes(glj.type)){
+                                        if (ration.quantityCoe._doc.labour)
+                                            coe = ration.quantityCoe._doc.labour;
+                                    }
+                                    else if ([gljType.GENERAL_MATERIAL,
+                                        gljType.CONCRETE,
+                                        gljType.MORTAR,
+                                        gljType.MIX_RATIO,
+                                        gljType.COMMERCIAL_CONCRETE,
+                                        gljType.COMMERCIAL_MORTAR].includes(glj.type)){
+                                        if (ration.quantityCoe._doc.material)
+                                            coe = ration.quantityCoe._doc.material;
+                                    }
+                                    else if ([gljType.GENERAL_MACHINE,
+                                        gljType.MACHINE_COMPOSITION,
+                                        gljType.MACHINE_LABOUR].includes(glj.type)){
+                                        if (ration.quantityCoe._doc.machine)
+                                            coe = ration.quantityCoe._doc.machine;
+                                    }
+                                    else if ([gljType.MAIN_MATERIAL].includes(glj.type)){
+                                        if (ration.quantityCoe._doc.main)
+                                            coe = ration.quantityCoe._doc.main;
+                                    }
+                                    else if ([gljType.EQUIPMENT].includes(glj.type)){
+                                        if (ration.quantityCoe._doc.equipment)
+                                            coe = ration.quantityCoe._doc.equipment;
+                                    };
+
+                                };
+                                glj.quantity = glj.quantity * coe;
+                            }
+                        }
+                    });
+            };
             callback(0, consts.projectConst.RATION_GLJ, datas);
         }
     })

+ 1 - 1
modules/reports/util/rpt_construct_data_util.js

@@ -268,7 +268,7 @@ class Rpt_Data_Extractor {
             let billsDatas = getModuleDataByKey(rawDataObj.prjData, "bills");
             let decimal = rawDataObj.prj.property.decimal.glj.quantity;
             if (projectGLJDatas && rationGLJDatas && rationDatas && billsDatas) {
-                gljUtil.calcProjectGLJQuantity(projectGLJDatas.data, rationGLJDatas.data, rationDatas.data, billsDatas.data, decimal);
+                gljUtil.calcProjectGLJQuantity(projectGLJDatas.data, rationGLJDatas.data, rationDatas.data, billsDatas.data, decimal, true);
             }
         }
         //还有汇总的...

+ 34 - 9
public/web/gljUtil.js

@@ -4,7 +4,7 @@
 
 
 let gljUtil = {
-    calcProjectGLJQuantity:function (projectGLJDatas,rationGLJDatas,rationDatas,billsDatas,q_decimal,_,scMathUtil,isTender) {
+    calcProjectGLJQuantity:function (projectGLJDatas,rationGLJDatas,rationDatas,billsDatas,q_decimal,_,scMathUtil,isReport) {
         let project_gljs = projectGLJDatas.gljList;
         let mixRatioMap = projectGLJDatas.mixRatioMap;
         let rations = rationDatas;
@@ -13,9 +13,9 @@ let gljUtil = {
         let rationGljGroup = _.groupBy(rationGLJDatas,'projectGLJID');
         let IDarray =  this.getSubdivisionAndTechBillsLeavesID(billsDatas);//分别取分部分项和技术措施项目的所有叶子清单ID
         let billIDs = IDarray[0],tech_billIDS = IDarray[1];
-        let sField = isTender==true?"tenderSubdivisionQuantity":"subdivisionQuantity";
-        let tField = isTender==true?"tenderTechQuantity":"techQuantity";
-        let qField = isTender==true?"tenderQuantity":"quantity";
+        let sField = "subdivisionQuantity";
+        let tField = "techQuantity";
+        let qField = "quantity";
 
         for(let pglj of project_gljs ){
             let pg_index = this.getIndex(pglj,this.gljKeyArray);
@@ -23,7 +23,7 @@ let gljUtil = {
             pglj[tField] = 0;
             pglj[qField] = 0;
             let gljGroup = rationGljGroup[pglj.id]?rationGljGroup[pglj.id]:[];//定额工料机没有,有可能是定额类型的工料机
-            let result = this.getQuantityPerGLJ(gljGroup,rations,rationMap,pglj,billIDs,tech_billIDS,q_decimal,_,scMathUtil,isTender);
+            let result = this.getQuantityPerGLJ(gljGroup,rations,rationMap,pglj,billIDs,tech_billIDS,q_decimal,_,scMathUtil);
             pglj[sField] = result.subdivisionQuantity;
             pglj[tField] = result.techQuantity;
             pglj[qField] = result.quantity;
@@ -49,8 +49,14 @@ let gljUtil = {
                 }
             }
         }
+
+        if (isReport) {
+            for(let pglj of project_gljs ){
+                pglj[qField] = pglj.tenderQuantity;
+            }
+        }
     },
-    getQuantityPerGLJ : function (ration_glj_list,rations,rationMap,pglj,billIDs,tech_billIDS,q_decimal,_,scMathUtil,isTender) {
+    getQuantityPerGLJ : function (ration_glj_list,rations,rationMap,pglj,billIDs,tech_billIDS,q_decimal,_,scMathUtil) {
         let result={};
         let quantity_sum=0;//工料机汇总消耗量
         let sum = 0;//分部分项总消耗量
@@ -174,10 +180,14 @@ let gljUtil = {
     getFlag:function (b) {
         return _.find(b.flags,{"fieldName":"fixed"});
     },
-    getGLJPrice:function (glj,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,isRadio,_,scMathUtil,tenderCoe) {
+    getGLJPrice:function (glj,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,isRadio,_,scMathUtil,tenderCoe, isReport) {
         let result = {};
-        result.marketPrice = this.getMarketPrice(glj,projectGLJDatas,calcOptions,decimalObj,isRadio,_,scMathUtil);
-        result.tenderPrice = this.getMarketPrice(glj,projectGLJDatas,calcOptions,decimalObj,isRadio,_,scMathUtil,tenderCoe);
+        if(isReport){
+            result.marketPrice = this.getMarketPrice(glj,projectGLJDatas,calcOptions,decimalObj,isRadio,_,scMathUtil,tenderCoe);
+        }else {
+            result.marketPrice = this.getMarketPrice(glj,projectGLJDatas,calcOptions,decimalObj,isRadio,_,scMathUtil);
+            result.tenderPrice = this.getMarketPrice(glj,projectGLJDatas,calcOptions,decimalObj,isRadio,_,scMathUtil,tenderCoe);
+        }
         if(this.calcPriceDiff(glj,calcOptions)==true){//计取价差
             result.basePrice = this.getBasePrice(glj,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,isRadio,_,scMathUtil);
             result.adjustPrice = this.getAdjustPrice(glj,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,isRadio,_,scMathUtil);
@@ -322,6 +332,8 @@ let gljUtil = {
             quantity = (quantity == 0 || quantity == undefined || quantity == null || quantity == "") ? 0 : quantity;
             quantity = scMathUtil.roundForObj(quantity, rd);//计算前进行4舍5入
             glj.quantity = scMathUtil.roundForObj(glj.quantity, gd);
+            glj.tenderQuantity = this.getRationGLJTenderQuantity(glj, ration, gd, scMathUtil);
+
             return scMathUtil.roundToString(quantity * glj.quantity, gd);
         }
     },
@@ -557,6 +569,19 @@ let gljUtil = {
 
         return datas;
     },
+    getTenderPriceCoe : function(glj,tproperty){
+        let tenderCoe = 1;
+        let property = tproperty?tproperty:projectObj.project.property;
+        if (!glj.is_adjust_price&&property.tenderSetting && isDef(property.tenderSetting.gljPriceTenderCoe) ){
+            tenderCoe = parseFloat(property.tenderSetting.gljPriceTenderCoe);
+        }
+        return tenderCoe;
+
+        function isDef (v) {
+            return v !== undefined && v !== null;
+        }
+    },
+
     fixedFlag : {
         // 分部分项工程
         SUB_ENGINERRING: 1,

+ 21 - 6
public/web/sheet/sheet_common.js

@@ -19,8 +19,12 @@ var sheetCommonObj = {
     },
 
     initSheet: function(sheet, setting, rowCount) {
+
         var me = this;
         var spreadNS = GC.Spread.Sheets;
+        if(setting.headRows == 2){
+            return me.buildSpanHeader(sheet, setting, rowCount);//初始化合并表格列头
+        }
         sheet.suspendPaint();
         sheet.suspendEvent();
         if(setting.frozenCols)  sheet.frozenColumnCount(setting.frozenCols);//冻结列s
@@ -46,10 +50,6 @@ var sheetCommonObj = {
         sheet.showRowOutline(false);
         sheet.options.allowCellOverflow = false;
         me.buildHeader(sheet, setting);
-        if (rowCount > 0)
-            sheet.setRowCount(rowCount);
-        else
-            sheet.setRowCount(1);
         sheet.resumeEvent();
         sheet.resumePaint();
     },
@@ -63,6 +63,21 @@ var sheetCommonObj = {
         return spreadBook;
     },
 
+    buildSpanHeader:function (sheet, setting, rowCount) {
+        let temSetting = {
+            "emptyRows":0,
+            "headRows":2,
+            "headRowHeight":[21],
+            "defaultRowHeight": 21,
+            "treeCol": 0,
+            "cols":[]
+        };
+        let spanSetting =   sheetCommonObj.transferToTreeSetting(setting,temSetting);
+        TREE_SHEET_HELPER.loadSheetHeader(spanSetting,sheet,rowCount);
+
+    },
+
+
     buildHeader: function(sheet, setting){
         var me = this, ch = GC.Spread.Sheets.SheetArea.colHeader;
         for (var i = 0; i < setting.header.length; i++) {
@@ -177,7 +192,7 @@ var sheetCommonObj = {
                     if(setting.header[col].hasOwnProperty('decimalField')){
                         let decimal = getDecimal(setting.header[col].decimalField);
                         val =scMathUtil.roundToString(val,decimal);
-                        sheet.setFormatter(row, col,getFormatter(decimal), GC.Spread.Sheets.SheetArea.viewport);
+                        sheet.setFormatter(-1, col,getFormatter(decimal), GC.Spread.Sheets.SheetArea.viewport);
                     }else {
                         val =scMathUtil.roundToString(val,2);
                     }
@@ -275,7 +290,7 @@ var sheetCommonObj = {
             if (setting.header[col].formatter) {
                 sheet.setFormatter(-1, col, setting.header[col].formatter, GC.Spread.Sheets.SheetArea.viewport);
             }
-            if(setting.header[col].cellType === "checkBox"||setting.header[col].cellType === "button"){//clear and reset
+            if(setting.headRows != 2 &&  setting.header[col].cellType === "checkBox"||setting.header[col].cellType === "button"){//clear and reset   2019 - 11- 11 加入了多行列头的判断情况,排除多行列头时清空操作,先试运行看是否有问题
                 var me = this, header = GC.Spread.Sheets.SheetArea.colHeader;
                 sheet.deleteColumns(col,1);
                 sheet.addColumns(col, 1);

+ 1 - 1
web/building_saas/main/html/main.html

@@ -76,7 +76,7 @@
                 <li class="nav-item"><a data-toggle="tab" href="#fee_rates" id="tab_fee_rate" role="tab" >费率</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#calc_program_manage" id="tab_calc_program_manage" role="tab" style="display:none">总计算程序</a></li>
                 <!--<li class="nav-item"><a data-toggle="tab" href="#tender_price" id="tab_tender_price" role="tab" style="display:none">调价</a></li>-->
-              <!--  <li class="nav-item"><a data-toggle="tab" href="#tender_price" id="tab_tender_price" role="tab">调价</a></li>-->
+                <li class="nav-item"><a data-toggle="tab" href="#tender_price" id="tab_tender_price" role="tab">调价</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#reports" role="tab" id="tab_report" onclick="rptTplObj.iniPage();">报表</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#index" id="tab_index" role="tab" style="display:none">指标信息</a></li>
             </ul>

+ 6 - 0
web/building_saas/main/html/tender_price.html

@@ -20,6 +20,12 @@
             <button type="button" class="btn btn-outline-primary btn-sm" id = "tenderPrice">调价计算</button>
         </div>
         <button type="button" class="btn btn-outline-danger btn-sm" id = "cleanTender">清空调价</button>
+        <div class="form-check" style="margin-left:40px; margin-top:5px;">
+            <label class="form-check-label">
+                <input class="form-check-input" name="cbShowTenderFields" id="cbShowTenderFields" value="true" type="checkbox">
+                显示调价后数据(造价书人材机界面、人材机汇总界面)
+            </label>
+        </div>
     </div>
 </div>
 <div class="container-fluid">

+ 163 - 24
web/building_saas/main/js/models/calc_program.js

@@ -111,11 +111,14 @@ let calcTools = {
             treeNode.source.children &&
             treeNode.source.children.length > 0;
     },
-    isLeafBill: function(treeNode){
+    isLeafBill: function(treeNode){      // 下面挂有定额的清单也是叶子清单
         return this.isBill(treeNode) &&
             treeNode.source.children &&
             treeNode.source.children.length === 0;
     },
+    isLeafNode: function(treeNode){      // 最底层结点,如定额等。
+        return treeNode.children.length === 0;
+    },
     isBill_DXFY: function(treeNode){
         return this.isBill(treeNode) && treeNode.data.type == billType.DXFY;
     },
@@ -841,8 +844,20 @@ let calcTools = {
         if (this.isBill(treeNode))                 // 清单只有一个工程量,没有调整后工程量。
             return this.uiNodeQty(treeNode)
         else{
-            let qCoe = (treeNode.data.rationQuantityCoe == undefined || treeNode.data.rationQuantityCoe == null ||
-                treeNode.data.rationQuantityCoe == 0) ? 1 : treeNode.data.rationQuantityCoe;
+            let qCoe = 1;
+            /* 量价、工料机类型的定额,在反向调价之调整人材机消耗量系数时,因为他们没有工料机可调,调价结果没变,影响汇总后的父结点金额。
+            所以要特殊处理:此种情况下仍然要调量价的消耗量,即还是要像"子目工程量调整系数"方式那样调,但系数又不能在"子目工程量调整系数"
+            中显示出来,所以可以改变tenderQuantity达到同样的效果以瞒天过海。所以在取系数时,无论什么系数,只要能取到就算正确。 */
+            if (treeNode.data.type == rationType.volumePrice || treeNode.data.type == rationType.gljRation){
+                if (treeNode.data.rationQuantityCoe)
+                    qCoe = treeNode.data.rationQuantityCoe
+                else if (treeNode.data.quantityCoe && treeNode.data.quantityCoe.labour)
+                    qCoe = treeNode.data.quantityCoe.labour;
+            }
+            else {
+                if (treeNode.data.rationQuantityCoe)
+                    qCoe = treeNode.data.rationQuantityCoe;
+            };
             treeNode.data.tenderQuantity = (this.uiNodeQty(treeNode) * qCoe).toDecimal(decimalObj.decimal("quantity", treeNode));
             return treeNode.data.tenderQuantity;
         }
@@ -907,6 +922,12 @@ let calcTools = {
             return parseFloat(quantity).toDecimal(decimalObj.glj.quantity)
         else return 0;
     },
+    hasTargetTotalFee: function (treeNode){    // targetTotalFee 有时为字符串“0”,此种情况会执行if 条件引起逻辑错误。所以这里封闭成方法直接调用。
+        return (treeNode.data.targetTotalFee && parseFloat(treeNode.data.targetTotalFee));
+    },
+    hasQuantity: function (treeNode){
+        return (treeNode.data.quantity && parseFloat(treeNode.data.quantity));
+    },
     
     getRationsByProjectGLJ(PGLJID){
         let rationIDs = [];
@@ -1882,7 +1903,7 @@ class CalcProgram {
                     if (treeNode.data.marketTotalFee != mtf){
                         treeNode.data.marketTotalFee = mtf;
                         treeNode.changed = true;
-                    } ;
+                    };
                 };
             };
             // 2018-08-27   zhang  插入空定额的时候,取费专业也为空
@@ -1932,7 +1953,6 @@ class CalcProgram {
 
         if (treeNode.changed && !changedArr.includes(treeNode)) changedArr.push(treeNode);
     };
-
     // 存储、刷新零散的多个结点。
     saveNodes(treeNodes, callback){
         if (treeNodes.length < 1) {
@@ -1943,15 +1963,6 @@ class CalcProgram {
         }
 
         let me = this;
-        /*        me.project.beginUpdate('');
-                for (let node of treeNodes){
-                    if (node.changed){
-                        let data = calcTools.cutNodeForSave(node);
-                        let newData = {'updateType': 'ut_update', 'updateData': data};
-                        me.project.push(node.sourceType, [newData]);
-                    }
-                };
-                me.project.endUpdate();*/
 
         let dataArr = [];
         for (let node of treeNodes){
@@ -1976,7 +1987,7 @@ class CalcProgram {
                 callback(data);
             };
 
-            for (let node of treeNodes){delete node.changed};
+            for (let node of treeNodes) { delete node.changed };
             projectObj.mainController.refreshTreeNode(treeNodes);
 
             // 批量树结点计算后,计算程序早已物是人非,所以这里要重新计算一下。警告:第二个参数千万不能改成3,否则死循环!
@@ -1985,8 +1996,7 @@ class CalcProgram {
             $.bootstrapLoading.end();
         });
     };
-
-    // 计算本节点、所有父节点(默认,可选)、公式引用节点(默认,可选)。
+    // 计算本节点及所有会被影响到的节点,如:所有父节点(默认,可选)、公式引用节点(默认,可选)。修改一个树节点,实际上要计算和保存的是一批树结点:层层父结点、被其它结点(的公式)引用的公式结点。
     calculate(treeNode, calcParents = true, calcFormulas = true, tender){
         let me = this;
         let changedNodes = [];
@@ -2008,7 +2018,7 @@ class CalcProgram {
 
         return changedNodes;
     };
-    // 计算并保存一个树节点。(修改一个树节点,实际上要计算和保存的是一批树结点:层层父结点、被其它结点(的公式)引用的公式结点)
+    // 计算并保存本节点及所有会被影响到的节点。
     calcAndSave(treeNode, callback, tender){
         let changedNodes = this.calculate(treeNode, true, true, tender);
         this.saveNodes(changedNodes, callback);
@@ -2019,6 +2029,8 @@ class CalcProgram {
         calcAllType.catBills     计算所有清单 (改变项目属性中清单取费算法时会用到)
         calcAllType.catRations   计算所有定额、工料机形式的定额、量价,因为它们都走自己的计算程序 (改变人工系数、费率值、工料机单价时会用到)
                                  (calcAllType.catRations时程序中做了特殊处理,实际上是计算所有树结点!)
+        调价相关参数:
+        tender:                 null:不调价(普通计算)。 1: 正向调价   2:反向调价-调子目    3: 反向调价-调工料机
     */
     calcAllNodes(calcType = calcAllType.catAll, tender){
         let me = this;
@@ -2042,6 +2054,13 @@ class CalcProgram {
 
         calcNodes(me.project.mainTree.roots);
         me.calcFormulaNodes(changedNodes, tender);
+
+        if (tender){    // 普通计算不执行,只有3种调价计算才清。
+            for(let node of projectObj.project.mainTree.items){
+                this.clearTenderCache(node);
+            };
+        };
+
         return changedNodes;
     };
     // tender: null:不调价(普通计算)。 1: 正向调价   2:反向调价-调子目    3: 反向调价-调工料机
@@ -2170,7 +2189,7 @@ class CalcProgram {
                 treeNode.data.targetTotalFee = (treeNode.data.targetUnitFee * treeNode.data.quantity).toDecimal(decimalObj.decimal('totalPrice', treeNode));
                 treeNode.changed = true;
             }
-            else{    // 既没有目标金额也没有目标单价,此时要初始化使调价合价=原始综合合价,调价单价=原始综合单价。(交叉调价后,旧值会留下来)
+            else{    // 既没有目标金额也没有目标单价,此时要初始化使调价合价=原始综合合价,调价单价=原始综合单价。
                 if (treeNode.data.feesIndex.common.tenderUnitFee != treeNode.data.feesIndex.common.unitFee) {
                     treeNode.data.feesIndex.common.tenderUnitFee = treeNode.data.feesIndex.common.unitFee;
                     treeNode.changed = true;
@@ -2183,11 +2202,13 @@ class CalcProgram {
             }
         };
 
-        if (!treeNode.data.targetUnitFee)
-            treeNode.data.targetUnitFee = (treeNode.data.targetTotalFee / treeNode.data.quantity).toDecimal(decimalObj.decimal('unitPrice', treeNode));
+        if (!treeNode.data.targetUnitFee || (parseFloat(treeNode.data.targetUnitFee) == 0)){
+            if (calcTools.hasQuantity(treeNode))
+                treeNode.data.targetUnitFee = (treeNode.data.targetTotalFee / treeNode.data.quantity).toDecimal(decimalObj.decimal('unitPrice', treeNode));
+        }
+
         let coe = 1;
         if (treeNode.data.feesIndex.common.totalFee != 0)
-            // coe = (treeNode.data.targetTotalFee / treeNode.data.feesIndex.common.totalFee).toDecimal(decimalObj.process);
             coe = (treeNode.data.targetUnitFee / treeNode.data.feesIndex.common.unitFee).toDecimal(decimalObj.process);
 
         if (tender == tenderTypes.ttReverseRation){
@@ -2203,7 +2224,7 @@ class CalcProgram {
                 treeNode.changed = true;
             };
         }else if (tender == tenderTypes.ttReverseGLJ){
-            treeNode.data.tenderQuantity = treeNode.data.quantity;
+            //     treeNode.data.tenderQuantity = treeNode.data.quantity;   // 这句好像多余,因为调用calculate()时里面会重新计算tenderQuantity,有问题再放开AAAAA
             let qcObj = treeNode.data.quantityCoe;
             if (!qcObj || calcTools.isEmptyObject(qcObj)){
                 treeNode.data.quantityCoe = {labour: coe, material: coe, machine: coe, main: coe, equipment: coe};
@@ -2219,6 +2240,123 @@ class CalcProgram {
             projectObj.project.calcProgram.calculate(treeNode, false, false, tenderTypes.ttCalc);  // 再正向算
         };
     };
+
+    // 清理调价缓存数据
+    clearTenderCache(treeNode){
+        // 这些属性值为什么不定义在一个对象里?因为每次要判断对象是否存在,十分麻烦。不如直接写简单。分散书写,统一处理也很好用。
+        if (treeNode.data.tender_activeTotal) delete treeNode.data.tender_activeTotal;
+        if (treeNode.data.tender_activeTarget) delete treeNode.data.tender_activeTarget;
+        if (treeNode.data.tender_fullLoad) delete treeNode.data.tender_fullLoad;
+        if (treeNode.data.tender_distribute){
+            delete treeNode.data.targetTotalFee;
+            delete treeNode.data.targetUnitFee;
+            delete treeNode.data.tender_distribute;
+        };
+    };
+
+    // 调价:分摊前的准备工作。主要标记满载的结点。
+    prepareForDistribute(treeNode){
+        if (!treeNode) return;
+
+        if (treeNode.firstChild())
+            this.prepareForDistribute(treeNode.firstChild());
+
+        if (treeNode.children.length == 0){
+            // if (!treeNode.data.feesIndex['common'])
+            //     treeNode.data.tender_fullLoad = true
+            // else
+            //     treeNode.data.tender_fullLoad = false;
+        }
+        else{
+            let full = true;
+            for (let i = 0; i < treeNode.children.length; i++) {
+                let child = treeNode.children[i];
+                if (!child.data.tender_fullLoad && !calcTools.hasTargetTotalFee(child)){
+                    full = false;
+                    break;
+                };
+            }
+            if (full) {
+                let total = 0, target = 0;
+                for (let i = 0; i < treeNode.children.length; i++) {
+                    let child = treeNode.children[i];
+                    total = total + parseFloat(child.data.feesIndex['common'].totalFee);
+                    target = target + parseFloat(child.data.targetTotalFee);
+                };
+                treeNode.data.tender_activeTotal = total;
+                treeNode.data.tender_activeTarget = target;
+                treeNode.data.targetTotalFee = target;
+                treeNode.data.tender_distribute = 2;
+            };
+
+            treeNode.data.tender_fullLoad = full;
+        };
+
+        /*if (calcTools.isBill(treeNode) && (treeNode.data.tender_fullLoad != undefined)){
+            console.log(treeNode.data.name + ',tender_fullLoad: ' + treeNode.data.tender_fullLoad + ', target: ' + calcTools.hasTargetTotalFee(treeNode));
+        };*/
+
+/*        if (calcTools.isRationItem(treeNode)){
+            console.log(treeNode.data);
+        }*/
+
+        if (treeNode.nextSibling)
+            this.prepareForDistribute(treeNode.nextSibling);
+    };
+
+
+    // 调价之分摊目标合价:从父到子往下分摊。
+    distributeTargetTotalFee(treeNode){
+        if (!treeNode) return;
+
+        if (treeNode.data.feesIndex['common']){     // 空清单忽略
+            // 默认能够执行到这里时每个节点已经被初始化,缓存已删除
+            treeNode.data.tender_activeTotal = treeNode.data.feesIndex['common'].totalFee;
+
+            // 开始分摊:只分摊自有目标金额、从父结点分摊到的金额(不分摊子结点摊上来的金额)
+            if (calcTools.hasTargetTotalFee(treeNode) && !(treeNode.data.tender_distribute && treeNode.data.tender_distribute == 2)){
+                treeNode.data.tender_activeTarget = treeNode.data.targetTotalFee;
+
+                // 先把会破坏金额比例关系的孩子排除:1.有目标金额的 2.满载的(孙子全满,没有分摊空间,所以实质上该孩子的金额已被锁死无法分摊)
+                for (let i = 0; i < treeNode.children.length; i++) {
+                    let child = treeNode.children[i];
+                    if (!child.data.feesIndex['common']) continue;     // 无计算金额的(如空清单)当它不存在
+
+                    child.data.tender_activeTotal = child.data.feesIndex['common'].totalFee;
+
+                    if (calcTools.hasTargetTotalFee(child)){
+                        child.data.tender_activeTarget = child.data.targetTotalFee;
+                        console.log(treeNode.data.tender_activeTotal);
+                        console.log(child.data.tender_activeTotal);
+                        treeNode.data.tender_activeTotal = treeNode.data.tender_activeTotal - child.data.tender_activeTotal;
+                        treeNode.data.tender_activeTarget = treeNode.data.tender_activeTarget - child.data.tender_activeTarget;
+                    };
+                }
+
+                if (treeNode.data.tender_activeTotal != 0){
+                    let coe = (treeNode.data.tender_activeTarget / treeNode.data.tender_activeTotal).toDecimal(decimalObj.process);
+
+                    for (let i = 0; i < treeNode.children.length; i++) {
+                        let child = treeNode.children[i];
+                        if (!child.data.feesIndex['common']) continue;
+                        if (!calcTools.hasTargetTotalFee(child)){
+                            child.data.tender_activeTarget = (coe * child.data.tender_activeTotal).toDecimal(decimalObj.decimal('totalPrice', treeNode));
+                            child.data.targetTotalFee = child.data.tender_activeTarget;
+                            child.data.tender_distribute = 1;        // 1表示分摊金额来自父结点。2表示分摊金额来自孩子结点。
+                        }
+                    }
+                };
+
+            };
+        }
+
+        if (treeNode.firstChild())
+            this.distributeTargetTotalFee(treeNode.firstChild());
+
+        if (treeNode.nextSibling)
+            this.distributeTargetTotalFee(treeNode.nextSibling);
+    };
+
     setRationMap(){
         if(this.rationMap == null){
             this.rationMap = {};
@@ -2234,6 +2372,7 @@ class CalcProgram {
             this.pgljMap = _.indexBy(projectObj.project.projectGLJ.datas.gljList, 'id');
         }
     };
+
     getGljArrByRation(ration){
         if (ration.type == rationType.gljRation){
             let glj = JSON.parse(JSON.stringify(ration));
@@ -2248,7 +2387,7 @@ class CalcProgram {
             result = gljOprObj.combineWithProjectGlj(result,false,ration,this.pgljMap);
             return result;
         }
-    }
+    };
 };
 
 // export default analyzer;

+ 2 - 6
web/building_saas/main/js/models/project_glj.js

@@ -869,12 +869,8 @@ ProjectGLJ.prototype.getTenderMarketPrice = function (glj,isRadio) {
     return gljUtil.getMarketPrice(glj,proGLJ.datas,calcOptions,decimalObj,isRadio,_,scMathUtil,tenderCoe);
 };
 
-ProjectGLJ.prototype.getTenderPriceCoe = function(glj){
-    let tenderCoe = 1;
-    if (!glj.is_adjust_price&&projectObj.project.property.tenderSetting && gljUtil.isDef(projectObj.project.property.tenderSetting.gljPriceTenderCoe) ){
-        tenderCoe = parseFloat(projectObj.project.property.tenderSetting.gljPriceTenderCoe);
-    }
-    return tenderCoe
+ProjectGLJ.prototype.getTenderPriceCoe = function(glj,tproperty){
+    return gljUtil.getTenderPriceCoe(glj,tproperty);
 };
 
 ProjectGLJ.prototype.isEstimateType = function(type){

+ 65 - 30
web/building_saas/main/js/views/glj_col.js

@@ -15,10 +15,13 @@ let gljCol = {
             {headerName: "定额价", headerWidth: 65, dataCode: "basePrice", dataType: "Number", hAlign: "right"},//, decimalField: "glj.unitPrice"
             {headerName: "定额消耗", headerWidth: 65, dataCode: "rationItemQuantity", dataType: "Number", hAlign: "right", decimalField: "glj.quantity"},   // dataType: "Number", formatter: "0.00"
             {headerName: "总消耗量", headerWidth: 80, dataCode: "totalQuantity", dataType: "Number", hAlign: "right", decimalField: "glj.quantity"},
-            {headerName: "暂估", headerWidth: 45, dataCode: "isEstimate", dataType: "String", hAlign: "center", vAlign: "center", cellType: "checkBox"}
+            {headerName: "暂估", headerWidth: 45, dataCode: "isEstimate", dataType: "String", hAlign: "center", vAlign: "center", cellType: "checkBox"},
+            {headerName: "调后市场价", headerWidth: 80, dataCode: "tenderPrice", dataType: "Number", hAlign: "right", visible: false},
+            {headerName: "调后消耗量", headerWidth: 80, dataCode: "tenderQuantity", dataType: "Number", hAlign: "right", visible: false}
         ],
         view: {
-            lockColumns: [ "adjustPrice", "rationItemQuantity", "quantity", "totalQuantity", "isEstimate"],//这里以后改成dataCode好一点
+            lockColumns: [ "adjustPrice", "rationItemQuantity", "quantity", "totalQuantity", "isEstimate",
+                "tenderPrice", "tenderQuantity"],//这里以后改成dataCode好一点
             rowHeaderWidth:25
         },
         getStyle:function (data) {
@@ -33,36 +36,39 @@ let gljCol = {
     },
     project_glj_setting:{
         header: [
-            {headerName: "编码", headerWidth: 80, dataCode: "code", dataType: "String"},
-            {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String",cellType:'tipsCell'},
-            {headerName: "规格型号", headerWidth: 120, dataCode: "specs", hAlign: "left", dataType: "String",cellType:'tipsCell'},
-            {headerName: "单位", headerWidth: 45, dataCode: "unit", hAlign: "center", dataType: "String"},
-            {headerName: "类型", headerWidth: 45, dataCode: "short_name", hAlign: "center", dataType: "String"},
-            {headerName: "市场价", headerWidth: 70, dataCode: "marketPrice", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:"glj.unitPrice"
-            {headerName: "调整价", headerWidth: 70, dataCode: "adjustPrice", hAlign: "right", dataType: "Number"},//,decimalField:"glj.unitPrice"
-            {headerName: "定额价", headerWidth: 70, dataCode: "basePrice", hAlign: "right", dataType: "Number",validator:"number"},//decimalField:'glj.unitPrice',
-            {headerName: "总消耗量", headerWidth: 90, dataCode: "quantity", hAlign: "right", dataType: "Number",decimalField:'glj.quantity'},
-            {headerName: "暂估", headerWidth: 45, dataCode: "is_evaluate", hAlign: "center", dataType: "String",cellType:'checkBox'},
-            {headerName: "主要\n材料", headerWidth: 45, dataCode: "is_main_material", hAlign: "center", dataType: "String",cellType:'checkBox'},
-            {headerName: "不调价", headerWidth: 55, dataCode: "is_adjust_price", dataType: "String",cellType: "checkBox"},
-            {headerName: "不计税设备", headerWidth: 55, dataCode: "no_tax_eqp", dataType: "String",cellType: "checkBox"},
-            {headerName: "评标材料", headerWidth: 35, dataCode: "is_eval_material", dataType: "String",cellType: "checkBox"},
-            {headerName: "供货方式", headerWidth: 70, dataCode: "supply", hAlign: "center", dataType: "String",cellType:'comboBox',editorValueType:true,options:supplyComboMap},
-            {headerName: "甲供数量", headerWidth: 90, dataCode: "supply_quantity", hAlign: "right", dataType: "Number",validator:"number",decimalField:'glj.quantity'},
-            {headerName: "三材类别", headerWidth: 70, dataCode: "materialType", hAlign: "center", dataType: "String",cellType:'comboBox',editorValueType:true,options:materialComboMap},
-            {headerName: "三材系数", headerWidth: 70, dataCode: "materialCoe", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:'material'
-            {headerName: "交货方式", headerWidth: 70, dataCode: "delivery", hAlign: "left", dataType: "String"},
-            {headerName: "送达地点", headerWidth: 70, dataCode: "delivery_address", hAlign: "left", dataType: "String"},
-            {headerName: "产地", headerWidth: 80, dataCode: "originPlace", hAlign: "left", dataType: "String"},
-            {headerName: "厂家", headerWidth: 80, dataCode: "vender", hAlign: "left", dataType: "String"},
-            {headerName: "质量等级", headerWidth: 80, dataCode: "qualityGrace", hAlign: "left", dataType: "String"},
-            {headerName: "品牌", headerWidth: 80, dataCode: "brand", hAlign: "left", dataType: "String"},
-            {headerName: "备注", headerWidth: 100, dataCode: "remark", hAlign: "left", dataType: "String"}
+            {headerName: "编码", headerWidth: 80, dataCode: "code", dataType: "String",spanRows: [2]},
+            {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String",cellType:'tipsCell',spanRows: [2]},
+            {headerName: "规格型号", headerWidth: 120, dataCode: "specs", hAlign: "left", dataType: "String",cellType:'tipsCell',spanRows: [2]},
+            {headerName: "单位", headerWidth: 45, dataCode: "unit", hAlign: "center", dataType: "String",spanRows: [2]},
+            {headerName: "类型", headerWidth: 45, dataCode: "short_name", hAlign: "center", dataType: "String",spanRows: [2]},
+            {headerName: "市场价", headerWidth: 70, dataCode: "marketPrice", hAlign: "right", dataType: "Number",validator:"number",spanRows: [2]},//,decimalField:"glj.unitPrice"
+            {headerName: "调整价", headerWidth: 70, dataCode: "adjustPrice", hAlign: "right", dataType: "Number",spanRows: [2]},//,decimalField:"glj.unitPrice"
+            {headerName: "定额价", headerWidth: 70, dataCode: "basePrice", hAlign: "right", dataType: "Number",validator:"number",spanRows: [2]},//decimalField:'glj.unitPrice',
+            {headerName: "总消耗量", headerWidth: 90, dataCode: "quantity", hAlign: "right", dataType: "Number",decimalField:'glj.quantity',spanRows: [2]},
+            {headerName: "暂估", headerWidth: 45, dataCode: "is_evaluate", hAlign: "center", dataType: "String",cellType:'checkBox',spanRows: [2]},
+            {headerName: "主要\n材料", headerWidth: 45, dataCode: "is_main_material", hAlign: "center", dataType: "String",cellType:'checkBox',spanRows: [2]},
+            {headerName: "不计税设备", headerWidth: 55, dataCode: "no_tax_eqp", dataType: "String",cellType: "checkBox",spanRows: [2]},
+            {headerName: "评标材料", headerWidth: 35, dataCode: "is_eval_material", dataType: "String",cellType: "checkBox",spanRows: [2]},
+            {headerName: "供货方式", headerWidth: 70, dataCode: "supply", hAlign: "center", dataType: "String",cellType:'comboBox',editorValueType:true,options:supplyComboMap,spanRows: [2]},
+            {headerName: "甲供数量", headerWidth: 90, dataCode: "supply_quantity", hAlign: "right", dataType: "Number",validator:"number",decimalField:'glj.quantity',spanRows: [2]},
+            {headerName: "三材类别", headerWidth: 70, dataCode: "materialType", hAlign: "center", dataType: "String",cellType:'comboBox',editorValueType:true,options:materialComboMap,spanRows: [2]},
+            {headerName: "三材系数", headerWidth: 70, dataCode: "materialCoe", hAlign: "right", dataType: "Number",validator:"number",spanRows: [2]},//,decimalField:'material'
+            {headerName: "交货方式", headerWidth: 70, dataCode: "delivery", hAlign: "left", dataType: "String",spanRows: [2]},
+            {headerName: "送达地点", headerWidth: 70, dataCode: "delivery_address", hAlign: "left", dataType: "String",spanRows: [2]},
+            {headerName: "产地", headerWidth: 80, dataCode: "originPlace", hAlign: "left", dataType: "String",spanRows: [2]},
+            {headerName: "厂家", headerWidth: 80, dataCode: "vender", hAlign: "left", dataType: "String",spanRows: [2]},
+            {headerName: "质量等级", headerWidth: 80, dataCode: "qualityGrace", hAlign: "left", dataType: "String",spanRows: [2]},
+            {headerName: "品牌", headerWidth: 80, dataCode: "brand", hAlign: "left", dataType: "String",spanRows: [2]},
+            {headerName: "备注", headerWidth: 100, dataCode: "remark", hAlign: "left", dataType: "String",spanRows: [2]},
+            {headerName: "不调价", headerWidth: 55, dataCode: "is_adjust_price", dataType: "String",cellType: "checkBox",spanRows: [2]},
+            {headerName: ["调价后","市场价"], headerWidth: 75, dataCode: "tenderPrice", hAlign: "right", dataType: "Number",validator:"number",spanCols: [2,1], visible: false},
+            {headerName: ["","总消耗量"], headerWidth: 90, dataCode: "tenderQuantity", hAlign: "right", dataType: "Number",decimalField:'glj.quantity',spanCols: [0,1], visible: false}
         ],
         view: {
             lockColumns: ["code","name","specs","unit","short_name","tenderPrice","adjustPrice","quantity","tenderQuantity"]
         },
-        frozenCols:4
+        frozenCols:4,
+        headRows:2
     },
     mixRatio_Setting:{
         header:[
@@ -232,19 +238,48 @@ let gljCol = {
             setting.view.lockColumns = newArray;
         }
     },
-    initGljCol:function (showAdjustPrice) {
+    initGljCol:function (showAdjustPrice, showTenderFields) {
         let me = gljCol;
         if(showAdjustPrice !== true){
             me.removeCol('adjustPrice',me.ration_glj_setting);
             me.removeCol('adjustPrice',me.project_glj_setting);
             me.removeCol('adjustPrice',me.mixRatio_Setting);
-        }
+        };
+        me.showTenderFields(showTenderFields, false);
+
         gljOprObj.setting = me.ration_glj_setting;
         projectGljObject.projectGljSetting = me.project_glj_setting;
         projectGljObject.mixRatioSetting = me.mixRatio_Setting;
         me.setScopeFormater();
         gljOprObj.scopeSetting = me.scopeSetting;
     },
+    showTenderFields: function (showFields = false, needRefresh = false){
+        let me = gljCol;
+
+        let PGLJHeader = me.project_glj_setting.header;
+        for (let e of PGLJHeader){
+            if (e.dataCode == 'tenderPrice' || e.dataCode == 'tenderQuantity'){
+                e.visible = showFields;
+            }
+        };
+
+        let RGLJHeader = me.ration_glj_setting.header;
+        for (let e of RGLJHeader){
+            if (e.dataCode == 'tenderPrice' || e.dataCode == 'tenderQuantity'){
+                e.visible = showFields;
+            }
+        };
+
+        if (needRefresh){
+            if(projectGljObject.projectGljSpread) {
+                projectGljObject.projectGljSheet = projectGljObject.projectGljSpread .getSheet(0);
+                projectGljObject.initSheet(projectGljObject.projectGljSheet, projectGljObject.projectGljSetting);
+            }
+            if (subSpread) {
+                gljOprObj.initSheet(subSpread.getSheet(0), false);
+            }
+        };
+    },
     setScopeFormater:function () {
         // 综合单价、综合合价,小数部分应补0对齐。  CSL
         for(let col of this.scopeSetting.cols){

+ 1 - 1
web/building_saas/main/js/views/project_glj_view.js

@@ -80,7 +80,7 @@ let projectGljObject={
         this.projectGljSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onProjectGljSelectionChange);
         this.projectGljSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onProjectGljEditStarting);
         this.projectGljSheet.name('projectGljSheet');
-        this.projectGljSheet.setRowHeight(0, 36, 1);
+        //this.projectGljSheet.setRowHeight(0, 36, 1);
     },
     initMixRatio:function () {
         let me = projectGljObject;

+ 61 - 28
web/building_saas/main/js/views/tender_price_view.js

@@ -48,7 +48,7 @@ let tender_obj={
         this.tenderSheet = this.tenderSpread.getSheet(0);
         this.tenderTree = cacheTree.createNew(this);
         this.tenderTreeSetting = this.createTenderTreeSetting();
-        console.log(this.tenderTreeSetting);
+        // console.log(this.tenderTreeSetting);
         TREE_SHEET_HELPER.initSetting($('#tenderSpread')[0], this.tenderTreeSetting );
         this.tenderTreeSetting.setAutoFitRow = MainTreeCol.getEvent("setAutoFitRow");
         this.tenderController = TREE_SHEET_CONTROLLER.createNew(this.tenderTree, this.tenderSheet, this.tenderTreeSetting);
@@ -176,11 +176,18 @@ let tender_obj={
         //在目标造价综合单价中输入数值,按项目属性中的清单单价精度取舍,并清空当前行的目标造价综合合价
         if(dataCode == 'targetUnitFee'){
             value = scMathUtil.roundForObj(value,getDecimal('unitPrice',node));
-            updateData?updateData.data["targetTotalFee"] = null:'';
+	    // updateData?updateData.data["targetTotalFee"] = null:'';
+            updateData?updateData.data["targetTotalFee"] = (value * node.data.quantity).toDecimal(decimalObj.decimal('totalPrice', node)):'';
         }
         if(dataCode == 'targetTotalFee'){
             value = scMathUtil.roundForObj(value,getDecimal('totalPrice',node));
-            updateData?updateData.data["targetUnitFee"] = null:'';
+            // updateData?updateData.data["targetUnitFee"] = null:'';
+            let rst = '';
+            if (updateData){
+                if (calcTools.hasQuantity(node))
+                   rst = (value / node.data.quantity).toDecimal(decimalObj.decimal('unitPrice', node));
+            };
+            updateData.data["targetUnitFee"] = rst;
         }
         updateData.data[dataCode] = value;
         updateNodes.push(updateData);
@@ -207,10 +214,10 @@ let tender_obj={
     },
     onEnterCell : function (sender,args) {
         let me = tender_obj, row = args.row, col = args.col;
-        if ([8, 9].includes(col)){
+        if ([7, 8].includes(col)){                                  // 目标单价、目标合价
             let node = me.tenderTree.items[row];
-            if (node.children && node.children.length > 0) {   // 父结点只读
-                me.tenderSheet.getCell(row, col).locked(true);// = true;
+            if (calcTools.isCalcBaseBill(node)){                    // 公式结点只读
+                me.tenderSheet.getCell(row, col).locked(true);
             }
         }
     },
@@ -255,26 +262,14 @@ let tender_obj={
             }
         }
     },
-    cleanCacheCoes: function (){
-        for(let node of tender_obj.tenderTree.items){
-            if (node.data.rationQuantityCoe) node.data.rationQuantityCoe = null;
-            let qcObj = node.data.quantityCoe;
-            if (qcObj){
-                for (let pn in qcObj){
-                    qcObj[pn] = null;
-                };
-            };
-        };
-    },
-
     calcOptionsChecking:function (option) {//调整选项检查,返回需要更新的数组
         let datas = [];
         let me = tender_obj;
         for(let node of me.tenderTree.items){
             let tem_updateData = {type:node.sourceType,data:{}};
-            if(option == 'coeBase') { //当值为“根据调整系数计算报价”时,清空目标报价。
+            if(option == 'coeBase') {                           // 正向:当值为“根据调整系数计算报价”时,清空目标报价。
                 me.cleanTargetPrice(tem_updateData,node);
-            }else if(option == 'priceBase'){//当值为“根据报价计算调整系数”时,清空调整系数。
+            }else if(option == 'priceBase'){                    // 反向:当值为“根据报价计算调整系数”时,清空调整系数。
                 me.cleanTenderCoe(tem_updateData,node);
             }
             if(!_.isEmpty(tem_updateData.data)){//如果需要更新
@@ -398,28 +393,60 @@ let tender_obj={
         let tenderSetting = projectObj.project.property.tenderSetting;
         let calcPriceOption = tenderSetting && tenderSetting.calcPriceOption? tenderSetting.calcPriceOption :"coeBase";
         let gljPriceTenderCoe = tenderSetting && tenderSetting.gljPriceTenderCoe?tenderSetting.gljPriceTenderCoe:1;
+        let showTenderFields = tenderSetting && tenderSetting.showTenderFields?tenderSetting.showTenderFields:false;
         $('#calcPriceOption').val(calcPriceOption);
         $('#gljPriceTenderCoe').val(gljPriceTenderCoe);
         if(calcPriceOption == 'coeBase'){
-            if(!projectReadOnly){
-                $('#tenderPrice').removeAttr("disabled");
-            }
+            $('#gljPriceTenderCoe').removeAttr("disabled");
             $('#tenderGLJQuantity').attr("disabled",true);
             $('#tenderRationQuantity').attr("disabled",true);
+            if(!projectReadOnly){
+                $('#tenderPrice').removeAttr("disabled");
+            };
         }else {
-            $('#tenderPrice').attr("disabled",true);
+            $('#gljPriceTenderCoe').attr("disabled",true);
             $('#tenderGLJQuantity').removeAttr("disabled");
             $('#tenderRationQuantity').removeAttr("disabled");
-        }
-        //gljPriceTenderCoe
+            $('#tenderPrice').attr("disabled",true);
+        };
+        $('#cbShowTenderFields').prop("checked", showTenderFields);
     },
     doTenderCalc: function(tender){
-        if (tender != tenderTypes.ttCalc)
-            tender_obj.cleanCacheCoes();
+        function initReverseTenderDatas (){
+            for(let node of tender_obj.tenderTree.items){
+                if (node.data.rationQuantityCoe) node.data.rationQuantityCoe = null;
+                let qcObj = node.data.quantityCoe;
+                if (qcObj){
+                    for (let pn in qcObj){
+                        qcObj[pn] = null;
+                    };
+                };
+                projectObj.project.calcProgram.clearTenderCache(node);
+            };
+            // 反向调价时人材机单价调整系数要归1:因为既可以调量又可以调价,以哪个为基准进行反调?过于复杂,仅以通用的调量逻辑为基准即可满足需求。
+            if (projectObj.project.property.tenderSetting && projectObj.project.property.tenderSetting.gljPriceTenderCoe
+                && (projectObj.project.property.tenderSetting.gljPriceTenderCoe != 1)){
+                projectObj.project.property.tenderSetting.gljPriceTenderCoe = 1;    // 修改缓存值,用于计算
+                projectObj.project.property.needRestoreGgljPriceTenderCoe = true;   // 标记:需保存入库
+            }
+
+        };
+
+        if (tender != tenderTypes.ttCalc) initReverseTenderDatas();
         let callback = function () {
             projectObj.project.saveProperty('hasTender', true);
+            if (projectObj.project.property.needRestoreGgljPriceTenderCoe){         // 入库存储,清理标记,刷新UI显示
+                projectObj.project.saveProperty('tenderSetting.gljPriceTenderCoe', 1);
+                delete projectObj.project.property.needRestoreGgljPriceTenderCoe;
+                $('#gljPriceTenderCoe').val(1);
+            }
+
             tender_obj.showTenderData();
         };
+        if (tender == tenderTypes.ttReverseGLJ || tender == tenderTypes.ttReverseRation){
+            projectObj.project.calcProgram.prepareForDistribute(tender_obj.tenderTree.roots[0]);
+            projectObj.project.calcProgram.distributeTargetTotalFee(tender_obj.tenderTree.roots[0]);
+        };
         projectObj.project.calcProgram.calcAllNodesAndSave(calcAllType.catAll, callback, tender);
     }
 };
@@ -494,4 +521,10 @@ $(function () {
         tender_obj.doTenderCalc(tenderTypes.ttReverseRation);
     });
 
+    $('#cbShowTenderFields').on('click', function () {
+        let showFields = $('#cbShowTenderFields').prop("checked");
+        projectObj.project.saveProperty('tenderSetting.showTenderFields', showFields);
+        gljCol.showTenderFields(showFields, true);
+    });
+
 });