material_bills.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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 newBills = {
  33. tid: this.ctx.tender.id,
  34. mid: this.ctx.material.id,
  35. in_time: new Date(),
  36. };
  37. // 新增工料
  38. const result = await this.db.insert(this.tableName, newBills);
  39. if (result.affectedRows !== 1) {
  40. throw '新增工料数据失败';
  41. }
  42. return await this.getDataById(result.insertId);
  43. }
  44. /**
  45. * 删除工料
  46. * @param {int} id 工料id
  47. * @return {void}
  48. */
  49. async del(id) {
  50. if (!this.ctx.tender || !this.ctx.material) {
  51. throw '数据错误';
  52. }
  53. // 判断t_type是否为费用,且存在quantity,m_spread值
  54. const transaction = await this.db.beginTransaction();
  55. try {
  56. const mbInfo = await this.getDataById(id);
  57. await transaction.delete(this.tableName, { id });
  58. let m_tp = this.ctx.material.m_tp;
  59. if (mbInfo.t_type === materialConst.t_type[1].value && mbInfo.quantity !== null && mbInfo.m_spread !== null) {
  60. // 金额发生变化,则重新计算本期金额
  61. m_tp = await this.calcMaterialMTp(transaction);
  62. }
  63. await transaction.commit();
  64. return m_tp;
  65. } catch (err) {
  66. await transaction.rollback();
  67. throw err;
  68. }
  69. }
  70. /**
  71. * 修改工料信息
  72. * @param {Object} data 工料内容
  73. * @return {void}
  74. */
  75. async save(data) {
  76. if (!this.ctx.tender || !this.ctx.material) {
  77. throw '数据错误';
  78. }
  79. delete data.in_time;
  80. // delete data.m_tp;
  81. // 判断是否可修改
  82. // 判断t_type是否为费用
  83. const transaction = await this.db.beginTransaction();
  84. try {
  85. await transaction.update(this.tableName, data);
  86. const m_tp = await this.calcMaterialMTp(transaction);
  87. await transaction.commit();
  88. return m_tp;
  89. } catch (err) {
  90. await transaction.rollback();
  91. throw err;
  92. }
  93. }
  94. /**
  95. * 修改工料信息
  96. * @param {Object} data 工料内容
  97. * @return {void}
  98. */
  99. async saveDatas(datas) {
  100. if (!this.ctx.tender || !this.ctx.material) {
  101. throw '数据错误';
  102. }
  103. // 判断是否可修改
  104. // 判断t_type是否为费用
  105. const transaction = await this.db.beginTransaction();
  106. try {
  107. for (const data of datas) {
  108. delete data.in_time;
  109. // delete data.m_tp;
  110. // console.log(data);
  111. await transaction.update(this.tableName, data);
  112. }
  113. // console.log(datas);
  114. // await transaction.update(this.tableName, datas);
  115. const m_tp = await this.calcMaterialMTp(transaction);
  116. await transaction.commit();
  117. return m_tp;
  118. } catch (err) {
  119. await transaction.rollback();
  120. throw err;
  121. }
  122. }
  123. /**
  124. * 更新新一期的quantity和截止上期金额并返回本期总金额
  125. * @param transaction
  126. * @param tid
  127. * @param mid
  128. * @returns {Promise<number>}
  129. */
  130. async updateNewMaterial(transaction, tid, mid, ctx, stage_id) {
  131. const materialBillsData = await this.getAllDataByCondition({ where: { tid } });
  132. let m_tp = 0;
  133. const materialCalculator = new MaterialCalculator(ctx, stage_id, ctx.tender.info);
  134. for (const mb of materialBillsData) {
  135. const one_tp = await this.calcQuantityByMB(transaction, mid, mb, materialCalculator);
  136. m_tp = this.ctx.helper.add(m_tp, one_tp);
  137. }
  138. return m_tp;
  139. }
  140. /**
  141. * 修改quantity,m_spread值和返回单条调差金额(新增一期)
  142. * @param transaction
  143. * @param mid
  144. * @param mb
  145. * @returns {Promise<*>}
  146. */
  147. async calcQuantityByMB(transaction, mid, mb, materialCalculator) {
  148. const [newmsg_spread, newm_spread] = await this.getSpread(mb);
  149. if (mb.t_type === materialConst.t_type[0].value) {
  150. const sql = 'SELECT SUM(`gather_qty`*`quantity`) as quantity FROM ' + this.ctx.service.materialList.tableName + ' WHERE `mid`=? AND `mb_id`=? AND `is_join`=1';
  151. const sqlParam = [mid, mb.id];
  152. const mb_quantity = await transaction.queryOne(sql, sqlParam);
  153. console.log(mb_quantity);
  154. // 取历史期记录获取截止上期调差金额,并清空本期单价和时间,重新计算价差和有效价差
  155. const updateData = {
  156. id: mb.id,
  157. quantity: this.ctx.helper.round(mb_quantity.quantity, 3),
  158. msg_tp: null,
  159. msg_times: null,
  160. msg_spread: newmsg_spread,
  161. m_spread: newm_spread,
  162. pre_tp: mb.m_tp !== null ? this.ctx.helper.round(this.ctx.helper.add(mb.pre_tp, mb.m_tp), 2) : mb.pre_tp,
  163. };
  164. await transaction.update(this.tableName, updateData);
  165. return await this.ctx.helper.round(this.ctx.helper.mul(mb_quantity.quantity, newm_spread), 2);
  166. } else if (mb.t_type === materialConst.t_type[1].value) {
  167. const quantity = await materialCalculator.calculateExpr(mb.expr);
  168. const updateData = {
  169. id: mb.id,
  170. quantity: quantity !== 0 && quantity !== null ? this.ctx.helper.round(quantity, 3) : null,
  171. msg_tp: null,
  172. msg_times: null,
  173. msg_spread: newmsg_spread,
  174. m_spread: newm_spread,
  175. pre_tp: mb.m_tp !== null ? this.ctx.helper.round(this.ctx.helper.add(mb.pre_tp, mb.m_tp), 2) : mb.pre_tp,
  176. };
  177. await transaction.update(this.tableName, updateData);
  178. return await this.ctx.helper.round(this.ctx.helper.mul(quantity, newm_spread), 2);
  179. }
  180. }
  181. /**
  182. * 清空本期信息价后更新价差和有效价差
  183. * @param data
  184. * @returns {Promise<void>}
  185. */
  186. async getSpread(data) {
  187. data.msg_tp = null;
  188. const msg_spread = this.ctx.helper.round(this.ctx.helper.sub(data.msg_tp, data.basic_price), 3);
  189. const cor = msg_spread >= 0 ? this.ctx.helper.mul(data.basic_price, this.ctx.helper.div(data.m_up_risk, 100)) : this.ctx.helper.mul(data.basic_price, this.ctx.helper.div(data.m_down_risk, 100));
  190. const m_spread = Math.abs(msg_spread) > Math.abs(cor) ? (msg_spread > 0 ? this.ctx.helper.round(this.ctx.helper.sub(msg_spread, cor), 3) : this.ctx.helper.round(this.ctx.helper.add(msg_spread, cor), 3)) : 0;
  191. return [msg_spread, m_spread];
  192. }
  193. /**
  194. * 修改 expr和quantity值,返回本期金额和单条数据
  195. * @param data
  196. * @returns {Promise<void>}
  197. */
  198. async updateFYQuantity(data) {
  199. if (!this.ctx.tender || !this.ctx.material) {
  200. throw '数据错误';
  201. }
  202. const transaction = await this.db.beginTransaction();
  203. try {
  204. const mbInfo = await this.getDataById(data.id);
  205. data.m_tp = this.ctx.helper.round(this.ctx.helper.mul(data.quantity, mbInfo.m_spread), 2);
  206. await transaction.update(this.tableName, data);
  207. let m_tp = this.ctx.material.m_tp;
  208. if (mbInfo.quantity !== data.quantity) {
  209. m_tp = await this.calcMaterialMTp(transaction);
  210. }
  211. await transaction.commit();
  212. const returnData = {
  213. m_tp,
  214. info: await this.getDataById(data.id),
  215. }
  216. return returnData;
  217. } catch (err) {
  218. await transaction.rollback();
  219. throw err;
  220. }
  221. }
  222. // 更改计算总金额并返回值
  223. async calcMaterialMTp(transaction) {
  224. // 金额发生变化,则重新计算本期金额
  225. const sql = 'SELECT SUM(`m_tp`) as total_price FROM ' + this.tableName + ' WHERE `tid` = ?';
  226. const sqlParam = [this.ctx.tender.id];
  227. const tp = await transaction.queryOne(sql, sqlParam);
  228. console.log(tp);
  229. const updateData2 = {
  230. id: this.ctx.material.id,
  231. m_tp: tp.total_price,
  232. };
  233. await transaction.update(this.ctx.service.material.tableName, updateData2);
  234. return tp.total_price;
  235. }
  236. }
  237. return MaterialBills;
  238. };