budget_final.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author Mai
  6. * @date
  7. * @version
  8. */
  9. const itemsPre = 'id_';
  10. const BillsTree = require('./ledger').billsTree;
  11. const TreeUtils = require('./ledger').treeUtils;
  12. const auditConst = require('../const/audit');
  13. class FinalTree extends BillsTree {
  14. constructor(ctx, setting) {
  15. super(ctx, setting);
  16. this._newId = 1;
  17. this.checkField = ['code', 'name'];
  18. }
  19. get newId() {
  20. return this._newId++;
  21. }
  22. loadNode(node, parent, loadFun) {
  23. if (node.b_code) return;
  24. const checkField = this.checkField;
  25. const siblings = parent ? parent.children : this.children;
  26. let cur = siblings.find(function (x) {
  27. for (const cf of checkField) {
  28. if (x[cf] !== node[cf]) return false;
  29. }
  30. return true;
  31. // return x.code === node.code && x.name === node.name;
  32. });
  33. if (!cur) {
  34. cur = { children: [], code: node.code || '', name: node.name || '', unit: node.unit || '' };
  35. const id = this.newId;
  36. cur[this.setting.id] = id;
  37. cur[this.setting.pid] = parent ? parent[this.setting.id] : this.setting.rootId;
  38. cur[this.setting.fullPath] = parent ? parent[this.setting.fullPath] + '-' + id : '' + id;
  39. cur[this.setting.level] = parent ? parent[this.setting.level] + 1 : 1;
  40. cur[this.setting.order] = siblings.length + 1;
  41. siblings.push(cur);
  42. this.datas.push(cur);
  43. }
  44. loadFun(cur, node);
  45. for (const c of node.children) {
  46. this.loadNode(c, cur, loadFun);
  47. }
  48. }
  49. loadTree(tree, loadFun) {
  50. for (const node of tree.children) {
  51. this.loadNode(node, null, loadFun);
  52. }
  53. }
  54. generateSortNodes() {
  55. const self = this;
  56. const addSortNode = function (node) {
  57. self.nodes.push(node);
  58. for (const c of node.children) {
  59. addSortNode(c);
  60. }
  61. };
  62. this.nodes = [];
  63. for (const n of this.children) {
  64. addSortNode(n);
  65. }
  66. }
  67. afterLoad(fun) {
  68. for (const d of this.datas) {
  69. fun && fun(d);
  70. d.is_leaf = d.children.length === 0;
  71. d.expanded = true;
  72. d.visible = true;
  73. this.items[itemsPre + d[this.setting.id]] = d;
  74. }
  75. this.generateSortNodes();
  76. }
  77. resortChildrenByCustom(fun) {
  78. for (const n of this.nodes) {
  79. if (n.children && n.children.length > 1) {
  80. n.children.sort(fun);
  81. n.children.forEach((x, y) => { x.order = y + 1; });
  82. }
  83. }
  84. this.generateSortNodes();
  85. }
  86. }
  87. class BudgetFinal {
  88. constructor (ctx) {
  89. this.ctx = ctx;
  90. this.budgetSetting = { id: 'tree_id', pid: 'tree_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price'] };
  91. this.tenderSetting = { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price', 'end_gather_tp', 'end_contract_tp', 'end_qc_tp', 'tz_qc_tp'] };
  92. this.finalTree = new FinalTree(this.ctx, { id: 'id', pid: 'pid', order: 'order', level: 'level', fullPath: 'full_path', rootId: -1 });
  93. }
  94. async _loadGu(budget) {
  95. const helper = this.ctx.helper;
  96. const gu = await this.ctx.service.budgetGu.getData(budget.id);
  97. const guTree = new BillsTree(this.ctx, { id: 'tree_id', pid: 'tree_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price'] });
  98. guTree.loadDatas(gu);
  99. guTree.calculateAll();
  100. this.finalTree.loadTree(guTree, function (cur, source) {
  101. cur.base = true;
  102. cur.gu_dgn_qty1 = helper.add(cur.gu_dgn_qty1, source.dgn_qty1);
  103. cur.gu_dgn_qty2 = helper.add(cur.gu_dgn_qty2, source.dgn_qty2);
  104. cur.gu_tp = helper.add(cur.gu_tp, source.total_price);
  105. });
  106. }
  107. async _loadGai(budget) {
  108. const helper = this.ctx.helper;
  109. const gai = await this.ctx.service.budgetGai.getData(budget.id);
  110. const gaiTree = new BillsTree(this.ctx, { id: 'tree_id', pid: 'tree_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price'] });
  111. gaiTree.loadDatas(gai);
  112. gaiTree.calculateAll();
  113. this.finalTree.loadTree(gaiTree, function (cur, source) {
  114. cur.base = true;
  115. cur.gai_dgn_qty1 = helper.add(cur.gai_dgn_qty1, source.dgn_qty1);
  116. cur.gai_dgn_qty2 = helper.add(cur.gai_dgn_qty2, source.dgn_qty2);
  117. cur.gai_tp = helper.add(cur.gai_tp, source.total_price);
  118. });
  119. }
  120. async _loadYu(budget) {
  121. const helper = this.ctx.helper;
  122. const yu = await this.ctx.service.budgetYu.getData(budget.id);
  123. const yuTree = new BillsTree(this.ctx, { id: 'tree_id', pid: 'tree_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price'] });
  124. yuTree.loadDatas(yu);
  125. yuTree.calculateAll();
  126. this.finalTree.loadTree(yuTree, function (cur, source) {
  127. cur.base = true;
  128. cur.yu_dgn_qty1 = helper.add(cur.yu_dgn_qty1, source.dgn_qty1);
  129. cur.yu_dgn_qty2 = helper.add(cur.yu_dgn_qty2, source.dgn_qty2);
  130. cur.yu_tp = helper.add(cur.yu_tp, source.total_price);
  131. });
  132. }
  133. async _loadZb(budget) {
  134. const helper = this.ctx.helper;
  135. const zb = await this.ctx.service.budgetZb.getData(budget.id);
  136. const zbTree = new BillsTree(this.ctx, { id: 'tree_id', pid: 'tree_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price'] });
  137. zbTree.loadDatas(zb);
  138. zbTree.calculateAll();
  139. this.finalTree.loadTree(zbTree, function (cur, source) {
  140. cur.base = true;
  141. cur.zb_dgn_qty1 = helper.add(cur.zb_dgn_qty1, source.dgn_qty1);
  142. cur.zb_dgn_qty2 = helper.add(cur.zb_dgn_qty2, source.dgn_qty2);
  143. cur.zb_tp = helper.add(cur.zb_tp, source.total_price);
  144. });
  145. }
  146. async _loadCtrl(budget) {
  147. const helper = this.ctx.helper;
  148. const ctrl = await this.ctx.service.budgetCtrl.getData(budget.id);
  149. const ctrlTree = new BillsTree(this.ctx, { id: 'tree_id', pid: 'tree_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price'] });
  150. ctrlTree.loadDatas(ctrl);
  151. ctrlTree.calculateAll();
  152. this.finalTree.loadTree(ctrlTree, function (cur, source) {
  153. cur.base = true;
  154. cur.ctrl_dgn_qty1 = helper.add(cur.ctrl_dgn_qty1, source.dgn_qty1);
  155. cur.ctrl_dgn_qty2 = helper.add(cur.ctrl_dgn_qty2, source.dgn_qty2);
  156. cur.ctrl_tp = helper.add(cur.ctrl_tp, source.total_price);
  157. });
  158. }
  159. async _loadReal(budget) {
  160. const helper = this.ctx.helper;
  161. const real = await this.ctx.service.budgetReal.getData(budget.id);
  162. const realTree = new BillsTree(this.ctx, { id: 'tree_id', pid: 'tree_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price'] });
  163. realTree.loadDatas(real);
  164. realTree.calculateAll();
  165. this.finalTree.loadTree(realTree, function (cur, source) {
  166. cur.base = true;
  167. cur.real_dgn_qty1 = helper.add(cur.real_dgn_qty1, source.dgn_qty1);
  168. cur.real_dgn_qty2 = helper.add(cur.real_dgn_qty2, source.dgn_qty2);
  169. cur.real_tp = helper.add(cur.real_tp, source.total_price);
  170. });
  171. }
  172. async _getValidStages(tenderId, sort = 'desc', checked = false) {
  173. const accountId = this.ctx.session.sessionUser.accountId;
  174. const condition = { tid: tenderId };
  175. if (checked) condition.status = auditConst.stage.status.checked;
  176. const stages = await this.ctx.service.stage.getAllDataByCondition({ where: condition, orders: [['order', sort]] });
  177. return stages.filter(s => { return s.status !== auditConst.stage.status.uncheck || s.user_id === accountId; });
  178. }
  179. async _filterOrder(id, order, checked) {
  180. const stages = await this._getValidStages(id, 'desc', checked);
  181. const stage = this.ctx.helper._.find(stages, { order });
  182. if (stage) await this.ctx.service.stage.doCheckStage(stage);
  183. return { type: 'stage', stage, filter: `第${order}期` };
  184. }
  185. async _filterMonth(id, month, checked) {
  186. const stages = await this._getValidStages(id, 'desc', checked);
  187. const stage = this.ctx.helper._.find(stages, { s_time: month });
  188. if (stage) await this.ctx.service.stage.doCheckStage(stage);
  189. return { type: 'stage', stage, filter: month };
  190. }
  191. async _filterFinal(id, checked) {
  192. const stages = await this._getValidStages(id, 'desc', checked);
  193. const stage = stages[0];
  194. if (stage) await this.ctx.service.stage.doCheckStage(stage);
  195. return { type: 'stage', stage, filter: stage ? `第${stage.order}期` : '' };
  196. }
  197. async _filterCheckedFinal(id, checked) {
  198. const stages = await this._getValidStages(id, 'desc', checked);
  199. const checkedStages = stages.filter(x => { return x.status === status.checked; });
  200. const stage = checkedStages[0];
  201. if (stage && stage.status !== auditConst.stage.status.checked) await this.ctx.service.stage.doCheckStage(stage);
  202. return { type: 'stage', stage, filter: stage ? `第${stage.order}期` : '' };
  203. }
  204. async _filterUnderMonth(id, month, checked) {
  205. const stages = await this._getValidStages(id, 'desc', checked);
  206. let stage = this.ctx.helper._.find(stages, { s_time: month });
  207. if (!stage) {
  208. const checkTime = this.ctx.moment(month);
  209. for (const s of stages) {
  210. const rela_time = this.ctx.moment(s.s_time);
  211. if (rela_time.isBefore(checkTime)) {
  212. stage = s;
  213. break;
  214. }
  215. }
  216. }
  217. if (stage) await this.ctx.service.stage.doCheckStage(stage);
  218. return { type: 'stage', stage, filter: stage ? stage.s_time : '' };
  219. }
  220. async _filterStage(tender, stageInfo) {
  221. switch(stageInfo.type) {
  222. case 'stage':
  223. return await this._filterOrder(tender, stageInfo.stage, stageInfo.checked);
  224. case 'month':
  225. return await this._filterMonth(tender, stageInfo.month, stageInfo.checked);
  226. case 'final':
  227. return await this._filterFinal(tender, stageInfo.checked);
  228. case 'checked-final':
  229. return await this._filterCheckedFinal(tender, stageInfo.checked);
  230. case 'under-month':
  231. return await this._filterUnderMonth(tender, stageInfo.month, stageInfo.checked);
  232. default:
  233. return await this._filterFinal(tender, stageInfo.checked);
  234. }
  235. }
  236. async _loadTender(id, stageInfo) {
  237. const helper = this.ctx.helper;
  238. const bills = await this.ctx.service.ledger.getFinalData(id, ['id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
  239. 'code', 'b_code', 'name', 'unit', 'unit_price', 'dgn_qty1', 'dgn_qty2', 'total_price']);
  240. const dgnData = await this.ctx.service.stageBillsDgn.getDgnData(id);
  241. // 使用最新一期对比
  242. const stageFilter = await this._filterStage(id, stageInfo);
  243. if (!stageFilter.stage) {
  244. helper.assignRelaData(bills, [
  245. { data: dgnData, fields: ['deal_dgn_qty1', 'deal_dgn_qty2', 'c_dgn_qty1', 'c_dgn_qty2'], prefix: '', relaId: 'id' },
  246. ]);
  247. this.final.tender_info.push({ id, stageCount: 0 });
  248. } else if (stageFilter.stage.status === auditConst.stage.status.checked) {
  249. const finalBills = await this.ctx.service.stageBillsFinal.getFinalData({ id }, stageFilter.stage.order);
  250. helper.assignRelaData(bills, [
  251. { data: finalBills, fields: ['contract_tp', 'qc_tp'], prefix: 'end_', relaId: 'lid' },
  252. { data: dgnData, fields: ['deal_dgn_qty1', 'deal_dgn_qty2', 'c_dgn_qty1', 'c_dgn_qty2'], prefix: '', relaId: 'id' },
  253. ]);
  254. bills.forEach(b => {
  255. b.end_gather_tp = helper.add(b.end_qc_tp, b.end_contract_tp);
  256. });
  257. this.final.tender_info.push({ id, stageOrder: stageFilter.stage.order });
  258. } else {
  259. const curBills = stageFilter.stage.readOnly
  260. ? await this.ctx.service.stageBills.getAuditorStageData2(id, stageFilter.stage.id, stageFilter.stage.curTimes, stageFilter.stage.curOrder)
  261. : await this.ctx.service.stageBills.getLastestStageData2(id, stageFilter.stage.id);
  262. const preBills = stageFilter.stage.preCheckedStage ? await this.ctx.service.stageBillsFinal.getFinalData({ id }, stageFilter.stage.preCheckedStage.order) : [];
  263. const bpcData = await this.ctx.service.stageBillsPc.getAllDataByCondition({ where: { sid: stageFilter.stage.id } });
  264. helper.assignRelaData(bills, [
  265. { data: curBills, fields: ['contract_tp', 'qc_tp'], prefix: '', relaId: 'lid' },
  266. { data: preBills, fields: ['contract_tp', 'qc_tp'], prefix: 'pre_', relaId: 'lid' },
  267. { data: dgnData, fields: ['deal_dgn_qty1', 'deal_dgn_qty2', 'c_dgn_qty1', 'c_dgn_qty2'], prefix: '', relaId: 'id' },
  268. { data: bpcData, fields: ['contract_pc_tp', 'qc_pc_tp', 'pc_tp', 'org_price'], prefix: '', relaId: 'lid' },
  269. ]);
  270. bills.forEach(b => {
  271. b.end_contract_tp = helper.sum([b.contract_tp, b.pre_contract_tp, b.contract_pc_tp]);
  272. b.end_qc_tp = helper.sum([b.qc_tp, b.pre_qc_tp, b.qc_pc_tp]);
  273. b.end_gather_tp = helper.sum([b.qc_tp, b.contract_tp, b.pre_qc_tp, b.pre_contract_tp, b.pc_tp]);
  274. });
  275. this.final.tender_info.push({ id, stageOrder: stageFilter.stage.order, stageStatus: stageFilter.stage.status, stageFlow: stageFilter.stage.curTimes + '-' + stageFilter.stage.curOrder });
  276. }
  277. const tree = new BillsTree(this.ctx, this.tenderSetting);
  278. tree.loadDatas(bills);
  279. const tenderInfo = await this.ctx.service.tenderInfo.getTenderInfo(id);
  280. const reCalcChange = await this.ctx.service.change.getReCalcChangeData(id, tenderInfo);
  281. TreeUtils.loadChangeData(tree, null, reCalcChange, tenderInfo, helper);
  282. tree.calculateAll();
  283. this.finalTree.loadTree(tree, function (cur, source) {
  284. cur.total_price = helper.add(cur.total_price, source.total_price);
  285. cur.dgn_qty1 = helper.add(cur.dgn_qty1, source.dgn_qty1);
  286. cur.dgn_qty2 = helper.add(cur.dgn_qty2, source.dgn_qty2);
  287. cur.deal_dgn_qty1 = helper.add(cur.deal_dgn_qty1, source.deal_dgn_qty1);
  288. cur.deal_dgn_qty2 = helper.add(cur.deal_dgn_qty2, source.deal_dgn_qty2);
  289. cur.c_dgn_qty1 = helper.add(cur.c_dgn_qty1, source.c_dgn_qty1);
  290. cur.c_dgn_qty2 = helper.add(cur.c_dgn_qty2, source.c_dgn_qty2);
  291. cur.final_dgn_qty1 = helper.sum([cur.final_dgn_qty1, source.deal_dgn_qty1, source.c_dgn_qty1]);
  292. cur.final_dgn_qty2 = helper.sum([cur.final_dgn_qty2, source.deal_dgn_qty2, source.c_dgn_qty2]);
  293. cur.final_contract_tp = helper.add(cur.final_contract_tp, source.end_contract_tp);
  294. cur.final_qc_tp = helper.add(cur.final_qc_tp, source.end_qc_tp);
  295. cur.final_tp = helper.add(cur.final_tp, source.end_gather_tp);
  296. cur.tz_qc_qty = helper.add(cur.tz_qc_qty, source.tz_qc_qty);
  297. cur.tz_qc_tp = helper.add(cur.tz_qc_tp, source.tz_qc_tp);
  298. });
  299. }
  300. async _loadDeal(deal, stage) {
  301. if (!deal || deal.length === 0) return;
  302. this.final.contract = deal;
  303. const helper = this.ctx.helper;
  304. const treeData = await this.ctx.service.contractTree.getAllDataByCondition({ where: { id: deal, spid: this.ctx.subProject.id, contract_type: 1 } });
  305. const contractData = await this.ctx.service.contract.getAllDataByCondition({ where: { id: deal, spid: this.ctx.subProject.id, contract_type: 1 } });
  306. const paySqlParam = [];
  307. const timeFilter = stage.type === 'under-month' ? `AND pay_time <= ? ` : '';
  308. if (stage.type === 'under-month') {
  309. paySqlParam.push(this.ctx.moment(stage.month, 'YYYY-MM').endOf('month').format('YYYY-MM-DD HH:mm:ss'));
  310. }
  311. const checkedFilter = stage.checked && this.ctx.subProject.page_show.openContractPaySubProjectShenpi ? ' AND status = 3 ' : '';
  312. const paySql = `SELECT cid, SUM(yf_price) AS yf_tp FROM ${this.ctx.service.contractPay.tableName}` +
  313. ` WHERE cid IN(${contractData.map(x => { return `'${x.id}'`}).join(', ')}) ` + timeFilter + checkedFilter +
  314. ' GROUP BY cid';
  315. const contractPayData = await this.ctx.service.contractPay.db.query(paySql, paySqlParam);
  316. for (const c of contractData) {
  317. const cp = contractPayData.find(x => { return x.cid === c.id; });
  318. c.yf_tp = cp ? cp.yf_tp || 0 : 0;
  319. }
  320. const tree = new BillsTree(this.ctx, {
  321. id: 'contract_id',
  322. pid: 'contract_pid',
  323. order: 'order',
  324. level: 'level',
  325. rootId: -1,
  326. calcFields: ['total_price', 'yf_tp'],
  327. calc: function (node, helper, decimal) {},
  328. });
  329. tree.loadDatas([...treeData, ...contractData]);
  330. tree.calculateAll();
  331. this.finalTree.loadTree(tree, function (cur, source) {
  332. if (source.c_code) cur.code = source.c_code;
  333. cur.total_price = helper.add(cur.total_price, source.total_price);
  334. cur.final_contract_tp = helper.add(cur.final_contract_tp, source.yf_tp);
  335. cur.final_tp = helper.add(cur.final_tp, source.yf_tp);
  336. });
  337. }
  338. async _afterLoad() {
  339. const helper = this.ctx.helper;
  340. const checkGaiExist = this.finalTree.datas.findIndex(x => {
  341. if (x.gai_tp || x.gai_dgn_qty1 || x.gai_dgn_qty2) return true;
  342. }) >= 0;
  343. this.finalTree.afterLoad(node => {
  344. node.dgn_price = helper.div(node.total_price, node.dgn_qty1, 2);
  345. node.dgn_qty = node.dgn_qty1
  346. ? (node.dgn_qty2 ? node.dgn_qty1 + '/' + node.dgn_qty2 : node.dgn_qty1)
  347. : (node.dgn_qty2 ? '/' + node.dgn_qty2 : '');
  348. node.gu_dgn_price = helper.div(node.gu_tp, node.gu_dgn_qty1, 2);
  349. node.gu_dgn_qty = node.gu_dgn_qty1
  350. ? (node.gu_dgn_qty2 ? node.gu_dgn_qty1 + '/' + node.gu_dgn_qty2 : node.gu_dgn_qty1 + '')
  351. : (node.gu_dgn_qty2 ? '/' + node.gu_dgn_qty2 : '');
  352. node.gai_dgn_price = helper.div(node.gai_tp, node.gai_dgn_qty1, 2);
  353. node.gai_dgn_qty = node.gai_dgn_qty1
  354. ? (node.gai_dgn_qty2 ? node.gai_dgn_qty1 + '/' + node.gai_dgn_qty2 : node.gai_dgn_qty1 + '')
  355. : (node.gai_dgn_qty2 ? '/' + node.gai_dgn_qty2 : '');
  356. node.yu_dgn_price = helper.div(node.yu_tp, node.yu_dgn_qty1, 2);
  357. node.yu_dgn_qty = node.yu_dgn_qty1
  358. ? (node.yu_dgn_qty2 ? node.yu_dgn_qty1 + '/' + node.yu_dgn_qty2 : node.yu_dgn_qty1 + '')
  359. : (node.yu_dgn_qty2 ? '/' + node.yu_dgn_qty2 : '');
  360. node.zb_dgn_price = helper.div(node.zb_tp, node.zb_dgn_qty1, 2);
  361. node.zb_dgn_qty = node.zb_dgn_qty1
  362. ? (node.zb_dgn_qty2 ? node.zb_dgn_qty1 + '/' + node.zb_dgn_qty2 : node.zb_dgn_qty1 + '')
  363. : (node.zb_dgn_qty2 ? '/' + node.zb_dgn_qty2 : '');
  364. node.ctrl_dgn_price = helper.div(node.ctrl_tp, node.ctrl_dgn_qty1, 2);
  365. node.ctrl_dgn_qty = node.ctrl_dgn_qty1
  366. ? (node.ctrl_dgn_qty2 ? node.ctrl_dgn_qty1 + '/' + node.ctrl_dgn_qty2 : node.ctrl_dgn_qty1 + '')
  367. : (node.ctrl_dgn_qty2 ? '/' + node.ctrl_dgn_qty2 : '');
  368. node.real_dgn_price = helper.div(node.real_tp, node.real_dgn_qty1, 2);
  369. node.real_dgn_qty = node.real_dgn_qty1
  370. ? (node.real_dgn_qty2 ? node.real_dgn_qty1 + '/' + node.real_dgn_qty2 : node.real_dgn_qty1 + '')
  371. : (node.real_dgn_qty2 ? '/' + node.real_dgn_qty2 : '');
  372. node.final_dgn_price = helper.div(node.final_tp, node.final_dgn_qty1, 2);
  373. node.final_dgn_qty = node.final_dgn_qty1
  374. ? (node.final_dgn_qty2 ? node.final_dgn_qty1 + '/' + node.final_dgn_qty2 : node.final_dgn_qty1)
  375. : (node.final_dgn_qty2 ? '/' + node.final_dgn_qty2 : '');
  376. if (checkGaiExist) {
  377. node.grow_dgn_qty1 = helper.mul(helper.div(helper.sub(node.final_dgn_qty1, node.gai_dgn_qty1), node.gai_dgn_qty1, 4), 100);
  378. node.grow_dgn_qty2 = helper.mul(helper.div(helper.sub(node.final_dgn_qty2, node.gai_dgn_qty2), node.gai_dgn_qty2, 4), 100);
  379. node.grow_dgn_qty = node.grow_dgn_qty1
  380. ? (node.grow_dgn_qty2 ? node.grow_dgn_qty1 + '/' + node.grow_dgn_qty2 : node.grow_dgn_qty1)
  381. : (node.grow_dgn_qty2 ? '/' + node.grow_dgn_qty2 : '');
  382. node.grow_tp = helper.mul(helper.div(helper.sub(node.final_tp, node.gai_tp), node.gai_tp, 4), 100);
  383. } else {
  384. node.grow_dgn_qty1 = helper.mul(helper.div(helper.sub(node.final_dgn_qty1, node.yu_dgn_qty1), node.yu_dgn_qty1, 4), 100);
  385. node.grow_dgn_qty2 = helper.mul(helper.div(helper.sub(node.final_dgn_qty2, node.yu_dgn_qty2), node.yu_dgn_qty2, 4), 100);
  386. node.grow_dgn_qty = node.grow_dgn_qty1
  387. ? (node.grow_dgn_qty2 ? node.grow_dgn_qty1 + '/' + node.grow_dgn_qty2 : node.grow_dgn_qty1)
  388. : (node.grow_dgn_qty2 ? '/' + node.grow_dgn_qty2 : '');
  389. node.grow_tp = helper.mul(helper.div(helper.sub(node.final_tp, node.yu_tp), node.yu_tp, 4), 100);
  390. }
  391. });
  392. this.finalTree.resortChildrenByCustom(function (x, y) {
  393. const iCode = helper.compareCode(x.code, y.code);
  394. if (iCode) return iCode;
  395. if (!x.name) return -1;
  396. if (!y.name) return 1;
  397. return x.name.localeCompare(y.name);
  398. });
  399. }
  400. getFinalData() {
  401. const data = [], ctx = this.ctx, bid = this.budget.id, final_id = this.final.id;
  402. this.finalTree.datas.forEach(x => {
  403. data.push({
  404. id: ctx.app.uuid.v4(), bid, final_id,
  405. tree_id: x.id, tree_pid: x.pid, order: x.order, level: x.level, full_path: x.full_path, is_leaf: x.children && x.children.length > 0 ? 0 : 1,
  406. code: x.code || '', name: x.name || '', unit: x.unit || '',
  407. gu_dgn_qty1: x.gu_dgn_qty1 || 0, gu_dgn_qty2: x.gu_dgn_qty2 || 0, gu_dgn_qty: x.gu_dgn_qty || '', gu_dgn_price: x.gu_dgn_price || 0, gu_tp: x.gu_tp || 0,
  408. gai_dgn_qty1: x.gai_dgn_qty1 || 0, gai_dgn_qty2: x.gai_dgn_qty2 || 0, gai_dgn_qty: x.gai_dgn_qty || '', gai_dgn_price: x.gai_dgn_price || 0, gai_tp: x.gai_tp || 0,
  409. yu_dgn_qty1: x.yu_dgn_qty1 || 0, yu_dgn_qty2: x.yu_dgn_qty2 || 0, yu_dgn_qty: x.yu_dgn_qty || '', yu_dgn_price: x.yu_dgn_price || 0, yu_tp: x.yu_tp || 0,
  410. zb_dgn_qty1: x.zb_dgn_qty1 || 0, zb_dgn_qty2: x.zb_dgn_qty2 || 0, zb_dgn_qty: x.zb_dgn_qty || '', zb_dgn_price: x.zb_dgn_price || 0, zb_tp: x.zb_tp || 0,
  411. ctrl_dgn_qty1: x.ctrl_dgn_qty1 || 0, ctrl_dgn_qty2: x.ctrl_dgn_qty2 || 0, ctrl_dgn_qty: x.ctrl_dgn_qty || '', ctrl_dgn_price: x.ctrl_dgn_price || 0, ctrl_tp: x.ctrl_tp || 0,
  412. real_dgn_qty1: x.real_dgn_qty1 || 0, real_dgn_qty2: x.real_dgn_qty2 || 0, real_dgn_qty: x.real_dgn_qty || '', real_dgn_price: x.real_dgn_price || 0, real_tp: x.real_tp || 0,
  413. dgn_qty1: x.dgn_qty1 || 0, dgn_qty2: x.dgn_qty2 || 0, total_price: x.total_price || 0,
  414. dgn_price: x.dgn_price || 0, dgn_qty: x.dgn_qty || '',
  415. deal_dgn_qty1: x.deal_dgn_qty1 || 0, deal_dgn_qty2: x.deal_dgn_qty2 || 0, c_dgn_qty1: x.c_dgn_qty1 || 0, c_dgn_qty2: x.c_dgn_qty2 || 0,
  416. final_dgn_qty1: x.final_dgn_qty1 || 0, final_dgn_qty2: x.final_dgn_qty2 || 0, final_tp: x.final_tp || 0,
  417. final_contract_tp: x.final_contract_tp || 0, final_qc_tp: x.final_qc_tp || 0,
  418. final_dgn_price: x.final_dgn_price || 0, final_dgn_qty: x.final_dgn_qty || '',
  419. tz_qc_qty: x.tz_qc_qty || 0, tz_qc_tp: x.tz_qc_tp || 0,
  420. grow_dgn_qty1: x.grow_dgn_qty1 || 0, grow_dgn_qty2: x.grow_dgn_qty2 || 0, grow_dgn_qty: x.grow_dgn_qty || '', grow_tp: x.grow_tp || 0,
  421. })
  422. });
  423. return data;
  424. }
  425. async doFinal(budget, final, stage, contract) {
  426. this.budget = budget;
  427. this.final = final;
  428. this.finalTree.checkField = budget.final_type.split('_');
  429. for (const t of final.tender) {
  430. await this._loadTender(t, stage);
  431. }
  432. await this._loadReal(budget);
  433. await this._loadCtrl(budget);
  434. await this._loadZb(budget);
  435. await this._loadYu(budget);
  436. await this._loadGai(budget);
  437. await this._loadGu(budget);
  438. await this._loadDeal(contract, stage);
  439. this._afterLoad();
  440. return this.getFinalData();
  441. }
  442. }
  443. module.exports = BudgetFinal;