/**
 * Created by vian on 2017/3/20.
 */
let mongoose = require('mongoose');
let counter = require("../../../public/counter/counter");
let async = require("async");
let _ = require("lodash");
let StdBillsLib = mongoose.model('std_bills_lib_list');
let Bills = mongoose.model('std_bills_lib_bills');
let JobContent = mongoose.model('std_bills_lib_jobContent');
let ItemCharacter = mongoose.model('std_bills_lib_itemCharacter');
let moment = require("moment");
let billsLibDao = function(){};


billsLibDao.prototype.getMaxNumber = function(gData, callback){
    let billsLibId = gData.billsLibId;
    let field = gData.field;
    if(field === 'jobs'){
        JobContent.find({billsLibId: billsLibId, deleted: false}).sort({code: -1}).limit(1).exec(function(err, result){
            if(err){
                callback(1, 'Error', null);
            }
            else {
                callback(0, '', result);
            }
        });
    }
    else if(field === 'items'){
        ItemCharacter.find({billsLibId: billsLibId, deleted: false}).sort({code: -1}).limit(1).exec(function(err, result){
            if(err){
                callback(1, 'Error', null);
            }
            else {
                callback(0, '', result);
            }
        });
    }
};
//----------StdBillsLib-------------------
billsLibDao.prototype.getABillsLib = function(data, callback){
    let billsLibId = data.billsLibId;
    StdBillsLib.find({billsLibId: billsLibId, deleted: false}, function(err, data){
        if(err){
            callback(1, 'Error', null);
        }
        else {
            callback(0, '', data);
        }
    });
};


billsLibDao.prototype.getStdBillsLib = function(callback){
   // let userId = data.userId;
    StdBillsLib.find({deleted: false}, "-_id", function(err, data){
        if(err){
            callback(1, "Error", null);
        }
        else{
            callback(0, "", data);
        }
    });
};


billsLibDao.prototype.createStdBillsLib = function(clibData, callback){
    counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib, 1, function(err, result){
        let billsLibId = result.sequence_value;
        let userAccount = clibData.userAccount;
        let billsLibName = clibData.name;
        let compilationId = clibData.compilationId;
        let compilationName = clibData.compilationName;
        let dateStr = moment().format('YYYY-MM-DD HH:mm:ss');
        let newStdBillsLib = {
            creator: userAccount,
            createDate: dateStr,
            recentOpr: [{operator: userAccount, operateDate: dateStr}],
            billsLibId: billsLibId,
            billsLibName: billsLibName,
            compilationId: compilationId,
            compilationName: compilationName,
            deleted: false
        };
        StdBillsLib.create(newStdBillsLib, function(err){
            if(err){
                callback(1, "Error", null);
            }
            else {
                StdBillsLib.find({billsLibId: billsLibId}, function(err, data){
                    if(err){
                        callback(1, "Error", null)
                    }
                    else {
                        callback(0, "", data);
                    }
                });
            }
        });
    });
};

function getNewOprArr(recentOprArr, oprtor, oprDate){
    let isExist = false;
    for(let i =0 ; i<recentOprArr.length; i++){
        if(recentOprArr[i].operator === oprtor){
           recentOprArr[i].operateDate = oprDate;
            isExist = true;
        }
    }
    if(!isExist){
        if(recentOprArr.length < 5){
            recentOprArr.push({operator: oprtor, operateDate: oprDate});
        }
        else if(recentOprArr.length === 5){
            recentOprArr.sort(function (a, b) {
                if(a.operateDate > b.operateDate){
                    return -1;
                }else {
                    return 1;
                }
                return 0;
            });
            recentOprArr.splice(recentOprArr.length -1, 1);
            recentOprArr.splice(0, 1, {operator: oprtor, operateDate: oprDate});
        }
    }
    return recentOprArr;
}

billsLibDao.prototype.deleteStdBillsLib = function(data, callback){
    let billsLibId = data.billsLibId, lastOperator = data.lastOperator,
        lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    async.parallel([
        function(cb){
            StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                if(err){
                    cb(err);
                }
                else{
                    if(result.length > 0 ){
                        let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                        StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr, deleted: true}}, function(err){
                            if(err){
                                cb(err);
                            }
                            else{
                                cb(null);
                            }
                        });
                    }
                }
            });
        },
        function(cb){
            Bills.update({billsLibId: billsLibId, deleted: false}, {$set: {deleted: true}}, {upsert: false, multi: true}, function(err){
                cb(null);
            });
        },
        function(cb){
            JobContent.update({billsLibId: billsLibId, deleted: false}, {$set: {deleted: true}}, {upsert: false, multi: true}, function(err, result){
                cb(null);
            });
        },
        function(cb){
            ItemCharacter.update({billsLibId: billsLibId, deleted: false}, {$set: {deleted: true}}, {upsert: false, multi: true}, function(err){
                cb(null);
            })
        }
    ], function(err){
        if(err){
            callback(1, 'Error');
        }
        else {
            callback(0, '');
        }
    });
};

billsLibDao.prototype.renameStdBillsLib = function(renameData, callback){
    let billsLibId = renameData.id;
    let renameVal = renameData.value;
    let lastOperator = renameData.lastOperator;
    let lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
        if(err){
            callback(0, '');
        }
        else{
            if(result.length > 0){
                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                StdBillsLib.update({billsLibId: billsLibId}, {$set:{billsLibName: renameVal, recentOpr: newRecentOpr}}, function(err){
                    if(err){
                        callback(1, "Error");
                    }
                    else{
                        callback(0, "");
                    }
                });
            }
        }
    })
};

billsLibDao.prototype.getStdBillsLibName = function(billsLibId, callback){
    StdBillsLib.find({billsLibId: billsLibId, deleted: false}, "-_id", function(err,  data){
        if(err){
            callback(1, "Error", null);
        }
        else {
            callback(0, "", data);
        }
    });
};

billsLibDao.prototype.getCurrentUniqId = function(callback){
    counter.counterDAO.getCurrentID(counter.moduleName.billsLib, function(result, err){
        let id = result.sequence_value;
        if(err){
            callback(1, 'Error', null);
        }
        else{
            callback(0, '', id);
        }
    });
}
//----------------------------Bills---------------------
billsLibDao.prototype.getBills = function (billsLibId, callback) {
    Bills.find({billsLibId: billsLibId}, "-_id -ruleText -recharge",  function(err, billsData){
        if(err){
            callback(1, "Error", null);
        }
        else{
            callback(0, "", billsData);
        }
    });
}

billsLibDao.prototype.createBills = function(cbillsData, callback){
    let newId = cbillsData.newId;
    let pid = cbillsData.ParentID;
    let nid = cbillsData.NextSiblingID;
    let billsLibId = cbillsData.billsLibId;
    let updatePreData = cbillsData.updatePreData;
    let lastOperator = cbillsData.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    let newBills = {
        ID: newId,
        ParentID: pid,
        NextSiblingID: nid,
        billsLibId: billsLibId,
        code: '',
        name: '',
        unit: '',
        ruleText: '',
        Expression: '',
        recharge:'',
        deleted: false
    };
    async.parallel([
        function(cb){
            Bills.create(newBills, function(err){
                if(err){
                    cb(err);
                }
                else {
                    cb(null);
                }
            });
        },
        function(cb){
            if(updatePreData){
                Bills.findOneAndUpdate({billsLibId: billsLibId, ID: updatePreData.ID, deleted: false}, {$set: {NextSiblingID: updatePreData.NextSiblingID}}, function(err, result){
                    if(err){
                        cb(err);
                    }
                    else {
                        cb(null)
                    }
                });
            }
            else {
                cb(null);
            }
        },
        function (cb) {
            StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                if(err){
                    cb(err);
                }
                else{
                    if(result.length > 0 ){
                        let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                        StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                            if(err){
                                cb(err);
                            }
                            else{
                                cb(null);
                            }
                        });
                    }
                }
            });
        }
    ], function(err){
        if(err){
            callback(1, 'Error');
        }
        else {
            callback(0, '');
        }
    });
};

billsLibDao.prototype.upMove = function(data, callback){
    let billsLibId = data.billsLibId,
        updateDatas = data.updateDatas,
        lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    async.parallel([
        function (cb) {
            async.each(updateDatas, function(updateData, ecb){
                Bills.findOneAndUpdate({billsLibId: billsLibId, ID: updateData.ID, deleted: false}, {$set: {NextSiblingID: updateData.NextSiblingID}}, function(err){
                    if(err){
                        ecb(err);
                    }
                    else {
                        ecb(null);
                    }
                });
            }, function(err){
                if(err){
                    cb(err);
                }
                else{
                    cb(null);
                }
            });
        },
        function (cb) {
            StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                if(err){
                    cb(err);
                }
                else{
                    if(result.length > 0 ){
                        let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                        StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                            if(err){
                                cb(err);
                            }
                            else{
                                cb(null);
                            }
                        });
                    }
                }
            });
        }
    ], function (err) {
        if(err){
            callback(1, 'Error');
        }
        else{
            callback(0, '');
        }
    });
};

