| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- 'use strict';
- /**
- *
- *
- * @author Mai
- * @date
- * @version
- */
- const audit = require('../const/audit').common;
- const auditType = require('../const/audit').auditType;
- const shenpiConst = require('../const/shenpi');
- module.exports = app => {
- class CostStage extends app.BaseService {
- /**
- * 构造函数
- *
- * @param {Object} ctx - egg全局变量
- * @return {void}
- */
- constructor(ctx) {
- super(ctx);
- this.tableName = 'cost_stage';
- this.stageType = {
- duty: { key: 'duty', name: '责任成本', decimal: { tp: 6, tax: 2, excl_tax_tp: 6 }, shenpi_status: 'cost_stage_duty', push_type: 'costStageDuty', dataService: 'costStageDuty' },
- ledger: { key: 'ledger', name: '成本报审', decimal: { tp: 6, tax: 2, excl_tax_tp: 6 }, shenpi_status: 'cost_stage_ledger', push_type: 'costStageLedger', dataService: 'costStageLedger', detailService: 'costStageDetail' },
- book: { key: 'book', name: '财务账面', decimal: { tp: 6, tax: 2, excl_tax_tp: 6 }, shenpi_status: 'cost_stage_book', push_type: 'costStageBook', dataService: 'costStageBook', detailService: 'costStageBookDetail' },
- analysis: { key: 'analysis', name: '成本分析', decimal: { tp: 6, tax: 2, excl_tax_tp: 6 }, shenpi_status: 'cost_stage_analysis', push_type: 'costStageAnalysis', dataService: 'costStageAnalysis', detailService: 'costStageAnalysisDetail' },
- };
- }
- _analysisStage(stage) {
- if (!stage) return;
- const stages = stage instanceof Array ? stage : [stage];
- if (stage.length === 0) return;
- const typeInfo = this.stageType[stages[0].stage_type];
- stages.forEach(s => {
- if (s.decimal) {
- s.decimal = this.ctx.helper._.assignIn(typeInfo.decimal, JSON.parse(s.decimal));
- } else {
- s.decimal = typeInfo.decimal;
- }
- s.stage_tp = s.stage_tp ? JSON.parse(s.stage_tp) : {};
- s.stage_pre_tp = s.stage_pre_tp ? JSON.parse(s.stage_pre_tp) : {};
- s.stage_end_tp = {};
- for (const prop in s.stage_tp) {
- s.stage_end_tp[prop] = this.ctx.helper.add(s.stage_tp[prop], s.stage_pre_tp[prop]);
- }
- s.typeInfo = this.stageType[s.stage_type];
- s.rela_stage = s.rela_stage ? JSON.parse(s.rela_stage) : null;
- s.extra_info = s.extra_info ? JSON.parse(s.extra_info) : {};
- });
- }
- async calcRuntime(stage) {
- const typeInfo = this.stageType[stage.stage_type];
- if (!typeInfo) return;
- stage.stage_tp = await this.ctx.service[typeInfo.dataService].getSum(stage);
- for (const prop in stage.stage_tp) {
- stage.stage_end_tp[prop] = this.ctx.helper.add(stage.stage_tp[prop], stage.stage_pre_tp[prop]);
- }
- }
- /**
- * 获取全部期
- * @param tid
- * @returns {Promise<*>}
- */
- async getAllStages(tid, stage_type, sort = 'ASC') {
- const sql = `SELECT cls.*, pa.name AS user_name FROM ${this.tableName} cls LEFT JOIN ${this.ctx.service.projectAccount.tableName} pa ON cls.create_user_id = pa.id` +
- ` WHERE cls.tid = ? and cls.stage_type = ? ORDER BY cls.stage_order ${sort}`;
- const result = await this.db.query(sql, [tid, stage_type]);
- this._analysisStage(result);
- return result;
- }
- async getAllCheckedStages(tid, stage_type, sort = 'ASC') {
- const sql = `SELECT cls.*, pa.name AS user_name FROM ${this.tableName} cls LEFT JOIN ${this.ctx.service.projectAccount.tableName} pa ON cls.create_user_id = pa.id` +
- ` WHERE cls.tid = ? AND cls.stage_type = ? AND audit_status = ? ORDER BY cls.stage_order ${sort}`;
- const result = await this.db.query(sql, [tid, stage_type, audit.status.checked]);
- this._analysisStage(result);
- return result;
- }
- async getStage(id) {
- const result = await this.getDataById(id);
- this._analysisStage(result);
- return result;
- }
- async getStageByOrder(tid, stage_type, stage_order) {
- const result = await this.getDataByCondition({ tid, stage_type, stage_order });
- this._analysisStage(result);
- return result;
- }
- async getMaxOrder(tid, stage_type) {
- const sql = 'SELECT Max(`stage_order`) As max_order FROM ' + this.tableName + ' Where `tid` = ? and stage_type = ?';
- const sqlParam = [tid, stage_type];
- const result = await this.db.queryOne(sql, sqlParam);
- return result.max_order || 0;
- }
- async add(tid, stage_type, stage_date, rela_stage) {
- const typeInfo = this.stageType[stage_type];
- if (!tid) throw '数据错误';
- const user_id = this.ctx.session.sessionUser.accountId;
- const maxOrder = await this.getMaxOrder(tid, stage_type);
- const data = {
- id: this.uuid.v4(), tid: tid, create_user_id: user_id, update_user_id: user_id,
- stage_order: maxOrder + 1, stage_date, stage_type,
- audit_times: 1, audit_status: audit.status.uncheck,
- decimal: JSON.stringify({ tp: 6 }),
- };
- if (stage_type === 'analysis') data.calc_template = this.ctx.subProject.cost_calc_template;
- if (rela_stage) data.rela_stage = JSON.stringify(rela_stage);
- const preStage = maxOrder > 0 ? await this.getStageByOrder(tid, stage_type, maxOrder) : null;
- if (preStage) {
- data.stage_pre_tp = JSON.stringify(preStage.stage_end_tp);
- data.decimal = JSON.stringify(preStage.decimal);
- }
- const transaction = await this.db.beginTransaction();
- try {
- const result = await transaction.insert(this.tableName, data);
- if (result.affectedRows !== 1) throw '新增安全计量期失败';
- await this.ctx.service[typeInfo.dataService].initStageData(transaction, data, preStage);
- await this.ctx.service.costStageAudit.copyPreAuditors(transaction, preStage, data);
- await transaction.commit();
- } catch(err) {
- this.ctx.log(err);
- await transaction.rollback();
- throw err;
- }
- return data;
- }
- async delete(id) {
- const stage = await this.getDataById(id);
- const typeInfo = this.stageType[stage.stage_type];
- const conn = await this.db.beginTransaction();
- try {
- await conn.delete(this.tableName, { id });
- await conn.delete(this.ctx.service[typeInfo.dataService].tableName, { stage_id: id });
- await conn.delete(this.ctx.service[typeInfo.detailService].tableName, { stage_id: id });
- const files = await this.ctx.service.costStageFile.getFiles({ where: { stage_id: id} });
- for (const f of files) {
- this.ctx.app.fujianOss.delete(f.filepath);
- }
- await conn.delete(this.ctx.service.costStageFile.tableName, { stage_id: id });
- await conn.delete(this.ctx.service.costStageAudit.tableName, { stage_id: id });
- // 记录删除日志
- // await this.ctx.service.projectLog.addProjectLog(conn, projectLogConst.type.stage, projectLogConst.status.delete, `第${info.stage_order}期`);
- await conn.commit();
- } catch (err) {
- await conn.rollback();
- throw err;
- }
- }
- async save(stage, data) {
- await this.defaultUpdate({ id: stage.id, stage_date: data.stage_date, update_user_id: this.ctx.session.sessionUser.accountId });
- }
- async loadUser(stage) {
- stage.user = await this.ctx.service.projectAccount.getAccountInfoById(stage.create_user_id);
- stage.auditors = await this.ctx.service.costStageAudit.getAuditors(stage.id, stage.curTimes || stage.audit_times);
- stage.auditorIds = this._.map(stage.auditors, 'audit_id');
- stage.curAuditors = stage.auditors.filter(x => { return x.audit_status === audit.status.checking; });
- stage.curAuditorIds = stage.curAuditors.map(x => { return x.audit_id; });
- stage.flowAuditors = stage.curAuditors.length === 0 ? [] : stage.auditors.filter(x => { return x.active_order === stage.curAuditors[0].active_order; });
- stage.flowAuditorIds = stage.flowAuditors.map(x => { return x.audit_id; });
- stage.nextAuditors = stage.curAuditors.length > 0 ? stage.auditors.filter(x => { return x.active_order === stage.curAuditors[0].active_order + 1; }) : [];
- stage.nextAuditorIds = this._.map(stage.nextAuditors, 'audit_id');
- stage.auditorGroups = this.ctx.helper.groupAuditors(stage.auditors, 'active_order');
- stage.userGroups = this.ctx.helper.groupAuditorsUniq(stage.auditorGroups);
- stage.finalAuditorIds = stage.userGroups.length > 1 ? stage.userGroups[stage.userGroups.length - 1].map(x => { return x.audit_id; }) : [];
- stage.userIds = stage.audit_status === audit.status.uncheck // 当前流程下全部参与人id
- ? [stage.create_user_id]
- : stage.auditorIds;
- if (stage.audit_status === audit.status.checkNo) {
- stage.checkNoAuditors = await this.ctx.service.costStageAudit.getAuditorsByStatus(stage.id, audit.status.checkNo, stage.audit_times-1);
- }
- }
- async loadAuditViewData(stage) {
- if (!stage.user) stage.user = await this.ctx.service.projectAccount.getAccountInfoById(stage.user_id);
- const auditTimes = stage.audit_status === audit.status.checkNo ? stage.audit_times - 1 : stage.audit_times;
- stage.auditHistory = await this.ctx.service.costStageAudit.getAuditorHistory(stage.id, auditTimes);
- // 获取审批流程中左边列表
- if (stage.audit_status === audit.status.checkNo && stage.create_user_id !== this.ctx.session.sessionUser.accountId) {
- const auditors = await this.ctx.service.costStageAudit.getAuditors(stage.id, stage.audit_times - 1); // 全部参与的审批人
- const auditorGroups = this.ctx.helper.groupAuditors(auditors);
- stage.hisUserGroup = this.ctx.helper.groupAuditorsUniq(auditorGroups);
- } else {
- stage.hisUserGroup = stage.userGroups;
- }
- }
- /**
- * cancancel = 0 不可撤回
- * cancancel = 1 原报撤回
- * cancancel = 2 审批人撤回 审批通过
- * cancancel = 3 审批人撤回 审批退回上一人
- * cancancel = 4 审批人撤回 退回原报
- * cancancel = 5 会签未全部审批通过时,审批人撤回 审批通过
- *
- * @param stage
- * @returns {Promise<void>}
- */
- async doCheckCanCancel(stage) {
- // 默认不可撤回
- stage.cancancel = 0;
- // 获取当前审批人的上一个审批人,判断是否是当前登录人,并赋予撤回功能,(当审批人存在有审批过时,上一人不允许再撤回)
- const status = audit.status;
- if (stage.audit_status === status.checked || stage.audit_status === status.uncheck) return;
- const accountId = this.ctx.session.sessionUser.accountId;
- if (stage.audit_status !== status.checkNo) {
- // 找出当前操作人上一个审批人,包括审批完成的和退回上一个审批人的,同时当前操作人为第一人时,就是则为原报
- if (stage.flowAuditors.find(x => { return x.audit_status !== status.checking}) && stage.flowAuditorIds.indexOf(accountId) < 0) return; // 当前流程存在审批人审批通过时,不可撤回
- if (stage.curAuditorIds.indexOf(accountId) < 0 && stage.flowAuditorIds.indexOf(accountId) >= 0) {
- stage.cancancel = 5; // 会签未全部审批通过时,审批人撤回审批通过
- return;
- }
- const preAuditors = stage.curAuditors[0] && stage.curAuditors[0].active_order !== 1 ? stage.auditors.filter(x => { return x.active_order === stage.curAuditors[0].active_order - 1; }) : [];
- const preAuditorCheckAgain = preAuditors.find(pa => { return pa.audit_status === status.checkAgain; });
- const preAuditorCheckCancel = preAuditors.find(pa => { return pa.audit_status === status.checkCancel; });
- const preAuditorHasOld = preAuditors.find(pa => { return pa.is_old === 1; });
- const preAuditorIds = (preAuditorCheckAgain ? [] : preAuditors.map(x => { return x.audit_id })); // 重审不可撤回
- if ((this._.isEqual(stage.flowAuditorIds, preAuditorIds) && preAuditorCheckCancel) || preAuditorHasOld) {
- return; // 不可以多次撤回
- }
- const preAuditChecked = preAuditors.find(pa => { return pa.audit_status === status.checked && pa.audit_id === accountId; });
- const preAuditCheckNoPre = preAuditors.find(pa => { return pa.audit_status === status.checkNoPre && pa.audit_id === accountId; });
- if (preAuditorIds.indexOf(accountId) >= 0) {
- if (preAuditChecked) {
- stage.cancancel = 2;// 审批人撤回审批通过
- } else if (preAuditCheckNoPre) {
- stage.cancancel = 3;// 审批人撤回审批退回上一人
- }
- stage.preAuditors = preAuditors;
- } else if (preAuditors.length === 0 && accountId === stage.create_user_id) {
- stage.cancancel = 1;// 原报撤回
- }
- } else {
- const lastAuditors = await this.ctx.service.costStageAudit.getAuditors(stage.id, stage.audit_times - 1);
- const onAuditor = this._.findLast(lastAuditors, { audit_status: status.checkNo });
- if (onAuditor.audit_id === accountId) {
- stage.cancancel = 4;// 审批人撤回退回原报
- stage.preAuditors = lastAuditors.filter(x => { return x.active_order === onAuditor.active_order });
- }
- }
- }
- async doCheckStage(stage) {
- const accountId = this.ctx.session.sessionUser.accountId;
- // 审批退回时,原报读取本轮流程,其他人读取上一轮流程
- if (stage.audit_status === audit.status.checkNo) {
- stage.curTimes = stage.create_user_id === accountId ? stage.audit_times : stage.audit_times - 1;
- } else {
- stage.curTimes = stage.audit_times;
- }
- // 加载参与人
- await this.loadUser(stage);
- if (stage.audit_status === audit.status.uncheck) {
- stage.readOnly = accountId !== stage.create_user_id;
- stage.curSort = 0;
- } else if (stage.audit_status === audit.status.checkNo) {
- stage.readOnly = accountId !== stage.create_user_id;
- if (!stage.readOnly) {
- stage.curSort = 0;
- } else {
- const checkNoAudit = await this.service.costStageAudit.getDataByCondition({
- stage_id: stage.id, audit_times: stage.audit_times - 1, audit_status: audit.status.checkNo,
- });
- stage.curSort = checkNoAudit.active_order;
- }
- } else if (stage.audit_status === audit.status.checked) {
- stage.readOnly = true;
- stage.curSort = stage.audit_max_sort;
- } else {
- // 会签,会签人部分审批通过时,只读,但是curSort需按原来的取值
- stage.curSort = stage.flowAuditorIds.indexOf(accountId) >= 0 ? stage.curAuditors[0].active_order : stage.curAuditors[0].active_order - 1;
- if (stage.curAuditors[0].audit_type === auditType.key.and) {
- stage.readOnly = !this.ctx.helper._.isEqual(stage.flowAuditorIds, stage.curAuditorIds);
- stage.canCheck = true;
- } else {
- stage.readOnly = stage.curAuditorIds.indexOf(accountId) < 0;
- stage.canCheck = stage.readOnly && stage.curAuditorIds.indexOf(accountId) > 0;
- }
- }
- await this.doCheckCanCancel(stage);
- }
- async checkShenpi(stage) {
- const status = audit.status;
- const info = this.ctx.tender.info;
- const typeInfo = this.stageType[stage.stage_type];
- const shenpi_status = info.shenpi[typeInfo.shenpi_status];
- console.log(typeInfo.shenpi_status, info.shenpi);
- if ((stage.audit_status === status.uncheck || stage.audit_status === status.checkNo) && shenpi_status !== shenpiConst.sp_status.sqspr) {
- // 进一步比较审批流是否与审批流程设置的相同,不同则替换为固定审批流或固定的终审
- const auditList = await this.ctx.service.costStageAudit.getAllDataByCondition({ where: { stage_id: stage.id, audit_times: stage.audit_times }, orders: [['audit_order', 'asc']] });
- auditList.shift();
- if (shenpi_status === shenpiConst.sp_status.gdspl) {
- const shenpiList = await this.ctx.service.shenpiAudit.getAllDataByCondition({ where: { tid: stage.tid, sp_type: shenpiConst.cost_sp_type[typeInfo.shenpi_status], sp_status: shenpi_status } });
- // 判断2个id数组是否相同,不同则删除原审批流,切换成固定的审批流
- let sameAudit = auditList.length === shenpiList.length;
- if (sameAudit) {
- for (const audit of auditList) {
- const shenpi = shenpiList.find(x => { return x.audit_id === audit.audit_id; });
- if (!shenpi || shenpi.audit_order !== audit.audit_order || shenpi.audit_type !== audit.audit_type) {
- sameAudit = false;
- break;
- }
- }
- }
- if (!sameAudit) {
- await this.ctx.service.costStageAudit.updateNewAuditList(stage, shenpiList);
- await this.loadUser(stage);
- }
- } else if (shenpi_status === shenpiConst.sp_status.gdzs) {
- const shenpiInfo = await this.ctx.service.shenpiAudit.getDataByCondition({ tid: stage.tid, sp_type: shenpiConst.cost_sp_type[typeInfo.shenpi_status], sp_status: shenpi_status });
- // 判断最后一个id是否与固定终审id相同,不同则删除原审批流中如果存在的id和添加终审
- const lastAuditors = auditList.filter(x => { x.active_order === auditList.active_order; });
- if (shenpiInfo && (lastAuditors.length === 0 || (lastAuditors.length > 1 || shenpiInfo.audit_id !== lastAuditors[0].audit_id))) {
- await this.ctx.service.costStageAudit.updateLastAudit(stage, auditList, shenpiInfo.audit_id);
- await this.loadUser(stage);
- } else if (!shenpiInfo) {
- // 不存在终审人的状态下这里恢复为授权审批人
- this.ctx.tender.info.shenpi[typeInfo.shenpi_status] = shenpiConst.sp_status.sqspr;
- }
- }
- }
- }
- async getLastCheckedStage(tid, stage_type) {
- const lastCheckedStage = await this.ctx.service.costStage.getAllDataByCondition({
- where: { tid, stage_type, audit_status: audit.status.checked },
- orders: [['stage_order', 'desc']],
- });
- if (lastCheckedStage && lastCheckedStage.length > 0) {
- this._analysisStage(lastCheckedStage[0]);
- return lastCheckedStage[0];
- }
- return null;
- }
- async getNumByChecked(tenderId, stage_type) {
- const num = await this.db.queryOne(`SELECT COUNT(*) as num From ${this.tableName} WHERE tid = ? and stage_type = ? and audit_status = ?`, [tenderId, stage_type, audit.status.checked]);
- return num ? num.num : 0;
- }
- async saveExtraInfo(stage, data) {
- const extra_info = this.ctx.helper._.assign(stage.extra_info, data);
- try {
- await this.defaultUpdate({ id: stage.id, extra_info: JSON.stringify(extra_info) });
- return extra_info;
- } catch (err) {
- throw '保存附加信息错误';
- }
- }
- }
- return CostStage;
- };
|