'use strict'; /** * 期计量 数据模型 * * @author Mai * @date 2018/8/13 * @version */ const auditConst = require('../const/audit').material; const projectLogConst = require('../const/project_log'); const materialConst = require('../const/material'); module.exports = app => { class Material extends app.BaseService { /** * 构造函数 * * @param {Object} ctx - egg全局变量 * @return {void} */ constructor(ctx) { super(ctx); this.tableName = 'material'; } /** * 获取 最新一期 材料调差期计量 * @param tenderId * @param includeUnCheck * @return {Promise<*>} */ async getLastestMaterial(tenderId, includeUnCheck = false) { this.initSqlBuilder(); this.sqlBuilder.setAndWhere('tid', { value: tenderId, operate: '=', }); if (!includeUnCheck) { this.sqlBuilder.setAndWhere('status', { value: auditConst.status.uncheck, operate: '!=', }); } this.sqlBuilder.orderBy = [['order', 'desc']]; const [sql, sqlParam] = this.sqlBuilder.build(this.tableName); const material = await this.db.queryOne(sql, sqlParam); return material; } /** * 获取 最新一期 审批完成的 材料调差期计量 * @param tenderId * @return {Promise<*>} */ async getLastestCompleteMaterial(tenderId) { this.initSqlBuilder(); this.sqlBuilder.setAndWhere('tid', { value: tenderId, operate: '=', }); this.sqlBuilder.setAndWhere('status', { value: auditConst.status.checked, operate: '=', }); this.sqlBuilder.orderBy = [['order', 'desc']]; const [sql, sqlParam] = this.sqlBuilder.build(this.tableName); const material = await this.db.queryOne(sql, sqlParam); return material; } async checkMaterial(tid, order) { if (this.ctx.material) return; const materials = await this.getSelectMaterial(tid, order); this.ctx.material = materials[0] } /** * 获取标段下的全部计量期,按倒序 * @param tenderId * @return {Promise} */ async getSelectMaterial(tenderId, order) { const materials = await this.db.select(this.tableName, { where: { tid: tenderId, order }, }); if (materials.length > 0 && materials[0].status !== auditConst.status.checked) { const material = materials[0]; const curAuditor = await this.ctx.service.materialAudit.getCurAuditor(material.id, material.times); const isActive = curAuditor ? curAuditor.id === this.ctx.session.sessionUser.accountId : material.user_id === this.ctx.session.sessionUser.accountId; if (isActive) { material.curTimes = material.times; material.curOrder = curAuditor ? curAuditor.order : 0; } } return materials; } async getValidMaterials(tenderId) { const materials = await this.db.select(this.tableName, { where: { tid: tenderId }, orders: [['order', 'desc']], }); if (materials.length !== 0) { const lastMaterial = materials[materials.length - 1]; if (lastMaterial.status === auditConst.status.uncheck && lastMaterial.user_id !== this.ctx.session.sessionUser.accountId && !this.ctx.tender.isTourist) { materials.splice(materials.length - 1, 1); } } // 最新一期计量(未审批完成),当前操作人的期详细数据,应实时计算 if (materials.length > 0 && materials[0].status !== auditConst.status.checked) { const material = materials[0]; const curAuditor = await this.ctx.service.materialAudit.getCurAuditor(material.id, material.times); const isActive = curAuditor ? curAuditor.id === this.ctx.session.sessionUser.accountId : material.user_id === this.ctx.session.sessionUser.accountId; if (isActive) { material.curTimes = material.times; material.curOrder = curAuditor ? curAuditor.order : 0; } } return materials; } /** * 添加材料调差期 * @param tenderId - 标段id * @param data - post的数据 * @return {Promise} */ async addMaterial(tenderId, data) { const materials = await this.getAllDataByCondition({ where: { tid: tenderId }, order: ['order'], }); const preMaterial = materials[materials.length - 1]; if (materials.length > 0 && materials[materials.length - 1].status !== auditConst.status.checked) { throw '上一期未审批通过,请等待上一期审批通过后,再新增数据'; } const order = materials.length + 1; const newMaterial = { tid: tenderId, order, period: data.period, in_time: new Date(), times: 1, status: auditConst.status.uncheck, user_id: this.ctx.session.sessionUser.accountId, stage_id: data.stage_id.join(','), s_order: data.s_order, material_tax: this.ctx.session.sessionProject.page_show.openMaterialTax, decimal: preMaterial && preMaterial.decimal ? preMaterial.decimal : JSON.stringify(materialConst.decimal), is_new: 1, }; const transaction = await this.db.beginTransaction(); try { if (preMaterial) { newMaterial.rate = preMaterial.rate; newMaterial.pre_tp = this.ctx.helper.add(preMaterial.m_tp, preMaterial.pre_tp); newMaterial.ex_pre_tp = this.ctx.helper.add(preMaterial.ex_tp, preMaterial.ex_pre_tp); newMaterial.m_tax_pre_tp = preMaterial.material_tax ? this.ctx.helper.add(preMaterial.m_tax_tp, preMaterial.m_tax_pre_tp) : preMaterial.m_tax_pre_tp; } // 新增期记录 const result = await transaction.insert(this.tableName, newMaterial); if (result.affectedRows === 1) { newMaterial.id = result.insertId; } else { throw '新增期数据失败'; } // 存在上一期时,复制上一期审批流程、不参与调差的清单、上期清单并算本期有效价差,本期应耗数量,并算本期总金额 if (preMaterial) { const auditResult = await this.ctx.service.materialAudit.copyPreMaterialAuditors(transaction, preMaterial, newMaterial); if (!auditResult) { throw '复制上一期审批流程失败'; } // 复制不参与调差清单 const preNotJoinList = await this.ctx.service.materialListNotjoin.getAllDataByCondition({ where: { tid: this.ctx.tender.id, mid: preMaterial.id } }); await this.ctx.service.materialListNotjoin.copyNewStageNotJoinList(transaction, preNotJoinList, newMaterial.id); // 复制调差清单工料关联表 // await this.ctx.service.materialList.copyPreMaterialList(transaction, preMaterial, newMaterial); await this.ctx.service.materialList.copyPreMaterialList2(transaction, data.material_list, preNotJoinList, newMaterial); // 新增或删除list_gcl表 await this.ctx.service.materialListGcl.insertOrDelGcl(transaction, data.insertGclList, data.removeGclList, newMaterial.id); // 设置list_gcl表old=>new更新 await this.ctx.service.materialListGcl.setNewOldData(transaction, this.ctx.tender.id); // 修改本期应耗数量值和有效价差,需要剔除不参与调差的清单数据,并返回总金额 const [m_tp, m_tax_tp] = await this.ctx.service.materialBills.updateNewMaterial(transaction, this.ctx.tender.id, newMaterial.id, this.ctx, newMaterial.stage_id, JSON.parse(newMaterial.decimal)); // 修改现行价格指数,并返回调差基数json const ex_calc = await this.ctx.service.materialExponent.updateNewMaterial(transaction, newMaterial.id, this.ctx, newMaterial.stage_id, preMaterial.ex_calc, JSON.parse(newMaterial.decimal)); // 计算得出本期总金额 const updateMaterialData = { id: newMaterial.id, m_tp, m_tax_tp, ex_calc: JSON.stringify(ex_calc), }; await transaction.update(this.tableName, updateMaterialData); } await transaction.commit(); return newMaterial; } catch (err) { await transaction.rollback(); throw err; } } /** * 编辑计量期 * * @param {Number} mid - 第N期 * @param {String} period - 开始-截止时间 * @return {Promise} */ async saveMaterial(mid, period) { await this.db.update(this.tableName, { period, }, { where: { id: mid } }); } /** * 删除材料调差期 * * @param {Number} id - 期Id * @return {Promise} */ async deleteMaterial(id) { const transaction = await this.db.beginTransaction(); try { // 删除文件 const attList = await this.ctx.service.materialFile.getAllMaterialFiles(this.ctx.tender.id, id); await this.ctx.helper.delFiles(attList); await transaction.delete(this.ctx.service.materialAudit.tableName, { mid: id }); await transaction.delete(this.ctx.service.materialBills.tableName, { mid: id }); await transaction.delete(this.ctx.service.materialList.tableName, { mid: id }); await transaction.delete(this.ctx.service.materialListGcl.tableName, { mid: id }); await transaction.delete(this.ctx.service.materialListNotjoin.tableName, { mid: id }); await transaction.delete(this.ctx.service.materialBillsHistory.tableName, { mid: id }); await transaction.delete(this.ctx.service.materialFile.tableName, { mid: id }); await transaction.delete(this.ctx.service.materialExponent.tableName, { mid: id }); await transaction.delete(this.ctx.service.materialExponentHistory.tableName, { mid: id }); // 如果存在上一期,把上一期的quantity,expr,msg_tp,msg_times,msg_spread,m_up_risk,m_down_risk,m_spread,m_tp,pre_tp,orgin,is_summary添加到bill中 const materialInfo = await this.getDataById(id); if (materialInfo.order > 1) { const sql = 'UPDATE ' + this.ctx.service.materialBills.tableName + ' as mb, ' + this.ctx.service.materialBillsHistory.tableName + ' as mbh ' + 'SET mb.`quantity` = mbh.`quantity`, mb.`expr` = mbh.`expr`, ' + 'mb.`msg_tp` = mbh.`msg_tp`, mb.`msg_times` = mbh.`msg_times`, ' + 'mb.`msg_spread` = mbh.`msg_spread`, mb.`m_up_risk` = mbh.`m_up_risk`, ' + 'mb.`m_down_risk` = mbh.`m_down_risk`, mb.`m_spread` = mbh.`m_spread`, ' + 'mb.`m_tp` = mbh.`m_tp`, mb.`pre_tp` = mbh.`pre_tp`, ' + 'mb.`m_tax_tp` = mbh.`m_tax_tp`, mb.`tax_pre_tp` = mbh.`tax_pre_tp`, ' + 'mb.`origin` = mbh.`origin`, mb.`is_summary` = mbh.`is_summary`, mb.`m_tax` = mbh.`m_tax` ' + 'WHERE mbh.`tid` = ? AND mbh.`order` = ? AND mbh.`mb_id` = mb.`id`'; const sqlParam = [this.ctx.tender.id, materialInfo.order - 1]; await transaction.query(sql, sqlParam); const sql2 = 'UPDATE ' + this.ctx.service.materialExponent.tableName + ' as me, ' + this.ctx.service.materialExponentHistory.tableName + ' as meh ' + 'SET me.`weight_num` = meh.`weight_num`, me.`basic_price` = meh.`basic_price`, ' + 'me.`basic_times` = meh.`basic_times`, me.`m_price` = meh.`m_price`, ' + 'me.`calc_num` = meh.`calc_num`, me.`is_summary` = meh.`is_summary` ' + 'WHERE meh.`tid` = ? AND meh.`order` = ? AND meh.`me_id` = me.`id`'; const sqlParam2 = [this.ctx.tender.id, materialInfo.order - 1]; await transaction.query(sql2, sqlParam2); } // 设置list_gcl表old => new更新 await this.ctx.service.materialListGcl.setNewOldData(transaction, this.ctx.tender.id, 'old2new'); // 还要从material_list表更新gcl的old数据,更新方法 await this.ctx.service.materialListGcl.setOldFromLast(transaction, this.ctx.tender.id, materialInfo.order - 2); await transaction.delete(this.tableName, { id }); // 记录删除日志 await this.ctx.service.projectLog.addProjectLog(transaction, projectLogConst.type.material, projectLogConst.status.delete, '第' + materialInfo.order + '期'); await transaction.commit(); return true; } catch (err) { await transaction.rollback(); throw err; } } /** * 获取包含当前期之前的调差期id * * @param {Number} id - 期Id * @return {Promise} */ async getPreMidList(tid, order) { const midList = await this.getAllDataByCondition({ where: { tid }, columns: ['id'], limit: order, offset: 0, }); const list = []; for (const ml of midList) { list.push(ml.id); } return list; } /** * 修改增税税率 * @param {int} rate 税率 * @return {Promise<*>} */ async changeRate(rate) { const updateData = { id: this.ctx.material.id, rate, }; return await this.db.update(this.tableName, updateData); } /** * 修改调差基数 * @param {int} rate 税率 * @return {Promise<*>} */ async changeExCalc(ex_calc) { const transaction = await this.db.beginTransaction(); try { const updateData = { id: this.ctx.material.id, ex_calc: JSON.stringify(ex_calc), }; await transaction.update(this.tableName, updateData); const [ex_tp, ex_expr] = await this.ctx.service.materialExponent.calcMaterialExTp(transaction, ex_calc); await transaction.commit(); return [ex_tp, ex_expr]; } catch (err) { await transaction.rollback(); throw err; } } /** * 取当前期截止上期含建筑税金额 * @param {int} tid 标段id * @param {int} order 调差期数 * @return {Promise<*>} */ async getPreTpHs(tid, order, tp) { const sql = 'SELECT SUM(ROUND(`m_tp`*(1+ `rate`/100),' + tp + ')) AS `pre_tp_hs` FROM ?? WHERE `tid` = ? AND `material_tax` = ? AND `order` < ?'; const sqlParam = [this.tableName, tid, 0, order]; const result = await this.db.queryOne(sql, sqlParam); return result.pre_tp_hs; } /** * 取当前期截止上期含材料税金额 * @param {int} tid 标段id * @param {int} order 调差期数 * @return {Promise<*>} */ async getTaxPreTpHs(tid, order) { const sql = 'SELECT SUM(`m_tax_tp`) AS `tax_pre_tp_hs` FROM ?? WHERE `tid` = ? AND `material_tax` = ? AND `order` < ?'; const sqlParam = [this.tableName, tid, 1, order]; const result = await this.db.queryOne(sql, sqlParam); return result.tax_pre_tp_hs; } /** * 取当前期截止上期含建筑税指数金额 * @param {int} tid 标段id * @param {int} order 调差期数 * @return {Promise<*>} */ async getExPreTpHs(tid, order, tp) { const sql = 'SELECT SUM(ROUND(`ex_tp`*(1+ `rate`/100),' + tp + ')) AS `ex_pre_tp_hs` FROM ?? WHERE `tid` = ? AND `order` < ?'; const sqlParam = [this.tableName, tid, order]; const result = await this.db.queryOne(sql, sqlParam); return result.ex_pre_tp_hs; } async updateMaterialTax(id, mtax) { const updateData = { id, material_tax: mtax, }; return await this.db.update(this.tableName, updateData); } async getMaterialTaxTp(id) { const info = await this.getDataById(id); return info.m_tax_tp; } async getSumMaterial(tid) { const sql = 'Select sum(IFNULL(m_tp, 0) + IFNULL(ex_tp, 0)) as tp From ' + this.tableName + ' where tid = ?'; const result = await this.db.queryOne(sql, [tid]); return result ? result.tp : 0; } async getOldMaterialTax(tid, order) { const sql = 'SELECT COUNT(id) as count FROM ?? WHERE `tid` = ? AND `order` <= ? AND `material_tax` = 1'; const sqlParam = [this.tableName, tid, order]; const result = await this.db.queryOne(sql, sqlParam); return result && result.count !== 0; } async saveDecimal(newUp, newTp) { const transaction = await this.db.beginTransaction(); try { await this.ctx.service.materialBills.resetDecimal(transaction, newUp, newTp); this.ctx.material.decimal.up = newUp; this.ctx.material.decimal.tp = newTp; const m_tp = await this.ctx.service.materialBills.calcMaterialMTp(transaction); let update_calc = false; if (this.ctx.material.ex_calc) { const ex_calc = JSON.parse(this.ctx.material.ex_calc); const zdy = this._.find(ex_calc, { code: 'zdy' }); zdy.value = this.ctx.helper.round(zdy.value, newTp); this.ctx.material.ex_calc = JSON.stringify(ex_calc); update_calc = true; } const [ex_tp, ex_expr] = await this.ctx.service.materialExponent.calcMaterialExTp(transaction); const updateData = { id: this.ctx.material.id, decimal: JSON.stringify(this.ctx.material.decimal), }; if (update_calc) updateData.ex_calc = this.ctx.material.ex_calc; await transaction.update(this.tableName, updateData); await transaction.commit(); return true; } catch (err) { console.log(err); await transaction.rollback(); return false; } } } return Material; };