/** * Created by zhang on 2018/2/9. */ //先导出后require可以解决循环引用问题 module.exports = { replaceRations: replaceRations, addNewRation:addNewRation, addMultiRation: addMultiRation, deleteMultiRation:deleteMultiRation, getSameSectionRations:getSameSectionRations, getExtendData:getExtendData, getDefaultProgramID:getDefaultProgramID, deleteSubListByQuery:deleteSubListByQuery, updateCoeAdjust:updateCoeAdjust }; let mongoose = require('mongoose'); import SearchDao from '../../complementary_ration_lib/models/searchModel'; const scMathUtil = require('../../../public/scMathUtil').getUtil(); let ration_glj_facade = require("../../ration_glj/facade/ration_glj_facade"); let glj_calculate_facade = require("../../ration_glj/facade/glj_calculate_facade"); let quantity_detail = require("../facade/quantity_detail_facade"); let ration_glj = mongoose.model('ration_glj'); let ration_coe = mongoose.model('ration_coe'); let ration_model = require('../models/ration'); let bill_model = require('../models/bills'); let decimal_facade = require('./decimal_facade'); let installationFeeModel = mongoose.model("installation_fee"); let rationInstallationModel = mongoose.model('ration_installation'); let rationTemplateModel = mongoose.model('ration_template'); const uuidV1 = require('uuid/v1'); let std_glj_lib_gljList_model = mongoose.model('std_glj_lib_gljList'); let complementary_glj_model = mongoose.model('complementary_glj_lib'); let rationItemModel = mongoose.model("std_ration_lib_ration_items"); let complementaryRationModel = mongoose.model('complementary_ration_items'); let coeMolde = mongoose.model('std_ration_lib_coe_list'); let compleCoeModel = mongoose.model('complementary_ration_coe_list'); let _= require('lodash'); const projectDao = require('../../pm/models/project_model').project; let projectModel = mongoose.model('projects'); const fs = require('fs'); async function addNewRation(data,compilation) { let query = data.itemQuery; let stdRation = null; let startTime = +new Date(); if(query){ let searchDao = new SearchDao(); stdRation = await searchDao.getRationItem(query.userID, compilation._id, [query.rationRepId],query.code, query.ID); //data.newData.code = query.code; } let stdRationTime = +new Date(); console.log("取std定额时间-------------------------------"+(stdRationTime - startTime)); if(data.brUpdate.length>0){ await updateSerialNo(data.brUpdate); } let newRation =await insertNewRation(data.newData,data.defaultLibID,stdRation,data.calQuantity); let addRationGLJTime = +new Date(); console.log("插入新定额时间-------------------------------"+(addRationGLJTime - stdRationTime)); if(stdRation){ return await addRationSubList(stdRation,newRation,data.needInstall,compilation); }else { return {ration:newRation}; } } async function addMultiRation(datas,compilation) { let rst = []; for(let data of datas){ let r = await addNewRation(data,compilation); rst.push(r); } return rst; } async function deleteMultiRation(rations) {//这里是只有删除的情况,删除定额的同时删除定额下挂的其它子项目 if(rations.length > 0){//删除定额下的 let rationIDS = _.map(rations,'ID'); await deleteSubListByQuery({projectID:rations[0].projectID,rationID:{"$in": rationIDS}}); await ration_model.model.deleteMany({ID:{"$in": rationIDS}}); } } async function getSameSectionRations(data,userId,compilationId){ //let userId //要先根据定额获取所属章节的ID let from = data.from; //定额类型,是标准的还是用户定义的 let code = data.code; let libID = data.libID; let sectionId,rations=[]; if(from == 'std'){ let ration = await rationItemModel.findOne({rationRepId:libID,code:code},['sectionId']); sectionId = ration? ration.sectionId:null; }else { let ration = await complementaryRationModel.findOne({userId:userId,compilationId: compilationId,code:code},['sectionId']); sectionId = ration?ration.sectionId:null; } if(sectionId){ if (from == 'std') { rations = await rationItemModel.find({sectionId: sectionId}); } else { rations = await complementaryRationModel.find({userId: userId, sectionId: sectionId}); } rations = _.sortBy(rations,'code'); } return rations } async function updateSerialNo(serialNoUpdate){ let tasks=[]; for(let data of serialNoUpdate){ let task={ updateOne:{ filter:{ ID:data.ID, projectID:data.projectID }, update :{ serialNo:data.serialNo } } }; tasks.push(task); } await ration_model.model.bulkWrite(tasks); } async function insertNewRation(newData,defaultLibID,std,calQuantity) {//插入新的定额 let startTime = +new Date(); if(std){ newData.code = std.code; newData.name = std.name; newData.caption = std.caption; newData.unit = std.unit; newData.libID = std.rationRepId; newData.stdID = std.ID; newData.content = std.jobContent; newData.annotation = std.annotation; if (std.chapter) { newData.comments = std.chapter.explanation; newData.ruleText = std.chapter.ruleText; } newData.prefix = ''; newData.from = std.type === 'complementary' ? 'cpt' : 'std'; if(defaultLibID !== std.rationRepId){//定额是默认定额库中的时,只显示编号; newData.prefix = '借';//定额不是默认定额库中的、且不是补充定额库中的时, 在定额编号前显示“借”。 if(newData.from === 'cpt') newData.prefix = '补';//定额是补充定额库中的时,在定额编号前显示“补”; } if(std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID newData.programID = await getProgramForProject(newData.projectID); }else { newData.programID = std.feeType; } newData.rationAssList = createRationAss(std); // calculate ration Quantity } if(calQuantity){ await CalculateQuantity(newData,newData.billsItemID,newData.projectID); } let addRationGLJTime = +new Date(); console.log("计算消耗量时间-------------------------------"+(addRationGLJTime - startTime)); let newRation = await ration_model.model.create(newData); return newRation; /*ration_model.model.create(newData); return newData;*/ } async function replaceRations(userID,data,compilation) { let searchDao = new SearchDao(); let recodes = []; for(let recode of data.nodeInfo){ let stdRation = await searchDao.getRationItem(userID,compilation._id,data.libIDs,recode.newCode, null); let newRecode = await replaceRation(recode,stdRation,data.defaultLibID,data.projectID,data.calQuantity,compilation,data.cleanzmhs); if(newRecode){ recodes.push(newRecode); }else { break; } } return recodes; } async function getDefaultProgramID(data) { let searchDao = new SearchDao(); let programID; let std = await searchDao.getRationItem(data.userID,data.compilationId,[data.libID],data.code, null); if(std == null||std ==undefined || std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID programID = await getProgramForProject(data.projectID); }else { programID = std.feeType; } return programID; } async function replaceRation(nodeInfo,stdRation,defaultLibID,projectID,calQuantity,compilation,cleanzmhs) { if(nodeInfo.newCode == null||nodeInfo.newCode ==""){//说明是删除编号,则要变成一条空定额 await deleRationSubRecode(projectID,nodeInfo.ID);//删除定额下挂的各种数据,如定额工料机等 return await setEmptyRation(projectID,nodeInfo.ID); }else if(stdRation){ await deleRationSubRecode(projectID,nodeInfo.ID,cleanzmhs);//删除定额下挂的各种数据,如定额工料机等 let newRation = await updateRation(stdRation,defaultLibID,nodeInfo.ID,nodeInfo.billsItemID,projectID,calQuantity,cleanzmhs);//生成并插入新的定额 return await addRationSubList(stdRation,newRation,nodeInfo.needInstall,compilation,cleanzmhs); }else { return null; } } async function addRationSubList(stdRation,newRation,needInstall,compilation,cleanzmhs=false) { let startTime = +new Date(); let ration_gljs = await addRationGLJ(stdRation,newRation,compilation); let addRationGLJTime = +new Date(); console.log("添加定额工料机时间-----"+(addRationGLJTime - startTime)); let ration_coes = await addRationCoe(stdRation,newRation,compilation); let addRationCoeTime = +new Date(); console.log("添加定额coe时间-----"+(addRationCoeTime - addRationGLJTime)); let ration_installations = []; let ration_template = []; if(cleanzmhs == false){//清除子目换算即cleanzmh==true时 模板子目、安装增加费不用恢复成标准的 if(needInstall && stdRation.type == 'std'){//只有标准的定额才有安装增加费,补充的定额没有安装增加费 ration_installations = await addRationInstallFee(stdRation,newRation); } let addRationInstallFeeTime = +new Date(); console.log("添加定额install时间-----"+(addRationInstallFeeTime - addRationCoeTime)); //添加定额模板子目 ration_template = await addRationTemplate(stdRation,newRation); } return {ration:newRation,ration_gljs:ration_gljs,ration_coes:ration_coes,ration_installations:ration_installations,ration_templates:ration_template?[ration_template]:[]}; } async function addRationInstallFee(std,newRation) { let install_fee_list = []; if(std.hasOwnProperty('rationInstList') && std.rationInstList.length > 0){ let installFee = await installationFeeModel.findOne({'projectID': newRation.projectID}); if(!installFee) return;//如果没有找到项目对应的安装增加费,则不添加 for(let ri of std.rationInstList){ let feeItem = _.find(installFee.installFeeItem,{'ID':ri.feeItemId}); let section = _.find(installFee.installSection,{'ID':ri.sectionId}); if(feeItem&§ion){ let tem_r_i = { libID:installFee.libID, projectID:newRation.projectID, rationID:newRation.ID, feeItemId:feeItem.ID, sectionId:section.ID, itemName:feeItem.feeItem, feeType:feeItem.feeType, sectionName:section.name, unifiedSetting:1, ruleId:'' }; if(feeItem.isCal==1&§ion.feeRuleId&§ion.feeRuleId!=''){//勾选记取时并且有规则ID时才读取 let feeRule = _.find(installFee.feeRule,{'ID':section.feeRuleId}); if(feeRule){ tem_r_i.ruleId = feeRule.ID; } } tem_r_i.ID = uuidV1(); install_fee_list.push(tem_r_i); } } if(install_fee_list.length>0){ await rationInstallationModel.insertMany(install_fee_list); } } return install_fee_list; } async function addRationTemplate(std,newRation) { let templateList = []; if(std.hasOwnProperty('rationTemplateList') && std.rationTemplateList.length > 0){ for(let tem of std.rationTemplateList){ let re_ration = await rationItemModel.findOne({rationRepId:std.rationRepId,ID:tem.rationID}); if(re_ration){ let template = { billID:"", fxID:"", quantity:"0", coe:"0" }; template.code = re_ration.code; template.name = re_ration.name; template.type = tem.type; template.unit = re_ration.unit; template.billsLocation = tem.billsLocation; template.defaultLocation = tem.billsLocation; templateList.push(template) } } } if(templateList.length > 0){ let ration_template = {}; ration_template.ID = uuidV1(); ration_template.projectID = newRation.projectID; ration_template.rationID = newRation.ID; ration_template.createLocation = 1; //默认模板子目分别放在措施项目下 ration_template.templateList = templateList; await rationTemplateModel.create(ration_template); return ration_template; } return null; } async function addRationCoe(std,newRation,compilation) { let ration_coe_list = []; let seq = 0; if(std.hasOwnProperty('rationCoeList')&&std.rationCoeList.length>0){//添加标准库的工料机 for(let sub of std.rationCoeList){ let libCoe; if (std.type === 'std') { libCoe = await coeMolde.findOne({'libID':std.rationRepId,'ID':sub.ID,"$or": [{"isDeleted": null}, {"isDeleted": false}]});//std.rationRepId; } else { libCoe = await compleCoeModel.findOne({ID: sub.ID, $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}]}); } if(libCoe){ let newCoe = {}; newCoe.ID = uuidV1(); newCoe.coeID = sub.ID; newCoe.seq = seq; newCoe.name = libCoe.name; newCoe.content = libCoe.content; newCoe.original_code = libCoe.original_code; newCoe.option_codes = libCoe.option_codes; newCoe.option_list = libCoe.option_list; newCoe.isAdjust=0; newCoe.coes = libCoe.coes; newCoe.rationID = newRation.ID; newCoe.projectID = newRation.projectID; seq++; ration_coe_list.push(newCoe); } } } let lastCoe = await getCustomerCoe(newRation.projectID,newRation.ID,seq,compilation); ration_coe_list.push(lastCoe); await ration_coe.insertMany(ration_coe_list); return ration_coe_list; } function getCustomerCoeData() { var coeList = [ {amount:1, operator:'*', gljCode:null, coeType:'定额'}, { amount:1, operator:'*', gljCode:null, coeType:'人工'}, { amount:1, operator:'*', gljCode:null, coeType:'材料'}, { amount:1, operator:'*', gljCode:null, coeType:'机械'}, { amount:1, operator:'*', gljCode:null, coeType:'主材'}, { amount:1, operator:'*', gljCode:null, coeType:'设备'} ]; return coeList; }; async function getCustomerCoe(projectID,rationID,seq,compilation){//取自定义乘系数,根据编办不同,内容可能不同 //生成默认的自定义乘系数 let lastCoe ={ coeID:-1, name : '自定义系数', content:'人工×1,材料×1,机械×1,主材×1,设备×1', isAdjust:1, seq:seq, rationID : rationID, projectID : projectID }; lastCoe.ID = uuidV1(); lastCoe.coes = getCustomerCoeData(); try { //查看编办中有没有重写路径 if(compilation.overWriteUrl && compilation.overWriteUrl!=""){ let overWrite = require("../../.."+compilation.overWriteUrl); if(overWrite.getCusCoeContent) lastCoe.content = overWrite.getCusCoeContent(); if(overWrite.getCustomerCoeData) lastCoe.coes = overWrite.getCustomerCoeData(); } return lastCoe }catch (err){ console.log("读取自定义系数重写文件失败"); console.log(err.message); return lastCoe } } //对于多单价,多组成物消耗量的编办,通过这个方法获取单价、组成物消耗量的字段, function getExtendData(property,compilation) { return projectDao.getExtendData(property,compilation); } async function addRationGLJ(std,newRation,compilation) { let newRationGLJList = []; let rationGLJShowList = []; let unitPriceFileId = 0; let property = await projectDao.getProjectProperty(newRation.projectID); if(property){ unitPriceFileId = property.unitPriceFile !== undefined ? property.unitPriceFile.id : 0; } let ext = getExtendData(property,compilation); let first = +new Date(); if(std.hasOwnProperty('rationGljList') && std.rationGljList.length > 0){ let stdGLJID =[];//标准工料机ID数组 let cptGLJID=[];//补充工料机ID数组 //let stdGLJID = _.map(std.rationGljList,'gljId'); for(let tem_g of std.rationGljList){ if(tem_g.type == 'complementary'){ cptGLJID.push(tem_g.gljId); }else { stdGLJID.push(tem_g.gljId); } } let stdGLJList = stdGLJID.length > 0 ? await std_glj_lib_gljList_model.find({'ID':{'$in':stdGLJID}}):[];//速度优化-------先一次性取出所有的工料机列表 let stdGLJMap = _.indexBy(stdGLJList, 'ID'); let cptGLJList = cptGLJID.length > 0 ? await complementary_glj_model.find({'userId':std.userId,'ID':{'$in':cptGLJID}}):[]; let cptGLJMap = _.indexBy(cptGLJList, 'ID'); let stdGLJMapTime = +new Date(); console.log("找到工料机映射表时间-------------------------------"+(stdGLJMapTime - first)); for(let sub of std.rationGljList){ let newGLJ = {}; newGLJ.ID = uuidV1(); newGLJ.projectID = newRation.projectID; newGLJ.GLJID = sub.gljId; newGLJ.rationID = newRation.ID; newGLJ.billsItemID = newRation.billsItemID; newGLJ.rationItemQuantity = sub.consumeAmt; newGLJ.quantity = sub.consumeAmt; newGLJ.glj_repository_id = std.rationRepId; let std_glj = null; if(sub.type == 'complementary'){//有可能来自标准工料机库或补充工料机库 std_glj = cptGLJMap[sub.gljId]; newGLJ.from = 'cpt'; }else { std_glj = stdGLJMap[sub.gljId]; newGLJ.from = 'std'; //多单价情况处理 if(ext && ext.priceField && std_glj && std_glj.priceProperty){ std_glj.basePrice = std_glj.priceProperty[ext.priceField]; } } if(std_glj){ newGLJ.name = std_glj.name; newGLJ.code = std_glj.code; newGLJ.original_code = std_glj.code; newGLJ.unit = std_glj.unit; newGLJ.specs = std_glj.specs; newGLJ.model = std_glj.model; newGLJ.basePrice = std_glj.basePrice; newGLJ.marketPrice = std_glj.basePrice; newGLJ.shortName = std_glj.shortName; newGLJ.type = std_glj.gljType; newGLJ.repositoryId = std_glj.repositoryId; newGLJ.adjCoe = std_glj.adjCoe; newGLJ.materialType = std_glj.materialType; newGLJ.materialCoe = std_glj.materialCoe; newGLJ.materialIndexType = std_glj.materialIndexType; newGLJ.materialIndexUnit = std_glj.materialIndexUnit; newGLJ.materialIndexCoe = std_glj.materialIndexCoe; newGLJ.createType = 'normal'; let info = await ration_glj_facade.getInfoFromProjectGLJ(newGLJ,unitPriceFileId,ext); newGLJ = ration_glj_facade.createNewRecord(info); newRationGLJList.push(newGLJ); rationGLJShowList.push(info); } //let InfoFromProjectGLJ = +new Date(); //console.log("找到项目工料机时间-------------------------------"+(InfoFromProjectGLJ - std_gljTime)); } } let before = +new Date(); console.log("总查询时间为-------------------------------"+(before-first)); if(newRationGLJList.length>0){ await ration_glj.insertMany(newRationGLJList); } let after = +new Date(); console.log("实际插入时间为-------------------------------"+(after-before)); console.log("总操作时间为-------------------------------"+(after-first)); return rationGLJShowList; } async function deleRationSubRecode(projectID,rationID,cleanzmhs=false) {//删除挂在定额下的数据,如工程量明细,定额工料机等 let delete_query={projectID: projectID, rationID: rationID}; //删除工程量明细 await deleteSubListByQuery(delete_query,cleanzmhs) ; } async function deleteSubListByQuery(delete_query,cleanzmhs=false) { if(cleanzmhs == false){//清空子目换算即cleanzmh==true时不需要清空工程量明细、模板关联子目、安装增加费 await quantity_detail.deleteByQuery(delete_query) ;//删除工程量明细 await rationInstallationModel.deleteMany(delete_query);//删除安装增加费 await rationTemplateModel.deleteMany(delete_query);//删除模板关联子目 } //to do稳定土也要删除 await ration_coe.deleteMany(delete_query);//删除附注条件 await ration_glj.deleteMany(delete_query);//删除定额工料机 } async function updateCoeAdjust(data,compilation) { let replace = []; await ration_coe.update({ID:data.ID},data.doc); //添加单个工料机的情况 if (data.add.length > 0) await ration_glj_facade.insertAddTypeGLJ(data.add,compilation); if(data.delete.length > 0) await ration_glj_facade.deleteGLJ(data.delete); //替换工料机的情况 if (data.replace.length > 0){ for(let r of data.replace){ replace.push(await ration_glj_facade.replaceGLJByData(r,compilation)) ; } } let cal_result = await glj_calculate_facade.calculateQuantity({projectID:data.projectID,rationID:data.rationID},null,true); let coe = { query:{ID:data.ID,projectID:data.projectID}, doc:data.doc }; let ration_glj ={ quantityRefresh:true, glj_result:cal_result.glj_result }; let ration = { ID:cal_result.rationID, adjustState:cal_result.adjustState, name:cal_result.rationName }; return {coe:coe,ration_glj:ration_glj,ration:ration,add:data.add,delete:data.delete,replace:replace} } async function updateRation(std,defaultLibID,rationID,billsItemID,projectID,calQuantity,cleanzmh=false) { // insertNewRation let ration ={}; ration.code = std.code; ration.name = std.name; ration.caption = std.caption; ration.unit = std.unit; if (std.type === 'std') { ration.libID = std.rationRepId; ration.stdID = std.ID; } ration.content = std.jobContent; ration.adjustState = ''; ration.isFromDetail=0; ration.isSubcontract=false; ration.fees=[]; if (std.chapter) { ration.comments = std.chapter.explanation; ration.ruleText = std.chapter.ruleText; } ration.from = std.type === 'complementary' ? 'cpt' : 'std'; //定额前缀 none:0, complementary:1, borrow: 2 ration.prefix = ''; if(parseInt(defaultLibID) !== std.rationRepId){//定额是默认定额库中的时,只显示编号; ration.prefix = '借';//定额不是默认定额库中的、且不是补充定额库中的时, 在定额编号前显示“借”。 if(ration.from === 'cpt') ration.prefix = '补';//定额是补充定额库中的时,在定额编号前显示“补”; } ration.rationAssList = createRationAss(std);//生成辅助定额 if(cleanzmh==false){//如果是清空子目换算,即cleanzmh==true 保留定额工程量、工程量表达式、含量(分解系数)、取费专业(取费类别) if(std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID ration.programID = await getProgramForProject(projectID); }else { ration.programID = std.feeType; } if(calQuantity){ await CalculateQuantity(ration,billsItemID,projectID); } } let unsetObject = { "marketUnitFee":1, 'marketTotalFee':1, "maskName":1 } let newRation = await ration_model.model.findOneAndUpdate({ID:rationID,projectID:projectID},{"$set":ration,"$unset":unsetObject},{new: true});//; return newRation; } async function setEmptyRation(projectID,rationID){ let ration ={}; ration.code = ""; ration.name = ""; ration.caption = ""; ration.unit = ""; ration.libID = null; ration.content = ""; ration.adjustState = ''; ration.isFromDetail=0; ration.isSubcontract=false; ration.fees=[]; ration.comments = ""; ration.ruleText = ""; ration.quantity=""; ration.contain=""; ration.quantityEXP=""; ration.from = 'std'; //定额前缀 none:0, complementary:1, borrow: 2 ration.prefix = ''; ration.rationAssList = []; ration.marketUnitFee =""; ration.marketTotalFee =""; ration.maskName = ""; ration.targetTotalFee =''; ration.targetUnitFee = ""; ration.deleteInfo = null; ration.quantityCoe = {}; ration.rationQuantityCoe=""; ration.tenderQuantity = ""; ration.programID = null; let newRation = await ration_model.model.findOneAndUpdate({ID:rationID,projectID:projectID},{"$set":ration},{new: true});//; return {ration:newRation,ration_gljs:[],ration_coes:[],ration_installs:[]}; } function createRationAss(std) { let rationAssList = [];//生成辅助定额 if(std.hasOwnProperty('rationAssList')&&std.rationAssList.length>0){ let assGroup = _.groupBy(std.rationAssList,'name'); for(let key in assGroup){ let assList = assGroup[key]; let ass = assList[0]; ass._doc.actualValue = ass.stdValue; ass._doc.isAdjust = 0; if(_.isString(ass._doc.assistCode)) ass._doc.assistCode = ass._doc.assistCode.replace("\n",""); if(_.isString(ass._doc.thirdRationCode)) ass._doc.thirdRationCode = ass._doc.thirdRationCode.replace("\n",""); if(assList.length > 1){ ass._doc.groupList = JSON.parse(JSON.stringify(assList)) ; ass._doc.maxValue = assList[assList.length-1]._doc.maxValue; } rationAssList.push(ass); } } return rationAssList; } async function CalculateQuantity (ration,billsItemID,projectID) { // calculate ration Quantity let project = await projectModel.findOne({ID:projectID}); let decimalObject =await decimal_facade.getProjectDecimal(projectID,project); let quantity_decimal = (decimalObject&&decimalObject.ration&&decimalObject.ration.quantity)?decimalObject.ration.quantity:3; let pbill = await bill_model.model.findOne({projectID:projectID,ID:billsItemID}); let t_unit = ration.unit?ration.unit.replace(/^\d+/,""):""; if(t_unit!=pbill.unit){//如果定额工程量的单位去除前面的数字后不等于清单单位,定额工程量保持不变 return ; } let billsQuantity = pbill.quantity ? pbill.quantity : 0; let bill_decimal = await decimal_facade.getBillsQuantityDecimal(projectID,pbill.unit,project); billsQuantity=scMathUtil.roundForObj(billsQuantity,bill_decimal); ration.quantityEXP="QDL"; ration.quantity = scMathUtil.roundForObj(billsQuantity / FilterNumberFromUnit(ration.unit),quantity_decimal);//不管是否打勾都做转换 ration.contain = scMathUtil.roundForObj(ration.quantity/billsQuantity,6); }; async function getProgramForProject(projectID){ let project = await projectModel.findOne({ID:projectID}); return project.property.engineering; } function FilterNumberFromUnit (unit) { let reg = new RegExp('^[0-9]+'); if (reg.test(unit)) { return parseInt(unit.match(reg)[0]); } else { return 1; } };