Procházet zdrojové kódy

Merge branch 'master' of http://192.168.1.41:3000/SmartCost/YangHuCost

chenshilong před 6 roky
rodič
revize
d92f1a49fc

+ 75 - 5
modules/all_models/material_calc.js

@@ -4,8 +4,73 @@
 import mongoose from "mongoose";
 
 let Schema = mongoose.Schema;
+
+var rationAssItemSchema = mongoose.Schema({
+    name: String,
+    assistID: Number,
+    assistCode: String,
+    stdValue: Number,
+    actualValue:Number,
+    stepValue: String,
+    decimal: Number,
+    carryBit: String,
+    minValue: String,
+    maxValue: String,
+    paramName:String,//参数名称
+    param:String,//参数
+    thirdRationCode:String,//第三定额
+    isAdjust:Number,//0不调整,1调整
+    groupList:[Schema.Types.Mixed],//当有分组的时候用这个
+    assRation:Schema.Types.Mixed//存放对应的定额,材料计算时用到
+}, { _id: false });
+
+var ration_glj = new Schema({
+    ID:{type: String},
+    GLJID:Number,
+    repositoryId:Number,
+    rationID:String,
+    projectGLJID:Number,
+    name:String,
+    code:String,
+    //原始的编码
+    original_code: {type: String},
+    rcode:String,
+    //新结构,计录替换前的工料机信息,对于混凝土,替换,计算等问题处理,替换时保存旧数据的5大项信息
+    mIndexObj: Schema.Types.Mixed,
+    specs:String,
+    unit:String,
+    shortName:String,
+    type:Number,
+    // 机型
+    model: Number,
+    // 调整系数ID
+    adjCoe: Number,
+    quantity:String,
+    customQuantity:String,
+    rationItemQuantity:String,
+    tenderQuantity:String,//调整后消耗量
+    createType: {type: String,default:'normal'},//normal、add、replace  正常、添加工料机、替换工料机
+    from:{type: String,default:'std'}//std, cpt  来自标准工料机库、补充工料机库
+},{versionKey:false,_id: false});
+
+let ration_schema = {
+    ID: {type: String},
+    projectID: Number,
+    code: String,
+    name: String,
+    unit: String,
+    quantity: String,
+    feeType:String,
+    caption:String,
+    libID:Number,
+    stdID:Number,
+    from:String,
+    rationAssList: [rationAssItemSchema]
+};
+
+
 let freightSchema = {
-    ID:String,
+    ID:{type:String,index: true},
     unit_price_file_id: Number,
     connect_key: {type: String, index: true},// 关联项目工料机的key 不能关联id,因为单价文件导入别的项目后项目工料机id不同
     start:String,//起讫地点
@@ -16,19 +81,24 @@ let freightSchema = {
     loadingTimes:String,//装卸次数
     otherFee:String,//其它费用
     freightIncreaseRate:String,//运价增加率
-    weightCoe:String//加权系数
-
+    weightCoe:String,//加权系数
+    rations:[ration_schema],
+    ration_gljs:[ration_glj],
+    calcType:String,//计算方式
+    materialType:String//材料类型
 };
 mongoose.model("freight_calc", new Schema(freightSchema, {versionKey: false, collection: "freight_calc"}));
 
 
 let originalSchema = {
-    ID:String,
+    ID:{type:String,index: true},
     unit_price_file_id: Number,
     connect_key: {type: String, index: true},// 关联项目工料机的key 不能关联id,因为单价文件导入别的项目后项目工料机id不同
     supplyLocation:String,//供应地点
     supplyPrice:String,//供应价
-    coe:String//加权系数
+    coe:String,//加权系数
+    rations:[ration_schema],
+    ration_gljs:[ration_glj]
 };
 
 mongoose.model("original_calc", new Schema(originalSchema, {versionKey: false, collection: "original_calc"}));

+ 1 - 0
modules/all_models/unit_price_file.js

@@ -24,6 +24,7 @@ let modelSchema = {
     // 顶层projectId
     root_project_id: Number,
     vvTaxFileID:String,//车船税文件ID
+    assistProductionFeeRate:String,//辅助生产间接费费率
     deleteInfo: deleteSchema
 };
 mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));

+ 28 - 1
modules/glj/controllers/glj_controller.js

@@ -391,6 +391,18 @@ class GLJController extends BaseController {
         }
         response.json(result);
     }
