'use strict'; /** * 合同支付 * * @author Mai * @date * @version */ const audit = require('../const/audit'); 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() { } async save() { } 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 renderData = { pays, calcBase, jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.phasePay.detail) }; 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 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 bonus = await ctx.service.stageBonus.getStageDataById(parts.field.bonus_id); //if (!bonus || bonus.sid !== ctx.stage.id) throw '该奖罚金,当前不允许上传附件'; while (stream !== undefined) { if (!stream.filename) { throw '未发现上传文件!'; } const fileInfo = path.parse(stream.filename); const dirName = 'app/public/upload/extra/' + moment().format('YYYYMMDD'); const fileName = create_time + '_' + index + fileInfo.ext; // 保存文件 await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, dirName, fileName)); await sendToWormhole(stream); // 插入到stage_pay对应的附件列表中 bonus.proof_file.push({ filename: fileInfo.name, fileext: fileInfo.ext, filesize: Array.isArray(parts.field.size) ? parts.field.size[index] : parts.field.size, filepath: path.join(dirName, fileName), uid: ctx.session.sessionUser.accountId, in_time: moment(create_time * 1000).format('YYYY-MM-DD'), renew: bonus.sid === ctx.stage.id ? ctx.stage.status === auditConst.status.checked : true, }); ++index; if (Array.isArray(parts.field.size) && index < parts.field.size.length) { stream = await parts(); } else { stream = undefined; } } const result = await ctx.service.stageBonus.updateDatas({ update: [ { id: bonus.id, proof_file: bonus.proof_file }, ] }); for (const pf of bonus.proof_file) { pf.username = (await ctx.service.projectAccount.getAccountInfoById(pf.uid)).name; if (ctx.helper.canPreview(pf.fileext)){ pf.viewpath = pf.filepath.substr(3, pf.filepath.length - 3); } delete pf.filepath; } ctx.body = {err: 0, msg: '', data: bonus.proof_file}; } catch (error) { ctx.helper.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); const bonus = await ctx.service.stageBonus.getStageDataById(data.b_id); if (!bonus || !bonus.proof_file || !bonus.proof_file[data.index]) throw '删除的文件不存在'; const fileInfo = bonus.proof_file[data.index]; if (fileInfo.uid !== ctx.session.sessionUser.accountId) throw '您无权删除该文件'; const deleteFilePermission = PermissionCheck.delFile(this.ctx.session.sessionUser.permission); if (ctx.stage.status === auditConst.status.checked && !fileInfo.renew && !deleteFilePermission) throw '不可删除该文件'; // 先删除文件 await fs.unlinkSync(path.join(this.app.baseDir, fileInfo.filepath)); // 再删除数据库 bonus.proof_file.splice(data.index, 1); const result = await ctx.service.stageBonus.updateDatas({ update: [ { id: bonus.id, proof_file: bonus.proof_file }, ] }); for (const pf of bonus.proof_file) { delete pf.filepath; pf.username = (await ctx.service.projectAccount.getAccountInfoById(pf.uid)).name; } ctx.body = {err: 0, msg: '', data: bonus.proof_file}; } catch (err) { this.log(err); this.ctx.ajaxErrorBody(err, '删除文件失败'); } } } return PayController; };