billsLibDao.prototype.downMove = function (data, callbck) {
    let billsLibId = data.billsLibId,
        updateDatas = data.updateDatas,
        functions = [], lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    let parallelFucs = {
        updateLastOpr: function () {
            return function (cb) {
                StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        },
        nextSiblingNode: function (data) {
            return function (cb) {
                Bills.update({billsLibId: billsLibId, ID: data.ID, deleted: false}, {$set: {NextSiblingID: data.NextSiblingID}}, function (err) {
                    if(err){
                        cb(err);
                    }
                    else{
                        cb(null);
                    }
                });
            };
        },
        oprNode: function (data) {
            return function (cb) {
                Bills.update({billsLibId: billsLibId, ID: data.ID, deleted: false}, {$set: {NextSiblingID: data.NextSiblingID}}, function (err) {
                    if(err){
                        cb(err);
                    }
                    else {
                        cb(null);
                    }
                })
            }
        },
        preSiblingNode: function (data) {
            return function (cb) {
                Bills.update({billsLibId: billsLibId, ID: data.ID, deleted: false}, {$set: {NextSiblingID: data.NextSiblingID}}, function (err) {
                    if(err){
                        cb(err);
                    }
                    else{
                        cb(null);
                    }
                });
            };
        }
    };
    for(let i =0; i< updateDatas.length; i++){
        if(updateDatas[i].type === 'nextSiblingNode'){
            functions.push(parallelFucs.nextSiblingNode(updateDatas[i]));
        }
        else if(updateDatas[i].type === 'oprNode'){
            functions.push(parallelFucs.oprNode(updateDatas[i]));
        }
        else {
            functions.push(parallelFucs.preSiblingNode(updateDatas[i]));
        }
    }
    functions.push(parallelFucs.updateLastOpr());
    async.parallel(functions, function (err) {
        if(err){
            callbck(1, 'Error');
        }
        else{
            callbck(0, '');
        }
    })
}

billsLibDao.prototype.upLevel = function(data, callback){
    let billsLibId = data.billsLibId,
        updateDatas = data.updateDatas, functions = [],
        lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    let parallelFucs = {
        updateLastOpr: function () {
            return function (cb) {
                StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        },
        oprNode: function (data) {
            return function (cb){
                Bills.update({billsLibId: billsLibId, ID: data.ID, deleted: false}, {$set: {ParentID: data.ParentID, NextSiblingID: data.NextSiblingID}}, function(err){
                    if(err){
                        cb(err);
                    }
                    else {
                        cb(null);
                    }
                });
            };
        },
        parentNode: function (data) {
            return function(cb){
                Bills.update({billsLibId: billsLibId, ID: data.ID, deleted: false}, {$set: {NextSiblingID: data.NextSiblingID}}, function (err) {
                    if(err){
                        cb(err);
                    }
                    else {
                        cb(null);
                    }
                })
            };
        },
        nextSiblingNode: function (data) {
            return function (cb) {
                Bills.update({billsLibId: billsLibId, ID: data.ID, deleted: false}, {$set: {ParentID: data.ParentID}}, function (err) {
                    if(err){
                        cb(err);
                    }
                    else{
                        cb(null);
                    }
                });
            };
        },
        preSiblingNode: function(data){
            return function (cb) {
                Bills.update({billsLibId: billsLibId, ID: data.ID, deleted: false}, {$set: {NextSiblingID: data.NextSiblingID}}, function (err) {
                    if(err){
                        cb(err);
                    }
                    else {
                        cb(null);
                    }
                });
            };
        }
    }
    for(let i=0; i< updateDatas.length; i++){
        if(updateDatas[i].type === 'oprNode'){
            functions.push(parallelFucs.oprNode(updateDatas[i]));
        }
        else if(updateDatas[i].type === 'parentNode'){
            functions.push(parallelFucs.parentNode(updateDatas[i]));
        }
        else if(updateDatas[i].type === 'nextSiblingNode'){
            updateDatas[i].ID.forEach(function (id) {
                let obj = {ID: id, ParentID: updateDatas[i].ParentID};
                functions.push(parallelFucs.nextSiblingNode(obj));
            });
        }
        else {
            functions.push(parallelFucs.preSiblingNode(updateDatas[i]));
        }
    }
    functions.push(parallelFucs.updateLastOpr());
    async.parallel(functions, function(err){
        if(err){
            callback(1, 'Error');
        }
        else{
            callback(0, '');
        }
    });
};

billsLibDao.prototype.downLevel = function (data, callback) {
    let billsLibId = data.billsLibId,
        updateDatas = data.updateDatas,
        functions = [], lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    let parallelFucs = {
        updateLastOpr: function () {
            return function (cb) {
                StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        },
        preSiblingNode: function (data) {
            return function (cb) {
                Bills.update({billsLibId: billsLibId, ID: data.ID, deleted: false}, {$set: {NextSiblingID: data.NextSiblingID}}, function (err) {
                    if(err){
                        cb(err);
                    }
                    else {
                        cb(null);
                    }
                });
            };
        },
        oprNode: function (data) {
            return function (cb) {
                Bills.update({billsLibId: billsLibId, ID: data.ID, deleted: false}, {$set: {ParentID: data.ParentID, NextSiblingID: data.NextSiblingID}}, function (err) {
                    if(err){
                        cb(err);
                    }
                    else{
                        cb(null);
                    }
                });
            };
        },
        preChildren: function (data) {
            return function (cb) {
                Bills.update({billsLibId: billsLibId, ID: data.ID, deleted: false}, {$set: {NextSiblingID: data.NextSiblingID}}, function (err) {
                    if(err){
                        cb(err);
                    }
                    else{
                        cb(null);
                    }
                });
            };
        }
    }
    for(let i=0; i<updateDatas.length; i++){
        if(updateDatas[i].type === 'preSiblingNode'){
            functions.push(parallelFucs.preSiblingNode(updateDatas[i]));
        }
        else if(updateDatas[i].type === 'oprNode'){
            functions.push(parallelFucs.oprNode(updateDatas[i]));
        }
        else {
            functions.push(parallelFucs.preChildren(updateDatas[i]));
        }
    }
    functions.push(parallelFucs.updateLastOpr());
    async.parallel(functions, function (err) {
        if(err){
            callback(1, 'Error');
        }
        else{
            callback(0, '');
        }
    })
};

billsLibDao.prototype.updatePNId= function(upData, callback){
    let billsLibId = upData.billsLibId;
    let updateDatas = upData.updateData;
    let eachDatas = [];
        for(let i=0; i< updateDatas.length; i++){
            if(updateDatas[i].ID.length > 1){
                let ids = updateDatas[i].ID;
                for(let j=0; j<ids.length; j++){
                    let eachObj = {
                        id: ids[j],
                        data: updateDatas[i]
                    }
                    eachDatas.push(eachObj);
                }
            }
            else {
                eachDatas.push({id: updateDatas[i].ID, data: updateDatas[i]});
            }
        }

        async.each(eachDatas, function(eachObj, cb){
            let id = eachObj.id, data = eachObj.data;
            if(data.ParentID && data.NextSiblingID){
                Bills.update({billsLibId: billsLibId, ID: id, deleted: false}, {$set: {ParentID: data.ParentID, NextSiblingID: data.NextSiblingID}}, function(err){
                    if(err){
                        cb(err);
                    }else {
                        cb(null);
                    }
                });
            }
            else if(data.ParentID && !data.NextSiblingID){
                Bills.update({billsLibId: billsLibId, ID: id, deleted: false}, {$set: {ParentID: data.ParentID}}, function(err){
                    if(err){
                        if(err){
                            cb(err);
                        }else {
                            cb(null);
                        }
                    }
                });
            }
            else if(!data.ParentID && data.NextSiblingID){
                Bills.update({billsLibId: billsLibId, ID: id, deleted: false}, {$set: {NextSiblingID: data.NextSiblingID}}, function(err){
                    if(err){
                        cb(err);
                    }else {
                        cb(null);
                    }
                });
            }
        }, function(err){
            if(err){
                callback(1, 'Error');
            }
            else {
                callback(0, '');
            }
        });
}

billsLibDao.prototype.updateBills = function(ubillsData, callback){
    let billsLibId = ubillsData.billsLibId;
    let updateId = ubillsData.updateId;
    let updateField = ubillsData.field;
    let updateData = ubillsData.data, lastOperator = ubillsData.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    let needSet = {};
    needSet[updateField] = updateData;
    async.parallel([
        function (cb) {
            if(updateField !== 'jobs' && updateField !== 'items'){
                Bills.update({billsLibId: billsLibId, ID: updateId, deleted: false}, {$set: needSet}, function (err) {
                    if(err){
                        cb(err);
                    }
                    else{
                        cb(null);
                    }
                })
            }
            else{
                Bills.update({billsLibId: billsLibId, ID: updateId, deleted: false}, {$addToSet: needSet}, function (err) {
                    if(err){
                        cb(err);
                    }
                    else{
                        cb(null);
                    }
                });
            }
        },
        function (cb) {
            StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                if(err){
                    cb(err);
                }
                else{
                    if(result.length > 0 ){
                        let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                        StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                            if(err){
                                cb(err);
                            }
                            else{
                                cb(null);
                            }
                        });
                    }
                }
            });
        }
    ], function (err) {
        if(err){
            callback(1, 'Error');
        }
        else{
            callback(0, '');
        }
    });
}

