'use strict'; /** * 期计量 数据模型 * * @author Mai * @date 2018/8/13 * @version */ const auditConst = require('../const/audit').material; const materialConst = require('../const/material'); const MaterialCalculator = require('../lib/material_calc'); module.exports = app => { class MaterialBills extends app.BaseService { /** * 构造函数 * * @param {Object} ctx - egg全局变量 * @return {void} */ constructor(ctx) { super(ctx); this.tableName = 'material_bills'; } /** * 添加工料 * @return {void} */ async add() { if (!this.ctx.tender || !this.ctx.material) { throw '数据错误'; } const transaction = await this.db.beginTransaction(); try { const newBills = { tid: this.ctx.tender.id, mid: this.ctx.material.id, in_time: new Date(), }; // 新增工料 const result = await transaction.insert(this.tableName, newBills); if (result.affectedRows !== 1) { throw '新增工料数据失败'; } const insertArray = []; const material_month = this.ctx.material.months ? this.ctx.material.months.split(',') : []; for (const ym of material_month) { const one_month = { tid: this.ctx.tender.id, mid: this.ctx.material.id, mb_id: result.insertId, msg_tp: null, yearmonth: ym, }; insertArray.push(one_month); } if (insertArray.length !== 0) await transaction.insert(this.ctx.service.materialMonth.tableName, insertArray); await transaction.commit(); return await this.getDataById(result.insertId); } catch (error) { console.log(error); await transaction.rollback(); throw error; } } /** * 删除工料 * @param {int} id 工料id * @return {void} */ async del(id) { if (!this.ctx.tender || !this.ctx.material) { throw '数据错误'; } // 判断t_type是否为费用,且存在quantity,m_spread值 const transaction = await this.db.beginTransaction(); try { const mbInfo = await this.getDataById(id); await transaction.delete(this.tableName, { id }); let m_tp = this.ctx.material.m_tp; if (mbInfo.t_type === materialConst.t_type[1].value && mbInfo.quantity !== null && mbInfo.m_spread !== null) { // 金额发生变化,则重新计算本期金额 m_tp = await this.calcMaterialMTp(transaction); } const material_month = this.ctx.material.months ? this.ctx.material.months.split(',') : []; if (material_month.length > 0) { await transaction.delete(this.ctx.service.materialMonth.tableName, { mb_id: id }); } await transaction.commit(); return m_tp; } catch (err) { await transaction.rollback(); throw err; } } /** * 修改工料信息 * @param {Object} data 工料内容 * @return {void} */ async save(data) { if (!this.ctx.tender || !this.ctx.material) { throw '数据错误'; } delete data.in_time; // delete data.m_tp; // 判断是否可修改 // 判断t_type是否为费用 const transaction = await this.db.beginTransaction(); try { await transaction.update(this.tableName, data); const m_tp = await this.calcMaterialMTp(transaction); await transaction.commit(); return m_tp; } catch (err) { await transaction.rollback(); throw err; } } /** * 修改工料信息 * @param {Object} data 工料内容 * @return {void} */ async saveDatas(datas) { if (!this.ctx.tender || !this.ctx.material) { throw '数据错误'; } // 判断是否可修改 // 判断t_type是否为费用 const transaction = await this.db.beginTransaction(); try { for (const data of datas) { delete data.in_time; // delete data.m_tp; // console.log(data); await transaction.update(this.tableName, data); } // console.log(datas); // await transaction.update(this.tableName, datas); const m_tp = await this.calcMaterialMTp(transaction); await transaction.commit(); return m_tp; } catch (err) { await transaction.rollback(); throw err; } } /** * 更新新一期的quantity和截止上期金额并返回本期总金额 * @param transaction * @param tid * @param mid * @returns {Promise} */ async updateNewMaterial(transaction, tid, mid, ctx, stage_id) { const materialBillsData = await this.getAllDataByCondition({ where: { tid } }); let m_tp = 0; const materialCalculator = new MaterialCalculator(ctx, stage_id, ctx.tender.info); for (const mb of materialBillsData) { const one_tp = await this.calcQuantityByMB(transaction, mid, mb, materialCalculator); m_tp = this.ctx.helper.add(m_tp, one_tp); } return m_tp; } /** * 修改quantity,m_spread值和返回单条调差金额(新增一期) * @param transaction * @param mid * @param mb * @returns {Promise<*>} */ async calcQuantityByMB(transaction, mid, mb, materialCalculator) { const [newmsg_spread, newm_spread] = await this.getSpread(mb, null); if (mb.t_type === materialConst.t_type[0].value) { const sql = 'SELECT SUM(`gather_qty`*`quantity`) as quantity FROM ' + this.ctx.service.materialList.tableName + ' WHERE `mid`=? AND `mb_id`=? AND `is_join`=1'; const sqlParam = [mid, mb.id]; const mb_quantity = await transaction.queryOne(sql, sqlParam); console.log(mb_quantity); // 取历史期记录获取截止上期调差金额,并清空本期单价和时间,重新计算价差和有效价差 const updateData = { id: mb.id, quantity: this.ctx.helper.round(mb_quantity.quantity, 3), msg_tp: null, msg_times: null, msg_spread: newmsg_spread, m_spread: newm_spread, m_tp: this.ctx.helper.round(this.ctx.helper.mul(this.ctx.helper.round(mb_quantity.quantity, 3), newm_spread), 2), pre_tp: mb.m_tp !== null ? this.ctx.helper.round(this.ctx.helper.add(mb.pre_tp, mb.m_tp), 2) : mb.pre_tp, }; await transaction.update(this.tableName, updateData); return mb.is_summary === 1 ? await this.ctx.helper.round(this.ctx.helper.mul(mb_quantity.quantity, newm_spread), 2) : 0; } else if (mb.t_type === materialConst.t_type[1].value) { const quantity = await materialCalculator.calculateExpr(mb.expr); const updateData = { id: mb.id, quantity: quantity !== 0 && quantity !== null ? this.ctx.helper.round(quantity, 3) : null, msg_tp: null, msg_times: null, msg_spread: newmsg_spread, m_spread: newm_spread, m_tp: quantity !== 0 && quantity !== null ? this.ctx.helper.round(this.ctx.helper.mul(this.ctx.helper.round(quantity, 3), newm_spread), 2) : null, pre_tp: mb.m_tp !== null ? this.ctx.helper.round(this.ctx.helper.add(mb.pre_tp, mb.m_tp), 2) : mb.pre_tp, }; await transaction.update(this.tableName, updateData); return mb.is_summary === 1 ? await this.ctx.helper.round(this.ctx.helper.mul(quantity, newm_spread), 2) : 0; } } /** * 清空本期信息价后更新价差和有效价差 * @param data * @returns {Promise} */ async getSpread(data, msg_tp) { data.msg_tp = msg_tp; const msg_spread = this.ctx.helper.round(this.ctx.helper.sub(data.msg_tp, data.basic_price), 3); 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)); 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; return [msg_spread, m_spread]; } /** * 修改 expr和quantity值,返回本期金额和单条数据 * @param data * @returns {Promise} */ async updateFYQuantity(data) { if (!this.ctx.tender || !this.ctx.material) { throw '数据错误'; } const transaction = await this.db.beginTransaction(); try { const mbInfo = await this.getDataById(data.id); data.m_tp = this.ctx.helper.round(this.ctx.helper.mul(data.quantity, mbInfo.m_spread), 2); await transaction.update(this.tableName, data); let m_tp = this.ctx.material.m_tp; if (mbInfo.quantity !== data.quantity) { m_tp = await this.calcMaterialMTp(transaction); } await transaction.commit(); const returnData = { m_tp, info: await this.getDataById(data.id), } return returnData; } catch (err) { await transaction.rollback(); throw err; } } // 更改计算总金额并返回值 async calcMaterialMTp(transaction) { // 金额发生变化,则重新计算本期金额 const sql = 'SELECT SUM(`m_tp`) as total_price FROM ' + this.tableName + ' WHERE `tid` = ? AND `is_summary` = 1'; const sqlParam = [this.ctx.tender.id]; const tp = await transaction.queryOne(sql, sqlParam); console.log(tp); const updateData2 = { id: this.ctx.material.id, m_tp: tp.total_price, }; await transaction.update(this.ctx.service.material.tableName, updateData2); return tp.total_price; } } return MaterialBills; };