/** * Created by zhang on 2018/1/22. */ let mongoose = require('mongoose'); let projectConst = require('../models/project_consts'); const rationType = projectConst.rationType; const rationKeyArray = projectConst.rationKeyArray; const gljKeyArray = projectConst.gljKeyArray; let quantity_detail = require("./quantity_detail_facade"); let quantity_detail_model = mongoose.model('quantity_detail'); let ration_glj_facade = require("../../ration_glj/facade/ration_glj_facade"); let Bills_Lib = mongoose.model('std_bills_lib_bills'); let ration_Model = mongoose.model('ration'); let ration_glj_Model = mongoose.model('ration_glj'); let ration_coe_Model = mongoose.model('ration_coe'); let ration_installation_Model = mongoose.model('ration_installation'); let ration_template_Model = mongoose.model('ration_template'); let bill_Model = require('../models/bills').model; let billsLibDao = require("../../bills_lib/models/bills_lib_interfaces"); const pmFacade = require('../../pm/facade/pm_facade'); const { getSortedTreeData } = require('../../../public/common_util'); const { constructionFeeNodeID, constructionEquipmentFeeNodeID, BudgetArea, fixedFlag } = require('../../../public/common_constants'); const uuidV1 = require('uuid/v1'); const GLJController = require("../../glj/controllers/glj_controller"); const GLJListModel = require('../../glj/models/glj_list_model'); let _ = require("lodash"); module.exports={ getSectionInfo : async function (data) { let conditions=[]; let fxList=[]; let sectionInfo ={}; for(let libID in data){ let codes=[]; let temp={}; codes= _.keys(data[libID]); temp['billsLibId']=libID; temp['code'] = {"$in": codes}; conditions.push(temp); } if(conditions.length>0){ fxList = await Bills_Lib.find({"$or":conditions}); } if(fxList.length>0){ let sectionIDs = {}; for(let f of fxList){ if(f._doc.sectionInfo){ f._doc.sectionInfo.first?sectionIDs[f._doc.sectionInfo.first]=true:""; f._doc.sectionInfo.second?sectionIDs[f._doc.sectionInfo.second]=true:""; f._doc.sectionInfo.third?sectionIDs[f._doc.sectionInfo.third]=true:""; } } let IDList = _.keys(sectionIDs); let sectionList = await Bills_Lib.find({'ID':{'$in':IDList}}); let sectionMap = _.mapKeys(sectionList,'ID'); let fxMap = _.mapKeys(fxList,'code'); sectionInfo={ fxMap:fxMap, sectionMap :sectionMap } return sectionInfo; } return null; }, reorganizeFBFX:async function(data){ let result = {}; let tasks = generateBillTasks(data); if(data.delete && data.delete.length > 0){ let qd_query={projectID: data.projectID, billID: {"$in": data.delete}}; await quantity_detail.deleteByQuery(qd_query) ; } if(tasks.length > 0){ result =await bill_Model.bulkWrite(tasks); } return result; }, pasteBlock : async function(data,compilation){ let pasteTasks = [ pasteRationsAndRationGLJ(data.rations,data.ration_gljs,compilation),//这一步会花费比较多时间 pasteOtherData(data) ]; let [rationsAndRationGLJ,resultMap] = await Promise.all(pasteTasks); let gljController = new GLJController(); // let projectGLJ = await gljController.getProjectGLJsByProjectID(data.projectID); resultMap.rations = rationsAndRationGLJ.rations; resultMap.ration_gljs = rationsAndRationGLJ.new_ration_gljs; resultMap.projectGLJList = rationsAndRationGLJ.projectGLJList; // resultMap.gljData = projectGLJ.data; return resultMap; }, createNewBills:async function(newDatas){ // billsLibDao.getStdBillsByCode 从这里取数据 let results = []; for(let bills of newDatas){ let stdB = await billsLibDao.getStdBillsByCode({billsLibId:bills.billsLibId,code:bills.billsLocation}); if(stdB){ stdB = JSON.parse(JSON.stringify(stdB)); if(!bills.unit && /\//.test(stdB.unit)){ bills.unit = stdB.unit.split(/\//)[0]; } //处理项目特征和工作内容,现在默认都添加到项目特征列中 stdB.itemCharacterText = "[项目特征]\n[工作内容]\n"+stdB.jobContentText; stdB.jobContentText=""; bills = _.merge(stdB,bills); } delete bills.billsLocation; results.push(bills); } if(results.length > 0){ await bill_Model.create(results); } return results; }, insertBills: async function(datas) { let bulks = []; for (let data of datas) { if (data.updateType === 'update') { bulks.push({updateOne: {filter: {ID: data.updateData.ID}, update: {NextSiblingID: data.updateData.NextSiblingID}}}); } else { bulks.push({insertOne: {document: data.updateData}}); } } if (bulks.length > 0) { await bill_Model.bulkWrite(bulks); } }, // 获取概算汇总数据 getBudgetSummary: async function (constructionID) { // 获取建设项目清单数据(工程建设其他费用 - 建设项目总概算)部分 const constructionOtherFeeBills = await bill_Model.find({ projectID: constructionID }).lean(); const sortedOtherFeeBills = getSortedTreeData('-1', constructionOtherFeeBills); constructionOtherFeeBills.forEach(item => item.area = BudgetArea.CONSTRUCTION_OTHER_FEE); // 获取工程费用数据 const constructionFeeBills = await this.getConstructionFeeData(constructionID, sortedOtherFeeBills[0].ID); return [...constructionFeeBills, ...constructionOtherFeeBills]; }, // 获取工程费用数据,作为概算汇总数据的拼接树数据 getConstructionFeeData: async function (constructionID, nextID) { const projects = await pmFacade.getPosterityProjects([constructionID], true, { _id: 0, ID: 1, ParentID: 1, NextSiblingID: 1, name: 1, 'property.feeStandardName': 1}); const construction = projects.find(p => p.ID === constructionID); const items = getSortedTreeData(construction.ParentID, projects); // 转换为uuid const IDMap = {}; items.forEach((item, index) => { if (index == 0) { IDMap[item.ID] = constructionFeeNodeID; } else { IDMap[item.ID] = uuidV1() } }); // 将项目调整为工程费用数据 let curConstructionID; let curSingleNo = 0; let curSingleID; let curUnitNo = 0; let latestSingleNode; items.forEach((item, index) => { item.area = BudgetArea.CONSTRUCTION_FEE; item.ID = IDMap[item.ID]; item.ParentID = IDMap[item.ParentID] || '-1'; item.NextSiblingID = IDMap[item.NextSiblingID] || '-1'; if (index === 0) { curConstructionID = item.ID; item.flags = [{ fieldName: 'fixed', flag: fixedFlag.CONSTRUCTION_FEE }]; item.code = '1'; item.name = '工程费用'; item.NextSiblingID = nextID; } else { if (item.ParentID === curConstructionID) { latestSingleNode = item; curSingleNo += 1; curUnitNo = 0; curSingleID = item.ID; item.code = `1.${curSingleNo}` } else if (item.ParentID === curSingleID) { curUnitNo += 1; item.code = `1.${curSingleNo}.${curUnitNo}` } } }); const constructionFeeNode = items[0]; // 设备及工器具购置费 const constructionEquipmentNode = { area: BudgetArea.CONSTRUCTION_FEE, flags: [{ fieldName: 'fixed', flag: fixedFlag.CONSTRUCTION_EQUIPMENT_FEE }], ID: constructionEquipmentFeeNodeID, ParentID: constructionFeeNode.ID, NextSiblingID: '-1', code: `1.${curSingleNo + 1}`, name: '设备及工器具购置费', }; latestSingleNode.NextSiblingID = constructionEquipmentNode.ID; items.push(constructionEquipmentNode); return items; } }; async function pasteOtherData(data) { let bills = data.bills; let quantity_details = data.quantity_details; let ration_coes = data.ration_coes; let ration_installations = data.ration_installations; let ration_templates = data.ration_templates; let updateData = data.updateData; let uModel = null; let tasks = []; //生成更新任务 for(let u of updateData){ if(u.type == "bills"){ uModel = bill_Model; }else { uModel = ration_Model; } let tem = { updateOne:{ filter:u.query, update :u.doc } }; tasks.push(tem); } bills.length > 0 ? await insertMany(bills,bill_Model):''; quantity_details.length > 0 ? await insertMany(quantity_details,quantity_detail_model):''; ration_coes.length > 0 ? await insertMany(ration_coes,ration_coe_Model):''; ration_installations.length > 0 ? await insertMany(ration_installations,ration_installation_Model):''; ration_templates.length > 0? await insertMany(ration_templates,ration_template_Model):''; tasks.length>0?await uModel.bulkWrite(tasks):''; return {bills:bills,quantity_details:quantity_details,ration_coes:ration_coes,ration_installations:ration_installations,ration_templates:ration_templates,updateData:updateData} } async function pasteRationsAndRationGLJ (rations,ration_gljs,compilation) { let projectGljModel = new GLJListModel(); let gljMap = {}, new_ration_gljs=[],projectID=null,projectGLJList =[]; if(rations.length > 0) projectID = rations[0].projectID; if(projectID==null && ration_gljs.length > 0) projectID = ration_gljs[0].projectID; if(projectID == null) return {rations:rations,new_ration_gljs:new_ration_gljs}; let [unitFileId,ext] = await ration_glj_facade.prepareExtData(projectID,compilation); //先根据定额类型的工料机,插入到项目工料机中 for(let r of rations){ if(r.type == rationType.gljRation){ let projectGLJ = await getProjectGLJ(r,rationKeyArray,gljMap,unitFileId,ext); projectGLJList.push(projectGLJ); } } for(let rg of ration_gljs){ let projectGLJ = await getProjectGLJ(rg,gljKeyArray,gljMap,unitFileId,ext); let temRecord = ration_glj_facade.createNewRecord(rg); rg.rcode?temRecord.rcode = rg.rcode:''; rg.hasOwnProperty("customQuantity")?temRecord.customQuantity = rg.customQuantity:''; new_ration_gljs.push(temRecord); projectGLJList.push(projectGLJ); } rations.length>0?await insertMany(rations,ration_Model):''; new_ration_gljs.length>0?await insertMany(new_ration_gljs,ration_glj_Model):''; return {rations:rations,new_ration_gljs:new_ration_gljs,projectGLJList:projectGLJList}; async function getProjectGLJ (glj,keyArray,gljMap,unitFileId,ext) { let keyIndex = projectGljModel.getIndex(glj,keyArray); let pgljResult = null; if(gljMap[keyIndex]){ pgljResult = gljMap[keyIndex] }else { let p_glj = ration_glj_facade.getGLJSearchInfo(glj); pgljResult = await projectGljModel.addList(p_glj,unitFileId,ext);//逐条添加到项目工料机 gljMap[keyIndex] = pgljResult; } setResult(glj,pgljResult); return pgljResult } function setResult(glj,result ) { let typeString = result.type+''; glj.marketPrice = result.unit_price.market_price; glj.adjustPrice = result.unit_price.base_price; glj.basePrice = result.unit_price.base_price; glj.isAdd = result.unit_price.is_add; glj.projectGLJID = result.id; if (typeString.startsWith("2")||typeString=='4'||typeString=='5') {//只有材料类型才显示是否暂估 glj.isEstimate = result.is_evaluate; } } } function generateBillTasks(data) { let tasks=[]; let user_id = data.user_id,projectID = data.projectID; let deleteInfo={deleted: true, deleteDateTime: new Date(), deleteBy: user_id}; if(data.delete && data.delete.length > 0){ for(let d_ID of data.delete){ //原先是假删除,现在改成真删除 let task = { deleteOne:{ filter:{ ID:d_ID, projectID:projectID } } }; /* let task={ updateOne:{ filter:{ ID:d_ID, projectID:projectID }, update :{ deleteInfo:deleteInfo } } };*/ tasks.push(task); } } if(data.update && data.update.length > 0){ for(let u_data of data.update){ let task ={ updateOne:{ filter : { ID:u_data.ID, projectID:projectID }, update : u_data.data } }; tasks.push(task); } } if(data.create && data.create.length > 0){ for(let n_data of data.create){ let task = { insertOne :{ document:n_data } }; tasks.push(task); } } return tasks; } async function insertMany(datas,model) { let tem = []; console.log(datas); while (datas.length>1000){//因为mongoose限制了批量插入的条数为1000.所以超出限制后需要分批插入 let newList = datas.splice(0,1000);//一次插入1000条 await model.insertMany(newList); tem = tem.concat(newList); } await model.insertMany(datas); if(tem.length > 0) datas.push(...tem);//还原数组 }