+    async changeAssistProductionFeeRate(request, response){
+        let result={error:0};
+        try {
+            let data = JSON.parse(request.body.data);
+            await glj_facade.changeAssistProductionFeeRate(data);
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
 
     async addOriginalCalc(request, response){
         let result={error:0};
@@ -469,6 +481,20 @@ class GLJController extends BaseController {
         response.json(result);
     }
 
+   async updateMaterialCalcTasks(request, response){
+       let result={error:0};
+       try {
+           let data = JSON.parse(request.body.data);
+           result.data = await glj_facade.updateMaterialCalcTasks(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 {
@@ -918,7 +944,8 @@ async function getGLJListByProjectID(projectId){
             GLJTypeConst: JSON.stringify(GLJTypeConst),
             usedUnitPriceInfo: usedUnitPriceInfo,
             gljTypeMap:gljTypeMap,
-            vvTaxFileID:unitFileInfo.vvTaxFileID
+            vvTaxFileID:unitFileInfo.vvTaxFileID,
+            assistProductionFeeRate:unitFileInfo.assistProductionFeeRate?unitFileInfo.assistProductionFeeRate:0
         };
     } catch (error) {
         console.log(error);

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

@@ -4,6 +4,7 @@
 module.exports={ //先导出后require可以解决循环引用问题
     changeUnitFile:changeUnitFile,
     changeVvTaxFile:changeVvTaxFile,
+    changeAssistProductionFeeRate:changeAssistProductionFeeRate,
     addMixRatioForNew:addMixRatioForNew,
     addOriginalCalc:addOriginalCalc,
     deletePriceCalc:deletePriceCalc,
@@ -11,7 +12,8 @@ module.exports={ //先导出后require可以解决循环引用问题
     addFreightCalc:addFreightCalc,
     deleteFreightCalc:deleteFreightCalc,
     updateFreightCalc:updateFreightCalc,
-    updateMaterialCalc:updateMaterialCalc
+    updateMaterialCalc:updateMaterialCalc,
+    updateMaterialCalcTasks:updateMaterialCalcTasks
 };
 
 const mongoose = require('mongoose');
@@ -111,6 +113,13 @@ async function changeVvTaxFile(data){//对于车船税,现在只是在组成
     await handleVvTaxForChang(unitFileID,newVvTaxFileID);
 }
 
+async function changeAssistProductionFeeRate(data){
+    let unitFileID = data.unitFileID,assistProductionFeeRate = data.assistProductionFeeRate;
+    let unitPriceFileModel = new UnitPriceFileModel();
+    //先更新单价文件中车船税文件ID
+    await unitPriceFileModel.model.update({id:unitFileID},{assistProductionFeeRate:assistProductionFeeRate});
+}
+
 async function handleVvTaxForChang(unitFileID,newVvTaxFileID) {//切换车船税,选择共用的单价文件时调用
     let mixRatioModel = new MixRatioModel();
     if(!newVvTaxFileID || newVvTaxFileID == ''){//如果新的车船税ID为空,则删除组成物表中车船税的记录
@@ -167,10 +176,19 @@ async function addMixRatioForNew(projectID,unitFileId,engineerID,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 updateUnitPrice(unitPrice) {//同时支持单个或多个更新
+    if(Array.isArray(unitPrice)){
+        let tasks = [];
+        for(let u of unitPrice){
+            if(u && !_.isEmpty(u.doc)) tasks.push({updateOne: {filter: {id: u.id,unit_price_file_id:u.unit_price_file_id}, update: u.doc}});
+        }
+        if(tasks.length > 0)  await unit_price_model.bulkWrite(tasks);
+    }else {
+        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) {
@@ -213,6 +231,52 @@ async function updateFreightCalc(data){
     return{};
 }
 
+async function updateMaterialCalcTasks(data) {
+    let freightTasks = [];
+    let priceTasks = [];
+    for(let key in data){
+        if(key == "freight"){
+            let fu = data[key];
+            genTasks(fu,freightTasks);
+        }
+        if(key =="price"){
+            let pu = data[key];
+            genTasks(pu,priceTasks);
+        }
+    }
+
+    if(freightTasks.length > 0) await freight_calc_model.bulkWrite(freightTasks);
+    if(priceTasks.length > 0) await original_calc_model.bulkWrite(priceTasks);
+    if(data["unitPrice"]) await updateUnitPrice(data["unitPrice"]);
+
+
+    function genTasks(obj,tasks) {
+        for(let key in obj){
+            if(key == "update"){
+                let u = obj[key];
+                for(let ID in u ){
+                    tasks.push({updateOne: {filter: {ID: ID}, update: u[ID]}})
+                }
+            }
+            if(key == "add"){
+                let a = obj[key];
+                for(let d of a){
+                   // d.ID = uuidV1(); 改成在前端自动生成
+                    tasks.push({insertOne: {document: d}});
+                }
+            }
+            if(key == "delete"){
+                let r = obj[key];
+                for(let ID in r){
+                    tasks.push({deleteOne: {filter:{ID: ID}}});
+                }
+            }
+        }
+    }
+
+}
+
+
 async function updateMaterialCalc(data) {
     if(data.tasks.length > 0) await unit_price_model.bulkWrite(data.tasks);
     return {}

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

@@ -30,6 +30,7 @@ router.post('/batchUpdateGLJProperty', gljController.init, gljController.batchUp
 router.post('/batchUpdateConsumption', gljController.init, gljController.batchUpdateConsumption);
 router.post('/modifyKeyValue',gljController.init, gljController.modifyKeyValue);
 router.post('/changeVvTaxFile',gljController.init, gljController.changeVvTaxFile);
+router.post('/changeAssistProductionFeeRate',gljController.init, gljController.changeAssistProductionFeeRate);
 router.post('/addOriginalCalc',gljController.init, gljController.addOriginalCalc);
 router.post('/deletePriceCalc',gljController.init, gljController.deletePriceCalc);
 router.post('/updateOriginalCalc',gljController.init, gljController.updateOriginalCalc);
@@ -37,6 +38,7 @@ 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.post('/updateMaterialCalcTasks',gljController.init, gljController.updateMaterialCalcTasks);
 
 router.get('/getVvTaxList', gljController.init, gljController.getVvTaxList);
 router.get('/test', gljController.init, gljController.test);

+ 18 - 2
modules/main/controllers/ration_controller.js

@@ -37,6 +37,17 @@ let controller = {
         console.log("实际插入时间为-------------------------------"+(end-start));
         return result
     },
+    updateMaterialRation:async function(req){
+        let data = req.body.data;
+        data = JSON.parse(data);
+        console.log(data);
+        let result = await ration_facade.updateMaterialRation(data,req.session.sessionCompilation);
+        //合并取项目工料机数据的情求,用于刷新项目工料机数据,当有添加、替换项目工料机的情况,才需要刷新
+        if(result.ration_gljs && result.ration_gljs.length > 0){
+            result.projectGLJDatas =  await getProjectGLJData(data.projectID);
+        }
+        return result
+    },
     addMultiRation: async function (req) {
         let data = req.body.data;
         if(typeof data === 'object'){
@@ -160,8 +171,13 @@ module.exports = {
             result.data = controller[functionName]?await controller[functionName](req):"";
         }catch (err){
             logger.err(err);
-            result.error=1;
-            result.message = err.message;
+            if(typeof err == "string"){
+                result.error=2;
+                result.message = err;
+            }else {
+                result.error=1;
+                result.message = err.message;
+            }
         }
         res.json(result);
     }

+ 5 - 3
modules/main/facade/project_facade.js

@@ -233,13 +233,15 @@ async function markUpdateProject(data,type) {
         query['property.unitPriceFile.id'] = data.unitFileID;//unitPriceFile
     }
     let projects = await projectsModel.find(query);
-    return await markProjectsToChange(projects,type,data.projectID);
+    return await markProjectsToChange(projects,type,data.projectID,data.isInclude);
 }
 
-async function markProjectsToChange(projects,type,extProjectID){
+async function markProjectsToChange(projects,type,extProjectID,isInclude){
     let tasks=[];
     for(let p of projects){
-        if(extProjectID && p.ID===extProjectID) continue;//排除当前项目
+        if(isInclude!= true ){
+            if(extProjectID && p.ID===extProjectID) continue;//排除当前项目
+        }
         tasks.push(generateMarkTask(type,p.ID));
     }
     return tasks.length>0 ? await projectsModel.bulkWrite(tasks):null;

+ 129 - 24
modules/main/facade/ration_facade.js

@@ -4,6 +4,7 @@
 let mongoose = require('mongoose');
 import SearchDao from '../../complementary_ration_lib/models/searchModel';
 const scMathUtil = require('../../../public/scMathUtil').getUtil();
+let gljUtil = require('../../../public/gljUtil');
 let ration_glj_facade = require("../../ration_glj/facade/ration_glj_facade");
 let glj_calculate_facade = require("../../ration_glj/facade/glj_calculate_facade");
 let quantity_detail = require("../facade/quantity_detail_facade");
@@ -20,10 +21,13 @@ let std_glj_lib_gljList_model = mongoose.model('std_glj_lib_gljList');
 let complementary_glj_model =  mongoose.model('complementary_glj_lib');
 let rationItemModel = mongoose.model("std_ration_lib_ration_items");
 let complementaryRationModel = mongoose.model('complementary_ration_items');
+let freightCalcModel = mongoose.model('freight_calc');
+let originaltCalcModel = mongoose.model('original_calc');
 
 let coeMolde = mongoose.model('std_ration_lib_coe_list');
 let compleCoeModel = mongoose.model('complementary_ration_coe_list');
 
+
 let _= require('lodash');
 const projectDao = require('../../pm/models/project_model').project;
 let projectModel = mongoose.model('projects');
@@ -32,6 +36,8 @@ const fs = require('fs');
 module.exports = {
     replaceRations: replaceRations,
     addNewRation:addNewRation,
+    updateMaterialRation:updateMaterialRation,
+    addMaterialRation:addMaterialRation,
     addMultiRation: addMultiRation,
     getSameSectionRations:getSameSectionRations,
     getExtendData:getExtendData,
@@ -63,6 +69,95 @@ async function addNewRation(data,compilation) {
     }
 }
 
+async function updateMaterialRation(data,compilation){
+    let result = {};
+    switch (data.actionType){
+        case "add":
+            result = await addMaterialRation(data,compilation);
+            break;
+        case "delete":
+            result = await deleteMaterialRation(data);
+        case "update":
+            result = await modifyMaterialRation(data,compilation);
+    }
+    return result;
+}
+
+async function deleteMaterialRation(data) {
+    let model = data.type == "freight"?freightCalcModel:originaltCalcModel;
+    await model.update(
+        {ID:data.parentID},
+        { $pull: { rations: { ID: data.rationID},ration_gljs:{rationID:data.rationID} } },
+        { multi: true }
+    );
+    return data;
+}
+
+async function modifyMaterialRation(data,compilation) {
+    let model = data.type == "freight"?freightCalcModel:originaltCalcModel;
+    if(data.field == "code"){
+        let [newRation,ration_gljs] = await getNewMaterialRationDatas(data,compilation);
+        let quantity = data.rations[data.row].quantity;
+        newRation.quantity = quantity;
+        data.rations[data.row] = newRation;
+        _.remove(data.ration_gljs,{rationID:data.rationID});
+        data.ration_gljs = data.ration_gljs.concat(ration_gljs);
+        await  model.update({'ID':data.parentID},{rations:data.rations,ration_gljs:data.ration_gljs});
+        return {ration:newRation,ration_gljs:ration_gljs}
+    }else {
+        let doc = {},pre = "rations.$.";
+        let field = pre+data.field;
+        doc[field] = data.value;
+        if(data.ext){
+            for(let key in data.ext){
+                doc[pre+key] = data.ext[key];
+            }
+        }
+        if(data.ration_gljs){
+            let tasks = [];
+            for(let g of data.ration_gljs){
+                tasks.push({updateOne: {filter: {'ID':data.parentID,'ration_gljs.ID':g.ID}, update: {"ration_gljs.$.quantity":g.quantity}}})
+            }
+            await model.bulkWrite(tasks);
+        }
+        return await  model.update({'ID':data.parentID,'rations.ID':data.rationID},doc);
+    }
+}
+
+async function addMaterialRation(data,compilation) {
+    let [newRation,ration_gljs] = await getNewMaterialRationDatas(data,compilation);
+    let model = data.type == "freight"?freightCalcModel:originaltCalcModel;
+    await model.update({ID:data.parentID},{$push:{rations:newRation,ration_gljs:{$each:ration_gljs}}});
+    return{ration:newRation,ration_gljs:ration_gljs};
+}
+
+async function getNewMaterialRationDatas(data,compilation){
+    let searchDao = new SearchDao();
+    let stdRation = await searchDao.getRationItem(data.userID, compilation._id, data.rationRepIds,data.code);
+    if(!stdRation) throw  "找不到指定的定额!";//new Error("找不到指定的定额!");
+
+    let newRation = await createNewMaterialRation(stdRation,data.quantityDecimal,data.projectID);
+    let ration_gljs = await addRationGLJ(stdRation,newRation,compilation,true,data.connect_key);
+    return [newRation,ration_gljs];
+}
+
+
+async function createNewMaterialRation(std,quantityDecimal,projectID){
+    let newData = {};
+    newData.ID = uuidV1();
+    newData.projectID = projectID;
+    newData.code = std.code;
+    newData.name = std.name;
+    newData.caption = std.caption;
+    newData.unit = std.unit;
+    newData.libID = std.rationRepId;
+    newData.stdID = std.ID;
+    newData.quantity=scMathUtil.roundForObj(1 / FilterNumberFromUnit(std.unit),quantityDecimal);
+    newData.from = std.type === 'complementary' ? 'cpt' : 'std';
+    newData.rationAssList =await  createRationAss(std,true);
+    return newData;
+}
+
 async function addMultiRation(datas,compilation) {
     let rst = [];
     for(let data of datas){
@@ -145,7 +240,7 @@ async function insertNewRation(newData,defaultLibID,std,calQuantity) {//插入
         }else {
             newData.programID = std.feeType;
         }
-        newData.rationAssList =  createRationAss(std);
+        newData.rationAssList =await  createRationAss(std);
         // calculate ration Quantity
     }
     if(calQuantity){
@@ -382,7 +477,7 @@ function getExtendData(property,compilation) {
 
 
 
-async function addRationGLJ(std,newRation,compilation) {
+async function addRationGLJ(std,newRation,compilation,isMaterial,connect_key) {
     let newRationGLJList = [];
     let rationGLJShowList = [];
     let unitPriceFileId = 0;
@@ -409,6 +504,12 @@ async function addRationGLJ(std,newRation,compilation) {
        let cptGLJMap = _.indexBy(cptGLJList, 'ID');
         let stdGLJMapTime = +new Date();
         console.log("找到工料机映射表时间-------------------------------"+(stdGLJMapTime - first));
+        if(isMaterial == true){//材料计算添加时要先检查
+            for(let sub of std.rationGljList){
+                let t_g = getStdGlj(sub,stdGLJMap,cptGLJMap,{},ext);
+                if(t_g && connect_key == gljUtil.getIndex(t_g)) throw `本定额中包含工料机${t_g.code},与当前工料机编号相同,添加定额失败`;
+            }
+        }
         for(let sub of std.rationGljList){
             let newGLJ = {};
             newGLJ.ID = uuidV1();
@@ -419,18 +520,7 @@ async function addRationGLJ(std,newRation,compilation) {
             newGLJ.rationItemQuantity = sub.consumeAmt;
             newGLJ.quantity = sub.consumeAmt;
             newGLJ.glj_repository_id = std.rationRepId;
-            let std_glj = null;
-            if(sub.type == 'complementary'){//有可能来自标准工料机库或补充工料机库
-                std_glj = cptGLJMap[sub.gljId];
-                newGLJ.from = 'cpt';
-            }else {
-                std_glj = stdGLJMap[sub.gljId];
-                newGLJ.from = 'std';
-                //多单价情况处理
-                if(ext && ext.priceField && std_glj && std_glj.priceProperty){
-                    std_glj.basePrice =  std_glj.priceProperty[ext.priceField];
-                }
-            }
+            let std_glj = getStdGlj(sub,stdGLJMap,cptGLJMap,{},ext);
             if(std_glj){
                 ration_glj_facade.setPropertyFromStd(newGLJ,std_glj);
                 let info =  await ration_glj_facade.getInfoFromProjectGLJ(newGLJ,unitPriceFileId,ext);
@@ -444,6 +534,8 @@ async function addRationGLJ(std,newRation,compilation) {
     }
     let before = +new Date();
     console.log("总查询时间为-------------------------------"+(before-first));
+    if(isMaterial == true) return newRationGLJList;//如果是材料计算的工料机,这里返回就可以了
+
     if(newRationGLJList.length>0){
         await ration_glj.insertMany(newRationGLJList);
     }
@@ -453,6 +545,23 @@ async function addRationGLJ(std,newRation,compilation) {
     return rationGLJShowList;
 }
 
+function getStdGlj(sub,stdGLJMap,cptGLJMap,newGLJ,ext) {
+    let std_glj = null;
+    if(sub.type == 'complementary'){//有可能来自标准工料机库或补充工料机库
+        std_glj = cptGLJMap[sub.gljId];
+        newGLJ.from = 'cpt';
+    }else {
+        std_glj = stdGLJMap[sub.gljId];
+        newGLJ.from = 'std';
+        //多单价情况处理
+        if(ext && ext.priceField && std_glj && std_glj.priceProperty){
+            std_glj.basePrice =  std_glj.priceProperty[ext.priceField];
+        }
+    }
+    return std_glj;
+}
+
+
 async function deleRationSubRecode(projectID,rationID,cleanzmhs=false) {//删除挂在定额下的数据,如工程量明细,定额工料机等
     let delete_query={projectID: projectID, rationID: rationID};
     //删除工程量明细
@@ -535,7 +644,7 @@ async function  updateRation(std,defaultLibID,rationID,billsItemID,projectID,cal
     else if(std.rationRepId === defaultLibID && ration.from === 'cpt') {
         ration.prefix = '补';
     }
-    ration.rationAssList = createRationAss(std);//生成辅助定额
+    ration.rationAssList =await createRationAss(std);//生成辅助定额
     if(cleanzmh==false){//如果是清空子目换算,即cleanzmh==true 保留定额工程量、工程量表达式、含量(分解系数)、取费专业(取费类别)
         if(std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID
             ration.programID = await getProgramForProject(projectID);
@@ -590,7 +699,7 @@ async function setEmptyRation(projectID,rationID){
     return {ration:newRation,ration_gljs:[],ration_coes:[],ration_installs:[]};
 }
 
-function createRationAss(std) {
+async function createRationAss(std,isMaterial) {
     let  rationAssList = [];//生成辅助定额
     if(std.hasOwnProperty('rationAssList')&&std.rationAssList.length>0){
         let assGroup =  _.groupBy(std.rationAssList,'name');
@@ -605,16 +714,12 @@ function createRationAss(std) {
                 ass._doc.groupList = JSON.parse(JSON.stringify(assList))  ;
                 ass._doc.maxValue = assList[assList.length-1]._doc.maxValue;
             }
+            if(isMaterial == true){//材料计算进来的,直接保存辅助定额的信息  //常规的定额以后可以考虑也这样做
+                let t_assRation =  await rationItemModel.findOne({rationRepId:std.rationRepId,code:ass.assistCode}).lean();
+                if(t_assRation) ass._doc.assRation = t_assRation;
+            }
             rationAssList.push(ass);
         }
-      /*  for(let i=0;i<std.rationAssList.length;i++){
-            let ass = std.rationAssList[i];
-            ass._doc.actualValue = ass.stdValue;
-            ass._doc.isAdjust = 0;
-            if(_.isString(ass._doc.assistCode)) ass._doc.assistCode = ass._doc.assistCode.replace("\n","");
-            if(_.isString(ass._doc.thirdRationCode)) ass._doc.thirdRationCode = ass._doc.thirdRationCode.replace("\n","");
-            rationAssList.push(ass);
-        }*/
     }
     return rationAssList;
 }

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

@@ -12,6 +12,7 @@ module.exports = function (app) {
     rationRouter.post('/insertGLJAsRation', rationController.action);
     rationRouter.post('/replaceRations', rationController.action);
     rationRouter.post('/addNewRation', rationController.action);
+    rationRouter.post('/updateMaterialRation', rationController.action);
     rationRouter.post('/addMultiRation', rationController.action);
     rationRouter.post('/getSameSectionRations', rationController.action);
     rationRouter.post('/getDefaultProgramID', rationController.action);

+ 4 - 1
public/web/common_ajax.js

@@ -175,7 +175,10 @@ async function ajaxPost(url, data) {
             success: function(result){
                 if (result.error === 0 || result.err ===0) {
                     resolve(result.data);
-                } else {
+                }else if(result.error === 2 ){
+                    alert(result.message);
+                    reject(result.message);
+                }else {
                     alert('error: ' + result.message);
                     reject(result.message);
                 }

+ 27 - 0
public/web/gljUtil.js

@@ -16,12 +16,14 @@ let gljUtil = {
         let sField = isTender==true?"tenderSubdivisionQuantity":"subdivisionQuantity";
         let tField = isTender==true?"tenderTechQuantity":"techQuantity";
         let qField = isTender==true?"tenderQuantity":"quantity";
+        let mField = "materialQuantity"; //材料计算的工料机消耗量
 
         for(let pglj of project_gljs ){
             let pg_index = this.getIndex(pglj,this.gljKeyArray);
             pglj[sField] = 0;
             pglj[tField] = 0;
             pglj[qField] = 0;
+            pglj[mField] = 0;
             let gljGroup = rationGljGroup[pglj.id]?rationGljGroup[pglj.id]:[];//定额工料机没有,有可能是定额类型的工料机
             let result = this.getQuantityPerGLJ(gljGroup,rations,rationMap,pglj,billIDs,tech_billIDS,q_decimal,_,scMathUtil,isTender);
             pglj[sField] = result.subdivisionQuantity;
@@ -29,6 +31,10 @@ let gljUtil = {
             pglj[qField] = result.quantity;
             quantityMap[pg_index] = pglj;
         }
+        //材料计算中,工料机的消耗量
+        if(projectGLJDatas.freightList) this.setMaterialCalcQuantity(quantityMap,projectGLJDatas.freightList,q_decimal,_,scMathUtil); //运费计算中工料机的消耗量
+        if(projectGLJDatas.originalList) this.setMaterialCalcQuantity(quantityMap,projectGLJDatas.originalList,q_decimal,_,scMathUtil);//原价计算中工料机的消耗量
+
         //计算做为组成物的消耗量
         for(let pkey in mixRatioMap){
             let mixRatioList = mixRatioMap[pkey];
@@ -40,9 +46,11 @@ let gljUtil = {
                     let quantity = scMathUtil.roundForObj(parseFloat(p_glj[qField])*parseFloat(m.consumption),q_decimal);
                     let techQuantity = scMathUtil.roundForObj(parseFloat(p_glj[tField])*parseFloat(m.consumption),q_decimal);
                     let subdivisionQuantity = scMathUtil.roundForObj(parseFloat(p_glj[sField])*parseFloat(m.consumption),q_decimal);
+                    let materialQuantity = scMathUtil.roundForObj(parseFloat(p_glj[mField])*parseFloat(m.consumption),q_decimal);
                     m_glj[qField] =  scMathUtil.roundForObj(parseFloat(m_glj[qField])+quantity,q_decimal);
                     m_glj[tField] =  scMathUtil.roundForObj(parseFloat(m_glj[tField])+techQuantity,q_decimal);
                     m_glj[sField] =  scMathUtil.roundForObj(parseFloat(m_glj[sField])+subdivisionQuantity,q_decimal);
+                    m_glj[mField] =  scMathUtil.roundForObj(parseFloat(m_glj[mField])+materialQuantity,q_decimal);
                 }
             }
         }
@@ -55,6 +63,25 @@ let gljUtil = {
             pglj.quantity = scMathUtil.roundForObj(pglj.quantity +  pglj.transportLossQuantity ,q_decimal);
         }
     },
+    setMaterialCalcQuantity:function (quantityMap,calcList,q_decimal,_,scMathUtil) {
+        for(let t of calcList){
+            let rationIDMap = _.indexBy(t.rations,"ID");
+            if(t.ration_gljs){
+                for(let rg of t.ration_gljs){
+                    let rIndex = this.getIndex(rg);
+                    let pglj = quantityMap[rIndex];
+                    let ration = rationIDMap[rg.rationID];
+                    if(pglj && ration){
+                        let rg_quantity = scMathUtil.roundForObj(rg.quantity,q_decimal);
+                        let r_quantity = scMathUtil.roundForObj(ration.quantity,q_decimal);
+                        let result = scMathUtil.roundForObj(rg_quantity * r_quantity,q_decimal);
+                        pglj.quantity = scMathUtil.roundForObj(pglj.quantity + result,q_decimal);
+                        pglj.materialQuantity = scMathUtil.roundForObj(pglj.materialQuantity + result,q_decimal);
+                    }
+                }
+            }
+        }
+    },
     getOffSiteTransportLossRate:function (pglj) {
         let offSiteTransportLossRate;//场外运输损耗率
         let handlingLossRate;//每增加一次装卸损耗率

+ 5 - 0
public/web/number_util.js

@@ -33,5 +33,10 @@ var  number_util = {
             value = scMathUtil.roundTo(Number(obj),-decimal);
         }
         return value.toFixed(decimal);
+    },
+    isNum(thisValue){
+        var regPos = /^\d+(\.\d+)?$/; //非负浮点数
+        var regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/; //负浮点数
+        return (regPos.test(thisValue) || regNeg.test(thisValue));
     }
 }

+ 42 - 3
web/building_saas/css/custom.css

@@ -58,7 +58,9 @@ legend.legend{
 .full-h{
     height: 100%;
 }
-
+.half-h{
+    height: 50%;
+}
 .a_color{
     color: #007bff;
 }
@@ -71,8 +73,8 @@ legend.legend{
 
 #gljPriceTenderCoe::-webkit-outer-spin-button,
 #gljPriceTenderCoe::-webkit-inner-spin-button {
-         -webkit-appearance: none;
-     }
+    -webkit-appearance: none;
+}
 #gljPriceTenderCoe {
     -moz-appearance: textfield;
 }
@@ -324,6 +326,43 @@ input.text-right{
 .occupied {
     background: #f1f1f1;
 }
+.material-ration-left{
+    float:left;
+    width: 90%;
+}
+.material-ass{
+    width: 10%;
+    background:#f7f7f9
+}
+/*书签批注*/
+.annotate-color-1::before{
+    color: #E2F2C5 !important;
+    -webkit-text-stroke:.5px #ced4da;
+}
+.annotate-color-2::before{
+    color: #F9E2CF !important;
+    -webkit-text-stroke:.5px #ced4da;
+}
+.annotate-color-3::before{
+    color:#F2EFD9 !important;
+    -webkit-text-stroke:.5px #ced4da;
+}
+.annotate-color-4::before{
+    color:#F5D1DA !important;
+    -webkit-text-stroke:.5px #ced4da;
+}
+.annotate-color-5::before{
+    color:#E3E3E3 !important;
+    -webkit-text-stroke:.5px #ced4da;
+}
+.annotate-color-6::before{
+    color:#B6F3F2 !important;
+    -webkit-text-stroke:.5px #ced4da;
+}
+.annotate-color-7::before{
+    color:#ECE0F5 !important;
+    -webkit-text-stroke:.5px #ced4da;
+}
 /*书签批注*/
 .annotate-color-1::before{
     color: #E2F2C5 !important;

+ 75 - 1
web/building_saas/glj/html/project_glj.html

@@ -45,6 +45,9 @@
                     <li class="nav-item">
                         <a class="nav-link " id="mixRatio-nav" data-toggle="tab" href="#ph_div" role="tab" aria-selected="false">组成物计算</a>
                     </li>
+                    <li class="nav-item">
+                         <a class="btn btn-sm ml-1" href="#" data-toggle="modal" data-target="#calcCoeDiv"></i> 计算系数</a>
+                    </li>
                 </ul>
                 <!-- Tab panes -->
                 <div class="tab-content">
@@ -71,11 +74,25 @@
                                         <div class="tab-pane full-h active" id="rnc-yf">
                                             <div class=" ovf-hidden full-h">
                                                 <div class="ovf-hidden full-h" id="freightSheet"></div>
+                                                <div class="ovf-hidden half-h" id="freight_ration" style="display: none">
+                                                    <div class="ovf-hidden full-h" id="freight_ration_sheet"></div>  <!---->
+                                                    <div class="left full-h" id="freight_ration_ass" style="display: none">
+                                                        <label class="mx-2" for="freight_ass_value" style="margin-top: 10px">运距m</label><br>
+                                                        <input type="text" class="form-control form-control-sm ration_ass_value" id="freight_ass_value">
+                                                    </div>
+                                                </div>
                                             </div>
                                         </div>
                                         <div class="tab-pane full-h" id="rnc-yj">
                                             <div class="full-h ovf-hidden">
-                                                <div class="ovf-hidden full-h" id="priceSheet" style=""></div>
+                                                <div class="ovf-hidden half-h" id="priceSheet" style=""></div>
+                                                <div class="ovf-hidden half-h" id="price_ration" >
+                                                    <div class="ovf-hidden full-h" id="price_ration_sheet" ></div>
+                                                    <div class="left full-h" id="price_ration_ass" style="display: none">
+                                                        <label class="mx-2" for="price_ass_value" style="margin-top: 10px">运距m</label><br>
+                                                        <input type="text" class="form-control form-control-sm ration_ass_value" id="price_ass_value">
+                                                    </div>
+                                                </div>
                                             </div>
                                         </div>
                                     </div>
@@ -194,3 +211,60 @@
         </div>
     </div>
 </div>
+
+<!--弹出 计算系数窗口-->
+<div class="modal fade" id="calcCoeDiv" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">计算系数</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>辅助生产间接费费率(%)</label>
+                    <input class="form-control" id="assistProductionFeeRate" value="">
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-primary" id="calcCoeConfirm">确定</button>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+
+<!--弹出 插入内蒙古运费计算窗口口-->
+<div class="modal fade" id="insertNeimengDiv" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">内蒙古运费计算</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>起讫地点</label>
+                    <input class="form-control" id="freight_start" value="">
+                    <label>材料种类</label>
+                    <select class="form-control" id="freight_materialType">
+                        <option value="地方材料">地方材料</option>
+                        <option value="外购材料">外购材料</option>
+                        <option value="沥青、燃料等">沥青、燃料等</option>
+                    </select>
+                    <label>运输距离</label>
+                    <input class="form-control" id="freight_kmDistance" value="0">
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-primary" id="insertFreightconfirm">确定</button>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 10 - 6
web/building_saas/js/global.js

@@ -18,7 +18,6 @@ function autoFlashHeight(){
     $('#glj_tree_div .modal-content').width($(window).width() < 1020 + 20 ? $(window).width() - 20 : 1020);
     //$("#main .main-data-top").height($(window).height()-headerHeight-toolsbarHeight-bottomContentHeight-1);
     typeof(loadMainSize)== 'function' ?loadMainSize():'';//zhang 2018-06-04  统一加载高度方法
-    typeof(loadProjectGljSize)== 'function'?loadProjectGljSize():'';
     $(".main-data-full").height($(window).height()-headerHeight-toolsbarHeight-1);
     $(".main-data-full-fl").height($(window).height()-headerHeight-toolsbarHeight-37);
     $(".main-data-full-feeRate").height($(window).height()-headerHeight-78);
@@ -33,7 +32,8 @@ function autoFlashHeight(){
     $(".form-list").height($(window).height()-headerHeight);
     $('#comments').find('textarea').height($('#comments').height() - 25);
     $('#project-glj-main').width($(window).width()-($('.main-nav').width()+ 2));//-($('.filterType').width()+12)-5); //2、12是padding宽度,width 是不算padding宽度的
-    $('#project_glj_sheet').width($('#project-glj-main').width()-($('.filterType').width()+12)-1)//12是padding宽度,1是border宽度,width 是不算padding和border宽度的
+    $('#project_glj_sheet').width($('#project-glj-main').width()-($('.filterType').width())-1)//1是border宽度,width 是不算padding和border宽度的
+    typeof(loadProjectGljSize)== 'function'?loadProjectGljSize():'';
     //typeof zmhs_obj === 'object' ? zmhs_obj.loadSideResize() : '';
 };
 
@@ -132,10 +132,14 @@ function getFeeIndex(fees) {
     let feesIndex = {};
     if (fees) {
         for(let fee of fees){
-            fee.unitFee = parseFloat(fee.unitFee);
-            fee.totalFee = parseFloat(fee.totalFee);
-            fee.tenderUnitFee = parseFloat(fee.tenderUnitFee);
-            fee.tenderTotalFee = parseFloat(fee.tenderTotalFee);
+            const parsedUnitFee = parseFloat(fee.unitFee);
+            const parsedTotalFee = parseFloat(fee.totalFee);
+            const parsedTenderUnitFee = parseFloat(fee.tenderUnitFee);
+            const parsedTenderTotalFee = parseFloat(fee.tenderTotalFee);
+            fee.unitFee = parsedUnitFee || 0;
+            fee.totalFee = parsedTotalFee || 0;
+            fee.tenderUnitFee = parsedTenderUnitFee || 0;
+            fee.tenderTotalFee = parsedTenderTotalFee || 0;
             feesIndex[fee.fieldName] = fee;
         }
     }

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

@@ -67,7 +67,7 @@
     </div>
     <div class="main">
         <div class="main-nav">
-            <ul class="nav nav-tabs flex-column" role="tablist">
+            <ul class="nav nav-tabs flex-column" role="tablist" id="mainNav">
                 <li class="nav-item"><a class="active" data-toggle="tab" href="#zaojiashu" id="tab_zaojiashu" role="tab">造价书</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#project_glj" id="tab_project_glj" data-name="tab_project_glj" role="tab">工料机汇总</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#fee_rates" id="tab_fee_rate" role="tab" >费率</a></li>

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

@@ -813,6 +813,7 @@ var Bills = {
                     gljOprObj.refreshView();
                 });*/
                 project.calcProgram.calcNodesAndSave(parentNodes);
+                project.projectGLJ.calcQuantity();
                 gljOprObj.refreshView();
                 if (isDeleteChild){
                     calcTools.forceSelect(parentNode);

+ 422 - 107
web/building_saas/main/js/models/project_glj.js

@@ -296,6 +296,7 @@ ProjectGLJ.prototype.updateCalcMaterial =async function (projectGLJ,updateField,
                 ext['purchaseStorageRate_n'] = glj.unit_price.purchaseStorageRate;
                 ext['offSiteTransportLossRate_n'] = glj.unit_price.offSiteTransportLossRate;
                 ext['handlingLossRate_n'] = glj.unit_price.handlingLossRate;
+                ext['totalLoadingTimes'] = '1';
             }else if(value == 0){//删除操作,恢复单位毛重/采购保管费率等数据
                 ext['supplyLocation'] = '';
                 ext['originalPrice'] = '0';
@@ -335,22 +336,97 @@ ProjectGLJ.prototype.updateCalcMaterial =async function (projectGLJ,updateField,
     }
 };
 
-ProjectGLJ.prototype.materialCal = function (id,dataMap) {
+ProjectGLJ.prototype.calcAllMaterial = function (unitPriecs) {//当材料发生改变时重算所有计算材料的价格
+    let priceMap = {};
+    for(let unitPrice of unitPriecs){
+        if(unitPrice && gljUtil.isDef(unitPrice.doc.market_price)) priceMap[unitPrice.projectGLJID] = unitPrice.doc.market_price;
+    }
+    let freightListMap =  _.groupBy(this.datas.freightList,'connect_key');//取运费计算项映射表
+    let originalListMap = _.groupBy(this.datas.originalList,'connect_key');//取原价计算项映射表
+    let sumFreightUpdateMap = {}; //存放所有材料下的运费更新信息;
+    let sumOriginalUpdateMap = {};//存放所有材料下的原价更新信息;
+
+    for(let g of this.datas.gljList){
+        if(g.quantity !== 0 && g.quantity !== '0'  && g.unit_price.calcMaterial == 1&&!priceMap[g.id]){//工料机本身不包含在要计算的列表内
+            //先判断要不要重算,只有包含相关工料机的定额的材料,才需要重新计算
+            let fOrPDataMap = {};
+            let tIndex = gljUtil.getIndex(g);
+            //运费和原价中的工料机只要有一个包含该材料,就要重算
+            if(freightListMap[tIndex]){ //运费重算
+                let freightUpdateMap = {};
+                for(let f of freightListMap[tIndex]){
+                    if(f.conveyance != "自办运输") continue;//不是自办运输的不用管
+                    let calf = ifNeedReCalc(f,priceMap);
+                    if(calf){
+                        let f_task = this.calcEachFreightOrPrice(f,"freight",priceMap);
+                        if(f_task){
+                            freightUpdateMap[f_task.ID] = f_task.doc;
+                            sumFreightUpdateMap[f_task.ID] = f_task.doc;
+                        }
+                    }
+                }
+                if(!_.isEmpty(freightUpdateMap)) fOrPDataMap["freight"] = {update:freightUpdateMap};
+            }
+            //原价重算
+            if(originalListMap[tIndex]){ //运费重算
+                let originalUpdateMap = {};
+                for(let o of originalListMap[tIndex]){
+                    let calo = ifNeedReCalc(o,priceMap);
+                    if(calo){
+                        let o_task = this.calcEachFreightOrPrice(o,"price",priceMap);
+                        if(o_task){
+                            originalUpdateMap[o_task.ID] = o_task.doc;
+                            sumOriginalUpdateMap[o_task.ID] = o_task.doc;
+                        }
+                    }
+                }
+                if(!_.isEmpty(originalUpdateMap)) fOrPDataMap["price"] = {update:originalUpdateMap};
+            }
+            //判断映射表是否为空,如果为空则说明不用计算
+            if(!_.isEmpty(fOrPDataMap)){
+                let t_unipPrice = this.materialCal(g.id,fOrPDataMap,g,freightListMap[tIndex],originalListMap[tIndex]);
+                if(t_unipPrice) unitPriecs.push(t_unipPrice);
+            }
+        }
+    }
+    let sumUpdateMap = {};
+    if(!_.isEmpty(sumFreightUpdateMap))sumUpdateMap["freight"] = {update:sumFreightUpdateMap};
+    if(!_.isEmpty(sumOriginalUpdateMap))sumUpdateMap["price"] = {update:sumOriginalUpdateMap};
+    return [unitPriecs,sumUpdateMap];
+
+
+    function ifNeedReCalc(obj,IDMap) {
+        let calcf = false;
+        if(obj.ration_gljs){
+            for(let rg of  obj.ration_gljs){
+                if(IDMap[rg.projectGLJID]){//判断是否关联了该项目工料机
+                    calcf = true;
+                    break;
+                }
+            }
+        }
+        return calcf;
+    }
+
+};
+
+
+ProjectGLJ.prototype.materialCal = function (id,dataMap,tglj,tfreightList,tpriceList) {
     let unitPriceHasMix = getDecimal("glj.unitPriceHasMix");
     let unitPirceDecimal = getDecimal("glj.unitPrice");
     let process = getDecimal("process");
-    let glj = _.find(this.datas.gljList,{'id':id});
+    let glj = tglj?tglj: _.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 unitPrice = {projectGLJID:glj.id,id:glj.unit_price.id,'unit_price_file_id':glj.unit_price.unit_price_file_id,doc:{}};
     //先计算原价
-    let [originalPrice,supplyLocation] = this.priceCalc(glj,dataMap);
+    let [originalPrice,supplyLocation] = this.priceCalc(glj,dataMap,tpriceList);
     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,process);
-    let unitFreight = this.freightCalc(glj,grossWeightCoe_n,dataMap);
+    let unitFreight = this.freightCalc(glj,grossWeightCoe_n,dataMap,tfreightList);
     doc['unitFreight'] = unitFreight+'';
     //计算场外运输损耗
     let sum_o_f = scMathUtil.roundForObj(originalPrice+unitFreight,process);//(原价+单位运费)
@@ -386,15 +462,15 @@ ProjectGLJ.prototype.materialCal = function (id,dataMap) {
     return unitPrice
 };
 
-ProjectGLJ.prototype.freightCalc= function (glj,grossWeightCoe_n,dataMap) {
+ProjectGLJ.prototype.freightCalc= function (glj,grossWeightCoe_n,dataMap,tfreightList) {
     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)});
+    let freightList = tfreightList?tfreightList:_.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;
+        let unitFreight = f.unitFreight,kmDistance = f.kmDistance,freightIncreaseRate = f.freightIncreaseRate,unitLoadingFee= f.unitLoadingFee,loadingTimes = f.loadingTimes,otherFee = f.otherFee,weightCoe = f.weightCoe,conveyance = f.conveyance,calcType=f.calcType,materialType=f.materialType;
         if(dataMap["freight"] && dataMap["freight"]["update"]){//覆盖更新的数据
             let t = dataMap["freight"]["update"][f.ID];
             if(t){
@@ -405,17 +481,22 @@ ProjectGLJ.prototype.freightCalc= function (glj,grossWeightCoe_n,dataMap) {
                 if(t['loadingTimes']) loadingTimes = t['loadingTimes'];
                 if(t['otherFee']) otherFee = t['otherFee'];
                 if(t['weightCoe']) weightCoe = t['weightCoe'];
+                if(t['conveyance']) conveyance = t['conveyance'];
+                if(t['calcType']) calcType = t['calcType'];
+                if(t['materialType']) materialType = t['materialType'];
             }
         }
         if(dataMap["freight"] && dataMap["freight"]["delete"]){//忽略删除的数据
-            if(f.ID ==dataMap["freight"]["delete"]) continue;
+            if(dataMap["freight"]["delete"][f.ID]) 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运距
+
+        let t = getPrice(unitFreight,kmDistance,conveyance,calcType,materialType,process);//单位运价×km运距
+        console.log(t);
         t = scMathUtil.roundForObj(t*freightIncreaseRate,process);//单位运价×km运距×(1+运距增加率%)
         unitLoadingFee = scMathUtil.roundForObj(unitLoadingFee,unitPirce);
         loadingTimes = scMathUtil.roundForObj(loadingTimes,unitPirce);
@@ -434,16 +515,25 @@ ProjectGLJ.prototype.freightCalc= function (glj,grossWeightCoe_n,dataMap) {
     }
     return scMathUtil.roundForObj(sum,unitPirce);
 
+
+    function getPrice(unitFreight,kmDistance,conveyance,calcType,materialType,process){
+        //如果运输方式为自办运输,则直接返回单位运价即可;
+        let price = conveyance == "自办运输"|| calcType =="内蒙古"? scMathUtil.roundForObj(unitFreight,process):scMathUtil.roundForObj(unitFreight * kmDistance,process);//单位运价×km运距
+
+        return price
+    }
+
+
 };
 
-ProjectGLJ.prototype.priceCalc = function (glj,dataMap) {
+ProjectGLJ.prototype.priceCalc = function (glj,dataMap,tpriceList) {
     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)});
+    let priceList = tpriceList?tpriceList:_.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,supplyLocation=p.supplyLocation;
@@ -454,7 +544,7 @@ ProjectGLJ.prototype.priceCalc = function (glj,dataMap) {
             if(t && t["supplyLocation"]) supplyLocation = t["supplyLocation"];
         }
         if(dataMap["price"] && dataMap["price"]["delete"]){//忽略删除的数据
-            if(p.ID ==dataMap["price"]["delete"]) continue;
+            if(dataMap["price"]["delete"][p.ID]) continue;
         }
         supplyPrice = scMathUtil.roundForObj(supplyPrice,unitPirce);
         coe = scMathUtil.roundForObj(coe,unitPirce);
@@ -476,7 +566,7 @@ ProjectGLJ.prototype.m_updateUnitPrice = function (datas) {//批量更新
     let me = this;
     let gljList = [];
     for(let d of datas){
-        let g = updateUnit(d.id,d.unitPrice);
+        let g = updateUnit(d.projectGLJID,d);
         if(g) gljList.push(g);
     }
     this.calcQuantity();
@@ -484,13 +574,19 @@ ProjectGLJ.prototype.m_updateUnitPrice = function (datas) {//批量更新
     projectGljObject.refreshDataSheet();
     //重新计算相关节点
 
-    let nodes = me.getImpactRationNodes(gljList);//取到因为改变工料机价格而受影响的定额
-    projectObj.project.calcProgram.calcNodesAndSave(nodes);//触发计算程序
+    /*  2019-10-29  这里改成修改材料计算后先不自动计算,先在项目属性上做标记,切换到其它标签页时才做自动计算
+
+        let nodes = me.getImpactRationNodes(gljList);//取到因为改变工料机价格而受影响的定额
+        projectObj.project.calcProgram.calcNodesAndSave(nodes);//触发计算程序
+
+    */
 
     //刷新定额工料机
     gljOprObj.refreshView();
+    //项目单价文件修改标记
+    projectObj.project.projectInfo.changeMark = 'unitFile';
     //socket推送更新信息
-    projectGljObject.onUnitFileChange();
+    projectGljObject.onUnitFileChange(true);
 
 
     function updateUnit(id,unitPrice) {
@@ -506,37 +602,27 @@ ProjectGLJ.prototype.m_updateUnitPrice = function (datas) {//批量更新
 };
 
 ProjectGLJ.prototype.updateUnitPrice = function(id,unitPrice){
-    this.m_updateUnitPrice([{id:id,unitPrice:unitPrice}]);
+    this.m_updateUnitPrice([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();
-    }
+    await this.updateMaterialCalcTasks(pgljID,datas,"add","price");
 };
 
 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})
+            updateDatas.push(unitPrice);
         }
+        if(updateDatas.length ==0 ) return;
+        let [unitPrices,sumMap] = this.calcAllMaterial(updateDatas);
+        sumMap = {"unitPrice":unitPrices};
         $.bootstrapLoading.start();
-        let result =  await ajaxPost('/glj/updateMaterialCalc',{tasks:tasks});
-        this.m_updateUnitPrice(updateDatas);
+        let result =  await ajaxPost('/glj/updateMaterialCalcTasks',sumMap);
+        this.refreshMaterialCalcCache(sumMap);
         materialCalcObj.showDatas();
     }catch (e){
         console.log(e)
@@ -547,111 +633,342 @@ ProjectGLJ.prototype.updateMaterialCalc = async function (datas) {
 };
 
 ProjectGLJ.prototype.updateFreightCalc = async function (datas,pgljID){
+    let updateMap = {};
+    for(let d of datas){
+        updateMap[d.ID] = d.doc;
+    }
+    await this.updateMaterialCalcTasks(pgljID,updateMap,"update","freight");
+};
+
+
+ProjectGLJ.prototype.updateMaterialCalcTasks =async function(pgljID,dataMap,actionType,model){
+    //为了统一接口, 参数dataMap 在添加操作时是一个数组,在修改的时候是一个ID - doc 映射表,在删除的时候传入的是一个ID
+
     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]);
+        let actionMap={};
+        let calMap = {};
+        actionMap[actionType] = dataMap;
+        calMap[model] = actionMap;//{freight:{update:updateMap}
+        let unitPrice = this.materialCal(pgljID,calMap);//计算当前这一条材料
+        let [unitPrices,sumMap] = this.calcAllMaterial([unitPrice]);//计算完一条材料后,还要计算因为这条材料而受影响的其它所有材料
+        if(actionType == "update") {//更新情况
+            if (sumMap[model] && sumMap[model][actionType]) {//这一步,合并需要提交后台修改的数据
+                let tt = sumMap[model][actionType];
+                for (let d of datas) {
+                    tt[d.ID] = d.doc;
+                }
+            } else {
+                sumMap[model] = actionMap;
             }
+        }else if(actionType == "delete"){
+            let IDMap = {};
+            IDMap[dataMap] = true;
+            sumMap[model] = {"delete":IDMap};
+        }else {
+            sumMap[model] = actionMap
         }
-        this.updateUnitPrice(pgljID,unitPrice);
+        sumMap["unitPrice"] = unitPrices;
+
+        $.bootstrapLoading.start();
+        let result = await ajaxPost('/glj/updateMaterialCalcTasks',sumMap);
+        this.refreshMaterialCalcCache(sumMap);
         materialCalcObj.showDatas();
     }catch (e){
         console.log(e)
     }finally {
         $.bootstrapLoading.end();
     }
+
 };
 
+
+
+ProjectGLJ.prototype.refreshMaterialCalcCache = function (updateMap){
+   if(updateMap["freight"]) updateList(this.datas.freightList,updateMap["freight"]);
+   if(updateMap["price"]) updateList(this.datas.originalList,updateMap["price"]);
+   if(updateMap["unitPrice"]) {
+      if(Array.isArray(updateMap["unitPrice"])){
+          this.m_updateUnitPrice(updateMap["unitPrice"]);
+      }else {
+          this.m_updateUnitPrice([updateMap["unitPrice"]]);
+      }
+   }
+
+    function updateList(list,updateMap) {
+       if(updateMap["update"]){
+           let map = updateMap["update"];
+           for(let o of list){
+               if(map[o.ID]){
+                   gljUtil.updateProperty(o,map[o.ID]);
+               }
+           }
+       }
+
+       if(updateMap["add"]){
+           for(let a of updateMap["add"]){
+               list.push(a);
+           }
+       }
+
+       if(updateMap["delete"]){
+           for(let ID in updateMap["delete"]){
+               _.remove(list,{'ID':ID});
+           }
+       }
+    }
+};
+
+
+
 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();
+    let updateMap = {};
+    for(let d of datas){
+        updateMap[d.ID] = d.doc;
     }
+    await this.updateMaterialCalcTasks(pgljID,updateMap,"update","price");
 };
 
 
 ProjectGLJ.prototype.addFreightCalc = async function (datas,pgljID) {
+    await this.updateMaterialCalcTasks(pgljID,datas,"add","freight");
+};
+
+ProjectGLJ.prototype.addMaterialRation = async function (code,type,parentID,connect_key){
+        let libIDs = rationLibObj.getStdRationLibIDs();
+        let defaultLibID = rationLibObj.getDefaultStdRationLibID();
+        let selectedLib =  sessionStorage.getItem("stdRationLib");
+        selectedLib&&selectedLib!='undefined'?libIDs.unshift(selectedLib):libIDs.unshift(defaultLibID);
+        let datas = {userID: userID,defaultLibID:defaultLibID, rationRepIds: libIDs, code: code,type:type,parentID:parentID,quantityDecimal:getDecimal("ration.quantity"),connect_key:connect_key,projectID:projectObj.project.ID()};
+        datas.actionType="add";
+        await this.updateMaterialRation(datas);
+};
+
+ProjectGLJ.prototype.changeAssistProductionFeeRate = async function (newFeeRate) {
+    $.bootstrapLoading.start();
     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);
+        await ajaxPost("/glj/changeAssistProductionFeeRate",{unitFileID:projectObj.project.property.unitPriceFile.id,assistProductionFeeRate:newFeeRate});
+        this.datas.constData.assistProductionFeeRate = newFeeRate;
+        //todo  调用材料计算方法,所有材料重算一遍
+        let [unitPrices,sumMap] = this.calcAllMaterial([]);
+        sumMap["unitPrice"] = unitPrices;
+        let result = await ajaxPost('/glj/updateMaterialCalcTasks',sumMap);
+        this.refreshMaterialCalcCache(sumMap);
         materialCalcObj.showDatas();
-
-    }catch (e){
-        console.log(e)
+    }catch (err){
+        console.log(err);
     }finally {
         $.bootstrapLoading.end();
     }
 };
 
-ProjectGLJ.prototype.deletePriceCalc = async function (ID,pgljID) {
+ProjectGLJ.prototype.updateMaterialRation = async function (datas){
     try {
-        let data={ID:ID};
-        // 计算预算价
-        let unitPrice = this.materialCal(pgljID,{price:{'delete':ID}});
-        data.unitPrice = unitPrice;
+        let lists = datas.type == "freight"?this.datas.freightList:this.datas.originalList;
         $.bootstrapLoading.start();
-        await ajaxPost('/glj/deletePriceCalc',data);
-        _.remove(this.datas.originalList,{'ID':data.ID});
-        //更新单价文件的值
-        this.updateUnitPrice(pgljID,unitPrice);
-        materialCalcObj.showDatas();
-
+        let result =  await ajaxPost('/ration/updateMaterialRation',datas);
+        if(datas.actionType=="add" && result.projectGLJDatas) this.refreshByDatas(result.projectGLJDatas);//这一步已经更新了运费和原价数据
+        if(datas.actionType == "delete"){
+           let parent = _.find(lists,{ID:datas.parentID}) ;
+           if(parent){
+               _.remove(parent.rations,{ID:datas.rationID});
+               _.remove(parent.ration_gljs,{rationID:datas.rationID});
+           }
+        }
+        if(datas.actionType == "update"){
+            let parent = _.find(lists,{ID:datas.parentID}) ;
+            let ration = parent?_.find(parent.rations,{ID:datas.rationID}):null;
+            if(ration){
+                if(datas.field == "code" && result.projectGLJDatas){
+                    this.refreshByDatas(result.projectGLJDatas);
+                }else {
+                    ration[datas.field] = datas.value;
+                    if(datas.ext){
+                        for(let key in datas.ext){
+                            ration[key] = datas.ext[key];
+                        }
+                    }
+                }
+                if(datas.ration_gljs){//更新定额工料机数量
+                    let gljMap = _.indexBy(parent.ration_gljs,"ID");
+                    for(let g of datas.ration_gljs){
+                        if(gljMap[g.ID]) gljMap[g.ID].quantity = g.quantity;
+                    }
+                }
+            }
+        }
     }catch (e){
         console.log(e)
     }finally {
+       //materialCalcObj.showDatas();
+        this.calcMaterialRation(datas.parentID,datas.type);
         $.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();
+ProjectGLJ.prototype.getHighlandFee = function (feeType) {
+    let rates = projectObj.project.FeeRate.getActivateFeeRate().rates;
+    let matchType = false;
+    let rate = 0;
+    //获取高原取费类别,是先按feeType取顶层的费率,然后取子项中的“高原地区施工增加费”
+    if(!feeType||feeType=="") return 0;//空时为0
+    let hightlandRate = null;
+    let topParentID = null;
+    for(let r of rates){//费率是按顺序排的,所以先取到顶层,之后的就是目标了。
+        if(matchType && r.ParentID == topParentID) break; //如果feeType已经匹配过了,又经过了下一个顶层节点,那说明该feeType下没有高原费率
+        if(r.name == feeType){
+            matchType = true;
+            topParentID = r.ParentID;
+        }
+        if(matchType && r.name == "高原地区施工增加费"){
+            //顶层先匹配上了,第一个就是要找的费率
+            hightlandRate = r;
+            break;
+        }
+    }
+    if(hightlandRate){
+        rate = scMathUtil.roundForObj(hightlandRate.rate,getDecimal("feeRate"));
+    }
+    return rate*0.01
+};
 
-    }catch (e){
-        console.log(e)
-    }finally {
-        $.bootstrapLoading.end();
+ProjectGLJ.prototype.calcEachFreightOrPrice = function (temp,type,priceMap) {//
+    if(temp){
+         if(type == "freight" && temp.conveyance !="自办运输") return null;
+        let sum =0;
+        let gljMap = {};
+        let pgljMap =_.indexBy(this.datas.gljList, 'id');
+        for(let g of temp.ration_gljs){
+            gljMap[g.rationID]?gljMap[g.rationID].push(g):gljMap[g.rationID]=[g];
+        }
+        for(let r of temp.rations){
+            sum = scMathUtil.roundForObj(sum + calcRation(r,gljMap[r.ID],pgljMap,priceMap),6);
+        }
+        sum = scMathUtil.roundForObj(sum,getDecimal("glj.unitPrice"))+"";
+        if(type == "freight" && temp.unitFreight!= sum) return {ID:temp.ID,doc:{unitFreight:sum}};
+        if(type == "price" && temp.supplyPrice !=sum) return {ID:temp.ID,doc:{supplyPrice:sum}};
     }
+    return null;
+
+
+    function calcRation(ration,gljs,pMap,priceMap){
+        let result = 0;
+        if(gljs){
+            //to do 计算有辅助定额的情况
+            let processDecimal = getDecimal("process");
+            let hightFeeRate = projectObj.project.projectGLJ.getHighlandFee(ration.feeType);//高原取费类别费率
+            let assFeeRate = scMathUtil.roundForObj(projectObj.project.projectGLJ.datas.constData.assistProductionFeeRate,getDecimal("feeRate")) * 0.01;//辅助生产间接费费率
+            let laberSum = 0;
+            let machineSum = 0;
+            let rationQuantity = scMathUtil.roundForObj(ration.quantity,getDecimal("ration.quantity"));
+            for(let g of gljs){
+                gljOprObj.setGLJPrice(g,pMap[g.projectGLJID]);
+                if(priceMap && priceMap[g.projectGLJID]) g.marketPrice = scMathUtil.roundForObj(priceMap[g.projectGLJID]);
+                let quantity = scMathUtil.roundForObj(g.quantity,getDecimal("glj.quantity"));
+                let t = scMathUtil.roundForObj(quantity * g.marketPrice * rationQuantity,processDecimal);//市场价
+                let rt = scMathUtil.roundForObj(quantity * g.basePrice * rationQuantity,processDecimal);//定额价
+                if(g.type == gljUtil.gljType.LABOUR) laberSum = scMathUtil.roundForObj(laberSum+rt,processDecimal);
+                if(gljUtil.getMainType(g.type) == 3) machineSum = scMathUtil.roundForObj(machineSum+rt,processDecimal);
+                result = scMathUtil.roundForObj(result + t,processDecimal);
+            }
+            let as = scMathUtil.roundForObj(laberSum * assFeeRate,processDecimal);//人工消耗量*定额价*定额工程量*辅助生产间接费费率
+            let tt = scMathUtil.roundForObj(laberSum + machineSum,processDecimal);//人工定额消耗量*定额价*定额工程量+机械定额消耗量*定额价*定额工程量
+            let hs = scMathUtil.roundForObj(tt*hightFeeRate,processDecimal);//(人工定额消耗量*定额价*定额工程量+机械定额消耗量*定额价*定额工程量)*高原取费类别费率
+            result = scMathUtil.roundForObj(as + result,processDecimal);
+            result = scMathUtil.roundForObj(hs + result,processDecimal);
+        }
+        return  result;
+    }
+
+
+
+
+
+};
+
+ProjectGLJ.prototype.calcMaterialAssQuantity = function (parent,ration,newAssList) {
+    let updateList = [];
+    let assList = calcAssList(newAssList);
+    for(let glj of parent.ration_gljs){
+        if(glj.rationID == ration.ID){
+            updateList.push(calcAssGljQuantity(glj,assList));
+        }
+    }
+
+    return updateList;
+
+
+    function calcAssGljQuantity(g,assList) {
+        g.quantity = scMathUtil.roundForObj(g.rationItemQuantity,getDecimal("glj.quantity"));
+        for(let a of assList){
+            let ass = a.ass;
+            let matchGlj = null;
+            for(let aglj of ass.rationGljList){
+                if(aglj.gljId == g.GLJID){
+                    matchGlj = aglj;
+                    break;
+                }
+            }
+            if(matchGlj){
+                let calQuantity =scMathUtil.roundForObj(matchGlj.consumeAmt*a.times,6);
+                g.quantity =  scMathUtil.roundForObj(calQuantity + g.quantity,getDecimal("glj.quantity"))+"";
+            }
+        }
+        return {ID:g.ID,quantity:g.quantity}
+    }
+
+    function calcAssList(rationAssList){
+        let calAss = [];
+        for(let ass of rationAssList){
+            let times = calculateTimes(ass);
+            if(times!=0){
+                calAss.push({ass:ass.assRation,times:times});
+            }
+        }
+        return calAss;
+    }
+
+    function calculateTimes(ass){
+        if(ass.name != "运距m") return 0;//只计算运距;
+        let times =(ass.actualValue-ass.stdValue)/ass.stepValue;
+        let r = false;
+        if(times<0){
+            r=true;
+            times=times*-1;
+        }
+        if(ass.carryBit=='四舍五入'){
+            times = _.round(times,ass.decimal);
+        }else if (ass.carryBit=='进一'){
+            times =_.ceil(times,ass.decimal);
+        }else if(ass.carryBit == '舍一'){
+            times = _.floor(times,ass.decimal);
+        }
+        if(r){
+            times=times*-1;
+        }
+        return scMathUtil.roundTo(times,-6);
+    }
+};
+
+
+ProjectGLJ.prototype.calcMaterialRation = function(ID,type){//计算带定额的运费或者原价
+    let lists = type == "freight"?this.datas.freightList:this.datas.originalList;
+    let temp = _.find(lists,{ID:ID});
+    if(temp){
+        let task = this.calcEachFreightOrPrice(temp,type);
+        let material = materialCalcObj.getMaterialSelected();
+        if(task && material){
+            if(type == "freight") projectObj.project.projectGLJ.updateFreightCalc([task],material.id);
+            if(type == "price") projectObj.project.projectGLJ.updatePriceCalc([task],material.id);
+        }
+    }
+};
+
+ProjectGLJ.prototype.deletePriceCalc = async function (ID,pgljID) {
+    await this.updateMaterialCalcTasks(pgljID,ID,"delete","price");
+};
+
+ProjectGLJ.prototype.deleteFreightCalc = async function (ID,pgljID) {
+    await this.updateMaterialCalcTasks(pgljID,ID,"delete","freight");
 };
 
 ProjectGLJ.prototype.updatePrice = function (recode, updateField, newval,from,cb) {
@@ -703,7 +1020,6 @@ ProjectGLJ.prototype.batchUpdateGLJProperty = function (updateMap,callback) {
     CommonAjax.post("/glj/batchUpdateGLJProperty", updateMap,function (result) {
         $.bootstrapLoading.end();
         let supplyChangeIDs = [],evaluate_gljs = [],rationNodes = [];
-        console.log(updateMap);
         for(let idKey in updateMap){
             let gljID = parseInt(idKey);
             let glj = me.getByID(gljID);
@@ -769,7 +1085,6 @@ ProjectGLJ.prototype.batchUpdatePrice = function (changeInfo,sheetName,callback)
             }
         }
     }
-    console.log(updateData);
     if(updateData.length > 0){
         $.bootstrapLoading.start();
         CommonAjax.post("/glj/batchUpdatePrices", updateData, function (result) {

+ 419 - 19
web/building_saas/main/js/views/material_calc_view.js

@@ -31,7 +31,7 @@ materialCalcObj = {
     freightSpread:null,
     freightSheet:null,
     freightDatas:[],
-    conveyanceOptions:["汽车","火车","船舶","马车","手推车","拖拉机"],
+    conveyanceOptions:["自办运输","汽车","火车","船舶","马车","手推车","拖拉机"],
     freightSetting:{
         header:[
             {headerName: "起讫地点", headerWidth: 80, dataCode: "start", dataType: "String"},
@@ -44,6 +44,8 @@ materialCalcObj = {
             {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: "left", dataType: "Number",getText:'forExp'},//,decimalField:"glj.unitPrice"
+            {headerName: "计算方式", headerWidth: 80, dataCode: "calcType", dataType: "String",cellType:"comboBox",options:["全国","内蒙古"]},
+            {headerName: "材料类型", headerWidth: 80, dataCode: "materialType", dataType: "String",cellType:"comboBox",options:["地方材料","外购材料","沥青、燃料等"]}
         ],
         view: {
             lockColumns: ["exp"],
@@ -52,8 +54,11 @@ materialCalcObj = {
         getText:{
             forExp:function (item) {
                 let material = materialCalcObj.getMaterialSelected();
+                //(单位运价×(1+运距增加率%)+装卸费单价×装卸次数+其它费用)×单位毛重×加权系数
+                if(item.conveyance == "自办运输" || item.calcType == "内蒙古") return `(${item.unitFreight}x(1+${item.freightIncreaseRate}%)+${item.unitLoadingFee}x${item.loadingTimes}+${item.otherFee})x${material.grossWeightCoe_n}x${item.weightCoe}`;
+
                 //(单位运价×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}`
+                return `(${item.unitFreight}x${item.kmDistance}x(1+${item.freightIncreaseRate}%)+${item.unitLoadingFee}x${item.loadingTimes}+${item.otherFee})x${material.grossWeightCoe_n}x${item.weightCoe}`;
             }
         }
     },
@@ -71,6 +76,26 @@ materialCalcObj = {
             colHeaderHeight:36
         }
     },
+    freightRationSpread:null,
+    freightRationSheet:null,
+    freightRations:[],
+    priceRations:[],
+    priceRationSpread:null,
+    priceRationSheet:null,
+    rationSetting:{
+        header:[
+            {headerName: "编号", headerWidth: 80, dataCode: "code", dataType: "String",formatter: "@"},
+            {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String"},
+            {headerName: "单位", headerWidth: 100, dataCode: "unit", dataType: "String"},
+            {headerName: "数量", headerWidth: 100, dataCode: "quantity", dataType: "String",hAlign: "right",validator:"number"},
+            {headerName: "高原取费类别", headerWidth: 100, dataCode: "feeType", dataType: "String",visible: false,cellType:"comboBox",options:[]}
+        ],
+        view: {
+            lockColumns: ["unit"],
+            colHeaderHeight:36
+        }
+
+    },
     initMaterialSpread:function () {
         this.materialSpread = SheetDataHelper.createNewSpread($("#materialCalcSheet")[0]);
         sheetCommonObj.spreadDefaultStyle(this.materialSpread);
@@ -101,12 +126,44 @@ materialCalcObj = {
             this.initRightClick("freightSheet",this.freightSpread)
         }
     },
+    initFreightRationSpread:function () {
+        this.freightRationSpread = SheetDataHelper.createNewSpread($("#freight_ration_sheet")[0]);
+        sheetCommonObj.spreadDefaultStyle(this.freightRationSpread);
+        this.freightRationSheet = this.freightRationSpread.getSheet(0);
+        sheetCommonObj.initSheet(this.freightRationSheet, this.rationSetting, 30);
+        this.freightRationSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onFreightRationValueChange);
+        this.freightRationSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onRationSelectionChange);
+        this.freightRationSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onFreightRationEditStarting);
+        this.freightRationSheet.name('freight_ration');
+        if(projectReadOnly){
+            disableSpread(this.freightRationSpread);
+        }else {
+            this.initRightClick("freight_ration_sheet",this.freightRationSpread);
+        }
+    },
+    initPriceRationSpread:function () {
+        this.priceRationSpread = SheetDataHelper.createNewSpread($("#price_ration_sheet")[0]);
+        sheetCommonObj.spreadDefaultStyle(this.priceRationSpread);
+        this.priceRationSheet = this.priceRationSpread.getSheet(0);
+        sheetCommonObj.initSheet(this.priceRationSheet, this.rationSetting, 30);
+        this.priceRationSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onPriceRationValueChange);
+        this.priceRationSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onRationSelectionChange);
+        this.priceRationSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onPriceRationEditStarting);
+
+        this.priceRationSheet.name('price_ration');
+        if(projectReadOnly){
+            disableSpread(this.priceRationSpread);
+        }else {
+            this.initRightClick("price_ration_sheet",this.priceRationSpread);
+        }
+    },
     initPriceSpread:function(){
         this.priceSpread = SheetDataHelper.createNewSpread($("#priceSheet")[0]);
         sheetCommonObj.spreadDefaultStyle(this.priceSpread);
         this.priceSheet = this.priceSpread.getSheet(0);
         sheetCommonObj.initSheet(this.priceSheet, this.priceSetting, 30);
         this.priceSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onPriceValueChange);
+        this.priceSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onPriceSelectionChange);
         this.priceSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onPriceEditStarting);
         this.priceSheet.name('price_calc');
         if(projectReadOnly){
@@ -127,6 +184,30 @@ materialCalcObj = {
         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);
+        this.refreshRationView();
+    },
+    showFreightRationDatas:function (freight) {
+        let sel = this.freightRationSheet.getSelections()[0];
+        let oldData = sel.row<this.freightRations.length?this.freightRations[sel.row]:"";
+        this.freightRationSheet.setRowCount(0);
+        this.freightRations = freight.rations?freight.rations:[];
+        sheetCommonObj.showData(this.freightRationSheet, this.rationSetting,this.freightRations);
+        this.freightRationSheet.setRowCount(this.freightRations+20);
+        sel.row =  oldData?_.findIndex(this.freightRations,{'ID':oldData.ID}):sel.row ;
+        this.freightRationSheet.setSelection(sel.row==-1?0:sel.row,sel.col,sel.rowCount,sel.colCount);
+        this.refreshAssView();
+    },
+    showPriceRationDatas:function () {
+        let price = this.getSelectedPrice();
+        let sel = this.priceRationSheet.getSelections()[0];
+        let oldData = sel.row<this.priceRations.length?this.priceRations[sel.row]:"";
+        this.priceRationSheet.setRowCount(0);
+        this.priceRations = price&&price.rations?price.rations:[];
+        sheetCommonObj.showData(this.priceRationSheet, this.rationSetting,this.priceRations);
+        this.priceRationSheet.setRowCount(this.priceRations+20);
+        sel.row =  oldData?_.findIndex(this.priceRations,{'ID':oldData.ID}):sel.row ;
+        this.priceRationSheet.setSelection(sel.row==-1?0:sel.row,sel.col,sel.rowCount,sel.colCount);
+        this.refreshAssView();
     },
     showMaterialCalcDatas:function(){
         let sel = this.materialSheet.getSelections()[0];
@@ -148,17 +229,21 @@ materialCalcObj = {
         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);
-
+        this.showPriceRationDatas();
     },
     showDatas:function(){
         if(!$('#materialCalcSheet').is(':visible')) return;
         if(!this.materialSpread) this.initMaterialSpread();
         if(!this.freightSpread) this.initFreightSpread();
         if(!this.priceSpread) this.initPriceSpread();
+        if(!this.freightRationSpread) this.initFreightRationSpread();
+        if(!this.priceRationSpread) this.initPriceRationSpread();
+        let h =_.find(this.rationSetting.header,{"dataCode":"feeType"});
+        if(h)  h.options = projectObj.project.calcProgram.compiledTemplateNames;
         this.showMaterialCalcDatas();
         this.showFreightDatas();
         this.showPriceDatas();
-        projectGljObject.refreshSubViews();
+        // 先试试看注释有没有bug  projectGljObject.refreshSubViews();
     },
     getMaterialSelected:function () {
         let sel = this.materialSheet.getSelections()[0];
@@ -220,8 +305,16 @@ materialCalcObj = {
         }
     },
     onFreightSelectionChange:function (sender,args) {
+        materialCalcObj.refreshRationView();
         args.sheet.repaint();
     },
+    onRationSelectionChange:function(sender,args){
+        materialCalcObj.refreshAssView(args);
+        args.sheet.repaint();
+    },
+    onPriceSelectionChange:function (sender,args) {
+        materialCalcObj.showPriceRationDatas();
+    },
     onPriceEditStarting:function (sender,args) {
         let me = materialCalcObj;
         if(!me.getMaterialSelected()){
@@ -232,6 +325,41 @@ materialCalcObj = {
         let me = materialCalcObj;
         if(!me.getMaterialSelected()){
             args.cancel = true;
+        }else {
+            let freigth = me.freightDatas[args.row];
+            let dataCode = me.freightSetting.header[args.col].dataCode;
+            if(dataCode == "calcType" || dataCode=="materialType"){
+                if(!freigth){
+                    args.cancel = true;
+                }else if(dataCode == "materialType" && freigth.calcType !="内蒙古"){//不是内蒙古的情况下,下拉框不可编辑
+                    args.cancel = true;
+                }
+            }
+            if(freigth){
+                if(dataCode == "kmDistance" || dataCode=="unitLoadingFee" || dataCode =="loadingTimes" || dataCode == "freightIncreaseRate"){
+                    if(freigth.conveyance == "自办运输") args.cancel = true;
+                }
+                if(dataCode == "unitFreight"){
+                    if(freigth.rations && freigth.rations.length > 0) args.cancel = true;
+                    if(freigth.calcType == "内蒙古") args.cancel = true;
+                }
+            }
+        }
+    },
+    onFreightRationEditStarting:function (sender,args) {
+        materialCalcObj.onRationEditStarting(sender,args,"freight");
+    },
+    onPriceRationEditStarting:function (sender,args) {
+       materialCalcObj.onRationEditStarting(sender,args,"price");
+    },
+    onRationEditStarting:function(sender,args,type){
+        let me = materialCalcObj;
+        let dataCode = me.rationSetting.header[args.col].dataCode;
+        let datas = type == "freight"?me.freightRations:me.priceRations;
+        if(args.row > datas.length){
+            args.cancel = true;
+        }else if(args.row == datas.length && dataCode != "code"){
+            args.cancel = true;
         }
     },
     onMaterialEditStarting:function (sender,args) {
@@ -263,7 +391,27 @@ materialCalcObj = {
         doc[dataCode] = value;
         projectObj.project.projectGLJ.updateMaterialCalc([{id:recode.id,doc:doc}]);
     },
+    getDefualtCalcType:function () {
+      return "全国";
+    },
 
+    getNewFreightData:function (material) {
+         let newData = {
+             ID: uuid.v1(),
+             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
+         }
+        return newData;
+    },
     onFreightValueChange:function (sender,args) {
         let me = materialCalcObj;
         let dataCode = me.freightSetting.header[args.col].dataCode;
@@ -274,32 +422,113 @@ materialCalcObj = {
             me.showDatas();
             return;
         }
-        if(dataCode != 'start'&&dataCode != 'conveyance'){
+        if(dataCode != 'start'&&dataCode != 'conveyance'&&dataCode != 'calcType'&&dataCode != 'materialType'){
             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
-            };
+            let newData = me.getNewFreightData(material);
             newData[dataCode] = value;
+            newData.calcType = me.getDefualtCalcType();
+            if(newData.calcType == "内蒙古") newData.materialType = "地方材料";
             projectObj.project.projectGLJ.addFreightCalc([newData],material.id);
         }else {//修改
             let recode = me.freightDatas[args.row];
             if(recode[dataCode] == value) return;
             let doc = {};
             doc[dataCode] = value;
+            if(dataCode == "conveyance"){//如果运输方式从自办运输切换成其它的东西时,要把底下挂的定额和定额工料机都清空
+                if(args.oldValue == "自办运输"){
+                    doc["rations"] = [];
+                    doc["ration_gljs"] = [];
+                }
+                if(value == "自办运输"){//当运输工具下拉选择“自办运输”时,“Km运距”、“装卸费单价”、“装卸次数”、“运价增加率(%)”列数据归0,且灰选不可编辑
+                    doc["kmDistance"] = '0';
+                    doc["unitLoadingFee"] ='0';
+                    doc["loadingTimes"] = '0';
+                    doc["freightIncreaseRate"] = '0';
+                }
+            }
+            if(dataCode == "calcType"){
+                if(value == "全国") doc["materialType"] = "";
+                if(value == "内蒙古"){
+                    doc["materialType"] = "地方材料";
+                    doc["unitFreight"] = me.calcNeiMengUnitFreight(recode.kmDistance,"地方材料");
+                }
+            }
+            if(recode.calcType == "内蒙古"){
+                if(dataCode == "materialType") doc["unitFreight"] = me.calcNeiMengUnitFreight(recode.kmDistance,value);
+                if(dataCode == "kmDistance") doc["unitFreight"] = me.calcNeiMengUnitFreight(value,recode.materialType);
+            }
             projectObj.project.projectGLJ.updateFreightCalc([{ID:recode.ID,doc:doc}],material.id);
         }
+    },
+    calcNeiMengUnitFreight:function (kmDistance,materialType) {
+        if(!kmDistance||kmDistance == '0') return "0";
+        let decimal = getDecimal("glj.unitPrice");
+        let baseMap = {"地方材料":6,"外购材料":13,"沥青、燃料等":19};//"地方材料","外购材料","沥青、燃料等"
+        let baseFreight = baseMap[materialType];
+        kmDistance =  scMathUtil.roundForObj(kmDistance,decimal);
+        //用截取的方式,一段段取值
+        let less = kmDistance - 5;//kmDistance <= 5 这段
+        if(less <= 0) return baseFreight+"" ;  //kmDistance <= 5 的时候直接取baseFreight
+
+         //5< kmDistance <= 15  每增运1km 则增加0.6
+        less = less - 10;
+        if(less <=0)  return scMathUtil.roundForObj(baseFreight + scMathUtil.roundForObj((less + 10) * 0.6,6),decimal)+"";//baseFreight + (less + 10) * 0.6;
+        baseFreight = baseFreight + 10 * 0.6; //累加5到15这一段的运费;
+
+         //15< kmDistance <= 100  每增运1km 则增加0.45
+        less = less - 85;
+        if(less <=0) return scMathUtil.roundForObj(baseFreight + scMathUtil.roundForObj((less + 85)*0.45,6),decimal)+"";//baseFreight + (less + 85)*0.45;
+        baseFreight = scMathUtil.roundForObj(baseFreight + scMathUtil.roundForObj(85*0.45,6),6) ;  //累加15到100这一段的运费;
+        return scMathUtil.roundForObj(baseFreight + scMathUtil.roundForObj(less * 0.35,6),decimal)+""; // >100 的所有部分每增运1km 则增加0.35  baseFreight + less * 0.35
+    },
+    onFreightRationValueChange:function (sender,args) {
+        materialCalcObj.onRationValueChange(sender,args,"freight");
+    },
+    onPriceRationValueChange:function (sender,args) {
+        materialCalcObj.onRationValueChange(sender,args,"price");
+    },
+    onRationValueChange:function (sender,args,type) {
+        let me = materialCalcObj;
+        let dataCode = me.rationSetting.header[args.col].dataCode;
+        let value = args.newValue;
+        let parent = type == "freight"? me.getSelectedFreight():me.getSelectedPrice();
+        let dataList = type == "freight"?me.freightRations:me.priceRations;
+        if(dataCode == "code" && args.row >= dataList.length) {//新增
+            if(parent) projectObj.project.projectGLJ.addMaterialRation(value,type,parent.ID,parent.connect_key);
+        }else { //修改
+            let ration = dataList[args.row];
+            if (value&&!sheetCommonObj.checkData(args.col,me.rationSetting,value)) {
+                alert('输入的数据类型不对,请重新输入!');
+                return   type == "freight"?me.showFreightRationDatas(parent):me.showPriceRationDatas();
+            }
+            if(dataCode == 'quantity'){
+                if(value){
+                    value = scMathUtil.roundForObj(parseFloat(value) / FilterNumberFromUnit(ration.unit),getDecimal("ration.quantity"))+"";
+                }else {
+                    value = "0";
+                }
+            }
+            let datas = {parentID:parent.ID,rationID:ration.ID,type:type,actionType:"update",field:dataCode,value:value};
+            if(dataCode == "code"){ //这时是替换,替换比较麻烦
+                datas.code = value;
+                datas.row = args.row;
+                let libIDs = rationLibObj.getStdRationLibIDs();
+                let defaultLibID = rationLibObj.getDefaultStdRationLibID();
+                let selectedLib =  sessionStorage.getItem("stdRationLib");
+                selectedLib&&selectedLib!='undefined'?libIDs.unshift(selectedLib):libIDs.unshift(defaultLibID);
+                datas.userID = userID;
+                datas.defaultLibID = defaultLibID;
+                datas.rationRepIds = libIDs;
+                datas.quantityDecimal = getDecimal("ration.quantity");
+                datas.connect_key =  parent.connect_key;
+                datas.projectID = projectObj.project.ID();
+                datas.rations = parent.rations;
+                datas.ration_gljs = parent.ration_gljs;
+            }
+            projectObj.project.projectGLJ.updateMaterialRation(datas);
+        }
 
     },
     onPriceValueChange:function(sender,args){
@@ -318,6 +547,7 @@ materialCalcObj = {
         }
         if(args.row >= me.priceDatas.length){//新增
             let newData = {
+                ID:uuid.v1(),
                 supplyLocation:"",
                 supplyPrice:'0',
                 coe:'1',
@@ -354,6 +584,14 @@ materialCalcObj = {
             projectObj.project.projectGLJ.deleteFreightCalc(record.ID,material.id);
         }
     },
+    deleteRation:function (row,type) {
+        let me = this;
+        let parent = type == "freight"?me.getSelectedFreight():me.getSelectedPrice();
+        let ration =  type == "freight"?me.freightRations[row]:me.priceRations[row];
+        let datas = {parentID:parent.ID,rationID:ration.ID,type:type,actionType:"delete"};
+        projectObj.project.projectGLJ.updateMaterialRation(datas);
+
+    },
     getSideResize: function () {
         let rg_sideResizeEles = {};
         rg_sideResizeEles.eleObj = {
@@ -379,19 +617,39 @@ materialCalcObj = {
                     me.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
             },
             items: {
+                "insertFreight":{
+                    name: "内蒙古计算",
+                    icon: 'fa-sign-in',
+                    visible:function () {
+                        return id == "freightSheet";
+                    },
+                    disabled: function (){
+                       let material = me.getMaterialSelected();
+                       return !material;
+                    },
+                    callback:function () {
+                        $("#insertNeimengDiv").modal("show");
+                    }
+
+                },
+
                 "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;
+                        if(id == "freight_ration_sheet") return me.rightClickTarget.row >= me.freightRations.length;
+                        if(id == "price_ration_sheet") return me.rightClickTarget.row >= me.priceRations.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);
+                        if (id == "freightSheet") me.deleteFreightCalc(row);
+                        if (id == "freight_ration_sheet") me.deleteRation(row,"freight");
+                        if (id == "price_ration_sheet") me.deleteRation(row,"price");
                     }
                 }
             }
@@ -403,7 +661,110 @@ materialCalcObj = {
         SlideResize.loadHorizonWidth(mr_sideResizeEles.eleObj.module,
             [mr_sideResizeEles.eleObj.resize], [mr_sideResizeEles.eleObj.left, mr_sideResizeEles.eleObj.right],null,2);
         $("#spreadTabDiv").width( $('#calcDiv').width() - mr_sideResizeEles.eleObj.resize.width() - 32)
+    },
+    refreshRationView:function () {
+        let freight = this.getSelectedFreight();
+        let hide = true;
+        let stats = $("#freight_ration").is(':visible');
+        if(freight && freight.conveyance == "自办运输"){
+            this.showFreightRationDatas(freight);
+            $("#freightSheet").css("height","50%");
+            $("#freight_ration").show();
+            hide = false;
+        }
+        if(hide){
+            $("#freightSheet").css("height","100%");
+            $("#freight_ration").hide();
+        }
+        if(stats != $("#freight_ration").is(':visible')){//状态改变了才刷新
+            this.freightSpread.refresh();
+            this.freightRationSpread.refresh();
+        }
+    },
+    refreshAssView:function () {
+        let me = materialCalcObj;
+        let sheet = $('#freightSheet').is(':visible')?me.freightRationSheet:me.priceRationSheet;
+        let preString = $('#freightSheet').is(':visible')?"freight":"price";
+        let show = false;
+        let ass = null;
+        let ration = me.getSelectedRation();
+        let stats = $(`#${preString}_ration_ass`).is(':visible');
+        if(ration && ration.rationAssList){
+            for(let r of ration.rationAssList){
+                if(r.name == "运距m"){//辅助定额只处理运距的情况,其它的都忽略
+                    show = true;
+                    ass = r;
+                }
+            }
+        }
+        if(show){
+            $(`#${preString}_ration_sheet`).addClass("material-ration-left");
+            $(`#${preString}_ration_ass`).addClass("material-ass");
+            $(`#${preString}_ass_value`).val(ass.actualValue);
+            $(`#${preString}_ration_ass`).show();
+        }else {
+            $(`#${preString}_ration_sheet`).removeClass("material-ration-left");
+            $(`#${preString}_ration_ass`).removeClass("material-ass");
+            $(`#${preString}_ration_ass`).hide();
+        }
+       if(stats !=  $(`#${preString}_ration_ass`).is(':visible')) sheet.parent.refresh();//状态改变了才刷新
+    },
+    updateMaterialRationAss:function (value,ele) {//to do 同步修改定额工料机的消耗量
+        let parent = this.getSelectedRationParent(),ration = this.getSelectedRation();
+        let replaceList = [];
+        if(value && !number_util.isNum(value)){
+            alert("输入的数据类型不对,请重新输入!");
+            let a = _.find(ration.rationAssList,{'name':"运距m"});
+            if(a)ele.val(a.actualValue);
+        }
+        for(let ass of ration.rationAssList){
+            if(ass.name == "运距m"){
+                ass.actualValue = value?scMathUtil.roundForObj(value,2):ass.stdValue;
+            }
+            replaceList.push(value);
+        }
+        let name = ration.caption;
+        for(let re of replaceList){
+            name = name.replace('%s',re);
+        }
+        let type =  $('#freightSheet').is(':visible')?"freight":"price";
+        //let ration_glj =
+        let datas = {parentID:parent.ID,rationID:ration.ID,type:type,actionType:"update",field:"name",value:name,ext:{rationAssList:ration.rationAssList}};
+
+        let ration_gljs = projectObj.project.projectGLJ.calcMaterialAssQuantity(parent,ration,ration.rationAssList);
+        if(ration_gljs.length > 0) datas.ration_gljs = ration_gljs;
+
+        projectObj.project.projectGLJ.updateMaterialRation(datas);
+    },
+    getSelectedRation:function () {
+        if($('#freightSheet').is(':visible')){
+            return this.getSelectedRecode(this.freightRationSheet,this.freightRations);
+        }else {
+            return this.getSelectedRecode(this.priceRationSheet,this.priceRations);
+        }
+    },
+    getSelectedRationParent:function () {
+        if($('#freightSheet').is(':visible')){
+            return this.getSelectedFreight();
+        }else {
+            return this.getSelectedRecode(this.priceSheet,this.priceDatas);
+        }
+    },
+    getSelectedFreight:function(){
+        return this.getSelectedRecode(this.freightSheet,this.freightDatas);
+    },
+    getSelectedPrice:function () {
+       return this.getSelectedRecode(this.priceSheet,this.priceDatas)
+    },
+    getSelectedRecode:function (sheet,datas) {
+        let sel = sheet.getSelections()[0];
+        let srow = sel.row == -1||sel.row == ""?0:sel.row;
+        if(gljUtil.isDef(srow) && datas.length>srow){
+            return datas[srow];
+        }
+        return null;
     }
+
 };
 $(function () {
     $("#calc-nav").on('shown.bs.tab', function () {
@@ -415,6 +776,45 @@ $(function () {
         materialCalcObj.showPriceDatas();
         projectGljObject.refreshSubViews();
     });
+    $(".ration_ass_value").change(function () {
+        let me = materialCalcObj;
+        me.updateMaterialRationAss($(this).val(),$(this));
+    });
+    $('#calcCoeDiv').on('show.bs.modal', function () {
+        $("#assistProductionFeeRate").val(scMathUtil.roundForObj(projectObj.project.projectGLJ.datas.constData.assistProductionFeeRate,getDecimal("feeRate")));
+    })
+    $("#calcCoeConfirm").click(function () {
+        let feeRate =  $("#assistProductionFeeRate").val();
+        if(!number_util.isNum(feeRate)){
+            alert("输入的数据类型不对,请重新输入!");
+           return $("#assistProductionFeeRate").val(scMathUtil.roundForObj(projectObj.project.projectGLJ.datas.constData.assistProductionFeeRate,getDecimal("feeRate")));
+        }
+        feeRate = scMathUtil.roundForObj(feeRate,getDecimal("feeRate"));
+        $("#calcCoeDiv").modal("hide");
+        projectObj.project.projectGLJ.changeAssistProductionFeeRate(feeRate);
+    });
+
+    $("#insertFreightconfirm").click(function () {
+        let me = materialCalcObj;
+        let material = me.getMaterialSelected();
+        let newData = me.getNewFreightData(material);
+        let start = $("#freight_start").val();
+        let kmDistance = $("#freight_kmDistance").val();
+        let materialType = $("#freight_materialType").val();
+        if(!number_util.isNum(kmDistance)){
+            alert("运输距离数据类型不对,请重新输入!");
+            return ;
+        }
+        kmDistance = scMathUtil.roundForObj(kmDistance,getDecimal("glj.unitPrice"))+'';
+        newData.start = start;
+        newData.kmDistance = kmDistance;
+        newData.materialType = materialType;
+        newData.calcType = "内蒙古";
+        newData.unitFreight = me.calcNeiMengUnitFreight(kmDistance,materialType);
+        $("#insertNeimengDiv").modal("hide");
+        projectObj.project.projectGLJ.addFreightCalc([newData],material.id);
+    })
+
 });
 
 let mr_sideResizeEles = materialCalcObj.getSideResize();

+ 6 - 3
web/building_saas/main/js/views/project_glj_view.js

@@ -836,8 +836,8 @@ projectGljObject={
         }
         gljOprObj.refreshView();
     },
-    onUnitFileChange:function (data) {
-        projectObj.project.markUpdateProject({projectID:projectObj.project.ID(),'unitFileID':socketObject.getUnitFileRoomID()},"unitFile",function(){
+    onUnitFileChange:function (isInclude) { //include用来标计是否排除本身, true时,不排除本身
+        projectObj.project.markUpdateProject({projectID:projectObj.project.ID(),'unitFileID':socketObject.getUnitFileRoomID(),isInclude:isInclude},"unitFile",function(){
             //socket.emit('unitFileChangeNotify', JSON.stringify(data));
             socket.emit('unitFileChangeNotify', {projectID:projectObj.project.ID(),userID:userID,'unitFileID':socketObject.getUnitFileRoomID()});
         });
@@ -1156,6 +1156,8 @@ projectGljObject={
         if($('#materialCalcSheet').is(':visible')&&materialCalcObj.materialSpread) materialCalcObj.materialSpread.refresh();
         if($('#freightSheet').is(':visible')&&materialCalcObj.freightSpread) materialCalcObj.freightSpread.refresh();
         if($('#priceSheet').is(':visible')&&materialCalcObj.priceSpread) materialCalcObj.priceSpread.refresh();
+        if($('#freight_ration').is(':visible')&&materialCalcObj.freightRationSpread) materialCalcObj.freightRationSpread.refresh();
+        if($('#price_ration').is(':visible')&&materialCalcObj.priceRationSpread) materialCalcObj.priceRationSpread.refresh();
     }
 };
 
@@ -1186,7 +1188,8 @@ function loadProjectGljSize() {
     let pojGljResizeEles = getProjectResizeEles();
     SlideResize.loadVerticalHeight(pojGljResizeEles.eleObj.module, pojGljResizeEles.eleObj, pojGljResizeEles.limit, function () {
         me.projectGljSpread?me.projectGljSpread.refresh():'';
-        me.refreshSubViews()
+        materialCalcObj.initTabWidth();
+        me.refreshSubViews();
     });
 }
 //从其他建设项目中复制中,建设项目的文件层次结构名称和顺序

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

@@ -3347,3 +3347,7 @@ $('#calcBaseFeeRateConf').click(function () {
 $('#menu_calc_program_manage').click(function () {
     $('#tab_calc_program_manage').click();
 });
+
+$("#mainNav").on("click"," li a",function(e){
+    projectObj.project.projectMarkChecking();
+});

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

@@ -127,7 +127,7 @@ let subObj = {
         this.initGljSubTab();
         zmhs_obj.showDatas();
         if (gljOprObj.activeTab !== gljOprObj.preActiveTab) {   //提高焦点变换性能 2019年4月15日
-            refreshSubSpread();
+            if($("#subItems").is(':visible')) refreshSubSpread();
         }
         if(this.firstOpen == true){
             $("#zmhs_toogle").click();

+ 8 - 0
web/over_write/js/neimeng_2019.js

@@ -246,4 +246,12 @@ if (typeof baseFigureTemplate !== 'undefined' && baseFigureTemplate.budget) {
             return (installFee * (Math.pow(1 + costGrowthRate, growthPeriod - 1) - 1)).toDecimal(decimalObj.bills.totalPrice);
         },
     };
+}
+
+if(typeof materialCalcObj !== 'undefined' && materialCalcObj.rationSetting){
+    let h =_.find(materialCalcObj.rationSetting.header,{"dataCode":"feeType"});
+    if(h) h.visible = true;
+    materialCalcObj.getDefualtCalcType = function () {
+        return "内蒙古";
+    }
 }