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