'use strict'; /** * * * @author Mai * @date 2018/7/16 * @version */ const auditConst = require('../const/audit').flow; module.exports = app => { class MeasureAudit extends app.BaseService { /** * 构造函数 * * @param {Object} ctx - egg全局变量 * @return {void} */ constructor(ctx) { super(ctx); this.tableName = 'measure_audit'; } /** * 获取 中间计量 审核人信息 * * @param {uuid} mid - 中间计量id * @param {Number} auditorId - 审核人id * @param {Number} times - 第几次审批 * @return {Promise<*>} */ async getAuditor(mid, auditorId, times = 1) { const sql = 'SELECT ma.*, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone` ' + 'FROM ?? AS ma, ?? AS pa ' + 'WHERE ma.`mid` = ? and ma.`audit_id` = ? and ma.`times` = ?' + ' and ma.`audit_id` = pa.`id`'; const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, mid, auditorId, times]; return await this.db.queryOne(sql, sqlParam); } /** * 获取 中间计量 审核人列表信息 * * @param {uuid} mid - 中间计量id * @param {Number} times - 第几次审批 * @return {Promise<*>} */ async getAuditors(mid, times = 1) { const sql = 'SELECT ma.*, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone` ' + 'FROM ?? AS ma, ?? AS pa ' + 'WHERE ma.`mid` = ? and ma.`times` = ?' + ' and ma.`audit_id` = pa.`id` and ma.`order` > 0'; const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, mid, times]; return await this.db.query(sql, sqlParam); } /** * 获取 中间计量 当前审核人 * * @param {uuid} mid - 中间计量id * @param {Number} times - 第几次审批 * @return {Promise<*>} */ async getCurAuditor(mid, times = 1) { const sql = 'SELECT ma.`audit_id`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, ma.`times`, ma.`order`, ma.`status`, ma.`opinion`, ma.`begin_time`, ma.`end_time` ' + 'FROM ?? AS ma, ?? AS pa ' + 'WHERE ma.`mid` = ? and ma.`status` = ? and ma.`times` = ?' + ' and ma.`audit_id` = pa.`id`'; const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, mid, auditConst.status.checking, times]; return await this.db.queryOne(sql, sqlParam); } /** * 获取 中间计量 最新审核顺序 * * @param {uuid} mid - 中间计量id * @param {Number} times - 第几次审批 * @return {Promise} */ async getNewOrder(mid, times = 1) { const sql = 'SELECT Max(??) As max_order FROM ?? Where `mid` = ? and `times` = ? and `order` > 0'; const sqlParam = ['order', this.tableName, mid, times]; const result = await this.db.queryOne(sql, sqlParam); return result && result.max_order ? result.max_order + 1 : 1; } /** * 新增审核人 * * @param {Number} tenderId - 标段id * @param {uuid} mid - 中间计量id * @param {Number} auditorId - 审核人id * @param {Number} times - 第几次审批 * @return {Promise} */ async addAuditor(tenderId, mid, auditorId, times = 1) { const newOrder = await this.getNewOrder(mid, times); const data = { tender_id: tenderId, mid, audit_id: auditorId, times, order: newOrder, status: auditConst.status.uncheck, }; const result = await this.db.insert(this.tableName, data); return result.effectRows = 1; } /** * 移除审核人时,同步其后审核人order * @param transaction - 事务 * @param {uuid} mid - 中间计量id * @param {Number} auditorId - 审核人id * @param {Number} times - 第几次审批 * @return {Promise<*>} * @private */ async _syncOrderByDelete(transaction, mid, order, times) { this.initSqlBuilder(); this.sqlBuilder.setAndWhere('mid', { value: this.db.escape(mid), operate: '=', }); this.sqlBuilder.setAndWhere('order', { value: order, operate: '>=', }); this.sqlBuilder.setAndWhere('times', { value: times, operate: '=', }); this.sqlBuilder.setUpdateData('order', { value: 1, selfOperate: '-', }); const [sql, sqlParam] = this.sqlBuilder.build(this.tableName, 'update'); const data = await transaction.query(sql, sqlParam); return data; } /** * 移除审核人 * * @param {uuid} mid - 中间计量id * @param {Number} auditorId - 审核人id * @param {Number} times - 第几次审批 * @return {Promise} */ async deleteAuditor(mid, auditorId, times = 1) { const transaction = await this.db.beginTransaction(); try { const condition = { mid, audit_id: auditorId, times }; const auditor = await this.getDataByCondition(condition); if (!auditor) { throw '该审核人不存在'; } await this._syncOrderByDelete(transaction, mid, auditor.order, times); await transaction.delete(this.tableName, condition); await transaction.commit(); } catch (err) { await transaction.rollback(); throw err; } return true; } _sumBills(bills) { const result = { deal: 0, qc: 0 }; for (const b of bills) { result.deal = result.deal + (b.deal_totalprice ? b.deal_totalprice : 0); result.qc = result.qc + (b.qc_totalprice ? b.qc_totalprice : 0); } return result; } /** * 拷贝原报的历史数据 * * @param transacation - 事务 * @param {uuid} mid - 中间计量 * @param {Number} times - 次数 * @return {Promise} * @private */ async _copyReportBillsHistory(transacation, mid, times) { const bills = await this.ctx.service.measureBills.getAllDataByCondition({ where: { mid } }); const sum = this._sumBills(bills); const history = await this.getDataByCondition({ mid, times, order: 0 }); if (history) { await transacation.update(this.tableName, { id: history.id, bills: JSON.stringify(bills), deal_sum: sum.deal, qc_sum: sum.qc, }); } else { const measure = await this.ctx.service.measure.getDataByCondition({ mid }); await transacation.insert(this.tableName, { tender_id: measure.tender_id, mid, times, order: 0, audit_id: measure.user_id, status: 0, bills: JSON.stringify(bills), deal_sum: sum.deal, qc_sum: sum.qc, }); } return sum; } /** * 开始审批 * * @param {uuid} mid - 中间计量id * @param {Number} times - 第几次审批 * @return {Promise} */ async start(mid, times = 1) { const audit = await this.getDataByCondition({ mid, times, order: 1 }); if (!audit) { throw '审核人信息错误'; } const transaction = await this.db.beginTransaction(); try { // 记录历史数据 const sum = await this._copyReportBillsHistory(transaction, mid, times); // 更新审核人状态 await transaction.update(this.tableName, { id: audit.id, status: auditConst.status.checking, begin_time: new Date(), }); // 改变中间计量状态 await transaction.update(this.ctx.service.measure.tableName, { times, status: auditConst.status.checking, deal_sum: sum.deal, qc_sum: sum.qc, }, { where: { mid } }); await transaction.commit(); } catch (err) { await transaction.rollback(); throw err; } return true; } /** * 审批 * @param {uuid} mid - 中间计量id * @param {auditConst.status.checked|auditConst.status.checkNo} checkType - 审批结果 * @param {Number} times - 第几次审批 * @return {Promise} */ async check(mid, checkType, opinion, times = 1) { if (checkType !== auditConst.status.checked && checkType !== auditConst.status.checkNo) { throw '提交数据错误'; } const transaction = await this.db.beginTransaction(); try { // 整理当前流程审核人状态更新 const time = new Date(); const audit = await this.getDataByCondition({ mid, times, status: auditConst.status.checking }); if (!audit) { throw '审核数据错误'; } // 更新当前审核流程 const bills = await this.ctx.service.measureBills.getAllDataByCondition({ where: { mid } }); const sum = this._sumBills(bills); await transaction.update(this.tableName, { id: audit.id, status: checkType, opinion, end_time: time, bills: JSON.stringify(bills), deal_sum: sum.deal, qc_sum: sum.qc, }); const measureTable = this.ctx.service.measure.tableName; if (checkType === auditConst.status.checked) { const nextAudit = await this.getDataByCondition({ mid, times, order: audit.order + 1 }); // 无下一审核人表示,审核结束 if (nextAudit) { await transaction.update(this.tableName, { id: nextAudit.id, status: auditConst.status.checking, begin_time: time }); await transaction.update(measureTable, { deal_sum: sum.deal, qc_sum: sum.qc }, { where: { mid } }); } else { // 同步标段信息 await transaction.update(measureTable, { status: checkType, deal_sum: sum.deal, qc_sum: sum.qc }, { where: { mid } }); } } else { // 同步标段信息 await transaction.update(measureTable, { times: times + 1, status: checkType, deal_sum: sum.deal, qc_sum: sum.qc }, { where: { mid } }); // 拷贝新一次审核流程列表 const auditors = await this.getAllDataByCondition({ where: { mid, times }, columns: ['tender_id', 'order', 'audit_id', 'mid'], }); for (const a of auditors) { a.times = times + 1; a.status = auditConst.status.uncheck; } await transaction.insert(this.tableName, auditors); } await transaction.commit(); } catch (err) { await transaction.rollback(); throw err; } } /** * 获取审核人需要审核的标段列表 * * @param auditorId * @return {Promise<*>} */ async getAuditTender(auditorId) { const sql = 'SELECT ma.`audit_id`, ma.`times`, ma.`order`, ma.`begin_time`, t.`id`, t.`name`, t.`project_id`, t.`type`, t.`user_id` ' + 'FROM ?? AS ma, ?? AS t ' + 'WHERE ma.`audit_id` = ? and ma.`status` = ?' + ' and ma.`tender_id` = t.`id`'; const sqlParam = [this.tableName, this.ctx.service.tender.tableName, auditorId, auditConst.status.checking]; return await this.db.query(sql, sqlParam); } } return MeasureAudit; };