'use strict'; /** * * * @author Mai * @date * @version */ const stdDataAddType = { withParent: 1, child: 2, next: 3, }; const audit = require('../const/audit'); const tenderMenu = require('../../config/menu').tenderMenu; const measureType = require('../const/tender').measureType; const spreadConst = require('../const/spread'); const fs = require('fs'); const LzString = require('lz-string'); module.exports = app => { class ReviseController extends app.BaseController { /** * 构造函数 * * @param {Object} ctx - egg全局变量 * @return {void} */ constructor(ctx) { super(ctx); } /** * 是否可以新增修订 * @param ctx * @returns {Promise} * @private */ async _getAddReviseValid(ctx) { const stage = await ctx.service.stage.getLastestStage(ctx.tender.id, true); const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); return (ctx.tender.data.user_id === ctx.session.sessionUser.accountId) && (ctx.tender.data.ledger_status === audit.ledger.status.checked) && (!stage || stage.status === audit.stage.status.checked) && (!revise || !revise.valid || revise.status === audit.revise.status.checked); } /** * 台账修订页面 (Get) * * @param {object} ctx - egg全局变量 * @return {void} */ async index(ctx) { try { // 分页相关 const count = await ctx.service.ledgerRevise.count({tid: ctx.tender.id}); const ledgerRevise = await ctx.service.ledgerRevise.getReviseList(ctx.tender.id); const addValid = await this._getAddReviseValid(ctx); const [stdBills, stdChapters] = await this.ctx.service.valuation.getValuationStdList(ctx.tender.data.valuation); const renderData = { tender: ctx.tender.data, tenderMenu: this.menu.tenderMenu, preUrl: '/tender/' + ctx.tender.id, pageInfo: { page: ctx.page, total: Math.ceil(count/app.config.pageSize), queryData: JSON.stringify(ctx.urlInfo.query), }, ledgerRevise, addValid, auditConst: audit.revise, stdBills, stdChapters, }; await this.layout('revise/index.ejs', renderData, 'revise/modal.ejs'); } catch (err) { this.log(err); ctx.redirect(ctx.request.header.referer); } } /** * 新增 修订 (Post) * @param ctx * @returns {Promise} */ async add(ctx) { try { const addValid = await this._getAddReviseValid(ctx); if (!addValid) { throw '无法新增修订'; } const revise = await ctx.service.ledgerRevise.add(ctx.tender.id, ctx.session.sessionUser.accountId); ctx.redirect('/tender/' + ctx.tender.id + '/revise/info'); } catch(err) { this.log(err); ctx.redirect(ctx.request.header.referer); } } /** * 作废 修订 (Post) * @param ctx * @returns {Promise} */ async cancel(ctx) { try { const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); if (revise.uid !== ctx.session.sessionUser.accountId) { throw '您无权作废该修订'; } if (revise.status === audit.revise.checking) { throw '修订审批中,不可作废'; } else if (revise.status === audit.revise.checked) { throw '修订已审批通过,不可作废'; } if (revise.valid) { const result = await ctx.service.ledgerRevise.cancelRevise(revise.id); } ctx.redirect('/tender/' + ctx.tender.id + '/revise/'); } catch(err) { this.log(err); ctx.redirect(ctx.request.header.referer); } } /** * 保存 修订详情 (Ajax-post) * @param ctx * @returns {Promise} */ async save(ctx) { try { const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); if (!revise.valid) { throw '该修订已作废'; } else if (revise.status === audit.revise.status.uncheck || revise.status === audit.revise.status.checkNo) { if (ctx.session.sessionUser.accountId !== revise.uid) { throw '您无权修改'; } } else if (revise.status === audit.revise.status.checking) { throw '修订在审批中,不可修改修订数据'; } else if (revise.staut === audit.revise.status.checked) { throw '修订已经审批通过,不可修改修订数据,请新增下一修订'; } const data = JSON.parse(ctx.request.body.data); if (data.content === undefined) { throw '保存数据有误' } const result = await ctx.service.ledgerRevise.defaultUpdate({id: revise.id, content: data.content}); if (result.affectedRows !== 1) { throw '保存数据失败,请重试'; } ctx.body = {err: 0, msg: '', data: null}; } catch(err) { this.log(err); ctx.body = this.ajaxErrorBody(err, '保存数据失败,请重试'); } } /** * 获取SpreadSetting * @private */ _getSpreadSetting(revise) { const _ = this.app._; function removeFieldCols(setting, cols) { _.remove(setting.cols, function(c) { return cols.indexOf(c.field) > -1; }); } const tender = this.ctx.tender; const setting = tender.info.display.ledger.clQty ? spreadConst.withCl : spreadConst.withoutCl; const ledger = JSON.parse(JSON.stringify(setting.ledger)); const pos = JSON.parse(JSON.stringify(setting.pos)); if (revise.status === audit.revise.status.checking || revise.status === audit.revise.status.checked) { ledger.readOnly = true; pos.readOnly = true; } if (tender.data.measure_type === measureType.tz.value) { removeFieldCols(ledger, spreadConst.filterCols.tzWithoutCols); } if (!tender.info.display.ledger.dgnQty) { removeFieldCols(ledger, spreadConst.filterCols.dgnCols); } return [ledger, pos]; } async _getDefaultReviseInfoData(ctx, revise) { const reviseBills = await ctx.service.reviseBills.getData(ctx.tender.id); const revisePos = await ctx.service.revisePos.getData(ctx.tender.id, revise.id); const [ledgerSpread, posSpread] = this._getSpreadSetting(revise); const [stdBills, stdChapters] = await this.ctx.service.valuation.getValuationStdList(ctx.tender.data.valuation); return { revise: revise, tender: ctx.tender.data, reviseBills, revisePos, ledgerSpread, posSpread, tenderMenu, measureType, preUrl: '/tender/' + ctx.tender.id, audit: audit.revise, jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.ledger.revise), stdBills, stdChapters, }; } /** * 历史修订页面(修订完成后,用于查看) * @param ctx * @param revise * @returns {Promise} * @private */ async _getHistoryReviseInfo(ctx, revise) { const renderData = await this._getDefaultReviseInfoData(ctx, revise); renderData.ledgerSpread.readOnly = true; renderData.posSpread.readOnly = true; renderData.readOnly = true; renderData.history = true; renderData.historyRevise = await ctx.service.ledgerRevise.getReviseList(ctx.tender.id); await this.layout('revise/info.ejs', renderData, 'revise/info_modal.ejs'); } /** * 修订页面(草稿,审批中) * @param ctx * @param revise * @returns {Promise} * @private */ async _getReviseInfo(ctx, revise) { const renderData = await this._getDefaultReviseInfoData(ctx, revise); const readOnly = (revise.status === audit.revise.status.checking || revise.status === audit.revise.status.checked || revise.uid !== ctx.session.sessionUser.accountId); if (readOnly) { renderData.ledgerSpread.readOnly = true; renderData.posSpread.readOnly = true; } renderData.readOnly = readOnly; if (!readOnly) { renderData.usedInfo = {}; const lastStage = await ctx.service.stage.getLastestStage(ctx.tender.id, true); if (lastStage.status === audit.stage.status.checked) { const usedPreBills = await ctx.service.stageBillsFinal.getUsedBills(ctx.tender.id, lastStage.order); for (const b of renderData.reviseBills) { b.used = usedPreBills.indexOf(b.id) >= 0; } const usedPrePos = await ctx.service.stagePosFinal.getUsedPos(ctx.tender.id, lastStage.order); for (const p of renderData.revisePos) { p.used = usedPrePos.indexOf(p.id) >= 0; } } else { const usedPreBills = lastStage.order > 1 ? await ctx.service.stageBillsFinal.getUsedBills(ctx.tender.id, lastStage.order - 1) : []; const usedCurBills = await ctx.service.stageBills.getStageUsedBills(ctx.tender.id, lastStage.id); for (const b of renderData.reviseBills) { b.used = usedPreBills.indexOf(b.id) >= 0 || usedCurBills.indexOf(b.id) >= 0; } const usedPrePos = lastStage.order > 1 ? await ctx.service.stagePosFinal.getUsedPos(ctx.tender.id, lastStage.order - 1) : []; const usedCurPos = await ctx.service.stageBills.getStageUsedPos(ctx.tender.id, lastStage.id); for (const p of renderData.revisePos) { p.used = usedPrePos.indexOf(b.id) >= 0 || usedCurPos.indexOf(p.id) >= 0; } } } renderData.history = false; renderData.historyRevise = []; await this.layout('revise/info.ejs', renderData, 'revise/info_modal.ejs'); } /** * 修订 详细页面(Get) * @param ctx * @returns {Promise} */ async info(ctx) { try { const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); if (revise.status === audit.revise.status.checked) { await this._getHistoryReviseInfo(ctx); } else { await this._getReviseInfo(ctx, revise); } } catch (err) { this.log(err); ctx.redirect(ctx.request.header.referer); } } async _checkRevise() { const revise = await this.ctx.service.ledgerRevise.getLastestRevise(this.ctx.tender.id); if (revise.uid !== this.ctx.session.sessionUser.accountId) { throw '修订数据错误'; } else if (revise.status === audit.revise.status.checking) { throw '修订审批中,不可修改'; } else if (revise.status === audit.revise.status.checked) { throw '修订已完成,如需修订台账,请新增修订'; } this.ctx.revise = revise; } /** * 增、删、上下移、升降级 * @param ctx * @returns {Promise} */ async _billsBase(ctx, type, data) { if (isNaN(data.id) || data.id <= 0) throw '数据错误'; if (type !== 'add') { if (isNaN(data.count) || data.count <= 0) data.count = 1; } switch (type) { case 'add': return await ctx.service.reviseBills.addReviseNode(ctx.tender.id, ctx.revise.id, data.id); case 'delete': return await ctx.service.reviseBills.delete(ctx.tender.id, data.id, data.count); case 'up-move': return await ctx.service.reviseBills.upMoveNode(ctx.tender.id, data.id, data.count); case 'down-move': return await ctx.service.reviseBills.downMoveNode(ctx.tender.id, data.id, data.count); case 'up-level': return await ctx.service.reviseBills.upLevelNode(ctx.tender.id, data.id, data.count); case 'down-level': return await ctx.service.reviseBills.downLevelNode(ctx.tender.id, data.id, data.count); } } /** * 批量插入数据 (Ajax) * * data = {id, batchData, batchType} * data.batchType = 'batchInsertChild'/'batchInsertNext' * data.batchData = [{name, children}] -- 项目节列表 * data.batchData.children = [{code, name, unit, unit_price, quantity}] -- 工程量清单列表 * * @param ctx * @return {Promise} */ async _batchInsert(ctx, data) { if ((isNaN(data.id) || data.id <= 0) || !data.batchType) { throw '参数错误'; } switch (data.batchType) { case 'child': return await ctx.service.reviseBills.batchInsertChild(ctx.tender.id, ctx.revise.id, data.id, data.batchData); case 'next': return await ctx.service.reviseBills.batchInsertNext(ctx.tender.id, ctx.revise.id, data.id, data.batchData); default: throw '参数错误'; } } async _pasteBlock(ctx, data) { if ((isNaN(data.id) || data.id <= 0) || (!data.tid && data.tid <= 0) || (!data.block || data.block.length <= 0)) throw '参数错误'; return await ctx.service.revise.pasteBlock(data.tid, data.id, data.block); } async _addStd(ctx, data) { if ((isNaN(data.id) || data.id <= 0) || !data.stdType || !data.stdNode) throw '参数错误'; // todo 校验项目是否使用该库的权限 let stdLib, addType; switch (data.stdType) { case 'xmj': stdLib = ctx.service.stdXmj; addType = stdDataAddType.withParent; break; case 'gcl': stdLib = ctx.service.stdGcl; const selectNode = await ctx.service.reviseBills.getDataByKid(ctx.tender.id, data.id); if (selectNode.b_code) { addType = stdDataAddType.next; } else { addType = stdDataAddType.child; } break; default: throw '未知标准库'; } const stdData = await stdLib.getDataByDataId(data.stdLibId, data.stdNode); switch (addType) { case stdDataAddType.child: return await ctx.service.reviseBills.addStdNodeAsChild(ctx.tender.id, data.id, stdData, ctx.revise.id); break; case stdDataAddType.next: return await ctx.service.reviseBills.addStdNode(ctx.tender.id, data.id, stdData, ctx.revise.id); case stdDataAddType.withParent: return await ctx.service.reviseBills.addStdNodeWithParent(ctx.tender.id, stdData, stdLib, ctx.revise.id); default: throw '未知添加方式'; } } async _addDeal(ctx, data) { if (!data.type || !data.dealBills) throw '数据错误'; if (data.type === 'child') { return await ctx.service.reviseBills.addChild(ctx.tender.id, data.id, data.dealBills, ctx.revise.id); } else if (data.type === 'next') { return await ctx.service.reviseBills.addBillsNode(ctx.tender.id, data.id, data.dealBills, ctx.revise.id); } else { throw '数据错误'; } } async _updatePos(ctx, data) { await this.checkMeasureType(measureType.tz.value); if (!data.posPostType) throw '数据错误'; switch (data.posPostType) { case 'add': return await ctx.service.revisePos.addPos(ctx.tender.id, ctx.revise.id, data.postData); case 'update': return await ctx.service.revisePos.updatePos(ctx.tender.id, data.postData); case 'delete': return await ctx.service.revisePos.deletePos(ctx.tender.id, data.postData); case 'paste': return await ctx.service.revisePos.pastePosData(ctx.tender.id, ctx.revise.id, data.postData); default: throw '未知操作'; } } async update(ctx) { try { if (!ctx.tender.data) throw '标段数据错误'; await this._checkRevise(); const data = JSON.parse(ctx.request.body.data); if (!data.postType || !data.postData) throw '数据错误'; const responseData = {err: 0, msg: '', data: {}}; console.log(data); switch (data.postType) { case 'add': case 'delete': case 'up-move': case 'down-move': case 'up-level': case 'down-level': responseData.data = await this._billsBase(ctx, data.postType, data.postData); break; case 'update': responseData.data = await this.ctx.service.reviseBills.updateCalc(ctx.tender.id, data.postData); break; case 'batch-insert': responseData.data = await this._batchInsert(ctx, data.postData); break; case 'add-deal': responseData.data = await this._addDeal(ctx, data.postData); break; case 'add-std': responseData.data = await this._addStd(ctx, data.postData); break; case 'paste-block': responseData.data = await this._pasteBlock(ctx, data.postData); break; case 'pos': responseData.data = await this._updatePos(ctx, data); break; default: throw '未知操作'; } ctx.body = responseData; } catch (err) { console.log(err); this.log(err); ctx.body = this.ajaxErrorBody(err, '数据错误'); } } } return ReviseController; };