billsLibDao.prototype.removeTotal = function (data, callback) {
    let billsLibId = data.billsLibId, billsIds = data.billsIds,
        delIds = data.delIds, field = data.field, functions = [], delArr = [],
        lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    if(billsIds.length > 0){
        billsIds.forEach(function (updateId) {
            delIds.forEach(function (delId) {
                delArr.push({updateID: updateId, delId: delId});
            });
        });
    }
    let parallelFucs = {
        updateLastOpr: function () {
            return function (cb) {
                StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        },
        delJobs: function () {
            return function (cb) {
                async.each(delIds, function (delJobId, ecb) {
                    JobContent.update({billsLibId: billsLibId, id: delJobId, deleted: false}, {$set: {deleted: true}}, function (err, result) {
                        if(err){
                            ecb(err);
                        }
                        else {
                            ecb(null);
                        }
                    });
                }, function (err) {
                    if(err){
                        cb(err);
                    }
                    else{
                        cb(null);
                    }
                });
            };
        },
        delJobsArr: function () {
            return function (cb) {
                async.each(delArr, function (delObj, ecb) {
                    Bills.update({billsLibId: billsLibId, ID: delObj.updateId, deleted: false}, {$pull: {jobs: {id: delObj.delId}}}, function (err) {
                        if(err){
                            ecb(err);
                        }else{
                            ecb(null);
                        }
                    });
                }, function (err) {
                    if(err){
                        cb(err);
                    }
                    else{
                        cb(null);
                    }
                })
            };
        },
        delItems: function () {
            return function (cb) {
                async.each(delIds, function (delItemId, ecb) {
                    ItemCharacter.update({billsLibId: billsLibId, id: delItemId, deleted: false}, {$set: {deleted: true}}, function (err) {
                        if(err){
                            ecb(err);
                        }
                        else{
                            ecb(null);
                        }
                    }, function (err) {
                        if(err){
                            cb(err);
                        }
                        else{
                            cb(null);
                        }
                    });
                });
            }
        },
        delItemsArr: function () {
            return function (cb) {
                async.each(delArr, function (delObj, ecb) {
                    Bills.update({billsLibId: billsLibId, ID: delObj.updateId, deleted:false}, {$pull: {items: {id: delObj.delId}}}, function(err){
                        if(err){
                            ecb(err);
                        }
                        else{
                            ecb(null);
                        }
                    });
                }, function (err) {
                    if(err){
                        cb(err);
                    }
                    else{
                        cb(null);
                    }
                });
            }
        }
    };
    if(field === 'jobs'){
        functions.push(parallelFucs.delJobs());
        functions.push(parallelFucs.delJobsArr());
    }
    else{
        functions.push(parallelFucs.delItems());
        functions.push(parallelFucs.delItemsArr());
    }
    functions.push(parallelFucs.updateLastOpr());
    async.parallel(functions, function (err) {
        if(err){
            callback(1, 'Error');
        }
        else{
            callback(0, '');
        }
    });
};

billsLibDao.prototype.updateSerialNo = function (data, callback) {
    let billsLibId = data.billsLibId, billsId = data.billsId,
        updateArr = data.updateArr, field = data.field,
        lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    if(field === 'jobs'){
        async.parallel([
            function (cb) {
                async.each(updateArr, function (updateObj, ecb) {
                    Bills.update({billsLibId: billsLibId, ID: billsId, deleted: false, 'jobs.id': updateObj.id}, {$set: {'jobs.$.serialNo': updateObj.serialNo}}, function (err) {
                        if(err){
                            ecb(err);
                        }
                        else{
                            ecb(null);
                        }
                    });
                }, function (err) {
                    if(err){
                        cb(err);
                    }
                    else{
                        cb(null);
                    }
                });
            },
            function (cb) {
                StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        ], function (err) {
            if(err){
                callback(1, 'Error');
            }
            else{
                callback(0, '');
            }
        });
    }
    else{
        async.parallel([
            function (cb) {
                async.each(updateArr, function (updateObj, ecb) {
                    Bills.update({billsLibId: billsLibId, ID: billsId, deleted: false, 'items.id': updateObj.id}, {$set: {'items.$.serialNo': updateObj.serialNo}}, function (err) {
                        if(err){
                            ecb(err);
                        }
                        else{
                            ecb(null);
                        }
                    });
                }, function (err) {
                    if(err){
                        cb(err);
                    }
                    else{
                        cb(null);
                    }
                });
            },
            function (cb) {
                StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        ], function (err) {
            if(err){
                callback(1, 'Error');
            }
            else{
                callback(0, '');
            }
        });
    }
};

billsLibDao.prototype.updateBillsArr = function(updateData, callback){
    let billsLibId = updateData.billsLibId;
    let updateId = updateData.updateId;
    let orgId = updateData.orgId;
    let newId = updateData.newId;
    let classify = updateData.classify;
    let type = updateData.type;
    let lastOperator = updateData.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    if(classify === 'jobs'){
        if(orgId && newId && type === 'update'){
            async.parallel([
                function (cb) {
                    Bills.update({billsLibId: billsLibId, ID: updateId, deleted: false, 'jobs.id': orgId}, {$set: {'jobs.$.id': newId}}, function(err){
                        if(err){
                            cb(err);
                        }
                        else {
                            cb(null);
                        }
                    });
                },
                function (cb) {
                    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                        if(err){
                            cb(err);
                        }
                        else{
                            if(result.length > 0 ){
                                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                                StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                    if(err){
                                        cb(err);
                                    }
                                    else{
                                        cb(null);
                                    }
                                });
                            }
                        }
                    });
                }
            ], function (err) {
                if(err){
                    callback(1, 'Error');
                }
                else{
                    callback(0, '');
                }
            });
        }
        if(orgId && !newId && type === 'delete'){
            async.parallel([
                function (cb) {
                    async.each(orgId, function(oid, ecb){
                        Bills.update({billsLibId: billsLibId, ID: updateId, deleted: false}, {$pull: {jobs: {id: oid}}}, function(err){
                            if(err){
                                ecb(err);
                            }else {
                                ecb(null);
                            }
                        });
                    }, function(err){
                        if(err){
                            cb(err);
                        }
                        else{
                            cb(null);
                        }
                    });
                },
                function (cb) {
                    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                        if(err){
                            cb(err);
                        }
                        else{
                            if(result.length > 0 ){
                                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                                StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                    if(err){
                                        cb(err);
                                    }
                                    else{
                                        cb(null);
                                    }
                                });
                            }
                        }
                    });
                }
            ], function (err) {
                if(err){
                    callback(1, 'Error');
                }
                else{
                    callback(0, '');
                }
            })
        }

        if(orgId && !newId && type === 'deleteAll'){
            let delArr = [];
            updateId.forEach(function(uid){
                orgId.forEach(function(oid){
                    delArr.push({updateId: uid, delId: oid});
                });
            });
            async.parallel([
                function (cb) {
                    async.each(delArr, function(delObj, ecb){
                        Bills.update({billsLibId: billsLibId, ID: delObj.updateId, deleted: false}, {$pull: {jobs: {id: delObj.delId}}}, function(err){
                            if(err){
                                ecb(err);
                            }else {
                                ecb(null);
                            }
                        });
                    }, function(err){
                        if(err){
                            cb(err);
                        }else {
                            cb(null);
                        }
                    });
                },
                function (cb) {
                    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                        if(err){
                            cb(err);
                        }
                        else{
                            if(result.length > 0 ){
                                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                                StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                    if(err){
                                        cb(err);
                                    }
                                    else{
                                        cb(null);
                                    }
                                });
                            }
                        }
                    });
                }
            ], function (err) {
                if(err){
                    callback(1, 'Error');
                }
                else{
                    callback(0, '');
                }
            });
        }
    }
    else if(classify === 'items'){
        if(orgId && newId && type === 'update'){
            async.parallel([
                function (cb) {
                    Bills.update({billsLibId: billsLibId, ID: updateId, deleted: false, 'items.id': orgId}, {$set: {'items.$.id': newId}}, function(err){
                        if(err){
                            cb(err);
                        }
                        else {
                            cb(null);
                        }
                    });
                },
                function (cb) {
                    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                        if(err){
                            cb(err);
                        }
                        else{
                            if(result.length > 0 ){
                                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                                StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                    if(err){
                                        cb(err);
                                    }
                                    else{
                                        cb(null);
                                    }
                                });
                            }
                        }
                    });
                }
            ], function (err) {
                if(err){
                    callback(1, 'Error');
                }
                else{
                    callback(0, '');
                }
            });
        }
        if(orgId && !newId && type === 'delete'){
            async.parallel([
                function (cb) {
                    async.each(orgId, function(oid, ecb){
                        Bills.update({billsLibId: billsLibId, ID: updateId, deleted: false}, {$pull: {items: {id: oid}}}, function(err){
                            if(err){
                                ecb(err);
                            }else {
                                ecb(null);
                            }
                        });
                    }, function(err){
                        if(err){
                            cb(err);
                        }else {
                            cb(null);
                        }
                    });
                },
                function (cb) {
                    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                        if(err){
                            cb(err);
                        }
                        else{
                            if(result.length > 0 ){
                                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                                StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                    if(err){
                                        cb(err);
                                    }
                                    else{
                                        cb(null);
                                    }
                                });
                            }
                        }
                    });
                }
            ], function (err) {
                if(err){
                    callback(1, 'Error');
                }
                else{
                    callback(0, '');
                }
            })
        }
        if(orgId && !newId &&  type === 'deleteAll'){
            let delArr = [];
            updateId.forEach(function(uid){
                orgId.forEach(function(oid){
                    delArr.push({updateId: uid, delId: oid});
                });
            });
            async.parallel([
                function (cb) {
                    async.each(delArr, function(delObj, ecb){
                        Bills.update({billsLibId: billsLibId, ID: delObj.updateId, deleted: false}, {$pull: {items: {id: delObj.delId}}}, function(err){
                            if(err){
                                ecb(err);
                            }else {
                                ecb(null);
                            }
                        });
                    }, function(err){
                        if(err){
                            cb(err);
                        }else {
                            cb(err);
                        }
                    });
                },
                function (cb) {
                    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                        if(err){
                            cb(err);
                        }
                        else{
                            if(result.length > 0 ){
                                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                                StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                    if(err){
                                        cb(err);
                                    }
                                    else{
                                        cb(null);
                                    }
                                });
                            }
                        }
                    });
                }
            ], function (err) {
                if(err){
                    callback(1, 'Error');
                }
                else{
                    callback(0, '');
                }
            });
        }
    }
};

