material_bills.js 11 KB

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