'use strict'; /** * * * @author Zhong * @date 2018/6/1 * @version */ const mongoose = require('mongoose'); const billsGuideLibModel = mongoose.model('std_billsGuidance_lib'); const billsGuideItemsModel = mongoose.model('std_billsGuidance_items'); const stdBillsLibModel = mongoose.model('std_bills_lib_list'); const stdBillsModel = mongoose.model('std_bills_lib_bills'); const stdRationModel = mongoose.model('std_ration_lib_ration_items'); const _ = require('lodash'); module.exports = { getLibWithBills, getItemsBybills, getItemsByCode, }; async function getBillsGuideLibs(findData) { return await billsGuideLibModel.find(findData); } async function getLibWithBills(libID, isGuidanceLib){ let billsLibId = libID; if (isGuidanceLib) { const guidanceLib = await getBillsGuideLibs({ID: libID}); if(guidanceLib.length === 0){ throw '不存在此指引库!'; } const billsLib = await stdBillsLibModel.findOne({billsLibId: guidanceLib[0].billsLibId}); if(!billsLib){ throw '引用的清单规则库不存在!'; } billsLibId = billsLib.billsLibId; } const bills = await stdBillsModel.find({ billsLibId }, '-_id').lean(); return { bills }; } function getAttrs(field, datas){ let rst = []; for(let data of datas){ if(data[field]){ rst.push(data[field]); } } return rst; } //定额项目指所引用定额是否被删除 function rationAllExist(rationItems, stdRationIdx) { for(let item of rationItems){ if(!stdRationIdx[item.rationID]){ return false; } } return true; } //将同层树结构转为顺序数组 function chainToArr(nodes){ let rst = []; let tempIdx = {}; let nodeIdx = {}; //建索引 for(let node of nodes){ tempIdx[node.ID] = {ID: node.ID, NextSiblingID: node.NextSiblingID, preSibling: null, nextSibling: null}; nodeIdx[node.ID] = node; } //建链 for(let i in tempIdx){ let temp = tempIdx[i]; if(temp.NextSiblingID != -1){ let next = tempIdx[temp.NextSiblingID]; temp.nextSibling = next; next.preSibling = temp; } } let firstNode = null; for(let i in tempIdx){ if(!tempIdx[i].preSibling){ firstNode = tempIdx[i]; break; } } //获得顺序队列 while(firstNode){ rst.push(nodeIdx[firstNode.ID]); firstNode = firstNode.nextSibling; } return rst; } async function getItemsBybills(guidanceLibID, billsID){ const type = {job: 0, ration: 1}; let items = await billsGuideItemsModel.find({libID: guidanceLibID, billsID: billsID, deleted: false}); let rationItems = _.filter(items, {type: type.ration}); let rationIds = getAttrs('rationID', rationItems); let stdRations = await stdRationModel.find({ID: {$in: rationIds}, $or: [{isDeleted: null}, {isDeleted: false}]}); let stdRationIndex = {}; for(let stdRation of stdRations){ stdRationIndex[stdRation.ID] = stdRation; } //判断定额完整性 if(!rationAllExist(rationItems, stdRationIndex)){ //建定额链, 排序后再清除不存在的定额,保证顺序正确性 rationItems = chainToArr(rationItems); //清除已被删除的定额 let removeIds = []; _.remove(rationItems, function (item) { if(!stdRationIndex[item.rationID]){ removeIds.push(item.ID); return true; } return false; }); _.remove(items, function (item) { return removeIds.includes(item.ID); }); await billsGuideItemsModel.remove({ID: {$in: removeIds}}); //重组树结构 let bulkArr = []; for(let i = 0, len = rationItems.length; i < len; i++){ rationItems[i].NextSiblingID = rationItems[i + 1] ? rationItems[i + 1].ID : -1; bulkArr.push({updateOne: {filter: {ID: rationItems[i].ID}, update: {$set: {NextSiblingID: rationItems[i].NextSiblingID}}}}); } await billsGuideItemsModel.bulkWrite(bulkArr); } return items; } async function getItemsByCode(guidanceLibID, code){ let rst = []; let guidanceLib = await billsGuideLibModel.findOne({ID: guidanceLibID}); if (!guidanceLib) { return rst; } let stdBills = await stdBillsModel.findOne({code: code, billsLibId: guidanceLib.billsLibId}).lean(); if (!stdBills) { return rst; } let items = await getItemsBybills(guidanceLibID, stdBills.ID); return items; }