billsLibDao.prototype.pasteBills = function(pData, callback){
    let datas = pData.datas,
        billsLibId = pData.billsLibId, lastOperator = pData.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    async.parallel([
        function (cb) {
            async.each(datas, function(data, ecb){
                let needSet = {};
                for(let i in data){
                    needSet[i] = data[i];
                }
                Bills.update({billsLibId: billsLibId, ID: data.ID, deleted: false}, {$set: needSet}, function (err) {
                    if(err){
                        ecb(err);
                    }
                    else {
                        ecb(null);
                    }
                });
            }, function(err){
                if(err){
                    cb(err);
                }else {
                    cb(null);
                }
            });
        },
        function (cb) {
            StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                if(err){
                    cb(err);
                }
                else{
                    if(result.length > 0 ){
                        let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                        StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                            if(err){
                                cb(err);
                            }
                            else{
                                cb(null);
                            }
                        });
                    }
                }
            });
        }
    ], function (err) {
        if(err){
            callback(1, 'Error');
        }
        else{
            callback(0, '');
        }
    });
}

billsLibDao.prototype.updateRecharge = function(uData, callback){
    let billsLibId = uData.billsLibId;
    let updateId = uData.updateId;
    let data = uData.data, lastOperator = uData.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    async.parallel([
        function (cb) {
            Bills.update({billsLibId: billsLibId, ID: updateId, deleted: false}, {$set: {recharge: data}}, function(err){
                if(err){
                    cb(err);
                }
                else {
                    cb(null);
                }
            });
        },
        function (cb) {
            StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                if(err){
                    cb(err);
                }
                else{
                    if(result.length > 0 ){
                        let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                        StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                            if(err){
                                cb(err);
                            }
                            else{
                                cb(null);
                            }
                        });
                    }
                }
            });
        }
    ], function (err) {
        if(err){
            callback(1, 'Error');
        }
        else{
            callback(0, '');
        }
    });
};

billsLibDao.prototype.pasteRel = function (data, callback) {
    const UpdateExist = 'updateExist', UpdateNew = 'updateNew', CreateExist = 'createExist', CreateNew = 'createNew';
    const Jobs = 'jobs', Items = 'items';
    let field = data.field;
    let updateDatas = data.updateDatas;
    let createDatas = data.createDatas;
    let functions = [], lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    let parallelFucs = {
        updateLastOpr: function () {
            return function (cb) {
                StdBillsLib.find({billsLibId: data.billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: data.billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        },
        updateExJobs: function(data){
            let orgJobId = data.orgJobId, newJobId = data.newJobId,
                nodeId = data.nodeId, billsLibId = data.billsLibId;
            return function (cb){
                if(orgJobId && newJobId && nodeId && billsLibId){
                    Bills.update({billsLibId: billsLibId, ID: nodeId, deleted: false, 'jobs.id': orgJobId}, {$set: {'jobs.$.id': newJobId}}, function(err){
                        if(err){
                            cb(err);
                        }
                        else{
                            cb(null, data)
                        }
                    });
                }
            }
        },
        updateNeJobs: function(data){
            let billsLibId = data.billsLibId, nodeId = data.nodeId, newData = data.newData,
                orgJobId = data.orgJobId, code = data.code;
            return function (cb){
                if(billsLibId && nodeId && newData && orgJobId && code){
                    counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_jobs, 1, function(err, result){
                        if(err){
                            cb(err);
                        }
                        else {
                            let newJobId = result.sequence_value;
                            let newJobContent = {
                                id: newJobId,
                                billsLibId: billsLibId,
                                code: code,
                                content: newData,
                                deleted: false
                            };
                            JobContent.create(newJobContent, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    Bills.update({billsLibId: billsLibId, ID: nodeId, deleted: false, 'jobs.id': orgJobId}, {$set: {'jobs.$.id': newJobId}}, function(err){
                                        if(err){
                                            cb(err);
                                        }
                                        else{
                                            data.newJobId = newJobId;
                                            cb(null, data);
                                        }
                                    });
                                }
                            });

                        }
                    });
                }
            }

        },
        createExJobs: function(data){
            let billsLibId = data.billsLibId, newData = data.newData,
                nodeId = data.nodeId, jobId = data.jobId, serialNo = data.serialNo;
            return function (cb){
                if(billsLibId && newData && nodeId && jobId){
                    Bills.update({billsLibId: billsLibId, ID: nodeId, deleted: false}, {$addToSet: {jobs: {id: jobId, serialNo: serialNo}}}, function(err){
                        if(err){
                            cb(err);
                        }
                        else {
                            cb(null, data);
                        }
                    });
                }
            }
        },
        createNeJobs: function(data){
            let billsLibId = data.billsLibId, newData = data.newData,
                code = data.code, nodeId = data.nodeId, serialNo = data.serialNo;
            return function (cb){
                if(billsLibId && newData && code){
                    counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_jobs, 1, function(err, result){
                        if(err){
                            cb(err);
                        }
                        else {
                            let newJobId = result.sequence_value;
                            let newJobContent = {
                                id: newJobId,
                                billsLibId: billsLibId,
                                code: code,
                                content: newData,
                                deleted: false
                            };
                            JobContent.create(newJobContent, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    Bills.update({billsLibId: billsLibId, ID: nodeId, deleted: false}, {$addToSet: {jobs: {id: newJobId, serialNo: serialNo}}}, function(err){
                                        if(err){
                                            cb(err);
                                        }
                                        else {
                                            data.newJobId = newJobId;
                                            cb(null, data);
                                        }
                                    });
                                }
                            });
                        }
                    });
                }
            }
        },
        updateExItems: function(data){
            let orgItemId = data.orgItemId, newItemId = data.newItemId,
                nodeId = data.nodeId, billsLibId = data.billsLibId;
            return function (cb){
                if(orgItemId && newItemId && nodeId && billsLibId){
                    Bills.update({billsLibId: billsLibId, ID: nodeId, deleted: false, 'items.id': orgItemId}, {$set: {'items.$.id': newItemId}}, function(err){
                        if(err){
                            cb(err);
                        }
                        else{
                            cb(null, data);
                        }
                    });
                }
            }
        },
        updateNeItems: function(data){
            let billsLibId = data.billsLibId, nodeId = data.nodeId, newData = data.newData,
                orgItemId = data.orgItemId, code = data.code;
            return function (cb){
                if(billsLibId && nodeId && newData && orgItemId && code){
                    counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_items, 1, function(err, result){
                        if(err){
                            cb(err);
                        }
                        else {
                            let newItemId = result.sequence_value;
                            let newItemContent = {
                                id: newItemId,
                                billsLibId: billsLibId,
                                code: code,
                                content: newData,
                                deleted: false
                            };
                            ItemCharacter.create(newItemContent, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    Bills.update({billsLibId: billsLibId, ID: nodeId, deleted: false, 'items.id': orgItemId}, {$set: {'items.$.id': newItemId}}, function(err){
                                        if(err){
                                            cb(err);
                                        }
                                        else{
                                            data.newItemId = newItemId;
                                            cb(null, data);
                                        }
                                    });
                                }
                            });
                        }
                    });
                }
            }
        },
        createExItems: function(data){
            let billsLibId = data.billsLibId, newData = data.newData,
                nodeId = data.nodeId, itemId = data.itemId, serialNo = data.serialNo;
            return function (cb){
                if(billsLibId && newData && nodeId && itemId){
                    Bills.update({billsLibId: billsLibId, ID: nodeId, deleted: false}, {$addToSet: {items: {id: itemId, serialNo: serialNo}}}, function(err){
                        if(err){
                            cb(err);
                        }
                        else {
                            cb(null, data);
                        }
                    });
                }
            }
        },
        createNeItems: function(data){
            let billsLibId = data.billsLibId, newData = data.newData,
                code = data.code, nodeId = data.nodeId, serialNo = data.serialNo;
            return function (cb){
                if(billsLibId && newData && code){
                    counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_items, 1, function(err, result){
                        if(err){
                            cb(err);
                        }
                        else {
                            let newItemId = result.sequence_value;
                            let newItemContent = {
                                id: newItemId,
                                billsLibId: billsLibId,
                                code: code,
                                content: newData,
                                deleted: false
                            };
                            ItemCharacter.create(newItemContent, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    Bills.update({billsLibId: billsLibId, ID: nodeId, deleted: false}, {$addToSet: {items: {id: newItemId, serialNo: serialNo}}}, function(err){
                                        if(err){
                                            cb(err);
                                        }
                                        else {
                                            data.newItemId = newItemId;
                                            cb(null, data);
                                        }
                                    });
                                }
                            });
                        }
                    });
                }
            }
        }
    };
    if(field === Jobs){
        if(updateDatas.length > 0){
            for(let i=0; i<updateDatas.length; i++){
                if(updateDatas[i].type === UpdateExist){
                    functions.push(parallelFucs.updateExJobs(updateDatas[i]));
                }
                if(updateDatas[i].type === UpdateNew){
                    functions.push(parallelFucs.updateNeJobs(updateDatas[i]));
                }
            }
        }
        if(createDatas.length > 0){
            for(let i=0; i<createDatas.length; i++){
                if(createDatas[i].type === CreateExist){
                    functions.push(parallelFucs.createExJobs(createDatas[i]));
                }
                if(createDatas[i].type === CreateNew){
                    functions.push(parallelFucs.createNeJobs(createDatas[i]));
                }
            }
        }
    }
    else {
        if(updateDatas.length > 0){
            for(let i=0; i<updateDatas.length; i++){
                if(updateDatas[i].type === UpdateExist){
                    functions.push(parallelFucs.updateExItems(updateDatas[i]));
                }
                if(updateDatas[i].type === UpdateNew){
                    functions.push(parallelFucs.updateNeItems(updateDatas[i]));
                }
            }
        }
        if(createDatas.length > 0){
            for(let i=0; i<createDatas.length; i++){
                if(createDatas[i].type === CreateExist){
                    functions.push(parallelFucs.createExItems(createDatas[i]));
                }
                if(createDatas[i].type === CreateNew){
                    functions.push(parallelFucs.createNeItems(createDatas[i]));
                }
            }
        }

    }
    functions.push(parallelFucs.updateLastOpr());
    async.parallel(functions, function(err, datas){
        if(err){
            callback(1, 'Error', null);
        }else {
            callback(0, '', datas);
        }
    });
};

