'use strict'; /** * * * @author Mai * @date * @version */ const stdDataAddType = { withParent: 1, child: 2, next: 3, }; const audit = require('../const/audit'); const accountGroup = require('../const/account_group').group; const tenderMenu = require('../../config/menu').tenderMenu; const measureType = require('../const/tender').measureType; const spreadConst = require('../const/spread'); const shenpiConst = require('../const/shenpi'); const fs = require('fs'); const LzString = require('lz-string'); const stdConst = require('../const/standard'); module.exports = app => { class ReviseController extends app.BaseController { /** * 构造函数 * * @param {Object} ctx - egg全局变量 * @return {void} */ constructor(ctx) { super(ctx); } /** * 是否可以新增修订 * @param ctx * @return {Promise} * @private */ async _getAddReviseValid(ctx) { const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); const lastStage = await ctx.service.stage.getLastestStage(ctx.tender.id, true); const addVisible = (ctx.tender.data.user_id === ctx.session.sessionUser.accountId) && (ctx.tender.data.ledger_status === audit.ledger.status.checked) && (!revise || !revise.valid || revise.status === audit.revise.status.checked); const addValid = addVisible && (!lastStage || lastStage.status === audit.stage.status.uncheck || lastStage.status === audit.stage.status.checkNo || lastStage.status === audit.stage.status.checked); let changeValid = true; // 判断变更是否存在审批中,有则可能无法新增修订 const changeList = await ctx.service.change.getAllDataByCondition({ where: { tid: ctx.tender.id, status: [audit.flow.status.checking, audit.flow.status.backnew], }, }); if (changeList.length > 0) { // 判断是否已存在新增部位,有则可能无法新增修订 const changeLedgerList = await ctx.service.changeLedger.getAllDataByCondition({ where: { tender_id: ctx.tender.id, is_leaf: 1 } }); const changePosList = await ctx.service.changePos.getAllDataByCondition({ where: { tid: ctx.tender.id } }); // 判断变更是否已添加新增部位,有则可能无法新增修订 if (changeLedgerList.length > 0 || changePosList.length > 0) { // 判断审批中的变更令是否有调用了新增部位,有则无法新增修订,都没有则可新增修订 for (const c of changeList) { const caList = await ctx.service.changeAuditList.getList(c.cid); const gclIdList = ctx.helper._.uniq(ctx.helper._.map(caList, 'gcl_id')); for (const gcl of gclIdList) { if (gcl && (ctx.helper._.findIndex(changeLedgerList, { id: gcl }) !== -1 || ctx.helper._.findIndex(changePosList, { lid: gcl }) !== -1)) { changeValid = false; break; } } if (!changeValid) { break; } } } } return [addVisible, addValid, changeValid]; } /** * 台账修订页面 (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); if (ledgerRevise.length > 0) { const revise = ledgerRevise[0]; if (ctx.page === 1) { if (revise.status === audit.revise.status.checked || !revise.valid) { revise.lastest = true; } else { if (ledgerRevise.length > 1) ledgerRevise[1].lastest = true; // if (revise.status === audit.revise.status.checking) { // revise.curAuditor = await ctx.service.reviseAudit.getCurAuditor(revise.id, revise.times); // } } } } for (const lr of ledgerRevise) { if (lr.valid) { lr.curAuditor = await ctx.service.reviseAudit.getAuditorByStatus(lr.id, lr.status, lr.times); } } const [addVisible, addValid, changeValid] = await this._getAddReviseValid(ctx); const [stdBills, stdChapters] = await this.ctx.service.valuation.getValuationStdList( ctx.tender.data.valuation, ctx.tender.data.measure_type); 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, addVisible, addValid, changeValid, auditConst: audit.revise, auditConst2: JSON.stringify(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); } } /** * 修订审批流程(Get) * @param ctx * @return {Promise} */ async reviseAuditors(ctx) { try { const responseData = { err: 0, msg: '', data: {}, }; const rid = JSON.parse(ctx.request.body.data).id; const reviseInfo = await ctx.service.ledgerRevise.getDataById(rid); // 获取审批流程中右边列表 const auditHistory = []; const times = reviseInfo.status === audit.revise.status.checkNo ? reviseInfo.times - 1 : reviseInfo.times; if (times >= 1) { for (let i = 1; i <= times; i++) { auditHistory.push(await ctx.service.reviseAudit.getAuditors2ReviseList(reviseInfo.id, i)); } } responseData.data.user = await ctx.service.projectAccount.getAccountInfoById(reviseInfo.uid); responseData.data.auditHistory = auditHistory; // 获取审批流程中左边列表 responseData.data.auditors = await ctx.service.reviseAudit.getAuditorsWithOwner(reviseInfo.id, times); // 获取原报信息 // const reviseAuditor = await ctx.service.projectAccount.getAccountInfoById(reviseInfo.uid); // responseData.data.reviseAuditor = reviseAuditor; ctx.body = responseData; } catch (error) { this.log(error); ctx.body = { err: 1, msg: error.toString(), data: null }; } } /** * 新增 修订 (Post) * @param ctx * @return {Promise} */ async add(ctx) { try { const [addValid, changeValid] = await this._getAddReviseValid(ctx); if (!addValid) { throw '无法新增修订'; } if (!changeValid) { throw '台账修订会影响审批中的变更令(包含新增部位),请审批完成后再创建台账修订'; } const revise = await ctx.service.ledgerRevise.add(ctx.tender.id, ctx.session.sessionUser.accountId); ctx.redirect(`/tender/${ctx.tender.id}/revise/${revise.id}/info`); } catch (err) { this.log(err); ctx.redirect(ctx.request.header.referer); } } /** * 作废 修订 (Post) * @param ctx * @return {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); } ctx.redirect('/tender/' + ctx.tender.id + '/revise/'); } catch (err) { this.log(err); ctx.redirect(ctx.request.header.referer); } } /** * 保存 修订详情 (Ajax-post) * @param ctx * @return {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.data.measure_type === measureType.tz.value ? (tender.info.display.ledger.clQty ? spreadConst.withCl : spreadConst.withoutCl) : (tender.info.display.ledger.clQty ? spreadConst.withClGcl : spreadConst.withoutClGcl); const ledger = JSON.parse(JSON.stringify(setting.ledger)); const pos = setting.pos ? JSON.parse(JSON.stringify(setting.pos)) : spreadConst.blank; 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 [ledgerSpread, posSpread] = this._getSpreadSetting(revise); const sjsRela = await this.ctx.service.project.getSjsRela(ctx.session.sessionProject.id); this.ctx.helper.refreshSpreadShow(sjsRela.ledgerCol, [ledgerSpread, posSpread]); const [stdBills, stdChapters] = await this.ctx.service.valuation.getValuationStdList( ctx.tender.data.valuation, ctx.tender.data.measure_type); const curAuditor = await ctx.service.reviseAudit.getCurAuditor(revise.id, revise.times); const user = await ctx.service.projectAccount.getAccountInfoById(revise.uid); const times = revise.status === audit.revise.status.checkNo ? revise.times - 1 : revise.times; const auditors = revise.status === audit.revise.status.checkNo && revise.uid === ctx.session.sessionUser.accountId ? await ctx.service.reviseAudit.getAuditorsWithOwner(revise.id, revise.times) : await ctx.service.reviseAudit.getAuditorsWithOwner(revise.id, times); const auditHistory = []; if (times >= 1) { for (let i = 1; i <= times; i++) { auditHistory.push(await ctx.service.reviseAudit.getAuditors(revise.id, i)); } } return { revise, tender: ctx.tender.data, ledgerSpread, posSpread, tenderMenu, measureType, audit: audit.revise, jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.revise.info), stdBills, auditConst: audit.revise, stdChapters, curAuditor, auditors, user, auditHistory, shenpiConst, }; } /** * 历史修订页面(修订完成后,用于查看) * @param ctx * @param revise * @return {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.getAllReviseList(ctx.tender.id); renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id); renderData.preUrl = ctx.url.replace('/info', ''); await this.layout('revise/info.ejs', renderData, 'revise/info_modal.ejs'); } /** * 修订页面(草稿,审批中) * @param ctx * @param revise * @return {Promise} * @private */ async _getAuditReviseInfo(ctx, revise) { const renderData = await this._getDefaultReviseInfoData(ctx, revise); renderData.readOnly = true; renderData.ledgerSpread.readOnly = true; renderData.posSpread.readOnly = true; renderData.history = false; renderData.historyRevise = []; renderData.curAuditor = await ctx.service.reviseAudit.getCurAuditor(revise.id, revise.times); renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id); renderData.preUrl = ctx.url.replace('/info', ''); await this.layout('revise/info.ejs', renderData, 'revise/info_modal.ejs'); } async _getDraftReviseInfo(ctx, revise) { const renderData = await this._getDefaultReviseInfoData(ctx, revise); // 台账只读、使用数据 renderData.readOnly = false; // 修订历史 renderData.history = false; renderData.historyRevise = []; // 添加审批人相关 // renderData.accountGroup = accountGroup; renderData.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'], }); renderData.accountGroup = accountGroup.map((item, idx) => { const groupList = renderData.accountList.filter(item => item.account_group === idx); return { groupName: item, groupList }; }); renderData.auditorList = await ctx.service.reviseAudit.getAuditors(revise.id, revise.times); renderData.curAuditor = await ctx.service.reviseAudit.getCurAuditor(revise.id, revise.times); renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id); renderData.preUrl = ctx.url.replace('/info', ''); await this.layout('revise/info.ejs', renderData, 'revise/info_modal.ejs'); } /** * 修订 详细页面(Get) * @param ctx * @return {Promise} */ async info(ctx) { try { const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); if (!revise) throw '台账修订数据有误'; if (revise.uid === ctx.session.sessionUser.accountId && (revise.status === audit.revise.status.uncheck || revise.status === audit.revise.status.checkNo)) { await this._getDraftReviseInfo(ctx, revise); } else if (revise.status === audit.revise.status.checked) { await this._getHistoryReviseInfo(ctx, revise); } else { await this._getAuditReviseInfo(ctx, revise); } } catch (err) { this.log(err); ctx.redirect(ctx.request.header.referer); } } async loadInfoData(ctx) { try { const revise = await ctx.revise; const reviseBills = revise.readOnly ? await ctx.helper.loadLedgerDataFromOss(revise.curHis.bills_file) : await ctx.service.reviseBills.getData(ctx.tender.id); const revisePos = revise.readOnly ? await ctx.helper.loadLedgerDataFromOss(revise.curHis.pos_file) : await ctx.service.revisePos.getData(ctx.tender.id); if (revise.uid === ctx.session.sessionUser.accountId && (revise.status === audit.revise.status.uncheck || revise.status === audit.revise.status.checkNo)) { const lastStage = await ctx.service.stage.getLastestStage(ctx.tender.id, true); if (lastStage) { if (lastStage.status === audit.stage.status.checked) { const usedPreBills = await ctx.service.stageBillsFinal.getUsedBills(ctx.tender.id, lastStage.order); for (const b of reviseBills) { b.used = usedPreBills.indexOf(b.id) >= 0; } const usedPrePos = await ctx.service.stagePosFinal.getUsedPos(ctx.tender.id, lastStage.order); for (const p of 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 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.stagePos.getStageUsedPos(ctx.tender.id, lastStage.id); for (const p of revisePos) { p.used = usedPrePos.indexOf(p.id) >= 0 || usedCurPos.indexOf(p.id) >= 0; } } } } const ledgerTags = await this.ctx.service.ledgerTag.getDatas(ctx.tender.id); ctx.body = { err: 0, msg: '', data: { bills: reviseBills, pos: revisePos, tags: ledgerTags } }; } catch (err) { ctx.helper.log(err); this.ajaxErrorBody(err, '加载台账修订数据错误'); } } async checkData(ctx) { try { const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); if (!revise) throw '台账修订数据有误'; const reviseBills = await ctx.service.reviseBills.getData(ctx.tender.id); const revisePos = await ctx.service.revisePos.getData(ctx.tender.id); const checkDataModel = require('../lib/ledger').checkData; const reviseCheck = new checkDataModel(ctx, measureType); reviseCheck.loadData(reviseBills, revisePos); ctx.tender.info.ledger_check.same_code && reviseCheck.checkSameCode(); ctx.tender.info.ledger_check.sibling && reviseCheck.checkSibling(); if (ctx.tender.data.measure_type === measureType.tz.value) reviseCheck.checkBillsQty(['sgfh_qty', 'qtcl_qty', 'sjcl_qty', 'quantity']); reviseCheck.checkBillsTp([ {qty: 'sgfh_qty', tp: 'sgfh_tp'}, {qty: 'qtcl_qty', tp: 'qtcl_tp'}, {qty: 'sjcl_qty', tp: 'sjcl_tp'}, {qty: 'quantity', tp: 'total_price'} ], this.ctx.tender.info.decimal); ctx.body = { err: 0, msg: '', data: reviseCheck.checkResult }; } catch (err) { this.log(err); ctx.body = this.ajaxErrorBody(err, '检查数据错误'); } } async history(ctx) { try { const revise = ctx.revise; const [ledgerSpread, posSpread] = this._getSpreadSetting(revise); const sjsRela = await this.ctx.service.project.getSjsRela(ctx.session.sessionProject.id); this.ctx.helper.refreshSpreadShow(sjsRela.ledgerCol, [ledgerSpread, posSpread]); ledgerSpread.readOnly = true; posSpread.readOnly = true; const historyRevise = await ctx.service.ledgerRevise.getAllReviseList(ctx.tender.id); // 获取审批流程中右边列表 const auditHistory = []; const times = revise.status === audit.revise.status.checkNo ? revise.times - 1 : revise.times; if (times >= 1) { for (let i = 1; i <= times; i++) { auditHistory.push(await ctx.service.reviseAudit.getAuditors2ReviseList(revise.id, i)); } } const user = await ctx.service.projectAccount.getAccountInfoById(revise.uid); // 获取审批流程中左边列表 const auditors = await ctx.service.reviseAudit.getAuditorsWithOwner(revise.id, times); const renderData = { preUrl: ctx.url.replace('/info', ''), measureType, audit, revise, ledgerSpread, posSpread, readOnly: true, historyRevise, auditHistory, auditors, auditConst: audit.revise, user, jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.revise.history), }; await this.layout('revise/history.ejs', renderData, 'revise/history_modal.ejs'); } catch (err) { this.log(err); ctx.redirect(ctx.request.header.referer); } } async checkRevise(ctx) { const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); if (revise.uid !== ctx.session.sessionUser.accountId) { throw '修订数据错误'; } else if (revise.status === audit.revise.status.checking) { throw '修订审批中,不可修改'; } else if (revise.status === audit.revise.status.checked) { throw '修订已完成,如需修订台账,请新增修订'; } return revise; } async _billsBase(revise, 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 this.ctx.service.reviseBills.addReviseNode(revise.tid, revise.id, data.id, data.count); case 'delete': return await this.ctx.service.reviseBills.delete(revise.tid, data.id, data.count); case 'up-move': return await this.ctx.service.reviseBills.upMoveNode(revise.tid, data.id, data.count); case 'down-move': return await this.ctx.service.reviseBills.downMoveNode(revise.tid, data.id, data.count); case 'up-level': return await this.ctx.service.reviseBills.upLevelNode(revise.tid, data.id, data.count); case 'down-level': return await this.ctx.service.reviseBills.downLevelNode(revise.tid, data.id, data.count); } } async _batchInsert(revise, data) { if ((isNaN(data.id) || data.id <= 0) || !data.batchType) { throw '参数错误'; } switch (data.batchType) { case 'child': return await this.ctx.service.reviseBills.batchInsertChild(revise.tid, revise.id, data.id, data.batchData); case 'next': return await this.ctx.service.reviseBills.batchInsertNext(revise.tid, revise.id, data.id, data.batchData); default: throw '参数错误'; } } async _pasteBlock(revise, data) { if ((isNaN(data.id) || data.id <= 0) || (!data.tid && data.tid <= 0) || (!data.block || data.block.length <= 0)) throw '参数错误'; return await this.ctx.service.reviseBills.pasteBlockData(this.ctx.tender.id, data.id, data.block, { crid: revise.id }); } async _addStd(revise, data) { if ((isNaN(data.id) || data.id <= 0) || !data.stdType || !data.stdNode) throw '参数错误'; // todo 校验项目是否使用该库的权限 let stdLib, addType; switch (data.stdType) { case 'xmj': stdLib = this.ctx.service.stdXmj; addType = stdDataAddType.withParent; break; case 'gcl': stdLib = this.ctx.service.stdGcl; const selectNode = await this.ctx.service.reviseBills.getDataByKid(revise.tid, 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 this.ctx.service.reviseBills.addStdNodeAsChild(revise.tid, data.id, stdData, revise.id); break; case stdDataAddType.next: return await this.ctx.service.reviseBills.addStdNode(revise.tid, data.id, stdData, revise.id); case stdDataAddType.withParent: return await this.ctx.service.reviseBills.addStdNodeWithParent(revise.tid, stdData, stdLib, revise.id); default: throw '未知添加方式'; } } async _addDeal(revise, data) { if (!data.type || !data.dealBills) throw '数据错误'; data.dealBills.unit_price = this.ctx.helper.round(data.dealBills.unit_price, this.ctx.tender.info.decimal.up); if (data.type === 'child') { return await this.ctx.service.reviseBills.addChild(revise.tid, data.id, data.dealBills, revise.id); } else if (data.type === 'next') { return await this.ctx.service.reviseBills.addBillsNode(revise.tid, data.id, data.dealBills, revise.id); } throw '数据错误'; } async _addBg(revise, data) { if (!data.type || !data.bgBills) throw '数据错误'; data.bgBills.unit_price = this.ctx.helper.round(data.bgBills.unit_price, this.ctx.tender.info.decimal.up); if (data.type === 'child') { return await this.ctx.service.reviseBills.addChild(revise.tid, data.id, data.bgBills, revise.id); } else if (data.type === 'next') { return await this.ctx.service.reviseBills.addBillsNode(revise.tid, data.id, data.bgBills, revise.id); } throw '数据错误'; } async _updatePos(revise, data) { await this.checkMeasureType(measureType.tz.value); if (!data.posPostType) throw '数据错误'; switch (data.posPostType) { case 'add': return await this.ctx.service.revisePos.addPos(revise.tid, revise.id, data.postData); case 'update': if (data.postData instanceof Array) { return await this.ctx.service.revisePos.updatePosArr(revise.tid, data.postData); } return await this.ctx.service.revisePos.updatePos(revise.tid, data.postData); case 'delete': return await this.ctx.service.revisePos.deletePos(revise.tid, data.postData); case 'paste': return await this.ctx.service.revisePos.pastePosData(revise.tid, revise.id, data.postData); default: throw '未知操作'; } } async update(ctx) { try { if (!ctx.tender.data) throw '标段数据错误'; const data = JSON.parse(ctx.request.body.data); if (!data.postType || !data.postData) throw '数据错误'; const responseData = { err: 0, msg: '', data: {} }; const revise = await this.checkRevise(ctx); switch (data.postType) { case 'add': case 'delete': case 'up-move': case 'down-move': case 'up-level': case 'down-level': responseData.data = await this._billsBase(revise, data.postType, data.postData); break; case 'update': ctx.helper.checkDgnQtyPrecision(data.postData); responseData.data = await this.ctx.service.reviseBills.updateCalc(revise.tid, data.postData); break; case 'batch-insert': responseData.data = await this._batchInsert(revise, data.postData); break; case 'add-deal': responseData.data = await this._addDeal(revise, data.postData); break; case 'add-bg': responseData.data = await this._addDeal(revise, data.postData); break; case 'add-std': responseData.data = await this._addStd(revise, data.postData); break; case 'paste-block': responseData.data = await this._pasteBlock(revise, data.postData); break; case 'pos': responseData.data = await this._updatePos(revise, data); break; default: throw '未知操作'; } ctx.body = responseData; } catch (err) { this.log(err); ctx.body = this.ajaxErrorBody(err, '数据错误'); } } /** * 上传 清单Excel 并导入 * @param ctx * @return {Promise} */ async uploadExcel(ctx) { try { const revise = await this.checkRevise(ctx); const ueType = ctx.params.ueType; const compressData = ctx.request.body.data; const data = JSON.parse(LzString.decompressFromUTF16(compressData)); const responseData = { err: 0, msg: '', data: {} }; switch (ueType) { case 'gcl2xmj': responseData.data = await ctx.service.reviseBills.importGclExcel(data.id, data.sheet, { crid: revise.id }); break; } ctx.body = responseData; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString(), data: null }; } } /** * 填设计量(Ajax) * * @param ctx * @return {Promise} */ async deal2sgfh(ctx) { try { if (this.ctx.tender.measure_type === measureType.tz.value) throw '该功能仅工程量清单模式可用'; await this.ctx.service.reviseBills.deal2sgfh(ctx.tender.id); const ledgerData = await ctx.service.reviseBills.getData(ctx.tender.id); ctx.body = { err: 0, msg: '', data: { bills: ledgerData } }; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString(), data: null }; } } /** * 新增审批人(Ajax) * * @param ctx * @return {Promise} */ async addAuditor(ctx) { try { const data = JSON.parse(ctx.request.body.data); const id = data.auditorId; if (isNaN(id) || id <= 0) { throw '参数错误'; } const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); if (!revise) throw '台账修订数据有误'; // 检查权限等 if (revise.uid !== ctx.session.sessionUser.accountId) throw '您无权添加审核人'; if (revise.status === audit.revise.status.checking || revise.status === audit.revise.status.checked) { throw '当前不允许添加审核人'; } // 检查审核人是否已存在 const exist = await ctx.service.reviseAudit.getAuditor(revise.id, id, revise.times); if (exist) throw '该审核人已存在,请勿重复添加'; const shenpiInfo = await ctx.service.shenpiAudit.getDataByCondition({ tid: ctx.tender.id, sp_type: shenpiConst.sp_type.revise, sp_status: shenpiConst.sp_status.gdzs }); const is_gdzs = shenpiInfo && ctx.tender.info.shenpi.revise === shenpiConst.sp_status.gdzs ? 1 : 0; const result = await ctx.service.reviseAudit.addAuditor(revise, id, is_gdzs); if (!result) throw '添加审核人失败'; const resultData = await ctx.service.reviseAudit.getAuditorsWithOwner(revise.id, revise.times); ctx.body = { err: 0, msg: '', data: resultData }; } catch (err) { this.log(err, '数据错误'); ctx.body = this.ajaxErrorBody(err); } } /** * 移除审批人(Ajax) * * @param ctx * @return {Promise} */ async removeAuditor(ctx) { try { const data = JSON.parse(ctx.request.body.data); const id = data.auditorId instanceof Number ? data.auditorId : this.app._.toNumber(data.auditorId); if (isNaN(id) || id <= 0) { throw '参数错误'; } const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); if (!revise) throw '台账修订数据有误'; const result = await ctx.service.reviseAudit.deleteAuditor(revise, id); if (!result) { throw '移除审核人失败'; } const resultData = await ctx.service.reviseAudit.getAuditors(revise.id, revise.times); ctx.body = { err: 0, msg: '', data: resultData }; } catch (err) { this.log(err, '数据错误'); ctx.body = this.ajaxErrorBody(err); } } /** * 上报(ajax-post) * * @param ctx * @return {Promise} */ async start(ctx) { try { const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); if (!revise || revise.status === audit.revise.status.checking || revise.status === audit.revise.status.checked) { throw '台账修订数据有误'; } if (revise.content === '') { throw '未填写修订内容,请先填写并保存修订内容'; } if (revise.uid !== ctx.session.sessionUser.accountId) throw '上报失败'; await ctx.service.reviseAudit.start(revise, revise.times); ctx.body = { err: 0, msg: '', data: {} }; } catch (err) { this.log(err); ctx.session.postError = err.toString(); ctx.body = this.ajaxErrorBody(err, '上报失败'); } } /** * 审批(post) * * @param ctx * @return {Promise} */ async check(ctx) { try { const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); if (!revise || revise.status !== audit.revise.status.checking) throw '台账修订数据有误'; const curAudit = await ctx.service.reviseAudit.getCurAuditor(revise.id, revise.times); if (curAudit.audit_id !== ctx.session.sessionUser.accountId) throw '审批失败'; const checkType = parseInt(ctx.request.body.checkType); if (!checkType || isNaN(checkType)) throw '提交数据错误'; await ctx.service.reviseAudit.check(revise, checkType, ctx.request.body.opinion, revise.times); ctx.redirect(ctx.request.headers.referer); } catch (err) { this.log(err); this.postError(err, '审批失败'); ctx.redirect(ctx.request.headers.referer); } } async _getLastStage(ctx) { const stages = await ctx.service.stage.getAllDataByCondition({ where: {tid: ctx.tender.id}, orders: [['order', 'desc']], }); if (stages.length > 0) { if (stages[0].status !== audit.stage.status.uncheck || stages[0].user_id === ctx.session.sessionUser.accountId) { return stages[0] } else if (stages.length > 1) { return stages[1]; } } return null; } async compare(ctx) { const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); if (!revise) throw '台账修订数据有误'; const lastStage = await this._getLastStage(ctx); const renderData = { preUrl: ctx.url.replace('/compare', ''), revise, measureType, lastStage, audit, jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.revise.compare), }; await this.layout('revise/compare.ejs', renderData, 'revise/compare_modal.ejs'); } _loadPreData(curData, preData, field, prefix, relaId, extraFields = []) { if (preData.length === 0) return; for (const pd of preData) { const cd = curData.find(x => {return x[relaId] === pd[relaId]}); if (cd) { for (const f of field) { cd[prefix + f] = pd[f]; } } else { const ncd = {id: pd.id}; ncd[relaId] = pd[relaId]; for (const ef of extraFields) { ncd[ef] = pd[ef]; } for (const f of field) { ncd[prefix + f] = pd[f]; } curData.push(ncd); } } } async _loadLastStageBillsData(ctx) { let curStageData; if (ctx.lastStage.readOnly) { curStageData = await ctx.service.stageBills.getAuditorStageData2(ctx.tender.id, ctx.lastStage.id, ctx.lastStage.curTimes, ctx.lastStage.curOrder); } else { curStageData = await ctx.service.stageBills.getLastestStageData2(ctx.tender.id, ctx.lastStage.id); } const preStageData = ctx.lastStage.order > 1 ? await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, ctx.lastStage.order - 1) : []; this._loadPreData(curStageData, preStageData, ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], 'pre_', 'lid'); return curStageData; } async _loadLastStagePosData(ctx) { let curStageData; if (ctx.lastStage.readOnly) { curStageData = await ctx.service.stagePos.getAuditorStageData2(ctx.tender.id, ctx.lastStage.id, ctx.lastStage.curTimes, ctx.lastStage.curOrder); } else { curStageData = await ctx.service.stagePos.getLastestStageData2(ctx.tender.id, ctx.lastStage.id); } const preStageData = ctx.lastStage.order > 1 ? await ctx.service.stagePosFinal.getFinalData(ctx.tender.data, ctx.lastStage.order - 1) : []; this._loadPreData(curStageData, preStageData, ['contract_qty', 'qc_qty'], 'pre_', 'pid', ['lid']); return curStageData; } async _loadDataByFilter(ctx, filter) { switch(filter) { case 'bills': return ctx.revise.preHis ? await this.ctx.helper.loadLedgerDataFromOss(ctx.revise.preHis.bills_file) : []; case 'pos': if (ctx.tender.data.measure_type === measureType.gcl.value) return []; return ctx.revise.preHis ? await this.ctx.helper.loadLedgerDataFromOss(ctx.revise.preHis.pos_file) : []; case 'reviseBills': return ctx.revise.readOnly && ctx.revise.curHis ? await this.ctx.helper.loadLedgerDataFromOss(ctx.revise.curHis.bills_file) : await ctx.service.reviseBills.getAllDataByCondition({ where: { tender_id: ctx.tender.id } }); case 'revisePos': if (ctx.tender.data.measure_type === measureType.gcl.value) return []; return ctx.revise.readOnly && ctx.revise.curHis ? await this.ctx.helper.loadLedgerDataFromOss(ctx.revise.curHis.pos_file) : await ctx.service.revisePos.getAllDataByCondition({ where: { tid: ctx.tender.id } }); case 'stageBills': case 'stagePos': if (!ctx.lastStage) ctx.lastStage = await this._getLastStage(ctx); await this.ctx.service.stage.doCheckStage(ctx.lastStage); if (filter === 'stageBills') { return await this._loadLastStageBillsData(ctx); } else { return await this._loadLastStagePosData(ctx); } case 'dealBills': return await ctx.service.dealBills.getAllDataByCondition({where: {tender_id: ctx.tender.id}}); case 'spec': const spec = {zlj: stdConst.zlj, jrg: stdConst.jrg}; spec.zlj.deal_bills_tp = ctx.tender.info.deal_param.zanLiePrice; return spec; case 'tags': return await this.ctx.service.ledgerTag.getDatas(ctx.tender.id); } } async loadData(ctx) { try { const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); if (!revise) throw '台账修订数据有误'; const data = JSON.parse(ctx.request.body.data); const filter = data.filter ? data.filter.split(';') : []; const responseData = { err: 0, msg: '', data: {} }; for (const f of filter) { if (!f) continue; responseData.data[f] = await this._loadDataByFilter(ctx, f); } ctx.body = responseData; } catch (err) { this.ctx.helper.log(err); this.ajaxErrorBody(err, '加载数据错误,请刷新页面重试'); } } async gclCompare(ctx) { const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); if (!revise) throw '台账修订数据有误'; const renderData = { measureType, preUrl: ctx.url.replace('/gcl-compare', ''), revise, jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.revise.gclCompare), }; await this.layout('revise/gcl_compare.ejs', renderData); } } return ReviseController; };