| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573 | /** * 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<datas.length;i++){            operations.push(operationMap[datas[i].updateType](user_id,datas[i]));        }    }else {        operations.push(operationMap[datas.updateType](user_id,datas));    }    async_n.parallel(operations,function (err,results) {        if(err){            callback(err,'');        }else {            if(results.length==1){                callback(null,results[0])            }else {                callback(null,results)            }        }    })}function deleteByRation(data) {    return function (callback) {        quantity_detail_model.deleteMany({projectID: data.projectID, rationID: data.ID},(err,result)=>{            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);    }}
 |