| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803 | /** * Created by Zhong on 2017/8/11. */const mongoose = require('mongoose');const gljMapModel = mongoose.model('std_glj_lib_map');const gljModel = mongoose.model('std_glj_lib_gljList');const gljClassModel = mongoose.model('std_glj_lib_gljClass');const projectGLJModel = mongoose.model('glj_list');const projectModel = mongoose.model('projects');const userModel = mongoose.model('users');const gljClassTemplateModel = mongoose.model('std_glj_lib_gljClassTemplate');const compilationModel = mongoose.model('compilation');const scMathUtil = require('../../../public/scMathUtil').getUtil();const rationMapModel = mongoose.model('std_ration_lib_map');const rationModel = mongoose.model('std_ration_lib_ration_items');const complementaryRationModel = mongoose.model('complementary_ration_items');import {OprDao} from  "./gljMapModel";import moment from "moment";import counter from "../../../public/counter/counter";import async from "async";let _ = require("lodash");class GljDao  extends OprDao{    async copyLib(sourceLibID, targetLibID) {        const task = [            this.copyClassData(sourceLibID, targetLibID),            this.copyGLJData(sourceLibID, targetLibID)        ];        await Promise.all(task);    }    async copyClassData(sourceLibID, targetLibID) {        const sourceClassData = await gljClassModel.find({ repositoryId: sourceLibID }, '-_id').lean();        const insertData = sourceClassData.map(item => ({            ... item,            repositoryId: targetLibID        }));        if (insertData.length) {            await gljClassModel.insertMany(insertData);        }    }    async copyGLJData(sourceLibID, targetLibID) {        const sourceGLJData = await gljModel.find({ repositoryId: sourceLibID }, '-_id').lean();        const IDMapping = {};        const countData = await counter.counterDAO.getIDAfterCount(counter.moduleName.GLJ, sourceGLJData.length);        const countIdx = countData.sequence_value - (sourceGLJData.length - 1);        sourceGLJData.forEach((glj, index) => {            IDMapping[glj.ID] = countIdx + index;        });        const insertData = sourceGLJData.map(glj => {            const newComponent = (glj.component || []).map(c => ({                ID: IDMapping[c.ID],                consumeAmt: c.consumeAmt            }));            // 设备改材料            const gljType = glj.gljType === 5 ? 201 : glj.gljType;            return {                ...glj,                gljType,                repositoryId: targetLibID,                ID: IDMapping[glj.ID],                component: newComponent            };        });        if (insertData.length) {            await gljModel.insertMany(insertData);        }    }    async getReference(repositoryId, gljId) {        const gljLib = await gljMapModel.findOne({ID: repositoryId});        const rationLibIds = gljLib.rationLibs.map(lib => lib.ID);        const rationLibs = await rationMapModel.find({ID: {$in: rationLibIds}}, '-_id ID dispName');        const rationLibNameMapping = {};        rationLibs.forEach(item => {            rationLibNameMapping[item.ID] = item.dispName;        });        const stdRations = await rationModel.find({rationRepId: {$in: rationLibIds}, 'rationGljList.gljId': gljId}, '-_id code rationRepId');        const rst = {};        const unknownLib = '未知定额库';        const complementaryLib = '补充定额库';        stdRations.forEach(ration => {            const libName = rationLibNameMapping[ration.rationRepId] || unknownLib;            if (!rst[libName]) {                rst[libName] = [];            }            rst[libName].push(ration);        });        const complementaryRations = await complementaryRationModel.find({'rationGljList.gljId': gljId}, '-_id code');        if (complementaryRations.length) {            rst[complementaryLib] = [];        }        complementaryRations.forEach(ration => rst[complementaryLib].push({code: ration.code}));        return rst;    }    async getUsedInfo(repositoryId, gljId) {        let userMap = {};        let userIDList = [];        let projectList = await projectGLJModel.find({"glj_id":gljId},'-_id project_id').lean();        if(projectList.length > 0){            let projectUserList =  await projectModel.find({'ID':{$in:_.map(projectList,"project_id")}},'-_id ID userID').lean();            for(let p of projectUserList){                if(!userMap[p.userID]){                    userMap[p.userID] = true;                    userIDList.push(p.userID);                }            }            let userList = await userModel.find({'_id':{$in:userIDList}},'_id username mobile').lean();            for(let u of userList){                userMap[u._id.toString()] = u;            }            for(let p of projectUserList){                p.username = userMap[p.userID].username;                p.mobile = userMap[p.userID].mobile;            }           return projectUserList        }        return [];    }    async getGljTreeSync(gljLibId) {        return await gljClassModel.find({repositoryId: gljLibId});    }    getGljTypes (gljLibId, callback){        gljClassModel.find({"repositoryId": gljLibId, "$or": [{"isDeleted": null}, {"isDeleted": false}, {deleted: false} ]},            '-_id', {lean: true}, function(err,data){            if(err) callback("获取工料机类型错误!",false)            else {                callback(0, data);            }        })    }    _exist(data, attr){        return data && data[attr] !== 'undefined' && data[attr];    }     sortToNumber(datas){        for(let i = 0, len = datas.length; i < len; i++){            let data = datas[i]._doc;            if(this._exist(data, 'basePrice')){                data['basePrice'] = parseFloat(data['basePrice']);            }            if(this._exist(data, 'component')){                for(let j = 0, jLen = data['component'].length; j < jLen; j++){                    let comGljObj = data['component'][j]._doc;                    if(this._exist(comGljObj, 'consumeAmt')){                        comGljObj['consumeAmt'] = parseFloat(comGljObj['consumeAmt']);                    }                }            }        }    }    async getGljItemsSync(gljLibId) {        return await gljModel.find({repositoryId: gljLibId}, '-_id', {lean: true});    }    async getGljItemsByRep(repositoryId,callback = null){   /*     let me = this;        if (callback === null) {            return gljModel.find({"repositoryId": repositoryId});        } else {            gljModel.find({"repositoryId": repositoryId},function(err,data){                if(err) callback(true, "")                else {                    me.sortToNumber(data);                    callback(false,data);                }            })        }*/        let me = this;        let rst = [];        //批量获取异步        let functions = [];        let count = await gljModel.find({repositoryId: repositoryId, $or: [{deleted: null}, {deleted: false}]}).count();        let findCount = Math.ceil(count/500);        for(let i = 0, len = findCount; i < len; i++){            functions.push((function(flag) {                return function (cb) {                    gljModel.find({repositoryId: repositoryId, deleted: null}, '-_id', {lean: true}, cb).skip(flag).sort({ID: 1}).limit(500);                }            })(i*500));        }        async.parallel(functions,  function (err, results) {            if(err){                callback(err, null);            }            else{                for(let stdGljs of results){                    rst = rst.concat(stdGljs);                }                me.sortToNumber(rst);                callback(0, rst);            }        });    }    getGljItemByType (repositoryId, type, callback){        let me = this;        gljModel.find({"repositoryId": repositoryId, "gljType": type},function(err,data){            if(err) callback(true, "");            else {                me.sortToNumber(data);                callback(false, data);            }        })    };    getGljItem (repositoryId, code, callback){        let me = this;        gljModel.find({"repositoryId": repositoryId, "code": code},function(err,data){            if(err) callback(true, "")            else {                me.sortToNumber(data);                callback(false, data);            }        })    };    getGljItems (gljIds, callback){        let me = this;        gljModel.find({"ID": {"$in": gljIds}},function(err,data){            if(err) callback(true, "")            else {                me.sortToNumber(data);                callback(false, data);            }        })    };    getGljItemsByCode (repositoryId, codes, callback){        let me = this;        gljModel.find({"repositoryId": repositoryId,"code": {"$in": codes}},function(err,data){            if(err) callback(true, "");            else {                me.sortToNumber(data);                callback(false, data);            }        })    };    updateComponent(libId, oprtor, updateArr, callback){        let parallelFucs = [];        for(let i = 0; i < updateArr.length; i++){            parallelFucs.push((function(obj){                return function (cb) {                    if(typeof obj.component === 'undefined'){                        obj.component = [];                    }                    gljModel.update({repositoryId: libId, ID: obj.ID}, obj, function (err, result) {                        if(err){                            cb(err);                        }                        else{                            cb(null, obj);                        }                    })                }            })(updateArr[i]));        }        parallelFucs.push((function () {            return function (cb) {                GljDao.updateOprArr({ID: libId}, oprtor, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {                    if(err){                        cb(err);                    }                    else{                        cb(null);                    }                })            }        })());        async.parallel(parallelFucs, function (err, result) {            if(err){                callback(err, '更新组成物错误!', null);            }            else{                callback(null, '成功!', result);            }        });    }    mixUpdateGljItems (repId, lastOpr, updateItems, addItems, rIds, callback) {        if (updateItems.length == 0 && rIds.length == 0) {            GljDao.addGljItems(repId, lastOpr, addItems, callback);        }        else if(rIds.length > 0 && updateItems.length > 0){            async.parallel([                function (cb) {                    GljDao.removeGljItems(repId, lastOpr, rIds, cb);                },                function (cb) {                    GljDao.updateGljItems(repId, lastOpr, updateItems, cb);                }            ], function (err) {                if(err){                    callback(true, "Fail to update and delete", false)                }                else{                    callback(false, "Save successfully", false);                }            })        }        else if (rIds.length > 0 && updateItems.length === 0) {            GljDao.removeGljItems(repId, lastOpr, rIds, callback);        }        else if(updateItems.length > 0 || addItems.length > 0){            GljDao.updateGljItems(repId, lastOpr, updateItems, function(err, results){                if (err) {                    callback(true, "Fail to update", false);                } else {                    if (addItems && addItems.length > 0) {                        GljDao.addGljItems(repId, lastOpr, addItems, callback);                    } else {                        callback(false, "Save successfully", results);                    }                }            });        }    }    /*mixUpdateGljItems (repId, lastOpr, updateItems, addItems, rIds, callback) {        if (updateItems.length == 0 && rIds.length == 0) {            GljDao.addGljItems(repId, lastOpr, addItems, callback);        } else if (rIds.length > 0) {            GljDao.removeGljItems(repId, lastOpr, rIds, function(err, message, docs) {            });        }else{            GljDao.updateGljItems(repId, lastOpr, updateItems, function(err, results){                if (err) {                    callback(true, "Fail to update", false);                } else {                    if (addItems && addItems.length > 0) {                        GljDao.addGljItems(repId, lastOpr, addItems, callback);                    } else {                        callback(false, "Save successfully", results);                    }                }            });        }    };*/    static removeGljItems (repId, lastOpr, rIds, callback) {        if (rIds && rIds.length > 0) {            gljModel.collection.remove({ID: {$in: rIds}}, null, function(err, docs){                if (err) {                    callback(true, "Fail to remove", false);                } else {                    GljDao.updateOprArr({ID: repId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {                        if(err){                            callback(true, "Fail to update operator", false);                        }                        else{                            callback(false, "Remove successfully", docs);                        }                    });                }            })        } else {            callback(false, "No records were deleted!", null);        }    }    static addGljItems (repId, lastOpr, items, callback) {        if (items && items.length > 0) {            const codes = [];            items.forEach(item => codes.push(item.code));            gljModel.find({repositoryId: repId, code: {$in: codes}}, '-_id code', {lean: true}, (err, codeData) => {                if (err) {                    callback(true, '判断编码唯一性失败', false);                    return;                }                const insertData = [];                const failCode = [];                items.forEach(item => {                    const matchData = codeData.find(codeItem => codeItem.code === item.code);                    if (!matchData) {                        insertData.push(item);                    } else {                        failCode.push(item.code);                    }                });                if (!insertData.length) {                    callback(false, 'empty data', {insertData, failCode});                    return;                }                counter.counterDAO.getIDAfterCount(counter.moduleName.GLJ, items.length, (counterErr, counterData) => {                    if (counterErr) {                        callback(true, '获取人材机ID失败', false);                        return;                    }                    const maxId = counterData.sequence_value;                    for (let i = 0; i < insertData.length; i++) {                        insertData[i].ID = (maxId - (insertData.length - 1) + i);                        insertData[i].repositoryId = repId;                    }                    const task = [];                    insertData.forEach(item => {                        task.push({                            insertOne: {document: item}                        });                    });                    gljModel.bulkWrite(task, (insertErr, rst) => {                        if (insertErr) {                            callback(true, '新增数据失败', false);                            return;                        }                        GljDao.updateOprArr({ID: repId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {                            if(err){                                callback(true, "Fail to update Operator", false);                            } else{                                callback(false, "Add successfully", {insertData, failCode});                            }                        });                    });                });            });        } else {            callback(true, "No source", false);        }    }    static updateGljItems(repId, lastOpr, items, callback) {        var functions = [];        for (var i=0; i < items.length; i++) {            functions.push((function(doc) {                return function(cb) {                    var filter = {};                    if (doc.ID) {                        filter.ID = doc.ID;                    } else {                        filter.repositoryId = repId;                        filter.code = doc.code;                    }                    gljModel.update(filter, doc, cb);                };            })(items[i]));        }        functions.push((function () {            return function (cb) {                GljDao.updateOprArr({ID: repId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {                    if(err){                        cb(err);                    }                    else{                        cb(null);                    }                })            }        })());        async.parallel(functions, function(err, results) {            callback(err, results);        });    }    getRationGljIds(rationLibs, callback){    }    updateNodes (updateData, lastOpr, callback) {        let functions = [];        for (let i = 0, len = updateData.length; i < len; i++) {            functions.push((function(doc) {                return function(cb) {                    if(doc.updateType === 'update' && !doc.updateData.deleted){                        gljClassModel.update({repositoryId: doc.updateData.repositoryId, ID: doc.updateData.ID}, doc.updateData, function (err) {                            if(err){                                cb(err);                            }                            else {                                cb(null);                            }                        });                    }                    else if(doc.updateType === 'update' && doc.updateData.deleted){                        gljClassModel.remove({repositoryId: doc.updateData.repositoryId, ID: doc.updateData.ID}, function (err) {                            if(err){                                cb(err);                            }                            else {                                gljModel.remove({repositoryId: doc.updateData.repositoryId, gljClass: doc.updateData.ID}, function (err) {                                    if(err){                                        cb(err);                                    }                                    else{                                        cb(null);                                    }                                });                            }                        });                    }                    else if(doc.updateType === 'new'){                        gljClassModel.create(doc.updateData, function (err) {                            if(err){                                cb(err);                            }                            else {                                cb(null);                            }                        });                    }                };            })(updateData[i]));        }        if(updateData.length > 0){            functions.push((function () {                return function (cb) {                    GljDao.updateOprArr({ID: updateData[0].updateData.rationRepId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {                        if(err){                            cb(err);                        }                        else{                            cb(null);                        }                    })                }            })());        }        async.parallel(functions, function(err, results) {            if(!err){                err = 0;            }            callback(err, results);        });    }  /*  updateNodes (repId, lastOpr, nodes, callback) {        var functions = [];        for (var i=0; i < nodes.length; i++) {            functions.push((function(doc) {                return function(cb) {                    gljClassModel.update({ID: doc.ID}, doc, cb);                };            })(nodes[i]));        }        functions.push((function () {            return function (cb) {                GljDao.updateOprArr({ID: repId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {                    if(err){                        cb(err);                    }                    else{                        cb(null);                    }                })            }        })());        async.parallel(functions, function(err, results) {            callback(err, results);        });    }*/    removeNodes (repId, lastOpr, nodeIds, preNodeId, preNodeNextId, callback){        var functions = [];        if (preNodeId != -1) {            functions.push((function(nodeId, nextId) {                return function(cb) {                    gljClassModel.update({ID: nodeId}, {"NextSiblingID": nextId}, cb);                };            })(preNodeId, preNodeNextId));        }        for (var i=0; i < nodeIds.length; i++) {            functions.push((function(nodeId) {                return function(cb) {                    gljClassModel.update({ID: nodeId}, {"isDeleted": true}, cb);                };            })(nodeIds[i]));        }        functions.push((function () {            return function (cb) {                GljDao.updateOprArr({ID: repId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {                    if(err){                        cb(err);                    }                    else{                        cb(null);                    }                })            }        })());        async.parallel(functions, function(err, results) {            callback(err, results);        });    }    createNewNode(repId, lastOpr, lastNodeId, nodeData, callback) {        return counter.counterDAO.getIDAfterCount(counter.moduleName.GLJ, 1, function(err, result){            nodeData.repositoryId = repId;            nodeData.ID = result.sequence_value;            var node = new gljModel(nodeData);            async.parallel([                function (cb) {                    node.save(function (err, result) {                        if (err) {                            cb("章节树ID错误!", false);                        } else {                            if (lastNodeId > 0) {                                gljClassModel.update({ID: lastNodeId}, {"NextSiblingID": nodeData.ID}, function(err, rst){                                    if (err) {                                        cb("章节树ID错误!", false);                                    } else {                                        cb(false, result);                                    }                                });                            } else cb(false, result);                        }                    });                },                function (cb) {                    GljDao.updateOprArr({ID: repId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {                        if(err){                            cb(err);                        }                        else{                            cb(null);                        }                    })                }            ], function (err, result) {                if(err){                    callback(true, "章节树错误!", false);                }                else{                    callback(false, '', result[0]);                }            })        });    }    getGljItemsOccupied(repId, occupation, callback){        gljModel.find({repositoryId: repId}, occupation, function (err, result) {            if(err) callback(true, 'fail', null);            else callback(false, 'sc', result);        });    }    async getGljItemsByRepId(repositoryId, returnFields = ''){         return gljModel.find({"repositoryId": repositoryId}, returnFields);    }    async batchUpdateGljPrice(gljLibId, sheetData){        let gljLib = await gljMapModel.findOne({ID: gljLibId});        if(!gljLib){            throw '不存在此人材机库';        }        let compilation = await compilationModel.findOne({_id: mongoose.Types.ObjectId(gljLib.compilationId)});        if(!compilation){            throw '不存在此费用定额';        }        let priceProperties = compilation.priceProperties ? compilation.priceProperties : [];        //根据第一行数据,获取列下标与字段名映射        let colMapping = {};        for(let col = 0; col < sheetData[0].length; col++){            let cData = sheetData[0][col];            if(cData === '编码'){                colMapping['code'] = col;            }            else {                if(priceProperties.length === 0){                    if(cData === '定额价'){                        colMapping['basePrice'] = col;                        break;                    }                }                else {                    for(let priceProp of priceProperties){                        if(priceProp.price.dataName === cData){                            colMapping[priceProp.price.dataCode] = col;                            break;                        }                    }                }            }        }        let colMappingKeys = Object.keys(colMapping);        if(colMappingKeys.length < 2){            throw 'excel数据不正确'        }        let updateBulk = [];        //避免重复        let updateCodes = [];        //库中存在的人材机        let dateA = Date.now();        let existGljs = await gljModel.find({repositoryId: gljLibId}, '-_id code ID');        let existMapping = {};        for (let glj of existGljs) {            existMapping[glj.code] = glj;        }        for(let row = 0; row < sheetData.length; row++){            if(row === 0){                continue;            }            let gljCode = sheetData[row][colMapping.code],                existGlj = existMapping[gljCode];            //更新多单价、不覆盖priceProperty字段,覆盖priceProperty下的子字段'priceProperty.x'            if(gljCode && gljCode !== '' && !updateCodes.includes(gljCode) && existGlj){                if(priceProperties.length > 0){                    for(let priceProp of priceProperties){                        let dataCode = priceProp.price.dataCode;                        let priceCellData = sheetData[row][colMapping[dataCode]];                        //Excel中没有这个单价则跳过                        if (!colMapping[dataCode]) {                            continue;                        }                        let updateSet = {};                        updateSet['priceProperty.' + dataCode] = priceCellData && !isNaN(priceCellData) ?                            scMathUtil.roundTo(parseFloat(priceCellData), -2) : 0;                        updateBulk.push({                            updateOne: {filter: {ID: existGlj.ID}, update: {$set: updateSet}}                        });                    }                    updateCodes.push(gljCode);                }                else {                    if(colMapping.basePrice){                        let priceCellData = sheetData[row][colMapping.basePrice];                        let basePrice = priceCellData  && !isNaN(priceCellData) ?                            scMathUtil.roundTo(priceCellData, -2) : 0;                        updateCodes.push(gljCode);                        updateBulk.push({                            updateOne: {filter: {ID: existGlj.ID}, update: {$set: {basePrice: basePrice}}}                        });                    }                }            }        }        if(updateBulk.length > 0){            while (updateBulk.length > 0) {                let sliceBulk = updateBulk.splice(0, 1000);                await gljModel.bulkWrite(sliceBulk);            }        }    }    async importComponents(gljLibId, sheetData) {        const gljLib = await gljMapModel.findOne({ID: gljLibId});        if (!gljLib) {            throw '不存在此人材机库';        }        const compilation = await compilationModel.findOne({_id: mongoose.Types.ObjectId(gljLib.compilationId)});        if (!compilation) {            throw '不存在此费用定额';        }        // 将所有人材机进行编码映射        const allGLJs = await gljModel.find({repositoryId: gljLibId}, {ID: true, code: true}).lean();        const codeMapping = {};        allGLJs.forEach(glj => codeMapping[glj.code] = glj);        // excel表格列号与字段的映射        const colMapping = {            // 材料编码            code: 0,            // 组成物编码            componentCode: 1,            // 组成物消耗量            consumeAmt: 2        };        // 跳过列头        for (let row = 1; row < sheetData.length; row++) {            const rowData = sheetData[row];            const code = rowData[colMapping.code];            const componentCode = rowData[colMapping.componentCode];            const consumeAmt = +rowData[colMapping.consumeAmt];            const glj = codeMapping[code];            const component = codeMapping[componentCode];            if (!glj || !component) {                continue;            }            if (!glj.component) {                glj.component = [];            }            glj.component.push({                ID: component.ID,                consumeAmt: consumeAmt            });        }        // 更新数据        const tasks = [];        allGLJs.filter(glj => glj.component && glj.component.length).forEach(glj => {            tasks.push({                updateOne: {                    filter: {                        ID: glj.ID                    },                    update: {$set: {component: glj.component}}                }            });        });        if (tasks.length) {            await gljModel.bulkWrite(tasks);        }    }}export default GljDao;
 |