'use strict'; /** * 合同支付 * * @author Mai * @date * @version */ const audit = require('../const/audit'); const shenpiConst = require('../const/shenpi'); const sendToWormhole = require('stream-wormhole'); const path = require('path'); module.exports = app => { class PayController extends app.BaseController { /** * 构造函数 * * @param {Object} ctx - egg全局变量 * @return {void} */ constructor(ctx) { super(ctx); } async index(ctx) { try { const phasePays = await this.ctx.service.phasePay.getAllPhasePay(ctx.tender.id, 'DESC'); const relaStage = []; for (const p of phasePays) { // todo 加载当前审批人 // if (p.audit_status !== checked) await this.ctx.service.phasePay.loadUser(p); p.curAuditors = []; relaStage.push(...p.rela_stage); } const stages = await this.ctx.service.stage.getAllDataByCondition({ where: { tid: ctx.tender.id }, orders: [['order', 'AEC']] }); const validStages = stages.filter(s => { return !relaStage.find(r => { return s.id === r.id; }); }); this.ctx.service.phasePay.calculatePhasePay(phasePays); const renderData = { phasePays, validStages, auditConst: audit.common, jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.phasePay.list) }; await this.layout('phase_pay/index.ejs', renderData, 'phase_pay/modal.ejs'); } catch (err) { ctx.helper.log(err); } } async add(ctx) { try { if (ctx.session.sessionUser.accountId !== ctx.tender.data.user_id && ctx.tender.userAssistsId.indexOf(ctx.session.sessionUser.accountId) < 0) { throw '您无权创建计量期'; } const date = ctx.request.body.date; if (!date) throw '请选择支付年月'; const stage = ctx.request.body.stage; if (!stage) throw '请选择计量期'; const memo = ctx.request.body.memo; const pays = await ctx.service.phasePay.getAllPhasePay(ctx.tender.id, 'DESC'); const unCompleteCount = pays.filter(s => { return s.status !== audit.common.status.checked; }).length; if (unCompleteCount.length > 0) throw `最新一起未审批通过,请审批通过后再新增`; // 预留可以关联多期 const stages = await ctx.service.stage.getAllDataByCondition({ where: { tid: ctx.tender.id, order: stage } }); const newPhase = await ctx.service.phasePay.add(ctx.tender.id, stages, date, memo); if (!newPhase) throw '新增期失败'; newPhase.curTimes = 1; newPhase.curOrder = 0; await ctx.service.phasePayDetail.calculateSave(newPhase); ctx.redirect('/tender/' + ctx.tender.id + '/pay' + newPhase.phase_order); } catch (err) { this.log(err); ctx.postError(err, '新增期失败'); ctx.redirect(ctx.request.header.referer); } } async del(ctx) { try { if (!ctx.session.sessionUser.is_admin && ctx.request.body.confirm !== '确认删除本期') throw '请输入文本确认删除本期'; const phase_id = ctx.request.body.phase_id; const phasePay = await ctx.service.phasePay.getDataById(phase_id); if (!phasePay) throw '删除的期不存在,请刷新页面'; if (!ctx.session.sessionUser.is_admin && phasePay.create_user_id !== ctx.session.sessionUser.accountId) throw '您无权删除本期'; // 获取最新的期数 const phasePayCount = await ctx.service.phasePay.count({ tid: ctx.tender.id }); if (phasePay.phase_order !== phasePayCount) throw '非最新一期,不可删除'; await ctx.service.phasePay.delete(phase_id); // todo 刷新金额概况缓存 // await ctx.service.tenderCache.refreshPayCache(phasePay.tenderId); ctx.redirect('/tender/' + ctx.tender.id + '/pay'); } catch (err) { ctx.log(err); ctx.redirect(ctx.request.header.referer); } } async save(ctx) { try { const phase_id = ctx.request.body.phase_id; const data = { phase_date: ctx.request.body.date, memo: ctx.request.body.memo, }; const phasePay = await ctx.service.phasePay.getPhasePay(phase_id); if (!phasePay) throw '删除的期不存在,请刷新页面'; if (!ctx.session.sessionUser.is_admin && phasePay.create_user_id !== ctx.session.sessionUser.accountId) throw '您无权修改该数据'; await this.ctx.service.phasePay.save(phasePay, data); if (phasePay.audit_status === audit.common.status.uncheck && ctx.request.body.stage) { const stages = await ctx.service.stage.getAllDataByCondition({ where: { tid: ctx.tender.id, order: ctx.request.body.stage } }); await this.ctx.service.phasePay.resetRelaStageId(phasePay, stages); } ctx.redirect('/tender/' + ctx.tender.id + '/pay'); } catch (err) { console.log(err); this.log(err); ctx.redirect('/tender/' + ctx.tender.id + '/pay'); } } async detail(ctx) { try { // await this.ctx.service.phasePayDetail.calculateSave(ctx.phasePay); const pays = await this.ctx.service.phasePayDetail.getDetailData(ctx.phasePay); const calcBase = this.ctx.service.phasePay.getPhasePayCalcBase(ctx.phasePay, ctx.tender.info); const projectFunInfo = await this.ctx.service.project.getFunRela(ctx.session.sessionProject.id); const lastStage = await this.ctx.service.stage.getLastestCompleteStage(ctx.tender.id); const accountList = await ctx.service.projectAccount.getAllDataByCondition({ where: { project_id: ctx.session.sessionProject.id, enable: 1 }, columns: ['id', 'name', 'company', 'role', 'enable', 'is_admin', 'account_group', 'mobile'], }); const unitList = await ctx.service.constructionUnit.getAllDataByCondition({ where: { pid: ctx.session.sessionProject.id } }); const accountGroup = unitList.map(item => { const groupList = accountList.filter(item1 => item1.company === item.name); return { groupName: item.name, groupList }; }); const renderData = { pays, calcBase, lockPayExpr: projectFunInfo.lockPayExpr, auditConst: audit.common, deadlineType: this.ctx.service.phasePayDetail.deadlineType, maxStageOrder: lastStage.order, jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.phasePay.detail), accountList, accountGroup, shenpiConst, }; await this.layout('phase_pay/detail.ejs', renderData, 'phase_pay/detail_modal.ejs'); } catch (err) { ctx.helper.log(err); ctx.postError(err, '读取合同支付数据错误'); ctx.redirect(ctx.request.headers.referer); } } async detailLoad(ctx) { try { const data = JSON.parse(ctx.request.body.data); if (!data.filter) throw '参数错误'; const filter = data.filter.split(','); const result = {}; for (const f of filter) { switch(f) { case 'pay': result.pay = await this.ctx.service.phasePayDetail.getDetailData(ctx.phasePay); break; case 'base': result.base = this.ctx.service.phasePay.getPhasePayCalcBase(ctx.phasePay, ctx.tender.info); break; case 'add': result.add = ctx.phasePay.calc_base; break; case 'file': result.file = await this.ctx.service.phasePayFile.getData(ctx.phasePay.id, 'pay'); } } ctx.body = { err: 0, msg: '', data: result }; } catch (err) { ctx.log(err); ctx.ajaxErrorBody(err, '读取合同支付数据错误'); } } async detailUpdate(ctx) { try { const data = JSON.parse(ctx.request.body.data); if (!data.postType || !data.postData) throw '数据错误'; const responseData = { err: 0, msg: '', data: {} }; switch (data.postType) { case 'add': responseData.data = await this.ctx.service.phasePayDetail.addDetailNode(ctx.phasePay, data.postData.id, data.postData.count || 1); break; case 'delete': await this.ctx.service.phasePayDetail.deleteDetailNode(ctx.phasePay, data.postData.id, data.postData.count || 1); await this.ctx.service.phasePayDetail.calculateSave(ctx.phasePay); responseData.data.reload = await this.ctx.service.phasePayDetail.getDetailData(ctx.phasePay); break; case 'up-move': responseData.data = await this.ctx.service.phasePayDetail.upMoveDetailNode(ctx.phasePay, data.postData.id, data.postData.count || 1); break; case 'down-move': responseData.data = await this.ctx.service.phasePayDetail.downMoveDetailNode(ctx.phasePay, data.postData.id, data.postData.count || 1); break; case 'update': const updateDetail = await this.ctx.service.phasePayDetail.updateDetail(ctx.phasePay, data.postData); if (this.ctx.service.phasePayDetail.checkCalc(data.postData)) { await this.ctx.service.phasePayDetail.calculateSave(ctx.phasePay); responseData.data.reload = await this.ctx.service.phasePayDetail.getDetailData(ctx.phasePay); } else { responseData.data.update = updateDetail; } break; case 'calc': await this.ctx.service.phasePayDetail.calculateSave(ctx.phasePay); responseData.data.reload = await this.ctx.service.phasePayDetail.getDetailData(ctx.phasePay); break; case 'refreshBase': await this.ctx.service.phasePay.refreshCalcBase(ctx.phasePay); responseData.data.reload = await this.ctx.service.phasePayDetail.getDetailData(ctx.phasePay); responseData.data.calcBase = this.ctx.service.phasePay.getPhasePayCalcBase(ctx.phasePay, ctx.tender.info); responseData.data.calcBase.forEach(x => { x.formatValue = ctx.tender.info.display.thousandth ? ctx.helper.formatNum(x.value, '#,##0.######') : x.value; }); responseData.data.addBase = ctx.phasePay.calc_base; break; default: throw '未知操作'; } ctx.body = responseData; } catch (err) { console.log(err); this.log(err); ctx.body = this.ajaxErrorBody(err, '数据错误'); } } async uploadFile(ctx) { let stream; try { const parts = ctx.multipart({autoFields: true}); let index = 0; const create_time = Date.parse(new Date()) / 1000; let stream = await parts(); const user = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId); const rela_type = parts.fields.type; const rela_id = parts.field.rela_id; const uploadfiles = []; while (stream !== undefined) { if (!stream.filename) throw '未发现上传文件!'; const fileInfo = path.parse(stream.filename); const filepath = `app/public/upload/${ctx.phasePay.tid}/phasePay/${ctx.moment().format('YYYYMMDD')}/${create_time + '_' + index + fileInfo.ext}`; // 保存文件 await ctx.app.fujianOss.put(ctx.app.config.fujianOssFolder + filepath, stream); await sendToWormhole(stream); // 插入到stage_pay对应的附件列表中 uploadfiles.push({ rela_id, filename: fileInfo.name, fileext: fileInfo.ext, filesize: Array.isArray(parts.field.size) ? parts.field.size[index] : parts.field.size, filepath, }); ++index; if (Array.isArray(parts.field.size) && index < parts.field.size.length) { stream = await parts(); } else { stream = undefined; } } const result = await ctx.service.phasePayFile.addFiles(ctx.phasePay, 'pay', uploadfiles, user); ctx.body = {err: 0, msg: '', data: result}; } catch (error) { ctx.log(error); // 失败需要消耗掉stream 以防卡死 if (stream) await sendToWormhole(stream); ctx.body = this.ajaxErrorBody(error, '上传附件失败,请重试'); } } async deleteFile(ctx) { try{ const data = JSON.parse(ctx.request.body.data); if (!data) throw '缺少参数'; const result = await ctx.service.phasePayFile.delFiles(data); ctx.body = { err: 0, msg: '', data: result }; } catch(error) { this.log(error); ctx.ajaxErrorBody(error, '删除附件失败'); } } async auditUpdate(ctx) { try { if (!ctx.session.sessionUser.accountId !== ctx.phasePay.create_user_id) throw '您无权进行操作'; if (ctx.phasePay.status !== audit.common.status.uncheck && ctx.phasePay.status !== audit.common.status.checkNo) throw '已上报,不可修改审批流程'; const data = JSON.parse(ctx.request.body.data); await ctx.service.phasePayAudit.saveAudit(ctx.phasePay, data); const auditors = await ctx.service.phasePayAudit.getUniqUserGroup(ctx.phasePay.id, ctx.phasePay.audit_times); ctx.body = { err: 0, msg: '', data: auditors }; } catch (err) { ctx.log(err); ctx.body = this.ajaxErrorBody(err, '保存审批人数据失败'); } } async auditSave(ctx) { try { if (!ctx.session.sessionUser.is_admin) throw '您无权进行操作'; if (ctx.phasePay.status === audit.common.status.checked) throw '已审批通过,不可修改审批流程'; const data = JSON.parse(ctx.request.body.data); await ctx.service.phasePayAudit.saveAudit(ctx.phasePay, data); const auditors = await ctx.service.phasePayAudit.getUniqUserGroup(ctx.phasePay.id, ctx.phasePay.audit_times); ctx.body = { err: 0, msg: '', data: auditors }; } catch (err) { ctx.log(err); ctx.body = this.ajaxErrorBody(err, '保存审批人数据失败'); } } } return PayController; };