Bladeren bron

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

Chenshilong 7 jaren geleden
bovenliggende
commit
5af39aa7b2
32 gewijzigde bestanden met toevoegingen van 667 en 149 verwijderingen
  1. 3 5
      Dockerfile
  2. 3 5
      Dockerfile_qa
  3. 15 0
      Dockerfile_test
  4. 19 1
      modules/fee_rates/controllers/fee_rates_controller.js
  5. 9 2
      modules/fee_rates/facade/fee_rates_facade.js
  6. 1 6
      modules/fee_rates/routes/fee_rates_route.js
  7. 2 1
      modules/glj/models/glj_list_model.js
  8. 2 0
      modules/glj/models/schemas/unit_price.js
  9. 1 0
      modules/glj/models/unit_price_model.js
  10. 1 1
      modules/main/models/bills.js
  11. 6 3
      modules/main/models/proj_setting_model.js
  12. 20 3
      modules/main/models/project_consts.js
  13. 15 3
      modules/main/models/schemas/proj_setting.js
  14. 2 0
      modules/ration_glj/facade/ration_glj_facade.js
  15. 1 0
      modules/ration_glj/models/ration_glj.js
  16. 2 0
      modules/ration_glj/models/ration_glj_temp.js
  17. 25 6
      modules/reports/facade/rpt_tpl_data_facade.js
  18. 254 0
      modules/reports/util/rpt_construct_data_util.js
  19. 0 66
      modules/reports/util/rpt_data_util.js
  20. 14 1
      public/web/rpt_value_define.js
  21. 126 0
      test/unit/reports/test_tpl_09_1.js
  22. 3 0
      web/building_saas/glj/js/project_glj_spread.js
  23. 18 2
      web/building_saas/main/html/main.html
  24. 26 9
      web/building_saas/main/js/calc/bills_calc.js
  25. 1 0
      web/building_saas/main/js/calc/calc_fees.js
  26. 27 3
      web/building_saas/main/js/models/fee_rate.js
  27. 13 8
      web/building_saas/main/js/models/project.js
  28. 2 0
      web/building_saas/main/js/models/ration_glj.js
  29. 30 12
      web/building_saas/main/js/views/fee_rate_view.js
  30. 1 0
      web/building_saas/main/js/views/glj_view.js
  31. 4 1
      web/building_saas/main/js/views/main_tree_col.js
  32. 21 11
      web/building_saas/main/js/views/project_view.js

+ 3 - 5
Dockerfile

@@ -1,10 +1,8 @@
-FROM server:3.0
+FROM costbase:latest
 
-COPY . ConstructionCost
+WORKDIR /home/ConstructionCost
 
-WORKDIR ConstructionCost
-
-RUN cnpm install -g gulp
+RUN git pull http://192.168.1.12:3000/SmartCost/ConstructionCost master
 
 RUN cnpm install
 

+ 3 - 5
Dockerfile_qa

@@ -1,10 +1,8 @@
-FROM server:3.0
+FROM costbase:latest
 
-COPY . ConstructionCost
+WORKDIR /home/ConstructionCost
 
-WORKDIR ConstructionCost
-
-RUN cnpm install -g gulp
+RUN git pull http://192.168.1.12:3000/SmartCost/ConstructionCost master
 
 RUN cnpm install
 

+ 15 - 0
Dockerfile_test

@@ -0,0 +1,15 @@
+FROM costbase:latest
+
+WORKDIR /home/ConstructionCost
+
+RUN git pull http://192.168.1.12:3000/SmartCost/ConstructionCost master
+
+RUN cnpm install
+
+RUN gulp build
+
+EXPOSE 6060
+
+ENV NODE_ENV=qa
+
+ENTRYPOINT babel-node server.js

+ 19 - 1
modules/fee_rates/controllers/fee_rates_controller.js