billsLibDao.prototype.deleteBills = function(delData, callback){
    let deleteIds = delData.deleteIds;
    let billsLibId = delData.billsLibId;
    let updateNode = delData.updateNode,
        lastOperator = delData.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    if(deleteIds){
        async.parallel([
            function(cb){
                async.each(deleteIds, function(delId, ecb){
                    Bills.update({billsLibId: billsLibId, ID: delId, deleted: false}, {$set: {deleted: true}}, function(err){
                        if(err){
                            ecb(err);
                        }
                        else {
                            ecb(null);
                        }
                    });
                }, function(err){
                    if(err){
                        cb(err);
                    }
                    else {
                        cb(null);
                    }
                });
            },
            function(cb){
                if(updateNode){
                    Bills.update({billsLibId: billsLibId, ID: updateNode.ID, deleted: false}, {$set: {NextSiblingID: updateNode.NextSiblingID}}, function(err){
                        if(err){
                            cb(err);
                        }
                        else {
                            cb(null);
                        }
                    });
                }else {
                    cb(null);
                }
            },
            function (cb) {
                StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        ], function(err){
            if(err){
                callback(1, 'Error');
            }else {
                callback(0, '');
            }
        });
    }
}

//--------------JobContent------------------

billsLibDao.prototype.getJobContent = function(gJobData, callback){
    let billsLibId = gJobData.billsLibId;
    JobContent.find({billsLibId: billsLibId, deleted: false}, '-_id').lean().sort({code: 1}).exec(function(err, result){
        if(err){
            callback(1, 'Error', null);
        }
        else {
            callback(0, '', result);
        }
    });
}

billsLibDao.prototype.createJobContent = function(cJobData, callback){
    let data = cJobData.data;
    let billsLibId = cJobData.billsLibId;
    let serialNo = cJobData.serialNo;
    let newJobContent, lastOperator = cJobData.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    async.parallel([
        function (cb) {
            counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_jobs, 1, function(err, result){
                if(err){
                    cb(err)
                }
                else {
                    let newJobId = result.sequence_value;
                    newJobContent = {
                        id: newJobId,
                        billsLibId: billsLibId,
                        code: serialNo,
                        content: data,
                        deleted: false
                    };
                    JobContent.create(newJobContent, function(err){
                        if(err){
                            cb(err);
                        }
                        else{
                            cb(null, newJobId);
                        }
                    });
                }
            });
        },
        function (cb) {
            StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                if(err){
                    cb(err);
                }
                else{
                    if(result.length > 0 ){
                        let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                        StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                            if(err){
                                cb(err);
                            }
                            else{
                                cb(null);
                            }
                        });
                    }
                }
            });
        }
    ], function (err, result) {
        if(err){
            callback(1, 'Error', null);
        }
        else{
            callback(0, '', result[0])
        }
    })
};

billsLibDao.prototype.updateJobContent = function(uJobData, callback){
    let billsLibId = uJobData.billsLibId;
    let field = uJobData.field;
    let updateData = uJobData.data;
    let updateid = uJobData.updateId, lastOperator = uJobData.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'),
        needSet = {};
    needSet[field] = updateData;
    async.parallel([
        function (cb) {
            JobContent.update({billsLibId: billsLibId, id: updateid}, {$set: needSet}, function (err) {
                if(err){
                    cb(err);
                }
                else{
                    cb(null);
                }
            });
        },
        function (cb) {
            StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                if(err){
                    cb(err);
                }
                else{
                    if(result.length > 0 ){
                        let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                        StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                            if(err){
                                cb(err);
                            }
                            else{
                                cb(null);
                            }
                        });
                    }
                }
            });
        }
    ], function (err) {
        if(err){
            callback(1, 'Error');
        }
        else{
            callback(0, '');
        }
    });
};

