/** * Created by chen on 2017/7/20. */ /** * Created by chen on 2017/7/10. */ let mongoose = require('mongoose'); let consts = require('../../main/models/project_consts'); let commonConsts = consts.commonConst; let _=require("lodash"); let async_n = require("async"); let quantity_detail_model = mongoose.model('quantity_detail'); const uuidV1 = require('uuid/v1'); let ration_model = mongoose.model('ration'); let bill_model=mongoose.model("bills"); const scMathUtil = require('../../../public/scMathUtil').getUtil(); let decimal_facade = require('./decimal_facade'); module.exports={ save:save, getData:getData, deleteByRation:deleteByRation, deleteByBill:deleteByBill, quantityEditChecking:quantityEditChecking, saveQuantityDetail:saveQuantityDetail, update:update, updateRegex:updateRegex, insertRecode:insertRecode, deleteRecode:deleteRecode, swapRow:swapRow, deleteByQuery:deleteByQuery }; let operationMap={ 'ut_update':update_quantity_detail, }; let updateFunctionMap = { 'insertRecode':insertRecode } async function saveQuantityDetail(datas) { let doc = datas; doc.ID = uuidV1(); if(doc.refreshQuantity==false){ //如果选择了不替换工程量,则清空 await cleanQuantityDetail(doc); return {}; } if(doc.hasOwnProperty('regex')){ return await insertRecodeWithReg(doc); }else { return await createNormalRecode(doc); } } async function update(datas) { let doc = datas.doc; if(doc.hasOwnProperty('isSummation')){ return await doIsSummationUpdate(datas.query,doc); }else { await quantity_detail_model.update(datas.query,doc); return datas; } } async function swapRow(datas) { for(let task of datas){ await update(task); } return {refreshList:datas}; } async function updateRegex(datas) { let resultObjec ={}; let detailList = []; let node ={}; let decimal =await decimal_facade.getProjectDecimal(datas.query.projectID); if(datas.query.hasOwnProperty('rationID')){ detailList = await quantity_detail_model.find({'projectID':datas.query.projectID,'rationID':datas.query.rationID}).sort('seq').exec(); node.type = consts.projectConst.RATION; node.ID = datas.query.rationID; }else { detailList = await quantity_detail_model.find({'projectID':datas.query.projectID,'billID':datas.query.billID}).sort('seq').exec(); node.type = consts.projectConst.BILLS; node.ID=datas.query.billID; } let regex; let result; if(datas.doc.regex==null){ result=0; datas.doc.referenceIndexs=[]; }else{ if(datas.doc.hasOwnProperty('result')){//如果前端已经计算好了 result = datas.doc.result; }else { regex = datas.doc.regex.toUpperCase(); let referenceIndexs = datas.doc.referenceIndexs; result = getEvalResult(referenceIndexs,detailList,regex,decimal); } } detailList[datas.query.index].result =result; detailList[datas.query.index].regex=datas.doc.regex; detailList[datas.query.index].referenceIndexs =datas.doc.referenceIndexs; let updateTasks =[]; datas.doc.result=result; updateTasks.push({ query:{ ID:datas.query.ID, projectID:datas.query.projectID }, doc:datas.doc }) updateReferenceRecode(datas.query.index+1,detailList,updateTasks); await quantity_detail_model.bulkWrite(generateUpdateTaks(updateTasks)); resultObjec.refreshList=updateTasks; if(datas.query.refreshQuantity==true){ let data = await summateResults(datas.query,detailList,decimal); node.data = data; resultObjec.node = node; } return resultObjec; } async function cleanQuantityDetail(doc) { let query = { projectID:doc.projectID } if(doc.hasOwnProperty('rationID')){ query.rationID = doc.rationID; }else { query.billID = doc.billID; } return await quantity_detail_model.deleteMany(query); } async function insertRecode(doc){ let query = { projectID:doc.projectID, seq : { $gte: doc.seq } } if(doc.hasOwnProperty('rationID')){ query.rationID = doc.rationID; }else { query.billID = doc.billID; } let quantity_detail_List = await getDatailList(doc,{data:{}}); let update_task = getUpdateReferenceTask(quantity_detail_List,doc.seq,1); await quantity_detail_model.update(query,{$inc:{seq:1}},{multi: true}); if(update_task.length>0){ await quantity_detail_model.bulkWrite(generateUpdateTaks(update_task)); } doc.ID = uuidV1(); let newrecode = await quantity_detail_model.create(doc); let data={ doc:newrecode, resort:true, update_task:update_task } return data; } async function doInsertRecode(doc) { let result={ err:null } try{ let query = { projectID:doc.projectID, seq : { $gte: doc.seq } } if(doc.hasOwnProperty('rationID')){ query.rationID = doc.rationID; }else { query.billID = doc.billID; } let quantity_detail_List = await getDatailList(doc,{data:{}}); let update_task = getUpdateReferenceTask(quantity_detail_List,doc.seq,1); await quantity_detail_model.update(query,{$inc:{seq:1}},{multi: true}); if(update_task.length>0){ await quantity_detail_model.bulkWrite(generateUpdateTaks(update_task)); } let newrecode = await quantity_detail_model.create(doc); let returndata ={ updateTpye:commonConsts.UT_CREATE, moduleName:consts.projectConst.QUANTITY_DETAIL, data:{ doc:newrecode, resort:true, update_task:update_task } }; result.returndata =returndata return result; }catch (error){ console.log(error) result.err; return result } } function getUpdateReferenceTask(quantity_detail_List,seq,re) { let update_task=[]; for(let q of quantity_detail_List){ let need_update =false; let newReg = q.regex; let newReferenceIndex; if(q.referenceIndexs.length>0){ for (let i =0;i< q.referenceIndexs.length;i++){ if(q.referenceIndexs[i]>seq){ newReg = replaceAll('C'+q.referenceIndexs[i],'C'+(q.referenceIndexs[i]+re),newReg); newReg = replaceAll('c'+q.referenceIndexs[i],'c'+(q.referenceIndexs[i]+re),newReg); q.referenceIndexs[i] +=re; need_update = true; } } } if(need_update){ newReferenceIndex = q.referenceIndexs; let task ={ query:{ ID:q.ID, projectID:q.projectID }, doc:{ regex:newReg, referenceIndexs:newReferenceIndex } } update_task.push(task); } } return update_task; } async function createNormalRecode(doc) { let result ={}; result.newRecord= await quantity_detail_model.create(doc); return result; } async function insertRecodeWithReg (doc) { let returnObjec={} try { let decimal =await decimal_facade.getProjectDecimal(doc.projectID); let regex = doc.regex.toUpperCase(); let referenceIndexs = doc.referenceIndexs; let detailList = await getDatailList(doc,returnObjec); if(!doc.hasOwnProperty('result')){//前端已结计算完了,后端就不用再计算了 doc.result =getEvalResult(referenceIndexs,detailList,regex,decimal); } let refreshQuantity =false; if(doc.refreshQuantity==true){ refreshQuantity = true; } delete doc.refreshQuantity; let newRecord = await quantity_detail_model.create(doc) ; detailList.push(newRecord); if(refreshQuantity==true){ let data = await summateResults(doc,detailList,decimal); returnObjec.node.data = data; } returnObjec.newRecord = newRecord; return returnObjec; }catch (error){ console.log(error); throw new Error('输入的表达式有误,请重新输入!'); } } async function doIsSummationUpdate(query,doc) { let returnObjec={query:query,doc:doc}; let decimal =await decimal_facade.getProjectDecimal(query.projectID); let refreshQuantity=false; if(query.refreshQuantity==true){ refreshQuantity=true; } delete query.refreshQuantity; await quantity_detail_model.update(query,doc); let detailList = await getDatailList(query,returnObjec); if(refreshQuantity==true){ let data = await summateResults(query,detailList,decimal); returnObjec.node.data = data; } return returnObjec; } async function getDatailList(query,resultObject) { let detailList = []; let node={}; if(query.hasOwnProperty('rationID')){ detailList = await quantity_detail_model.find({'projectID':query.projectID,'rationID':query.rationID}).sort('seq').exec(); node.type = consts.projectConst.RATION; node.ID = query.rationID; }else { detailList = await quantity_detail_model.find({'projectID':query.projectID,'billID':query.billID}).sort('seq').exec(); node.type = consts.projectConst.BILLS; node.ID=query.billID; } resultObject.node = node; return detailList; } function updateReferenceRecode(index,detailList,updateTasks) { for(let d of detailList){ if(_.includes(d.referenceIndexs,index)){ let tResult = getEvalResult(d.referenceIndexs,detailList,d.regex); let t = { query:{ ID:d.ID, projectID:d.projectID }, doc:{ result:tResult } }; d.result = tResult; updateTasks.push(t); updateReferenceRecode(d.seq+1,detailList,updateTasks); } } } async function summateResults (query,detailList,decimal) { let quantity = 0; let doc = {}; decimal = decimal?decimal:await decimal_facade.getProjectDecimal(query.projectID); for(let d of detailList){ if(d.isSummation==1){ let result = d.result==null||d.result==undefined?0:d.result; quantity+=result; } } if(query.hasOwnProperty('rationID')){ let ration = await ration_model.findOne({'ID':query.rationID,'projectID':query.projectID,deleteInfo: null}); let bill = await bill_model.findOne({'projectID':query.projectID,deleteInfo: null,"ID":ration.billsItemID}); let bill_decimal = await decimal_facade.getBillsQuantityDecimal(query.projectID,bill.unit); let bill_quantity = scMathUtil.roundForObj(bill.quantity,bill_decimal); let contain = bill_quantity==0?0:scMathUtil.roundForObj(quantity/bill_quantity,decimal.process); let r_quantity = quantity; quantity = getQuantityByUnit(quantity,ration.unit); quantity = scMathUtil.roundTo(quantity, -decimal.ration.quantity); doc={quantity:quantity,isFromDetail:1,quantityEXP:'GCLMXHJ',contain:contain}; await ration_model.update({'ID':query.rationID,'projectID':query.projectID,deleteInfo: null},doc); doc.r_quantity = r_quantity; }else { let bill = await bill_model.findOne({'ID':query.billID,'projectID':query.projectID,deleteInfo: null}); decimal = await decimal_facade.getBillsQuantityDecimal(query.projectID,bill.unit); // quantity = getQuantityByUnit(quantity,bill.unit); quantity = scMathUtil.roundTo(quantity, -decimal); doc = {quantity:quantity,isFromDetail:1,quantityEXP:'GCLMXHJ'}; await bill_model.update({'ID':query.billID,'projectID':query.projectID,deleteInfo: null},doc); } return doc } function getQuantityByUnit(quantity,unit) { if(unit){ let times = parseInt(unit); if(isNaN(times)){ times = 1 } quantity = quantity/times; } return quantity; } function getEvalResult(referenceIndexs,detailList,regex,decimal={}) { try { decimal = decimal.quantity_detail?decimal.quantity_detail:4; for(let i of referenceIndexs){ regex = replaceReference(i,detailList,regex) } console.log('replace all C reference -----'+regex); regex =replaceSqr(regex); console.log('replace all sqar reference -----'+regex); return scMathUtil.roundTo(eval(regex), -decimal); }catch (error){ console.log(error); throw new Error('输入的表达式有误,请重新输入!'); } } function generateUpdateTaks(updateTasks) { var tasks=[]; for(let u of updateTasks){ let t ={ updateOne:{ filter:u.query, update: u.doc } } tasks.push(t); } return tasks; } function replaceReference(index,detailList,str) { str=str.toUpperCase(); let rstr= detailList[index-1].regex==null?'0':'('+detailList[index-1].regex+')'; str=replaceAll('C'+index,rstr,str); if(detailList[index-1].referenceIndexs.length>0){ for (let i of detailList[index-1].referenceIndexs){ str =replaceReference(i,detailList,str); } } return str; } function replaceAll (FindText, RepText,str) { let regExp = new RegExp(FindText, "g"); return str.replace(regExp, RepText); } function replaceSqr(text) { var squarRegex = /\([^\^]+\)\^\d+/g; var sqararr = text.match(squarRegex); var squarRegex2 = /C[0-9]+\^\d+|[0-9]+([.]{1}[0-9]+){0,1}\^\d+/g; //匹配没有括号的 var sqararr2=text.match(squarRegex2); if(sqararr){ text=converSqrByArr(sqararr,text); } if(sqararr2){ text=converSqrByArr(sqararr2,text); } return text; } function converSqrByArr (sqararr,text) { var temp = text; sqararr.forEach(function (item) { var arr = item.split('\^'); var y = parseInt(arr[1]); var x_arr = []; for (var i = 0; i < y; i++) { x_arr.push(arr[0]); } var temStr = x_arr.join('*'); temp = temp.replace(item, temStr); }); return temp; }; function update_quantity_detail(user_id,datas) { if(datas.updateFunction){ return updateFunctionMap[datas.updateFunction](user_id,datas); }else { return normalUpdate(user_id,datas); } } async function deleteRecode(doc) { let resultObject = {}; let decimal =await decimal_facade.getProjectDecimal(doc.projectID); let query = { projectID:doc.projectID, seq : { $gt: doc.seq } } if(doc.hasOwnProperty('rationID')){ query.rationID = doc.rationID; }else { query.billID = doc.billID; } let quantity_detail_List = await getDatailList(doc,resultObject); let update_task = getUpdateReferenceTask(quantity_detail_List,doc.seq,-1); await quantity_detail_model.update(query,{$inc:{seq:-1}},{multi: true}); if(update_task.length>0){ await quantity_detail_model.bulkWrite(generateUpdateTaks(update_task)); } await quantity_detail_model.deleteOne({ID:doc.ID,projectID:doc.projectID}); _.remove(quantity_detail_List,{ID:doc.ID,projectID:doc.projectID}); //更新节点信息 let n_data = await summateResults(query,quantity_detail_List,decimal); resultObject.node.data = n_data; let r_data ={ doc:doc, resort:true, update_task:update_task, updateTpye:commonConsts.UT_DELETE }; resultObject.data = r_data; return resultObject; } function getData(projectID, callback) { quantity_detail_model.find({'projectID':projectID}).sort('seq').exec((err,datas)=>{ if(err){ callback(1, '', null); }else { callback(0, consts.projectConst.QUANTITY_DETAIL, datas); } }) } function save (user_id, datas, callback) { let operations=[]; if(_.isArray(datas)){ for(let i=0;i{ commonCallback(callback,result,err); }); } } function deleteByBill(data) { return function (callback) { console.log({projectID: data.projectID, billID: data.ID}); quantity_detail_model.deleteMany({projectID: data.projectID, billID: data.ID},(err,result)=>{ commonCallback(callback,result,err); }); } } async function deleteByQuery(query) { return await quantity_detail_model.deleteMany(query); } function quantityEditChecking(doc,type,functions) { if(doc.updateType == commonConsts.UT_UPDATE&&doc.updateData.hasOwnProperty('isFromDetail')&&doc.updateData.isFromDetail==0) { if(type=='bills'){ functions.push(deleteByBill(doc.updateData)); }else if(type=='ration'){ functions.push(deleteByRation(doc.updateData)); } } } function commonCallback(callback,result,err) { if(err){ callback(err,''); }else { callback(null,result); } }