stage_pos.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author Mai
  6. * @date
  7. * @version
  8. */
  9. const measureType = require('../const/tender').measureType;
  10. module.exports = app => {
  11. class StagePos extends app.BaseService {
  12. /**
  13. * 构造函数
  14. *
  15. * @param {Object} ctx - egg全局变量
  16. * @return {void}
  17. */
  18. constructor(ctx) {
  19. super(ctx);
  20. this.tableName = 'stage_pos';
  21. }
  22. /**
  23. * 查询期计量最后审核人数据
  24. * @param {Number} tid - 标段id
  25. * @param {Number} sid - 期id
  26. * @param {Number|Array} pid - 部位明细id(可以为空)
  27. * @returns {Promise<*>}
  28. */
  29. async getLastestStageData(tid, sid, pid) {
  30. let pidSql = pid ? (' And Pos.pid in (' + (pid instanceof Array ? pid.join(', ') : pid) + ')') : '';
  31. const sql = 'SELECT * FROM ' + this.tableName + ' As Pos ' +
  32. ' INNER JOIN ( ' +
  33. ' SELECT MAX(`times`) As `times`, MAX(`order`) As `order`, `pid` From ' + this.tableName +
  34. ' GROUP BY `pid`' +
  35. ' ) As MaxFilter ' +
  36. ' ON Pos.times = MaxFilter.times And Pos.order = MaxFilter.order And Pos.pid = MaxFilter.pid' +
  37. ' WHERE Pos.tid = ? And Pos.sid = ?' + pidSql;
  38. const sqlParam = [tid, sid];
  39. if (!pid) {
  40. return await this.db.query(sql, sqlParam);
  41. } else if (pid instanceof Array) {
  42. return await this.db.query(sql, sqlParam);
  43. } else {
  44. return await this.db.queryOne(sql, sqlParam);
  45. }
  46. }
  47. /**
  48. * 查询 某期 某轮审批 某审核人数据
  49. * @param {Number} tid - 标段id
  50. * @param {Number} sid - 期id
  51. * @param {Number} times - 期第几轮审批
  52. * @param {Number} order - 审核人顺序
  53. * @param {Number|Array|Null} pid - 部位明细id - 为空则查询全部
  54. * @returns {Promise<*>}
  55. */
  56. async getAuditorStageData(tid, sid, times, order, pid) {
  57. let pidSql = pid ? (' And Pos.pid in (' + (pid instanceof Array ? pid.join(', ') : pid) + ')') : '';
  58. const sql = 'SELECT * FROM ' + this.tableName + ' As Pos ' +
  59. ' INNER JOIN ( ' +
  60. ' SELECT MAX(`times`) As `times`, MAX(`order`) As `order`, `pid` From ' + this.tableName +
  61. ' WHERE `times` <= ? AND `order` <= ?' +
  62. ' GROUP BY `pid`' +
  63. ' ) As MaxFilter ' +
  64. ' ON Pos.times = MaxFilter.times And Pos.order = MaxFilter.order And Pos.pid = MaxFilter.pid' +
  65. ' WHERE Pos.tid = ? And Pos.sid = ?' + pidSql;
  66. const sqlParam = [times, order, tid, sid];
  67. if (!pid) {
  68. return await this.db.query(sql, sqlParam);
  69. } else if (pid instanceof Array) {
  70. return await this.db.query(sql, sqlParam);
  71. } else {
  72. return await this.db.queryOne(sql, sqlParam);
  73. }
  74. }
  75. /**
  76. * 新增部位明细数据(仅供updateStageData调用)
  77. *
  78. * @param transaction - 事务
  79. * @param data - 新增数据
  80. * @returns {Promise<{}>}
  81. * @private
  82. */
  83. async _addStagePosData(transaction, data) {
  84. const result = {};
  85. // 在主表pos中新增数据
  86. const p = JSON.parse(JSON.stringify(data.updateData));
  87. p.tid = this.ctx.tender.id;
  88. p.add_stage = this.ctx.stage.id;
  89. p.add_times = this.ctx.stage.times;
  90. p.add_user = this.ctx.session.sessionUser.accountId;
  91. if (p.contract_qty) { delete p.contract_qty; }
  92. if (p.qc_qty) { delete p.qc_qty; }
  93. if (p.postil) { delete p.postil; }
  94. const addRst = await transaction.insert(this.ctx.service.pos.tableName, data.updateData);
  95. p.id = addRst.insertId;
  96. result.pos = p.id;
  97. // 如果存在复核数据,更新计算主表清单
  98. if (p.quantity) {
  99. await this.ctx.service.ledger.calc(this.ctx.tender.id, p.lid, transaction);
  100. result.ledger = p.lid;
  101. }
  102. // 如果存在本期计算数据,更新计算清单本期计量数据
  103. if (data.contract_qty || data.qc_qty || data.postil) {
  104. const ps = {
  105. pid: p.id,
  106. lid: p.lid,
  107. tid: this.ctx.tender.id,
  108. sid: this.ctx.stage.id,
  109. said: this.ctx.session.sessionUser.accountId,
  110. times: this.ctx.stage.times,
  111. order: 0,
  112. };
  113. if (data.contract_qty) { ps.contract_qty = data.contract_qty; }
  114. if (data.qc_qty) { ps.qc_qty = data.qc_qty; }
  115. if (data.postil) { ps.postil = data.postil; }
  116. await transaction.insert(ps);
  117. await this.ctx.service.stageBills.calc(ctx.tender.id, ctx.stage.id, ps.lid, transaction);
  118. result.stageUpdate = true;
  119. }
  120. return result;
  121. }
  122. /**
  123. * 更新部位明细数据(仅供updateStageData调用)
  124. *
  125. * @param transaction - 事务
  126. * @param data - 更新数据(允许一次性提交多条)
  127. * @returns {Promise<{ledger: Array, pos: Array}>}
  128. * @private
  129. */
  130. async _updateStagePosData(transaction, data) {
  131. const result = {ledger: [], pos: [], stageUpdate: true};
  132. const datas = data instanceof Array ? data : [data];
  133. const orgStagePos = await this.getLastestStageData(this.ctx.tender.id, this.ctx.stage.id, this._.map(datas, 'pid'));
  134. const userOrder = this.ctx.stage.curAuditor ? this.ctx.stage.curAuditor.order : 0;
  135. for (const d of datas) {
  136. const osp = this._.find(orgStagePos, function (p) { return p.pid === d.pid; });
  137. if (osp && osp.times === this.ctx.stage.times && osp.order === userOrder) {
  138. await transaction.update(this.tableName, d, {where: {id: osp.id}});
  139. } else {
  140. console.log(osp);
  141. d.tid = this.ctx.tender.id;
  142. d.sid = this.ctx.stage.id;
  143. d.said = this.ctx.session.sessionUser.accountId;
  144. d.times = this.ctx.stage.times;
  145. d.order = userOrder;
  146. await transaction.insert(this.tableName, d);
  147. }
  148. result.pos.push(d.pid);
  149. if ((d.contract_qty === undefined || d.qc_qty === undefined) && (result.ledger.indexOf(d.lid) === -1)) {
  150. result.ledger.push(d.lid);
  151. }
  152. }
  153. for (const lid of result.ledger) {
  154. await this.ctx.service.stageBills.calc(this.ctx.tender.id, this.ctx.stage.id, lid, transaction);
  155. }
  156. return result;
  157. }
  158. /**
  159. * 删除部位明细数据(仅供updateStageData调用)
  160. *
  161. * @param transaction - 事务
  162. * @param data - 删除的部位明细(允许一次提醒多条,也允许跨清单(但前端操作不允许))
  163. * @returns {Promise<{}>}
  164. * @private
  165. */
  166. async _deleteStagePosData(transaction, data) {
  167. const result = {};
  168. const pos = await this.ctx.service.pos.getPosData({tid: this.ctx.tender.id, id: data});
  169. if (pos instanceof Array) {
  170. for (const p of pos) {
  171. if (p.add_stage !== this.ctx.stage.id || p.add_times !== this.ctx.stage.times || p.add_user !== this.ctx.session.sessionUser.accountId) {
  172. throw '您无权删除该数据';
  173. }
  174. }
  175. } else if (pos.add_stage !== this.ctx.stage.id || pos.add_times !== this.ctx.stage.times || pos.add_user !== this.ctx.session.sessionUser.accountId) {
  176. throw '您无权删除该数据';
  177. }
  178. const ledgerIds = this._.map(pos, 'lid');
  179. // 删除部位明细
  180. await transaction.delete(this.ctx.service.pos.tableName, {tid: this.ctx.tender.id, id: data});
  181. for (const lid of ledgerIds) {
  182. await this.ctx.service.ledger.calc(tid, lid, transaction);
  183. }
  184. // 删除部位明细计量数据
  185. await transaction.delete(this.tableName, {tid: this.ctx.tender.id, lid: data});
  186. for (const lid of ledgerIds) {
  187. await this.ctx.service.stageBills.calc(this.ctx.tender.id, this.ctx.stage.id, lid, transaction);
  188. }
  189. // 获取需要更新的数据
  190. result.ledger = ledgerIds;
  191. result.stageUpdate = true;
  192. return result;
  193. }
  194. /**
  195. * 根据前端提交数据,更新并计算
  196. *
  197. * @param data
  198. * @returns {Promise<{ledger: {}, pos: {}}>}
  199. */
  200. async updateStageData(data) {
  201. let refreshData;
  202. const transaction = await this.db.beginTransaction();
  203. try {
  204. if ((data.updateType === 'add' || data.upateType === 'delete') && this.ctx.tender.measure_type === measureType.tz) {
  205. throw '台账模式下,不可在计量中新增或删除部位明细,如需操作,请进行台账修订';
  206. }
  207. if (data.updateType === 'add') {
  208. refreshData = await this._addStagePosData(transaction, data.updateData);
  209. } else if (data.updateType === 'update') {
  210. refreshData = await this._updateStagePosData(transaction, data.updateData);
  211. console.log(refreshData);
  212. } else if (data.updateType === 'delete') {
  213. if (!data.updateData || data.updateData.length === 0) {
  214. throw '提交数据错误';
  215. }
  216. refreshData = await this._deleteStagePosData(transaction, data.updateData);
  217. } else {
  218. throw '提交数据错误';
  219. }
  220. await transaction.commit();
  221. } catch (err) {
  222. await transaction.rollback();
  223. throw err;
  224. }
  225. try {
  226. const result = {ledger: {}, pos: {}};
  227. if (refreshData.ledger && refreshData.ledger.length > 0) {
  228. result.ledger.bills = await this.ctx.service.ledger.getDataByIds(refreshData.ledger);
  229. if (refreshData.stageUpdate) {
  230. result.ledger.curStageData = await await this.ctx.service.stageBills.getLastestStageData(this.ctx.tender.id, this.ctx.stage.id, refreshData.ledger);
  231. }
  232. }
  233. if (refreshData.pos && refreshData.pos.length > 0) {
  234. result.pos.pos = await this.ctx.service.pos.getPosData({id: refreshData.pos});
  235. if (refreshData.stageUpdate) {
  236. result.pos.curStageData = await this.getLastestStageData(this.ctx.tender.id, this.ctx.stage.id, refreshData.pos);
  237. }
  238. }
  239. return result;
  240. } catch(err) {
  241. throw '获取数据异常,请刷新页面。';
  242. }
  243. }
  244. /**
  245. * 统计清单下部位明细合计
  246. * @param {Number} tid - 标段id
  247. * @param {Number} sid - 期id
  248. * @param {Number} lid - 清单节点id
  249. * @param transaction - 事务(不为空则在事务中查询,反之在数据库中查询)
  250. * @returns {Promise<*>}
  251. */
  252. async getPosGather(tid, sid, lid, transaction) {
  253. const calcQtySql = 'SELECT SUM(`contract_qty`) As `contract_qty`, SUM(`qc_qty`) As `qc_qty` FROM (' +
  254. ' SELECT `contract_qty`, `qc_qty` FROM ' + this.ctx.service.stagePos.tableName + ' As Pos ' +
  255. ' INNER JOIN (' +
  256. ' SELECT MAX(`times`) As `times`, MAX(`order`) As `order`, `pid` ' +
  257. ' FROM ' + this.ctx.service.stagePos.tableName +
  258. ' WHERE `tid` = ? And sid = ? And `lid` = ? ' +
  259. ' GROUP BY `pid`' +
  260. ' ) As MaxFilter ' +
  261. ' ON Pos.times = MaxFilter.times And Pos.order = MaxFilter.order And Pos.pid = MaxFilter.pid ' +
  262. ' WHERE Pos.tid = ? And Pos.sid = ? And Pos.lid = ?' +
  263. ' ) As Gather';
  264. const param = [tid, sid, lid];
  265. const sqlParam = param.concat(param);
  266. if (transaction) {
  267. return await transaction.queryOne(calcQtySql, sqlParam);
  268. } else {
  269. return await this.db.queryOne(calcQtySql, sqlParam);
  270. }
  271. }
  272. }
  273. return StagePos;
  274. };