'use strict'; /** * 期 - 变更数据 * * @author Mai * @date * @version */ const defaultPid = -1; // 非pid const audit = require('../const/audit'); const timesLen = audit.stage.timesLen; const changeConst = require('../const/change'); module.exports = app => { class StageChange extends app.BaseService { /** * 构造函数 * * @param {Object} ctx - egg全局变量 * @return {void} */ constructor(ctx) { super(ctx); this.tableName = 'stage_change'; } /** * 查询 调用的变更令 最新数据 * @param {Number} tid - 标段id * @param {Number} sid - 期id * @param {Number} lid - 台账节点id * @param {Number} pid - 部位明细id * @return {Promise<*>} */ async getLastestStageData(tid, sid, lid, pid) { const sql = 'SELECT c.*,' + ' oc.p_code As c_code, oc.new_code As c_new_code' + ' FROM ' + this.tableName + ' As c ' + ' INNER JOIN ( ' + ' SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid` From ' + this.tableName + ' WHERE tid = ? And sid = ? And lid = ? And pid = ?' + ' GROUP By `lid`, `pid`, `cid`, `cbid`' + ' ) As m ' + ' ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid`' + ' LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' + ' ON c.cid = oc.cid' + ' LEFT JOIN ' + this.ctx.service.changeAuditList.tableName + ' As ocb' + ' ON c.cbid = ocb.id' + ' WHERE not ISNULL(ocb.id)'; const sqlParam = [tid, sid, lid, pid ? pid : -1]; return await this.db.query(sql, sqlParam); } /** * 查询 调用的变更令 某轮 某人的数据 * @param {Number} tid - 标段id * @param {Number} sid - 期id * @param {Number} times - 第几轮 * @param {Number} order - 第几人 * @param {Number} lid - 台账节点id * @param {Number} pid - 部位明细id * @return {Promise<*>} */ async getAuditorStageData(tid, sid, times, order, lid, pid) { const sql = 'SELECT c.*,' + ' oc.p_code As c_code, oc.new_code As c_new_code, oc.quality, ocb.code as b_code, ocb.name, ocb.unit' + ' FROM ' + this.tableName + ' As c ' + ' INNER JOIN ( ' + ' SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid` From ' + this.tableName + ' WHERE tid = ? And sid = ? And (`stimes` < ? OR (`stimes` = ? AND `sorder` <= ?)) And lid = ? And pid = ?' + ' GROUP By `lid`, `pid`, cid, cbid' + ' ) As m ' + ' ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid`' + ' LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' + ' ON c.cid = oc.cid' + ' LEFT JOIN ' + this.ctx.service.changeAuditList.tableName + ' As ocb' + ' ON c.cbid = ocb.id' + ' WHERE not ISNULL(ocb.id)'; const sqlParam = [tid, sid, times, times, order, lid, pid ? pid : -1]; return await this.db.query(sql, sqlParam); } async getLastestAllStageData(tid, sid) { const sql = 'SELECT c.*,' + ' oc.p_code As c_code, oc.new_code As c_new_code, oc.quality, ocb.code as b_code, ocb.name, ocb.unit' + ' FROM ' + this.tableName + ' As c ' + ' INNER JOIN ( ' + ' SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid` From ' + this.tableName + ' WHERE tid = ? And sid = ?' + ' GROUP By `lid`, `pid`, cid, cbid' + ' ) As m ' + ' ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid`' + ' LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' + ' ON c.cid = oc.cid' + ' LEFT JOIN ' + this.ctx.service.changeAuditList.tableName + ' As ocb' + ' ON c.cbid = ocb.id' + ' WHERE not ISNULL(ocb.id)'; const sqlParam = [tid, sid]; return await this.db.query(sql, sqlParam); } async getAuditorAllStageData(tid, sid, times, order) { const sql = 'SELECT c.*, ' + ' oc.p_code As c_code, oc.new_code As c_new_code, oc.quality, ocb.code as b_code, ocb.name, ocb.unit' + ' FROM ' + this.tableName + ' As c ' + ' INNER JOIN ( ' + ' SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid` From ' + this.tableName + ' WHERE tid = ? And sid = ? And (`stimes` < ? OR (`stimes` = ? AND `sorder` <= ?))' + ' GROUP By `lid`, `pid`, cid, cbid' + ' ) As m ' + ' ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid`' + ' LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' + ' ON c.cid = oc.cid' + ' LEFT JOIN ' + this.ctx.service.changeAuditList.tableName + ' As ocb' + ' ON c.cbid = ocb.id' + ' WHERE not ISNULL(ocb.id)'; const sqlParam = [tid, sid, times, times, order]; return await this.db.query(sql, sqlParam); } /** * 台账,调用变更令 * * @param {Object} bills - 台账节点数据 * @param {Array} changes - 调用的变更令 * @return {Promise} */ async billsChange(bills, changes) { const self = this; function getNewChange(cid, cbid, times, order, qty) { return { tid: self.ctx.tender.id, sid: self.ctx.stage.id, lid: bills.id, pid: -1, cid, cbid, stimes: times, sorder: order, qty, }; } const ledgerBills = await this.ctx.service.ledger.getDataById(bills.id); if (!ledgerBills || ledgerBills.tender_id !== this.ctx.tender.id) { throw '提交数据错误'; } const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, ledgerBills.unit); // 获取原变更令 const oldChanges = await this.getLastestStageData(this.ctx.tender.id, this.ctx.stage.id, bills.id, -1); // 获取更新数据 const updateChanges = [], newChanges = []; let billsQty = 0; for (const oc of oldChanges) { const nc = this._.find(changes, { cid: oc.cid, cbid: oc.cbid }); if (!nc || nc.qty !== oc.qty) { const qty = nc ? this.round(nc.qty, precision.value) : null; const change = getNewChange(oc.cid, oc.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, qty); billsQty = this.ctx.helper.add(billsQty, change.qty); if (oc.stimes === this.ctx.stage.curTimes && oc.sorder === this.ctx.stage.curOrder) { change.id = oc.id; updateChanges.push(change); } else { newChanges.push(change); } } else { billsQty = this.ctx.helper.add(billsQty, oc.qty); } } for (const c of changes) { const nc = this._.find(oldChanges, { cid: c.cid, cbid: c.cbid }); if (!nc) { const change = getNewChange(c.cid, c.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, this.round(c.qty, precision.value)); billsQty = this.ctx.helper.add(billsQty, change.qty); newChanges.push(change); } } // 更新数据 const transaction = await this.db.beginTransaction(); try { if (newChanges.length > 0) { await transaction.insert(this.tableName, newChanges); } for (const c of updateChanges) { await transaction.update(this.tableName, c); } const stageBills = await this.ctx.service.stageBills.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id, bills.id); await this.ctx.service.stageBills.updateStageBillsQty(transaction, ledgerBills, stageBills, { qc_qty: billsQty }); await transaction.commit(); } catch (err) { await transaction.rollback(); throw err; } const result = await this.ctx.service.stageBills.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id, [bills.id]); return { bills: { curStageData: result } }; } /** * 部位明细,调用变更令 * * @param {Object} pos - 部位明细数据 * @param {Array} changes - 调用的变更令 * @return {Promise<{}>} */ async posChange(pos, changes) { const self = this; function getNewChange(cid, cbid, times, order, qty) { return { tid: self.ctx.tender.id, sid: self.ctx.stage.id, lid: pos.lid, pid: pos.id, cid, cbid, stimes: times, sorder: order, qty, }; } const ledgerBills = await this.ctx.service.ledger.getDataById(pos.lid); if (!ledgerBills || ledgerBills.tender_id !== this.ctx.tender.id) { throw '提交数据错误'; } const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, ledgerBills.unit); // 获取原变更令 const oldChanges = await this.getLastestStageData(this.ctx.tender.id, this.ctx.stage.id, pos.lid, pos.id); const updateChanges = [], newChanges = []; let posQty = 0; for (const oc of oldChanges) { const nc = this._.find(changes, { cid: oc.cid, cbid: oc.cbid }); if (!nc || nc.qty !== oc.qty) { const qty = nc ? this.round(nc.qty, precision.value) : null; const change = getNewChange(oc.cid, oc.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, qty); posQty = this.ctx.helper.add(posQty, change.qty); if (oc.stimes === this.ctx.stage.curTimes && oc.sorder === this.ctx.stage.curOrder) { change.id = oc.id; updateChanges.push(change); } else { newChanges.push(change); } } else { posQty = this.ctx.helper.add(posQty, oc.qty); } } for (const c of changes) { const nc = this._.find(oldChanges, { cid: c.cid, cbid: c.cbid }); if (!nc) { const change = getNewChange(c.cid, c.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, this.round(c.qty, precision.value)); posQty = this.ctx.helper.add(posQty, change.qty); newChanges.push(change); } } // 更新数据 const transaction = await this.db.beginTransaction(); try { if (newChanges.length > 0) await transaction.insert(this.tableName, newChanges); for (const c of updateChanges) { await transaction.update(this.tableName, c); } await this.ctx.service.stagePos.updateChangeQuantity(transaction, pos, posQty); await transaction.commit(); } catch (err) { await transaction.rollback(); throw err; } // 获取返回数据 try { const data = { bills: {}, pos: {} }; data.bills.curStageData = await this.ctx.service.stageBills.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id, [pos.lid]); data.pos.curStageData = await this.ctx.service.stagePos.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id, { pid: pos.id }); return data; } catch (err) { throw '获取数据错误,请刷新页面'; } } /** * 获取 变更令 - 变更清单 使用情况 * @param {Number} sid - 查询期id * @param {uuid} cid - 变更令id * @return {Promise} */ async getUsedData(tid, cid) { if (this.ctx.stage.status === audit.stage.status.checked) { const sql = 'SELECT scf.* ' + ' FROM ' + this.tableName + ' scf ' + ' LEFT JOIN ' + this.ctx.service.stage.tableName + ' s ON scf.sid = s.id' + ' WHERE scf.tid = ? And scf.cid = ? And s.order = ?'; const result = await this.db.query(sql, [tid, cid, this.ctx.stage.order]); return result; } else { const sql = 'SELECT * FROM ' + this.tableName + ' WHERE sid = ? AND (stimes * 100 + sorder) <= (? * 100 + ?)'; const curAll = await this.db.query(sql, [this.ctx.stage.id, this.ctx.stage.curTimes, this.ctx.stage.curOrder]); const cur = this.ctx.helper.filterLastestData(curAll, ['lid', 'pid', 'cid', 'cbid'], 'stimes', 'sorder'); return cur; } } async getFinalUsedData(tid, cid) { if (this.ctx.stage.status === audit.stage.status.checked) { const sql = 'SELECT scf.* ' + ' FROM ' + this.ctx.service.stageChangeFinal.tableName + ' scf ' + ' LEFT JOIN ' + this.ctx.service.stage.tableName + ' s ON scf.sid = s.id' + ' WHERE scf.tid = ? And scf.cid = ? And s.order <= ?'; const result = await this.db.query(sql, [tid, cid, this.ctx.stage.order]); return result; } else { const preSql = 'SELECT scf.* ' + ' FROM ' + this.ctx.service.stageChangeFinal.tableName + ' scf ' + ' LEFT JOIN ' + this.ctx.service.stage.tableName + ' s ON scf.sid = s.id' + ' WHERE scf.tid = ? And scf.cid = ? And s.order < ?'; const pre = await this.db.query(preSql, [tid, cid, stage.order]); const sql = 'SELECT * FROM ' + this.tableName + ' WHERE sid'; const curAll = await this.db.query(sql, [this.ctx.stage.id]); const cur = this.ctx.helper.filterLastestData(curAll, ['lid', 'pid', 'cid', 'cbid'], 'stimes', 'sorder'); return [...pre, ...cur]; } } /** * 获取 变更令 - 变更清单 当期使用情况 * @param {Number} sid - 查询期id * @param {uuid} cid - 变更令id * @return {Promise<*>} */ async getStageUsedData(sid, cid) { const sql = 'SELECT c.*, ' + ' l.ledger_id As `ledger_id`, l.b_code As `l_code`, l.name As `l_name`, l.unit As `l_unit`, l.unit_price As `l_up`,' + ' l.deal_qty As `l_deal_qty`, l.deal_tp As `l_deal_tp`, l.quantity As `l_qty`, l.total_price As `l_tp`, ' + ' l.drawing_code As `l_drawing_code`, ' + ' p.name As `p_name`, p.drawing_code As `p_drawing_code`, p.`quantity` As `p_qty`' + ' FROM ' + this.tableName + ' As c ' + ' INNER JOIN ( ' + ' SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `flow`, `lid`, `pid`, `cbid`, `sid` From ' + this.tableName + ' WHERE sid = ? And cid = ?' + ' GROUP By `lid`, `pid`, `cbid`' + ' ) As m ' + ' ON (c.stimes * ' + timesLen + ' + c.sorder) = m.flow And c.lid = m.lid And c.pid = m.pid And c.cbid = m.cbid And c.sid = m.sid' + ' LEFT JOIN ' + this.ctx.service.ledger.tableName + ' As l ON c.lid = l.id' + ' LEFT JOIN ' + this.ctx.service.pos.tableName + ' As p ON c.pid = p.id'; const sqlParam = [sid, cid]; return await this.db.query(sql, sqlParam); } /** * 获取 本期 使用的变更令 * @param sid * @return {Promise} */ async getStageUsedChangeId(sid) { const sql = 'SELECT c.`cid`, sum(qty) As qty FROM ' + this.tableName + ' As c' + ' INNER JOIN (' + ' SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `flow`, `lid`, `pid`, `cbid` From ' + this.tableName + ' WHERE sid = ?' + ' GROUP By `lid`, `pid`, `cbid`' + ' ) As m' + ' ON (c.stimes * ' + timesLen + ' + c.sorder) = m.flow And c.lid = m.lid And c.pid = m.pid And c.cbid = m.cbid' + ' GROUP BY c.`cid`'; const sqlParam = [sid]; const result = await this.db.query(sql, sqlParam); return this._.map(this._.filter(result, 'qty'), 'cid'); } async getFinalStageData(tid, sid) { const data = await this.getAllDataByCondition({ where: { tid, sid } }); return this.ctx.helper.filterLastestData(data, ['lid', 'pid', 'cid', 'cbid'], 'stimes', 'sorder'); } async _getTender(stage) { if (this.ctx.tender) return this.ctx.tender; const tender = { id: stage.tid }; tender.data = await this.ctx.service.tender.getTender(stage.tid); tender.info = await this.service.tenderInfo.getTenderInfo(tender.id); return tender; } async getQualityTotalPrice(stage) { const helper = this.ctx.helper; const tender = await this._getTender(stage); const sql = 'SELECT sc.*, c.quality FROM ' + this.tableName + ' sc' + ' LEFT JOIN ' + this.ctx.service.change.tableName + ' c ON sc.cid = c.cid' + ' WHERE sid = ?'; let data = await this.db.query(sql, [stage.id]); data = helper.filterLastestData(data, ['lid', 'pid', 'cbid'], 'stimes', 'sorder'); const bqData = []; for (const d of data) { if (!d.qty) continue; let bd = bqData.find(x => { return x.lid === d.lid && x.quality === d.quality; }); if (!bd) { const bills = await this.db.get(this.ctx.service.ledger.departTableName(tender.id), { id: d.lid }); if (!bills) continue; bd = { lid: d.lid, quality: d.quality, unit_price: bills.unit_price }; bqData.push(bd); } const tp = this.ctx.helper.mul(d.qty, bd.unit_price, tender.info.decimal.tp); bd.tp = this.ctx.helper.add(bd.tp, tp); } const result = {}; result.common = helper.sum(helper._.map(bqData.filter(x => {return x.quality === changeConst.quality.common.value; }), 'tp')); result.more = helper.sum(helper._.map(bqData.filter(x => {return x.quality === changeConst.quality.more.value; }), 'tp')); result.great = helper.sum(helper._.map(bqData.filter(x => {return x.quality === changeConst.quality.great.value; }), 'tp')); return result; } async _getChangeBillsWithUsedInfo(stage) { if (stage.status === audit.stage.status.checked) { const sql = 'SELECT scf.* ' + ' FROM ' + this.ctx.service.stageChangeFinal.tableName + ' scf ' + ' LEFT JOIN ' + this.ctx.service.stage.tableName + ' s ON scf.sid = s.id' + ' WHERE scf.tid = ? And s.order <= ?'; const result = await this.db.query(sql, [stage.tid, stage.order]); return result; } else { const preSql = 'SELECT scf.* ' + ' FROM ' + this.ctx.service.stageChangeFinal.tableName + ' scf ' + ' LEFT JOIN ' + this.ctx.service.stage.tableName + ' s ON scf.sid = s.id' + ' WHERE scf.tid = ? And s.order < ?'; const pre = await this.db.query(preSql, [stage.tid, stage.order]); const sql = 'SELECT * FROM ' + this.tableName + ' WHERE sid = ? AND (stimes * 100 + sorder) <= (? * 100 + ?)'; const curAll = await this.db.query(sql, [stage.id, stage.curTimes, stage.curOrder]); const cur = this.ctx.helper.filterLastestData(curAll, ['lid', 'pid', 'cid', 'cbid'], 'stimes', 'sorder'); return [...pre, ...cur]; } } async getChangeWithUsedInfo(stage) { const change = await this.ctx.service.change.getAllDataByCondition({ where: { tid: stage.tid, status: audit.flow.status.checked } }); if (change.length === 0) return []; const changeBills = await this.ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: change.map(x => { return x.cid; }) } }); const changeBillsIndex = {}, changeBillsPart = {}; for (const cb of changeBills) { changeBillsIndex[cb.id] = cb; if (!changeBillsPart[cb.cid]) changeBillsPart[cb.cid] = []; changeBillsPart[cb.cid].push(cb); } const stageChangeBills = await this._getChangeBillsWithUsedInfo(stage); for (const scb of stageChangeBills) { if (!scb.qty) continue; const cb = changeBillsIndex[scb.cbid]; if (cb) cb.used_qty = this.ctx.helper.add(cb.used_qty, scb.qty); } for (const cid in changeBillsPart) { const c = change.find(x => { return x.cid === cid }); if (!c) continue; for (const cb of changeBillsPart[cid]) { cb.tp = this.ctx.helper.mul(cb.spamount, cb.unit_price, c.tp_decimal); cb.used_tp = this.ctx.helper.mul(cb.used_qty, cb.unit_price, this.ctx.tender.info.decimal.tp); c.used_tp = this.ctx.helper.add(c.used_tp, cb.used_tp); if (cb.spamount > 0) { c.p_tp = this.ctx.helper.add(c.p_tp, cb.tp); c.p_used_tp = this.ctx.helper.add(c.p_used_tp, cb.used_tp); } else if (cb.spamount < 0){ c.n_tp = this.ctx.helper.add(c.n_tp, cb.tp); c.n_used_tp = this.ctx.helper.add(c.n_used_tp, cb.used_tp); } } c.used_pt = c.total_price ? this.ctx.helper.mul(this.ctx.helper.div(c.used_tp, c.total_price, 4), 100) : 0; c.p_used_pt = c.p_tp ? this.ctx.helper.mul(this.ctx.helper.div(c.p_used_tp, c.p_tp, 4), 100) : 0; c.n_used_pt = c.n_tp ? this.ctx.helper.mul(this.ctx.helper.div(c.n_used_tp, c.n_tp, 4), 100) : 0; } return change; } } return StageChange; };