'use strict'; /** * * * @author Mai * @date 2018/8/14 * @version */ const moment = require('moment'); const sendToWormhole = require('stream-wormhole'); const fs = require('fs'); const path = require('path'); const audit = require('../const/audit'); const codeRuleConst = require('../const/code_rule'); const changeConst = require('../const/change'); const accountGroup = require('../const/account_group').group; const shenpiConst = require('../const/shenpi'); // const tenderMenu = require('../../config/menu').tenderMenu; module.exports = app => { class ChangeController extends app.BaseController { /** * 构造函数 * * @param {Object} ctx - egg全局变量 * @return {void} */ constructor(ctx) { super(ctx); ctx.showProject = true; ctx.showTender = true; ctx.showTitle = true; } async _filterChanges(ctx, status = 0) { const tenderId = ctx.params.id; ctx.session.sessionUser.tenderId = tenderId; const tender = await this.service.tender.getDataById(tenderId); // const tenderList = await this.service.tender.getList(); const page = ctx.page; const changes = await ctx.service.change.getListByStatus(tender.id, status); const total = await ctx.service.change.getCountByStatus(tender.id, status); if (changes !== null) { let i = 0; for (const c of changes) { const status = c.status === audit.flow.status.uncheck ? 0 : 1; // 根据审批人对当前变更令的状态取不同的展示方式。 let changeAudit = ''; let auditStatus = 0; switch (c.status) { case 1: auditStatus = 1; break; case 2: changeAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times, status); auditStatus = changeAudit.uid === ctx.session.sessionUser.accountId ? 1 : 0; break; case 3: case 4: auditStatus = 0; changeAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times, status); break; case 5: changeAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times - 1, status); auditStatus = c.uid === ctx.session.sessionUser.accountId ? 1 : 0; break; case 6: changeAudit = await ctx.service.changeAudit.getLastBackUser(c.cid, c.times); const checkingAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times, status); auditStatus = checkingAudit.uid === ctx.session.sessionUser.accountId ? 1 : 0; break; default: break; } changes[i].changeAudit = changeAudit; changes[i].auditStatus = auditStatus; i++; } } // 分页相关 const pageInfo = { page, total: Math.ceil(total / app.config.pageSize), queryData: JSON.stringify(ctx.urlInfo.query), }; const filter = JSON.parse(JSON.stringify(audit.filter)); filter.count = []; filter.count[filter.status.pending] = await ctx.service.change.getCountByStatus(tender.id, filter.status.pending);// await ctx.service.change.pendingDatas(tender.id, ctx.session.sessionUser.accountId); filter.count[filter.status.uncheck] = await ctx.service.change.getCountByStatus(tender.id, filter.status.uncheck);// await ctx.service.change.checkingDatas(tender.id, ctx.session.sessionUser.accountId); filter.count[filter.status.checking] = await ctx.service.change.getCountByStatus(tender.id, filter.status.checking);// await ctx.service.change.checkedDatas(tender.id, ctx.session.sessionUser.accountId); filter.count[filter.status.checked] = await ctx.service.change.getCountByStatus(tender.id, filter.status.checked);// await ctx.service.change.pendingDatas(tender.id, ctx.session.sessionUser.accountId); filter.count[filter.status.checkNo] = await ctx.service.change.getCountByStatus(tender.id, filter.status.checkNo);// await ctx.service.change.pendingDatas(tender.id, ctx.session.sessionUser.accountId); const codeRule = tender.c_rule ? JSON.parse(tender.c_rule) : []; for (const rule of codeRule) { switch (rule.rule_type) { case codeRuleConst.measure.ruleType.dealCode: rule.preview = ctx.tender.info.deal_info.dealCode; break; case codeRuleConst.measure.ruleType.tenderName: rule.preview = tender.name; break; case codeRuleConst.measure.ruleType.inDate: rule.preview = moment().format('YYYY'); break; case codeRuleConst.measure.ruleType.text: rule.preview = rule.text; break; case codeRuleConst.measure.ruleType.addNo: const s = '0000000000'; rule.preview = s.substr(s.length - rule.format); break; default: break; } } const renderData = { uid: ctx.session.sessionUser.accountId, moment, tender, // tenderList, pageInfo, changes, filter, status, codeRule, dealCode: ctx.tender.info.deal_info.dealCode, auditConst: audit.flow, changeConst, ruleType: codeRuleConst.ruleType.change, ruleConst: codeRuleConst.measure, tenderMenu: this.menu.tenderMenu, preUrl: '/tender/' + tenderId, tpUnit: ctx.tender.info.decimal.tp, }; await this.layout('change/index.ejs', renderData, 'change/modal.ejs'); } /** * 变更管理 页面 (Get) * * @param {Object} ctx - egg全局变量 * @return {void} */ async index(ctx) { try { await this._filterChanges(ctx); } catch (err) { this.log(err); ctx.redirect('/dashboard'); } } /** * * @param {Object} ctx - egg全局变量 * @return {void} */ async newCode(ctx) { const responseData = { err: 0, msg: '', data: '', }; try { const tenderId = ctx.params.id; if (!tenderId) { throw '当前未打开标段'; } const tenderData = await ctx.service.tender.getDataById(tenderId); const cCodeRule = tenderData.c_rule !== null ? JSON.parse(tenderData.c_rule) : []; const code = []; for (const rule of cCodeRule) { switch (rule.rule_type) { case codeRuleConst.measure.ruleType.dealCode: code.push(ctx.tender.info.deal_info.dealCode); break; case codeRuleConst.measure.ruleType.tenderName: code.push(tenderData.name); break; case codeRuleConst.measure.ruleType.text: code.push(rule.text); break; case codeRuleConst.measure.ruleType.inDate: code.push(moment().format('YYYY')); break; case codeRuleConst.measure.ruleType.addNo: let s = '0000000000'; const count = rule.start + await ctx.service.change.count({ tid: tenderId }); s = s + count; code.push(s.substr(s.length - rule.format)); break; default: break; } } responseData.data = code.join(tenderData.c_connector !== null && tenderData.c_connector !== 3 ? codeRuleConst.measure.connectorString[tenderData.c_connector] : ''); } catch (err) { responseData.err = 1; responseData.msg = err; } ctx.body = responseData; } /** * 新增变更 (Post) * * @param {Object} ctx - egg全局变量 * @return {void} */ async add(ctx) { try { const tenderId = ctx.params.id; if (!tenderId) { throw '当前未打开标段'; } const data = JSON.parse(ctx.request.body.data); if (!data.code || data.code === '' || !data.name || data.name === '') { throw '变更令号不能为空'; } const change = await ctx.service.change.add(tenderId, ctx.session.sessionUser.accountId, data.code, data.name); ctx.body = { err: 0, msg: '', data: change }; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString() }; } } /** * 变更管理 状态筛选 页面 (Get) * @param {Object} ctx - egg全局变量 * @return {void} */ async status(ctx) { try { const status = parseInt(ctx.params.status); await this._filterChanges(ctx, status); } catch (err) { this.logger.error(err); ctx.redirect('/tender/' + ctx.params.id + '/change'); } } /** * 变更信息 页面 (Get) * * @param {Object} ctx - egg全局变量 * @return {void} */ async info(ctx) { try { const whiteList = this.ctx.app.config.multipart.whitelist; const tenderid = ctx.params.id !== undefined ? ctx.params.id : ctx.session.sessionUser.tenderId; ctx.session.sessionUser.tenderId = tenderid; const tender = await ctx.service.tender.getDataById(tenderid); const change = await ctx.service.change.getDataByCondition({ cid: ctx.params.cid }); // 后台判断当前人查看info状态 const auditStatus = await ctx.service.changeAudit.getStatusByChange(change); // 获取附件列表 const attList = await ctx.service.changeAtt.getChangeAttachment(ctx.params.cid); // 获取其他变更令数据 const othersChange = await ctx.service.change.getOthersChange(ctx.params.id, ctx.params.cid); // 根据auditStatus获取审批人列表 const auditList = await ctx.service.changeAudit.getListByStatus(change, auditStatus); // 获取已选清单 let changeList = await ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: ctx.params.cid } }); // 获取用户人验证手机号 const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId); const auth_mobile = pa.auth_mobile; const renderData = { uid: ctx.session.sessionUser.accountId, tender, change, othersChange, changeConst, auditStatus, auditConst: audit.flow, ledgerConsts: audit.ledger.status, attList, whiteList, auditList, changeList, tpUnit: ctx.tender.info.decimal.tp, upUnit: ctx.tender.info.decimal.up, authMobile: auth_mobile, shenpiConst, }; // 根据auditStatus状态获取的不同的数据 if (auditStatus === 1 || auditStatus === 2) { renderData.changeUnits = changeConst.units; renderData.precision = ctx.tender.info.precision; // renderData.accountGroup = accountGroup; // 获取所有项目参与者 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'], }); renderData.accountList = accountList; renderData.accountGroup = accountGroup.map((item, idx) => { const groupList = accountList.filter(item => item.account_group === idx); return { groupName: item, groupList }; }); // 重新上报获取审批流程 if (auditStatus === 2) { const auditList2 = await ctx.service.changeAudit.getListByBack(change.cid, change.times); // 展示页右侧审批流程列表 const auditList3 = []; for (let time = 1; time <= change.times - 1; time++) { const auditTimeList = []; let max_sort = 1; for (const al of auditList2) { if (al.times === time) { auditTimeList.push(al); if (al.usite > max_sort) { max_sort = al.usite; } } } for (const i in auditTimeList) { auditTimeList[i].max_sort = max_sort; } auditList3.push(auditTimeList); } renderData.auditList3 = auditList3; } // 根据清单获取提交数据和计算总金额 const changeListData = []; const changeWhiteListData = []; let ototalCost = 0; let ctotalCost = 0; for (const cl of changeList) { const cLArray = [ cl.code, cl.name, cl.bwmx, cl.unit, cl.unit_price, cl.oamount, cl.camount, cl.detail, cl.lid, cl.xmj_code, cl.xmj_jldy, cl.gcl_id, ]; ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, ctx.tender.info.decimal.tp); ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, ctx.tender.info.decimal.tp); if (cl.lid !== '0') { changeListData.push(cLArray.join('*;*')); } else { changeWhiteListData.push(cLArray.join('*;*')); } } renderData.changeListData = changeListData.join('^_^'); renderData.changeWhiteListData = changeWhiteListData.join('^_^'); renderData.ototalCost = ototalCost; renderData.ctotalCost = ctotalCost; // 获取公司列表 const companyList = await ctx.service.changeCompany.getAllDataByCondition({ where: { tid: tenderid } }); renderData.companyList = companyList; } else if (auditStatus === 3 || auditStatus === 4 || auditStatus === 5 || auditStatus === 7) { // 展示页左侧审批流程列表和清单审批列表数据 const times = change.status === audit.flow.status.back ? change.times - 1 : change.times; const auditList2 = await ctx.service.changeAudit.getListGroupByTimes(change.cid, times); // 展示页右侧审批流程列表 const auditList3 = []; for (let time = 1; time <= times; time++) { const auditTimeList = []; let max_sort = 1; for (const al of auditList) { if (al.times === time) { auditTimeList.push(al); if (al.usite > max_sort) { max_sort = al.usite; } } } for (const i in auditTimeList) { auditTimeList[i].max_sort = max_sort; } auditList3.push(auditTimeList); } renderData.auditList3 = auditList3; changeList = JSON.parse(JSON.stringify(changeList.sort())).sort().sort(); renderData.changeList = changeList; let ototalCost = 0; let ctotalCost = 0; let stotalCost = 0; const auditTotalCost = []; for (const cl of changeList) { // ototalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.oamount), renderData.tpUnit)); ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, renderData.tpUnit); // ctotalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.camount), renderData.tpUnit)); ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, renderData.tpUnit); // stotalCost += cl.samount !== '' && cl.unit_price !== null ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.samount), renderData.tpUnit)) : 0; stotalCost += cl.samount !== '' && cl.unit_price !== null ? ctx.helper.mul(cl.unit_price, cl.samount, renderData.tpUnit) : 0; const audit_amount = cl.audit_amount !== null && cl.audit_amount !== '' ? cl.audit_amount.split(',') : ''; auditTotalCost.push(audit_amount); } renderData.ototalCost = ototalCost; renderData.ctotalCost = ctotalCost; renderData.stotalCost = stotalCost; // 清单表页赋值 for (const [index, au] of auditList2.entries()) { if (au.usite !== 0) { au.list_amount = []; au.totalCost = 0; for (const [auindex, at] of auditTotalCost.entries()) { au.list_amount.push(at[index - 1]); // au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 1]), renderData.tpUnit)) : 0; au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? ctx.helper.mul(changeList[auindex].unit_price, at[index - 1], renderData.tpUnit) : 0; } } } renderData.auditList2 = auditList2; } else if (auditStatus === 6) { // 展示页左侧审批流程列表和清单审批列表数据 const auditList2 = await ctx.service.changeAudit.getListGroupByTimes(change.cid, change.times); renderData.auditList2 = auditList2; const auditList3 = await ctx.service.changeAudit.getListOrderByTimes(change.cid, change.times); for (const i in auditList3) { auditList3[i].max_sort = auditList2.length - 1; } renderData.auditList3 = auditList3; // 展示页右侧审批流程列表 const auditList5 = await ctx.service.changeAudit.getListByBack(change.cid, change.times); const auditList4 = []; for (let time = 1; time <= change.times; time++) { const auditTimeList = []; let max_sort = 1; for (const al of auditList5) { if (al.times === time) { auditTimeList.push(al); if (al.usite > max_sort) { max_sort = al.usite; } } } for (const i in auditTimeList) { auditTimeList[i].max_sort = max_sort; } if (auditTimeList.length > 0) { auditList4.push(auditTimeList); } } renderData.auditList4 = auditList4; changeList = JSON.parse(JSON.stringify(changeList.sort())).sort().sort(); renderData.changeList = changeList; let ototalCost = 0; let ctotalCost = 0; const auditTotalCost = []; const auditUnit = []; for (const cl of changeList) { // ototalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.oamount), renderData.tpUnit)); ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, renderData.tpUnit); // ctotalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.camount), renderData.tpUnit)); ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, renderData.tpUnit); const audit_amount = cl.audit_amount !== null && cl.audit_amount !== '' ? cl.audit_amount.split(',') : ''; auditTotalCost.push(audit_amount); } renderData.ototalCost = ototalCost; renderData.ctotalCost = ctotalCost; // 清单表页赋值 for (const [index, au] of auditList.entries()) { if (au.usite !== 0) { au.list_amount = []; au.totalCost = 0; if (au.uid === renderData.uid) { for (const [auindex, at] of auditTotalCost.entries()) { // if (at[index - 2] !== undefined) { // au.list_amount.push(at[index - 2]); // au.totalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 2]), renderData.tpUnit)); // } else if (at[index - 2] === undefined) { // au.list_amount.push(changeList[auindex].camount); // au.totalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, changeList[auindex].camount), renderData.tpUnit)); // } au.list_amount.push(changeList[auindex].spamount); // au.totalCost += changeList[auindex].unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, changeList[auindex].spamount), renderData.tpUnit)); au.totalCost += changeList[auindex].unit_price === null ? 0 : ctx.helper.mul(changeList[auindex].unit_price, changeList[auindex].spamount, renderData.tpUnit); } } else { for (const [auindex, at] of auditTotalCost.entries()) { au.list_amount.push(at[index - 1]); // au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 1]), renderData.tpUnit)) : 0; au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? ctx.helper.mul(changeList[auindex].unit_price, at[index - 1], renderData.tpUnit) : 0; } } } } } renderData.auditList = auditList; // 获取是否已存在调用变更令 const changeUsedData = await ctx.service.stageChange.getFinalUsedData(ctx.tender.id, change.cid); renderData.stageChangeNum = this.ctx.helper.sum(changeUsedData.map(x => { return Math.abs(x.used_qty); })); await this.layout('change/info.ejs', renderData, 'change/info_modal.ejs'); } catch (err) { this.log(err); ctx.redirect('/tender/' + ctx.params.id + '/change'); } } /** * 变更信息 新版本页面 (Get) * * @param {Object} ctx - egg全局变量 * @return {void} */ async information(ctx) { try { const whiteList = this.ctx.app.config.multipart.whitelist; const tender = await ctx.service.tender.getDataById(ctx.tender.id); const change = ctx.change; // 后台判断当前人查看info状态 const auditStatus = await ctx.service.changeAudit.getStatusByChange(change); // 获取附件列表 const attList = await ctx.service.changeAtt.getChangeAttachment(change.cid); // 获取其他变更令数据 const othersChange = await ctx.service.change.getOthersChange(ctx.tender.id, change.cid); // 根据auditStatus获取审批人列表 const auditList = await ctx.service.changeAudit.getListByStatus(change, auditStatus); // 获取已选清单 let changeList = await ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: change.cid }, orders: [['lid', 'desc'], ['id', 'asc']], }); // 获取用户人验证手机号 const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId); const auth_mobile = pa.auth_mobile; const renderData = { tender, change, othersChange, changeConst, auditStatus, auditConst: audit.flow, ledgerConsts: audit.ledger.status, attList, whiteList, auditList, changeList, tpUnit: ctx.tender.info.decimal.tp, upUnit: ctx.tender.info.decimal.up, authMobile: auth_mobile, shenpiConst, jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.change.information), }; // 根据auditStatus状态获取的不同的数据 if (auditStatus === 1 || auditStatus === 2) { renderData.changeUnits = changeConst.units; renderData.precision = ctx.tender.info.precision; // renderData.accountGroup = accountGroup; // 获取所有项目参与者 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'], }); renderData.accountList = accountList; renderData.accountGroup = accountGroup.map((item, idx) => { const groupList = accountList.filter(item => item.account_group === idx); return { groupName: item, groupList }; }); // 重新上报获取审批流程 if (auditStatus === 2) { const auditList2 = await ctx.service.changeAudit.getListByBack(change.cid, change.times); // 展示页右侧审批流程列表 const auditList3 = []; for (let time = 1; time <= change.times - 1; time++) { const auditTimeList = []; let max_sort = 1; for (const al of auditList2) { if (al.times === time) { auditTimeList.push(al); if (al.usite > max_sort) { max_sort = al.usite; } } } for (const i in auditTimeList) { auditTimeList[i].max_sort = max_sort; } auditList3.push(auditTimeList); } renderData.auditList3 = auditList3; } // 根据清单获取提交数据和计算总金额 let ototalCost = 0; let ctotalCost = 0; for (const cl of changeList) { ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, ctx.tender.info.decimal.tp); ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, ctx.tender.info.decimal.tp); } renderData.ototalCost = ototalCost; renderData.ctotalCost = ctotalCost; // 获取公司列表 const companyList = await ctx.service.changeCompany.getAllDataByCondition({ where: { tid: ctx.tender.id } }); renderData.companyList = companyList; } else if (auditStatus === 3 || auditStatus === 4 || auditStatus === 5 || auditStatus === 7) { // 展示页左侧审批流程列表和清单审批列表数据 const times = change.status === audit.flow.status.back ? change.times - 1 : change.times; const auditList2 = await ctx.service.changeAudit.getListGroupByTimes(change.cid, times); // 展示页右侧审批流程列表 const auditList3 = []; for (let time = 1; time <= times; time++) { const auditTimeList = []; let max_sort = 1; for (const al of auditList) { if (al.times === time) { auditTimeList.push(al); if (al.usite > max_sort) { max_sort = al.usite; } } } for (const i in auditTimeList) { auditTimeList[i].max_sort = max_sort; } auditList3.push(auditTimeList); } renderData.auditList3 = auditList3; changeList = JSON.parse(JSON.stringify(changeList.sort())).sort().sort(); renderData.changeList = changeList; let ototalCost = 0; let ctotalCost = 0; let stotalCost = 0; const auditTotalCost = []; for (const cl of changeList) { // ototalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.oamount), renderData.tpUnit)); ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, renderData.tpUnit); // ctotalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.camount), renderData.tpUnit)); ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, renderData.tpUnit); // stotalCost += cl.samount !== '' && cl.unit_price !== null ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.samount), renderData.tpUnit)) : 0; stotalCost += cl.samount !== '' && cl.unit_price !== null ? ctx.helper.mul(cl.unit_price, cl.samount, renderData.tpUnit) : 0; const audit_amount = cl.audit_amount !== null && cl.audit_amount !== '' ? cl.audit_amount.split(',') : ''; auditTotalCost.push(audit_amount); } renderData.ototalCost = ototalCost; renderData.ctotalCost = ctotalCost; renderData.stotalCost = stotalCost; // 清单表页赋值 for (const [index, au] of auditList2.entries()) { if (au.usite !== 0) { au.list_amount = []; au.totalCost = 0; for (const [auindex, at] of auditTotalCost.entries()) { au.list_amount.push(at[index - 1]); // au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 1]), renderData.tpUnit)) : 0; au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? ctx.helper.mul(changeList[auindex].unit_price, at[index - 1], renderData.tpUnit) : 0; } } } renderData.auditList2 = auditList2; } else if (auditStatus === 6) { // 展示页左侧审批流程列表和清单审批列表数据 const auditList2 = await ctx.service.changeAudit.getListGroupByTimes(change.cid, change.times); renderData.auditList2 = auditList2; const auditList3 = await ctx.service.changeAudit.getListOrderByTimes(change.cid, change.times); for (const i in auditList3) { auditList3[i].max_sort = auditList2.length - 1; } renderData.auditList3 = auditList3; // 展示页右侧审批流程列表 const auditList5 = await ctx.service.changeAudit.getListByBack(change.cid, change.times); const auditList4 = []; for (let time = 1; time <= change.times; time++) { const auditTimeList = []; let max_sort = 1; for (const al of auditList5) { if (al.times === time) { auditTimeList.push(al); if (al.usite > max_sort) { max_sort = al.usite; } } } for (const i in auditTimeList) { auditTimeList[i].max_sort = max_sort; } if (auditTimeList.length > 0) { auditList4.push(auditTimeList); } } renderData.auditList4 = auditList4; changeList = JSON.parse(JSON.stringify(changeList.sort())).sort().sort(); renderData.changeList = changeList; let ototalCost = 0; let ctotalCost = 0; const auditTotalCost = []; const auditUnit = []; for (const cl of changeList) { // ototalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.oamount), renderData.tpUnit)); ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, renderData.tpUnit); // ctotalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.camount), renderData.tpUnit)); ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, renderData.tpUnit); const audit_amount = cl.audit_amount !== null && cl.audit_amount !== '' ? cl.audit_amount.split(',') : ''; auditTotalCost.push(audit_amount); } renderData.ototalCost = ototalCost; renderData.ctotalCost = ctotalCost; // 清单表页赋值 for (const [index, au] of auditList.entries()) { if (au.usite !== 0) { au.list_amount = []; au.totalCost = 0; if (au.uid === renderData.uid) { for (const [auindex, at] of auditTotalCost.entries()) { // if (at[index - 2] !== undefined) { // au.list_amount.push(at[index - 2]); // au.totalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 2]), renderData.tpUnit)); // } else if (at[index - 2] === undefined) { // au.list_amount.push(changeList[auindex].camount); // au.totalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, changeList[auindex].camount), renderData.tpUnit)); // } au.list_amount.push(changeList[auindex].spamount); // au.totalCost += changeList[auindex].unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, changeList[auindex].spamount), renderData.tpUnit)); au.totalCost += changeList[auindex].unit_price === null ? 0 : ctx.helper.mul(changeList[auindex].unit_price, changeList[auindex].spamount, renderData.tpUnit); } } else { for (const [auindex, at] of auditTotalCost.entries()) { au.list_amount.push(at[index - 1]); // au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 1]), renderData.tpUnit)) : 0; au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? ctx.helper.mul(changeList[auindex].unit_price, at[index - 1], renderData.tpUnit) : 0; } } } } } renderData.auditList = auditList; // 获取是否已存在调用变更令 const changeUsedData = await ctx.service.stageChange.getFinalUsedData(ctx.tender.id, change.cid); renderData.stageChangeNum = this.ctx.helper.sum(changeUsedData.map(x => { return Math.abs(x.used_qty); })); await this.layout('change/information.ejs', renderData, 'change/information_modal.ejs'); } catch (err) { this.log(err); ctx.redirect('/tender/' + ctx.params.id + '/change'); } } /** * 变更清单 - 操作 (Ajax) * @param ctx * @return {Promise} */ async saveListsData(ctx) { try { const data = JSON.parse(ctx.request.body.data); const responseData = { err: 0, msg: '', data: {}, }; switch (data.type) { case 'add': responseData.data = await ctx.service.changeAuditList.add(data.postData); break; case 'del': await ctx.service.changeAuditList.del(data.id); break; case 'update': await ctx.service.changeAuditList.save(data.updateData); break; case 'paste': await ctx.service.changeAuditList.saveDatas(data.updateData); // 取所有工料表 responseData.data = await ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: ctx.change.cid }, orders: [['lid', 'desc'], ['id', 'asc']], }); break; case 'ledger_list': await ctx.service.changeAuditList.saveLedgerListDatas(data.updateData); // 取所有工料表 responseData.data = await ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: ctx.change.cid }, orders: [['lid', 'desc'], ['id', 'asc']], }); break; default: throw '参数有误'; } ctx.body = responseData; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString(), data: null }; } } // 审批相关 /** * 添加审批人 * @param ctx * @return {Promise} */ async addAudit(ctx) { try { const data = JSON.parse(ctx.request.body.data); const id = this.app._.toInteger(data.auditorId); if (isNaN(id) || id <= 0) { throw '参数错误'; } // 检查权限等 if (ctx.change.uid !== ctx.session.sessionUser.accountId) { throw '您无权添加审核人'; } if (ctx.change.status === audit.flow.status.checking || ctx.change.status === audit.flow.status.checked) { throw '当前不允许添加审核人'; } const auditorList = await ctx.service.changeAudit.getAuditors(ctx.change.cid, ctx.change.times); // 检查审核人是否已存在 const exist = this.app._.find(auditorList, { uid: id }); if (exist) { throw '该审核人已存在,请勿重复添加'; } const is_gdzs = ctx.tender.info.shenpi.change === shenpiConst.sp_status.gdzs ? 1 : 0; const result = await ctx.service.changeAudit.addAuditor(ctx.change.cid, id, ctx.change.times, is_gdzs); if (!result) { throw '添加审核人失败'; } // const auditors = await ctx.service.changeAudit.getAuditorsWithOwner(ctx.change.id, ctx.change.times); const auditors = null; ctx.body = { err: 0, msg: '', data: auditors }; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString(), data: null }; } } /** * 移除审批人 * @param ctx * @return {Promise} */ async deleteAudit(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 result = await ctx.service.changeAudit.deleteAuditor(ctx.change.cid, id, ctx.change.times); if (!result) { throw '移除审核人失败'; } const auditors = null; ctx.body = { err: 0, msg: '', data: auditors }; } catch (err) { ctx.body = { err: 1, msg: err.toString(), data: null }; } } async defaultBills(ctx) { try { const ledgerData = await ctx.service.ledger.getData(ctx.tender.id); const posData = await ctx.service.pos.getPosData({ tid: ctx.tender.id }); const dealBills = await ctx.service.dealBills.getAllDataByCondition({ where: { tender_id: ctx.tender.id } }); ctx.body = { err: 0, msg: '', data: { bills: ledgerData, pos: posData, dealBills } }; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString(), data: [] }; } } /** * 变更令上报和保存 * @param {Object} ctx - egg全局变量 * @return {void} */ async save(ctx) { // 变更令信息 const changeInfo = await ctx.service.change.getDataByCondition({ cid: ctx.request.body.cid }); try { const result = await ctx.service.change.save(ctx.request.body, changeInfo.tid); if (!result) { throw '上报失败'; } if (ctx.request.body.changestatus !== undefined && parseInt(ctx.request.body.changestatus) === 2) { ctx.body = { err: 0, msg: '保存成功' }; } else { ctx.redirect('/tender/' + changeInfo.tid + '/change'); } } catch (err) { this.log(err); if (ctx.request.body.changestatus !== undefined && parseInt(ctx.request.body.changestatus) === 2) { ctx.body = { err: 1, msg: err.toString() }; } else { ctx.redirect('/tender/' + changeInfo.tid + '/change/' + ctx.request.body.cid + '/info'); } } } /** * 变更令审批 * @param {Object} ctx - egg全局变量 * @return {void} */ async approval(ctx) { try { const changeData = await ctx.service.change.getDataByCondition({ cid: ctx.request.body.change_id }); if (!changeData) { throw '变更令数据错误'; } const status = parseInt(ctx.request.body.status); let result = false; const pid = this.ctx.session.sessionProject.id; switch (status) { case 3:// 审批通过 result = await ctx.service.change.approvalSuccess(pid, ctx.request.body, changeData); break; case 4:// 审批终止 result = await ctx.service.change.approvalStop(ctx.request.body); break; case 5:// 审批退回到原报人 result = await ctx.service.change.approvalBack(pid, ctx.request.body, changeData); break; case 6:// 审批退回到上一个审批人 result = await ctx.service.change.approvalBackNew(pid, ctx.request.body, changeData); break; default:break; } if (!result) { throw '审批失败'; } ctx.redirect(ctx.request.header.referer); } catch (err) { console.log(err); ctx.redirect(ctx.request.header.referer); } } /** * 变更公司管理 * @param {Object} ctx - egg全局变量 * @return {void} */ async updateCompany(ctx) { const responseData = { err: 0, msg: '', data: '', }; try { const data = JSON.parse(ctx.request.body.data); if (data.tid === undefined || data.uci === undefined || data.uc === undefined || data.ac === undefined) { throw '参数有误'; } const [addCompany, selectCompany] = await ctx.service.changeCompany.setCompanyList(data); responseData.data = { add: addCompany, select: selectCompany }; } catch (err) { responseData.err = 1; responseData.msg = err; } ctx.body = responseData; } /** * 上传附件 * @param {Object} ctx - egg全局变量 * @return {void} */ async uploadFile(ctx) { const responseData = { err: 0, msg: '', data: [], }; let stream; try { const parts = ctx.multipart({ autoFields: true }); const files = []; let index = 0; const change = await ctx.service.change.getDataByCondition({ cid: ctx.params.cid }); const extra_upload = change.status === audit.flow.status.checked; while ((stream = await parts()) !== undefined) { // 判断用户是否选择上传文件 if (!stream.filename) { throw '请选择上传的文件!'; } // const create_time = Date.parse(new Date()) / 1000; // const fileInfo = path.parse(stream.filename); // const dirName = 'app/public/upload/changes/' + moment().format('YYYYMMDD'); // const fileName = 'changes' + create_time + '_' + index + fileInfo.ext; // // 判断文件夹是否存在,不存在则直接创建文件夹 // if (!fs.existsSync(path.join(this.app.baseDir, dirName))) { // await fs.mkdirSync(path.join(this.app.baseDir, dirName)); // } // // 保存文件 // await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, dirName, fileName)); const fileInfo = path.parse(stream.filename); const create_time = Date.parse(new Date()) / 1000; const filepath = `app/public/upload/change/fujian_${create_time + index.toString() + fileInfo.ext}`; await ctx.helper.saveStreamFile(stream, path.resolve(this.app.baseDir, filepath)); await sendToWormhole(stream); // 保存数据到att表 const fileData = { in_time: create_time, filename: fileInfo.name, fileext: fileInfo.ext, filesize: Array.isArray(parts.field.size) ? parts.field.size[index] : parts.field.size, filepath, extra_upload, }; const result = await ctx.service.changeAtt.save(parts.field, fileData, ctx.session.sessionUser.accountId); if (!result) { throw '导入数据库保存失败'; } fileData.in_time = moment(create_time * 1000).format('YYYY-MM-DD'); fileData.filesize = await ctx.helper.bytesToSize(fileData.filesize); fileData.id = result.insertId; delete fileData.filepath; files.push(fileData); ++index; } responseData.data = files; } catch (err) { this.log(err); // 失败需要消耗掉stream 以防卡死 if (stream) { await sendToWormhole(stream); } this.setMessage(err.toString(), this.messageType.ERROR); } ctx.body = responseData; } /** * 下载附件 * @param {Object} ctx - egg全局变量 * @return {void} */ async downloadFile(ctx) { const id = ctx.params.id; if (id) { try { const fileInfo = await ctx.service.changeAtt.getDataById(id); if (fileInfo !== undefined && fileInfo !== '') { const fileName = path.join(this.app.baseDir, fileInfo.filepath); // 解决中文无法下载问题 const userAgent = (ctx.request.header['user-agent'] || '').toLowerCase(); let disposition = ''; if (userAgent.indexOf('msie') >= 0 || userAgent.indexOf('chrome') >= 0) { disposition = 'attachment; filename=' + encodeURIComponent(fileInfo.filename + fileInfo.fileext); } else if (userAgent.indexOf('firefox') >= 0) { disposition = 'attachment; filename*="utf8\'\'' + encodeURIComponent(fileInfo.filename + fileInfo.fileext) + '"'; } else { /* safari等其他非主流浏览器只能自求多福了 */ disposition = 'attachment; filename=' + new Buffer(fileInfo.filename + fileInfo.fileext).toString('binary'); } ctx.response.set({ 'Content-Type': 'application/octet-stream', 'Content-Disposition': disposition, 'Content-Length': fileInfo.filesize, }); ctx.body = await fs.createReadStream(fileName); } else { throw '不存在该文件'; } } catch (err) { this.log(err); this.setMessage(err.toString(), this.messageType.ERROR); } } } /** * 批量下载 - 压缩成zip文件返回 * @param {Oject} ctx - 全局上下文 */ async downloadZip(ctx) { try { const fileIds = JSON.parse(ctx.request.query.fileIds); // const { fileIds } = JSON.parse(ctx.request.body.data); // console.log('fileIds', fileIds); const { name: changeName } = await ctx.service.changeAtt.getChangeName(ctx.params.cid); const zipFilename = `${ctx.tender.data.name}-工程变更-${changeName}-附件.zip`; const time = Date.now(); const zipPath = `app/public/upload/change/fu_jian_zip${time}.zip`; const size = await ctx.service.changeAtt.compressedFile(fileIds, zipPath); // 解决中文无法下载问题 const userAgent = (ctx.request.header['user-agent'] || '').toLowerCase(); let disposition = ''; if (userAgent.indexOf('msie') >= 0 || userAgent.indexOf('chrome') >= 0) { disposition = 'attachment; filename=' + encodeURIComponent(zipFilename); } else if (userAgent.indexOf('firefox') >= 0) { disposition = 'attachment; filename*="utf8\'\'' + encodeURIComponent(zipFilename) + '"'; } else { /* safari等其他非主流浏览器只能自求多福了 */ disposition = 'attachment; filename=' + new Buffer(zipFilename).toString('binary'); } ctx.response.set({ 'Content-Type': 'application/octet-stream', 'Content-Disposition': disposition, 'Content-Length': size, }); const readStream = fs.createReadStream(path.join(this.app.baseDir, zipPath)); ctx.body = readStream; // ctx.body = fs.readFileSync(path.resolve(this.app.baseDir, zipPath)); readStream.on('close', () => { if (fs.existsSync(path.resolve(this.app.baseDir, zipPath))) { fs.unlinkSync(path.resolve(this.app.baseDir, zipPath)); } }); } catch (error) { this.log(error); } } /** * 删除附件 * @param {Object} ctx - egg全局变量 * @return {void} */ async deleteFile(ctx) { const responseData = { err: 0, msg: '', data: '', }; try { const data = JSON.parse(ctx.request.body.data); const change = await ctx.service.change.getDataByCondition({ cid: ctx.params.cid }); const fileInfo = await ctx.service.changeAtt.getDataById(data.id); if (!fileInfo || !Object.keys(fileInfo).length) { throw '该文件不存在'; } if (!fileInfo.extra_upload && change.status === audit.flow.status.checked) { throw '无权限删除'; } if (fileInfo !== undefined && fileInfo !== '') { // 先删除文件 await fs.unlinkSync(path.join(this.app.baseDir, fileInfo.filepath)); // 再删除数据库 await ctx.service.changeAtt.deleteById(data.id); responseData.data = ''; } else { throw '不存在该文件'; } // if (data.tid === undefined || data.uci === undefined || data.uc === undefined || data.ac === undefined) { // throw '参数有误'; // } // const [addCompany, selectCompany] = await ctx.service.changeCompany.setCompanyList(data); // responseData.data = { add: addCompany, select: selectCompany }; } catch (err) { responseData.err = 1; responseData.msg = err; } ctx.body = responseData; } /** * 查看附件 * @param {Object} ctx - egg全局变量 * @return {void} */ async checkFile(ctx) { const responseData = { err: 0, msg: '' }; const id = parseInt(ctx.params.id); if (id) { try { const fileInfo = await ctx.service.changeAtt.getDataById(id); if (fileInfo && Object.keys(fileInfo).length) { let filepath = fileInfo.filepath; if (!ctx.helper.canPreview(fileInfo.fileext)) { filepath = `/change/download/file/${fileInfo.id}`; } else { filepath = filepath.replace(/^app|\/app/, ''); } fileInfo.filepath && (responseData.data = { filepath }); } } catch (error) { this.log(error); this.setMessage(error.toString(), this.messageType.ERROR); responseData.err = 1; responseData.msg = error.toString(); } } ctx.body = responseData; } /** * 删除变更令 * @param {Object} ctx - egg全局变量 * @return {void} */ async delete(ctx) { try { const result = await ctx.service.change.delete(ctx.request.body.cid); if (!result) { throw '删除变更令失败'; } ctx.redirect(ctx.request.header.referer); } catch (err) { console.log(err); ctx.redirect(ctx.request.header.referer); } } /** * 变更令重新审批 * @param {Object} ctx - egg全局变量 * @return {void} */ async checkAgain(ctx) { try { const changeData = await ctx.service.change.getDataByCondition({ cid: ctx.request.body.cid }); if (!changeData) { throw '变更令数据错误'; } // 获取终审 const auditInfo = (await this.ctx.service.changeAudit.getAllDataByCondition({ where: { cid: changeData.cid }, orders: [['usort', 'desc']], limit: 1, offset: 0 }))[0]; if (changeData.status !== audit.flow.status.checked || ctx.session.sessionUser.accountId !== auditInfo.uid) { throw '您无权进行该操作'; } if (ctx.session.sessionUser.loginStatus === 0) { const code = ctx.request.body.code; const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId); if (!pa.auth_mobile) { throw '未绑定手机号'; } const cacheKey = 'smsCode:' + ctx.session.sessionUser.accountId; const cacheCode = await app.redis.get(cacheKey); // console.log(cacheCode); if (cacheCode === null || code === undefined || cacheCode !== (code + pa.auth_mobile)) { throw '验证码不正确!'; } } // 重新审批 const result = await ctx.service.change.checkAgain(changeData.cid); if (!result) { throw '重新审批失败'; } // ctx.redirect('/tender/' + changeData.tid + '/change/' + changeData.cid + '/info'); ctx.body = { err: 0, url: ctx.request.header.referer, msg: '', }; } catch (err) { console.log(err); // ctx.redirect(ctx.request.header.referer); ctx.body = { err: 1, // url: ctx.request.header.referer, msg: err, }; } } /** * 获取变更清单 * @param ctx * @return {Promise} */ async bills(ctx) { try { const data = JSON.parse(ctx.request.body.data); const responseData = { err: 0, msg: '', data: [] }; switch (data.type) { case 'gather': responseData.data = await ctx.service.changeAuditList.gatherBgBills(ctx.tender.id); break; default: throw '查询的数据不存在'; } ctx.body = responseData; } catch (err) { this.log(err); this.ajaxErrorBody(err, '获取变更清单失败'); } } /** * 最后审批人审批成功检查批复编号和其它变更令是否出现重名情况 * @param ctx * @return {Promise} */ async checkCodeRepeat(ctx) { const responseData = { err: 0, msg: '', data: '', }; try { const tenderId = ctx.params.id; const cid = ctx.params.cid; const data = JSON.parse(ctx.request.body.data); const result = await ctx.service.change.isRepeat(cid, data.p_code, tenderId); if (result) { throw '该变更令号(批复编号)已使用'; } } catch (err) { responseData.err = 1; responseData.msg = err; } ctx.body = responseData; } /** * 拷贝其他变更令 * @param {object} ctx - 全局上下文 */ async copyChange(ctx) { const responseData = { err: 0, msg: '', data: '', }; try { const cid = ctx.params.cid; const copy_cid = JSON.parse(ctx.request.body.data); const result = await ctx.service.change.handleCopyChange(cid, copy_cid); if (!result) { responseData.err = 1; responseData.msg = '拷贝失败!'; } } catch (error) { responseData.err = 1; responseData.msg = error; } ctx.body = responseData; } } return ChangeController; };