123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- 'use strict';
- /**
- * 定制报表 注意不做任何混用,也不做任何继承
- *
- * @author Mai
- * @date
- * @version
- */
- const auditConst = require('../const/audit');
- /**
- * 季华项目 定制报表
- * 汇总表,流水汇总2个标段(N个),汇总到期,每期汇总3个人的数据(3个),工程量清单流水表,并根据截至本期变更令使用情况筛选
- *
- * 借用 通用汇总标段选的界面
- * 故配置可与汇总标段选择相同
- *
- * define: {
- * "title": "请选择汇总的标段", "type": "month/final/checked-final/stage",
- * "defaultCompare": [1, 2, 3], // 结果按序 t_n_qty, t_n_tp
- * "match": { "quality": [2, 3], "qty": "<0" }, // class根据变更类型过滤,qty根据数量过滤
- * "selectCompare": [{ "key": "jl", "title": "驻地监理" }, ...] // 结果按key t_key_qty, t_key_tp
- * "merge": true,
- * }
- * defaultCompare为默认选择的审批人,0为原报,1-N为1-N审
- * match为保留的类型
- * 如需要用户选择审批人,则应配置selectCompare(目前不可用,不可配置,如需使用,则需要额外界面),为后期可能的变动预留
- *
- */
- class jhHelper {
- constructor (ctx) {
- this.ctx = ctx;
- this.result = [];
- }
- async _getValidStages(tenderId) {
- const stages = await this.ctx.service.stage.db.select(this.ctx.service.stage.tableName, {
- where: { tid: tenderId },
- orders: [['order', 'desc']],
- });
- if (stages.length !== 0) {
- const lastStage = stages[0];
- if (lastStage.status === auditConst.stage.status.uncheck && lastStage.user_id !== this.ctx.session.sessionUser.accountId) {
- stages.splice(0, 1);
- }
- }
- return stages;
- }
- async _getCheckedStages(tenderId) {
- const stages = await this.db.select(this.ctx.service.stage.tableName, {
- where: { tid: tenderId },
- orders: [['order', 'desc']],
- });
- if (stages.length !== 0) {
- const lastStage = stages[0];
- if (lastStage.status !== auditConst.stage.status.checked) {
- stages.splice(0, 1);
- }
- }
- return stages;
- }
- /**
- * 查询本期所有变更明细
- * @param tid
- * @param sid
- * @returns {Promise<void>}
- */
- async getCurChangeDetailData(tid, sid) {
- const sql = 'SELECT sc.*, c.type As c_type, c.class As c_class, c.quality As c_quality FROM ' + this.ctx.service.stageChange.tableName + ' sc' +
- ' Left Join ' + this.ctx.service.change.tableName + ' c ON sc.cid = c.cid' +
- ' WHERE sc.tid = ? and sc.sid = ?';
- return await this.ctx.service.stageChange.db.query(sql, [tid, sid]);
- }
- async getPreChangeDetailData(tid, sOrder) {
- const sql = 'SELECT sc.*, c.type As c_type, c.class As c_class, c.quality As c_quality FROM ' + this.ctx.service.stageChangeFinal.tableName + ' sc' +
- ' Left Join ' + this.ctx.service.change.tableName + ' c ON sc.cid = c.cid' +
- ' Left Join ' + this.ctx.service.stage.tableName + ' s ON sc.sid = s.id' +
- ' WHERE sc.tid = ? and s.order < ?';
- return await this.ctx.service.stageChangeFinal.db.query(sql, [tid, sOrder]);
- }
- getLastestAuditors(auditors) {
- const index = {};
- for (const auditor of auditors) {
- if (!index[auditor.aid] || auditor.order > index[auditor.aid].order) index[auditor.aid] = auditor;
- }
- const result = [];
- for (const i in index) {
- result.push(index[i]);
- }
- result.sort((x, y) => { return x.order - y.order; });
- return result;
- }
- _loadChangeDetail(billsIndex, changeDetail, gsDefine, prefix) {
- for (const cd of changeDetail) {
- if (!cd.qty) continue;
- let match = false;
- for (const m of gsDefine.match) {
- if (m.quality === cd.c_quality && ((m.minus && cd.qty < 0) || (!m.minus && cd.qty > 0))) match = true;
- }
- if (!match) continue;
- const bills = billsIndex[cd.lid];
- if (!bills) continue;
- if (!bills[prefix + 'cd']) bills[prefix + 'cd'] = [];
- bills[prefix + 'cd'].push(cd);
- if (cd.pid) {
- const pos = bills.pos.find(x => {return x.id === cd.pid});
- if (pos) {
- if (!pos[prefix + 'cd']) pos[prefix + 'cd'] = [];
- pos[prefix + 'cd'].push(cd);
- }
- }
- }
- }
- _loadMergeResult(bills, prefixes) {
- const rst = {
- id: bills.id,
- tid: bills.tender_id,
- b_code: bills.b_code,
- name: bills.name,
- unit: bills.unit,
- unit_price: bills.unit_price
- };
- if (bills.pos && bills.pos.length > 0) {
- for (const p of bills.pos) {
- let gather = false;
- if (p.pre_cd && p.pre_cd.length > 0) gather = true;
- for (const prefix of prefixes) {
- if (p[prefix + '_cd'] && p[prefix + '_cd'].length > 0) gather = true;
- }
- if (gather) {
- rst.qc_qty = this.ctx.helper.add(rst.qc_qty, p.qc_qty);
- rst.qc_tp = this.ctx.helper.add(rst.qc_qty, p.qc_tp);
- rst.pre_qc_qty = this.ctx.helper.add(rst.pre_qc_qty, p.pre_qc_qty);
- rst.pre_qc_tp = this.ctx.helper.add(rst.pre_qc_tp, p.pre_qc_tp);
- rst.end_qc_qty = this.ctx.helper.add(rst.end_qc_qty, p.end_qc_qty);
- rst.end_qc_tp = this.ctx.helper.add(rst.end_qc_tp, p.end_qc_tp);
- for (const prefix of prefixes) {
- rst[prefix + 'qc_qty'] = this.ctx.helper.add(rst[prefix + 'qc_qty'], p[prefix + 'qc_qty']);
- }
- }
- }
- for (const prefix of prefixes) {
- rst[prefix + 'qc_tp'] = this.ctx.helper.mul(rst.unit_price, rst[prefix + 'qc_qty'], 2);
- }
- } else {
- rst.qc_qty = bills.qc_qty;
- rst.qc_tp = bills.qc_tp;
- rst.pre_qc_qty = bills.pre_qc_qty;
- rst.pre_qc_tp = bills.pre_qc_tp;
- rst.end_qc_qty = bills.end_qc_qty;
- rst.end_qc_tp = bills.end_qc_tp;
- for (const prefix of prefixes) {
- rst[prefix + 'qc_qty'] = bills[prefix + 'qc_qty'];
- rst[prefix + 'qc_tp'] = bills[prefix + 'qc_tp'];
- }
- }
- this.result.push(rst);
- }
- _loadResult(bills, prefixes) {
- if (bills.pos) {
- for (const p of bills.pos) {
- let load = false;
- if (p.pre_cd && p.pre_cd.length > 0) load = true;
- for (const prefix of prefixes) {
- if (p[prefix + '_cd'] && p[prefix + '_cd'].length > 0) load = true;
- }
- if (!load) continue;
- const rst = {
- b_code: bills.b_code,
- name: bills.name,
- unit: bills.unit,
- unit_price: bills.unit_price,
- };
- rst.qc_qty = p.qc_qty;
- rst.qc_tp = p.qc_tp;
- rst.pre_qc_qty = p.pre_qc_qty;
- rst.pre_qc_tp = p.pre_qc_tp;
- rst.end_qc_qty = p.end_qc_qty;
- rst.end_qc_tp = p.end_qc_tp;
- for (const prefix of prefixes) {
- rst[prefix + 'qc_qty'] = p[prefix + 'qc_qty'];
- rst[prefix + 'qc_tp'] = p[prefix + 'qc_tp'];
- }
- this.result.push(rst);
- }
- } else {
- const rst = {
- b_code: bills.b_code,
- name: bills.name,
- unit: bills.unit,
- unit_price: bills.unit_price,
- };
- rst.qc_qty = bills.qc_qty;
- rst.qc_tp = bills.qc_tp;
- rst.pre_qc_qty = bills.pre_qc_qty;
- rst.pre_qc_tp = bills.pre_qc_tp;
- rst.end_qc_qty = bills.end_qc_qty;
- rst.end_qc_tp = bills.end_qc_tp;
- for (const prefix of prefixes) {
- rst[prefix + 'qc_qty'] = bills[prefix + 'qc_qty'];
- rst[prefix + 'qc_tp'] = bills[prefix + 'qc_tp'];
- }
- this.result.push(rst);
- }
- }
- _generateResult(billsData, gsDefine) {
- for (const bills of billsData) {
- let load = false;
- if (bills.pre_cd && bills.pre_cd.length > 0) load = true;
- for (const dc of gsDefine.defaultCompare) {
- if (bills['t_' + dc + '_cd'] && bills['t_' + dc + '_cd'].length > 0) load = true;
- }
- if (!load) continue;
- gsDefine.merge ? this._loadMergeResult(bills, this.prefixes) : this._loadResult(bills, this.prefixes);
- }
- }
- async _loadStageBillsData(tender, stage, gsDefine, auditors) {
- const helper = this.ctx.helper;
- // 加载截止上期/本期
- let billsData = await this.ctx.service.ledger.getData(tender.id);
- billsData = billsData.filter(x => { return x.b_code && x.is_leaf });
- const curStage = await this.ctx.service.stageBills.getLastestStageData(tender.id, stage.id);
- const preStage = stage.order > 1 ? await this.ctx.service.stageBillsFinal.getFinalData(tender, stage.order - 1) : [];
- const loadData = [
- { data: curStage, fields: ['qc_qty', 'qc_tp'], prefix: '', relaId: 'lid' },
- { data: preStage, fields: ['qc_qty', 'qc_tp'], prefix: 'pre_', relaId: 'lid' }
- ];
- for (const dc of gsDefine.defaultCompare) {
- const auditor = auditors[dc];
- const auditorStage = await this.ctx.service.stagePos.getAuditorStageData2(tender.id, stage.id, auditor.times, auditor.order);
- loadData.push({ data: auditorStage, fields: ['qc_qty', 'qc_tp'], prefix: `t_${dc}_`, relaId: 'pid' });
- }
- helper.assignRelaData(billsData, loadData);
- // 计算截止本期
- billsData.forEach(x => {
- x.end_qc_qty = helper.add(x.qc_qty, x.pre_qc_qty);
- x.end_qc_tp = helper.add(x.qc_tp, x.pre_qc_tp);
- });
- return billsData;
- }
- async _loadStagePosData(tender, stage, gsDefine, auditors) {
- const helper = this.ctx.helper;
- const posData = await this.ctx.service.pos.getPosData({tid: tender.id});
- const curStage = await this.ctx.service.stagePos.getLastestStageData2(tender.id, stage.id);
- const preStage = stage.order > 1 ? await this.ctx.service.stagePosFinal.getFinalData(tender, stage.order - 1) : [];
- const loadData = [
- { data: curStage, fields: ['qc_qty'], prefix: '', relaId: 'pid' },
- { data: preStage, fields: ['qc_qty'], prefix: 'pre_', relaId: 'pid' }
- ];
- for (const dc of gsDefine.defaultCompare) {
- const auditor = auditors[dc];
- const auditorStage = await this.ctx.service.stagePos.getAuditorStageData2(tender.id, stage.id, auditor.times, auditor.order);
- loadData.push({ data: auditorStage, fields: ['qc_qty'], prefix: `t_${dc}_`, relaId: 'pid' });
- }
- helper.assignRelaData(posData, loadData);
- posData.forEach(x => {
- x.end_qc_qty = helper.add(x.qc_qty, x.pre_qc_qty);
- });
- return posData;
- }
- async _gatherStageData(tender, stage, gsDefine) {
- if (!stage) return;
- const helper = this.ctx.helper;
- await this.ctx.service.stage.doCheckStage(stage);
- const auditors = this.getLastestAuditors(stage.auditors);
- const billsData = await this._loadStageBillsData(tender, stage, gsDefine, auditors);
- const posData = await this._loadStagePosData(tender, stage, gsDefine, auditors);
- // 创建索引
- const billsIndex = {};
- for (const b of billsData) {
- billsIndex[b.id] = b;
- b.pos = posData.filter(x => { return x.lid === b.id; });
- b.pos.forEach(x => {
- x.qc_tp = helper.mul(b.unit_price, x.qc_qty, 2);
- x.pre_qc_tp = helper.mul(b.unit_price, x.pre_qc_qty, 2);
- x.end_qc_tp = helper.add(x.qc_tp, x.pre_qc_tp);
- })
- }
- // 查询比较人数据
- this.prefixes = [];
- const stageChangeDetail = await this.getCurChangeDetailData(tender.id, stage.id);
- for (const dc of gsDefine.defaultCompare) {
- const scd = helper.filterTimesOrderData(stageChangeDetail, ['lid', 'pid', 'cid', 'cbid'], auditors[dc].times, auditors[dc].order);
- this._loadChangeDetail(billsIndex, scd, gsDefine, `t_${dc}_`);
- this.prefixes.push(`t_${dc}_`);
- }
- const finalChangeData = await this.getPreChangeDetailData(tender.id, stage.order);
- this._loadChangeDetail(billsIndex, finalChangeData, gsDefine, 'pre_');
- this._generateResult(billsData, gsDefine);
- }
- async _gatherMonthData(tender, month, defaultCompare) {
- const stages = await this._getValidStages(tender.id);
- const stage = this.ctx.helper._.find(stages, {s_time: month});
- await this._gatherStageData(tender, stage, defaultCompare);
- }
- async _gatherFinalData(tender, defaultCompare) {
- const stages = await this._getValidStages(tender.id);
- await this._gatherStageData(tender, stages[0], defaultCompare);
- }
- async _gatherCheckedFinalData(tender, defaultCompare) {
- const stages = await this._getCheckedStages(tender.id);
- await this._gatherStageData(tender, stages[0], defaultCompare);
- }
- async _gatherIndexData(tender, index, defaultCompare) {
- const stages = await this._getValidStages(tender.id);
- const stage = this.ctx.helper._.find(stages, {order: index});
- await this._gatherStageData(tender, stage, defaultCompare);
- }
- /**
- *
- * @param {Array} memFieldKeys 报表添加的指标字段
- * @param {object} gsDefine
- * @param {object} gsCustom
- * @returns {Promise<Array>}
- */
- async gather(memFieldKeys, gsDefine, gsCustom) {
- if (!gsDefine || !gsDefine.enable) return [];
- if (!gsCustom || !gsCustom.tenders || gsCustom.tenders.length === 0) return [];
- const gsSetting = JSON.parse(gsDefine.setting);
- if (!gsSetting.defaultCompare || !gsSetting.match) return[];
- for (const t of gsCustom.tenders) {
- const tender = await this.ctx.service.tender.getCheckTender(t.tid);
- switch (gsSetting.type) {
- case 'month':
- await this._gatherMonthData(tender, gsCustom.month, gsSetting);
- break;
- case 'final':
- await this._gatherFinalData(tender, gsSetting);
- break;
- case 'checked-final':
- await this._gatherCheckedFinalData(tender, gsSetting);
- break;
- case 'stage':
- await this._gatherIndexData(tender, gsCustom.stage, gsSetting);
- break;
- default: throw '未知汇总类型';
- }
- }
- const helper = this.ctx.helper;
- // 排序
- this.result.sort((x, y) => { return helper.compareCode(x.b_code, y.b_code); });
- return this.result;
- }
- async convert(tid, sid, memFieldKeys, setting) {
- if (!setting || !setting.defaultCompare) return [];
- const tender = await this.ctx.service.tender.getCheckTender(tid);
- const stage = await this.ctx.service.stage.getDataById(sid);
- await this._gatherStageData(tender, stage, { defaultCompare: setting.defaultCompare });
- }
- }
- module.exports = {
- jhHelper,
- };
|