change_audit_list.js 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author Mai
  6. * @date 2018/8/14
  7. * @version
  8. */
  9. const audit = require('../const/audit');
  10. module.exports = app => {
  11. class ChangeAuditList extends app.BaseService {
  12. /**
  13. * 构造函数
  14. *
  15. * @param {Object} ctx - egg全局变量
  16. * @return {void}
  17. */
  18. constructor(ctx) {
  19. super(ctx);
  20. this.tableName = 'change_audit_list';
  21. }
  22. /**
  23. * 取出变更令清单列表,并按台账清单在前,空白清单在后排序
  24. * @return {void}
  25. */
  26. async getList(cid, order_by = this.ctx.change.order_by) {
  27. if (order_by) {
  28. return await this.getAllDataByCondition({ where: { cid }, orders: [['order', 'asc']] });
  29. }
  30. const sql = 'SELECT * FROM ?? WHERE `cid` = ? ORDER BY `lid` = "0", `id` asc';
  31. const sqlParam = [this.tableName, cid];
  32. return await this.db.query(sql, sqlParam);
  33. }
  34. /**
  35. * 移除清单时,同步其后清单order
  36. * @param transaction - 事务
  37. * @param {Number} cid - 变更cid
  38. * @param {Number} order - order之后的
  39. * @return {Promise<*>}
  40. * @private
  41. */
  42. async _syncOrder(transaction, cid, order, selfOperate = '-', num = 1) {
  43. this.initSqlBuilder();
  44. this.sqlBuilder.setAndWhere('cid', {
  45. value: this.db.escape(cid),
  46. operate: '=',
  47. });
  48. this.sqlBuilder.setAndWhere('order', {
  49. value: order,
  50. operate: '>=',
  51. });
  52. this.sqlBuilder.setUpdateData('order', {
  53. value: num,
  54. selfOperate,
  55. });
  56. const [sql, sqlParam] = this.sqlBuilder.build(this.tableName, 'update');
  57. const data = await transaction.query(sql, sqlParam);
  58. return data;
  59. }
  60. /**
  61. * 添加空白变更清单
  62. * @return {void}
  63. */
  64. async add(data) {
  65. if (!this.ctx.tender || !this.ctx.change) {
  66. throw '数据错误';
  67. }
  68. const transaction = await this.db.beginTransaction();
  69. try {
  70. let order = null;
  71. if (this.ctx.change.order_by) {
  72. if (data) {
  73. order = parseInt(data) + 1;
  74. // order以下的清单+1
  75. await this._syncOrder(transaction, this.ctx.change.cid, order, '+');
  76. } else {
  77. order = await this.count({ cid: this.ctx.change.cid });
  78. order = order ? order + 1 : 1;
  79. }
  80. }
  81. const insertData = {
  82. tid: this.ctx.tender.id,
  83. cid: this.ctx.change.cid,
  84. lid: '0',
  85. code: '',
  86. name: '',
  87. bwmx: '',
  88. unit: '',
  89. unit_price: null,
  90. oamount: 0,
  91. camount: 0,
  92. samount: '',
  93. detail: '',
  94. spamount: 0,
  95. xmj_code: null,
  96. xmj_jldy: null,
  97. xmj_dwgc: null,
  98. xmj_fbgc: null,
  99. xmj_fxgc: null,
  100. gcl_id: '',
  101. order,
  102. };
  103. // 新增工料
  104. const result = await transaction.insert(this.tableName, insertData);
  105. if (result.affectedRows === 0) {
  106. throw '新增空白清单数据失败';
  107. }
  108. await transaction.commit();
  109. return await this.getDataById(result.insertId);
  110. } catch (err) {
  111. await transaction.rollback();
  112. throw err;
  113. }
  114. }
  115. /**
  116. * 批量添加空白变更清单
  117. * @return {void}
  118. */
  119. async batchAdd(data) {
  120. if (!this.ctx.tender || !this.ctx.change) {
  121. throw '数据错误';
  122. }
  123. const transaction = await this.db.beginTransaction();
  124. try {
  125. const num = data.num ? parseInt(data.num) : 0;
  126. if (num < 1 || num > 100) {
  127. throw '批量添加的空白清单数目不能小于1或大于100';
  128. }
  129. let order = null;
  130. if (this.ctx.change.order_by) {
  131. if (data) {
  132. order = parseInt(data.postData) + 1;
  133. // order以下的清单+1
  134. await this._syncOrder(transaction, this.ctx.change.cid, order, '+', num);
  135. } else {
  136. order = await this.count({ cid: this.ctx.change.cid });
  137. order = order ? order + 1 : 1;
  138. }
  139. }
  140. const insertArray = [];
  141. for (let i = 0; i < num; i++) {
  142. const insertData = {
  143. tid: this.ctx.tender.id,
  144. cid: this.ctx.change.cid,
  145. lid: '0',
  146. code: '',
  147. name: '',
  148. bwmx: '',
  149. unit: '',
  150. unit_price: null,
  151. oamount: 0,
  152. camount: 0,
  153. samount: '',
  154. detail: '',
  155. spamount: 0,
  156. xmj_code: null,
  157. xmj_jldy: null,
  158. xmj_dwgc: null,
  159. xmj_fbgc: null,
  160. xmj_fxgc: null,
  161. gcl_id: '',
  162. order: order ? order + i : null,
  163. };
  164. insertArray.push(insertData);
  165. }
  166. // 新增工料
  167. const result = await transaction.insert(this.tableName, insertArray);
  168. if (result.affectedRows !== num) {
  169. throw '批量添加空白清单数据失败';
  170. }
  171. await transaction.commit();
  172. // // 获取刚批量添加的所有list
  173. // for (let j = 0; j < num; j++) {
  174. // insertArray[j].id = result.insertId + j;
  175. // }
  176. // return insertArray;
  177. return await this.getList(this.ctx.change.cid);
  178. } catch (err) {
  179. await transaction.rollback();
  180. throw err;
  181. }
  182. }
  183. /**
  184. * 删除变更清单
  185. * @param {int} id 清单id
  186. * @return {void}
  187. */
  188. async del(data) {
  189. if (!this.ctx.tender || !this.ctx.change) {
  190. throw '数据错误';
  191. }
  192. const transaction = await this.db.beginTransaction();
  193. try {
  194. // 判断是否可删
  195. await transaction.delete(this.tableName, { id: data.ids });
  196. // // order以下的清单-1
  197. if (this.ctx.change.order_by) {
  198. await this._syncOrder(transaction, this.ctx.change.cid, data.postData, '-', data.ids.length);
  199. }
  200. // 重新算变更令总额
  201. await this.calcCamountSum(transaction);
  202. await transaction.commit();
  203. return true;
  204. } catch (err) {
  205. await transaction.rollback();
  206. throw err;
  207. }
  208. }
  209. /**
  210. * 修改变更清单
  211. * @param {Object} data 工料内容
  212. * @param {int} order 期数
  213. * @return {void}
  214. */
  215. async save(data, order) {
  216. if (!this.ctx.tender || !this.ctx.change) {
  217. throw '数据错误';
  218. }
  219. const transaction = await this.db.beginTransaction();
  220. try {
  221. // const mb_id = data.mb_id;
  222. // delete data.mb_id;
  223. await transaction.update(this.tableName, data);
  224. // await this.calcQuantityByML(transaction, mb_id);
  225. await this.calcCamountSum(transaction);
  226. await transaction.commit();
  227. return true;
  228. } catch (err) {
  229. await transaction.rollback();
  230. throw err;
  231. }
  232. }
  233. /**
  234. * 修改变更清单 复制粘贴
  235. * @param {Object} datas 修改内容
  236. * @return {void}
  237. */
  238. async saveDatas(datas) {
  239. if (!this.ctx.tender || !this.ctx.change) {
  240. throw '数据错误';
  241. }
  242. // 判断是否可修改
  243. // 判断t_type是否为费用
  244. const transaction = await this.db.beginTransaction();
  245. try {
  246. // for (const data of datas) {
  247. // const mb_id = data.mb_id;
  248. // delete data.mb_id;
  249. // await transaction.update(this.tableName, data);
  250. // await this.calcQuantityByML(transaction, mb_id);
  251. // }
  252. await transaction.updateRows(this.tableName, datas);
  253. await this.calcCamountSum(transaction);
  254. await transaction.commit();
  255. return true;
  256. } catch (err) {
  257. await transaction.rollback();
  258. throw err;
  259. }
  260. }
  261. /**
  262. * 台账数据清单 重新选择
  263. * @param {Object} datas 内容
  264. * @return {void}
  265. */
  266. async saveLedgerListDatas(datas, data = null, order_by = this.ctx.change.order_by) {
  267. if (!this.ctx.tender || !this.ctx.change) {
  268. throw '数据错误';
  269. }
  270. // 判断是否可修改
  271. // 判断t_type是否为费用
  272. const transaction = await this.db.beginTransaction();
  273. try {
  274. let usedList = [];
  275. let order = null;
  276. if (order_by) {
  277. if (data) {
  278. order = parseInt(data) + 1;
  279. // order以下的清单+1
  280. await this._syncOrder(transaction, this.ctx.change.cid, order, '+', datas.length);
  281. } else {
  282. order = await this.count({ cid: this.ctx.change.cid });
  283. order = order ? order + 1 : 1;
  284. }
  285. } else {
  286. const sql1 = 'SELECT a.* FROM ?? as b LEFT JOIN ?? as a ON b.cbid = a.id WHERE b.cid = ? GROUP BY b.cbid';
  287. const sqlParam1 = [this.ctx.service.stageChange.tableName, this.tableName, this.ctx.change.cid];
  288. usedList = await transaction.query(sql1, sqlParam1);
  289. // 先删除原本的台账清单数据
  290. const sql = 'DELETE FROM ?? WHERE cid = ? and lid != "0"';
  291. const sqlParam = [this.tableName, this.ctx.change.cid];
  292. await transaction.query(sql, sqlParam);
  293. }
  294. const insertDatas = [];
  295. for (const data of datas) {
  296. data.tid = this.ctx.tender.id;
  297. data.cid = this.ctx.change.cid;
  298. data.spamount = data.camount;
  299. data.samount = '';
  300. data.order = order ? order : null;
  301. order = order ? order + 1 : null;
  302. insertDatas.push(data);
  303. }
  304. if (insertDatas.length > 0) await transaction.insert(this.tableName, insertDatas);
  305. await this.calcCamountSum(transaction);
  306. if (!order_by) {
  307. // 更新stage_change和stage_change_final的cbid
  308. if (usedList.length > 0) {
  309. const updateList = [];
  310. const sql2 = 'SELECT * FROM ?? WHERE `cid` = ? AND `lid` != "0"';
  311. const sqlParam2 = [this.tableName, this.ctx.change.cid];
  312. const newList = await transaction.query(sql2, sqlParam2);
  313. // const newList = await transaction.select(this.tableName, { where: { cid: this.ctx.change.cid } });
  314. for (const used of usedList) {
  315. const newone = this._.find(newList, { code: used.code, lid: used.lid, gcl_id: used.gcl_id, bwmx: used.bwmx });
  316. if (newone) {
  317. updateList.push({
  318. row: {
  319. cbid: newone.id,
  320. },
  321. where: {
  322. cid: this.ctx.change.cid,
  323. cbid: used.id,
  324. },
  325. });
  326. }
  327. }
  328. if (updateList.length > 0) {
  329. await transaction.updateRows(this.ctx.service.stageChange.tableName, updateList);
  330. await transaction.updateRows(this.ctx.service.stageChangeFinal.tableName, updateList);
  331. }
  332. }
  333. }
  334. await transaction.commit();
  335. return true;
  336. } catch (err) {
  337. await transaction.rollback();
  338. throw err;
  339. }
  340. }
  341. /**
  342. * 台账数据清单 清除部分并重新算原设计总金额
  343. * @param {Object} datas 内容
  344. * @return {void}
  345. */
  346. async removeLedgerListDatas(datas) {
  347. if (!this.ctx.tender || !this.ctx.change) {
  348. throw '数据错误';
  349. }
  350. // 判断是否可修改
  351. // 判断t_type是否为费用
  352. const transaction = await this.db.beginTransaction();
  353. try {
  354. // 先删除原本的台账清单数据
  355. // const sql = 'DELETE FROM ?? WHERE cid = ? and lid != "0"';
  356. // const sqlParam = [this.tableName, this.ctx.change.cid];
  357. // await transaction.query(sql, sqlParam);
  358. // const insertDatas = [];
  359. for (const data of datas) {
  360. // data.tid = this.ctx.tender.id;
  361. // data.cid = this.ctx.change.cid;
  362. // data.spamount = data.camount;
  363. // data.samount = '';
  364. // insertDatas.push(data);
  365. await transaction.delete(this.tableName, { id: data.id });
  366. }
  367. // if (insertDatas.length > 0) await transaction.insert(this.tableName, insertDatas);
  368. await this.calcCamountSum(transaction);
  369. await transaction.commit();
  370. return true;
  371. } catch (err) {
  372. await transaction.rollback();
  373. throw err;
  374. }
  375. }
  376. async calcCamountSum(transaction, updateTpDecimal = false) {
  377. // const sql = 'SELECT SUM(ROUND(`camount`*`unit_price`, )) as total_price FROM ?? WHERE cid = ?';
  378. // const sqlParam = [this.tableName, this.change.cid];
  379. // const tp = await transaction.queryOne(sql, sqlParam);
  380. // 防止小数位不精确,采用取值计算
  381. const sql = 'SELECT unit_price, spamount FROM ?? WHERE cid = ?';
  382. const sqlParam = [this.tableName, this.ctx.change.cid];
  383. const changeList = await transaction.query(sql, sqlParam);
  384. let total_price = 0;
  385. const tp_decimal = this.ctx.change.tp_decimal ? this.ctx.change.tp_decimal : this.ctx.tender.info.decimal.tp;
  386. for (const cl of changeList) {
  387. total_price = this.ctx.helper.accAdd(total_price, this.ctx.helper.mul(cl.unit_price, cl.spamount, tp_decimal));
  388. }
  389. const updateData = {
  390. total_price,
  391. };
  392. if (updateTpDecimal) {
  393. updateData.tp_decimal = tp_decimal;
  394. }
  395. const options = {
  396. where: {
  397. cid: this.ctx.change.cid,
  398. },
  399. };
  400. await transaction.update(this.ctx.service.change.tableName, updateData, options);
  401. }
  402. /**
  403. * 用户数据数量提交
  404. * @param {Object} data 内容
  405. * @return {void}
  406. */
  407. async saveAmountData(data) {
  408. if (!this.ctx.tender || !this.ctx.change) {
  409. throw '数据错误';
  410. }
  411. // 判断是否可修改
  412. // 判断t_type是否为费用
  413. const transaction = await this.db.beginTransaction();
  414. try {
  415. await transaction.update(this.tableName, data);
  416. await this.calcCamountSum(transaction);
  417. await transaction.commit();
  418. return true;
  419. } catch (err) {
  420. await transaction.rollback();
  421. throw err;
  422. }
  423. }
  424. async gatherBgBills(tid) {
  425. const sql = 'SELECT cb.code, cb.name, cb.unit, cb.unit_price, Round(Sum(cb.samount + 0), 6) as quantity' +
  426. ' FROM ' + this.tableName + ' cb' +
  427. ' LEFT JOIN ' + this.ctx.service.change.tableName + ' c ON cb.cid = c.cid' +
  428. ' WHERE cb.tid = ? and c.status = ?' +
  429. ' GROUP BY code, name, unit, unit_price';
  430. const param = [tid, audit.flow.status.checked];
  431. const result = await this.db.query(sql, param);
  432. for (const b of result) {
  433. b.total_price = this.ctx.helper.mul(b.unit_price, b.quantity, this.ctx.tender.info.decimal.tp);
  434. }
  435. return result;
  436. }
  437. /**
  438. * 报表用
  439. * Tony Kang
  440. * @param {tid} tid - 标段id
  441. * @return {void}
  442. */
  443. async getChangeAuditBills(tid, onlyChecked) {
  444. const sql = 'SELECT cb.*' +
  445. ' FROM ' + this.tableName + ' cb' +
  446. ' LEFT JOIN ' + this.ctx.service.change.tableName + ' c ON cb.cid = c.cid' +
  447. ' WHERE c.tid = ? ' + (onlyChecked ? 'and c.status = 3' : '') +
  448. ' ORDER BY cb.cid, cb.code';
  449. const param = [tid];
  450. const result = await this.db.query(sql, param);
  451. return result;
  452. }
  453. /**
  454. * 删除变更清单(form 变更新增部位页)
  455. * Tony Kang
  456. * @param {String} transaction - 队列
  457. * @param {String} tid - 标段id
  458. * @param {Array} ids - id列表
  459. * @param {String} column - id所属字段
  460. * @param {String} mx_id - mx_id为空列删除
  461. * @return {void}
  462. */
  463. async deleteDataByRevise(transaction, tid, ids, column = 'gcl_id', mx_id = 'hello') {
  464. if (ids.length > 0) {
  465. const addSql = mx_id === '' ? ' AND (`mx_id` is NULL OR `mx_id` = "")' : '';
  466. const sql = 'SELECT `cid` FROM ?? WHERE `tid` = ? AND ' + column + ' in (' + this.ctx.helper.getInArrStrSqlFilter(ids) + ')' + addSql + ' GROUP BY `cid`';
  467. const params = [this.tableName, tid];
  468. const changes = await transaction.query(sql, params);
  469. if (changes.length > 0) {
  470. const delData = {
  471. tid,
  472. };
  473. delData[column] = ids;
  474. await transaction.delete(this.tableName, delData);
  475. for (const c of changes) {
  476. // 重算选了此清单的变更令已变更金额
  477. await this.reCalcTp(transaction, c.cid);
  478. }
  479. }
  480. }
  481. }
  482. /**
  483. * 修改变更清单(form 变更新增部位页台账子节点清单编号编辑)
  484. * Tony Kang
  485. * @param {String} transaction - 队列
  486. * @param {String} tid - 标段id
  487. * @param {Array} datas - 更新列表
  488. * @param {String} column - id所属字段
  489. * @return {void}
  490. */
  491. async updateDataByReviseLedger(transaction, tid, datas, column = 'gcl_id') {
  492. if (datas.length > 0) {
  493. const ids = this._.map(datas, 'id');
  494. const sql = 'SELECT ' + column + ' FROM ?? WHERE `tid` = ? AND ' + column + ' in (' + this.ctx.helper.getInArrStrSqlFilter(ids) + ') GROUP BY ' + column;
  495. const params = [this.tableName, tid];
  496. const changeAuditLists = await transaction.query(sql, params);
  497. if (changeAuditLists.length > 0) {
  498. const updateArr = [];
  499. const cidList = [];
  500. for (const ca of changeAuditLists) {
  501. const d = this._.find(datas, { id: ca[column] });
  502. if (d.id) {
  503. const changePosNum = await transaction.count(this.ctx.service.changePos.tableName, { lid: d.id });
  504. const updateCol = {};
  505. if (column === 'gcl_id' && d.b_code) updateCol.code = d.b_code;
  506. if (column === 'gcl_id' && d.quantity !== undefined && changePosNum === 0) updateCol.oamount = d.quantity ? d.quantity : 0;
  507. if (column === 'gcl_id' && d.unit_price !== undefined) updateCol.unit_price = d.unit_price ? d.unit_price : 0;
  508. if (column === 'gcl_id' && d.unit !== undefined) updateCol.unit = d.unit;
  509. if (column === 'gcl_id' && d.name !== undefined) updateCol.name = d.name;
  510. if (d.b_code !== undefined && d.b_code === null) {
  511. // 清单升级成了项目节,故删除变更已有的此清单,并找出需要重新计算的变更令
  512. const sql = 'SELECT `cid` FROM ?? WHERE `tid` = ? AND ' + column + ' = ? GROUP BY `cid`';
  513. const params = [this.tableName, tid, d.id];
  514. const changes = await transaction.query(sql, params);
  515. for (const c of changes) {
  516. if (this._.indexOf(cidList, c.cid) === -1) {
  517. cidList.push(c.cid);
  518. }
  519. }
  520. const delData = {
  521. tid,
  522. };
  523. delData[column] = d.id;
  524. await transaction.delete(this.tableName, delData);
  525. } else {
  526. const options = {
  527. row: {},
  528. where: {},
  529. };
  530. options.row = updateCol;
  531. options.where[column] = d.id;
  532. if (!this._.isEmpty(options.row)) updateArr.push(options);
  533. if (updateCol.unit !== undefined || updateCol.unit_price !== undefined) {
  534. const sql = 'SELECT `cid` FROM ?? WHERE `tid` = ? AND ' + column + ' = ? GROUP BY `cid`';
  535. const params = [this.tableName, tid, d.id];
  536. const changes = await transaction.query(sql, params);
  537. for (const c of changes) {
  538. if (this._.indexOf(cidList, c.cid) === -1) {
  539. cidList.push(c.cid);
  540. }
  541. }
  542. }
  543. }
  544. }
  545. }
  546. if (updateArr.length > 0) await transaction.updateRows(this.tableName, updateArr);
  547. if (cidList.length > 0) {
  548. for (const c of cidList) {
  549. await this.reCalcTp(transaction, c);
  550. }
  551. }
  552. }
  553. // 针对项目节更新可能对清单影响判断,修正变更清单项目节编号,细目,单位工程,分部分项工程数据
  554. for (const data of datas) {
  555. const select = await transaction.get(this.ctx.service.changeLedger.tableName, { id: data.id });
  556. if (select && select.is_leaf === 0) {
  557. const lists = await this.ctx.service.changeLedger.getDataByFullPath(this.ctx.service.changeLedger.tableName, tid, select.full_path + '%', transaction);
  558. const childLists = this._.filter(lists, { level: select.level + 1 }); // 细目or项目节编号更新
  559. if (childLists.length > 0) {
  560. const d = { xmj_code: '', xmj_jldy: '' };
  561. if (select.code !== null) {
  562. d.xmj_code = select.code;
  563. d.xmj_jldy = select.name;
  564. } else {
  565. // 再找出上一个项目节节点并更新
  566. this.newBills = false;
  567. const parents = await this.ctx.service.changeLedger.getDataByKid(tid, select.ledger_pid);
  568. d.xmj_code = parents.code;
  569. d.xmj_jldy = parents.name;
  570. }
  571. for (const cl of childLists) {
  572. await transaction.update(this.tableName, { xmj_code: d.xmj_code, xmj_jldy: d.xmj_jldy }, { where: { tid, gcl_id: cl.id } });
  573. }
  574. }
  575. if (select.code !== null && data.name !== undefined) { // 名称修改则可能影响几个数据
  576. const secondChildLists = this._.filter(lists, { level: select.level + 2 }); // 分项工程更新
  577. const thirdChildLists = this._.filter(lists, { level: select.level + 3 }); // 分部工程更新
  578. const fourthChildLists = this._.filter(lists, { level: select.level + 4 }); // 单位工程更新
  579. if (secondChildLists.length > 0) {
  580. for (const sl of secondChildLists) {
  581. await transaction.update(this.tableName, { xmj_fxgc: select.name }, { where: { tid, gcl_id: sl.id } });
  582. }
  583. }
  584. if (thirdChildLists.length > 0) {
  585. for (const tl of thirdChildLists) {
  586. await transaction.update(this.tableName, { xmj_fbgc: select.name }, { where: { tid, gcl_id: tl.id } });
  587. }
  588. }
  589. if (fourthChildLists.length > 0 && select.level === 2) {
  590. for (const fl of fourthChildLists) {
  591. await transaction.update(this.tableName, { xmj_dwgc: select.name }, { where: { tid, gcl_id: fl.id } });
  592. }
  593. }
  594. }
  595. }
  596. }
  597. }
  598. }
  599. /**
  600. * 修改变更清单(form 变更新增部位页台账节点清单编号升降级)
  601. * Tony Kang
  602. * @param {String} transaction - 队列
  603. * @param {String} tid - 标段id
  604. * @param {Array} datas - 更新列表
  605. * @param {String} column - id所属字段
  606. * @return {void}
  607. */
  608. async updateDataByReviseLedgerUpDownLevel(transaction, tid, datas, column = 'gcl_id') {
  609. if (datas.length > 0) {
  610. console.log(datas);
  611. // const ids = this._.map(datas, 'id');
  612. // const sql = 'SELECT ' + column + ' FROM ?? WHERE `tid` = ? AND ' + column + ' in (' + this.ctx.helper.getInArrStrSqlFilter(ids) + ') GROUP BY ' + column;
  613. // const params = [this.tableName, tid];
  614. // const changeAuditLists = await transaction.query(sql, params);
  615. // if (changeAuditLists.length > 0) {
  616. // const updateArr = [];
  617. // const cidList = [];
  618. // for (const ca of changeAuditLists) {
  619. // const d = this._.find(datas, { id: ca[column] });
  620. // console.log(d);
  621. // if (d.id) {
  622. // const changePosNum = await transaction.count(this.ctx.service.changePos.tableName, { lid: d.id });
  623. // const updateCol = {};
  624. // if (column === 'gcl_id' && d.b_code !== undefined) updateCol.code = d.b_code;
  625. // if (column === 'gcl_id' && d.sgfh_qty !== undefined && changePosNum === 0) updateCol.oamount = d.sgfh_qty ? d.sgfh_qty : 0;
  626. // if (column === 'gcl_id' && d.unit_price !== undefined) updateCol.unit_price = d.unit_price ? d.unit_price : 0;
  627. // if (column === 'gcl_id' && d.unit !== undefined) updateCol.unit = d.unit;
  628. // if (column === 'gcl_id' && d.name !== undefined) updateCol.name = d.name;
  629. // if (d.code !== undefined && d.b_code === null) {
  630. // // 清单升级成了项目节,故删除变更已有的此清单,并找出需要重新计算的变更令
  631. // const sql = 'SELECT `cid` FROM ?? WHERE `tid` = ? AND ' + column + ' = ? GROUP BY `cid`';
  632. // const params = [this.tableName, tid, d.id];
  633. // const changes = await transaction.query(sql, params);
  634. // for (const c of changes) {
  635. // if (this._.indexOf(cidList, c.cid) === -1) {
  636. // cidList.push(c.cid);
  637. // }
  638. // }
  639. // const delData = {
  640. // tid,
  641. // };
  642. // delData[column] = d.id;
  643. // console.log(delData);
  644. // await transaction.delete(this.tableName, delData);
  645. // } else {
  646. // const options = {
  647. // row: {},
  648. // where: {},
  649. // };
  650. // options.row = updateCol;
  651. // options.where[column] = d.id;
  652. // if (!this._.isEmpty(options.row)) updateArr.push(options);
  653. // if (updateCol.unit !== undefined || updateCol.unit_price !== undefined) {
  654. // const sql = 'SELECT `cid` FROM ?? WHERE `tid` = ? AND ' + column + ' = ? GROUP BY `cid`';
  655. // const params = [this.tableName, tid, d.id];
  656. // const changes = await transaction.query(sql, params);
  657. // for (const c of changes) {
  658. // if (this._.indexOf(cidList, c.cid) === -1) {
  659. // cidList.push(c.cid);
  660. // }
  661. // }
  662. // }
  663. // }
  664. // }
  665. // }
  666. // console.log(updateArr, cidList);
  667. // if (updateArr.length > 0) await transaction.updateRows(this.tableName, updateArr);
  668. // if (cidList.length > 0) {
  669. // for (const c of cidList) {
  670. // await this.reCalcTp(transaction, c);
  671. // }
  672. // }
  673. // }
  674. // 针对项目节更新可能对清单影响判断,修正变更清单项目节编号,细目,单位工程,分部分项工程数据
  675. // for (const data of datas) {
  676. // const select = await transaction.get(this.ctx.service.changeLedger.tableName, { id: data.id });
  677. // console.log(select);
  678. // if (select && select.is_leaf === 0) {
  679. // const lists = await this.ctx.service.changeLedger.getDataByFullPath(this.ctx.service.changeLedger.tableName, tid, select.full_path + '%', transaction);
  680. // const childLists = this._.filter(lists, { level: select.level + 1 }); // 细目or项目节编号更新
  681. // if (childLists.length > 0) {
  682. // const d = { xmj_code: '', xmj_jldy: '' };
  683. // if (select.code !== null) {
  684. // d.xmj_code = select.code;
  685. // d.xmj_jldy = select.name;
  686. // } else {
  687. // // 再找出上一个项目节节点并更新
  688. // this.newBills = false;
  689. // const parents = await this.ctx.service.changeLedger.getDataByKid(tid, select.ledger_pid);
  690. // console.log('hello :', parents);
  691. // d.xmj_code = parents.code;
  692. // d.xmj_jldy = parents.name;
  693. // }
  694. // for (const cl of childLists) {
  695. // await transaction.update(this.tableName, { xmj_code: d.xmj_code, xmj_jldy: d.xmj_jldy }, { where: { tid, gcl_id: cl.id } });
  696. // }
  697. // }
  698. // if (select.code !== null && data.name !== undefined) { // 名称修改则可能影响几个数据
  699. // const secondChildLists = this._.filter(lists, { level: select.level + 2 }); // 分项工程更新
  700. // const thirdChildLists = this._.filter(lists, { level: select.level + 3 }); // 分部工程更新
  701. // const fourthChildLists = this._.filter(lists, { level: select.level + 4 }); // 单位工程更新
  702. // if (secondChildLists.length > 0) {
  703. // for (const sl of secondChildLists) {
  704. // await transaction.update(this.tableName, { xmj_fxgc: select.name }, { where: { tid, gcl_id: sl.id } });
  705. // }
  706. // }
  707. // if (thirdChildLists.length > 0) {
  708. // for (const tl of thirdChildLists) {
  709. // await transaction.update(this.tableName, { xmj_fbgc: select.name }, { where: { tid, gcl_id: tl.id } });
  710. // }
  711. // }
  712. // if (fourthChildLists.length > 0) {
  713. // for (const fl of fourthChildLists) {
  714. // await transaction.update(this.tableName, { xmj_dwgc: select.name }, { where: { tid, gcl_id: fl.id } });
  715. // }
  716. // }
  717. // }
  718. // }
  719. // }
  720. }
  721. }
  722. /**
  723. * 修改变更清单(form 变更新增部位页计量单元编辑)
  724. * Tony Kang
  725. * @param {String} transaction - 队列
  726. * @param {String} tid - 标段id
  727. * @param {Array} datas - 更新列表
  728. * @param {String} column - id所属字段
  729. * @return {void}
  730. */
  731. async updateDataByRevisePos(transaction, tid, datas, column = 'mx_id') {
  732. if (datas.length > 0) {
  733. const ids = this._.map(datas, 'id');
  734. const sql = 'SELECT ' + column + ' FROM ?? WHERE `tid` = ? AND ' + column + ' in (' + this.ctx.helper.getInArrStrSqlFilter(ids) + ') GROUP BY ' + column;
  735. const params = [this.tableName, tid];
  736. const changeAuditLists = await transaction.query(sql, params);
  737. if (changeAuditLists.length > 0) {
  738. const updateArr = [];
  739. for (const ca of changeAuditLists) {
  740. const d = this._.find(datas, { id: ca[column] });
  741. if (d.id) {
  742. const updateCol = {};
  743. if (column === 'mx_id' && d.name !== undefined) updateCol.bwmx = d.name;
  744. if (column === 'mx_id' && d.quantity !== undefined) updateCol.oamount = d.quantity ? d.quantity : 0;
  745. if (column === 'mx_id' && d.quantity === undefined &&
  746. ((d.sgfh_expr && d.sgfh_expr === '') || (d.sjcl_expr && d.sjcl_expr === '') || (d.qtcl_expr && d.qtcl_expr === ''))) updateCol.oamount = 0;
  747. const options = {
  748. row: {},
  749. where: {},
  750. };
  751. options.row = updateCol;
  752. options.where[column] = d.id;
  753. // if (!this._.isEmpty(updateCol)) await transaction.update(this.tableName, updateCol, options);
  754. if (!this._.isEmpty(options.row)) updateArr.push(options);
  755. }
  756. }
  757. if (updateArr.length > 0) await transaction.updateRows(this.tableName, updateArr);
  758. }
  759. }
  760. }
  761. /**
  762. * 重算变更令总金额(变更新增部位设置时使用)
  763. * @param {String} transaction - 队列
  764. * @param {String} cid - 变更令id
  765. */
  766. async reCalcTp(transaction, cid) {
  767. const change = await transaction.get(this.ctx.service.change.tableName, { cid });
  768. let count = '';
  769. if (change.status === audit.flow.status.uncheck || change.status === audit.flow.status.back || change.status === audit.flow.status.revise) {
  770. count = '`camount`';
  771. } else if (change.status === audit.flow.status.checking || change.status === audit.flow.status.backnew) {
  772. count = '`spamount`';
  773. }
  774. if (count) {
  775. const sql = 'SELECT `unit_price`, ' + count + ' as `count` FROM ?? WHERE `cid` = ?';
  776. const params = [this.tableName, change.cid];
  777. const caLists = await transaction.query(sql, params);
  778. let tp = 0;
  779. const tpUnit = change.tp_decimal ? change.tp_decimal : this.ctx.tender.info.decimal.tp;
  780. for (const ca of caLists) {
  781. const catp = this.ctx.helper.round(this.ctx.helper.mul(ca.unit_price, ca.count), tpUnit);
  782. tp = this.ctx.helper.add(tp, catp);
  783. }
  784. console.log(tp);
  785. if (tp !== change.total_price) {
  786. const options = {
  787. where: {
  788. cid: change.cid,
  789. },
  790. };
  791. const change_update = {
  792. total_price: tp,
  793. };
  794. await transaction.update(this.ctx.service.change.tableName, change_update, options);
  795. }
  796. }
  797. }
  798. async updateToLedger(transaction, tid, cid) {
  799. // 找出本条变更属于新增部位的数据
  800. const allList = await transaction.select(this.tableName, { where: { tid, cid } });
  801. const result = [];
  802. const result2 = [];
  803. for (const l of allList) {
  804. const changeLedgerInfo = await transaction.get(this.ctx.service.changeLedger.tableName, { id: l.gcl_id });
  805. if (changeLedgerInfo && this._.findIndex(result, { id: l.gcl_id }) === -1) {
  806. result.push(changeLedgerInfo);
  807. }
  808. const changePosInfo = await transaction.get(this.ctx.service.changePos.tableName, { id: l.mx_id });
  809. if (changePosInfo) {
  810. result2.push(changePosInfo);
  811. }
  812. }
  813. // const sql = 'SELECT a.* FROM ?? a LEFT JOIN ?? b ON a.id = b.gcl_id WHERE b.tid = ? AND b.cid = ? GROUP BY a.id';
  814. // const sqlParam = [this.ctx.service.changeLedger.tableName, this.tableName, tid, cid];
  815. // const result = await transaction.query(sql, sqlParam);
  816. // const sql2 = 'SELECT a.* FROM ?? a LEFT JOIN ?? b ON a.id = b.mx_id WHERE b.tid = ? AND b.cid = ?';
  817. // const sqlParam2 = [this.ctx.service.changePos.tableName, this.tableName, tid, cid];
  818. // const result2 = await transaction.query(sql2, sqlParam2);
  819. if (result.length > 0 || result2.length > 0) {
  820. const changeLedgerGclIdList = this._.map(result, 'id');
  821. const changeLedgerIdList = this._.uniq(this._.map(result, 'ledger_pid'));// 父节点集合
  822. const needUpdateLedgerList = [];// 找出需要更新的原台账清单的id
  823. const needUpdateChangeLedgerList = [];// 找出需要更新的新台账清单的id
  824. const tpDecimal = this.ctx.tender.info.decimal.tp;
  825. // 要更新的ledger节点,数量及总数
  826. for (const data of result2) {
  827. if (this._.indexOf(changeLedgerGclIdList, data.lid) === -1) {
  828. const info = this._.find(needUpdateLedgerList, { id: data.lid });
  829. if (info) {
  830. info.sgfh_qty = this.ctx.helper.add(info.sgfh_qty, data.sgfh_qty);
  831. info.sjcl_qty = this.ctx.helper.add(info.sjcl_qty, data.sjcl_qty);
  832. info.qtcl_qty = this.ctx.helper.add(info.qtcl_qty, data.qtcl_qty);
  833. info.quantity = this.ctx.helper.add(info.quantity, data.quantity);
  834. } else {
  835. needUpdateLedgerList.push({ id: data.lid, sgfh_qty: data.sgfh_qty, sjcl_qty: data.sjcl_qty, qtcl_qty: data.qtcl_qty, quantity: data.quantity });
  836. }
  837. } else {
  838. const info = this._.find(needUpdateChangeLedgerList, { id: data.lid });
  839. if (info) {
  840. info.sgfh_qty = this.ctx.helper.add(info.sgfh_qty, data.sgfh_qty);
  841. info.sjcl_qty = this.ctx.helper.add(info.sjcl_qty, data.sjcl_qty);
  842. info.qtcl_qty = this.ctx.helper.add(info.qtcl_qty, data.qtcl_qty);
  843. info.quantity = this.ctx.helper.add(info.quantity, data.quantity);
  844. } else {
  845. needUpdateChangeLedgerList.push({ id: data.lid, sgfh_qty: data.sgfh_qty, sjcl_qty: data.sjcl_qty, qtcl_qty: data.qtcl_qty, quantity: data.quantity });
  846. }
  847. }
  848. }
  849. // 更新到result上
  850. if (needUpdateChangeLedgerList.length > 0) {
  851. for (const nucl of needUpdateChangeLedgerList) {
  852. const now = this._.find(result, { id: nucl.id });
  853. now.sgfh_qty = nucl.sgfh_qty;
  854. now.sjcl_qty = nucl.sjcl_qty;
  855. now.qtcl_qty = nucl.qtcl_qty;
  856. now.quantity = nucl.quantity;
  857. now.sgfh_tp = this.ctx.helper.mul(now.sgfh_qty, now.unit_price, tpDecimal);
  858. now.sjcl_tp = this.ctx.helper.mul(now.sjcl_qty, now.unit_price, tpDecimal);
  859. now.qtcl_tp = this.ctx.helper.mul(now.qtcl_qty, now.unit_price, tpDecimal);
  860. now.total_price = this.ctx.helper.mul(now.quantity, now.unit_price, tpDecimal);
  861. }
  862. }
  863. // 更新到ledger上
  864. if (needUpdateLedgerList.length > 0) {
  865. for (const nul of needUpdateLedgerList) {
  866. const ledgerInfo = await this.ctx.service.ledger.getDataById(nul.id);
  867. ledgerInfo.sgfh_qty = this.ctx.helper.add(ledgerInfo.sgfh_qty, nul.sgfh_qty);
  868. ledgerInfo.sjcl_qty = this.ctx.helper.add(ledgerInfo.sjcl_qty, nul.sjcl_qty);
  869. ledgerInfo.qtcl_qty = this.ctx.helper.add(ledgerInfo.qtcl_qty, nul.qtcl_qty);
  870. ledgerInfo.quantity = this.ctx.helper.add(ledgerInfo.quantity, nul.quantity);
  871. ledgerInfo.sgfh_tp = this.ctx.helper.mul(ledgerInfo.sgfh_qty, ledgerInfo.unit_price, tpDecimal);
  872. ledgerInfo.sjcl_tp = this.ctx.helper.mul(ledgerInfo.sjcl_qty, ledgerInfo.unit_price, tpDecimal);
  873. ledgerInfo.qtcl_tp = this.ctx.helper.mul(ledgerInfo.qtcl_qty, ledgerInfo.unit_price, tpDecimal);
  874. ledgerInfo.total_price = this.ctx.helper.mul(ledgerInfo.quantity, ledgerInfo.unit_price, tpDecimal);
  875. await transaction.update(this.ctx.service.ledger.tableName, ledgerInfo);
  876. }
  877. }
  878. // 找出所有新增的父节点并插入到result中
  879. for (const r of changeLedgerIdList) {
  880. await this._findParents(transaction, tid, r, result);
  881. }
  882. // 插入到计量单元表,并删除变更的计量单元数据, 插入清单表,并删除变更的清单表
  883. await this._insertByChangeRevise(transaction, tid, cid, result, result2);
  884. // 更新标段总金额
  885. const sumSql = 'SELECT Sum(total_price) As total_price, Sum(deal_tp) As deal_tp' +
  886. ' FROM ' + this.ctx.service.ledger.tableName + this.ctx.helper.whereSql({ tender_id: tid });
  887. const sum = await transaction.queryOne(sumSql);
  888. await transaction.update(this.ctx.service.tender.tableName, {
  889. id: tid,
  890. total_price: sum.total_price,
  891. deal_tp: sum.deal_tp,
  892. });
  893. // 清除修订及台账的maxLid缓存,防止树结构混乱
  894. await this.ctx.service.reviseBills._removeCacheMaxLid(tid);
  895. await this.ctx.service.ledger._removeCacheMaxLid(tid);
  896. }
  897. }
  898. async _findParents(transaction, tid, id, result) {
  899. const info = await transaction.get(this.ctx.service.changeLedger.tableName, { tender_id: tid, ledger_id: id });
  900. if (info && this._.findIndex(result, { ledger_id: info.ledger_id }) === -1) {
  901. result.push(info);
  902. await this._findParents(transaction, tid, info.ledger_pid, result);
  903. } else {
  904. return;
  905. }
  906. }
  907. async _insertByChangeRevise(transaction, tid, cid, ledgerList, posList) {
  908. if (ledgerList.length > 0) {
  909. const insertLedgerArr = [];
  910. for (const l of ledgerList) {
  911. const insertL = [
  912. l.id, l.code, l.b_code, l.name, l.unit, l.source, l.remark, l.ledger_id,
  913. l.ledger_pid, l.level, l.order, l.full_path, l.is_leaf, l.quantity, l.total_price,
  914. l.unit_price, l.drawing_code, l.memo, l.dgn_qty1, l.dgn_qty2, l.deal_qty, l.deal_tp,
  915. l.sgfh_qty, l.sgfh_tp, l.sjcl_qty, l.sjcl_tp, l.qtcl_qty, l.qtcl_tp, l.node_type, l.crid,
  916. l.tender_id, l.sgfh_expr, l.sjcl_expr, l.qtcl_expr, l.check_calc,
  917. l.ex_memo1, l.ex_memo2, l.ex_memo3,
  918. ];
  919. insertLedgerArr.push('(' + this.ctx.helper.getInArrStrSqlFilter(insertL) + ')');
  920. await transaction.delete(this.ctx.service.changeLedger.tableName, { id: l.id });
  921. // 日志添加
  922. await transaction.insert(this.ctx.service.changeReviseLog.tableName, { tid, cid, lid: l.id, name: l.name ? l.name : (l.code ? l.code : ''), create_time: new Date() });
  923. }
  924. const bSql = 'Insert Into ' +
  925. this.ctx.service.ledger.tableName +
  926. ' (id, code, b_code, name, unit, source, remark, ledger_id, ledger_pid, level, `order`, full_path, is_leaf,' +
  927. ' quantity, total_price, unit_price, drawing_code, memo, dgn_qty1, dgn_qty2, deal_qty, deal_tp,' +
  928. ' sgfh_qty, sgfh_tp, sjcl_qty, sjcl_tp, qtcl_qty, qtcl_tp, node_type, crid, tender_id,' +
  929. ' sgfh_expr, sjcl_expr, qtcl_expr, check_calc,' +
  930. ' ex_memo1, ex_memo2, ex_memo3) VALUES ' + insertLedgerArr.join(',') + ';';
  931. await transaction.query(bSql, []);
  932. }
  933. if (posList.length > 0) {
  934. const insertPosArr = [];
  935. for (const p of posList) {
  936. const insertp = [
  937. p.id, p.tid, p.lid, p.name, p.drawing_code, p.quantity, p.add_stage, p.add_stage_order, p.add_times,
  938. p.add_user, p.sgfh_qty, p.sjcl_qty, p.qtcl_qty, p.crid, p.porder, p.position,
  939. p.sgfh_expr, p.sjcl_expr, p.qtcl_expr, p.real_qty,
  940. p.ex_memo1, p.ex_memo2, p.ex_memo3,
  941. ];
  942. insertPosArr.push('(' + this.ctx.helper.getInArrStrSqlFilter(insertp) + ')');
  943. await transaction.delete(this.ctx.service.changePos.tableName, { id: p.id });
  944. // 日志添加
  945. await transaction.insert(this.ctx.service.changeReviseLog.tableName, { tid, cid, pid: p.id, name: p.name, create_time: new Date() });
  946. }
  947. const pSql =
  948. 'Insert Into ' +
  949. this.ctx.service.pos.tableName +
  950. ' (id, tid, lid, name, drawing_code, quantity, add_stage, add_stage_order, add_times, add_user,' +
  951. ' sgfh_qty, sjcl_qty, qtcl_qty, crid, porder, position, ' +
  952. ' sgfh_expr, sjcl_expr, qtcl_expr, real_qty,' +
  953. ' ex_memo1, ex_memo2, ex_memo3) VALUES ' + insertPosArr.join(',') + ';';
  954. await transaction.query(pSql, []);
  955. }
  956. }
  957. async checkedChangeBills(tid) {
  958. const DefaultDecimal = this.ctx.tender.info.decimal.tp;
  959. const sql = 'SELECT cal.*, c.tp_decimal FROM ' + this.ctx.service.changeAuditList.tableName + ' cal LEFT JOIN ' + this.ctx.service.change.tableName + ' c on cal.cid = c.cid where c.tid = ? and c.valid and c.status = ?';
  960. const changeBills = await this.db.query(sql, [tid, audit.flow.status.checked]);
  961. changeBills.forEach(x => {
  962. x.tp_decimal = x.tp_decimal !== 0 ? x.tp_decimal : DefaultDecimal
  963. });
  964. return changeBills;
  965. }
  966. /**
  967. * 交换两个清单的顺序
  968. * @param {Number} id1 - 工料1的id
  969. * @param {Number} id2 - 工料2的id
  970. * @returns {Promise<void>}
  971. */
  972. async changeOrder(datas) {
  973. if (!this.ctx.tender || !this.ctx.change) {
  974. throw '数据错误';
  975. }
  976. // const bill1 = await this.getDataByCondition({ tid: this.ctx.tender.id, id: id1 });
  977. // const bill2 = await this.getDataByCondition({ tid: this.ctx.tender.id, id: id2 });
  978. // if (!bill1 || !bill2) {
  979. // throw '数据错误';
  980. // }
  981. const transaction = await this.db.beginTransaction();
  982. try {
  983. // const order = bill1.order;
  984. // bill1.order = bill2.order;
  985. // bill2.order = order;
  986. // await transaction.update(this.tableName, { id: bill1.id, order: bill1.order });
  987. // await transaction.update(this.tableName, { id: bill2.id, order: bill2.order });
  988. await transaction.updateRows(this.tableName, datas);
  989. await transaction.commit();
  990. return true;
  991. } catch (err) {
  992. await transaction.rollback();
  993. throw err;
  994. }
  995. }
  996. }
  997. return ChangeAuditList;
  998. };