|  | @@ -277,7 +277,6 @@ module.exports = app => {
 | 
	
		
			
				|  |  |              revise.nextAuditors = revise.curAuditors.length > 0 ? revise.auditors.filter(x => { return x.audit_order === revise.curAuditors[0].audit_order + 1; }) : [];
 | 
	
		
			
				|  |  |              revise.nextAuditorIds = this._.map(revise.nextAuditors, 'audit_id');
 | 
	
		
			
				|  |  |              revise.auditorGroups = this.ctx.helper.groupAuditors(revise.auditors, 'audit_order');
 | 
	
		
			
				|  |  | -            console.log(revise.auditorGroups);
 | 
	
		
			
				|  |  |              revise.userGroups = this.ctx.helper.groupAuditorsUniq(revise.auditorGroups);
 | 
	
		
			
				|  |  |              revise.userGroups.unshift([{
 | 
	
		
			
				|  |  |                  aid: revise.user.id, order: 0, times: revise.times, audit_order: 0, audit_type: auditType.key.common,
 | 
	
	
		
			
				|  | @@ -311,7 +310,7 @@ module.exports = app => {
 | 
	
		
			
				|  |  |                  const auditorGroups = this.ctx.helper.groupAuditors(auditors, 'audit_order');
 | 
	
		
			
				|  |  |                  revise.auditors2 = this.ctx.helper.groupAuditorsUniq(auditorGroups, 'audit_order');
 | 
	
		
			
				|  |  |                  revise.auditors2.unshift([{
 | 
	
		
			
				|  |  | -                    aid: revise.user.id, order: 0, times: revise.times - 1, audit_order: 0, audit_type: auditConst.auditType.key.common,
 | 
	
		
			
				|  |  | +                    aid: revise.user.id, order: 0, times: revise.times - 1, audit_order: 0, audit_type: auditType.key.common,
 | 
	
		
			
				|  |  |                      name: revise.user.name, role: revise.user.role, company: revise.user.company
 | 
	
		
			
				|  |  |                  }]);
 | 
	
		
			
				|  |  |              } else {
 | 
	
	
		
			
				|  | @@ -561,243 +560,230 @@ module.exports = app => {
 | 
	
		
			
				|  |  |              await transaction.query(pSql, sqlParam);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        /**
 | 
	
		
			
				|  |  | -         * 审批
 | 
	
		
			
				|  |  | -         * @param {Object} revise - 修订
 | 
	
		
			
				|  |  | -         * @param {auditConst.status.checked|auditConst.status.checkNo} checkType - 审批结果
 | 
	
		
			
				|  |  | -         * @param {String} opinion - 审批意见
 | 
	
		
			
				|  |  | -         * @param {Number} times - 第几次审批
 | 
	
		
			
				|  |  | -         * @return {Promise<void>}
 | 
	
		
			
				|  |  | -         */
 | 
	
		
			
				|  |  | -        async check(revise, checkType, opinion, times = 1) {
 | 
	
		
			
				|  |  | -            if (checkType !== auditConst.status.checked && checkType !== auditConst.status.checkNo) throw '提交数据错误';
 | 
	
		
			
				|  |  | -            const audit = await this.getDataByCondition({
 | 
	
		
			
				|  |  | -                rid: revise.id,
 | 
	
		
			
				|  |  | -                times,
 | 
	
		
			
				|  |  | -                status: auditConst.status.checking,
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -            if (!audit) throw '审核数据错误';
 | 
	
		
			
				|  |  | +        async _checked(revise, opinion, times) {
 | 
	
		
			
				|  |  | +            const accountId = this.ctx.session.sessionUser.accountId;
 | 
	
		
			
				|  |  |              const pid = this.ctx.session.sessionProject.id;
 | 
	
		
			
				|  |  | +            const auditors = await this.getAllDataByCondition({ where: { rid: revise.id, times, status: auditConst.status.checking } });
 | 
	
		
			
				|  |  | +            const selfAuditor = auditors.find(x => { return x.audit_id === accountId; });
 | 
	
		
			
				|  |  | +            if (!selfAuditor) throw '审核数据错误';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            const flowAuditors = await this.getAllDataByCondition({ where: { rid: revise.id, times, audit_order: selfAuditor.audit_order } });
 | 
	
		
			
				|  |  | +            const nextAuditors = await this.getAllDataByCondition({ where: { rid: revise.id, times, audit_order: selfAuditor.audit_order + 1 } });
 | 
	
		
			
				|  |  | +            const beginAuditors = await this.getAllDataByCondition({ where: { rid: revise.id, audit_order: 1, times } });
 | 
	
		
			
				|  |  | +            const time = new Date();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            const noticeContent = await this.getNoticeContent(pid, selfAuditor.tender_id, revise.id, selfAuditor.audit_id, opinion);
 | 
	
		
			
				|  |  | +            const defaultNoticeRecord = { pid, type: pushType.revise, status: auditConst.status.checked, content: noticeContent};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              const transaction = await this.db.beginTransaction();
 | 
	
		
			
				|  |  |              try {
 | 
	
		
			
				|  |  |                  const auditList = await this.getAuditors(revise.id, times);
 | 
	
		
			
				|  |  |                  // 审核通过添加到推送表
 | 
	
		
			
				|  |  | -                const noticeContent = await this.getNoticeContent(pid, audit.tender_id, audit.rid, audit.audit_id, opinion);
 | 
	
		
			
				|  |  | -                const records = [
 | 
	
		
			
				|  |  | -                    {
 | 
	
		
			
				|  |  | -                        pid,
 | 
	
		
			
				|  |  | -                        type: pushType.revise,
 | 
	
		
			
				|  |  | -                        uid: revise.uid,
 | 
	
		
			
				|  |  | -                        status: checkType,
 | 
	
		
			
				|  |  | -                        content: noticeContent,
 | 
	
		
			
				|  |  | -                    },
 | 
	
		
			
				|  |  | -                ];
 | 
	
		
			
				|  |  | +                const records = [ { uid: revise.uid, ...defaultNoticeRecord } ];
 | 
	
		
			
				|  |  |                  auditList.forEach(audit => {
 | 
	
		
			
				|  |  | -                    records.push({
 | 
	
		
			
				|  |  | -                        pid,
 | 
	
		
			
				|  |  | -                        type: pushType.revise,
 | 
	
		
			
				|  |  | -                        uid: audit.audit_id,
 | 
	
		
			
				|  |  | -                        status: checkType,
 | 
	
		
			
				|  |  | -                        content: noticeContent,
 | 
	
		
			
				|  |  | -                    });
 | 
	
		
			
				|  |  | +                    records.push({ uid: audit.audit_id, ...defaultNoticeRecord });
 | 
	
		
			
				|  |  |                  });
 | 
	
		
			
				|  |  |                  await transaction.insert('zh_notice', records);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  // 整理当前流程审核人状态更新
 | 
	
		
			
				|  |  | -                const time = new Date();
 | 
	
		
			
				|  |  |                  // 更新当前审核流程
 | 
	
		
			
				|  |  | -                await transaction.update(this.tableName, {
 | 
	
		
			
				|  |  | -                    id: audit.id,
 | 
	
		
			
				|  |  | -                    status: checkType,
 | 
	
		
			
				|  |  | -                    opinion,
 | 
	
		
			
				|  |  | -                    end_time: time,
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -                await this.ctx.service.noticeAgain.stopNoticeAgain(transaction, this.tableName, audit.id);
 | 
	
		
			
				|  |  | -                if (checkType === auditConst.status.checked) {
 | 
	
		
			
				|  |  | -                    const nextAudit = await this.getDataByCondition({
 | 
	
		
			
				|  |  | -                        rid: revise.id,
 | 
	
		
			
				|  |  | -                        times,
 | 
	
		
			
				|  |  | -                        audit_order: audit.audit_order + 1,
 | 
	
		
			
				|  |  | -                    });
 | 
	
		
			
				|  |  | -                    // 无下一审核人表示,审核结束
 | 
	
		
			
				|  |  | -                    if (nextAudit) {
 | 
	
		
			
				|  |  | -                        await transaction.update(this.tableName, {
 | 
	
		
			
				|  |  | -                            id: nextAudit.id,
 | 
	
		
			
				|  |  | -                            status: auditConst.status.checking,
 | 
	
		
			
				|  |  | -                            begin_time: time,
 | 
	
		
			
				|  |  | -                        });
 | 
	
		
			
				|  |  | +                await transaction.update(this.tableName, { id: selfAuditor.id, status: auditConst.status.checked, opinion, end_time: time });
 | 
	
		
			
				|  |  | +                await this.ctx.service.noticeAgain.stopNoticeAgain(transaction, this.tableName, selfAuditor.id);
 | 
	
		
			
				|  |  | +                if (auditors.length === 1 || selfAuditor.audit_type === auditType.key.or) {
 | 
	
		
			
				|  |  | +                    // 或签更新他人审批状态
 | 
	
		
			
				|  |  | +                    if (selfAuditor.audit_type === auditType.key.or) {
 | 
	
		
			
				|  |  | +                        const updateOther = [];
 | 
	
		
			
				|  |  | +                        for (const audit of auditors) {
 | 
	
		
			
				|  |  | +                            if (audit.audit_id === selfAuditor.audit_id) continue;
 | 
	
		
			
				|  |  | +                            updateOther.push({ id: audit.id, status: auditConst.status.checkSkip, opinion: '', end_time: time });
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                        if (updateOther.length > 0) {
 | 
	
		
			
				|  |  | +                            await this.ctx.service.noticeAgain.stopNoticeAgain(transaction, this.tableName, updateOther.map(x => { return x.id}));
 | 
	
		
			
				|  |  | +                            await transaction.updateRows(this.tableName, updateOther);
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                        // 短信通知-需要审批提醒功能
 | 
	
		
			
				|  |  | -                        // 下一人
 | 
	
		
			
				|  |  | -                        // await this.ctx.helper.sendUserSms(nextAudit.user_id, smsTypeConst.const.XD,
 | 
	
		
			
				|  |  | -                        //     smsTypeConst.judge.approval.toString(), '台账修订需要您审批,请登录系统处理。');
 | 
	
		
			
				|  |  | -                        await this.ctx.helper.sendAliSms(nextAudit.audit_id, smsTypeConst.const.XD, smsTypeConst.judge.approval.toString(), SmsAliConst.template.revise_check);
 | 
	
		
			
				|  |  | -                        // 微信模板通知
 | 
	
		
			
				|  |  | -                        const shenpiUrl = await this.ctx.helper.urlToShort(
 | 
	
		
			
				|  |  | -                            this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + revise.tid + '/revise/' + revise.id + '/info'
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                        const wechatData = {
 | 
	
		
			
				|  |  | -                            wap_url: shenpiUrl,
 | 
	
		
			
				|  |  | -                            status: wxConst.status.check,
 | 
	
		
			
				|  |  | -                            tips: wxConst.tips.check,
 | 
	
		
			
				|  |  | -                            code: this.ctx.session.sessionProject.code,
 | 
	
		
			
				|  |  | -                            begin_time: Date.parse(revise.begin_time),
 | 
	
		
			
				|  |  | -                        };
 | 
	
		
			
				|  |  | -                        await this.ctx.helper.sendWechat(nextAudit.audit_id, smsTypeConst.const.XD, smsTypeConst.judge.approval.toString(), wxConst.template.revise, wechatData);
 | 
	
		
			
				|  |  | +                // 无下一审核人表示,审核结束
 | 
	
		
			
				|  |  | +                if (nextAuditors.length > 0) {
 | 
	
		
			
				|  |  | +                    const nextAuditUpdateData = nextAuditors.map(x => { return { id: x.id, status: auditConst.status.checking, begin_time: time }});
 | 
	
		
			
				|  |  | +                    await transaction.updateRows(this.tableName, nextAuditUpdateData);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    // 短信通知-需要审批提醒功能
 | 
	
		
			
				|  |  | +                    const nextAuditorIds = nextAuditors.map(x => { return x.audit_id; });
 | 
	
		
			
				|  |  | +                    await this.ctx.helper.sendAliSms(nextAuditorIds, smsTypeConst.const.XD, smsTypeConst.judge.approval.toString(), SmsAliConst.template.revise_check);
 | 
	
		
			
				|  |  | +                    // 微信模板通知
 | 
	
		
			
				|  |  | +                    const shenpiUrl = await this.ctx.helper.urlToShort(
 | 
	
		
			
				|  |  | +                        this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + revise.tid + '/revise/' + revise.id + '/info'
 | 
	
		
			
				|  |  | +                    );
 | 
	
		
			
				|  |  | +                    const wechatData = {
 | 
	
		
			
				|  |  | +                        wap_url: shenpiUrl,
 | 
	
		
			
				|  |  | +                        status: wxConst.status.check,
 | 
	
		
			
				|  |  | +                        tips: wxConst.tips.check,
 | 
	
		
			
				|  |  | +                        code: this.ctx.session.sessionProject.code,
 | 
	
		
			
				|  |  | +                        begin_time: Date.parse(revise.begin_time),
 | 
	
		
			
				|  |  | +                    };
 | 
	
		
			
				|  |  | +                    await this.ctx.helper.sendWechat(nextAuditorIds, smsTypeConst.const.XD, smsTypeConst.judge.approval.toString(), wxConst.template.revise, wechatData);
 | 
	
		
			
				|  |  | +                    for (const audit of nextAuditors) {
 | 
	
		
			
				|  |  |                          await this.ctx.service.noticeAgain.addNoticeAgain(transaction, smsTypeConst.const.XD, {
 | 
	
		
			
				|  |  |                              pid: this.ctx.session.sessionProject.id,
 | 
	
		
			
				|  |  |                              tid: this.ctx.tender.id,
 | 
	
		
			
				|  |  | -                            uid: nextAudit.audit_id,
 | 
	
		
			
				|  |  | +                            uid: audit.audit_id,
 | 
	
		
			
				|  |  |                              sp_type: 'revise',
 | 
	
		
			
				|  |  | -                            sp_id: nextAudit.id,
 | 
	
		
			
				|  |  | +                            sp_id: audit.id,
 | 
	
		
			
				|  |  |                              table_name: this.tableName,
 | 
	
		
			
				|  |  |                              template: wxConst.template.revise,
 | 
	
		
			
				|  |  |                              wx_data: wechatData,
 | 
	
		
			
				|  |  |                          });
 | 
	
		
			
				|  |  | -                        // 其他参与人
 | 
	
		
			
				|  |  | -                        const users = this._.pull(this._.map(auditList, 'audit_id'), audit.audit_id);
 | 
	
		
			
				|  |  | -                        users.push(revise.uid);
 | 
	
		
			
				|  |  | -                        // await this.ctx.helper.sendUserSms(users, smsTypeConst.const.XD,
 | 
	
		
			
				|  |  | -                        //     smsTypeConst.judge.result.toString(), '台账修订审批通过。');
 | 
	
		
			
				|  |  | -                        await this.ctx.helper.sendAliSms(users, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), SmsAliConst.template.revise_result2, {
 | 
	
		
			
				|  |  | -                            status: SmsAliConst.status.success,
 | 
	
		
			
				|  |  | -                        });
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                        // 微信模板通知
 | 
	
		
			
				|  |  | -                        // const wechatData2 = {
 | 
	
		
			
				|  |  | -                        //     status: wxConst.status.success,
 | 
	
		
			
				|  |  | -                        //     tips: wxConst.tips.success,
 | 
	
		
			
				|  |  | -                        //     begin_time: Date.parse(revise.begin_time),
 | 
	
		
			
				|  |  | -                        // };
 | 
	
		
			
				|  |  | -                        // await this.ctx.helper.sendWechat(users, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), wxConst.template.revise, wechatData2);
 | 
	
		
			
				|  |  | -                    } else {
 | 
	
		
			
				|  |  | -                        // 同步修订信息
 | 
	
		
			
				|  |  | -                        await transaction.update(this.ctx.service.ledgerRevise.tableName, {
 | 
	
		
			
				|  |  | -                            id: revise.id,
 | 
	
		
			
				|  |  | -                            status: checkType,
 | 
	
		
			
				|  |  | -                            end_time: time,
 | 
	
		
			
				|  |  | -                        });
 | 
	
		
			
				|  |  | -                        await this.ctx.service.tenderTag.saveTenderTag(revise.tid, {revise_time: new Date()}, transaction);
 | 
	
		
			
				|  |  | -                        // 最新一期跟台账相关的缓存数据应过期
 | 
	
		
			
				|  |  | -                        const lastStage = await this.ctx.service.stage.getFlowLatestStage(revise.tid, true);
 | 
	
		
			
				|  |  | -                        const cacheTime = new Date();
 | 
	
		
			
				|  |  | -                        if (lastStage) {
 | 
	
		
			
				|  |  | -                            await transaction.update(this.ctx.service.stage.tableName, {
 | 
	
		
			
				|  |  | -                                id: lastStage.id,
 | 
	
		
			
				|  |  | -                                cache_time_l: cacheTime,
 | 
	
		
			
				|  |  | -                                cache_time_r: cacheTime,
 | 
	
		
			
				|  |  | -                            });
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                        // 重算台账、计量、工程变更
 | 
	
		
			
				|  |  | -                        const reviseCalc = new RevisePrice(this.ctx);
 | 
	
		
			
				|  |  | -                        const pcTp = await reviseCalc.calcRevise(revise, transaction);
 | 
	
		
			
				|  |  | -                        const sum = revise.sum || await this.ctx.service.reviseBills.addUp({
 | 
	
		
			
				|  |  | -                            tender_id: revise.tid, /* , is_leaf: true*/
 | 
	
		
			
				|  |  | -                        });
 | 
	
		
			
				|  |  | -                        await transaction.update(this.ctx.service.tender.tableName, {
 | 
	
		
			
				|  |  | -                            id: revise.tid,
 | 
	
		
			
				|  |  | -                            total_price: sum.total_price,
 | 
	
		
			
				|  |  | -                            deal_tp: sum.deal_tp,
 | 
	
		
			
				|  |  | -                        });
 | 
	
		
			
				|  |  | -                        // 修订附件取消修订中标记
 | 
	
		
			
				|  |  | -                        await transaction.update(this.ctx.service.ledgerAtt.tableName, { revising: 0 }, { where: { revise_id: revise.id } });
 | 
	
		
			
				|  |  | -                        await this.ctx.service.tenderCache.updateStageCache4Revise(transaction, revise.tid, sum, pcTp);
 | 
	
		
			
				|  |  | -                        // 清除变更新增部位maxLid缓存,防止树结构混乱
 | 
	
		
			
				|  |  | -                        await this.ctx.service.changeLedger._removeCacheMaxLid(audit.tender_id);
 | 
	
		
			
				|  |  | -                        // 短信通知-审批通过提醒功能
 | 
	
		
			
				|  |  | -                        // 下一人
 | 
	
		
			
				|  |  | -                        // const msg = '台账修订审批通过,请登录系统处理。';
 | 
	
		
			
				|  |  | -                        // await this.ctx.helper.sendUserSms(revise.uid, smsTypeConst.const.XD,
 | 
	
		
			
				|  |  | -                        //     smsTypeConst.judge.result.toString(), msg);
 | 
	
		
			
				|  |  | -                        await this.ctx.helper.sendAliSms(revise.uid, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), SmsAliConst.template.revise_result, {
 | 
	
		
			
				|  |  | -                            status: SmsAliConst.status.success,
 | 
	
		
			
				|  |  | -                        });
 | 
	
		
			
				|  |  | -                        // 其他参与人
 | 
	
		
			
				|  |  | -                        const users = this._.pull(this._.map(auditList, 'audit_id'), revise.uid);
 | 
	
		
			
				|  |  | -                        // await this.ctx.helper.sendUserSms(users, smsTypeConst.const.XD,
 | 
	
		
			
				|  |  | -                        //     smsTypeConst.judge.result.toString(), '台账修订审批通过。');
 | 
	
		
			
				|  |  | -                        await this.ctx.helper.sendAliSms(users, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), SmsAliConst.template.revise_result2, {
 | 
	
		
			
				|  |  | -                            status: SmsAliConst.status.success,
 | 
	
		
			
				|  |  | -                        });
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                        users.push(revise.uid);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                        // 微信模板通知
 | 
	
		
			
				|  |  | -                        const shenpiUrl = await this.ctx.helper.urlToShort(
 | 
	
		
			
				|  |  | -                            this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + revise.tid + '/revise/' + revise.id + '/info'
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                        const wechatData2 = {
 | 
	
		
			
				|  |  | -                            wap_url: shenpiUrl,
 | 
	
		
			
				|  |  | -                            status: wxConst.status.success,
 | 
	
		
			
				|  |  | -                            tips: wxConst.tips.success,
 | 
	
		
			
				|  |  | -                            begin_time: Date.parse(revise.begin_time),
 | 
	
		
			
				|  |  | -                            code: this.ctx.session.sessionProject.code,
 | 
	
		
			
				|  |  | -                        };
 | 
	
		
			
				|  |  | -                        await this.ctx.helper.sendWechat(users, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), wxConst.template.revise, wechatData2);
 | 
	
		
			
				|  |  | -                        // 审批通过 - 检查三方特殊推送
 | 
	
		
			
				|  |  | -                        await this.ctx.service.specMsg.addReviseMsg(transaction, pid, revise, pushOperate.ledger.checked);
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | +                    const users = this._.map(auditList.filter(x => { return x.audit_id !== accountId}), 'audit_id');
 | 
	
		
			
				|  |  | +                    users.push(revise.uid);
 | 
	
		
			
				|  |  | +                    await this.ctx.helper.sendAliSms(users, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), SmsAliConst.template.revise_result2, {
 | 
	
		
			
				|  |  | +                        status: SmsAliConst.status.success,
 | 
	
		
			
				|  |  | +                    });
 | 
	
		
			
				|  |  |                  } else {
 | 
	
		
			
				|  |  |                      // 同步修订信息
 | 
	
		
			
				|  |  |                      await transaction.update(this.ctx.service.ledgerRevise.tableName, {
 | 
	
		
			
				|  |  | -                        id: revise.id,
 | 
	
		
			
				|  |  | -                        times: times + 1,
 | 
	
		
			
				|  |  | -                        status: checkType,
 | 
	
		
			
				|  |  | +                        id: revise.id, status: auditConst.status.checked, end_time: time,
 | 
	
		
			
				|  |  |                      });
 | 
	
		
			
				|  |  | -                    // 拷贝新一次审核流程列表
 | 
	
		
			
				|  |  | -                    const auditors = await this.getAllDataByCondition({
 | 
	
		
			
				|  |  | -                        where: { rid: revise.id, times },
 | 
	
		
			
				|  |  | -                        columns: ['tender_id', 'rid', 'audit_order', 'audit_id'],
 | 
	
		
			
				|  |  | -                    });
 | 
	
		
			
				|  |  | -                    for (const a of auditors) {
 | 
	
		
			
				|  |  | -                        a.times = times + 1;
 | 
	
		
			
				|  |  | -                        a.status = auditConst.status.uncheck;
 | 
	
		
			
				|  |  | -                        a.in_time = time;
 | 
	
		
			
				|  |  | +                    await this.ctx.service.tenderTag.saveTenderTag(revise.tid, {revise_time: new Date()}, transaction);
 | 
	
		
			
				|  |  | +                    // 最新一期跟台账相关的缓存数据应过期
 | 
	
		
			
				|  |  | +                    const lastStage = await this.ctx.service.stage.getFlowLatestStage(revise.tid, true);
 | 
	
		
			
				|  |  | +                    const cacheTime = new Date();
 | 
	
		
			
				|  |  | +                    if (lastStage) {
 | 
	
		
			
				|  |  | +                        await transaction.update(this.ctx.service.stage.tableName, {
 | 
	
		
			
				|  |  | +                            id: lastStage.id,
 | 
	
		
			
				|  |  | +                            cache_time_l: cacheTime,
 | 
	
		
			
				|  |  | +                            cache_time_r: cacheTime,
 | 
	
		
			
				|  |  | +                        });
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | -                    await transaction.insert(this.tableName, auditors);
 | 
	
		
			
				|  |  | -                    await transaction.update(this.ctx.service.ledgerHistory.tableName, { id: revise.his_id, valid: 0 });
 | 
	
		
			
				|  |  | +                    // 重算台账、计量、工程变更
 | 
	
		
			
				|  |  | +                    const reviseCalc = new RevisePrice(this.ctx);
 | 
	
		
			
				|  |  | +                    const pcTp = await reviseCalc.calcRevise(revise, transaction);
 | 
	
		
			
				|  |  | +                    const sum = revise.sum || await this.ctx.service.reviseBills.addUp({
 | 
	
		
			
				|  |  | +                        tender_id: revise.tid, /* , is_leaf: true*/
 | 
	
		
			
				|  |  | +                    });
 | 
	
		
			
				|  |  | +                    await transaction.update(this.ctx.service.tender.tableName, {
 | 
	
		
			
				|  |  | +                        id: revise.tid,
 | 
	
		
			
				|  |  | +                        total_price: sum.total_price, deal_tp: sum.deal_tp,
 | 
	
		
			
				|  |  | +                    });
 | 
	
		
			
				|  |  | +                    // 修订附件取消修订中标记
 | 
	
		
			
				|  |  | +                    await transaction.update(this.ctx.service.ledgerAtt.tableName, { revising: 0 }, { where: { revise_id: revise.id } });
 | 
	
		
			
				|  |  | +                    // 更新台账缓存
 | 
	
		
			
				|  |  | +                    await this.ctx.service.tenderCache.updateStageCache4Revise(transaction, revise.tid, sum, pcTp);
 | 
	
		
			
				|  |  | +                    // 清除变更新增部位maxLid缓存,防止树结构混乱
 | 
	
		
			
				|  |  | +                    await this.ctx.service.changeLedger._removeCacheMaxLid(audit.tender_id);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    // 短信通知-审批退回提醒功能
 | 
	
		
			
				|  |  | -                    // 下一人
 | 
	
		
			
				|  |  | -                    // await this.ctx.helper.sendUserSms(revise.uid, smsTypeConst.const.XD,
 | 
	
		
			
				|  |  | -                    //     smsTypeConst.judge.result.toString(), '台账修订审批退回,请登录系统处理。');
 | 
	
		
			
				|  |  | +                    // 短信通知-审批通过提醒功能
 | 
	
		
			
				|  |  |                      await this.ctx.helper.sendAliSms(revise.uid, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), SmsAliConst.template.revise_result, {
 | 
	
		
			
				|  |  | -                        status: SmsAliConst.status.back,
 | 
	
		
			
				|  |  | +                        status: SmsAliConst.status.success,
 | 
	
		
			
				|  |  | +                    });
 | 
	
		
			
				|  |  | +                    const users = this._.pull(this._.map(auditList, 'audit_id'), revise.uid);
 | 
	
		
			
				|  |  | +                    await this.ctx.helper.sendAliSms(users, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), SmsAliConst.template.revise_result2, {
 | 
	
		
			
				|  |  | +                        status: SmsAliConst.status.success,
 | 
	
		
			
				|  |  |                      });
 | 
	
		
			
				|  |  | +                    users.push(revise.uid);
 | 
	
		
			
				|  |  |                      // 微信模板通知
 | 
	
		
			
				|  |  |                      const shenpiUrl = await this.ctx.helper.urlToShort(
 | 
	
		
			
				|  |  |                          this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + revise.tid + '/revise/' + revise.id + '/info'
 | 
	
		
			
				|  |  |                      );
 | 
	
		
			
				|  |  | -                    const wechatData = {
 | 
	
		
			
				|  |  | -                        wap_url: shenpiUrl,
 | 
	
		
			
				|  |  | -                        status: wxConst.status.back,
 | 
	
		
			
				|  |  | -                        tips: wxConst.tips.back,
 | 
	
		
			
				|  |  | -                        begin_time: Date.parse(revise.begin_time),
 | 
	
		
			
				|  |  | -                        code: this.ctx.session.sessionProject.code,
 | 
	
		
			
				|  |  | -                    };
 | 
	
		
			
				|  |  | -                    await this.ctx.helper.sendWechat(revise.uid, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), wxConst.template.revise, wechatData);
 | 
	
		
			
				|  |  | -                    // 其他参与人
 | 
	
		
			
				|  |  | -                    // await this.ctx.helper.sendUserSms(this._.map(auditors, 'user_id'),
 | 
	
		
			
				|  |  | -                    //     smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), '台账修订审批退回。');
 | 
	
		
			
				|  |  | -                    await this.ctx.helper.sendAliSms(
 | 
	
		
			
				|  |  | -                        this._.map(auditors, 'user_id'),
 | 
	
		
			
				|  |  | -                        smsTypeConst.const.XD,
 | 
	
		
			
				|  |  | -                        smsTypeConst.judge.result.toString(),
 | 
	
		
			
				|  |  | -                        SmsAliConst.template.revise_result2,
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            status: SmsAliConst.status.back,
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                    );
 | 
	
		
			
				|  |  | -                    // 微信模板通知
 | 
	
		
			
				|  |  |                      const wechatData2 = {
 | 
	
		
			
				|  |  |                          wap_url: shenpiUrl,
 | 
	
		
			
				|  |  | -                        status: wxConst.status.back,
 | 
	
		
			
				|  |  | -                        tips: wxConst.tips.back,
 | 
	
		
			
				|  |  | +                        status: wxConst.status.success,
 | 
	
		
			
				|  |  | +                        tips: wxConst.tips.success,
 | 
	
		
			
				|  |  |                          begin_time: Date.parse(revise.begin_time),
 | 
	
		
			
				|  |  |                          code: this.ctx.session.sessionProject.code,
 | 
	
		
			
				|  |  |                      };
 | 
	
		
			
				|  |  | -                    await this.ctx.helper.sendWechat(this._.map(auditors, 'user_id'), smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), wxConst.template.revise, wechatData2);
 | 
	
		
			
				|  |  | +                    await this.ctx.helper.sendWechat(users, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), wxConst.template.revise, wechatData2);
 | 
	
		
			
				|  |  | +                    // 审批通过 - 检查三方特殊推送
 | 
	
		
			
				|  |  | +                    await this.ctx.service.specMsg.addReviseMsg(transaction, pid, revise, pushOperate.ledger.checked);
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | +                await transaction.commit();
 | 
	
		
			
				|  |  | +            } catch (err) {
 | 
	
		
			
				|  |  | +                await transaction.rollback();
 | 
	
		
			
				|  |  | +                throw err;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        async _checkNo(revise, opinion, times) {
 | 
	
		
			
				|  |  | +            const accountId = this.ctx.session.sessionUser.accountId;
 | 
	
		
			
				|  |  | +            const pid = this.ctx.session.sessionProject.id;
 | 
	
		
			
				|  |  | +            let audits = await this.getAllDataByCondition({ where: { rid: revise.id, times, status: auditConst.status.checking } });
 | 
	
		
			
				|  |  | +            const selfAuditor = audits.find(x => { return x.audit_id === accountId; });
 | 
	
		
			
				|  |  | +            if (!selfAuditor) throw '当前标段您无权审批';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            const beginAuditors = await this.getAllDataByCondition({ where: { rid: revise.id, audit_order: 1, times } });
 | 
	
		
			
				|  |  | +            const time = new Date();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            const noticeContent = await this.getNoticeContent(pid, revise.tid, revise.id, accountId, opinion);
 | 
	
		
			
				|  |  | +            const defaultNoticeRecord = { pid, type: pushType.revise, status: auditConst.status.checkNo, content: noticeContent };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 整理当前流程审核人状态更新 warning(在try catch中写,会报auditors未初始化)
 | 
	
		
			
				|  |  | +            const updateAuditData = audits.map(x => {
 | 
	
		
			
				|  |  | +                return {
 | 
	
		
			
				|  |  | +                    id: x.id,
 | 
	
		
			
				|  |  | +                    status: x.audit_id === selfAuditor.audit_id ? auditConst.status.checkNo : auditConst.status.checkSkip,
 | 
	
		
			
				|  |  | +                    opinion: x.audit_id === selfAuditor.aid ? opinion : '',
 | 
	
		
			
				|  |  | +                    end_time: x.audit_id === selfAuditor.aid ? time : null,
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            const transaction = await this.db.beginTransaction();
 | 
	
		
			
				|  |  | +            try {
 | 
	
		
			
				|  |  | +                const auditList = await this.getAuditors(revise.id, times);
 | 
	
		
			
				|  |  | +                // 审核通过添加到推送表
 | 
	
		
			
				|  |  | +                const records = [{ uid: revise.uid, ...defaultNoticeRecord }];
 | 
	
		
			
				|  |  | +                auditList.forEach(audit => {
 | 
	
		
			
				|  |  | +                    records.push({ uid: audit.audit_id, ...defaultNoticeRecord });
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +                await transaction.insert('zh_notice', records);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                // 更新当前审核流程
 | 
	
		
			
				|  |  | +                await transaction.updateRows(this.tableName, updateAuditData);
 | 
	
		
			
				|  |  | +                await this.ctx.service.noticeAgain.stopNoticeAgain(transaction, this.tableName, this._.map(audits, 'id'));
 | 
	
		
			
				|  |  | +                // 同步修订信息
 | 
	
		
			
				|  |  | +                await transaction.update(this.ctx.service.ledgerRevise.tableName, {
 | 
	
		
			
				|  |  | +                    id: revise.id, times: times + 1, status: auditConst.status.checkNo,
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +                // 拷贝新一次审核流程列表
 | 
	
		
			
				|  |  | +                const orgAuditors = await this.getAllDataByCondition({
 | 
	
		
			
				|  |  | +                    where: { rid: revise.id, times },
 | 
	
		
			
				|  |  | +                    columns: ['tender_id', 'rid', 'audit_order', 'audit_id', 'audit_type', 'audit_ledger_id'],
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +                const insertAuditors = orgAuditors.map(x => {
 | 
	
		
			
				|  |  | +                    return { ...x, times: times + 1, status: auditConst.status.uncheck, in_time: time };
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +                await transaction.insert(this.tableName, insertAuditors);
 | 
	
		
			
				|  |  | +                await transaction.update(this.ctx.service.ledgerHistory.tableName, { id: revise.his_id, valid: 0 });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                // 短信通知-审批退回提醒功能
 | 
	
		
			
				|  |  | +                await this.ctx.helper.sendAliSms(revise.uid, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), SmsAliConst.template.revise_result, {
 | 
	
		
			
				|  |  | +                    status: SmsAliConst.status.back,
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +                // 微信模板通知
 | 
	
		
			
				|  |  | +                const shenpiUrl = await this.ctx.helper.urlToShort(
 | 
	
		
			
				|  |  | +                    this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + revise.tid + '/revise/' + revise.id + '/info'
 | 
	
		
			
				|  |  | +                );
 | 
	
		
			
				|  |  | +                const wechatData = {
 | 
	
		
			
				|  |  | +                    wap_url: shenpiUrl,
 | 
	
		
			
				|  |  | +                    status: wxConst.status.back,
 | 
	
		
			
				|  |  | +                    tips: wxConst.tips.back,
 | 
	
		
			
				|  |  | +                    begin_time: Date.parse(revise.begin_time),
 | 
	
		
			
				|  |  | +                    code: this.ctx.session.sessionProject.code,
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  | +                await this.ctx.helper.sendWechat(revise.uid, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), wxConst.template.revise, wechatData);
 | 
	
		
			
				|  |  | +                // 其他参与人
 | 
	
		
			
				|  |  | +                const users = this._.map(orgAuditors.filter(x => { return x.audit_id !== accountId; }), 'audit_id');
 | 
	
		
			
				|  |  | +                await this.ctx.helper.sendAliSms(users, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), SmsAliConst.template.revise_result2, {status: SmsAliConst.status.back});
 | 
	
		
			
				|  |  | +                // 微信模板通知
 | 
	
		
			
				|  |  | +                const wechatData2 = {
 | 
	
		
			
				|  |  | +                    wap_url: shenpiUrl,
 | 
	
		
			
				|  |  | +                    status: wxConst.status.back,
 | 
	
		
			
				|  |  | +                    tips: wxConst.tips.back,
 | 
	
		
			
				|  |  | +                    begin_time: Date.parse(revise.begin_time),
 | 
	
		
			
				|  |  | +                    code: this.ctx.session.sessionProject.code,
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  | +                await this.ctx.helper.sendWechat(users, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), wxConst.template.revise, wechatData2);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  await transaction.commit();
 | 
	
		
			
				|  |  |              } catch (err) {
 | 
	
	
		
			
				|  | @@ -807,6 +793,22 @@ module.exports = app => {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /**
 | 
	
		
			
				|  |  | +         * 审批
 | 
	
		
			
				|  |  | +         * @param {Object} revise - 修订
 | 
	
		
			
				|  |  | +         * @param {auditConst.status.checked|auditConst.status.checkNo} checkType - 审批结果
 | 
	
		
			
				|  |  | +         * @param {String} opinion - 审批意见
 | 
	
		
			
				|  |  | +         * @param {Number} times - 第几次审批
 | 
	
		
			
				|  |  | +         * @return {Promise<void>}
 | 
	
		
			
				|  |  | +         */
 | 
	
		
			
				|  |  | +        async check(revise, checkType, opinion, times = 1) {
 | 
	
		
			
				|  |  | +            switch (checkType) {
 | 
	
		
			
				|  |  | +                case auditConst.status.checked: await this._checked(revise, opinion, times); break;
 | 
	
		
			
				|  |  | +                case auditConst.status.checkNo: await this._checkNo(revise, opinion, times); break;
 | 
	
		
			
				|  |  | +                default: throw '提交数据错误';
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /**
 | 
	
		
			
				|  |  |           * 取待审批修订列表(wap用)
 | 
	
		
			
				|  |  |           *
 | 
	
		
			
				|  |  |           * @param auditorId
 |