|
@@ -7,6 +7,7 @@
|
|
|
const BaseService = require('../base/base_service');
|
|
|
const contractConst = require('../const/contract');
|
|
|
const rootId = -1;
|
|
|
+const billsUtils = require('../lib/bills_utils');
|
|
|
|
|
|
module.exports = app => {
|
|
|
|
|
@@ -1036,6 +1037,180 @@ module.exports = app => {
|
|
|
|
|
|
return data;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加节点,并同步添加父节点
|
|
|
+ * @param {Number} tenderId - 标段id
|
|
|
+ * @param {Number} selectId - 选中节点id
|
|
|
+ * @param {Object} stdData - 节点数据
|
|
|
+ * @param {StandardLib} stdLib - 标准库
|
|
|
+ * @return {Promise<void>}
|
|
|
+ */
|
|
|
+ async addStdNodeWithParent(options, kid, stdData, stdLib) {
|
|
|
+ if (!options[this.setting.type]) throw '参数有误';
|
|
|
+ const select = kid ? await this.getDataByKid(options, kid) : null;
|
|
|
+ if (!select) throw '新增子节点数据错误';
|
|
|
+ if (select && select.c_code) throw '合同无法新增子节点';
|
|
|
+ // 查询完整标准清单,并按层次排序
|
|
|
+ const fullLevel = await stdLib.getFullLevelDataByFullPath(stdData.list_id, stdData.full_path);
|
|
|
+ fullLevel.sort(function(x, y) {
|
|
|
+ return x.level - y.level;
|
|
|
+ });
|
|
|
+
|
|
|
+ let isNew = false,
|
|
|
+ node,
|
|
|
+ firstNew,
|
|
|
+ updateParent,
|
|
|
+ addResult;
|
|
|
+ const expandIds = [];
|
|
|
+ this.transaction = await this.db.beginTransaction();
|
|
|
+ try {
|
|
|
+ // 从最顶层节点依次查询是否存在,否则添加
|
|
|
+ for (let i = 0, len = fullLevel.length; i < len; i++) {
|
|
|
+ const stdNode = fullLevel[i];
|
|
|
+
|
|
|
+ if (isNew) {
|
|
|
+ const newData = {
|
|
|
+ name: stdNode.name,
|
|
|
+ unit: stdNode.unit,
|
|
|
+ };
|
|
|
+ newData.code = stdNode.code ? stdNode.code : '';
|
|
|
+ newData.is_leaf = (i === len - 1) ? 1 : 0;
|
|
|
+ [addResult, node] = await this._addChildNodeData(options, node, newData);
|
|
|
+ } else {
|
|
|
+ const parent = node;
|
|
|
+ const condition = this._.cloneDeep(options);
|
|
|
+ condition.code = stdNode.code;
|
|
|
+ condition.name = stdNode.name;
|
|
|
+ node = await this.getDataByCondition(condition);
|
|
|
+ if (!node) {
|
|
|
+ // let children = await this.getChildrenByParentId(options, parent[this.setting.pid]);
|
|
|
+ // if (children.length === 0) {
|
|
|
+ // throw '原台账节点为子项时不能添加它的子项';
|
|
|
+ // }
|
|
|
+ isNew = true;
|
|
|
+ const newData = {
|
|
|
+ name: stdNode.name,
|
|
|
+ unit: stdNode.unit,
|
|
|
+ };
|
|
|
+ newData.code = stdNode.code ? stdNode.code : '';
|
|
|
+ newData.is_leaf = (i === len - 1) ? 1 : 0;
|
|
|
+ [addResult, node] = await this._addChildAutoOrder(options, parent, newData);
|
|
|
+ if (parent && parent.is_leaf) {
|
|
|
+ await this.transaction.update(this.tableName, { id: parent.id, is_leaf: 0 });
|
|
|
+ updateParent = parent;
|
|
|
+ }
|
|
|
+ firstNew = node;
|
|
|
+ } else {
|
|
|
+ expandIds.push(node[this.setting.pid]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ await this.transaction.commit();
|
|
|
+ } catch (err) {
|
|
|
+ await this.transaction.rollback();
|
|
|
+ throw err;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询应返回的结果
|
|
|
+ let createData = [],
|
|
|
+ updateData = [];
|
|
|
+ if (firstNew) {
|
|
|
+ createData = await this.getDataByFullPath(options, firstNew[this.setting.fullPath] + '%');
|
|
|
+ updateData = await this.getNextsData(options, firstNew[this.setting.pid], firstNew[this.setting.order]);
|
|
|
+ if (updateParent) {
|
|
|
+ updateData.push(await this.getDataByCondition({ id: updateParent.id }));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return { create: createData, update: updateData };
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据 父节点id 获取子节点
|
|
|
+ * @param tenderId
|
|
|
+ * @param nodeId
|
|
|
+ * @return {Promise<*>}
|
|
|
+ */
|
|
|
+ async getChildrenByParentId(options, pid) {
|
|
|
+ const sql = 'SELECT * FROM ?? WHERE ' + this.ctx.helper._getOptionsSql(options) + ' AND ' + this.setting.pid + ' = ? ORDER BY `order` ASC';
|
|
|
+ const sqlParam = [this.tableName, pid];
|
|
|
+ const data = await this.db.query(sql, sqlParam);
|
|
|
+
|
|
|
+ const sql1 = 'SELECT * FROM ?? WHERE ' + this.ctx.helper._getOptionsSql(options) + ' AND ' + this.setting.pid + ' = ? ORDER BY `order` ASC';
|
|
|
+ const sqlParam1 = [this.ctx.service.contract.tableName, pid];
|
|
|
+ const data1 = await this.db.query(sql1, sqlParam1);
|
|
|
+ // data和data1合并且按order排序
|
|
|
+ const resultData = data.concat(data1).sort((a, b) => a.order - b.order);
|
|
|
+ return resultData;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据parentData, data新增数据(新增为parentData的最后一个子项)
|
|
|
+ * @param {Number} tenderId - 标段id
|
|
|
+ * @param {Object} parentData - 父项数据
|
|
|
+ * @param {Object} data - 新增节点,初始数据
|
|
|
+ * @return {Promise<*>} - 新增结果
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ async _addChildNodeData(options, parentData, data) {
|
|
|
+ if (!data) {
|
|
|
+ data = {};
|
|
|
+ }
|
|
|
+ const pid = parentData ? parentData[this.setting.kid] : rootId;
|
|
|
+
|
|
|
+ const maxId = await this._getMaxLid(options);
|
|
|
+ data.id = this.uuid.v4();
|
|
|
+ data[this.setting.spid] = options.spid || null;
|
|
|
+ data[this.setting.pid] = pid;
|
|
|
+ data[this.setting.kid] = maxId + 1;
|
|
|
+ data[this.setting.type] = options[this.setting.type];
|
|
|
+ data[this.setting.mid] = options.tid || null;
|
|
|
+ data[this.setting.level] = parentData ? parentData[this.setting.level] + 1 : 1;
|
|
|
+ if (data[this.setting.order] === undefined) {
|
|
|
+ data[this.setting.order] = 1;
|
|
|
+ }
|
|
|
+ data.full_path = parentData ? parentData.full_path + '-' + data[this.setting.kid] : '' + data[this.setting.kid];
|
|
|
+ if (data[this.setting.isLeaf] === undefined) {
|
|
|
+ data[this.setting.isLeaf] = true;
|
|
|
+ }
|
|
|
+ const result = await this.transaction.insert(this.tableName, data);
|
|
|
+
|
|
|
+ this._cacheMaxLid(options, maxId + 1);
|
|
|
+
|
|
|
+ return [result, data];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据parentData, data新增数据(自动排序)
|
|
|
+ * @param tenderId
|
|
|
+ * @param parentData
|
|
|
+ * @param data
|
|
|
+ * @return {Promise<void>}
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ async _addChildAutoOrder(options, parentData, data) {
|
|
|
+ const self = this;
|
|
|
+ const findPreData = function(list, a) {
|
|
|
+ if (!list || list.length === 0) { return null; }
|
|
|
+ for (let i = 0, iLen = list.length; i < iLen; i++) {
|
|
|
+ if (billsUtils.compareCode(list[i].code, a.code) > 0) {
|
|
|
+ return i > 0 ? list[i - 1] : null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return list[list.length - 1];
|
|
|
+ };
|
|
|
+
|
|
|
+ const pid = parentData ? parentData[this.setting.kid] : rootId;
|
|
|
+ const children = await this.getChildrenByParentId(options, pid);
|
|
|
+ const preData = findPreData(children, data);
|
|
|
+ if (!preData || children.indexOf(preData) < children.length - 1) {
|
|
|
+ await this._updateChildrenOrder(options, pid, preData ? preData.order + 1 : 1);
|
|
|
+ }
|
|
|
+ data.order = preData ? preData.order + 1 : 1;
|
|
|
+ const [addResult, node] = await this._addChildNodeData(options, parentData, data);
|
|
|
+
|
|
|
+ return [addResult, node];
|
|
|
+ }
|
|
|
}
|
|
|
return ContractTree;
|
|
|
};
|