|
|
@@ -11,6 +11,7 @@ let ItemCharacter = mongoose.model('std_bills_lib_itemCharacter');
|
|
|
let moment = require("moment");
|
|
|
let billsGuidanceLib = mongoose.model('std_billsGuidance_lib');
|
|
|
const engLibModel = mongoose.model('engineering_lib');
|
|
|
+let uuid = require('uuid');
|
|
|
let billsLibDao = function(){};
|
|
|
|
|
|
|
|
|
@@ -3091,7 +3092,203 @@ billsLibDao.prototype.edUpdateItem = function(data, callback){
|
|
|
}
|
|
|
});
|
|
|
};
|
|
|
-//
|
|
|
+
|
|
|
+billsLibDao.prototype.hasData = async function (billsLibId) {
|
|
|
+ let bills = await Bills.findOne({billsLibId: billsLibId});
|
|
|
+ if (bills) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+};
|
|
|
+
|
|
|
+billsLibDao.prototype.importBills = async function (billsLibId, sheetData) {
|
|
|
+ //实际节点深度数组,下标等于深度,元素为该为上一个该深度清单数据, 数组长度-1等于最大深度
|
|
|
+ let depthArr = [];
|
|
|
+ const deepest = 10000;
|
|
|
+ //深度的值,并不是真正的深度,只是三种类型节点(顶节点、中间节点、底节点)的深度值,节点根据深度值与深度数组最大深度的比较,对深度数组进行更新,
|
|
|
+ //并且确定父子上下关系
|
|
|
+ function getDepthValue(code){
|
|
|
+ let midReg = /\.{1,}/g;
|
|
|
+ //root
|
|
|
+ if (code.length === 1) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (midReg.test(code)) {
|
|
|
+ return code.match(midReg).length;
|
|
|
+ }
|
|
|
+ return deepest;
|
|
|
+ }
|
|
|
+ let billsDatas = [],
|
|
|
+ jobMapping = {},
|
|
|
+ itemMapping = {};
|
|
|
+ function getDivideData(data){
|
|
|
+ let rst = [];
|
|
|
+ let divideReg = /[\n,\r]/g,
|
|
|
+ prefixReg = /\d+\.{1}/g; //前缀 1. 2.
|
|
|
+ let divideArr = data.split(divideReg);
|
|
|
+ for (let dData of divideArr) {
|
|
|
+ if (dData !== '') {
|
|
|
+ rst.push(dData.replace(prefixReg, ''));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return rst;
|
|
|
+ }
|
|
|
+ //设置总工作内容/项目特征映射
|
|
|
+ function setBillsSubMapping(subData, mapping){
|
|
|
+ for (let data of subData) {
|
|
|
+ if (!mapping[data]) {
|
|
|
+ let code = Object.keys(mapping).length + 1;
|
|
|
+ mapping[data] = {billsLibId: billsLibId, code: code, content: data, deleted: false};
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let row = -1;
|
|
|
+ //从表格中获取清单数据
|
|
|
+ for (let rowData of sheetData) {
|
|
|
+ row++;
|
|
|
+ if (row === 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ let bills = {
|
|
|
+ deleted: false,
|
|
|
+ billsLibId: billsLibId,
|
|
|
+ parent: null,
|
|
|
+ ID: uuid.v1(),
|
|
|
+ ParentID: -1,
|
|
|
+ NextSiblingID: -1,
|
|
|
+ code: typeof rowData[0] !== 'undefined' ? rowData[0] : '',
|
|
|
+ name: typeof rowData[1] !== 'undefined' ? rowData[1] : '',
|
|
|
+ unit: typeof rowData[2] !== 'undefined' ? rowData[2] : '',
|
|
|
+ ruleText: typeof rowData[3] !== 'undefined' ? rowData[3] : '',
|
|
|
+ recharge: '',
|
|
|
+ };
|
|
|
+ let jobData = typeof rowData[4] !== 'undefined' ? getDivideData(rowData[4]) : [],
|
|
|
+ itemData = typeof rowData[5] !== 'undefined' ? getDivideData(rowData[5]) :[];
|
|
|
+ bills.jobData = jobData;
|
|
|
+ bills.itemData = itemData;
|
|
|
+ setBillsSubMapping(jobData, jobMapping);
|
|
|
+ setBillsSubMapping(itemData, itemMapping);
|
|
|
+ billsDatas.push(bills);
|
|
|
+ }
|
|
|
+ //设置工作内容、项目特征id
|
|
|
+ async function setSubId(moduleName, subMapping) {
|
|
|
+ let idx = 0,
|
|
|
+ subCount = Object.keys(subMapping).length;
|
|
|
+ let subCounter = await counter.counterDAO.getIDAfterCount(moduleName, subCount);
|
|
|
+ for (let mapping in subMapping) {
|
|
|
+ let id = subCounter.sequence_value - (subCount - 1) + idx;
|
|
|
+ let sub = subMapping[mapping];
|
|
|
+ sub.id = id;
|
|
|
+ idx++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ await setSubId(counter.moduleName.billsLib_jobs, jobMapping);
|
|
|
+ await setSubId(counter.moduleName.billsLib_items, itemMapping);
|
|
|
+ //获得清单、工作内容/项目特征关联数组
|
|
|
+ //subDatas为清单工作内容/项目特征的字符串数组 eg: ['场内运输', '开挖'];
|
|
|
+ //mapping为总工作内容/项目特征字符串映射 eg: {'场内运输': {content: '场内运输', id: 1, code: 1, deleted: false}}
|
|
|
+ function getBillsSubRef(subDatas, mapping) {
|
|
|
+ let rst = [];
|
|
|
+ for (let i = 0; i < subDatas.length; i++) {
|
|
|
+ let data = subDatas[i];
|
|
|
+ if (mapping[data]) {
|
|
|
+ rst.push({id: mapping[data].id, serialNo: i + 1});
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return rst;
|
|
|
+ }
|
|
|
+ //设置完整的清单数据(树结构、工作内容/项目特征)
|
|
|
+ for (let i = 0; i < billsDatas.length; i++) {
|
|
|
+ let bills = billsDatas[i],
|
|
|
+ preBills = billsDatas[i - 1];
|
|
|
+ //树结构相关设置
|
|
|
+ let maxDepth = depthArr.length - 1;
|
|
|
+ let depthV = getDepthValue(bills.code);
|
|
|
+ //前节点为最底层节点,且这个节点为最底层节点,则深度相同
|
|
|
+ let preIsDeepest = preBills && getDepthValue(preBills.code) === deepest ? true : false;
|
|
|
+ if (preIsDeepest && depthV === deepest) {
|
|
|
+ depthV = maxDepth;
|
|
|
+ }
|
|
|
+ if (depthV > maxDepth) {
|
|
|
+ let parent = depthArr[depthArr.length - 1];
|
|
|
+ if (parent) {
|
|
|
+ bills.ParentID = parent.ID;
|
|
|
+ bills.parent = parent;
|
|
|
+ }
|
|
|
+ depthArr.push(bills);
|
|
|
+ } else {
|
|
|
+ let parent = depthArr[depthV -1];
|
|
|
+ if (parent) {
|
|
|
+ bills.ParentID = parent.ID;
|
|
|
+ bills.parent = parent;
|
|
|
+ }
|
|
|
+ depthArr[depthV].NextSiblingID = bills.ID;
|
|
|
+ depthArr.splice(depthV, 1);
|
|
|
+ if (depthV < maxDepth) { //切割
|
|
|
+ depthArr = depthArr.slice(0, depthV);
|
|
|
+ }
|
|
|
+ depthArr.push(bills);
|
|
|
+ }
|
|
|
+ //工作内容项目特征
|
|
|
+ bills.jobs = getBillsSubRef(bills.jobData, jobMapping);
|
|
|
+ bills.items = getBillsSubRef(bills.itemData, itemMapping);
|
|
|
+ }
|
|
|
+ function getSectionInfo(bills){
|
|
|
+ let parentIDs = [];
|
|
|
+ let sectionInfo = {first: null, second: null, third: null};
|
|
|
+ getParent(bills);
|
|
|
+ if(parentIDs[parentIDs.length - 1]){
|
|
|
+ sectionInfo.first = parentIDs[parentIDs.length - 1];
|
|
|
+ }
|
|
|
+ if(parentIDs[parentIDs.length - 2]){
|
|
|
+ sectionInfo.second = parentIDs[parentIDs.length - 2];
|
|
|
+ }
|
|
|
+ if(parentIDs[parentIDs.length - 3]){
|
|
|
+ sectionInfo.third = parentIDs[parentIDs.length - 3];
|
|
|
+ }
|
|
|
+ return sectionInfo;
|
|
|
+ function getParent(bills){
|
|
|
+ if(bills.parent){
|
|
|
+ parentIDs.push(bills.parent.ID);
|
|
|
+ getParent(bills.parent);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //设置sectionInfo
|
|
|
+ for (let bills of billsDatas) {
|
|
|
+ bills.sectionInfo = getSectionInfo(bills);
|
|
|
+ }
|
|
|
+ //插入清单
|
|
|
+ let bulks = [];
|
|
|
+ for (let bills of billsDatas) {
|
|
|
+ delete bills.parent;
|
|
|
+ bulks.push({insertOne: {document: bills}});
|
|
|
+ }
|
|
|
+ if (bulks.length > 0) {
|
|
|
+ await Bills.bulkWrite(bulks);
|
|
|
+ }
|
|
|
+ //清除工作内容、项目特征
|
|
|
+ await JobContent.remove({billsLibId: billsLibId});
|
|
|
+ await ItemCharacter.remove({billsLibId: billsLibId});
|
|
|
+ function getSubBulks(subMapping) {
|
|
|
+ let rst = [];
|
|
|
+ for (let mapping in subMapping) {
|
|
|
+ let sub = subMapping[mapping];
|
|
|
+ rst.push({insertOne: {document: sub}});
|
|
|
+ }
|
|
|
+ return rst;
|
|
|
+ }
|
|
|
+ //插入工作内容
|
|
|
+ let jobBulks = getSubBulks(jobMapping);
|
|
|
+ if (jobBulks.length > 0) {
|
|
|
+ await JobContent.bulkWrite(jobBulks);
|
|
|
+ }
|
|
|
+ //插入项目特征
|
|
|
+ let itemBulks = getSubBulks(itemMapping);
|
|
|
+ if (itemBulks.length > 0) {
|
|
|
+ await ItemCharacter.bulkWrite(itemBulks);
|
|
|
+ }
|
|
|
+};
|
|
|
|
|
|
|
|
|
module.exports = new billsLibDao();
|