'use strict'; /** * 标段管理控制器 * * @author CaiAoLin * @date 2018/2/5 * @version */ const tenderConst = require('../const/tender'); const codeRuleConst = require('../const/code_rule'); const settingConst = require('../const/setting.js'); const tenderMenu = require('../../config/menu').tenderMenu; const auditConst = require('../const/audit'); const accountPermission = require('../const/account_permission'); module.exports = app => { class TenderController extends app.BaseController { /** * 构造函数 * * @param {Object} ctx - egg全局变量 * @return {void} */ constructor(ctx) { super(ctx); ctx.showProject = true; ctx.showTitle = true; } async _listDetail(view, modal = '') { try { // 获取用户新建标段权利 const accountInfo = await this.ctx.service.projectAccount.getDataById(this.ctx.session.sessionUser.accountId); const userPermission = accountInfo !== undefined && accountInfo.permission !== '' ? JSON.parse(accountInfo.permission) : null; const tenderList = await this.ctx.service.tender.getList('', userPermission); for (const t of tenderList) { if (t.user_id === this.ctx.session.sessionUser.accountId && ( t.ledger_status === auditConst.ledger.status.checkNo || t.ledger_status === auditConst.ledger.status.uncheck)) { const sum = await this.ctx.service.ledger.addUp({tender_id: t.id, is_leaf: true}); t.total_price = sum.total_price; t.deal_tp = sum.deal_tp; } if (t.ledger_status === auditConst.ledger.status.checked) { t.lastStage = await this.ctx.service.stage.getLastestStage(t.id, true); if (t.lastStage) { await this.ctx.service.stage.checkStageGatherData(t.lastStage); } } } const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id); const valuations = await this.ctx.service.valuation.getProjectValidValuation(this.ctx.session.sessionProject.id); const renderData = { tenderList, tenderConst, settingConst, categoryData, measureType: tenderConst.measureType, jsFiles: this.app.jsFiles.common.concat(this.jsFiles), auditConst, userPermission, valuations, }; await this.layout(view, renderData, modal); } catch (err) { this.log(err); this.ctx.redirect('/dashboard'); } } async _list(view, renderData, modal = '') { try { renderData.tenderList = await this.ctx.service.tender.getList('', renderData.userPermission); for (const t of renderData.tenderList) { if (t.ledger_status === auditConst.ledger.status.checked) { t.lastStage = await this.ctx.service.stage.getLastestStage(t.id, true); t.completeStage = await this.ctx.service.stage.getLastestCompleteStage(t.id); } } renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id); renderData.valuations = await this.ctx.service.valuation.getProjectValidValuation(this.ctx.session.sessionProject.id); renderData.tenderConst = tenderConst; renderData.settingConst = settingConst; renderData.measureType = tenderConst.measureType; renderData.jsFiles = this.app.jsFiles.common.concat(this.jsFiles); renderData.auditConst = auditConst; await this.layout(view, renderData, modal); } catch (err) { this.log(err); this.ctx.redirect('/dashboard') } } async listDefault(ctx) { this.jsFiles = this.app.jsFiles.tender.list; const accountInfo = await this.ctx.service.projectAccount.getDataById(this.ctx.session.sessionUser.accountId); const userPermission = accountInfo !== undefined && accountInfo.permission !== '' ? JSON.parse(accountInfo.permission) : null; const renderData = { accountInfo, userPermission, }; await this._list('tender/index.ejs', renderData, 'tender/modal.ejs'); } /** * 标段概况(Get) * * @param {object} ctx - egg全局变量 * @return {void} */ async listInfo(ctx) { this.jsFiles = this.app.jsFiles.tender.info; await this._listDetail('tender/info.ejs', 'tender/modal.ejs'); } /** * 计量进度(Get) * * @param ctx * @return {Promise} */ async listProgress(ctx) { this.jsFiles = this.app.jsFiles.tender.progress; await this._listDetail('tender/progress.ejs', 'tender/modal.ejs'); } /** * 标段管理(Get) * * @param ctx * @return {Promise} */ async listManage(ctx) { this.jsFiles = this.app.jsFiles.tender.manage; // 先判断权限 // 获取用户新建标段权利 const accountInfo = await this.ctx.service.projectAccount.getDataById(this.ctx.session.sessionUser.accountId); const userPermission = accountInfo !== undefined && accountInfo.permission !== '' ? JSON.parse(accountInfo.permission) : null; if (userPermission !== null && userPermission.tender !== undefined && userPermission.tender.indexOf('1') !== -1) { const renderData = { accountInfo, userPermission }; await this._list('tender/manage.ejs', renderData, 'tender/manage_modal.ejs') // 获取用户新建标段权利 // const accountInfo = await this.ctx.service.projectAccount.getDataById(this.ctx.session.sessionUser.accountId); // const userPermission = accountInfo !== undefined && accountInfo.permission !== '' ? JSON.parse(accountInfo.permission) : null; // // const tenderList = await this.ctx.service.tender.getList('manage', userPermission); // for (const t of tenderList) { // t.lastStage = await this.ctx.service.stage.getLastestStage(t.id, true); // t.completeStage = await this.ctx.service.stage.getLastestCompleteStage(t.id); // } // const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id); // const valuations = await this.ctx.service.valuation.getProjectValidValuation(this.ctx.session.sessionProject.id); // const renderData = { // tenderList, // tenderConst, // settingConst, // categoryData, // measureType: tenderConst.measureType, // jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.tender.manage), // auditConst, // userPermission, // valuations, // }; // await this.layout('tender/manage.ejs', renderData, 'tender/manage_modal.ejs'); } else { this.ctx.redirect(ctx.request.header.referer); } } /** * 新增标段(Ajax) * * @param ctx * @return {Promise} */ async addTender(ctx) { try { const responseData = { err: 0, msg: '', data: null, }; // 获取用户新建标段权利 const accountInfo = await this.ctx.service.projectAccount.getDataById(this.ctx.session.sessionUser.accountId); const userPermission = accountInfo !== undefined && accountInfo.permission !== '' ? JSON.parse(accountInfo.permission) : null; if (userPermission === null || userPermission.tender === undefined || userPermission.tender.indexOf('1') === -1) { throw '当前用户没有创建标段的权限'; } const data = JSON.parse(ctx.request.body.data); if (!data.name || data.name === '' || !data.valuation) { throw '标段信息不完整'; } responseData.data = await ctx.service.tender.add(data); ctx.body = responseData; } catch (error) { this.log(error); ctx.body = { err: 1, msg: error.toString(), data: null }; } } /** * 编辑标段(Ajax) * * @param ctx * @return {Promise} */ async updateTender(ctx) { try { const responseData = { err: 0, msg: '', data: null, }; const data = JSON.parse(ctx.request.body.data); if (!data.id) { throw '提交信息错误'; } if (!data.name || data.name === '') { throw '标段信息不完整'; } if (await ctx.service.tender.save(data, data.id)) { responseData.data = await ctx.service.tender.getTender(data.id); } ctx.body = responseData; } catch (error) { this.log(error); ctx.body = { err: 1, msg: error.toString(), data: null }; } } /** * 删除标段(Ajax) * * @param ctx * @return {Promise} */ async deleteTender(ctx) { try { const data = JSON.parse(ctx.request.body.data), result = []; if (!(data instanceof Array) && (data.length === 0)) { throw '提交数据有误'; } for (const id of data) { if (await ctx.service.tender.deleteTenderNoBackup(id)) { result.push(id); } } ctx.body = {err: 0, msg: '', data: result}; } catch (err) { ctx.body = {err: 1, msg: err.toString(), data: []} } } /** * 标段概况(Get) * * @param ctx * @return {Promise} */ async tenderInfo(ctx) { try { const tender = ctx.tender.data; if (tender.user_id === this.ctx.session.sessionUser.accountId && ( tender.ledger_status === auditConst.ledger.status.checkNo || tender.ledger_status === auditConst.ledger.status.uncheck)) { const sum = await this.ctx.service.ledger.addUp({tender_id: tender.id, is_leaf: true}); tender.total_price = sum.total_price; tender.deal_tp = sum.deal_tp; } const stages = await ctx.service.stage.getValidStages(ctx.tender.id); const lastStage = stages[0]; //await ctx.service.stage.getLastestStage(ctx.tender.id); if (lastStage) { await this.ctx.service.stage.checkStageGatherData(lastStage); tender.gather_tp = ctx.helper.add(lastStage.contract_tp, lastStage.qc_tp); tender.end_contract_tp = ctx.helper.add(lastStage.contract_tp, lastStage.pre_contract_tp); tender.end_qc_tp = ctx.helper.add(lastStage.qc_tp, lastStage.pre_qc_tp); tender.end_gather_tp = ctx.helper.add(tender.end_contract_tp, tender.end_qc_tp); tender.pre_gather_tp = ctx.helper.add(lastStage.pre_contract_tp, lastStage.pre_qc_tp); tender.yf_tp = lastStage.yf_tp; tender.qc_ratio = ctx.helper.mul(ctx.helper.div(tender.end_qc_tp, tender.gather_tp, 2), 100); tender.sum = ctx.helper.add(tender.total_price, tender.end_qc_tp); tender.pre_ratio = ctx.helper.mul(ctx.helper.div(tender.pre_gather_tp, tender.sum, 2), 100); tender.cur_ratio = ctx.helper.mul(ctx.helper.div(tender.gather_tp, tender.sum, 2), 100); tender.other_tp = ctx.helper.sub(ctx.helper.sub(tender.sum, tender.pre_gather_tp), tender.gather_tp); tender.other_ratio = Math.max(0, 100 - tender.pre_ratio - tender.cur_ratio); } const monthProgress = []; for (const s of stages) { if (s.s_time) { let progress = monthProgress.find(function (x) { return x.month === s.s_time; }); if (!progress) { progress = {month: s.s_time}; monthProgress.push(progress); } progress.tp = ctx.helper.add(ctx.helper.add(progress.tp, s.contract_tp), s.qc_tp); } } monthProgress.sort(function (x, y) { return Date.parse(x.month) - Date.parse(y.month); }); let sum = 0; for (const p of monthProgress) { p.ratio = ctx.helper.mul(ctx.helper.div(p.tp, tender.sum, 4), 100); sum = ctx.helper.add(sum, p.tp); p.end_tp = sum; p.end_ratio = ctx.helper.mul(ctx.helper.div(p.end_tp, tender.sum, 4), 100); } const renderData = { tender: tender, tenderInfo: ctx.tender.info, tenderMenu: this.menu.tenderMenu, preUrl: '/tender/' + ctx.tender.id, cooperation: ctx.session.sessionUser.cooperation, lastStage, stages: stages.reverse(), monthProgress, audit: auditConst, jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.tender.tenderInfo), }; await this.layout('tender/detail.ejs', renderData, 'tender/detail_modal.ejs'); } catch (error) { this.log(error); this.ctx.redirect('/list'); } } /** * 保存标段属性等(Ajax) * * @param ctx * @return {Promise} */ async saveTenderInfo(ctx) { try { const data = JSON.parse(ctx.request.body.data); if (!data) { throw '提交数据错误'; } if (ctx.tender.data.ledger_status === auditConst.ledger.status.checked) { if (data.deal_param) { const lastStage = await this.ctx.service.stage.getLastestStage(ctx.tender.id, true); if (lastStage) { if (lastStage.order > 1 || (lastStage.status === auditConst.stage.status.checked || lastStage.status === auditConst.stage.status.checking)) throw '第一期上报后不可修改合同参数'; if (lastStage.user_id !== ctx.session.sessionUser.accountId) throw '仅原报可修改合同参数'; } } } if (data.decimal) { if (ctx.tender.data.user_id !== ctx.session.sessionUser.accountId) throw '仅原报可修改小数位数'; await ctx.service.tenderInfo.saveDecimal(ctx.tender.id, data.decimal, ctx.tender.info.decimal); } else if (data.precision) { if (ctx.tender.data.user_id !== ctx.session.sessionUser.accountId) throw '仅原报可修改清单精度'; await ctx.service.tenderInfo.savePrecision(ctx.tender.id, data.precision, ctx.tender.info.precision, ctx.tender.info.decimal); } else { await ctx.service.tenderInfo.saveTenderInfo(ctx.tender.id, data); } ctx.body = { err: 0, msg: '', data: JSON.parse(ctx.request.body.data) }; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString(), data: null }; } } /** * 设置标段计量类型并调整到标段概况(Get) * * @param ctx * @return {Promise} */ async tenderType(ctx) { try { const tenderId = ctx.params.id, type = ctx.query.type; if (!tenderId) { throw '当前未打开标段'; } const tender = await ctx.service.tender.getTender(tenderId); if (!tender) { throw '标段数据错误'; } if (!tender.measure_type) { await ctx.service.tender.update({ measure_type: type }, { id: tender.id }); } ctx.redirect('/tender/' + tenderId); } catch (error) { this.log(error); ctx.redirect('/list'); } } /** * 标段协作办公 * * @param {Object} ctx - egg全局变量 * @return {void} */ async tenderCooperation(ctx) { const tenderId = ctx.params.id; try { if (!ctx.session.sessionUser.cooperation) { throw '权限不足'; } const tender = await ctx.service.tender.getDataById(tenderId); const user = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId); // 获取已参与协作用户列表 const cooperationArray = []; if (tender.cooperation !== null && tender.cooperation !== '') { const cooperationList = JSON.parse(tender.cooperation); for (const cl in cooperationList) { const clArray = []; for (const audit of cooperationList[cl]) { const userInfo = await ctx.service.projectAccount.getDataById(audit); clArray.push(userInfo); } cooperationArray[cl] = clArray; } } const renderData = { user, tender, tenderMenu: this.menu.tenderMenu, preUrl: '/tender/' + tenderId, tenderPermissionList: accountPermission.tenderPermissionList, cooperationArray, }; await this.layout('tender/cooperation.ejs', renderData, 'tender/cooperationModal.ejs'); } catch (error) { this.log(error); this.ctx.redirect('/tender/' + tenderId); } } /** * 添加标段操作 * * @param {Object} ctx - egg全局变量 * @return {void} */ async add(ctx) { try { const rule = ctx.service.tender.rule('add'); ctx.helper.validate(rule); const result = ctx.service.tender.add(ctx.request.body); if (!result) { throw '新增标段失败'; } } catch (error) { this.log(error); this.setMessage(error.toString(), this.messageType.ERROR); } ctx.redirect(ctx.request.header.referer); } /** * 切换标段 --》 暂时废弃,不存在此功能 * * @param {Object} ctx - egg全局变量 * @return {void} */ async switchTender(ctx) { let tenderId = ctx.params.tenderId; tenderId = parseInt(tenderId); try { if (isNaN(tenderId) || tenderId <= 0) { throw '参数错误'; } const result = await ctx.service.tender.switchTender(tenderId); if (!result) { throw '切换标段失败!'; } } catch (error) { this.setMessage(error.toString(), this.messageType.ERROR); } ctx.redirect(ctx.request.header.referer); } /** * 保存标段操作 * * @param {Object} ctx - egg全局变量 * @return {void} */ async save(ctx) { let id = ctx.request.body.tenderId; id = parseInt(id); try { if (isNaN(id) || id < 0) { throw '参数错误'; } // 获取数据规则 const rule = ctx.service.tender.rule('save'); ctx.validate(rule); const result = await ctx.service.tender.save(ctx.request.body, id); if (!result) { throw '保存标段数据失败'; } this.setMessage('保存标段数据成功', this.messageType.SUCCESS); } catch (error) { this.setMessage(error.toString(), this.messageType.ERROR); } ctx.redirect(ctx.request.header.referer); } /** * 删除标段 * * @param {Object} ctx -egg全局变量 * @return {void} */ async delete(ctx) { let id = ctx.request.body.tenderId; id = parseInt(id); try { if (isNaN(id) || id <= 0) { throw '参数错误'; } const result = ctx.service.tender.deleteTenderById(id); if (!result) { throw '删除标段失败'; } this.setMessage('删除标段成功', this.messageType.SUCCESS); } catch (error) { this.setMessage(error.toString(), this.messageType.ERROR); } ctx.redirect(ctx.request.header.referer); } async rule(ctx) { const responseData = { err: 0, msg: '', data: {}, }; try { const tenderId = ctx.session.sessionUser.tenderId; if (!tenderId) { throw '当前未打开标段'; } const data = JSON.parse(ctx.request.body.data); if (!data.rule || !JSON.parse(data.data).length || !codeRuleConst.ruleField[data.rule]) { throw '请选择组件再添加'; } if (!data.connector) { throw '请选择连接符'; } const updateData = { id: tenderId, }; updateData[codeRuleConst.ruleField[data.rule]] = data.data; updateData.c_connector = data.connector; updateData.c_rule_first = 0; const result = await ctx.service.tender.db.update(ctx.service.tender.tableName, updateData); if (result.affectedRows !== 1) { throw '更新规则失败'; } } catch (err) { this.log(err); responseData.err = 1; responseData.msg = err.toString(); } ctx.body = responseData; } async ruleFirst(ctx) { const responseData = { err: 0, msg: '', data: {}, }; try { const tenderId = ctx.session.sessionUser.tenderId; if (!tenderId) { throw '当前未打开标段'; } const updateData = { id: tenderId, }; updateData.c_rule_first = 0; const result = await ctx.service.tender.db.update(ctx.service.tender.tableName, updateData); if (result.affectedRows !== 1) { throw '更新规则失败'; } } catch (err) { this.log(err); responseData.err = 1; responseData.msg = err.toString(); } ctx.body = responseData; } } return TenderController; };