measure_controller.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. 'use strict';
  2. /**
  3. * 计量相关控制器
  4. *
  5. * @author olym
  6. * @date 2018/2/11
  7. * @version
  8. */
  9. const spreadConst = require('../const/spread');
  10. const codeRuleConst = require('../const/code_rule');
  11. const auditConst = require('../const/audit').flow;
  12. const moment = require('moment');
  13. const measureType = require('../const/tender').measureType;
  14. module.exports = app => {
  15. class MeasureController extends app.BaseController {
  16. /**
  17. * 构造函数
  18. *
  19. * @param {Object} ctx - egg全局变量
  20. * @return {void}
  21. */
  22. constructor(ctx) {
  23. super(ctx);
  24. ctx.showProject = true;
  25. ctx.showTender = true;
  26. ctx.showTitle = true;
  27. }
  28. /**
  29. * 期计量(Get)
  30. * @param ctx
  31. * @returns {Promise<void>}
  32. */
  33. async stage(ctx) {
  34. try {
  35. const renderData = {
  36. tender: ctx.tender.data,
  37. tenderMenu: this.menu.tenderMenu,
  38. preUrl: '/tender/' + ctx.tender.id,
  39. auditConst,
  40. };
  41. renderData.stages = await ctx.service.stage.getValidStages(ctx.tender.id);
  42. for (const s of renderData.stages) {
  43. s.curAuditor = null;
  44. }
  45. await this.layout('measure/stage.ejs', renderData, 'measure/stage_modal.ejs');
  46. } catch (err) {
  47. this.log(err);
  48. ctx.redirect(this.menu.menu.dashboard.url);
  49. }
  50. }
  51. /**
  52. * 新增期(Post)
  53. * @param ctx
  54. * @returns {Promise<void>}
  55. */
  56. async addStage(ctx) {
  57. try {
  58. if (ctx.session.sessionUser.accountId !== ctx.tender.data.user_id) {
  59. throw '您无权创建计量期';
  60. }
  61. const date = ctx.request.body.date;
  62. const period = ctx.request.body.period;
  63. const newStage = await ctx.service.stage.addStage(ctx.tender.id, date, period);
  64. if (!newStage) {
  65. throw '新增计量期失败,请重试';
  66. }
  67. ctx.redirect('/tender/' + ctx.tender.id + '/measure/stage/' + newStage.order);
  68. } catch (err) {
  69. this.log(err);
  70. ctx.redirect(ctx.request.header.referer)
  71. }
  72. }
  73. async saveStage(ctx) {
  74. try {
  75. const data = JSON.parse(ctx.request.body.data);
  76. const stage = await ctx.service.stage.getDataByCondition({
  77. tid: ctx.tender.id,
  78. order: data.order,
  79. });
  80. if (!stage) {
  81. throw '提交数据错误';
  82. }
  83. if (stage.status !== auditConst.status.uncheck) {
  84. throw '该计量期当前不可编辑';
  85. }
  86. if (ctx.session.sessionUser.accountId !== stage.user_id) {
  87. throw '您无权修改该数据';
  88. }
  89. await this.ctx.service.stage.saveStage(ctx.tender.id, data.order, data.date, data.period);
  90. ctx.body = {err: 0, msg: '', data: null};
  91. } catch (err) {
  92. this.log(err);
  93. ctx.body = {err: 1, msg: err.toString(), data: null};
  94. }
  95. }
  96. /**
  97. * 清单汇总
  98. * @param ctx
  99. * @returns {Promise<void>}
  100. */
  101. async gather(ctx) {
  102. try {
  103. const renderData = {
  104. tender: ctx.tender.data,
  105. tenderMenu: this.menu.tenderMenu,
  106. preUrl: '/tender/' + ctx.tender.id,
  107. }
  108. await this.layout('measure/gather.ejs', renderData);
  109. } catch (err) {
  110. this.log(err);
  111. ctx.redirect(this.menu.menu.dashboard.url);
  112. }
  113. }
  114. async compare(ctx) {
  115. try {
  116. const renderData = {
  117. tender: ctx.tender.data,
  118. tenderMenu: this.menu.tenderMenu,
  119. preUrl: '/tender/' + ctx.tender.id,
  120. }
  121. await this.layout('measure/compare.ejs', renderData, 'measure/compare_modal.ejs');
  122. } catch (err) {
  123. this.log(err);
  124. ctx.redirect(this.menu.menu.dashboard.url);
  125. }
  126. }
  127. async list(ctx) {
  128. try {
  129. const tenderList = ctx.tenderList;
  130. const tenderData = ctx.tenderData;
  131. const codeRule = tenderData.m_rule ? JSON.parse(tenderData.m_rule) : [];
  132. for (const rule of codeRule) {
  133. switch (rule.rule_type) {
  134. case codeRuleConst.measure.ruleType.tenderName:
  135. rule.preview = tenderData.name;
  136. break;
  137. case codeRuleConst.measure.ruleType.inDate:
  138. rule.preview = moment().format('YYYYMM');
  139. break;
  140. case codeRuleConst.measure.ruleType.text:
  141. rule.preview = rule.text;
  142. break;
  143. case codeRuleConst.measure.ruleType.addNo:
  144. const s = '0000000000';
  145. rule.preview = s.substr(s.length - rule.format);
  146. break;
  147. }
  148. }
  149. const works = await ctx.service.measure.measureList({
  150. tender_id: tenderData.id,
  151. user_id: ctx.session.sessionUser.accountId,
  152. valid: true,
  153. });
  154. const renderData = {
  155. tenderData,
  156. tenderList,
  157. ruleType: codeRuleConst.ruleType.measure,
  158. ruleConst: codeRuleConst.measure,
  159. codeRule,
  160. works,
  161. auditConst,
  162. };
  163. await this.layout('measure/wlist.ejs', renderData, 'measure/wlist_modal.ejs');
  164. } catch (err) {
  165. this.log(err);
  166. ctx.redirect(ctx.menuList.dashboard.url);
  167. }
  168. }
  169. /**
  170. * 中间计量--计量编制 页面 (Get)
  171. *
  172. * @param {Object} ctx - egg全局变量
  173. * @return {void}
  174. */
  175. async work(ctx) {
  176. try {
  177. const tenderList = ctx.tenderList;
  178. const tenderData = ctx.tenderData;
  179. const codeRule = tenderData.m_rule ? JSON.parse(tenderData.m_rule) : [];
  180. for (const rule of codeRule) {
  181. switch (rule.rule_type) {
  182. case codeRuleConst.measure.ruleType.tenderName:
  183. rule.preview = tenderData.name;
  184. break;
  185. case codeRuleConst.measure.ruleType.inDate:
  186. rule.preview = moment().format('YYYYMM');
  187. break;
  188. case codeRuleConst.measure.ruleType.text:
  189. rule.preview = rule.text;
  190. break;
  191. case codeRuleConst.measure.ruleType.addNo:
  192. const s = '0000000000';
  193. rule.preview = s.substr(s.length - rule.format);
  194. break;
  195. }
  196. }
  197. const mid = ctx.params.mid
  198. const measure = await ctx.service.measure.getDataByCondition({mid: mid, valid: true});
  199. if (!measure) {
  200. throw '该数据已被删除'
  201. }
  202. const renderData = {
  203. tenderData,
  204. tenderList,
  205. auditConst,
  206. measure,
  207. measureSpreadSetting: JSON.stringify(spreadConst.measureSpread),
  208. };
  209. await this.layout('measure/work.ejs', renderData, 'measure/work_modal.ejs');
  210. } catch (err) {
  211. this.log(err);
  212. ctx.redirect(ctx.menuList.dashboard.url);
  213. }
  214. }
  215. /**
  216. * 中间计量 -- 获取新编号 (Ajax)
  217. *
  218. * @param {Object} ctx - egg全局变量
  219. * @returns {Promise<void>}
  220. */
  221. async newCode(ctx) {
  222. const responseData = {
  223. err: 0,
  224. msg: '',
  225. data: '',
  226. };
  227. try {
  228. const tenderId = ctx.session.sessionUser.tenderId;
  229. if (!tenderId) {
  230. throw '当前未打开标段';
  231. }
  232. const tenderData = await ctx.service.tender.getDataById(tenderId);
  233. const mCodeRule = JSON.parse(tenderData.m_rule);
  234. const code = [];
  235. for (const rule of mCodeRule) {
  236. switch (rule.rule_type) {
  237. case codeRuleConst.measure.ruleType.tenderName:
  238. code.push(tenderData.name);
  239. break;
  240. case codeRuleConst.measure.ruleType.text:
  241. code.push(rule.text);
  242. break;
  243. case codeRuleConst.measure.ruleType.inDate:
  244. code.push(moment().format('YYYYMM'));
  245. break;
  246. case codeRuleConst.measure.ruleType.addNo:
  247. let s = '0000000000';
  248. const count = rule.start + await ctx.service.measure.count({tender_id: tenderId});
  249. s = s + count;
  250. code.push(s.substr(s.length - rule.format));
  251. break;
  252. }
  253. }
  254. responseData.data = code.join('');
  255. } catch (err) {
  256. responseData.err = 1;
  257. responseData.msg = err;
  258. }
  259. ctx.body = responseData;
  260. }
  261. /**
  262. * 中间计量 -- 新增中间计量 (Ajax)
  263. *
  264. * @param {Object} ctx - egg全局变量
  265. * @returns {Promise<void>}
  266. */
  267. async addMeasure(ctx) {
  268. const responseData = {
  269. err: 0,
  270. msg: '',
  271. data: '',
  272. };
  273. try {
  274. const tenderId = ctx.session.sessionUser.tenderId;
  275. if (!tenderId) {
  276. throw '当前未打开标段';
  277. }
  278. const tenderData = await ctx.service.tender.getDataById(tenderId);
  279. const data = JSON.parse(ctx.request.body.data);
  280. await ctx.service.measure.add(tenderId, data.code, ctx.session.sessionUser.accountId, data.date, data.stage);
  281. responseData.data = await ctx.service.measure.measureData({
  282. tender_id: tenderId, code: data.code,
  283. });
  284. } catch (err) {
  285. this.log(err);
  286. responseData.err = 1;
  287. responseData.msg = err.toString();
  288. }
  289. ctx.body = responseData;
  290. }
  291. async deleteMeasure(ctx) {
  292. const responseData = {
  293. err: 0,
  294. msg: '',
  295. data: '',
  296. };
  297. try {
  298. const tenderId = ctx.session.sessionUser.tenderId;
  299. if (!tenderId) {
  300. throw '当前未打开标段';
  301. }
  302. const data = JSON.parse(ctx.request.body.data);
  303. responseData.data = await ctx.service.measure.invalid(tenderId, data.code, ctx.session.sessionUser.accountId);
  304. } catch (err) {
  305. this.log(err);
  306. responseData.err = 1;
  307. responseData.msg = err.toString();
  308. }
  309. ctx.body = responseData;
  310. }
  311. /**
  312. * 获取中间计量详细数据(包括部位和清单) (Ajax)
  313. * @param ctx - egg全局变量
  314. * @returns {Promise<void>}
  315. */
  316. async measureDetail(ctx) {
  317. const responseData = {
  318. err: 0,
  319. msg: '',
  320. data: '',
  321. };
  322. try {
  323. const tenderId = ctx.session.sessionUser.tenderId;
  324. if (!tenderId) {
  325. throw '当前未打开标段';
  326. }
  327. const tenderData = await ctx.service.tender.getDataById(tenderId);
  328. const data = JSON.parse(ctx.request.body.data);
  329. if (!data.mid) {
  330. throw '查询数据有误';
  331. }
  332. const measure = await ctx.service.measure.getDataByCondition({
  333. tender_id: tenderId,
  334. mid: data.mid,
  335. });
  336. if (!measure.times) {
  337. measure.times = 1;
  338. }
  339. measure.pos = await ctx.service.measurePos.getPosDetail(tenderId, data.mid);
  340. measure.bills = await ctx.service.measureBills.getBillsDetail(tenderId, data.mid);
  341. measure.billsTree = await ctx.service.measureBills.getBillsDetailWithParent(tenderId, data.mid);
  342. measure.curAuditor = await ctx.service.measureAudit.getCurAuditor(data.mid, measure.times);
  343. if (measure.times > 1 && measure.status === auditConst.status.checkNo) {
  344. measure.auditors = await ctx.service.measureAudit.getAuditors(data.mid, measure.times-1);
  345. } else {
  346. measure.auditors = await ctx.service.measureAudit.getAuditors(data.mid, measure.times);
  347. }
  348. responseData.data = measure;
  349. } catch (err) {
  350. this.log(err);
  351. responseData.err = 1;
  352. responseData.msg = err.toString();
  353. }
  354. ctx.body = responseData;
  355. }
  356. /**
  357. * 查询部位或者清单 (Ajax)
  358. *
  359. * @param ctx - egg全局变量
  360. * @returns {Promise<void>}
  361. */
  362. async search(ctx) {
  363. const responseData = {
  364. err: 0,
  365. msg: '',
  366. data: '',
  367. };
  368. try {
  369. const tenderId = ctx.session.sessionUser.tenderId;
  370. if (!tenderId) {
  371. throw '当前未打开标段';
  372. }
  373. const tenderData = await ctx.service.tender.getDataById(tenderId);
  374. const data = JSON.parse(ctx.request.body.data);
  375. if (!data.mid || !data.searchType) {
  376. throw '查询数据有误';
  377. }
  378. if (data.searchType === 'pos') {
  379. const key = {
  380. value: app.mysql.escape('%' + data.keyword + '%'),
  381. operate: 'Like',
  382. fields: ['code', 'name'],
  383. };
  384. responseData.data = await ctx.service.ledger.search(tenderId, key);
  385. } else if (data.searchType === 'bills') {
  386. const key = {
  387. value: app.mysql.escape('%' + data.keyword + '%'),
  388. operate: 'Like',
  389. fields: ['b_code', 'name'],
  390. };
  391. const range = [];
  392. const pos = await ctx.service.measurePos.getPosDetail(tenderId, data.mid);
  393. const posFullPath = [];
  394. for (const p of pos) {
  395. posFullPath.push(app.mysql.escape(p.full_path + '.%'));
  396. }
  397. responseData.data = await ctx.service.ledger.searchRange(tenderId, key, [{
  398. value: posFullPath,
  399. operate: 'Like',
  400. fields: ['full_path'],
  401. }, {
  402. value: true,
  403. operate: '=',
  404. fields: ['is_leaf'],
  405. }]);
  406. } else {
  407. throw '查询数据有误';
  408. }
  409. } catch (err) {
  410. this.log(err);
  411. responseData.err = 1;
  412. responseData.msg = err.toString();
  413. }
  414. ctx.body = responseData;
  415. }
  416. /**
  417. * 操作部位 -- 增删 (Ajax)
  418. *
  419. * @param ctx - egg全局变量
  420. * @returns {Promise<void>}
  421. */
  422. async pos(ctx) {
  423. const responseData = {
  424. err: 0,
  425. msg: '',
  426. data: {},
  427. };
  428. try {
  429. const tenderId = ctx.session.sessionUser.tenderId;
  430. if (!tenderId) {
  431. throw '当前未打开标段';
  432. }
  433. const data = JSON.parse(ctx.request.body.data);
  434. if (!data.mid || !data.operate || !data.pid) {
  435. throw '计量范围数据有误';
  436. }
  437. if (data.operate === 'add') {
  438. responseData.data = await ctx.service.measurePos.addPos(tenderId, data.mid, data.pid);
  439. } else if (data.operate === 'remove') {
  440. await ctx.service.measurePos.removePos(tenderId, data.mid, data.pid);
  441. } else {
  442. throw '未知操作';
  443. }
  444. } catch(err) {
  445. this.log(err);
  446. responseData.err = 1;
  447. responseData.msg = err.toString();
  448. }
  449. ctx.body = responseData;
  450. }
  451. /**
  452. * 操作清单 -- 增删 (Ajax)
  453. * @param ctx
  454. * @returns {Promise<void>}
  455. */
  456. async bills(ctx) {
  457. const responseData = {
  458. err: 0,
  459. msg: '',
  460. data: {},
  461. };
  462. try {
  463. const tenderId = ctx.session.sessionUser.tenderId;
  464. if (!tenderId) {
  465. throw '当前未打开标段';
  466. }
  467. const data = JSON.parse(ctx.request.body.data);
  468. if (!data.mid || !data.operate || !data.bid) {
  469. throw '计量清单数据有误';
  470. }
  471. if (data.operate === 'add') {
  472. await ctx.service.measureBills.addBills(tenderId, data.mid, data.bid);
  473. responseData.data = await ctx.service.measureBills.getBillsDataWithParent(tenderId, data.mid, data.bid);
  474. } else if (data.operate === 'remove') {
  475. responseData.data = await ctx.service.measureBills.getBillsDataWithParent(tenderId, data.mid, data.bid);
  476. await ctx.service.measureBills.removeBills(tenderId, data.mid, data.bid);
  477. } else {
  478. throw '未知操作';
  479. }
  480. } catch(err) {
  481. this.log(err);
  482. responseData.err = 1;
  483. responseData.msg = err.toString();
  484. responseData.data = {};
  485. }
  486. ctx.body = responseData;
  487. }
  488. /**
  489. * 清单 -- 计量 (Ajax)
  490. * @param ctx
  491. * @returns {Promise<void>}
  492. */
  493. async billsUpdate (ctx) {
  494. const responseData = { err: 0, msg: '', data: {} };
  495. try {
  496. const tenderId = ctx.session.sessionUser.tenderId;
  497. if (!tenderId) {
  498. throw '当前未打开标段';
  499. }
  500. const data = JSON.parse(ctx.request.body.data);
  501. if (!data.mid || !data.bid || !data.update) {
  502. throw '计量清单数据有误';
  503. }
  504. responseData.data = await ctx.service.measureBills.updateBills(tenderId, data.mid, data.bid, data.update);
  505. } catch(err) {
  506. this.log(err);
  507. responseData.err = 1;
  508. responseData.msg = err.toString();
  509. responseData.data = {};
  510. }
  511. ctx.body = responseData;
  512. }
  513. }
  514. return MeasureController;
  515. };