'use strict'; /** * * * @author Ellisran * @date 2020/7/2 * @version */ const moment = require('moment'); const reviseStatus = require('../const/audit').revise.status; const measureType = require('../const/tender').measureType; const scheduleConst = require('../const/schedule'); const billsPosConvert = require('../lib/bills_pos_convert'); const _ = require('lodash'); module.exports = app => { class ScheduleController extends app.BaseController { async _getSelectedLedgerList(ctx) { const scheduleLedgerList = await ctx.service.scheduleLedger.getAllDataByCondition({ where: { tid: ctx.tender.id } }); return _.map(scheduleLedgerList, 'ledger_id'); } async _getLastPlanMonth(ctx) { const lastMonth = await ctx.service.scheduleMonth.getLastPlanMonth(); return lastMonth && lastMonth[0] && lastMonth[0].yearmonth ? lastMonth[0].yearmonth : null; } async _getLastReviseStatus(ctx) { const lastRevise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id); return (lastRevise && lastRevise.status !== reviseStatus.checked) || false; } async _checkScheduleCanModify(ctx) { if (await this._getLastReviseStatus(ctx)) { throw '台账修订中,请勿修改提交进度数据'; } if (ctx.tender.schedule_permission !== scheduleConst.permission.edit) { throw '权限不足,无法修改进度数据'; } } async index(ctx) { try { const schedule = await ctx.service.schedule.getDataByCondition({ tid: ctx.tender.id }); const scheduleMonth = await ctx.service.scheduleMonth.getAllDataByCondition({ where: { tid: ctx.tender.id }, orders: [['yearmonth', 'asc']] }); const scheduleStage = await ctx.service.scheduleStage.getAllDataByCondition({ where: { tid: ctx.tender.id }, orders: [['yearmonth', 'asc']] }); // 汇总并统计前几个计划月总计划额 for (const i in scheduleStage) { let nowIndex = 0; let lastIndex = 0; if (i > 0) { nowIndex = _.findIndex(scheduleMonth, { yearmonth: scheduleStage[i].yearmonth }) + 1; lastIndex = _.findIndex(scheduleMonth, { yearmonth: scheduleStage[i - 1].yearmonth }) + 1; } else { nowIndex = _.findIndex(scheduleMonth, { yearmonth: scheduleStage[i].yearmonth }) + 1; } // 获取新计划月数组 const newSm = scheduleMonth.slice(lastIndex, nowIndex); scheduleStage[i].plan_tp = _.sumBy(newSm, 'plan_tp'); } const renderData = { schedule, scheduleMonth, scheduleStage, tender: ctx.tender.data, tenderMenu: this.menu.tenderMenu, planMonth: await this._getLastPlanMonth(ctx), scheduleLedgerList: await this._getSelectedLedgerList(ctx), preUrl: '/tender/' + ctx.tender.id, scPermission: scheduleConst.permission, revising: await this._getLastReviseStatus(ctx), }; await this.layout('schedule/index.ejs', renderData, 'schedule/modal.ejs'); } catch (err) { this.log(err); ctx.redirect(this.menu.menu.dashboard.url); } } async ledger(ctx) { const tender = ctx.tender; const schedule = await ctx.service.schedule.getDataByCondition({ tid: ctx.tender.id }); const scheduleLedgerList = await this._getSelectedLedgerList(ctx); const allSlmList = await ctx.service.scheduleLedgerMonth.getAllDataByCondition({ where: { tid: ctx.tender.id } }); const scheduleStage = await ctx.service.scheduleStage.getAllDataByCondition({ where: { tid: tender.id }, orders: [['order', 'desc']] }); const hadDataLidList = []; for (const sl of scheduleLedgerList) { const info = _.find(allSlmList, function(item) { return item.lid === sl && ((item.plan_tp !== null && item.plan_tp !== 0) || (item.plan_gcl !== null && item.plan_gcl !== 0) || (item.sj_tp !== null && item.sj_tp !== 0) || (item.sj_gcl !== null && item.sj_gcl !== 0)); }); if (info) { hadDataLidList.push(info.lid); } } const renderData = { schedule, tender: tender.data, tenderInfo: tender.info, measureType, scheduleLedgerList, hadDataLidList, scheduleStage, scPermission: scheduleConst.permission, jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.schedule.ledger), revising: await this._getLastReviseStatus(ctx), }; await this.layout('schedule/ledger.ejs', renderData, 'schedule/modal.ejs'); } async plan(ctx) { const tender = ctx.tender; const schedule = await ctx.service.schedule.getDataByCondition({ tid: tender.id }); const scheduleMonth = await ctx.service.scheduleMonth.getAllDataByCondition({ where: { tid: tender.id }, orders: [['yearmonth', 'asc']] }); const renderData = { tender: tender.data, tenderInfo: tender.info, schedule, scheduleMonth, planMonth: await this._getLastPlanMonth(ctx), measureType, mode: scheduleConst.plan_mode, scPermission: scheduleConst.permission, scheduleLedgerList: await this._getSelectedLedgerList(ctx), jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.schedule.plan), revising: await this._getLastReviseStatus(ctx), }; await this.layout('schedule/plan.ejs', renderData, 'schedule/plan_modal.ejs'); } async stageTp(ctx) { const tender = ctx.tender; const schedule = await ctx.service.schedule.getDataByCondition({ tid: tender.id }); const { slmList, nextSlmList, endSlmList, yearSlmList, curYearStageData, scheduleMonth, stageOrderList, scheduleStage, curScheduleStage } = await this._getStageAndPlanData(ctx); const renderData = { tender: tender.data, tenderInfo: tender.info, schedule, scheduleMonth, measureType, stageOrderList, scheduleStage, curScheduleStage, slmList, nextSlmList, endSlmList, yearSlmList, curYearStageData, scPermission: scheduleConst.permission, scheduleLedgerList: await this._getSelectedLedgerList(ctx), revising: await this._getLastReviseStatus(ctx), jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.schedule.stageTp), }; await this.layout('schedule/stage_tp.ejs', renderData, 'schedule/stage_tp_modal.ejs'); } async stageGcl(ctx) { const tender = ctx.tender; const schedule = await ctx.service.schedule.getDataByCondition({ tid: tender.id }); const scheduleMonth = await ctx.service.scheduleMonth.getAllDataByCondition({ where: { tid: tender.id }, orders: [['yearmonth', 'asc']] }); // const scheduleStage = await ctx.service.scheduleStage.getAllDataByCondition({ where: { tid: tender.id }, orders: [['order', 'desc']] }); const gclScheduleMonth = _.orderBy(_.filter(scheduleMonth, { stage_gcl_used: 1 }), ['yearmonth'], ['desc']); const curScheduleMonth = scheduleMonth.length > 0 ? _.maxBy(gclScheduleMonth, 'yearmonth') : null; const renderData = { tender: tender.data, tenderInfo: tender.info, schedule, scheduleMonth, measureType, // scheduleStage, curScheduleMonth, gclScheduleMonth, scPermission: scheduleConst.permission, scheduleLedgerList: await this._getSelectedLedgerList(ctx), revising: await this._getLastReviseStatus(ctx), jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.schedule.stageGcl), }; await this.layout('schedule/stage_gcl.ejs', renderData, 'schedule/stage_gcl_modal.ejs'); } /** * 获取金额模式下台账数据(Ajax) * * @param ctx * @return {Promise} */ async loadTpLedgerData(ctx) { try { const ledgerData = await this._getStageLedgerData(ctx, ctx.params.order); const postData = { ledgerData }; const data = JSON.parse(ctx.request.body.data); if (data.filter && data.filter === 'gcl') { const { slmList, nextSlmList, endSlmList, yearSlmList, curYearStageData } = await this._getStageAndPlanData(ctx); _.assignIn(postData, { slmList, nextSlmList, endSlmList, yearSlmList, curYearStageData }); } ctx.body = { err: 0, msg: '', data: postData }; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString(), data: [] }; } } /** * 获取工程量模式下台账数据(Ajax) * * @param ctx * @return {Promise} */ async loadGclLedgerData(ctx) { try { const ledgerData = await ctx.service.ledger.getData(ctx.tender.id); const postData = { ledgerData }; const { slmList, nextSlmList, endSlmList, yearSlmList } = await this._getGclAndPlanData(ctx); _.assignIn(postData, { slmList, nextSlmList, endSlmList, yearSlmList }); ctx.body = { err: 0, msg: '', data: postData }; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString(), data: [] }; } } /** * 获取所有期下台账数据(Ajax) * * @param ctx * @return {Promise} */ async _getAllStageLedgerData(ctx) { let ledgerData = await ctx.service.ledger.getData(ctx.tender.id); const stageList = await ctx.service.scheduleStage.getAllDataByCondition({ where: { tid: ctx.tender.id }, orders: [['order', 'desc']] }); if (stageList.length > 0) { const dgnData = await ctx.service.stageBillsDgn.getDgnData(ctx.tender.id); for (const d of dgnData) { const l = ctx.app._.find(ledgerData, { id: d.id }); ctx.app._.assignIn(l, d); } for (const s of stageList) { const stageInfo = await ctx.service.stage.getDataByCondition({ tid: ctx.tender.id, order: s.order, }); // let preStageData; // 当前操作人查看最新数据,其他人查看历史数据 const curStageData = await ctx.service.stageBills.getLastestStageData2(ctx.tender.id, stageInfo.id); // // 查询截止上期数据 // if (stageInfo.order > 1) { // preStageData = await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, stageInfo.order - 1); // } else { // preStageData = []; // } this.ctx.helper.assignRelaData(ledgerData, [ { data: curStageData, fields: ['contract_tp', 'qc_tp'], prefix: s.order + '_', relaId: 'lid' }, // { data: preStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'used'], prefix: s.order + '_pre_', relaId: 'lid' }, ]); } ledgerData = await this._addFinalStageData(ctx, ledgerData); } return ledgerData; } async _getStageLedgerData(ctx, stageOrder) { let ledgerData = await ctx.service.ledger.getData(ctx.tender.id); const dgnData = await ctx.service.stageBillsDgn.getDgnData(ctx.tender.id); for (const d of dgnData) { const l = ctx.app._.find(ledgerData, { id: d.id }); ctx.app._.assignIn(l, d); } const stageInfo = await ctx.service.stage.getDataByCondition({ tid: ctx.tender.id, order: stageOrder, }); await ctx.service.stage.loadPreCheckedStage(stageInfo); // 当前操作人查看最新数据,其他人查看历史数据 const curStageData = await ctx.service.stageBills.getLastestStageData2(ctx.tender.id, stageInfo.id); const preStageData = stageInfo.preCheckedStage ? await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, stageInfo.preCheckedStage.order) : []; const pcData = await ctx.service.stageBillsPc.getAllDataByCondition({ where: { sid: stageInfo.id } }); this.ctx.helper.assignRelaData(ledgerData, [ { data: curStageData, fields: ['contract_qty', 'contract_expr', 'contract_tp', 'qc_qty', 'qc_tp', 'postil'], prefix: '', relaId: 'lid' }, { data: preStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'used'], prefix: 'pre_', relaId: 'lid' }, { data: pcData, fields: ['contract_pc_tp', 'qc_pc_tp', 'pc_tp', 'org_price'], prefix: '', relaId: 'lid' }, ]); // 获取进度最新期的数据 ledgerData = await this._addFinalStageData(ctx, ledgerData); return ledgerData; } /** * 添加最新一期的进度期下期数据到台账数据中(Ajax) * * @param ctx * @return {Promise} */ async _addFinalStageData(ctx, ledgerData) { const scheduleStage = await ctx.service.scheduleStage.getAllDataByCondition({ where: { tid: ctx.tender.id }, orders: [['order', 'desc']] }); if (scheduleStage && scheduleStage.length > 0) { let prefinalStageData; const finalStageInfo = await ctx.service.stage.getDataByCondition({ tid: ctx.tender.id, order: scheduleStage[0].order, }); const finalStageData = await ctx.service.stageBills.getLastestStageData2(ctx.tender.id, finalStageInfo.id); if (finalStageInfo.order > 1) { prefinalStageData = await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, finalStageInfo.order - 1); } else { prefinalStageData = []; } const finalPcData = await ctx.service.stageBillsPc.getAllDataByCondition({ where: { sid: finalStageInfo.id } }); this.ctx.helper.assignRelaData(ledgerData, [ { data: finalStageData, fields: ['contract_qty', 'contract_expr', 'contract_tp', 'qc_qty', 'qc_tp', 'postil'], prefix: 'final_', relaId: 'lid' }, { data: prefinalStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'used'], prefix: 'pre_final_', relaId: 'lid' }, { data: finalPcData, fields: ['contract_pc_tp', 'qc_pc_tp', 'pc_tp', 'org_price'], prefix: 'final_', relaId: 'lid' }, ]); } return ledgerData; } /** * 获取本期下台账计量和计划数据(Ajax) * * @param ctx * @return {Promise} */ async _getStageAndPlanData(ctx) { const tender = ctx.tender; const scheduleMonth = await ctx.service.scheduleMonth.getAllDataByCondition({ where: { tid: tender.id }, orders: [['yearmonth', 'asc']] }); const stageOrderList = await ctx.service.stage.getAllDataByCondition({ columns: ['id', 's_time', 'order'], where: { tid: tender.id } }); const scheduleStage = await ctx.service.scheduleStage.getAllDataByCondition({ where: { tid: tender.id }, orders: [['yearmonth', 'desc']] }); let curScheduleStage = scheduleStage.length > 0 ? _.maxBy(scheduleStage, 'yearmonth') : null; if (ctx.params.order && scheduleStage.length > 0) { curScheduleStage = _.find(scheduleStage, { order: parseInt(ctx.params.order) }); } let slmList = []; let nextSlmList = []; let endSlmList = []; let yearSlmList = []; let curYearStageData = []; if (curScheduleStage) { const newSM = _.sortBy(scheduleMonth, 'yearmonth'); const nowScheduleStage = _.findIndex(newSM, { yearmonth: curScheduleStage.yearmonth }); slmList = await ctx.service.scheduleLedgerMonth.getAllDataByCondition({ where: { tid: tender.id, yearmonth: curScheduleStage.yearmonth } }); const nextScheduleStage = nowScheduleStage >= 0 && nowScheduleStage + 1 <= newSM.length - 1 ? newSM[nowScheduleStage + 1] : null; if (nextScheduleStage) nextSlmList = await ctx.service.scheduleLedgerMonth.getAllDataByCondition({ where: { tid: tender.id, yearmonth: nextScheduleStage.yearmonth } }); if (nowScheduleStage === 0) { endSlmList = slmList; } else if (nowScheduleStage > 0) { const endYearmonthCollection = _.map(_.take(newSM, nowScheduleStage + 1), 'yearmonth'); endSlmList = await ctx.service.scheduleLedgerMonth.getConllectionList(tender.id, endYearmonthCollection); } const yearConllection = _.map(_.filter(newSM, function(item) { return item.yearmonth.indexOf(curScheduleStage.yearmonth.split('-')[0]) !== -1; }), 'yearmonth'); yearSlmList = await ctx.service.scheduleLedgerMonth.getConllectionList(tender.id, yearConllection); // 获取本年完成计量数据 const curStage = _.find(stageOrderList, { order: curScheduleStage.order }); const stageList = _.filter(stageOrderList, function(item) { return item.s_time.indexOf(curStage.s_time.split('-')[0]) !== -1; }); // const newSS = _.sortBy(scheduleStage, 'yearmonth'); // const stageIdList = _.map(_.filter(stageList, function(item) { // return _.find(newSS, { order: item.order }); // }), 'id'); const stageIdList = _.map(stageList, 'id'); curYearStageData = await ctx.service.stageBills.getStagesData(tender.id, stageIdList.join(',')); const curYearStagePcData = await ctx.service.stageBillsPc.getStagesData(tender.id, stageIdList.join(',')); for (const cys of curYearStageData) { const cyspc = ctx.helper._.find(curYearStagePcData, { lid: cys.lid }); if (cyspc) ctx.helper._.assign(cys, cyspc); } } return { slmList, nextSlmList, endSlmList, yearSlmList, curYearStageData, scheduleMonth, stageOrderList, scheduleStage, curScheduleStage }; } /** * 获取工程量模式汇总下台账的计划数据(Ajax) * * @param ctx * @return {Promise} */ async _getGclAndPlanData(ctx) { const tender = ctx.tender; const scheduleMonth = await ctx.service.scheduleMonth.getAllDataByCondition({ where: { tid: tender.id }, orders: [['yearmonth', 'asc']] }); let curScheduleMonth = scheduleMonth.length > 0 ? _.maxBy(scheduleMonth, 'order') : null; const gclScheduleMonth = _.filter(scheduleMonth, { stage_gcl_used: 1 }); if (ctx.params.order && gclScheduleMonth.length > 0) { curScheduleMonth = _.find(gclScheduleMonth, { id: parseInt(ctx.params.order) }); } let slmList = []; let nextSlmList = []; let endSlmList = []; let yearSlmList = []; if (curScheduleMonth) { const newSM = _.sortBy(scheduleMonth, 'yearmonth'); const nowScheduleMonth = _.findIndex(newSM, { yearmonth: curScheduleMonth.yearmonth }); slmList = await ctx.service.scheduleLedgerMonth.getAllDataByCondition({ where: { tid: tender.id, yearmonth: curScheduleMonth.yearmonth } }); const nextScheduleMonth = nowScheduleMonth >= 0 && nowScheduleMonth + 1 <= newSM.length - 1 ? newSM[nowScheduleMonth + 1] : null; if (nextScheduleMonth) nextSlmList = await ctx.service.scheduleLedgerMonth.getAllDataByCondition({ where: { tid: tender.id, yearmonth: nextScheduleMonth.yearmonth } }); if (nowScheduleMonth === 0) { endSlmList = slmList; } else if (nowScheduleMonth > 0) { const endYearmonthCollection = _.map(_.take(newSM, nowScheduleMonth + 1), 'yearmonth'); endSlmList = await ctx.service.scheduleLedgerMonth.getConllectionList(tender.id, endYearmonthCollection); } const yearConllection = _.map(_.filter(newSM, function(item) { return item.yearmonth.indexOf(curScheduleMonth.yearmonth.split('-')[0]) !== -1; }), 'yearmonth'); yearSlmList = await ctx.service.scheduleLedgerMonth.getConllectionList(tender.id, yearConllection); } return { slmList, nextSlmList, endSlmList, yearSlmList, scheduleMonth, curScheduleMonth }; } /** * 获取台账数据(Ajax) * * @param ctx * @return {Promise} */ async loadLedgerData(ctx) { try { // const ledgerData = await ctx.service.ledger.getData(ctx.tender.id); const ledgerData = await this._getAllStageLedgerData(ctx); // const posData = ctx.tender.data.measure_type === measureType.tz.value // ? await ctx.service.pos.getPosData({ tid: ctx.tender.id }) : []; // const convert = new billsPosConvert(ctx); // convert.loadData(ledgerData, posData, []); // const result = await convert.convert(); const scheduleLedgerMonthData = await ctx.service.scheduleLedgerMonth.getAllDataByCondition({ where: { tid: ctx.tender.id } }); const scheduleLedgerHistoryData = await ctx.service.scheduleLedgerHistory.getAllDataByCondition({ where: { tid: ctx.tender.id } }); ctx.body = { err: 0, msg: '', data: { bills: ledgerData, slm: scheduleLedgerMonthData, slh: scheduleLedgerHistoryData } }; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString(), data: [] }; } } /** * 台账选中提交(Ajax) * * @param ctx * @return {Promise} */ async saveLedger(ctx) { try { await this._checkScheduleCanModify(ctx); const data = JSON.parse(ctx.request.body.data); const result = await ctx.service.scheduleLedger.saveLedger(data); ctx.body = { err: 0, msg: '', data: result }; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString(), data: [] }; } } /** * 计划进度计算方式提交(Ajax) * * @param ctx * @return {Promise} */ async savePlan(ctx) { try { await this._checkScheduleCanModify(ctx); const data = JSON.parse(ctx.request.body.data); const responseData = { err: 0, msg: '', data: {}, }; switch (data.type) { case 'mode': responseData.data = await ctx.service.schedule.saveMode(data.postData); break; case 'addmonth': responseData.data = await ctx.service.scheduleMonth.add(data.postData); break; case 'delmonth': responseData.data = await ctx.service.scheduleMonth.del(data.postData); break; case 'ledger_edit': responseData.data = await ctx.service.scheduleLedgerMonth.save(data.postData); break; case 'ledger_paste': responseData.data = await ctx.service.scheduleLedgerMonth.saveDatas(data.postData); break; default: throw '参数有误'; } ctx.body = responseData; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString(), data: null }; } } /** * 计量进度金额模式计算方式提交(Ajax) * * @param ctx * @return {Promise} */ async saveStageTp(ctx) { try { await this._checkScheduleCanModify(ctx); const data = JSON.parse(ctx.request.body.data); const responseData = { err: 0, msg: '', data: {}, }; switch (data.type) { case 'add_stage': responseData.data = await ctx.service.scheduleStage.add(data.postData); break; case 'del_stage': responseData.data = await ctx.service.scheduleStage.del(data.postData); break; case 'reload_stage': responseData.data = await ctx.service.scheduleStage.changeOrder(data.postData); break; case 'update_tp': responseData.data = await ctx.service.scheduleStage.updateOneTp(data.postData); break; default: throw '参数有误'; } ctx.body = responseData; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString(), data: null }; } } /** * 计量进度工程量模式计算方式提交(Ajax) * * @param ctx * @return {Promise} */ async saveStageGcl(ctx) { try { await this._checkScheduleCanModify(ctx); const data = JSON.parse(ctx.request.body.data); const responseData = { err: 0, msg: '', data: {}, }; switch (data.type) { case 'add_stage': responseData.data = await ctx.service.scheduleMonth.addStageUsed(data.postData); break; case 'del_stage': responseData.data = await ctx.service.scheduleMonth.delStageUsed(data.postData); break; case 'ledger_edit': responseData.data = await ctx.service.scheduleLedgerMonth.saveSj(data.postData); break; case 'ledger_paste': responseData.data = await ctx.service.scheduleLedgerMonth.saveSjDatas(data.postData); break; default: throw '参数有误'; } ctx.body = responseData; } catch (err) { this.log(err); ctx.body = { err: 1, msg: err.toString(), data: null }; } } async saveAudit(ctx) { try { const data = JSON.parse(ctx.request.body.data); if (!data) { throw '提交数据错误'; } // 判断修改权限 if (ctx.session.sessionUser.is_admin === 0) { throw '你没有权限修改投资进度'; } let info = ''; switch (data.type) { case 'add': const result = await ctx.service.scheduleAudit.addAudit(data); if (!result) { throw '添加审批人失败'; } info = result; break; case 'del': await ctx.service.scheduleAudit.removeAudit(data); break; case 'edit': await ctx.service.scheduleAudit.editAudit(data); break; default:break; } ctx.body = { err: 0, msg: '', data: info }; } catch (err) { this.log(err); ctx.body = this.ajaxErrorBody(err, '保存审批流程设置失败'); } } } return ScheduleController; };