|
@@ -24,6 +24,7 @@ const keyFields = {
|
|
|
const readOnlyFields = ['id', 'tender_id', 'ledger_id', 'ledger_pid', 'order', 'level', 'full_path', 'is_leaf'];
|
|
|
const calcFields = ['quantity', 'unit_price', 'total_price'];
|
|
|
const zeroRange = 0.0000000001;
|
|
|
+const rootId = -1;
|
|
|
|
|
|
module.exports = app => {
|
|
|
|
|
@@ -40,15 +41,24 @@ module.exports = app => {
|
|
|
this.tableName = 'ledger';
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 新增数据(供内部或其他service类调用, controller不可直接使用)
|
|
|
+ * @param {Array|Object} data - 新增数据
|
|
|
+ * @param {Number} tenderId - 标段id
|
|
|
+ * @param {Object} transaction - 新增事务
|
|
|
+ * @returns {Promise<boolean>} - {Promise<是否正确新增成功>}
|
|
|
+ */
|
|
|
async innerAdd(data, tenderId, transaction) {
|
|
|
const datas = data instanceof Array ? data : [data];
|
|
|
if (tenderId <= 0) {
|
|
|
throw '标段id错误';
|
|
|
}
|
|
|
- // 数组则为批量插入
|
|
|
if (datas.length <= 0) {
|
|
|
throw '插入数据为空';
|
|
|
}
|
|
|
+ if (!transaction) {
|
|
|
+ throw '内部错误';
|
|
|
+ }
|
|
|
// 整理数据
|
|
|
const insertData = [];
|
|
|
for (const tmp of datas) {
|
|
@@ -62,7 +72,6 @@ module.exports = app => {
|
|
|
const operate = await transaction.insert(this.tableName, insertData);
|
|
|
return operate.affectedRows === datas.length;
|
|
|
}
|
|
|
-
|
|
|
/**
|
|
|
* 新增数据
|
|
|
*
|
|
@@ -190,6 +199,29 @@ module.exports = app => {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * 根据标准清单源检索
|
|
|
+ * @param tenderId
|
|
|
+ * @param source
|
|
|
+ * @returns {Promise<*>}
|
|
|
+ */
|
|
|
+ async getDataBySource(tenderId, source) {
|
|
|
+ this.initSqlBuilder();
|
|
|
+ this.sqlBuilder.setAndWhere('tender_id', {
|
|
|
+ value: tenderId,
|
|
|
+ operate: '=',
|
|
|
+ });
|
|
|
+ this.sqlBuilder.setAndWhere('source', {
|
|
|
+ value: source,
|
|
|
+ operate: '=',
|
|
|
+ });
|
|
|
+
|
|
|
+ const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
|
|
|
+ const data = await this.db.query(sql, sqlParam);
|
|
|
+
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* 获取最末的子节点
|
|
|
* @param {Number} tenderId - 标段id
|
|
|
* @param {Number} pid - 父节点id
|
|
@@ -262,9 +294,13 @@ module.exports = app => {
|
|
|
* @return {Promise<*>}
|
|
|
*/
|
|
|
async getChildrenByParentId(tenderId, nodeId) {
|
|
|
- if ((nodeId <= 0) || (tenderId <= 0)) {
|
|
|
+ if (tenderId <= 0 || !nodeId) {
|
|
|
return undefined;
|
|
|
}
|
|
|
+ const nodeIds = nodeId instanceof Array ? nodeId : [nodeId];
|
|
|
+ if (nodeIds.length === 0) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
|
|
|
this.initSqlBuilder();
|
|
|
this.sqlBuilder.setAndWhere('tender_id', {
|
|
@@ -272,9 +308,10 @@ module.exports = app => {
|
|
|
operate: '=',
|
|
|
});
|
|
|
this.sqlBuilder.setAndWhere('ledger_pid', {
|
|
|
- value: nodeId,
|
|
|
- operate: '=',
|
|
|
+ value: nodeIds,
|
|
|
+ operate: 'in',
|
|
|
});
|
|
|
+ this.sqlBuilder.orderBy = [['order', 'ASC']];
|
|
|
|
|
|
const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
|
|
|
const data = await this.db.query(sql, sqlParam);
|
|
@@ -289,7 +326,7 @@ module.exports = app => {
|
|
|
* @return {Array}
|
|
|
*/
|
|
|
async getNextsData(tenderId, pid, order) {
|
|
|
- if ((tenderId <= 0) || (pid <= 0) || (order < 0)) {
|
|
|
+ if ((tenderId <= 0) || (order < 0)) {
|
|
|
return undefined;
|
|
|
}
|
|
|
|
|
@@ -383,37 +420,48 @@ module.exports = app => {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * select的全部后兄弟节点,Order自增
|
|
|
- *
|
|
|
- * @param {Object} select - 选中的节点
|
|
|
- * @param {Number} incre - 自增值
|
|
|
- * @return {Array} - 自增后的数据
|
|
|
+ * 更新order
|
|
|
+ * @param {Number} tenderId - 标段id
|
|
|
+ * @param {Number} parentId - 父节点id
|
|
|
+ * @param {Number} order - 自增起始order(含)
|
|
|
+ * @param {Number} incre - 自增量
|
|
|
+ * @returns {Promise<*>}
|
|
|
* @private
|
|
|
*/
|
|
|
- async _updateSelectNextsOrder(select, incre = 1) {
|
|
|
+ async _updateChildrenOrderAfter(tenderId, parentId, order, incre = 1) {
|
|
|
this.initSqlBuilder();
|
|
|
this.sqlBuilder.setAndWhere('tender_id', {
|
|
|
- value: select.tender_id,
|
|
|
- operate: '=',
|
|
|
+ value: tenderId,
|
|
|
+ operate: '='
|
|
|
});
|
|
|
this.sqlBuilder.setAndWhere('order', {
|
|
|
- value: select.order + 1,
|
|
|
+ value: order,
|
|
|
operate: '>=',
|
|
|
});
|
|
|
this.sqlBuilder.setAndWhere('ledger_pid', {
|
|
|
- value: select.ledger_pid,
|
|
|
+ value: parentId,
|
|
|
operate: '=',
|
|
|
});
|
|
|
this.sqlBuilder.setUpdateData('order', {
|
|
|
value: Math.abs(incre),
|
|
|
selfOperate: incre > 0 ? '+' : '-',
|
|
|
});
|
|
|
- // sql = update this.tableName set order = order + 1 where (tender_id = select.tender_id) && (pid = select.pid) && (order >= select.order+1)
|
|
|
const [sql, sqlParam] = this.sqlBuilder.build(this.tableName, 'update');
|
|
|
const data = await this.transaction.query(sql, sqlParam);
|
|
|
|
|
|
return data;
|
|
|
}
|
|
|
+ /**
|
|
|
+ * select的全部后兄弟节点,Order自增
|
|
|
+ *
|
|
|
+ * @param {Object} select - 选中的节点
|
|
|
+ * @param {Number} incre - 自增值
|
|
|
+ * @return {Array} - 自增后的数据
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ async _updateSelectNextsOrder(select, incre = 1) {
|
|
|
+ return await this._updateChildrenOrderAfter(select.tender_id, select.ledger_pid, select.order + 1, incre);
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* 从数据库获取标段的最大节点id
|
|
@@ -430,7 +478,7 @@ module.exports = app => {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 根据selectData, data 新增数据
|
|
|
+ * 根据selectData, data 新增数据(新增为selectData的后项,该方法不可单独使用)
|
|
|
*
|
|
|
* @param {Number} tenderId - 标段id
|
|
|
* @param {Object} selectData - 选中节点的数据
|
|
@@ -457,7 +505,7 @@ module.exports = app => {
|
|
|
data.ledger_pid = selectData.ledger_pid;
|
|
|
data.level = selectData.level;
|
|
|
data.order = selectData.order + 1;
|
|
|
- data.full_path = selectData.full_path.replace(selectData.ledger_id, data.ledger_id);
|
|
|
+ data.full_path = selectData.full_path.replace('.' + selectData.ledger_id, '.' + data.ledger_id);
|
|
|
data.is_leaf = true;
|
|
|
const result = await this.transaction.insert(this.tableName, data);
|
|
|
|
|
@@ -465,6 +513,79 @@ module.exports = app => {
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
+ /**
|
|
|
+ * 根据parentData, data新增数据(新增为parentData的最后一个子项)
|
|
|
+ * @param {Number} tenderId - 标段id
|
|
|
+ * @param {Object} parentData - 父项数据
|
|
|
+ * @param {Object} data - 新增节点,初始数据
|
|
|
+ * @returns {Promise<*>} - 新增结果
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ async _addChildNodeData(tenderId, parentData, data) {
|
|
|
+ if (tenderId <= 0) {
|
|
|
+ return undefined;
|
|
|
+ }
|
|
|
+ if (!data) {
|
|
|
+ data = {};
|
|
|
+ }
|
|
|
+ const pid = parentData ? parentData.ledger_id : rootId;
|
|
|
+
|
|
|
+ const cacheKey = 'tender_node_maxId: ' + tenderId;
|
|
|
+ let maxId = parseInt(await this.cache.get(cacheKey));
|
|
|
+ if (!maxId) {
|
|
|
+ maxId = await this._getMaxNodeId(tenderId);
|
|
|
+ this.cache.set(cacheKey, maxId, 'EX', this.ctx.app.config.cacheTime);
|
|
|
+ }
|
|
|
+
|
|
|
+ data.tender_id = tenderId;
|
|
|
+ data.ledger_id = maxId + 1;
|
|
|
+ data.ledger_pid = pid;
|
|
|
+ if (data.order === undefined) {
|
|
|
+ data.order = 1;
|
|
|
+ }
|
|
|
+ data.level = parentData ? parentData.level + 1 : 1;
|
|
|
+ data.full_path = parentData ? parentData.full_path + '.' + data.ledger_id : '' + data.ledger_id;
|
|
|
+ if (data.is_leaf === undefined) {
|
|
|
+ data.is_leaf = true;
|
|
|
+ }
|
|
|
+ const result = await this.transaction.insert(this.tableName, data);
|
|
|
+
|
|
|
+ this.cache.set(cacheKey, maxId + 1, 'EX', this.ctx.app.config.cacheTime);
|
|
|
+ return [result, data];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据parentData, data新增数据(自动排序)
|
|
|
+ * @param tenderId
|
|
|
+ * @param parentData
|
|
|
+ * @param data
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ async _addChildAutoOrder(tenderId, 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 (self.ctx.helper.compareCode(list[i].code, a.code) > 0) {
|
|
|
+ return i > 0 ? list[i-1] : null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return list[list.length -1];
|
|
|
+ }
|
|
|
+
|
|
|
+ const pid = parentData ? parentData.ledger_id : rootId;
|
|
|
+ const children = await this.getChildrenByParentId(tenderId, pid);
|
|
|
+ const preData = findPreData(children, data);
|
|
|
+ let parent = null;
|
|
|
+ if (!preData || children.indexOf(preData) < children.length - 1) {
|
|
|
+ await this._updateChildrenOrderAfter(tenderId, pid, preData ? preData.order + 1 : 1);
|
|
|
+ }
|
|
|
+ data.order = preData ? preData.order + 1 : 1;
|
|
|
+ const [addResult, node] = await this._addChildNodeData(tenderId, parentData, data);
|
|
|
+
|
|
|
+ return [addResult, node];
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* tenderId标段中, 在selectId后新增一个节点
|
|
@@ -482,19 +603,23 @@ module.exports = app => {
|
|
|
if (!selectData) {
|
|
|
throw '新增节点数据错误';
|
|
|
}
|
|
|
- this.transaction = await this.db.beginTransaction();
|
|
|
-
|
|
|
+ if (!this.transaction) {
|
|
|
+ this.transaction = await this.db.beginTransaction();
|
|
|
+ }
|
|
|
|
|
|
try {
|
|
|
// 选中节点的所有后兄弟节点,order+1
|
|
|
await this._updateSelectNextsOrder(selectData);
|
|
|
// 数据库创建新增节点数据
|
|
|
- await this._addNodeData(tenderId, selectData, data);
|
|
|
+ const newNode = await this._addNodeData(tenderId, selectData, data);
|
|
|
+ if (!newNode) { throw '新增节点数据错误'; }
|
|
|
await this.transaction.commit();
|
|
|
} catch (err) {
|
|
|
await this.transaction.rollback();
|
|
|
+ this.transaction = null;
|
|
|
throw err;
|
|
|
}
|
|
|
+ this.transaction = null;
|
|
|
|
|
|
// 查询应返回的结果
|
|
|
const createData = await this.getDataByParentAndOrder(selectData.tender_id, selectData.ledger_pid, [selectData.order + 1]);
|
|
@@ -502,6 +627,109 @@ module.exports = app => {
|
|
|
return { create: createData, update: updateData };
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 从标准数据中提取有效数据
|
|
|
+ * @param {Object} stdData - 从标准库中查询所得
|
|
|
+ * @returns {name, unit, source, code, b_code}
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ _filterStdData(stdData) {
|
|
|
+ const result = {
|
|
|
+ name: stdData.name,
|
|
|
+ unit: stdData.unit,
|
|
|
+ source: stdData.source
|
|
|
+ }
|
|
|
+ result.code = stdData.code ? stdData.code : '';
|
|
|
+ result.b_code = stdData.b_code ? stdData.b_code : '';
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加节点(来自标准清单)
|
|
|
+ * @param {Number} tenderId
|
|
|
+ * @param {Number} selectId
|
|
|
+ * @param {Object} stdData
|
|
|
+ * @returns {Promise<*>}
|
|
|
+ */
|
|
|
+ async addStdNode(tenderId, selectId, stdData) {
|
|
|
+ const newData = this.filterStdData(stdData);
|
|
|
+ const result = await this.addNode(tenderId, selectId, newData);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加节点,并同步添加父节点
|
|
|
+ * @param {Number} tenderId - 标段id
|
|
|
+ * @param {Number} selectId - 选中节点id
|
|
|
+ * @param {Object} stdData - 节点数据
|
|
|
+ * @param {StandardLib} stdLib - 标准库
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ */
|
|
|
+ async addStdNodeWithParent(tenderId, stdData, stdLib) {
|
|
|
+ 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 = this._filterStdData(stdNode);
|
|
|
+ newData.is_leaf = (i === len - 1);
|
|
|
+ [addResult, node] = await this._addChildNodeData(tenderId, node, newData);
|
|
|
+ } else {
|
|
|
+ const parent = node;
|
|
|
+ node = await this.getDataByCondition({
|
|
|
+ tender_id: tenderId,
|
|
|
+ ledger_pid: parent ? parent.ledger_id : rootId,
|
|
|
+ code: stdNode.code,
|
|
|
+ name: stdNode.name
|
|
|
+ });
|
|
|
+ if (!node) {
|
|
|
+ isNew = true;
|
|
|
+ const newData = this._filterStdData(stdNode);
|
|
|
+ newData.is_leaf = (i === len - 1);
|
|
|
+ [addResult, node] = await this._addChildAutoOrder(tenderId, parent, newData);
|
|
|
+ if (parent && parent.is_leaf) {
|
|
|
+ await this.transaction.update(this.tableName, {id: parent.id, is_leaf: false} );
|
|
|
+ updateParent = parent;
|
|
|
+ }
|
|
|
+ firstNew = node;
|
|
|
+ } else {
|
|
|
+ expandIds.push(node.ledger_id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.transaction.commit();
|
|
|
+ } catch (err) {
|
|
|
+ await this.transaction.rollback();
|
|
|
+ throw err;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询应返回的结果
|
|
|
+ let createData = [], updateData = [];
|
|
|
+ if (firstNew) {
|
|
|
+ createData = await this.getDataByFullPath(tenderId, firstNew.full_path + '%');
|
|
|
+ updateData = await this.getNextsData(tenderId, firstNew.ledger_pid, firstNew.order);
|
|
|
+ if (updateParent) {
|
|
|
+ updateData.push(await this.getDataByCondition({id: updateParent.id}));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const expandData = await this.getChildrenByParentId(tenderId, expandIds);
|
|
|
+ return { create: createData, update: updateData, expand: expandData };
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除节点
|
|
|
+ * @param {Number} tenderId - 标段id
|
|
|
+ * @param {Object} deleteData - 删除节点数据
|
|
|
+ * @returns {Promise<*>}
|
|
|
+ * @private
|
|
|
+ */
|
|
|
async _deleteNodeData(tenderId, deleteData) {
|
|
|
this.initSqlBuilder();
|
|
|
this.sqlBuilder.setAndWhere('tender_id', {
|
|
@@ -546,10 +774,7 @@ module.exports = app => {
|
|
|
if (parentData) {
|
|
|
const count = this.db.count(this.tableName, { ledger_pid: selectData.ledger_pid });
|
|
|
if (count === 1) {
|
|
|
- await this.transaction.update({
|
|
|
- id: parentData.id,
|
|
|
- is_leaf: true,
|
|
|
- });
|
|
|
+ await this.transaction.update(this.tableName, { id: parentData.id, is_leaf: true });
|
|
|
}
|
|
|
}
|
|
|
// 选中节点--全部后节点 order--
|
|
@@ -1170,6 +1395,12 @@ module.exports = app => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 提交数据 - 响应计算(增量方式计算)
|
|
|
+ * @param {Number} tenderId
|
|
|
+ * @param {Object} data
|
|
|
+ * @returns {Promise<*>}
|
|
|
+ */
|
|
|
async updateCalc(tenderId, data) {
|
|
|
const findData = function (id, datas) {
|
|
|
for (const d of datas) {
|