material_exponent.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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 MaterialExponent 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_exponent';
  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 newExponent = {
  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, newExponent);
  41. if (result.affectedRows !== 1) {
  42. throw '新增指数数据失败';
  43. }
  44. await transaction.commit();
  45. return await this.getDataById(result.insertId);
  46. } catch (error) {
  47. console.log(error);
  48. await transaction.rollback();
  49. throw error;
  50. }
  51. }
  52. /**
  53. * 删除指数清单
  54. * @param {int} id 工料id
  55. * @return {void}
  56. */
  57. async del(id) {
  58. if (!this.ctx.tender || !this.ctx.material) {
  59. throw '数据错误';
  60. }
  61. // 判断t_type是否为费用,且存在quantity,m_spread值
  62. const transaction = await this.db.beginTransaction();
  63. try {
  64. const meInfo = await this.getDataById(id);
  65. await transaction.delete(this.tableName, { id });
  66. let ex_tp = this.ctx.material.ex_tp;
  67. let ex_expr = this.ctx.material.ex_expr;
  68. if (meInfo.is_summary === materialConst.is_summary.yes) {
  69. // 金额发生变化,则重新计算本期金额
  70. [ex_tp, ex_expr] = await this.ctx.service.materialExponent.calcMaterialExTp(transaction);
  71. }
  72. await transaction.commit();
  73. return [ex_tp, ex_expr];
  74. } catch (err) {
  75. await transaction.rollback();
  76. throw err;
  77. }
  78. }
  79. /**
  80. * 修改指数清单信息
  81. * @param {Object} data 工料内容
  82. * @return {void}
  83. */
  84. async save(data) {
  85. if (!this.ctx.tender || !this.ctx.material) {
  86. throw '数据错误';
  87. }
  88. delete data.in_time;
  89. // delete data.m_tp;
  90. // 判断是否可修改
  91. // 判断t_type是否为费用
  92. const transaction = await this.db.beginTransaction();
  93. try {
  94. await transaction.update(this.tableName, data);
  95. const [ex_tp, ex_expr] = await this.calcMaterialExTp(transaction);
  96. await transaction.commit();
  97. return [ex_tp, ex_expr];
  98. } catch (err) {
  99. await transaction.rollback();
  100. throw err;
  101. }
  102. }
  103. /**
  104. * 复制粘贴指数清单
  105. * @param {Object} data 工料内容
  106. * @return {void}
  107. */
  108. async saveDatas(datas) {
  109. if (!this.ctx.tender || !this.ctx.material) {
  110. throw '数据错误';
  111. }
  112. // 判断是否可修改
  113. // 判断t_type是否为费用
  114. const transaction = await this.db.beginTransaction();
  115. try {
  116. await transaction.updateRows(this.tableName, datas);
  117. const [ex_tp, ex_expr] = await this.calcMaterialExTp(transaction);
  118. await transaction.commit();
  119. return [ex_tp, ex_expr];
  120. } catch (err) {
  121. await transaction.rollback();
  122. throw err;
  123. }
  124. }
  125. /**
  126. * 旧数据补充定值和历史数据
  127. * @returns {Promise<void>}
  128. */
  129. async addOldData() {
  130. if (!this.ctx.tender || !this.ctx.material) {
  131. throw '数据错误';
  132. }
  133. const transaction = await this.db.beginTransaction();
  134. try {
  135. // 先获取第一期的mid
  136. const first_material = await this.ctx.service.material.getDataByCondition({
  137. tid: this.ctx.tender.id,
  138. order: 1,
  139. });
  140. const insert_data = {
  141. tid: this.ctx.tender.id,
  142. mid: first_material.id,
  143. type: materialConst.ex_type[0].value,
  144. symbol: 'X',
  145. symbol_desc: '非可调因子',
  146. code: 'A',
  147. weight_num: 0,
  148. is_summary: materialConst.is_summary.yes,
  149. in_time: new Date(),
  150. };
  151. const result = await transaction.insert(this.tableName, insert_data);
  152. // 获取最新期数据
  153. const high_material = await this.ctx.service.material.getDataByCondition({
  154. tid: this.ctx.tender.id,
  155. order: this.ctx.material.highOrder,
  156. });
  157. const qi_order = high_material.status === auditConst.status.uncheck || high_material.status === auditConst.status.checkNo ? high_material.order - 1 : high_material;
  158. const insert_history_data = [];
  159. for (let i = 1; i <= qi_order; i++) {
  160. const one_insert = {
  161. tid: this.ctx.tender.id,
  162. mid: first_material.id,
  163. order: i,
  164. me_id: result.insertId,
  165. type: materialConst.ex_type[0].value,
  166. weight_num: 0,
  167. is_summary: materialConst.is_summary.yes,
  168. };
  169. insert_history_data.push(one_insert);
  170. }
  171. if (insert_history_data.length > 0) await transaction.insert(this.ctx.service.materialExponentHistory.tableName, insert_history_data);
  172. await transaction.commit();
  173. } catch (err) {
  174. await transaction.rollback();
  175. throw err;
  176. }
  177. }
  178. // 更改计算总指数金额并返回值和公式
  179. async calcMaterialExTp(transaction, ex_calc = (this.ctx.material.ex_calc ? JSON.parse(this.ctx.material.ex_calc) : null), mid = null) {
  180. let basic_calc = 0;
  181. if (ex_calc) {
  182. for (const calc of ex_calc) {
  183. if (calc.select) {
  184. basic_calc = this.ctx.helper.add(basic_calc, calc.value);
  185. }
  186. }
  187. }
  188. let expr = basic_calc + '*[';
  189. const exponentList = await transaction.select(this.tableName, { where: { tid: this.ctx.tender.id, is_summary: materialConst.is_summary.yes } });
  190. let sumByChange = 0;
  191. let constant = 0;
  192. for (const ex of exponentList) {
  193. if (ex.type === materialConst.ex_type[0].value) {
  194. constant = ex.weight_num ? ex.weight_num : 0;
  195. expr += constant.toString();
  196. } else if (ex.type === materialConst.ex_type[1].value) {
  197. const change = ex.calc_num ? ex.calc_num : 0;
  198. expr = expr + (change !== 0 ? '+' + ex.weight_num.toString() + '*(' + ex.m_price.toString() + '/' + ex.basic_price.toString() + ')' : '');
  199. sumByChange = this.ctx.helper.add(sumByChange, change);
  200. }
  201. }
  202. expr += '-1]';
  203. const ex_tp = this.ctx.helper.mul(basic_calc, this.ctx.helper.sub(this.ctx.helper.add(constant, sumByChange), 1));
  204. await transaction.update(this.ctx.service.material.tableName, {
  205. id: mid ? mid : this.ctx.material.id,
  206. ex_tp,
  207. ex_expr: expr,
  208. });
  209. console.log(ex_tp, expr);
  210. return [ex_tp, expr];
  211. }
  212. /**
  213. * 更新新一期的现行价格指数,并返回指数总金额和公式
  214. * @param transaction
  215. * @param tid
  216. * @param mid
  217. * @returns {Promise<number>}
  218. */
  219. async updateNewMaterial(transaction, mid, ctx, stage_id, ex_calc) {
  220. const calcBase = await ctx.service.stage.getMaterialCalcBase(stage_id, ctx.tender.info);
  221. const old_ex_calc = ex_calc ? JSON.parse(ex_calc) : null;
  222. const new_ex_calc = materialConst.ex_calc;
  223. for (const bq of new_ex_calc) {
  224. const calc = this._.find(calcBase, function(item) {
  225. return bq.code === item.code;
  226. });
  227. const oldcalc = old_ex_calc ? this._.find(JSON.parse(old_ex_calc), function(item) {
  228. return bq.code === item.code;
  229. }) : null;
  230. bq.value = calc.value;
  231. bq.select = oldcalc ? oldcalc.select : false;
  232. }
  233. await this.calcMaterialExTp(transaction, new_ex_calc, mid);
  234. return new_ex_calc;
  235. }
  236. }
  237. return MaterialExponent;
  238. };