ledger_controller.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. 'use strict';
  2. /**
  3. * 台账相关控制器
  4. *
  5. * @author CaiAoLin
  6. * @date 2017/11/30
  7. * @version
  8. */
  9. const stdDataAddType = {
  10. self: 1,
  11. withParent: 2
  12. }
  13. const auditConst = require('../const/audit').flow;
  14. const spreadConst = require('../const/spread');
  15. const tenderMenu = require('../../config/menu').tenderMenu;
  16. const measureType = require('../const/tender').measureType;
  17. module.exports = app => {
  18. class LedgerController extends app.BaseController {
  19. /**
  20. * 构造函数
  21. *
  22. * @param {Object} ctx - egg全局变量
  23. * @return {void}
  24. */
  25. constructor(ctx) {
  26. super(ctx);
  27. ctx.showProject = true;
  28. ctx.showTitle = true;
  29. ctx.showTender = true;
  30. }
  31. /**
  32. * 台账分解页面 (Get)
  33. *
  34. * @param {Object} ctx - egg全局变量
  35. * @return {void}
  36. */
  37. async explode(ctx) {
  38. try {
  39. const tenderId = ctx.params.id;
  40. const tender = await this.service.tender.getTender(tenderId);
  41. const tenderInfo = await this.service.tenderInfo.getTenderInfo(tenderId);
  42. if (!tender.ledger_status) {
  43. tender.ledger_status = auditConst.status.uncheck;
  44. }
  45. if (!tender.ledger_times) {
  46. tender.ledger_times = 1;
  47. }
  48. const curAuditor = await ctx.service.ledgerAudit.getCurAuditor(tenderId, tender.ledger_times);
  49. const times = tender.ledger_status === auditConst.status.checkNo ? tender.ledger_times - 1 : tender.ledger_times;
  50. const auditors = await ctx.service.ledgerAudit.getAuditors(tenderId, times);
  51. const content = auditors.length > 0 ? await ctx.service.ledgerAuditContent.getAllDataByCondition({
  52. where: {tender_id: tenderId, times: times, audit_id: auditors[0].audit_id}
  53. }) : null;
  54. const ledgerData = await ctx.service.ledger.getDataByTenderId(tenderId, -1);
  55. const renderData = {
  56. tender,
  57. tenderInfo,
  58. auditConst,
  59. auditors,
  60. curAuditor,
  61. content,
  62. ledger: JSON.stringify(ledgerData),
  63. ledgerSpreadSetting: JSON.stringify(spreadConst.ledgerSpread),
  64. posSpreadSetting: JSON.stringify(spreadConst.ledgerPosSpread),
  65. tenderMenu,
  66. preUrl: '/tender/' + tenderId,
  67. measureType,
  68. };
  69. await this.layout('ledger/explode.ejs', renderData, 'ledger/explode_modal.ejs');
  70. } catch (err) {
  71. this.log(err);
  72. await this.layout('/dashboard');
  73. }
  74. }
  75. /**
  76. * 检查标段是否只读(审核中,审核完成)
  77. * @param {Object} tenderData
  78. * @returns {boolean}
  79. * @private
  80. */
  81. _ledgerReadOnly (tenderData) {
  82. return tenderData.ledger_status === auditConst.status.checking || tenderData.ledger_status === auditConst.status.checked;
  83. }
  84. /**
  85. * 获取子节点 (Ajax)
  86. * @param ctx
  87. * @return {Promise<void>}
  88. */
  89. async getChildren(ctx) {
  90. const responseData = {
  91. err: 0,
  92. msg: '',
  93. data: [],
  94. };
  95. try {
  96. const tenderId = ctx.params.id;
  97. if (!tenderId) {
  98. throw '当前未打开标段';
  99. }
  100. const data = JSON.parse(ctx.request.body.data);
  101. const id = data.ledger_id;
  102. if (isNaN(id) || id <= 0) {
  103. throw '参数错误';
  104. }
  105. responseData.data = await ctx.service.ledger.getChildrenByParentId(tenderId, id);
  106. } catch (err) {
  107. responseData.err = 1;
  108. responseData.msg = err;
  109. }
  110. ctx.body = responseData;
  111. }
  112. /**
  113. * 树结构基本操作(增、删、上下移、升降级)(Ajax)
  114. * @param {Object} ctx - egg全局变量
  115. * @return {Promise<void>}
  116. */
  117. async baseOperation(ctx) {
  118. const responseData = {
  119. err: 0,
  120. msg: '',
  121. data: [],
  122. };
  123. try {
  124. const tenderId = ctx.params.id;
  125. if (!tenderId) {
  126. throw '当前未打开标段';
  127. }
  128. const tenderData = await ctx.service.tender.getDataById(tenderId);
  129. if (!tenderData || tenderData.user_id !== ctx.session.sessionUser.accountId || this._ledgerReadOnly(tenderData)) {
  130. throw '标段数据错误';
  131. }
  132. const data = JSON.parse(ctx.request.body.data);
  133. if ((isNaN(data.id) || data.id <= 0) || (!data.postType)) {
  134. throw '参数错误';
  135. }
  136. switch (data.postType) {
  137. case 'add':
  138. responseData.data = await ctx.service.ledger.addNode(tenderId, data.id);
  139. break;
  140. case 'delete':
  141. responseData.data = await ctx.service.ledger.deleteNode(tenderId, data.id);
  142. break;
  143. case 'up-move':
  144. responseData.data = await ctx.service.ledger.upMoveNode(tenderId, data.id);
  145. break;
  146. case 'down-move':
  147. responseData.data = await ctx.service.ledger.downMoveNode(tenderId, data.id);
  148. break;
  149. case 'up-level':
  150. responseData.data = await ctx.service.ledger.upLevelNode(tenderId, data.id);
  151. break;
  152. case 'down-level':
  153. responseData.data = await ctx.service.ledger.downLevelNode(tenderId, data.id);
  154. break;
  155. default:
  156. throw '未知操作';
  157. }
  158. } catch (err) {
  159. responseData.err = 1;
  160. responseData.msg = err;
  161. this.log(err);
  162. }
  163. ctx.body = responseData;
  164. }
  165. /**
  166. * 提交更新数据 (Ajax)
  167. * @param ctx
  168. * @return {Promise<void>}
  169. */
  170. async updateInfo(ctx) {
  171. const responseData = {
  172. err: 0,
  173. msg: '',
  174. data: [],
  175. };
  176. try {
  177. const tenderId = ctx.params.id;
  178. if (!tenderId) {
  179. throw '当前未打开标段';
  180. }
  181. const tenderData = await ctx.service.tender.getDataById(tenderId);
  182. if (!tenderData || tenderData.user_id !== ctx.session.sessionUser.accountId || this._ledgerReadOnly(tenderData)) {
  183. throw '标段数据错误';
  184. }
  185. const data = JSON.parse(ctx.request.body.data);
  186. if (data instanceof Array) {
  187. responseData.data = await ctx.service.ledger.updateInfos(tenderId, data);
  188. } else {
  189. responseData.data = await ctx.service.ledger.updateInfo(tenderId, data);
  190. }
  191. } catch (err) {
  192. responseData.err = 1;
  193. responseData.msg = err;
  194. }
  195. ctx.body = responseData;
  196. }
  197. async update(ctx) {
  198. const responseData = {
  199. err: 0,
  200. msg: '',
  201. data: [],
  202. };
  203. try {
  204. const tenderId = parseInt(ctx.params.id);
  205. if (!tenderId) {
  206. throw '当前未打开标段';
  207. }
  208. const tenderData = await ctx.service.tender.getDataById(tenderId);
  209. if (!tenderData || tenderData.user_id !== ctx.session.sessionUser.accountId || this._ledgerReadOnly(tenderData)) {
  210. throw '标段数据错误';
  211. }
  212. const data = JSON.parse(ctx.request.body.data);
  213. responseData.data = await ctx.service.ledger.updateCalc(tenderId, data);
  214. } catch (err) {
  215. this.log(err);
  216. responseData.err = 1;
  217. responseData.msg = err;
  218. }
  219. ctx.body = responseData;
  220. }
  221. /**
  222. * 复制粘贴整块 (Ajax)
  223. *
  224. * @param ctx
  225. * @return {Promise<void>}
  226. */
  227. async pasteBlock(ctx) {
  228. const responseData = {
  229. err: 0,
  230. msg: '',
  231. data: [],
  232. };
  233. try {
  234. const tenderId = ctx.params.id;
  235. if (!tenderId) {
  236. throw '当前未打开标段';
  237. }
  238. const tenderData = await ctx.service.tender.getDataById(tenderId);
  239. if (!tenderData || tenderData.user_id !== ctx.session.sessionUser.accountId || this._ledgerReadOnly(tenderData)) {
  240. throw '标段数据错误';
  241. }
  242. const data = JSON.parse(ctx.request.body.data);
  243. if ((isNaN(data.id) || data.id <= 0) || (!data.block || data.block.length <= 0)) {
  244. throw '参数错误';
  245. }
  246. responseData.data = await ctx.service.ledger.pasteBlock(tenderId, data.id, data.block);
  247. } catch (err) {
  248. responseData.err = 1;
  249. responseData.msg = err;
  250. }
  251. ctx.body = responseData;
  252. }
  253. /**
  254. * 从标准项目表添加数据 (Ajax)
  255. * @param ctx
  256. * @returns {Promise<void>}
  257. */
  258. async addFromStandardLib(ctx) {
  259. const responseData = {
  260. err: 0,
  261. msg: '',
  262. data: [],
  263. };
  264. try {
  265. const tenderId = ctx.params.id;
  266. if (!tenderId) {
  267. throw '当前未打开标段';
  268. }
  269. const tenderData = await ctx.service.tender.getDataById(tenderId);
  270. if (!tenderData || tenderData.user_id !== ctx.session.sessionUser.accountId || this._ledgerReadOnly(tenderData)) {
  271. throw '标段数据错误';
  272. }
  273. const data = JSON.parse(ctx.request.body.data);
  274. if ((isNaN(data.id) || data.id <= 0) || !data.stdType || !data.stdNode) {
  275. throw '参数错误';
  276. }
  277. //todo 校验项目是否使用该库的权限
  278. let stdLib;
  279. switch (data.stdType) {
  280. case 'chapter':
  281. stdLib = ctx.service.stdChapter;
  282. break;
  283. case 'bills':
  284. stdLib = ctx.service.stdBills;
  285. break;
  286. default:
  287. throw '未知标准库';
  288. }
  289. const stdData = await stdLib.getDataByDataId(data.stdLibId, data.stdNode);
  290. const addType = stdDataAddType.withParent;
  291. switch (addType) {
  292. case stdDataAddType.self:
  293. responseData.data = await ctx.service.ledger.addStdNode(tenderId, data.id, stdData);
  294. break;
  295. case stdDataAddType.withParent:
  296. responseData.data = await ctx.service.ledger.addStdNodeWithParent(tenderId, stdData, stdLib);
  297. break;
  298. default:
  299. throw '未知添加方法';
  300. }
  301. } catch (err) {
  302. responseData.err = 1;
  303. responseData.msg = err;
  304. }
  305. ctx.body = responseData;
  306. }
  307. /**
  308. * 批量插入数据 (Ajax)
  309. *
  310. * data = {id, batchData, batchType}
  311. * data.batchType = 'batchInsertChild'/'batchInsertNext'
  312. * data.batchData = [{name, children}] -- 项目节列表
  313. * data.batchData.children = [{code, name, unit, unit_price, quantity}] -- 工程量清单列表
  314. *
  315. * @param ctx
  316. * @returns {Promise<void>}
  317. */
  318. async batchInsert(ctx) {
  319. const responseData = {
  320. err: 0,
  321. msg: '',
  322. data: [],
  323. };
  324. try {
  325. const tenderId = ctx.params.id;
  326. if (!tenderId) {
  327. throw '当前未打开标段';
  328. }
  329. const tenderData = await ctx.service.tender.getDataById(tenderId);
  330. if (!tenderData || tenderData.user_id !== ctx.session.sessionUser.accountId || this._ledgerReadOnly(tenderData)) {
  331. throw '标段数据错误';
  332. }
  333. const data = JSON.parse(ctx.request.body.data);
  334. if ((isNaN(data.id) || data.id <= 0) || !data.batchType) {
  335. throw '参数错误';
  336. }
  337. switch (data.batchType) {
  338. case 'child':
  339. responseData.data = await ctx.service.ledger.batchInsertChild(tenderId, data.id, data.batchData);
  340. break;
  341. case 'next':
  342. responseData.data = await ctx.service.ledger.batchInsertNext(tenderId, data.id, data.batchData);
  343. break;
  344. default:
  345. throw '参数错误';
  346. }
  347. } catch (err) {
  348. this.log(err);
  349. responseData.err = 1;
  350. responseData.msg = err;
  351. }
  352. ctx.body = responseData;
  353. }
  354. /**
  355. * 查询
  356. *
  357. * @param ctx
  358. * @returns {Promise<void>}
  359. */
  360. async search(ctx) {
  361. const responseData = {
  362. err: 0,
  363. msg: '',
  364. data: [],
  365. };
  366. try {
  367. const tenderId = ctx.params.id;
  368. if (!tenderId) {
  369. throw '当前未打开标段';
  370. }
  371. const data = JSON.parse(ctx.request.body.data);
  372. if (!data.keyword || data.keyword === '') {
  373. throw '参数错误';
  374. }
  375. responseData.data = await ctx.service.ledger.search(tenderId, {
  376. value: ctx.app.mysql.escape('%' + data.keyword + '%'),
  377. operate: 'Like',
  378. fields: ['code', 'b_code', 'name'],
  379. });
  380. } catch (err) {
  381. this.log(err);
  382. responseData.err = 1;
  383. responseData.msg = err;
  384. }
  385. ctx.body = responseData;
  386. }
  387. /**
  388. * 定位
  389. * @param ctx
  390. * @returns {Promise<void>}
  391. */
  392. async locate(ctx) {
  393. const responseData = {
  394. err: 0,
  395. msg: '',
  396. data: [],
  397. };
  398. try {
  399. const tenderId = ctx.params.id;
  400. if (!tenderId) {
  401. throw '当前未打开标段';
  402. }
  403. const data = JSON.parse(ctx.request.body.data);
  404. if ((isNaN(data.id) || data.id <= 0)) {
  405. throw '参数错误';
  406. }
  407. responseData.data = await ctx.service.ledger.locateNode(tenderId, data.id);
  408. } catch (err) {
  409. this.log(err);
  410. responseData.err = 1;
  411. responseData.msg = err;
  412. }
  413. ctx.body = responseData;
  414. }
  415. /**
  416. * 获取全部子节点
  417. *
  418. * @param ctx
  419. * @returns {Promise<void>}
  420. */
  421. async posterity(ctx) {
  422. const responseData = {
  423. err: 0,
  424. msg: '',
  425. data: [],
  426. };
  427. try {
  428. const tenderId = ctx.params.id;
  429. if (!tenderId) {
  430. throw '当前未打开标段';
  431. }
  432. const data = JSON.parse(ctx.request.body.data);
  433. if ((isNaN(data.id) || data.id <= 0)) {
  434. throw '参数错误';
  435. }
  436. const expandData = await ctx.service.ledger.getPosterityByParentId(tenderId, data.id);
  437. responseData.data = { expand: expandData };
  438. } catch (err) {
  439. this.log(err);
  440. responseData.err = 1;
  441. responseData.msg = err;
  442. }
  443. ctx.body = responseData;
  444. }
  445. /**
  446. * 获取部位明细数据(Ajax)
  447. *
  448. * @param ctx
  449. * @returns {Promise<void>}
  450. */
  451. async pos(ctx) {
  452. try {
  453. const tenderId = ctx.params.id;
  454. if (!tenderId) {
  455. throw '当前未打开标段';
  456. }
  457. await this.checkMeasureType(tenderId, measureType.tz.value);
  458. const condition = JSON.parse(ctx.request.body.data) || {};
  459. condition.tid = tenderId;
  460. const posData = await ctx.service.pos.getPosData(condition);
  461. ctx.body = {err: 0, msg: '', data: posData};
  462. } catch (err) {
  463. this.log(err);
  464. ctx.body = {err: 1, msg: err.toString(), data: []};
  465. }
  466. }
  467. /**
  468. * 更新部位明细数据
  469. *
  470. * @param ctx
  471. * @returns {Promise<void>}
  472. */
  473. async posUpdate(ctx) {
  474. try {
  475. const tenderId = ctx.params.id;
  476. if (!tenderId) {
  477. throw '当前未打开标段';
  478. }
  479. await this.checkMeasureType(tenderId, measureType.tz.value);
  480. const data = JSON.parse(ctx.request.body.data);
  481. const responseData = await ctx.service.pos.savePosData(data, tenderId);
  482. ctx.body = { err: 0, msg: '', data: responseData };
  483. } catch(err) {
  484. this.log(err);
  485. ctx.body = { err: 1, msg: err.toString(), data: null };
  486. }
  487. }
  488. /**
  489. * 台账变更页面 (Get)
  490. *
  491. * @param {object} ctx - egg全局变量
  492. * @return {void}
  493. */
  494. async change(ctx) {
  495. try {
  496. const renderData = await this.getCommonRenderData(ctx);
  497. await this.layout('ledger/change.ejs', renderData, 'ledger/change_modal.ejs');
  498. } catch(err) {
  499. this.log(err);
  500. ctx.redirect(ctx.request.header.referer);
  501. }
  502. }
  503. /**
  504. * 计量台账页面 (Get)
  505. *
  506. * @param {object} ctx - egg全局变量
  507. * @return {void}
  508. */
  509. async index(ctx) {
  510. const renderData = {};
  511. await this.layout('ledger/index.ejs', renderData);
  512. }
  513. }
  514. return LedgerController;
  515. };