浏览代码

材料计算相关功能

zhangweicheng 6 年之前
父节点
当前提交
be10e61250

+ 34 - 0
modules/all_models/material_calc.js

@@ -0,0 +1,34 @@
+/**
+ * Created by zhang on 2019/3/18.
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let freightSchema = {
+    ID:String,
+    unit_price_file_id: Number,
+    connect_key: {type: String, index: true},// 关联项目工料机的key 不能关联id,因为单价文件导入别的项目后项目工料机id不同
+    start:String,//起讫地点
+    conveyance:String,//运输工具
+    unitFreight:String,//单位运价
+    kmDistance:String,//km运距
+    unitLoadingFee:String,//装卸费单价
+    loadingTimes:String,//装卸次数
+    otherFee:String,//其它费用
+    freightIncreaseRate:String,//运价增加率
+    weightCoe:String//加权系数
+
+};
+mongoose.model("freight_calc", new Schema(freightSchema, {versionKey: false, collection: "freight_calc"}));
+
+
+let originalSchema = {
+    ID:String,
+    unit_price_file_id: Number,
+    connect_key: {type: String, index: true},// 关联项目工料机的key 不能关联id,因为单价文件导入别的项目后项目工料机id不同
+    supplyLocation:String,//供应地点
+    supplyPrice:String,//供应价
+    coe:String//加权系数
+};
+
+mongoose.model("original_calc", new Schema(originalSchema, {versionKey: false, collection: "original_calc"}));

+ 15 - 2
modules/all_models/unit_price.js

@@ -51,9 +51,22 @@ let modelSchema = {
         type: Number,
         default: 0
     },
-    grossWeightCoe: Number, //毛重系数
+    supplyLocation:String,//供应地点
+    originalPrice:String,//原价
+    unitFreight:String,//单价运费
+    totalLoadingTimes:String,//装卸总次数
+    offSiteTransportLoss:String,//场外运输损耗
+    purchaseStorage:String,//采购及保管费
+    packageRecoverValue:String,//包装品回收价值
+    calcMaterial:{ type: Number, default: 0},//材料计算标计,1为材料计算
+    grossWeightCoe_n: Number, //单位毛重
+    purchaseStorageRate_n: Number, //采购保管费率
+    offSiteTransportLossRate_n: Number, //场外运输损耗率
+    handlingLossRate_n: Number, //每增一次装卸损耗率
+    //----初始计算数据
+    grossWeightCoe: Number, //单位毛重
     purchaseStorageRate: Number, //采购保管费率
-    offSiteTransportLossRate: Number, //场外运输损耗率
+    offSiteTransportLossRate:Number, //场外运输损耗率
     handlingLossRate: Number //每增一次装卸损耗率
 };
 mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));

+ 114 - 0
modules/glj/controllers/glj_controller.js

@@ -17,6 +17,8 @@ let glj_type_util = require('../../../public/cache/std_glj_type_util');
 let ration_glj_facade = require('../../ration_glj/facade/ration_glj_facade');
 let EngineeringLibModel = require("../../users/models/engineering_lib_model");
 let mongoose = require('mongoose');
+let original_calc_model = mongoose.model('original_calc');
+let freight_calc_model = mongoose.model('freight_calc');
 let ration = mongoose.model('ration');
 let projectModel = mongoose.model('projects');
 let _ = require('lodash');
@@ -390,6 +392,96 @@ class GLJController extends BaseController {
         response.json(result);
     }
 
+    async addOriginalCalc(request, response){
+        let result={error:0};
+        try {
+            let data = JSON.parse(request.body.data);
+            result.data = await glj_facade.addOriginalCalc(data);
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+
+    async addFreightCalc(request, response){
+        let result={error:0};
+        try {
+            let data = JSON.parse(request.body.data);
+            result.data = await glj_facade.addFreightCalc(data);
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+
+    async deletePriceCalc(request, response){
+        let result={error:0};
+        try {
+            let data = JSON.parse(request.body.data);
+            result.data = await glj_facade.deletePriceCalc(data);
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async updateOriginalCalc(request, response){
+        let result={error:0};
+        try {
+            let data = JSON.parse(request.body.data);
+            result.data = await glj_facade.updateOriginalCalc(data);
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async updateMaterialCalc(request, response){
+        let result={error:0};
+        try {
+            let data = JSON.parse(request.body.data);
+            result.data = await glj_facade.updateMaterialCalc(data);
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+
+
+    async updateFreightCalc(request, response){
+        let result={error:0};
+        try {
+            let data = JSON.parse(request.body.data);
+            result.data = await glj_facade.updateFreightCalc(data);
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+
+    async deleteFreightCalc(request, response){
+        let result={error:0};
+        try {
+            let data = JSON.parse(request.body.data);
+            result.data = await glj_facade.deleteFreightCalc(data);
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+
     async checkUnitFileName(request, response){
         let result={
             error:0
@@ -621,6 +713,26 @@ class GLJController extends BaseController {
         }
         res.json(result);
     }
+    async updateCalcMaterial(req, res){
+        let result={
+            error:0
+        }
+        try {
+            let data = req.body.data;
+            data = JSON.parse(data);
+            let unitPriceModel = new UnitPriceModel();
+            // 更新数据
+            let datas = await unitPriceModel.updateCalcMaterial(data);
+            result.data=datas;
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        res.json(result);
+    }
+
+
     async batchUpdatePrices(req, res){
         let result={
             error:0
@@ -795,6 +907,8 @@ async function getGLJListByProjectID(projectId){
         responseData.data.mixRatioMap = mixRationMap;
         responseData.data.usedTenderList = usedTenderList;
         responseData.data.unitPriceMap = unitPriceMap;
+        responseData.data.originalList = await original_calc_model.find({"unit_price_file_id":unitPriceFileId});
+        responseData.data.freightList = await freight_calc_model .find({"unit_price_file_id":unitPriceFileId});
         let gljTypeMap = glj_type_util.getStdGljTypeCacheObj().innerGljTypeObj;
         let unitPriceFileModel = new UnitPriceFileModel();
         let unitFileInfo =  await unitPriceFileModel.findDataByCondition({id: unitPriceFileId});

+ 72 - 4
modules/glj/facade/glj_facade.js

@@ -4,7 +4,14 @@
 module.exports={ //先导出后require可以解决循环引用问题
     changeUnitFile:changeUnitFile,
     changeVvTaxFile:changeVvTaxFile,
-    addMixRatioForNew:addMixRatioForNew
+    addMixRatioForNew:addMixRatioForNew,
+    addOriginalCalc:addOriginalCalc,
+    deletePriceCalc:deletePriceCalc,
+    updateOriginalCalc:updateOriginalCalc,
+    addFreightCalc:addFreightCalc,
+    deleteFreightCalc:deleteFreightCalc,
+    updateFreightCalc:updateFreightCalc,
+    updateMaterialCalc:updateMaterialCalc
 };
 
 const mongoose = require('mongoose');
@@ -15,8 +22,12 @@ import MixRatioModel from "../models/mix_ratio_model";
 import CounterModel from "../models/counter_model";
 import GLJListModel from '../../glj/models/glj_list_model';
 let std_glj_lib_gljList_model = mongoose.model('std_glj_lib_gljList');
-let ration_glj = require('../../ration_glj/facade/ration_glj_facade');
+let original_calc_model = mongoose.model('original_calc');
+let freight_calc_model = mongoose.model('freight_calc');
+let unit_price_model = mongoose.model('unit_price');
 
+let ration_glj = require('../../ration_glj/facade/ration_glj_facade');
+const uuidV1 = require('uuid/v1');
 let  vvTaxModel =  mongoose.model("std_vehicleVesselTax_items");
 let gljUtil = require('../../../public/gljUtil');
 let _ = require("lodash");
@@ -56,7 +67,7 @@ async function changeUnitFile(projectData,unitFile,type,userID) {
 
         // 查找对应单价文件的项目工料机数据
         let unitPriceModel = new UnitPriceModel();
-        if(type ===1){//从其它项目复制,则先复制一份数据。
+   /*     if(type ===1){//从其它项目复制,则先复制一份数据。 后面会做复制操作了,
             let needCopyList = await unitPriceModel.findDataByCondition({unit_price_file_id: changeUnitPriceId}, null, false);
             if(needCopyList){
                 // 过滤mongoose格式
@@ -71,7 +82,7 @@ async function changeUnitFile(projectData,unitFile,type,userID) {
                 }
                 copyList.length>0 ? await unitPriceModel.add(copyList):'';
             }
-        }
+        }*/
         let copyResult = await unitPriceModel.copyNotExist(currentUnitPriceId, targetUnitPriceFile.id,projectId);
         // 复制成功后更改project数据
         if (!copyResult) {
@@ -154,4 +165,61 @@ async function addMixRatioForNew(projectID,unitFileId,engineerID,ext){
         ration_glj.setPropertyFromStd(tem,glj);
         await projectGljModel.addList(ration_glj.getGLJSearchInfo(tem),unitFileId,ext);
     }
+}
+
+async function updateUnitPrice(unitPrice) {
+    if(unitPrice && !_.isEmpty(unitPrice.doc)){
+       await unit_price_model.findOneAndUpdate({id:unitPrice.id,unit_price_file_id:unitPrice.unit_price_file_id},unitPrice.doc);
+    }
+}
+
+async function addOriginalCalc(data) {
+    let datas = data.datas;
+    for(let d of datas){
+        d.ID = uuidV1();
+    }
+    let result = await original_calc_model.create(datas);
+    await updateUnitPrice(data.unitPrice);
+    return result;
+}
+
+
+
+async function addFreightCalc(data){
+    let datas = data.datas;
+    for(let d of datas){
+        d.ID = uuidV1();
+    }
+    let result = await freight_calc_model.create(datas);
+    await updateUnitPrice(data.unitPrice);
+    return result;
+}
+
+async function deletePriceCalc(data){
+    let result = await original_calc_model.deleteOne({ID:data.ID});
+    await updateUnitPrice(data.unitPrice);
+    return result
+}
+
+async function updateOriginalCalc(data){
+    if(data.tasks.length > 0 ) await original_calc_model.bulkWrite(data.tasks);
+    await updateUnitPrice(data.unitPrice);
+    return{};
+}
+
+async function updateFreightCalc(data){
+    if(data.tasks.length > 0 ) await freight_calc_model.bulkWrite(data.tasks);
+    await updateUnitPrice(data.unitPrice);
+    return{};
+}
+
+async function updateMaterialCalc(data) {
+    if(data.tasks.length > 0) await unit_price_model.bulkWrite(data.tasks);
+    return {}
+}
+
+async function deleteFreightCalc(data){
+    let result = await freight_calc_model.deleteOne({ID:data.ID});
+    await updateUnitPrice(data.unitPrice);
+    return result
 }

