material.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author Mai
  6. * @date
  7. * @version
  8. */
  9. const materialConst = require('../../const/material');
  10. const Ledger = require('../../lib/ledger');
  11. const billsFields = (function () {
  12. const cur = ['contract_qty', 'contract_tp', 'contract_expr', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp', 'postil'];
  13. const pre = ['pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_gather_qty', 'pre_gather_tp'];
  14. const end = ['end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_gather_qty', 'end_gather_tp'];
  15. const final = ['final_tp', 'final_ratio'];
  16. const stageDgn = ['deal_dgn_qty1', 'deal_dgn_qty2', 'c_dgn_qty1', 'c_dgn_qty2'];
  17. const stage = cur.concat(pre, end, final);
  18. const stageEnd = pre.concat(end, final);
  19. const bgl = ['qc_bgl_code'];
  20. const leafXmj = ['leaf_xmj_id'];
  21. return {cur, pre, end, final, stageDgn, stage, stageEnd, bgl, leafXmj};
  22. })();
  23. const posFields = (function () {
  24. const cur = ['contract_qty', 'qc_qty', 'gather_qty', 'postil'];
  25. const pre = ['pre_contract_qty', 'pre_qc_qty', 'pre_gather_qty'];
  26. const end = ['end_contract_qty', 'end_qc_qty', 'end_gather_qty'];
  27. const final = ['final_ratio'];
  28. const stage = cur.concat(pre, end, final);
  29. const stageEnd = pre.concat(end, final);
  30. const bgl = ['qc_bgl_code'];
  31. return {cur, pre, end, final, stage, stageEnd, bgl};
  32. })();
  33. class ReportMemoryMaterial {
  34. constructor(ctx) {
  35. this.ctx = ctx;
  36. }
  37. _getNewPos(updateFields) {
  38. const helper = this.ctx.helper;
  39. return new Ledger.pos({
  40. id: 'id', ledgerId: 'lid',
  41. updateFields: ['contract_qty', 'qc_qty', 'postil'],
  42. calc: function (p) {
  43. p.pre_gather_qty = helper.add(p.pre_contract_qty, p.pre_qc_qty);
  44. p.gather_qty = helper.add(p.contract_qty, p.qc_qty);
  45. p.end_contract_qty = helper.add(p.pre_contract_qty, p.contract_qty);
  46. p.end_qc_qty = helper.add(p.pre_qc_qty, p.qc_qty);
  47. p.end_gather_qty = helper.add(p.pre_gather_qty, p.gather_qty);
  48. }
  49. });
  50. }
  51. _getNewBillsTree(calcFields) {
  52. return new Ledger.billsTree(this.ctx, {
  53. id: 'ledger_id',
  54. pid: 'ledger_pid',
  55. order: 'order',
  56. level: 'level',
  57. rootId: -1,
  58. keys: ['id', 'tender_id', 'ledger_id'],
  59. stageId: 'id',
  60. calcFields: calcFields || ['deal_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp', 'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp'],
  61. calc: function (node, helper) {
  62. if (node.children && node.children.length === 0) {
  63. node.pre_gather_qty = helper.add(node.pre_contract_qty, node.pre_qc_qty);
  64. node.gather_qty = helper.add(node.contract_qty, node.qc_qty);
  65. node.end_contract_qty = helper.add(node.pre_contract_qty, node.contract_qty);
  66. node.end_qc_qty = helper.add(node.pre_qc_qty, node.qc_qty);
  67. node.end_gather_qty = helper.add(node.pre_gather_qty, node.gather_qty);
  68. }
  69. node.pre_gather_tp = helper.add(node.pre_contract_tp, node.pre_qc_tp);
  70. node.gather_tp = helper.add(node.contract_tp, node.qc_tp);
  71. node.end_contract_tp = helper.add(node.pre_contract_tp, node.contract_tp);
  72. node.end_qc_tp = helper.add(node.pre_qc_tp, node.qc_tp);
  73. node.end_gather_tp = helper.add(node.pre_gather_tp, node.gather_tp);
  74. node.final_tp = helper.add(node.total_price, node.end_qc_tp);
  75. node.final_ratio = helper.mul(helper.div(node.end_gather_tp, node.final_tp, 4), 100);
  76. }
  77. });
  78. }
  79. _checkFieldsExist(source, check) {
  80. for (const s of source) {
  81. if (check.indexOf(s) >= 0) {
  82. return true;
  83. }
  84. }
  85. return false;
  86. }
  87. async getSelectMaterialAuditors(tid, material_order, fields) {
  88. await this.ctx.service.material.checkMaterial(tid, material_order);
  89. const auditors = await this.ctx.service.materialAudit.getFinalAuditGroup(this.ctx.material.id, this.ctx.material.curTimes);
  90. const user = await this.ctx.service.projectAccount.getDataById(this.ctx.material.user_id);
  91. const result = [{
  92. aid: user.id,
  93. name: user.name,
  94. company: user.company,
  95. role: user.role,
  96. mobile: user.mobile,
  97. telephone: user.telephone,
  98. sign_path: user.sign_path,
  99. opinion: user.opinion,
  100. end_time: auditors && auditors.length > 0 ? auditors[0].begin_time : null,
  101. sort: 0,
  102. }, ...auditors];
  103. return result;
  104. }
  105. async getMaterial(tender_id, material_order, fields) {
  106. const result = await this.ctx.service.material.getValidMaterials(tender_id);
  107. if (this._checkFieldsExist(fields, ['checked_time'])) {
  108. for (const r of result) {
  109. const auditors = await this.ctx.service.materialAudit.getFinalAuditGroup(r.id, r.curTimes || r.times);
  110. r.checked_time = !r.curTimes ? auditors[auditors.length - 1].end_time : null;
  111. }
  112. }
  113. return result;
  114. }
  115. _completeMaterialGl(materialGl) {
  116. const tTypeStr = [], mTypeStr = [];
  117. for (const t of materialConst.t_type) {
  118. tTypeStr[t.value] = t.text;
  119. }
  120. for (const m of materialConst.m_type) {
  121. mTypeStr[m.value] = m.text;
  122. }
  123. for (const gl of materialGl) {
  124. gl.tp = this.ctx.helper.mul(gl.quantity, gl.m_spread, 2);
  125. gl.t_type_str = tTypeStr[gl.t_type];
  126. gl.m_type_str = mTypeStr[gl.m_type];
  127. gl.end_tp = this.ctx.helper.add(gl.tp, gl.pre_tp);
  128. }
  129. }
  130. async _loadMaterialMonth(material, gl) {
  131. const materialMonth = await this.ctx.service.materialMonth.getAllDataByCondition({
  132. where: { mid: material.id },
  133. orders: [['mb_id', 'asc'], ['yearmonth', 'asc']],
  134. });
  135. const month = this.ctx.helper._.uniq(materialMonth.map(x => { return x.yearmonth; }));
  136. let g;
  137. for (const mm of materialMonth) {
  138. if (!g || g.id !== mm.mb_id) g = gl.find(x => { return mm.mb_id === x.id; });
  139. if (!g.month_msg_tp) g.month_msg_tp = [];
  140. if (!g.month) g.month = month.concat([]);
  141. const index = month.indexOf(mm.yearmonth);
  142. if (index >= 0) g.month_msg_tp[index] = mm.msg_tp;
  143. }
  144. }
  145. async getMaterialGl(tender_id, material_order, fields) {
  146. const materials = await this.ctx.service.material.getAllDataByCondition({
  147. where: {tid: tender_id},
  148. orders: [['order', 'desc']],
  149. });
  150. if (materials.length === 0) return [];
  151. let result, material;
  152. if (materials[0].order === material_order) {
  153. material = materials[0];
  154. if (material.is_stage_self) {
  155. const sql = 'SELECT msb.id, msb.tid, msb.mid, msb.ms_id, ms.sid, ms.`order` as s_order, mb.order, mb.t_type, mb.code, mb.name, mb.unit, mb.spec, mb.m_type,' +
  156. ' msb.quantity, mb.expr,' +
  157. ' mb.basic_price, mb.basic_times, ' +
  158. ' msb.msg_tp, msb.msg_times, msb.msg_spread, mb.m_up_risk, mb.m_down_risk, msb.m_spread, msb.m_tp, mb.pre_tp, msb.m_tax_tp, mb.tax_pre_tp, mb.origin, ' +
  159. ' msb.remark, msb.is_summary, mb.m_tax, mb.in_time, mb.origin' +
  160. ` FROM ${this.ctx.service.materialStageBills.tableName} msb` +
  161. ` LEFT JOIN ${this.ctx.service.materialBills.tableName} mb ON msb.mb_id = mb.id` +
  162. ' LEFT JOIN ' + this.ctx.service.materialStage.tableName + ' ms ON msb.ms_id = ms.id ' +
  163. ` WHERE msb.mid = ?` +
  164. ' ORDER By msb.ms_id, mb.order';
  165. result = await this.ctx.app.mysql.query(sql, [material.id]);
  166. } else {
  167. result = await this.ctx.service.materialBills.getAllDataByCondition({
  168. where: {tid: tender_id}
  169. });
  170. }
  171. } else {
  172. material = this.ctx.helper._.find(materials, {order: material_order});
  173. if (!material) return [];
  174. if (material.is_stage_self) {
  175. const sql = 'SELECT msb.id, msb.tid, msb.mid, msb.ms_id, ms.sid, ms.`order` as s_order, mb.order, mb.t_type, mb.code, mb.name, mb.unit, mb.spec, mb.m_type,' +
  176. ' msb.quantity, mbh.expr,' +
  177. ' mb.basic_price, mb.basic_times, ' +
  178. ' msb.msg_tp, msb.msg_times, msb.msg_spread, mbh.m_up_risk, mbh.m_down_risk, msb.m_spread, msb.m_tp, mbh.pre_tp, msb.m_tax_tp, mbh.tax_pre_tp, mbh.origin, ' +
  179. ' msb.remark, msb.is_summary, mbh.m_tax, mb.in_time, mbh.origin' +
  180. ` FROM ${this.ctx.service.materialStageBills.tableName} msb` +
  181. ' LEFT JOIN ' + this.ctx.service.materialBillsHistory.tableName + ' mbh ON msb.mb_id = mbh.mb_id AND msb.mid = mbh.mid' +
  182. ' LEFT JOIN ' + this.ctx.service.materialBills.tableName + ' mb ON msb.mb_id = mb.id ' +
  183. ' LEFT JOIN ' + this.ctx.service.materialStage.tableName + ' ms ON msb.ms_id = ms.id ' +
  184. ' WHERE msb.mid = ?'+
  185. ' ORDER By msb.ms_id, mb.order';
  186. result = await this.ctx.app.mysql.query(sql, [material.id]);
  187. } else {
  188. const sql = 'SELECT mb.id, mb.tid, mb.mid, mb.order, mb.t_type, mb.code, mb.name, mb.unit, mb.spec, mb.m_type,' +
  189. ' mbh.quantity, mbh.expr,' +
  190. ' mb.basic_price, mb.basic_times, ' +
  191. ' mbh.msg_tp, mbh.msg_times, mbh.msg_spread, mbh.m_up_risk, mbh.m_down_risk, mbh.m_spread, mbh.m_tp, mbh.pre_tp, mbh.m_tax_tp, mbh.tax_pre_tp, mbh.origin, ' +
  192. ' mb.remark, mb.is_summary, mbh.m_tax, mb.in_time, mbh.origin' +
  193. ' FROM ' + this.ctx.service.materialBillsHistory.tableName + ' mbh ' +
  194. ' LEFT JOIN ' + this.ctx.service.materialBills.tableName + ' mb ON mbh.mb_id = mb.id ' +
  195. ' WHERE mbh.tid = ? And mbh.mid = ?'+
  196. ' ORDER By mb.order';
  197. result = await this.ctx.app.mysql.query(sql, [tender_id, material.id]);
  198. }
  199. }
  200. this._completeMaterialGl(result);
  201. if (this._checkFieldsExist(fields, ['month_msg_tp', 'month'])) await this._loadMaterialMonth(material, result);
  202. return result;
  203. }
  204. async getMaterialGlDetail(tender_id, material_order, fields) {
  205. const material = await this.ctx.service.material.getDataByCondition({tid: tender_id, order: material_order});
  206. if (!material) return [];
  207. if (material.is_stage_self) {
  208. return await this.ctx.service.materialList.getMaterialStageData(tender_id, material.id);
  209. } else {
  210. return await this.ctx.service.materialList.getMaterialData(tender_id, material.id);
  211. }
  212. }
  213. async getMaterialBills(tender_id, material_order, fields, showLevel) {
  214. await this.ctx.service.tender.checkTender(tender_id);
  215. const material = await this.ctx.service.material.getDataByCondition({tid: tender_id, order: material_order});
  216. if (!material) return [];
  217. try {
  218. const billsData = await this.ctx.service.ledger.getData(tender_id);
  219. if (this._checkFieldsExist(fields, billsFields.stage)) {
  220. const curStage = await this.ctx.service.stageBills.getStagesData(tender_id, material.stage_id);
  221. this.ctx.helper.assignRelaData(billsData, [
  222. {data: curStage, fields: ['contract_qty', 'contract_tp', 'contract_expr', 'qc_qty', 'qc_tp', 'postil'], prefix: '', relaId: 'lid'}
  223. ]);
  224. }
  225. const billsTree = this._getNewBillsTree();
  226. billsTree.loadDatas(billsData);
  227. billsTree.calculateAll();
  228. return showLevel ? billsTree.getDefaultDatasByLevel(this.ctx.tender.rpt_show_level) : billsTree.getDefaultDatas();
  229. } catch(err) {
  230. this.ctx.helper.log(err);
  231. return [];
  232. }
  233. }
  234. async getMaterialPos(tender_id, material_order, fields) {
  235. const material = await this.ctx.service.material.getDataByCondition({tid: tender_id, order: material_order});
  236. if (!material) return [];
  237. try {
  238. const posData = await this.ctx.service.pos.getAllDataByCondition({ where: {tid: tender_id }});
  239. if (this._checkFieldsExist(fields, posFields.stage)) {
  240. const curPosStage = await this.ctx.service.stagePos.getStagesData(tender_id, material.stage_id);
  241. this.ctx.helper.assignRelaData(posData, [
  242. {data: curPosStage, fields: ['contract_qty', 'qc_qty', 'contract_expr', 'postil'], prefix: '', relaId: 'pid'}
  243. ]);
  244. }
  245. const pos = this._getNewPos();
  246. pos.loadDatas(posData);
  247. pos.calculateAll();
  248. return pos.getDatas();
  249. } catch (err) {
  250. this.ctx.helper.log(err);
  251. return [];
  252. }
  253. }
  254. async _getMaterialStageGatherBills(tender_id, stage_id, stage_order, stageSelf, stageIndex = 0) {
  255. const decimal = this.materialGatherBase.decimal;
  256. //const billsData = this.ctx.helper.clone(this.materialGatherBase.billsData);
  257. const billsData = this.materialGatherBase.billsData;
  258. billsData.forEach(x => {
  259. for (const prop of ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp']) {
  260. x[prop] = undefined;
  261. }
  262. });
  263. const curStageBills = await this.ctx.service.stageBills.getStagesData(tender_id, stage_id);
  264. this.ctx.helper.assignRelaData(billsData, [
  265. { data: curStageBills, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: '', relaId: 'lid' },
  266. ]);
  267. const billsTree = this._getNewBillsTree();
  268. billsTree.loadDatas(billsData);
  269. billsTree.calculateAll();
  270. //const posData = this.ctx.helper.clone(this.materialGatherBase.posData);
  271. const posData = this.materialGatherBase.posData;
  272. posData.forEach(x => {
  273. for (const prop of ['contract_qty', 'qc_qty']) {
  274. x[prop] = undefined;
  275. }
  276. });
  277. const curStage = await this.ctx.service.stagePos.getStagesData(tender_id, stage_id);
  278. this.ctx.helper.assignRelaData(posData, [
  279. { data: curStage, fields: ['contract_qty', 'qc_qty'], prefix: '', relaId: 'pid' },
  280. ]);
  281. const pos = this._getNewPos();
  282. pos.loadDatas(posData);
  283. pos.calculateAll();
  284. const gclGatherModel = require('../gcl_gather').gclGather;
  285. const gatherUtil = new gclGatherModel(this.ctx);
  286. gatherUtil.gatherObj(billsTree, pos);
  287. const materialGl = stageSelf
  288. ? this.materialGatherBase.materialGl.filter(x => { return x.sid === parseInt(stage_id); })
  289. : this.materialGatherBase.materialGl;
  290. if (stageIndex) materialGl.forEach(x => { x.s_index = stageIndex });
  291. const materialNotJoin = this.materialGatherBase.materialNotJoin;
  292. const helper = this.ctx.helper;
  293. console.time('calcMaterialBills');
  294. for (const g of gatherUtil.gclList) {
  295. if (!g.contract_qty && !g.qc_qty) continue;
  296. g.sid = stage_id;
  297. g.sorder = stage_order;
  298. g.s_index = stageIndex;
  299. g.jiacha = 0;
  300. for (const x of g.leafXmjs) {
  301. x.sid = stage_id;
  302. x.sorder = stage_order;
  303. x.s_index = stageIndex;
  304. x.jiacha = 0;
  305. const mnj = materialNotJoin.find(m => {
  306. return m.gcl_id === x.org_gcl_id && m.xmj_id === x.id && (x.mx_id && x.mx_id !== x.id ? x.mx_id === m.mx_id : true);
  307. });
  308. x.is_join = !mnj;
  309. const list = materialGl.filter(gl => {
  310. return gl.gcl_id === x.org_gcl_id && gl.xmj_id === x.id && (x.mx_id && x.mx_id !== x.id ? x.mx_id === gl.mx_id : true);
  311. });
  312. list.forEach(l => { l.gather_gcl_id = x.gcl_id});
  313. if (mnj) continue;
  314. for (const l of list) {
  315. x.jiacha = helper.add(x.jiacha, helper.mul(helper.mul(x.gather_qty, l.quantity), l.m_spread));
  316. }
  317. x.jiacha = helper.round(x.jiacha, decimal.tp);
  318. g.jiacha = helper.add(g.jiacha, x.jiacha);
  319. g.jiacha_qty = helper.add(g.jiacha_qty, x.gather_qty);
  320. }
  321. }
  322. console.timeEnd('calcMaterialBills');
  323. return [gatherUtil.gclList, gatherUtil.leafXmjs];
  324. }
  325. async getMaterialGatherBills(tender_id, material_order) {
  326. const materials = await this.ctx.service.material.getAllDataByCondition({
  327. where: { tid: tender_id },
  328. orders: [['order', 'desc']],
  329. });
  330. if (materials.length === 0) return {};
  331. const material = await this.ctx.service.material.getDataByCondition({ tid: tender_id, order: material_order });
  332. this.materialGatherBase = {};
  333. this.materialGatherBase.decimal = material.decimal ? JSON.parse(material.decimal) : materialConst.decimal;
  334. try {
  335. // 获取基础数据
  336. this.materialGatherBase.billsData = await this.ctx.service.ledger.getData(tender_id);
  337. this.materialGatherBase.posData = await this.ctx.service.pos.getPosData({ tid: tender_id });
  338. if (material.is_stage_self) {
  339. this.materialGatherBase.materialGl = material_order === materials[0].order
  340. ? await this.ctx.service.materialList.getMaterialStageData(tender_id, material.id)
  341. : await this.ctx.service.materialList.getPreMaterialStageData(tender_id, material.id);
  342. } else {
  343. this.materialGatherBase.materialGl = material_order === materials[0].order
  344. ? await this.ctx.service.materialList.getMaterialData(tender_id, material.id)
  345. : await this.ctx.service.materialList.getPreMaterialData(tender_id, material.id);
  346. }
  347. this.materialGatherBase.materialNotJoin = await this.ctx.service.materialListNotjoin.getAllDataByCondition({ where: { mid: material.id } });
  348. const mem_material_gather_bills = [], mem_material_gather_xmj = [];
  349. if (material.is_stage_self) {
  350. const stageIds = material.stage_id.split(',');
  351. const stageOrders = material.s_order.split(',');
  352. for (const [i, sid] of stageIds.entries()) {
  353. const [gclList, leafXmjs] = await this._getMaterialStageGatherBills(tender_id, sid, stageOrders[i], true, i + 1);
  354. mem_material_gather_bills.push(...gclList);
  355. mem_material_gather_xmj.push(...leafXmjs);
  356. }
  357. } else {
  358. const [gclList, leafXmjs] = await this._getMaterialStageGatherBills(tender_id, material.stage_id, material.stage_order, false);
  359. mem_material_gather_bills.push(...gclList);
  360. mem_material_gather_xmj.push(...leafXmjs);
  361. }
  362. return {mem_material_gather_bills, mem_material_gather_xmj, mem_material_gather_gl: this.materialGatherBase.materialGl};
  363. } catch (err) {
  364. this.ctx.log(err);
  365. return {};
  366. }
  367. }
  368. async getMaterialStage(tender_id, material_order, fields) {
  369. const material = await this.ctx.service.material.getDataByCondition({tid: tender_id, order: material_order});
  370. if (!material) return [];
  371. if (material.is_stage_self) {
  372. return await this.ctx.service.materialStage.getAllDataByCondition({ where: { mid: material.id } });
  373. } else {
  374. return [{
  375. id: -1, tid: material.id, mid: material.id, sid: material.stage_id, order: material.stage_order,
  376. m_tp: material.m_tp, m_tax_tp: material.m_tax_tp,
  377. }];
  378. }
  379. }
  380. }
  381. module.exports = ReportMemoryMaterial;