/** * 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 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'); const { isDef, isEmptyVal } = require('../../../public/common_util'); import {OprDao} from "./gljMapModel"; import moment from "moment"; import counter from "../../../public/counter/counter"; import async from "async"; class GljDao extends OprDao{ // 自动计算组含有组成物的人材机的定额价 async calcPriceForComposition(gljLibID) { const gljs = await gljModel.find({ repositoryId: gljLibID }, '-_id ID component basePrice').lean(); const updateData = []; const toCalcGLJs = []; const gljIDMap = {}; for (let i = 0; i < gljs.length; i++) { const glj = gljs[i]; gljIDMap[glj.ID] = glj; if (glj.component && glj.component.length) { toCalcGLJs.push(glj); } } for (let i = 0; i < toCalcGLJs.length; i++) { const glj = toCalcGLJs[i]; let sum = 0; for (let j = 0; j < glj.component.length; j++) { const c = glj.component[j]; if (!gljIDMap[c.ID]) { continue; } sum += c.consumeAmt * gljIDMap[c.ID].basePrice; } sum = scMathUtil.roundTo(sum, -2); updateData.push({ updateOne: { filter: { ID: glj.ID }, update: { basePrice: sum } } }); } if (updateData.length) { await gljModel.bulkWrite(updateData); } } async copyLib(sourceLibID, targetLibID) { const task = [ this.copyClassData(sourceLibID, targetLibID), this.copyGLJData(sourceLibID, targetLibID) ]; await Promise.all(task); } async copyClassData(sourceLibID, targetLibID) { const sourceClassData = await gljClassModel.find({ repositoryId: sourceLibID }, '-_id').lean(); const insertData = sourceClassData.map(item => ({ ... item, repositoryId: targetLibID })); if (insertData.length) { await gljClassModel.insertMany(insertData); } } async copyGLJData(sourceLibID, targetLibID) { const sourceGLJData = await gljModel.find({ repositoryId: sourceLibID }, '-_id').lean(); const IDMapping = {}; const countData = await counter.counterDAO.getIDAfterCount(counter.moduleName.GLJ, sourceGLJData.length); const countIdx = countData.sequence_value - (sourceGLJData.length - 1); sourceGLJData.forEach((glj, index) => { IDMapping[glj.ID] = countIdx + index; }); const insertData = sourceGLJData.map(glj => { const newComponent = (glj.component || []).map(c => ({ ID: IDMapping[c.ID], consumeAmt: c.consumeAmt })); return { ...glj, repositoryId: targetLibID, ID: IDMapping[glj.ID], component: newComponent }; }); if (insertData.length) { await gljModel.insertMany(insertData); } } async getReference(repositoryId, gljId) { const gljLib = await gljMapModel.findOne({ID: repositoryId}); const rationLibIds = gljLib.rationLibs.map(lib => lib.ID); const rationLibs = await rationMapModel.find({ID: {$in: rationLibIds}}, '-_id ID dispName'); const rationLibNameMapping = {}; rationLibs.forEach(item => { rationLibNameMapping[item.ID] = item.dispName; }); const stdRations = await rationModel.find({rationRepId: {$in: rationLibIds}, 'rationGljList.gljId': gljId}, '-_id code rationRepId'); const rst = {}; const unknownLib = '未知定额库'; const complementaryLib = '补充定额库'; stdRations.forEach(ration => { const libName = rationLibNameMapping[ration.rationRepId] || unknownLib; if (!rst[libName]) { rst[libName] = []; } rst[libName].push(ration); }); const complementaryRations = await complementaryRationModel.find({'rationGljList.gljId': gljId}, '-_id code'); if (complementaryRations.length) { rst[complementaryLib] = []; } complementaryRations.forEach(ration => rst[complementaryLib].push({code: ration.code})); return rst; } async 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]; 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]; 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){ try { let rst = await gljModel.find({repositoryId: repositoryId}).lean(); // test-- 删除重复编码数据 /*const map = {}; rst.forEach(glj => { if (glj.code === '016100400') { console.log(glj); } const obj = {code: glj.code, ID: glj.ID}; if (!map[glj.code]) { map[glj.code] = [obj]; } else { map[glj.code].push(obj); } }); const IDs = []; for (let code in map) { if (map[code].length > 1) { map[code].sort((a, b) => a.ID - b.ID); console.log(map[code]); let hasUsed = false; const removeIDs = []; const tempIDs = []; for (let i = 0; i < map[code].length; i++) { const glj = map[code][i]; if (i !== 0) { tempIDs.push(glj.ID); } const isUsed = await rationModel.findOne({'rationGljList.gljId': glj.ID}); if (isUsed) { hasUsed = true; } else { removeIDs.push(glj.ID); } } if (hasUsed) { IDs.push(...removeIDs); } else { IDs.push(...tempIDs); } //console.log(map[code]); } } if (IDs.length) { await gljModel.deleteMany({ID: {$in: IDs}}); } console.log(IDs);*/ // test-- this.sortToNumber(rst); callback(0, rst); } catch (err) { callback(1, null); } } getGljItemByType (repositoryId, type, callback){ let me = this; gljModel.find({"repositoryId": repositoryId, "gljType": type}, '-_id', {lean: true}, 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}, '-_id', {lean: true}, 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}}, '-_id', {lean: true}, 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}}, '-_id', {lean: true}, 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}); } }); }); }); }); /*counter.counterDAO.getIDAfterCount(counter.moduleName.GLJ, items.length, function(err, result){ const maxId = result.sequence_value; const arr = []; for (let i = 0; i < items.length; i++) { const obj = new gljModel(items[i]); obj.ID = (maxId - (items.length - 1) + i); obj.repositoryId = repId; arr.push(obj); } gljModel.collection.insert(arr, null, function(err, docs){ if (err) { callback(true, "Fail to add", 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, "Add successfully", docs); } }); } }) });*/ } 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 (cData === '税率') { colMapping.taxRate = 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){ const updateSet = {}; // 税率 const taxRateCol = colMapping.taxRate; if (isDef(taxRateCol) && !isEmptyVal(sheetData[row][taxRateCol])) { updateSet.taxRate = sheetData[row][taxRateCol]; } // 价格 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 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 (cData === '税率') { colMapping.taxRate = 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){ const updateSet = {}; // 税率 const taxRateCol = colMapping.taxRate; if (isDef(taxRateCol) && !isEmptyVal(sheetData[row][taxRateCol])) { updateSet.taxRate = sheetData[row][taxRateCol]; } // 价格 if(priceProperties.length > 0){ // 多单价 for(let priceProp of priceProperties){ let dataCode = priceProp.price.dataCode; let priceCellData = sheetData[row][colMapping[dataCode]]; //Excel中没有这个单价则跳过 if (!colMapping[dataCode] || isEmptyVal(priceCellData)) { continue; } 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 && !isEmptyVal(sheetData[row][colMapping.basePrice])){ let priceCellData = sheetData[row][colMapping.basePrice]; let basePrice = priceCellData && !isNaN(priceCellData) ? scMathUtil.roundTo(priceCellData, -2) : 0; updateSet.basePrice = basePrice; /* updateCodes.push(gljCode); updateBulk.push({ updateOne: {filter: {ID: existGlj.ID}, update: {$set: {basePrice: basePrice}}} }); */ } } if (Object.keys(updateSet).length) { updateCodes.push(gljCode); updateBulk.push({ updateOne: {filter: {ID: existGlj.ID}, update: {$set: updateSet}} }); } } } if(updateBulk.length > 0){ while (updateBulk.length > 0) { let sliceBulk = updateBulk.splice(0, 1000); await gljModel.bulkWrite(sliceBulk); } } } // 批量修改人材机类型 async batchUpdateGLJType(gljLibId, sheetData) { // 将所有人材机进行编码映射 const allGLJs = await gljModel.find({repositoryId: gljLibId}, {ID: true, code: true, gljType: true, shortName: true}).lean(); const codeMapping = {}; allGLJs.forEach(glj => codeMapping[glj.code] = glj); const updateTask = []; for (let row = 1; row < sheetData.length; row++) { const rowData = sheetData[row]; const code = rowData[0]; const gljType = rowData[1]; const shortName = rowData[2]; const glj = codeMapping[code]; if (!glj) { continue; } updateTask.push({ updateOne: { filter: { ID: glj.ID }, update: { gljType, shortName } } }); } if (updateTask.length) { gljModel.bulkWrite(updateTask); } } // 导入组成物(替换原本的数据) // excel第一行应为:人材机、组成物、消耗量(或者:消耗-一般、消耗-简易等) 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 consumeAmtProperties = compilation.consumeAmtProperties || []; // 根据第一行数据,获取列号与字段映射 const colMapping = {}; const firstRow = sheetData[0]; const multiConsumeAmt = []; firstRow.forEach((colData, col) => { if (colData === '人材机') { colMapping.code = col; } else if (colData === '组成物') { colMapping.componentCode = col; } else if (colData === '消耗量') { colMapping.consumeAmt = col; } else { // 多消耗量 const consumeAmtItem = consumeAmtProperties.find(item => item.consumeAmt.dataName === colData); if (consumeAmtItem) { colMapping[consumeAmtItem.consumeAmt.dataCode] = col; multiConsumeAmt.push(consumeAmtItem.consumeAmt.dataCode); } } }); if (Object.getOwnPropertyNames(colMapping).length < 3) { throw 'exel数据错误'; } // 将所有人材机进行编码映射 const allGLJs = await gljModel.find({repositoryId: gljLibId}, {ID: true, code: true}).lean(); const codeMapping = {}; allGLJs.forEach(glj => codeMapping[glj.code] = glj); const updateGLJs = []; //const forTest = []; // 跳过列头 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 = []; } const componentIsExist = glj.component.some(item => item.ID === component.ID); if (componentIsExist) { //forTest.push(code); continue; } const componentGLJ = { ID: component.ID }; if (multiConsumeAmt.length) { // 多消耗量 const consumeAmtProperty = {}; for (const dataCode of multiConsumeAmt) { consumeAmtProperty[dataCode] = +rowData[colMapping[dataCode]] } componentGLJ.consumeAmtProperty = consumeAmtProperty; } else { // 单消耗量 componentGLJ.consumeAmt = +rowData[colMapping.consumeAmt] } glj.component.push(componentGLJ); if (updateGLJs.indexOf(glj) < 0) { updateGLJs.push(glj); } } // 更新数据 const tasks = []; //console.log(`[new Set(forTest)]`); //console.log([new Set(forTest)]); updateGLJs.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;