Selaa lähdekoodia

Merge branch 'dev' of http://192.168.1.41:3000/maixinrong/Calculation into dev

TonyKang 4 vuotta sitten
vanhempi
commit
95c71f0fb5

+ 192 - 89
app/controller/schedule_controller.js

@@ -9,6 +9,7 @@
  */
 
 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');
@@ -27,18 +28,46 @@ module.exports = app => {
             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 '台账修订中,请勿修改提交进度数据';
+            }
+        }
+
         async index(ctx) {
             try {
-                const scheduleInfo = await ctx.service.schedule.getDataByCondition({ tid: ctx.tender.id });
+                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 = {
-                    scheduleInfo,
+                    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,
+                    revising: await this._getLastReviseStatus(ctx),
                 };
                 await this.layout('schedule/index.ejs', renderData, 'schedule/modal.ejs');
             } catch (err) {
@@ -49,14 +78,34 @@ module.exports = app => {
 
         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: await this._getSelectedLedgerList(ctx),
+                scheduleLedgerList,
+                hadDataLidList,
+                scheduleStage,
                 jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.schedule.ledger),
+                revising: await this._getLastReviseStatus(ctx),
             };
-            await this.layout('schedule/ledger.ejs', renderData);
+            await this.layout('schedule/ledger.ejs', renderData, 'schedule/modal.ejs');
         }
 
         async plan(ctx) {
@@ -73,6 +122,7 @@ module.exports = app => {
                 mode: scheduleConst.plan_mode,
                 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');
         }
@@ -80,44 +130,8 @@ module.exports = app => {
         async stageTp(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 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: [['order', 'desc']] });
-            let curScheduleStage = scheduleStage.length > 0 ? _.maxBy(scheduleStage, 'order') : null;
-            let slmList = [];
-            let nextSlmList = [];
-            let endSlmList = [];
-            let yearSlmList = [];
-            let curYearStageData = [];
-            if (ctx.params.order && scheduleStage.length > 0) {
-                curScheduleStage = _.find(scheduleStage, { order: parseInt(ctx.params.order) });
-            }
-            if (curScheduleStage) {
-                const newSS = _.sortBy(scheduleStage, 'yearmonth');
-                const nowScheduleStage = _.findIndex(newSS, { yearmonth: curScheduleStage.yearmonth });
-                slmList = await ctx.service.scheduleLedgerMonth.getAllDataByCondition({ where: { tid: tender.id, yearmonth: curScheduleStage.yearmonth } });
-                const nextScheduleStage = nowScheduleStage >= 0 && nowScheduleStage + 1 <= newSS.length - 1 ? newSS[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(newSS, nowScheduleStage + 1), 'yearmonth');
-                    endSlmList = await ctx.service.scheduleLedgerMonth.getConllectionList(tender.id, endYearmonthCollection);
-                }
-                const yearConllection = _.map(_.filter(newSS, 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 stageIdList = _.map(_.filter(stageList, function(item) {
-                    return _.find(newSS, { order: item.order });
-                }), 'id');
-                curYearStageData = await ctx.service.stageBills.getStagesData(ctx.tender.id, stageIdList.join(','));
-            }
+            const { slmList, nextSlmList, endSlmList, yearSlmList, curYearStageData,
+                scheduleMonth, stageOrderList, scheduleStage, curScheduleStage } = await this._getStageAndPlanData(ctx);
             const renderData = {
                 tender: tender.data,
                 tenderInfo: tender.info,
@@ -133,6 +147,7 @@ module.exports = app => {
                 yearSlmList,
                 curYearStageData,
                 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');
@@ -153,6 +168,7 @@ module.exports = app => {
                 scheduleStage,
                 curScheduleStage,
                 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');
@@ -166,51 +182,14 @@ module.exports = app => {
          */
         async loadTpLedgerData(ctx) {
             try {
-                const tender = ctx.tender;
-                // const ledgerData = await ctx.controller.stage._getStageLedgerData(ctx);
-                // console.log(ledgerData);
-                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: [['order', 'desc']] });
-                const curScheduleStage = _.find(scheduleStage, { order: parseInt(ctx.params.order) });
-                let slmList = [];
-                let nextSlmList = [];
-                let endSlmList = [];
-                let yearSlmList = [];
-                let curYearStageData = [];
-                if (curScheduleStage) {
-                    const newSS = _.sortBy(scheduleStage, 'yearmonth');
-                    const nowScheduleStage = _.findIndex(newSS, { yearmonth: curScheduleStage.yearmonth });
-                    slmList = await ctx.service.scheduleLedgerMonth.getAllDataByCondition({ where: { tid: tender.id, yearmonth: curScheduleStage.yearmonth } });
-                    const nextScheduleStage = nowScheduleStage >= 0 && nowScheduleStage + 1 <= newSS.length - 1 ? newSS[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(newSS, nowScheduleStage + 1), 'yearmonth');
-                        endSlmList = await ctx.service.scheduleLedgerMonth.getConllectionList(tender.id, endYearmonthCollection);
-                    }
-                    const yearConllection = _.map(_.filter(newSS, 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 stageIdList = _.map(_.filter(stageList, function(item) {
-                        return _.find(newSS, { order: item.order });
-                    }), 'id');
-                    curYearStageData = await ctx.service.stageBills.getStagesData(tender.id, stageIdList.join(','));
+                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: {
-                    // ledgerData,
-                    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: [] };
@@ -218,6 +197,121 @@ module.exports = app => {
         }
 
         /**
+         * 获取所有期下台账数据(Ajax)
+         *
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async _getAllStageLedgerData(ctx) {
+            const 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.getLastestStageData(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' },
+                    ]);
+                }
+            }
+            return ledgerData;
+        }
+
+        async _getStageLedgerData(ctx, stageOrder) {
+            const 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,
+            });
+            let preStageData;
+            // 当前操作人查看最新数据,其他人查看历史数据
+            const curStageData = await ctx.service.stageBills.getLastestStageData(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_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' },
+            ]);
+            return ledgerData;
+        }
+
+        /**
+         * 获取本期下台账计量和计划数据(Ajax)
+         *
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        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: [['order', 'desc']] });
+            let curScheduleStage = scheduleStage.length > 0 ? _.maxBy(scheduleStage, 'order') : 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');
+                curYearStageData = await ctx.service.stageBills.getStagesData(tender.id, stageIdList.join(','));
+            }
+            return { slmList, nextSlmList, endSlmList, yearSlmList, curYearStageData, scheduleMonth, stageOrderList, scheduleStage, curScheduleStage };
+        }
+
+        /**
          * 获取台账数据(Ajax)
          *
          * @param ctx
@@ -225,14 +319,16 @@ module.exports = app => {
          */
         async loadLedgerData(ctx) {
             try {
-                const ledgerData = await ctx.service.ledger.getData(ctx.tender.id);
+                // 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({ tid: ctx.tender.id });
-                ctx.body = { err: 0, msg: '', data: { bills: ledgerData, slm: scheduleLedgerMonthData } };
+                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: [] };
@@ -247,6 +343,7 @@ module.exports = app => {
          */
         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 };
@@ -264,6 +361,7 @@ module.exports = app => {
          */
         async savePlan(ctx) {
             try {
+                await this._checkScheduleCanModify(ctx);
                 const data = JSON.parse(ctx.request.body.data);
                 const responseData = {
                     err: 0,
@@ -300,6 +398,7 @@ module.exports = app => {
          */
         async saveStageTp(ctx) {
             try {
+                await this._checkScheduleCanModify(ctx);
                 const data = JSON.parse(ctx.request.body.data);
                 const responseData = {
                     err: 0,
@@ -316,6 +415,9 @@ module.exports = app => {
                     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;
@@ -333,6 +435,7 @@ module.exports = app => {
          */
         async saveStageGcl(ctx) {
             try {
+                await this._checkScheduleCanModify(ctx);
                 const data = JSON.parse(ctx.request.body.data);
                 const responseData = {
                     err: 0,

+ 169 - 15
app/public/js/schedule_ledger.js

@@ -9,6 +9,7 @@ function getTenderId() {
     return window.location.pathname.split('/')[2];
 }
 const selects = [];
+let slh = [];
 $(function () {
     autoFlashHeight();
     // 初始化台账
@@ -20,15 +21,13 @@ $(function () {
         level: 'level',
         rootId: -1,
         fullPath: 'full_path',
-        //treeCacheKey: 'ledger_bills_fold' + '_' + getTenderId(),
-        // markFoldKey: 'bills-fold',
-        // markFoldSubKey: window.location.pathname.split('/')[2],
+        // calcFields: ['can_select'],
     };
     const ledgerTree = createNewPathTree('filter', treeSetting);
 
     const ledgerSpreadSetting = {
         cols: [
-            {title: '', colSpan: '1', rowSpan: '2', field: 'is_select', hAlign: 1, width: 40, formatter: '@', cellType: 'checkbox'},
+            {title: '', colSpan: '1', rowSpan: '2', field: 'is_select', hAlign: 1, width: 40, formatter: '@', cellType: 'checkbox', readOnly: 'readOnly.can_select'},
             {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 185, formatter: '@', readOnly: true, cellType: 'tree'},
             {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 205, formatter: '@', readOnly: true},
             {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 100, formatter: '@', readOnly: true},
@@ -49,12 +48,38 @@ $(function () {
         }
     };
 
+    const ledgerCol = {
+        readOnly: {
+            can_select: function (data) {
+                return !(data.can_select && !revising);
+            },
+        },
+    };
+
     sjsSettingObj.setFxTreeStyle(ledgerSpreadSetting, sjsSettingObj.FxTreeStyle.jz);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(ledgerSpreadSetting);
+    SpreadJsObj.initSpreadSettingEvents(ledgerSpreadSetting, ledgerCol);
     SpreadJsObj.initSheet(ledgerSpread.getActiveSheet(), ledgerSpreadSetting);
     SpreadJsObj.selChangedRefreshBackColor(ledgerSpread.getActiveSheet());
 
     postData(window.location.pathname + '/load', {}, function (data) {
+        const showList = ['is_select', 'can_select', 'ledger_id', 'ledger_pid', 'order', 'level', 'tender_id', 'full_path',
+            'code', 'name', 'unit', 'dgn_qty1', 'dgn_qty2', 'dgn_price', 'quantity', 'total_price'];
+        const calcList = ['total_price'];
+        const fileds = [];
+        if (scheduleStage.length > 0) {
+            for (const ss of scheduleStage) {
+                // const pushTp = [ss.order + '_gather_tp', ss.order + '_contract_tp', ss.order + '_qc_tp'];
+                showList.push(ss.order + '_gather_tp');
+                showList.push(ss.order + '_contract_tp');
+                showList.push(ss.order + '_qc_tp');
+                calcList.push(ss.order + '_gather_tp');
+                calcList.push(ss.order + '_contract_tp');
+                calcList.push(ss.order + '_qc_tp');
+                fileds.push(ss.order + '_contract_tp');
+                fileds.push(ss.order + '_qc_tp');
+            }
+        }
         const baseLedgerTree = createNewPathTree('base', {
             id: 'ledger_id',
             pid: 'ledger_pid',
@@ -62,20 +87,28 @@ $(function () {
             level: 'level',
             rootId: -1,
             fullPath: 'full_path',
-            calcFields: ['total_price'],
+            updateFields: fileds,
+            calcFields: calcList,
             calcFun: function (node) {
                 node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
+                if (scheduleStage.length > 0) {
+                    for (const ss of scheduleStage) {
+                        node[ss.order + '_gather_tp'] = ZhCalc.add(node[ss.order + '_contract_tp'], node[ss.order + '_qc_tp']);
+                    }
+                }
             }
         });
+        slh = data.slh;
         const datas = addIsSelect(data.bills);
         baseLedgerTree.loadDatas(datas);
         treeCalc.calculateAll(baseLedgerTree);
         for (const d of baseLedgerTree.nodes) {
             if (!d.b_code)
-                ledgerTree.addData(d, ['is_select', 'ledger_id', 'ledger_pid', 'order', 'level', 'tender_id', 'full_path',
-                    'code', 'name', 'unit', 'dgn_qty1', 'dgn_qty2', 'dgn_price', 'quantity', 'total_price']);
+                ledgerTree.addData(d, showList);
         }
         ledgerTree.sortTreeNode(true);
+        // treeCalc.calculateAll(ledgerTree);
+        console.log(ledgerTree);
 
         SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), SpreadJsObj.DataType.Tree, ledgerTree);
     }, null, true);
@@ -138,13 +171,16 @@ $(function () {
             });
         },
         buttonClicked: function (e, info) {
+            if(revising) {
+                return;
+            }
             if (info.sheet.zh_setting) {
                 const select = SpreadJsObj.getSelectObject(info.sheet);
                 const col = info.sheet.zh_setting.cols[info.col];
                 // if (materialCol.readOnly.isEdit(select)) {
                 //     return;
                 // }
-                if (col.field === 'is_select') {
+                if (col.field === 'is_select' && select.can_select) {
                     if (info.sheet.isEditing()) {
                         info.sheet.endEdit(true);
                     }
@@ -178,19 +214,87 @@ $(function () {
 
     $('#ledger_submit').click(function () {
         const select_ledger = _.filter(ledgerTree.nodes, { 'is_select': 1 });
-        console.log(select_ledger);
         if (select_ledger.length === 0) {
-            toastr.error('请选择清单项');
+            toastr.error('请至少勾选一个节点');
             return;
         }
         $(this).attr('disabled', true);
-        postData(window.location.pathname + '/save',  _.map(select_ledger, 'ledger_id'), function (result) {
+        const [under_ledger, parent_ledger] = getPAndULedger(select_ledger);
+        // 重新计算每一期计量进度金额并提交
+        const stageTpList = calcStageTp(under_ledger);
+        postData(window.location.pathname + '/save',  { select_ledger: _.map(select_ledger, 'ledger_id'), under_ledger, parent_ledger, stageTpList, type: 'sz' } , function (result) {
             toastr.success('设置成功');
             setTimeout(function () {
                 window.location.reload();
             },1500);
         });
     });
+    $('#update-ledger').click(function () {
+        const addLedgerData = _.map(_.differenceBy(ledgerTree.nodes, slh, 'ledger_id'), 'ledger_id');
+        const select_ledger = _.filter(ledgerTree.nodes, { 'is_select': 1 });
+        // 找出addLedgerData父节点并一起加入到select_ledger中
+        if (addLedgerData.length > 0) {
+            for (const a of addLedgerData) {
+                const ainfo = _.find(ledgerTree.nodes, { 'ledger_id': a });
+                select_ledger.push(ainfo);
+                findandpush(ainfo.ledger_pid);
+            }
+        }
+        function findandpush(ledger) {
+            const parent = _.find(ledgerTree.nodes, { ledger_id: ledger });
+            if (parent) {
+                const hadinfo = _.find(select_ledger, { ledger_id: parent.ledger_id });
+                if (!hadinfo) {
+                    select_ledger.push(parent);
+                    findandpush(parent);
+                }
+            }
+        }
+        $(this).attr('disabled', true);
+        const [under_ledger, parent_ledger] = getPAndULedger(select_ledger);
+        // 重新计算每一期计量进度金额并提交
+        const stageTpList = calcStageTp(under_ledger);
+        postData(window.location.pathname + '/save',  { select_ledger: _.map(select_ledger, 'ledger_id'), under_ledger, parent_ledger, stageTpList, type: 'xz' } , function (result) {
+            toastr.success('进度台账数据修正成功');
+            setTimeout(function () {
+                window.location.reload();
+            },1500);
+        });
+    });
+
+    function getPAndULedger(select_ledger) {
+        // 找出所选的最底层,并统计总设计金额用
+        const under_ledger = [];
+        for (const sl of select_ledger) {
+            const hadChild = _.find(select_ledger, { ledger_pid: sl.ledger_id });
+            if (!hadChild) {
+                const pushArray = { ledger_id: sl.ledger_id, ledger_pid: sl.ledger_pid, gcl: sl.dgn_qty1, tp: sl.total_price };
+                if (scheduleStage.length > 0) {
+                    for (const ss of scheduleStage) {
+                        pushArray[ss.order + '_gather_tp'] = sl[ss.order + '_gather_tp'];
+                    }
+                }
+                under_ledger.push(pushArray);
+            }
+        }
+        // 从最底层找出之前的所有父节点,删除他们可能存在已填的值
+        const parent_ledger = [];
+        if (under_ledger.length > 0) {
+            for (const ul of under_ledger) {
+                digui(select_ledger, ul.ledger_pid);
+            }
+        }
+        function digui(select_ledger, ul) {
+            const parent = _.find(select_ledger, { ledger_id: ul });
+            if (parent && parent_ledger.indexOf(ul) === -1) {
+                digui(select_ledger, parent.ledger_pid);
+                if (!parent.can_select) {
+                    parent_ledger.push(parent.ledger_id);
+                }
+            }
+        }
+        return [under_ledger, parent_ledger];
+    }
 
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
@@ -238,20 +342,57 @@ $(function () {
     //     });
     // })('a[name=showLevel]', ledgerSpread.getActiveSheet());
 });
+
+function calcStageTp(list) {
+    if (scheduleStage.length > 0) {
+        const stageTp = [];
+        for (const ss of scheduleStage) {
+            let stage_price = 0;
+            for (const l of list) {
+                stage_price = ZhCalc.add(stage_price, l[ss.order + '_gather_tp']);
+            }
+            stageTp.push({ id: ss.id, tp: stage_price });
+        }
+        return stageTp;
+    }
+    return false;
+}
 function addIsSelect(datas) {
     // const newDatas = [];
     for (const d of datas) {
         if (!d.b_code) {
             d.is_select = selectedLedgerList.length === 0 ? 1: selectedLedgerList.indexOf(d.ledger_id) !== -1 ? 1 : 0;
-            // newDatas.push(d);
+            if (!d.is_leaf) {
+                d.can_select = hadDataLidList.length === 0 ? true : hadDataLidList.indexOf(d.ledger_id) !== -1 ? false : true;
+                // console.log(d.can_select);
+            } else if(d.can_select === undefined) {
+                d.can_select = true;
+            }
+        }
+    }
+    for (const d2 of datas) {
+        if (!d2.b_code && !d2.can_select) {
+            updateParentCanSelect(datas, d2.ledger_pid);
         }
     }
     return datas;
 }
 
+function updateParentCanSelect(datas, ledger_pid) {
+    if (ledger_pid !== 0) {
+        const info = _.find(datas, { ledger_id: ledger_pid});
+        if (info) {
+            info.can_select = false;
+            updateParentCanSelect(datas, info.ledger_pid);
+        }
+    }
+}
+
 function updateChildrenSelect(datas, is_select) {
     for (const data of datas) {
-        data.is_select = is_select;
+        if (data.can_select) {
+            data.is_select = is_select;
+        }
         if(data.children && data.children.length > 0) {
             updateChildrenSelect(data.children, is_select);
         }
@@ -263,7 +404,10 @@ function updateSiblingsSelect(tree, pid, is_select, select_msg) {
     const parent = pid !== -1 ? _.find(tree.nodes, { 'ledger_id': pid }) : tree;
     if (parent) {
         for(const d of parent.children) {
-            d.is_select = is_select;
+            if (d.can_select) {
+                d.is_select = is_select;
+            }
+            // d.is_select = is_select;
             if (select_msg.select_children || is_select === 0) {
                 updateChildrenSelect(d.children, is_select);
             }
@@ -282,15 +426,25 @@ function updateOtherSiblingsSelect(tree, pid, is_select, select_msg) {
         if (grandparent) {
             for (const d of grandparent.children) {
                 if (d.ledger_id !== pid) {
+                    let p = false;
                     if(d.children && d.children.length > 0) {
                         for (const dd of d.children) {
-                            dd.is_select = is_select;
+                            if (dd.can_select) {
+                                dd.is_select = is_select;
+                            }
+                            p = true;
                             if (select_msg.select_children || is_select === 0) {
                                 updateChildrenSelect(dd.children, is_select);
                             }
                             selects.push(dd);
                         }
                     }
+                    if(p) {
+                        if(d.can_select) {
+                            d.is_select = is_select;
+                        }
+                        selects.push(d);
+                    }
                 }
             }
         }

+ 90 - 42
app/public/js/schedule_plan.js

@@ -10,7 +10,7 @@ function getTenderId() {
 }
 $(function () {
     autoFlashHeight();
-    if(schedule && !schedule.mode) {
+    if(schedule && !schedule.mode && !revising && !schedule.revising) {
         $('#mode').modal('show');
     }
     // 初始化台账
@@ -22,6 +22,9 @@ $(function () {
         level: 'level',
         rootId: -1,
         fullPath: 'full_path',
+        calcFun: function (node) {
+            node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
+        }
         //treeCacheKey: 'ledger_bills_fold' + '_' + getTenderId(),
         // markFoldKey: 'bills-fold',
         // markFoldSubKey: window.location.pathname.split('/')[2],
@@ -34,7 +37,7 @@ $(function () {
         {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: true},
         {title: '经济指标', colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
         {title: '总设计|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
     ];
 
     const ledgerSpreadSetting = {
@@ -51,16 +54,16 @@ $(function () {
         }
     };
     const monthsCols = [];
-    const calcCols = [];
+    const calcCols = ['total_price'];
     if(scheduleMonth.length > 0) {
         for (const sm of scheduleMonth) {
-            const readOnly = sm.stage_used !== 0;
+            const readOnly = sm.stage_gcl_used !== 0 || sm.stage_tp_used !== 0;
             const yearmonth = sm.yearmonth.split('-')[0] + '年' + parseInt(sm.yearmonth.split('-')[1]) + '月';
             const cols = {title: yearmonth + '|计划工程量', colSpan: '2|1', rowSpan: '1|1', field: sm.yearmonth+'_gcl', hAlign: 2, width: 90, type: 'Number', readOnly: readOnly ? readOnly : 'readOnly.gcl'};
-            const cols2 = {title: '|计划金额(元)', colSpan: '|1', rowSpan: '|1', field: sm.yearmonth+'_tp', hAlign: 2, width: 90, type: 'Number', readOnly: readOnly ? readOnly : 'readOnly.tp'};
+            const cols2 = {title: '|计划金额(元)', colSpan: '|1', rowSpan: '|1', field: sm.yearmonth+'_tp', hAlign: 2, width: 90, type: 'Number', readOnly: readOnly ? readOnly : 'readOnly.tp'};
             monthsCols.push(cols);
             monthsCols.push(cols2);
-            calcCols.push(sm.yearmonth+'_gcl');
+            // calcCols.push(sm.yearmonth+'_gcl');
             calcCols.push(sm.yearmonth+'_tp');
         }
     }
@@ -76,14 +79,14 @@ $(function () {
                 if (data.is_leaf) {
                     flag = schedule && schedule.mode === mode.tp;
                 }
-                return !flag;
+                return !(flag && !revising);
             },
             gcl: function (data) {
                 let flag = data.is_leaf;
                 if (data.is_leaf) {
                     flag = schedule && schedule.mode === mode.gcl;
                 }
-                return !flag;
+                return !(flag && !revising);
             },
         },
     };
@@ -138,10 +141,10 @@ $(function () {
                 }
             }
         }
-        console.log(ledgerTree);
+        // console.log(ledgerTree);
         ledgerTree.sortTreeNode(true);
         treeCalc.calculateAll(ledgerTree);
-        // console.log(ledgerTree);
+        console.log(ledgerTree);
         SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), SpreadJsObj.DataType.Tree, ledgerTree);
     }, null, true);
 
@@ -199,7 +202,7 @@ $(function () {
             if (info.sheet.zh_setting) {
                 const select = SpreadJsObj.getSelectObject(info.sheet);
                 const col = info.sheet.zh_setting.cols[info.col];
-                const validText = is_numeric(info.editingText) ? parseFloat(info.editingText) : (info.editingText ? trimInvalidChar(info.editingText) : null);
+                let validText = is_numeric(info.editingText) ? parseFloat(info.editingText) : (info.editingText ? trimInvalidChar(info.editingText) : null);
                 const orgValue = select[col.field];
                 if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
@@ -216,23 +219,25 @@ $(function () {
                 let plan_tp = 0;
                 // 判断输入位数,提示
                 if (mode === 'tp') {
-                    const reg = new RegExp('^([-]?)\\d+(\\.\\d{0,'+ parseInt(tenderInfo.decimal.tp) +'})?$');
+                    const reg = new RegExp('^([-]?)\\d+$');
                     if (validText !== null && (!reg.test(validText))) {
-                        toastr.error('输入金额小数位数不能大于' + tenderInfo.decimal.tp + '位');
-                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                        return;
+                        // toastr.error('输入金额请为整数');
+                        // SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        // return;
+                        validText = ZhCalc.round(validText, 0);
                     }
-                    plan_gcl = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.div(validText, select.dgn_price), tenderInfo.decimal.up) : 0;
+                    plan_gcl = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.div(validText, select.dgn_price), 3) : 0;
                     plan_tp = validText;
                 } else {
-                    const reg = new RegExp('^([-]?)\\d+(\\.\\d{0,'+ parseInt(tenderInfo.decimal.up) +'})?$');
+                    const reg = new RegExp('^([-]?)\\d+$');
                     if (validText !== null && (!reg.test(validText))) {
-                        toastr.error('输入工程量小数位数不能大于' + tenderInfo.decimal.up + '位');
-                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                        return;
+                        // toastr.error('输入工程量小数位数不能大于3位');
+                        // SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        // return;
+                        validText = ZhCalc.round(validText, 3);
                     }
                     plan_gcl = validText;
-                    plan_tp = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.mul(validText, select.dgn_price), tenderInfo.decimal.tp) : 0;
+                    plan_tp = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.mul(validText, select.dgn_price), 0) : 0;
                 }
                 select[col.field] = validText;
                 const updateData = {
@@ -249,13 +254,13 @@ $(function () {
                         select[yearmonth + '_tp'] = plan_tp;
                     }
                     const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
-                    SpreadJsObj.reLoadNodesData(info.sheet, nodes);
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    const refreshNode = ledgerTree.loadPostData({update: nodes});
+                    ledgerSpreadObj.refreshTree(info.sheet, refreshNode);
                 },function () {
                     select[col.field] = orgValue;
                     const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
-                    SpreadJsObj.reLoadNodesData(info.sheet, nodes);
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    const refreshNode = ledgerTree.loadPostData({update: nodes});
+                    ledgerSpreadObj.refreshTree(info.sheet, refreshNode);
                 })
             }
         },
@@ -276,7 +281,7 @@ $(function () {
             }
             const select = SpreadJsObj.getSelectObject(info.sheet);
             const col = info.sheet.zh_setting.cols[range.col];
-            const validText = is_numeric(info.pasteData.text) ? parseFloat(info.pasteData.text) : (info.pasteData.text ? trimInvalidChar(info.pasteData.text) : null);
+            let validText = is_numeric(info.pasteData.text) ? parseFloat(info.pasteData.text) : (info.pasteData.text ? trimInvalidChar(info.pasteData.text) : null);
             const orgValue = select[col.field];
             if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
                 SpreadJsObj.reLoadRowData(info.sheet, info.row);
@@ -293,23 +298,26 @@ $(function () {
             let plan_tp = 0;
             // 判断输入位数,提示
             if (mode === 'tp') {
-                const reg = new RegExp('^([-]?)\\d+(\\.\\d{0,'+ parseInt(tenderInfo.decimal.tp) +'})?$');
+                const reg = new RegExp('^([-]?)\\d+$');
                 if (validText !== null && (!reg.test(validText))) {
-                    toastr.error('粘贴的金额小数位数不能大于' + tenderInfo.decimal.tp + '位');
-                    SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
-                    return;
+                    // toastr.error('粘贴的金额小数位数不能大于0位');
+                    // SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                    // return;
+                    validText = ZhCalc.round(validText, 0);
                 }
-                plan_gcl = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.div(validText, select.dgn_price), tenderInfo.decimal.up) : 0;
+                plan_gcl = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.div(validText, select.dgn_price), 3) : 0;
                 plan_tp = validText;
             } else {
-                const reg = new RegExp('^([-]?)\\d+(\\.\\d{0,'+ parseInt(tenderInfo.decimal.up) +'})?$');
+                // const reg = new RegExp('^([-]?)\\d+(\\.\\d{0,3})?$');
+                const reg = new RegExp('^([-]?)\\d+$');
                 if (validText !== null && (!reg.test(validText))) {
-                    toastr.error('粘贴的工程量小数位数不能大于' + tenderInfo.decimal.up + '位');
-                    SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
-                    return;
+                    // toastr.error('粘贴的工程量小数位数不能大于3位');
+                    // SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                    // return;
+                    validText = ZhCalc.round(validText, 3);
                 }
                 plan_gcl = validText;
-                plan_tp = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.mul(validText, select.dgn_price), tenderInfo.decimal.tp) : 0;
+                plan_tp = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.mul(validText, select.dgn_price), 0) : 0;
             }
             select[col.field] = validText;
             const updateData = {
@@ -325,13 +333,13 @@ $(function () {
                     select[yearmonth + '_tp'] = plan_tp;
                 }
                 const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
-                SpreadJsObj.reLoadNodesData(info.sheet, nodes);
-                SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                const refreshNode = ledgerTree.loadPostData({update: nodes});
+                ledgerSpreadObj.refreshTree(info.sheet, refreshNode);
             },function () {
                 select[col.field] = orgValue;
                 const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
-                SpreadJsObj.reLoadNodesData(info.sheet, nodes);
-                SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                const refreshNode = ledgerTree.loadPostData({update: nodes});
+                ledgerSpreadObj.refreshTree(info.sheet, refreshNode);
             })
         },
     };
@@ -343,13 +351,53 @@ $(function () {
     // 进度计算方式选择
     $('.mode-select').on('click', function () {
         const _self = $(this);
-        postData(window.location.pathname + '/save', {type: 'mode', postData: $(this).data('mode')}, function (result) {
+        const this_mode = _self.data('mode');
+        // 重新计算所有月份数据
+        const under_ledger = _.filter(ledgerTree.nodes, { is_leaf: true});
+        const update_nodes = [];
+        for (const ul of under_ledger) {
+            for (const m of monthList) {
+                if (ul[m+'_tp'] || ul[m+'_gcl']) {
+                    update_nodes.push(ul);
+                    break;
+                }
+            }
+        }
+        const update_under_ledger = [];
+        if(update_nodes.length > 0) {
+            for (const un of update_nodes) {
+                if (this_mode === mode.gcl) {
+                    for (const m of monthList) {
+                        if(un[m+'_tp']) {
+                            un[m+'_tp'] = un.dgn_price && un.dgn_price !== 0 ? ZhCalc.round(ZhCalc.mul(un[m+'_gcl'], un.dgn_price), 0) : 0;
+                            update_under_ledger.push({lid: un.ledger_id, yearmonth: m, plan_tp: un[m+'_tp'], plan_gcl: un[m+'_gcl']});
+                        }
+                    }
+                } else {
+                    for (const m of monthList) {
+                        if(un[m+'_gcl']) {
+                            un[m+'_gcl'] = un.dgn_price && un.dgn_price !== 0 ? ZhCalc.round(ZhCalc.div(un[m+'_tp'], un.dgn_price), 3) : 0;
+                            update_under_ledger.push({lid: un.ledger_id, yearmonth: m, plan_tp: un[m+'_tp'], plan_gcl: un[m+'_gcl']});
+                        }
+                    }
+                }
+            }
+        }
+        console.log(update_under_ledger);
+        postData(window.location.pathname + '/save', {type: 'mode', postData: {mode: this_mode, update_under_ledger}}, function (result) {
             _self.addClass('disabled').attr('disabled', true);
             _self.parents('.col-6').siblings('.col-6').find('button').removeClass('disabled').removeAttr('disabled');
             $('#mode-tips').show();
             $('#mode-cancel').show();
             $('#mode').modal('hide');
-            schedule.mode = _self.data('mode');
+            schedule.mode = this_mode;
+            if (update_nodes.length > 0) {
+                for (const uul of update_nodes) {
+                    const nodes = treeCalc.calculateParent(ledgerSpread.getActiveSheet().zh_tree, uul);
+                    const refreshNode = ledgerTree.loadPostData({update: nodes});
+                    ledgerSpreadObj.refreshTree(ledgerSpread.getActiveSheet(), refreshNode);
+                }
+            }
             SpreadJsObj.reLoadSheetData(ledgerSpread.getActiveSheet());
         })
     });

+ 106 - 100
app/public/js/schedule_stage_gcl.js

@@ -22,6 +22,9 @@ $(function () {
         level: 'level',
         rootId: -1,
         fullPath: 'full_path',
+        calcFun: function (node) {
+            node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
+        }
         //treeCacheKey: 'ledger_bills_fold' + '_' + getTenderId(),
         // markFoldKey: 'bills-fold',
         // markFoldSubKey: window.location.pathname.split('/')[2],
@@ -34,7 +37,7 @@ $(function () {
         {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: true},
         {title: '经济指标', colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
         {title: '总设计|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
     ];
 
     const ledgerSpreadSetting = {
@@ -51,22 +54,22 @@ $(function () {
         }
     };
     const monthsCols = [];
-    const calcCols = [];
+    const calcCols = ['total_price'];
     if(scheduleMonth.length > 0) {
         for (const sm of scheduleMonth) {
             if (sm.stage_gcl_used === 1) {
                 const yearmonth = sm.yearmonth.split('-')[0] + '年' + parseInt(sm.yearmonth.split('-')[1]) + '月';
                 const cols = {title: yearmonth + '|计划工程量', colSpan: '4|1', rowSpan: '1|1', field: sm.yearmonth+'_plan_gcl', hAlign: 2, width: 90, type: 'Number', readOnly: true};
-                const cols2 = {title: '|计划金额(元)', colSpan: '|1', rowSpan: '|1', field: sm.yearmonth+'_plan_tp', hAlign: 2, width: 90, type: 'Number', readOnly: true};
+                const cols2 = {title: '|计划金额(元)', colSpan: '|1', rowSpan: '|1', field: sm.yearmonth+'_plan_tp', hAlign: 2, width: 90, type: 'Number', readOnly: true};
                 const cols3 = {title: '|计量工程量', colSpan: '|1', rowSpan: '|1', field: sm.yearmonth+'_sj_gcl', hAlign: 2, width: 90, type: 'Number', readOnly: 'readOnly.gcl'};
-                const cols4 = {title: '|计量金额(元)', colSpan: '|1', rowSpan: '|1', field: sm.yearmonth+'_sj_tp', hAlign: 2, width: 90, type: 'Number', readOnly : true};
+                const cols4 = {title: '|计量金额(元)', colSpan: '|1', rowSpan: '|1', field: sm.yearmonth+'_sj_tp', hAlign: 2, width: 90, type: 'Number', readOnly : true};
                 monthsCols.push(cols);
                 monthsCols.push(cols2);
                 monthsCols.push(cols3);
                 monthsCols.push(cols4);
-                calcCols.push(sm.yearmonth + '_plan_gcl');
+                // calcCols.push(sm.yearmonth + '_plan_gcl');
                 calcCols.push(sm.yearmonth + '_plan_tp');
-                calcCols.push(sm.yearmonth + '_sj_gcl');
+                // calcCols.push(sm.yearmonth + '_sj_gcl');
                 calcCols.push(sm.yearmonth + '_sj_tp');
             }
         }
@@ -79,7 +82,7 @@ $(function () {
     const ledgerCol = {
         readOnly: {
             gcl: function (data) {
-                return !data.is_leaf;
+                return !(data.is_leaf && !revising);
             },
         },
     };
@@ -199,7 +202,7 @@ $(function () {
             if (info.sheet.zh_setting) {
                 const select = SpreadJsObj.getSelectObject(info.sheet);
                 const col = info.sheet.zh_setting.cols[info.col];
-                const validText = is_numeric(info.editingText) ? parseFloat(info.editingText) : (info.editingText ? trimInvalidChar(info.editingText) : null);
+                let validText = is_numeric(info.editingText) ? parseFloat(info.editingText) : (info.editingText ? trimInvalidChar(info.editingText) : null);
                 const orgValue = select[col.field];
                 if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
@@ -212,14 +215,15 @@ $(function () {
                 }
                 const yearmonth = col.field.split('_')[0];
                 // 判断输入位数,提示
-                const reg = new RegExp('^([-]?)\\d+(\\.\\d{0,'+ parseInt(tenderInfo.decimal.up) +'})?$');
+                const reg = new RegExp('^([-]?)\\d+$');
                 if (validText !== null && (!reg.test(validText))) {
-                    toastr.error('输入工程量小数位数不能大于' + tenderInfo.decimal.up + '位');
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                    return;
+                    // toastr.error('输入工程量小数位数不能大于3位');
+                    // SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    // return;
+                    validText = ZhCalc.round(validText, 3);
                 }
                 const sj_gcl = validText;
-                const sj_tp = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.mul(validText, select.dgn_price), tenderInfo.decimal.tp) : 0;
+                const sj_tp = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.mul(validText, select.dgn_price), 0) : 0;
                 select[col.field] = validText;
                 const updateData = {
                     lid: select.ledger_id,
@@ -231,13 +235,13 @@ $(function () {
                 postData(window.location.pathname + '/save', {type: 'ledger_edit', postData: updateData}, function (result) {
                     select[yearmonth + '_sj_tp'] = sj_tp;
                     const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
-                    SpreadJsObj.reLoadNodesData(info.sheet, nodes);
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    const refreshNode = ledgerTree.loadPostData({update: nodes});
+                    ledgerSpreadObj.refreshTree(info.sheet, refreshNode);
                 },function () {
                     select[col.field] = orgValue;
                     const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
-                    SpreadJsObj.reLoadNodesData(info.sheet, nodes);
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    const refreshNode = ledgerTree.loadPostData({update: nodes});
+                    ledgerSpreadObj.refreshTree(info.sheet, refreshNode);
                 })
             }
         },
@@ -258,7 +262,7 @@ $(function () {
             }
             const select = SpreadJsObj.getSelectObject(info.sheet);
             const col = info.sheet.zh_setting.cols[range.col];
-            const validText = is_numeric(info.pasteData.text) ? parseFloat(info.pasteData.text) : (info.pasteData.text ? trimInvalidChar(info.pasteData.text) : null);
+            let validText = is_numeric(info.pasteData.text) ? parseFloat(info.pasteData.text) : (info.pasteData.text ? trimInvalidChar(info.pasteData.text) : null);
             const orgValue = select[col.field];
             if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
                 SpreadJsObj.reLoadRowData(info.sheet, info.row);
@@ -271,14 +275,15 @@ $(function () {
             }
             const yearmonth = col.field.split('_')[0];
             // 判断输入位数,提示
-            const reg = new RegExp('^([-]?)\\d+(\\.\\d{0,'+ parseInt(tenderInfo.decimal.up) +'})?$');
+            const reg = new RegExp('^([-]?)\\d+$');
             if (validText !== null && (!reg.test(validText))) {
-                toastr.error('粘贴的工程量小数位数不能大于' + tenderInfo.decimal.up + '位');
-                SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
-                return;
+                // toastr.error('粘贴的工程量小数位数不能大于3位');
+                // SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                // return;
+                validText = ZhCalc.round(validText, 3);
             }
             const sj_gcl = validText;
-            const sj_tp = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.mul(validText, select.dgn_price), tenderInfo.decimal.tp) : 0;
+            const sj_tp = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.mul(validText, select.dgn_price), 0) : 0;
             select[col.field] = validText;
             const updateData = {
                 lid: select.ledger_id,
@@ -290,13 +295,13 @@ $(function () {
             postData(window.location.pathname + '/save', {type: 'ledger_edit', postData: updateData}, function (result) {
                 select[yearmonth + '_sj_tp'] = sj_tp;
                 const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
-                SpreadJsObj.reLoadNodesData(info.sheet, nodes);
-                SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                const refreshNode = ledgerTree.loadPostData({update: nodes});
+                ledgerSpreadObj.refreshTree(info.sheet, refreshNode);
             },function () {
                 select[col.field] = orgValue;
                 const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
-                SpreadJsObj.reLoadNodesData(info.sheet, nodes);
-                SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                const refreshNode = ledgerTree.loadPostData({update: nodes});
+                ledgerSpreadObj.refreshTree(info.sheet, refreshNode);
             })
         },
     };
@@ -315,7 +320,10 @@ $(function () {
         level: 'level',
         rootId: -1,
         fullPath: 'full_path',
-        calcFields: ['plan_gcl', 'plan_tp', 'next_plan_gcl', 'next_plan_tp', 'end_plan_gcl', 'end_plan_tp', 'year_plan_gcl', 'year_plan_tp'],
+        calcFun: function (node) {
+            node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
+        },
+        calcFields: ['plan_tp', 'next_plan_tp', 'end_plan_tp', 'year_plan_tp', 'total_price', 'end_gather_tp', 'year_gather_tp', 'gather_tp'],
     };
 
     const huizong_static_cols = [
@@ -324,19 +332,19 @@ $(function () {
         {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: true},
         {title: '经济指标', colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
         {title: '总设计|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '自开工至本月计划完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'end_plan_gcl', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'end_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'end_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '截止本月完成计量|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '本年计划完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'year_plan_gcl', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'year_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'year_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '本年累计完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'year_contract_qty', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'year_gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'year_gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '本月计划完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'plan_gcl', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '下月计划|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'next_plan_gcl', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'next_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'next_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
     ];
 
     const huizongSpreadSetting = {
@@ -361,72 +369,70 @@ $(function () {
 
     const huizongObj = {
         setSjs: function (order) {
-            postData('/tender/' + getTenderId() + '/measure/stage/' + order + '/load', { filter: 'ledger' }, function (data) {
-                postData('/tender/' + getTenderId() + '/schedule/stage/' + order + '/load', {}, function (data2) {
-                    const calcList = ['year_contract_qty', 'year_gather_tp',
-                        'contract_qty', 'end_gather_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp',
-                        'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp', 'end_correct_tp'];
-                    const showList = ['plan_gcl', 'plan_tp', 'next_plan_gcl', 'next_plan_tp', 'end_plan_gcl', 'end_plan_tp', 'year_plan_gcl', 'year_plan_tp',
-                        'year_contract_qty', 'year_gather_tp',
-                        'contract_qty', 'end_gather_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'ledger_id', 'ledger_pid', 'order', 'level', 'tender_id', 'full_path',
-                        'code', 'name', 'unit', 'dgn_qty1', 'dgn_qty2', 'dgn_price', 'quantity', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp',
-                        'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp', 'end_correct_tp'];
-                    const baseLedgerTreeSetting = {
-                        id: 'ledger_id',
-                        pid: 'ledger_pid',
-                        order: 'order',
-                        level: 'level',
-                        rootId: -1,
-                        fullPath: 'full_path',
-                        calcFields: calcList,
-                    };
-                    baseLedgerTreeSetting.updateFields = ['year_contract_qty', 'year_gather_tp', 'contract_qty', 'end_gather_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'postil', 'used', 'contract_expr'];
-                    baseLedgerTreeSetting.calcFun = function (node) {
-                        if (!node.children || node.children.length === 0) {
-                            node.pre_gather_qty = ZhCalc.add(node.pre_contract_qty, node.pre_qc_qty);
-                            node.gather_qty = ZhCalc.add(node.contract_qty, node.qc_qty);
-                            node.end_contract_qty = ZhCalc.add(node.pre_contract_qty, node.contract_qty);
-                            node.end_qc_qty = ZhCalc.add(node.pre_qc_qty, node.qc_qty);
-                            node.end_gather_qty = ZhCalc.add(node.pre_gather_qty, node.gather_qty);
-                        }
-                        node.pre_gather_tp = ZhCalc.add(node.pre_contract_tp, node.pre_qc_tp);
-                        node.gather_tp = ZhCalc.add(node.contract_tp, node.qc_tp);
-                        node.end_contract_tp = ZhCalc.add(node.pre_contract_tp, node.contract_tp);
-                        node.end_qc_tp = ZhCalc.add(node.pre_qc_tp, node.qc_tp);
-                        node.end_gather_tp = ZhCalc.add(node.pre_gather_tp, node.gather_tp);
-                        node.end_final_tp = ZhCalc.add(node.end_qc_tp, node.total_price);
-                        if (!node.children || node.children.length === 0) {
-                            if (node.end_contract_qty) {
-                                node.end_correct_tp = ZhCalc.add(node.end_qc_tp, ZhCalc.mul(node.end_contract_qty, node.unit_price, tenderInfo.decimal.tp));
-                            } else {
-                                node.end_correct_tp = node.end_gather_tp;
-                            }
+            postData('/tender/' + getTenderId() + '/schedule/stage/' + order + '/load', {filter: 'gcl' }, function (data) {
+                const calcList = ['year_gather_tp',
+                    'contract_tp', 'qc_qty', 'qc_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp',
+                    'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp', 'end_correct_tp'];
+                const showList = ['plan_gcl', 'plan_tp', 'next_plan_gcl', 'next_plan_tp', 'end_plan_gcl', 'end_plan_tp', 'year_plan_gcl', 'year_plan_tp',
+                    'year_contract_qty', 'year_gather_tp',
+                    'contract_qty', 'end_gather_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'ledger_id', 'ledger_pid', 'order', 'level', 'tender_id', 'full_path',
+                    'code', 'name', 'unit', 'dgn_qty1', 'dgn_qty2', 'dgn_price', 'quantity', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp',
+                    'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp', 'end_correct_tp'];
+                const baseLedgerTreeSetting = {
+                    id: 'ledger_id',
+                    pid: 'ledger_pid',
+                    order: 'order',
+                    level: 'level',
+                    rootId: -1,
+                    fullPath: 'full_path',
+                    calcFields: calcList,
+                };
+                baseLedgerTreeSetting.updateFields = ['year_contract_qty', 'year_gather_tp', 'contract_qty', 'end_gather_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'postil', 'used', 'contract_expr'];
+                baseLedgerTreeSetting.calcFun = function (node) {
+                    if (!node.children || node.children.length === 0) {
+                        node.pre_gather_qty = ZhCalc.add(node.pre_contract_qty, node.pre_qc_qty);
+                        node.gather_qty = ZhCalc.add(node.contract_qty, node.qc_qty);
+                        node.end_contract_qty = ZhCalc.add(node.pre_contract_qty, node.contract_qty);
+                        node.end_qc_qty = ZhCalc.add(node.pre_qc_qty, node.qc_qty);
+                        node.end_gather_qty = ZhCalc.add(node.pre_gather_qty, node.gather_qty);
+                    }
+                    node.pre_gather_tp = ZhCalc.add(node.pre_contract_tp, node.pre_qc_tp);
+                    node.gather_tp = ZhCalc.add(node.contract_tp, node.qc_tp);
+                    node.end_contract_tp = ZhCalc.add(node.pre_contract_tp, node.contract_tp);
+                    node.end_qc_tp = ZhCalc.add(node.pre_qc_tp, node.qc_tp);
+                    node.end_gather_tp = ZhCalc.add(node.pre_gather_tp, node.gather_tp);
+                    node.end_final_tp = ZhCalc.add(node.end_qc_tp, node.total_price);
+                    if (!node.children || node.children.length === 0) {
+                        if (node.end_contract_qty) {
+                            node.end_correct_tp = ZhCalc.add(node.end_qc_tp, ZhCalc.mul(node.end_contract_qty, node.unit_price, tenderInfo.decimal.tp));
+                        } else {
+                            node.end_correct_tp = node.end_gather_tp;
                         }
-                        node.end_gather_percent = ZhCalc.mul(ZhCalc.div(node.end_gather_tp, node.end_final_tp), 100, 2);
-                        node.end_correct_percent = ZhCalc.mul(ZhCalc.div(node.end_correct_tp, node.end_final_tp), 100, 2);
-                        node.final_dgn_price = ZhCalc.round(ZhCalc.div(node.end_gather_tp, ZhCalc.add(node.deal_dgn_qty1, node.c_dgn_qty1)), tenderInfo.decimal.up);
-                        node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
-                    };
-                    const baseLedgerTree = createNewPathTree('base', baseLedgerTreeSetting);
-                    const newLedgerList = setTpMonthToLedger(data.ledgerData, data2.slmList, data2.nextSlmList, data2.endSlmList, data2.yearSlmList, data2.curYearStageData);
-                    baseLedgerTree.loadDatas(newLedgerList);
-                    treeCalc.calculateAll(baseLedgerTree);
-                    const huizongTree = createNewPathTree('filter', huizongTreeSetting);
-                    for (const d of baseLedgerTree.nodes) {
-                        if (!d.b_code) {
-                            const one = _.find(selectedLedgerList, function (item) {
-                                return item === d.ledger_id;
-                            });
-                            if (one) {
-                                huizongTree.addData(d, showList);
-                            }
+                    }
+                    node.end_gather_percent = ZhCalc.mul(ZhCalc.div(node.end_gather_tp, node.end_final_tp), 100, 2);
+                    node.end_correct_percent = ZhCalc.mul(ZhCalc.div(node.end_correct_tp, node.end_final_tp), 100, 2);
+                    node.final_dgn_price = ZhCalc.round(ZhCalc.div(node.end_gather_tp, ZhCalc.add(node.deal_dgn_qty1, node.c_dgn_qty1)), tenderInfo.decimal.up);
+                    node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
+                };
+                const baseLedgerTree = createNewPathTree('base', baseLedgerTreeSetting);
+                const newLedgerList = setTpMonthToLedger(data.ledgerData, data.slmList, data.nextSlmList, data.endSlmList, data.yearSlmList, data.curYearStageData);
+                baseLedgerTree.loadDatas(newLedgerList);
+                treeCalc.calculateAll(baseLedgerTree);
+                const huizongTree = createNewPathTree('filter', huizongTreeSetting);
+                for (const d of baseLedgerTree.nodes) {
+                    if (!d.b_code) {
+                        const one = _.find(selectedLedgerList, function (item) {
+                            return item === d.ledger_id;
+                        });
+                        if (one) {
+                            huizongTree.addData(d, showList);
                         }
                     }
-                    huizongTree.sortTreeNode(true);
-                    treeCalc.calculateAll(huizongTree);
-                    console.log(huizongTree);
-                    SpreadJsObj.loadSheetData(huizongSpread.getActiveSheet(), SpreadJsObj.DataType.Tree, huizongTree);
-                }, null, true);
+                }
+                huizongTree.sortTreeNode(true);
+                treeCalc.calculateAll(huizongTree);
+                console.log(huizongTree);
+                SpreadJsObj.loadSheetData(huizongSpread.getActiveSheet(), SpreadJsObj.DataType.Tree, huizongTree);
             }, null, true);
         },
         dropDownHtml: function (order) {
@@ -435,10 +441,10 @@ $(function () {
                 if (ss.order !== order) {
                     html += '<a class="dropdown-item change-tp" data-order="'+ ss.order +'" href="javascript:void(0);">'+ ss.yearmonth.split('-')[0] + '年' + parseInt(ss.yearmonth.split('-')[1]) +'月(第'+ ss.order +'期)</a>';
                 } else {
-                    $('#dropdownMenuButton').text(ss.yearmonth.split('-')[0] + '年' + parseInt(ss.yearmonth.split('-')[1]) +'月(第'+ ss.order +'期)');
+                    $('#stageDropdownMenuButton').text(ss.yearmonth.split('-')[0] + '年' + parseInt(ss.yearmonth.split('-')[1]) +'月(第'+ ss.order +'期)');
                 }
             }
-            $('.dropdown-menu').html(html);
+            $('#stageDropdownMenu').html(html);
         }
     };
 

+ 36 - 12
app/public/js/schedule_stage_tp.js

@@ -22,7 +22,10 @@ $(function () {
         level: 'level',
         rootId: -1,
         fullPath: 'full_path',
-        calcFields: ['plan_gcl', 'plan_tp', 'next_plan_gcl', 'next_plan_tp', 'end_plan_gcl', 'end_plan_tp', 'year_plan_gcl', 'year_plan_tp'],
+        calcFun: function (node) {
+            node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
+        },
+        calcFields: ['plan_tp', 'next_plan_tp', 'end_plan_tp', 'year_plan_tp', 'total_price', 'end_gather_tp', 'year_gather_tp', 'gather_tp'],
     };
     const ledgerTree = createNewPathTree('filter', treeSetting);
 
@@ -32,21 +35,21 @@ $(function () {
         {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: true},
         {title: '经济指标', colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
         {title: '总设计|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '自开工至本月计划完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'end_plan_gcl', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'end_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'end_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '截止本期完成计量|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '本年计划完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'year_plan_gcl', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'year_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'year_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '本年累计完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'year_contract_qty', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'year_gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'year_gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '本月计划完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'plan_gcl', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '本期完成计量|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '下月计划|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'next_plan_gcl', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'next_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(元)', colSpan: '|1', rowSpan: '|1', field: 'next_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
     ];
 
     const ledgerSpreadSetting = {
@@ -70,9 +73,9 @@ $(function () {
     SpreadJsObj.selChangedRefreshBackColor(ledgerSpread.getActiveSheet());
 
     if (curScheduleStage && curScheduleStage.order) {
-        postData('/tender/' + getTenderId() + '/measure/stage/' + curScheduleStage.order + '/load', { filter: 'ledger' }, function (data) {
-            const calcList = ['year_contract_qty', 'year_gather_tp',
-                'contract_qty', 'end_gather_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp',
+        postData('/tender/' + getTenderId() + '/schedule/stage/' + curScheduleStage.order + '/load', {}, function (data) {
+            const calcList = ['year_gather_tp',
+                'contract_tp', 'qc_qty', 'qc_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp',
                 'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp', 'end_correct_tp'];
             const showList = ['plan_gcl', 'plan_tp', 'next_plan_gcl', 'next_plan_tp', 'end_plan_gcl', 'end_plan_tp', 'year_plan_gcl', 'year_plan_tp',
                 'year_contract_qty', 'year_gather_tp',
@@ -119,6 +122,7 @@ $(function () {
             const newLedgerList = setMonthToLedger(data.ledgerData, slmList, nextSlmList, endSlmList, yearSlmList, curYearStageData);
             baseLedgerTree.loadDatas(newLedgerList);
             treeCalc.calculateAll(baseLedgerTree);
+            console.log(baseLedgerTree);
             for (const d of baseLedgerTree.nodes) {
                 if (!d.b_code) {
                     const one = _.find(selectedLedgerList, function (item) {
@@ -131,6 +135,7 @@ $(function () {
             }
             ledgerTree.sortTreeNode(true);
             treeCalc.calculateAll(ledgerTree);
+            calcGatherTpAndUpdate(ledgerTree.nodes);
             SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), SpreadJsObj.DataType.Tree, ledgerTree);
         }, null, true);
     }
@@ -204,6 +209,25 @@ $(function () {
     });
 });
 
+function calcGatherTpAndUpdate(tree) {
+    if (tree.length > 0) {
+        let total_tp = 0;
+        for (const t of tree) {
+            if (t.is_leaf && t.gather_tp) {
+                total_tp = ZhCalc.add(total_tp, t.gather_tp);
+            }
+        }
+        console.log(curScheduleStage.tp, total_tp);
+        if (curScheduleStage.tp !== total_tp) {
+            // 更新计量总金额并更新金额模式总金额
+            postData('/tender/' + getTenderId() + '/schedule/stage/save', { type: 'update_tp', postData: { tp: total_tp, order: curScheduleStage.order } }, function (data) {
+                console.log('总金额已更新');
+            })
+        }
+    }
+
+}
+
 function setMonthToLedger(ledgerList, slm, nextSlm, endSlm, yearSlm, yearLedgerData) {
     if (slm.length > 0) {
         for(const s of slm) {

+ 2 - 1
app/public/js/stage.js

@@ -301,6 +301,7 @@ $(document).ready(() => {
     const reloadCooperationHtml = function () {
         const html = [];
         for (const p of stageTree.pwd) {
+            if (!p.node) continue;
             html.push('<tr>', `<td>${p.node.code}</td>`, `<td>${p.node.name}</td>`);
             html.push('<td>', p.check ? `已解锁:${p.pwd}` : `<a name="ledger-unlock" lid="${p.ledger_id}" href="javascript: void(0);">解锁</a>`, '</td>');
             html.push('</tr>');
@@ -1492,8 +1493,8 @@ $(document).ready(() => {
         loadCurPosData: function () {
             const sheet = slSpread.getActiveSheet();
             const node = SpreadJsObj.getSelectObject(sheet);
-            spSpread.getActiveSheet().zh_setting.readOnly = node.lock;
             if (node) {
+                spSpread.getActiveSheet().zh_setting.readOnly = node.lock;
                 const posData = stagePos.ledgerPos[itemsPre + node.id] || [];
                 SpreadJsObj.loadSheetData(spSpread.getActiveSheet(), 'data', posData);
                 getNodeList(node.id);

+ 1 - 1
app/router.js

@@ -449,7 +449,7 @@ module.exports = app => {
     app.post('/tender/:id/schedule/stage/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.saveStageTp');
     app.get('/tender/:id/schedule/stage/gcl', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.stageGcl');
     app.post('/tender/:id/schedule/stage/gcl/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.saveStageGcl');
-    app.post('/tender/:id/schedule/stage/:order/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'scheduleController.loadTpLedgerData');
+    app.post('/tender/:id/schedule/stage/:order/load', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.loadTpLedgerData');
 
     // 书签
     app.post('/tender/:id/ledger/tag', sessionAuth, tenderCheck, uncheckTenderCheck, 'tenderController.billsTag');

+ 16 - 7
app/service/ledger_revise.js

@@ -205,15 +205,24 @@ module.exports = app => {
          * @returns {Promise<void>}
          */
         async cancelRevise(revise) {
-            const [billsHis, posHis] = await this.backupReviseHistoryFile(revise);
-            const result = await this.db.update(this.tableName, {
-                id: revise.id, valid: false, end_time: new Date(),
-                bills_file: billsHis, pos_file: posHis,
-            });
-            return result.affectedRows === 1;
+            const transaction = await this.db.beginTransaction();
+            try {
+                const [billsHis, posHis] = await this.backupReviseHistoryFile(revise);
+                const result = await transaction.update(this.tableName, {
+                    id: revise.id, valid: false, end_time: new Date(),
+                    bills_file: billsHis, pos_file: posHis,
+                });
+                // 形象进度改变状态
+                await transaction.update(this.ctx.service.schedule.tableName, { revising: 0 }, { where: { tid: this.ctx.tender.id } });
+                await transaction.commit();
+                return result.affectedRows === 1;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
         }
 
     }
 
     return LedgerRevise;
-};
+};

+ 3 - 0
app/service/revise_audit.js

@@ -258,6 +258,9 @@ module.exports = app => {
                 }
                 await transaction.update(this.ctx.service.ledgerRevise.tableName, reviseData);
 
+                // 形象进度改变状态
+                await transaction.update(this.ctx.service.schedule.tableName, { revising: 1 }, { where: { tid: this.ctx.tender.id } });
+
                 // 添加短信通知-需要审批提醒功能
                 // 下一人
                 // await this.ctx.helper.sendUserSms(audit.audit_id, smsTypeConst.const.XD,

+ 29 - 1
app/service/schedule.js

@@ -16,9 +16,37 @@ module.exports = app => {
                     },
                 };
                 const updateData = {
-                    mode: data,
+                    mode: data.mode,
                 };
                 await transaction.update(this.tableName, updateData, options);
+                if (data.update_under_ledger.length > 0) {
+                    const month_list = [];
+                    const update_options = [];
+                    for (const un of data.update_under_ledger) {
+                        const option = {
+                            row: {
+                                plan_tp: un.plan_tp,
+                                plan_gcl: un.plan_gcl,
+                            },
+                            where: {
+                                tid: this.ctx.tender.id,
+                                lid: un.lid,
+                                yearmonth: un.yearmonth,
+                            },
+                        };
+                        update_options.push(option);
+                        if (!this._.find(month_list, un.yearmonth)) {
+                            month_list.push(un.yearmonth);
+                        }
+                    }
+                    if (update_options.length > 0) {
+                        await transaction.updateRows(this.ctx.service.scheduleLedgerMonth.tableName, update_options);
+                        for (const m of month_list) {
+                            await this.ctx.service.scheduleLedgerMonth.calcMonthPlan(transaction, this.ctx.tender.id, m);
+                        }
+                        await this.ctx.service.scheduleMonth.calcPlan(transaction, this.ctx.tender.id);
+                    }
+                }
                 await transaction.commit();
                 return true;
             } catch (err) {

+ 85 - 2
app/service/schedule_ledger.js

@@ -1,5 +1,5 @@
 'use strict';
-
+const scheduleConst = require('../const/schedule');
 module.exports = app => {
     class ScheduleLedger extends app.BaseService {
         constructor(ctx) {
@@ -15,7 +15,7 @@ module.exports = app => {
                 });
                 const oldLids = this._.map(oldDatas, 'ledger_id');
                 const insertDatas = [];
-                for (const l of datas) {
+                for (const l of datas.select_ledger) {
                     if (oldLids.indexOf(l) === -1) {
                         const data = {
                             tid: this.ctx.tender.id,
@@ -29,16 +29,99 @@ module.exports = app => {
                 if (oldLids.length > 0) {
                     for (const ol of oldLids) {
                         await transaction.delete(this.tableName, { tid: this.ctx.tender.id, ledger_id: ol });
+                        // 更新已选标段值
+                        await transaction.delete(this.ctx.service.scheduleLedgerMonth.tableName, { tid: this.ctx.tender.id, lid: ol });
                     }
                 }
                 if (insertDatas.length > 0) await transaction.insert(this.tableName, insertDatas);
+                // 更新所有为null
+                await transaction.update(this.tableName, { gcl: null, tp: null }, { where: { tid: this.ctx.tender.id } });
+                const updateOptions = [];
+                let total_tp = 0;
+                // 更新最底层和总设计值并更新最底层已填的计划与实际(金额、工程量)
+                for (const u of datas.under_ledger) {
+                    updateOptions.push({
+                        row: {
+                            gcl: u.gcl,
+                            tp: u.tp,
+                        },
+                        where: {
+                            ledger_id: u.ledger_id,
+                            tid: this.ctx.tender.id,
+                        },
+                    });
+                    total_tp = this.ctx.helper.add(total_tp, u.tp);
+                }
+                if (updateOptions.length > 0) await transaction.updateRows(this.tableName, updateOptions);
                 // 判断是否已创建了形象进度表
                 const scheduleInfo = await this.ctx.service.schedule.getDataByCondition({ tid: this.ctx.tender.id });
                 if (!scheduleInfo) {
                     const newSchedule = {
                         tid: this.ctx.tender.id,
+                        total_tp,
                     };
                     await transaction.insert(this.ctx.service.schedule.tableName, newSchedule);
+                    const ledgerData = await this.ctx.service.ledger.getData(this.ctx.tender.id);
+                    const insertDatas = [];
+                    for (const le of ledgerData) {
+                        insertDatas.push({ tid: this.ctx.tender.id, ledger_id: le.ledger_id });
+                    }
+                    await transaction.insert(this.ctx.service.scheduleLedgerHistory.tableName, insertDatas);
+                } else {
+                    await transaction.update(this.ctx.service.schedule.tableName, { id: scheduleInfo.id, total_tp, revising: 0 });
+                }
+                // 判断是否已存在计划月,并更新计划月统计数据,再更新总的统计数据
+                const smList = await this.ctx.service.scheduleMonth.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
+                if (scheduleInfo && smList.length > 0) {
+                    // 删除所有父节点已填过的值
+                    for (const p of datas.parent_ledger) {
+                        await transaction.delete(this.ctx.service.scheduleLedgerMonth.tableName, { tid: this.ctx.tender.id, lid: p });
+                    }
+                    if (datas.type === 'xz') {
+                        const slmUpdateOption = [];
+                        const mode = scheduleInfo.mode;
+                        for (const u of datas.under_ledger) {
+                            const dgn_price = this.ctx.helper.round(this.ctx.helper.div(u.tp, u.gcl), 2);
+                            if (dgn_price && dgn_price !== 0) {
+                                const sql = 'SELECT * FROM ?? WHERE tid = ? and lid = ?';
+                                const sqlParam = [this.ctx.service.scheduleLedgerMonth.tableName, this.ctx.tender.id, u.ledger_id];
+                                const lidList = await transaction.query(sql, sqlParam);
+                                if (lidList.length > 0) {
+                                    for (const l of lidList) {
+                                        if (mode === scheduleConst.plan_mode.tp) {
+                                            const new_plan_gcl = l.plan_tp ? this.ctx.helper.round(this.ctx.helper.div(l.plan_tp, dgn_price), 3) : null;
+                                            const new_sj_gcl = l.sj_tp ? this.ctx.helper.round(this.ctx.helper.div(l.sj_tp, dgn_price), 3) : null;
+                                            slmUpdateOption.push({ id: l.id, plan_gcl: new_plan_gcl, sj_gcl: new_sj_gcl });
+                                        } else if (mode === scheduleConst.plan_mode.gcl) {
+                                            const new_plan_tp = l.plan_gcl ? this.ctx.helper.round(this.ctx.helper.div(l.plan_gcl, dgn_price), 0) : null;
+                                            const new_sj_tp = l.sj_gcl ? this.ctx.helper.round(this.ctx.helper.div(l.sj_gcl, dgn_price), 0) : null;
+                                            slmUpdateOption.push({ id: l.id, plan_tp: new_plan_tp, sj_tp: new_sj_tp });
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        if (slmUpdateOption.length > 0) await transaction.updateRows(this.ctx.service.scheduleLedgerMonth.tableName, slmUpdateOption);
+                        // scheduleLedgerHistory更新到最新版台账
+                        const ledgerData = await this.ctx.service.ledger.getData(this.ctx.tender.id);
+                        const insertDatas = [];
+                        for (const le of ledgerData) {
+                            insertDatas.push({ tid: this.ctx.tender.id, ledger_id: le.ledger_id });
+                        }
+                        await transaction.delete(this.ctx.service.scheduleLedgerHistory.tableName, { tid: this.ctx.tender.id });
+                        await transaction.insert(this.ctx.service.scheduleLedgerHistory.tableName, insertDatas);
+                    }
+                    for (const sm of smList) {
+                        await this.ctx.service.scheduleLedgerMonth.calcMonthPlan(transaction, this.ctx.tender.id, sm.yearmonth);
+                        await this.ctx.service.scheduleLedgerMonth.calcMonthSj(transaction, this.ctx.tender.id, sm.yearmonth);
+                    }
+                    await this.ctx.service.scheduleMonth.calcPlan(transaction, this.ctx.tender.id);
+                    await this.ctx.service.scheduleMonth.calcSj(transaction, this.ctx.tender.id);
+                }
+                // 判断是否已存在计量进度,并更新计量统计数据,再更新总的统计数据
+                if (datas.stageTpList) {
+                    await transaction.updateRows(this.ctx.service.scheduleStage.tableName, datas.stageTpList);
+                    await this.ctx.service.scheduleStage.calcStageSjTp(transaction, this.ctx.tender.id);
                 }
                 await transaction.commit();
                 return true;

+ 11 - 0
app/service/schedule_ledger_history.js

@@ -0,0 +1,11 @@
+'use strict';
+
+module.exports = app => {
+    class ScheduleLedgerHistory extends app.BaseService {
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'schedule_ledger_history';
+        }
+    }
+    return ScheduleLedgerHistory;
+};

+ 4 - 0
app/service/schedule_ledger_month.js

@@ -122,6 +122,10 @@ module.exports = app => {
             const result = await this.db.query(sql, sqlParam);
             return result;
         }
+
+        // async getHadDataList(tid) {
+        //     const sql = 'SELECT lid FROM ?? WHERE tid = ? '
+        // }
     }
     return ScheduleLedgerMonth;
 };

+ 40 - 0
app/service/schedule_stage.js

@@ -57,6 +57,8 @@ module.exports = app => {
                     },
                 };
                 await transaction.update(this.ctx.service.scheduleMonth.tableName, updateData, option);
+                // 重算计量总金额
+                await this.calcStageSjTp(transaction, this.ctx.tender.id);
                 await transaction.commit();
                 return true;
             } catch (err) {
@@ -80,6 +82,44 @@ module.exports = app => {
                 throw err;
             }
         }
+
+        async updateOneTp(data) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                const updateData = {
+                    tp: data.tp,
+                };
+                const option = {
+                    where: {
+                        tid: this.ctx.tender.id,
+                        order: data.order,
+                    },
+                };
+                await transaction.update(this.tableName, updateData, option);
+                // 重算计量总金额
+                await this.calcStageSjTp(transaction, this.ctx.tender.id);
+                await transaction.commit();
+                return true;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        async calcStageSjTp(transaction, tid) {
+            const sql = 'SELECT SUM(`tp`) as stage_sj_tp FROM ?? WHERE tid = ?';
+            const sqlParam = [this.tableName, tid];
+            const result = await transaction.queryOne(sql, sqlParam);
+            const updateData = {
+                stage_sj_tp: result.stage_sj_tp,
+            };
+            const option = {
+                where: {
+                    tid,
+                },
+            };
+            return await transaction.update(this.ctx.service.schedule.tableName, updateData, option);
+        }
     }
     return ScheduleStage;
 };

+ 4 - 0
app/service/stage.js

@@ -547,6 +547,10 @@ module.exports = app => {
                 }
                 await transaction.delete(this.ctx.service.stageBonus.tableName, { sid: id });
                 await transaction.delete(this.ctx.service.stageOther.tableName, { sid: id });
+                // 同步删除进度里所选的期
+                await transaction.delete(this.ctx.service.scheduleStage.tableName, { tid: stageInfo.tid, order: stageInfo.order });
+                // 重算进度计量总金额
+                await this.ctx.service.scheduleStage.calcStageSjTp(transaction, stageInfo.tid);
                 // 记录删除日志
                 await this.ctx.service.projectLog.addProjectLog(transaction, projectLogConst.type.stage, projectLogConst.status.delete, '第' + stageInfo.order + '期');
                 await transaction.commit();

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 111 - 134
app/view/schedule/index.ejs


+ 4 - 3
app/view/schedule/ledger.ejs

@@ -15,7 +15,7 @@
                 <div class="d-inline-block">
                     <a class="btn btn-sm btn-light">
                         <div class="custom-control custom-checkbox">
-                            <input type="checkbox" class="custom-control-input" id="select_other_siblings">
+                            <input type="checkbox" class="custom-control-input" id="select_other_siblings" checked>
                             <label class="custom-control-label text-primary" for="select_other_siblings">跨级选择同级项</label>
                         </div>
                     </a>
@@ -29,7 +29,7 @@
                     </a>
                 </div>
             </div>
-            <% if (tender.user_id === ctx.session.sessionUser.accountId) { %>
+            <% if (tender.user_id === ctx.session.sessionUser.accountId && !revising) { %>
             <div class="ml-auto">
                 <button type="button" id="ledger_submit" class="btn btn-primary btn-sm pull-right">确认提交</button>
             </div>
@@ -51,5 +51,6 @@
     const tenderInfo = JSON.parse(unescape('<%- escape(JSON.stringify(tenderInfo)) %>'));
     const thousandth = <%- ctx.tender.info.display.thousandth %>;
     const measureType = JSON.parse('<%- JSON.stringify(measureType) %>');
-    const selectedLedgerList = JSON.parse('<%- JSON.stringify(scheduleLedgerList) %>');
+    const hadDataLidList = JSON.parse('<%- JSON.stringify(hadDataLidList) %>');
+    const scheduleStage = JSON.parse('<%- JSON.stringify(scheduleStage) %>');
 </script>

+ 50 - 1
app/view/schedule/modal.ejs

@@ -1,3 +1,4 @@
+<% if (scheduleLedgerList.length === 0 && ctx.url !== '/tender/' + ctx.tender.id + '/schedule/ledger') { %>
 <!--首次使用提示-->
 <div class="modal fade" id="first" data-backdrop="static">
     <div class="modal-dialog" role="document">
@@ -23,12 +24,60 @@
         </div>
     </div>
 </div>
+<% } %>
+<% if (revising) { %>
+    <!--正在修订提示-->
+    <div class="modal fade" id="unedit" data-backdrop="static">
+        <div class="modal-dialog " role="document" >
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">提示</h5>
+                </div>
+                <div class="modal-body">
+                    <h5>台账正在进行修订,形象进度无法进行任何操作。</h5>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">好的</button>
+                </div>
+            </div>
+        </div>
+    </div>
+    <script type="text/javascript">$('#unedit').modal('show');</script>
+<% } %>
+<% if (!revising && schedule && schedule.revising === 1) { %>
+    <!--正在修订提示-->
+    <div class="modal fade" id="okedit" data-backdrop="static">
+        <div class="modal-dialog " role="document" >
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">提示</h5>
+                </div>
+                <div class="modal-body">
+                    <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>
+                        <h5>台账已完成修订,点击更新进度台账更新进度数据</h5>
+                    <% } else { %>
+                        <h5>台账已完成修订,进入进度台账并更新最新台账数据。</h5>
+                    <% } %>
+                </div>
+                <div class="modal-footer">
+                    <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>
+                    <button type="button" class="btn btn-primary" id="update-ledger">更新进度台账</button>
+                    <% } else { %>
+                    <a href="/tender/<%- ctx.tender.id %>/schedule/ledger" class="btn btn-primary">进入进度台账</a>
+                    <% } %>
+                </div>
+            </div>
+        </div>
+    </div>
+    <script type="text/javascript">$('#okedit').modal('show');</script>
+<% } %>
 <script>
     const selectedLedgerList = JSON.parse('<%- JSON.stringify(scheduleLedgerList) %>');
+    const revising = <%- revising %>;
 </script>
 <script type="text/javascript">
     $(function () {
-        if (selectedLedgerList.length === 0) {
+        if (selectedLedgerList.length === 0 && !revising) {
             $('#first').modal('show');
         }
     })

+ 2 - 0
app/view/schedule/plan.ejs

@@ -6,11 +6,13 @@
             <h2>
                 <% if (planMonth) { %>计划至 <%- planMonth.split('-')[0] %>年<%- parseInt(planMonth.split('-')[1]) %>月 <% } %>
             </h2>
+            <% if (!revising) { %>
             <div class="ml-auto">
                 <a href="#mode" data-toggle="modal" data-target="#mode" class="btn btn-sm btn-outline-primary">计算方式</a>
                 <a href="#edit-plan" data-toggle="modal" data-target="#edit-plan" class="btn btn-sm btn-outline-primary">管理计划</a>
                 <a href="#add-plan" data-toggle="modal" data-target="#add-plan" class="btn btn-sm btn-primary">新增计划</a>
             </div>
+            <% } %>
         </div>
     </div>
     <div class="content-wrap">

+ 4 - 2
app/view/schedule/stage_gcl.ejs

@@ -15,10 +15,12 @@
                     </div>
                 </div>
             </div>
+            <% if (!revising) { %>
             <div class="ml-auto">
                 <a href="#edit-stage" data-toggle="modal" data-target="#edit-stage" class="btn btn-sm btn-outline-primary">管理计量</a>
                 <a href="#add" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#add">创建实际计量</a>
             </div>
+            <% } %>
         </div>
     </div>
     <div class="content-wrap">
@@ -36,10 +38,10 @@
                             <% if (scheduleStage.length > 0) { %>
                                 <div class="d-inline-block ml-2">
                                     <div class="dropdown">
-                                        <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                        <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="stageDropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                             <%- curScheduleStage.yearmonth.split('-')[0] %>年<%- parseInt(curScheduleStage.yearmonth.split('-')[1]) %>月(第<%- curScheduleStage.order %>期)
                                         </button>
-                                        <div class="dropdown-menu" aria-labelledby="dropdownMenuButton" x-placement="bottom-start" style="position: absolute; transform: translate3d(0px, 26px, 0px); top: 0px; left: 0px; will-change: transform;">
+                                        <div class="dropdown-menu" id="stageDropdownMenu" aria-labelledby="stageDropdownMenuButton" x-placement="bottom-start" style="position: absolute; transform: translate3d(0px, 26px, 0px); top: 0px; left: 0px; will-change: transform;">
                                             <% for (const s of scheduleStage) { %>
                                                 <% if (s.id !== curScheduleStage.id) { %>
                                                     <a class="dropdown-item change-tp" data-order="<%- s.order %>" href="javascript:void(0);"><%- s.yearmonth.split('-')[0] %>年<%- parseInt(s.yearmonth.split('-')[1]) %>月(第<%- s.order %>期)</a>

+ 4 - 0
app/view/schedule/stage_tp.ejs

@@ -29,17 +29,21 @@
                         </div>
                     </div>
                 </div>
+                <% if (!revising) { %>
                 <div class="d-inline-flex">
                     <a href="#delete" data-toggle="modal" data-target="#delete" class="btn btn-sm btn-outline-danger">删除本期进度</a>
                 </div>
                 <% } %>
+                <% } %>
             </div>
+            <% if (!revising) { %>
             <div class="ml-auto">
                 <a href="" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#add">创建新计量进度</a>
                 <% if (scheduleStage.length > 0) { %>
                 <a href="" class="btn btn-sm btn-warning" data-toggle="modal" data-target="#re-build">重新生成本月进度</a>
                 <% } %>
             </div>
+            <% } %>
         </div>
     </div>
     <div class="content-wrap">