/** * 项目工料机列表数据模型 * * @author CaiAoLin * @date 2017/6/22 * @version */ const mongoose = require("mongoose"); const BaseModel = require("../../common/base/base_model"); const CounterModel = require("./counter_model"); const UnitPriceModel = require("./unit_price_model"); const UnitPriceFileModel = require("./unit_price_file_model"); const GLJTypeConst = require("../../common/const/glj_type_const"); const STDGLJLibGLJListModel = require("../../common/std/std_glj_lib_glj_list_model"); const MixRatioModel = require("./mix_ratio_model"); const GljModel = require("../../complementary_glj_lib/models/gljModel"); const ProjectModel = require('../../pm/models/project_model').project; const scMathUtil = require('../../../public/scMathUtil').getUtil(); const unitPriceFacade = require("../../unit_price_file/facade/unit_price_facade"); let gljCollectionName = 'glj_list'; let GLJSchemas = mongoose.model(gljCollectionName); let _ = require("lodash"); class GLJListModel extends BaseModel { /** * 材料、主材、设备类型id * * @var {Array} */ materialIdList = [GLJTypeConst.GENERAL_MATERIAL, GLJTypeConst.CONCRETE, GLJTypeConst.MORTAR, GLJTypeConst.MIX_RATIO, GLJTypeConst.COMMERCIAL_CONCRETE, GLJTypeConst.COMMERCIAL_MORTAR, GLJTypeConst.MAIN_MATERIAL, GLJTypeConst.EQUIPMENT]; /** * 拥有组成物的工料机类型id * * @var {Array} */ ownCompositionTypes = [GLJTypeConst.CONCRETE, GLJTypeConst.MORTAR, GLJTypeConst.MIX_RATIO, GLJTypeConst.GENERAL_MACHINE,GLJTypeConst.MAIN_MATERIAL,GLJTypeConst.INSTRUMENT]; /** * 构造函数 * * @return {void} */ constructor() { let parent = super(); parent.model = GLJSchemas; parent.init(); } /** * 设置场景 * * @param {string} scene * @return {void} */ setScene(scene = '') { switch (scene) { // 新增数据的验证规则 case 'add': //this.model.schema.path('glj_id').required(true); this.model.schema.path('project_id').required(true); this.model.schema.path('code').required(true); // this.model.schema.path('name').required(true); break; } } /** * 根据标段对应项目工料机列表 * * @param {Number} projectId * @param {Number} unitPriceFileId * @return {Promise} */ async getListByProjectId(projectId, unitPriceFileId) { let gljData = null; /*let decimal =await decimal_facade.getProjectDecimal(projectId); let quantity_decimal = decimal&&decimal.glj.quantity?decimal.glj.quantity:6;//取消耗量保留小数据位,默认6位*/ let mixRatioConnectData = {}; let mixRationMap={}; let keyMap={}; let unitPriceList={}; unitPriceFileId = unitPriceFileId?unitPriceFileId:await ProjectModel.getUnitPriceFileId(projectId); try { // 首先获取对应标段下所有的项目工料机数据 let condition = {project_id: projectId}; let fields = {_id: 0}; gljData = await this.model.find(condition, fields).lean(); // 没有数据则直接返回空 if (gljData.length <= 0) { throw '无数据'; } // 获取标段设置的单价文件数据 let unitPriceModel = new UnitPriceModel(); unitPriceList = await unitPriceModel.getDataByFileId(unitPriceFileId); let connect_keys = []; for(let tmp of gljData) { let c_key = this.getIndex(tmp,['code','name','specs','unit','type']); if(this.ownCompositionTypes.indexOf(tmp.type)!=-1){ connect_keys.push(c_key); } keyMap[c_key] = tmp; //项目工料机连接key和工料机的对照表; } // 查找组成物的消耗量 let totalComposition = {}; let mixRatioData = {}; let missMaxRatio = [];//由于共享单价文件,单价文件编辑器造成的,存在组成物和对应的单价,但是项目工料机不存的情况 if (connect_keys.length > 0) { let mixRatioModel = new MixRatioModel(); condition = {connect_key: {"$in": connect_keys}, unit_price_file_id: unitPriceFileId}; let mixRatioList = await mixRatioModel.findDataByCondition(condition, null, false); for (let tmp of mixRatioList) { let t_index = tmp.connect_key; let m_index = this.getIndex(tmp,['code','name','specs','unit','type']); if (mixRatioData[t_index] !== undefined) { mixRatioData[t_index].push(tmp); } else { mixRatioData[t_index] = [tmp]; } if(mixRationMap[t_index]!=undefined){ mixRationMap[t_index].push(tmp); }else { mixRationMap[t_index]=[tmp]; } if (mixRatioConnectData[m_index] !== undefined) { mixRatioConnectData[m_index].push(tmp.connect_key); } else { mixRatioConnectData[m_index] = [tmp.connect_key]; } //检查该组成物对应的项目工料机是否存在 if(!keyMap[m_index]) missMaxRatio.push(tmp);//这里可能会有重复,但是后面的添加操作中会去重 } } if(missMaxRatio.length > 0){ let newList = await unitPriceFacade.getNewProjectGLJFromMissMixratio(projectId,missMaxRatio,keyMap,[]); await unitPriceFacade.setIDfromCounter("glj_list",newList); await this.model.insertMany(newList); gljData=gljData.concat(newList); } // 组合单价数据 gljData = this.combineData(gljData, unitPriceList, {}, mixRatioData, totalComposition); // 排序 gljData.sort(function (a, b) { a.unit_price = a.unit_price === null ? 0 : a.unit_price; b.unit_price = b.unit_price === null ? 0 : b.unit_price; return a.unit_price.type - b.unit_price.type; }); } catch (error) { console.log("glj_list_model:" + error); gljData = []; } return [gljData, mixRatioConnectData,mixRationMap,unitPriceList]; } /** * 组合工料机数据和单价文件数据 * * @param {object} gljList * @param {object} unitPriceList * @param {object} quantityList * @param {object} mixRatioData 组合物明细数据 * @param {object} totalComposition 组合物父工料机统计数据 * @return {Array} */ combineData(gljList, unitPriceList, quantityList = {}, mixRatioData = {}, totalComposition = {}) { // 整理组成物消耗量(只有在总列表显示的时候才需用到,获取单项项目工料机内容则忽略) let compositionConsumption = {}; if (Object.keys(mixRatioData).length > 0 && Object.keys(totalComposition).length > 0) { for(let index in mixRatioData) { for(let tmp of mixRatioData[index]) { let t_index = this.getIndex(tmp,['code','name','specs','unit','type']);//取做为组成物的工料机的总消耗量 compositionConsumption[t_index] = compositionConsumption[t_index] === undefined ? tmp.consumption : compositionConsumption[t_index] + tmp.consumption; } } } let result = []; // 循环组合数据 for(let index in gljList) { let glj = gljList[index]; if (glj.code === undefined) { continue; } let g_index = this.getIndex(glj,['code','name','specs','unit','type']); glj.unit_price = unitPriceList !== null && unitPriceList[g_index] !== undefined ? unitPriceList[g_index] : null; if (glj.unit_price === null) { continue; } let gljId = glj.glj_id + ''; let projectGljId = glj.id + ''; glj.quantity = quantityList[g_index]?quantityList[g_index]:0; // 组成物数据 gljList[index].ratio_data = mixRatioData[g_index] !== undefined ? mixRatioData[g_index] : []; //因为schema中设置base_price 为string 类型,所以要通过中间变量转换为数字再做计算,不然会自动变成字符串类型 this.getGLJPrice(glj); result.push(glj); } return result; } getGLJPrice(glj){ let glj_basePrice = parseFloat(glj.unit_price.base_price); glj.unit_price.base_price = glj_basePrice; glj.unit_price.market_price = parseFloat(glj.unit_price.market_price); } /** * 新增项目工料机数据(包括新增单价文件) 定额工料机新增时调用 * * @param {object} data * @return {Promise} 返回插入成功的数据id */ async addList(data,unitFileId,ext) { let result = null; try { if (Object.keys(data).length <= 0) { throw '新增数据为空'; } //if(data.specs==undefined||data.specs==null||data.specs=="") data.specs = null; let condition={ code: data.code, project_id: data.project_id, name:data.name, type:data.type, unit:data.unit }; let projectGljData = null; let projectGLJList = await this.findDataByCondition(condition,null,false); if(projectGLJList.length > 0){//specs有可能为空或"",所以这里做这样处理 let p = data.specs; if(p==undefined||p==null||p=="") p = null; for(let g of projectGLJList){ let t = g.specs; if(t==undefined||t==null||t=="") t = null; if(p == t) projectGljData = g; } } // let projectGljData = await this.findDataByCondition(condition); let isAddProjectGLJ = false; // 获取标段对应的单价文件id let unitPriceFileId = unitFileId?unitFileId:await ProjectModel.getUnitPriceFileId(data.project_id); if (unitPriceFileId <= 0) { throw '没有对应的单价文件'; } let unitPriceModel = new UnitPriceModel(); // 新增单条记录 (两个操作本来应该是事务操作,然而mongodb事务支持比较弱,就当作是都可以顺利执行) // 如果找不到数据则新增 if (!projectGljData) { let gljInsertData = await this.add(data); if (!gljInsertData) { throw '新增项目工料机失败!'; } isAddProjectGLJ = true; projectGljData = gljInsertData; } let CompositionGLJ=[]; // 判断类型,如果是混凝土、砂浆、配合比或者主材则查找对应的组成物(前提是没有对应的项目工料机数据) if(this.ownCompositionTypes.indexOf(data.type)!=-1) { //如果是新增 if(isAddProjectGLJ ){ await this.compositionInit(data, unitPriceFileId,ext); } CompositionGLJ=await this.getCompositionGLJByData(data,unitPriceFileId); if(isAddProjectGLJ==false&&CompositionGLJ.length==0){//如果不是新增,并且是有组成物的类型但又没有发现组成物的情况下,有可能是错误数据,重新在库中查找一下组成物,有则插入 await this.compositionInit(data, unitPriceFileId,ext); CompositionGLJ=await this.getCompositionGLJByData(data,unitPriceFileId); if(CompositionGLJ.length>0){//如果这次发现又有组成物了,则把旧的单价数据删除,在后面的操作中会重新增加 let de_condition ={unit_price_file_id: unitPriceFileId,code:data.code,name:data.name,unit:data.unit,type:data.type}; data.specs!=null&&data.specs!=undefined&&data.specs!=""?de_condition.specs = data.specs:de_condition; await unitPriceModel.db.delete(de_condition); } } } projectGljData.subList=CompositionGLJ; // 新增单价文件 let [unitPriceInsertData, isAdd] = await unitPriceModel.addUnitPrice(data, unitPriceFileId); if (!unitPriceInsertData) { throw '新增单价失败!'; } projectGljData.unit_price = unitPriceInsertData; result = projectGljData; } catch (error) { console.log(error); result = null; } return result; } /** * 新增单条工料机数据 * * @param {object} data * @return {Promise} */ async add(data) { if (Object.keys(data).length <= 0) { throw '新增数据为空'; } let counterModel = new CounterModel(); if (data instanceof Array) { // 如果是批量新增 for(let tmp in data) { data[tmp].id = await counterModel.getId(gljCollectionName); } } else { data.id = await counterModel.getId(gljCollectionName); } this.setScene('add'); let result = await this.db.create(data); return result; } /** * 修改名称、规格型号、单位、市场单价等 * @param data * @returns {Promise.} */ async modifyGLJ(data,ration_glj){ let unitPriceFileModel = new UnitPriceFileModel(); let unitPriceFile = await unitPriceFileModel.getDataByProject(data.project_id); if (!unitPriceFile) { throw '没有对应的单价文件'; } //查找单价信息,有则返回,没有则新增并返回 let unitPriceFileId = unitPriceFile.id; let unitPriceModel = new UnitPriceModel(); let [unitPriceData, isAdd] = await unitPriceModel.addUnitPrice(data, unitPriceFileId,"modify"); let gljData=null; if(isAdd){ //如果是新增,则新增一条新的项目工料机 data.code = unitPriceData.code; gljData = await this.insertGLJWhenIsAdd(data,ration_glj,unitPriceFileId); }else { //如果不是新增,则查找是否有对应的项目工料机,有则返回,没有则新增 let condition = { project_id:data.project_id, original_code: data.original_code, name:data.name, specs:data.specs, type:data.type, unit:data.unit } let gljList = await this.findDataByCondition(condition,{_id: 0},false); if(gljList&&gljList.length>0){ for(let tem of gljList){ if(tem.code == unitPriceData.code){ gljData = tem; } } } if(gljData==null){ data.code = unitPriceData.code; gljData = await this.insertGLJWhenIsAdd(data,ration_glj,unitPriceFileId); } } gljData.unit_price = unitPriceData; return gljData } //修改属性后插入项目工料机 async insertGLJWhenIsAdd(glj,ration_glj,unitPriceFileId){ //新增项目工料机 let gljData = await this.add(glj); //查看是否是有配合比的工料机类型 if(this.ownCompositionTypes.indexOf(glj.type)!=-1){ // 配合比数据插入 let key_array = []; if(ration_glj.subType){//定额类型的工料机和定额工料机的key有点不同subType key_array= ['code','name','specs','unit','subType']; }else { key_array= ['code','name','specs','unit','type']; } let connect_key =this.getIndex(ration_glj,key_array); let connect_key_n =this.getIndex(glj,['code','name','specs','unit','type']); //先查找配合比数据是否已经存在 let mixRatioModel = new MixRatioModel(); let mixRatios_o = await mixRatioModel.findDataByCondition({connect_key: connect_key_n, unit_price_file_id: unitPriceFileId}, {_id: 0}, false); if(mixRatios_o&&mixRatios_o.length>0){//已经存在,不用再插入配合比数据,直接返回 return gljData; } //不存在,则查找原始的配合比数据,并为新工料机增加配合比数据 let mixRatios = await mixRatioModel.findDataByCondition({connect_key: connect_key, unit_price_file_id: unitPriceFileId}, {_id: 0}, false); let mixInsertResult ={}; if(mixRatios&&mixRatios.length>0){ let newMixRatioData = []; for(let m of mixRatios){ let tem ={ consumption: m.consumption, glj_id: m.glj_id, unit_price_file_id: m.unit_price_file_id, connect_key: connect_key_n, type: m.type, code: m.code, specs:m.specs, name:m.name, unit:m.unit }; newMixRatioData.push(tem); } mixInsertResult= await mixRatioModel.add(newMixRatioData); } } return gljData; } /** * 根据工料机id修改市场单价 * * @param {Object} updateData * @return {Promise} */ async modifyMarketPrice(updateData) { let result = {}; try { if (updateData.code === undefined || updateData.market_price === undefined || updateData.name === undefined || updateData.project_id === undefined) { throw '参数有误!'; } // 先查是否有对应code的数据 let gljListData = await this.findDataByCondition({code: updateData.code, project_id: updateData.project_id}, {_id: 0}, false); if (!gljListData) { throw '不存在对应code数据'; } // 获取标段对应的单价文件id let unitPriceFileModel = new UnitPriceFileModel(); let unitPriceFile = await unitPriceFileModel.getDataByProject(updateData.project_id); if (!unitPriceFile) { throw '没有对应的单价文件'; } let unitPriceFileId = unitPriceFile.id; let unitPriceModel = new UnitPriceModel(); let gljCount = gljListData.length; let [unitPriceData, isAdd] = await unitPriceModel.addUnitPrice(updateData, unitPriceFileId,"modify", gljCount); // 判断是否已存在对应数据 let includeField = [ {field: 'name', value: unitPriceData.name} ]; let gljIndex = this.isIncluded(gljListData, includeField); let gljData = isAdd ? {} : gljListData[gljIndex]; // 如果单价数据新增则工料机也需要新增 if (isAdd) { // 如果没有对应的记录则新增一条工料机数据,并更改name let regular = /\(\d+\)/; let changeString = '(' + gljCount + ')'; updateData.name = regular.test(updateData.name) ? updateData.name.replace(regular, changeString) : updateData.name + changeString; // 获取第一条数据作为数据源 let originalData = gljListData[0]; // 更改名称 originalData.name = updateData.name; originalData = JSON.stringify(originalData); gljData = await this.add(JSON.parse(originalData)); if (!gljData) { throw '新增工料机数据失败!'; } } gljData.unit_price = unitPriceData; result = gljData; } catch (error) { console.log(error); result = {}; } return result; } /** * 判断数据中是否包含某个数据 * * @param {Array} data * @param {Array} includeField * @return {Number} */ isIncluded(data, includeField) { let index = -1; if (data.length <= 0) { return index; } for(let tmp in data) { let counter = 0; for (let includeTmp of includeField) { if (data[tmp][includeTmp.field] === includeTmp.value) { counter++; } } if (counter === includeField.length) { index = tmp; break; } } return index; } /** * 工料机中组成物操作 * 该方法只在确保没有对应项目工料机的时候才会调用 * * @param {Object} data * @param {Number} projectId * @return {void} */ async compositionInit(data, unitPriceFileId,ext) { let gljId = data.glj_id === undefined ? 0 : data.glj_id; let projectId = data.project_id === undefined ? 0 : data.project_id; let mixRatioModel = new MixRatioModel(); if (gljId === 0 || projectId === 0) { throw '参数错误'; } let fromTable = data.from === undefined ? 'std' : data.from; var connect_key =this.getIndex(data,['code','name','specs','unit','type']); let e_mList = await this.getCompositionGLJListFromMixRatio(projectId,unitPriceFileId,connect_key,fromTable); //如果组成物数据已经存在,则以单价文件中组成物的数据为准,不用再往下做判断了(项目工料机中需要插入的已经在上一步中生成插入) if(e_mList.length > 0) return; // 查找对应组成物的项目工料机数据 let indexs=['code','name','specs','unit','type']; let [projectGljList, compositionGljList] = await this.getCompositionGLJList(gljId, projectId, indexs, fromTable); // 整理配合比待插入数据,单价文件中配合比没有数据,则以库中的组成物信息为准 let mixRatioInsertData = []; for (let tmp of compositionGljList) { let consumpiton = tmp.consumption; //多单价、多组成物消耗量的情况 fromTable if(ext && ext.quantityField &&( tmp.consumption[ext.quantityField]!= undefined && tmp.consumption[ext.quantityField]!=null)){ consumpiton = tmp.consumption[ext.quantityField]; } // 配合比数据插入 let mixRatioData = { consumption: consumpiton, glj_id: tmp.ID, unit_price_file_id: unitPriceFileId, connect_key: connect_key, type: tmp.gljType, code: tmp.code, specs:tmp.specs, name:tmp.name, unit:tmp.unit }; mixRatioInsertData.push(mixRatioData); } let unitPriceModel = new UnitPriceModel(); let unitPriceList = await unitPriceModel.model.find({unit_price_file_id:unitPriceFileId});//查找按文件id查找单价文件数据,用来判断单价文件信息是否已存在 // 整理插入的数据 let gljInsertData = []; let unitPriceInsertData = []; for(let tmp of compositionGljList) { let key = this.getIndex(tmp,['code','name','specs','unit','gljType']); if (projectGljList[key] === undefined) { // 项目工料机插入的数据 let gljData = this.getProjectGLJNewData(tmp,projectId); gljInsertData.push(gljData); } let basePrice = tmp.basePrice; //多单价、多组成物消耗量的情况 fromTable if(ext && ext.priceField &&(tmp.priceProperty && tmp.priceProperty[ext.priceField]!= undefined && tmp.priceProperty[ext.priceField]!=null)){ basePrice = tmp.priceProperty[ext.priceField]; } basePrice = scMathUtil.roundTo(basePrice,-6); // 单价文件插入的数据 let unitPriceData = { base_price: basePrice, // 初始市场价=基价 market_price: basePrice, code: tmp.code, name: tmp.name, unit_price_file_id: unitPriceFileId, type: tmp.gljType, short_name: tmp.shortName === undefined ? '' : tmp.shortName, glj_id: tmp.ID, specs: tmp.specs, unit: tmp.unit === undefined ? '' : tmp.unit, original_code:tmp.code, }; if(tmp.from=='cpt'){ unitPriceData.is_add = 1; } if(!unitPriceModel.isPropertyInclude(unitPriceList,['code','name','specs','unit','type'],unitPriceData)){ unitPriceInsertData.push(unitPriceData); } } // 整理完后开始插入数据 // 插入单价数据表 if(unitPriceInsertData.length >0) await unitPriceModel.add(unitPriceInsertData); // 插入配合比表 // 因为有可能项目工料机与单价数据已存在,但配合比数据不存在,所以先插入配合比,后续判断如果存在项目工料机则可以省下数据库操作 if(mixRatioInsertData.length>0){ let addMixRatioResult = await mixRatioModel.add(mixRatioInsertData); if (!addMixRatioResult) { throw '组成物插入单价数据失败!'; } } //插入项目工料机 if(gljInsertData.length > 0) await this.add(gljInsertData); return } getProjectGLJNewData(tmp,projectId){ let gljData = { glj_id: tmp.ID, project_id: projectId, code: tmp.code, name: tmp.name, specs: tmp.specs, unit: tmp.unit === undefined ? '' : tmp.unit, type: tmp.gljType, adjCoe:tmp.adjCoe, original_code:tmp.code, materialType: tmp.materialType, //三材类别 materialCoe: tmp.materialCoe, materialIndexType: tmp.materialIndexType, materialIndexUnit: tmp.materialIndexUnit, materialIndexCoe: tmp.materialIndexCoe }; return gljData; } //从配合比表中取组成物的信息以及对应的项目工料机信息,再从配合比数据中反查工料机库中的信息 async getCompositionGLJListFromMixRatio (projectId,unitPriceFileId,connect_key,fromTable = 'std'){ let mixRatioModel = new MixRatioModel(); let e_mList = await mixRatioModel.model.find({unit_price_file_id: unitPriceFileId,connect_key: connect_key}).lean(); if (e_mList.length <= 0) return []; let codeList = []; let ratioMap = {}; for(let tmp of e_mList) { codeList.push(tmp.code); let ckey = this.getIndex(tmp); ratioMap[ckey] = tmp } // 查找对应的项目工料机数据 let condition = {project_id: projectId,code: {"$in": codeList} }; let gljData = await this.model.find(condition, {_id: 0}).lean(); let matchGljs = {}; for(let g of gljData){ let gkey = this.getIndex(g); if(ratioMap[gkey]) matchGljs[gkey] = g; } //如果有组成物信息存在,但项目工料机信息不全的情况,应从数据库中查存询原始信息 // (只有在父工料机是来自标准的情况下做这个操作,因为组成物表中没有存具体的工料机是来自补充的还是标准库,而父工料机是补充库的,组成物有可能来自两个库,而父来自标准,子只会来自标准) let lessIDList = [],lessMix=[];//lessMix只有在父工料机是来自补充工料机的时候才要用到 let componentGljData = []; let gljInsertData = []; for(let mk in ratioMap){//找出缺少的工料机 if(!matchGljs[mk]){ lessMix.push(ratioMap[mk]); lessIDList.push(ratioMap[mk].glj_id); } } if(lessIDList.length > 0){ if(fromTable == "std"){ let gljListModel = new STDGLJLibGLJListModel(); let condition = {ID: {$in: lessIDList}}; componentGljData = await gljListModel.model.find(condition).lean(); for(let tmp of componentGljData){ let newProjctData = this.getProjectGLJNewData(tmp,projectId); gljInsertData.push(newProjctData) } }else { for(let m of lessMix){ m.from = 'cpt'; let newProjctData = this.getProjectGLJNewData(m,projectId); gljInsertData.push(newProjctData); } } } //这边只插入项目工料机数据,对于组成物文件中有的数据,理论上单价文件也是应该要有的,如果没有,那只能是mongodb数据库不支持事务的情况的问题 if(gljInsertData.length > 0) await this.add(gljInsertData); return e_mList; } /** * 获取组成物具体数据 * * @param {Number} projectGLJId * @param {Number} unitPriceFileId * @return {Promise} */ async getCompositionList(projectGLJId, unitPriceFileId) { let result = []; try { // 查找对应的项目工料机数据 let projectGLJData = await this.getDataById(projectGLJId,unitPriceFileId); let allowType = this.ownCompositionTypes; if (projectGLJData.unit_price === null || allowType.indexOf(projectGLJData.unit_price.type) < 0) { throw '找不到相关项目工料机'; } // 查找对应的项目工料机数据配合比,单价数据 let [gljData, mixRatioData,unitPriceData] = await this.getCompositionListByGLJ(projectGLJData, unitPriceFileId); if (gljData.length <= 0) { throw '没有对应的组成物项目工料机'; } gljData = this.combineData(gljData, unitPriceData, [], mixRatioData); // 排序 gljData.sort(function (a, b) { return parseInt(a.code) - parseInt(b.code); }); result = gljData; } catch (error) { console.log(error); result = []; } return result; } /** * 获取混凝土等有组成物相关工料机对应的组成物项目工料机数据 * * @param {Number} gljId * @param {Number} projectId * @param {String} indexBy * @param {String} fromTable * @return {Promise} 返回组成物工料机数据和组成物列表数据 */ async getCompositionGLJList(gljId, projectId, indexBy = null, fromTable = 'std') { // 获取对应的组成物数据 let gljListModel = fromTable === 'std' ? new STDGLJLibGLJListModel() : new GljModel(); let componentGljList = await gljListModel.getComponent(gljId); if (componentGljList.length <= 0) { return [{},[]]; } //2019-11-15 优化,用5个属性条件去查意义不大,用编号就能过滤得差不多了,最后再用5个属性去匹配。 同时可以提高查询效率 let codeList = []; let componentMap = {}; for(let tmp of componentGljList) { codeList.push(tmp.code); let ckey = this.getIndex(tmp,['code','name','specs','unit','gljType']); componentMap[ckey] = tmp } // 查找对应的项目工料机数据 let condition = {project_id: projectId,code: {"$in": codeList} }; let gljData = await this.model.find(condition, {_id: 0}).lean(); let matchGljs = {}; for(let g of gljData){ let gkey = this.getIndex(g); if(componentMap[gkey]) matchGljs[gkey] = g; } return [matchGljs, componentGljList]; } async getCompositionGLJByData(glj,unitPriceFileId){ let [gljData,mixRatioData,unitPriceData] = await this.getCompositionListByGLJ(glj,unitPriceFileId); let priceNum = unitPriceData?Object.getOwnPropertyNames(unitPriceData).length:0; let mixNum = mixRatioData?Object.getOwnPropertyNames(mixRatioData).length:0; if(priceNum !==mixNum){//检查组成物数据是否一致 console.log("组成物数据有误,组成物单价文件个数:"+priceNum+", 组成物个数:"+mixNum); return [] } gljData = this.combineData(gljData, unitPriceData, [], mixRatioData); return gljData; } /** * 反回组成物工料机和配合比数据 * @param glj * @param unitPriceFileId * @returns {Promise.} */ async getCompositionListByGLJ(glj,unitPriceFileId){ let t_index = this.getIndex(glj,['code','name','specs','unit','type']); // 查找对应的配合比数据 let mixRatioModel = new MixRatioModel(); let condition = {connect_key: t_index, unit_price_file_id: unitPriceFileId}; let mixRatios = await mixRatioModel.model.find(condition, {_id: 0}).lean(); //2019-11-15 优化,用5个属性条件去查意义不大,用编号就能过滤得差不多了,最后再用5个属性去匹配。 同时可以提高查询效率 let codeList = []; if(mixRatios.length<=0){ return [[],[],[]]; } let mixRatioData={}; for(let tmp of mixRatios) { codeList.push(tmp.code); let m_index = this.getIndex(tmp,['code','name','specs','unit','type']); mixRatioData[m_index]=tmp; } //数组去重 codeList = _.uniq(codeList); // 查找对应的项目工料机数据 let gcondition = {project_id: glj.project_id?glj.project_id:glj.projectID,code: {"$in": codeList}}; let gljData = await this.model.find(gcondition, {_id: 0}).lean(); // 查找对应的单价数据 let unitPriceModel = new UnitPriceModel(); let ucondition = { unit_price_file_id: unitPriceFileId,code: {"$in": codeList}}; let unitPriceList = await unitPriceModel.model.find(ucondition, {_id: 0}).lean(); // 整理数据 let unitPriceData = {}; for(let tmp of unitPriceList) { let u_index = this.getIndex(tmp,['code','name','specs','unit','type']); if(mixRatioData[u_index]) unitPriceData[u_index] = tmp;//过滤掉不完全匹配的工料机单价 } let c_gljData = []; for(let g of gljData){//过滤掉不是组成物的工料机 let g_index = this.getIndex(g,['code','name','specs','unit','type']); if(mixRatioData[g_index]) c_gljData.push(g); } return [c_gljData,mixRatioData,unitPriceData]; } /** * 根据条件获取对应项目工料机数据 * * @param {Number} id * @return {Promise} */ async getDataById(id,unitPriceFileId) { // 查找对应的项目工料机数据 let projectGLJData = await this.findDataByCondition({id: id}); if (projectGLJData === null) { throw '没有找到对应数据'; } // 查找对应的单价数据 let unitPriceModel = new UnitPriceModel(); let condition={ unit_price_file_id:unitPriceFileId, code: projectGLJData.code, name:projectGLJData.name, specs:projectGLJData.specs, type:projectGLJData.type, unit:projectGLJData.unit }; if (!condition.specs) { delete condition.specs; condition.$or = [{specs: null}, {specs: ''}]; } let unitPrice = await unitPriceModel.findDataByCondition(condition); projectGLJData.unit_price = unitPrice; return projectGLJData; } } module.exports = GLJListModel;