Explorar el Código

台账历史相关

MaiXinRong hace 3 años
padre
commit
357c747832

+ 0 - 12
app/controller/dashboard_controller.js

@@ -30,19 +30,7 @@ module.exports = app => {
             const auditMaterial = await ctx.service.materialAudit.getAuditMaterial(ctx.session.sessionUser.accountId);
             const auditAdvance = await ctx.service.advanceAudit.getAuditAdvance(ctx.session.sessionUser.accountId);
             const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
-            // const lastNotice = pa.last_notice ? pa.last_notice : (pa.last_notice === 0 ? new Date() : new Date(pa.last_login * 1000));
-            // const noticeLedger = await ctx.service.ledgerAudit.getNoticeTender(ctx.session.sessionProject.id, pa.id);
-            // const noticeStage = await ctx.service.stageAudit.getNoticeStage(ctx.session.sessionProject.id, pa.id);
-            // const noticeChange = await ctx.service.changeAudit.getNoticeChange(ctx.session.sessionProject.id, pa.id);
-            // const noticeRevise = await ctx.service.reviseAudit.getNoticeRevise(ctx.session.sessionProject.id, pa.id);
-            // const noticeMaterial = await ctx.service.materialAudit.getNoticeMaterial(ctx.session.sessionProject.id, pa.id);
-            // const noticeList = [...noticeLedger, ...noticeStage, ...noticeChange, ...noticeRevise, ...noticeMaterial].sort((a, b) => a.name.localeCompare(b.name, 'zh') && b.create_time - a.create_time).slice(0, 10);
             const noticeList = await ctx.service.noticePush.getNotice(ctx.session.sessionProject.id, pa.id);
-            // const noticeLedger = [];
-            // const noticeStage = [];
-            // const noticeChange = [];
-            // const noticeRevise = [];
-            // const noticeMaterial = [];
             const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
             // 获取销售人员数据
             const salesmanData = await ctx.service.manager.getDataById(projectData.manager_id);

+ 7 - 2
app/controller/ledger_controller.js

@@ -473,9 +473,14 @@ module.exports = app => {
          */
         async loadExplodeData(ctx) {
             try {
-                const ledgerData = await ctx.service.ledger.getData(ctx.tender.id);
+                const ledgerData = ctx.tender.ledgerReadOnly
+                    ? await ctx.helper.loadLedgerDataFromOss(ctx.tender.his.bills_file)
+                    : await ctx.service.ledger.getData(ctx.tender.id);
                 const posData = this.ctx.tender.data.measure_type === measureType.tz.value
-                    ? await ctx.service.pos.getPosData({ tid: ctx.tender.id }) : [];
+                    ? (ctx.tender.ledgerReadOnly
+                        ? await ctx.helper.loadLedgerDataFromOss(ctx.tender.his.pos_file)
+                        : await ctx.service.pos.getData(ctx.tender.id))
+                    : [];
                 const ledgerTags = await this.ctx.service.ledgerTag.getDatas(ctx.tender.id);
                 ctx.body = { err: 0, msg: '', data: { bills: ledgerData, pos: posData, tags: ledgerTags } };
             } catch (err) {

+ 24 - 69
app/controller/revise_controller.js

@@ -189,7 +189,7 @@ module.exports = app => {
                     throw '台账修订会影响审批中的变更令(包含新增部位),请审批完成后再创建台账修订';
                 }
                 const revise = await ctx.service.ledgerRevise.add(ctx.tender.id, ctx.session.sessionUser.accountId);
-                ctx.redirect('/tender/' + ctx.tender.id + '/revise/info');
+                ctx.redirect(`/tender/${ctx.tender.id}/revise/${revise.id}/info`);
             } catch (err) {
                 this.log(err);
                 ctx.redirect(ctx.request.header.referer);
@@ -289,13 +289,6 @@ module.exports = app => {
         }
 
         async _getDefaultReviseInfoData(ctx, revise) {
-            // const reviseBills = revise.bills_file
-            //     ? JSON.parse(await fs.readFileSync(this.ctx.app.config.filePath + revise.bills_file, 'utf8'))
-            //     : await ctx.service.reviseBills.getData(ctx.tender.id);
-
-            // const revisePos = revise.pos_file
-            //     ? JSON.parse(await fs.readFileSync(this.ctx.app.config.filePath + revise.pos_file, 'utf8'))
-            //     : await ctx.service.revisePos.getData(ctx.tender.id);
             const [ledgerSpread, posSpread] = this._getSpreadSetting(revise);
             const sjsRela = await this.ctx.service.project.getSjsRela(ctx.session.sessionProject.id);
             this.ctx.helper.refreshSpreadShow(sjsRela.ledgerCol, [ledgerSpread, posSpread]);
@@ -315,9 +308,7 @@ module.exports = app => {
             }
             return {
                 revise, tender: ctx.tender.data,
-                // reviseBills, revisePos,
                 ledgerSpread, posSpread, tenderMenu, measureType,
-                preUrl: '/tender/' + ctx.tender.id,
                 audit: audit.revise,
                 jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.revise.info),
                 stdBills,
@@ -346,6 +337,7 @@ module.exports = app => {
             renderData.history = true;
             renderData.historyRevise = await ctx.service.ledgerRevise.getAllReviseList(ctx.tender.id);
             renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
+            renderData.preUrl = ctx.url.replace('/info', '');
             await this.layout('revise/info.ejs', renderData, 'revise/info_modal.ejs');
         }
 
@@ -365,6 +357,7 @@ module.exports = app => {
             renderData.historyRevise = [];
             renderData.curAuditor = await ctx.service.reviseAudit.getCurAuditor(revise.id, revise.times);
             renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
+            renderData.preUrl = ctx.url.replace('/info', '');
             await this.layout('revise/info.ejs', renderData, 'revise/info_modal.ejs');
         }
 
@@ -388,6 +381,7 @@ module.exports = app => {
             renderData.auditorList = await ctx.service.reviseAudit.getAuditors(revise.id, revise.times);
             renderData.curAuditor = await ctx.service.reviseAudit.getCurAuditor(revise.id, revise.times);
             renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
+            renderData.preUrl = ctx.url.replace('/info', '');
             await this.layout('revise/info.ejs', renderData, 'revise/info_modal.ejs');
         }
 
@@ -417,21 +411,14 @@ module.exports = app => {
 
         async loadInfoData(ctx) {
             try {
-                const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
-                if (!revise) throw '台账修订数据有误';
+                const revise = await ctx.revise;
 
-                const billsFile = revise.status === audit.revise.status.checked && revise.bills_file
-                    ? this.ctx.app.config.filePath + revise.bills_file
-                    : undefined;
-                const reviseBills = billsFile && fs.existsSync(billsFile)
-                    ? JSON.parse(await fs.readFileSync(billsFile, 'utf8'))
+                const reviseBills = revise.readOnly
+                    ? await ctx.helper.loadLedgerDataFromOss(revise.curHis.bills_file)
                     : await ctx.service.reviseBills.getData(ctx.tender.id);
 
-                const posFile = revise.status === audit.revise.status.checked && revise.pos_file
-                    ? this.ctx.app.config.filePath + revise.pos_file
-                    : undefined;
-                const revisePos = posFile && fs.existsSync(posFile)
-                    ? JSON.parse(await fs.readFileSync(posFile, 'utf8'))
+                const revisePos = revise.readOnly
+                    ? await ctx.helper.loadLedgerDataFromOss(revise.curHis.pos_file)
                     : await ctx.service.revisePos.getData(ctx.tender.id);
 
                 if (revise.uid === ctx.session.sessionUser.accountId &&
@@ -517,6 +504,7 @@ module.exports = app => {
                 // 获取审批流程中左边列表
                 const auditors = await ctx.service.reviseAudit.getAuditorsWithOwner(revise.id, times);
                 const renderData = {
+                    preUrl: ctx.url.replace('/info', ''),
                     measureType, audit, revise,
                     ledgerSpread, posSpread,
                     readOnly: true,
@@ -534,36 +522,6 @@ module.exports = app => {
             }
         }
 
-        async historyInfo(ctx) {
-            try {
-                const data = JSON.parse(ctx.request.body.data);
-                if (!data || !data.rid || data.rid === '') throw '查询的台账修订有误';
-                const reviseInfo = await ctx.service.ledgerRevise.getRevise(ctx.tender.id, data.rid);
-                reviseInfo.end_time_str = reviseInfo.end_time ? ctx.moment(reviseInfo.end_time).format('YYYY-MM-DD HH:mm:ss') : '';
-                ctx.body = { err: 0, msg: '', data: reviseInfo };
-            } catch (err) {
-                this.log(err);
-                ctx.body = this.ajaxErrorBody(err, '获取台账修订历史数据错误');
-            }
-        }
-
-        /**
-         * 加载 数据
-         * @param {} ctx
-         */
-        async loadHistoryData(ctx) {
-            try {
-                const billsFile = await this.ctx.app.hisOss.get(ctx.app.config.hisOssPath + ctx.revise.bills_file);
-                const reviseBills = JSON.parse(billsFile.content);
-                const posFile = await this.ctx.app.hisOss.get(ctx.app.config.hisOssPath + ctx.revise.pos_file);
-                const revisePos = JSON.parse(posFile.content);
-                ctx.body = { err: 0, msg: '', data: { bills: reviseBills, pos: revisePos } };
-            } catch (error) {
-                ctx.helper.log(error);
-                this.ajaxErrorBody(error, '获取台账修订数据错误');
-            }
-        }
-
         async checkRevise(ctx) {
             const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
             if (revise.uid !== ctx.session.sessionUser.accountId) {
@@ -896,12 +854,10 @@ module.exports = app => {
 
                 await ctx.service.reviseAudit.check(revise, checkType, ctx.request.body.opinion, revise.times);
 
-                // ctx.redirect('/tender/' + ctx.tender.id + '/revise/info');
                 ctx.redirect(ctx.request.headers.referer);
             } catch (err) {
                 this.log(err);
                 this.postError(err, '审批失败');
-                // ctx.redirect('/tender/' + ctx.tender.id + '/revise/info');
                 ctx.redirect(ctx.request.headers.referer);
             }
         }
@@ -928,6 +884,7 @@ module.exports = app => {
             const lastStage = await this._getLastStage(ctx);
 
             const renderData = {
+                preUrl: ctx.url.replace('/compare', ''),
                 revise,
                 measureType,
                 lastStage,
@@ -991,10 +948,18 @@ module.exports = app => {
 
         async _loadDataByFilter(ctx, filter) {
             switch(filter) {
-                case 'bills': return await ctx.service.ledger.getAllDataByCondition({where: {tender_id: ctx.tender.id} });
-                case 'pos': return await ctx.service.pos.getAllDataByCondition({where: {tid: ctx.tender.id} });
-                case 'reviseBills': return await ctx.service.reviseBills.getAllDataByCondition({where: {tender_id: ctx.tender.id}});
-                case 'revisePos': return await ctx.service.revisePos.getAllDataByCondition({where: {tid: ctx.tender.id}});
+                case 'bills':
+                    return ctx.revise.preHis ? await this.ctx.helper.loadLedgerDataFromOss(ctx.revise.preHis.bills_file) : [];
+                case 'pos':
+                    return ctx.revise.preHis ? await this.ctx.helper.loadLedgerDataFromOss(ctx.revise.preHis.pos_file) : [];
+                case 'reviseBills':
+                    return ctx.revise.readOnly && ctx.revise.curHis
+                        ? await this.ctx.helper.loadLedgerDataFromOss(ctx.revise.curHis.bills_file)
+                        : await ctx.service.reviseBills.getAllDataByCondition({ where: { tender_id: ctx.tender.id } });
+                case 'revisePos':
+                    return ctx.revise.readOnly && ctx.revise.curHis
+                        ? await this.ctx.helper.loadLedgerDataFromOss(ctx.revise.curHis.pos_file)
+                        : await ctx.service.revisePos.getAllDataByCondition({ where: { tid: ctx.tender.id } });
                 case 'stageBills':
                 case 'stagePos':
                     if (!ctx.lastStage) ctx.lastStage = await this._getLastStage(ctx);
@@ -1039,22 +1004,12 @@ module.exports = app => {
             if (!revise) throw '台账修订数据有误';
 
             const renderData = {
+                preUrl: ctx.url.replace('/gcl-compare', ''),
                 revise,
                 jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.revise.gclCompare),
             };
             await this.layout('revise/gcl_compare.ejs', renderData);
         }
-
-        async bwtz(ctx) {
-            const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
-            if (!revise) throw '台账修订数据有误';
-
-            const renderData = {
-                revise,
-                jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.revise.bwtz),
-            };
-            await this.layout('revise/bwtz.ejs', renderData);
-        }
     }
 
     return ReviseController;

+ 12 - 4
app/controller/stage_controller.js

@@ -234,7 +234,9 @@ module.exports = app => {
         }
 
         async _getStageLedgerData(ctx) {
-            const ledgerData = await ctx.service.ledger.getData(ctx.tender.id);
+            const ledgerData = ctx.stage.ledgerHis
+                ? await ctx.helper.loadLedgerDataFromOss(ctx.stage.ledgerHis.bills_file)
+                : await ctx.service.ledger.getData(ctx.tender.id);
             const dgnData = await ctx.service.stageBillsDgn.getDgnData(ctx.tender.id);
             for (const d of dgnData) {
                 const l = ctx.app._.find(ledgerData, { id: d.id });
@@ -267,7 +269,9 @@ module.exports = app => {
         async _getStagePosData(ctx) {
             let curStageData,
                 preStageData;
-            const posData = await ctx.service.pos.getPosDataWithAddStageOrder({ tid: ctx.tender.id });
+            const posData = ctx.stage.ledgerHis
+                ? await ctx.helper.loadLedgerDataFromOss(ctx.stage.ledgerHis.pos_file)
+                : await ctx.service.pos.getData(ctx.tender.id);
             // 根据当前人,或指定对象查询数据
             // console.time('cur');
             if (ctx.stage.readOnly) {
@@ -1340,8 +1344,12 @@ module.exports = app => {
                 };
                 if (data.main) {
                     result.main = {};
-                    result.main.ledger = await ctx.service.ledger.getData(ctx.tender.id);
-                    result.main.pos = await ctx.service.pos.getPosData({ tid: ctx.tender.id });
+                    result.main.ledger = ctx.stage.ledgerHis
+                        ? await ctx.helper.loadLedgerDataFromOss(ctx.stage.ledgerHis.bills_file)
+                        : await ctx.service.ledger.getData(ctx.tender.id);
+                    result.main.pos = ctx.stage.ledgerHis
+                        ? await ctx.helper.loadLedgerDataFromOss(ctx.stage.ledgerHis.pos_file)
+                        : await ctx.service.pos.getData(ctx.tender.id);
                 }
                 for (const order of data.roles) {
                     const data = { order, bills: [], pos: [] };

+ 6 - 0
app/extend/helper.js

@@ -1472,4 +1472,10 @@ module.exports = {
     createJWT(data) {
         return jwt.sign({ data }, sign.managementApiSecretKey, { expiresIn: '15s' });
     },
+
+    async loadLedgerDataFromOss(url) {
+        const File = await this.ctx.app.hisOss.get(ctx.app.config.hisOssPath + url);
+        if (File.res.status !== 200) return '获取修订台账有误';
+        return JSON.parse(File.content);
+    },
 };

+ 5 - 1
app/middleware/revise_check.js

@@ -25,6 +25,9 @@ module.exports = options => {
                 ? yield this.service.ledgerRevise.getRevise(this.tender.id, this.params.rid)
                 : yield this.service.ledgerRevise.getLastestRevise(this.tender.id);
             if (!revise) throw '台账修订数据有误';
+            // 修订前后,历史台账
+            revise.preHis = revise.pre_his_id ? yield this.service.ledgerHistory.getDataById(revise.pre_his_id) : null;
+            revise.curHis = revise.his_id ? yield this.service.ledgerHistory.getDataById(revise.his_id) : null;
             revise.reviseUsers = [revise.uid];
             if (revise.status !== auditConst.status.uncheck) {
                 const times = revise.status === auditConst.status.checkNo ? revise.times - 1 : revise.times;
@@ -32,7 +35,8 @@ module.exports = options => {
                 const auditorsId = this.helper._.map(auditors, 'audit_id');
                 revise.reviseUsers.push(...auditorsId);
             }
-            revise.readOnly = revise.status === auditConst.status.uncheck || revise.status === auditConst.status.checkNo;
+            revise.readOnly = revise.uid !== this.session.sessionUser.accountId ||
+                revise.status === auditConst.status.checking || revise.status === auditConst.status.checked;
             this.revise = revise;
             yield next;
         } catch (err) {

+ 5 - 0
app/middleware/stage_check.js

@@ -50,6 +50,11 @@ module.exports = options => {
             stage.auditors = yield this.service.stageAudit.getAuditors(stage.id, stage.times);
             stage.curAuditor = yield this.service.stageAudit.getCurAuditor(stage.id, stage.times);
 
+            // 历史台账
+            if (stage.status === status.checked) {
+                stage.ledgerHis = yield this.service.ledgerHistory.getDataById(stage.his_id);
+            }
+
             // 获取最新的期
             stage.highOrder = yield this.service.stage.count({
                 tid: this.tender.id,

+ 1 - 0
app/middleware/tender_check.js

@@ -46,6 +46,7 @@ module.exports = options => {
             if (tender.data.project_id !== this.session.sessionProject.id) {
                 throw '您无权查看该项目';
             }
+            tender.his = tender.data.his_id ? yield this.service.ledgerHistory.getDataById(tender.data.his_id) : null;
             const accountId = this.session.sessionUser.accountId;
             const advanceAuditors = yield this.service.advanceAudit.getAllAuditors(tender.id);
             const advanceAuditorsId = this.helper._.map(advanceAuditors, 'audit_id');

+ 1 - 1
app/public/js/revise.js

@@ -2648,7 +2648,7 @@ $(document).ready(() => {
         // 修订详情 保存
         $('#save').click(function () {
             const content = $('#content').val();
-            postData('save', { content: content }, function () {
+            postData(`/tender/${window.location.pathname.split('/')[2]}/revise/save`, { content: content }, function () {
                 $('#content').attr('org-value', content);
             });
         });

+ 1 - 1
app/public/js/revise_compare.js

@@ -253,7 +253,7 @@ $(document).ready(() => {
     };
 
     // 加载清单&计量单元数据
-    postData('/tender/' + window.location.pathname.split('/')[2] + '/revise/load', {filter: 'bills;pos;reviseBills;revisePos'}, function (result) {
+    postData('load', {filter: 'bills;pos;reviseBills;revisePos'}, function (result) {
         const tenderTreeSetting = {
             id: 'ledger_id',
             pid: 'ledger_pid',

+ 1 - 1
app/public/js/revise_gcl_compare.js

@@ -149,7 +149,7 @@ $(document).ready(() => {
         $('#chapter-list').html(html.join(''));
     }
 
-    postData('/tender/' + window.location.pathname.split('/')[2] + '/revise/load', {filter: 'bills;pos;reviseBills;revisePos;dealBills;spec'}, function (data) {
+    postData('load', {filter: 'bills;pos;reviseBills;revisePos;dealBills;spec'}, function (data) {
         const setting = {
             tree: {
                 id: 'ledger_id',

+ 4 - 4
app/public/js/revise_history.js

@@ -155,15 +155,15 @@ $(document).ready(() => {
         },
     };
     // 加载清单&计量单元数据
-    postData(window.location.pathname + '/load', {}, function (result) {
-        billsTree.loadDatas(result.bills);
+    postData('load', {filter:'reviseBills;revisePos'}, function (result) {
+        billsTree.loadDatas(result.reviseBills);
         treeCalc.calculateAll(billsTree);
         SpreadJsObj.loadSheetData(billsSheet, SpreadJsObj.DataType.Tree, billsTree);
         SpreadJsObj.loadTopAndSelect(billsSheet, ckBillsSpread);
 
-        checkShowLast(result.bills.length);
+        checkShowLast(result.reviseBills.length);
 
-        pos.loadDatas(result.pos);
+        pos.loadDatas(result.revisePos);
         posSpreadObj.loadCurPosData();
         SpreadJsObj.resetTopAndSelect(posSheet);
     }, null);   

+ 13 - 12
app/router.js

@@ -217,21 +217,22 @@ module.exports = app => {
     // app.post('/tender/:id/revise/deal2sgfh', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.deal2sgfh');
 
     // 台账修订页面
-    app.get('/tender/:id/revise/info', sessionAuth, tenderCheck, uncheckTenderCheck, reviseAuditCheck, 'reviseController.info');
-    app.post('/tender/:id/revise/auditors', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.reviseAuditors');
-    app.post('/tender/:id/revise/info/load', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.loadInfoData');
-    app.post('/tender/:id/revise/info/update', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.update');
-    app.post('/tender/:id/revise/info/upload-excel/:ueType', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.uploadExcel');
-    app.post('/tender/:id/revise/info/check', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.checkData');
+    app.get('/tender/:id/revise/:rid/info', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, reviseAuditCheck, 'reviseController.info');
+    app.post('/tender/:id/revise/:rid/auditors', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, 'reviseController.reviseAuditors');
+    app.post('/tender/:id/revise/:rid/info/load', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, 'reviseController.loadInfoData');
+    app.post('/tender/:id/revise/:rid/info/update', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, 'reviseController.update');
+    app.post('/tender/:id/revise/:rid/info/upload-excel/:ueType', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, 'reviseController.uploadExcel');
+    app.post('/tender/:id/revise/:rid/info/check', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, 'reviseController.checkData');
 
-    app.get('/tender/:id/revise/compare', sessionAuth, tenderCheck, uncheckTenderCheck, reviseAuditCheck, 'reviseController.compare');
-    app.get('/tender/:id/revise/gcl-compare', sessionAuth, tenderCheck, uncheckTenderCheck, reviseAuditCheck, 'reviseController.gclCompare');
-    app.post('/tender/:id/revise/load', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, reviseAuditCheck, 'reviseController.loadData');
+    app.get('/tender/:id/revise/:rid/compare', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, reviseAuditCheck, 'reviseController.compare');
+    app.get('/tender/:id/revise/:rid/gcl-compare', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, reviseAuditCheck, 'reviseController.gclCompare');
+    app.post('/tender/:id/revise/:rid/load', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, reviseAuditCheck, 'reviseController.loadData');
 
     // 查看修订数据
-    app.get('/tender/:id/revise/history/:rid', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, 'reviseController.history');
-    app.post('/tender/:id/revise/history/:rid/load', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, 'reviseController.loadHistoryData');
-    app.post('/tender/:id/revise/history/info', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.historyInfo');
+    app.get('/tender/:id/revise/history/:rid/info', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, 'reviseController.history');
+    app.post('/tender/:id/revise/history/:rid/load', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, 'reviseController.loadData');
+    app.get('/tender/:id/revise/history/:rid/gcl-compare', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, 'reviseController.gclCompare');
+    app.get('/tender/:id/revise/history/:rid/compare', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, 'reviseController.compare');
 
     // 修订审批
     app.post('/tender/:id/revise/audit/add', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.addAuditor');

+ 3 - 2
app/service/ledger_audit.js

@@ -278,6 +278,8 @@ module.exports = app => {
                 }
             }
             const sum = await this.ctx.service.ledger.addUp({ tender_id: tenderId /* , is_leaf: true*/ });
+            // 拷贝备份台账数据
+            const his_id = await this.ctx.service.ledgerHistory.backupLedgerHistory(this.ctx.tender.data);
 
             // 拷贝备份台账数据
             const [billsHis, posHis] = await this.backupLedgerHistoryFile();
@@ -294,8 +296,7 @@ module.exports = app => {
                     ledger_status: auditConst.status.checking,
                     total_price: sum.total_price,
                     deal_tp: sum.deal_tp,
-                    bills_file: billsHis,
-                    pos_file: posHis,
+                    his_id: his_id,
                 });
 
                 // 添加短信通知-需要审批提醒功能

+ 130 - 0
app/service/ledger_history.js

@@ -0,0 +1,130 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+module.exports = app => {
+
+    class LedgerTag extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'ledger_history';
+        }
+
+        /** 获取最新数据
+         *
+         * @param {Number}tid - 标段id
+         * @return {Promise<*>} 最新数据
+         */
+        async getLatestHistory(tid) {
+            const his = await this.db.select(this.tableName, {
+                where: { tid },
+                orders: [['in_time', 'desc']],
+                limit: 1, offset: 0,
+            });
+            return his[0];
+        }
+
+        /**
+         * 备份
+         * @param {Object} tender - 标段
+         * @return {Promise<void>} - 新增备份id
+         * @private
+         */
+        async backupLedgerHistory(tender) {
+            const now = new Date();
+            const timestamp = (now).getTime();
+
+            const billsHis = `${this.ctx.session.sessionProject.id}/${tender.id}/ledger/bills${timestamp}.json`;
+            const bills = await this.ctx.service.ledger.getData(tender.id);
+            await this.ctx.oss.put(billsHis, Buffer.from(JSON.stringify(bills), 'utf8'));
+
+            const posHis = `${this.ctx.session.sessionProject.id}/${tender.id}/ledger/pos${timestamp}.json`;
+            const pos = await this.ctx.service.pos.getData(tender.id);
+            await this.ctx.oss.put(posHis, Buffer.from(JSON.stringify(pos), 'utf8'));
+
+            const result = await this.db.insert(this.tableName, {
+                pid: this.ctx.session.sessionProject.id, tid: tender.id,
+                in_time: now,
+                bills_file: billsHis, pos_file: posHis,
+            });
+
+            return result.insertId;
+        }
+
+        /**
+         * 备份
+         * @param {Object} revise - 修订
+         * @return {Promise<void>} - 新增备份id
+         * @private
+         */
+        async backupReviseLedgerHistory(revise) {
+            const now = new Date();
+            const timestamp = (now).getTime();
+
+            const billsHis = `${this.ctx.session.sessionProject.id}/${revise.tid}/ledger/bills${timestamp}-r.json`;
+            const bills = await this.ctx.service.reviseBills.getData(revise.tid);
+            await this.ctx.oss.put(billsHis, Buffer.from(JSON.stringify(bills), 'utf8'));
+
+            const posHis = `${this.ctx.session.sessionProject.id}/${revise.tid}/ledger/pos${timestamp}-r.json`;
+            const pos = await this.ctx.service.revisePos.getData(revise.tid);
+            await this.ctx.oss.put(posHis, Buffer.from(JSON.stringify(pos), 'utf8'));
+
+            const result = await this.db.insert(this.tableName, {
+                pid: this.ctx.session.sessionProject.id, tid: revise.tid,
+                rid: revise.id, rorder: revise.corder,
+                in_time: now,
+                bills_file: billsHis, pos_file: posHis,
+            });
+
+            return result.insertId;
+        }
+
+        /**
+         * 备份 (预留功能)
+         * @param {Object} transaction - 事务
+         * @param {Object} change - 工程变更
+         * @param {Array} newBillsNode - 新增项目节节点
+         * @param {Array} newPosNode - 新增计量单元节点
+         * @return {Promise<void>} - 新增备份id
+         * @private
+         */
+        async backupChangeHistory(transaction, change, newBillsNodes, newPosNodes) {
+            if ((newBillsNodes || newBillsNodes === 0) && (newPosNodes || newPosNodes.length === 0)) return;
+            const now = new Date();
+            const timestamp = (now).getTime();
+
+            const billsHis = `${this.ctx.session.sessionProject.id}/${change.tid}/ledger/bills${timestamp}-c.json`;
+            const bills = await this.ctx.service.ledger.getData(change.tid);
+            if (newBillsNodes.length > 0) bills.push(...newBillsNodes);
+            await this.ctx.oss.put(billsHis, Buffer.from(JSON.stringify(bills), 'utf8'));
+
+            const posHis = `${this.ctx.session.sessionProject.id}/${change.tid}/ledger/pos${timestamp}-c.json`;
+            const pos = await this.ctx.service.pos.getData(change.tid);
+            if (newPosNodes.length > 0) pos.push(...newPosNodes);
+            await this.ctx.oss.put(posHis, Buffer.from(JSON.stringify(pos), 'utf8'));
+
+            const result = await transaction.insert(this.tableName, {
+                pid: this.ctx.session.sessionProject.id, tid: change.tid,
+                cid: change.cid,
+                in_time: now,
+                bills_file: billsHis, pos_file: posHis,
+            });
+
+            return result.insertId;
+        }
+    }
+
+    return LedgerTag;
+};

+ 8 - 23
app/service/ledger_revise.js

@@ -30,7 +30,7 @@ module.exports = app => {
          * @returns {Promise<*>} - ledger_change下所有数据,并关联 project_account(读取提交人名称、单位、公司)
          */
         async getReviseList (tid) {
-            const sql = 'SELECT lc.id, lc.tid, lc.corder, lc.in_time, lc.uid, lc.begin_time, lc.end_time, lc.times, lc.status, lc.valid, lc.content, lc.bills_file,' +
+            const sql = 'SELECT lc.id, lc.tid, lc.corder, lc.in_time, lc.uid, lc.begin_time, lc.end_time, lc.times, lc.status, lc.valid, lc.content, lc.pre_his_id, lc.his_id,' +
                 '    pa.name As user_name, pa.role As user_role, pa.company As user_company' +
                 '  FROM ' + this.tableName + ' As lc' +
                 '  INNER JOIN ' + this.ctx.service.projectAccount.tableName + ' As pa ON lc.uid = pa.id' +
@@ -48,7 +48,7 @@ module.exports = app => {
          * @returns {Promise<*>}
          */
         async getAllReviseList (tid) {
-            const sql = 'SELECT lc.id, lc.tid, lc.corder, lc.in_time, lc.uid, lc.begin_time, lc.end_time, lc.times, lc.status, lc.valid,' +
+            const sql = 'SELECT lc.id, lc.tid, lc.corder, lc.in_time, lc.uid, lc.begin_time, lc.end_time, lc.times, lc.status, lc.valid, lc.pre_his_id, lc.his_id,' +
                 '    pa.name As user_name, pa.role As user_role, pa.company As user_company' +
                 '  FROM ' + this.tableName + ' As lc' +
                 '  INNER JOIN ' + this.ctx.service.projectAccount.tableName + ' As pa ON lc.uid = pa.id' +
@@ -150,26 +150,6 @@ module.exports = app => {
         }
 
         /**
-         * 备份
-         * @param {Object} revise - 修订
-         * @returns {Promise<void>}
-         * @private
-         */
-        async backupReviseHistoryFile(revise) {
-            const timestamp = (new Date()).getTime();
-
-            const billsHis = `${this.ctx.session.sessionProject.id}/${this.ctx.tender.id}/bills${timestamp}.json`;
-            const bills = await this.ctx.service.reviseBills.getData(revise.tid);
-            await this.ctx.app.hisOss.put(this.ctx.app.config.hisOssPath + billsHis, Buffer.from(JSON.stringify(bills), 'utf8'));
-
-            const posHis = `${this.ctx.session.sessionProject.id}/${this.ctx.tender.id}/pos${timestamp}.json`;
-            const pos = await this.ctx.service.revisePos.getData(revise.tid);
-            await this.ctx.app.hisOss.put(this.ctx.app.config.hisOssPath + posHis, Buffer.from(JSON.stringify(pos), 'utf8'));
-
-            return [billsHis, posHis];
-        }
-
-        /**
          * 新增修订
          * @param {Number}tid - 标段id
          * @param {Number}uid - 提交人id
@@ -180,9 +160,11 @@ module.exports = app => {
                 throw '数据错误';
             }
             const maxOrder = await this.getNewOrder(tid);
+            const latest = await this.ctx.service.ledgerHistory.getLatestHistory(tid);
+            if (!latest) throw '台账历史数据有误';
             const data = {
                 id: this.uuid.v4(), tid: tid, uid: uid,
-                corder: maxOrder + 1, in_time: new Date(), status: audit.status.uncheck,
+                corder: maxOrder + 1, in_time: new Date(), status: audit.status.uncheck, pre_his_id: latest.id,
             };
             const transaction = await this.db.beginTransaction();
             try {
@@ -209,13 +191,16 @@ module.exports = app => {
          * @returns {Promise<void>}
          */
         async cancelRevise(revise) {
+            const his_id = await this.ctx.service.ledgerHistory.backupReviseLedgerHistory(revise);
             const transaction = await this.db.beginTransaction();
             try {
                 const [billsHis, posHis] = await this.backupReviseHistoryFile(revise);
                 const result = await transaction.update(this.tableName, {
                     id: revise.id, valid: false, end_time: new Date(),
                     bills_file: billsHis, pos_file: posHis,
+                    his_id,
                 });
+                await transaction.update(this.ctx.service.ledgerHistory.tableName, { id: his_id, valid: 0 });
                 // 投资进度改变状态
                 await transaction.update(this.ctx.service.schedule.tableName, { revising: 0 }, { where: { tid: this.ctx.tender.id } });
                 await transaction.commit();

+ 3 - 4
app/service/revise_audit.js

@@ -231,7 +231,7 @@ module.exports = app => {
             const time = new Date();
 
             // 拷贝备份台账数据
-            const [billsHis, posHis] = await this.ctx.service.ledgerRevise.backupReviseHistoryFile(revise);
+            const his_id = await this.ctx.service.ledgerRevise.backupReviseLedgerHistory(revise);
 
             const transaction = await this.db.beginTransaction();
             try {
@@ -245,8 +245,7 @@ module.exports = app => {
                 const reviseData = {
                     id: revise.id,
                     status: auditConst.status.checking,
-                    bills_file: billsHis,
-                    pos_file: posHis,
+                    his_id,
                 };
                 if (revise.times === 1) {
                     reviseData.begin_time = time;
@@ -653,7 +652,7 @@ module.exports = app => {
         async getNoticeContent(pid, tid, rid, uid) {
             const noticeSql =
                 'SELECT * FROM (SELECT ' +
-                '  t.`id` As `tid`, t.`name`, r.`corder`, pa.`name` As `su_name`, pa.role As `su_role`' +
+                '  t.`id` As `tid`, t.`name`, r.`corder`, r.`id` As rid, pa.`name` As `su_name`, pa.role As `su_role`' +
                 '  FROM (SELECT * FROM ?? WHERE `id` = ? ) As t' +
                 '  LEFT JOIN ?? As r On r.`id` = ? ' +
                 '  LEFT JOIN ?? As pa ON pa.`id` = ? ' +

+ 4 - 0
app/service/rpt_gather_memory.js

@@ -25,12 +25,14 @@ const gatherUtils = {
             for (const cd of completeDatas) {
                 data[cd.prefix + 'id'] = cd.id;
                 data[cd.prefix + 'name'] = cd.name;
+                data[cd.prefix + 'category'] = cd.category;
             }
         }
     },
     gatherStage: function (tender, gatherNode, sourceNode, prefix, helper) {
         gatherNode[prefix + 'id'] = tender.id;
         gatherNode[prefix + 'name'] = tender.name;
+        gatherNode[prefix + 'category'] = tender.category;
 
         gatherNode[prefix + "qty"] = helper.add(gatherNode[prefix + "qty"], sourceNode.quantity);
         gatherNode[prefix + "tp"] = helper.add(gatherNode[prefix + "tp"], sourceNode.total_price);
@@ -99,6 +101,7 @@ const gatherUtils = {
     gatherZone: function (tender, gatherNode, sourceNode, prefix, helper) {
         gatherNode[prefix + 'id'] = tender.id;
         gatherNode[prefix + 'name'] = tender.name;
+        gatherNode[prefix + 'category'] = tender.category;
 
         gatherNode[prefix + "qty"] = helper.add(gatherNode[prefix + "qty"], sourceNode.quantity);
         gatherNode[prefix + "tp"] = helper.add(gatherNode[prefix + "tp"], sourceNode.total_price);
@@ -131,6 +134,7 @@ const gatherUtils = {
     gatherLedger: function (tender, gatherNode, sourceNode, prefix, helper) {
         gatherNode[prefix + 'id'] = tender.id;
         gatherNode[prefix + 'name'] = tender.name;
+        gatherNode[prefix + 'category'] = tender.category;
 
         gatherNode[prefix + "qty"] = helper.add(gatherNode[prefix + "qty"], sourceNode.quantity);
         gatherNode[prefix + "tp"] = helper.add(gatherNode[prefix + "tp"], sourceNode.total_price);

+ 2 - 0
app/service/stage_audit.js

@@ -470,6 +470,7 @@ module.exports = app => {
                     await this.ctx.helper.sendWechat(nextAudit.aid, smsTypeConst.const.JL, smsTypeConst.judge.approval.toString(), wxConst.template.stage, wechatData);
                 } else {
                     await this.ctx.service.tenderTag.saveTenderTag(this.ctx.tender.id, {stage_time: new Date()}, transaction);
+                    const ledgerHis = await this.ctx.service.ledgerHistory.getLatestHistory(this.ctx.tender.id);
                     // 本期结束
                     // 生成截止本期数据 final数据
                     await this.ctx.service.stageBillsFinal.generateFinalData(transaction, this.ctx.tender, this.ctx.stage);
@@ -485,6 +486,7 @@ module.exports = app => {
                         sf_tp: sfPay.tp,
                         tp_history: JSON.stringify(this.ctx.stage.tp_history),
                         cache_time_r: this.ctx.stage.cache_time_l,
+                        his_id: ledgerHis.id,
                     });
 
                     // 添加短信通知-审批通过提醒功能

+ 1 - 1
app/service/tender.js

@@ -15,7 +15,7 @@ const fs = require('fs');
 const path = require('path');
 const commonQueryColumns = [
     'id', 'project_id', 'name', 'status', 'category', 'ledger_times', 'ledger_status', 'measure_type', 'user_id', 'valuation',
-    'total_price', 'deal_tp', 'copy_id', 's2b_gxby_check', 's2b_gxby_limit', 's2b_dagl_check', 's2b_dagl_limit', 'has_rela',
+    'total_price', 'deal_tp', 'copy_id', 's2b_gxby_check', 's2b_gxby_limit', 's2b_dagl_check', 's2b_dagl_limit', 'has_rela', 'his_id',
 ];
 
 module.exports = app => {

+ 2 - 2
app/view/dashboard/index.ejs

@@ -65,7 +65,7 @@
                                                 <div class="row">
                                                     <div class="col-auto"><span class="badge badge-info">台账修订</span></div>
                                                     <div class="col-6"><a href="/tender/<%- revise.t_id %>"><%- revise.t_name %></a> 台账修订(第<%- revise.corder %>次)</div>
-                                                    <div class="col-3 ml-auto text-right pl-0"><a href="/tender/<%- revise.t_id %>/revise/info" class="btn btn-sm btn-outline-primary"><% if (revise.status === acRevise.status.checking) { %>审批<% } else if (revise.status === acRevise.status.checkNo) { %>重新上报<% } %></a></div>
+                                                    <div class="col-3 ml-auto text-right pl-0"><a href="/tender/<%- revise.t_id %>/revise/<%- revise.id %>/info" class="btn btn-sm btn-outline-primary"><% if (revise.status === acRevise.status.checking) { %>审批<% } else if (revise.status === acRevise.status.checkNo) { %>重新上报<% } %></a></div>
                                                 </div>
                                                 <p class="mt-1 mb-0"><%- revise.audit_name %><small class="ml-1 text-muted"><%- (revise.audit_role ? '- ' + revise.audit_role: '') %></small>
                                                     <span class="pull-right text-muted"><%- (
@@ -246,7 +246,7 @@
                                                         <div class="col-auto"><span class="badge badge-info">台账修订</span></div>
                                                         <div class="col-6">
                                                             <a href="/tender/<%- notice.tid %>"><%- notice.name %></a>
-                                                            <a href="/tender/<%- notice.tid %>/revise/info">台账修订(第<%- notice.corder %>次)</a>
+                                                            <a href="/tender/<%- notice.tid %>/revise/<%- notice.rid %>/info">台账修订(第<%- notice.corder %>次)</a>
                                                             <%- acRevise.statusString[notice.status]%>
                                                         </div>
                                                     </div>

+ 2 - 2
app/view/revise/history.ejs

@@ -1,8 +1,8 @@
-<% include ../tender/tender_sub_menu.ejs %>
+<% include ./sub_menu.ejs %>
 <div class="panel-content">
     <div class="panel-title">
         <div class="title-main d-flex justify-content-between">
-            <% include ../tender/tender_sub_mini_menu.ejs %>
+            <% include ./sub_mini_menu.ejs %>
             <!--工具-->
             <div>
                 <div class="d-inline-block">

+ 6 - 6
app/view/revise/index.ejs

@@ -64,19 +64,19 @@
                         <td>
                             <% if (lr.valid) { %>
                             <% if (lr.status === auditConst.status.uncheck && lr.uid === ctx.session.sessionUser.accountId) { %>
-                            <a href="<%- preUrl + '/revise/info' %>" class="btn btn-primary btn-sm">修订</a>
+                            <a href="<%- preUrl + '/revise/' + lr.id + '/info' %>" class="btn btn-primary btn-sm">修订</a>
                             <a href="#remove" data-toggle="modal" data-target="#remove" class="btn btn-secondary btn-sm">作废</a>
                             <% } else if (lr.status === auditConst.status.checking && lr.curAuditor.audit_id === ctx.session.sessionUser.accountId) { %>
-                            <a href="<%- preUrl + '/revise/info' %>" class="btn btn-success btn-sm">审批</a>
+                            <a href="<%- preUrl + '/revise/' + lr.id + '/info' %>" class="btn btn-success btn-sm">审批</a>
                             <% } else if (lr.status === auditConst.status.checkNo && lr.uid === ctx.session.sessionUser.accountId) { %>
-                            <a href="<%- preUrl + '/revise/info' %>" class="btn btn-primary btn-sm">重新上报</a>
+                            <a href="<%- preUrl + '/revise/'  + lr.id + '/info' %>" class="btn btn-primary btn-sm">重新上报</a>
                             <a href="#remove" data-toggle="modal" data-target="#remove" class="btn btn-secondary btn-sm">作废</a>
                             <% } else if (lr.status !== auditConst.status.checked) { %>
-                            <a href="<%- preUrl + '/revise/info' %>">查看修订内容</a>
+                            <a href="<%- preUrl + '/revise/' + lr.id + '/info' %>">查看修订内容</a>
                             <% } %>
                             <% } %>
-                            <% if (lr.bills_file && (lr.status === auditConst.status.checked || lr.valid)) { %>
-                                <a href="<%- preUrl + '/revise/history/' + lr.id %>">查看修订内容</a>
+                            <% if (lr.his_id && (lr.status === auditConst.status.checked && lr.valid)) { %>
+                                <a href="<%- preUrl + '/revise/history/' + lr.id + '/info' %>">查看修订内容</a>
                             <% } %>
                         </td>
                     </tr>

+ 3 - 3
app/view/revise/info_modal.ejs

@@ -113,7 +113,7 @@
 <<!--审批通过-->
     <div class="modal fade sp-location-list" id="sp-done" data-backdrop="static">
         <div class="modal-dialog modal-lg" role="document">
-            <form class="modal-content" action="<%- preUrl %>/revise/audit/check" method="post"
+            <form class="modal-content" action="/tender/<%- ctx.tender.id %>/revise/audit/check" method="post"
                 onsubmit="return auditCheck(0);">
                 <div class="modal-header">
                     <h5 class="modal-title">审批通过</h5>
@@ -304,7 +304,7 @@
     <!--审批退回-->
     <div class="modal fade sp-location-list" id="sp-back" data-backdrop="static">
         <div class="modal-dialog modal-lg" role="document">
-            <form class="modal-content modal-lg" action="<%- preUrl %>/revise/audit/check" method="post"
+            <form class="modal-content modal-lg" action="/tender/<%- ctx.tender.id %>/revise/audit/check" method="post"
                 onsubmit="return auditCheck(1);">
                 <div class="modal-header">
                     <h5 class="modal-title">审批退回</h5>
@@ -711,7 +711,7 @@
                         </div>
                     </div>
                 </div>
-                <form class="modal-footer" method="post" action="<%- preUrl %>/revise/audit/start"
+                <form class="modal-footer" method="post" action="/tender/<%- ctx.tender.id %>/revise/audit/start"
                     name="revise-start">
                     <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>">
                     <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>

+ 1 - 1
app/view/revise/sub_menu.ejs

@@ -1,5 +1,5 @@
 <div class="panel-sidebar" id="sub-menu">
-    <div class="sidebar-title" data-toggle="tooltip" data-placement="right" data-original-title="<%- revise.corder %># 台账修订"><%- revise.corder %># 台账修订</div>
+    <div class="sidebar-title" data-toggle="tooltip" data-placement="right" data-original-title="<%- ctx.revise.corder %># 台账修订"><%- ctx.revise.corder %># 台账修订</div>
     <div class="scrollbar-auto">
         <% include ./sub_menu_list.ejs %>
         <div class="side-fold"><a href="javascript: void(0)" data-toggle="tooltip" data-placement="top" data-original-title="折叠侧栏" id="to-mini-menu"><i class="fa fa-upload fa-rotate-270"></i></a></div>

+ 3 - 3
app/view/revise/sub_menu_list.ejs

@@ -1,4 +1,4 @@
 <nav-menu title="返回" url="/tender/<%= ctx.tender.id %>/revise" tclass="text-primary" ml="1" icon="fa-chevron-left"></nav-menu>
-<nav-menu title="台账修订" url="/tender/<%= ctx.tender.id %>/revise/info" ml="3" active="<%= ctx.url.indexOf('revise/info') %>"></nav-menu>
-<nav-menu title="台账对比" url="/tender/<%= ctx.tender.id %>/revise/compare" ml="3" active="<%= ctx.url.indexOf('revise/compare') %>"></nav-menu>
-<nav-menu title="清单对比" url="/tender/<%= ctx.tender.id %>/revise/gcl-compare" ml="3" active="<%= ctx.url.indexOf('revise/gcl-compare') %>"></nav-menu>
+<nav-menu title="台账修订" url="<%= preUrl %>/info" ml="3" active="<%= ctx.url.indexOf('/info') %>"></nav-menu>
+<nav-menu title="台账对比" url="<%= preUrl %>/compare" ml="3" active="<%= ctx.url.indexOf('/compare') %>"></nav-menu>
+<nav-menu title="清单对比" url="<%= preUrl %>/gcl-compare" ml="3" active="<%= ctx.url.indexOf('/gcl-compare') %>"></nav-menu>

+ 2 - 0
builder_report_index_define.js

@@ -1105,6 +1105,8 @@ const gather_stage_bills = {
         { name: '(合计)合同-设计数量2', field: 's_deal_dgn_qty2', type: dataType.currency },
         { name: '(合计)变更-设计数量1', field: 's_c_dgn_qty1', type: dataType.currency },
         { name: '(合计)变更-设计数量2', field: 's_c_dgn_qty2', type: dataType.currency },
+
+        { name: '标段-分类', field: 't_category', type: dataType.str },
     ],
 };
 const gather_tender_info = {

+ 3 - 0
config/config.local.js

@@ -100,6 +100,9 @@ module.exports = appInfo => {
             fujian: {
                 bucket: 'jiliang-qa',
             },
+            his: {
+                bucket: 'jiliang-his',
+            }
         },
         default: {
             accessKeyId: 'LTAIALMjBHOs9PLA',

+ 3 - 0
config/config.qa.js

@@ -62,6 +62,9 @@ module.exports = appInfo => {
             fujian: {
                 bucket: 'jiliang-qa',
             },
+            his: {
+                bucket: 'jiliang-his',
+            }
         },
         default: {
             accessKeyId: 'LTAIALMjBHOs9PLA',

+ 3 - 0
config/config.uat.js

@@ -68,6 +68,9 @@ module.exports = appInfo => {
             fujian: {
                 bucket: 'jiliang-qa',
             },
+            his: {
+                bucket: 'jiliang-his',
+            }
         },
         default: {
             accessKeyId: 'LTAIALMjBHOs9PLA',

+ 1 - 1
config/web.js

@@ -248,7 +248,7 @@ const JsFiles = {
                 mergeFile: 'revise',
             },
             history: {
-                files: ['/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js', '/public/js/decimal.min.js'],
+                files: ['/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js', '/public/js/decimal.min.js', '/public/js/component/menu.js'],
                 mergeFiles: [
                     '/public/js/sub_menu.js',
                     '/public/js/div_resizer.js',

+ 151 - 0
db_script/ledger_his.js

@@ -0,0 +1,151 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const audit = require('../app/const/audit');
+
+const mysql = require('mysql');
+const oss = require('ali-oss');
+const config = process.argv.splice(2)[0];
+if (['local', 'uat', 'default'].indexOf(config) < 0) throw `参数错误: ${config}`;
+const options = require(`../config/config.${config}`)({ baseDir: __dirname + '/app', root: __dirname, name: 'calc' });
+
+const pool = mysql.createPool(options.mysql.client);
+const ossOption = {
+    bucket: options.oss.clients.his.bucket,
+    accessKeyId: options.oss.default.accessKeyId,
+    accessKeySecret: options.oss.default.accessKeySecret,
+    endpoint: options.oss.default.endpoint,
+    timeout: options.oss.default.timeout,
+};
+const ossClient = new oss(ossOption);
+
+const querySql = async function(sql, sqlParam) {
+    return new Promise(function(resolve, reject) {
+        pool.getConnection(function(err, conn) {
+            if (err) {
+                if (err) console.log(err);
+                reject(err);
+            } else {
+                conn.query(sql, sqlParam, function(err, rows, fields) {
+                    if (err) console.log(err);
+                    // 释放连接
+                    conn.release();
+                    // 传递Promise回调对象
+                    resolve(rows);
+                });
+            }
+        });
+    });
+};
+
+const getTableName = function(tender, table) {
+    // switch(table) {
+    //     case 'ledger': return 'zh_ledger_' + (tender.id % 10);
+    //     case 'pos': return 'zh_pos_' + (tender.id % 20);
+    //     case 'revise_bills': return 'zh_revise_bills_' + (tender.id % 10);
+    //     case 'revise_pos': return 'zh_revise_pos_' + (tender.id % 20);
+    // }
+    return table.indexOf('pos') > 0 ? `zh_${table}_${tender.id % 20}` : `zh_${table}_${tender.id % 10}`;
+};
+
+const saveLedgerHis = async function(tender) {
+    const now = new Date();
+    const timestamp = (now).getTime();
+
+    const billsHis = `${tender.project_id}/${tender.id}/ledger/bills${timestamp}.json`;
+    const bills = await querySql('Select * From ?? where tender_id = ?', [getTableName(tender, 'ledger'), tender.id]);
+    console.log(`saveBillsFile: ${billsHis}(${bills.length})`);
+    await ossClient.put(options.hisOssPath + billsHis, Buffer.from(JSON.stringify(bills), 'utf8'));
+
+    const posHis = `${tender.project_id}/${tender.id}/ledger/pos${timestamp}.json`;
+    const pos = await querySql('Select * From ?? where tid = ?', [getTableName(tender, 'pos'), tender.id]);
+    console.log(`savePosFile: ${posHis}(${pos.length})`);
+    await ossClient.put(options.hisOssPath + posHis, Buffer.from(JSON.stringify(pos), 'utf8'));
+
+    const result = await querySql('Insert Into zh_ledger_history(pid, tid, in_time, bills_file, pos_file) Values(?, ?, ?, ?, ?)',
+        [tender.project_id, tender.id, now, billsHis, posHis]);
+
+    if (!result) throw 'err';
+    return result.insertId;
+};
+
+const saveReviseLedgerHis = async function (tender, revise) {
+    const now = new Date();
+    const billsHis = revise.bills_file;
+    const posHis = revise.pos_file;
+
+    const result = await querySql('Insert Into zh_ledger_history(pid, tid, in_time, bills_file, pos_file, rid, rorder) Values(?, ?, ?, ?, ?)',
+        [tender.project_id, tender.id, now, billsHis, posHis, revise.id, revise.corder]);
+
+    console.log(result);
+    if (!result) throw 'err';
+    return result.insertId;
+};
+
+const doCompleteTender = async function(t) {
+    if (t.his_id) return;
+    const revise = await querySql('Select * From zh_stage where tid = ? order By in_time asc', [t.id]);
+    if (revise.length > 0) {
+        let his_id;
+        for (const r of revise) {
+            const preRevise = revise.find(x => { return x.status === audit.revise.status.checked && x.corder === r.corder - 1});
+            if (preRevise) {
+                await querySql('Update zh_stage Set pre_his_id = ? Where id = ?', [preRevise.his_id, r.id]);
+            }
+            if (r.bills_file) {
+                r.his_id = saveReviseLedgerHis(t, r);
+                his_id = r.his_id;
+            }
+        }
+        if (!his_id) his_id = await saveLedgerHis(t);
+        await querySql('Update zh_tender Set his_id = ? Where id = ?', [his_id, t.id]);
+        const stages = await querySql('Select * From zh_stage where tid = ? and status = ?', [t.id, audit.stage.status.checked]);
+        for (const s of stages) {
+            if (s.status === audit.stage.status.checked) {
+                await querySql('Update zh_stage Set his_id = ? Where id = ?', [his_id, s.id]);
+            }
+        }
+    } else {
+        const ledgerHis = await saveLedgerHis(t);
+        console.log(`saveLedgerHis: ${t.name}(${t.id})`);
+        await querySql('Update zh_tender Set his_id = ? Where id = ?', [ledgerHis, t.id]);
+        const stages = await querySql('Select * From zh_stage where tid = ? and status = ?', [t.id, audit.stage.status.checked]);
+        for (const s of stages) {
+            if (s.status === audit.stage.status.checked) {
+                await querySql('Update zh_stage Set his_id = ? Where id = ?', [ledgerHis, s.id]);
+            }
+        }
+    }
+};
+
+const doComplete = async function() {
+    try {
+        const tenders = await querySql('Select * From zh_tender where ledger_status <> ?', [audit.ledger.status.uncheck]);
+        for (const t of tenders) {
+            await doCompleteTender(t);
+        }
+    } catch (err) {
+        console.log(err);
+    }
+    pool.end();
+};
+doComplete();
+
+// const doCompeletTest = async function() {
+//     try {
+//         const t = await querySql('Select * From zh_tender where id = ?', [1003]);
+//         await doCompleteTender(t[0]);
+//     } catch (err) {
+//         console.log(err);
+//     }
+//     pool.end();
+// };
+// doCompeletTest();
+

+ 25 - 0
sql/update.sql

@@ -237,3 +237,28 @@ CREATE TABLE `zh_material_checklist`  (
   `had_bills` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否已添加工料',
   PRIMARY KEY (`id`) USING BTREE
 ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '默认清单设置功能';
+
+CREATE TABLE `zh_ledger_history` (
+  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+  `pid` bigint(20) unsigned NOT NULL COMMENT '项目id',
+  `tid` bigint(20) unsigned NOT NULL COMMENT '标段id',
+  `rid` varchar(36) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '修订id',
+  `rorder` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '修订序号',
+  `cid` varchar(36) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '工程变更id',
+  `in_time` datetime NOT NULL,
+  `bills_file` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '项目节数据文件',
+  `pos_file` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '计量单元数据文件',
+  `valid`  tinyint(4) UNSIGNED NOT NULL DEFAULT 1 COMMENT '是否有效',
+  PRIMARY KEY (`id`),
+  KEY `idx_tid_valid_time` (`tid`,`valid`,`in_time`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+
+ALTER TABLE `zh_ledger_revise`
+ADD COLUMN `his_id`  bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT '修订后,台账历史数据id' AFTER `content`,
+ADD COLUMN `pre_his_id`  bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT '修订前,台账历史数据id' AFTER `his_id`;
+
+ALTER TABLE `zh_tender`
+ADD COLUMN `his_id`  bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT '台账历史数据id' AFTER `s2b_dagl_limit`;
+
+ALTER TABLE `zh_stage`
+ADD COLUMN `his_id`  bigint(20) UNSIGNED NOT NULL COMMENT '历史台账id' AFTER `tp_history`;