@@ -53,7 +53,8 @@ module.exports = {
     checkFeeRateName:checkFeeRateName,
     getChangeInfo:getChangeInfo,
     changeFeeRateFileFromCurrent:changeFeeRateFileFromCurrent,
-    changeFeeRateFileFromOthers:changeFeeRateFileFromOthers
+    changeFeeRateFileFromOthers:changeFeeRateFileFromOthers,
+    setFeeRateToBill:setFeeRateToBill
 }
 
 function libNames(req, res) {
@@ -175,4 +176,21 @@ async function changeFeeRateFileFromOthers(req, res) {
         result.message = err.message;
     }
     res.json(result);
+}
+
+
+async function setFeeRateToBill(req,res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        let uresult= await feeRateFacde.setFeeRateToBill(data);
+        console.log(uresult);
+    }catch (err){
+        console.log(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
 }

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

@@ -7,7 +7,7 @@ let mongoose = require('mongoose');
 let feeRateModel = mongoose.model('fee_rates');
 let feeRateFileModel = mongoose.model('fee_rate_file');
 let std_fee_rate_lib_model = mongoose.model('std_fee_rate_libs');
-let project_feerate_temp = mongoose.model('project_feerate_temp');
+let billModel=require('../../main/models/bills');//mongoose.model('bills');
 let projectsModel = require("../../pm/models/project_schema");
 let consts = require('../../main/models/project_consts');
 let _=require("lodash");
@@ -26,7 +26,8 @@ module.exports={
     changeFeeRateFileFromCurrent:changeFeeRateFileFromCurrent,
     changeFeeRateFileFromOthers:changeFeeRateFileFromOthers,
     newFeeRateFile:newFeeRateFile,
-    getFeeRatesByProject:getFeeRatesByProject
+    getFeeRatesByProject:getFeeRatesByProject,
+    setFeeRateToBill:setFeeRateToBill
 };
 let operationMap={
     'ut_create':create_fee_rate,
@@ -346,6 +347,12 @@ async function getFeeRatesByProject(rootProjectID) {
        return feeRates;
 }
 
+async function setFeeRateToBill(data){
+    data=JSON.parse(data);
+    let result  = await billModel.model.findOneAndUpdate(data.query,data.doc);
+    return result
+}
+
 async function changeFeeRateFileFromCurrent(jdata){
     let data = JSON.parse(jdata);
     let newFeeRateFile=data.newFeeRateFile;

+ 1 - 6
modules/fee_rates/routes/fee_rates_route.js

@@ -18,12 +18,7 @@ module.exports = function (app) {
     frRouter.post('/getChangeInfo', frController.getChangeInfo);
     frRouter.post('/changeFeeRateFileFromCurrent', frController.changeFeeRateFileFromCurrent);
     frRouter.post('/changeFeeRateFileFromOthers', frController.changeFeeRateFileFromOthers);
-
-    //
-/*    frRouter.post('/getLibNames', frController.libNames);
-    frRouter.post('/getLibFeeRates', frController.libFeeRates);
-    frRouter.post('/getProjectFeeRates', frController.projectFeeRates);
-    frRouter.post('/updateProjectFeeRate', frController.projectFeeUpdateRate);*/
+    frRouter.post('/setFeeRateToBill', frController.setFeeRateToBill);
 
     app.use('/feeRates',frRouter);
 }

+ 2 - 1
modules/glj/models/glj_list_model.js

@@ -482,7 +482,8 @@ class GLJListModel extends BaseModel {
                 code: tmp.code,
                 name: tmp.name,
                 unit_price_file_id: unitPriceFileId,
-                type: tmp.gljType
+                type: tmp.gljType,
+                short_name: tmp.shortName === undefined ? '' : tmp.shortName,
             };
             unitPriceInsertData.push(unitPriceData);
         }

+ 2 - 0
modules/glj/models/schemas/unit_price.js

@@ -28,6 +28,8 @@ let modelSchema = {
     },
     // 类型
     type: Number,
+    // 类型简称
+    short_name: String,
     // 单价文件表id
     unit_price_file_id: Number,
 };

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

@@ -115,6 +115,7 @@ class UnitPriceModel extends BaseModel {
             unit_price_file_id: unitPriceFileId,
             name: data.name,
             type: data.type,
+            short_name: data.shortName !== undefined ? data.shortName : ''
         };
 
         let addPriceResult = await this.add(insertData);

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

@@ -26,7 +26,7 @@ let billsSchema = new Schema({
     name: String,
     unit: String,
     quantity: String, // Decimal
-    feeRateID:String,
+    feeRateID:Number,
     feeRate:String,
     isFromDetail:{type: Number,default:0},//1 true 0 false
     programID: Number,

+ 6 - 3
modules/main/models/proj_setting_model.js

@@ -3,7 +3,7 @@
  */
 
 let baseModel = require('./base_model');
-import {default as projSettingSchema, collectionName as collectionName, billsCalcModeConst as billsCalcModeConst} from "./schemas/proj_setting";
+import {default as projSettingSchema, collectionName as collectionName, settingConst as settingConst} from "./schemas/proj_setting";
 
 class projSettingModel extends baseModel {
 
@@ -17,9 +17,12 @@ class projSettingModel extends baseModel {
             if (!err) {
                 let data = JSON.parse(JSON.stringify(result));
                 if (!data.billsCalcMode) {
-                    data.billsCalcMode = billsCalcModeConst.rationContent;
+                    data.billsCalcMode = settingConst.billsCalcMode.rationContent;
                 }
-                data.billsCalcModeConst = billsCalcModeConst;
+                if (!data.zanguCalcMode) {
+                    data.zanguCalcMode = settingConst.zanguCalcMode.common;
+                }
+                data.settingConst = settingConst;
                 callback(0, collectionName, data);
             } else {
                 callback(1, '查询数据失败。', null);

+ 20 - 3
modules/main/models/project_consts.js

@@ -1,7 +1,7 @@
 /**
  * Created by jimiz on 2017/4/18.
  */
-var projectConst = {
+let projectConst = {
     BILLS: 'bills',
     RATION: 'ration',
     GLJ: 'GLJ',
@@ -19,10 +19,27 @@ var projectConst = {
     CALC_PROGRAM:'calc_program'
 };
 
-var commonConst = {
+let projectConstList = [
+    'bills',
+    'ration',
+    'GLJ',
+    'ration_glj',
+    'ration_coe',
+    'ration_ass',
+    'quantity_detail',
+    'projectGLJ',
+    'GLJList',
+    'unitPriceFile',
+    'properties',
+    'volume_price',
+    'feeRate',
+    'labour_coe'
+];
+
+let commonConst = {
     UT_UPDATE: 'ut_update',
     UT_CREATE: 'ut_create',
     UT_DELETE: 'ut_delete'
 };
 
-module.exports = {projectConst: projectConst, commonConst: commonConst};
+module.exports = {projectConst: projectConst, commonConst: commonConst, projectConstList: projectConstList};

+ 15 - 3
modules/main/models/schemas/proj_setting.js

@@ -5,8 +5,16 @@
 let mongoose = require("mongoose");
 let Schema = mongoose.Schema;
 let collectionName = 'proj_setting';
+let settingConst = {
+    billsCalcMode: {
+        rationContent: 0, rationPrice: 1, rationPriceConverse: 2, billsPrice: 3
+    },
+    zanguCalcMode: {
+        common: 0, gatherMaterial: 1
+    }
+}
 let billsCalcModeConst = {
-    rationContent: 0, rationPrice: 1, rationPriceConverse: 2, billsPrice: 3
+    
 };
 let projSettingSchema = {
     projectID: Number,
@@ -17,9 +25,13 @@ let projSettingSchema = {
     },
     billsCalcMode: {
         type: Number,
-        default: billsCalcModeConst.rationContent
+        default: settingConst.billsCalcMode.rationContent
         // rationContent = 0, rationPrice = 1, rationPriceConverse = 2, billsPrice = 3
+    },
+    zanguCalcMode: {
+        type: Number,
+        default: settingConst.zanguCalcMode.common
     }
 };
 let model = mongoose.model(collectionName, new Schema(projSettingSchema, {versionKey: false, collection: collectionName}));
-export {model as default, collectionName as collectionName, billsCalcModeConst as billsCalcModeConst};
+export {model as default, collectionName as collectionName, settingConst as settingConst};

+ 2 - 0
modules/ration_glj/facade/ration_glj_facade.js

@@ -157,6 +157,7 @@ function createNewRecord(ration_glj) {
     newRecoed.from=ration_glj.from?ration_glj.from:undefined;
     newRecoed.createType=ration_glj.createType?ration_glj.createType:undefined;
     newRecoed.shortName = ration_glj.shortName;
+    newRecoed.billsItemID=ration_glj.billsItemID,
     newRecoed.type = ration_glj.type;
     newRecoed.repositoryId = ration_glj.repositoryId;
     newRecoed.projectGLJID=ration_glj.projectGLJID;
@@ -622,6 +623,7 @@ function getGLJSearchInfo(ration_glj) {
         project_id: ration_glj.projectID,
         code: ration_glj.code,
         name: ration_glj.name,
+        shortName:ration_glj.shortName,
         specs: ration_glj.specs,
         unit: ration_glj.unit,
         type: ration_glj.type,

+ 1 - 0
modules/ration_glj/models/ration_glj.js

@@ -17,6 +17,7 @@ var ration_glj = new Schema({
     specs:String,
     unit:String,
     shortName:String,
+    billsItemID: Number,
     type:Number,
     quantity:Number,
     customQuantity:Number,

+ 2 - 0
modules/ration_glj/models/ration_glj_temp.js

@@ -132,6 +132,8 @@ let billsSchema = new Schema({
     name: String,
     unit: String,
     quantity: String, // Decimal
+    feeRateID:String,
+    feeRate:String,
     isFromDetail:{type: Number,default:0},//1 true 2 false
     programID: Number,
     comments: String,

+ 25 - 6
modules/reports/facade/rpt_tpl_data_facade.js

@@ -2,13 +2,32 @@
  * Created by Tony on 2017/8/9.
  */
 
-import mongoose from "mongoose";
-let rpt_tpl_mdl = mongoose.model("rpt_templates");
+// import mongoose from "mongoose";
+// let consts = require('../../../modules/main/models/project_consts');
+// let projectConst = consts.projectConst;
+let prjMdl = require('../../../modules/pm/models/project_model');
+let projectDataMdl = require('../../../modules/main/models/project');
 
 module.exports = {
+    prepareProjectData: prepareProjectData
+};
 
-}
-
-async function prepareProjectData(prjId, userId) {
-    //
+function prepareProjectData(userId, prjId, filter, callback) {
+    let rawDataObj = null;
+    prjMdl.project.getUserProject(userId, prjId, function(err, msg, rst){
+        if (!err) {
+            rawDataObj = {};
+            rawDataObj.prj = rst;
+            projectDataMdl.getFilterData(prjId, filter, function (results) {
+                if (results) {
+                    rawDataObj.prjData = results;
+                    callback(false, 'Succeeded!', rawDataObj);
+                } else {
+                    callback(true, 'No data were found!', null);
+                }
+            });
+        } else {
+            callback(err, msg, null);
+        }
+    });
 }

+ 254 - 0
modules/reports/util/rpt_construct_data_util.js

@@ -0,0 +1,254 @@
+/**
+ * Created by Tony on 2017/7/14.
+ * 报表数据提取class,是协助报表模板里指标字段自主提取数据的工具类
+ */
+let JV = require('../rpt_component/jpc_value_define');
+let $JE = require('../rpt_component/jpc_rte');
+let consts = require('../../../modules/main/models/project_consts');
+let projectConst = consts.projectConst;
+let projectConstList = consts.projectConstList;
+
+class Rpt_Common{
+    initialize(Projects) {
+        this.Projects = Projects;
+    };
+
+    getSerialNo(fieldId, $CURRENT_RPT, $CURRENT_DATA){
+        let itemSerialNoRec = $JE.F(fieldId, $CURRENT_RPT);
+        if (itemSerialNoRec) {
+            itemSerialNoRec[JV.PROP_AD_HOC_DATA] = [];
+            for (var innerFmlIdx = 0; innerFmlIdx < $CURRENT_DATA[JV.DATA_DETAIL_DATA][0].length; innerFmlIdx++) {
+                itemSerialNoRec[JV.PROP_AD_HOC_DATA][innerFmlIdx] = (innerFmlIdx + 1);
+            }
+            itemSerialNoRec = null;
+        }
+    };
+}
+
+class Rpt_Data_Extractor {
+    constructor () {
+        this.COMMON = new Rpt_Common();
+    };
+
+    initialize(tpl) {
+        this.rptTpl = tpl;
+    };
+
+    getDataRequestFilter() {
+        let rst = [];
+        let tpl = this.rptTpl;
+        let pri_func_chk_filter = function (field) {
+            for (let key of projectConstList) {
+                if (rst.indexOf(key) < 0) {
+                    if (field[JV.PROP_FIELD_EXP_MAP]) {
+                        if (field[JV.PROP_FIELD_EXP_MAP].indexOf('.' + key + '.') >= 0) {
+                            rst.push(key);
+                        }
+                    }
+                }
+            }
+        };
+        if (tpl[JV.NODE_FIELD_MAP][JV.NODE_DISCRETE_FIELDS]) {
+            for (let field of tpl[JV.NODE_FIELD_MAP][JV.NODE_DISCRETE_FIELDS]) {
+                pri_func_chk_filter(field);
+            }
+        }
+        if (tpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS]) {
+            for (let field of tpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS]) {
+                pri_func_chk_filter(field);
+            }
+        }
+        if (tpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS]) {
+            for (let field of tpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS]) {
+                pri_func_chk_filter(field);
+            }
+        }
+        if (tpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS_EX]) {
+            for (let field of tpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS_EX]) {
+                pri_func_chk_filter(field);
+            }
+        }
+        if (tpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS_EX]) {
+            for (let field of tpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS_EX]) {
+                pri_func_chk_filter(field);
+            }
+        }
+        return rst;
+    };
+
+    //--- 装配数据(把收集到的数据,依据报表模板的指示,预处理(如:排序、过滤、合计)及装配到相关指标) ---//
+    assembleData(rawDataObj) {
+        let $PROJECT = {"COMMON": {}, "MAIN": {}, "DETAIL": {}};
+        let tpl = this.rptTpl;
+        $PROJECT.MAIN["myOwnRawDataObj"] = rawDataObj.prj._doc;
+        $PROJECT.MAIN.getProperty = ext_mainGetPropety;
+        $PROJECT.MAIN.getFee = ext_mainGetFee;
+        $PROJECT.DETAIL.getRationPropertyByID = ext_getRationPropertyByID;
+        if (tpl[JV.NODE_MAP_DATA_HANDLE_INFO]) {
+            for (let preHandle of tpl[JV.NODE_MAP_DATA_HANDLE_INFO]) {
+                switch(preHandle[JV.PROP_HANDLE_TYPE]) {
+                    case JV.PROP_HANDLE_TYPE_SORT:
+                        break;
+                    case JV.PROP_HANDLE_TYPE_FILTER:
+                        break;
+                    case JV.PROP_HANDLE_TYPE_SUM:
+                        //
+                }
+            }
+        }
+        for (let item of rawDataObj.prjData) {
+            setupFunc($PROJECT.DETAIL, item.moduleName, item);
+        }
+        let rptDataObj = {};
+        rptDataObj[JV.DATA_DISCRETE_DATA] = [];
+        rptDataObj[JV.DATA_MASTER_DATA] = [];
+        rptDataObj[JV.DATA_DETAIL_DATA] = [];
+        rptDataObj[JV.DATA_MASTER_DATA_EX] = [];
+        rptDataObj[JV.DATA_DETAIL_DATA_EX] = [];
+        assembleFields(tpl[JV.NODE_FIELD_MAP][JV.NODE_DISCRETE_FIELDS], rptDataObj[JV.DATA_DISCRETE_DATA], $PROJECT);
+        // console.log(JV.DATA_DISCRETE_DATA);
+        // console.log(rptDataObj[JV.DATA_DISCRETE_DATA]);
+        assembleFields(tpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS], rptDataObj[JV.DATA_MASTER_DATA], $PROJECT);
+        // console.log(JV.DATA_MASTER_DATA);
+        // console.log(rptDataObj[JV.DATA_MASTER_DATA]);
+        assembleFields(tpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS], rptDataObj[JV.DATA_DETAIL_DATA], $PROJECT);
+        // console.log(JV.DATA_DETAIL_DATA);
+        // console.log(rptDataObj[JV.DATA_DETAIL_DATA]);
+        assembleFields(tpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS_EX], rptDataObj[JV.DATA_MASTER_DATA_EX], $PROJECT);
+        // console.log(JV.DATA_MASTER_DATA_EX);
+        // console.log(rptDataObj[JV.DATA_MASTER_DATA_EX]);
+        assembleFields(tpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS_EX], rptDataObj[JV.DATA_DETAIL_DATA_EX], $PROJECT);
+        // console.log(JV.DATA_DETAIL_DATA_EX);
+        // console.log(rptDataObj[JV.DATA_DETAIL_DATA_EX]);
+    };
+
+}
+
+function setupFunc(obj, prop, ownRawObj) {
+    obj[prop] = {};
+    obj[prop]["myOwnRawDataObj"] = ownRawObj;
+    obj[prop].getProperty = ext_getPropety;
+    obj[prop].getFee = ext_getFee;
+}
+
+function assembleFields(fieldList, rstDataArr, $PROJECT) {
+    if (fieldList) {
+        for (let field of fieldList) {
+            shielded_exec_env($PROJECT, field, rstDataArr);
+        }
+    }
+}
+
+function shielded_exec_env($PROJECT, $ME, rptDataItemObj) {
+    if ($ME[JV.PROP_FIELD_EXP_MAP]) {
+        rptDataItemObj.push(eval($ME[JV.PROP_FIELD_EXP_MAP]));
+    }
+}
+
+function ext_mainGetPropety(propKey) {
+    let rst = [];
+    let parentObj = this;
+    //console.log(this);
+    let dtObj = parentObj["myOwnRawDataObj"];
+    if ((dtObj) && (propKey)) {
+        if (dtObj.hasOwnProperty("property")) {
+            rst.push(dtObj["property"][propKey]);
+        } else  {
+            rst.push(dtObj[propKey]);
+        }
+    }
+    return rst;
+}
+
+function ext_mainGetFee(feeKey) {
+    let rst = [];
+    let parentObj = this;
+    let dtObj = parentObj["myOwnRawDataObj"];
+    if ((dtObj) && (feeKey)) {
+        if (dtObj.hasOwnProperty("fees")) {
+            for (let fee of dtObj["fees"]) {
+                if (fee["fieldName"] === feeKey) {
+                    rst.push(dtObj["fees"][feeKey]);
+                    break;
+                }
+            }
+        } else if (dtObj.hasOwnProperty(feeKey)) {
+            rst.push(dtObj[feeKey]);
+        } else {
+            //
+        }
+    }
+    return rst;
+}
+
+function ext_getPropety(propKey) {
+    let rst = [], parentObj = this;
+    let dtObj = parentObj["myOwnRawDataObj"];
+    if (propKey && dtObj) {
+        for (let dItem of dtObj.data) {
+            let doc = dItem._doc;
+            if (doc.hasOwnProperty("property")) {
+                rst.push(doc["property"][propKey]);
+            } else if (doc.hasOwnProperty(propKey)) {
+                rst.push(doc[propKey]);
+            } else {
+                rst.push('');
+            }
+        }
+    }
+    return rst;
+}
+
+function ext_getFee(feeKey) {
+    let rst = [], parentObj = this;
+    let dtObj = parentObj["myOwnRawDataObj"];
+    if (feeKey && dtObj) {
+        for (let dItem of dtObj.data) {
+            if (dItem.hasOwnProperty("fees")) {
+                for (let fee of dItem["fees"]) {
+                    if (fee["fieldName"] === feeKey) {
+                        rst.push(dItem["fees"][feeKey]);
+                        break;
+                    }
+                }
+            } else if (dItem.hasOwnProperty(feeKey)) {
+                rst.push(dItem[feeKey]);
+            } else {
+                rst.push[0];
+            }
+        }
+    }
+    return rst;
+}
+
+function ext_getRationPropertyByID(IdVal, propKey) {
+    let rst = [], me = this;
+    if (IdVal !== null && IdVal !== undefined && me[projectConst.RATION]) {
+        let isFound = false;
+        if (IdVal instanceof Array) {
+            for (let id of IdVal) {
+                isFound = false;
+                for (let item of me[projectConst.RATION]["myOwnRawDataObj"].data) {
+                    if (item.ID === id) {
+                        rst.push(item[propKey]);
+                        isFound = true;
+                        break;
+                    }
+                }
+                // if (!isFound) rst.push[null];
+            }
+        } else {
+            for (let item of me[projectConst.RATION]["myOwnRawDataObj"].data) {
+                if (item.ID === IdVal) {
+                    rst.push(item[propKey]);
+                    isFound = true;
+                    break;
+                }
+            }
+            // if (!isFound) rst.push[null];
+        }
+    }
+    return rst;
+}
+
+export default Rpt_Data_Extractor;

+ 0 - 66
modules/reports/util/rpt_data_util.js

@@ -1,66 +0,0 @@
-/**
- * Created by Tony on 2017/7/14.
- * 报表数据提取class,是协助报表模板里指标字段自主提取数据的工具类
- */
-let JV = require('../rpt_component/jpc_value_define');
-let $JE = require('../rpt_component/jpc_rte');
-
-class Rpt_Common{
-    initialize(Projects) {
-        this.Projects = Projects;
-    };
-
-    getSerialNo(fieldId, $CURRENT_RPT, $CURRENT_DATA){
-        let itemSerialNoRec = $JE.F(fieldId, $CURRENT_RPT);
-        if (itemSerialNoRec) {
-            itemSerialNoRec[JV.PROP_AD_HOC_DATA] = [];
-            for (var innerFmlIdx = 0; innerFmlIdx < $CURRENT_DATA[JV.DATA_DETAIL_DATA][0].length; innerFmlIdx++) {
-                itemSerialNoRec[JV.PROP_AD_HOC_DATA][innerFmlIdx] = (innerFmlIdx + 1);
-            }
-            itemSerialNoRec = null;
-        }
-    };
-};
-
-class Rpt_Data_Extractor {
-    constructor () {
-        this.COMMON = new Rpt_Common();
-    };
-
-    initialize(Projects) {
-        this.Projects = Projects;
-        //Projects对象应该从前端传送过来,无需在后端重复查询及构建
-        /* 结构:
-         {
-            currentPrjId: int,
-            topPrj: [
-                //单项工程
-                {
-                    subPrjName: String,
-                    subPrjId: int,
-                    detailPrj: [
-                        //单位工程
-                        {
-                            detailPrjName: String,
-                            subPrjId: int,
-                        }
-                        ...
-                    ]
-                }
-                ...
-            ]
-         }
-         */
-    };
-
-    prepareData($CURRENT_RPT) {
-        //在报表提取数据前的准备工作,主要有:
-        //1. 确认指标数据的类型(离散/主/从)
-        //2. 根据类型提取数据,排序
-        // 2.1. header类型
-        // 2.2. 章类型
-        // 2.3. detail类型
-        // 2.4. 排序
-    };
-
-}

+ 14 - 1
public/web/rpt_value_define.js

@@ -35,7 +35,6 @@ const JV = {
     DISPLAY_MODE_INDEPENDENT: "单独模式",
     DISPLAY_MODE_FOLLOW: "紧随模式",
 
-
     NODE_MAIN_INFO: "主信息",
     NODE_MAIN_INFO_RPT_NAME: "报表名称",
     NODE_PAGE_INFO: "打印页面_信息",
@@ -46,6 +45,20 @@ const JV = {
     NODE_BIZ_TYPE_SUM: "汇总类型",
     NODE_BIZ_TYPE_DETAIL: "明细类型",
 
+    NODE_MAP_DATA_HANDLE_INFO: "映射数据过滤及统计处理",
+    PROP_DATA_KEY: "映射数据对象",
+    PROP_HANDLE_TYPE: "预处理类型",
+    PROP_FILTER_KEY: "过滤键属性",
+    PROP_FILTER_DEPENDENT_ON: "过滤依据对象",
+    PROP_FILTER_DEPENDENT_ON_KEY: "过滤依据对象键属性",
+    PROP_FILTER_CONDITION: "条件",
+    PROP_HANDLE_TYPE_FILTER: "过滤",
+    PROP_HANDLE_TYPE_SUM: "合计",
+    PROP_HANDLE_TYPE_SORT: "排序",
+    PROP_SUM_GROUP_KEYS: "分组键值集",
+    PROP_SUM_SUM_KEYS: "统计键值集",
+    PROP_FIELD_EXP_MAP: "mapExpression",
+
     NODE_FONT_COLLECTION: "font_collection",
     NODE_STYLE_COLLECTION: "style_collection",
     NODE_CONTROL_COLLECTION: "control_collection",

+ 126 - 0
test/unit/reports/test_tpl_09_1.js

@@ -0,0 +1,126 @@
+/**
+ * Created by Tony on 2017/10/18.
+ */
+let test = require('tape');
+import JV from "../../../modules/reports/rpt_component/jpc_value_define";
+let mongoose = require("mongoose");
+let fileUtils = require("../../../modules/common/fileUtils");
+let path = require('path');
+let dbm = require("../../../config/db/db_manager");
+dbm.connect();
+let consts = require('../../../modules/main/models/project_consts');
+let projectConsts = consts.projectConst;
+fileUtils.getGlobbedFiles('../../../modules/complementary_glj_lib/models/*.js').forEach(function(modelPath) {
+    require(path.resolve(modelPath));
+});
+
+fileUtils.getGlobbedFiles('../../../modules/ration_glj/models/*.js').forEach(function(modelPath) {
+    require(path.resolve(modelPath));
+});
+
+//引入报表模块
+fileUtils.getGlobbedFiles('../../../modules/reports/models/*.js').forEach(function(modelPath) {
+    require(path.resolve(modelPath));
+})
+
+//暂时引入其它模块的model
+require('../../../modules/fee_rates/models/fee_rates');
+// 引入人工系数模块
+require('../../../modules/main/models/labour_coe');
+
+let fsUtil = require("../../../public/fsUtil");
+
+let prjMdl = require('../../../modules/pm/models/project_model');
+let projectDataMdl = require('../../../modules/main/models/project');
+let demoPrjId = - 1;
+let demoRptId = 226, pagesize = "A4";
+
+demoPrjId = 469; //QA: 1号教学楼建筑工程
+// demoPrjId = 491; //QA: 2号教学楼建筑工程
+// demoPrjId = 492; //QA: 3号教学楼建筑工程
+let userId_Leng = 1142; //小冷User Id
+
+let rptTplFacade = require("../../../modules/reports/facade/rpt_template_facade");
+let rptTplDataFacade = require("../../../modules/reports/facade/rpt_tpl_data_facade");
+
+import rptDataExtractor from "../../../modules/reports/util/rpt_construct_data_util";
+
+// test('测试 - 获取project数据: ', function (t) {
+//     projectDataMdl.getData(demoPrjId, function (err, message, result) {
+//         if (!err) {
+//             fsUtil.wirteObjToFile(result, "D:/GitHome/ConstructionCost/tmp/ProjectDataFullObject.js");
+//             t.pass('pass succeeded!');
+//             t.end();
+//         } else {
+//             //callback(req, res, err, message, null);
+//             t.pass('pass failed!');
+//             t.end();
+//         }
+//     });
+// });
+
+// test('测试 - 获取project部分数据: ', function (t) {
+//     let filter = [];
+//     filter.push(projectConsts.BILLS);
+//     filter.push(projectConsts.RATION);
+//     filter.push(projectConsts.RATION_GLJ);
+//     filter.push(projectConsts.FEERATE);
+//     prjMdl.project.getUserProject(userId_Leng, demoPrjId, function(err, msg, prjObj){
+//         if (!err) {
+//             projectDataMdl.getFilterData(demoPrjId, filter, function (results) {
+//                 if (results) {
+//                     // let newData = [];
+//                     // for (let item of results) {
+//                     //     newData.push(JSON.stringify(item));
+//                     // }
+//                     // fsUtil.writeArrayToFile(newData, "D:/GitHome/ConstructionCost/tmp/getProjectData_partial.js");
+//                     fsUtil.wirteObjToFile(prjObj, "D:/GitHome/ConstructionCost/tmp/getProjectObjectNew.js");
+//                     fsUtil.wirteObjToFile(results, "D:/GitHome/ConstructionCost/tmp/getProjectData_partialNew.js");
+//                     t.pass('pass succeeded!');
+//                     t.end();
+//                 } else {
+//                     //callback(req, res, err, message, null);
+//                     t.pass('get project data failed!');
+//                     t.end();
+//                 }
+//             });
+//         } else {
+//             t.pass('get project failed!');
+//             t.end();
+//         }
+//     });
+// });
+
+test('测试 - 测试模板啦: ', function (t) {
+    rptTplFacade.getRptTemplate(demoRptId).then(function(tpl) {
+        let rptDataUtil = new rptDataExtractor();
+        rptDataUtil.initialize(tpl);
+        let filter = rptDataUtil.getDataRequestFilter();
+        console.log(filter);
+        //正常应该根据报表模板定义的数据类型来请求数据
+        rptTplDataFacade.prepareProjectData(userId_Leng, demoPrjId, filter, function (err, msg, rawDataObj) {
+            if (!err) {
+                rptDataUtil.assembleData(rawDataObj);
+                t.pass('pass succeeded!');
+                t.end();
+                //fsUtil.wirteObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/rptTplRawDataObject1.js");
+                //准备执行公式需要的对象
+            } else {
+                console.log(msg);
+                t.pass('pass with error!');
+                t.end();
+            }
+        })
+    });
+});
+
+test('close the connection', function (t) {
+    setTimeout(function () {
+        mongoose.disconnect();
+        t.pass('closing db connection');
+        t.end();
+    }, 3000);
+    // mongoose.disconnect();
+    // t.pass('closing db connection');
+    // t.end();
+});

+ 3 - 0
web/building_saas/glj/js/project_glj_spread.js

@@ -44,6 +44,7 @@ ProjectGLJSpread.prototype.init = function () {
         {name: '名称', field: 'name', visible: true},
         {name: '规格型号', field: 'specs', visible: true},
         {name: '单位', field: 'unit', visible: true},
+        {name: '类型', field: 'unit_price.short_name', visible: true},
         {name: 'ID', field: 'id', visible: false},
         {name: '类型', field: 'unit_price.type', visible: false},
         {name: '总消耗量', field: 'quantity', visible: true},
@@ -88,12 +89,14 @@ ProjectGLJSpread.prototype.init = function () {
     let adjustPriceColumn = this.sheetObj.getFieldColumn('adjust_price');
     let marketPriceColumn = this.sheetObj.getFieldColumn('unit_price.market_price');
     let supplyColumn = this.sheetObj.getFieldColumn('supply');
+    let shortNameColumn = this.sheetObj.getFieldColumn('unit_price.short_name');
 
     // 居中样式
     let centerStyleSetting = {hAlign: 1};
     this.sheetObj.setStyle(-1, isEvaluateColumn, centerStyleSetting);
     this.sheetObj.setStyle(-1, isAdjustPriceColumn, centerStyleSetting);
     this.sheetObj.setStyle(-1, unitColumn, centerStyleSetting);
+    this.sheetObj.setStyle(-1, shortNameColumn, centerStyleSetting);
 
     // 向右对齐样式
     let rightStyleSetting = {hAlign: GC.Spread.Sheets.HorizontalAlign.right};

+ 18 - 2
web/building_saas/main/html/main.html

@@ -413,7 +413,7 @@
                                 <li class="nav-item"><a class="nav-link active" data-toggle="pill" href="#poj-settings-1" role="tab">基本信息</a></li>
                                 <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-2" role="tab">工程特征</a></li>
                                 <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-3" role="tab">指标信息</a></li>
-                                <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-4" role="tab">取费方式</a></li>
+                                <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-4" role="tab">关于计算</a></li>
                                 <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-5" role="tab">清单工程精度</a></li>
                                 <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-6" role="tab" id="tab_poj-settings-6">人工单价调整</a></li>
                             </ul>
@@ -438,10 +438,11 @@
                                         指标信息
                                     </div>
                                 </div>
-                                <!--取费方式-->
+                                <!--关于计算-->
                                 <div class="tab-pane fade" id="poj-settings-4" role="tabpanel">
                                     <div class="modal-auto-height">
                                         <fieldset class="form-group">
+                                            <h5>取费方式</h5>
                                             <div class="form-check">
                                                 <label class="form-check-label">
                                                     <input class="form-check-input" name="calcFlag" id="rationContent" value="0" type="radio">
@@ -467,6 +468,21 @@
                                                 </label>
                                             </div>
                                         </fieldset>
+                                        <fieldset class="form-group">
+                                            <h5>暂估合价计算方式</h5>
+                                            <div class="form-check">
+                                                <label class="form-check-label">
+                                                    <input class="form-check-input" name="zangu" id="zangu_common" value="0" type="radio">
+                                                    暂估合价=暂估单价×定额工程量
+                                                </label>
+                                            </div>
+                                            <div class="form-check">
+                                                <label class="form-check-label">
+                                                    <input class="form-check-input" name="zangu" id="zangu_gatherMaterial" value="1" type="radio">
+                                                    暂估合价=∑暂估材料数量×暂估材料单价
+                                                </label>
+                                            </div>
+                                        </fieldset>
                                     </div>
                                 </div>
                                 <!--清单工程精度-->

+ 26 - 9
web/building_saas/main/js/calc/bills_calc.js

@@ -4,8 +4,13 @@
 
 const rationContent = 0, rationPrice = 1, rationPriceConverse = 2, billsPrice = 3;
 
+// sumTotalFeeFlag: sum(child.totalFee), totalFeeFlag: bills.quantity × bills.unitFee
 const sumTotalFeeFlag = 0, totalFeeFlag = 1;
-const rationContentUnitFeeFlag = 0, averageQtyUnitFeeFlag = 1, billsPriceUnitFeeFlag = 2;
+// rationContentUnitFeeFlag: sum(child.unitFee * child.quantity / bills.quantity)
+// averageQtyUnitFeeFlag: sum(child.totalFee/bills.quantity)
+// billsPriceUnitFeeFlag: 根据定额计算程序
+// converseUnitFeeFalg: bills.totalFee / bills.quantity
+const rationContentUnitFeeFlag = 0, averageQtyUnitFeeFlag = 1, billsPriceUnitFeeFlag = 2, converseUnitFeeFlag = 3;
 
 let rationContentCalcFields = [
     {'type': 'common', 'unitFeeFlag': rationContentUnitFeeFlag, 'totalFeeFlag': totalFeeFlag},
@@ -83,6 +88,15 @@ let nodeCalcObj = {
             result += (childUnitFee * childQuantity / qty).toDecimal(this.digit);
         }
         return result;
+    },
+    converseUnitFee: function (digit) {
+        let totalFee = this.sumTotalFee().toDecimal(digit);
+        let qty = this.getFee(this.node.data, 'quantity');
+        if (qty !== 0){
+            return totalFee / qty;
+        } else {
+            return 0;
+        }
     }
 };
 
@@ -251,7 +265,7 @@ class BillsCalcHelper {
         nodeCalcObj.node = node;
         nodeCalcObj.digit = this.project.Decimal.unitFee;
         calcFees.checkFields(node.data, fields);
-        let nodeCalc = nodeCalcObj, virData= null;
+        let nodeCalc = nodeCalcObj, virData= null, decimal = this.project.Decimal;
 
         // 清单单价:套用定额计算程序
         if (this.project.calcFlag === billsPrice) {
@@ -265,24 +279,27 @@ class BillsCalcHelper {
             nodeCalcObj.field = field;
             switch (field.unitFeeFlag) {
                 case rationContentUnitFeeFlag:
-                    node.data.feesIndex[field.type].unitFee = nodeCalcObj.rationContentUnitFee().toDecimal(this.project.Decimal.common.unitFee);
+                    node.data.feesIndex[field.type].unitFee = nodeCalcObj.rationContentUnitFee().toDecimal(decimal.common.unitFee);
                     break;
                 case averageQtyUnitFeeFlag:
-                    node.data.feesIndex[field.type].unitFee = nodeCalcObj.averageQty().toDecimal(this.project.Decimal.common.unitFee);
+                    node.data.feesIndex[field.type].unitFee = nodeCalcObj.averageQty().toDecimal(decimal.common.unitFee);
+                    break;
+                case billsPriceUnitFeeFlag:
+                    node.data.feesIndex[field.type].unitFee = virData[field.type];
+                    break;
+                case converseUnitFeeFlag:
+                    node.data.feesIndex[field.type].unitFee = nodeCalcObj.converseUnitFee(decimal.common.totalFee).toDecimal(decimal.common.unitFee);
                     break;
-                 case billsPriceUnitFeeFlag:
-                     node.data.feesIndex[field.type].unitFee = virData[field.type];
-                     break;
                 default:
                     node.data.feesIndex[field.type].unitFee = 0;
             }
             let value = 0;
             switch (field.totalFeeFlag) {
                 case sumTotalFeeFlag:
-                    value = nodeCalcObj.sumTotalFee().toDecimal(this.project.Decimal.common.totalFee);
+                    value = nodeCalcObj.sumTotalFee().toDecimal(decimal.common.totalFee);
                     break;
                 case totalFeeFlag:
-                    value = nodeCalcObj.totalFee().toDecimal(this.project.Decimal.common.totalFee);
+                    value = nodeCalcObj.totalFee().toDecimal(decimal.common.totalFee);
                     break;
                 default:
                     value = 0;

+ 1 - 0
web/building_saas/main/js/calc/calc_fees.js

@@ -27,6 +27,7 @@ let feeType = [
     {type: 'common', name: '工程造价'},
     {type: 'adjustLabour', name: '调整人工费'},
     {type: 'adjustMachineLabour', name: '调整机上人工费'},
+    {type: 'zangu', name: '暂估'},
     // 模拟用户新增
     {type: 'fee1', name: '甲供材料费'}
 ];

+ 27 - 3
web/building_saas/main/js/models/fee_rate.js

@@ -34,14 +34,17 @@ var FeeRate = {
             return feeRate;
         };
         FeeRate.prototype.getActivateFeeRateID = function(){
-            var feeRate = this.getActivateFeeRate()
+            var feeRate = this.getActivateFeeRate();
             if(feeRate){
                 return feeRate.ID;
             }else {
                 return 0;
             }
         };
-
+        FeeRate.prototype.getFeeRateByID=function (ID) {
+            var rates = this.getActivateFeeRate().rates;
+            return _.find(rates,{'ID':ID})
+        };
         FeeRate.prototype.getSubViewData= function(item) {
             var datas = [];
             if(item.hasOwnProperty('subFeeRate')&&item.subFeeRate!=undefined){
@@ -213,7 +216,28 @@ var FeeRate = {
                 callback(data);
             });
         };
-
+        FeeRate.prototype.setFeeRateToBill=function (rate,bills,callback) {
+            var query={
+                ID:bills.ID,
+                projectID:bills.projectID,
+                deleteInfo:null
+            }
+            var doc={
+                feeRate:null,
+                feeRateID:rate.ID
+            }
+            CommonAjax.post('/feeRates/setFeeRateToBill', {query:query,doc:doc}, function (data) {
+                callback(data);
+            });
+        };
+        FeeRate.prototype.loadFeeRateToBill=function (node) {
+            if(node.data.feeRateID){
+                var feeRate = this.getFeeRateByID(node.data.feeRateID);
+                if(feeRate){
+                    node.data.feeRate=feeRate.rate.toString();
+                }
+            }
+        };
         FeeRate.prototype.changeFeeRateFileFromCurrent = function (newFeeRateFile,callback){
             var me=this;
             var projectID = projectInfoObj.projectInfo.ID;

+ 13 - 8
web/building_saas/main/js/models/project.js

@@ -149,7 +149,7 @@ var PROJECT = {
                     newNode.source = nodes[i];
                     newNode.sourceType = that.Bills.getSourceType();
                     newNode.data = nodes[i].data;
-
+                    that.FeeRate.loadFeeRateToBill(newNode);
                     if (nodes[i].children.length === 0) {
                         loadRationNode(that.Ration.datas, newNode);
                         loadVolumePriceNode(newNode);
@@ -295,19 +295,24 @@ var PROJECT = {
         };
 
         project.prototype.initCalcFields = function () {
+            let settingConst = this.projSetting.settingConst;
             if (this.calcFields) {
                 for (let field of this.calcFields) {
                     // unitFeeCalcFlag
-                    if (this.projSetting.billsCalcMode === this.projSetting.billsCalcModeConst.rationContent) {
-                        field.unitFeeFlag = rationContentUnitFeeFlag;
-                    } else if ( this.projSetting.billsCalcMode === this.projSetting.billsCalcModeConst.billsPrice) {
-                        field.unitFeeFlag = billsPriceUnitFeeFlag;
-                    } else {
-                        field.unitFeeFlag = averageQtyUnitFeeFlag;
+                    if (field.type === 'zangu') {
+                        field.unitFeeFlag = converseUnitFeeFlag;
+                    } else {   
+                        if (this.projSetting.billsCalcMode === settingConst.billsCalcMode.rationContent) {
+                            field.unitFeeFlag = rationContentUnitFeeFlag;
+                        } else if ( this.projSetting.billsCalcMode === settingConst.billsCalcMode.billsPrice) {
+                            field.unitFeeFlag = billsPriceUnitFeeFlag;
+                        } else {
+                            field.unitFeeFlag = averageQtyUnitFeeFlag;
+                        }
                     }
                     // totalFeeCalcFlag
                     if (field.type === 'common') {
-                        if (this.projSetting.billsCalcMode === this.projSetting.billsCalcModeConst.rationPriceConverse) {
+                        if (this.projSetting.billsCalcMode === settingConst.billsCalcMode.rationPriceConverse) {
                             field.totalFeeFlag = sumTotalFeeFlag;
                         } else {
                             field.totalFeeFlag = totalFeeFlag;

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

@@ -182,6 +182,7 @@ var ration_glj = {
                     newGLJ.projectID = newRation.projectID;
                     newGLJ.GLJID = temdata.gljId;
                     newGLJ.rationID = newRation.ID;
+                    newGLJ.billsItemID=newRation.billsItemID,
                     newGLJ.rationItemQuantity= temdata.consumeAmt;
                     newGLJ.quantity=temdata.consumeAmt;
                     newGLJ.glj_repository_id=data.rationRepId;
@@ -327,6 +328,7 @@ var ration_glj = {
                   projectID:ration.projectID,
                   GLJID:glj.ID,
                   rationID:ration.ID,
+                  billsItemID:ration.billsItemID,
                   rationItemQuantity:0,
                   quantity:0,
                   name:glj.name,

+ 30 - 12
web/building_saas/main/js/views/fee_rate_view.js

@@ -123,6 +123,7 @@ var feeRateObject={
         feeRateObject.feeRateSheet.options.isProtected = true;
         feeRateObject.feeRateSheet.name('fee_rate');
         feeRateObject.feeRateSheet.bind(GC.Spread.Sheets.Events.CellClick,feeRateObject.onCellClick);
+        feeRateObject.feeRateSheet.bind(GC.Spread.Sheets.Events.CellDoubleClick,feeRateObject.onCellDoubleClick);
     },
     showSelectTree:function () {
         var sheet= feeRateObject.feeRateSheet;
@@ -162,7 +163,6 @@ var feeRateObject={
             }
         }
         //this.lockCells(sheet,setting);
-        console.log(groups);
         _.forEach(groups,function (g) {
             for(var k in g){
                 sheet.rowOutlines.group(parseInt(k), g[k]);
@@ -302,7 +302,7 @@ var feeRateObject={
                 var offset=hitinfo.cellRect.x+hitinfo.cellRect.width-6;
                 var imageMagin=3;
                 var imageHeight = hitinfo.cellRect.height-2*imageMagin;
-                var imageWidth = imageHeight* 4/3;
+                var imageWidth = hitinfo.cellRect.width*2/7;
                 if(hitinfo.x<offset&&hitinfo.x>offset-imageWidth){
                     me.showSelectModal(hitinfo);
                 }
@@ -621,6 +621,11 @@ var feeRateObject={
        var data =projectObj.project.FeeRate.getActivateFeeRate().rates;
        feeRateObject.feeRateSelection=data[args.row];
     },
+    onCellDoubleClick:function (sender,args) {
+        var data =projectObj.project.FeeRate.getActivateFeeRate().rates;
+        feeRateObject.feeRateSelection=data[args.row];
+        feeRateObject.submitFeeRateBySelect();
+    },
     checkSelectedFeeRate:function () {
         var validate = false;
         var data =projectObj.project.FeeRate.getActivateFeeRate().rates;
@@ -629,6 +634,28 @@ var feeRateObject={
             validate=children&&children.length==0;
         }
         return validate;
+    },
+    setFeeRateToBill:function () {
+       var rate = feeRateObject.feeRateSelection;
+       var selected = projectObj.project.mainTree.selected;
+        projectObj.project.FeeRate.setFeeRateToBill(rate,selected.data,function (data) {
+            selected.data.feeRateID=rate.ID.toString();
+            selected.data.feeRate=rate.rate.toString();
+            projectObj.mainController.refreshTreeNode([selected]);
+            $("#fee_rate_tree").modal('hide');
+        });
+    },
+    submitFeeRateBySelect:function () {
+        var validate = this.checkSelectedFeeRate();
+        if(validate){
+            if($('#edit_from').val()=='calc_detail'){
+                //do calc_detail
+            }else {
+                this.setFeeRateToBill();
+            }
+        }else {
+            //$("#fee_rate_tree").modal('hide');
+        }
     }
 }
 
@@ -805,14 +832,5 @@ $('#fee_rate_tree').on('hidden.bs.modal', function (e) {
 });
 
 $('#fee_selected_conf').bind('click',function (){
-    var validate = feeRateObject.checkSelectedFeeRate();
-    if(validate){
-        if($('#edit_from').val()=='calc_detail'){
-            //do calc_detail
-        }else {
-            
-        }
-    }
-    console.log(validate);
-
+    feeRateObject.submitFeeRateBySelect();
 })

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

@@ -881,6 +881,7 @@ $(function(){
             gljOprObj.gljLibSheet = gljOprObj.gljLibSpresd.getSheet(0);
             gljOprObj.gljLibSheet.options.isProtected = true;
             gljOprObj.gljLibSheet.name('glj_lib');
+            console.log("show feeRate tree");
         }
         gljOprObj.gljLibSheetData =gljOprObj.AllRecode;
         var selected=null;

+ 4 - 1
web/building_saas/main/js/views/main_tree_col.js

@@ -58,8 +58,11 @@ let MainTreeCol = {
             combo.itemHeight(10).items(['m', 'm2', 'm3', 'km', 't', 'kg', '台班', '工日', '昼夜', '元', '项', '处', '个', '件',
                 '根', '组', '系统', '台', '套', '株', '丛', '缸', '支', '只', '块', '座', '对', '份', '樘', '攒', '榀']);
             return combo;
+        },
+        feeRate: function () {
+            return feeRateObject.getFeeRateEditCellType();
         }
-    },
+     },
     getEvent: function (eventName) {
         let names = eventName.split('.');
         let event = this;

+ 21 - 11
web/building_saas/main/js/views/project_view.js

@@ -291,12 +291,11 @@ var projectObj = {
             if (!err) {
                 that.project.calcFields = JSON.parse(JSON.stringify(feeType));
                 that.project.initCalcFields();
-                var feeRateCol = 0;
                 let str = JSON.stringify(that.project.projSetting.main_tree_col);
                 that.project.projSetting.mainGridSetting = JSON.parse(str);
                 that.project.projSetting.mainGridSetting.frozenCols = 4;
                 TREE_SHEET_HELPER.initSetting($('#billsSpread')[0], that.project.projSetting.mainGridSetting);
-                that.project.projSetting.mainGridSetting.cols.forEach(function (col,index) {
+                that.project.projSetting.mainGridSetting.cols.forEach(function (col) {
                     col.data.splitFields = col.data.field.split('.');
                     if (col.data.getText && Object.prototype.toString.apply(col.data.getText) === "[object String]") {
                         col.data.getText = MainTreeCol.getEvent(col.data.getText);
@@ -315,9 +314,6 @@ var projectObj = {
                     if (col.data.field === 'code') {
                         col.data.formatter = '@';
                     }
-                    if(col.data.field==='feeRate'){
-                        feeRateCol=index;
-                    }
                 });
 
                 that.project.calcProgram.compileAllTemps();
@@ -327,8 +323,8 @@ var projectObj = {
                 that.mainController.bind('refreshBaseActn', that.refreshBaseActn);
                 that.mainController.bind(TREE_SHEET_CONTROLLER.eventName.beforeTreeSelectedChange, that.beforeMainTreeSelectedChange);
                 that.mainController.bind(TREE_SHEET_CONTROLLER.eventName.treeSelectedChanged, that.treeSelectedChanged);
+
                 that.mainSpread.bind(GC.Spread.Sheets.Events.EditEnded, that.mainSpreadEditEnded);
-                feeRateObject.setFeeRateCellCol(that.mainSpread.getActiveSheet(),feeRateCol);
                 that.loadMainSpreadContextMenu();
             }
             else {
@@ -552,16 +548,30 @@ $('#poj-set').on('show.bs.modal', function () {
     }
     if (projectObj.project) {
         let mode = projectObj.project.projSetting.billsCalcMode;
-        setCalcFlag($('#rationContent'), projectObj.project.projSetting.billsCalcModeConst.rationContent, mode);
-        setCalcFlag($('#rationPrice'), projectObj.project.projSetting.billsCalcModeConst.rationPrice, mode);
-        setCalcFlag($('#rationPriceConverse'), projectObj.project.projSetting.billsCalcModeConst.rationPriceConverse, mode);
-        setCalcFlag($('#billsPrice'), projectObj.project.projSetting.billsCalcModeConst.billsPrice, mode);
+        let settingConst = projectObj.project.projSetting.settingConst;
+        setCalcFlag($('#rationContent'), settingConst.billsCalcMode.rationContent, mode);
+        setCalcFlag($('#rationPrice'), settingConst.billsCalcMode.rationPrice, mode);
+        setCalcFlag($('#rationPriceConverse'), settingConst.billsCalcMode.rationPriceConverse, mode);
+        setCalcFlag($('#billsPrice'), settingConst.billsCalcMode.billsPrice, mode);
+
+        mode = projectObj.project.projSetting.zanguCalcMode;
+        setCalcFlag($('#zangu_common'), settingConst.zanguCalcMode.common, mode);
+        setCalcFlag($('#zangu_gatherMatherial'), settingConst.zanguCalcMode.gatherMaterial, mode);
     }
 });
 $('#property_ok').click(function () {
-    let project = projectObj.project, mode = parseInt($("input[name='calcFlag']:checked").val());
+    let project = projectObj.project, reCalc= false;
+    let mode = parseInt($("input[name='calcFlag']:checked").val());
+    let zanguMode = parseInt($("input[name='zangu']:checked").val());
     if (mode !== project.projSetting.billsCalcMode) {
         project.setBillsCalcMode(mode);
+        reCalc = true;
+    }
+    if (zanguMode !== project.projSetting.zanguCalcMode) {
+        project.projSetting.zanguCalcMode = zanguMode;
+        reCalc = true;
+    }
+    if (reCalc) {
         projectObj.calculateAll();
         project.pushNow('editBillsCalcMode',
             [project.projSetting.moduleName, project.Bills.getSourceType()],