spss_controller.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. 'use strict';
  2. /**
  3. * 标段对比 控制器
  4. *
  5. * @author Mai
  6. * @date 2020/2/21
  7. * @version
  8. */
  9. const measureType = require('../const/tender').measureType;
  10. const status = require('../const/audit').stage.status;
  11. module.exports = app => {
  12. class SpssController extends app.BaseController {
  13. /**
  14. * 构造函数
  15. *
  16. * @param {Object} ctx - egg全局context
  17. * @return {void}
  18. */
  19. constructor(ctx) {
  20. super(ctx);
  21. ctx.showProject = true;
  22. }
  23. async info(ctx) {
  24. try {
  25. const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.subProject);
  26. const renderData = {
  27. categoryData,
  28. jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.spss.info)
  29. };
  30. await this.layout('spss/info.ejs', renderData, 'spss/gather_select_modal.ejs');
  31. } catch (err) {
  32. ctx.helper.log(err);
  33. }
  34. }
  35. async gatherLedger(ctx) {
  36. try {
  37. const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.subProject);
  38. const renderData = {
  39. categoryData,
  40. jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.spss.gatherLedger)
  41. };
  42. await this.layout('spss/gather_ledger.ejs', renderData, 'spss/gather_select_modal.ejs');
  43. } catch (err) {
  44. ctx.helper.log(err);
  45. }
  46. }
  47. async gatherStage(ctx) {
  48. try {
  49. const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.subProject);
  50. const renderData = {
  51. categoryData,
  52. jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.spss.gatherStage)
  53. };
  54. await this.layout('spss/gather_stage.ejs', renderData, 'spss/gather_select_modal.ejs');
  55. } catch (err) {
  56. ctx.helper.log(err);
  57. }
  58. }
  59. async gatherStageExtra(ctx) {
  60. try {
  61. const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.subProject);
  62. const renderData = {
  63. categoryData,
  64. jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.spss.gatherStageExtra)
  65. };
  66. await this.layout('spss/gather_stage_extra.ejs', renderData, 'spss/gather_select_modal.ejs');
  67. } catch (err) {
  68. ctx.helper.log(err);
  69. }
  70. }
  71. async compareLedger(ctx) {
  72. try {
  73. const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.subProject);
  74. const renderData = {
  75. categoryData,
  76. jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.spss.compareLedger)
  77. };
  78. await this.layout('spss/compare_ledger.ejs', renderData, 'spss/compare_select_modal.ejs');
  79. } catch (err) {
  80. ctx.helper.log(err);
  81. }
  82. }
  83. async compareStage(ctx) {
  84. try {
  85. const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.subProject);
  86. const renderData = {
  87. categoryData,
  88. jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.spss.compareStage),
  89. };
  90. await this.layout('spss/compare_stage.ejs', renderData, 'spss/compare_select_modal.ejs');
  91. } catch (err) {
  92. ctx.helper.log(err);
  93. }
  94. }
  95. async _loadInfoData(tender) {
  96. }
  97. async _loadLedgerData(tender) {
  98. const bills = await this.ctx.service.ledger.getAllDataByCondition({
  99. columns: ['id', 'ledger_id', 'ledger_pid', 'level', 'full_path', 'is_leaf', 'order', 'code', 'b_code', 'name', 'unit', 'unit_price', 'quantity', 'total_price'],
  100. where: { tender_id: tender.id },
  101. });
  102. const pos = await this.ctx.service.pos.getAllDataByCondition({
  103. columns: ['id', 'lid', 'name', 'quantity'],
  104. where: { tid: tender.id },
  105. });
  106. return [bills, pos];
  107. }
  108. async _loadDealBillsData(tender) {
  109. }
  110. async _getValidStages(tenderId, sort = 'desc') {
  111. const accountId = this.ctx.session.sessionUser.accountId;
  112. const stages = await this.ctx.service.stage.getAllDataByCondition({ where: { tid: tenderId }, orders: [['order', sort]] });
  113. return stages.filter(s => { return s.status !== status.uncheck || s.user_id === accountId; });
  114. }
  115. async _filterOrder(tender, order) {
  116. const stages = await this._getValidStages(tender.id);
  117. return { type: 'stage', stage: this.ctx.helper._.find(stages, { order }) };
  118. }
  119. async _filterMonth(tender, month) {
  120. const stages = await this._getValidStages(tender.id);
  121. return { type: 'stage', stage: this.ctx.helper._.find(stages, { s_time: month }) };
  122. }
  123. async _filterFinal(tender) {
  124. const stages = await this._getValidStages(tender.id);
  125. return { type: 'stage', stage: stages[0] };
  126. }
  127. async _filterCheckedFinal(tender) {
  128. const stages = await this._getValidStages(tender.id);
  129. const checkedStages = stages.filter(x => { return x.status === status.checked; });
  130. return { type: 'stage', stage: checkedStages[0] };
  131. }
  132. async _filterOrderZone(tender, zone) {
  133. let [iBegin, iEnd] = zone.split(':');
  134. iBegin = this.ctx.helper._.toInteger(iBegin) || 0;
  135. iEnd = this.ctx.helper._.toInteger(iEnd) || 0;
  136. const stages = await this._getValidStages(tender.id, 'asc'), validStages = [];
  137. let preStage, endStage;
  138. for (const stage of stages) {
  139. if (stage.order < iBegin) {
  140. if (!preStage || preStage.order < stage.order) preStage = stage;
  141. } else if (stage.order > iEnd) {
  142. if (!endStage || endStage.order > stage.order) endStage = stage;
  143. } else {
  144. validStages.push(stage);
  145. }
  146. }
  147. return { type: 'stages', stages: validStages, preStage, endStage };
  148. }
  149. async _filterTimeZone(tender, zone) {
  150. const times = zone.split(' - ');
  151. if (times.length !== 2) throw '选择的汇总周期无效';
  152. const beginTime = moment(times[0], 'YYYY-MM');
  153. const endTime = moment(times[1], 'YYYY-MM');
  154. const stages = await this._getValidStages(tender.id, 'asc'), validStages = [];
  155. let preStage, endStage;
  156. for (const stage of stages) {
  157. const sTime = moment(stage.s_time, 'YYYY-MM');
  158. if (sTime.isBetween(beginTime, endTime, null, '[]')) {
  159. validStages.push(stage);
  160. } else if (sTime.isBefore(beginTime)) {
  161. if (!preStage || moment(preStage.s_time, 'YYYY-MM').isBefore(sTime)) preStage = stage;
  162. } else if (sTime.isAfter(endTime)) {
  163. if (!endStage || moment(endStage.s_time, 'YYYY-MM').isAfter(sTime)) endStage = stage;
  164. }
  165. }
  166. return { type: 'stages', stages: validStages, preStage, endStage };
  167. }
  168. async _filterStages(tender, stageInfo) {
  169. switch (stageInfo.type) {
  170. case 'stage':
  171. return await this._filterOrder(tender, stageInfo.stage);
  172. case 'month':
  173. return await this._filterMonth(tender, stageInfo.month);
  174. case 'final':
  175. return await this._filterFinal(tender);
  176. case 'checked-final':
  177. return await this._filterCheckedFinal(tender);
  178. case 'zone':
  179. return await this._filterTimeZone(tender, stageInfo.zone);
  180. case 'stage-zone':
  181. return await this._filterOrderZone(tender, stageInfo.stage_zone);
  182. default:
  183. return;
  184. }
  185. }
  186. async _loadStageData(tender, stage) {
  187. await this.ctx.service.stage.doCheckStage(stage);
  188. const bills = await this.ctx.service.ledger.getAllDataByCondition({
  189. columns: ['id', 'ledger_id', 'ledger_pid', 'level', 'full_path', 'is_leaf', 'order', 'code', 'b_code', 'name', 'unit', 'unit_price', 'quantity', 'total_price'],
  190. where: { tender_id: tender.id },
  191. });
  192. const curStage = stage.readOnly
  193. ? await this.ctx.service.stageBills.getAuditorStageData2(tender.id, stage.id, stage.curTimes, stage.curOrder)
  194. : await this.ctx.service.stageBills.getLastestStageData2(tender.id, stage.id);
  195. const preStage = stage.preCheckedStage ? await this.ctx.service.stageBillsFinal.getFinalData(tender, stage.preCheckedStage.order) : [];
  196. const bpcStage = await this.ctx.service.stageBillsPc.getAllDataByCondition({ where: { sid: stage.id } });
  197. this.ctx.helper.assignRelaData(bills, [
  198. { data: curStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: '', relaId: 'lid' },
  199. { data: preStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: 'pre_', relaId: 'lid' },
  200. { data: bpcStage, fields: ['contract_pc_tp', 'qc_pc_tp', 'pc_tp'], prefix: '', relaId: 'lid' },
  201. ]);
  202. const pos = await this.ctx.service.pos.getAllDataByCondition({
  203. columns: ['id', 'lid', 'name', 'quantity'],
  204. where: { tid: tender.id },
  205. });
  206. const curStagePos = stage.readOnly
  207. ? await this.ctx.service.stagePos.getAuditorStageData2(tender.id, stage.id, stage.curTimes, stage.curOrder)
  208. : await this.ctx.service.stagePos.getLastestStageData2(tender.id, stage.id);
  209. const preStagePos = stage.preCheckedStage ? await this.ctx.service.stagePosFinal.getFinalData(tender, stage.preCheckedStage.order) : [];
  210. this.ctx.helper.assignRelaData(pos, [
  211. { data: curStagePos, fields: ['contract_qty', 'qc_qty'], prefix: '', relaId: 'pid' },
  212. { data: preStagePos, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid' },
  213. ]);
  214. return [bills, pos];
  215. }
  216. async _loadStagesData(tender, stages, preStage, endStage) {
  217. const indexPre = 'id_';
  218. const sumAssignRelaData = function (index, rela) {
  219. const loadFields = function (datas, fields, prefix, relaId) {
  220. for (const d of datas) {
  221. const key = indexPre + d[relaId];
  222. const m = index[key];
  223. if (m) {
  224. for (const f of fields) {
  225. if (d[f] !== undefined) {
  226. m[prefix + f] = helper.add(m[prefix + f], d[f]);
  227. }
  228. }
  229. }
  230. }
  231. };
  232. for (const r of rela) {
  233. loadFields(r.data, r.fields, r.prefix, r.relaId);
  234. }
  235. };
  236. const bills = await this.ctx.service.ledger.getAllDataByCondition({
  237. columns: ['id', 'ledger_id', 'ledger_pid', 'level', 'full_path', 'is_leaf', 'order', 'code', 'b_code', 'name', 'unit', 'unit_price', 'quantity', 'total_price'],
  238. where: { tender_id: tender.id },
  239. });
  240. const pos = await this.ctx.service.pos.getAllDataByCondition({
  241. columns: ['id', 'lid', 'name', 'quantity'],
  242. where: { tid: tender.id },
  243. });
  244. let billsIndexData = {};
  245. for (const bd of billsData) {
  246. billsIndexData[indexPre + bd.id] = bd;
  247. }
  248. let posIndexData = {};
  249. for (const p of posData) {
  250. posIndexData[indexPre + p.id] = p;
  251. }
  252. if (preStage) {
  253. const endStage = await this.ctx.service.stageBillsFinal.getFinalData(tender, preStage.order);
  254. sumAssignRelaData(billsIndexData, [
  255. { data: endStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: 'pre_', relaId: 'lid'},
  256. ]);
  257. const endStagePos = await this.ctx.service.stagePosFinal.getFinalData(tender, preStage.order);
  258. sumAssignRelaData(posIndexData, [
  259. {data: endStagePos, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'lid'},
  260. ]);
  261. }
  262. for (const stage of stages) {
  263. await this.ctx.service.stage.doCheckStage(stage);
  264. const curStage = stage.readOnly
  265. ? await this.ctx.service.stageBills.getAuditorStageData2(tender.id, stage.id, stage.curTimes, stage.curOrder)
  266. : await this.ctx.service.stageBills.getLastestStageData2(tender.id, stage.id);
  267. const bpcStage = await this.ctx.service.stageBillsPc.getAllDataByCondition({ where: { sid: stage.id } });
  268. sumAssignRelaData(billsIndexData, [
  269. {data: curStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: '', relaId: 'lid'},
  270. { data: bpcStage, fields: ['contract_pc_tp', 'qc_pc_tp', 'pc_tp'], prefix: '', relaId: 'lid' },
  271. ]);
  272. const curStagePos = stage.readOnly
  273. ? await this.ctx.service.stagePos.getAuditorStageData2(tender.id, stage.id, stage.curTimes, stage.curOrder)
  274. : await this.ctx.service.stagePos.getLastestStageData2(tender.id, stage.id);
  275. sumAssignRelaData(posIndexData, [
  276. {data: curStagePos, fields: ['contract_qty', 'qc_qty'], prefix: '', relaId: 'pid'},
  277. ]);
  278. }
  279. return [bills, pos];
  280. }
  281. async _loadStageLedgerData(tender, filter) {
  282. return filter.type === 'stage'
  283. ? await this._loadStageData(tender, filter.stage)
  284. : await this._loadStagesData(tender, filter.stages, filter.preStage, filter.endStage);
  285. }
  286. async _loadJgclData(tender, stages) {
  287. };
  288. async _loadYjclData(tender, stages) {
  289. };
  290. async _loadBonusData(tender, stages) {
  291. };
  292. async _loadSafeProdData(tender, stages) {
  293. };
  294. async _loadTempLandData(tender, stages) {
  295. };
  296. async _loadOtherData(tender, stages) {
  297. };
  298. async _loadTenderData(tid, filter, stageInfo) {
  299. this.ctx.tender = null;
  300. const tender = await this.ctx.service.tender.checkTender(tid);
  301. const result = { id: tender.id, name: tender.name };
  302. let stageFilter = null;
  303. for (const f of filter) {
  304. switch (f) {
  305. case 'info':
  306. result.info = await this._loadInfoData(tender);
  307. break;
  308. case 'ledger':
  309. if (filter.indexOf('stage') < 0) [result.bills, result.pos] = await this._loadLedgerData(tender);
  310. break;
  311. case 'stage':
  312. if (!stageFilter) stageFilter = await this._filterStages(tender, stageInfo);
  313. [result.bills, result.pos, result.stages] = await this._loadStageLedgerData(tender, stageFilter);
  314. break;
  315. case 'jgcl':
  316. if (!stageFilter) stageFilter = await this._filterStages(tender, stageInfo);
  317. result.jgcl = await this._loadJgclData(tender, stageFilter);
  318. break;
  319. case 'yjcl':
  320. if (!stageFilter) stageFilter = await this._filterStages(tender, stageInfo);
  321. result.jgcl = await this._loadYjclData(tender, stageFilter);
  322. break;
  323. case 'bonus':
  324. if (!stageFilter) stageFilter = await this._filterStages(tender, stageInfo);
  325. result.jgcl = await this._loadBonusData(tender, stageFilter);
  326. break;
  327. case 'safeProd':
  328. if (!stageFilter) stageFilter = await this._filterStages(tender, stageInfo);
  329. result.jgcl = await this._loadSafeProdData(tender, stageFilter);
  330. break;
  331. case 'tempLand':
  332. if (!stageFilter) stageFilter = await this._filterStages(tender, stageInfo);
  333. result.jgcl = await this._loadTempLandData(tender, stageFilter);
  334. break;
  335. case 'other':
  336. if (!stageFilter) stageFilter = await this._filterStages(tender, stageInfo);
  337. result.jgcl = await this._loadOtherData(tender, stageFilter);
  338. break;
  339. default: throw '查询的数据类型未定义';
  340. }
  341. }
  342. return result;
  343. }
  344. async load(ctx) {
  345. try {
  346. const data = JSON.parse(ctx.request.body.data);
  347. const filter = data.filter.split(',');
  348. const result = [];
  349. for (const t of data.tender) {
  350. result.push(await this._loadTenderData(t.tid, filter, t.stageInfo));
  351. }
  352. ctx.body = { err: 0, msg: '', data: result };
  353. } catch (err) {
  354. ctx.log(err);
  355. ctx.ajaxErrorBody(err, '加载数据错误');
  356. }
  357. }
  358. async _getTzData(tid, includePos = false) {
  359. const tender = await this.ctx.service.tender.getTender(tid);
  360. if (!tender || tender.project_id !== this.ctx.session.sessionProject.id) {
  361. throw '不存在该标段';
  362. }
  363. const bills = await this.ctx.service.ledger.getData(tid);
  364. const pos = tender.measure_type === measureType.tz.value || includePos
  365. ? await this.ctx.service.pos.getPosData({tid: tid})
  366. : [];
  367. return { id: tid, name: tender.name, bills: bills, pos: pos };
  368. }
  369. async _checkStage(tid, sorder) {
  370. const stage = await this.service.stage.getDataByCondition({ tid: tid, order: sorder });
  371. if (!stage) throw '期数据错误';
  372. await this.service.stage.doCheckStage(stage);
  373. return stage;
  374. }
  375. async _getStageData(tid, sorder) {
  376. const data = await this._getTzData(tid, true);
  377. const stage = await this._checkStage(tid, sorder);
  378. const bills = await this.ctx.service.stageBills.getAuditorStageData2(tid, stage.id, stage.curTimes, stage.curOrder);
  379. const pos = await this.ctx.service.stagePos.getAuditorStageData2(tid, stage.id, stage.curTimes, stage.curOrder);
  380. data.stage = {
  381. sid: stage.id, sorder: stage.order, curTimes: stage.curTimes, curOrder: stage.curOrder,
  382. bills: bills, pos: pos
  383. };
  384. return data;
  385. }
  386. /**
  387. * 检测台账 页面
  388. *
  389. * @param {Object} ctx - egg全局变量
  390. * @return {void}
  391. */
  392. async checkTz(ctx) {
  393. try {
  394. const renderData = {
  395. jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.tools.checkTz)
  396. };
  397. await this.layout('spss/check_tz.ejs', renderData);
  398. } catch (err) {
  399. ctx.helper.log(err);
  400. }
  401. }
  402. /**
  403. * 获取 期计量 汇总 数据(Ajax)
  404. * @param ctx
  405. * @returns {Promise<void>}
  406. */
  407. async loadBaseData(ctx) {
  408. try {
  409. const data = JSON.parse(ctx.request.body.data);
  410. const responseData = {err: 0, msg: '', data: []};
  411. responseData.data = await this._getTzData(data.id);
  412. ctx.body = responseData;
  413. } catch (err) {
  414. ctx.helper.log(err);
  415. ctx.body = this.ajaxErrorBody(err, '查询数据错误');
  416. }
  417. }
  418. }
  419. return SpssController;
  420. };