+ 1 - 1
modules/glj/models/mix_ratio_model.js

@@ -96,7 +96,7 @@ class MixRatioModel extends BaseModel {
             if(targetMap[ckey]){//如果切换后的单价文件已经存在,则不用复
                 continue;
             }
-            if(gljMap[ckey]){//在本项目中有用到
+            if(gljMap[ckey] && gljMap[ckey].copy  == true){//在本项目中有用到
                 for(let ratio of  currentMap[ckey]){
                     delete ratio._id;  // 删除原有id信息
                     delete ratio.id;

+ 56 - 1
modules/glj/models/unit_price_model.js

@@ -15,6 +15,10 @@ const scMathUtil = require('../../../public/scMathUtil').getUtil();
 let collectionName = 'unit_price';
 let decimal_facade = require('../../main/facade/decimal_facade');
 let gljListModel = mongoose.model("glj_list");
+let original_calc_model = mongoose.model('original_calc');
+let freight_calc_model = mongoose.model('freight_calc');
+let gljUtil = require('../../../public/gljUtil');
+const uuidV1 = require('uuid/v1');
 
 
 class UnitPriceModel extends BaseModel {
@@ -275,6 +279,21 @@ class UnitPriceModel extends BaseModel {
         return rList;
     }
 
+    async updateCalcMaterial(data){
+        let doc = data.ext?data.ext:{};
+        doc[data.updateField] = data.value;
+        let unitPrice = await this.db.findAndModify({id:data.id,unit_price_file_id:data.unit_price_file_id},doc);
+        if(data.updateField == 'calcMaterial' && doc['calcMaterial'] == 0){//标记为0即删除材料计算标记,要删除其下挂的原价计算,运费计算,定额计算
+            let connect_key = gljUtil.getIndex(unitPrice);
+            await original_calc_model.deleteMany({unit_price_file_id:data.unit_price_file_id,connect_key:connect_key});
+            await freight_calc_model.deleteMany({unit_price_file_id:data.unit_price_file_id,connect_key:connect_key});
+            //to do 删除定额计算
+        }
+        if(!unitPrice){
+            throw "没有找到对应的单价";
+        }
+        return unitPrice;
+    }
     needUpdateParent(connect_key){
         let noNeedUpdateType = ["202","203","204"];//父类型为混凝土、砂浆,配合比,类型的,不用更新价格
         let keyList = connect_key.split("|-|");
@@ -441,14 +460,50 @@ class UnitPriceModel extends BaseModel {
                 delete tmp.id;
                 tmp.unit_price_file_id = changeUnitPriceId;
                 insertData.push(tmp);
+                gljMap[t_index].copy = true;//复制标记,用于组成物,材料计算等的复制
             }
         }
         let uResult = insertData.length > 0 ? this.add(insertData) : true;
         let mixRatioModel = new MixRatioModel();
         let mResult = await mixRatioModel.copyNotExist(currentUnitPriceId, changeUnitPriceId,gljMap);//复制组成物
-        return uResult&&mResult;
+        let cResult = await this.copyMaterialNotExist(currentUnitPriceId, changeUnitPriceId,gljMap);
+
+        return uResult&&mResult&&cResult;
 
     }
+    async copyMaterialNotExist(currentUnitPriceId, changeUnitPriceId,gljMap){
+        await  this.copyCalcNotExist(currentUnitPriceId, changeUnitPriceId,gljMap,original_calc_model);//复制原价计算
+        await  this.copyCalcNotExist(currentUnitPriceId, changeUnitPriceId,gljMap,freight_calc_model);//复制运费计算
+        return true;
+    }
+
+    async  copyCalcNotExist(currentUnitPriceId, changeUnitPriceId,gljMap,model){
+        let currentMap = {},targetMap = {}, insertData = [];
+        //取原单价文件所有的原价、运费计算计录
+        let currentList = await model.find({'unit_price_file_id':currentUnitPriceId});
+        // 过滤mongoose格式
+        currentList = JSON.stringify(currentList);
+        currentList = JSON.parse(currentList);
+        currentMap = _.groupBy(currentList,"connect_key");
+
+        //切换后的单价文件所有的的组成物
+        let targetList = await model.find({'unit_price_file_id':changeUnitPriceId});
+        targetMap =  _.groupBy(targetList,"connect_key");
+        for(let ckey in currentMap){
+            if(targetMap[ckey]){//如果切换后已经存在,则不用复制
+                continue;
+            }
+            if(gljMap[ckey] && gljMap[ckey].copy  == true){//在本项目中有用到并且复制标记为true
+                for(let c of  currentMap[ckey]){
+                    delete c._id;  // 删除原有id信息
+                    c.ID = uuidV1();
+                    c.unit_price_file_id = changeUnitPriceId;
+                    insertData.push(c);
+                }
+            }
+        }
+        if(insertData.length > 0)  await model.create(insertData);
+    }
 
 
 }

+ 8 - 0
modules/glj/routes/glj_router.js

@@ -24,11 +24,19 @@ router.post('/checkUnitFileName', gljController.init, gljController.checkUnitFil
 router.post('/save-as', gljController.init, gljController.unitPriceSaveAs);
 router.post('/get-composition', gljController.init, gljController.getComposition);
 router.post('/updatePrice', gljController.init, gljController.updateUnitPrice);
+router.post('/updateCalcMaterial', gljController.init, gljController.updateCalcMaterial);
 router.post('/batchUpdatePrices', gljController.init, gljController.batchUpdatePrices);
 router.post('/batchUpdateGLJProperty', gljController.init, gljController.batchUpdateGLJProperty);
 router.post('/batchUpdateConsumption', gljController.init, gljController.batchUpdateConsumption);
 router.post('/modifyKeyValue',gljController.init, gljController.modifyKeyValue);
 router.post('/changeVvTaxFile',gljController.init, gljController.changeVvTaxFile);
+router.post('/addOriginalCalc',gljController.init, gljController.addOriginalCalc);
+router.post('/deletePriceCalc',gljController.init, gljController.deletePriceCalc);
+router.post('/updateOriginalCalc',gljController.init, gljController.updateOriginalCalc);
+router.post('/addFreightCalc',gljController.init, gljController.addFreightCalc);
+router.post('/deleteFreightCalc',gljController.init, gljController.deleteFreightCalc);
+router.post('/updateFreightCalc',gljController.init, gljController.updateFreightCalc);
+router.post('/updateMaterialCalc',gljController.init, gljController.updateMaterialCalc);
 
 router.get('/getVvTaxList', gljController.init, gljController.getVvTaxList);
 router.get('/test', gljController.init, gljController.test);

+ 43 - 2
modules/main/facade/project_facade.js

@@ -25,7 +25,8 @@ module.exports = {
     calcInstallationFee:calcInstallationFee,
     saveProperty: saveProperty,
     getDefaultColSetting: getDefaultColSetting,
-    markProjectsToChange:markProjectsToChange
+    markProjectsToChange:markProjectsToChange,
+    getBudgetSummayDatas:getBudgetSummayDatas
 };
 
 async function calcInstallationFee(data) {
@@ -271,4 +272,44 @@ function saveProperty(data, callback){
 
 async function getDefaultColSetting(libID){
     return await stdColSettingModel.findOne({ID: libID, deleted: false}, '-_id main_tree_col');
-}
+}
+
+async function getBudgetSummayDatas(projectIDs){
+    let projects = [];
+    for(let ID of projectIDs){
+        projects.push(await getBillsByProjectID(ID)) ;
+    }
+
+
+
+}
+
+async function getBillsByProjectID(projectID){
+    let items = [],roots=[],parentMap={};
+    let bills =  await bill_model.model.find({projectID: projectID}, '-_id');//取出所有清单
+    let project = await projectsModel.findOne({ID:projectID});
+    let projectName = project?project.name:"";
+   for(let b of  bills){
+       items.push(b._doc);
+       if(b.parentID == -1) roots.push(b._doc);
+       parentMap[b.parentID]?parentMap[b.parentID].push[b._doc]:parentMap[b.parentID]=[b._doc];
+   }//设置子节点+排序
+   for(let r of roots){
+        setChildren(r,parentMap)
+   }
+}
+
+function setChildren(bill,parentMap) {
+    let children = parentMap[bill.ID];
+    let childrenMap = {};
+    let firstNode = null;
+    if(children){
+        for(let c of children){
+            childrenMap[c.ID] = c;
+            setChildren(c,parentMap)
+        }
+
+
+        bill.children = children;
+    }
+}

+ 9 - 1
public/web/gljUtil.js

@@ -330,6 +330,10 @@ let gljUtil = {
     isAddCommercialForReplace:function (oldType,newType,rationItemQuantity) {
         return gljUtil.isConcreteType(oldType)&&gljUtil.isCommercialConcreteType(newType)&&rationItemQuantity&&rationItemQuantity!='0';
     },
+    isMaterialType:function (type) {
+       let materialType = [gljType.GENERAL_MATERIAL,gljType.GREEN_SEEDLING,gljType.PURCHASE_COMPONENT,gljType.COMMERCIAL_CONCRETE,gljType.COMMERCIAL_MORTAR];//可以添加材料计算的类型普通材料”、“绿化苗木”、“外购砼构件”、“商品混凝土”、“商品砂浆”
+        return materialType.indexOf(type)!= -1
+    },
     hasComposition:function (ration_glj,isRationType) {//判断是否有组成物,有则返回true   现在主材类型的工料机也有可能有组成物。
         let type = isRationType==true? ration_glj.subType:ration_glj.type;
         if(gljUtil.notEditType.indexOf(type)!=-1||type==gljType.MAIN_MATERIAL){
@@ -348,7 +352,11 @@ let gljUtil = {
     getBaseCCSMixRatio:function (unitFileID,consumption,connect_key) {
         return {glj_id:-99,unit_price_file_id:unitFileID,connect_key:connect_key,consumption:consumption,code:'80CCS',name:'车船税',unit:'元',type:302,specs:''}
     },
-
+    updateProperty: function (obj, doc) {
+        _.forEach(doc, function (n, key) {
+            obj[key] = n;
+        });
+    },
     fixedFlag : {
         // 分部分项工程
         SUB_ENGINERRING: 1,

+ 4 - 4
web/building_saas/glj/html/project_glj.html

@@ -40,10 +40,10 @@
             <div class="bottom-content" id="projectGljBottom">
                 <ul class="nav nav-tabs d-flex" role="tablist">
                     <li class="nav-item">
-                       <!-- <a class="nav-link  show" id="calc-nav" data-toggle="tab" href="#mc" role="tab" aria-selected="true">材料计算</a>-->
+                        <a class="nav-link active show" id="calc-nav" data-toggle="tab" href="#mc" role="tab" aria-selected="true">材料计算</a>
                     </li>
                     <li class="nav-item">
-                        <a class="nav-link active" id="mixRatio-nav" data-toggle="tab" href="#ph_div" role="tab" aria-selected="false">组成物计算</a>
+                        <a class="nav-link " id="mixRatio-nav" data-toggle="tab" href="#ph_div" role="tab" aria-selected="false">组成物计算</a>
                     </li>
                 </ul>
                 <!-- Tab panes -->
@@ -53,7 +53,7 @@
                             相关定额
                         </div>
                     </div>-->
-                    <div class="tab-pane container-fluid" id="mc" role="tabpanel">
+                    <div class="tab-pane container-fluid active" id="mc" role="tabpanel">
                         <div class="row">
                             <div class="main-data-bottom ovf-hidden" id="materialCalcSheet" style="width: 55%"></div>
                             <div class="main-data-bottom ovf-hidden full-h "  id="calcDiv" style="width: 45%">
@@ -85,7 +85,7 @@
 
                         </div>
                  </div>
-                    <div class="tab-pane active" id="ph_div" role="tabpanel">
+                    <div class="tab-pane" id="ph_div" role="tabpanel">
                         <div class="main-data-bottom" id="mix_ratio_sheet" style="overflow:hidden">
                         </div>
                     </div>

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

@@ -277,6 +277,372 @@ ProjectGLJ.prototype.getPriceDecimal = function (glj) {//价格的小数位数
     }
 
 };
+ProjectGLJ.prototype.updateCalcMaterial =async function (projectGLJ,updateField,value,ext) {//只有添加、删除走这个方法
+    let glj = _.find(this.datas.gljList,{'id':projectGLJ.id});
+    if (glj) {
+        if(glj.unit_price[updateField] == value){
+            return;
+        }
+        if(updateField == 'calcMaterial'){
+            ext=ext?ext:{};
+            if(value == 1){//添加材料计算操作,把单位毛重/采购保管费率等数据复制一份
+                ext['grossWeightCoe_n'] = glj.unit_price.grossWeightCoe;
+                ext['purchaseStorageRate_n'] = glj.unit_price.purchaseStorageRate;
+                ext['offSiteTransportLossRate_n'] = glj.unit_price.offSiteTransportLossRate;
+                ext['handlingLossRate_n'] = glj.unit_price.handlingLossRate;
+            }else if(value == 0){//删除操作,恢复单位毛重/采购保管费率等数据
+                ext['supplyLocation'] = '';
+                ext['originalPrice'] = '0';
+                ext['unitFreight']='0';
+                ext['totalLoadingTimes']='0';
+                ext['offSiteTransportLoss']='0';
+                ext['purchaseStorage']='0';
+                ext['packageRecoverValue']='0';
+            }
+        }
+        let data = {id: glj.unit_price.id,updateField:updateField ,value: value,unit_price_file_id:glj.unit_price.unit_price_file_id,ext:ext};
+        $.bootstrapLoading.start();
+        try {
+            let result = await ajaxPost('/glj/updateCalcMaterial',data);
+            glj.unit_price[updateField] = value;
+            if(ext){
+                for(let key in ext){
+                    glj.unit_price[key] = ext[key];
+                }
+            }
+            if(updateField == 'calcMaterial' && value ==0){///标记为0即删除材料计算标记,要删除其下挂的原价计算,运费计算,定额计算
+                let connect_key = gljUtil.getIndex(glj);
+                _.remove(this.datas.originalList,{'connect_key':connect_key});
+                _.remove(this.datas.freightList,{'connect_key':connect_key});
+                // to do 删除定额计算
+
+            }
+            projectGljObject.refreshDataSheet();
+            materialCalcObj.showDatas();
+        }catch (e){
+            console.log(e)
+        }finally {
+            $.bootstrapLoading.end();
+        }
+
+    }
+};
+
+ProjectGLJ.prototype.materialCal = function (id,dataMap) {
+    let unitPriceHasMix = getDecimal("glj.unitPriceHasMix");
+    let unitPirceDecimal = getDecimal("glj.unitPrice");
+    let process = getDecimal("process");
+    let glj = _.find(this.datas.gljList,{'id':id});
+    let doc = dataMap['material']&&dataMap['material']['update']?dataMap['material']['update']:{};//材料的update结构不同,不用ID做key
+    if(!glj) return;
+    let unitPrice = {id:glj.unit_price.id,'unit_price_file_id':glj.unit_price.unit_price_file_id,doc:{}};
+    //先计算原价
+    let [originalPrice,supplyLocation] = this.priceCalc(glj,dataMap);
+    doc['originalPrice'] = originalPrice+'';
+    doc['supplyLocation'] = supplyLocation;
+    //再计算运费
+    let grossWeightCoe_n = doc['grossWeightCoe_n']?doc['grossWeightCoe_n']:glj.unit_price.grossWeightCoe_n;
+    grossWeightCoe_n = scMathUtil.roundForObj(grossWeightCoe_n,unitPirceDecimal);
+    let unitFreight = this.freightCalc(glj,grossWeightCoe_n,dataMap);
+    doc['unitFreight'] = unitFreight+'';
+    //计算场外运输损耗
+    let sum_o_f = scMathUtil.roundForObj(originalPrice+unitFreight,process);//(原价+单位运费)
+    let totalLoadingTimes = doc["totalLoadingTimes"]?doc["totalLoadingTimes"]:glj.unit_price.totalLoadingTimes;//装卸总次数
+    let handlingLossRate_n = doc["handlingLossRate_n"]?doc["handlingLossRate_n"]:glj.unit_price.handlingLossRate_n;//每增加一次装卸损耗率%
+    let offSiteTransportLossRate_n = doc["offSiteTransportLossRate_n"]?doc["offSiteTransportLossRate_n"]:glj.unit_price.offSiteTransportLossRate_n;//场外运输损耗率
+    handlingLossRate_n = scMathUtil.roundForObj(handlingLossRate_n,unitPirceDecimal)/100;
+    offSiteTransportLossRate_n = scMathUtil.roundForObj(offSiteTransportLossRate_n,unitPirceDecimal)/100;
+    totalLoadingTimes = scMathUtil.roundForObj(totalLoadingTimes,unitPirceDecimal) - 1;//(装卸总次数-1)
+    totalLoadingTimes = scMathUtil.roundForObj(totalLoadingTimes * handlingLossRate_n,process);//(装卸总次数-1)*每增加一次装卸损耗率%
+    totalLoadingTimes = scMathUtil.roundForObj(totalLoadingTimes + offSiteTransportLossRate_n,process);//(装卸总次数-1)*每增加一次装卸损耗率%+场外运输损耗率%
+    let offSiteTransportLoss = scMathUtil.roundForObj(sum_o_f*totalLoadingTimes,unitPirceDecimal); //场外运输损耗=(原价+单位运费)*((装卸总次数-1)*每增加一次装卸损耗率%+场外运输损耗率%)。
+    doc['offSiteTransportLoss'] = offSiteTransportLoss+'';
+    //计算采购及保管费
+    let purchaseStorageRate_n =  doc["purchaseStorageRate_n"]?doc["purchaseStorageRate_n"]:glj.unit_price.purchaseStorageRate_n;//采购及保管费率%
+    purchaseStorageRate_n = scMathUtil.roundForObj(purchaseStorageRate_n,unitPirceDecimal)/100;
+    let purchaseStorage = scMathUtil.roundForObj(sum_o_f + offSiteTransportLoss,process)//(原价+单位运费+场外运输损耗)
+    purchaseStorage = scMathUtil.roundForObj(purchaseStorage*purchaseStorageRate_n,unitPirceDecimal)//采购及保管费=(原价+单位运费+场外运输损耗)* 采购及保管费率%。
+    doc['purchaseStorage'] = purchaseStorage+'';
+    //再计算预算价
+    let packageRecoverValue = doc['packageRecoverValue']?doc['packageRecoverValue']:glj.unit_price.packageRecoverValue;//包装品回收价值。
+    packageRecoverValue = scMathUtil.roundForObj(packageRecoverValue,unitPirceDecimal);
+    let market_price = scMathUtil.roundForObj(sum_o_f+offSiteTransportLoss,process);//原价+单位运费+场外运输损耗
+    market_price = scMathUtil.roundForObj(market_price+purchaseStorage,process);//原价+单位运费+场外运输损耗+采购及保管费
+    market_price = scMathUtil.roundForObj(market_price - packageRecoverValue,unitPriceHasMix)//预算价=原价+单位运费+场外运输损耗+采购及保管费-包装品回收价值。
+    if(market_price>0) doc['market_price'] = market_price+'';//单机版预算价小于等于0的时候不更新
+    let o_unit = glj.unit_price;
+    for(let key in doc){
+        if(o_unit[key]  == doc[key]) continue; //忽略一样的值
+        unitPrice.doc[key] = doc[key];
+    }
+    return unitPrice
+};
+
+ProjectGLJ.prototype.freightCalc= function (glj,grossWeightCoe_n,dataMap) {
+    let process = getDecimal("process");
+    let unitPirce = getDecimal("glj.unitPrice");
+    let unitPriceHasMix = getDecimal("glj.unitPriceHasMix");//这里暂时没用到
+    let sum = 0;
+    let freightList = _.filter(this.datas.freightList,{"connect_key":gljUtil.getIndex(glj)});
+    if(dataMap["freight"] && dataMap["freight"]["add"])  freightList = freightList.concat(dataMap["freight"]["add"]); //把添加的加进去
+    for(let f of freightList){
+        let unitFreight = f.unitFreight,kmDistance = f.kmDistance,freightIncreaseRate = f.freightIncreaseRate,unitLoadingFee= f.unitLoadingFee,loadingTimes = f.loadingTimes,otherFee = f.otherFee,weightCoe = f.weightCoe;
+        if(dataMap["freight"] && dataMap["freight"]["update"]){//覆盖更新的数据
+            let t = dataMap["freight"]["update"][f.ID];
+            if(t){
+                if(t['unitFreight']) unitFreight = t['unitFreight'];
+                if(t['kmDistance']) kmDistance = t['kmDistance'];
+                if(t['freightIncreaseRate']) freightIncreaseRate = t['freightIncreaseRate'];
+                if(t['unitLoadingFee']) unitLoadingFee = t['unitLoadingFee'];
+                if(t['loadingTimes']) loadingTimes = t['loadingTimes'];
+                if(t['otherFee']) otherFee = t['otherFee'];
+                if(t['weightCoe']) weightCoe = t['weightCoe'];
+            }
+        }
+        if(dataMap["freight"] && dataMap["freight"]["delete"]){//忽略删除的数据
+            if(f.ID ==dataMap["freight"]["delete"]) continue;
+        }
+        //开始计算
+        freightIncreaseRate = scMathUtil.roundForObj(freightIncreaseRate,unitPirce);
+        freightIncreaseRate = scMathUtil.roundForObj(1+freightIncreaseRate/100,process);//(1+运距增加率%)
+        unitFreight = scMathUtil.roundForObj(unitFreight,unitPirce);
+        kmDistance = scMathUtil.roundForObj(kmDistance,unitPirce);
+        let t = scMathUtil.roundForObj(unitFreight * kmDistance,process);//单位运价×km运距
+        t = scMathUtil.roundForObj(t*freightIncreaseRate,process);//单位运价×km运距×(1+运距增加率%)
+        unitLoadingFee = scMathUtil.roundForObj(unitLoadingFee,unitPirce);
+        loadingTimes = scMathUtil.roundForObj(loadingTimes,unitPirce);
+        let s = scMathUtil.roundForObj(unitLoadingFee*loadingTimes,process);//装卸费单价×装卸次数
+        t = scMathUtil.roundForObj(t + s,process);//单位运价×km运距×(1+运距增加率%)+装卸费单价×装卸次数
+        otherFee = scMathUtil.roundForObj(otherFee,unitPirce);
+        t = scMathUtil.roundForObj(t+otherFee,process);//单位运价×km运距×(1+运距增加率%)+装卸费单价×装卸次数+其它费用
+        t = scMathUtil.roundForObj(t*grossWeightCoe_n,process); //(单位运价×km运距×(1+运距增加率%)+装卸费单价×装卸次数+其它费用)×单位毛重”。 单位毛重:毛重系数
+        weightCoe = scMathUtil.roundForObj(weightCoe,unitPirce);
+        t = scMathUtil.roundForObj(t*weightCoe,process);//(单位运价×km运距×(1+运距增加率%)+装卸费单价×装卸次数+其它费用)×单位毛重×加权系数
+        sum = scMathUtil.roundForObj(sum + t,process);
+    }
+    if(freightList.length == 0){//如果运费计算表没有数据,则读取输入的或单价文件的值
+        let doc = dataMap['material']&&dataMap['material']['update']?dataMap['material']['update']:{};
+        sum = doc['unitFreight']?doc['unitFreight']:glj.unit_price.unitFreight;
+    }
+    return scMathUtil.roundForObj(sum,unitPirce);
+
+};
+
+ProjectGLJ.prototype.priceCalc = function (glj,dataMap) {
+    let process = getDecimal("process");
+    let unitPirce = getDecimal("glj.unitPrice");
+    let unitPriceHasMix = getDecimal("glj.unitPriceHasMix");
+    let original_price = 0;
+    let supplyList = [];
+    let supplyLocation = "";
+    let priceList = _.filter(this.datas.originalList,{"connect_key":gljUtil.getIndex(glj)});
+    if(dataMap["price"] && dataMap["price"]["add"])  priceList = priceList.concat(dataMap["price"]["add"]); //把添加的加进去
+    for(let p of priceList){
+        let supplyPrice = p.supplyPrice ,coe = p.coe;
+        if(dataMap["price"] && dataMap["price"]["update"]){//覆盖更新的数据
+            let t = dataMap["price"]["update"][p.ID];
+            if(t && t["supplyPrice"]) supplyPrice =t["supplyPrice"];
+            if(t && t["coe"]) coe =t["coe"];
+        }
+        if(dataMap["price"] && dataMap["price"]["delete"]){//忽略删除的数据
+            if(p.ID ==dataMap["price"]["delete"]) continue;
+        }
+        supplyPrice = scMathUtil.roundForObj(supplyPrice,unitPirce);
+        coe = scMathUtil.roundForObj(coe,unitPirce);
+        let t_p = scMathUtil.roundForObj(supplyPrice *  coe,process);
+        original_price=scMathUtil.roundForObj(original_price+t_p,process);
+        supplyList.push(p.supplyLocation);
+    }
+    supplyLocation = supplyList.join(',');
+    if(priceList.length == 0){//如果原价计算表没有数据,则读取输入的或单价文件的值
+        let doc = dataMap['material']&&dataMap['material']['update']?dataMap['material']['update']:{};
+        original_price = doc['originalPrice']?doc['originalPrice']:glj.unit_price.originalPrice;
+        supplyLocation = doc['supplyLocation']?doc['supplyLocation']:glj.unit_price.supplyLocation;
+    }
+    return [scMathUtil.roundForObj(original_price,unitPriceHasMix),supplyLocation];
+};
+
+
+ProjectGLJ.prototype.m_updateUnitPrice = function (datas) {//批量更新
+    let me = this;
+    let gljList = [];
+    for(let d of datas){
+        let g = updateUnit(d.id,d.unitPrice);
+        if(g) gljList.push(g);
+    }
+    //刷新项目工料机表显示
+    projectGljObject.refreshDataSheet();
+    //重新计算相关节点
+
+    let nodes = me.getImpactRationNodes(gljList);//取到因为改变工料机价格而受影响的定额
+    projectObj.project.calcProgram.calcNodesAndSave(nodes);//触发计算程序
+
+    //刷新定额工料机
+    gljOprObj.refreshView();
+    //socket推送更新信息
+    projectGljObject.onUnitFileChange();
+
+
+    function updateUnit(id,unitPrice) {
+        let glj = _.find(me.datas.gljList,{'id':id});
+        if(glj && !_.isEmpty(unitPrice.doc)){
+            for(let key in unitPrice.doc){
+                glj.unit_price[key] = unitPrice.doc[key];
+            }
+        }
+        return glj;
+    }
+
+};
+
+ProjectGLJ.prototype.updateUnitPrice = function(id,unitPrice){
+    this.m_updateUnitPrice([{id:id,unitPrice:unitPrice}]);
+};
+
+ProjectGLJ.prototype.addPriceCalc = async function (datas,pgljID) {
+    try {
+        let unitPrice = this.materialCal(pgljID,{price:{add:datas}});
+        $.bootstrapLoading.start();
+        let result =  await ajaxPost('/glj/addOriginalCalc',{datas:datas,unitPrice:unitPrice});
+        this.datas.originalList = this.datas.originalList.concat(result);
+        this.updateUnitPrice(pgljID,unitPrice);
+        materialCalcObj.showDatas();
+    }catch (e){
+        console.log(e)
+    }finally {
+        $.bootstrapLoading.end();
+    }
+};
+
+ProjectGLJ.prototype.updateMaterialCalc = async function (datas) {
+    let tasks = [];
+    let updateDatas=[];
+    try {
+        for(let d of datas){
+            let unitPrice = this.materialCal(d.id,{material:{update:d.doc}});
+            if(_.isEmpty(unitPrice.doc)) continue;
+            tasks.push({updateOne: {filter: {id: unitPrice.id,unit_price_file_id:unitPrice.unit_price_file_id}, update: unitPrice.doc}})
+            updateDatas.push({id:d.id,unitPrice:unitPrice})
+        }
+        $.bootstrapLoading.start();
+        let result =  await ajaxPost('/glj/updateMaterialCalc',{tasks:tasks});
+        this.m_updateUnitPrice(updateDatas);
+        materialCalcObj.showDatas();
+    }catch (e){
+        console.log(e)
+    }finally {
+        $.bootstrapLoading.end();
+    }
+
+};
+
+ProjectGLJ.prototype.updateFreightCalc = async function (datas,pgljID){
+    try {
+        let updateMap = {};
+        let tasks = [];
+        for(let d of datas){
+            updateMap[d.ID] = d.doc;
+            tasks.push({updateOne: {filter: {ID: d.ID}, update: d.doc}})
+        }
+        let unitPrice = this.materialCal(pgljID,{freight:{update:updateMap}});
+        $.bootstrapLoading.start();
+        let result =  await ajaxPost('/glj/updateFreightCalc',{tasks:tasks,unitPrice:unitPrice});
+        for(let o of  this.datas.freightList){
+            if(updateMap[o.ID]){
+                gljUtil.updateProperty(o,updateMap[o.ID]);
+            }
+        }
+        this.updateUnitPrice(pgljID,unitPrice);
+        materialCalcObj.showDatas();
+    }catch (e){
+        console.log(e)
+    }finally {
+        $.bootstrapLoading.end();
+    }
+};
+
+ProjectGLJ.prototype.updatePriceCalc = async function (datas,pgljID) {
+    try {
+        let updateMap = {};
+        let tasks = [];
+        for(let d of datas){
+            updateMap[d.ID] = d.doc;
+            tasks.push({updateOne: {filter: {ID: d.ID}, update: d.doc}})
+        }
+        let unitPrice = this.materialCal(pgljID,{price:{update:updateMap}});
+        $.bootstrapLoading.start();
+        let result =  await ajaxPost('/glj/updateOriginalCalc',{tasks:tasks,unitPrice:unitPrice});
+        for(let o of  this.datas.originalList){
+            if(updateMap[o.ID]){
+                gljUtil.updateProperty(o,updateMap[o.ID]);
+            }
+        }
+        this.updateUnitPrice(pgljID,unitPrice);
+        materialCalcObj.showDatas();
+    }catch (e){
+        console.log(e)
+    }finally {
+        $.bootstrapLoading.end();
+    }
+};
+
+
+ProjectGLJ.prototype.addFreightCalc = async function (datas,pgljID) {
+    try {
+        let unitPrice = this.materialCal(pgljID,{freight:{add:datas}});
+        $.bootstrapLoading.start();
+        let result =  await ajaxPost('/glj/addFreightCalc',{datas:datas,unitPrice:unitPrice});
+        this.datas.freightList = this.datas.freightList.concat(result);
+        this.updateUnitPrice(pgljID,unitPrice);
+        materialCalcObj.showDatas();
+
+    }catch (e){
+        console.log(e)
+    }finally {
+        $.bootstrapLoading.end();
+    }
+};
+
+ProjectGLJ.prototype.deletePriceCalc = async function (ID,pgljID) {
+    try {
+        let data={ID:ID};
+        // 计算预算价
+        let unitPrice = this.materialCal(pgljID,{price:{'delete':ID}});
+        data.unitPrice = unitPrice;
+        $.bootstrapLoading.start();
+        await ajaxPost('/glj/deletePriceCalc',data);
+        _.remove(this.datas.originalList,{'ID':data.ID});
+        //更新单价文件的值
+        this.updateUnitPrice(pgljID,unitPrice);
+        materialCalcObj.showDatas();
+
+    }catch (e){
+        console.log(e)
+    }finally {
+        $.bootstrapLoading.end();
+    }
+};
+
+ProjectGLJ.prototype.deleteFreightCalc = async function (ID,pgljID) {
+    try {
+        let data={ID:ID};
+        // 计算预算价
+        let unitPrice = this.materialCal(pgljID,{freight:{'delete':ID}});
+        data.unitPrice = unitPrice;
+        $.bootstrapLoading.start();
+        let result =  await ajaxPost('/glj/deleteFreightCalc',data);
+        console.log(result);
+        _.remove(this.datas.freightList,{'ID':data.ID});
+        // 更新单价文件的值
+        this.updateUnitPrice(pgljID,unitPrice);
+        materialCalcObj.showDatas();
+
+    }catch (e){
+        console.log(e)
+    }finally {
+        $.bootstrapLoading.end();
+    }
+};
 
 ProjectGLJ.prototype.updatePrice = function (recode, updateField, newval,from,cb) {
     let me = this;

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

@@ -1236,9 +1236,7 @@ var gljOprObj = {
         })
     },
     updateProperty: function (obj, doc) {
-        _.forEach(doc, function (n, key) {
-            obj[key] = n;
-        });
+       gljUtil.updateProperty(obj,doc);
     },
     refreshStateAfterMreplace: function (stateList, gljNodes) {
         let nodes = [];

+ 288 - 30
web/building_saas/main/js/views/material_calc_view.js

@@ -11,55 +11,63 @@ materialCalcObj = {
             {headerName: "编号", headerWidth: 80, dataCode: "code", dataType: "String"},
             {headerName: "名称", headerWidth: 100, dataCode: "name", dataType: "String"},
             {headerName: "预算价", headerWidth: 70, dataCode: "marketPrice", hAlign: "right", dataType: "Number",validator:"number"},
-            {headerName: "供应地点", headerWidth: 100, dataCode: "unit", hAlign: "left", dataType: "String"},
-            {headerName: "原价", headerWidth: 45, dataCode: "originalPrice", hAlign: "center", dataType: "String"},
-            {headerName: "单位运费", headerWidth: 80, dataCode: "unitFreight", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:'glj.unitPrice'
-            {headerName: "单位毛重(吨)", headerWidth: 60, dataCode: "unitWeight", hAlign: "right", dataType: "Number"},//,decimalField:"glj.unitPrice"
-            {headerName: "装卸总次数", headerWidth: 50, dataCode: "totalLoadingTimes", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:"glj.unitPrice"
-            {headerName: "每增加一次装卸损耗率", headerWidth: 80, dataCode: "handlingLossRate", hAlign: "right", dataType: "Number",decimalField:"glj.quantity",validator:"number"},
-            {headerName: "场外运输损耗率", headerWidth: 60, dataCode: "offSiteTransportLossRate", hAlign: "right", dataType: "Number"},//,decimalField:"glj.unitPrice"
+            {headerName: "供应地点", headerWidth: 100, dataCode: "supplyLocation", hAlign: "left", dataType: "String"},
+            {headerName: "原价", headerWidth: 60, dataCode: "originalPrice", hAlign: "right", dataType: "String"},
+            {headerName: "单位运费", headerWidth: 60, dataCode: "unitFreight", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:'glj.unitPrice'
+            {headerName: "单位毛重(吨)", headerWidth: 60, dataCode: "grossWeightCoe_n", hAlign: "right", dataType: "Number"},//,decimalField:"glj.unitPrice"
+            {headerName: "装卸总次数", headerWidth: 60, dataCode: "totalLoadingTimes", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:"glj.unitPrice"
+            {headerName: "每增加一次装卸损耗率", headerWidth: 80, dataCode: "handlingLossRate_n", hAlign: "right", dataType: "Number",validator:"number"},
+            {headerName: "场外运输损耗率", headerWidth: 60, dataCode: "offSiteTransportLossRate_n", hAlign: "right", dataType: "Number"},//,decimalField:"glj.unitPrice"
             {headerName: "场外运输损耗", headerWidth: 60, dataCode: "offSiteTransportLoss", hAlign: "right", dataType: "Number"},//,decimalField:"glj.unitPrice"
-            {headerName: "采购及保管费率", headerWidth: 60, dataCode: "purchaseStorageRate", hAlign: "right", dataType: "Number"},//,decimalField:"glj.unitPrice"
+            {headerName: "采购及保管费率", headerWidth: 60, dataCode: "purchaseStorageRate_n", hAlign: "right", dataType: "Number"},//,decimalField:"glj.unitPrice"
             {headerName: "采购及保管费", headerWidth: 60, dataCode: "purchaseStorage", hAlign: "right", dataType: "Number"},//,decimalField:"glj.unitPrice"
             {headerName: "包装品回收价值", headerWidth: 60, dataCode: "packageRecoverValue", hAlign: "right", dataType: "Number"}//,decimalField:"glj.unitPrice"
         ],
         view: {
-            lockColumns: [0,1,2,3,4,5,6,7],
+            lockColumns: ["code","name","marketPrice",'offSiteTransportLoss','purchaseStorage'],
             colHeaderHeight:45
         }
     },
     freightSpread:null,
     freightSheet:null,
     freightDatas:[],
+    conveyanceOptions:["汽车","火车","船舶","马车","手推车","拖拉机"],
     freightSetting:{
         header:[
             {headerName: "起讫地点", headerWidth: 80, dataCode: "start", dataType: "String"},
             {headerName: "运输工具", headerWidth: 80, dataCode: "conveyance", dataType: "String"},
-            {headerName: "单位运价", headerWidth: 70, dataCode: "unitFreight", hAlign: "right", dataType: "Number",validator:"number"},
-            {headerName: "km运距", headerWidth: 50, dataCode: "kmDistance", hAlign: "left", dataType: "String"},
-            {headerName: "装卸费单价", headerWidth: 45, dataCode: "unitLoadingFee", hAlign: "center", dataType: "String"},
-            {headerName: "装卸次数", headerWidth: 80, dataCode: "loadingTimes", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:'glj.unitPrice'
-            {headerName: "其它费用", headerWidth: 60, dataCode: "otherFee", hAlign: "right", dataType: "Number"},//,decimalField:"glj.unitPrice"
-            {headerName: "运价增加率(%)", headerWidth: 80, dataCode: "freightIncreaseRate", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:"glj.unitPrice"
-            {headerName: "加权系数", headerWidth: 80, dataCode: "weightCoe", hAlign: "right", dataType: "Number",decimalField:"glj.quantity",validator:"number"},
-            {headerName: "计算式", headerWidth: 60, dataCode: "exp", hAlign: "right", dataType: "Number"},//,decimalField:"glj.unitPrice"
+            {headerName: "单位运价", headerWidth: 60, dataCode: "unitFreight", hAlign: "right", dataType: "Number",validator:"number"},
+            {headerName: "km运距", headerWidth: 60, dataCode: "kmDistance", hAlign: "right", dataType: "String",validator:"number"},
+            {headerName: "装卸费\n单价", headerWidth: 60, dataCode: "unitLoadingFee", hAlign: "right", dataType: "String",validator:"number"},
+            {headerName: "装卸\n次数", headerWidth: 60, dataCode: "loadingTimes", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:'glj.unitPrice'
+            {headerName: "其它\n费用", headerWidth: 60, dataCode: "otherFee", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:"glj.unitPrice"
+            {headerName: "运价增\n加率(%)", headerWidth: 60, dataCode: "freightIncreaseRate", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:"glj.unitPrice"
+            {headerName: "加权\n系数", headerWidth: 60, dataCode: "weightCoe", hAlign: "right", dataType: "Number",validator:"number"},
+            {headerName: "计算式", headerWidth: 170, dataCode: "exp", hAlign: "right", dataType: "Number",getText:'forExp'},//,decimalField:"glj.unitPrice"
         ],
         view: {
-            lockColumns: [0,1,2,3,4,5,6,7],
+            lockColumns: ["exp"],
             colHeaderHeight:45
+        },
+        getText:{
+            forExp:function (item) {
+                let material = materialCalcObj.getMaterialSelected();
+                //(单位运价×km运距×(1+运距增加率%)+装卸费单价×装卸次数+其它费用)×单位毛重×加权系数
+                return `(${item.unitFreight}x${item.kmDistance}x(1+${item.freightIncreaseRate}%)+${item.unitLoadingFee}x${item.loadingTimes}+${item.otherFee})x${material.grossWeightCoe_n}x${item.weightCoe}`
+            }
         }
     },
     priceSpread:null,
     priceSheet:null,
-    priceData:[],
+    priceDatas:[],
     priceSetting:{
         header:[
-            {headerName: "供应地点", headerWidth: 80, dataCode: "start", dataType: "String"},
-            {headerName: "供应价", headerWidth: 70, dataCode: "unitFreight", hAlign: "right", dataType: "Number",validator:"number"},
-            {headerName: "加权系数", headerWidth: 80, dataCode: "loadingTimes", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:'glj.unitPrice'
+            {headerName: "供应地点", headerWidth: 80, dataCode: "supplyLocation", dataType: "String"},
+            {headerName: "供应价", headerWidth: 70, dataCode: "supplyPrice", hAlign: "right", dataType: "Number",validator:"number"},
+            {headerName: "加权系数", headerWidth: 80, dataCode: "coe", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:'glj.unitPrice'
         ],
         view: {
-            lockColumns: [0,1,2],
+            lockColumns: [],
             colHeaderHeight:45
         }
     },
@@ -68,11 +76,14 @@ materialCalcObj = {
         sheetCommonObj.spreadDefaultStyle(this.materialSpread);
         this.materialSheet = this.materialSpread.getSheet(0);
         sheetCommonObj.initSheet(this.materialSheet, this.materialSetting, 30);
-       /* this.materialSheet.bind(GC.Spread.Sheets.Events.EditEnded, this.onAssEditEnded);
-        this.materialSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onAssRangeChanged);*/
+        this.materialSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onMaterialValueChange);
+        this.materialSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onMaterialSelectionChange);
+        this.materialSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onMaterialEditStarting);
         this.materialSheet.name('material_calc');
         if(projectReadOnly){
             disableSpread(this.materialSpread);
+        }else {
+            this.initRightClick("materialCalcSheet",this.materialSpread)
         }
     },
     initFreightSpread:function(){
@@ -80,11 +91,14 @@ materialCalcObj = {
         sheetCommonObj.spreadDefaultStyle(this.freightSpread);
         this.freightSheet = this.freightSpread.getSheet(0);
         sheetCommonObj.initSheet(this.freightSheet, this.freightSetting, 30);
-     /*   this.freightSheet.bind(GC.Spread.Sheets.Events.EditEnded, this.onAssEditEnded);
-        this.freightSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onAssRangeChanged);*/
+        this.freightSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onFreightValueChange);
+        this.freightSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onFreightSelectionChange);
+        this.freightSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onFreightEditStarting);
         this.freightSheet.name('freight_calc');
         if(projectReadOnly){
             disableSpread(this.freightSpread);
+        }else {
+            this.initRightClick("freightSheet",this.freightSpread)
         }
     },
     initPriceSpread:function(){
@@ -92,27 +106,49 @@ materialCalcObj = {
         sheetCommonObj.spreadDefaultStyle(this.priceSpread);
         this.priceSheet = this.priceSpread.getSheet(0);
         sheetCommonObj.initSheet(this.priceSheet, this.priceSetting, 30);
-        /*   this.freightSheet.bind(GC.Spread.Sheets.Events.EditEnded, this.onAssEditEnded);
-         this.freightSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onAssRangeChanged);*/
+        this.priceSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onPriceValueChange);
+        this.priceSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onPriceEditStarting);
         this.priceSheet.name('price_calc');
         if(projectReadOnly){
             disableSpread(this.priceSpread);
+        }else {
+            this.initRightClick("priceSheet",this.priceSpread)
         }
     },
     showFreightDatas:function () {
         if(!$('#freightSheet').is(':visible')) return;
+        let sel = this.freightSheet.getSelections()[0];
+        let oldData = sel.row<this.freightDatas.length?this.freightDatas[sel.row]:"";
         this.freightSheet.setRowCount(0);
+        this.freightDatas = this.getFreightDatas();
         sheetCommonObj.showData(this.freightSheet, this.freightSetting,this.freightDatas);
+        this.freightSheet.setRowCount(this.freightDatas+20);
+        let convCol = _.findIndex(this.freightSetting.header,{'dataCode':'conveyance'});
+        sheetCommonObj.setComboBox(-1,convCol,this.freightSheet,this.conveyanceOptions,false);
+        sel.row =  oldData?_.findIndex(this.freightDatas,{'ID':oldData.ID}):sel.row ;
+        this.freightSheet.setSelection(sel.row==-1?0:sel.row,sel.col,sel.rowCount,sel.colCount);
     },
     showMaterialCalcDatas:function(){
+        let sel = this.materialSheet.getSelections()[0];
+        let oldData = sel.row<this.materialDatas.length?this.materialDatas[sel.row]:"";
         this.materialSheet.setRowCount(0);
+        this.materialDatas = this.getMaterialCalcDatas();
         sheetCommonObj.showData(this.materialSheet, this.materialSetting,this.materialDatas);
         this.materialSheet.setRowCount(this.materialDatas.length);
+        sel.row = oldData?_.findIndex(this.materialDatas,{'id':oldData.id}):-1;
+        this.materialSheet.setSelection(sel.row==-1?0:sel.row,sel.col,sel.rowCount,sel.colCount);
     },
     showPriceDatas:function () {
         if(!$('#priceSheet').is(':visible')) return;
+        let sel = this.priceSheet.getSelections()[0];
+        let oldData = sel.row<this.priceDatas.length?this.priceDatas[sel.row]:"";
         this.priceSheet.setRowCount(0);
-        sheetCommonObj.showData(this.priceSheet, this.priceSetting,this.priceData);
+        this.priceDatas = this.getPriceDatas();
+        sheetCommonObj.showData(this.priceSheet, this.priceSetting,this.priceDatas);
+        this.priceSheet.setRowCount(this.priceDatas.length+20);
+        sel.row =  oldData?_.findIndex(this.priceDatas,{'ID':oldData.ID}):sel.row ;
+        this.priceSheet.setSelection(sel.row==-1?0:sel.row,sel.col,sel.rowCount,sel.colCount);
+
     },
     showDatas:function(){
         if(!$('#materialCalcSheet').is(':visible')) return;
@@ -124,6 +160,200 @@ materialCalcObj = {
         this.showPriceDatas();
         projectGljObject.refreshSubViews();
     },
+    getMaterialSelected:function () {
+        let sel = this.materialSheet.getSelections()[0];
+        if(sel.row != -1 && this.materialDatas.length>sel.row){
+            return this.materialDatas[sel.row]
+        }
+        return null;
+    },
+
+    getPriceDatas:function () {
+        let list =  projectObj.project.projectGLJ.datas.originalList;
+        let material = this.getMaterialSelected();
+        return material?_.filter(list,{"connect_key":gljUtil.getIndex(material)}):[];
+    },
+    getFreightDatas:function () {
+        let list =  projectObj.project.projectGLJ.datas.freightList;
+        let material = this.getMaterialSelected();
+        return material?_.filter(list,{"connect_key":gljUtil.getIndex(material)}):[];
+    },
+    getMaterialCalcDatas:function () {
+        let gljList = projectObj.project.projectGLJ.datas.gljList;
+        let datas = [];
+        for(let g of gljList){
+            if(g.quantity !== 0 && g.quantity !== '0' && g.unit_price.calcMaterial == 1){
+                let data = {
+                    id:g.id,
+                    code:g.code,
+                    name:g.name,
+                    type:g.type,
+                    unit:g.unit,
+                    specs:g.specs,
+                    unit_price:{id:g.unit_price.id,type:g.type,unit_price_file_id:g.unit_price.unit_price_file_id},//type用来排序
+                    supplyLocation:g.unit_price.supplyLocation,
+                    originalPrice:g.unit_price.originalPrice?g.unit_price.originalPrice:0,
+                    unitFreight:g.unit_price.unitFreight?g.unit_price.unitFreight:0,
+                   // unitWeight:g.unit_price.unitWeight?g.unit_price.unitWeight:0,
+                    totalLoadingTimes:g.unit_price.totalLoadingTimes?g.unit_price.totalLoadingTimes:0,
+                    handlingLossRate_n:g.unit_price.handlingLossRate_n?g.unit_price.handlingLossRate_n:0,
+                    offSiteTransportLossRate_n:g.unit_price.offSiteTransportLossRate_n?g.unit_price.offSiteTransportLossRate_n:0,
+                    offSiteTransportLoss:g.unit_price.offSiteTransportLoss?g.unit_price.offSiteTransportLoss:0,
+                    purchaseStorageRate_n:g.unit_price.purchaseStorageRate_n?g.unit_price.purchaseStorageRate_n:0,
+                    purchaseStorage:g.unit_price.purchaseStorage?g.unit_price.purchaseStorage:0,
+                    grossWeightCoe_n:g.unit_price.grossWeightCoe_n?g.unit_price.grossWeightCoe_n:0,
+                    packageRecoverValue:g.unit_price.packageRecoverValue?g.unit_price.packageRecoverValue:0
+                };
+                gljOprObj.setGLJPrice(data,g);
+                datas.push(data);
+            }
+        }
+        return gljUtil.sortProjectGLJ(datas);
+    },
+    onMaterialSelectionChange:function(sender,args){
+        let me = materialCalcObj;
+        let newSel = args.newSelections[0];
+        let oldSel = args.oldSelections?args.oldSelections[0]:{};
+        if(newSel.row != oldSel.row){
+            me.showPriceDatas();
+            me.showFreightDatas();
+        }
+    },
+    onFreightSelectionChange:function (sender,args) {
+        args.sheet.repaint();
+    },
+    onPriceEditStarting:function (sender,args) {
+        let me = materialCalcObj;
+        if(!me.getMaterialSelected()){
+            args.cancel = true;
+        }
+    },
+    onFreightEditStarting:function(sender,args){
+        let me = materialCalcObj;
+        if(!me.getMaterialSelected()){
+            args.cancel = true;
+        }
+    },
+    onMaterialEditStarting:function (sender,args) {
+        let me = materialCalcObj;
+        let dataCode = me.materialSetting.header[args.col].dataCode;
+        if(dataCode == "supplyLocation" ||dataCode == "originalPrice"){//原价计算表有数据时只读,
+            args.cancel = me.getPriceDatas().length > 0;
+        }
+        if(dataCode == "unitFreight"){//当运费计算表有数据时,则只读
+            args.cancel = me.getFreightDatas().length > 0;
+        }
+    },
+
+    onMaterialValueChange:function (sender,args) {
+        let me = materialCalcObj;
+        let dataCode = me.materialSetting.header[args.col].dataCode;
+        let value = args.newValue;
+        if (value&&!sheetCommonObj.checkData(args.col,me.materialSetting,value)) {
+            alert('输入的数据类型不对,请重新输入!');
+            me.showDatas();
+            return;
+        }
+        if(dataCode != 'supplyLocation'){
+            value = value?scMathUtil.roundForObj(value,getDecimal("glj.unitPrice"))+'':'0'//4舍五入加默认为0
+        }
+        let recode = me.materialDatas[args.row];
+        if(recode[dataCode] == value) return;
+        let doc = {};
+        doc[dataCode] = value;
+        projectObj.project.projectGLJ.updateMaterialCalc([{id:recode.id,doc:doc}]);
+    },
+
+    onFreightValueChange:function (sender,args) {
+        let me = materialCalcObj;
+        let dataCode = me.freightSetting.header[args.col].dataCode;
+        let value = args.newValue;
+        let material = me.getMaterialSelected();
+        if (value&&!sheetCommonObj.checkData(args.col,me.freightSetting,value)) {
+            alert('输入的数据类型不对,请重新输入!');
+            me.showDatas();
+            return;
+        }
+        if(dataCode != 'start'&&dataCode != 'conveyance'){
+            value = value?scMathUtil.roundForObj(value,getDecimal("glj.unitPrice"))+'':'0'//4舍五入加默认为0
+        }
+        if(args.row >= me.freightDatas.length){//新增
+            let newData = {
+                start:"",//起讫地点
+                conveyance:"汽车",//运输工具
+                unitFreight:'0',//单位运价
+                kmDistance:'0',//km运距
+                unitLoadingFee:'0',//装卸费单价
+                loadingTimes:'0',//装卸次数
+                otherFee:'0',//其它费用
+                freightIncreaseRate:'0',//运价增加率
+                weightCoe:'1',//加权系数
+                connect_key:gljUtil.getIndex(material),
+                unit_price_file_id:material.unit_price.unit_price_file_id
+            };
+            newData[dataCode] = value;
+            projectObj.project.projectGLJ.addFreightCalc([newData],material.id);
+        }else {//修改
+            let recode = me.freightDatas[args.row];
+            if(recode[dataCode] == value) return;
+            let doc = {};
+            doc[dataCode] = value;
+            projectObj.project.projectGLJ.updateFreightCalc([{ID:recode.ID,doc:doc}],material.id);
+        }
+
+    },
+    onPriceValueChange:function(sender,args){
+        let me = materialCalcObj;
+        let dataCode = me.priceSetting.header[args.col].dataCode;
+        let value = args.newValue;
+        let material = me.getMaterialSelected();
+        //输入有效性判断, to do
+        if (value&&!sheetCommonObj.checkData(args.col,me.priceSetting,value)) {
+            alert('输入的数据类型不对,请重新输入!');
+            me.showDatas();
+            return;
+        }
+        if(dataCode == 'coe'||dataCode == 'supplyPrice'){
+            value = value?scMathUtil.roundForObj(value,getDecimal("glj.unitPrice"))+'':'0'//4舍五入加默认为0
+        }
+        if(args.row >= me.priceDatas.length){//新增
+            let newData = {
+                supplyLocation:"",
+                supplyPrice:'0',
+                coe:'1',
+                connect_key:gljUtil.getIndex(material),
+                unit_price_file_id:material.unit_price.unit_price_file_id
+            };
+            newData[dataCode] = value;
+            projectObj.project.projectGLJ.addPriceCalc([newData],material.id);
+        }else {//修改
+            let recode = me.priceDatas[args.row];
+            if(recode[dataCode] == value) return;
+            let doc = {};
+            doc[dataCode] = value;
+            projectObj.project.projectGLJ.updatePriceCalc([{ID:recode.ID,doc:doc}],material.id);
+        }
+    },
+    deleteMaterialCal:function (row) {
+        let record = this.materialDatas[row];//修改材料计算标记的同时还要删除原价计算,运费计算等
+        if(record){
+            projectObj.project.projectGLJ.updateCalcMaterial(record,'calcMaterial',0);
+        }
+    },
+    deletePriceCalc:function (row) {
+        let record = this.priceDatas[row];
+        if(record){
+            let material = this.getMaterialSelected();
+            projectObj.project.projectGLJ.deletePriceCalc(record.ID,material.id);
+        }
+    },
+    deleteFreightCalc:function (row) {
+        let record = this.freightDatas[row];
+        if(record){
+            let material = this.getMaterialSelected();
+            projectObj.project.projectGLJ.deleteFreightCalc(record.ID,material.id);
+        }
+    },
     getSideResize: function () {
         let rg_sideResizeEles = {};
         rg_sideResizeEles.eleObj = {
@@ -139,6 +369,34 @@ materialCalcObj = {
         };
         return rg_sideResizeEles;
     },
+    initRightClick:function (id,spread) {
+        let me = this;
+        $.contextMenu({
+            selector: '#'+id,
+            build: function ($trigger, e) {
+                me.rightClickTarget = SheetDataHelper.safeRightClickSelection($trigger, e, spread);
+                return me.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.viewport ||
+                    me.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
+            },
+            items: {
+                "delete": {
+                    name: "删除",
+                    icon: 'fa-trash-o',
+                    disabled: function () {
+                        if(id == "priceSheet") return me.rightClickTarget.row >= me.priceDatas.length;
+                        if(id == "freightSheet") return me.rightClickTarget.row >= me.freightDatas.length;
+                        return me.rightClickTarget.row === undefined;
+                    },
+                    callback: function (key, opt) {
+                        let row = me.rightClickTarget.row;
+                        if (id == "materialCalcSheet") me.deleteMaterialCal(row);
+                        if (id == "priceSheet") me.deletePriceCalc(row);
+                        if(id == "freightSheet") me.deleteFreightCalc(row);
+                    }
+                }
+            }
+        });
+    },
     initTabWidth:function () {
         if($("#mix_ratio_sheet").is(':visible')) return ;//如果是组成物计算界面,返回
         let mr_sideResizeEles = this.getSideResize();

+ 44 - 9
web/building_saas/main/js/views/project_glj_view.js

@@ -58,7 +58,7 @@ projectGljObject={
         this.projectGljSpread.bind(GC.Spread.Sheets.Events.RangeChanged, this.onProjectGljRangeChange);
         this.initProjectGljSheet();
         this.initMaterialTreeSheet();
-        disableRightMenu("project_glj_sheet",this.projectGljSpread,this.rightClickCallback);
+        this.initProjectGljRightClick();
         //打开别人分享的项目,只读
         if(projectReadOnly){
             //锁定逻辑走disabledSpread里的
@@ -66,6 +66,7 @@ projectGljObject={
                 this.projectGljSetting.view.lockColumns = null;
             }
             disableSpread(this.projectGljSpread);
+            disableRightMenu("project_glj_sheet",this.projectGljSpread,this.rightClickCallback);
         }
     },
     initProjectGljSheet:function () {
@@ -74,6 +75,7 @@ projectGljObject={
         this.initSheet(this.projectGljSheet,this.projectGljSetting);
         this.projectGljSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onProjectGljSelectionChange);
         this.projectGljSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onProjectGljEditStarting);
+        this.projectGljSheet.bind(GC.Spread.Sheets.Events.CellDoubleClick, this.onProjectGljDoubleClick);
         this.projectGljSheet.name('projectGljSheet');
         this.projectGljSheet.setRowHeight(0, 45, 1);
     },
@@ -82,7 +84,7 @@ projectGljObject={
         if(me.mixRatioSpread==null){
             me.initMixRatioSpread();
             if(!projectReadOnly){
-                me.initRightClick();
+                me.initMixRatioRightClick();
             }
         }
     },
@@ -268,6 +270,8 @@ projectGljObject={
             if(dataCode=='basePrice'&&data.is_add!=1){//如果不是新增,定额价不可修改。
                 return false;
             }
+            if(dataCode=='marketPrice' && data.calcMaterial == 1) return false //有材料计算时不能修改
+
         }
         if(dataCode == 'supply_quantity'){
             if (data.supply != 1) {// 如果为部分甲供则甲供数量需要可编辑,其它的都不能编辑
@@ -279,7 +283,6 @@ projectGljObject={
                 return false;
             }
         }
-
         return true;
     },
     onSelectionChange:function (){
@@ -287,6 +290,12 @@ projectGljObject={
         me.showMixRatioData();
         me.materialTreeSheet.repaint();
     },
+    onProjectGljDoubleClick:function (sender,args) {
+        let me = projectGljObject;
+        let recode = me.projectGljSheetData[args.row];
+        let dataCode = me.projectGljSetting.header[args.col].dataCode;
+        if(dataCode=='name'&& recode && gljUtil.isMaterialType(recode.type)) projectObj.project.projectGLJ.updateCalcMaterial(recode,'calcMaterial',1);
+    },
     onProjectGljSelectionChange:function (sender, args) {
         let me = projectGljObject;
         let newSel = args.newSelections[0];
@@ -688,6 +697,7 @@ projectGljObject={
             delivery_address:glj.delivery_address,
             is_adjust_price:glj.is_adjust_price,
             ratio_data:glj.ratio_data,
+            calcMaterial:glj.unit_price.calcMaterial,
             is_add:glj.unit_price.is_add,
             bgColour:'white',
             techQuantity:glj.techQuantity,
@@ -920,11 +930,7 @@ projectGljObject={
                 value=  scMathUtil.roundForObj(value,getDecimal('glj.quantity'));
             }
             if(dataCode === 'is_evaluate'||dataCode === 'is_adjust_price'||dataCode === 'is_main_material'){
-                if(value == true){
-                    value = 1;
-                }else if(value == false){
-                    value = 0;
-                }
+                value = value == true?1:0;
             }
             if(dataCode === 'materialType' && (value == null || value=="")){//删除三材类别时,清空三材系数
                 value = null;
@@ -1005,7 +1011,35 @@ projectGljObject={
         }
         return selectedProjectGLJ;
     },
-    initRightClick : function() {
+    initProjectGljRightClick:function(){
+        //如果当前行是无组成物的“普通材料”、“绿化苗木”、“外购砼构件”、“商品混凝土”、“商品砂浆”,则右键“添加计算材料”按钮有效。
+        let me = this;
+        $.contextMenu({
+            selector: '#project_glj_sheet',
+            build: function ($trigger, e) {
+                me.rightClickTarget = SheetDataHelper.safeRightClickSelection($trigger, e, me.projectGljSpread);
+                return me.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.viewport ||
+                    me.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
+            },
+            items: {
+                "addCalcMaterial": {
+                    name: "添加计算材料",
+                    icon: 'fa-sign-in',
+                    disabled: function () {
+                        let projectGLJ = projectGljObject.getProjectGLJSelected();
+                        return  !projectGLJ || !gljUtil.isMaterialType(projectGLJ.type);
+                    },
+                    callback: function (key, opt) {
+                        let projectGLJ = projectGljObject.getProjectGLJSelected();
+                        projectObj.project.projectGLJ.updateCalcMaterial(projectGLJ,'calcMaterial',1);
+                    }
+                }
+            }
+        });
+
+
+    },
+    initMixRatioRightClick : function() {
         let activeSheet = this.mixRatioSheet;
         let me = this;
         $.contextMenu({
@@ -1055,6 +1089,7 @@ projectGljObject={
         projectGljObject.refreshDataSheet();
         gljOprObj.refreshView();
         projectGljObject.initVvTax();
+        materialCalcObj.showDatas();
         projectObj.project.calcProgram.calcAllNodesAndSave(calcAllType.catAll,function () {
             if(socketObject.roomInfo){
                 let data ={