|  | @@ -23,6 +23,7 @@ const compilationModel = mongoose.model('compilation');
 | 
	
		
			
				|  |  |  const _ = require('lodash');
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  module.exports = {
 | 
	
		
			
				|  |  | +    handleCopyItems,
 | 
	
		
			
				|  |  |      getComBillsLibInfo,
 | 
	
		
			
				|  |  |      getBillsGuideLibs,
 | 
	
		
			
				|  |  |      initBillsGuideLib,
 | 
	
	
		
			
				|  | @@ -33,6 +34,126 @@ module.exports = {
 | 
	
		
			
				|  |  |      testItems
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +function setChildren(bill, parentMap) {
 | 
	
		
			
				|  |  | +    let children = parentMap[bill.ID];
 | 
	
		
			
				|  |  | +    if (children) {
 | 
	
		
			
				|  |  | +        for (let c of children) {
 | 
	
		
			
				|  |  | +            setChildren(c, parentMap);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        bill.children = children;
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +        bill.children = [];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function sortChildren(lists) {
 | 
	
		
			
				|  |  | +    let IDMap = {},
 | 
	
		
			
				|  |  | +        nextMap = {},
 | 
	
		
			
				|  |  | +        firstNode = null,
 | 
	
		
			
				|  |  | +        newList = [];
 | 
	
		
			
				|  |  | +    for (let l of lists) {
 | 
	
		
			
				|  |  | +        if (l.children && l.children.length > 0) l.children = sortChildren(l.children); //递规排序
 | 
	
		
			
				|  |  | +        IDMap[l.ID] = l;
 | 
	
		
			
				|  |  | +        if (l.NextSiblingID != -1) nextMap[l.NextSiblingID] = l;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    for (let t of lists) {
 | 
	
		
			
				|  |  | +        if (!nextMap[t.ID]) { //如果在下一节点映射没找到,则是第一个节点
 | 
	
		
			
				|  |  | +            firstNode = t;
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (firstNode) {
 | 
	
		
			
				|  |  | +        newList.push(firstNode);
 | 
	
		
			
				|  |  | +        delete IDMap[firstNode.ID];
 | 
	
		
			
				|  |  | +        setNext(firstNode, newList);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //容错处理,如果链断了的情况,直接添加到后面
 | 
	
		
			
				|  |  | +    for (let key in IDMap) {
 | 
	
		
			
				|  |  | +        if (IDMap[key]) newList.push(IDMap[key])
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return newList;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    function setNext(node, array) {
 | 
	
		
			
				|  |  | +        if (node.NextSiblingID != -1) {
 | 
	
		
			
				|  |  | +            let next = IDMap[node.NextSiblingID];
 | 
	
		
			
				|  |  | +            if (next) {
 | 
	
		
			
				|  |  | +                array.push(next);
 | 
	
		
			
				|  |  | +                delete IDMap[next.ID];
 | 
	
		
			
				|  |  | +                setNext(next, array);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function getItemFromChildren(children, allItems) {
 | 
	
		
			
				|  |  | +    for (let i = 0; i < children.length; i++) {
 | 
	
		
			
				|  |  | +        const cur = children[i];
 | 
	
		
			
				|  |  | +        const next = children[i + 1];
 | 
	
		
			
				|  |  | +        cur.NextSiblingID = next && next.ID || -1;
 | 
	
		
			
				|  |  | +        allItems.push(cur);
 | 
	
		
			
				|  |  | +        if (cur.children && cur.children.length) {
 | 
	
		
			
				|  |  | +            getItemFromChildren(cur.children, allItems);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function resetTreeData(billsList) {
 | 
	
		
			
				|  |  | +    const idMapping = {};
 | 
	
		
			
				|  |  | +    idMapping['-1'] = -1;
 | 
	
		
			
				|  |  | +    // 建立新ID-旧ID映射
 | 
	
		
			
				|  |  | +    billsList.forEach(bills => idMapping[bills.ID] = uuidV1());
 | 
	
		
			
				|  |  | +    billsList.forEach(function (bills) {
 | 
	
		
			
				|  |  | +        bills.ID = idMapping[bills.ID] ? idMapping[bills.ID] : -1;
 | 
	
		
			
				|  |  | +        bills.ParentID = idMapping[bills.ParentID] ? idMapping[bills.ParentID] : -1;
 | 
	
		
			
				|  |  | +        bills.NextSiblingID = idMapping[bills.NextSiblingID] ? idMapping[bills.NextSiblingID] : -1;
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 从某库中根据清单编号拷贝工艺
 | 
	
		
			
				|  |  | +async function handleCopyItems(sourceGuideLibID, sourceBillsLibID, targetGuideLibID, targetBillsLibID) {
 | 
	
		
			
				|  |  | +    const sourceBills = await stdBillsModel.find({ billsLibId: sourceBillsLibID, deleted: false }, '-_id ID code').lean();
 | 
	
		
			
				|  |  | +    const targetBills = await stdBillsModel.find({ billsLibId: targetBillsLibID, deleted: false }, '-_id ID code').lean();
 | 
	
		
			
				|  |  | +    const sourceItems = await billsGuideItemsModel.find({ libID: sourceGuideLibID, type: 0, deleted: false }, '-_id').lean(); // 过滤掉定额项
 | 
	
		
			
				|  |  | +    const targetCodeIDMap = {};
 | 
	
		
			
				|  |  | +    targetBills.forEach(bills => targetCodeIDMap[bills.code] = bills.ID);
 | 
	
		
			
				|  |  | +    const toDeleteIDList = [];
 | 
	
		
			
				|  |  | +    const insertBulks = [];
 | 
	
		
			
				|  |  | +    sourceBills.forEach(bills => {
 | 
	
		
			
				|  |  | +        const matchedItems = sourceItems.filter(item => item.billsID === bills.ID);
 | 
	
		
			
				|  |  | +        // 重新将断缺的树结构数据整理好
 | 
	
		
			
				|  |  | +        if (matchedItems.length) {
 | 
	
		
			
				|  |  | +            const parentMap = {};
 | 
	
		
			
				|  |  | +            matchedItems.forEach(item => {
 | 
	
		
			
				|  |  | +                (parentMap[item.ParentID] || (parentMap[item.ParentID] = [])).push(item);
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +            const roots = parentMap['-1'];
 | 
	
		
			
				|  |  | +            roots.forEach(root => setChildren(root, parentMap));
 | 
	
		
			
				|  |  | +            const sorted = sortChildren(roots);
 | 
	
		
			
				|  |  | +            const newItems = [];
 | 
	
		
			
				|  |  | +            getItemFromChildren(sorted, newItems);
 | 
	
		
			
				|  |  | +            resetTreeData(newItems);
 | 
	
		
			
				|  |  | +            const targetBillsID = targetCodeIDMap[bills.code];
 | 
	
		
			
				|  |  | +            if (targetBillsID) {
 | 
	
		
			
				|  |  | +                toDeleteIDList.push(targetBillsID);
 | 
	
		
			
				|  |  | +                newItems.forEach(newItem => {
 | 
	
		
			
				|  |  | +                    newItem.libID = targetGuideLibID;
 | 
	
		
			
				|  |  | +                    newItem.billsID = targetBillsID;
 | 
	
		
			
				|  |  | +                    insertBulks.push({
 | 
	
		
			
				|  |  | +                        insertOne: { document: newItem }
 | 
	
		
			
				|  |  | +                    });
 | 
	
		
			
				|  |  | +                })
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    if (toDeleteIDList.length) {
 | 
	
		
			
				|  |  | +        await billsGuideItemsModel.remove({ libID: targetGuideLibID, billsID: { $in : toDeleteIDList } });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (insertBulks.length) {
 | 
	
		
			
				|  |  | +        await billsGuideItemsModel.bulkWrite(insertBulks);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  async function getCompilationList() {
 | 
	
		
			
				|  |  |      let compilationModel = new CompilationModel();
 | 
	
		
			
				|  |  |      return await compilationModel.getCompilationList();
 |