material_exponent.js 11 KB

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