material_bills.js 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  1. 'use strict';
  2. /**
  3. * 期计量 数据模型
  4. *
  5. * @author Mai
  6. * @date 2018/8/13
  7. * @version
  8. */
  9. const auditConst = require('../const/audit').material;
  10. const materialConst = require('../const/material');
  11. const MaterialCalculator = require('../lib/material_calc');
  12. module.exports = app => {
  13. class MaterialBills extends app.BaseService {
  14. /**
  15. * 构造函数
  16. *
  17. * @param {Object} ctx - egg全局变量
  18. * @return {void}
  19. */
  20. constructor(ctx) {
  21. super(ctx);
  22. this.tableName = 'material_bills';
  23. }
  24. /**
  25. * 添加工料
  26. * @return {void}
  27. */
  28. async add() {
  29. if (!this.ctx.tender || !this.ctx.material) {
  30. throw '数据错误';
  31. }
  32. const order = await this._getMaxOrder(this.ctx.tender.id);
  33. const transaction = await this.db.beginTransaction();
  34. try {
  35. const resultData = {};
  36. const newBills = {
  37. tid: this.ctx.tender.id,
  38. mid: this.ctx.material.id,
  39. order: order + 1,
  40. in_time: new Date(),
  41. };
  42. // 新增工料
  43. const result = await transaction.insert(this.tableName, newBills);
  44. if (result.affectedRows !== 1) {
  45. throw '新增工料数据失败';
  46. }
  47. if (this.ctx.material.is_stage_self) {
  48. await this.ctx.service.materialStageBills.add(transaction, result.insertId);
  49. resultData.pushStageBillsData = await transaction.select(this.ctx.service.materialStageBills.tableName, { where: { mid: this.ctx.material.id, mb_id: result.insertId } });
  50. }
  51. const insertArray = [];
  52. const material_month = this.ctx.material.months ? this.ctx.material.months.split(',') : [];
  53. for (const ym of material_month) {
  54. const one_month = {
  55. tid: this.ctx.tender.id,
  56. mid: this.ctx.material.id,
  57. mb_id: result.insertId,
  58. msg_tp: null,
  59. yearmonth: ym,
  60. };
  61. insertArray.push(one_month);
  62. }
  63. if (insertArray.length !== 0) await transaction.insert(this.ctx.service.materialMonth.tableName, insertArray);
  64. await transaction.commit();
  65. resultData.info = await this.getDataById(result.insertId);
  66. return resultData;
  67. } catch (error) {
  68. console.log(error);
  69. await transaction.rollback();
  70. throw error;
  71. }
  72. }
  73. /**
  74. * 导入工料
  75. * @return {void}
  76. */
  77. async exportData(datas, includeSpec = false, ms_id = null) {
  78. if (!this.ctx.tender || !this.ctx.material) {
  79. throw '数据错误';
  80. }
  81. let order = await this._getMaxOrder(this.ctx.tender.id);
  82. const transaction = await this.db.beginTransaction();
  83. try {
  84. const resultData = {};
  85. let needUpdateTp = false;
  86. // 找出需要导入的工料 (隐藏未存在的工料导入问题)
  87. const bills = await this.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
  88. // const newBills = this._.differenceWith(datas, bills, function(item1, item2) {
  89. // return item1.code.toString() === item2.code.toString() && item1.name === item2.name && item1.unit === item2.unit && (!includeSpec || (includeSpec && item1.spec.toString() === item2.spec.toString()));
  90. // });
  91. const newBills = [];
  92. const material_month = this.ctx.material.months ? this.ctx.material.months.split(',') : [];
  93. if (newBills.length !== 0) {
  94. const newBillsData = [];
  95. const newMonthList = [];
  96. for (const t of newBills) {
  97. // 判断msg_tp是否为数字,不是则报错
  98. if (t.msg_tp && !this._.isNumber(t.msg_tp)) {
  99. throw '信息价数据存在非数字字符,无法导入';
  100. }
  101. t.msg_tp = t.msg_tp ? this.ctx.helper.round(t.msg_tp, this.ctx.material.decimal.up) : null;
  102. const newBill = {
  103. tid: this.ctx.tender.id,
  104. mid: this.ctx.material.id,
  105. order: order + 1,
  106. code: t.code.toString(),
  107. name: t.name,
  108. unit: t.unit,
  109. spec: t.spec,
  110. msg_tp: this.ctx.material.is_stage_self ? null : t.msg_tp,
  111. msg_times: this.ctx.material.is_stage_self ? null : t.msg_times,
  112. msg_spread: this.ctx.material.is_stage_self ? null : t.msg_tp,
  113. m_spread: this.ctx.material.is_stage_self ? null : t.msg_tp,
  114. m_tp: 0,
  115. m_tax_tp: 0,
  116. in_time: new Date(),
  117. };
  118. order = order + 1;
  119. newBillsData.push(newBill);
  120. }
  121. const result = await transaction.insert(this.tableName, newBillsData);
  122. resultData.addNum = newBillsData.length;
  123. for (let j = 0; j < newBills.length; j++) {
  124. newBills[j].id = result.insertId + j;
  125. if (material_month.length > 0) {
  126. for (const ym of material_month) {
  127. const one_month = {
  128. tid: this.ctx.tender.id,
  129. mid: this.ctx.material.id,
  130. mb_id: newBills[j].id,
  131. msg_tp: newBills[j].msg_tp,
  132. yearmonth: ym,
  133. };
  134. newMonthList.push(one_month);
  135. }
  136. }
  137. }
  138. if (this.ctx.material.is_stage_self) {
  139. // 获取刚批量添加的所有list
  140. await this.ctx.service.materialStageBills.adds(transaction, newBills, null, ms_id);
  141. }
  142. if (newMonthList.length > 0) await transaction.insert(this.ctx.service.materialMonth.tableName, newMonthList);
  143. }
  144. // 找出需要更新的工料
  145. const updateBills = this._.intersectionWith(bills, datas, function(item1, item2) {
  146. return item1.code.toString() === item2.code.toString() && item1.name === item2.name && item1.unit === item2.unit &&
  147. (!includeSpec || (includeSpec && (item1.spec === null ? '' : item1.spec).toString() === (item2.spec === null ? '' : item2.spec).toString()));
  148. });
  149. if (updateBills.length !== 0) {
  150. const updateDatas = [];
  151. const updateMonthList = [];
  152. for (const u of updateBills) {
  153. const oneData = this._.find(datas, function(item) {
  154. return item.code.toString() === u.code.toString() && item.name === u.name && item.unit === u.unit &&
  155. (!includeSpec || (includeSpec && (item.spec === null ? '' : item.spec).toString() === (u.spec === null ? '' : u.spec).toString()));
  156. });
  157. const upd = { id: u.id };
  158. oneData.msg_tp = this.ctx.helper.round(oneData.msg_tp, this.ctx.material.decimal.up);
  159. // 判断msg_tp是否为数字,不是则报错
  160. if (oneData.msg_tp && !this._.isNumber(oneData.msg_tp)) {
  161. throw '信息价数据存在非数字字符,无法导入';
  162. }
  163. if (!this.ctx.material.is_stage_self) {
  164. if (oneData.msg_tp !== u.msg_tp) {
  165. needUpdateTp = true;
  166. upd.msg_tp = oneData.msg_tp;
  167. const [newmsg_spread, newm_spread] = await this.getSpread(u, oneData.msg_tp);
  168. upd.msg_spread = newmsg_spread;
  169. upd.m_spread = newm_spread;
  170. const newTp = this.ctx.helper.round(this.ctx.helper.mul(u.quantity, newm_spread), this.ctx.material.decimal.tp);
  171. upd.m_tp = newTp;
  172. upd.m_tax_tp = this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(u.m_tax, 100))), this.ctx.material.decimal.tp);
  173. }
  174. if (oneData.msg_times !== u.msg_times) {
  175. upd.msg_times = oneData.msg_times;
  176. }
  177. }
  178. if (!includeSpec && (oneData.spec === null ? '' : oneData.spec).toString() !== (u.spec === null ? '' : u.spec).toString()) {
  179. upd.spec = oneData.spec;
  180. }
  181. if (!this._.isEqual(upd, { id: u.id })) updateDatas.push(upd);
  182. // 判断是否有月信息价,如果有则msg_tp都更改为统一值
  183. if (material_month.length > 0) {
  184. const monthList = await transaction.select(this.ctx.service.materialMonth.tableName, { where: { mb_id: u.id, mid: this.ctx.material.id } });
  185. if (monthList.length !== 0) {
  186. for (const m of monthList) {
  187. // 更新月信息单价小数位
  188. if (oneData.msg_tp !== m.msg_tp) {
  189. m.msg_tp = oneData.msg_tp;
  190. updateMonthList.push({ id: m.id, msg_tp: m.msg_tp });
  191. }
  192. }
  193. }
  194. }
  195. }
  196. if (updateDatas.length !== 0) await transaction.updateRows(this.tableName, updateDatas);
  197. resultData.updateNum = updateDatas.length;
  198. if (updateMonthList.length !== 0) await transaction.updateRows(this.ctx.service.materialMonth.tableName, updateMonthList);
  199. if (this.ctx.material.is_stage_self) {
  200. let selfUpdateNum = 0;
  201. [needUpdateTp, selfUpdateNum] = await this.ctx.service.materialStageBills.updateByExport(transaction, updateBills, datas, includeSpec, ms_id);
  202. if (resultData.updateNum === 0 || resultData.updateNum < selfUpdateNum) resultData.updateNum = selfUpdateNum;
  203. }
  204. }
  205. // 更新materialStage 值
  206. if (this.ctx.material.is_stage_self) {
  207. resultData.stageBillsData = await transaction.select(this.ctx.service.materialStageBills.tableName, { where: { mid: this.ctx.material.id } });
  208. resultData.stageData = await transaction.select(this.ctx.service.materialStage.tableName, { where: { mid: this.ctx.material.id } });
  209. }
  210. resultData.billsData = await transaction.select(this.tableName, { where: { tid: this.ctx.tender.id }, orders: [['order', 'asc']] });
  211. if (material_month.length > 0) {
  212. resultData.monthsList = await this.ctx.service.materialMonth.getMonthList(resultData.billsData, transaction);
  213. }
  214. resultData.m_tp = needUpdateTp ? await this.calcMaterialMTp(transaction) : this.ctx.material.m_tp;
  215. await transaction.commit();
  216. return resultData;
  217. } catch (error) {
  218. console.log(error);
  219. await transaction.rollback();
  220. throw error;
  221. }
  222. }
  223. /**
  224. * 添加工料
  225. * @return {void}
  226. */
  227. async addByGlj(data, order = null) {
  228. if (!this.ctx.tender || !this.ctx.material) {
  229. throw '数据错误';
  230. }
  231. const newOrder = this._.isNumber(order) ? parseInt(order) + 1 : await this._getMaxOrder(this.ctx.tender.id);
  232. const transaction = await this.db.beginTransaction();
  233. try {
  234. // order以下的工料+1
  235. await this._syncOrder(transaction, this.ctx.tender.id, newOrder, '+');
  236. const resultData = {};
  237. const newBills = {
  238. tid: this.ctx.tender.id,
  239. mid: this.ctx.material.id,
  240. code: data.code,
  241. name: data.name,
  242. unit: data.unit,
  243. m_up_risk: data.rise_range,
  244. m_down_risk: data.fall_range,
  245. spec: data.spec,
  246. m_type: data.type,
  247. remark: data.memo,
  248. order: newOrder,
  249. in_time: new Date(),
  250. };
  251. // 新增工料
  252. const result = await transaction.insert(this.tableName, newBills);
  253. if (result.affectedRows !== 1) {
  254. throw '新增工料数据失败';
  255. }
  256. if (this.ctx.material.is_stage_self) {
  257. await this.ctx.service.materialStageBills.add(transaction, result.insertId, data.memo);
  258. resultData.pushStageBillsData = await transaction.select(this.ctx.service.materialStageBills.tableName, { where: { mid: this.ctx.material.id, mb_id: result.insertId } });
  259. }
  260. const insertArray = [];
  261. const material_month = this.ctx.material.months ? this.ctx.material.months.split(',') : [];
  262. for (const ym of material_month) {
  263. const one_month = {
  264. tid: this.ctx.tender.id,
  265. mid: this.ctx.material.id,
  266. mb_id: result.insertId,
  267. msg_tp: null,
  268. yearmonth: ym,
  269. };
  270. insertArray.push(one_month);
  271. }
  272. if (insertArray.length !== 0) await transaction.insert(this.ctx.service.materialMonth.tableName, insertArray);
  273. await transaction.commit();
  274. resultData.info = await this.getDataById(result.insertId);
  275. return resultData;
  276. } catch (error) {
  277. console.log(error);
  278. await transaction.rollback();
  279. throw error;
  280. }
  281. }
  282. /**
  283. * 移除清单时,同步其后清单order
  284. * @param transaction - 事务
  285. * @param {Number} cid - 变更cid
  286. * @param {Number} order - order之后的
  287. * @return {Promise<*>}
  288. * @private
  289. */
  290. async _syncOrder(transaction, tid, order, selfOperate = '-', num = 1) {
  291. this.initSqlBuilder();
  292. this.sqlBuilder.setAndWhere('tid', {
  293. value: this.db.escape(tid),
  294. operate: '=',
  295. });
  296. this.sqlBuilder.setAndWhere('order', {
  297. value: order,
  298. operate: '>=',
  299. });
  300. this.sqlBuilder.setUpdateData('order', {
  301. value: num,
  302. selfOperate,
  303. });
  304. const [sql, sqlParam] = this.sqlBuilder.build(this.tableName, 'update');
  305. const data = await transaction.query(sql, sqlParam);
  306. return data;
  307. }
  308. async _getMaxOrder(tenderId) {
  309. const sql = 'SELECT Max(??) As value FROM ?? Where tid = ' + tenderId;
  310. const sqlParam = ['order', this.tableName];
  311. const queryResult = await this.db.queryOne(sql, sqlParam);
  312. return queryResult.value ? queryResult.value : 0;
  313. }
  314. /**
  315. * 删除工料
  316. * @param {int} id 工料id
  317. * @return {void}
  318. */
  319. async del(id) {
  320. if (!this.ctx.tender || !this.ctx.material) {
  321. throw '数据错误';
  322. }
  323. // 判断t_type是否为费用,且存在quantity,m_spread值
  324. const transaction = await this.db.beginTransaction();
  325. try {
  326. // 防止多页面操作时,清单工料含量存在时工料可删
  327. const materialListNum = await this.ctx.service.materialList.count({ tid: this.ctx.tender.id, mb_id: id });
  328. if (materialListNum > 0) {
  329. throw '该工料已存在对应的清单工料含量,删除失败';
  330. }
  331. const mbInfo = await this.getDataById(id);
  332. await transaction.delete(this.tableName, { id });
  333. const m_tp = this.ctx.material.m_tp;
  334. const result = { m_tp };
  335. if (this.ctx.material.is_stage_self) {
  336. await transaction.delete(this.ctx.service.materialStageBills.tableName, { mb_id: id });
  337. // 金额发生变化,则重新计算本期金额
  338. for (const sid of this.ctx.material.stage_id.split(',')) {
  339. const msInfo = await transaction.get(this.ctx.service.materialStage.tableName, { tid: this.ctx.tender.id, sid });
  340. await this.ctx.service.materialStage.updateMtp(transaction, msInfo.id);
  341. }
  342. result.stageBillsData = await transaction.select(this.ctx.service.materialStageBills.tableName, { where: { mid: this.ctx.material.id } });
  343. result.stageData = await transaction.select(this.ctx.service.materialStage.tableName, { where: { mid: this.ctx.material.id } });
  344. result.m_tp = await this.calcMaterialMTp(transaction);
  345. } else if (mbInfo.t_type === materialConst.t_type[1].value && mbInfo.quantity !== null && mbInfo.m_spread !== null) {
  346. // 金额发生变化,则重新计算本期金额
  347. result.m_tp = await this.calcMaterialMTp(transaction);
  348. }
  349. const material_month = this.ctx.material.months ? this.ctx.material.months.split(',') : [];
  350. if (material_month.length > 0) {
  351. await transaction.delete(this.ctx.service.materialMonth.tableName, { mb_id: id });
  352. }
  353. // order以下的清单-1
  354. await this._syncOrder(transaction, this.ctx.tender.id, mbInfo.order, '-');
  355. await transaction.commit();
  356. return result;
  357. } catch (err) {
  358. await transaction.rollback();
  359. throw err;
  360. }
  361. }
  362. /**
  363. * 交换两个工料的顺序
  364. * @param {Number} id1 - 工料1的id
  365. * @param {Number} id2 - 工料2的id
  366. * @returns {Promise<void>}
  367. */
  368. async changeOrder(datas) {
  369. if (!this.ctx.tender || !this.ctx.material) {
  370. throw '数据错误';
  371. }
  372. // const bill1 = await this.getDataByCondition({ tid: this.ctx.tender.id, id: id1 });
  373. // const bill2 = await this.getDataByCondition({ tid: this.ctx.tender.id, id: id2 });
  374. // if (!bill1 || !bill2) {
  375. // throw '数据错误';
  376. // }
  377. const transaction = await this.db.beginTransaction();
  378. try {
  379. // const order = bill1.order;
  380. // bill1.order = bill2.order;
  381. // bill2.order = order;
  382. // await transaction.update(this.tableName, { id: bill1.id, order: bill1.order });
  383. // await transaction.update(this.tableName, { id: bill2.id, order: bill2.order });
  384. await transaction.updateRows(this.tableName, datas);
  385. await transaction.commit();
  386. return true;
  387. } catch (err) {
  388. await transaction.rollback();
  389. throw err;
  390. }
  391. }
  392. /**
  393. * 修改工料信息
  394. * @param {Object} data 工料内容
  395. * @return {void}
  396. */
  397. async save(data, ms_id = null) {
  398. if (!this.ctx.tender || !this.ctx.material) {
  399. throw '数据错误';
  400. }
  401. delete data.in_time;
  402. // delete data.m_tp;
  403. // 判断是否可修改
  404. // 判断t_type是否为费用
  405. const transaction = await this.db.beginTransaction();
  406. try {
  407. const result = {};
  408. if (this.ctx.material.is_stage_self) {
  409. if (!ms_id) {
  410. throw '期参数有误';
  411. }
  412. const needUp = await this.updateOneBillsData(transaction, data, ms_id);
  413. const [one_m_tp, one_tax_tp] = await this.ctx.service.materialStageBills.update(transaction, data, ms_id);
  414. // 更新materialStage 值
  415. data.m_tp = this.ctx.helper.round(one_m_tp, this.ctx.material.decimal.tp);
  416. data.m_tax_tp = this.ctx.helper.round(one_tax_tp, this.ctx.material.decimal.tp);
  417. data.quantity = null;
  418. data.msg_tp = null;
  419. data.msg_times = null;
  420. data.msg_spread = null;
  421. data.m_spread = null;
  422. delete data.ms_id;
  423. // 更新materialStage 值
  424. await this.ctx.service.materialStage.updateMtp(transaction, ms_id);
  425. result.stageBillsData = this.ctx.material.is_stage_self && needUp ?
  426. await transaction.select(this.ctx.service.materialStageBills.tableName, { where: { mid: this.ctx.material.id, mb_id: data.id } }) :
  427. await transaction.select(this.ctx.service.materialStageBills.tableName, { where: { mid: this.ctx.material.id, ms_id, mb_id: data.id } });
  428. result.stageData = this.ctx.material.is_stage_self && needUp ?
  429. await transaction.select(this.ctx.service.materialStage.tableName, { where: { mid: this.ctx.material.id } }) :
  430. await transaction.select(this.ctx.service.materialStage.tableName, { where: { mid: this.ctx.material.id, id: ms_id } });
  431. }
  432. await transaction.update(this.tableName, data);
  433. if (this.ctx.material.is_stage_self) {
  434. result.billsData = await transaction.select(this.tableName, { where: { id: data.id } });
  435. }
  436. result.m_tp = await this.calcMaterialMTp(transaction);
  437. await transaction.commit();
  438. return result;
  439. } catch (err) {
  440. await transaction.rollback();
  441. throw err;
  442. }
  443. }
  444. async updateOneBillsData(transaction, data, ms_id) {
  445. // 当以下值和bills值不相同时,需要同步更新最新的计算值到stageBills表里
  446. const updateColsArray = ['t_type', 'm_tax', 'basic_price', 'm_up_risk', 'm_down_risk', 'is_summary'];
  447. let needUp = null;
  448. const mbInfo = await this.getDataById(data.id);
  449. for (const uc of updateColsArray) {
  450. if (data[uc] !== undefined && data[uc] !== mbInfo[uc]) {
  451. needUp = uc;
  452. break;
  453. }
  454. }
  455. if (needUp) {
  456. const msList = await this.ctx.service.materialStage.getAllDataByCondition({ where: { mid: this.ctx.material.id } });
  457. for (const ms of msList) {
  458. if (ms.id !== parseInt(ms_id)) {
  459. const msbInfo = await this.ctx.service.materialStageBills.getDataByCondition({
  460. mid: this.ctx.material.id,
  461. ms_id: ms.id,
  462. mb_id: data.id,
  463. });
  464. const updateData = {
  465. id: msbInfo.id,
  466. };
  467. if (needUp === 'm_tax') {
  468. updateData.m_tax_tp = this.ctx.helper.round(this.ctx.helper.mul(msbInfo.m_tp, (1 + this.ctx.helper.div(data.m_tax, 100))), this.ctx.material.decimal.tp);
  469. } else if (needUp === 'm_up_risk' || needUp === 'm_down_risk' || needUp === 'basic_price') {
  470. const basic_price = needUp === 'basic_price' ? data.basic_price : mbInfo.basic_price;
  471. const [msg_spread, m_spread] = await this.getSpread(mbInfo, msbInfo.msg_tp, this.ctx.material.decimal.up, basic_price);
  472. updateData.msg_spread = msg_spread;
  473. updateData.m_spread = m_spread;
  474. const newTp = this.ctx.helper.round(this.ctx.helper.mul(msbInfo.quantity, m_spread), this.ctx.material.decimal.tp);
  475. updateData.m_tp = newTp;
  476. updateData.m_tax_tp = this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mbInfo.m_tax, 100))), this.ctx.material.decimal.tp);
  477. } else if (needUp === 't_type') {
  478. updateData.quantity = null;
  479. updateData.m_tp = null;
  480. updateData.m_tax_tp = null;
  481. } else if (needUp === 'is_summary') {
  482. updateData.is_summary = data.is_summary;
  483. }
  484. await transaction.update(this.ctx.service.materialStageBills.tableName, updateData);
  485. await this.ctx.service.materialStage.updateMtp(transaction, ms.id);
  486. }
  487. }
  488. }
  489. return needUp;
  490. }
  491. async saveOrigin(data) {
  492. if (!this.ctx.tender || !this.ctx.material) {
  493. throw '数据错误';
  494. }
  495. return await this.db.update(this.tableName, { id: data.mb_id, origin: data.value });
  496. }
  497. async saveOrigins(datas) {
  498. if (!this.ctx.tender || !this.ctx.material) {
  499. throw '数据错误';
  500. }
  501. const updateData = [];
  502. for (const data of datas) {
  503. updateData.push({
  504. id: data.mb_id,
  505. origin: data.origin,
  506. });
  507. }
  508. if (updateData.length > 0) await this.db.updateRows(this.tableName, updateData);
  509. return true;
  510. }
  511. /**
  512. * 修改工料信息
  513. * @param {Object} data 工料内容
  514. * @return {void}
  515. */
  516. async saveDatas(datas, ms_id = null) {
  517. if (!this.ctx.tender || !this.ctx.material) {
  518. throw '数据错误';
  519. }
  520. // 判断是否可修改
  521. // 判断t_type是否为费用
  522. const transaction = await this.db.beginTransaction();
  523. try {
  524. for (const data of datas) {
  525. delete data.in_time;
  526. let needUp = null;
  527. if (this.ctx.material.is_stage_self) {
  528. needUp = await this.updateOneBillsData(transaction, data, ms_id);
  529. const [one_m_tp, one_tax_tp] = await this.ctx.service.materialStageBills.update(transaction, data, ms_id);
  530. // 更新materialStage 值
  531. data.m_tp = this.ctx.helper.round(one_m_tp, this.ctx.material.decimal.tp);
  532. data.m_tax_tp = this.ctx.helper.round(one_tax_tp, this.ctx.material.decimal.tp);
  533. data.quantity = null;
  534. data.msg_tp = null;
  535. data.msg_times = null;
  536. data.msg_spread = null;
  537. data.msg_spread = null;
  538. data.m_spread = null;
  539. }
  540. // delete data.m_tp;
  541. // console.log(data);
  542. await transaction.update(this.tableName, data);
  543. }
  544. // 更新materialStage 值
  545. const result = {};
  546. if (this.ctx.material.is_stage_self) {
  547. await this.ctx.service.materialStage.updateMtp(transaction, ms_id);
  548. result.stageBillsData = await transaction.select(this.ctx.service.materialStageBills.tableName, { where: { mid: this.ctx.material.id } });
  549. result.stageData = await transaction.select(this.ctx.service.materialStage.tableName, { where: { mid: this.ctx.material.id } });
  550. result.billsData = await transaction.select(this.tableName, { where: { mid: this.ctx.material.id }, orders: [['order', 'asc']] });
  551. }
  552. result.m_tp = await this.calcMaterialMTp(transaction);
  553. await transaction.commit();
  554. return result;
  555. } catch (err) {
  556. await transaction.rollback();
  557. throw err;
  558. }
  559. }
  560. /**
  561. * 更新新一期的quantity和截止上期金额并返回本期总金额
  562. * @param transaction
  563. * @param tid
  564. * @param mid
  565. * @returns {Promise<number>}
  566. */
  567. async updateNewMaterial(transaction, tid, mid, ctx, stage_id, decimal, pre_is_stage_self = 0, qty_source = 1) {
  568. const materialBillsData = await this.getAllDataByCondition({ where: { tid } });
  569. let m_tp = 0;
  570. let m_tax_tp = 0;
  571. const materialCalculator = new MaterialCalculator(ctx, stage_id, ctx.tender.info);
  572. for (const mb of materialBillsData) {
  573. const [one_tp, one_tax_tp] = await this.calcQuantityByMB(transaction, mid, mb, materialCalculator, decimal, pre_is_stage_self, qty_source);
  574. m_tp = this.ctx.helper.add(m_tp, one_tp);
  575. m_tax_tp = this.ctx.helper.add(m_tax_tp, one_tax_tp);
  576. }
  577. return [m_tp, m_tax_tp];
  578. }
  579. /**
  580. * 修改quantity,m_spread值和返回单条调差金额(新增一期)
  581. * @param transaction
  582. * @param mid
  583. * @param mb
  584. * @returns {Promise<*>}
  585. */
  586. async calcQuantityByMB(transaction, mid, mb, materialCalculator, decimal, pre_is_stage_self, qty_source) {
  587. const [newmsg_spread, newm_spread] = await this.getSpread(mb, null, decimal.up);
  588. if (mb.t_type === materialConst.t_type[0].value) {
  589. const sql = 'SELECT SUM(' + this.ctx.helper.getQtySource(qty_source) + '*`quantity`) as quantity FROM ' + this.ctx.service.materialList.tableName + ' WHERE `mid`=? AND `mb_id`=? AND `is_join`=1';
  590. const sqlParam = [mid, mb.id];
  591. const mb_quantity = await transaction.queryOne(sql, sqlParam);
  592. console.log(mb_quantity);
  593. // 取历史期记录获取截止上期调差金额,并清空本期单价和时间,来源地,重新计算价差和有效价差
  594. const newQuantity = this.ctx.helper.round(mb_quantity.quantity, decimal.qty);
  595. const newTp = this.ctx.helper.round(this.ctx.helper.mul(newQuantity, newm_spread), decimal.tp);
  596. const updateData = {
  597. id: mb.id,
  598. quantity: newQuantity,
  599. msg_tp: null,
  600. msg_times: null,
  601. msg_spread: newmsg_spread,
  602. m_spread: newm_spread,
  603. origin: null,
  604. m_tp: newTp,
  605. pre_tp: mb.m_tp !== null ? this.ctx.helper.add(mb.pre_tp, mb.m_tp) : mb.pre_tp,
  606. m_tax_tp: this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mb.m_tax, 100))), decimal.tp),
  607. tax_pre_tp: mb.m_tax_tp !== null ? this.ctx.helper.add(mb.tax_pre_tp, mb.m_tax_tp) : mb.tax_pre_tp,
  608. };
  609. await transaction.update(this.tableName, updateData);
  610. const m_tp = mb.is_summary === 1 ? await this.ctx.helper.round(this.ctx.helper.mul(mb_quantity.quantity, newm_spread), decimal.tp) : 0;
  611. const m_tax_tp = this.ctx.helper.round(this.ctx.helper.mul(m_tp, (1 + this.ctx.helper.div(mb.m_tax, 100))), decimal.tp);
  612. return [m_tp, m_tax_tp];
  613. } else if (mb.t_type === materialConst.t_type[1].value) {
  614. const quantity = pre_is_stage_self ? 0 : await materialCalculator.calculateExpr(mb.expr);
  615. const newTp = quantity !== 0 && quantity !== null ? this.ctx.helper.round(this.ctx.helper.mul(this.ctx.helper.round(quantity, decimal.qty), newm_spread), decimal.tp) : null;
  616. const updateData = {
  617. id: mb.id,
  618. quantity: quantity !== 0 && quantity !== null ? this.ctx.helper.round(quantity, decimal.qty) : null,
  619. expr: pre_is_stage_self ? null : mb.expr,
  620. msg_tp: null,
  621. msg_times: null,
  622. msg_spread: newmsg_spread,
  623. m_spread: newm_spread,
  624. origin: null,
  625. m_tp: newTp,
  626. pre_tp: mb.m_tp !== null ? this.ctx.helper.add(mb.pre_tp, mb.m_tp) : mb.pre_tp,
  627. m_tax_tp: this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mb.m_tax, 100))), decimal.tp),
  628. tax_pre_tp: mb.m_tax_tp !== null ? this.ctx.helper.add(mb.tax_pre_tp, mb.m_tax_tp) : mb.tax_pre_tp,
  629. };
  630. await transaction.update(this.tableName, updateData);
  631. const m_tp = mb.is_summary === 1 ? await this.ctx.helper.round(this.ctx.helper.mul(quantity, newm_spread), decimal.tp) : 0;
  632. const m_tax_tp = this.ctx.helper.round(this.ctx.helper.mul(m_tp, (1 + this.ctx.helper.div(mb.m_tax, 100))), decimal.tp);
  633. return [m_tp, m_tax_tp];
  634. }
  635. }
  636. /**
  637. * 清空本期信息价后更新价差和有效价差
  638. * @param data
  639. * @returns {Promise<void>}
  640. */
  641. async getSpread(data, msg_tp, newDecimalUp = this.ctx.material.decimal.up, basic_price = null) {
  642. data.msg_tp = msg_tp;
  643. const newBp = basic_price ? basic_price : data.basic_price;
  644. const msg_spread = this.ctx.helper.round(this.ctx.helper.sub(data.msg_tp, newBp), newDecimalUp);
  645. const cor = msg_spread >= 0 ? this.ctx.helper.mul(newBp, this.ctx.helper.div(data.m_up_risk, 100)) : this.ctx.helper.mul(newBp, this.ctx.helper.div(data.m_down_risk, 100));
  646. const m_spread = Math.abs(msg_spread) > Math.abs(cor) ? (msg_spread > 0 ? this.ctx.helper.round(this.ctx.helper.sub(msg_spread, cor), newDecimalUp) : this.ctx.helper.round(this.ctx.helper.add(msg_spread, cor), newDecimalUp)) : 0;
  647. return [msg_spread, m_spread];
  648. }
  649. /**
  650. * 修改 expr和quantity值,返回本期金额和单条数据
  651. * @param data
  652. * @returns {Promise<void>}
  653. */
  654. async updateFYQuantity(data) {
  655. if (!this.ctx.tender || !this.ctx.material) {
  656. throw '数据错误';
  657. }
  658. const transaction = await this.db.beginTransaction();
  659. try {
  660. const returnData = {};
  661. returnData.m_tp = this.ctx.material.m_tp;
  662. if (this.ctx.material.is_stage_self) {
  663. if (!data.ms_id) throw '参数有误';
  664. const mbInfo = await this.getDataById(data.id);
  665. const msInfo = await this.ctx.service.materialStage.getDataById(data.ms_id);
  666. const msbInfo = await this.ctx.service.materialStageBills.getDataByCondition({ mid: this.ctx.material.id, mb_id: data.id, ms_id: data.ms_id });
  667. // let all_m_tp = 0;
  668. // let all_tax_tp = 0;
  669. const materialCalculator = new MaterialCalculator(this.ctx, msInfo.sid, this.ctx.tender.info);
  670. const quantity = await materialCalculator.calculateExpr(data.expr);
  671. const newQuantity = quantity !== 0 ? this.ctx.helper.round(quantity, this.ctx.material.decimal.qty) : null;
  672. const m_tp = newQuantity ? this.ctx.helper.round(this.ctx.helper.mul(newQuantity, msbInfo.m_spread), this.ctx.material.decimal.tp) : null;
  673. const updateData = {
  674. id: data.id,
  675. quantity: newQuantity,
  676. expr: data.expr,
  677. m_tp,
  678. m_tax_tp: this.ctx.helper.round(this.ctx.helper.mul(m_tp, (1 + this.ctx.helper.div(mbInfo.m_tax, 100))), this.ctx.material.decimal.tp),
  679. };
  680. const [one_bill_m_tp, one_bill_tax_tp] = await this.ctx.service.materialStageBills.update(transaction, updateData, msInfo.id);
  681. await this.ctx.service.materialStage.updateMtp(transaction, msInfo.id);
  682. const all_m_tp = this.ctx.helper.round(one_bill_m_tp, this.ctx.material.decimal.tp);
  683. const all_tax_tp = this.ctx.helper.round(one_bill_tax_tp, this.ctx.material.decimal.tp);
  684. // for (const sid of this.ctx.material.stage_id.split(',')) {
  685. // const materialCalculator = new MaterialCalculator(this.ctx, sid, this.ctx.tender.info);
  686. // const quantity = await materialCalculator.calculateExpr(data.expr);
  687. // const msInfo = await this.ctx.service.materialStage.getDataByCondition({ mid: this.ctx.material.id, sid });
  688. // const msbInfo = await this.ctx.service.materialStageBills.getDataByCondition({ mid: this.ctx.material.id, mb_id: data.id, ms_id: msInfo.id });
  689. // const newQuantity = quantity !== 0 ? this.ctx.helper.round(quantity, this.ctx.material.decimal.qty) : null;
  690. // const m_tp = newQuantity ? this.ctx.helper.round(this.ctx.helper.mul(newQuantity, msbInfo.m_spread), this.ctx.material.decimal.tp) : null;
  691. // const updateData = {
  692. // id: data.id,
  693. // quantity: newQuantity,
  694. // m_tp,
  695. // m_tax_tp: this.ctx.helper.round(this.ctx.helper.mul(m_tp, (1 + this.ctx.helper.div(mbInfo.m_tax, 100))), this.ctx.material.decimal.tp),
  696. // };
  697. // const [one_bill_m_tp, one_bill_tax_tp] = await this.ctx.service.materialStageBills.update(transaction, updateData, msInfo.id);
  698. // await this.ctx.service.materialStage.updateMtp(transaction, msInfo.id);
  699. // all_m_tp = this.ctx.helper.round(one_bill_m_tp, this.ctx.material.decimal.tp);
  700. // all_tax_tp = this.ctx.helper.round(one_bill_tax_tp, this.ctx.material.decimal.tp);
  701. // }
  702. const updateBillsData = {
  703. id: data.id,
  704. // expr: data.expr,
  705. m_tp: all_m_tp ? all_m_tp : null,
  706. m_tax_tp: all_tax_tp ? all_tax_tp : null,
  707. };
  708. console.log(all_m_tp);
  709. await transaction.update(this.tableName, updateBillsData);
  710. returnData.m_tp = await this.calcMaterialMTp(transaction);
  711. returnData.stageBillsData = await transaction.select(this.ctx.service.materialStageBills.tableName, { where: { mid: this.ctx.material.id, mb_id: data.id } });
  712. returnData.stageData = await transaction.select(this.ctx.service.materialStage.tableName, { where: { mid: this.ctx.material.id } });
  713. } else {
  714. const materialCalculator = new MaterialCalculator(this.ctx, this.ctx.material.stage_id, this.ctx.tender.info);
  715. const quantity = await materialCalculator.calculateExpr(data.expr);
  716. // 更新quantity值并重新返回计算本期金额,截止本期金额
  717. const updateData = {
  718. id: data.id,
  719. quantity: quantity !== 0 ? this.ctx.helper.round(quantity, this.ctx.material.decimal.qty) : null,
  720. expr: data.expr,
  721. };
  722. const mbInfo = await this.getDataById(updateData.id);
  723. updateData.m_tp = this.ctx.helper.round(this.ctx.helper.mul(updateData.quantity, mbInfo.m_spread), this.ctx.material.decimal.tp);
  724. updateData.m_tax_tp = this.ctx.helper.round(this.ctx.helper.mul(updateData.m_tp, (1 + this.ctx.helper.div(mbInfo.m_tax, 100))), this.ctx.material.decimal.tp);
  725. await transaction.update(this.tableName, updateData);
  726. if (mbInfo.quantity !== updateData.quantity) {
  727. returnData.m_tp = await this.calcMaterialMTp(transaction);
  728. }
  729. }
  730. await transaction.commit();
  731. returnData.info = await this.getDataById(data.id);
  732. return returnData;
  733. } catch (err) {
  734. await transaction.rollback();
  735. throw err;
  736. }
  737. }
  738. // 更改计算总金额并返回值
  739. async calcMaterialMTp(transaction) {
  740. // 金额发生变化,则重新计算本期金额
  741. const sql = 'SELECT SUM(`m_tp`) as total_price, SUM(IF(`m_tax_tp` is null, `m_tp`, `m_tax_tp`)) as tax_total_price FROM ' + this.tableName + ' WHERE `tid` = ? AND `is_summary` = 1';
  742. const sqlParam = [this.ctx.tender.id];
  743. const tp = await transaction.queryOne(sql, sqlParam);
  744. const updateData2 = {
  745. id: this.ctx.material.id,
  746. m_tp: tp.total_price,
  747. m_tax_tp: tp.tax_total_price,
  748. };
  749. console.log(tp);
  750. // if (this.ctx.material.material_tax) {
  751. // updateData2.m_tax_tp = tp.tax_total_price;
  752. // }
  753. await transaction.update(this.ctx.service.material.tableName, updateData2);
  754. // 找出当前人并更新tp_data
  755. const tp_data = await this.ctx.service.materialAudit.getTpData(transaction, this.ctx.material.id);
  756. if (this.ctx.material.status === auditConst.status.uncheck || this.ctx.material.status === auditConst.status.checkNo) {
  757. await transaction.update(this.ctx.service.material.tableName, {
  758. id: this.ctx.material.id,
  759. tp_data: JSON.stringify(tp_data),
  760. });
  761. } else if (this.ctx.material.curAuditor) {
  762. await transaction.update(this.ctx.service.materialAudit.tableName, {
  763. id: this.ctx.material.curAuditor.id,
  764. tp_data: JSON.stringify(tp_data),
  765. });
  766. }
  767. return tp.total_price;
  768. }
  769. // 小数位变化更新单价和金额
  770. async resetDecimal(transaction, newDecimalUp, newDecimalTp, newDecimalQty) {
  771. const mbList = await transaction.select(this.tableName, { where: { tid: this.ctx.tender.id }, orders: [['order', 'asc']] });
  772. const updateList = [];
  773. const material_month = this.ctx.material.months ? this.ctx.material.months.split(',') : [];
  774. const updateMonthList = [];
  775. const materialStageList = this.ctx.material.is_stage_self ? await transaction.select(this.ctx.service.materialStage.tableName, { where: { mid: this.ctx.material.id } }) : [];
  776. for (const mb of mbList) {
  777. const updateData = {
  778. id: mb.id,
  779. };
  780. if (this.ctx.material.is_stage_self) {
  781. const updateStageBillsList = [];
  782. for (const ms of materialStageList) {
  783. const msb = await transaction.get(this.ctx.service.materialStageBills.tableName, { mid: this.ctx.material.id, mb_id: mb.id, ms_id: ms.id });
  784. msb.m_up_risk = mb.m_up_risk;
  785. msb.m_down_risk = mb.m_down_risk;
  786. const updateStageBillData = {
  787. id: msb.id,
  788. };
  789. if (newDecimalQty !== this.ctx.material.decimal.qty) {
  790. // 通过管理重新算出quantity并保留小数位
  791. if (mb.t_type === materialConst.t_type[0].value) {
  792. // 通过管理重新算出quantity并保留小数位
  793. const sql = 'SELECT SUM(' + this.ctx.helper.getQtySource(this.ctx.material.qty_source) + '*`quantity`) as quantity FROM ' + this.ctx.service.materialList.tableName + ' WHERE `mid`=? AND `mb_id`=? AND `ms_id`=? AND `is_join`=1';
  794. const sqlParam = [this.ctx.material.id, mb.id, ms.id];
  795. const mb_quantity = await transaction.queryOne(sql, sqlParam);
  796. const newQuantity = this.ctx.helper.round(mb_quantity.quantity, newDecimalQty);
  797. if (newQuantity !== msb.quantity) {
  798. updateStageBillData.quantity = newQuantity;
  799. msb.quantity = newQuantity;
  800. }
  801. } else if (mb.t_type === materialConst.t_type[1].value) {
  802. const materialCalculator = new MaterialCalculator(this.ctx, ms.sid, this.ctx.tender.info);
  803. const quantity = await materialCalculator.calculateExpr(msb.expr);
  804. const newQuantity = this.ctx.helper.round(quantity, newDecimalQty);
  805. if (newQuantity !== msb.quantity) {
  806. updateStageBillData.quantity = newQuantity;
  807. msb.quantity = newQuantity;
  808. }
  809. }
  810. }
  811. if (newDecimalUp !== this.ctx.material.decimal.up) {
  812. const newmsg_tp = this.ctx.helper.round(msb.msg_tp, newDecimalUp);
  813. msb.msg_tp = newmsg_tp;
  814. const newbasic_price = this.ctx.helper.round(mb.basic_price, newDecimalUp);
  815. const [newmsg_spread, newm_spread] = await this.getSpread(msb, msb.msg_tp, newDecimalUp, newbasic_price);
  816. msb.m_spread = newm_spread;
  817. updateStageBillData.msg_tp = newmsg_tp;
  818. updateStageBillData.msg_spread = newmsg_spread;
  819. updateStageBillData.m_spread = newm_spread;
  820. }
  821. const newTp = this.ctx.helper.round(this.ctx.helper.mul(msb.quantity, msb.m_spread), newDecimalTp);
  822. updateStageBillData.m_tp = newTp;
  823. updateStageBillData.m_tax_tp = this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mb.m_tax, 100))), newDecimalTp);
  824. updateStageBillsList.push(updateStageBillData);
  825. }
  826. if (newDecimalUp !== this.ctx.material.decimal.up) {
  827. const newbasic_price = this.ctx.helper.round(mb.basic_price, newDecimalUp);
  828. updateData.basic_price = newbasic_price;
  829. }
  830. if (updateStageBillsList.length > 0) await transaction.updateRows(this.ctx.service.materialStageBills.tableName, updateStageBillsList);
  831. const sql = 'SELECT SUM(`m_tp`) as total_price, SUM(IF(`m_tax_tp` is null, `m_tp`, `m_tax_tp`)) as tax_total_price FROM ' + this.ctx.service.materialStageBills.tableName + ' WHERE `tid` = ? AND `mid` = ? AND `mb_id` = ? AND `is_summary` = 1';
  832. const sqlParam = [this.ctx.tender.id, this.ctx.material.id, mb.id];
  833. const tp = await transaction.queryOne(sql, sqlParam);
  834. updateData.m_tp = this.ctx.helper.round(tp.total_price, newDecimalTp);
  835. updateData.m_tax_tp = this.ctx.helper.round(tp.tax_total_price, newDecimalTp);
  836. updateList.push(updateData);
  837. } else {
  838. if (newDecimalUp !== this.ctx.material.decimal.up) {
  839. let newmsg_tp = this.ctx.helper.round(mb.msg_tp, newDecimalUp);
  840. mb.msg_tp = newmsg_tp;
  841. // 判断是否有月信息价,如果有则msg_tp值由月信息价的平均单价获得,并更新月信息价单价
  842. if (material_month.length > 0) {
  843. const monthList = await transaction.select(this.ctx.service.materialMonth.tableName, { where: { mb_id: mb.id, mid: this.ctx.material.id } });
  844. if (monthList.length !== 0) {
  845. for (const m of monthList) {
  846. // 更新月信息单价小数位
  847. const newMonthMsgTP = this.ctx.helper.round(m.msg_tp, newDecimalUp);
  848. if (m.msg_tp && newMonthMsgTP !== m.msg_tp) {
  849. m.msg_tp = newMonthMsgTP;
  850. updateMonthList.push({ id: m.id, msg_tp: m.msg_tp });
  851. }
  852. }
  853. const mb_msg_tp_sum = this._.sumBy(monthList, 'msg_tp');
  854. const month_num = material_month.length - this.ctx.helper.arrayCount(this._.map(monthList, 'msg_tp'), [null, '', 0]);
  855. newmsg_tp = month_num !== 0 ? this.ctx.helper.round(this.ctx.helper.div(mb_msg_tp_sum, month_num), newDecimalUp) : null;
  856. mb.msg_tp = newmsg_tp;
  857. }
  858. }
  859. const newbasic_price = this.ctx.helper.round(mb.basic_price, newDecimalUp);
  860. mb.basic_price = newbasic_price;
  861. const [newmsg_spread, newm_spread] = await this.getSpread(mb, mb.msg_tp, newDecimalUp);
  862. mb.m_spread = newm_spread;
  863. updateData.basic_price = newbasic_price;
  864. updateData.msg_tp = newmsg_tp;
  865. updateData.msg_spread = newmsg_spread;
  866. updateData.m_spread = newm_spread;
  867. }
  868. if (newDecimalQty !== this.ctx.material.decimal.qty) {
  869. // 通过管理重新算出quantity并保留小数位
  870. if (mb.t_type === materialConst.t_type[0].value) {
  871. const sql = 'SELECT SUM(' + this.ctx.helper.getQtySource(this.ctx.material.qty_source) + '*`quantity`) as quantity FROM ' + this.ctx.service.materialList.tableName + ' WHERE `mid`=? AND `mb_id`=? AND `is_join`=1';
  872. const sqlParam = [this.ctx.material.id, mb.id];
  873. const mb_quantity = await transaction.queryOne(sql, sqlParam);
  874. const newQuantity = this.ctx.helper.round(mb_quantity.quantity, newDecimalQty);
  875. mb.quantity = newQuantity;
  876. updateData.quantity = newQuantity;
  877. } else if (mb.t_type === materialConst.t_type[1].value) {
  878. const materialCalculator = new MaterialCalculator(this.ctx, this.ctx.material.stage_id, this.ctx.tender.info);
  879. const quantity = await materialCalculator.calculateExpr(mb.expr);
  880. const newQuantity = this.ctx.helper.round(quantity, newDecimalQty);
  881. mb.quantity = newQuantity;
  882. updateData.quantity = newQuantity;
  883. }
  884. }
  885. const newTp = this.ctx.helper.round(this.ctx.helper.mul(mb.quantity, mb.m_spread), newDecimalTp);
  886. updateData.m_tp = newTp;
  887. updateData.m_tax_tp = this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mb.m_tax, 100))), newDecimalTp);
  888. updateList.push(updateData);
  889. }
  890. }
  891. if (updateMonthList.length > 0) await transaction.updateRows(this.ctx.service.materialMonth.tableName, updateMonthList);
  892. if (updateList.length > 0) await transaction.updateRows(this.tableName, updateList);
  893. if (this.ctx.material.is_stage_self) {
  894. for (const ms of materialStageList) {
  895. await this.ctx.service.materialStage.updateMtp(transaction, ms.id);
  896. }
  897. }
  898. }
  899. // 来源模式变化更新单价和金额
  900. async resetQuantityByQtySource(transaction, newQtySource) {
  901. const mbList = await transaction.select(this.tableName, { where: { tid: this.ctx.tender.id }, orders: [['order', 'asc']] });
  902. const updateList = [];
  903. const materialStageList = this.ctx.material.is_stage_self ? await transaction.select(this.ctx.service.materialStage.tableName, { where: { mid: this.ctx.material.id } }) : [];
  904. for (const mb of mbList) {
  905. if (mb.t_type === materialConst.t_type[0].value) {
  906. const updateData = {
  907. id: mb.id,
  908. };
  909. if (this.ctx.material.is_stage_self) {
  910. const updateStageBillsList = [];
  911. for (const ms of materialStageList) {
  912. const msb = await transaction.get(this.ctx.service.materialStageBills.tableName, {
  913. mid: this.ctx.material.id,
  914. mb_id: mb.id,
  915. ms_id: ms.id,
  916. });
  917. // 通过管理重新算出quantity并保留小数位
  918. const sql = 'SELECT SUM(' + this.ctx.helper.getQtySource(newQtySource) + '*`quantity`) as quantity FROM ' + this.ctx.service.materialList.tableName + ' WHERE `mid`=? AND `mb_id`=? AND `ms_id`=? AND `is_join`=1';
  919. const sqlParam = [this.ctx.material.id, mb.id, ms.id];
  920. const mb_quantity = await transaction.queryOne(sql, sqlParam);
  921. const newQuantity = this.ctx.helper.round(mb_quantity.quantity, this.ctx.material.decimal.qty);
  922. if (newQuantity !== msb.quantity) {
  923. const updateStageBillData = {
  924. id: msb.id,
  925. quantity: newQuantity,
  926. };
  927. msb.quantity = newQuantity;
  928. const newTp = this.ctx.helper.round(this.ctx.helper.mul(msb.quantity, msb.m_spread), this.ctx.material.decimal.tp);
  929. updateStageBillData.m_tp = newTp;
  930. updateStageBillData.m_tax_tp = this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mb.m_tax, 100))), this.ctx.material.decimal.tp);
  931. updateStageBillsList.push(updateStageBillData);
  932. }
  933. }
  934. if (updateStageBillsList.length > 0) await transaction.updateRows(this.ctx.service.materialStageBills.tableName, updateStageBillsList);
  935. const sql = 'SELECT SUM(`m_tp`) as total_price, SUM(IF(`m_tax_tp` is null, `m_tp`, `m_tax_tp`)) as tax_total_price FROM ' + this.ctx.service.materialStageBills.tableName + ' WHERE `tid` = ? AND `mid` = ? AND `mb_id` = ? AND `is_summary` = 1';
  936. const sqlParam = [this.ctx.tender.id, this.ctx.material.id, mb.id];
  937. const tp = await transaction.queryOne(sql, sqlParam);
  938. updateData.m_tp = this.ctx.helper.round(tp.total_price, this.ctx.material.decimal.tp);
  939. updateData.m_tax_tp = this.ctx.helper.round(tp.tax_total_price, this.ctx.material.decimal.tp);
  940. updateList.push(updateData);
  941. } else {
  942. const sql = 'SELECT SUM(' + this.ctx.helper.getQtySource(newQtySource) + '*`quantity`) as quantity FROM ' + this.ctx.service.materialList.tableName + ' WHERE `mid`=? AND `mb_id`=? AND `is_join`=1';
  943. const sqlParam = [this.ctx.material.id, mb.id];
  944. const mb_quantity = await transaction.queryOne(sql, sqlParam);
  945. const newQuantity = this.ctx.helper.round(mb_quantity.quantity, this.ctx.material.decimal.qty);
  946. if (newQuantity !== mb.quantity) {
  947. mb.quantity = newQuantity;
  948. updateData.quantity = newQuantity;
  949. const newTp = this.ctx.helper.round(this.ctx.helper.mul(mb.quantity, mb.m_spread), this.ctx.material.decimal.tp);
  950. updateData.m_tp = newTp;
  951. updateData.m_tax_tp = this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mb.m_tax, 100))), this.ctx.material.decimal.tp);
  952. updateList.push(updateData);
  953. }
  954. }
  955. }
  956. }
  957. if (updateList.length > 0) await transaction.updateRows(this.tableName, updateList);
  958. if (this.ctx.material.is_stage_self) {
  959. for (const ms of materialStageList) {
  960. await this.ctx.service.materialStage.updateMtp(transaction, ms.id);
  961. }
  962. }
  963. }
  964. async updateAllOrder(updateList) {
  965. await this.db.updateRows(this.tableName, updateList);
  966. }
  967. }
  968. return MaterialBills;
  969. };