Преглед изворни кода

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

Tony Kang пре 2 година
родитељ
комит
cc5dd7067f

+ 6 - 0
app/controller/stage_rela_controller.js

@@ -128,6 +128,8 @@ module.exports = app => {
                 l.org_unit_price = l.unit_price;
                 delete l.unit_price;
             }
+            const extraFields = ['is_tp', 'gxby_status', 'gxby_url', 'gxby_limit', 'dagl_status', 'dagl_url', 'dagl_limit'];
+            const extraData = await ctx.service.ledgerExtra.getData(relaStage.rela_tid, extraFields);
             const dgnData = await ctx.service.stageBillsDgn.getDgnData(relaStage.rela_tid);
             const curStageData = await ctx.service.stageRelaBills.getAllDataByCondition({
                 where: {sid: ctx.stage.id, rela_tid: relaStage.rela_tid},
@@ -136,6 +138,7 @@ module.exports = app => {
                 where: {sid: ctx.stage.id, rela_tid: relaStage.rela_tid},
             });
             this.ctx.helper.assignRelaData(ledgerData, [
+                { data: extraData, fields: extraFields, prefix: '', relaId: 'id' },
                 { data: dgnData, fields: ['deal_dgn_qty1', 'deal_dgn_qty2', 'c_dgn_qty1', 'c_dgn_qty2'], prefix: '', relaId: 'id' },
                 { data: curStageData, fields: ['contract_qty', 'contract_expr', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty', 'postil'], prefix: '', relaId: 'lid' },
                 { data: endStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty',], prefix: 'end_', relaId: 'lid' },
@@ -145,6 +148,8 @@ module.exports = app => {
 
         async _getStageRelaPosData(ctx, relaStage) {
             const posData = await ctx.service.pos.getPosData({tid: relaStage.rela_tid});
+            const extraFields = ['gxby_status', 'gxby_url', 'gxby_limit', 'dagl_status', 'dagl_url', 'dagl_limit'];
+            const extraData = await ctx.service.posExtra.getData(relaStage.rela_tid, extraFields);
             const curStageData = await ctx.service.stageRelaPos.getAllDataByCondition({
                 where: {sid: ctx.stage.id, rela_tid: relaStage.rela_tid},
             });
@@ -152,6 +157,7 @@ module.exports = app => {
                 where: {sid: ctx.stage.id, rela_tid: relaStage.rela_tid},
             });
             this.ctx.helper.assignRelaData(posData, [
+                { data: extraData, fields: extraFields, prefix: '', relaId: 'id' },
                 { data: curStageData, fields: ['contract_qty', 'contract_expr', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty', 'postil'], prefix: '', relaId: 'pid' },
                 { data: endStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty' ], prefix: 'end_', relaId: 'pid' },
             ]);

+ 67 - 24
app/controller/tender_controller.js

@@ -188,6 +188,38 @@ module.exports = app => {
             }
         }
 
+        async _listDetailCache(view, modal = '') {
+            try {
+                // 获取用户新建标段权利
+                const accountInfo = await this.ctx.service.projectAccount.getDataById(this.ctx.session.sessionUser.accountId);
+                const userPermission = accountInfo !== undefined && accountInfo.permission !== ''
+                    ? JSON.parse(accountInfo.permission) : null;
+                const tenderList = await this.ctx.service.tender.getList('', userPermission, this.ctx.session.sessionUser.is_admin);
+                for (const t of tenderList) {
+                    await this.ctx.service.tenderCache.loadTenderCache(t, this.ctx.session.sessionUser.accountId);
+                }
+                const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
+                const valuations = await this.ctx.service.valuation.getProjectValidValuation(this.ctx.session.sessionProject.id);
+                const renderData = {
+                    tenderList,
+                    tenderConst,
+                    settingConst,
+                    categoryData,
+                    measureType: tenderConst.measureType,
+                    jsFiles: this.app.jsFiles.common.concat(this.jsFiles),
+                    auditConst,
+                    userPermission,
+                    valuations,
+                    uid: this.ctx.session.sessionUser.accountId,
+                    pid: this.ctx.session.sessionProject.id,
+                };
+                await this.layout(view, renderData, modal);
+            } catch (err) {
+                this.log(err);
+                this.ctx.redirect('/dashboard');
+            }
+        }
+
         async _list(view, renderData, modal = '', list_status = '') {
             try {
                 renderData.tenderList = await this.ctx.service.tender.getList(list_status, renderData.userPermission, this.ctx.session.sessionUser.is_admin);
@@ -250,7 +282,7 @@ module.exports = app => {
          */
         async listInfo(ctx) {
             this.jsFiles = this.app.jsFiles.tender.info;
-            await this._listDetail('tender/info.ejs', 'tender/modal.ejs');
+            await this._listDetailCache('tender/info.ejs', 'tender/modal.ejs');
         }
 
         /**
@@ -261,6 +293,28 @@ module.exports = app => {
          */
         async listProgress(ctx) {
             this.jsFiles = this.app.jsFiles.tender.progress;
+            await this._listDetailCache('tender/progress.ejs', 'tender/modal.ejs');
+        }
+
+        /**
+         * 标段概况(Get)
+         *
+         * @param {object} ctx - egg全局变量
+         * @return {void}
+         */
+        async listInfoOrg(ctx) {
+            this.jsFiles = this.app.jsFiles.tender.info;
+            await this._listDetail('tender/info.ejs', 'tender/modal.ejs');
+        }
+
+        /**
+         * 计量进度(Get)
+         *
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async listProgressOrg(ctx) {
+            this.jsFiles = this.app.jsFiles.tender.progress;
             await this._listDetail('tender/progress.ejs', 'tender/modal.ejs');
         }
 
@@ -282,29 +336,6 @@ module.exports = app => {
                     userPermission,
                 };
                 await this._list('tender/manage.ejs', renderData, 'tender/manage_modal.ejs', 'manage');
-                // 获取用户新建标段权利
-                // const accountInfo = await this.ctx.service.projectAccount.getDataById(this.ctx.session.sessionUser.accountId);
-                // const userPermission = accountInfo !== undefined && accountInfo.permission !== '' ? JSON.parse(accountInfo.permission) : null;
-                //
-                // const tenderList = await this.ctx.service.tender.getList('manage', userPermission);
-                // for (const t of tenderList) {
-                //     t.lastStage = await this.ctx.service.stage.getLastestStage(t.id, true);
-                //     t.completeStage = await this.ctx.service.stage.getLastestCompleteStage(t.id);
-                // }
-                // const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
-                // const valuations = await this.ctx.service.valuation.getProjectValidValuation(this.ctx.session.sessionProject.id);
-                // const renderData = {
-                //     tenderList,
-                //     tenderConst,
-                //     settingConst,
-                //     categoryData,
-                //     measureType: tenderConst.measureType,
-                //     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.tender.manage),
-                //     auditConst,
-                //     userPermission,
-                //     valuations,
-                // };
-                // await this.layout('tender/manage.ejs', renderData, 'tender/manage_modal.ejs');
             } else {
                 this.ctx.redirect(ctx.request.header.referer);
             }
@@ -1566,6 +1597,18 @@ module.exports = app => {
                 ctx.ajaxErrorBody(err, '保存数据错误');
             }
         }
+
+        async refreshCache(ctx) {
+            try {
+                const tid = ctx.query.tid;
+                if (!tid) throw '参数错误';
+                const tender = await this.ctx.service.tender.getTender(tid);
+                await this.ctx.service.tenderCache.refreshTenderCache(tender);
+            } catch(err) {
+                ctx.log(err);
+            }
+            ctx.redirect(ctx.request.header.referer);
+        }
     }
 
     return TenderController;

+ 31 - 27
app/lib/revise_price.js

@@ -60,12 +60,13 @@ class revisePriceCalc {
      * @return { inseretPosData, insertBillsData }
      */
     async newStagePriceChange(newStage, preStage, transaction) {
+        const pcTp = { contract_pc_tp: 0, qc_pc_tp: 0, pc_tp: 0, positive_qc_pc_tp: 0, negative_qc_pc_tp: 0 };
         // 获取未执行的单价变更,无单价变更不执行
         this.price = await this.ctx.service.revisePrice.getAllDataByCondition({ where: { tid: newStage.tid, valid: 1, use_stage: 0 } });
-        if (this.price.length === 0) return;
+        if (this.price.length === 0) return pcTp;
         // 无截止上期数据不执行
         const preBillsData = await this.ctx.service.stageBillsFinal.getAllDataByCondition({ where: { sid: preStage.id } });
-        if (preBillsData.length === 0) return;
+        if (preBillsData.length === 0) return pcTp;
 
         // 加载树结构
         const bills = await this.ctx.service.ledger.getData(newStage.tid);
@@ -98,16 +99,16 @@ class revisePriceCalc {
         });
         if (result.ibData.length > 0) await transaction.insert(this.ctx.service.stageBillsPc.tableName, result.ibData);
 
-        let contract_pc_tp = 0, qc_pc_tp = 0, pc_tp = 0, positive_qc_pc_tp = 0, negative_qc_pc_tp = 0;
         for (const ibc of result.ibData) {
-            contract_pc_tp = helper.add(contract_pc_tp, ibc.contract_pc_tp);
-            qc_pc_tp = helper.add(qc_pc_tp, ibc.qc_pc_tp);
-            pc_tp = helper.add(pc_tp, ibc.pc_tp);
-            positive_qc_pc_tp = helper.add(positive_qc_pc_tp, ibc.positive_qc_pc_tp);
-            negative_qc_pc_tp = helper.add(negative_qc_pc_tp, ibc.negative_qc_pc_tp);
+            pcTp.contract_pc_tp = helper.add(pcTp.contract_pc_tp, ibc.contract_pc_tp);
+            pcTp.qc_pc_tp = helper.add(pcTp.qc_pc_tp, ibc.qc_pc_tp);
+            pcTp.pc_tp = helper.add(pcTp.pc_tp, ibc.pc_tp);
+            pcTp.positive_qc_pc_tp = helper.add(pcTp.positive_qc_pc_tp, ibc.positive_qc_pc_tp);
+            pcTp.negative_qc_pc_tp = helper.add(pcTp.negative_qc_pc_tp, ibc.negative_qc_pc_tp);
         }
         await transaction.update(this.ctx.service.stage.tableName,
-            { id: newStage.id, contract_pc_tp, qc_pc_tp, pc_tp, positive_qc_pc_tp, negative_qc_pc_tp, check_calc: true, cache_time_l: new Date() });
+            { id: newStage.id, ...pcTp, check_calc: true, cache_time_l: new Date() });
+        return pcTp;
     }
 
     /**
@@ -117,9 +118,10 @@ class revisePriceCalc {
      * @param {Object} transaction - 事务
      */
     async stageCheckAgainPriceChange(stage, auditOrder, transaction) {
+        const pcTp = { contract_pc_tp: 0, qc_pc_tp: 0, pc_tp: 0, positive_qc_pc_tp: 0, negative_qc_pc_tp: 0 };
         // 获取未执行的单价变更,无单价变更不执行
         this.price = await this.ctx.service.revisePrice.getAllDataByCondition({ where: { tid: stage.tid, valid: 1, use_stage: 0 } });
-        if (this.price.length === 0) return;
+        if (this.price.length === 0) return pcTp;
 
         const curBillsData = await this.ctx.service.stageBills.getLastestStageData2(stage.tid, stage.id);
         const preBillsData = await this.ctx.service.stageBillsFinal.getAllDataByCondition({ where: { tid: stage.tid, sorder: stage.order - 1 } });
@@ -182,16 +184,16 @@ class revisePriceCalc {
         if (result.bpcData.length > 0) await transaction.insert(this.ctx.service.stageBillsPc.tableName, result.bpcData);
         if (result.scData.length > 0) await transaction.updateRows(this.ctx.service.stageChange.tableName, result.scData);
 
-        let contract_pc_tp = 0, qc_pc_tp = 0, pc_tp = 0, positive_qc_pc_tp = 0, negative_qc_pc_tp = 0;
         for (const bpc of result.bpcData) {
-            contract_pc_tp = helper.add(contract_pc_tp, bpc.contract_pc_tp);
-            qc_pc_tp = helper.add(qc_pc_tp, bpc.qc_pc_tp);
-            pc_tp = helper.add(pc_tp, bpc.pc_tp);
-            positive_qc_pc_tp = helper.add(positive_qc_pc_tp, bpc.positive_qc_pc_tp);
-            negative_qc_pc_tp = helper.add(negative_qc_pc_tp, bpc.negative_qc_pc_tp);
+            pcTp.contract_pc_tp = helper.add(pcTp.contract_pc_tp, bpc.contract_pc_tp);
+            pcTp.qc_pc_tp = helper.add(pcTp.qc_pc_tp, bpc.qc_pc_tp);
+            pcTp.pc_tp = helper.add(pcTp.pc_tp, bpc.pc_tp);
+            pcTp.positive_qc_pc_tp = helper.add(pcTp.positive_qc_pc_tp, bpc.positive_qc_pc_tp);
+            pcTp.negative_qc_pc_tp = helper.add(pcTp.negative_qc_pc_tp, bpc.negative_qc_pc_tp);
         }
         await transaction.update(this.ctx.service.stage.tableName,
-            { id: stage.id, contract_pc_tp, qc_pc_tp, pc_tp, positive_qc_pc_tp, negative_qc_pc_tp, check_calc: true, cache_time_l: new Date() });
+            { id: stage.id, ...pc_tp, check_calc: true, cache_time_l: new Date() });
+        return pcTp;
     }
 
     /**
@@ -244,8 +246,9 @@ class revisePriceCalc {
         if (revisePriceUpdate.length > 0) await transaction.updateRows(this.ctx.service.revisePrice.tableName, revisePriceUpdate);
     }
     async _calcStage(stage, bills, transaction) {
+        const pcTp = { contract_pc_tp: 0, qc_pc_tp: 0, pc_tp: 0, positive_qc_pc_tp: 0, negative_qc_pc_tp: 0 };
         // 无单价变更不执行
-        if (this.price.length === 0) return;
+        if (this.price.length === 0) return pcTp;
 
         const curBillsData = await this.ctx.service.stageBills.getLastestStageData2(stage.tid, stage.id);
         const preBillsData = await this.ctx.service.stageBillsFinal.getAllDataByCondition({ where: { tid: stage.tid, sorder: stage.order - 1 } });
@@ -314,16 +317,16 @@ class revisePriceCalc {
         if (result.bpcData.length > 0) await transaction.insert(this.ctx.service.stageBillsPc.tableName, result.bpcData);
         if (result.scData.length > 0) await transaction.updateRows(this.ctx.service.stageChange.tableName, result.scData);
 
-        let contract_pc_tp = 0, qc_pc_tp = 0, pc_tp = 0, positive_qc_pc_tp = 0, negative_qc_pc_tp = 0;
         for (const bpc of result.bpcData) {
-            contract_pc_tp = helper.add(contract_pc_tp, bpc.contract_pc_tp);
-            qc_pc_tp = helper.add(qc_pc_tp, bpc.qc_pc_tp);
-            pc_tp = helper.add(pc_tp, bpc.pc_tp);
-            positive_qc_pc_tp = helper.add(positive_qc_pc_tp, bpc.positive_qc_pc_tp);
-            negative_qc_pc_tp = helper.add(negative_qc_pc_tp, bpc.negative_qc_pc_tp);
+            pcTp.contract_pc_tp = helper.add(pcTp.contract_pc_tp, bpc.contract_pc_tp);
+            pcTp.qc_pc_tp = helper.add(pcTp.qc_pc_tp, bpc.qc_pc_tp);
+            pcTp.pc_tp = helper.add(pcTp.pc_tp, bpc.pc_tp);
+            pcTp.positive_qc_pc_tp = helper.add(pcTp.positive_qc_pc_tp, bpc.positive_qc_pc_tp);
+            pcTp.negative_qc_pc_tp = helper.add(pcTp.negative_qc_pc_tp, bpc.negative_qc_pc_tp);
         }
         await transaction.update(this.ctx.service.stage.tableName,
-            { id: stage.id, contract_pc_tp, qc_pc_tp, pc_tp, positive_qc_pc_tp, negative_qc_pc_tp, check_calc: true, cache_time_l: new Date() });
+            { id: stage.id, ...pcTp, check_calc: true, cache_time_l: new Date() });
+        return pcTp;
     }
     /**
      * 计算修订台账
@@ -362,15 +365,16 @@ class revisePriceCalc {
 
         // 应用到未审完成期
         const latestStage = await this.ctx.service.stage.getLastestStage(revise.tid, true);
-        if (latestStage && latestStage.status !== audit.stage.status.checked) await this._calcStage(latestStage, xmj, transaction);
+        if (latestStage && latestStage.status !== audit.stage.status.checked) return await this._calcStage(latestStage, xmj, transaction);
     }
     async calcRevise(revise, transaction) {
         if (revise.tid !== this.ctx.tender.id) throw '数据错误';
 
         this.price = await this.ctx.service.revisePrice.getAllDataByCondition({ where: { rid: revise.id } });
-        await this.calcReviseLedger(revise, transaction);
+        const pcTp = await this.calcReviseLedger(revise, transaction);
         // 引用到所有工程变更
         await this.calcAllChanges(revise.tid, transaction);
+        return pcTp;
     }
 }
 

+ 0 - 1
app/public/js/budget_detail.js

@@ -703,7 +703,6 @@ $(document).ready(() => {
         page: 'budget' + window.location.pathname.split('/')[3],
         tid: window.location.pathname.split('/')[2],
     };
-    console.log(window.location.pathname.split('/')[2]);
     // 展开收起标准清单
     $('a', 'ul.right-nav').bind('click', function (e) {
         e.preventDefault();

+ 8 - 6
app/public/js/change_revise.js

@@ -2481,12 +2481,13 @@ $(document).ready(() => {
                         searchEmpty: true,
                         resultSpreadSetting: {
                             cols: [
-                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@', readOnly: true},
-                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
-                                {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@', readOnly: true},
-                                {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@', readOnly: true},
-                                {title: '单价', field: 'unit_price', hAlign: 2, width: 50, readOnly: true},
-                                {title: '数量', field: 'quantity', hAlign: 2, width: 50, readOnly: true},
+                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@'},
+                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@'},
+                                {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@'},
+                                {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@'},
+                                {title: '单价', field: 'unit_price', hAlign: 2, width: 50},
+                                {title: '数量', field: 'quantity', hAlign: 2, width: 50},
+                                {title: '部位', field: 'bw', hAlign: 2, width: 90},
                             ],
                             emptyRows: 0,
                             headRows: 1,
@@ -2496,6 +2497,7 @@ $(document).ready(() => {
                             headerFont: '12px 微软雅黑',
                             font: '12px 微软雅黑',
                             selectedBackColor: '#fffacd',
+                            readOnly: true,
                         },
                         afterLocated: function () {
                             posSpreadObj.loadCurPosData();

+ 8 - 6
app/public/js/ledger.js

@@ -2456,12 +2456,13 @@ $(document).ready(function() {
                         searchSpread: ledgerSpread,
                         resultSpreadSetting: {
                             cols: [
-                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@', readOnly: true},
-                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
-                                {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@', readOnly: true},
-                                {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@', readOnly: true},
-                                {title: '单价', field: 'unit_price', hAlign: 2, width: 50, readOnly: true},
-                                {title: '数量', field: 'quantity', hAlign: 2, width: 50, readOnly: true},
+                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@'},
+                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@'},
+                                {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@'},
+                                {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@'},
+                                {title: '单价', field: 'unit_price', hAlign: 2, width: 50},
+                                {title: '数量', field: 'quantity', hAlign: 2, width: 50},
+                                {title: '部位', field: 'bw', hAlign: 2, width: 90},
                             ],
                             emptyRows: 0,
                             headRows: 1,
@@ -2471,6 +2472,7 @@ $(document).ready(function() {
                             headerFont: '12px 微软雅黑',
                             font: '12px 微软雅黑',
                             selectedBackColor: '#fffacd',
+                            readOnly: true,
                         },
                         afterLocated: function () {
                             posOperationObj.loadCurPosData();

+ 8 - 6
app/public/js/ledger_audit.js

@@ -217,12 +217,13 @@ $(document).ready(() => {
                         searchSpread: ledgerSpread,
                         resultSpreadSetting: {
                             cols: [
-                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@', readOnly: true},
-                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
-                                {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@', readOnly: true},
-                                {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@', readOnly: true},
-                                {title: '单价', field: 'unit_price', hAlign: 2, width: 50, readOnly: true},
-                                {title: '数量', field: 'quantity', hAlign: 2, width: 50, readOnly: true},
+                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@'},
+                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@'},
+                                {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@'},
+                                {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@'},
+                                {title: '单价', field: 'unit_price', hAlign: 2, width: 50},
+                                {title: '数量', field: 'quantity', hAlign: 2, width: 50},
+                                {title: '部位', field: 'bw', hAlign: 2, width: 90},
                             ],
                             emptyRows: 0,
                             headRows: 1,
@@ -232,6 +233,7 @@ $(document).ready(() => {
                             headerFont: '12px 微软雅黑',
                             font: '12px 微软雅黑',
                             selectedBackColor: '#fffacd',
+                            readOnly: true
                         },
                         afterLocated: function () {
                             loadCurPosData();

+ 5 - 5
app/public/js/material_checklist.js

@@ -419,7 +419,7 @@ $(document).ready(() => {
         const sheet = ledgerSpread.getActiveSheet();
         const select = SpreadJsObj.getSelectObject(sheet);
         const gclIndex = _.findIndex(gclGatherData, { b_code: select.b_code, name: select.name, unit: select.unit, unit_price: select.unit_price });
-        const gcl = gclGatherData[gclIndex].leafXmjs.filter(item => item.gather_qty !== null && item.gather_qty !== undefined);
+        const gcl = gclGatherData[gclIndex].leafXmjs;
         const ms_id = isStageSelf ? materialStageData[0].id : null;
         const index = materialChecklistData.indexOf(select);
         const datas = [];
@@ -481,7 +481,7 @@ $(document).ready(() => {
                 const select = SpreadJsObj.getSelectObject(sheet);
                 const index = materialChecklistData.indexOf(select);
                 const gclIndex = _.findIndex(gclGatherData, { b_code: select.b_code, name: select.name, unit: select.unit, unit_price: select.unit_price });
-                const gcl = gclGatherData[gclIndex].leafXmjs.filter(item => item.gather_qty !== null && item.gather_qty !== undefined);
+                const gcl = gclGatherData[gclIndex].leafXmjs;
                 const datas = [];
                 const ms_id = isStageSelf ? materialStageData[0].id : null;
                 for (const xmj of gcl) {
@@ -591,7 +591,7 @@ $(document).ready(() => {
                     const ledgerSheet = ledgerSpread.getActiveSheet();
                     const ledgerSelect = SpreadJsObj.getSelectObject(ledgerSheet);
                     const gclIndex = _.findIndex(gclGatherData, { b_code: ledgerSelect.b_code, name: ledgerSelect.name, unit: ledgerSelect.unit, unit_price: ledgerSelect.unit_price });
-                    const gcl = gclGatherData[gclIndex].leafXmjs.filter(item => item.gather_qty !== null && item.gather_qty !== undefined);
+                    const gcl = gclGatherData[gclIndex].leafXmjs;
                     const datas = [];
                     const ms_id = isStageSelf ? materialStageData[0].id : null;
                     for (const xmj of gcl) {
@@ -713,7 +713,7 @@ $(document).ready(() => {
                 const ledgerSheet = ledgerSpread.getActiveSheet();
                 const ledgerSelect = SpreadJsObj.getSelectObject(ledgerSheet);
                 const gclIndex = _.findIndex(gclGatherData, { b_code: ledgerSelect.b_code, name: ledgerSelect.name, unit: ledgerSelect.unit, unit_price: ledgerSelect.unit_price });
-                const gcl = gclGatherData[gclIndex].leafXmjs.filter(item => item.gather_qty !== null && item.gather_qty !== undefined);
+                const gcl = gclGatherData[gclIndex].leafXmjs;
                 const datas = [];
                 const ms_id = isStageSelf ? materialStageData[0].id : null;
                 for (const xmj of gcl) {
@@ -1311,7 +1311,7 @@ $(document).ready(() => {
                 }
 
                 const gclIndex = _.findIndex(gclGatherData, { b_code: t.b_code, name: t.name, unit: t.unit, unit_price: t.unit_price ? parseFloat(t.unit_price) : null });
-                const gcl = gclGatherData[gclIndex].leafXmjs.filter(item => item.gather_qty !== null && item.gather_qty !== undefined);
+                const gcl = gclGatherData[gclIndex].leafXmjs;
                 const ms_id = isStageSelf ? materialStageData[0].id : null;
                 // const index = materialChecklistData.indexOf(select);
                 const datas = [];

+ 8 - 6
app/public/js/revise.js

@@ -2705,12 +2705,13 @@ $(document).ready(() => {
                         searchSpread: billsSpread,
                         resultSpreadSetting: {
                             cols: [
-                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@', readOnly: true},
-                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
-                                {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@', readOnly: true},
-                                {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@', readOnly: true},
-                                {title: '单价', field: 'unit_price', hAlign: 2, width: 50, readOnly: true},
-                                {title: '数量', field: 'quantity', hAlign: 2, width: 50, readOnly: true},
+                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@'},
+                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@'},
+                                {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@'},
+                                {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@'},
+                                {title: '单价', field: 'unit_price', hAlign: 2, width: 50},
+                                {title: '数量', field: 'quantity', hAlign: 2, width: 50},
+                                {title: '部位', field: 'bw', hAlign: 2, width: 90},
                             ],
                             emptyRows: 0,
                             headRows: 1,
@@ -2720,6 +2721,7 @@ $(document).ready(() => {
                             headerFont: '12px 微软雅黑',
                             font: '12px 微软雅黑',
                             selectedBackColor: '#fffacd',
+                            readOnly: true,
                         },
                         afterLocated: function () {
                             posSpreadObj.loadCurPosData();

+ 8 - 6
app/public/js/revise_history.js

@@ -234,12 +234,13 @@ $(document).ready(() => {
                         searchSpread: billsSpread,
                         resultSpreadSetting: {
                             cols: [
-                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@', readOnly: true},
-                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
-                                {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@', readOnly: true},
-                                {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@', readOnly: true},
-                                {title: '单价', field: 'unit_price', hAlign: 2, width: 50, readOnly: true},
-                                {title: '数量', field: 'quantity', hAlign: 2, width: 50, readOnly: true},
+                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@'},
+                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@'},
+                                {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@'},
+                                {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@'},
+                                {title: '单价', field: 'unit_price', hAlign: 2, width: 50},
+                                {title: '数量', field: 'quantity', hAlign: 2, width: 50},
+                                {title: '部位', field: 'bw', hAlign: 2, width: 90},
                             ],
                             emptyRows: 0,
                             headRows: 1,
@@ -249,6 +250,7 @@ $(document).ready(() => {
                             headerFont: '12px 微软雅黑',
                             font: '12px 微软雅黑',
                             selectedBackColor: '#fffacd',
+                            readOnly: true,
                         },
                         afterLocated: function () {
                             posSpreadObj.loadCurPosData();

+ 31 - 0
app/public/js/shares/cs_tools.js

@@ -527,6 +527,36 @@ const showSelectTab = function(select, spread, afterShow) {
                 searchBills();
             }
         };
+        const get18Bw = function(tree, data) {
+            let parent = tree.getParent(data);
+            while (parent && parent.code.test(/^[a-zA-Z]/)) {
+                parent = tree.getParent(parent);
+            }
+            return parent ? parent.code : '';
+        };
+        const get08Bw = function(tree, data) {
+            let parent = tree.getParent(data);
+            let lastXmjCode = '', level4XmjCode = '';
+            while (parent) {
+                if (parent.code && !lastXmjCode) lastXmjCode = parent.code;
+                if (parent.code && parent.level === 4) level4XmjCode = parent.code;
+                parent = tree.getParent(parent);
+            }
+            return level4XmjCode || lastXmjCode;
+        };
+        const getBw = function (data) {
+            if (!data.b_code) return '';
+            if (searchSheet.zh_dataType !== SpreadJsObj.DataType.Tree) return '';
+
+            const sortTree = searchSheet.zh_tree;
+            if (!sortTree.checkCodeType) return '';
+
+            if (sortTree.checkCodeType() === '18') {
+                return get18Bw(sortTree, data)
+            } else {
+                return get08Bw(sortTree, data);
+            }
+        };
         const searchBills = function () {
             const keyword = $('#searchKeyword', obj).val();
             const keyNum = _.toNumber(keyword);
@@ -540,6 +570,7 @@ const showSelectTab = function(select, spread, afterShow) {
                 ) {
                     const data = JSON.parse(JSON.stringify(node));
                     data.visible = true;
+                    data.bw = getBw(data);
                     searchResult.push(data);
                 }
             }

+ 1 - 0
app/public/js/sr_detail.js

@@ -1073,6 +1073,7 @@ $(document).ready(() => {
                             {title: '单价', field: 'unit_price', hAlign: 2, width: 50},
                             {title: '数量', field: 'quantity', hAlign: 2, width: 50},
                             {title: '完成率(%)', field: 'complete_percent', hAlign: 2, width: 70},
+                            {title: '部位', field: 'bw', hAlign: 2, width: 90},
                         ],
                         emptyRows: 0,
                         headRows: 1,

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

@@ -4089,6 +4089,7 @@ $(document).ready(() => {
                             {title: '单价', field: 'unit_price', hAlign: 2, width: 50},
                             {title: '数量', field: 'quantity', hAlign: 2, width: 50},
                             {title: '完成率(%)', field: 'end_gather_percent', hAlign: 2, width: 70},
+                            {title: '部位', field: 'bw', hAlign: 2, width: 90},
                         ],
                         emptyRows: 0,
                         headRows: 1,

+ 2 - 0
app/public/js/tender_list.js

@@ -320,7 +320,9 @@ function recursiveGetTenderNodeHtml (node, arr, pid) {
     html.push('</td>');
     // 审批状态
     html.push('<td style="width: 15%">');
+    html.push(`<span class="${node.lastStage ? auditConst.stage.tiStatusStringClass[node.lastStage.status] : auditConst.ledger.tiStatusStringClass[node.ledger_status]}">`);
     html.push(node.lastStage ? auditConst.stage.statusString[node.lastStage.status] : auditConst.ledger.statusString[node.ledger_status]);
+    html.push('</span>');
     html.push(node.status_users ? '(' + node.status_users + ')' : '');
     html.push('</td>');
     html.push('</tr>');

+ 29 - 8
app/public/js/tender_list_info.js

@@ -270,7 +270,15 @@ function initTenderTree () {
         return tenderCategory;
     }
     function calculateTender(tender) {
-        if (tender.lastStage) {
+        if (tender.stage_tp) {
+            tender.gather_tp = ZhCalc.sum([tender.stage_tp.contract_tp, tender.stage_tp.qc_tp, tender.stage_tp.pc_tp]);
+            tender.end_contract_tp = ZhCalc.sum([tender.stage_tp.pre_contract_tp, tender.stage_tp.contract_tp, tender.stage_tp.contract_pc_tp]);
+            tender.end_qc_tp = ZhCalc.sum([tender.stage_tp.pre_qc_tp, tender.stage_tp.qc_tp, tender.stage_tp.qc_pc_tp]);
+            tender.end_gather_tp = ZhCalc.add(tender.end_contract_tp, tender.end_qc_tp);
+            tender.pre_gather_tp = ZhCalc.add(tender.stage_tp.pre_contract_tp, tender.stage_tp.pre_qc_tp);
+            tender.yf_tp = ZhCalc.add(tender.stage_tp.yf_tp);
+            tender.end_yf_tp = ZhCalc.add(tender.stage_tp.pre_yf_tp, tender.yf_tp);
+        } else if (tender.lastStage) {
             tender.gather_tp = ZhCalc.sum([tender.lastStage.contract_tp, tender.lastStage.qc_tp, tender.lastStage.pc_tp]);
             tender.end_contract_tp = ZhCalc.sum([tender.lastStage.pre_contract_tp, tender.lastStage.contract_tp, tender.lastStage.contract_pc_tp]);
             tender.end_qc_tp = ZhCalc.sum([tender.lastStage.pre_qc_tp, tender.lastStage.qc_tp, tender.lastStage.qc_pc_tp]);
@@ -326,19 +334,32 @@ function recursiveGetTenderNodeHtml (node, arr, pid) {
     // 计量进度
     html.push('<td style="width: 105px">');
     if (!node.cid && node.cur_flow) {
-        html.push(node.cur_flow.title + ' (' + '<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>' + ')');
+        if (node.progress) {
+            html.push(node.progress.title + ' (' + '<span class="' + node.progress.status_class +'">' + node.progress.status + '</span>' + ')');
+        } else {
+            html.push(node.cur_flow.title + ' (' + '<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>' + ')');
+        }
     }
     html.push('</td>');
     // 当前流程
     html.push('<td style="width: 230px">');
     if (!node.cid && node.cur_flow) {
-        html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? '' :
-            '<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="'+ (node.lastStage ? 'stage' : 'ledger') +'"' +
-            ' data-tender="'+ node.id +'" data-order="'+ (node.lastStage ? node.lastStage.order : '') +'">');
-        html.push(node.cur_flow.name+ (node.cur_flow.role ? '-'+node.cur_flow.role  : ''));
-        html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? ' ':
+        if (node.stage_status !== undefined) {
+            const curUser = node.cur_flow.name + (node.cur_flow.role ? '-'+node.cur_flow.role  : '');
+            html.push((node.stage_status === auditConst.stage.status.uncheck || node.ledger_status === auditConst.ledger.status.uncheck)
+                ? curUser
+                : `<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="${node.stage_count ? 'stage' : 'ledger'}" data-tender="${node.id}" data-order="${node.stage_count ? node.stage_count + '' : ''}">${curUser}</a>`
+            );
+            html.push(`<span class="${node.progress.status_class} ml-1">${node.progress.status}</span>`);
+        } else {
+            html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? '' :
+                '<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="'+ (node.lastStage ? 'stage' : 'ledger') +'"' +
+                ' data-tender="'+ node.id +'" data-order="'+ (node.lastStage ? node.lastStage.order : '') +'">');
+            html.push(node.cur_flow.name+ (node.cur_flow.role ? '-'+node.cur_flow.role  : ''));
+            html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? ' ':
                 '</a> ');
-        html.push('<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>');
+            html.push('<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>');
+        }
     }
     html.push('</td>');
     // 上一流程审批时间

+ 1 - 0
app/public/js/tender_list_manage.js

@@ -295,6 +295,7 @@ function recursiveGetTenderNodeHtml (node, arr, pid) {
         } else {
             html.push('<button class="btn btn-outline-secondary btn-sm ml-1" data-toggle="tooltip" data-placement="top" title="请先删除所有期">删除</button>');
         }
+        if (cache) html.push(`<a href="/list/refreshCache?tid=${node.id}" class="btn btn-outline-primary btn-sm ml-1">更新缓存</a>`);
     }
     html.push('</td>');
     html.push('</tr>');

+ 31 - 10
app/public/js/tender_list_progress.js

@@ -198,6 +198,7 @@ function calculateParent(node) {
         node.sum_tp = 0;
         node.lastStage = 0;
         node.contract_price = 0;
+        node.stage_count = 0;
         for (const c of node.children) {
             calculateParent(c);
             node.end_qc_tp = ZhCalc.add(node.end_qc_tp, c.end_qc_tp);
@@ -207,6 +208,7 @@ function calculateParent(node) {
             node.lastStage = c.cid
                 ? Math.max(node.lastStage, c.lastStage)
                 : (c.lastStage ? Math.max(node.lastStage, c.lastStage.order) : node.lastStage);
+            node.stage_count = c.cid ? Math.max(node.stage_count, c.stage_count) : (c.stage_count ? Math.max(node.stage_count, c.stage_count): node.stage_count);
             node.contract_price = ZhCalc.add(node.contract_price, c.contract_price);
         }
     }
@@ -265,7 +267,12 @@ function initTenderTree () {
         return tenderCategory;
     }
     function calculateTender(tender) {
-        if (tender.lastStage) {
+        if (tender.stage_tp) {
+            tender.end_qc_tp = ZhCalc.sum([tender.stage_tp.pre_qc_tp, tender.stage_tp.qc_tp, tender.stage_tp.qc_pc_tp]);
+            tender.pre_gather_tp = ZhCalc.add(tender.stage_tp.pre_contract_tp, tender.stage_tp.pre_qc_tp);
+            tender.gather_tp = ZhCalc.sum([tender.stage_tp.contract_tp, tender.stage_tp.qc_tp, tender.stage_tp.pc_tp]);
+            tender.sum_tp = ZhCalc.add(tender.total_price, tender.end_qc_tp);
+        } else if (tender.lastStage) {
             tender.end_qc_tp = ZhCalc.sum([tender.lastStage.pre_qc_tp, tender.lastStage.qc_tp, tender.lastStage.qc_pc_tp]);
             tender.pre_gather_tp = ZhCalc.add(tender.lastStage.pre_contract_tp, tender.lastStage.pre_qc_tp);
             tender.gather_tp = ZhCalc.sum([tender.lastStage.contract_tp, tender.lastStage.qc_tp, tender.lastStage.pc_tp]);
@@ -330,24 +337,38 @@ function recursiveGetTenderNodeHtml (node, arr, pid) {
     // 计量进度
     html.push('<td style="width: 8%">');
     if (!node.cid && node.cur_flow) {
-        html.push(node.cur_flow.title + ' (' + '<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>' + ')');
+        if (node.progress) {
+            html.push(node.progress.title + ' (' + '<span class="' + node.progress.status_class +'">' + node.progress.status + '</span>' + ')');
+        } else {
+            html.push(node.cur_flow.title + ' (' + '<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>' + ')');
+        }
     }
     html.push('</td>');
     // 当前流程
     html.push('<td style="width: 13%">');
     if (!node.cid && node.cur_flow) {
-        html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? '' :
-            '<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="'+ (node.lastStage ? 'stage' : 'ledger') +'"' +
-            ' data-tender="'+ node.id +'" data-order="'+ (node.lastStage ? node.lastStage.order : '') +'">');
-        html.push(node.cur_flow.name+ (node.cur_flow.role ? '-'+node.cur_flow.role  : ''));
-        html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? ' ':
-            '</a> ');
-        html.push('<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>');
+        if (node.stage_status !== undefined) {
+            const curUser = node.cur_flow.name + (node.cur_flow.role ? '-'+node.cur_flow.role  : '');
+            html.push((node.stage_status === auditConst.stage.status.uncheck || node.ledger_status === auditConst.ledger.status.uncheck)
+                ? curUser
+                : `<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="${node.stage_count ? 'stage' : 'ledger'}" data-tender="${node.id}" data-order="${node.stage_count ? node.stage_count + '' : ''}">${curUser}</a>`
+            );
+            html.push(`<span class="${node.progress.status_class} ml-1">${node.progress.status}</span>`);
+        } else {
+            html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? '' :
+                '<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="'+ (node.lastStage ? 'stage' : 'ledger') +'"' +
+                ' data-tender="'+ node.id +'" data-order="'+ (node.lastStage ? node.lastStage.order : '') +'">');
+            html.push(node.cur_flow.name+ (node.cur_flow.role ? '-'+node.cur_flow.role  : ''));
+            html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? ' ':
+                '</a> ');
+            html.push('<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>');
+        }
     }
     html.push('</td>');
     // 上一流程审批时间
     html.push('<td style="width: 8%">');
     if (!node.cid && node.pre_flow) {
+        if (node.name === '123456677') console.log(node.pre_flow);
         html.push(node.pre_flow.name + ' ' + moment(node.pre_flow.time).format('YYYY-MM-DD'));
     }
     html.push('</td>');
@@ -361,7 +382,7 @@ function recursiveGetTenderNodeHtml (node, arr, pid) {
     html.push('</td>');
     // 截止本期累计完成/本期完成/未完成
     html.push('<td>');
-    if (node.lastStage) {
+    if (node.lastStage || node.stage_count > 0) {
         html.push(getProgressHtml(node.sum_tp, node.pre_gather_tp, node.gather_tp));
     } else {
         html.push('');

+ 3 - 0
app/router.js

@@ -140,15 +140,18 @@ module.exports = app => {
     app.post('/list/load', sessionAuth, 'tenderController.listLoad');
     app.post('/list/load2', sessionAuth, 'tenderController.listLoad2');
     app.get('/list/info', sessionAuth, 'tenderController.listInfo');
+    app.get('/list/infoOrg', sessionAuth, 'tenderController.listInfoOrg');
 
     // 计量进度
     app.get('/list/progress', sessionAuth, 'tenderController.listProgress');
+    app.get('/list/progressOrg', sessionAuth, 'tenderController.listProgressOrg');
 
     // 管理标段
     app.get('/list/manage', sessionAuth, 'tenderController.listManage');
     app.post('/list/add', sessionAuth, 'tenderController.addTender');
     app.post('/list/update', sessionAuth, 'tenderController.updateTender');
     app.post('/list/del', sessionAuth, 'tenderController.deleteTender');
+    app.get('/list/refreshCache', sessionAuth, 'tenderController.refreshCache');
 
     // 标段概况
     app.get('/tender/:id', sessionAuth, tenderCheck, 'tenderController.tenderInfo');

+ 1 - 1
app/service/advance.js

@@ -98,7 +98,7 @@ module.exports = app => {
         async getSumAdvance(tid) {
             const sql = 'Select sum(cur_amount) as tp From ' + this.tableName + ' where tid = ?';
             const result = await this.db.queryOne(sql, [tid]);
-            return result ? result.tp : 0;
+            return result ? result.tp || 0 : 0;
         }
 
         /**

+ 56 - 28
app/service/budget_permission.js

@@ -20,72 +20,86 @@ module.exports = app => {
          */
         constructor(ctx) {
             super(ctx);
-            this.tableName = 'budget_permission';
-            this.PermissionConst = {
+            this.tableName = 'sub_project_permission';
+            this.BudgetPermissionConst = {
                 view: { title: '查看', value: 1 },
                 edit: { title: '编辑', value: 2 },
             };
+            this.FilePermissionConst = {
+                view: { title: '查看', value: 1 },
+                upload: { title: '上传文件', value: 2 },
+                edit: { title: '文件类别编辑', value: 3 },
+            };
+            this.ManagePermissionConst = {
+                rela: { title: '关联标段', value: 1 },
+            };
         }
 
+        async showSubTab(uid, type) {
+            const sql = `SELECT count(*) FROM ${this.tableName} WHERE ${type}_permission <> '' AND uid = ?`;
+            const result = await this.db.queryOne(sql, [uid]);
+            return result.count;
+        }
         async showBudget(uid) {
-            const count = await this.count({ pid: this.ctx.session.sessionProject.id, uid });
-            return count > 0;
+            return await this.showSubTab(uid, 'budget');
+        }
+        async showFile(uid) {
+            return await this.showSubTab(uid, 'file');
         }
 
-        async getBudgetPermission(bid) {
+        parsePermission(data) {
             const _ = this.ctx.helper._;
-            const result = await this.db.query(`SELECT bp.*, p.name, p.role 
-                FROM ${this.tableName} bp LEFT JOIN ${this.ctx.service.projectAccount.tableName} p
-                On bp.uid = p.id WHERE bid = ?`, [bid]);
-            result.forEach(x => {
-                x.permission = x.permission ? _.map(x.permission.split(','), _.toInteger) : []
+            const datas = data instanceof Array ? data : [data];
+            datas.forEach(x => {
+                x.budget_permission = x.budget_permission ? _.map(x.budget_permission.split(','), _.toInteger) : [];
+                x.file_permission = x.file_permission ? _.map(x.file_permission.split(','), _.toInteger) : [];
+                x.manage_permission = x.manage_permission ? _.map(x.manage_permission.split(','), _.toInteger) : [];
             });
+        }
+
+        async getBudgetPermission(subProjectId) {
+            const result = await this.db.query(`SELECT spp.*, p.name, p.role 
+                FROM ${this.tableName} spp LEFT JOIN ${this.ctx.service.projectAccount.tableName} p
+                On spp.uid = p.id WHERE spp.spid = ? and budget_permission <> ''`, [subProjectId]);
+            this.parsePermission(result);
             return result;
         }
 
         async getUserPermission() {
-            const _ = this.ctx.helper._;
             const result = await this.getAllDataByCondition({
                 where: { uid: this.ctx.session.sessionUser.accountId, pid: this.ctx.session.sessionProject.id }
             });
-            result.forEach(x => {
-                x.permission = x.permission ? _.map(x.permission.split(','), _.toInteger) : []
-            });
+            this.parsePermission(result);
             return result;
         }
 
         async getBudgetUserPermission(bid) {
             const _ = this.ctx.helper._;
             const result = await this.getDataByCondition({uid: this.ctx.session.sessionUser.accountId, bid});
-            if (result) result.permission = result.permission ? _.map(result.permission.split(','), _.toInteger) : [];
+            if (result) this.parsePermission(result);
             return result;
         }
 
-        async saveBudgetPermission(bid, member) {
-            const orgMember = await this.getAllDataByCondition({ where: { bid } });
-            const dm = [], um = [], im = [], cur = new Date();
+        async saveBudgetPermission(subProjectId, member) {
+            const orgMember = await this.getAllDataByCondition({ where: { spid: subProjectId } });
+            const um = [], im = [];
             for (const om of orgMember) {
-                const nm = member.find(x => { return om.uid === x.uid });
+                const nm = member.find(x => { return om.uid === x.uid; });
                 if (!nm) {
-                    dm.push(om.id);
+                    um.push({ id: om.id, budget_permission: '' });
                 } else {
-                    um.push({
-                        id: om.id,
-                        permission: nm.permission.join(','),
-                        modify_time: cur,
-                    });
+                    um.push({ id: om.id, budget_permission: nm.permission.join(',') });
                     member.splice(member.indexOf(nm), 1);
                 }
             }
             for (const m of member) {
                 im.push({
-                    pid: this.ctx.session.sessionProject.id, bid, uid: m.uid,
-                    permission: m.permission.join(','), in_time: cur, modify_time: cur,
+                    spid: subProjectId, pid: this.ctx.session.sessionProject.id, uid: m.uid,
+                    budget_permission: m.permission.join(',')
                 })
             }
             const conn = await this.db.beginTransaction();
             try {
-                if (dm.length > 0) await conn.delete(this.tableName, { id: dm });
                 if (um.length > 0) await conn.updateRows(this.tableName, um);
                 if (im.length > 0) await conn.insert(this.tableName, im);
                 await conn.commit();
@@ -94,6 +108,20 @@ module.exports = app => {
                 throw err;
             }
         }
+
+        async saveFilePermission(subProjectId, uid, permission) {
+            const member = await this.getDataByCondition({ where: { spid: subProjectId, uid } });
+            if (!permission) {
+                if (!member) return;
+                await this.defaultUpdate({ id: member.id, file_permission: '', manager_permission: '' });
+            } else {
+                if (!member) {
+                    await this.db.insert(this.tableName, { spid: subProjectId, uid, pid: this.ctx.sessionProject.id, ...permission });
+                } else {
+                    await this.db.update(this.tableName, { id: member.id, ...permission });
+                }
+            }
+        }
     }
 
     return BudgetPermission;

+ 4 - 0
app/service/ledger_audit.js

@@ -276,6 +276,7 @@ module.exports = app => {
                     deal_tp: sum.deal_tp,
                     his_id: his_id,
                 });
+                await this.ctx.service.tenderCache.updateLedgerCache4Start(transaction, tenderId, auditConst.status.checking, audit, sum);
 
                 // 添加短信通知-需要审批提醒功能
                 await this.ctx.helper.sendAliSms(audit.audit_id, smsTypeConst.const.TZ, smsTypeConst.judge.approval.toString(), SmsAliConst.template.ledger_check);
@@ -365,6 +366,7 @@ module.exports = app => {
                             status: auditConst.status.checking,
                             begin_time: time,
                         });
+                        await this.ctx.service.tenderCache.updateLedgerCache(transaction, tenderId, auditConst.status.checking, checkType, nextAudit);
                         await this.ctx.helper.sendAliSms(nextAudit.audit_id, smsTypeConst.const.TZ, smsTypeConst.judge.approval.toString(), SmsAliConst.template.ledger_check);
                         // 微信模板通知
                         const wechatData = {
@@ -379,6 +381,7 @@ module.exports = app => {
                             id: tenderId,
                             ledger_status: checkType,
                         });
+                        await this.ctx.service.tenderCache.updateLedgerCache(transaction, tenderId, checkType, checkType);
                         await this.ctx.service.tenderTag.saveTenderTag(tenderId, {ledger_time: new Date()}, transaction);
                         // const users = this._.pull(this._.map(auditList, 'audit_id'), audit.id);
                         await this.ctx.helper.sendAliSms(users, smsTypeConst.const.TZ, smsTypeConst.judge.result.toString(), SmsAliConst.template.ledger_result, {
@@ -401,6 +404,7 @@ module.exports = app => {
                         ledger_times: times + 1,
                         ledger_status: checkType,
                     });
+                    await this.ctx.service.tenderCache.updateLedgerCache(transaction, tenderId, checkType, checkType, { audit_id: this.ctx.tender.data.user_id });
                     // 拷贝新一次审核流程列表
                     const auditors = await this.getAllDataByCondition({
                         where: { tender_id: tenderId, times },

+ 1 - 1
app/service/ledger_extra.js

@@ -26,7 +26,7 @@ module.exports = app => {
         async getData(tid, columns) {
             if (!columns || columns.length === 0) return [];
 
-            return await this.getAllDataByCondition({
+            return await this.db.select(this.departTableName(tid), {
                 where: { tid },
                 columns: ['id', ...columns],
             });

+ 1 - 1
app/service/pos_extra.js

@@ -26,7 +26,7 @@ module.exports = app => {
         async getData(tid, columns) {
             if (!columns || columns.length === 0) return [];
 
-            return await this.getAllDataByCondition({
+            return await this.db.select(this.departTableName(tid), {
                 where: { tid },
                 columns: ['id', ...columns],
             });

+ 6 - 0
app/service/project_account.js

@@ -907,6 +907,12 @@ module.exports = app => {
                 });
             });
         }
+
+        async getAccountCacheData(id, defaultData) {
+            const sql = 'Select `name`, `company`, `role`, `mobile`, `telephone` From ' + this.tableName + ' where id = ?';
+            const result = await this.db.queryOne(sql, [id]);
+            return this._.assign(result, defaultData);
+        }
     }
 
     return ProjectAccount;

+ 2 - 1
app/service/revise_audit.js

@@ -453,7 +453,7 @@ module.exports = app => {
                         }
                         // 重算台账、计量、工程变更
                         const reviseCalc = new RevisePrice(this.ctx);
-                        await reviseCalc.calcRevise(revise, transaction);
+                        const pcTp = await reviseCalc.calcRevise(revise, transaction);
                         const sum = revise.sum || await this.ctx.service.reviseBills.addUp({
                             tender_id: revise.tid, /* , is_leaf: true*/
                         });
@@ -462,6 +462,7 @@ module.exports = app => {
                             total_price: sum.total_price,
                             deal_tp: sum.deal_tp,
                         });
+                        await this.ctx.service.tenderCache.updateStageCache4Revise(transaction, revise.tid, sum, pcTp);
                         // 清除变更新增部位maxLid缓存,防止树结构混乱
                         await this.ctx.service.changeLedger._removeCacheMaxLid(audit.tender_id);
                         // 短信通知-审批通过提醒功能

+ 4 - 1
app/service/stage.js

@@ -413,6 +413,7 @@ module.exports = app => {
                     throw '新增期合同支付数据失败';
                 }
                 // 新增期其他台账数据
+                let pcTp = { contract_pc_tp: 0, qc_pc_tp: 0, pc_tp: 0, positive_qc_pc_tp: 0, negative_qc_pc_tp: 0 };
                 if (preStage) {
                     const jgclResult = await this.ctx.service.stageJgcl.addInitialStageData(newStage, preStage, transaction);
                     if (!jgclResult) throw '初始化甲供材料数据失败';
@@ -424,8 +425,9 @@ module.exports = app => {
                     if (!tempResult) throw '初始化其他台账数据失败';
 
                     const priceCalc = new RevisePrice(this.ctx);
-                    await priceCalc.newStagePriceChange(newStage, preStage, transaction);
+                    pcTp = await priceCalc.newStagePriceChange(newStage, preStage, transaction);
                 }
+                await this.ctx.service.tenderCache.updateStageCache4Add(transaction, newStage, pcTp);
                 // 新增期拷贝报表相关配置/签名角色 等
                 if (preStage) {
                     const rptResult = await this.ctx.service.rptCustomDefine.addInitialStageData(newStage, preStage, transaction);
@@ -588,6 +590,7 @@ module.exports = app => {
                 //     await this.ctx.helper.syncNoticeSend(this.ctx.session.sessionProject.customType, JSON.stringify(base_data));
                 // }
                 await transaction.delete(this.tableName, { id });
+                await this.ctx.service.tenderCache.updateStageCache4Del(transaction, stageInfo);
                 await transaction.delete(this.ctx.service.pos.tableName, { add_stage: id });
                 await transaction.delete(this.ctx.service.stageAudit.tableName, { sid: id });
                 await transaction.delete(this.ctx.service.stageBills.tableName, { sid: id });

+ 60 - 109
app/service/stage_audit.js

@@ -255,6 +255,7 @@ module.exports = app => {
             await transaction.update(this.ctx.service.tender.tableName, {
                 id: this.ctx.tender.id, total_price: sum.total_price, deal_tp: sum.deal_tp
             });
+            return sum;
         }
 
         /**
@@ -276,7 +277,7 @@ module.exports = app => {
 
             const transaction = await this.db.beginTransaction();
             try {
-                await this._updateTender(transaction);
+                const ledgerTp = await this._updateTender(transaction);
                 await transaction.update(this.tableName, {
                     id: audit.id,
                     status: auditConst.status.checking,
@@ -293,25 +294,20 @@ module.exports = app => {
                 await this.ctx.service.stageTempLand.updateHistory(this.ctx.stage, transaction);
                 // 更新期数据
                 const tpData = await this.ctx.service.stageBills.getSumTotalPrice(this.ctx.stage);
-                this.ctx.stage.tp_history.push({
-                    times: this.ctx.stage.curTimes,
-                    order: 0,
+                const stageTp = {
                     contract_tp: tpData.contract_tp,
                     qc_tp: tpData.qc_tp,
                     positive_qc_tp: tpData.positive_qc_tp,
                     negative_qc_tp: tpData.negative_qc_tp,
                     yf_tp: yfPay.tp,
                     sf_tp: sfPay.tp,
-                });
+                };
+                this.ctx.stage.tp_history.push({ times: this.ctx.stage.curTimes, order: 0, ...stageTp });
+                await this.ctx.service.tenderCache.updateStageCache4Start(transaction, this.ctx.stage, auditConst.status.checking, audit, ledgerTp, stageTp);
                 await transaction.update(this.ctx.service.stage.tableName, {
                     id: stageId,
                     status: auditConst.status.checking,
-                    contract_tp: tpData.contract_tp,
-                    qc_tp: tpData.qc_tp,
-                    positive_qc_tp: tpData.positive_qc_tp,
-                    negative_qc_tp: tpData.negative_qc_tp,
-                    yf_tp: yfPay.tp,
-                    sf_tp: sfPay.tp,
+                    ...stageTp,
                     tp_history: JSON.stringify(this.ctx.stage.tp_history),
                     cache_time_r: this.ctx.stage.cache_time_l,
                 });
@@ -374,7 +370,7 @@ module.exports = app => {
             const transaction = await this.db.beginTransaction();
 
             try {
-                await this._updateTender(transaction);
+                const ledgerTp = await this._updateTender(transaction);
                 // 添加推送
                 const noticeContent = await this.getNoticeContent(pid, audit.tid, stageId, audit.aid, checkData.opinion);
                 const auditors = await this.getAuditGroupByListWithOwner(stageId, times);
@@ -407,16 +403,15 @@ module.exports = app => {
                 });
                 // 计算并合同支付最终数据
                 const [yfPay, sfPay] = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
-                this.ctx.stage.tp_history.push({
-                    times,
-                    order: audit.order,
+                const stageTp = {
                     contract_tp: tpData.contract_tp,
                     qc_tp: tpData.qc_tp,
                     positive_qc_tp: tpData.positive_qc_tp,
                     negative_qc_tp: tpData.negative_qc_tp,
                     yf_tp: yfPay.tp,
                     sf_tp: sfPay.tp,
-                });
+                };
+                this.ctx.stage.tp_history.push({ times, order: audit.order, ...stageTp });
                 // 无下一审核人表示,审核结束
                 if (nextAudit) {
                     // 复制一份下一审核人数据
@@ -436,15 +431,11 @@ module.exports = app => {
                     await transaction.update(this.ctx.service.stage.tableName, {
                         id: stageId,
                         status: auditConst.status.checking,
-                        contract_tp: tpData.contract_tp,
-                        qc_tp: tpData.qc_tp,
-                        positive_qc_tp: tpData.positive_qc_tp,
-                        negative_qc_tp: tpData.negative_qc_tp,
-                        yf_tp: yfPay.tp,
-                        sf_tp: sfPay.tp,
+                        ...stageTp,
                         tp_history: JSON.stringify(this.ctx.stage.tp_history),
                         cache_time_r: this.ctx.stage.cache_time_l,
                     });
+                    await this.ctx.service.tenderCache.updateStageCache4Flow(transaction, this.ctx.stage, auditConst.status.checking, audit, nextAudit, ledgerTp, stageTp);
                     // 多人协同,取消下一审批人存在的锁定
                     await this.ctx.service.stageAuditAss.cancelLock(this.ctx.stage, nextAudit.aid, transaction);
 
@@ -479,16 +470,12 @@ module.exports = app => {
                     await transaction.update(this.ctx.service.stage.tableName, {
                         id: stageId,
                         status: checkData.checkType,
-                        contract_tp: tpData.contract_tp,
-                        qc_tp: tpData.qc_tp,
-                        positive_qc_tp: tpData.positive_qc_tp,
-                        negative_qc_tp: tpData.negative_qc_tp,
-                        yf_tp: yfPay.tp,
-                        sf_tp: sfPay.tp,
+                        ...stageTp,
                         tp_history: JSON.stringify(this.ctx.stage.tp_history),
                         cache_time_r: this.ctx.stage.cache_time_l,
                         his_id,
                     });
+                    await this.ctx.service.tenderCache.updateStageCache4Flow(transaction, this.ctx.stage, checkData.checkType, audit, nextAudit, ledgerTp, stageTp);
                     await this.ctx.service.stagePay.cacheOrder(this.ctx.stage, transaction);
 
                     // 添加短信通知-审批通过提醒功能
@@ -543,7 +530,7 @@ module.exports = app => {
 
             const transaction = await this.db.beginTransaction();
             try {
-                await this._updateTender(transaction);
+                const ledgerTp = await this._updateTender(transaction);
                 // 添加推送
                 const noticeContent = await this.getNoticeContent(pid, audit.tid, stageId, audit.aid, checkData.opinion);
                 const defaultNoticeRecord = {
@@ -574,16 +561,15 @@ module.exports = app => {
 
                 // 计算并合同支付最终数据
                 const [yfPay, sfPay] = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
-                this.ctx.stage.tp_history.push({
-                    times,
-                    order: audit.order,
+                const stageTp = {
                     contract_tp: tpData.contract_tp,
                     qc_tp: tpData.qc_tp,
                     positive_qc_tp: tpData.positive_qc_tp,
                     negative_qc_tp: tpData.negative_qc_tp,
                     yf_tp: yfPay.tp,
                     sf_tp: sfPay.tp,
-                });
+                };
+                this.ctx.stage.tp_history.push({ times, order: audit.order, ...stageTp });
                 await transaction.update(this.tableName, {
                     id: audit.id,
                     status: checkData.checkType,
@@ -594,16 +580,12 @@ module.exports = app => {
                 await transaction.update(this.ctx.service.stage.tableName, {
                     id: stageId,
                     status: checkData.checkType,
-                    contract_tp: tpData.contract_tp,
-                    qc_tp: tpData.qc_tp,
-                    positive_qc_tp: tpData.positive_qc_tp,
-                    negative_qc_tp: tpData.negative_qc_tp,
+                    ...stageTp,
                     times: times + 1,
-                    yf_tp: yfPay.tp,
-                    sf_tp: sfPay.tp,
                     tp_history: JSON.stringify(this.ctx.stage.tp_history),
                     cache_time_r: this.ctx.stage.cache_time_l,
                 });
+                await this.ctx.service.tenderCache.updateStageCache4Flow(transaction, this.ctx.stage, checkData.checkType, { id: this.ctx.stage.user_id }, audit, ledgerTp, stageTp);
                 // 拷贝新一次审核流程列表
                 await transaction.insert(this.tableName, auditors);
                 // 计算该审批人最终数据
@@ -666,7 +648,7 @@ module.exports = app => {
             const tpData = await this.ctx.service.stageBills.getSumTotalPrice(this.ctx.stage);
             const transaction = await this.db.beginTransaction();
             try {
-                await this._updateTender(transaction);
+                const ledgerTp = await this._updateTender(transaction);
                 // 添加推送
                 const noticeContent = await this.getNoticeContent(pid, audit.tid, stageId, audit.aid, checkData.opinion);
                 const defaultNoticeRecord = {
@@ -698,36 +680,31 @@ module.exports = app => {
 
                 // 计算并合同支付最终数据
                 const [yfPay, sfPay] = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
-                this.ctx.stage.tp_history.push({
-                    times,
-                    order: audit.order,
+                const stageTp = {
                     contract_tp: tpData.contract_tp,
                     qc_tp: tpData.qc_tp,
                     positive_qc_tp: tpData.positive_qc_tp,
                     negative_qc_tp: tpData.negative_qc_tp,
                     yf_tp: yfPay.tp,
                     sf_tp: sfPay.tp,
-                });
+                };
+                this.ctx.stage.tp_history.push({ times, order: audit.order, ...stageTp });
                 // 同步 期信息
                 await transaction.update(this.ctx.service.stage.tableName, {
                     id: stageId,
-                    contract_tp: tpData.contract_tp,
-                    qc_tp: tpData.qc_tp,
-                    positive_qc_tp: tpData.positive_qc_tp,
-                    negative_qc_tp: tpData.negative_qc_tp,
                     times,
-                    yf_tp: yfPay.tp,
-                    sf_tp: sfPay.tp,
+                    ...stageTp,
                     tp_history: JSON.stringify(this.ctx.stage.tp_history),
                     cache_time_r: this.ctx.stage.cache_time_l,
                 });
+                await this.ctx.service.tenderCache.updateStageCache4Flow(transaction, this.ctx.stage, checkData.checkType, audit, preAuditor, ledgerTp, stageTp);
                 await transaction.update(this.tableName, {
                     id: audit.id,
                     status: checkData.checkType,
                     opinion: checkData.opinion,
                     end_time: time,
                 });
-                // 顺移气候审核人流程顺序
+                // 顺移其后审核人流程顺序
                 this.initSqlBuilder();
                 this.sqlBuilder.setAndWhere('sid', { value: this.ctx.stage.id, operate: '=' });
                 this.sqlBuilder.setAndWhere('order', { value: audit.order, operate: '>' });
@@ -902,14 +879,15 @@ module.exports = app => {
 
                 // 同步 期信息
                 const his = this.ctx.stage.tp_history.find(x => { return x.times === times && x.order === audit.order });
-                this.ctx.stage.tp_history.push({
-                    times,
-                    order: audit.order + 1,
+                const stageTp = {
                     contract_tp: his.contract_tp,
                     qc_tp: his.qc_tp,
-                    yf_tp: his.yf_tp,
-                    sf_tp: his.sf_tp,
-                });
+                    positive_qc_tp: his.positive_qc_tp,
+                    negative_qc_tp: his.negative_qc_tp,
+                    yf_tp: his.tp,
+                    sf_tp: his.tp,
+                };
+                this.ctx.stage.tp_history.push({ times, order: audit.order + 1, ...stageTp });
                 await transaction.update(this.ctx.service.stage.tableName, {
                     id: stageId,
                     status: auditConst.status.checking,
@@ -920,7 +898,8 @@ module.exports = app => {
                 await this.ctx.service.revisePrice.cancelPriceUsed(this.ctx.stage, transaction);
                 // 重算所有单价变更
                 const priceCalc = new RevisePrice(this.ctx);
-                await priceCalc.stageCheckAgainPriceChange(this.ctx.stage, audit.order + 2, transaction);
+                const pcTp = await priceCalc.stageCheckAgainPriceChange(this.ctx.stage, audit.order + 2, transaction);
+                await this.ctx.service.tenderCache.updateStageCache4Flow(transaction, this.ctx.stage, auditConst.status.checking, audit, audit, null, stageTp, pcTp);
 
                 // 添加短信通知-需要审批提醒功能
                 // const smsUser = await this.ctx.service.projectAccount.getDataById(audit.aid);
@@ -992,7 +971,7 @@ module.exports = app => {
             const transaction = await this.db.beginTransaction();
             const time = new Date();
             try {
-                await this._updateTender(transaction);
+                const ledgerTp = await this._updateTender(transaction);
                 let newTimes, newOrder, newSaid, oldTimes, oldOrder, oldSaid = '';
                 if (this.ctx.stage.cancancel === 1) {
                     // 原报撤回,判断是否为多次,多次则为退回状态
@@ -1008,29 +987,24 @@ module.exports = app => {
                     const tpData = await this.ctx.service.stageBills.getSumTotalPrice(this.ctx.stage);
                     // 计算并合同支付最终数据
                     const [yfPay, sfPay] = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
-                    this.ctx.stage.tp_history.push({
-                        times,
-                        order: curAudit.order,
+                    const stageTp = {
                         contract_tp: tpData.contract_tp,
                         qc_tp: tpData.qc_tp,
                         positive_qc_tp: tpData.positive_qc_tp,
                         negative_qc_tp: tpData.negative_qc_tp,
                         yf_tp: yfPay.tp,
                         sf_tp: sfPay.tp,
-                    });
+                    };
+                    this.ctx.stage.tp_history.push({ times, order: curAudit.order, ...stageTp });
                     await transaction.update(this.ctx.service.stage.tableName, {
                         id: stageId,
-                        contract_tp: tpData.contract_tp,
-                        qc_tp: tpData.qc_tp,
-                        positive_qc_tp: tpData.positive_qc_tp,
-                        negative_qc_tp: tpData.negative_qc_tp,
                         times,
-                        yf_tp: yfPay.tp,
-                        sf_tp: sfPay.tp,
+                        ...stageTp,
                         tp_history: JSON.stringify(this.ctx.stage.tp_history),
                         cache_time_r: this.ctx.stage.cache_time_l,
                         status: times === 1 ? auditConst.status.uncheck : auditConst.status.checkNo,
                     });
+                    await this.ctx.service.tenderCache.updateStageCache4Flow(transaction, this.ctx.stage, times === 1 ? auditConst.status.uncheck : auditConst.status.checkNo, { id: this.ctx.stage.user_id }, { id: this.ctx.stage.user_id }, ledgerTp, stageTp);
                     // 计算该审批人最终数据
                     await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
                     // 复制一份最新数据给下一人
@@ -1086,29 +1060,24 @@ module.exports = app => {
                     await transaction.update(this.tableName, { id: curAudit.id, order: curAudit.order + 2, begin_time: null, status: auditConst.status.uncheck });
                     // 计算并合同支付最终数据
                     const [yfPay, sfPay] = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
-                    this.ctx.stage.tp_history.push({
-                        times,
-                        order: curAudit.order,
+                    const stageTp = {
                         contract_tp: tpData.contract_tp,
                         qc_tp: tpData.qc_tp,
                         positive_qc_tp: tpData.positive_qc_tp,
                         negative_qc_tp: tpData.negative_qc_tp,
                         yf_tp: yfPay.tp,
                         sf_tp: sfPay.tp,
-                    });
+                    };
+                    this.ctx.stage.tp_history.push({ times, order: curAudit.order, ...stageTp });
                     // 同步 期信息
                     await transaction.update(this.ctx.service.stage.tableName, {
                         id: stageId,
-                        contract_tp: tpData.contract_tp,
-                        qc_tp: tpData.qc_tp,
-                        positive_qc_tp: tpData.positive_qc_tp,
-                        negative_qc_tp: tpData.negative_qc_tp,
                         times,
-                        yf_tp: yfPay.tp,
-                        sf_tp: sfPay.tp,
+                        ...stageTp,
                         tp_history: JSON.stringify(this.ctx.stage.tp_history),
                         cache_time_r: this.ctx.stage.cache_time_l,
                     });
+                    await this.ctx.service.tenderCache.updateStageCache4Flow(transaction, this.ctx.stage.status, preAudit, preAudit, ledgerTp, stageTp);
 
                     // 计算该审批人最终数据
                     await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
@@ -1130,13 +1099,6 @@ module.exports = app => {
                     if (!curAudit || curAudit.order <= 1) {
                         throw '撤回用户数据错误';
                     }
-                    // // 顺移气候审核人流程顺序
-                    // this.initSqlBuilder();
-                    // this.sqlBuilder.setAndWhere('sid', { value: this.ctx.stage.id, operate: '=' });
-                    // this.sqlBuilder.setAndWhere('order', { value: curAudit.order, operate: '>' });
-                    // this.sqlBuilder.setUpdateData('order', { value: 2, selfOperate: '+' });
-                    // const [sql, sqlParam] = this.sqlBuilder.build(this.tableName, 'update');
-                    // const data = await transaction.query(sql, sqlParam);
                     // 添加撤回人到审批流程中
                     const newAuditors = [];
                     newAuditors.push({
@@ -1161,33 +1123,27 @@ module.exports = app => {
                             order: curAudit.order + 1,
                         }
                     });
-                    // 修改stage状态为审批中
-                    await transaction.update(this.ctx.service.stage.tableName, { id: this.ctx.stage.id, status: auditConst.status.checking });
                     // 计算并合同支付最终数据
                     const [yfPay, sfPay] = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
-                    this.ctx.stage.tp_history.push({
-                        times,
-                        order: curAudit.order,
+                    const stageTp = {
                         contract_tp: tpData.contract_tp,
                         qc_tp: tpData.qc_tp,
                         positive_qc_tp: tpData.positive_qc_tp,
                         negative_qc_tp: tpData.negative_qc_tp,
                         yf_tp: yfPay.tp,
                         sf_tp: sfPay.tp,
-                    });
+                    };
+                    this.ctx.stage.tp_history.push({ times, order: curAudit.order, ...stageTp });
                     // 同步 期信息
                     await transaction.update(this.ctx.service.stage.tableName, {
                         id: stageId,
-                        contract_tp: tpData.contract_tp,
-                        qc_tp: tpData.qc_tp,
-                        positive_qc_tp: tpData.positive_qc_tp,
-                        negative_qc_tp: tpData.negative_qc_tp,
                         times,
-                        yf_tp: yfPay.tp,
-                        sf_tp: sfPay.tp,
+                        ...stageTp,
+                        status: auditConst.status.checking,
                         tp_history: JSON.stringify(this.ctx.stage.tp_history),
                         cache_time_r: this.ctx.stage.cache_time_l,
                     });
+                    await this.ctx.service.tenderCache.updateStageCache4Flow(transaction, this.ctx.stage.status, preAudit, preAudit, ledgerTp, stageTp);
 
                     // 计算该审批人最终数据
                     await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
@@ -1242,29 +1198,24 @@ module.exports = app => {
                     const tpData = await this.ctx.service.stageBills.getSumTotalPrice(this.ctx.stage);
                     // 计算并合同支付最终数据
                     const [yfPay, sfPay] = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
-                    this.ctx.stage.tp_history.push({
-                        times: times - 1,
-                        order: curAudit.order,
+                    const stageTp = {
                         contract_tp: tpData.contract_tp,
                         qc_tp: tpData.qc_tp,
                         positive_qc_tp: tpData.positive_qc_tp,
                         negative_qc_tp: tpData.negative_qc_tp,
                         yf_tp: yfPay.tp,
                         sf_tp: sfPay.tp,
-                    });
+                    };
+                    this.ctx.stage.tp_history.push({ times: times - 1, order: curAudit.order, ...stageTp });
                     await transaction.update(this.ctx.service.stage.tableName, {
                         id: stageId,
-                        contract_tp: tpData.contract_tp,
-                        qc_tp: tpData.qc_tp,
-                        positive_qc_tp: tpData.positive_qc_tp,
-                        negative_qc_tp: tpData.negative_qc_tp,
                         times: times - 1,
-                        yf_tp: yfPay.tp,
-                        sf_tp: sfPay.tp,
+                        ...stageTp,
                         tp_history: JSON.stringify(this.ctx.stage.tp_history),
                         cache_time_r: this.ctx.stage.cache_time_l,
                         status: auditConst.status.checking,
                     });
+                    await this.ctx.service.tenderCache.updateStageCache4Flow(transaction, this.ctx.stage.status, curAudit, curAudit, ledgerTp, stageTp);
                     // 计算该审批人最终数据
                     await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
                     // 复制一份最新数据给下一人
@@ -1611,7 +1562,7 @@ module.exports = app => {
                     order++;
                 }
 
-                await this._updateTender(transaction);
+                const ledgerTp = await this._updateTender(transaction);
                 // 拷贝新一次审核流程列表
                 await transaction.insert(this.tableName, auditors);
 

+ 13 - 0
app/service/stage_bills.js

@@ -400,6 +400,19 @@ module.exports = app => {
             return result;
         }
 
+        async getLatestSumTotalPrice(tid, sid) {
+            const sql = 'SELECT Sum(`contract_tp`) As `contract_tp`, Sum(`qc_tp`) As `qc_tp`, Sum(`positive_qc_tp`) As positive_qc_tp, Sum(`negative_qc_tp`) As negative_qc_tp FROM ' + this.departTableName(tid) + ' As Bills ' +
+                '  INNER JOIN ( ' +
+                '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `flow`, `lid`, `sid` From ' + this.departTableName(tid) +
+                '      WHERE `sid` = ?' +
+                '      GROUP BY `lid`' +
+                '  ) As MaxFilter ' +
+                '  ON (Bills.times * ' + timesLen + ' + `order`) = MaxFilter.flow And Bills.lid = MaxFilter.lid And Bills.sid = MaxFilter.sid';
+            const sqlParam = [sid];
+            const result = await this.db.queryOne(sql, sqlParam);
+            return result;
+        }
+
         async getSumTotalPriceFilter(stage, operate, filter) {
             const sql = 'SELECT Sum(`contract_tp`) As `contract_tp`, Sum(`qc_tp`) As `qc_tp`, Sum(`positive_qc_tp`) As positive_qc_tp, Sum(`negative_qc_tp`) As negative_qc_tp' +
                 '  FROM ' + this.departTableName(stage.tid) + ' As Bills ' +

+ 2 - 0
app/service/tender.js

@@ -247,6 +247,7 @@ module.exports = app => {
                 if (!result) {
                     throw '新增标段数据失败';
                 }
+                await this.ctx.service.tenderCache.insertTenderCache(this.transaction, operate.insertId, sessionUser.accountId);
 
 
                 // 获取合同支付模板 并添加到标段
@@ -335,6 +336,7 @@ module.exports = app => {
                 await this.ctx.helper.delFiles(attList);
                 await transaction.delete(this.tableName, { id });
                 await transaction.delete(this.ctx.service.tenderInfo.tableName, { tid: id });
+                await transaction.delete(this.ctx.service.tenderCache.tableName, { id });
                 await transaction.delete(this.ctx.service.tenderTourist.tableName, { tid: id });
                 await transaction.delete(this.ctx.service.tenderMap.tableName, { tid: id });
                 await transaction.delete(this.ctx.service.tenderTag.tableName, { tid: id });

+ 458 - 0
app/service/tender_cache.js

@@ -0,0 +1,458 @@
+'use strict';
+
+/**
+ * xxx_flow_cur为当前流程,审批通过时为空值
+ * xxx_flow_pre为上一流程, 未上报时 为空值/上一期终审,pre比cur多一个time值
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const auditConst = require('../const/audit.js');
+const commonField = ['ledger_status', 'stage_status', 'revise_status', 'stage_count', 'stage_complete_count', 'contract_tp', 'advance_tp', 'change_tp'];
+
+module.exports = app => {
+
+    class TenderCache extends app.BaseService {
+
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'tender_cache';
+        }
+
+        _analysisTenderCache(tender, cache, uid) {
+            commonField.forEach(f => { tender[f] = cache[f]; });
+            tender.ledger_tp = cache.ledger_tp ? JSON.parse(cache.ledger_tp) : {};
+            if (!cache.stage_count || (cache.stage_count === 1 && cache.stage_status === auditConst.stage.status.uncheck && cache.stage_flow_cur_uid !== uid)) {
+                tender.cur_flow = JSON.parse(cache.ledger_flow_cur_info || cache.ledger_flow_pre_info);
+                tender.cur_flow.title = '台账';
+                tender.pre_flow = cache.ledger_flow_pre_info ? JSON.parse(cache.ledger_flow_pre_info) : null;
+                tender.stage_tp = {};
+                tender.progress = {
+                    title: '台账',
+                    status: auditConst.ledger.tiStatusString[cache.ledger_status],
+                    status_class: auditConst.ledger.tiStatusStringClass[cache.ledger_status],
+                };
+            } else if (cache.stage_status !== auditConst.stage.status.uncheck || cache.stage_flow_cur_uid === uid) {
+                tender.stage_status = cache.stage_status;
+                tender.stage_count = tender.stage_count;
+                tender.stage_complete_count = tender.stage_complete_count;
+                tender.cur_flow = cache.stage_status === auditConst.stage.status.checkNo
+                    ? JSON.parse(cache.stage_flow_pre_info)
+                    : JSON.parse(cache.stage_flow_cur_info || cache.stage_flow_pre_info);
+                tender.pre_flow = cache.stage_flow_pre_info ? JSON.parse(cache.stage_flow_pre_info) : null;
+                tender.stage_tp = JSON.parse(cache.stage_flow_cur_tp || cache.stage_flow_pre_tp);
+                tender.progress = {
+                    title: `第${cache.stage_count}期`,
+                    status: auditConst.stage.tiStatusString[cache.stage_status],
+                    status_class: auditConst.stage.tiStatusStringClass[cache.stage_status],
+                };
+            } else {
+                tender.stage_status = auditConst.stage.status.checked;
+                tender.stage_count = tender.stage_complete_count;
+                tender.stage_complete_count = tender.stage_complete_count;
+                tender.cur_flow = JSON.parse(cache.stage_flow_cur_info || cache.stage_flow_pre_info);
+                tender.pre_flow = cache.stage_flow_pre_info ? JSON.parse(cache.stage_flow_pre_info) : null;
+                tender.stage_tp = JSON.parse(cache.stage_flow_cur_tp || cache.stage_flow_pre_tp);
+                tender.progress = {
+                    title: `第${cache.stage_complete_count}期`,
+                    status: auditConst.stage.tiStatusString[auditConst.stage.status.checked],
+                    status_class: auditConst.stage.tiStatusStringClass[auditConst.stage.status.checked],
+                };
+            }
+            tender.contract_price = cache.contract_price;
+            tender.advance_tp = cache.advance_tp;
+            tender.change_tp = cache.change_tp;
+        }
+
+        async loadTenderCache(tender, uid) {
+            const cache = await this.getDataById(tender.id);
+            if (cache) this._analysisTenderCache(tender, cache, uid);
+        }
+
+        async insertTenderCache(transaction, tid, uid) {
+            const user = await this.ctx.service.projectAccount.getAccountCacheData(uid);
+            user.order = 0;
+            user.status = auditConst.ledger.status.uncheck;
+            const data = {
+                id: tid,
+                ledger_status: auditConst.flow.status.uncheck,
+                ledger_flow_cur_uid: uid,
+                ledger_flow_cur_info: JSON.stringify(user),
+            };
+            await transaction.insert(this.tableName, data);
+        }
+
+        async updateLedgerCache4Start(transaction, tid, status, audit, tp) {
+            const orgCache = await this.getDataById(tid);
+            const preInfo = JSON.parse(orgCache.ledger_flow_cur_info);
+            preInfo.time = new Date();
+            const data = {
+                id: tid, ledger_status: status,
+                ledger_flow_pre_uid: orgCache.ledger_flow_cur_uid, ledger_flow_pre_info: JSON.stringify(preInfo),
+            };
+            if (audit) {
+                const info = await this.ctx.service.projectAccount.getAccountCacheData(audit.audit_id);
+                info.order = audit.audit_order;
+                info.status = status;
+                data.ledger_flow_cur_uid = audit.audit_id;
+                data.ledger_flow_cur_info = JSON.stringify(info);
+            }
+            if (tp) data.ledger_tp = JSON.stringify(tp);
+            await transaction.update(this.tableName, data);
+        }
+
+        async updateLedgerCache(transaction, tid, status, checkType, next, tp) {
+            const orgCache = await this.getDataById(tid);
+            const preInfo = JSON.parse(orgCache.ledger_flow_cur_info);
+            preInfo.time = new Date();
+            preInfo.status = checkType;
+            const data = {
+                id: tid, ledger_status: status,
+                ledger_flow_pre_uid: orgCache.ledger_flow_cur_uid, ledger_flow_pre_info: JSON.stringify(preInfo),
+            };
+            if (next) {
+                const info = await this.ctx.service.projectAccount.getAccountCacheData(next.audit_id);
+                info.status = checkType === auditConst.ledger.status.checkNo ? status : auditConst.ledger.status.uncheck;
+                data.ledger_flow_cur_uid = next.audit_id;
+                data.ledger_flow_cur_info = JSON.stringify(info);
+            } else {
+                data.ledger_flow_cur_uid = 0;
+                data.ledger_flow_cur_info = '';
+            }
+            if (tp) data.ledger_tp = JSON.stringify(tp);
+            await transaction.update(this.tableName, data);
+        }
+
+        async updateStageCache4Add(transaction, newStage, pcTp) {
+            const tp = {
+                contract_tp: 0, qc_tp: 0,
+                positive_qc_tp: 0, negative_qc_tp: 0,
+                yf_tp: 0, sf_tp: 0,
+                pre_contract_tp: newStage.pre_contract_tp, pre_qc_tp: newStage.pre_qc_tp,
+                pre_positive_qc_tp: newStage.pre_positive_qc_tp, pre_negative_qc_tp: newStage.pre_positive_qc_tp,
+                pre_yf_tp: newStage.pre_yf_tp, pre_sf_tp: newStage.pre_sf_tp,
+                ...pcTp,
+            };
+            const cur_flow_info = await this.ctx.service.projectAccount.getAccountCacheData(newStage.user_id);
+            cur_flow_info.order = newStage.order;
+            cur_flow_info.status = auditConst.stage.status.uncheck;
+            await transaction.update(this.tableName, {
+                id: newStage.tid, stage_count: newStage.order, stage_status: auditConst.stage.status.uncheck,
+                stage_flow_cur_uid: newStage.user_id, stage_flow_cur_info: JSON.stringify(cur_flow_info),
+                stage_flow_cur_tp: JSON.stringify(tp),
+            });
+        }
+
+        async updateStageCache4Del(transaction, delStage) {
+            const preStage = delStage.order > 1 ? await this.ctx.service.stage.getDataBYCondition({ tid: delStage.tid, order: delStage.order - 1 }): {};
+            if (preStage) {
+                const tp = JSON.stringify({
+                    contract_tp: preStage.contract_tp, qc_tp: preStage.qc_tp, contract_pc_tp: preStage.contract_pc_tp, qc_pc_tp: preStage.qc_pc_tp, pc_tp: preStage.pc_tp,
+                    positive_qc_tp: preStage.positive_qc_tp, positive_qc_pc_tp: preStage.positive_qc_pc_tp, negative_qc_tp: preStage.negative_qc_pc_tp, negative_qc_pc_tp: preStage.negative_qc_pc_tp,
+                    yf_tp: preStage.yf_tp, sf_tp: preStage.sf_tp,
+                    pre_contract_tp: preStage.pre_contract_tp, pre_qc_tp: preStage.pre_qc_tp,
+                    pre_positive_qc_tp: preStage.pre_positive_qc_tp, pre_negative_qc_tp: preStage.pre_positive_qc_tp,
+                    pre_yf_tp: preStage.pre_yf_tp, pre_sf_tp: preStage.pre_sf_tp,
+                });
+                const auditor = await this.ctx.service.stageAudit.getLastestAuditor(preStage.id, preStage.times, preStage.status);
+                const user_info = JSON.stringify({
+                    order: preStage.order, status: preStage.status, time: auditor.end_time,
+                    name: auditor.name, company: auditor.company, role: auditor.role, mobile: auditor.mobile, telephone: auditor.telephone,
+                });
+                await transaction.update(this.tableName, {
+                    id: delStage.tid, stage_count: preStage.order, stage_status: preStage.status,
+                    stage_flow_cur_uid: 0, stage_flow_cur_info: '', stage_flow_cur_tp: '',
+                    stage_flow_pre_uid: auditor.id, stage_flow_pre_info: user_info, stage_flow_pre_tp: tp,
+                });
+            } else {
+                await transaction.update(this.tableName, {
+                    id: delStage.tid, stage_count: 0, stage_complete_count: 0, stage_status: 0,
+                    stage_flow_cur_uid: 0, stage_flow_cur_info: '', stage_flow_cur_tp: '',
+                    stage_flow_pre_uid: 0, stage_flow_pre_info: '', stage_flow_pre_tp: '',
+                });
+            }
+        }
+
+        async updateStageCache4Start(transaction, stage, status, auditor, ledgerTp, stageTp) {
+            const orgCache = await this.getDataById(stage.tid);
+            const data = { id: stage.tid, stage_status: status };
+            if (ledgerTp) data.ledger_tp = JSON.stringify(ledgerTp);
+            const tp = JSON.parse(orgCache.stage_flow_cur_tp);
+            if (stageTp) this._.assign(tp, stageTp);
+            data.stage_flow_pre_uid = orgCache.stage_flow_cur_uid;
+            data.stage_flow_pre_info = orgCache.stage_flow_cur_info;
+            data.stage_flow_pre_tp = JSON.stringify(tp);
+            data.stage_flow_cur_uid = auditor.id;
+            const cur_flow_info = await this.ctx.service.projectAccount.getAccountCacheData(auditor.id);
+            cur_flow_info.stage_order = stage.order;
+            cur_flow_info.stage_status = stage.status;
+            data.stage_flow_cur_info = JSON.stringify(cur_flow_info);
+            data.stage_flow_cur_tp = JSON.stringify(tp);
+            await transaction.update(this.tableName, data);
+        }
+
+        async updateStageCache4Flow(transaction, stage, status, auditor, preAuditor, ledgerTp, stageTp, pcTp) {
+            const orgCache = await this.getDataById(stage.tid);
+            const data = { id: stage.tid, stage_status: status };
+            if (ledgerTp) data.ledger_tp = JSON.stringify(ledgerTp);
+            const tp = JSON.parse(orgCache.stage_flow_cur_tp);
+            if (stageTp) this._.assign(tp, stageTp);
+            if (pcTp) this._.assign(tp, pcTp);
+            if (preAuditor) {
+                data.stage_flow_pre_uid = preAuditor.id;
+                const info = await this.ctx.service.projectAccount.getAccountCacheData(preAuditor.id);
+                data.stage_flow_pre_info = JSON.stringify(info);
+            }
+            data.stage_flow_pre_uid = orgCache.stage_flow_cur_uid;
+            data.stage_flow_pre_info = orgCache.stage_flow_cur_info;
+            data.stage_flow_pre_tp = JSON.stringify(tp);
+            if (auditor) {
+                data.stage_flow_cur_uid = auditor.id;
+                const info = await this.ctx.service.projectAccount.getAccountCacheData(auditor.id);
+                data.stage_flow_cur_info = JSON.stringify(info);
+            }
+            data.stage_flow_cur_tp = JSON.stringify(tp);
+            await transaction.update(this.tableName, data);
+        }
+
+        async updateStageCache4Revise(transaction, tid, ledgerTp, pcTp) {
+            const orgCache = await this.getDataById(tid);
+            const data = { id: tid };
+            if (ledgerTp) data.ledger_tp = JSON.stringify(ledgerTp);
+            if (data.stage_status !== auditConst.stage.status.checked && pcTp) {
+                const curTp = JSON.parse(orgCache.stage_flow_cur_tp);
+                this._.assign(curTp, pcTp);
+                data.stage_flow_cur_tp = JSON.stringify(curTp);
+                if (orgCache.stage_status !== auditConst.stage.status.uncheck) {
+                    const preTp = JSON.parse(orgCache.stage_flow_pre_tp);
+                    this._.assign(preTp, pcTp);
+                    data.stage_flow_cur_tp = JSON.stringify(preTp);
+                }
+            }
+            await transaction.update(this.tableName, data);
+        }
+
+        async _refreshLedgerRela(tender, data) {
+            data.ledger_status = tender.ledger_status || 0;
+            if (tender.ledger_status === auditConst.ledger.status.uncheck) {
+                data.ledger_flow_cur_uid = tender.user_id;
+                const user = await this.ctx.service.projectAccount.getAccountCacheData(tender.user_id);
+                user.status = tender.ledger_status;
+                user.order = 0;
+                data.ledger_flow_cur_info = JSON.stringify(user);
+            } else if (tender.ledger_status === auditConst.ledger.status.checked) {
+                const pre = await this.ctx.service.ledgerAudit.getLastestAuditor(tender.id, tender.ledger_times, tender.ledger_status);
+                data.ledger_flow_pre_uid = pre.audit_id;
+                data.ledger_flow_pre_info = JSON.stringify({
+                    order: pre.order, status: pre.status, time: pre.end_time,
+                    name: pre.name, company: pre.company, role: pre.role, mobile: pre.mobile, telephone: pre.telephone,
+                });
+            } else if (tender.ledger_status === auditConst.ledger.status.checkNo) {
+                data.ledger_flow_cur_uid = tender.user_id;
+                const user = await this.ctx.service.projectAccount.getAccountCacheData(tender.user_id);
+                user.order = 0;
+                user.status = auditConst.ledger.status.uncheck;
+                data.ledger_flow_cur_info = JSON.stringify(user);
+                const pre = await this.ctx.service.ledgerAudit.getLastestAuditor(tender.id, tender.ledger_times - 1, tender.ledger_status);
+                data.ledger_flow_pre_uid = pre.audit_id;
+                data.ledger_flow_pre_info = JSON.stringify({
+                    order: pre.order, status: pre.status, time: pre.end_time,
+                    name: pre.name, company: pre.company, role: pre.role, mobile: pre.mobile, telephone: pre.telephone,
+                });
+            } else {
+                const cur = await this.ctx.service.ledgerAudit.getLastestAuditor(tender.id, tender.ledger_times, tender.ledger_status);
+                if (cur) {
+                    data.ledger_flow_cur_uid = cur.audit_id;
+                    data.ledger_flow_cur_info = JSON.stringify({
+                        order: cur.order, status: cur.status, time: cur.end_time,
+                        name: cur.name, company: cur.company, role: cur.role, mobile: cur.mobile, telephone: cur.telephone,
+                    });
+                    if (cur.audit_order === 1) {
+                        data.ledger_flow_pre_uid = tender.user_id;
+                        const user = await await this.ctx.service.projectAccount.getAccountCacheData(tender.user_id, { order: 0, time: cur.begin_time });
+                        data.ledger_flow_pre_info = JSON.stringify(user);
+                    } else {
+                        const pre = await this.ctx.service.ledgerAudit.getAuditorByOrder(tender.id, cur.audit_order - 1, cur.times);
+                        data.ledger_flow_pre_uid = pre.audit_id;
+                        data.ledger_flow_pre_info = JSON.stringify({
+                            order: pre.order, status: pre.status, time: pre.end_time,
+                            name: pre.name, company: pre.company, role: pre.role, mobile: pre.mobile, telephone: pre.telephone,
+                        });
+                    }
+                }
+            }
+            data.ledger_tp = JSON.stringify(await this.ctx.service.ledger.addUp({ tender_id: tender.id/* , is_leaf: true*/ }));
+            const revise = await this.service.ledgerRevise.getLastestRevise(tender.id);
+            data.revise_status = revise ? revise.status : 0;
+        }
+
+        async _calcTp (lastStage, tp) {
+            lastStage.curTimes = lastStage.times;
+            const tpData = await this.ctx.service.stageBills.getSumTotalPrice(lastStage);
+            const pcSum = await this.ctx.service.stageBillsPc.getSumTotalPrice(lastStage);
+            tp.contract_tp = tpData.contract_tp;
+            tp.qc_tp = tpData.qc_tp;
+            tp.positive_qc_tp = tpData.positive_qc_tp;
+            tp.negative_qc_tp = tpData.negative_qc_tp;
+            tp.contract_pc_tp = pcSum.contract_pc_tp;
+            tp.qc_pc_tp = pcSum.qc_pc_tp;
+            tp.pc_tp = pcSum.pc_tp;
+            tp.positive_qc_pc_tp = pcSum.positive_qc_pc_tp;
+            tp.negative_qc_pc_tp = pcSum.negative_qc_pc_tp;
+            const payTp = await this.ctx.service.stagePay.getSpecialTotalPrice(lastStage);
+            tp.yf_tp = payTp.yf;
+            tp.sf_tp = payTp.sf;
+        };
+
+        async _refreshStageRela(tender, data) {
+            if (tender.ledger_status === auditConst.ledger.status.checked) {
+                const lastStage = await this.ctx.service.stage.getLastestStage(tender.id, true);
+                if (!lastStage) return;
+
+                data.stage_count = lastStage.order;
+                data.stage_complete_count = lastStage.status === auditConst.stage.status.checked ? lastStage.order : lastStage.order - 1;
+                data.stage_status = lastStage.status;
+                const tp = {
+                    contract_tp: lastStage.contract_tp || 0, qc_tp: lastStage.qc_tp || 0, contract_pc_tp: lastStage.contract_pc_tp, qc_pc_tp: lastStage.qc_pc_tp, pc_tp: lastStage.pc_tp,
+                    positive_qc_tp: lastStage.positive_qc_tp, positive_qc_pc_tp: lastStage.positive_qc_pc_tp, negative_qc_tp: lastStage.negative_qc_pc_tp, negative_qc_pc_tp: lastStage.negative_qc_pc_tp,
+                    yf_tp: lastStage.yf_tp, sf_tp: lastStage.sf_tp,
+                    pre_contract_tp: lastStage.pre_contract_tp, pre_qc_tp: lastStage.pre_qc_tp,
+                    pre_positive_qc_tp: lastStage.pre_positive_qc_tp, pre_negative_qc_tp: lastStage.pre_positive_qc_tp,
+                    pre_yf_tp: lastStage.pre_yf_tp, pre_sf_tp: lastStage.pre_sf_tp,
+                };
+                const preStage = lastStage.order > 1 ? await this.ctx.service.stage.getDataByCondition({ tid: lastStage.tid, order: lastStage.order - 1}) : null;
+                if (lastStage.status === auditConst.stage.status.uncheck) {
+                    if (preStage) {
+                        const preAuditor = await this.ctx.service.stageAudit.getLastestAuditor(preStage.id, preStage.times, preStage.status);
+                        data.stage_flow_pre_uid = preAuditor.aid;
+                        data.stage_flow_pre_info = JSON.stringify({
+                            order: preAuditor.order, status: preAuditor.status, time: preAuditor.end_time,
+                            name: preAuditor.name, company: preAuditor.company, role: preAuditor.role, mobile: preAuditor.mobile, telephone: preAuditor.telephone,
+                        });
+                        data.stage_flow_pre_tp = JSON.stringify({
+                            contract_tp: preStage.contract_tp || 0, qc_tp: preStage.qc_tp || 0, contract_pc_tp: preStage.contract_pc_tp, qc_pc_tp: preStage.qc_pc_tp, pc_tp: preStage.pc_tp,
+                            positive_qc_tp: preStage.positive_qc_tp, positive_qc_pc_tp: preStage.positive_qc_pc_tp, negative_qc_tp: preStage.negative_qc_pc_tp, negative_qc_pc_tp: preStage.negative_qc_pc_tp,
+                            yf_tp: preStage.yf_tp, sf_tp: preStage.sf_tp,
+                            pre_contract_tp: preStage.pre_contract_tp, pre_qc_tp: preStage.pre_qc_tp,
+                            pre_positive_qc_tp: preStage.pre_positive_qc_tp, pre_negative_qc_tp: preStage.pre_positive_qc_tp,
+                            pre_yf_tp: preStage.pre_yf_tp, pre_sf_tp: preStage.pre_sf_tp,
+                        });
+                    }
+                    lastStage.curOrder = 0;
+                    await this._calcTp(lastStage, tp);
+                    data.stage_flow_cur_uid = lastStage.user_id;
+                    const curInfo = await this.ctx.service.projectAccount.getAccountCacheData(lastStage.user_id, { order: 0, status: lastStage.status });
+                    data.stage_flow_cur_info = JSON.stringify(curInfo);
+                    data.stage_flow_cur_tp = JSON.stringify(tp);
+                } else if (lastStage.status === auditConst.stage.status.checked) {
+                    const preAuditor = await this.ctx.service.stageAudit.getLastestAuditor(lastStage.id, lastStage.times, lastStage.status);
+                    lastStage.curOrder = preAuditor.order;
+                    await this._calcTp(lastStage, tp);
+                    data.stage_flow_pre_uid = preAuditor.aid;
+                    data.stage_flow_pre_info = JSON.stringify({
+                        order: preAuditor.order, status: preAuditor.status, time: preAuditor.end_time,
+                        name: preAuditor.name, company: preAuditor.company, role: preAuditor.role, mobile: preAuditor.mobile, telephone: preAuditor.telephone,
+                    });
+                    data.stage_flow_cur_tp = JSON.stringify(tp);
+                    data.stage_flow_pre_tp = JSON.stringify(tp);
+                } else if (lastStage.status === auditConst.stage.status.checkNo) {
+                    lastStage.curOrder = 0;
+                    await this._calcTp(lastStage, tp);
+                    data.stage_flow_cur_uid = lastStage.user_id;
+                    const curInfo = await this.ctx.service.projectAccount.getAccountCacheData(lastStage.user_id, { order: 0, status: auditConst.stage.status.uncheck });
+                    data.stage_flow_cur_info = JSON.stringify(curInfo);
+                    data.stage_flow_cur_tp = JSON.stringify(tp);
+                    const preAuditor = await this.ctx.service.stageAudit.getLastestAuditor(lastStage.id, lastStage.times - 1, lastStage.status);
+                    data.stage_flow_pre_uid = preAuditor.aid;
+                    data.stage_flow_pre_info = JSON.stringify({
+                        order: preAuditor.order, status: preAuditor.status, time: preAuditor.end_time,
+                        name: preAuditor.name, company: preAuditor.company, role: preAuditor.role, mobile: preAuditor.mobile, telephone: preAuditor.telephone,
+                    });
+                    const his = lastStage.tp_history.find(x => { return x.times === preAuditor.times && x.order === preAuditor.order; });
+                    if (his) {
+                        tp.contract_tp = his.contract_tp;
+                        tp.qc_tp = his.qc_tp;
+                        tp.positive_qc_tp = his.positive_qc_tp;
+                        tp.negative_qc_tp = his.negative_qc_tp;
+                        tp.yf_tp = his.yf_tp;
+                        tp.sf_tp = his.sf_tp;
+                    }
+                    data.stage_flow_pre_tp = JSON.stringify(tp);
+                } else {
+                    const curAuditor = await this.ctx.service.stageAudit.getLastestAuditor(lastStage.id, lastStage.times, lastStage.status);
+                    lastStage.curOrder = curAuditor.order;
+                    await this._calcTp(lastStage, tp);
+                    data.stage_flow_cur_uid = curAuditor.aid;
+                    data.stage_flow_cur_info = JSON.stringify({
+                        order: curAuditor.order, status: curAuditor.status,
+                        name: curAuditor.name, company: curAuditor.company, role: curAuditor.role, mobile: curAuditor.mobile, telephone: curAuditor.telephone,
+                    });
+                    data.stage_flow_cur_tp = JSON.stringify(tp);
+                    const preAuditor = curAuditor.order > 1 ? await this.ctx.service.stageAudit.getAuditorByOrder(lastStage.id, lastStage.times, curAuditor.order - 1) : null;
+                    if (preAuditor) {
+                        data.stage_flow_pre_uid = preAuditor.aid;
+                        data.stage_flow_pre_info = JSON.stringify({
+                            order: preAuditor.order, status: preAuditor.status, time: curAuditor.begin_time,
+                            name: preAuditor.name, company: preAuditor.company, role: preAuditor.role, mobile: preAuditor.mobile, telephone: preAuditor.telephone,
+                        });
+                    } else {
+                        data.stage_flow_pre_uid = lastStage.user_id;
+                        const preInfo = await this.ctx.service.projectAccount.getAccountCacheData(lastStage.user_id, { order: 0, status: auditConst.stage.status.uncheck, time: curAuditor.begin_time });
+                        data.stage_flow_pre_info = JSON.stringify(preInfo);
+                    }
+                    const his = preAuditor
+                        ? lastStage.tp_history.find(x => { return x.times === preAuditor.times && x.order === preAuditor.order; })
+                        : lastStage.tp_history.find(x => { return x.times === lastStage.times && x.order === 0; });
+                    if (his) {
+                        tp.contract_tp = his.contract_tp;
+                        tp.qc_tp = his.qc_tp;
+                        tp.positive_qc_tp = his.positive_qc_tp;
+                        tp.negative_qc_tp = his.negative_qc_tp;
+                        tp.yf_tp = his.yf_tp;
+                        tp.sf_tp = his.sf_tp;
+                    }
+                    data.stage_flow_pre_tp = JSON.stringify(tp);
+                }
+            }
+        }
+
+        async refreshTenderCache(tender, transaction) {
+            const orgCache = await this.getDataById(tender.id);
+            const data = { id: tender.id, ledger_status: 0,
+                ledger_flow_cur_uid: 0, ledger_flow_cur_info: '', ledger_flow_pre_uid: 0, ledger_flow_pre_info: '',
+                stage_count: 0, stage_complete_count: 0, stage_status: 0,
+                stage_flow_cur_uid: 0, stage_flow_cur_info: '', stage_flow_cur_tp: '',
+                stage_flow_pre_uid: 0, stage_flow_pre_info: '', stage_flow_pre_tp: '',
+            };
+            // 台账
+            await this._refreshLedgerRela(tender, data);
+            // 计量
+            await this._refreshStageRela(tender, data);
+            // 其他计算项
+            const tenderInfo = await this.ctx.service.tenderInfo.getTenderInfo(tender.id, tender.project_id);
+            data.contract_price = tenderInfo.deal_param.contractPrice || 0;
+            data.advance_tp = await this.ctx.service.advance.getSumAdvance(tender.id);
+            const changeSum = await this.db.queryOne(`SELECT SUM(cast (total_price as decimal(18,6))) AS total_price FROM ${this.ctx.service.change.tableName} WHERE tid = ? AND status = ? And valid = 1`, [tender.id, auditConst.flow.status.checked]);
+            data.change_tp = changeSum.total_price || 0;
+            console.log(data);
+
+            const conn = transaction || this.db;
+            if (orgCache) {
+                conn.update(this.tableName, data);
+            } else {
+                conn.insert(this.tableName, data);
+            }
+        }
+    }
+
+    return TenderCache;
+};

+ 2 - 2
app/service/tender_info.js

@@ -68,11 +68,11 @@ module.exports = app => {
          * @param tenderId
          * @return {Promise<void>}
          */
-        async getTenderInfo(tenderId) {
+        async getTenderInfo(tenderId, projectId) {
             const defaultInfo = await this.getDefaultInfo(tenderId);
             let info = await this.getDataByCondition({ tid: tenderId });
             // 兼容不存在info的情况
-            if (!info) info = await this.addTenderInfo(tenderId, this.ctx.session.sessionProject.id);
+            if (!info) info = await this.addTenderInfo(tenderId, projectId || this.ctx.session.sessionProject.id);
             for (const pi of parseInfo) {
                 info[pi] = !info[pi] || info[pi] === '' ? (pi === 'shenpi' ? JSON.parse(JSON.stringify(defaultInfo[pi])) : defaultInfo[pi]) : JSON.parse(info[pi]);
                 this.ctx.helper._.defaultsDeep(info[pi], defaultInfo[pi]);

+ 1 - 0
app/view/tender/manage.ejs

@@ -15,4 +15,5 @@
     const uid = '<%- uid %>';
     const pid = '<%- pid %>';
     const uphlname = 'user_' + uid + '_pro_' + pid + '_category_hide_manange_list';
+    const cache = <%- ctx.session.sessionUser.is_admin %>;
 </script>

+ 6 - 0
app/view/tender/sub_menu.ejs

@@ -21,6 +21,12 @@
                         <input type="radio" name="options" id="option2" autocomplete="off"> 管理标段
                     </label>
                     <% } %>
+                    <label class="btn btn-sm btn-light <% if (ctx.url === '/list/infoOrg') { %>active<% } %>" onclick="window.location.href='/list/infoOrg'">
+                        <input type="radio" name="options" id="option1" autocomplete="off"> 金额概况(旧)
+                    </label>
+                    <label class="btn btn-sm btn-light  <% if (ctx.url === '/list/progressOrg') { %>active<% } %>" onclick="window.location.href='/list/progressOrg'">
+                        <input type="radio" name="options" id="option2" autocomplete="off"> 计量进度(旧)
+                    </label>
                 </div>
             </div>
             <!--<div class="d-inline-block ml-3">-->

+ 141 - 0
db_script/tender_cache.js

@@ -0,0 +1,141 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const { app, assert } = require('egg-mock/bootstrap');
+// const completeTenderCache = async function () {
+//     const ctx = app.mockContext();
+//     const tenders = await ctx.app.mysql.query('SELECT * FROM zh_tender WHERE id > 0');
+//     console.log(tenders.length);
+//     for (const t of tenders) {
+//         await ctx.service.tenderCache.refreshTenderCache(t);
+//         console.log(`complete ${t.name}(${t.id})`);
+//     }
+// };
+// completeTenderCache();
+
+// const depart = 100;
+// describe('refreshTenderCache.js', () => {
+//     it('refreshTenderCache', function* () {
+//         let ctx = app.mockContext();
+//         const lastTender = yield ctx.app.mysql.queryOne(`Select * From zh_tender WHERE id > 0 ORDER By id DESC`);
+//         let iBegin = 0;
+//         while (iBegin < lastTender.id) {
+//             ctx = app.mockContext();
+//             const tenders = yield ctx.app.mysql.query('SELECT * FROM zh_tender WHERE id > ? and id <= ?', [iBegin, iBegin+depart]);
+//             for (const t of tenders) {
+//                 yield ctx.service.tenderCache.refreshTenderCache(t);
+//                 console.log(`complete ${t.name}(${t.id})`);
+//             }
+//             iBegin = iBegin + depart;
+//         }
+//     });
+// });
+
+describe('refreshTenderCache.js', () => {
+    it('refreshTenderCache', function* () {
+        const ctx = app.mockContext();
+        const tenders = yield ctx.app.mysql.query('SELECT * FROM zh_tender WHERE id > ? and id < ?', [0, 500]);
+        console.log(tenders.length);
+        for (const t of tenders) {
+            yield ctx.service.tenderCache.refreshTenderCache(t);
+            console.log(`complete ${t.name}(${t.id})`);
+        }
+    });
+    it('refreshTenderCache', function* () {
+        const ctx = app.mockContext();
+        const tenders = yield ctx.app.mysql.query('SELECT * FROM zh_tender WHERE id > ? and id < ?', [500, 1000]);
+        console.log(tenders.length);
+        for (const t of tenders) {
+            yield ctx.service.tenderCache.refreshTenderCache(t);
+            console.log(`complete ${t.name}(${t.id})`);
+        }
+    });
+    it('refreshTenderCache', function* () {
+        const ctx = app.mockContext();
+        const tenders = yield ctx.app.mysql.query('SELECT * FROM zh_tender WHERE id > ? and id < ?', [1000, 1500]);
+        console.log(tenders.length);
+        for (const t of tenders) {
+            yield ctx.service.tenderCache.refreshTenderCache(t);
+            console.log(`complete ${t.name}(${t.id})`);
+        }
+    });
+    it('refreshTenderCache', function* () {
+        const ctx = app.mockContext();
+        const tenders = yield ctx.app.mysql.query('SELECT * FROM zh_tender WHERE id > ? and id < ?', [1500, 2000]);
+        console.log(tenders.length);
+        for (const t of tenders) {
+            yield ctx.service.tenderCache.refreshTenderCache(t);
+            console.log(`complete ${t.name}(${t.id})`);
+        }
+    });
+    it('refreshTenderCache', function* () {
+        const ctx = app.mockContext();
+        const tenders = yield ctx.app.mysql.query('SELECT * FROM zh_tender WHERE id > ? and id < ?', [2000, 2500]);
+        console.log(tenders.length);
+        for (const t of tenders) {
+            yield ctx.service.tenderCache.refreshTenderCache(t);
+            console.log(`complete ${t.name}(${t.id})`);
+        }
+    });
+    it('refreshTenderCache', function* () {
+        const ctx = app.mockContext();
+        const tenders = yield ctx.app.mysql.query('SELECT * FROM zh_tender WHERE id > ? and id < ?', [2500, 3000]);
+        console.log(tenders.length);
+        for (const t of tenders) {
+            yield ctx.service.tenderCache.refreshTenderCache(t);
+            console.log(`complete ${t.name}(${t.id})`);
+        }
+    });
+    it('refreshTenderCache', function* () {
+        const ctx = app.mockContext();
+        const tenders = yield ctx.app.mysql.query('SELECT * FROM zh_tender WHERE id > ? and id < ?', [3000, 3500]);
+        console.log(tenders.length);
+        for (const t of tenders) {
+            yield ctx.service.tenderCache.refreshTenderCache(t);
+            console.log(`complete ${t.name}(${t.id})`);
+        }
+    });
+    it('refreshTenderCache', function* () {
+        const ctx = app.mockContext();
+        const tenders = yield ctx.app.mysql.query('SELECT * FROM zh_tender WHERE id > ? and id < ?', [4000, 4500]);
+        console.log(tenders.length);
+        for (const t of tenders) {
+            yield ctx.service.tenderCache.refreshTenderCache(t);
+            console.log(`complete ${t.name}(${t.id})`);
+        }
+    });
+    it('refreshTenderCache', function* () {
+        const ctx = app.mockContext();
+        const tenders = yield ctx.app.mysql.query('SELECT * FROM zh_tender WHERE id > ? and id < ?', [4500, 5000]);
+        console.log(tenders.length);
+        for (const t of tenders) {
+            yield ctx.service.tenderCache.refreshTenderCache(t);
+            console.log(`complete ${t.name}(${t.id})`);
+        }
+    });
+    it('refreshTenderCache', function* () {
+        const ctx = app.mockContext();
+        const tenders = yield ctx.app.mysql.query('SELECT * FROM zh_tender WHERE id > ? and id < ?', [5000, 5500]);
+        console.log(tenders.length);
+        for (const t of tenders) {
+            yield ctx.service.tenderCache.refreshTenderCache(t);
+            console.log(`complete ${t.name}(${t.id})`);
+        }
+    });
+    it('refreshTenderCache', function* () {
+        const ctx = app.mockContext();
+        const tenders = yield ctx.app.mysql.query('SELECT * FROM zh_tender WHERE id > ? and id < ?', [5500, 6000]);
+        console.log(tenders.length);
+        for (const t of tenders) {
+            yield ctx.service.tenderCache.refreshTenderCache(t);
+            console.log(`complete ${t.name}(${t.id})`);
+        }
+    });
+});