billsLibDao.prototype.deleteJobContent = function(data, callback){
    let delIds = data.ids;
    let billsLibId = data.billsLibId, lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    if(delIds){
        async.parallel([
            function (cb) {
                async.each(delIds, function(id, ecb){
                    JobContent.update({billsLibId: billsLibId, id: id}, {$set: {deleted: true}}, function(err){
                        if(err){
                            ecb(err);
                        }
                        else {
                            ecb(null);
                        }
                    });
                }, function(err){
                    if(err){
                        cb(err);
                    }else {
                        cb(null);
                    }
                });
            },
            function (cb) {
                StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        ], function (err) {
            if(err){
                callback(1, 'Error');
            }
            else{
                callback(0, '');
            }
        })
    }
}

billsLibDao.prototype.pasteJobs = function (data, callback) {
    let pasteDatas = data.pasteDatas;
    let updateDatas = pasteDatas.updateDatas,
        createDatas = pasteDatas.createDatas;
    let functions = [], lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    let parallelFucs = {
        updateLastOpr: function () {
            return function (cb) {
                StdBillsLib.find({billsLibId: data.billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: data.billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        },
        updateFuc: function(data){
            let updateId = data.orgId,
                field = data.field,
                updateData = data.data, billsLibId = data.billsLibId;
            if(field === 'code'){
                return function (cb){
                    JobContent.update({billsLibId: billsLibId, id: updateId}, {$set: {code: updateData}}, function(err){
                        if(err){
                            cb(err);
                        }else {
                            cb(null, data);
                        }
                    });
                };
            }else {
                return function (cb){
                    JobContent.update({billsLibId: billsLibId, id: updateId}, {$set: {content: updateData}}, function(err){
                        if(err){
                            cb(err);
                        }else {
                            cb(null, data);
                        }
                    });
                }
            }
        },
        createFuc: function(data){
            let billsLibId = data.billsLibId,
                code;
            let jobObj;
            if(data.type === 'CreateT'){
                jobObj = {
                    billsLibId: billsLibId,
                    code: data.code,
                    content: data.content,
                    deleted: false
                }
            }
            else{
                if(data.field === 'code'){
                    jobObj = {
                        billsLibId: billsLibId,
                        code: data.data,
                        content: '',
                        deleted: false
                    }
                }
                else {
                    jobObj = {
                        billsLibId: billsLibId,
                        code: data.code,
                        content: data.data,
                        deleted: false
                    }
                }
            }
            return function (cb){
                counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_jobs, 1, function(err, result){
                    if(err){
                        cb(err);
                    }
                    else {
                        let newJobId = result.sequence_value;
                        jobObj.id = newJobId;
                        data.newJobId = newJobId
                        JobContent.create(jobObj, function(err){
                            if(err){
                                cb(err);
                            }else {
                                cb(null, data);
                            }
                        });
                    }
                });
            }
        }
    };
    if(updateDatas.length > 0){
        for(let i=0; i<updateDatas.length; i++){
            functions.push(parallelFucs.updateFuc(updateDatas[i]));
        }
    }
    if(createDatas.length > 0){
        for(let i =0; i<createDatas.length; i++){
            functions.push(parallelFucs.createFuc(createDatas[i]));
        }
    }
    functions.push(parallelFucs.updateLastOpr());
    async.parallel(functions, function(err, datas){
        if(err){
            callback(1, 'Error', null);
        }else {
            callback(0, '', datas);
        }
    });
};

billsLibDao.prototype.edCreateJob = function(data, callback){
    let billsLibId = data.billsLibId,
        code = data.code,
        billsId = data.billsId,
        content = data.data,
        serialNo = data.serialNo, lastOperator = data.lastOperator, lastOperateDate =  moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    async.waterfall([
        function(cb){
            counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_jobs, 1, function(err, result){
                if(err){
                    cb(err, null);
                }
                else {
                    let newJobId = result.sequence_value;
                    cb(null, newJobId);
                }
            })
        },
        function(newJobId, cb){
            async.parallel([
                function(pcb){
                    JobContent.create({id: newJobId, billsLibId: billsLibId, code: code, content: content, deleted: false}, function(err){
                        if(err){
                            pcb(err, null);
                        }
                        else {
                            pcb(null, newJobId);
                        }
                    });
                },
                function(pcb){
                    Bills.update({billsLibId: billsLibId, ID: billsId, deleted: false}, {$addToSet: {jobs: {id: newJobId, serialNo: serialNo}}}, function(err){
                        if(err){
                            pcb(err, null);
                        }
                        else {
                            pcb(null, newJobId);
                        }
                    });
                },
                function (pcb) {
                    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                        if(err){
                            pcb(err);
                        }
                        else{
                            if(result.length > 0 ){
                                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                                StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                    if(err){
                                        pcb(err);
                                    }
                                    else{
                                        pcb(null);
                                    }
                                });
                            }
                        }
                    });
                }
            ], function(err, result){
                if(err){
                    cb(err, null);
                }
                else {
                    cb(null, result[0]);
                }
            });
        }
    ], function(err, reslut){
        if(err){
            callback(1, "Error", null);
        }
        else {
            callback(0, '', reslut);
        }
    });
};

billsLibDao.prototype.edUpdateJob = function(data, callback){
    let billsLibId = data.billsLibId,
        billsId = data.billsId,
        content = data.content,
        code = data.code,
        orgJobId = data.orgJobId, lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    async.waterfall([
        function(cb){
            counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_jobs, 1, function(err, result){
                if(err){
                    cb(err, null);
                }
                else {
                    let newJobId = result.sequence_value;
                    cb(null, newJobId);
                }
            })
        },
        function(newJobId, cb){
            async.parallel([
                function(pcb){
                    JobContent.create({id: newJobId, billsLibId: billsLibId, code: code, content: content, deleted: false}, function(err){
                        if(err){
                            pcb(err, null);
                        }
                        else {
                            pcb(null, newJobId);
                        }
                    });
                },
                function(pcb){
                    Bills.update({billsLibId: billsLibId, ID: billsId, deleted: false, 'jobs.id': orgJobId}, {$set: {'jobs.$.id': newJobId}}, function(err){
                        if(err){
                            pcb(err, null);
                        }
                        else {
                            pcb(null, newJobId);
                        }
                    });
                },
                function (pcb) {
                    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                        if(err){
                            pcb(err);
                        }
                        else{
                            if(result.length > 0 ){
                                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                                StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                    if(err){
                                        pcb(err);
                                    }
                                    else{
                                        pcb(null);
                                    }
                                });
                            }
                        }
                    });
                }
            ], function(err, result){
                if(err){
                    cb(err, null);
                }
                else {
                    cb(null, result[0]);
                }
            });
        }
    ], function(err, reslut){
        if(err){
            callback(1, "Error", null);
        }
        else {
            callback(0, '', reslut);
        }
    });
};
//----------------------ItemCharacter---------------------
billsLibDao.prototype.getItemCharacter = function(gdata, callback){
    let billsLibId = gdata.billsLibId;
    ItemCharacter.find({billsLibId: billsLibId, deleted: false}, '-_id').lean().sort({code: 1}).exec(function(err, result){
        if(err){
            callback(1, 'Error', null);
        }
        else {
            callback(0, '', result);
        }
    });
}

billsLibDao.prototype.createItemCharacter = function(cItemData, callback){
    let data = cItemData.data;
    let billsLibId = cItemData.billsLibId;
    let code = cItemData.code;
    let newItemCharacter, lastOperator = cItemData.lastOperator, lastOperateDate =  moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    async.parallel([
        function (cb) {
            counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_items, 1, function (err, result) {
                if(err){
                    cb(err);
                }
                else{
                    let newItemId = result.sequence_value;
                    newItemCharacter = {
                        id: newItemId,
                        billsLibId: billsLibId,
                        content: data,
                        code: code,
                        deleted: false
                    }
                    ItemCharacter.create(newItemCharacter, function(err){
                        if(err){
                            cb(err);
                        }
                        else{
                            cb(null, newItemId);
                        }
                    });
                }
            });
        },
        function (cb) {
            StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                if(err){
                    cb(err);
                }
                else{
                    if(result.length > 0 ){
                        let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                        StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                            if(err){
                                cb(err);
                            }
                            else{
                                cb(null);
                            }
                        });
                    }
                }
            });
        }
    ], function (err, result) {
        if(err){
            callback(1, 'Error', null);
        }
        else{
            callback(0, '', result[0]);
        }
    });
};

billsLibDao.prototype.updateItemCharacter = function(uItemData, callback){
    let field = uItemData.field;
    let updateData = uItemData.data;
    let id = uItemData.updateId;
    let billsLibId = uItemData.billsLibId, needSet = {},
        lastOperator = uItemData.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    needSet[field] = updateData;
    async.parallel([
        function (cb) {
            ItemCharacter.update({billsLibId: billsLibId, id: id}, {$set: needSet}, function(err){
                if(err){
                    cb(err);
                }
                else{
                    cb(null);
                }
            });
        },
        function (cb) {
            StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                if(err){
                    cb(err);
                }
                else{
                    if(result.length > 0 ){
                        let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                        StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                            if(err){
                                cb(err);
                            }
                            else{
                                cb(null);
                            }
                        });
                    }
                }
            });
        }
    ], function (err) {
        if(err){
            callback(1, 'Error');
        }
        else{
            callback(0, '');
        }
    });
};

