zhangweicheng 5 роки тому
батько
коміт
180cb7fc43

+ 1 - 1
modules/all_models/divide_setting.js

@@ -7,7 +7,7 @@ let divideSchema = {
   divideList:[Schema.Types.Mixed],
   ration_gljs:[Schema.Types.Mixed],
   ration_coes:[Schema.Types.Mixed],
-  bills:[Schema.Types.Mixed]
+  divideType:Number//分摊方式(3种)
 }
 
 mongoose.model("divide_setting", new Schema(divideSchema, {versionKey: false, collection: "divide_setting"}));

+ 1 - 0
modules/all_models/ration.js

@@ -73,6 +73,7 @@ let rationSchema = new Schema({
     ruleText: String,                            // 计算规则
     prefix: {type: String, default: ''},                              //定额是补充、借用时用  补 借
     referenceRationID:String,//如果是通过模板关联子目生成的定额,这里记录对应的主定额ID
+    divideID:String,//分摊项生成的量价关联的ID
 
     //工料机特有属性
     projectGLJID:Number,  //项目工料机ID

+ 4 - 0
modules/main/controllers/divide_controller.js

@@ -8,6 +8,10 @@ let controller = {
     updateItem:async function(req) {
         let data = req.body.data;
         return await divideFacade.updateItem(JSON.parse(data));
+    },
+    updateCoeAdjust:async function(req){
+      let data = req.body.data;
+      return await divideFacade.updateCoeAdjust(JSON.parse(data),req.session.sessionCompilation);
     }
    
 };

+ 0 - 9
modules/main/controllers/project_controller.js

@@ -81,15 +81,6 @@ module.exports = {
         res.json(result);
     },
     updateNodes:async function (req,res) {
-    /*    var data = JSON.parse(req.body.data);
-        project_facade.updateNodes(data, function (err, message, result) {
-            if (err) {
-                logger.err(err);
-                callback(req, res, err, message, null);
-            } else {
-                callback(req, res, err, message, result);
-            }
-        });*/
         let result={
             error:0
         }

+ 104 - 7
modules/main/facade/divide_facade.js

@@ -1,11 +1,14 @@
 module.exports = {
   getData: getData,
-  updateItem:updateItem
+  updateItem:updateItem,
+  updateCoeAdjust:updateCoeAdjust
 };
 
 let mongoose = require('mongoose');
 let divideModel = mongoose.model("divide_setting");
 let consts = require('../models/project_consts');
+let calculate_facade = require("../../ration_glj/facade/glj_calculate_facade");
+let ration_glj_facade = require("../../ration_glj/facade/ration_glj_facade");
 let projectConsts = consts.projectConst;
 const uuidV1 = require('uuid/v1');
 
@@ -13,6 +16,8 @@ const uuidV1 = require('uuid/v1');
 async function updateItem(data){
   let ID = data.ID;
   let tasks= [];
+  let udatas = [];
+  let proportioRationID = null;
   for(let u of data.updateDatas){
     if(u.type == 'add'){
       tasks.push({updateOne: {filter: {ID: ID}, update: {"$push":{divideList:u.doc} }}});
@@ -20,10 +25,31 @@ async function updateItem(data){
     if(u.type == "update"){
       let ndoc = {};
       let pre = "divideList.$."
+      if(u.model) pre= u.model+".$."; 
       for(let key in u.doc){
         ndoc[pre+key] = u.doc[key]
       }
-      tasks.push({updateOne: {filter: {"ID": ID,"divideList.ID":u.ID}, update: ndoc}});
+      if(u.model){//改定额工料机的自定消耗或者子目换算时,要重算消耗量,所以就不走task流程了,另外算
+        let query = {"ID": ID};
+        query[u.model+".ID"] = u.ID;
+        if(u.updateProportion == true){//更新稳定土的时候要先把所有定额工料机更新后,再计算消耗量,所以放在builkWrite后面
+          tasks.push({updateOne: {filter: query, update: ndoc}});
+          proportioRationID = u.rationID;
+        }else{
+          await divideModel.update(query,ndoc);
+          //重新计算消耗量
+          let [ntasks,ndatas] = await calculate_facade.calculateQuantityFromDivide(ID,u.rationID);
+          if(ntasks.length > 0) tasks = tasks.concat(ntasks);
+          if(ndatas.length > 0) udatas = udatas.concat(ndatas);
+        }   
+      }else if(u.updateAss == true){//修改辅助定额
+        await divideModel.update({"ID": ID,"divideList.ID":u.ID},ndoc);
+        let [ntasks,ndatas] = await calculate_facade.calculateQuantityFromDivide(ID,u.ID);
+        if(ntasks.length > 0) tasks = tasks.concat(ntasks);
+        if(ndatas.length > 0) udatas = udatas.concat(ndatas);
+      }else{
+        tasks.push({updateOne: {filter: {"ID": ID,"divideList.ID":u.ID}, update: ndoc}});
+      }
     }
     if(u.type == "delete"){
       tasks.push({updateOne: {filter: {ID: ID}, update: {"$pull":{divideList:{ID:u.ID}} }}});
@@ -34,16 +60,90 @@ async function updateItem(data){
           { multi: true })
       }
     }
-
   }
 
   if(tasks.length > 0) await divideModel.bulkWrite(tasks);
+  if(udatas.length > 0) data.updateDatas = data.updateDatas.concat(udatas);
 
+  if(proportioRationID!=null){//说明更新了稳定土
+    let [ptasks,pdatas] = await calculate_facade.calculateQuantityFromDivide(ID,proportioRationID);
+    if(ptasks.length > 0) await divideModel.bulkWrite(ptasks);
+    if(pdatas.length > 0) data.updateDatas = data.updateDatas.concat(pdatas);
+  }
 
 
   return data;
 }
 
+async function updateCoeAdjust(data,compilation){
+  let replace = [],projectGLJList=[],ration_gljs=[];
+  let result = {updateDatas:[]}
+  let ndoc = {};
+  let pre = "ration_coes.$."
+  for(let key in data.doc){
+    ndoc[pre+key] = data.doc[key]
+  }
+  await divideModel.update({ID:data.divideID,"ration_coes.ID":data.ID},ndoc);
+  result.updateDatas.push({ID:data.ID,type:'update',model:'ration_coes',doc:data.doc});
+   //添加单个工料机的情况
+   if (data.add.length > 0){
+     let [tg,pl] = await ration_glj_facade.insertAddTypeGLJ(data.add,compilation,false);
+     await divideModel.update({ID:data.divideID},{$push:{ration_gljs:{$each:tg}}});
+     ration_gljs = ration_gljs.concat(tg);
+     if(pl.length > 0) projectGLJList = projectGLJList.concat(pl);
+   }
+  //删除的情况 
+  if(data.delete.length > 0){
+    await divideModel.update({ID:data.divideID},{$pull:{ration_gljs:{$in: data.delete}}});
+  } 
+  //替换工料机的情况
+  if (data.replace.length > 0){
+    let rationGLJlist = await getRationGLJs(data.divideID,data.rationID);
+    for(let r of data.replace){
+        let ration_glj_ID = r.ID;
+        if(data.toCommercial == true) ration_glj_ID = r.originalID;
+        let r_result = await  ration_glj_facade.replaceGLJByData(r,compilation,false,rationGLJlist);
+        let rdoc = {};
+        for(let key in r_result.data){
+          rdoc[pre+key] = result.data[key]
+        }
+        //修改定额工料机
+        await divideModel.update({ID:data.divideID,"ration_gljs.ID":ration_glj_ID},rdoc);
+        result.updateDatas.push({ID:data.ID,type:'update',model:'ration_gljs',doc:r_result.data});
+        projectGLJList.push(r_result.projectGLJ);
+        
+        //新增定额工料机
+        if(r_result.newRecodes.length > 0){
+          await divideModel.update({ID:data.divideID},{$push:{ration_gljs:{$each:r_result.newRecodes}}});
+          ration_gljs = ration_gljs.concat(r_result.newRecodes);
+        }
+        //删除定额工料机
+        if(r_result.deleteList.length > 0){
+          await divideModel.update({ID:data.divideID},{$pull:{ration_gljs:{$in: r_result.deleteList}}});
+          data.delete = data.delete.concat(r_result.deleteList);
+        } 
+    }
+  }
+
+  let [ptasks,pdatas] = await calculate_facade.calculateQuantityFromDivide(data.divideID,data.rationID);
+  if(ptasks.length > 0) await divideModel.bulkWrite(ptasks);
+  if(pdatas.length > 0) result.updateDatas = result.updateDatas.concat(pdatas);
+  result.ration_gljs= ration_gljs;
+  result.projectGLJList = projectGLJList;
+  result.delete = data.delete;
+
+  return result;
+}
+
+
+async function getRationGLJs(divideID,rationID){
+  let gljList = [];
+  let divide_setting = await divideModel.findOne({ID:divideID}).lean();
+  for(let rg of divide_setting.ration_gljs){
+    if(rg.rationID == rationID) gljList.push(rg);
+  }
+  return gljList;
+}
 
 function getData(projectID, callback) {
   divideModel.findOne({projectID: projectID}, '-_id', async function (err, datas) {
@@ -55,8 +155,7 @@ function getData(projectID, callback) {
             projectID:projectID,
             divideList:[],
             ration_gljs:[],
-            ration_coes:[],
-            bills:[]
+            ration_coes:[]
           }
           await divideModel.create(datas);
           callback(0, projectConsts.DIVIDE_SETTING, datas);
@@ -68,6 +167,4 @@ function getData(projectID, callback) {
     };
   });
 
-
-
 }

+ 64 - 140
modules/main/facade/project_facade.js

@@ -6,7 +6,6 @@ module.exports = {
     markUpdateProject:markUpdateProject,
     removeProjectMark:removeProjectMark,
     updateNodes:updateNodes,
-    calcInstallationFee:calcInstallationFee,
     saveProperty: saveProperty,
     getDefaultColSetting: getDefaultColSetting,
     markProjectsToChange:markProjectsToChange,
@@ -38,77 +37,13 @@ const { fixedFlag } = require('../../../public/common_constants');
 import GLJListModel from "../../glj/models/glj_list_model";
 const projectDao = require('../../pm/models/project_model').project;
 
-
-
-async function calcInstallationFee(data) {
-    let result={};
-    let projectGLJList = [];
-    let billTasks  = generateTasks(data.bills,data.useID);
-    let rationTasks = generateTasks(data.ration,data.useID);
-    if(billTasks.length>0){
-        await bill_model.model.bulkWrite(billTasks);
-    }
-    console.log(rationTasks);
-    if(rationTasks.length>0){
-        await ration_model.model.bulkWrite(rationTasks);
-    }
-    //如果删除定额,需要删除对应的工料机
-    if(data.ration.delete.length>0){
-        let rationIDS = _.map(data.ration.delete,'ID');
-        await ration_glj_model.deleteMany({projectID: data.ration.delete[0].projectID, rationID: {"$in": rationIDS}});//删除定额工料机
-    }
-
-    let rationGLJTasks = [];
-    let updateList = [];
-    if(data.ration.update.length>0){//如果有需要更新的定额工料机
-        for(let ur of data.ration.update){
-            for(let g of ur.glj){
-                let gTasks = {
-                    updateOne:{
-                        filter:{
-                            ID:g.ID,
-                            projectID:g.projectID
-                        },
-                        update :{
-                            quantity:g.quantity,
-                            rationItemQuantity:g.rationItemQuantity
-                        }
-                    }
-                };
-                rationGLJTasks.push(gTasks);
-                updateList.push(g);
-            }
-        }
-    }
-    if(rationGLJTasks.length>0){
-       await ration_glj_model.bulkWrite(rationGLJTasks);
-    }
-
-    let newGljList = [];
-    if(data.ration.add.length>0){//新增的安装子目要增加对应的工料机
-        for(let nr of data.ration.add){
-            for(let tkey in nr.glj){
-                let [newRecode,projectGLJ] = await addInstallationGLJ(nr.glj[tkey]);
-                newGljList.push(newRecode);
-            }
-        }
-    }
-    if(newGljList.length>0){
-        await ration_glj_model.insertMany(newGljList);
-    }
-    result.update = updateList;
-    result.add = newGljList;
-    return result;
+async function createRationGLJData(glj) {
+  glj.ID = uuidV1();
+  let [info,projectGLJ ] = await ration_glj_facade.getInfoFromProjectGLJ(glj);
+  let newRecode  = ration_glj_facade.createNewRecord(info);
+  return [newRecode,projectGLJ];
 }
 
-async function addInstallationGLJ(glj) {
-    glj.ID = uuidV1();
-    let [info,projectGLJ ] = await ration_glj_facade.getInfoFromProjectGLJ(glj);
-    let newRecode  = ration_glj_facade.createNewRecord(info);
-    return [newRecode,projectGLJ];
-}
-
-
 function generateTasks(data,userID) {
     let tasks=[];
     let deleteInfo={deleted: true, deleteDateTime: new Date(), deleteBy: userID};
@@ -151,81 +86,70 @@ function generateTasks(data,userID) {
 }
 
 async function updateNodes(datas){
-    let nodeGroups = _.groupBy(datas,'type');
-    let rationTasks = [];
-    let billTasks = [];
-    let rationGLJTasks = [];
-    let projectGLJTasks = [];
-    let projectTasks = [];
-    let rationTemplateTasks = [];
-    let asyncTasks = [];
-    for(let type in nodeGroups){
-        for(let node of nodeGroups[type]){
-            if(type == projectConsts.BILLS){
-                billTasks.push(getTask(node));
-            }else if(type == projectConsts.RATION){
-                rationTasks.push(getTask(node));
-            }else if(type == projectConsts.RATION_GLJ){
-                rationGLJTasks.push(getTask(node));
-            }else if(type == projectConsts.PROJECTGLJ){
-                projectGLJTasks.push(getTask(node,'id'));
-            }else if(type == projectConsts.PROJECT){
-                projectTasks.push(getTask(node));
-            }else if(type == projectConsts.RATION_TEMPLATE){
-                rationTemplateTasks.push(getTask(node))
-            }
+  let nodeGroups = _.groupBy(datas,'type');
+  let asyncTasks = [];
+  let deleteRationIDs=[];
+  let taskMap = {};
+  taskMap[projectConsts.BILLS] = {tasks:[],model:bill_model.model};
+  taskMap[projectConsts.RATION] = {tasks:[],model:ration_model.model};
+  taskMap[projectConsts.RATION_GLJ] = {tasks:[],model:ration_glj_model};
+  taskMap[projectConsts.PROJECTGLJ] = {tasks:[],model:project_glj_model};
+  taskMap[projectConsts.PROJECT] = {tasks:[],model:projectsModel};
+  taskMap[projectConsts.RATION_TEMPLATE] = {tasks:[],model:rationTemplateModel};
+
+  for(let type in nodeGroups){
+      for(let node of nodeGroups[type]){
+          if(taskMap[type]){
+              if(type == projectConsts.RATION){
+                  if(node.action == "delete") deleteRationIDs.push(node.data.ID);
+              }
+              if(type == projectConsts.RATION_GLJ){
+                  if(node.action == "add"){//添加定額工料机的時候,要先走项目工料机的逻辑
+                      let [newRecode,projectGLJ] = await createRationGLJData(node.data);
+                      node.data =newRecode;
+                      node.projectGLJ = projectGLJ;
+                  }
+              }
+              taskMap[type].tasks.push(getTask(node));
+          }
+      }
+  }
 
-        }
-    }
-    rationTasks.length>0?asyncTasks.push(ration_model.model.bulkWrite(rationTasks)):'';
-    billTasks.length>0?asyncTasks.push(bill_model.model.bulkWrite(billTasks)):"";
-    rationGLJTasks.length>0?asyncTasks.push(ration_glj_model.bulkWrite(rationGLJTasks)):"";
-    projectGLJTasks.length>0?asyncTasks.push(project_glj_model.bulkWrite(projectGLJTasks)):"";
-    projectTasks.length>0?asyncTasks.push(projectsModel.bulkWrite(projectTasks)):"";
-    rationTemplateTasks.length>0?asyncTasks.push(rationTemplateModel.bulkWrite(rationTemplateTasks)):"";
-    return  asyncTasks.length>0?await Promise.all(asyncTasks):"";
+  for(let key in taskMap){
+      if(taskMap[key].tasks.length> 0) asyncTasks.push(taskMap[key].model.bulkWrite(taskMap[key].tasks))
+  }
 
-    function getTask(node,idFiled = 'ID') {
+  if(asyncTasks.length>0) await Promise.all(asyncTasks);
+  if(deleteRationIDs.length > 0) await ration_glj_model.deleteMany({rationID: {$in: deleteRationIDs}});
 
-        let task={
-            updateOne:{
-                filter:{},
-                update :_.cloneDeep(node.data)
-            }
-        };
-        task.updateOne.filter[idFiled] = node.data[idFiled];//现在复制项目也重新生成一个新的ID了,所以ID是唯一的
-        delete task.updateOne.update[idFiled];//防止误操作
-        return task;
-    }
-}
 
+  return datas;
+
+
+  function getTask(node,idFiled = 'ID') {
+      let task={};
+      if(node.action == "add"){
+          task.insertOne ={
+              document:node.data
+          }
+      }else if(node.action =="delete"){
+          task.deleteOne ={
+              filter:{}
+          };
+          task.deleteOne.filter[idFiled] = node.data[idFiled];
+      }else {
+          task.updateOne = {
+              filter:{},
+              update :_.cloneDeep(node.data)
+          };
+          task.updateOne.filter[idFiled] = node.data[idFiled];//现在复制项目也重新生成一个新的ID了,所以ID是唯一的
+          delete task.updateOne.update[idFiled];//防止误操作
+      }
+
+      return task;
+  }
+}
 
-/*function updateNodes(datas,callback) {
-    let tasks = [];
-    for(let node of datas){
-        tasks.push(updateOne(node))
-    }
-    async_n.parallel(tasks, function(err, results) {
-        if (!err){
-            callback(0, '', results);
-        }
-        else{
-            console.log(err);
-            callback(1, 'save project failed'+err.message, null);
-        }
-    });
-    function updateOne(node) {
-        if(node.type == projectConsts.BILLS){
-            return function (asCallback) {
-                bill_model.model.findOneAndUpdate({projectID: node.data.projectID, ID: node.data.ID,deleteInfo: null}, node.data,{new: true}, asCallback);
-            }
-        }else if(node.type ==projectConsts.RATION){
-            return function (asCallback) {
-                ration_model.model.findOneAndUpdate({projectID: node.data.projectID, ID: node.data.ID,deleteInfo: null}, node.data,{new: true}, asCallback);
-            }
-        }
-    }
-}*/
 
 //data = {feeRateID:111111,projectID:1245}; type = feeRate
 async function markUpdateProject(data,type) {

+ 1 - 0
modules/main/routes/divide_route.js

@@ -10,6 +10,7 @@ module.exports = function (app) {
     var divideRouter = express.Router();
 
     divideRouter.post('/updateItem', divideController.action);
+    divideRouter.post('/updateCoeAdjust', divideController.action);
     //materialRouter.post('/replace', materialController.action);//材料替换,其实是材料修改
 
     app.use('/divide',divideRouter);

+ 80 - 32
modules/ration_glj/facade/glj_calculate_facade.js

@@ -11,6 +11,7 @@ let ration_coe = mongoose.model('ration_coe');
 const ProjectModel = require('../../pm/models/project_model').project;
 let mixRatioModel = mongoose.model('mix_ratio');
 let std_ration_lib_ration_items = mongoose.model('std_ration_lib_ration_items');
+let divideModel = mongoose.model("divide_setting");
 let std_glj_lib_gljList_model = mongoose.model('std_glj_lib_gljList');
 let glj_type_util = require('../../../public/cache/std_glj_type_util');
 const scMathUtil = require('../../../public/scMathUtil').getUtil();
@@ -20,6 +21,7 @@ const common_util = require('../../../public/common_util');
 
 module.exports={
     calculateQuantity:calculateQuantity,
+    calculateQuantityFromDivide:calculateQuantityFromDivide,
     getGLJTypeByID:getGLJTypeByID
 }
 //辅助定额调整、稳定土配合比、替换工料机、标准附注条件调整、添加工料机、自定义消耗量(包括删除工料机)、自定义乘系数、市场单价调整
@@ -44,6 +46,75 @@ let coeTypeMap = {
 };
 
 
+async function handleAndGetAssList(impactRation,adjustState){
+  let assList=[], assRation = null;
+  if(impactRation && impactRation.rationAssList.length>0){
+    prepareAss(impactRation.rationAssList);
+    let temTimes = [];
+    let thirdRationCodes=[];
+    for(let i=0;i<impactRation.rationAssList.length;i++){
+        let times = calculateTimes(impactRation.rationAssList[i]);
+        if(times!=0){
+            let thirdRationCode = impactRation.rationAssList[i].thirdRationCode;
+            if(thirdRationCode && thirdRationCode !=''){
+                temTimes.push(times);
+                thirdRationCodes.push(thirdRationCode)
+            }
+            assRation = await  std_ration_lib_ration_items.findOne({rationRepId:impactRation.libID,code:impactRation.rationAssList[i].assistCode});
+            assList.push({times:times,assRation:assRation});
+            adjustState.push({index:stateSeq.ass,content:impactRation.rationAssList[i].name+" "+impactRation.rationAssList[i].actualValue+" : +"+impactRation.rationAssList[i].assistCode+"x"+times});
+        }
+    }
+    if(temTimes.length == 2 &&thirdRationCodes[0] == thirdRationCodes[1] ){ //说明有第三定额
+        let times_t = temTimes[0] * temTimes[1];
+        let tration =  await  std_ration_lib_ration_items.findOne({rationRepId:impactRation.libID,code:thirdRationCodes[0]});
+        if(tration){
+            assList.push({times:times_t,assRation:tration});
+            adjustState.push({index:stateSeq.ass,content:"+"+thirdRationCodes[0]+"x"+times_t});
+        }
+    }
+  }
+  return assList;
+}
+
+
+async function calculateQuantityFromDivide(ID,rationID){
+  let tasks=[],udatas=[];
+  let divide_setting = await divideModel.findOne({ID:ID}).lean();
+  let impactRation = null,gljList=[],coeList=[],assList=[], adjustState=[],mixRatioMap = {};
+  for(let r of divide_setting.divideList){
+    if(r.ID == rationID){
+      impactRation = r;
+      break; 
+    } 
+  }
+  if(impactRation == null) return null;
+  for(let rg of divide_setting.ration_gljs){
+    if(rg.rationID == rationID) gljList.push(rg);
+  }
+  for(let co of divide_setting.ration_coes){
+    if(co.rationID == rationID) coeList.push(co);
+  }
+  assList = await handleAndGetAssList(impactRation,adjustState);
+  for(let glj of gljList){//先把混凝土,砂浆,配合比有自定义消耗的挑出来
+    if(gljUtil.isConcreteType(glj.type)) await getMixRatioMap(glj,gljList,coeList,assList,mixRatioMap);
+  }
+  for(let i =0;i<gljList.length;i++ ){
+    let r = await calculateQuantityPerGLJ(gljList[i],gljList,coeList,assList,adjustState,mixRatioMap,null);
+    if(quantityUpdateCheck(gljList[i],r) == true){
+      let ndoc={};
+      for(let key in r.doc){
+        ndoc["ration_gljs.$."+key] = r.doc[key]
+      }
+      udatas.push({ID:gljList[i].ID,model:"ration_gljs",type:"update",doc:r.doc});
+      tasks.push({updateOne: {filter: {"ID": ID,"ration_gljs.ID":gljList[i].ID}, update: ndoc}});
+    } 
+  }
+  return [tasks,udatas];
+}
+  
+
+
 async function calculateQuantity(query,noNeedCal=null,refreshRationName = false){
     try {
         let  result ={
@@ -53,35 +124,12 @@ async function calculateQuantity(query,noNeedCal=null,refreshRationName = false)
         let impactRation = await ration.findOne({ID:query.rationID});
         let gljList = await ration_glj.find(query);//{projectID:query.projectID,rationID:query.rationID}
         let coeList = await ration_coe.find({rationID:query.rationID}).sort('seq').exec();
-        let assList=[], assRation = null, adjustState=[],mixRatioMap = {};
+        let assList=[], adjustState=[],mixRatioMap = {};
         if(!impactRation){//如果定额不存在或者已删除,返回空
             return null;
         }
         if(impactRation._doc.hasOwnProperty("rationAssList")&&impactRation.rationAssList.length>0){
-            prepareAss(impactRation.rationAssList);
-            let temTimes = [];
-            let thirdRationCodes=[];
-            for(let i=0;i<impactRation.rationAssList.length;i++){
-                let times = calculateTimes(impactRation.rationAssList[i]);
-                if(times!=0){
-                    let thirdRationCode = impactRation.rationAssList[i].thirdRationCode;
-                    if(thirdRationCode && thirdRationCode !=''){
-                        temTimes.push(times);
-                        thirdRationCodes.push(thirdRationCode)
-                    }
-                    assRation = await  std_ration_lib_ration_items.findOne({rationRepId:impactRation.libID,code:impactRation.rationAssList[i].assistCode});
-                    assList.push({times:times,assRation:assRation});
-                    adjustState.push({index:stateSeq.ass,content:impactRation.rationAssList[i].name+" "+impactRation.rationAssList[i].actualValue+" : +"+impactRation.rationAssList[i].assistCode+"x"+times});
-                }
-            }
-            if(temTimes.length == 2 &&thirdRationCodes[0] == thirdRationCodes[1] ){ //说明有第三定额
-                let times_t = temTimes[0] * temTimes[1];
-                let tration =  await  std_ration_lib_ration_items.findOne({rationRepId:impactRation.libID,code:thirdRationCodes[0]});
-                if(tration){
-                    assList.push({times:times_t,assRation:tration});
-                    adjustState.push({index:stateSeq.ass,content:"+"+thirdRationCodes[0]+"x"+times_t});
-                }
-            }
+          assList = await handleAndGetAssList(impactRation,adjustState);
         }
         // 稳定土调整状态
         const proportionStr = gljList.filter(glj => glj.rationProportion).map(glj => glj.adjustProportion || 0).join(':');
@@ -119,7 +167,7 @@ async function calculateQuantity(query,noNeedCal=null,refreshRationName = false)
 
 function quantityUpdateCheck(glj,r) {//检查,有改变的才更新
     for(let key in r.doc){
-        if(glj._doc[key] != r.doc[key]) return true
+        if(glj[key] != r.doc[key]) return true
     }
     return false
 }
@@ -290,7 +338,7 @@ async function getMixRatioMap(glj,gljList,coeList,assList,mixRatioMap) {//生成
 
 
 function noCustomQuantiyt(glj) {//是否有自定义消耗量
-    return !glj._doc.hasOwnProperty('customQuantity')||glj.customQuantity==null||glj.customQuantity==""
+    return glj.customQuantity===undefined||glj.customQuantity===null||glj.customQuantity==""
 }
 
 async function calculateAss(quantity,assList,glj) {
@@ -320,11 +368,11 @@ async function calculateAss(quantity,assList,glj) {
 
 function generateAdjustState(glj,coeList,adjustState,gljList,quantity) {
    //替换工料机 and 添加工料机
-    if(glj._doc.createType=='replace'&&glj.rcode!=glj.code){
+    if(glj.createType=='replace'&&glj.rcode!=glj.code){
         adjustState.push({index:stateSeq.replace,content:glj.rcode+'换'+glj.code});
-    }else if(glj._doc.createType=='add'){
+    }else if(glj.createType=='add'){
         let displayQuantity = quantity;
-        if(glj._doc.hasOwnProperty('customQuantity')&&(glj.customQuantity != null||glj.customQuantity != '')){
+        if(glj.hasOwnProperty('customQuantity')&&(glj.customQuantity != null||glj.customQuantity != '')){
             displayQuantity = glj.customQuantity;
         }
         displayQuantity = displayQuantity&&displayQuantity!=""?parseFloat(displayQuantity):0;
@@ -354,13 +402,13 @@ function generateAdjustState(glj,coeList,adjustState,gljList,quantity) {
     }
 
     //自定义消耗量
-    if(glj._doc.createType!='add'&&glj._doc.hasOwnProperty('customQuantity')){
+    if(glj.createType!='add'&&glj.hasOwnProperty('customQuantity')){
         if(glj.customQuantity!==null&&glj.customQuantity!=""){
             adjustState.push({index:stateSeq.cusQuantity,content:glj.code+'量'+parseFloat(glj.customQuantity)});
         }
     }
     //市场单价调整
-    if(glj._doc.hasOwnProperty('marketPriceAdjust')&&glj.marketPriceAdjust&&glj.marketPriceAdjust!=0){
+    if(glj.hasOwnProperty('marketPriceAdjust')&&glj.marketPriceAdjust&&glj.marketPriceAdjust!=0){
         //0101005价66.00
         adjustState.push({index:stateSeq.adjMak,content:glj.code+'价'+glj.marketPriceAdjust});
     }

+ 20 - 14
modules/ration_glj/facade/ration_glj_facade.js

@@ -732,7 +732,7 @@ async function addGLJ(rgList,compilation) {
     return result;
 }
 
-async function insertAddTypeGLJ(rgList,compilation) {
+async function insertAddTypeGLJ(rgList,compilation,needInsert=true) {
     let newRecodes = [],GLJMap=null;
     let projectGLJList = [];
     let [unitFileId,ext] = await  prepareExtData(rgList[0].projectID,compilation);
@@ -764,7 +764,8 @@ async function insertAddTypeGLJ(rgList,compilation) {
         newRecodes.push(createNewRecord(g));
         projectGLJList.push(result);
     }
-    await ration_glj.insertMany(newRecodes);
+    //分摊那里调用时不用真的插入
+    if(needInsert == true) await ration_glj.insertMany(newRecodes);
     return [newRecodes,projectGLJList];
 }
 
@@ -843,32 +844,37 @@ function addMixRatioToRationGLJ(g,subList,newRecodes,GLJMap){
     return newMap;
 }
 
-async  function replaceGLJByData(data,compilation) {
+async  function replaceGLJByData(data,compilation,needUpdate = true,rationGLJList) {
     let projectGljModel = new GLJListModel(),newRecodes=[],deleteList=[];
     let [unitFileId,ext] = await  prepareExtData(data.projectID,compilation);
     let result = await projectGljModel.addList(getGLJSearchInfo(data),unitFileId,ext);
     data.projectGLJID = result.id;
     if(data.toCommercial == true){//从混凝土改成商品混凝土,
-       let [contype,newR] =  await concreteTypeToCommercial(data);
+       let [contype,newR] =  await concreteTypeToCommercial(data,needUpdate);
         newRecodes.push(newR);
         data=contype;
     }else {
-        let [newList,tdelList] = await replaceMixRatio(data,result,unitFileId);
+        let [newList,tdelList] = await replaceMixRatio(data,result,unitFileId,needUpdate,rationGLJList);
         newRecodes = newList;
         deleteList = tdelList;
-        let updateResult = await ration_glj.findOneAndUpdate({ID: data.ID, projectID: data.projectID}, data);//更新定额工料机
+        if(needUpdate==true) await ration_glj.findOneAndUpdate({ID: data.ID, projectID: data.projectID}, data);//更新定额工料机
     }
 
     return {data:data,newRecodes:newRecodes,deleteList:deleteList,projectGLJ:result};
 }
 
 
-async function concreteTypeToCommercial(data) {
-   //旧的自定义消耗量改为0
-   let contype =  await ration_glj.findOneAndUpdate({ID: data.originalID}, {customQuantity:'0'});
+async function concreteTypeToCommercial(data,needUpdate) {
+    //旧的自定义消耗量改为0
+    let contype = null;
+    if(needUpdate == true){
+      contype =  await ration_glj.findOneAndUpdate({ID: data.originalID}, {customQuantity:'0'});
+    }else{
+      contype = {customQuantity:'0'}
+    }
     //因为商品混凝土是没有组成物的,所以不用考虑组成物的情况
     let new_glj =  createComercialConcreteData(data);
-    await ration_glj.create(new_glj);
+    if(needUpdate == true) await ration_glj.create(new_glj);
     return [contype,new_glj];
 }
 
@@ -878,12 +884,12 @@ function createComercialConcreteData(data){
 }
 
 
-async function replaceMixRatio(g,result,unitFileId){
+async function replaceMixRatio(g,result,unitFileId,needUpdate,trationGLJList){
     let newRecodes=[],deleteList = [];
     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});
+        let rationGLJList = trationGLJList?trationGLJList:await ration_glj.find({'rationID':g.rationID});
         for(let r of rationGLJList){
             IDMap[r.ID] = r;
             projectGLJMap[r.projectGLJID] = r;
@@ -906,8 +912,8 @@ async function replaceMixRatio(g,result,unitFileId){
         }
     }
 
-    if(deleteList.length > 0) await ration_glj.deleteMany({'ID': {"$in": deleteList}});//删除定额工料机
-    if(newRecodes.length > 0)  await ration_glj.insertMany(newRecodes);
+    if(deleteList.length > 0 && needUpdate==true) await ration_glj.deleteMany({'ID': {"$in": deleteList}});//删除定额工料机
+    if(newRecodes.length > 0 && needUpdate==true)  await ration_glj.insertMany(newRecodes);
     return [newRecodes,deleteList]
 }
 

+ 9 - 27
web/building_saas/main/html/divide.html

@@ -1,8 +1,8 @@
 <div class="toolsbar d-flex px-1 justify-content-between" id="divideToolsBar">
   <div class="form-inline py-1">
-      <a class="btn btn-sm ml-1" href="#" id = "exec_divide_btn" >执行分摊</a>
-      <a class="btn btn-sm ml-1" href="#" data-toggle="modal" data-target="#cancel_divide"> 取消分摊</a></label>
-      <a class="btn btn-sm ml-1" href="#" data-toggle="modal" data-target="#cancel_all_divide"> 取消所有分摊</a></label>
+      <a class="btn btn-sm ml-1" href="#" id ="exec_divide_btn" >执行分摊</a>
+      <a class="btn btn-sm ml-1" href="#" id="cancel_divide_btn" > 取消分摊</a></label>
+      <a class="btn btn-sm ml-1" href="#" id="cancel_all_divide_btn" > 取消所有分摊</a></label>
   </div>
   <div class="divide_side-tabs form-inline">
     <ul class="nav nav-tabs" role="tablist">
@@ -18,8 +18,8 @@
   <div class="row" id="divideRow">
       <div class="main-content col p-0 " id="divide_main" style="overflow: hidden">
        <div class="top-content row"  id="divide_top" style="overflow: hidden;margin-left: 0px;margin-right: 0px;">
-          <div class="main-data-top left col-6" style="padding: 0px;" id="divide_main_sheet"></div>
-          <div class="main-data-top left col-6" style="padding: 0px;" id="divide_bills_sheet"></div>
+          <div class="main-data-top left col-7" style="padding: 0px;" id="divide_main_sheet"></div>
+          <div class="main-data-top left col-5" style="padding: 0px;" id="divide_bills_sheet"></div>
        </div>
        <div class="resize-y" id="divideResize"></div>
           <div class="bottom-content" id="divideBottom">
@@ -148,45 +148,27 @@
                       <div class=" row" style="margin-left: 10px;">
                         <div class=" col-6">
                           <label class="form-check-label">
-                            <input class="form-check-input" name="divide_type" id="divide_by_bills" value="0" type="radio">
+                            <input class="form-check-input divide_type" name="divide_type" id="divide_by_bills" value="0" type="radio">
                             按清单金额分摊
                         </label>
                         </div>
                          <div class=" col-6">
                           <label class="form-check-label">
-                              <input class="form-check-input" name="divide_type" id="divide_by_concrete" value="1" type="radio">
+                              <input class="form-check-input divide_type" name="divide_type" id="divide_by_concrete" value="1" type="radio">
                               按混凝土用量分摊
                           </label>
                         </div>
                         <div class=" col-6">
                           <label class="form-check-label">
-                            <input class="form-check-input" name="divide_type" id="divide_by_customer" value="2" type="radio">
+                            <input class="form-check-input divide_type" name="divide_type" id="divide_by_customer" value="2" type="radio">
                             自定义分摊比例
                         </label>
                         </div>
                       </div>
-                     <!--  <div class="form-check col-6">
-                          <label class="form-check-label">
-                              <input class="form-check-input" name="install_setting_radios" id="all_project_calc" value="0" type="radio">
-                              整个项目统一计取
-                          </label>
-                      </div>
-                      <div class="form-check col-6">
-                          <label class="form-check-label">
-                              <input class="form-check-input" name="install_setting_radios" id="FB_calc" value="1" type="radio">
-                              每个分部单独计取
-                          </label>
-                      </div>
-                      <div class="form-check col-6">
-                        <label class="form-check-label">
-                            <input class="form-check-input" name="install_setting_radios" id="FB_calc" value="1" type="radio">
-                            每个分部单独计取
-                        </label>
-                    </div> -->
                   </fieldset>
               </div>
           </div>
-              <button  class="btn btn-primary" id="calc_installation_fee_confirm">确定</button>
+              <button  class="btn btn-primary" id="divide_confirm" data-dismiss="modal">确定</button>
               <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
           </div>
       </div>

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

@@ -1906,7 +1906,7 @@
     <img src="/web/dest/css/img/engineering.png" id="eng_pic" style="display: none">
     <img src="/web/dest/css/img/tender.png" id="tender_pic" style="display: none">
 
-    <img src="/web/dest/css/img/blockLib.png" id="blockLib_pic" style="display: none">
+    <img src="/web/dest/css/img/blocklib.png" id="blockLib_pic" style="display: none">
     <img src="/web/dest/css/img/folder_open.png" id="folder_pic" style="display: none">
     <img src="/web/dest/css/img/tender.png" id="block_pic" style="display: none">
 

+ 101 - 23
web/building_saas/main/js/models/project.js

@@ -404,30 +404,108 @@ var PROJECT = {
                 }
             })
         };
-
+        project.prototype.syncUpdateNodesAndRefresh =async function (datas) {
+          let me = this;
+          return new Promise(function (resolve, reject) {
+              me.updateNodes(datas,function (result) {
+                  let nodes = me.updateNodesCache(result);
+                  projectObj.mainController.refreshTreeNode(nodes);
+                  resolve(nodes);
+              });
+          });
+      };
         project.prototype.updateNodesCache =function (datas) {
-            let refreshNode = [];
-            for(let d of datas){
-                let temObj = null;
-                if(d.type == ModuleNames.bills || d.type == ModuleNames.ration){//如果是树节点类型,直接取树节点更新
-                    let temNode = this.mainTree.getNodeByID(d.data.ID);
-                    if(temNode){
-                        temObj = temNode.data;
-                        refreshNode.push(temNode);
-                    }
-                }else {//其它类型,更新datas
-                    temObj = _.find(this[d.type].datas,{"ID":d.data.ID});
-                }
-                if(temObj){
-                    for(let key in d.data){
-                        if(key == 'ID' || key == 'id'){
-                            continue;
-                        }
-                        this.setValue(temObj,key,d.data[key])
-                    }
-                }
-            }
-            return refreshNode;
+          let refreshNode = [];
+          let reclacQuantity = false;
+          let deleteNode=[],addNodeDatas=[];
+          for(let d of datas){
+              let temObj = null;
+              if(d.type == ModuleNames.bills || d.type == ModuleNames.ration){//如果是树节点类型,直接取树节点更新
+                  if(d.action =="add"){
+                      if(d.type == ModuleNames.ration) this.Ration.datas.push(d.data);
+                      reclacQuantity = true;
+                      addNodeDatas.push(d);
+                  }else {
+                      let temNode = this.mainTree.getNodeByID(d.data.ID);
+                      if(temNode){
+                          if(d.action =="delete"){
+                              if(d.type == ModuleNames.ration){
+                                  _.remove(this.Ration.datas,{'ID':d.data.ID});
+                                  this.Ration.deleteSubListOfRation({ID:d.data.ID});
+                                  reclacQuantity = true;
+                              }
+                              deleteNode.push(temNode);//对于删除节点,统一不加入refreshNode中,由外部加入,避免重复
+                          }else {
+                              temObj = temNode.data;
+                              if(gljUtil.isDef(d.data.quantity))reclacQuantity = true;
+                              refreshNode.push(temNode);
+                          }
+                      }
+                  }
+              }else if(d.type == ModuleNames.project){
+                  temObj = this;
+              }else if (d.type == ModuleNames.ration_glj && d.action == "add"){
+                  this[d.type].datas.push(d.data);
+                  if(d.projectGLJ) this.projectGLJ.loadNewProjectGLJToCache(d.projectGLJ);
+              } else {//其它类型,更新datas
+                  temObj = _.find(this[d.type].datas,{"ID":d.data.ID});
+              }
+              if(temObj){
+                  for(let key in d.data){
+                      if(key == 'ID' || key == 'id'){
+                          continue;
+                      }
+                      this.setValue(temObj,key,d.data[key])
+                  }
+              }
+          }
+
+          //对树节点的操作并删除、添加清单、删除添加定额、删除对应的定额工料机缓存
+          TREE_SHEET_HELPER.massOperationSheet(projectObj.mainController.sheet, function () {
+              deleteTreeNodes(deleteNode);
+              addNewNodes(addNodeDatas,refreshNode);
+          });
+
+
+          if(reclacQuantity) this.projectGLJ.calcQuantity();
+          return refreshNode;
+
+
+
+
+          function deleteTreeNodes(deleteNodes) {
+              let controller = projectObj.mainController, project = projectObj.project;
+              let Bill = project.Bills, Ration = project.Ration;
+              for(let rd of deleteNodes){
+                  controller.sheet.deleteRows(rd.serialNo(),1);
+                  controller.tree.delete(rd);
+                  if(rd.sourceType == Bill.getSourceType()) Bill.tree.delete(rd.source);
+              }
+          }
+          function addNewNodes(newDatas,refreshNode) {
+              let controller = projectObj.mainController;
+              let Bill = projectObj.project.Bills;
+              let newAddNode = [];
+              for(let nr of newDatas){
+                  let nextID = -1;
+                  let preNode = projectObj.project.mainTree.getNodeByID(nr.preSiblingID);
+                  if(preNode) nextID = preNode.getNextSiblingID();
+                  let newNode = projectObj.project.mainTree.insert(nr.parentID, nextID, nr.data.ID);
+                  if(nr.type == ModuleNames.bills){
+                      let newSource = Bill.tree.insertByData(nr.data, nr.ParentID, nextID, true);
+                      newNode.source = newSource;
+                  }else {
+                      newNode.source = nr.data;
+                  }
+                  newNode.sourceType = nr.type;
+                  newNode.data = nr.data;
+                  controller.sheet.addRows(newNode.serialNo(), 1);
+                  controller.sheet.showRow(newNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
+                  newAddNode.push(newNode);
+                  refreshNode.push(newNode);
+              }
+              TREE_SHEET_HELPER.refreshTreeNodeData(controller.setting, controller.sheet, newAddNode, false);
+          }
         };
         project.prototype.setValue=function (obj,key,value) {
             let keyArray = key.split('.');

+ 1 - 0
web/building_saas/main/js/models/project_glj.js

@@ -1151,6 +1151,7 @@ ProjectGLJ.prototype.updatePrice = function (recode, updateField, newval,from,cb
             let nodes = me.getImpactRationNodes(gljs);//取到因为改变工料机价格而受影响的定额
             projectObj.project.calcProgram.calcNodesAndSave(nodes);//触发计算程序
             if(materialGljList.length==0)projectGljObject.onUnitFileChange(result);
+            divideObj.calcDivideAfterGLJUpdate(gljs);
             if(cb){
                 cb(gljs);
             }

+ 3 - 0
web/building_saas/main/js/models/ration_coe.js

@@ -193,6 +193,9 @@ var ration_coe = {
                         updateData.replace.push(r_tem);
                     }
                 }
+                if($('#divide_subSpread').is(':visible')){
+                  return divideObj.updateCoeAdjust(updateData);
+                }
                 $.bootstrapLoading.start();
                 CommonAjax.post("/ration/updateCoeAdjust",updateData,function (result) {
                     $.bootstrapLoading.end();

+ 504 - 88
web/building_saas/main/js/views/divide_view.js

@@ -3,13 +3,13 @@ let divideObj = {
     header: [
       {headerName: "类别", headerWidth: 60, dataCode: "itemType", hAlign:'center', dataType: "String"},
       {headerName: "清单编号", headerWidth: 130, dataCode: "code", hAlign:'left', dataType: "String", formatter: "@"},
-      {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String",formatter: "@"},
-      {headerName: "单位", headerWidth: 100, dataCode: "unit", dataType: "String",cellType:'comboBox',editable:true,options:['m', 'm2', 'm3', 'km', 't', 'kg', '台班', '工日', '昼夜', '元', '项', '处', '个', '件',
+      {headerName: "名称", headerWidth: 250, dataCode: "name", dataType: "String",formatter: "@"},
+      {headerName: "单位", headerWidth: 50, dataCode: "unit", dataType: "String",cellType:'comboBox',editable:true,options:['m', 'm2', 'm3', 'km', 't', 'kg', '台班', '工日', '昼夜', '元', '项', '处', '个', '件',
       '根', '组', '系统', '台', '套', '株', '丛', '缸', '支', '只', '块', '座', '对', '份', '樘', '攒', '榀']},
       {headerName: "工程量", headerWidth: 80, dataCode: "quantity", dataType: "Number",validator:"number",getText:"notZero"},
-      {headerName: "单价", headerWidth: 100, dataCode: "marketPrice", dataType: "Number",validator:"number",getText:"notZero"},
-      {headerName: "金额", headerWidth: 100, dataCode: "marketTotalFee", dataType: "Number",validator:"number",getText:"notZero"},
-      {headerName: "预算价", headerWidth: 100, dataCode: "marketUnitFee", dataType: "Number",validator:"number",getText:"notZero"},
+      {headerName: "单价", headerWidth: 80, dataCode: "marketPrice", dataType: "Number",validator:"number",getText:"notZero"},
+      {headerName: "金额", headerWidth: 80, dataCode: "marketTotalFee", dataType: "Number",validator:"number",getText:"notZero"},
+      {headerName: "预算价", headerWidth: 80, dataCode: "marketUnitFee", dataType: "Number",validator:"number",getText:"notZero"},
       {headerName: "取费类别", headerWidth: 60, dataCode: "programID", hAlign:'center', dataType: "String",cellType:'comboBox',editorValueType:true}
     ],
     view:{ 
@@ -35,7 +35,7 @@ let divideObj = {
       {headerName: "不可分摊", headerWidth: 80, dataCode: "unDivide", dataType: "Number",cellType:'checkBox'}
     ],
     view:{ 
-      lockColumns: [0,1,2,3,4,5,6],
+      lockColumns: [0,1,2,3,4,5,6,7],
       colHeaderHeight:30
     },
     treeCol:1
@@ -47,19 +47,19 @@ let divideObj = {
       {headerName: "分摊比例", headerWidth: 100, dataCode: "divideRate", dataType: "Number",validator:"number"}
     ],
     view:{ 
-      lockColumns: [0,1,2],
+      lockColumns: [0,1],
       colHeaderHeight:30
     }
   },
   billsSetting:{
     header: [
-      {headerName: "编号", headerWidth: 130, dataCode: "code", hAlign:'left', dataType: "String"},
-      {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String"},
-      {headerName: "分摊比例", headerWidth: 80, dataCode: "divideRate", dataType: "Number",validator:"number"},
-      {headerName: "分摊金额", headerWidth: 100, dataCode: "dividePrice", dataType: "Number",validator:"number"},
-      {headerName: "原始金额", headerWidth: 100, dataCode: "originalPrice", dataType: "Number",validator:"number"},
-      {headerName: "合计", headerWidth: 100, dataCode: "totalPrice", dataType: "Number",validator:"number"},
-      {headerName: "金额", headerWidth: 60, dataCode: "price", dataType: "Number",validator:"number"}
+      {headerName: "编号", headerWidth: 100, dataCode: "code", hAlign:'left', dataType: "String"},
+      {headerName: "名称", headerWidth: 250, dataCode: "name", dataType: "String"},
+      {headerName: "分摊比例", headerWidth: 70, dataCode: "divideRate", dataType: "Number",validator:"number"},
+      {headerName: "分摊金额", headerWidth: 80, dataCode: "dividePrice", dataType: "Number",validator:"number"},
+      {headerName: "原始金额", headerWidth: 80, dataCode: "originalPrice", dataType: "Number",validator:"number"},
+      {headerName: "合计", headerWidth: 80, dataCode: "totalPrice", dataType: "Number",validator:"number"},
+      {headerName: "金额", headerWidth: 80, dataCode: "price", dataType: "Number",validator:"number"}
     ],
     view:{ 
       lockColumns: [0,1,2,3,4,5,6],
@@ -82,30 +82,39 @@ let divideObj = {
     }
   },
   initExecSpread:function(){
-    if(this.billsSelectedSpread) return;
+    if(this.billsSelectedSpread){
+      this.billsSelectedSpread.refresh();
+      this.execBillsSpread.refresh();
+      return;
+    } 
     this.billsSelectedSpread = SheetDataHelper.createNewSpread($("#billSelectedSheet")[0]);
     sheetCommonObj.spreadDefaultStyle(this.billsSelectedSpread);
     this.billsSelectedSheet = this.billsSelectedSpread.getSheet(0);
     sheetCommonObj.initSheet(this.billsSelectedSheet, this.billsSelectedSetting);
-    // this.billsSelectedSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onDivideEditStarting);
-    // this.billsSelectedSheet.bind(GC.Spread.Sheets.Events.ValueChanged,this.onDivideValueChange)
-    // this.billsSelectedSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onDivideSelectionChange);  
+    this.billsSelectedSpread.bind(GC.Spread.Sheets.Events.ButtonClicked, this.onbillsSelected);
+
     this.execBillsSpread = SheetDataHelper.createNewSpread($("#execBillSheet")[0]);
     sheetCommonObj.spreadDefaultStyle(this.execBillsSpread);
     this.execBillsSheet = this.execBillsSpread.getSheet(0);
     sheetCommonObj.initSheet(this.execBillsSheet, this.execBillsSetting);
+    this.execBillsSheet.bind(GC.Spread.Sheets.Events.ValueChanged,this.onExecBillsValueChange);
+    this.execBillsSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onExecBillsRangeChanged); 
 
     SheetDataHelper.protectdSheet(this.billsSelectedSheet);
     SheetDataHelper.protectdSheet(this.execBillsSheet);
   },
   showDatas:function(){
     this.showDivideDatas();
+    this.showSubDatas();
+  },
+  showSubDatas:function(){
     this.showBillsDatas();
     this.showRationGLJDatas();
     this.showCalcProgramDatas();
   },
-  showExecDatas:function(){
+  showExecDatas:function(init){
     this.showSelectedBillsDatas();
+    this.showExecBillsDatas(init);
   },
   refreshViews:function(){
     if(!$('#divide_main').is(':visible')) return;
@@ -175,14 +184,76 @@ let divideObj = {
     sheetCommonObj.showData(this.calcProgramSheet, calcProgramObj.setting, datas);
     customRowHeader(this.calcProgramSheet, datas.length);
   },
-  showSelectedBillsDatas:function(){
+  showExecBillsDatas:function(init=false){
+    this.execBillsDatas = [];
+    let parentMap = _.indexBy(this.selectedBillsDatas,"ParentID");
+    let divideType = parseInt($("input[name='divide_type']:checked").val());
+    let total = 0;
+    let ctotal = 0;
+    let concreteMap = {};
+    let billsRationGLJMap = {};
+    if(divideType == 1){//按混凝土计算
+      billsRationGLJMap = _.groupBy(projectObj.project.ration_glj.datas,"billsItemID");
+    }
+    for(let b of this.selectedBillsDatas){
+      if(b.selected == 1 && !parentMap[b.ID]){
+        let e = {ID:b.ID,code:b.code,name:b.name,divideRate:0,totalFee:b.totalFee};
+        if(b.totalFee != "") total = scMathUtil.roundForObj(total + parseFloat(b.totalFee),getDecimal("process"))
+        if(divideType == 1 && billsRationGLJMap[b.ID]){
+          let btotal = 0;
+          for(let glj of billsRationGLJMap[b.ID]){
+            //“混凝土”、“砂浆”、“配合比”。
+            if(glj.type == gljType.CONCRETE || glj.type == gljType.MORTAR||glj.type == gljType.MIX_RATIO){
+              let rNode = projectObj.project.mainTree.findNode(glj.rationID);
+              let gquantity = gljUtil.getTotalQuantity(glj,rNode.data,getDecimal("ration.quantity"),getDecimal("glj.quantity"));
+              btotal = scMathUtil.roundForObj(btotal + parseFloat(gquantity),getDecimal("process"));
+            }
+          }
+          btotal = scMathUtil.roundForObj(btotal,getDecimal("glj.quantity"));
+          ctotal = scMathUtil.roundForObj(ctotal + btotal,getDecimal("process"));
+          concreteMap[b.ID] = btotal;
+        }
+        this.execBillsDatas.push(e);
+      }
+    }
+    total = scMathUtil.roundForObj(total,getDecimal("bills.totalPrice"));
+    for(let e of this.execBillsDatas){
+      if(init == true){//如果是初始化打开页面,要读取已经保存的分摊比例
+         //使用已保存的分摊信息
+         let item = divideObj.getSelectedItem();
+         let IDMap = {};
+         if(item.bills) IDMap = _.indexBy(item.bills,"ID");
+         if(IDMap[e.ID]){
+          e.divideRate = IDMap[e.ID].divideRate;
+         } 
+      }else if(divideType == 0){//按清单金额比例
+        if(e.totalFee != "" && total!=0) {
+          totalFee = scMathUtil.roundForObj(e.totalFee,getDecimal("bills.totalPrice"));
+          e.divideRate = scMathUtil.roundForObj((totalFee/total) * 100,3);
+        }
+      }else if(divideType == 1){//按混凝土用量
+         let cquantity = concreteMap[e.ID];
+         if(cquantity && ctotal != 0) e.divideRate = scMathUtil.roundForObj((cquantity/ctotal) * 100,3);
+      }
+      //自定义的不用管
+    }
     
-    this.selectedBillsDatas = getSelectedBillsDatas();
+    sheetCommonObj.showData(this.execBillsSheet, this.execBillsSetting,this.execBillsDatas);
+    this.execBillsSheet.setRowCount(this.execBillsDatas.length);
+  },
+
+  
+
+  showSelectedBillsDatas:function(datas){
+    if(!datas)this.selectedBillsDatas = getSelectedBillsDatas();
     this.billsSelectedSheet.setRowCount(this.selectedBillsDatas.length);
     sheetCommonObj.showTreeData(this.billsSelectedSheet, this.billsSelectedSetting,this.selectedBillsDatas);
 
     function getSelectedBillsDatas(){
       let datas = [];
+      let item = divideObj.getSelectedItem();
+      let IDMap = {};
+      if(item.bills) IDMap = _.indexBy(item.bills,"ID");
       for(let n of projectObj.project.mainTree.roots){
         getDatas(n)
       }
@@ -203,6 +274,12 @@ let divideObj = {
           unDivide:0,
           collapsed:false
         };
+        if(IDMap[d.ID]) t.selected = 1;
+        //有基数计算的,不可选择
+        if(d.calcBase&&d.calcBase!="") t.unDivide = 1;
+        //数量*单价的(判断金额列是否有值),不可选择
+        if(d.calcFlag == treeNodeCalcFlag.customUnitPrice && t.totalFee !="") t.unDivide = 1;
+
         datas.push(t);
         if(!node.children) return;
         for(let c of node.children){
@@ -334,9 +411,53 @@ let divideObj = {
     }
     return cusList;
   },
+  updateActualValue:async function(assList,index,newVal,isAdjust = 1){
+    let item = this.getSelectedItem();
+    let newList = _.cloneDeep(assList);
+    if(gljUtil.isDef(newVal))newList[index].actualValue=newVal;
+    newList[index].isAdjust = isAdjust;
+    let u = {ID:item.ID,type:'update',updateAss:true,doc:{rationAssList:newList}}
+    await this.updateItem([u]);
+    await this.calcDivideItem(item);
+    zmhs_obj.showDatas();
+  },
   getStableList:function(){
     return this.rationGLJDatas.filter(glj => !glj.isMixRatio && glj.rationProportion);
   },
+  updateProportion:async function(datas){
+    let updateDatas = [];
+    let item = this.getSelectedItem();
+    for(let d of datas){
+      updateDatas.push({ID:d.ID,type:'update',rationID:item.ID,model:'ration_gljs',updateProportion:true,doc:{"adjustProportion":d.adjustProportion}});
+    }
+    await this.updateItem(updateDatas);
+    await this.calcDivideItem(item);
+    zmhs_obj.showDatas();
+  },
+  updateCoeAdjust:async function(data){
+    console.log(data);
+    let divideSetting =  projectObj.project.divide_setting.datas;
+    data.divideID = divideSetting.ID;
+    try {
+      $.bootstrapLoading.start();
+      let result = await ajaxPost("/divide/updateCoeAdjust",data)
+      this.refreshDivideCaches(result.updateDatas);
+      if(result.projectGLJList && result.projectGLJList.length > 0) projectObj.project.projectGLJ.loadNewProjectGLJToCaches(result.projectGLJList);   
+      if(result.ration_gljs && result.ration_gljs.length > 0) divideSetting.ration_gljs = divideSetting.ration_gljs.concat(result.ration_gljs);
+      if(result.delete && result.delete.length > 0){
+        _.remove(result.ration_gljs,function(o){
+          return _.includes(result.delete,o.ID)
+        })
+      }
+    } catch (error) {
+      console.log(error)
+    }
+    $.bootstrapLoading.end();
+    await this.calcDivideItem(this.getSelectedItem());
+    this.showDatas();
+    zmhs_obj.showDatas();
+  },
+
   getProgramOptions:function(){
     let names = projectObj.project.calcProgram.compiledTemplateNames;
     let map = projectObj.project.calcProgram.compiledTemplateMaps;
@@ -366,6 +487,15 @@ let divideObj = {
     }
     return false;  
   },
+
+  rationGLJEditChecking:function(row,col){//return false表示不能编辑
+    let me = this;
+    let data = me.rationGLJDatas[row],setting = gljCol.ration_glj_setting;
+    let dataCode = setting.header[col].dataCode;
+    if(data.isMixRatio == true && (dataCode=="customQuantity"||dataCode=="basePrice")) return false;
+    return true;
+  },
+
   showBillsDatas:function(){
     if(!$('#divide_bills_sheet').is(':visible')) return;
     this.billsDatas = getBillsDatas();
@@ -373,7 +503,36 @@ let divideObj = {
     this.billsSheet.setRowCount(this.billsDatas.length);
 
     function getBillsDatas(){
-      return [];
+      let datas = [];
+      let item = divideObj.getSelectedItem();
+      if(item.bills){
+        for(let b of item.bills){
+          let bNode = projectObj.project.mainTree.findNode(b.ID);
+          if (!bNode) continue;
+          let t = {
+            ID:b.ID,
+            divideRate:b.divideRate,
+            name:bNode.data.name,
+            code:bNode.data.code,
+            dividePrice:0,
+            originalPrice:0,
+            totalPrice:0,
+            price:0
+          }
+          if(bNode.data.feesIndex.common.totalFee){
+            let totalFee = scMathUtil.roundForObj(bNode.data.feesIndex.common.totalFee,getDecimal("bills.totalPrice"));
+            t.price = totalFee;
+            t.divideRate = scMathUtil.roundForObj(t.divideRate * 0.01,3);
+            t.dividePrice = scMathUtil.roundForObj(item.marketTotalFee * t.divideRate,getDecimal("bills.totalPrice"));
+          }
+          if(bNode.data.feesIndex.rationCommon && bNode.data.feesIndex.rationCommon.totalFee){
+            t.originalPrice = scMathUtil.roundForObj(bNode.data.feesIndex.rationCommon.totalFee,getDecimal("bills.totalPrice"));
+          }
+          t.totalPrice = scMathUtil.roundForObj(t.dividePrice + t.originalPrice,getDecimal("bills.totalPrice"));
+          datas.push(t);
+        }
+      }
+      return datas;
     }
   },
   getSelectedItem:function(){
@@ -394,6 +553,7 @@ let divideObj = {
     if(type) newItem.subType = type;
     let selected = this.getSelectedItem();
     if(itemType!="分摊项"){//当插入定额或者量价时:
+      newItem.divideType = 0;
       newItem.ParentID = selected.itemType == "分摊项"?selected.ID:selected.ParentID;
       newItem.fees = [{fieldName:"common",tenderTotalFee:0,unitFee:0,totalFee:0,tenderUnitFee:0}];
     }
@@ -421,6 +581,8 @@ let divideObj = {
       } 
       if(c.ID == bills.ID) item = c;
     }
+    item.fees=[];
+    item.feesIndex={};
     if(subNodes.length > 0) projectObj.project.calcProgram.innerCalcBill({data:item, sourceType:"bills", updateData:[],children:subNodes},3);
     if(subNodes.length == 0){
       item.calcFlag = 2;
@@ -454,7 +616,7 @@ let divideObj = {
     }
     subItems.push({type:"delete",ID:selected.ID,itemType:selected.itemType});
     await this.updateItem(subItems);
-
+    zmhs_obj.showDatas();
   },
   getNewSeqs:function(selected,newItem){
     let seq = 1,datas=[],refreshSeq = false;
@@ -476,8 +638,8 @@ let divideObj = {
     let divideSetting =  projectObj.project.divide_setting.datas
     try {
       $.bootstrapLoading.start();
-      let result = ajaxPost("/divide/updateItem",{ID:divideSetting.ID,updateDatas:datas})
-      this.refreshDivideCaches(datas);
+      let result = await ajaxPost("/divide/updateItem",{ID:divideSetting.ID,updateDatas:datas})
+      this.refreshDivideCaches(result.updateDatas);
     } catch (error) {
       console.log(error)
     }
@@ -498,7 +660,9 @@ let divideObj = {
         } 
       }
       if(d.type == "update"){
-        let item = _.find(divideSetting.divideList,{'ID':d.ID});
+        let model = "divideList";
+        if(d.model) model = d.model;
+        let item = _.find(divideSetting[model],{'ID':d.ID});
         if(item) gljUtil.updateProperty(item,d.doc);
       }
     }
@@ -521,9 +685,8 @@ let divideObj = {
     let sel = this.divideSheet.getSelections()[0];
     await this.updateDivideRation(data);
     this.divideSheet.setSelection(sel.row+1,sel.col,sel.rowCount,sel.colCount);
-    this.showRationGLJDatas();
-    this.showCalcProgramDatas();
-
+    this.showSubDatas();
+    zmhs_obj.showDatas();
   },
   updateDivideRation:async function(data){
     let divideSetting =  projectObj.project.divide_setting.datas;
@@ -555,36 +718,73 @@ let divideObj = {
     }
     $.bootstrapLoading.end();
   },
+  calcDivideAfterGLJUpdate:async function(gljs){
+    let divideSetting =  projectObj.project.divide_setting.datas
+    let indexMap = {};
+    let rationIDMap = {};
+    let rations = [];
+    for(let glj of gljs){
+      let index = gljUtil.getIndex(glj);
+      indexMap[index] = true;
+    }
+    for(let rg of divideSetting.ration_gljs){    
+       if(indexMap[gljUtil.getIndex(rg)]){
+         rationIDMap[rg.rationID] = true;
+       }
+    }
+    if(_.isEmpty(rationIDMap)) return;
+    for(let d of divideSetting.divideList){
+      if(rationIDMap[d.ID]){
+        rations.push(d)
+      }
+    }
+    if(rations.length > 0){
+      let updateDatas= this.getCalcDivideDatas(rations);
+      updateDatas.length > 0?await this.updateItem(updateDatas):this.showDatas();
+    }
+  },
+
   calcDivideItem:async function(divide){
+    let updateDatas= this.getCalcDivideDatas([divide]);
+    updateDatas.length > 0?await this.updateItem(updateDatas):this.showDatas();
+  },
+  getCalcDivideDatas:function(divides){
     let updateDatas = [];
-    let children =[];
     let divideSetting =  projectObj.project.divide_setting.datas
-    if(divide.itemType != "分摊项"){//不是分摊项,调用计算程序
-      let parentSum = 0;
-      let parent = null;
-      projectObj.project.calcProgram.innerCalcRation({data:divide, sourceType:"ration", calcType: 1, updateData:[]});
-      if(divide.itemType == "定额"){
-        updateDatas.push({ID:divide.ID,type:'update',doc:{fees:divide.fees}});  
+    let parentMap={};
+    let parents=[];
+    for(let divide of divides){//先计算所有子项和传入的分摊项(与传入子项不关联,因为计算子项时会计算对应的分摊项)
+      if(divide.itemType != "分摊项"){//不是分摊项,调用计算程序
+        divide.fees=[];
+        divide.feesIndex={};
+        projectObj.project.calcProgram.innerCalcRation({data:divide, sourceType:"ration", calcType: 1, updateData:[]});
+        if(divide.itemType == "定额"){
+          updateDatas.push({ID:divide.ID,type:'update',doc:{fees:divide.fees}});  
+        }else{
+          updateDatas.push({ID:divide.ID,type:'update',doc:{fees:divide.fees,marketUnitFee:divide.marketUnitFee}});
+        } 
+        parentMap[divide.ParentID] = [];
       }else{
-        updateDatas.push({ID:divide.ID,type:'update',doc:{fees:divide.fees,marketUnitFee:divide.marketUnitFee}});
-      } 
-      for(let c of divideSetting.divideList){
-        if(c.ID == divide.ParentID) parent = c;
-        if(c.ParentID == divide.ParentID){
-          let t = c.ID != divide.ID?c:divide;
-          this.initFeeIndexs(t);
-          children.push({data:t, sourceType:"ration", calcType: 1, updateData:[]});
-        }
+        divide = this.calcBills(divide);
+        updateDatas.push({ID:divide.ID,type:'update',doc:{fees:divide.fees}});  
       }
-      if(children.length > 0){
-        projectObj.project.calcProgram.innerCalcBill({data:parent, sourceType:"bills", updateData:[],children:children},3);
-        updateDatas.push({ID:parent.ID,type:'update',doc:{fees:parent.fees}});  
-      } 
-    }else{
-      divide = this.calcBills(divide);
-      updateDatas.push({ID:divide.ID,type:'update',doc:{fees:divide.fees}});  
     }
-    updateDatas.length > 0?await this.updateItem(updateDatas):this.showDatas();
+    for(let c of divideSetting.divideList){
+      if(parentMap[c.ID]) parents.push(c);//把所有父节点挑出来
+      if(parentMap[c.ParentID]){
+        let t = c.ID != divide.ID?c:divide;
+        this.initFeeIndexs(t);
+        //生成并归类父节点对应的子节点(用于父节点的计算)
+        parentMap[c.ParentID].push({data:t, sourceType:"ration", calcType: 1, updateData:[]});
+      }
+    }
+    for(let p of parents){
+      p.fees=[];
+      p.feesIndex={};
+      projectObj.project.calcProgram.innerCalcBill({data:p, sourceType:"bills", updateData:[],children:parentMap[p.ID]},3);
+      updateDatas.push({ID:p.ID,type:'update',doc:{fees:p.fees}});  
+    }  
+    return updateDatas;
   },
 
   getTotolFee:function name(divide) {
@@ -606,10 +806,9 @@ let divideObj = {
     this.divideSheet = this.divideSpread.getSheet(0);
     sheetCommonObj.initSheet(this.divideSheet, this.divideSetting, 2);
     this.divideSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onDivideEditStarting);
-    this.divideSheet.bind(GC.Spread.Sheets.Events.ValueChanged,this.onDivideValueChange)
+    this.divideSheet.bind(GC.Spread.Sheets.Events.ValueChanged,this.onDivideValueChange);
     this.divideSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onDivideSelectionChange);  
-    /*     ;
-    this.divideSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onCoeRangeChanged); */
+    this.divideSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onDivideRangeChanged); 
 
     SheetDataHelper.protectdSheet(this.divideSheet);
   },
@@ -621,6 +820,54 @@ let divideObj = {
         args.cancel = true;
     }
   },
+  onRationGljEditStarting:function(sender,args){
+    let me = divideObj;
+    let row = args.row;
+    let col = args.col;
+    if(divideObj.rationGLJEditChecking(row,col)==false){
+      args.cancel = true;
+    }
+  },
+  onRationGLJRangeChanged:async function(e,args){
+    for(let c of args.changedCells){
+      let value=  args.sheet.getCell(c.row, c.col).text();
+      if(divideObj.rationGLJEditChecking(c.row,c.col)==false){
+        return divideObj.showRationGLJDatas();
+      }
+      divideObj.onRationGLJValueChange(e,{row:c.row,col:c.col,newValue:value,sheet:args.sheet});
+    }
+  },
+
+  onExecBillsRangeChanged:async function(e,args){
+    for(let c of args.changedCells){
+      let value=  args.sheet.getCell(c.row, c.col).text();
+      divideObj.onExecBillsValueChange(e,{row:c.row,col:c.col,newValue:value,sheet:args.sheet});
+    }
+  },
+
+  onExecBillsValueChange:function(sender,info){
+    let me = divideObj,row = info.row, col = info.col;
+    let setting = me.execBillsSetting;
+    let dataCode = setting.header[col].dataCode;
+    let record = me.execBillsDatas[row];
+    let value = info.newValue;
+    if(value && !sheetCommonObj.checkData(col,setting,value)) {
+      alert('输入的数据类型不对,请重新输入!');
+      return info.sheet.setValue(row, col, record[dataCode], GC.Spread.Sheets.SheetArea.viewport);
+    }
+    record[dataCode] = scMathUtil.roundForObj(value,3);
+
+  },
+  onDivideRangeChanged:async function(e,args){
+    for(let c of args.changedCells){
+      if(divideObj.divideEditChecking(c.row,c.col)==false){
+        return divideObj.showDivideDatas();
+      }
+      let value=  args.sheet.getCell(c.row, c.col).text();
+      divideObj.onDivideValueChange(e,{row:c.row,col:c.col,newValue:value});
+    }
+  },
+
   onDivideValueChange:async function(sender,info){
     let me = divideObj,row = info.row, col = info.col;
     let setting = me.divideSetting;
@@ -641,6 +888,48 @@ let divideObj = {
     await me.updateItem([me.getDivideUpdateData(record,dataCode,value)]);
     await me.calcDivideItem(record);
   },
+
+  onRationGLJValueChange:async function(sender,info){
+    let me = divideObj,row = info.row, col = info.col;
+    let setting = gljCol.ration_glj_setting;
+    let dataCode = setting.header[col].dataCode;
+    let record = me.rationGLJDatas[row];
+    let value = info.newValue;
+    if(value && !sheetCommonObj.checkData(col,setting,value)) {
+      alert('输入的数据类型不对,请重新输入!');
+      return me.showRationGLJDatas();
+    }
+    if (dataCode == 'marketPrice' || dataCode == 'basePrice') {
+      if(!value) value = 0;
+      projectObj.project.projectGLJ.updatePriceFromRG(record, dataCode, value);
+    }else if(dataCode=='customQuantity'){
+      if(value) value = scMathUtil.roundForObj(value, getDecimal("glj.quantity"))
+      let u= {ID:record.ID,type:'update',rationID:record.rationID,model:'ration_gljs',doc:{"customQuantity":value}}
+      await me.updateItem([u]);
+      await me.calcDivideItem(me.getSelectedItem());
+
+    }
+  },
+
+  onbillsSelected:function(sender, args){
+    let dataCode = divideObj.billsSelectedSetting.header[args.col].dataCode;
+    if(dataCode != "selected") return;
+    let checkboxValue = args.sheet.getCell(args.row, args.col).value();
+    let newval = checkboxValue? 0:1;
+    let data = divideObj.selectedBillsDatas[args.row];
+    let parentMap = {};
+    parentMap[data.ID]=true;
+    data.selected=newval;
+    for(let d of divideObj.selectedBillsDatas){
+      if(parentMap[d.ParentID]){
+        if(d.unDivide == 0) d.selected=newval;
+        parentMap[d.ID] = true;
+      }
+    }
+    divideObj.showSelectedBillsDatas(divideObj.selectedBillsDatas);
+    divideObj.showExecBillsDatas();
+  },
+
   replaceDivideRation:async function(code,record){
     let divideSetting =  projectObj.project.divide_setting.datas;
     let data = {ID:divideSetting.ID,type:"update",rationID:record.ID,code:code};
@@ -665,8 +954,8 @@ let divideObj = {
     let oldSel = args.oldSelections?args.oldSelections[0]:{};
     if(newSel.row != oldSel.row){
       me.initNavItem();
-      me.showRationGLJDatas();
-      me.showCalcProgramDatas();
+      me.showSubDatas();
+      zmhs_obj.showDatas();
     }
     args.sheet.repaint();
   },
@@ -685,11 +974,14 @@ let divideObj = {
       if(dataCode == "marketPrice"){
         value = scMathUtil.roundForObj(value,getDecimal("bills.unitPrice"));
         let commonFee = _.find(recode.fees,{"fieldName":"common"})
-        if (commonFee){
-          //let tu = scMathUtil.roundForObj(commonFee.unitFee&&commonFee.unitFee!=""?commonFee.unitFee:0,getDecimal("bills.unitPrice"))
-          commonFee.unitFee = scMathUtil.roundForObj(value,getDecimal("bills.unitPrice"));
-          doc["fees"] = recode.fees;
-        }
+        if(!commonFee){
+          commonFee = {fieldName: "common",tenderTotalFee: 0,tenderUnitFee: 0,totalFee: 0,unitFee: 0};
+          recode.fees?recode.fees.push(commonFee):recode.fees=[commonFee];
+        } 
+        //let tu = scMathUtil.roundForObj(commonFee.unitFee&&commonFee.unitFee!=""?commonFee.unitFee:0,getDecimal("bills.unitPrice"))
+        commonFee.unitFee = scMathUtil.roundForObj(value,getDecimal("bills.unitPrice"));
+        doc["fees"] = recode.fees;
+
         return {ID:recode.ID,type:'update',doc:doc};
       }
       
@@ -720,6 +1012,10 @@ let divideObj = {
     sheetCommonObj.spreadDefaultStyle(this.divideSubSpread);
     this.divideSubSheet = this.divideSubSpread.getSheet(0);
     sheetCommonObj.initSheet(this.divideSubSheet, gljCol.ration_glj_setting, 0);
+    this.divideSubSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onRationGljEditStarting);
+    this.divideSubSheet.bind(GC.Spread.Sheets.Events.ValueChanged,this.onRationGLJValueChange);
+    this.divideSubSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onRationGLJRangeChanged); 
+
     SheetDataHelper.protectdSheet(this.divideSubSheet);
     this.calcProgramSheet = this.divideSubSpread.getSheet(1);
     calcProgramObj.initSheet(this.calcProgramSheet);
@@ -857,29 +1153,6 @@ let divideObj = {
                   }
                 }
             },
-            "calcRation": {
-                name: "计算定额/量价",
-                icon: 'fa-sign-in',
-                disabled: function () {
-                  return me.rightClickTarget.row === undefined
-                },
-                callback: function (key, opt) {  
-                  let selected = me.getSelectedItem();
-                  projectObj.project.calcProgram.innerCalcRation({data:selected, sourceType:"ration", calcType: 1, updateData:[]});
-                  console.log(selected)
-                }
-            },
-            "calcBills": {
-                name: "计算分摊项",
-                icon: 'fa-sign-in',
-                disabled: function () {
-                  return me.rightClickTarget.row === undefined
-                },
-                callback: function (key, opt) {  
-                  let selected = me.getSelectedItem();
-                  console.log(me.calcBills(selected));
-                }
-            },
             "removeItem": {
                 name: "删除",
                 icon: 'fa-trash-o',
@@ -914,6 +1187,98 @@ let divideObj = {
         totalHeight: `$(window).height()-$('.header').height()-$('#divideToolsBar').height()-5`
     };
     return divideResizeEles;
+  },
+  calcDivideNodes : async function(item){
+    if(!item.marketTotalFee) return;
+    let changeNode=[];
+    let datas = [];
+    let usedIDMap={};
+    for(let b of item.bills){
+      let bNode = projectObj.project.mainTree.findNode(b.ID);
+      if(!bNode) continue;
+      let divideRate = scMathUtil.roundForObj(b.divideRate * 0.01,3);
+      let marketUnitFee = item.marketPrice?scMathUtil.roundForObj(item.marketPrice,getDecimal("bills.unitPrice")):0;
+      let quantity = item.quantity?scMathUtil.roundForObj(item.quantity,3):0;
+      quantity = scMathUtil.roundForObj(quantity*divideRate,getDecimal("ration.quantity"))//量价数量为分摊项的数量*分摊比例
+      if(quantity > 0 && marketUnitFee > 0){
+        let serialNo = 0;
+        let preID = "";
+        let divdeNode = null;
+        for(let cNode of bNode.children ){
+          if(cNode.data.divideID == item.ID){//说明已经存在了自动生成的量价,更新一下数据就行
+            let doc = {};
+            usedIDMap[cNode.data.ID] = true;
+            divdeNode = cNode;
+            if(cNode.data.name != item.name) doc.name = item.name;
+            if(cNode.data.unit != item.unit) doc.unit = item.unit;
+            if(cNode.data.quantity != quantity) doc.quantity = quantity;
+            if(cNode.data.marketUnitFee != marketUnitFee) doc.marketUnitFee = marketUnitFee;
+            if(!_.isEmpty(doc)){
+              doc.ID = cNode.data.ID;
+              datas.push({type:ModuleNames.ration,data:doc})
+              break;
+            }
+          }
+          preID = cNode.data.ID;
+          serialNo = cNode.data.serialNo;
+        }
+        if(divdeNode == null){//说明需要新增
+          let newID = uuid.v1() 
+          let newData = projectObj.project.Ration.getTempRationData(newID, b.ID, serialNo+1, rationType.volumePrice);
+          newData.name = item.name;
+          newData.unit = item.unit;
+          newData.quantity = quantity; 
+          newData.marketUnitFee = marketUnitFee;
+          newData.divideID = item.ID;
+          datas.push({type:ModuleNames.ration,data:newData,preSiblingID:preID,action:"add",parentID:b.ID});
+        }
+      }
+    }
+    //删除之前生成的,但是这次执行时没有用的节点
+    for(let r of projectObj.project.Ration.datas){
+       if(r.divideID == item.ID){
+         if(!usedIDMap[r.ID]){//没有用的删除
+          datas.push({type:ModuleNames.ration,data:{ID:r.ID},action:"delete"});
+          let pNode = projectObj.project.mainTree.findNode(r.billsItemID);
+          if(pNode)changeNode.push(pNode);
+         }
+       }
+    }
+
+
+    if(datas.length == 0) return;
+    //刷新缓存和树节点的插入删除
+    let nodes = await projectObj.project.syncUpdateNodesAndRefresh(datas);
+    //重新计算
+    cbTools.refreshFormulaNodes();
+    projectObj.project.calcProgram.calcNodesAndSave(changeNode.concat(nodes));
+  },
+  cancelDivide:async function(divideID){//如果不传ID,相当于取消所有
+     let changeNode=[],datas=[],itemDatas=[];
+     let divideSetting =  projectObj.project.divide_setting.datas
+     for(let d of divideSetting.divideList){
+        if(d.itemType == "分摊项"){
+          if(divideID && d.ID != divideID) continue;
+          if(d.bills && d.bills.length > 0){
+            itemDatas.push({ID:d.ID,type:'update',doc:{bills:[],divideType:0}});
+          }
+       }
+      }
+      if(itemDatas.length > 0) await this.updateItem(itemDatas);
+
+     for(let r of projectObj.project.Ration.datas){
+      if(!r.divideID || r.divideID=="") continue;
+      if(divideID && r.divideID != divideID)  continue;
+      datas.push({type:ModuleNames.ration,data:{ID:r.ID},action:"delete"});
+      let pNode = projectObj.project.mainTree.findNode(r.billsItemID);
+      if(pNode)changeNode.push(pNode);
+    }
+    if(datas.length == 0) return;
+  //刷新缓存和树节点的插入删除
+    let nodes = await projectObj.project.syncUpdateNodesAndRefresh(datas);
+    //重新计算
+    cbTools.refreshFormulaNodes();
+    projectObj.project.calcProgram.calcNodesAndSave(changeNode.concat(nodes));
   }
 }
 
@@ -974,7 +1339,7 @@ dividRationLibResizeEles.limit = {
     totalHeight: `$(window).height()-$('.header').height()-$('.toolsbar').height()-$('#divide_deToolsBar').height()-5`
 };
 
-function showDivideSide(tabPanel, show, id){
+function getDivideSideResizeEles(){
   let divideSideResizeEles = {};
   divideSideResizeEles.eleObj = {
       module: 'divideRationLibTab',
@@ -987,7 +1352,21 @@ function showDivideSide(tabPanel, show, id){
       min: 150,
       max: `$('#divideRow').width()-150`
   };
+  return divideSideResizeEles;
+}
 
+let dSideResizeEles =  getDivideSideResizeEles();
+//水平拖动
+SlideResize.horizontalSlide(dSideResizeEles.eleObj, dSideResizeEles.limit, function(){
+  SlideResize.loadVerticalHeight(dividRationLibResizeEles.eleObj.module, dividRationLibResizeEles.eleObj, dividRationLibResizeEles.limit, function () {
+    if(rationLibObj.divide_rationChapterSpread) rationLibObj.divide_rationChapterSpread.refresh();
+    if(rationLibObj.divide_sectionRationsSpread) rationLibObj.divide_sectionRationsSpread.refresh();
+  });
+  divideObj.refreshViews();  
+});
+
+function showDivideSide(tabPanel, show, id){
+  let divideSideResizeEles = getDivideSideResizeEles();
   divideSideResizeEles.eleObj.module = id;
   if (show) {
       //刚打开各库时的默认比例
@@ -1069,9 +1448,22 @@ $('#divide_zmhs_toogle').bind('click',function (){
 
 $('#exec_divide_btn').bind('click',function (){
    if(projectReadOnly) return;
+   let selected = divideObj.getSelectedItem();
+   if(selected.itemType !="分摊项") return;
   $("#exec_divide_div").modal('show');
 });
 
+$('#cancel_divide_btn').bind('click',function (){
+  if(projectReadOnly) return;
+  let selected = divideObj.getSelectedItem();
+  if(selected.itemType !="分摊项") return;
+  divideObj.cancelDivide(selected.ID);
+});
+
+$('#cancel_all_divide_btn').bind('click',function (){
+  if(projectReadOnly) return;
+  divideObj.cancelDivide();
+});
 
 $('#divideBottom ul li a').on('shown.bs.tab',function () {
   divideObj.showRationGLJDatas();
@@ -1080,5 +1472,29 @@ $('#divideBottom ul li a').on('shown.bs.tab',function () {
 
 $('#exec_divide_div').on('shown.bs.modal',function () {
   divideObj.initExecSpread();
-  divideObj.showExecDatas();
+  divideObj.showExecDatas(true);
+  let selected = divideObj.getSelectedItem();
+  let divideType = selected.divideType?selected.divideType:0;
+  for(let radio of $(".divide_type")){
+    $(radio).prop('checked', divideType == $(radio).val());
+  }
+  divideObj.selectedRadio=divideType;
+});
+
+$("#divide_confirm").bind('click',async function (){
+  let divideType = parseInt($("input[name='divide_type']:checked").val());
+  let item = divideObj.getSelectedItem();
+  let updateData = {ID:item.ID,type:'update',doc:{bills:divideObj.execBillsDatas,divideType:divideType}}
+  await divideObj.updateItem([updateData]);
+  await divideObj.calcDivideNodes(item);
+});
+
+
+$("input[name='divide_type']").each(function(){
+  $(this).click(function(){
+      if(divideObj.selectedRadio == $(this).val()) return;
+      if($(this).val() == 2)  return;
+      divideObj.selectedRadio = $(this).val();
+      divideObj.showExecBillsDatas();
+  });
 });

+ 3 - 3
web/building_saas/main/js/views/glj_col.js

@@ -8,9 +8,9 @@ let gljCol = {
             {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String",cellType:'tipsCell'},
             {headerName: "规格", headerWidth: 120, dataCode: "specs", dataType: "String", hAlign: "left",cellType:'tipsCell'},
             {headerName: "单位", headerWidth: 45, dataCode: "unit", dataType: "String", hAlign: "center"},
-            {headerName: "预算价", headerWidth: 65, dataCode: "marketPrice", dataType: "Number", hAlign: "right"},//, decimalField: "glj.unitPrice"
-            {headerName: "调整价", headerWidth: 65, dataCode: "adjustPrice", dataType: "Number", hAlign: "right"},//, decimalField: "glj.unitPrice"1
-            {headerName: "自定消耗", headerWidth: 65, dataCode: "customQuantity", dataType: "Number", hAlign: "right", decimalField: "glj.quantity"},
+            {headerName: "预算价", headerWidth: 65, dataCode: "marketPrice", dataType: "Number", validator:"number",hAlign: "right"},//, decimalField: "glj.unitPrice"
+            {headerName: "调整价", headerWidth: 65, dataCode: "adjustPrice", dataType: "Number",validator:"number", hAlign: "right"},//, decimalField: "glj.unitPrice"1
+            {headerName: "自定消耗", headerWidth: 65, dataCode: "customQuantity", dataType: "Number",validator:"number", hAlign: "right", decimalField: "glj.quantity"},
             {headerName: "消耗量", headerWidth: 65, dataCode: "quantity", dataType: "Number", hAlign: "right", decimalField: "glj.quantity"},
             {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"

+ 39 - 18
web/building_saas/main/js/views/zmhs_view.js

@@ -105,6 +105,8 @@ let zmhs_obj = {
               args.sheet.repaint();
           });
           SheetDataHelper.protectdSheet(this[pre+"coeSheet"]);
+      }else{
+        zmhs_obj[pre+"coeSpread"].refresh();
       }
     },
     initCusSpread:function () {
@@ -142,7 +144,7 @@ let zmhs_obj = {
           this[pre+"stableSheet"].name(pre+'ration_stable');
           this[pre+"stableSheet"].bind(GC.Spread.Sheets.Events.ValueChanged,this.onStableValueChange);
           this[pre+"stableSheet"].bind(GC.Spread.Sheets.Events.RangeChanged, this.onStableRangeChanged);
-          SheetDataHelper.protectdSheet(this);
+          SheetDataHelper.protectdSheet(this[pre+"stableSheet"]);
       }
     },
     showCoeData:function (node) {
@@ -151,8 +153,8 @@ let zmhs_obj = {
         let ration_coe = projectObj.project.ration_coe;
         let coeList = [];
         let coeSheet = this[pre+'coeSheet'];
-        this.coeSheet.suspendPaint();
-        this.coeSheet.suspendEvent();
+        coeSheet.suspendPaint();
+        coeSheet.suspendEvent();
         if(pre == "divide_"){//来自分摊
           coeList = divideObj.getCoeList();
         }else{
@@ -348,7 +350,7 @@ let zmhs_obj = {
         let me = zmhs_obj;
         let sheet = args.sheet, row = args.row, col = args.col;
         let cellType = sheet.getCellType(row, col);
-        if (args.sheetName == 'ration_coe' && cellType instanceof GC.Spread.Sheets.CellTypes.CheckBox) {
+        if ((args.sheetName == 'divide_ration_coe'||args.sheetName == 'ration_coe')&& cellType instanceof GC.Spread.Sheets.CellTypes.CheckBox) {
             me.onCoeCheckBoxClick(sender, args)
         }
     },
@@ -442,6 +444,7 @@ let zmhs_obj = {
     },
     onCoeCheckBoxClick:function (sender, args) {
         let me = zmhs_obj;
+        let pre = $('#divide_subSpread').is(':visible')?"divide_":"";
         let checkboxValue = args.sheet.getCell(args.row, args.col).value();
         let newval = 0;
         if (checkboxValue) {
@@ -451,7 +454,7 @@ let zmhs_obj = {
             newval = 1;
             args.sheet.getCell(args.row, args.col).value(newval);
         }
-        let recode = me.coeSheetData[args.row];
+        let recode = me[pre+"coeSheetData"][args.row];
         recode.assistCode && recode.assistCode != "" ? me.adjustAssClick(args,newval) : projectObj.project.ration_coe.adjustCoeClick(recode, newval);
     },
     generateHtmlString: function (context,cellRect,$editor) {//这里要改成动态的了,根据自定义系数内容生成对应的输入框
@@ -495,19 +498,22 @@ let zmhs_obj = {
     },
     onCoeValueChange:function (e,args) {
         let fieldID =  zmhs_obj.coeSetting.header[args.col].dataCode;
-        let recode = zmhs_obj.coeSheetData[args.row];
+        let pre = $('#divide_subSpread').is(':visible')?"divide_":"";
+        let recode = zmhs_obj[pre+"coeSheetData"][args.row];   
         if(gljUtil.isDef(recode.option_codes)&&recode.option_codes!=""&& fieldID == 'name'){//说明是选择了下拉框
-            projectObj.project.ration_coe.adjustCoeClick(recode, 1,{'select_code':args.newValue});
+          projectObj.project.ration_coe.adjustCoeClick(recode, 1,{'select_code':args.newValue});
         }else if(recode.assistCode &&recode.assistCode!=""){//编辑的是辅助定额
             zmhs_obj.updateRationAss({editingText:args.newValue,row:args.row - zmhs_obj.assFirstIndex})//转换一下
         }
+        
     },
     onCusValueChange:function (e,args) {
       zmhs_obj.changeCusValue([{row:args.row,col:args.col,value:args.newValue}]);
     },
     changeCusValue:function (datas) {//[{row:,col,value}]
-        if(this.cusSheetData){
-            let tem_coes = _.cloneDeep(this.cusSheetData.coes);
+        let pre = $('#divide_subSpread').is(':visible')?"divide_":"";
+        if(this[pre+"cusSheetData"]){
+            let tem_coes = _.cloneDeep(this[pre+"cusSheetData"].coes);
             for(let d of datas){
                 if(d.value&&!sheetCommonObj.checkData(d.col,this.cusSetting,d.value)){
                     this.showDatas();
@@ -525,7 +531,7 @@ let zmhs_obj = {
                 }
             }
             let doc = {'coes':tem_coes,'content':this.generationContent(tem_coes)};
-            projectObj.project.ration_coe.adjustCoeClick(this.cusSheetData, 1,doc);
+            projectObj.project.ration_coe.adjustCoeClick(this[pre+"cusSheetData"], 1,doc);
         }
     },
     generationContent:function (coes) {
@@ -574,13 +580,18 @@ let zmhs_obj = {
     },
     adjustAssClick:function (args,newval) {
         let me = zmhs_obj, row = args.row - me.assFirstIndex;
-        projectObj.project.ration_ass.updateActualValue(me.assSheetData, row,null,newval);
+        if($('#divide_subSpread').is(':visible')){
+          divideObj.updateActualValue(me.divide_assSheetData, args.row, null,newval);
+        }else{
+          projectObj.project.ration_ass.updateActualValue(me.assSheetData, row,null,newval);
+        }
     },
     updateRationAss: function (args) {
         var me = zmhs_obj;
         var newval;
+        let pre = $('#divide_subSpread').is(':visible')?"divide_":"";
         newval = me.numberValueChecking(args.editingText);
-        var recode = me.assSheetData[args.row];
+        var recode = me[pre+"assSheetData"][args.row];
         if (args.editingText === null) {
             newval = parseFloat(recode.stdValue);
         }
@@ -590,7 +601,11 @@ let zmhs_obj = {
         }
         if (isValidate) {
             newval = scMathUtil.roundTo(newval, -2);
-            projectObj.project.ration_ass.updateActualValue(me.assSheetData, args.row, newval);
+            if($('#divide_subSpread').is(':visible')){
+              divideObj.updateActualValue(me.divide_assSheetData, args.row, newval);
+            }else{
+              projectObj.project.ration_ass.updateActualValue(me.assSheetData, args.row, newval);
+            }
         } else {
             me.showDatas();
         }
@@ -645,9 +660,13 @@ let zmhs_obj = {
         // 获取需要更新的数据
         const rationGLJ = projectObj.project.ration_glj;
         const updateProportionList = this.getStablePostData(sheetData);
-        const projectID = projectObj.project.ID();
-        const rationID = projectObj.project.mainTree.selected.data.ID;
-        rationGLJ.updateProportion(updateProportionList, projectID, rationID);
+        if($('#divide_subSpread').is(':visible')){
+          divideObj.updateProportion(updateProportionList);
+        }else{
+          const projectID = projectObj.project.ID();
+          const rationID = projectObj.project.mainTree.selected.data.ID;
+          rationGLJ.updateProportion(updateProportionList, projectID, rationID);
+        }
     },
     // 将值进行四舍五入处理
     handleDataWithPrecision: function (data, precision) {
@@ -657,10 +676,11 @@ let zmhs_obj = {
     },
     // 获取经过自动处理后的表格数据
     getAutoStableSheetData: function (changedData, precision) {
+        let pre = $('#divide_subSpread').is(':visible')?"divide_":"";
         const expectedValue = 100;
         const unchangedData = [];
         const col = this.stableSetting.header.findIndex(item => item.dataCode === 'adjustProportion');
-        this.stableSheetData.forEach((item, index) => {
+        this[pre+"stableSheetData"].forEach((item, index) => {
             const matchData = changedData.find(dItem => dItem.row === index);
             if (!matchData) {
                 unchangedData.push({ row: index, col: col, value: item.adjustProportion});
@@ -696,9 +716,10 @@ let zmhs_obj = {
         }
     },
     getStablePostData: function (sheetData) {
+        let pre = $('#divide_subSpread').is(':visible')?"divide_":"";
         const postData = [];
         sheetData.forEach(cell => {
-            const originItem = this.stableSheetData[cell.row];
+            const originItem = this[pre+"stableSheetData"][cell.row];
             if (cell.value !== originItem.adjustProportion) {
                 postData.push({ ID: originItem.ID, adjustProportion: cell.value});
             }

+ 1 - 1
web/building_saas/unit_price_file/index.html

@@ -174,7 +174,7 @@
     <img src="/web/dest/css/img/engineering.png" id="eng_pic" style="display: none">
     <img src="/web/dest/css/img/tender.png" id="tender_pic" style="display: none">
 
-    <img src="/web/dest/css/img/blockLib.png" id="blockLib_pic" style="display: none">
+    <img src="/web/dest/css/img/blocklib.png" id="blockLib_pic" style="display: none">
     <img src="/web/dest/css/img/folder_open.png" id="folder_pic" style="display: none">
     <img src="/web/dest/css/img/tender.png" id="block_pic" style="display: none">