Browse Source

导入标准文件相关

zhongzewei 6 years atrás
parent
commit
53af81edc2

+ 12 - 3
modules/pm/controllers/pm_controller.js

@@ -39,7 +39,6 @@ let callback = function(req, res, err, message, data){
 
 module.exports = {
     checkRight: function (req, res) {
-        return true;
         if(typeof req.body.data === 'object'){
             req.body.data = JSON.stringify(req.body.data);
         }
@@ -751,6 +750,16 @@ module.exports = {
             callback(req, res, 1, err, null);
         }
     },
+    getProjectPlaceholder: async function(req, res) {
+        let data = JSON.parse(req.body.data);
+        try {
+            let countRst = await pm_facade.getProjectPlaceholder(data);
+            callback(req, res, 0, 'succes', countRst);
+        } catch (err) {
+            console.log(err);
+            callback(req, res, 1, err, null);
+        }
+    },
     importInterface: async function(req, res) {
         logger.info(`${req.ip} importInterface`);
         const uploadOption = {
@@ -770,9 +779,9 @@ module.exports = {
                 if (!srcStr) {
                     throw '无有效数据'
                 }
-                let srcData = JSON.parse(srcStr);
+                let importData = JSON.parse(srcStr);
                 fs.unlinkSync(file.path);
-                let projectData = await pm_facade.importProject(srcData, req.session.sessionUser.id, req.session.sessionCompilation._id);
+                let projectData = await pm_facade.importProject(importData, req.session.sessionUser.id, req.session.sessionCompilation._id);
                 callback(req, res, 0, '', projectData);
             } catch (err) {
                 console.log(err);

+ 218 - 238
modules/pm/facade/pm_facade.js

@@ -27,7 +27,8 @@ module.exports={
     getBasicInfo: getBasicInfo,
     getProjectFeature: getProjectFeature,
     getProjectByGranularity: getProjectByGranularity,
-    importProject: importProject
+    importProject: importProject,
+    getProjectPlaceholder: getProjectPlaceholder
 };
 
 
@@ -65,6 +66,8 @@ let engineeringModel = mongoose.model('engineering_lib');
 let basicInfoModel = mongoose.model('std_basic_info_lib');
 let projectFeatureModel = mongoose.model('std_project_feature_lib');
 let productModel = mongoose.model('product');
+let stdRationItemModel = mongoose.model('std_ration_lib_ration_items');
+let stdGljItemModel = mongoose.model('std_glj_lib_gljList');
 import BillsTemplateModel from "../models/templates/bills_template_model";
 
 let featureLibModel =  mongoose.model("std_project_feature_lib");
@@ -79,14 +82,11 @@ const notDeleted = [{deleteInfo: null}, {'deleteInfo.deleted': false}];
 import {
     defaultDecimal,
     billsQuantityDecimal,
-    basicInformation,
-    projectFeature,
     displaySetting,
     calcOptions,
     tenderSetting,
     G_FILE_VER
 } from '../models/project_property_template';
-import UnitPriceFileModel from "../../glj/models/unit_price_file_model";
 let labourCoeFacade = require('../../main/facade/labour_coe_facade');
 let calcProgramFacade = require('../../main/facade/calc_program_facade');
 let mainColLibModel = mongoose.model('std_main_col_lib');
@@ -1161,38 +1161,56 @@ async function getProjectByGranularity(tenderID, granularity, userID, versionNam
     return constructionProject;
 }
 
+//获取项目数据占位ID
+async function getProjectPlaceholder(data) {
+    let rst = {};
+    //项目本身数据
+    if (data.projectCount) {
+        let projectCount = await counter.counterDAO.getIDAfterCountSync(counter.moduleName.project, data.projectCount);
+        rst.project = projectCount.sequence_value - data.projectCount + 1;
+    }
+    //项目人材机数据
+    if (data.projectGLJCount) {
+        let projectGLJCount =  await counter.counterDAO.getIDAfterCountSync(counter.moduleName.glj_list, data.projectGLJCount);
+        rst.projectGLJ = projectGLJCount.sequence_value - data.projectGLJCount + 1;
+    }
+    //组成物数据
+    if (data.ratioCount) {
+        let ratioCount = await counter.counterDAO.getIDAfterCountSync(counter.moduleName.mix_ratio, data.ratioCount);
+        rst.ratio = ratioCount.sequence_value - data.ratioCount + 1;
+    }
+    //单价文件数据
+    if (data.unitPriceFileCount) {
+        let unitPriceFileCount = await counter.counterDAO.getIDAfterCountSync(counter.moduleName.unit_price_file, data.unitPriceFileCount);
+        rst.unitPriceFile = unitPriceFileCount.sequence_value - data.unitPriceFileCount + 1;
+    }
+    //单价数据
+    if (data.unitPriceCount) {
+        let unitPriceCount = await counter.counterDAO.getIDAfterCountSync(counter.moduleName.unit_price, data.unitPriceCount);
+        rst.unitPrice = unitPriceCount.sequence_value - data.unitPriceCount + 1;
+    }
+    return rst;
+}
+
 /*
 * 项目详细数据都导入完成了,再生成项目数据(项目管理界面数据)
 * */
 async function importProject(importObj, userID, compilationID) {
     let toInsertProjects = [importObj];  //待新增项目数据
-    //获取项目ID
-    let projectIDs = await counter.counterDAO.getIDAfterCountSync(counter.moduleName.project, importObj.projectCount);
-    let curID = projectIDs.sequence_value - importObj.projectCount + 1;
-    importObj.ID = curID++;
     await setupProject(importObj);
     //设置项目ID及相关数据
-    for (let i = 0; i < importObj.engs.length; i++) {
-        let curEng = importObj.engs[i],
-            nextEng = importObj.engs[i + 1];
-        curEng.ID = curID++;
-        curEng.ParentID = importObj.ID;
+    for (let curEng of importObj.engs) {
         await setupProject(curEng);
         toInsertProjects.push(curEng);
-        for (let j = 0; j < curEng.tenders.length; j++) {
-            let curTender = curEng.tenders[j],
-                nextTender = curEng.tenders[j + 1];
-            curTender.ID = curID++;
-            curTender.ParentID = curEng.ID;
-            curTender.NextSiblingID = nextTender ? curID : -1;
-            curTender.property.rootProjectID = importObj.ID;
-            await setupProject(curTender);
+        for (let curTender of curEng.tenders) {
+            await setupProject(curTender.tender);
             //插入单位工程的详细数据
             await importTenderDetail(curTender);
-            toInsertProjects.push(curTender);
+            toInsertProjects.push(curTender.tender);
         }
-        curEng.NextSiblingID = nextEng ? curID : -1;
+        delete curEng.tenders;
     }
+    delete importObj.engs;
     //项目内部数据设置、新增完毕后,插入项目本身的数据,更新前节点数据
     let bulks = [];
     //如果有前节点,更新前节点
@@ -1201,23 +1219,32 @@ async function importProject(importObj, userID, compilationID) {
             updateOne: {filter: {ID: importObj.preID}, update: {$set: {NextSiblingID: importObj.ID}}}
         });
     }
-    let needFields = ['ID', 'ParentID', 'NextSiblingID', 'name', 'projType', 'userID', 'compilation',
-                     'createDateTime', 'fileVer', 'property', 'shareInfo', 'fullFolder'],
-        rst = [];
     for (let insertP of toInsertProjects) {
-        let needData= {};
-        for (let needField of needFields) {
-            needData[needField] = insertP[needField];
-        }
-        rst.push(needData);
         bulks.push({
-            insertOne: {document: needData}
+            insertOne: {document: insertP}
         });
     }
     if (bulks.length > 0) {
         await projectModel.bulkWrite(bulks);
     }
-    return rst;
+    let summaryInfo = await getSummaryInfo([importObj.ID]);
+    //设置汇总字段
+    for(let proj of toInsertProjects){
+        let summaryProj = summaryInfo[proj.ID];
+        if(summaryProj){
+            proj.engineeringCost = summaryProj.engineeringCost;
+            proj.subEngineering = summaryProj.subEngineering;
+            proj.measure = summaryProj.measure;
+            proj.safetyConstruction = summaryProj.safetyConstruction;
+            proj.other = summaryProj.other;
+            proj.charge = summaryProj.charge;
+            proj.tax = summaryProj.tax;
+            proj.rate = summaryProj.rate;
+            proj.buildingArea = summaryProj.buildingArea;
+            proj.perCost = summaryProj.perCost;
+        }
+    }
+    return toInsertProjects;
 
 
     //给项目数据设置一些需要的数据
@@ -1237,13 +1264,22 @@ async function importProject(importObj, userID, compilationID) {
         //更新基本信息, 按照key匹配
         let infoLib = await getBasicInfo(data.compilation);
         if (infoLib) {
+            //标准基本信息库的数据打平
             let flatDatas = [];
             infoLib.info.forEach(ifData => flatDatas.push(...ifData.items));
             data.basicInformation.forEach(importI => {
-                let matchData = flatDatas.find(f => f.key === importI.key);
-                if (matchData) {
-                    matchData.value = importI.value;
-                }
+                flatDatas.forEach(item => {
+                    if (item.key === 'engineeringName') {
+                        item.value = data.name;
+                    } else if (item.key === 'fileKind') {
+                        item.value = {'1': '投标', '2': '招标'}[data.property.fileKind]
+                    } else if (item.key === 'taxModel') {
+                        item.value = {'1': '一般计税法', '2': '简易计税法'}[data.property.taxType]
+                    }
+                    if (item.key === importI.key) {
+                        item.value = importI.value;
+                    }
+                });
             });
         }
         data.property.basicInformation = infoLib ? infoLib.info : [];
@@ -1280,12 +1316,11 @@ async function importProject(importObj, userID, compilationID) {
                 }
             });
             //设置工程专业的值为费用标准的值..
-            let engData = featureLib.feature.find(function (d) {
-                return d.key === 'engineering';
+            featureLib.feature.forEach(f => {
+                if (f.key === 'engineering') {
+                    f.value = data.property.feeStandardName;
+                }
             });
-            if (engData) {
-                engData.value = data.feeName;
-            }
         }
         data.property.projectFeature = featureLib ? featureLib.feature : [];
     }
@@ -1295,218 +1330,163 @@ async function importProject(importObj, userID, compilationID) {
 async function importTenderDetail(tenderData) {
     //单价文件
     let upFile = {
-        name: tenderData.name,
-        project_id: tenderData.ID,
-        user_id: tenderData.userID,
-        root_project_id: tenderData.property.rootProjectID
+        id: tenderData.tender.property.unitPriceFile.id,
+        name: tenderData.tender.name,
+        project_id: tenderData.tender.ID,
+        user_id: tenderData.tender.userID,
+        root_project_id: tenderData.tender.property.rootProjectID
     };
-    let unitPriceFileModel = new UnitPriceFileModel();
-    let addResult = await unitPriceFileModel.add(upFile);
-    if (!addResult) {
-        throw '新增单价文件失败';
-    }
-    tenderData.property.unitPriceFile.id = parseInt(addResult.id);
+    await unitPriceFileModel.create(upFile);
     //费率文件
-    let feeRateFileID = await feeRate_facade.newFeeRateFile(tenderData.userID, tenderData);
-    tenderData.property.feeFile = feeRateFileID ? feeRateFileID : -1;
+    let feeRateFileID = await feeRate_facade.newFeeRateFile(tenderData.tender.userID, tenderData.tender);
+    tenderData.tender.property.feeFile = feeRateFileID ? feeRateFileID : -1;
     //人工系数文件
-    let lcFile = await labourCoeFacade.newProjectLabourCoe(tenderData);
-    tenderData.property.labourCoeFile = lcFile ? lcFile : null;
-    let cpFile = await calcProgramFacade.newProjectCalcProgramFile(tenderData);
-    tenderData.property.calcProgramFile = cpFile ? cpFile : null;
+    let lcFile = await labourCoeFacade.newProjectLabourCoe(tenderData.tender);
+    tenderData.tender.property.labourCoeFile = lcFile ? lcFile : null;
+    let cpFile = await calcProgramFacade.newProjectCalcProgramFile(tenderData.tender);
+    tenderData.tender.property.calcProgramFile = cpFile ? cpFile : null;
     //列设置
     let engineeringModel = new EngineeringLibModel();
-    let engineering = await engineeringModel.getEngineering(tenderData.property.engineering_id);
-    let mainTreeCol = await mainColLibModel.findOne({ID: tenderData.property.colLibID});
-    await projectSettingModel.create({projectID: tenderData.ID, main_tree_col: mainTreeCol.main_tree_col, glj_col: engineering.glj_col});
+    let engineering = await engineeringModel.getEngineering(tenderData.tender.property.engineering_id);
+    let mainTreeCol = await mainColLibModel.findOne({ID: tenderData.tender.property.colLibID});
+    await projectSettingModel.create({projectID: tenderData.tender.ID, main_tree_col: mainTreeCol.main_tree_col, glj_col: engineering.glj_col});
     //清单
-    await importBills(tenderData);
-}
-
-//插入单位工程的清单
-async function importBills(tenderData) {
-    //获取清单模板数据
-    let billsTemplateModel = new BillsTemplateModel();
-    let templateData = await billsTemplateModel.getTemplateDataForNewProj(tenderData.property.templateLibID);
-    let billsDatas = JSON.parse(JSON.stringify(templateData));
-    //设置同层序号,为了后续过滤掉非必要模板数据、插入接口清单数据后,能生成正确的顺序的树
-    setSeqByNext(billsDatas);
-    function getFlag(data) {
-        return data.flags && data.flags[0] && data.flags[0].flag || '';
-    }
-    //过滤掉不含清单固定类别的模板数据 (导入接口只包含必要的清单模板数据)
-    let needfulDatas = billsDatas.filter(data => getFlag(data));
-    sortToTreeData(tenderData.ID, needfulDatas);
-    let newDatas = [];
-    //如果模板存在分部分项,插入分部分项数据
-    insertAndUpdate(billsFlags.SUB_ENGINERRING, tenderData.fbfx);
-    //技术措施项目
-    insertAndUpdate(billsFlags.CONSTRUCTION_TECH, tenderData.csxm.jscs);
-    //组织措施项目
-    insertAndUpdate(billsFlags.CONSTRUCTION_ORGANIZATION, tenderData.csxm.zzcs);
-    //暂列
-    insertAndUpdate(billsFlags.PROVISIONAL, tenderData.other.provisional);
-    //专业工程暂估
-    insertAndUpdate(billsFlags.ENGINEERING_ESITIMATE, tenderData.other.engineeringPro);
-    //计日工-人工
-    insertAndUpdate(billsFlags.LABOUR, tenderData.other.dayWork.labour);
-    //计日工-材料
-    insertAndUpdate(billsFlags.MATERIAL, tenderData.other.dayWork.material);
-    //计日工-机械
-    insertAndUpdate(billsFlags.MACHINE, tenderData.other.dayWork.machine);
-    //总承包服务费
-    insertAndUpdate(billsFlags.TURN_KEY_CONTRACT, tenderData.other.service);
-    //索赔
-    insertAndUpdate(billsFlags.CLAIM, tenderData.other.claim);
-    //签证
-    insertAndUpdate(billsFlags.VISA, tenderData.other.visa);
-    //其他
-    //找出材料工程设备暂估价
-    let materialPro = tenderData.other.others.find(data => data.name === '材料(工程设备)暂估价');
-    if (materialPro) {
-        tenderData.other.others.splice(tenderData.other.others.indexOf(materialPro), 1);
-        update(billsFlags.MATERIAL_PROVISIONAL, materialPro);
-    }
-    insertAndUpdate(billsFlags.OTHER, tenderData.other.others);
-    //规费和税金,非规费税金
-    let notChargeAndTax = [];
-    tenderData.chargeTax.forEach(data => {
-        if (data.name === '规费') {
-            update(billsFlags.CHARGE, data);
-        } else if (data.name === '税金') {
-            update(billsFlags.TAX, data);
-        } else {
-            notChargeAndTax.push(data);
+    if (tenderData.bills.length) {
+        await billsModel.insertMany(tenderData.bills);
+    }
+    //投标文件中,才会有下面这些数据
+    if (enterDetail(tenderData)) {
+        //匹配标准数据,更新一些标准数据
+        await setupStdData(tenderData);
+        let task = [];
+        //定额
+        if (tenderData.ration.length) {
+            task.push(rationModel.insertMany(tenderData.ration))
         }
-    });
-    //除了规费税金,就是税金下的增值税等数据
-    insertAndUpdate(billsFlags.TAX, notChargeAndTax);
-    insertAndUpdate(billsFlags.CHARGE, tenderData.chargeTax);
-    newDatas.push(...needfulDatas);
-    console.log(newDatas);
-    await billsModel.insertMany(newDatas);
-    //数据插入到数据库中
-    return newDatas;
-    //给新增数据设置ID数据,并且添加到待新增数组中
-    function setIDs(projectID, parentID, datas) {
-        newDatas.push(...datas);
-        datas.forEach((data) => {
-            data.projectID = tenderData.ID;
-            data.ID = uuidV1();
-            data.ParentID = parentID;
-        });
-        for (let i = 0; i < datas.length; i++) {
-            let cur = datas[i],
-                next = datas[i + 1];
-            cur.NextSiblingID = next ? next.ID : -1;
-            if (cur.items && cur.items.length) {
-                setIDs(projectID, cur.ID, cur.items);
-            }
+        //定额人材机
+        if (tenderData.rationGLJ.length) {
+            task.push(rationGLJModel.insertMany(tenderData.rationGLJ));
         }
-    }
-    //单独更新一条数据
-    function update(flag, data) {
-        let target = needfulDatas.find(data => getFlag(data) === flag);
-        if (target) {
-            for (let [k, v] of Object.entries(data)) {
-                target[k] = v;
-            }
+        //定额调整系数
+        if (tenderData.rationCoe.length) {
+            task.push(rationCoeModel.insertMany(tenderData.rationCoe));
         }
-    }
-    //插入、更新数据
-    function insertAndUpdate(flag, inserts) {
-        if (!inserts || !inserts.length) {
-            return;
+        //项目人材机
+        if (tenderData.projectGLJ.length) {
+            task.push(gljListModel.insertMany(tenderData.projectGLJ));
         }
-        let target = needfulDatas.find(data => getFlag(data) === flag);
-        if (target) {
-            let targetChildren = needfulDatas.filter(data => data.ParentID == target.ID);
-            for (let insertData of inserts) {
-                //存在同名模板数据
-                let sameNameData = targetChildren.find(data => data.name === insertData.name);
-                if (sameNameData) {
-                    //将插入数据的子数据插入到同名模板数据中
-                    setIDs(tenderData.ID, sameNameData.ID, insertData.items);
-                    //更新该模板数据的一些值
-                    for (let [k, v] of Object.entries(insertData)) {
-                        sameNameData[k] = v;
-                    }
-                } else {    //不存在同名模板,直接将数据插入到目标中
-                    setIDs(tenderData.ID, target.ID, [insertData]);
-                }
-            }
+        //组成物
+        if (tenderData.mixRatio.length) {
+            task.push(mixRatioModel.insertMany(tenderData.mixRatio));
         }
+        //单价文件
+        if (tenderData.unitPrice.length) {
+            task.push(unitPriceModel.insertMany(tenderData.unitPrice));
+        }
+        await Promise.all(task);
+    }
+    //继续处理定额等数据
+    function enterDetail(tenderData) {
+        return tenderData.ration.length ||
+            tenderData.rationGLJ.length ||
+            tenderData.projectGLJ.length ||
+            tenderData.mixRatio.length ||
+            tenderData.unitPrice.length;
     }
-
 }
-
-/*
-* 将同层的清单数据,按照树结构顺序设置序号
-* @param {Array} billsData(清单模板数据)
-* */
-function setSeqByNext(billsData) {
-    //获取同层数据
-    let sameDepthDatas = {};    //按照ParentID区分
-    for (let data of billsData) {
-        if (!sameDepthDatas[data.ParentID]) {
-            sameDepthDatas[data.ParentID] = [];
+//匹配标准数据,需要匹配标准定额,更新导入的定额人材机的定额消耗量等数据
+async function setupStdData(tenderData) {
+    //获取标准定额数据 (定额子目的编码查找)
+    let matchRationCodes = [...new Set(tenderData.ration.map(ration => ration.code))];
+    if (!matchRationCodes.length) {
+        return;
+    }
+    //限制在当前费用定额可用的定额库里查找
+    let stdRations = await stdRationItemModel.find({code: {$in: matchRationCodes}, rationRepId: {$in: tenderData.tender.rationLibIDs}},
+                                                    '-_id -rationAssList -rationCoeList -rationInstList');
+    //标准定额code - 映射
+    let stdRationCodeMap = {};
+    stdRations.forEach(stdRation => stdRationCodeMap[stdRation.code] = stdRation);
+    //获取标准人材机数据 (人材机汇总的编码查找)
+    let matchGLJCodes = [...new Set(tenderData.projectGLJ.map(pGLJ => pGLJ.original_code))];
+    if (!matchGLJCodes.length) {
+        return;
+    }
+    //限制在当前费用定额可用的人材机库里查找
+    let stdGLJs = await stdGljItemModel.find({code: {$in: matchGLJCodes}, repositoryId: {$in: tenderData.tender.gljLibIDs}},
+                                             '-_id -component -priceProperty');
+    //标准人材机code - 映射
+    let stdGLJCodeMap = {};
+    stdGLJs.forEach(stdGLJ => stdGLJCodeMap[stdGLJ.code] = stdGLJ);
+    //更新定额数据
+    tenderData.ration.forEach(r => {
+        let stdRation = stdRationCodeMap[r.code];
+        if (stdRation) {
+            r.caption = stdRation.caption;
+            r.from = 'std';
+            r.libID = stdRation.rationRepId;
+            r.stdID = stdRation.ID;
+            r.prefix = stdRation.rationRepId == tenderData.tender.defaultRationLib ? '' : '借';
+            r.content = stdRation.jobContent;
+        } else {
+            r.from = 'cpt';
+            r.prefix = '补';
         }
-        sameDepthDatas[data.ParentID].push(data);
-    }
-    //设置同层节点的序号
-    for (let sameDepth of Object.values(sameDepthDatas)) {
-        let sortedData = getDataBySorted(sameDepth),
-            seq = 1;
-        sortedData.forEach((data => data.seq = seq++));
-    }
-    //将每个同层的数据设置好序号
-    //获取根据树结构NextSibling排序的同层数据
-    function getDataBySorted(datas) {
-        //链断了返回空数组
-        let target = [];
-        let last = datas.find(data => data.NextSiblingID == -1);
-        while (last && target.length !== datas.length) {
-            target.push(last);
-            last = datas.find(data => data.NextSiblingID == last.ID);
+    });
+    //更新定额人材机数据
+    tenderData.rationGLJ.forEach(rGLJ => {
+        rGLJ.from = 'cpt';
+        //匹配定额
+        let stdRation = stdRationCodeMap[rGLJ.rationCode];
+        if (stdRation) {
+            //根据导入数据的定额人材机编码匹配人材机
+            let stdGLJ = stdGLJCodeMap[rGLJ.original_code];
+            if (stdGLJ) {
+                rGLJ.from = 'std';
+                rGLJ.GLJID = stdGLJ.ID;
+                rGLJ.type = stdGLJ.gljType;
+                rGLJ.shortName = stdGLJ.shortName;
+                rGLJ.repositoryId = stdGLJ.repositoryId;
+                rGLJ.model = stdGLJ.model;
+                rGLJ.adjCoe = stdGLJ.adjCoe;
+                //找匹配到的标准定额中定额人材机的相应人材机,更新定额消耗
+                let stdRationGLJ = stdRation.rationGljList.find(data => data.gljId === stdGLJ.ID);
+                if (stdRationGLJ) {
+                    rGLJ.rationItemQuantity = stdRationGLJ.consumeAmt;
+                }
+            }
         }
-        //链断了即清单模板数据的树结构有问题,这里做下兼容:
-        // 1.数据没问题,返回排序过后的同层数据数组    2.数据有问题,返回不排序的同层数组
-        return target.length === datas.length ? target.reverse() : datas;
-    }
-}
-
-//根据同层序号,设置NextSiblingID
-function sortSeqToNextSibling(needfulData) {
-    let sameDepthDatas = {};    //按照ParentID区分
-    for (let data of needfulData) {
-        if (!sameDepthDatas[data.ParentID]) {
-            sameDepthDatas[data.ParentID] = [];
+    });
+    //更新人材机汇总数据
+    tenderData.projectGLJ.forEach(pGLJ => {
+        let stdGLJ = stdGLJCodeMap[pGLJ.original_code];
+        if (stdGLJ) {
+            pGLJ.glj_id = stdGLJ.ID;
+            if (pGLJ.type !== stdGLJ.gljType) { //更新组成物connect_key
+                let keyStr = [pGLJ.code, pGLJ.name, pGLJ.specs, pGLJ.unit, pGLJ.type].join('|-|');
+                let ratios = tenderData.mixRatio.filter(ratio =>
+                    ratio.connect_key === keyStr);
+                let newKeyStr = [pGLJ.code, pGLJ.name, pGLJ.specs, pGLJ.unit, stdGLJ.gljType].join('|-|');
+                ratios.forEach(ratio => ratio.connect_key = newKeyStr);
+            }
+            pGLJ.type = stdGLJ.gljType;  //更新类型,标准的数据类型更准确,导入的类型数据有细分识别不了
         }
-        sameDepthDatas[data.ParentID].push(data);
-    }
-    for (let sameDepth of Object.values(sameDepthDatas)) {
-        sameDepth.sort((a, b) => a.seq - a.seq);
-        for (let i = 0; i < sameDepth.length; i++) {
-            let cur = sameDepth[i],
-                next = sameDepth[i + 1];
-            cur.NextSiblingID = next ? next.ID : -1;
+    });
+    //更新单价文件数据
+    tenderData.unitPrice.forEach(up => {
+        let stdGLJ = stdGLJCodeMap[up.original_code];
+        if (stdGLJ) {
+            up.glj_id = stdGLJ.ID;
+            up.type = stdGLJ.gljType;
+            up.short_name = stdGLJ.shortName;
+        }
+    });
+    //更新组成物数据
+    tenderData.mixRatio.forEach(ratio => {
+        let stdGLJ = stdGLJCodeMap[ratio.code];
+        if (stdGLJ) {
+            ratio.glj_id = stdGLJ.ID;
+            ratio.type = stdGLJ.gljType;
         }
-    }
-}
-
-//清单模板数据转换为uuID树结构数据
-function sortToTreeData(projectID, needfulData) {
-    sortSeqToNextSibling(needfulData);
-    let uuidMaping = {};
-    uuidMaping['-1'] = -1;
-    //建立uuid-ID映射
-    for(let bill of needfulData){
-        uuidMaping[bill.ID] = uuidV1();
-    }
-    needfulData.forEach(function (template) {
-        template.projectID = projectID;
-        template.ID = uuidMaping[template.ID] ? uuidMaping[template.ID] : -1;
-        template.ParentID = uuidMaping[template.ParentID] ? uuidMaping[template.ParentID] : -1;
-        template.NextSiblingID = uuidMaping[template.NextSiblingID] ? uuidMaping[template.NextSiblingID] : -1;
     });
 }

+ 31 - 14
modules/pm/models/project_model.js

@@ -183,15 +183,22 @@ ProjectsDAO.prototype.updateUserProjects = async function (userId, compilationId
                     data.updateData.property.lockBills = false;
                     //工料机单价调整系数
                     data.updateData.property.tenderSetting = tenderSetting;
+                } else if (data.updateData.projType === projectType.project) {
+                    //更新基本信息
+                    data.updateData.property.basicInformation.forEach(function (pData) {
+                        pData.items.forEach(function (item) {
+                            if (item.key === 'engineeringName') {
+                                item.value = data.updateData.name;
+                            } else if (item.key === 'fileKind') {
+                                item.value = {'1': '投标', '2': '招标'}[data.updateData.property.fileKind]
+                            } else if (item.key === 'taxModel') {
+                                item.value = {'1': '一般计税法', '2': '简易计税法'}[data.updateData.property.taxType]
+                            }
+                        });
+                    });
                 }
-
                 newProject = new Projects(data.updateData);
-               /* // 查找同级是否存在同名数据
-                let exist = await this.isExist(userId, compilationId, data.updateData.name, data.updateData.ParentID);
-                if (exist) {
-                    callback(1, '同级目录已存在相同名称数据.', null);
-                    return;
-                }*/
+
                 if (data.updateData.projType === 'Tender') {
                     let feeRateFileID = await feeRateFacade.newFeeRateFile(userId, data.updateData);
                     newProject.property.feeFile = feeRateFileID ? feeRateFileID : -1;
@@ -392,13 +399,23 @@ ProjectsDAO.prototype.rename = async function (userId, compilationId, data, call
             throw '请填写名称!';
         }
         data.newName = data.newName.trim();
-        //重名前端控制
-       /* // 查找同级是否存在同名数据
-        let exist = await this.isExist(userId, compilationId, data.newName, data.parentID);
-        if (exist) {
-            throw '同级目录已存在相同名称数据';
-        }*/
-
+        let project = await Projects.findOne({ID: data.id});
+        if (!project) {
+            throw '项目不存在';
+        }
+        if (project.projType === 'Project' && project.property && Array.isArray(project.property.basicInformation)) {
+            //更新基本信息
+            project.property.basicInformation.forEach(function (pData) {
+                pData.items.forEach(function (item) {
+                    if (item.key === 'engineeringName') {
+                        item.value = data.newName;
+                    }
+                });
+            });
+            await Projects.update({ID: data.id}, {$set: {name: data.newName, 'property.basicInformation': project.property.basicInformation}});
+        } else {
+            await Projects.update({ID: data.id}, {$set: {name: data.newName}});
+        }
         Projects.update({userID: userId, ID: data.id}, {name: data.newName}, function (err) {
             if (err) {
                 throw '项目不存在';

+ 5 - 1
modules/pm/routes/pm_route.js

@@ -65,8 +65,12 @@ module.exports = function (app) {
     pmRouter.post('/getProjectFeature', pmController.getProjectFeature);
     pmRouter.post('/getProjectByGranularity', pmController.getProjectByGranularity);
 
-    pmRouter.post('/importInterface', pmController.importInterface);
     app.use('/pm/api', pmRouter);
+
+    let importRouter = express.Router();
+    importRouter.post('/getProjectPlaceholder', pmController.getProjectPlaceholder);
+    importRouter.post('/importInterface', pmController.importInterface);
+    app.use('/pm/import', importRouter);
 };
 
 

+ 10 - 0
modules/templates/controllers/bills_template_controller.js

@@ -33,5 +33,15 @@ module.exports = {
         BillsTemplateData.getNewBillsTemplateID(data.count, function (err, message, data) {
             callback(req, res, err, message, data);
         });
+    },
+    getNeedfulTemplate: async function (req, res) {
+        let data = JSON.parse(req.body.data);
+        try {
+            let needfulDatas = await BillsTemplateData.getNeedfulTemplate(data.templateLibID);
+            callback(req, res, 0, 'succes', needfulDatas);
+        } catch (err) {
+            console.log(err);
+            callback(req, res, 1, err, null);
+        }
     }
 }

+ 88 - 0
modules/templates/models/bills_template.js

@@ -6,6 +6,8 @@ let counter = require("../../../public/counter/counter.js");
 let mongoose = require('mongoose');
 let BillsTemplates = mongoose.model('temp_bills');
 let BillsTemplateDAO = function(){};
+import BillsTemplateModel from "../../pm/models/templates/bills_template_model";
+const uuidV1 = require('uuid/v1');
 
 BillsTemplateDAO.prototype.getTemplate = function (type, callback) {
     if (callback) {
@@ -68,4 +70,90 @@ BillsTemplateDAO.prototype.getNewBillsTemplateID = function (count, callback) {
     });
 }
 
+//过滤掉非必要清单的清单模板
+BillsTemplateDAO.prototype.getNeedfulTemplate = async function (templateLibID) {
+    let billsTemplateModel = new BillsTemplateModel();
+    let templateData = await billsTemplateModel.getTemplateDataForNewProj(templateLibID);
+    let billsDatas = JSON.parse(JSON.stringify(templateData));
+    //设置同层序号,为了后续过滤掉非必要模板数据、插入接口清单数据后,能生成正确的顺序的树
+    setSeqByNext(billsDatas);
+    function getFlag(data) {
+        return data.flags && data.flags[0] && data.flags[0].flag || '';
+    }
+    //过滤掉不含清单固定类别的模板数据 (导入接口只包含必要的清单模板数据)
+    let needfulDatas = billsDatas.filter(data => getFlag(data));
+    sortToTreeData(needfulDatas);
+    return needfulDatas;
+};
+
+/*
+ * 将同层的清单数据,按照树结构顺序设置序号
+ * @param {Array} billsData(清单模板数据)
+ * */
+function setSeqByNext(billsData) {
+    //获取同层数据
+    let sameDepthDatas = {};    //按照ParentID区分
+    for (let data of billsData) {
+        if (!sameDepthDatas[data.ParentID]) {
+            sameDepthDatas[data.ParentID] = [];
+        }
+        sameDepthDatas[data.ParentID].push(data);
+    }
+    //设置同层节点的序号
+    for (let sameDepth of Object.values(sameDepthDatas)) {
+        let sortedData = getDataBySorted(sameDepth),
+            seq = 1;
+        sortedData.forEach((data => data.seq = seq++));
+    }
+    //将每个同层的数据设置好序号
+    //获取根据树结构NextSibling排序的同层数据
+    function getDataBySorted(datas) {
+        //链断了返回空数组
+        let target = [];
+        let last = datas.find(data => data.NextSiblingID == -1);
+        while (last && target.length !== datas.length) {
+            target.push(last);
+            last = datas.find(data => data.NextSiblingID == last.ID);
+        }
+        //链断了即清单模板数据的树结构有问题,这里做下兼容:
+        // 1.数据没问题,返回排序过后的同层数据数组    2.数据有问题,返回不排序的同层数组
+        return target.length === datas.length ? target.reverse() : datas;
+    }
+}
+
+//根据同层序号,设置NextSiblingID
+function sortSeqToNextSibling(needfulData) {
+    let sameDepthDatas = {};    //按照ParentID区分
+    for (let data of needfulData) {
+        if (!sameDepthDatas[data.ParentID]) {
+            sameDepthDatas[data.ParentID] = [];
+        }
+        sameDepthDatas[data.ParentID].push(data);
+    }
+    for (let sameDepth of Object.values(sameDepthDatas)) {
+        sameDepth.sort((a, b) => a.seq - a.seq);
+        for (let i = 0; i < sameDepth.length; i++) {
+            let cur = sameDepth[i],
+                next = sameDepth[i + 1];
+            cur.NextSiblingID = next ? next.ID : -1;
+        }
+    }
+}
+
+//清单模板数据转换为uuID树结构数据
+function sortToTreeData(needfulData) {
+    sortSeqToNextSibling(needfulData);
+    let uuidMaping = {};
+    uuidMaping['-1'] = -1;
+    //建立uuid-ID映射
+    for(let bill of needfulData){
+        uuidMaping[bill.ID] = uuidV1();
+    }
+    needfulData.forEach(function (template) {
+        template.ID = uuidMaping[template.ID] ? uuidMaping[template.ID] : -1;
+        template.ParentID = uuidMaping[template.ParentID] ? uuidMaping[template.ParentID] : -1;
+        template.NextSiblingID = uuidMaping[template.NextSiblingID] ? uuidMaping[template.NextSiblingID] : -1;
+    });
+}
+
 module.exports = new BillsTemplateDAO();

+ 1 - 0
modules/templates/routes/bills_template_router.js

@@ -37,6 +37,7 @@ module.exports = function (app) {
     billsTemplateRouter.post('/getBillsTemplate', billsTemplateController.getBillsTemplate);
     billsTemplateRouter.post('/updateBillsTemplate', billsTemplateController.updateBillsTemplate);
     billsTemplateRouter.post('/getNewBillsTemplateID', billsTemplateController.getNewBillsTemplateID);
+    billsTemplateRouter.post('/getNeedfulTemplate', billsTemplateController.getNeedfulTemplate);
     app.use('/template/bills/api', billsTemplateRouter);
 }
 

+ 4 - 1
public/counter/counter.js

@@ -21,7 +21,10 @@ const COUNTER_MODULE_NAME = {
     billsLib: 'billsLib',
     coeList: 'coeList',
     complementaryCoeList: 'complementary_coe_list',
-    glj_list: 'glj_list'
+    glj_list: 'glj_list',
+    mix_ratio: 'mix_ratio',
+    unit_price_file: 'unit_price_file',
+    unit_price: 'unit_price'
 }
 /*const PROJECT_COUNTER = 'projects', USER_COUNTER = 'users', BILL_COUNTER = 'bills', RATION_COUNTER = 'rations',
     REPORT_COUNTER = 'rptTemplates', FEE_COUNTER = 'fees'*/

+ 23 - 2
web/building_saas/main/js/models/calc_base.js

@@ -28,13 +28,21 @@ let cbTools = {
     //通过行获取根节点清单
     getBillByRow: function (items, row) {
         if(cbTools.isDef(items[row]) &&
-            cbTools.isUnDef(items[row]['parent'])&&
             cbTools.isDef(items[row]['sourceType']) &&
             items[row]['sourceType'] === calcBase.project.Bills.getSourceType()){
             return items[row];
         }
         return null;
     },
+    /*getBillByRow: function (items, row) {
+        if(cbTools.isDef(items[row]) &&
+            cbTools.isUnDef(items[row]['parent'])&&
+            cbTools.isDef(items[row]['sourceType']) &&
+            items[row]['sourceType'] === calcBase.project.Bills.getSourceType()){
+            return items[row];
+        }
+        return null;
+    },*/
     //通过ID获取节点行
     getRowByID: function (items, ID) {
         for(let i = 0, len = items.length; i < len; i++){
@@ -51,6 +59,7 @@ let cbTools = {
     //获取该节点所有父节点
     getParents: function (node) {
         let rst = [];
+        rst.push(node);
         rParent(node);
         return rst;
         function rParent(node){
@@ -60,6 +69,17 @@ let cbTools = {
             }
         }
     },
+    /*getParents: function (node) {
+        let rst = [];
+        rParent(node);
+        return rst;
+        function rParent(node){
+            if(cbTools.isDef(node.parent)){
+                rst.push(node.parent);
+                rParent(node.parent);
+            }
+        }
+    },*/
     //获取所有节点的ID
     getNodeIDs: function (nodes) {
         let rst = [];
@@ -1123,7 +1143,8 @@ let cbAnalyzer = {
             return false;
         }
         //用于判断的起始清单ID
-        let sIDs = cbTools.getNodeIDs(Array.from(new Set([cbTools.getBaseBill(node)].concat(cbTools.getParents(node)))));
+        //let sIDs = cbTools.getNodeIDs(Array.from(new Set([cbTools.getBaseBill(node)].concat(cbTools.getParents(node)))));
+        let sIDs = cbTools.getNodeIDs(cbTools.getParents(node));
         let figureF = cbParser.getFigureF(cbParser.getFigure(exp), cbParser.getUID(cbParser.getFIDArr(exp)));
         for(let i = 0, len = figureF.length; i < len; i++){
             let figure = figureF[i];

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

@@ -1982,7 +1982,6 @@ class CalcProgram {
                 if (node.children.length > 0) {
                     calcNodes(node.children);
                 };
-
                 if (calcType == calcAllType.catAll || calcType == node.sourceType) {
                     node.calcType = calcTools.getCalcType(node);
                     if (node.calcType != treeNodeCalcType.ctCalcBaseValue)

+ 2 - 1
web/building_saas/main/js/models/exportStandardInterface.js

@@ -40,6 +40,7 @@ const XMLStandard = (function () {
         [fixedFlag.ADDED_VALUE_TAX]: '9001',
         [fixedFlag.ADDITIONAL_TAX]: '9002',
         [fixedFlag.ENVIRONMENTAL_PROTECTION_TAX]: '9003',
+        [fixedFlag.ENGINEERINGCOST]: '1',
         0: '1800',  //其他未定义的大项费用
     };
     //文件类型
@@ -448,7 +449,7 @@ const XMLStandard = (function () {
                 {name: '综合单价', value: getFee(source.fees, 'common.unitFee'), required: true, type: TYPE.DECIMAL},
                 {name: '综合合价', value: getFee(source.fees, 'common.totalFee'), required: true, type: TYPE.NUM2},
                 {name: '单价构成文件ID', value: source.programID, required: true, type: TYPE.INT},
-                {name: '分包标志', value: false, type: TYPE.BOOL},
+                {name: '分包标志', value: !!source.isSubcontract, type: TYPE.BOOL},
                 {name: '备注', value: source.remark}
             ];
             element.call(this, '定额子目', attrs);

File diff suppressed because it is too large
+ 1073 - 58
web/building_saas/main/js/models/importStandardInterface.js


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

@@ -1481,7 +1481,7 @@ var projectObj = {
                         }
                     },
                     visible:function(key, opt){//2018-11-15 新需求隐藏右键“造价计算”。
-                        return false;
+                        return true;
                     }
                 },
                 "spr4":'--------',

+ 58 - 14
web/building_saas/pm/html/project-management.html

@@ -239,6 +239,17 @@
                         </div>
                     </div>
                     <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">计价规则</label>
+                        <div class="col">
+                            <select class="form-control  form-control-sm" id="proj-valuation">
+                                <% for (let valuation of valuationOpts) { %>
+                                <option value="<%= valuation.id %>"><%= valuation.name %></option>
+                                <% } %>
+                            </select>
+                        </div>
+                    </div>
+                    <span class="form-text text-danger" id="proj-valuation-info" style="display: none;">请选择计价规则</span>
+                    <div class="form-group row">
                         <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">文件类型</label>
                         <div class="col">
                             <div class="custom-control custom-radio custom-control-inline">
@@ -336,6 +347,17 @@
                     <span class="form-text text-info" id="poj-name-info" style="display: none;">新建 “汽车生产车间5”</span>
                     <div id="newProjectSet" style="display: none">
                         <div class="form-group row">
+                            <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">计价规则</label>
+                            <div class="col">
+                                <select class="form-control  form-control-sm" id="valuation">
+                                    <% for (let valuation of valuationOpts) { %>
+                                    <option value="<%= valuation.id %>"><%= valuation.name %></option>
+                                    <% } %>
+                                </select>
+                            </div>
+                        </div>
+                        <span class="form-text text-danger" id="valuation-info" style="display: none;">请选择计价规则</span>
+                        <div class="form-group row">
                             <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">文件类型</label>
                             <div class="col">
                                 <div class="custom-control custom-radio custom-control-inline">
@@ -403,27 +425,27 @@
                     </div>
                 </form>
                 <form id="secondStep" style="display: none">
-                    <div class="form-group row">
+                    <!--<div class="form-group row">
                         <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">计价方式</label>
                         <div class="col">
                             <div class="custom-control custom-radio custom-control-inline">
                                 <input type="radio" value="bill" checked id="radioBill" name="valuation_type" class="custom-control-input">
                                 <label class="custom-control-label" for="radioBill">清单计价</label>
                             </div>
-                           <!-- <div class="custom-control custom-radio custom-control-inline">
+                           &lt;!&ndash; <div class="custom-control custom-radio custom-control-inline">
                                 <input type="radio" value="ration" id="radioRation" name="valuation_type" class="custom-control-input">
                                 <label class="custom-control-label" for="radioRation">定额计价</label>
-                            </div>-->
+                            </div>&ndash;&gt;
                         </div>
-                    </div>
-                    <div class="form-group row">
+                    </div>-->
+                    <!--<div class="form-group row">
                         <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">计价规则</label>
                         <div class="col">
                             <select class="form-control  form-control-sm" id="valuation">
                             </select>
                         </div>
                     </div>
-                    <span class="form-text text-danger" id="valuation-info" style="display: none;">请选择计价规则</span>
+                    <span class="form-text text-danger" id="valuation-info" style="display: none;">请选择计价规则</span>-->
                     <div class="form-group row" id="regionDiv" style="display: none;">
                         <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">地&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;区</label>
                         <div class="col">
@@ -779,6 +801,19 @@
                         </div>
                     </div>
                     <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">文件类型</label>
+                        <div class="col">
+                            <div class="custom-control custom-radio custom-control-inline">
+                                <input type="radio" value="1" checked id="radioTender-import" name="fileKind-import" class="custom-control-input">
+                                <label class="custom-control-label" for="radioTender-import">投标</label>
+                            </div>
+                            <div class="custom-control custom-radio custom-control-inline">
+                                <input type="radio" value="2" disabled id="radioBid-import" name="fileKind-import" class="custom-control-input">
+                                <label class="custom-control-label" for="radioBid-import">招标</label>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group row">
                         <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">计价规则</label>
                         <div class="col">
                             <select id="import-valuation" class="form-control form-control-sm">
@@ -788,6 +823,15 @@
                             </select>
                         </div>
                     </div>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">计税方法</label>
+                        <div class="col">
+                            <select id="import-taxType" class="form-control form-control-sm">
+                                <option value="1">一般计税法</option>
+                                <option value="2">简易计税法</option>
+                            </select>
+                        </div>
+                    </div>
                 </form>
             </div>
             <div class="modal-footer">
@@ -866,6 +910,14 @@
 <script src = "/lib/spreadjs/sheets/gc.spread.sheets.all.11.1.2.min.js"></script>
 <script>GC.Spread.Sheets.LicenseKey = '<%- LicenseKey %>';</script>
 <script src="/lib/x2js/xml2json.min.js"></script>
+<script type="text/javascript">
+    let billValuation = JSON.parse('<%- billValuation %>');
+    let rationValuation = JSON.parse('<%- rationValuation %>');
+    let engineeringList = '<%- engineeringList %>';
+    let compilationData = '<%- compilationData %>';
+    compilationData = JSON.parse(compilationData.replace(/[\s\r\n]/g, ""));//去掉空格字符
+    console.log(billValuation);
+</script>
 <!-- inject:js -->
 <script src="/web/building_saas/js/global.js"></script>
 <script src="/public/web/uuid.js"></script>
@@ -898,12 +950,4 @@
 <script type="text/javascript">
     autoFlashHeight();
 </script>
-<script type="text/javascript">
-    let billValuation = JSON.parse('<%- billValuation %>');
-    let rationValuation = JSON.parse('<%- rationValuation %>');
-    let engineeringList = '<%- engineeringList %>';
-    let compilationData = '<%- compilationData %>';
-    compilationData = JSON.parse(compilationData.replace(/[\s\r\n]/g, ""));//去掉空格字符
-    console.log(billValuation);
-</script>
 </html>

+ 83 - 36
web/building_saas/pm/js/pm_import.js

@@ -9,6 +9,7 @@
  */
 //操作接口为eventListen
 const importView = (() => {
+    let importXML = null;
     let xmlObj = null;  //导入xml转化后的对象
     let tbcObj = null;  //待确认对象
     //显示、隐藏提示上传文件窗口相关提示信息
@@ -52,10 +53,12 @@ const importView = (() => {
     }
     //待确认界面相关
     class TBC {
-        constructor(xmlObj, valuation) {
+        constructor(xmlObj, fileKind, valuation, taxType) {
             this.datas = getTenderDatas(xmlObj);
+            this.fileKind = fileKind;   //文件类型
             this.valuationType = 'bill';    //计价方式 暂时默认为清单计价
             this.valuation = valuation;     //计价规则数据
+            this.taxType = taxType; //计税方法
             this.engineeringList = valuation ? valuation.engineering_list : []; //工程专业库数据
             this.curIdx = 0;    //当前单位工程数据索引
             this.init();
@@ -184,7 +187,7 @@ const importView = (() => {
             //根据工程专业及费用标准确定的当前选中的工程专业库
             let curEngineering = engineerings.find(data => data.lib.feeName === tenderData.temp.feeStandard) || engineerings[0];
             //根据计税方法过滤出来的计税组合
-            let taxDatas = curEngineering.lib.tax_group.filter(data => data.taxType == tenderData.taxType);
+            let taxDatas = curEngineering.lib.tax_group.filter(data => data.taxType == this.taxType);
             //计算程序,若当前工程有计算程序(该数据本身没有计算程序数据,选择过了,就会记录),则选中该计算程序
             let calcOptsHtml = taxDatas.map(data =>
                 `<option ${tenderData.temp.calcProgram === data.program_lib.name ? 'selected' : ''} value="${data.program_lib.name}">${data.program_lib.name}</option>`);
@@ -222,7 +225,7 @@ const importView = (() => {
         let query = {
             engineeringName: curData.engineering,
             feeStandard: curData.temp.feeStandard,
-            taxType: curData.taxType,
+            taxType: tbcObj.taxType,    //取导入时选择的计税方法,不读取文件中的计税方法
             calcProgram: curData.temp.calcProgram
         };
         let taxData = getTaxData(query, tbcObj.engineeringList);
@@ -265,17 +268,17 @@ const importView = (() => {
                 if(file.name && !reg.test(file.name)){
                     $('.selFile').hide();
                     showUploadAlert(false, '请选择xml或qtf文件。');
-                    //$('.custom-file-label').text(`${file.name || ''}`);
-                    //$(this).val('');
                     return;
                 }
                 $.bootstrapLoading.start();
                 $('#loadingPage').css('z-index', '2000');
                 //转换数据
-                let importXML = new ImportXML();
+                importXML = new ImportXML();
                 try {
                     xmlObj = await importXML.extractData(file);
-                    $('.selFile input').val(xmlObj && xmlObj.name ? xmlObj.name : '');
+                    $('.selFile input:eq(0)').val(xmlObj && xmlObj.name ? xmlObj.name : '');
+                    $('.selFile input[name="fileKind-import"]:eq(0)').prop('checked', true);    //文件类型恢复成投标
+                    $('#import-taxType').val('1');  //计税方法显示回默认的一般计税法
                     $('.selFile').show();   //显示建设项目、计价规则
                 } catch (err) {
                     console.log(err);
@@ -296,17 +299,28 @@ const importView = (() => {
                 showUploadAlert(false, '不存在有效数据。');
                 return;
             }
-            let projectName = $('.selFile input').val();
+            let projectName = $('.selFile input:eq(0)').val();
             if (!projectName) {
                 showUploadAlert(false, '不存在有效建设项目。');
                 return;
             }
+            //文件类型
+            let fileKind = $('.selFile input[name="fileKind-import"]:checked').val();
+            if (!fileKind) {
+                showUploadAlert(false, '不存在有效文件类型。');
+            }
             //计价规则
             let valuation = $('#import-valuation').val();
             if (!valuation) {
                 showUploadAlert(false, '不存在有效计价规则。');
                 return;
             }
+            //计税方法
+            let taxType = $('#import-taxType').val();
+            if (!taxType) {
+                showUploadAlert(false, '不存在有效计税方法。');
+                return;
+            }
             if (!xmlObj.engs.length) {
                 showUploadAlert(false, '不存在单项工程数据。');
                 return;
@@ -317,10 +331,10 @@ const importView = (() => {
             }
             $('#importInterface .modal-content:eq(0)').hide();  //隐藏第一步内容
             $('#importInterface .modal-content:eq(1)').show();  //显示第二步内容
-            console.log(getTenderDatas(xmlObj));
-            console.log(xmlObj);
+            //console.log(getTenderDatas(xmlObj));
+            //console.log(xmlObj);
             let selValuation = billValuation.find(data => data.id === valuation);
-            tbcObj = new TBC(xmlObj, selValuation);
+            tbcObj = new TBC(xmlObj, fileKind, selValuation, taxType);
         });
         //上一步
         $('#import-prev').click(function () {
@@ -362,48 +376,74 @@ const importView = (() => {
             hideTBCInfo();
         });
         //确认导入
-        $('#import-confirm').click(function () {
+        $('#import-confirm').click(async function () {
             if (tbcObj && tbcObj.checkValid()) {
                 return;
             }
+            //建设项目设置选择的文件类型和选择的计税方法
+            xmlObj.property.fileKind = tbcObj.fileKind;
+            xmlObj.property.taxType = tbcObj.taxType;
             //确定使用的计税组合
             tbcObj.datas.map(data => {
                 data.property = getProperty(tbcObj, data);
+                //默认定额库
+                let curEngineering = tbcObj.engineeringList.find(enData => data.engineering === enData.lib.name &&
+                data.temp.feeStandard === enData.lib.feeName);
+                let defaultLib = curEngineering.lib.ration_lib.find(data => data.isDefault) || curEngineering.lib.ration_lib[0];
+                data.defaultRationLib = parseInt(defaultLib.id);
+                //此费用定额下可用的定额库id,人材机库id
+                data.rationLibIDs = curEngineering.lib.ration_lib.map(data => parseInt(data.id));
+                data.gljLibIDs = curEngineering.lib.glj_lib.map(data => parseInt(data.id));
             });
             //确定生成建设项目的父、前、后节点ID
             let {parentProjectID, preProjectID, nextProjectID} = projTreeObj.getRelProjectID(projTreeObj.tree.selected);
             xmlObj.ParentID = parentProjectID;
             xmlObj.preID = preProjectID;
             xmlObj.NextSiblingID = nextProjectID;
-            console.log(xmlObj);
-            let blob = new Blob([JSON.stringify(xmlObj)], {type: 'text/plain;charset=utf-8'});
-            console.log(blob);
-            let formData = new FormData();
-            formData.append('file', blob);
+            //确定建设项目的名称(不允许重复)
+            let sameDepthProjs = getProjs(projTreeObj.tree.selected);
+            if (sameDepthProjs.find(node => node.data.name === xmlObj.name)) {
+                xmlObj.name += `(${moment(Date.now()).format('YYYY-MM-DD HH:mm:ss')})`;
+            }
+            //console.log(xmlObj);
             $('#importInterface').modal('hide');
+            //let importData = await importXML.transformData(xmlObj);
             let pr = new SCComponent.InitProgressBar($('#progress'), $('#progress-title'), $('#progress-content'), $('#progressBar'));
             pr.start('导入文件', '正在生成文件,请稍候……');
-            $.ajax({
-                url: '/pm/api/importInterface',
-                type: 'POST',
-                data: formData,
-                cache: false,
-                contentType: false,
-                processData: false,
-                success: function(response){
-                    if (response.data && Array.isArray(response.data)) {
-                        doAfterImport(response.data);
+            try {
+                let importData = await importXML.transformData(xmlObj);
+                let blob = new Blob([JSON.stringify(importData)], {type: 'text/plain;charset=utf-8'});
+                console.log(blob);
+                let formData = new FormData();
+                formData.append('file', blob);
+                $.ajax({
+                    url: '/pm/import/importInterface',
+                    type: 'POST',
+                    data: formData,
+                    cache: false,
+                    contentType: false,
+                    processData: false,
+                    timeout: 1000 * 60 * 3, //3分钟
+                    success: function(response){
+                        if (response.data && Array.isArray(response.data)) {
+                            doAfterImport(response.data);
+                        }
+                        pr.end();
+                    },
+                    error: function(jqXHR){
+                        pr.end();
+                        throw `与服务器通信发生错误${jqXHR.status} ${jqXHR.statusText}`;
                     }
-                    pr.end();
-                },
-                error: function(jqXHR){
-                    pr.end();
-                    alert(`与服务器通信发生错误${jqXHR.status} ${jqXHR.statusText}`);
-                }
-            });
+                });
+            } catch (err) {
+                console.log(err);
+                pr.end();
+                alert(err);
+            }
     });
         //导入窗口消失后
         $('#importInterface').on('hidden.bs.modal', function () {
+            importXML = null;
             xmlObj = null;  //重置数据
             tbcObj = null;
             $('#importInterface .modal-content:eq(0)').show();  //显示第一步内容
@@ -413,17 +453,24 @@ const importView = (() => {
             $('#uploadAlert').hide();   //隐藏提示
             $('.selFile').hide();   //隐藏建设项目及计价规则
             $('#import-confirm').prop('disabled', true);    //确认导入无效
+            $('.selFile input[name="fileKind-import"]:eq(0)').prop('checked', true);    //文件类型恢复成投标
+            $('#import-taxType').val('1');  //显示回一般计税
             hideTBCInfo();
         });
     }
     //projectDatas在后端已经按照顺序排过了: project eng1 tender1-1 tender1-2 eng2 tender2-1 tender2-2
     function doAfterImport(projectDatas) {
         //插入节点
+        let lastNode;
         for (let data of projectDatas) {
+            data.feeStandardName = data.property && data.property.feeStandardName || ''; //工程专业列显示用
             let parent = projTreeObj.tree.items.find(node => node.data.ID === data.ParentID),
                 next = projTreeObj.tree.items.find(node => node.data.ID === data.NextSiblingID);
-            projTreeObj.insert(data, parent, next);
+            lastNode = projTreeObj.insert(data, parent, next);
+        }
+        if(lastNode) {
+            projTreeObj.workBook.getSheet(0).showRow(lastNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
         }
     }
     return {eventListen};
-})();
+})();

+ 107 - 40
web/building_saas/pm/js/pm_newMain.js

@@ -37,6 +37,9 @@ const FileKind = {
     bid: 2  //招标
 };
 let curTaxType = 1; //1:"一般计税",2:"简易计税"
+let curValutionType = 'bill',   //计价方式默认只有清单计价
+    curValuation = billValuation[0].id, //计价规则初始取第一个
+    curValuationName = billValuation[0].name; //计价规则初始取第一个
 /*
 * 地区,同一费用定额下不同地区有不同单价,则新建单位工程时需要选择地区项
 * 地区项为空的时候,前端不显示该下拉项,地区的赋值覆盖在over_write相关文件中
@@ -1756,7 +1759,6 @@ $(document).ready(function() {
             html += `<option ${i === targetData.length -1 ? 'selected' : ''} value="${valuation.id}">${valuation.name}</option>`;
         }
         $("#valuation").html(html);
-        //$("#tender-engineering").html('<option value="">请选择对应的工程专业</option>');
         let engineeringList = getEngineeringList();
         let engineeringHtml = getEngineeringHtml(engineeringList);
         $("#tender-engineering").html(engineeringHtml);
@@ -1765,6 +1767,8 @@ $(document).ready(function() {
 
     //选择计价规则
     $("#valuation").change(function () {
+        curValuation = $(this).val();
+        curValuationName = $(this).text();
         let engineeringList = getEngineeringList();
         console.log(engineeringList);
         let engineeringHtml = getEngineeringHtml(engineeringList);
@@ -1792,7 +1796,7 @@ $(document).ready(function() {
         let isExist = hasListName(nameList, pojName);
         if(!isExist){
             if(pojName !== ''){
-                //新建建设项目,显示文件类型、计税方法选项
+                //新建建设项目,显示计价规则、文件类型、计税方法选项
                 $('#newProjectSet').show();
                 $('input[name="fileKind-tender"]:eq(0)').prop('checked', true);
                 $('input[name="taxType-tender"]:eq(0)').prop('checked', true);
@@ -1908,7 +1912,8 @@ $(document).ready(function() {
         let selected = projTreeObj.tree.selected;
         let projs = getProjs(selected);
         setProjOptions(projs, selected);
-        $($("input[name='valuation_type']")[0]).click();
+        //$($("input[name='valuation_type']")[0]).click();
+        initEngineering();
         //设置地区选项
         if(regions.length > 0){
             setRegionOpts(regions);
@@ -2038,7 +2043,7 @@ $(document).ready(function() {
         }
         if (!featureData) {
             try{
-                let valuation = $("#valuation").val();
+                let valuation = curValuation;
                 let engineeringName = $("#tender-engineering").val();
                 let feeName = $('#tender-feeStandard').val();
                 featureData = await ajaxPost('/pm/api/getProjectFeature',
@@ -2083,22 +2088,6 @@ $(document).ready(function() {
         $('#tender-required-warn').show();
         showRequiredInfo($('#featureStep'), featureData);
     }
-    function getRequired(rst, datas) {
-        if (!datas) {
-            return rst;
-        }
-        for (let data of datas) {
-            let required = typeof data.required === 'string' ? JSON.parse(data.required) : data.required,
-                readOnly = typeof data.readOnly === 'string' ? JSON.parse(data.readOnly) : data.readOnly;
-            if (required && !readOnly) {
-                rst.push(data);
-            }
-            if (data.items && data.items.length > 0) {
-                getRequired(rst, data.items);
-            }
-        }
-        return rst;
-    }
     //显示必填信息(建设项目基本信息、单位工程工程特征)
     //必填信息:标记了必填required且不只读!readOnly
     function showRequiredInfo($form, datas) {
@@ -2404,8 +2393,16 @@ $(document).ready(function() {
     //导入相关
     importView.eventListen();
 });
-function changeEngineering(){
-    featureData = null;
+
+//初始化工程专业库
+function initEngineering() {
+    let engineeringList = getEngineeringList();
+    let engineeringHtml = getEngineeringHtml(engineeringList);
+    $("#tender-engineering").html(engineeringHtml);
+    changeEngineering();
+}
+
+async function changeEngineering(){
     $('#engineering-info').hide();
     initFeeStandardSel();
 }
@@ -2424,8 +2421,42 @@ function changeFeeRate(engLib) {
         $("#tender-fee-rate").children("option").first().val($('#tender-name').val());
     }
 }
+function getRequired(rst, datas) {
+    if (!datas) {
+        return rst;
+    }
+    for (let data of datas) {
+        let required = typeof data.required === 'string' ? JSON.parse(data.required) : data.required,
+            readOnly = typeof data.readOnly === 'string' ? JSON.parse(data.readOnly) : data.readOnly;
+        if (required && !readOnly) {
+            rst.push(data);
+        }
+        if (data.items && data.items.length > 0) {
+            getRequired(rst, data.items);
+        }
+    }
+    return rst;
+}
+//变换专业工程、变换费用标准,重新获取工程库数据...
+async function changeFeature() {
+    let valuation = curValuation;
+    let engineeringName = $("#tender-engineering").val();
+    let feeName = $('#tender-feeStandard').val();
+    featureData = await ajaxPost('/pm/api/getProjectFeature',
+        {user_id: userID, valuationID: valuation, engineeringName: engineeringName, feeName: feeName});
+    let infoRequired = getRequired([], infoData),
+        featureRequired = getRequired([], featureData),
+        path = getAddPath();
+    if (path === addPath.p_e_t && infoRequired.length > 0 || featureRequired.length > 0) {
+        $('#add-tender-next').show();
+        $('#add-tender-confirm').hide();
+    } else {
+        $('#add-tender-next').hide();
+        $('#add-tender-confirm').show();
+    }
+}
 
-function initFeeStandardSel() {
+async function initFeeStandardSel() {
     $('#tender-feeStandard').empty();
     let feeStandards = [];
     let engineeringList = getEngineeringList();
@@ -2444,14 +2475,21 @@ function initFeeStandardSel() {
             $('#feeStandard-info').hide();
         }
     }
+    //变换专业工程、变换费用标准,重新获取工程库数据...
+    if (curStep === 2) {
+        await changeFeature();
+    }
     let currentEngLib = getEngineeringLib(currentEngName + $('#tender-feeStandard').val(), engineeringList);
     changeFeeRate(currentEngLib);
     //setTaxGroupHtml();
     getStdCalcProgramFiles();
 }
 
-function changeFeeStandard() {
-    featureData = null;
+async function changeFeeStandard() {
+    //变换专业工程、变换费用标准,重新获取工程库数据...
+    if (curStep === 2) {
+        await changeFeature();
+    }
     let currentEngLib = getEngineeringLib($('#tender-engineering').val() + $('#tender-feeStandard').val(), getEngineeringList());
     changeFeeRate(currentEngLib);
     //setTaxGroupHtml();
@@ -2494,10 +2532,7 @@ function getStdCalcProgramFiles(){
         };
         return result;
     };
-    //let taxType = $("#taxType").val();
     let taxType = curTaxType; //计税方法取建设项目的
-    //let selected = projTreeObj.tree.selected;
-
     let stdCPHtml = getStdCPFilesHtml(getTaxGroupList(taxType));
     $("#tender-calcProgram").html(stdCPHtml);
     if ($("#tender-calcProgram")[0].options.length > 1)
@@ -2616,6 +2651,12 @@ function AddProject() {
         setDangerInfo($('#fileKind-info'));
         return false;
     }
+    let valuation = $('#proj-valuation').val();
+    if (!valuation) {
+        setDangerInfo($('#proj-valuation-info'));
+        return false;
+    }
+    let valuationName = $('#proj-valuation').text().trim();
     let taxType = $('input[name="taxType"]:checked').val();
     if (!taxType) {
         setDangerInfo($('#taxType-info'));
@@ -2637,7 +2678,13 @@ function AddProject() {
      (3)、当前定位在建设项目,新建建设项目为其后兄弟。
      (4)、当前定位在单项工程或单位工程,新建项目为当前所属建设项目的后兄弟。
      * */
-    let property = {basicInformation: infoData ? infoData : [], fileKind: fileKind, taxType: taxType};
+    let property = {basicInformation: infoData ? infoData : [],
+        fileKind: fileKind,
+        taxType: taxType,
+        valuation: valuation,
+        valuationName: valuationName,
+        valuationType: curValutionType
+    };
     if(!selectedItem){
         AddSiblingsItem(selectedItem, name, property, projectType.project, existCallback, sucCallback);
     }
@@ -2747,7 +2794,10 @@ function AddTenderItems(selected, projName, engName, tenderName, property, callb
                 next = selectedProj ? selectedProj.nextSibling : projTreeObj.tree.firstNode();
             }
             let fileKind = $('input[name="fileKind-tender"]:checked').val();
-            let updateProjs = GetUpdateData(pre, parent, next, projName, {basicInformation: infoData ? infoData : [], fileKind: parseInt(fileKind), taxType: curTaxType}, projID, {updateType: 'new', projectType: projectType.project});
+            let updateProjs = GetUpdateData(pre, parent, next, projName, {
+                basicInformation: infoData ? infoData : [],
+                fileKind: parseInt(fileKind), taxType: curTaxType, valuationType: curValutionType, valuation: curValuation, valuationName: curValuationName},
+                projID, {updateType: 'new', projectType: projectType.project});
             let updateEng = {updateType: 'new', updateData: {ID: engID, ParentID: projID, NextSiblingID: -1, name: engName, projType: projectType.engineering}};
             property.rootProjectID = projID;
             let updateTender = {updateType: 'new', updateData: {ID: tenderID, ParentID: engID, NextSiblingID: -1, shareInfo: [], name: tenderName, projType: projectType.tender, property: property}};
@@ -2931,8 +2981,10 @@ function getEngineeringLib(cascadeName, engineeringList) {
 }
 
 function getEngineeringList(){
-    let valuation = $("#valuation").val();
-    let valuationType = $("input[name='valuation_type']:checked").val();
+    //let valuation = $("#valuation").val();
+    let valuation = curValuation;
+    //let valuationType = $("input[name='valuation_type']:checked").val();
+    let valuationType = curValutionType;
     let valuationData = valuationType === 'bill' ? billValuation : rationValuation;
     let engineeringList = [];
     for(let tmp of valuationData) {
@@ -3103,6 +3155,16 @@ function setProjOptions(projs, selected){
     if(projs.length > 0){
         let firstProj = selected && selected.data.projType === projectType.project ? selected: projs[0];
         curTaxType = firstProj.data.property.taxType || 1;
+        if (firstProj.data.property.valuationType) {
+            curValutionType = firstProj.data.property.valuationType;
+        }
+        if (firstProj.data.property.valuation) {
+            curValuation = firstProj.data.property.valuation;
+        }
+        if (firstProj.data.property.valuationName) {
+            curValuationName = firstProj.data.property.valuationName;
+        }
+        if (firstProj.data.property.valuation)
         getStdCalcProgramFiles();
         $("#poj-name").val(firstProj.data.name);
         setFileOptions(firstProj.data.ID);
@@ -3113,6 +3175,15 @@ function setProjOptions(projs, selected){
             $proj.attr("href", "javascript:void(0);");
             $proj.click(function () {
                 curTaxType = projs[i].data.property.taxType || 1;
+                if (projs[i].data.property.valuationType) {
+                    curValutionType = projs[i].data.property.valuationType;
+                }
+                if (projs[i].data.property.valuation) {
+                    curValuation = projs[i].data.property.valuation;
+                }
+                if (projs[i].data.property.valuationName) {
+                    curValuationName = projs[i].data.property.valuationName;
+                }
                 getStdCalcProgramFiles();
                 $('#newProjectSet').hide();//隐藏文件类型、计税方法选项
                 $("#poj-name").val(projs[i].data.name);
@@ -3291,11 +3362,8 @@ function AddTender() {
         let unitPriceFileObj = getAddTenderFile(tenderName, $('#unit-price'), $("#unit-price").children());
         let feeFileObj = getAddTenderFile(tenderName, $('#tender-fee-rate'), $("#tender-fee-rate").children());
 
-        let valuation = $("#valuation").val();
-        if(!valuation || valuation === ''){
-            setDangerInfo($('#valuation-info'), '请选择计价规则');
-            return false;
-        }
+        //let valuation = $("#valuation").val();
+        let valuation = curValuation;   //跟建设项目一样的计价规则
 
         let engineeringName = $("#tender-engineering").val();
         if (!engineeringName || engineeringName === '') {
@@ -3327,8 +3395,8 @@ function AddTender() {
         }
         //如果是新建费率的情况
         if(feeFileObj.id.indexOf("newFeeRate")!=-1) feeFileObj.id +=feeLibID;
-        let valuationName = $("#valuation").children("option:selected").text();
-        let valuationType = $("input[name='valuation_type']:checked").val();
+        let valuationName = curValuationName;   //跟建设项目一样的计价方式
+        let valuationType = curValutionType;    //跟建设项目一样的计价方式
 
         let engineering = undefined;
         let valuationData = valuationType === 'bill' ? billValuation : rationValuation;
@@ -3789,7 +3857,6 @@ function getUnitFile(parentID, callback) {
     });
 
 }
-
 /**
  * 获取费率文件
  *

+ 1 - 1
web/over_write/js/chongqing_2018.js

@@ -287,7 +287,7 @@ if(typeof baseFigureMap !== 'undefined'){
         '甲供定额施工机具使用费': {base: 'JGDEJJJXF', class: 'RCJ'},
         '甲供人工费': {base: 'JGRGF', class: 'RCJ'},
         '甲供材料费': {base: 'JGCLF', class: 'RCJ'},
-        '甲供施工机具使用费': {base: 'JGJXF', class: 'RCJ'},
+        '甲供施工机具使用费': {base: 'JGJXF', class: 'RCJ'},
         '甲供主材费': {base: 'JGZCF', class: 'RCJ'},
         '甲定定额人工费': {base: 'JDDEJJRGF', class: 'RCJ'},
         '甲定定额材料费': {base: 'JDDEJJCLF', class: 'RCJ'},