quality.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. 'use strict';
  2. /**
  3. * 质量管理 - 工程质量
  4. *
  5. * @author Mai
  6. * @date 2024/7/22
  7. * @version
  8. */
  9. const Ledger = require('../lib/ledger');
  10. class RuleCheck {
  11. sortCondition(condition) {
  12. const fieldKey = ['gongxu_name', 'yinbi_name', 'file_count', 'file_name'];
  13. condition.forEach(c => { c.fieldKeyIndex = fieldKey.indexOf(c.fieldKey); });
  14. condition.sort((a, b) => { return a.fieldKeyIndex - b.fieldKeyIndex; });
  15. }
  16. fileCountCheck(files, check) {
  17. if (check.operateKey === '>') return files.length > parseInt(check.value);
  18. if (check.operateKey === '=') return files.length === parseInt(check.value);
  19. }
  20. fileNameCheck(files, check) {
  21. const matchName = check.multi ? check.value.split(';') : [check.value];
  22. if (check.operateKey === '=') return files.findIndex(f => { return matchName.indexOf(f.filename) >= 0; }) >= 0;
  23. if (check.operateKey === 'has') return files.findIndex(f => {
  24. return matchName.findIndex(x => { return f.filename.indexOf(x) >= 0; }) >= 0;
  25. }) >= 0;
  26. }
  27. getAllFiles() {
  28. const files = [];
  29. if (this.quality.kaigong) files.push(...this.quality.kaigong.files);
  30. if (this.quality.gongxu) {
  31. for (const gx of this.quality.gongxu.list) {
  32. files.push(...gx.files);
  33. }
  34. }
  35. if (this.quality.pingding) {
  36. files.push(...this.quality.pingding.files);
  37. this.quality.pingding.source_files.forEach(sf => {
  38. if (sf.spec_type === 'add') files.push(sf);
  39. });
  40. }
  41. if (this.quality.jiaogong) files.push(...this.quality.jiaogong.files);
  42. // if (this.quality.yinbi) {
  43. // for (const yb of this.quality.yinbi.list) {
  44. // files.push(...yb.files);
  45. // }
  46. // }
  47. return files;
  48. }
  49. kaigongCheck(check) {
  50. if (!this.quality.kaigong) return false;
  51. switch (check.fieldKey) {
  52. case 'file_count':
  53. return this.fileCountCheck(this.quality.kaigong.files, check);
  54. case 'file_name':
  55. return this.fileNameCheck(this.quality.kaigong.files, check);
  56. default:
  57. return false;
  58. }
  59. }
  60. GongxuNameCheck(check) {
  61. const matchName = check.multi ? check.value.split(';') : [check.value];
  62. if (check.operateKey === '=') {
  63. this.matchGongxu = this.quality.gongxu.list.filter(f => { return matchName.indexOf(f.name) >= 0; });
  64. }
  65. if (check.operateKey === 'has') {
  66. this.matchGongxu = this.quality.gongxu.list.filter(f => {
  67. return matchName.findIndex(x => { return f.name.indexOf(x) >= 0; }) >= 0;
  68. });
  69. }
  70. return this.matchGongxu.length > 0;
  71. }
  72. getGongxuFiles() {
  73. const files = [];
  74. const gongxuList = this.matchGongxu || this.quality.gongxu.list;
  75. for (const gx of gongxuList) {
  76. files.push(...gx.files);
  77. }
  78. return files;
  79. }
  80. gongxuCheck(check) {
  81. switch (check.fieldKey) {
  82. case 'gongxu_name':
  83. return this.GongxuNameCheck(check);
  84. case 'file_count':
  85. return this.fileCountCheck(this.getGongxuFiles(), check);
  86. case 'file_name':
  87. return this.fileNameCheck(this.getGongxuFiles(), check);
  88. default:
  89. return false;
  90. }
  91. }
  92. pingdingCheck(check) {
  93. if (!this.quality.pingding) return false;
  94. const files = [...this.quality.pingding.files, ...this.quality.pingding.source_files];
  95. switch (check.fieldKey) {
  96. case 'file_count':
  97. return this.fileCountCheck(files, check);
  98. case 'file_name':
  99. return this.fileNameCheck(files, check);
  100. default:
  101. return false;
  102. }
  103. }
  104. jiaogongCheck(check) {
  105. if (!this.quality.jiaogong) return false;
  106. switch (check.fieldKey) {
  107. case 'file_count':
  108. return this.fileCountCheck(this.quality.jiaogong.files, check);
  109. case 'file_name':
  110. return this.fileNameCheck(this.quality.jiaogong.files, check);
  111. default:
  112. return false;
  113. }
  114. }
  115. YinbiNameCheck(check) {
  116. const matchName = check.multi ? check.value.split(';') : [check.value];
  117. if (check.operateKey === '=') {
  118. this.matchYinbi = this.quality.yinbi.list.filter(f => { return matchName.indexOf(f.name) >= 0; });
  119. }
  120. if (check.operateKey === '>') {
  121. this.matchYinbi = this.quality.yinbi.list.filter(f => {
  122. return matchName.findIndex(x => { return f.name.indexOf(x) >= 0; }) >= 0;
  123. });
  124. }
  125. return this.matchYinbi.length > 0;
  126. }
  127. getYinbiFiles() {
  128. const files = [];
  129. const yinbiList = this.matchYinbi || this.quality.yinbi.list;
  130. for (const yb of yinbiList) {
  131. files.push(...yb.files);
  132. }
  133. return files;
  134. }
  135. yinbiCheck(check) {
  136. switch (check.fieldKey) {
  137. case 'gongxu_name':
  138. return this.YinbiNameCheck(check);
  139. case 'file_count':
  140. return this.fileCountCheck(this.getYinbiFiles(), check);
  141. case 'file_name':
  142. return this.fileNameCheck(this.getYinbiFiles(), check);
  143. default:
  144. return false;
  145. }
  146. }
  147. allFilesCheck(check) {
  148. const allFiles = this.getAllFiles();
  149. switch (check.fieldKey) {
  150. case 'file_count':
  151. return this.fileCountCheck(allFiles, check);
  152. case 'file_name':
  153. return this.fileNameCheck(allFiles, check);
  154. default:
  155. return false;
  156. }
  157. }
  158. conditionCheck(check) {
  159. switch (check.blockKey) {
  160. case 'kaigong':
  161. return this.kaigongCheck(check);
  162. case 'gongxu':
  163. return this.gongxuCheck(check);
  164. case 'pingding':
  165. return this.pingdingCheck(check);
  166. case 'jiaogong':
  167. return this.jiaogongCheck(check);
  168. case 'yinbi':
  169. return this.yinbiCheck(check);
  170. case 'all':
  171. return this.allFilesCheck(check);
  172. default:
  173. return false;
  174. }
  175. }
  176. calcQualityStatus(quality, group) {
  177. this.quality = quality;
  178. this.group = group;
  179. for (const r of group.rules) {
  180. if (r.condition.length === 0) return false;
  181. if (r.condition.length > 1) this.sortCondition(r.condition);
  182. }
  183. const match = group.rules.filter(r => {
  184. this.matchGongxu = null;
  185. this.matchYinbi = null;
  186. for (const check of r.condition) {
  187. if (!this.conditionCheck(check)) {
  188. return false;
  189. }
  190. }
  191. return true;
  192. });
  193. if (match.length === 0) return null;
  194. const data = {};
  195. for (const m of match) {
  196. for (const s of m.push_status) {
  197. if (!data[s.field] || s.value > data[s.field]) {
  198. data[s.field] = s.value;
  199. }
  200. }
  201. }
  202. return data;
  203. }
  204. }
  205. module.exports = app => {
  206. class Quality extends app.BaseService {
  207. /**
  208. * 构造函数
  209. *
  210. * @param {Object} ctx - egg全局变量
  211. * @return {void}
  212. */
  213. constructor(ctx) {
  214. super(ctx);
  215. this.tableName = 'quality';
  216. this.editableColumns = ['gxby_status', 'gxby_date', 'gxby_limit', 'dagl_status', 'dagl_limit'];
  217. this.blockType = {
  218. kaigong: { key: 'kaigong', name: '开工' },
  219. gongxu: { key: 'gongxu', name: '工序' },
  220. jiaogong: { key: 'jiaogong', name: '中间交工' },
  221. pingding: { key: 'pingding', name: '评定' },
  222. yinbi: { key: 'yinbi', name: '隐蔽工程' },
  223. shiyan: { key: 'shiyan', name: '试验检测' },
  224. waiwei: { key: 'waiwei', name: '外委检测' },
  225. sanfang: { key: 'sanfang', name: '第三方检测' },
  226. };
  227. }
  228. async saveQualityManage(tid, data) {
  229. const quality = await this.getDataByCondition({ tid, rela_type: data.rela_type, rela_id: data.rela_id, rela_name: data.rela_name });
  230. if (quality) {
  231. const updateData = { id: quality.id, group_id: data.group_id, update_uid: this.ctx.session.sessionUser.accountId, };
  232. await this.db.update(this.tableName, updateData);
  233. updateData.rela_id = data.rela_id;
  234. updateData.rela_name = data.rela_name;
  235. return updateData;
  236. } else {
  237. const newQuality = {
  238. id: this.uuid.v4(), tid, rela_type: data.rela_type, rela_id: data.rela_id, rela_name: data.rela_name,
  239. create_uid: this.ctx.session.sessionUser.accountId, update_uid: this.ctx.session.sessionUser.accountId,
  240. group_id: data.group_id,
  241. };
  242. await this.db.insert(this.tableName, newQuality);
  243. return newQuality;
  244. }
  245. }
  246. async saveQuality(quality, filter, data, conn) {
  247. data.update_uid = this.ctx.session.sessionUser.accountId;
  248. data.is_used = 1;
  249. if (quality) {
  250. data.id = quality.id;
  251. if (conn) {
  252. await conn.update(this.tableName, data);
  253. } else {
  254. await this.db.update(this.tableName, data);
  255. }
  256. return data;
  257. } else {
  258. data.id = this.uuid.v4();
  259. data.tid = this.ctx.tender.id;
  260. data.rela_type = filter.rela_type;
  261. data.rela_id = filter.rela_id;
  262. data.rela_name = filter.rela_name;
  263. data.create_uid = this.ctx.session.sessionUser.accountId;
  264. if (conn) {
  265. await conn.insert(this.tableName, data);
  266. } else {
  267. await this.db.insert(this.tableName, data);
  268. }
  269. return data;
  270. }
  271. }
  272. async getQuality(filter) {
  273. if (filter.quality_id) return await this.getDataByCondition({ id: filter.quality_id });
  274. if (filter.rela_type && filter.rela_id) return await this.getDataByCondition({ tid: filter.tid || this.ctx.tender.id, rela_type: filter.rela_type, rela_id: filter.rela_id, rela_name: filter.rela_name });
  275. throw '参数错误';
  276. }
  277. async _loadKgData(quality) {
  278. if (!quality.kaigong_time) return;
  279. quality.kaigong = {};
  280. for (const p in quality) {
  281. if (p.indexOf('kaigong_') !== 0) continue;
  282. quality.kaigong[p] = quality[p];
  283. delete quality[p];
  284. }
  285. const files = await this.ctx.service.qualityFile.getBlockFiles(quality, 'kaigong');
  286. quality.kaigong.files = files.filter(f => { return !f.spec_type; });
  287. quality.kaigong.qa_files = files.filter(f => { return f.spec_type === 'qa'; });
  288. // todo 加载开工审批数据
  289. }
  290. async _loadGxData(quality) {
  291. quality.gongxu = {};
  292. // todo 加载工序审批数据
  293. quality.gongxu.list = await this.ctx.service.qualityGongxu.getAllDataByCondition({ where: { quality_id: quality.id }, orders:[['create_time', 'asc']] });
  294. for (const gx of quality.gongxu.list) {
  295. gx.canEdit = gx.user_id === this.ctx.session.sessionUser.accountId;
  296. gx.files = await this.ctx.service.qualityFile.getBlockFiles(quality, 'gongxu', gx.id);
  297. // todo 加载工序步骤审批数据
  298. }
  299. }
  300. async _loadPdData(quality) {
  301. if (!quality.kaigong && quality.gongxu.list.length === 0) return;
  302. quality.pingding = {};
  303. for (const p in quality) {
  304. if (p.indexOf('pingding_') !== 0) continue;
  305. quality.kaigong[p] = quality[p];
  306. delete quality[p];
  307. }
  308. const files = await this.ctx.service.qualityFile.getBlockFiles(quality, 'pingding');
  309. quality.pingding.files = files.filter(f => { return !f.spec_type; });
  310. quality.pingding.source_files = files.filter(f => { return f.spec_type === 'add'; }); // addtional
  311. if (quality.gongxu) {
  312. for (const gx of quality.gongxu.list) {
  313. const qaFiles = gx.files.filter(f => { return f.spec_type === 'qa'; });
  314. for (const f of qaFiles) {
  315. const qaF = JSON.parse(JSON.stringify(f));
  316. qaF.canEdit = false;
  317. quality.pingding.source_files.push(qaF);
  318. }
  319. }
  320. }
  321. // todo 加载评定审批数据
  322. }
  323. async _loadJgData(quality) {
  324. if (!quality.kaigong && quality.gongxu.list.length === 0) return;
  325. quality.jiaogong = {};
  326. for (const p in quality) {
  327. if (p.indexOf('jiaogong_') !== 0) continue;
  328. quality.jiaogong[p] = quality[p];
  329. delete quality[p];
  330. }
  331. quality.jiaogong.files = await this.ctx.service.qualityFile.getBlockFiles(quality, 'jiaogong');
  332. }
  333. async _loadYbData(quality) {
  334. quality.yinbi = {};
  335. quality.yinbi.list = await this.ctx.service.qualityYinbi.getAllDataByCondition({ where: { quality_id: quality.id }, orders:[['create_time', 'asc']] });
  336. for (const yb of quality.yinbi.list) {
  337. yb.canEdit = yb.user_id === this.ctx.session.sessionUser.accountId;
  338. const files = await this.ctx.service.qualityFile.getBlockFiles(quality, 'yinbi', yb.id);
  339. yb.before_files = files.filter(f => { return f.spec_type === 'before'; });
  340. yb.after_files = files.filter(f => { return f.spec_type === 'after'; });
  341. }
  342. }
  343. async loadQualityDetail(quality) {
  344. if (!quality) return;
  345. await this._loadKgData(quality);
  346. await this._loadGxData(quality);
  347. await this._loadPdData(quality);
  348. await this._loadJgData(quality);
  349. await this._loadYbData(quality);
  350. }
  351. async getQualityGroup(quality) {
  352. if (quality.group_id) return quality.group_id;
  353. const ledger = await this.ctx.service.ledger.getDataById(quality.rela_id);
  354. const sql = 'SELECT l.id, l.ledger_id, l.level, q.group_id ' +
  355. ` FROM ${this.tableName} q LEFT JOIN ${this.ctx.service.ledger.tableName} l ON q.rela_id = l.id ` +
  356. ` WHERE q.tid = ${quality.tid} and l.ledger_id in (${ledger.full_path.split('-').join(', ')}) and group_id <> ''` +
  357. ' ORDER BY l.level DESC';
  358. const allQuality = await this.db.query(sql);
  359. return allQuality.length > 0 ? allQuality[0].group_id : '';
  360. }
  361. async checkQualityStatus(quality) {
  362. const groupId = await this.getQualityGroup(quality);
  363. if (!groupId) return null;
  364. const groupRule = await this.ctx.service.qualityRule.getGroupRule(groupId);
  365. if (!groupRule) return null;
  366. const ruleCheck = new RuleCheck();
  367. return ruleCheck.calcQualityStatus(quality, groupRule);
  368. }
  369. async checkQualityStatusAndSave(quality) {
  370. const data = await this.checkQualityStatus(quality);
  371. if (!data) return;
  372. for (const field in data) {
  373. quality[field] = data[field];
  374. }
  375. data.id = quality.id;
  376. await this.db.update(this.tableName, data);
  377. }
  378. async kaigong(filter, name, date) {
  379. const quality = await this.getQuality(filter);
  380. const conn = await this.db.beginTransaction();
  381. try {
  382. const kaigongData = {
  383. kaigong_name: name || '开工工序', kaigong_date: date || this.ctx.moment().format('YYYY-MM-DD'),
  384. kaigong_uid: this.ctx.session.sessionUser.accountId, kaigong_time: new Date(),
  385. };
  386. await this.saveQuality(quality, filter, kaigongData, conn);
  387. await conn.commit();
  388. } catch (err) {
  389. await conn.rollback();
  390. throw err;
  391. }
  392. }
  393. async delKaigong(filter) {
  394. const quality = await this.getQuality(filter);
  395. if (!quality || !quality.kaigong_uid) throw '该工程未开工';
  396. if (quality.kaigong_uid !== this.ctx.session.sessionUser.accountId) throw '开工数据不是您新增的,无权删除';
  397. const conn = await this.db.beginTransaction();
  398. try {
  399. await this.saveQuality(quality, filter, { kaigong_name: '', kaigong_date: '', kaigong_uid: 0, kaigong_time: null }, conn);
  400. await conn.update(this.ctx.service.qualityFile.tableName, { is_deleted: 1 }, { where: { quality_id: quality.id, block_type: 'kaigong' } });
  401. await conn.commit();
  402. } catch (err) {
  403. await conn.rollback();
  404. throw err;
  405. }
  406. }
  407. async pushIncStatus(select) {
  408. const quality = [];
  409. for (const s of select) {
  410. const sq = await this.ctx.service.quality.getDataByCondition({ tid: this.ctx.tender.id, rela_type: s.rela_type, rela_id: s.rela_id, rela_name: s.rela_name });
  411. if (sq && sq.is_used) {
  412. quality.push(sq);
  413. if (sq.rela_type === 'pos') sq.rela_pid = s.pid;
  414. }
  415. }
  416. const xmjInsert = [], xmjUpdate = [], posInsert = [], posUpdate = [];
  417. const xmjQuality = [], posQuality = [];
  418. quality.forEach(q => {
  419. if (q.rela_type === 'xmj') {
  420. xmjQuality.push(q);
  421. } else {
  422. posQuality.push(q);
  423. }
  424. });
  425. const xmjExtra = xmjQuality.length > 0 ? await this.ctx.service.ledgerExtra.getAllDataByCondition({ where: { id: xmjQuality.map(x => { return x.rela_id; }) } }) : [];
  426. for (const xq of xmjQuality) {
  427. const xe = xmjExtra.find(x => { return x.id === xq.rela_id; });
  428. const wbs_url = `/3f/zh/info?pid=${this.ctx.session.sessionProject.id}&tid=${xq.tid}&${xq.rela_type}id=${xq.rela_id}`;
  429. if (xe) {
  430. // xmjUpdate.push({ id: xe.id, gxby_status: xq.gxby_status, gxby_date: xq.gxby_date, dagl_status: xq.dagl_status, wbs_url });
  431. xmjUpdate.push({ id: xe.id, gxby_status: xq.gxby_status, dagl_status: xq.dagl_status, wbs_url });
  432. } else {
  433. // xmjInsert.push({ id: xq.rela_id, gxby_status: xq.gxby_status, gxby_date: xq.gxby_date, dagl_status: xq.dagl_status, wbs_url });
  434. xmjInsert.push({ id: xq.rela_id, tid: this.ctx.tender.id, gxby_status: xq.gxby_status, dagl_status: xq.dagl_status, wbs_url });
  435. }
  436. }
  437. for (const pq of posQuality) {
  438. if (!pq.rela_pid || pq.rela_pid.length === 0) continue;
  439. const posExtra = await this.ctx.service.posExtra.getAllDataByCondition({ where: { id: pq.rela_pid } });
  440. for (const pid of pq.rela_pid) {
  441. const pe = posExtra.find(x => { return x.id === pid; });
  442. const wbs_url = `/3f/zh/info?pid=${this.ctx.session.sessionProject.id}&tid=${pq.tid}&${pq.rela_type}id=${pid}`;
  443. if (pe) {
  444. // posUpdate.push({ id: pe.id, gxby_status: pq.gxby_status, gxby_date: pq.gxby_date, dagl_status: pq.dagl_status, wbs_url });
  445. posUpdate.push({ id: pe.id, gxby_status: pq.gxby_status, dagl_status: pq.dagl_status, wbs_url });
  446. } else {
  447. // posInsert.push({ id: pid, gxby_status: pq.gxby_status, gxby_date: pq.gxby_date, dagl_status: pq.dagl_status, wbs_url });
  448. posInsert.push({ id: pid, tid: this.ctx.tender.id, gxby_status: pq.gxby_status, dagl_status: pq.dagl_status, wbs_url });
  449. }
  450. }
  451. }
  452. const conn = await this.db.beginTransaction();
  453. try {
  454. if (xmjInsert.length > 0) await conn.insert(this.ctx.service.ledgerExtra.tableName, xmjInsert);
  455. if (xmjUpdate.length > 0) await conn.updateRows(this.ctx.service.ledgerExtra.tableName, xmjUpdate);
  456. if (posInsert.length > 0) await conn.insert(this.ctx.service.posExtra.tableName, posInsert);
  457. if (posUpdate.length > 0) await conn.updateRows(this.ctx.service.posExtra.tableName, posUpdate);
  458. await conn.commit();
  459. } catch (err) {
  460. this.ctx.log(err);
  461. await conn.rollback();
  462. throw '推送状态错误';
  463. }
  464. return xmjInsert.length + xmjUpdate.length + posInsert.length + posUpdate.length;
  465. }
  466. async getQualityTree(quality) {
  467. const ledgerData = await this.ctx.service.ledger.getAllDataByCondition({ where: { tender_id: this.ctx.tender.id }});
  468. const posData = await this.ctx.service.pos.getAllDataByCondition({ where: { tid: this.ctx.tender.id }});
  469. const qualityTree = new Ledger.filterGatherTree(this.ctx, { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1 });
  470. const ledgerTree = new Ledger.billsTree(this.ctx, {id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1});
  471. const pos = new Ledger.pos({ id: 'id', ledgerId: 'lid' });
  472. ledgerTree.loadDatas(ledgerData);
  473. pos.loadDatas(posData);
  474. const recursiveLoad = function (node, parent, type = 'xmj') {
  475. if (type === 'xmj') {
  476. const cur = !node.b_code ? qualityTree.addNode({ id: node.id, tender_id: node.tender_id, code: node.code, name: node.name, rela_type: type, rela_id: node.id, rela_name: '', }, parent) : parent;
  477. if (node.children && node.children.length > 0) {
  478. for (const child of node.children) {
  479. recursiveLoad(child, cur);
  480. }
  481. } else {
  482. const posRange = pos.getLedgerPos(node.id) || [];
  483. for (const pos of posRange) {
  484. recursiveLoad(pos, cur, 'pos');
  485. }
  486. }
  487. }
  488. if (type === 'pos') {
  489. if (!parent) return;
  490. const cur = parent.children ? parent.children.find(x => { return x.name === node.name }) : null;
  491. if (!cur) {
  492. qualityTree.addNode({ id: node.id, tender_id: node.tid, rela_id: parent.id, code: '', name: node.name, rela_type: 'pos', rela_name: node.name, pid: [node.id]}, parent);
  493. } else {
  494. cur.pid.push(node.id);
  495. }
  496. }
  497. };
  498. for (const node of ledgerTree.children) {
  499. recursiveLoad(node);
  500. }
  501. qualityTree.sortTreeNode(false);
  502. if (quality) {
  503. const qualityIndex = [];
  504. for (const q of quality) {
  505. const key = q.rela_type + ';' + q.rela_id + ';' + q.rela_name;
  506. qualityIndex[key] = q;
  507. }
  508. for (const x of qualityTree.nodes) {
  509. const qua = qualityIndex[x.rela_type + ';' + x.rela_id + ';' + x.rela_name];
  510. if (qua) x.quality = qua;
  511. }
  512. }
  513. return qualityTree;
  514. }
  515. async pushAllStatus() {
  516. const quality = await this.ctx.service.quality.getAllDataByCondition({ where: { tid: this.ctx.tender.id, is_used: 1 } });
  517. if (quality.length === 0) return 0;
  518. const qualityTree = await this.getQualityTree(quality);
  519. const xmjInsert = [], xmjUpdate = [], posInsert = [], posUpdate = [];
  520. const xmjExtra = await this.ctx.service.ledgerExtra.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
  521. const posExtra = await this.ctx.service.posExtra.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
  522. for (const node of qualityTree.nodes) {
  523. if (!node.quality) continue;
  524. if (node.rela_type === 'xmj') {
  525. const xe = xmjExtra.find(x => { return x.id === node.rela_id; });
  526. const wbs_url = `/3f/zh/info?pid=${this.ctx.session.sessionProject.id}&tid=${this.ctx.tender.id}&xmjid=${node.rela_id}`;
  527. if (xe) {
  528. // xmjUpdate.push({ id: xe.id, gxby_status: node.quality.gxby_status, gxby_date: node.quality.gxby_date, dagl_status: node.quality.dagl_status, wbs_url });
  529. xmjUpdate.push({ id: xe.id, gxby_status: node.quality.gxby_status, dagl_status: node.quality.dagl_status, wbs_url });
  530. } else {
  531. // xmjInsert.push({ id: node.rela_id, tid: this.ctx.tender.id, gxby_status: node.quality.gxby_status, gxby_date: node.quality.gxby_date, dagl_status: node.quality.dagl_status, wbs_url });
  532. xmjInsert.push({ id: node.rela_id, tid: this.ctx.tender.id, gxby_status: node.quality.gxby_status, dagl_status: node.quality.dagl_status, wbs_url });
  533. }
  534. } else {
  535. for (const pid of node.pid) {
  536. const pe = posExtra.find(x => { return x.id === pid; });
  537. const wbs_url = `/3f/zh/info?pid=${this.ctx.session.sessionProject.id}&tid=${this.ctx.tender.id}&posid=${pid}`;
  538. if (pe) {
  539. // posUpdate.push({ id: pe.id, gxby_status: node.quality.gxby_status, gxby_date: node.quality.gxby_date, dagl_status: node.quality.dagl_status, wbs_url });
  540. posUpdate.push({ id: pe.id, gxby_status: node.quality.gxby_status, dagl_status: node.quality.dagl_status, wbs_url });
  541. } else {
  542. // posInsert.push({ id: pid, tid: this.ctx.tender.id, gxby_status: node.quality.gxby_status, gxby_date: node.quality.gxby_date, dagl_status: node.quality.dagl_status, wbs_url });
  543. posInsert.push({ id: pid, tid: this.ctx.tender.id, gxby_status: node.quality.gxby_status, dagl_status: node.quality.dagl_status, wbs_url });
  544. }
  545. }
  546. }
  547. }
  548. const conn = await this.db.beginTransaction();
  549. try {
  550. // const defaultData = { gxby_status: -1, gxby_date: null, dagl_status: -1 };
  551. const defaultData = { gxby_status: -1, dagl_status: -1 };
  552. await conn.update(this.ctx.service.ledgerExtra.tableName, defaultData, { where: {tid: this.ctx.tender.id } });
  553. await conn.update(this.ctx.service.posExtra.tableName, defaultData, { where: {tid: this.ctx.tender.id } });
  554. if (xmjInsert.length > 0) await conn.insert(this.ctx.service.ledgerExtra.tableName, xmjInsert);
  555. if (xmjUpdate.length > 0) await conn.updateRows(this.ctx.service.ledgerExtra.tableName, xmjUpdate);
  556. if (posInsert.length > 0) await conn.insert(this.ctx.service.posExtra.tableName, posInsert);
  557. if (posUpdate.length > 0) await conn.updateRows(this.ctx.service.posExtra.tableName, posUpdate);
  558. await conn.commit();
  559. } catch (err) {
  560. this.ctx.log(err);
  561. await conn.rollback();
  562. throw '推送状态错误';
  563. }
  564. return xmjInsert.length + xmjUpdate.length + posInsert.length + posUpdate.length;
  565. }
  566. }
  567. return Quality;
  568. };