sub_proj_progress.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author Mai
  6. * @date
  7. * @version
  8. */
  9. const readOnlyFields = ['id', 'spid', 'tree_id', 'tree_pid', 'tree_order', 'tree_level', 'tree_full_path', 'tree_is_leaf'];
  10. const defaultData = [
  11. { code: '1', name: '前期阶段', tree_id: 1, tree_pid: -1, tree_level: 1, tree_order: 1, tree_full_path: '1', tree_is_leaf: 1 },
  12. { code: '2', name: '实施阶段', tree_id: 2, tree_pid: -1, tree_level: 1, tree_order: 2, tree_full_path: '2', tree_is_leaf: 1 },
  13. { code: '3', name: '竣(交)工阶段', tree_id: 3, tree_pid: -1, tree_level: 1, tree_order: 3, tree_full_path: '3', tree_is_leaf: 1 },
  14. ];
  15. const billsUtils = require('../lib/bills_utils');
  16. module.exports = app => {
  17. class SubProjProgress extends app.BaseTreeService {
  18. /**
  19. * 构造函数
  20. *
  21. * @param {Object} ctx - egg全局变量
  22. * @param {String} tableName - 表名
  23. * @return {void}
  24. */
  25. constructor(ctx) {
  26. super(ctx, {
  27. mid: 'spid',
  28. kid: 'tree_id',
  29. pid: 'tree_pid',
  30. order: 'tree_order',
  31. level: 'tree_level',
  32. isLeaf: 'tree_is_leaf',
  33. fullPath: 'tree_full_path',
  34. cacheKey: false,
  35. uuid: true,
  36. });
  37. this.tableName = 'sub_project_progress';
  38. }
  39. _getDefaultData(data, spid) {
  40. data.id = this.uuid.v4();
  41. data.spid = spid;
  42. data.add_user_id = this.ctx.session.sessionUser.accountId;
  43. data.update_user_id = this.ctx.session.sessionUser.accountId;
  44. }
  45. async init(subProj) {
  46. if (!subProj) throw '阶段进度数据错误';
  47. const budgetStd = subProj.std_id ? await this.ctx.service.budgetStd.getDataById(subProj.std_id) : null;
  48. const template_id = budgetStd ? budgetStd.progress_template_id.split(',')[0] : '';
  49. const insertData = [];
  50. if (template_id) {
  51. const templateData = await this.ctx.service.tenderNodeTemplate.getData(template_id);
  52. for (const tmp of templateData) {
  53. const bills = {
  54. code: tmp.code || '',
  55. name: tmp.name || '',
  56. tree_id: tmp.template_id,
  57. tree_pid: tmp.pid,
  58. tree_level: tmp.level,
  59. tree_order: tmp.order,
  60. tree_full_path: tmp.full_path,
  61. tree_is_leaf: tmp.is_leaf,
  62. };
  63. this._getDefaultData(bills, subProj.id);
  64. insertData.push(bills);
  65. }
  66. } else {
  67. for (const b of defaultData) {
  68. const bills = JSON.parse(JSON.stringify(b));
  69. this._getDefaultData(bills, subProj.id);
  70. insertData.push(bills);
  71. }
  72. }
  73. const operate = await this.db.insert(this.tableName, insertData);
  74. return operate.affectedRows === insertData.length;
  75. }
  76. async getData(subProj) {
  77. let result = await this.getAllDataByCondition({ where: { spid: subProj.id } });
  78. if (result.length === 0) {
  79. await this.init(subProj);
  80. result = await this.getAllDataByCondition({ where: { spid: subProj.id } });
  81. }
  82. return result;
  83. }
  84. async addStdNode(subProj, targetId, stdData) {
  85. const findPreData = function(list, a) {
  86. if (!list || list.length === 0) { return null; }
  87. for (let i = 0, iLen = list.length; i < iLen; i++) {
  88. if (billsUtils.compareCode(list[i].code, a.code) > 0) {
  89. return i > 0 ? list[i - 1] : null;
  90. }
  91. }
  92. return list[list.length - 1];
  93. };
  94. let parent = await this.getDataByKid(subProj.id, targetId);
  95. if (targetId && !parent) throw '新增节点数据错误,请刷新页面重试';
  96. const orgParentId = parent.id;
  97. let children = await this.getChildrenByParentId(subProj.id, targetId);
  98. const updateParent = children.length === 0;
  99. const insertData = [];
  100. const maxId = await this._getMaxLid(subProj.id);
  101. this.transaction = await this.db.beginTransaction();
  102. try {
  103. if (updateParent) {
  104. const updateData = { id: parent.id };
  105. updateData[this.setting.isLeaf] = false;
  106. this.clearParentingData(updateData);
  107. await this.transaction.update(this.tableName, updateData);
  108. }
  109. // 从最顶层节点依次查询是否存在,否则添加
  110. const addStdData = stdData[stdData.length - 1];
  111. const newData = { code: addStdData.code, name: addStdData.name };
  112. newData[this.setting.kid] = maxId + 1;
  113. newData[this.setting.pid] = parent ? parent[this.setting.kid] : this.rootId;
  114. newData[this.setting.level] = parent ? parent[this.setting.level] + 1 : 1;
  115. newData[this.setting.fullPath] = parent ? `${parent[this.setting.fullPath]}-${newData[this.setting.kid]}` : `${newData[this.setting.kid]}`;
  116. const pre = findPreData(children, newData);
  117. newData[this.setting.order] = pre ? pre[this.setting.order] + 1 : 1;
  118. if (!pre || children.indexOf(pre) < children.length - 1) {
  119. await this._updateChildrenOrder(subProj.id, parent ? parent[this.setting.kid] : this.rootId, pre ? pre[this.setting.order] + 1 : 1);
  120. }
  121. newData[this.setting.isLeaf] = 1;
  122. this._getDefaultData(newData, subProj.id);
  123. insertData.push(newData);
  124. await this.transaction.insert(this.tableName, insertData);
  125. await this.transaction.commit();
  126. } catch (err) {
  127. await this.transaction.rollback();
  128. throw err;
  129. }
  130. this._cacheMaxLid(subProj.id, maxId + stdData.length);
  131. // 查询应返回的结果
  132. const createData = await this.getDataByFullPath(subProj.id, insertData[0][this.setting.fullPath] + '%');
  133. const updateData = await this.getNextsData(subProj.id, targetId, insertData[0][this.setting.order]);
  134. if (updateParent) {
  135. updateData.push(await this.getDataByKid(subProj.id, targetId));
  136. }
  137. return { create: createData, update: updateData };
  138. }
  139. async addStdNodeWithParent(subProj, targetId, stdData) {
  140. const findPreData = function(list, a) {
  141. if (!list || list.length === 0) { return null; }
  142. for (let i = 0, iLen = list.length; i < iLen; i++) {
  143. if (billsUtils.compareCode(list[i].code, a.code) > 0) {
  144. return i > 0 ? list[i - 1] : null;
  145. }
  146. }
  147. return list[list.length - 1];
  148. };
  149. let parent = await this.getDataByKid(subProj.id, targetId);
  150. if (targetId && !parent) throw '新增节点数据错误,请刷新页面重试';
  151. const orgParentId = parent.id;
  152. let children = await this.getChildrenByParentId(subProj.id, targetId);
  153. const updateParent = children.length === 0;
  154. const insertData = [];
  155. const maxId = await this._getMaxLid(subProj.id);
  156. this.transaction = await this.db.beginTransaction();
  157. try {
  158. if (updateParent) {
  159. const updateData = { id: parent.id };
  160. updateData[this.setting.isLeaf] = false;
  161. this.clearParentingData(updateData);
  162. await this.transaction.update(this.tableName, updateData);
  163. }
  164. // 从最顶层节点依次查询是否存在,否则添加
  165. for (let i = 0, len = stdData.length; i < len; i++) {
  166. const newData = { code: stdData[i].code, name: stdData[i].name };
  167. newData[this.setting.kid] = maxId + i + 1;
  168. newData[this.setting.pid] = parent ? parent[this.setting.kid] : this.rootId;
  169. newData[this.setting.level] = parent ? parent[this.setting.level] + 1 : 1;
  170. newData[this.setting.fullPath] = parent ? `${parent[this.setting.fullPath]}-${newData[this.setting.kid]}` : `${newData[this.setting.kid]}`;
  171. const pre = findPreData(children, newData);
  172. newData[this.setting.order] = pre ? pre[this.setting.order] + 1 : 1;
  173. if (!pre || children.indexOf(pre) < children.length - 1) {
  174. await this._updateChildrenOrder(subProj.id, parent ? parent[this.setting.kid] : this.rootId, pre ? pre[this.setting.order] + 1 : 1);
  175. }
  176. newData[this.setting.isLeaf] = (i === len - 1);
  177. this._getDefaultData(newData, subProj.id);
  178. insertData.push(newData);
  179. parent = newData;
  180. children = [];
  181. }
  182. await this.transaction.insert(this.tableName, insertData);
  183. await this.transaction.commit();
  184. } catch (err) {
  185. await this.transaction.rollback();
  186. throw err;
  187. }
  188. this._cacheMaxLid(subProj.id, maxId + stdData.length);
  189. // 查询应返回的结果
  190. const createData = await this.getDataByFullPath(subProj.id, insertData[0][this.setting.fullPath] + '%');
  191. const updateData = await this.getNextsData(subProj.id, targetId, insertData[0][this.setting.order]);
  192. if (updateParent) {
  193. updateData.push(await this.getDataByKid(subProj.id, targetId));
  194. }
  195. return { create: createData, update: updateData };
  196. }
  197. async addChild(spid, select, count) {
  198. const maxId = await this._getMaxLid(spid);
  199. const children = await this.getChildrenByParentId(spid, select[this.setting.kid]);
  200. const newDatas = [];
  201. for (let i = 1; i < count + 1; i++) {
  202. const newData = {};
  203. newData[this.setting.kid] = maxId + i;
  204. newData[this.setting.pid] = select[this.setting.kid];
  205. newData[this.setting.level] = select[this.setting.level] + 1;
  206. newData[this.setting.order] = children.length + i;
  207. newData[this.setting.fullPath] = select[this.setting.fullPath] + '-' + newData[this.setting.kid];
  208. newData[this.setting.isLeaf] = true;
  209. this._getDefaultData(newData, spid);
  210. newDatas.push(newData);
  211. }
  212. this.transaction = await this.db.beginTransaction();
  213. try {
  214. const result = await this.transaction.insert(this.tableName, newDatas);
  215. if (children.length === 0) await this.transaction.update(this.tableName, { id: select.id, tree_is_leaf: 0 });
  216. await this.transaction.commit();
  217. } catch(err) {
  218. this.transaction.rollback();
  219. throw err;
  220. }
  221. // 查询应返回的结果
  222. const resultData = {};
  223. resultData.create = await this.getNextsData(spid, select[this.setting.kid], children.length);
  224. if (children.length === 0) resultData.update = await this.getDataByKid(spid, select[this.setting.kid]);
  225. return resultData;
  226. }
  227. async addNextSibling(spid, select, count) {
  228. const maxId = await this._getMaxLid(spid);
  229. const newDatas = [];
  230. for (let i = 1; i < count + 1; i++) {
  231. const newData = {};
  232. newData[this.setting.kid] = maxId + i;
  233. newData[this.setting.pid] = select ? select[this.setting.pid] : this.rootId;
  234. newData[this.setting.level] = select ? select[this.setting.level] : 1;
  235. newData[this.setting.order] = select ? select[this.setting.order] + i : i;
  236. newData[this.setting.fullPath] = newData[this.setting.level] > 1
  237. ? select[this.setting.fullPath].replace('-' + select[this.setting.kid], '-' + newData[this.setting.kid])
  238. : newData[this.setting.kid] + '';
  239. newData[this.setting.isLeaf] = true;
  240. this._getDefaultData(newData, spid);
  241. newDatas.push(newData);
  242. }
  243. this.transaction = await this.db.beginTransaction();
  244. try {
  245. if (select) await this._updateChildrenOrder(spid, select[this.setting.pid], select[this.setting.order] + 1, count);
  246. const insertResult = await this.transaction.insert(this.tableName, newDatas);
  247. if (insertResult.affectedRows !== count) throw '新增节点数据错误';
  248. await this.transaction.commit();
  249. } catch (err) {
  250. await this.transaction.rollback();
  251. this.transaction = null;
  252. throw err;
  253. }
  254. if (select) {
  255. const createData = await this.getChildBetween(spid, select[this.setting.pid], select[this.setting.order], select[this.setting.order] + count + 1);
  256. const updateData = await this.getNextsData(spid, select[this.setting.pid], select[this.setting.order] + count);
  257. return {create: createData, update: updateData};
  258. } else {
  259. const createData = await this.getChildBetween(spid, -1, 0, count + 1);
  260. return {create: createData};
  261. }
  262. }
  263. async addProgressNode(spid, targetId, count) {
  264. if (!spid) return null;
  265. const select = targetId ? await this.getDataByKid(spid, targetId) : null;
  266. if (targetId && !select) throw '新增节点数据错误';
  267. if (select[this.setting.level] === 1) {
  268. return await this.addChild(spid, select, count);
  269. } else {
  270. return await this.addNextSibling(spid, select, count);
  271. }
  272. }
  273. async _deleteRelaData(spid, deleteData) {
  274. if (!this.transaction) throw '删除相关数据错误';
  275. await this.transaction.update(this.ctx.service.subProjFile.tableName, {is_deleted: 1},
  276. { where: { spid, type: 'progress', rela_id: deleteData.map(x => { return x.id; })} });
  277. }
  278. async updateInfos(spid, data) {
  279. if (!spid) throw '数据错误';
  280. const datas = Array.isArray(data) ? data : [data];
  281. const orgDatas = await this.getAllDataByCondition({ where: { id: datas.map(x => { return x.id; })} });
  282. const updateDatas = [];
  283. for (const d of datas) {
  284. const node = orgDatas.find(x => { return x.id === d.id; });
  285. if (!node || node.spid !== spid) throw '提交数据错误';
  286. d.update_user_id = this.ctx.session.sessionUser.accountId;
  287. updateDatas.push(this._filterUpdateInvalidField(node.id, d));
  288. }
  289. await this.db.updateRows(this.tableName, updateDatas);
  290. const resultData = await this.getDataById(this._.map(datas, 'id'));
  291. return { update: resultData };
  292. }
  293. }
  294. return SubProjProgress;
  295. }