billsLibDao.prototype.updateValue = function(uData, callback){
    let type = uData.type;
    let updateId = uData.updateId;
    let data = uData.data;
    let deleteCodes = uData.deleteCodes;
    let billsLibId = uData.billsLibId, lastOperator = uData.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    if(type === 'create'){
        async.parallel([
            function (cb) {
                ItemCharacter.update({billsLibId: billsLibId, id: updateId}, {$addToSet: {itemValue: data}}, function(err){
                    if(err){
                        cb(err);
                    }
                    else{
                        cb(null);
                    }
                });
            },
            function (cb) {
                StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        ], function (err) {
            if(err){
                callback(1, 'Error');
            }
            else{
                callback(0, '');
            }
        })
    }
    else if(type === 'update'){
        if(data.field === 'code'){
            async.parallel([
                function (cb) {
                    ItemCharacter.update({billsLibId: billsLibId, id: updateId,  'itemValue.code': data.code}, {$set: {'itemValue.$.code': data.newData}}, function(err){
                        if(err){
                            cb(err);
                        }
                        else{
                            cb(null);
                        }
                    });
                },
                function (cb) {
                    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                        if(err){
                            cb(err);
                        }
                        else{
                            if(result.length > 0 ){
                                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                                StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                    if(err){
                                        cb(err);
                                    }
                                    else{
                                        cb(null);
                                    }
                                });
                            }
                        }
                    });
                }
            ], function (err) {
                if(err){
                    callback(1, 'Error');
                }
                else{
                    callback(0, '');
                }
            });
        }
        else {
            async.parallel([
                function (cb) {
                    ItemCharacter.update({billsLibId: billsLibId, id: updateId,  'itemValue.code': data.code}, {$set: {'itemValue.$.value': data.newData}}, function(err,result){
                        if(err){
                            cb(err);
                        }
                        else{
                            cb(null);
                        }
                    });
                },
                function (cb) {
                    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                        if(err){
                            cb(err);
                        }
                        else{
                            if(result.length > 0 ){
                                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                                StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                    if(err){
                                        cb(err);
                                    }
                                    else{
                                        cb(null);
                                    }
                                });
                            }
                        }
                    });
                }
            ], function (err) {
                if(err){
                    callback(1, 'Error');
                }
                else{
                    callback(0, '');
                }
            })
        }
    }
    //delete
    else {
        if(deleteCodes.length > 0){
            async.parallel([
                function (cb) {
                    async.each(deleteCodes, function(code, ecb){
                        ItemCharacter.update({billsLibId: billsLibId, id: updateId}, {$pull: {itemValue: {code: code}}}, function(err){
                            if(err){
                                ecb(err);
                            }else {
                                ecb(null);
                            }
                        });
                    }, function(err){
                        if(err){
                            cb(err);
                        }else {
                            cb(null);
                        }
                    });
                },
                function (cb) {
                    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                        if(err){
                            cb(err);
                        }
                        else{
                            if(result.length > 0 ){
                                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                                StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                    if(err){
                                        cb(err);
                                    }
                                    else{
                                        cb(null);
                                    }
                                });
                            }
                        }
                    });
                }
            ], function (err) {
                if(err){
                    callback(1, 'Error');
                }
                else{
                    callback(0, '');
                }
            });
        }
    }
};

billsLibDao.prototype.deleteItemCharacter = function(data, callback){
    let delIds = data.ids;
    let billsLibId = data.billsLibId, lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    if(delIds){
        async.parallel([
            function (cb) {
                async.each(delIds, function(id, ecb){
                    ItemCharacter.update({billsLibId: billsLibId, id: id}, {$set: {deleted: true}}, function(err){
                        if(err){
                            ecb(err);
                        }else {
                            ecb(null);
                        }
                    }, function(err){
                        if(err){
                            cb(err);
                        }else {
                            cb(null);
                        }
                    });
                });
            },
            function (cb) {
                StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        ], function (err) {
            if(err){
                callback(1, 'Error');
            }
            else{
                callback(0, '');
            }
        });
    }
};


billsLibDao.prototype.pasteItems = function (data, callback) {
    let pasteDatas = data.pasteDatas;
    let updateDatas = pasteDatas.updateDatas,
        createDatas = pasteDatas.createDatas;
    let functions = [], lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    let parallelFucs = {
        updateLastOpr: function () {
            return function (cb) {
                StdBillsLib.find({billsLibId: data.billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: data.billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        },
        updateFuc: function(data){
            let updateId = data.orgId,
                field = data.field,
                updateData = data.data, billsLibId = data.billsLibId;
            if(field === 'code'){
                return function (cb){
                    ItemCharacter.update({billsLibId: billsLibId, id: updateId}, {$set: {code: updateData}}, function(err){
                        if(err){
                            cb(err);
                        }else {
                            cb(null, data);
                        }
                    });
                };
            }
            else{
                return function(cb){
                    ItemCharacter.update({billsLibId: billsLibId, id: updateId}, {$set: {content: updateData}}, function(err){
                        if(err){
                            cb(err);
                        }else {
                            cb(null, data);
                        }
                    });
                }
            }
        },
        createFuc: function(data){
            let billsLibId = data.billsLibId,
                code;
            let itemObj;
            if(data.type === 'CreateT'){
                itemObj = {
                    billsLibId: billsLibId,
                    code: data.code,
                    content: data.content,
                    deleted: false
                }
            }
            else{
                if(data.field === 'code'){
                    itemObj = {
                        billsLibId: billsLibId,
                        code: data.data,
                        content: '',
                        deleted: false
                    }
                }
                else {
                    itemObj = {
                        billsLibId: billsLibId,
                        code: data.code,
                        content: data.data,
                        deleted: false
                    }
                }
            }
            return function (cb){
                counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_items, 1, function(err, result){
                    if(err){
                        cb(err);
                    }
                    else{
                        let newItemId = result.sequence_value;
                        itemObj.id = newItemId;
                        data.newItemId = newItemId;
                        ItemCharacter.create(itemObj, function(err){
                            if(err){
                                cb(err);
                            }else {
                                cb(null, data);
                            }
                        });
                    }
                });
            }
        }
    };
    if(updateDatas.length > 0){
        for(let i=0; i<updateDatas.length; i++){
            functions.push(parallelFucs.updateFuc(updateDatas[i]));
        }
    }
    if(createDatas.length > 0){
        for(let i =0; i<createDatas.length; i++){
            functions.push(parallelFucs.createFuc(createDatas[i]));
        }
    }
    functions.push(parallelFucs.updateLastOpr());
    async.parallel(functions, function(err, datas){
        if(err){
            callback(1, 'Error', null);
        }else {
            callback(0, '', datas);
        }
    });

};

billsLibDao.prototype.pasteValues = function(data, callback) {
    let pasteDatas = data.pasteDatas;
    let updateDatas = pasteDatas.updateDatas, createDatas = pasteDatas.createDatas;
    let functions = [], lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    let parallelFucs = {
        updateLastOpr: function () {
            return function (cb) {
                StdBillsLib.find({billsLibId: data.billsLibId}, function (err, result) {
                    if(err){
                        cb(err);
                    }
                    else{
                        if(result.length > 0 ){
                            let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                            StdBillsLib.update({billsLibId: data.billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                if(err){
                                    cb(err);
                                }
                                else{
                                    cb(null);
                                }
                            });
                        }
                    }
                });
            }
        },
        updateFuc: function(data){
            let billsLibId = data.billsLibId, itemId = data.itemId, orgCode = data.orgId;
            if (data.type === 'UpdateT') {
                let valueObj = {code: data.code, value: data.content};
                return function (cb){
                    ItemCharacter.update({billsLibId: billsLibId, id: itemId}, {$pull: {itemValue: {code: orgCode}}}, function (err) {
                        if (err) {
                            cb(err);
                        }
                        else {
                            ItemCharacter.update({billsLibId: billsLibId, id: itemId}, {$addToSet: {itemValue: valueObj}}, function (err) {
                                if (err) {
                                    cb(err);
                                }
                                else {
                                    cb(null, data);
                                }
                            });
                        }
                    });
                };
            }
            else if (data.type === 'Update' && data.field === 'code') {
                return function (cb) {
                    ItemCharacter.update({billsLibId: billsLibId, id: itemId, 'itemValue.code': orgCode},
                        {$set: {'itemValue.$.code': data.data}}, function (err) {
                            if(err){
                                cb(err);
                            }
                            else {
                                cb(null, data);
                            }
                        });
                }
            }
            else if(data.type === 'Update' && data.field === 'value') {
                return function (cb){
                    ItemCharacter.update({billsLibId: billsLibId, id: itemId, 'itemValue.code': orgCode}, {$set: {'itemValue.$.value': data.data}}, function(err){
                        if(err){
                            cb(err);
                        }
                        else {
                            cb(null, data);
                        }
                    });
                };
            }
        },

        createFuc: function(data){
            let valueObj;
            if(data.type === 'CreateT'){
                valueObj = {code: data.code, value: data.content};
                return function (cb){
                    ItemCharacter.update({billsLibId: data.billsLibId, id: data.itemId}, {$addToSet: {itemValue: valueObj}}, function (err) {
                        if (err) {
                            cb(err);
                        }
                        else {
                            cb(null, data);
                        }
                    });
                };
            }
            else if(data.type === 'Create' && data.field === 'code'){
                valueObj = {code: data.data, value: ''};
                return function (cb){
                    ItemCharacter.update({billsLibId: data.billsLibId, id: data.itemId}, {$addToSet: {itemValue: valueObj}}, function (err) {
                        if (err) {
                            cb(err);
                        }
                        else {
                            cb(null, data);
                        }
                    });
                };
            }
            else {
                valueObj = {code: data.code, value: data.data};
                return function(cb){
                    ItemCharacter.update({billsLibId: data.billsLibId, id: data.itemId}, {$addToSet: {itemValue: valueObj}}, function (err) {
                        if (err) {
                            cb(err);
                        }
                        else {
                            cb(null, data);
                        }
                    });
                };
            }
        }
    };
    if (updateDatas.length > 0) {
        for (let i = 0; i < updateDatas.length; i++) {
            functions.push(parallelFucs.updateFuc(updateDatas[i]));
        }
    }
    if(createDatas.length >0){
        for(let i=0; i< createDatas.length; i++){
            functions.push(parallelFucs.createFuc(createDatas[i]));
        }
    }
    functions.push(parallelFucs.updateLastOpr());
    async.parallel(functions, function(err, datas){
        if(err){
            callback(1, 'Error', null);
        }
        else {
            callback(0, '', datas);
        }
    });
};

billsLibDao.prototype.edCreateItem = function(data, callback){
    let billsLibId = data.billsLibId,
        code = data.code,
        billsId = data.billsId,
        content = data.data,
        serialNo = data.serialNo, lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    async.waterfall([
        function(cb){
            counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_items, 1, function(err, result){
                if(err){
                    cb(err, null);
                }
                else {
                    let newItemId = result.sequence_value;
                    cb(null, newItemId);
                }
            })
        },
        function(newItemId, cb){
            async.parallel([
                function(pcb){
                    ItemCharacter.create({id: newItemId, billsLibId: billsLibId, code: code, content: content, deleted: false}, function(err){
                        if(err){
                            pcb(err, null);
                        }
                        else {
                            pcb(null, newItemId);
                        }
                    });
                },
                function(pcb){
                    Bills.update({billsLibId: billsLibId, ID: billsId, deleted: false}, {$addToSet: {items: {id: newItemId, serialNo: serialNo}}}, function(err){
                        if(err){
                            pcb(err, null);
                        }
                        else {
                            pcb(null, newItemId);
                        }
                    });
                },
                function (pcb) {
                    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                        if(err){
                            pcb(err);
                        }
                        else{
                            if(result.length > 0 ){
                                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                                StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                    if(err){
                                        pcb(err);
                                    }
                                    else{
                                        pcb(null);
                                    }
                                });
                            }
                        }
                    });
                }
            ], function(err, result){
                if(err){
                    cb(err, null);
                }
                else {
                    cb(null, result[0]);
                }
            });
        }
    ], function(err, reslut){
        if(err){
            callback(1, "Error", null);
        }
        else {
            callback(0, '', reslut);
        }
    });
};

billsLibDao.prototype.edUpdateItem = function(data, callback){
    let billsLibId = data.billsLibId,
        billsId = data.billsId,
        content = data.content,
        code = data.code,
        orgItemId = data.orgItemId, lastOperator = data.lastOperator, lastOperateDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    async.waterfall([
        function(cb){
            counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_items, 1, function(err, result){
                if(err){
                    cb(err, null);
                }
                else {
                    let newItemId = result.sequence_value;
                    cb(null, newItemId);
                }
            })
        },
        function(newItemId, cb){
            async.parallel([
                function(pcb){
                    ItemCharacter.create({id: newItemId, billsLibId: billsLibId, code: code, content: content, deleted: false}, function(err){
                        if(err){
                            pcb(err, null);
                        }
                        else {
                            pcb(null, newItemId);
                        }
                    });
                },
                function(pcb){
                    Bills.update({billsLibId: billsLibId, ID: billsId, deleted: false, 'items.id': orgItemId}, {$set: {'items.$.id': newItemId}}, function(err){
                        if(err){
                            pcb(err, null);
                        }
                        else {
                            pcb(null, newItemId);
                        }
                    });
                },
                function (pcb) {
                    StdBillsLib.find({billsLibId: billsLibId}, function (err, result) {
                        if(err){
                            pcb(err);
                        }
                        else{
                            if(result.length > 0 ){
                                let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
                                StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr}}, function(err){
                                    if(err){
                                        pcb(err);
                                    }
                                    else{
                                        pcb(null);
                                    }
                                });
                            }
                        }
                    });
                }
            ], function(err, result){
                if(err){
                    cb(err, null);
                }
                else {
                    cb(null, result[0]);
                }
            });
        }
    ], function(err, reslut){
        if(err){
            callback(1, "Error", null);
        }
        else {
            callback(0, '', reslut);
        }
    });
};
//

billsLibDao.prototype.getStdBillsByCode = async function (data, callback) {
    let findData = function (value, field, Array) {
        let i = 0;
        for (i = 0; i < Array.length; i++) {
            if (value[field] === Array[i][field]) {
                return Array[i];
            }
        }
        return null;
    };
    let MergeData = function (arr) {
        let result = "", count = 0;
        for(let i = 0; i < arr.length; i++){
            if(arr[i].isChecked === true){
                count += 1;
                if (count === 1) {
                    result += count + ". " + arr[i].content;
                } else {
                    result += "\n" + count + ". " + arr[i].content;
                }
            }
        }
        return result;
    }
    try{
        let bills = await Bills.findOne({billsLibId: data.billsLibId, code: data.code, deleted: false}, '-_id');

        if(bills){
            //设置清单备注(父项清单补注)
            if(bills.ParentID != -1){
                let parentBills = await Bills.findOne({billsLibId: data.billsLibId, ID: bills.ParentID, deleted: false});
                if(parentBills && parentBills.recharge){
                    bills.recharge = parentBills.recharge;
                }
            }
            //设置项目特征
            let itemCharacters = await ItemCharacter.find({billsLibId: data.billsLibId, deleted: false}, '-_id');
            bills._doc.itemCharacter = [];
            bills.items = _.sortBy(bills.items,"serialNo");//排序
            if(itemCharacters && bills.items){
                for(let item of bills.items){
                    let itemData = findData(item, 'id', itemCharacters);
                    if(itemData){
                        itemData._doc.serialNo = item.serialNo;
                        bills._doc.itemCharacter.push(itemData);
                    }
                }
            }
            bills._doc.itemCharacterText = MergeData(bills._doc.itemCharacter);
            //设置工作内容
            let jobContents = await JobContent.find({billsLibId: data.billsLibId, deleted: false}, '-_id');
            bills._doc.jobContent = [];
            bills.jobs = _.sortBy(bills.jobs,"serialNo");//排序
            if(jobContents && bills.jobs){
                for(let job of bills.jobs){
                    let jobData = findData(job, 'id', jobContents);
                    jobData.isChecked = true;
                    jobData._doc.serialNo = job.serialNo;
                    bills._doc.jobContent.push(jobData);
                }
            }
            bills._doc.jobContentText = MergeData(bills._doc.jobContent);
        }
        if(callback){
            callback(0, '', bills);
        }else {
            return bills;
        }
    }
    catch(err){
        callback(1, err, null);
        return null;
    }
};
billsLibDao.prototype.getStdBillsByCodet = function (data, callback) {
    let findData = function (value, field, Array) {
        let i = 0;
        for (i = 0; i < Array.length; i++) {
            if (value[field] === Array[i][field]) {
                return Array[i];
            }
        }
        return null;
    };
    let MergeData = function (arr) {
        let result = "", count = 0;
        for(let i = 0; i < arr.length; i++){
            if(arr[i].isChecked === true){
                count += 1;
                if (count === 1) {
                    result += count + ". " + arr[i].content;
                } else {
                    result += "\n" + count + ". " + arr[i].content;
                }
            }
        }
        return result;
    }
    async.waterfall([
        function (callback) {
            Bills.findOne({'billsLibId': data.billsLibId, 'code': data.code, 'deleted': false}, "-_id", function (err, result) {
                callback(err, JSON.parse(JSON.stringify(result)));
            });
        },
        function (bills, callback) {
            if (bills) {
                ItemCharacter.find({'billsLibId': data.billsLibId, 'deleted': false}, '-_id', function (err, result) {
                    if (err) {
                        callback(err, bills);
                    } else {
                        bills._doc.itemCharacter = [];
                        if (result && bills && bills.items) {
                            for (let item of bills.items) {
                                let itemData = findData(item, 'id', result);
                                if (itemData) {
                                    bills._doc.itemCharacter.push(JSON.parse(JSON.stringify(itemData)));
                                }
                            }
                        }
                        bills._doc.itemCharacterText = MergeData(bills.itemCharacter);
                        callback(err, bills);
                    }
                });
            } else {
                callback(null, bills);
            }

        },
        function (bills, callback) {
            if (bills) {
                JobContent.find({'billsLibId': data.billsLibId, 'deleted': false}, '-_id', function (err, result) {
                    if (err) {
                        callback(err, bills);
                    } else {
                        bills.jobContent = [];
                        if (result && bills && bills.jobs) {
                            for (let job of bills.jobs) {
                                let jobData = findData(job, 'id', result);;
                                if (jobData) {
                                    jobData = JSON.parse(JSON.stringify(jobData));
                                    jobData.isChecked = true;
                                    bills.jobContent.push(jobData);
                                }
                            }
                        }
                        bills.jobContentText = MergeData(bills.jobContent);
                        callback(err, bills);
                    }
                });
            } else {
                callback(null, bills);
            }
        }
    ], function (err, result) {
        if (err) {
            callback(1, err, null);
        } else {
            callback(0, err, result);
        }
    });
};


module.exports = new billsLibDao();
