浏览代码

1. 引入期变更数据,V0.5
2. 日志调整

MaiXinRong 3 年之前
父节点
当前提交
82f81157d5

+ 44 - 30
app/controller/stage_controller.js

@@ -252,12 +252,8 @@ module.exports = app => {
                 ? await ctx.service.ledger.loadDataFromOss(ctx.tender.id, ctx.stage.ledgerHis.bills_file)
                 : await ctx.service.ledger.getAllDataByCondition({ columns: ledgerColumn, where: { tender_id: ctx.tender.id } });
             const dgnData = await ctx.service.stageBillsDgn.getDgnData(ctx.tender.id);
-            for (const d of dgnData) {
-                const l = ctx.app._.find(ledgerData, { id: d.id });
-                ctx.app._.assignIn(l, d);
-            }
-            let curStageData,
-                preStageData;
+            const importData = await ctx.service.stageImportChange.getImportLid(ctx.stage.id);
+            let curStageData;
             // 当前操作人查看最新数据,其他人查看历史数据
             if (ctx.stage.readOnly) {
                 curStageData = await ctx.service.stageBills.getAuditorStageData2(ctx.tender.id, ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder);
@@ -269,25 +265,21 @@ module.exports = app => {
                 }
             }
             // 查询截止上期数据
-            if (ctx.stage.order > 1) {
-                preStageData = await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, ctx.stage.order - 1);
-            } else {
-                preStageData = [];
-            }
+            const preStageData = ctx.stage.order > 1 ? await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, ctx.stage.order - 1) : [];
             this.ctx.helper.assignRelaData(ledgerData, [
+                { data: dgnData, fields: ['deal_dgn_qty1', 'deal_dgn_qty2', 'c_dgn_qty1', 'c_dgn_qty2'], prefix: '', relaId: 'id'},
+                { data: importData, fields: ['is_import'], prefix: '', relaId: 'lid'},
                 { data: curStageData, fields: ['contract_qty', 'contract_expr', 'contract_tp', 'qc_qty', 'qc_tp', 'postil'], prefix: '', relaId: 'lid' },
                 { data: preStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'used'], prefix: 'pre_', relaId: 'lid' },
             ]);
             return ledgerData;
         }
         async _getStagePosData(ctx, posColumn) {
-            let curStageData,
-                preStageData;
+            let curStageData;
             const posData =  ctx.stage.ledgerHis
                 ? await ctx.service.ledger.loadDataFromOss(ctx.tender.id, ctx.stage.ledgerHis.pos_file)
                 : await ctx.service.pos.getAllDataByCondition({ columns: posColumn, where: { tid: ctx.tender.id } });
             // 根据当前人,或指定对象查询数据
-            // console.time('cur');
             if (ctx.stage.readOnly) {
                 curStageData = await ctx.service.stagePos.getAuditorStageData2(ctx.tender.id,
                     ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder);
@@ -299,18 +291,8 @@ module.exports = app => {
                     await ctx.service.stagePos.deleteById(surplus);
                 }
             }
-            // console.timeEnd('cur');
             // 查询截止上期数据
-            // console.time('pre');
-            if (ctx.stage.order > 1) {
-                preStageData = await ctx.service.stagePosFinal.getFinalData(ctx.tender.data, ctx.stage.order - 1);
-            } else {
-                preStageData = [];
-            }
-            // console.timeEnd('pre');
-            // console.time('assign');
-            // console.log('cur: ' + curStageData.length);
-            // console.log('pre: ' + preStageData.length);
+            const preStageData = ctx.stage.order > 1 ? await ctx.service.stagePosFinal.getFinalData(ctx.tender.data, ctx.stage.order - 1) : [];
             this.ctx.helper.assignRelaData(posData, [
                 { data: curStageData, fields: ['contract_qty', 'contract_expr', 'qc_qty', 'postil'], prefix: '', relaId: 'pid' },
                 { data: preStageData, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid' },
@@ -364,6 +346,9 @@ module.exports = app => {
                         case 'change':
                             responseData.data.changeData = await this._getStageChangeData(ctx);
                             break;
+                        case 'import_change':
+                            responseData.data.import_change = await this.ctx.service.stageImportChange.getAllDataByCondition({ where: { sid: this.ctx.stage.id } });
+                            break;
                         case 'dealBills':
                             responseData.data.dealBills = await ctx.service.dealBills.getAllDataByCondition({
                                 where: { tender_id: this.ctx.tender.id },
@@ -576,7 +561,8 @@ module.exports = app => {
                 if (!data.cid) {
                     throw '查询数据错误';
                 }
-                const detailData = await this._getChangeDetailData(ctx.tender.id, ctx.stage.id, data.cid);
+                console.log(data);
+                const detailData = await this._getChangeDetailData(ctx.tender.id, ctx.stage.id, data.cid, data.is_import);
                 ctx.body = { err: 0, msg: '', data: detailData };
             } catch (err) {
                 this.log(err);
@@ -1055,12 +1041,17 @@ module.exports = app => {
          * @return {Promise<{}>}
          * @private
          */
-        async _getChangeDetailData(tid, sid, cid) {
+        async _getChangeDetailData(tid, sid, cid, isImport) {
             const data = {};
             data.attachments = await this.ctx.service.changeAtt.getChangeAttachment(cid);
             data.bills = await this.ctx.service.changeAuditList.getAllDataByCondition({ where: { cid } });
-            data.addUsedBills = await this.ctx.service.stageChange.getUsedData(tid, cid);
-            data.curUsedBills = await this.ctx.service.stageChange.getStageUsedData(sid, cid);
+            if (isImport) {
+                data.endUsedBills = await this.ctx.service.stageImportChange.getChangeEndUsedData(tid, cid);
+                data.curUsedBills = await this.ctx.service.stageImportChange.getChangeUsedData(sid, cid);
+            } else {
+                data.endUsedBills = await this.ctx.service.stageChange.getUsedData(tid, cid);
+                data.curUsedBills = await this.ctx.service.stageChange.getStageUsedData(sid, cid);
+            }
             return data;
         }
         /**
@@ -1077,14 +1068,37 @@ module.exports = app => {
                 data.changes = await ctx.service.stageChange.getChangeWithUsedInfo(ctx.stage);
                 if (data.changes.length > 0) {
                     const change = data.changes[0];
-                    change.detail = await this._getChangeDetailData(ctx.tender.id, ctx.stage.id, change.cid);
+                    change.detail = await this._getChangeDetailData(ctx.tender.id, ctx.stage.id, change.cid, false);
                 }
+                data.import_changes = await ctx.service.stageImportChange.getChangeWithUsedInfo(ctx.stage);
+                if (data.import_changes.length > 0) {
+                    const change = data.import_changes[0];
+                    change.detail = await this._getChangeDetailData(ctx.tender.id, ctx.stage.id, change.cid, true);
+                }
+                data.used_import_cid = await ctx.service.stageImportChange.getStageUsedChangeId(ctx.stage.id);
                 ctx.body = { err: 0, msg: '', data };
             } catch (err) {
                 this.log(err);
                 ctx.body = { err: 1, msg: err.toString(), data: null };
             }
         }
+
+        async getImportChangeData(ctx) {
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                if (!data.import_lid) throw '查询数据错误';
+                const result = {};
+                result.import_changes = await ctx.service.stageImportChange.getChangeWithUsedInfo(ctx.stage, data.import_lid);
+                if (result.import_changes.length > 0) {
+                    const change = result.import_changes[0];
+                    change.detail = await this._getChangeDetailData(ctx.tender.id, ctx.stage.id, change.cid, true);
+                }
+                ctx.body = { err: 0, msg: '', data: result };
+            } catch (err) {
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
+            }
+        }
         /**
          * 变更令 (Get)
          * @param ctx

+ 26 - 24
app/lib/sum_load.js

@@ -340,9 +340,13 @@ class gatherStageGclTree extends loadGclBaseTree {
                 unit_price: d.unit_price,
                 org_contract_qty: this.cover ? d.contract_qty || 0 : 0,
                 org_contract_tp: this.cover ? d.contract_tp || 0 : 0,
+                org_qc_qty: d.is_import ? 0 : d.qc_qty || 0,
+                org_qc_tp: d.is_import ? 0 : d.qc_tp || 0,
                 org_order: d.order,
                 contract_qty: 0,
                 contract_tp: 0,
+                qc_qty: 0,
+                qc_tp: 0,
                 is_tp: d.is_tp,
                 hasPos: relaPos.length > 0,
             };
@@ -357,12 +361,7 @@ class gatherStageGclTree extends loadGclBaseTree {
         if (!node.change_detail) node.change_detail = [];
         for (const cd of source.change_detail) {
             if (!cd.qty) continue;
-            let ncd = node.change_detail.find(x => { return x.cid === cd.cid; });
-            if (!ncd) {
-                ncd = { cid: cd.cid, c_code: cd.c_code };
-                node.change_detail.push(ncd);
-            }
-            ncd.qty = this.ctx.helper.add(ncd.qty, cd.qty);
+            node.change_detail.push(cd);
         }
     }
     gather(source, parent) {
@@ -376,36 +375,36 @@ class gatherStageGclTree extends loadGclBaseTree {
         } else {
             node.contract_qty = this.ctx.helper.add(node.contract_qty, source.contract_qty);
             node.contract_tp = this.ctx.helper.mul(node.unit_price, node.contract_qty, this.ctx.tender.info.decimal.tp);
+
+            node.qc_qty = this.ctx.helper.add(node.qc_qty, source.qc_qty);
+            node.qc_tp = this.ctx.helper.mul(node.unit_price, node.qc_qty, this.ctx.tender.info.decimal.tp);
         }
         this._gatherChange(node, source);
         return node;
     }
     getUpdateData() {
-        const result = {update: [], errors: []};
+        const result = { update: [], errors: [], qc_detail: [] };
         for (const bn of this.baseNodes) {
-            if (bn.contract_qty !== bn.org_contract_qty || bn.contract_tp !== bn.org_contract_tp) {
-                result.update.push({lid: bn.id, contract_qty: bn.contract_qty, contract_tp: bn.contract_tp });
+            if (!bn.is_import && bn.org_qc_qty !== 0 && bn.qc_qty !== 0) {
+                result.errors.push({ b_code: bn.b_code, name: bn.name, unit: bn.unit, qc_qty: bn.qc_qty, type: 'qc-conflict'});
+                if (bn.contract_qty !== bn.org_contract_qty || bn.contract_tp !== bn.org_contract_tp) {
+                    result.update.push({ lid: bn.id, contract_qty: bn.contract_qty, contract_tp: bn.contract_tp, qc_qty: bn.org_qc_qty, qc_tp: bn.org_qc_tp });
+                }
+                continue;
+            }
+            if (bn.contract_qty !== bn.org_contract_qty || bn.contract_tp !== bn.org_contract_tp || bn.qc_qty !== bn.org_qc_qty) {
+                result.update.push({ lid: bn.id, contract_qty: bn.contract_qty, contract_tp: bn.contract_tp, qc_qty: bn.qc_qty, qc_tp: bn.qc_tp });
             }
             if (bn.change_detail && bn.change_detail.length > 0) {
                 for (const cd of bn.change_detail) {
-                    result.errors.push({
-                        ledger_id: bn.ledger_id,
-                        b_code: bn.b_code, name: bn.name, unit: bn.unit,
-                        c_code: cd.c_code, qty: cd.qty, type: 'qc',
+                    result.qc_detail.push({
+                        lid: bn.id, rela_tid: cd.tid, rela_sid: cd.sid, rela_lid: cd.lid, rela_cid: cd.cid, rela_cbid: cd.cbid, rela_qty: cd.qty
                     });
                 }
             }
         }
         for (const i of this.items) {
-            result.errors.push({ b_code: i.b_code, name: i.name, unit: i.unit, qty: i.contract_qty, type: 'miss' });
-            if (i.change_detail && i.change_detail.length > 0) {
-                for (const cd of i.change_detail) {
-                    result.errors.push({
-                        b_code: i.b_code, name: i.name, unit: i.unit,
-                        c_code: cd.c_code, qty: cd.qty, type: 'miss-qc',
-                    });
-                }
-            }
+            result.errors.push({ b_code: i.b_code, name: i.name, unit: i.unit, qty: i.contract_qty, qc_qty: i.qc_qty, type: 'miss' });
         }
         return result;
     }
@@ -493,6 +492,7 @@ class sumLoad {
             if (!b) continue;
             b.contract_qty = csb.contract_qty;
             b.contract_tp = csb.contract_tp;
+            b.qc_qty = csb.qc_qty;
         }
         for (const csc of curStageChange) {
             if (!csc.qty) continue;
@@ -500,9 +500,9 @@ class sumLoad {
             const b = billsIndex[csc.lid];
             if (!b) continue;
             if (!b.change_detail) b.change_detail = [];
-            let c = b.change_detail.find(x => { return x.cid === csc.cid });
+            let c = b.change_detail.find(x => { return x.cbid === csc.cbid });
             if (!c) {
-                c = { cid: csc.cid };
+                c = { tid: csc.tid, sid: csc.sid, cid: csc.cid, cbid: csc.cbid, lid: csc.lid, c_code: csc.c_code };
                 b.change_detail.push(c);
             }
             c.qty = this.ctx.helper.add(c.qty, csc.qty);
@@ -516,7 +516,9 @@ class sumLoad {
         });
         const posterity = await this.ctx.service.ledger.getPosterityByParentId(this.ctx.tender.id, select.ledger_id);
         const stageBills = await this.ctx.service.stageBills.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id);
+        const importLid = await this.ctx.service.stageImportChange.getLeafXmjImportLid(this.ctx.stage.id, select.id);
         this.ctx.helper.assignRelaData(posterity, [
+            { data: importLid, fields: [ 'is_import' ], prefix: '', relaId: 'lid' },
             { data: stageBills, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp' ], prefix: '', relaId: 'lid' },
         ]);
         const pos = await this.ctx.service.revisePos.getData(this.ctx.tender.id);

+ 38 - 0
app/middleware/auto_finish_logger.js

@@ -0,0 +1,38 @@
+'use strict';
+
+/**
+ * 自动记录日志
+ *
+ * @author CaiAoLin
+ * @date 2017/10/30
+ * @version
+ */
+
+module.exports = options => {
+    return async function autoFinishLogger(ctx, next) {
+        await next();
+
+        const bLogger = ctx.getLogger('finish');
+        const responseTime = new Date();
+        const runTime = responseTime.getTime() - responseTime.getTime();
+        if (ctx.session && ctx.session.sessionUser) {
+            const logData = {
+                requestTime: ctx.logTime,
+                responseTime, runTime,
+                method: ctx.method,
+                user: ctx.session.sessionUser,
+                project: ctx.session.sessionProject,
+                data: ctx.request.body,
+            };
+            bLogger.info(JSON.stringify(logData));
+        } else {
+            const logData = {
+                requestTime: ctx.logTime,
+                responseTime, runTime,
+                method: ctx.method,
+                data: ctx.body,
+            };
+            bLogger.info(JSON.stringify(logData));
+        }
+    };
+};

+ 1 - 0
app/middleware/auto_logger.js

@@ -36,6 +36,7 @@ module.exports = options => {
             };
             bLogger.info(JSON.stringify(logData));
         }
+        this.logTime = new Date();
 
         // 自动记录log的action
         // const autoLogAction = ['save', 'delete'];

+ 1 - 2
app/public/js/shares/cs_tools.js

@@ -965,8 +965,7 @@ const showSelectTab = function(select, spread, afterShow) {
                             switch (x.type) {
                                 case 'less': return '数量变少';
                                 case 'miss': return '找不到清单';
-                                case 'qc': return '变更';
-                                case 'miss-qc': return '变更(找不到清单)';
+                                case 'qc-conflict': return '变更冲突(已调用变更令)';
                                 default: return '';
                             }
                         }

+ 1 - 1
app/public/js/shares/tender_select.js

@@ -181,7 +181,7 @@ const TenderSelect = function (setting) {
                 if (tsObj.setting.type === 'stage') updateData.cover = $('#ts-cover')[0].checked;
                 if (updateData.tenders.length > 0) {
                     postData(window.location.pathname + '/sumLoad', updateData, result => {
-                        tsObj.setting.afterLoad(result);
+                        tsObj.setting.afterLoad(result, tsObj.select);
                         $('#tender-select').modal('hide');
                     });
                 } else {

+ 57 - 35
app/public/js/stage.js

@@ -657,7 +657,7 @@ $(document).ready(() => {
             case 'dagl': data.dagl_url && window.open(data.dagl_url); break;
             case 'gxby': data.gxby_url && window.open(data.gxby_url); break;
             case 'qc_qty':
-                if (data.children && data.children.length > 0 || data.lock) return;
+                if (data.children && data.children.length > 0 || data.lock || data.is_import) return;
                 const nodePos = stagePos.getLedgerPos(data.id);
                 if (nodePos && nodePos.length > 0) return;
                 changesObj.loadChanges({bills: data});
@@ -1455,7 +1455,7 @@ $(document).ready(() => {
     const addTag = newTag({ledgerSheet: slSpread.getActiveSheet(), billsTag});
     const tenderSelect = TenderSelect({
         type: 'stage',
-        afterLoad: function (result) {
+        afterLoad: function (result, select) {
             const nodes = stageTree.loadPostStageData(result);
             stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), nodes);
             if (detail) {
@@ -1469,6 +1469,8 @@ $(document).ready(() => {
             } else {
                 sumLoadMiss.clearMissData();
             }
+            // todo 优化,仅加载需要刷新的变更令
+            if (checkedChanges) checkedChanges.reloadChangeData();
         }
     });
     $.contextMenu({
@@ -3500,17 +3502,6 @@ $(document).ready(() => {
                     $('#view-calc-remark').text(img_remark);
 
                     $('#edit-img').modal('hide');
-                    // updateImageData = updateData;
-                    // $('#edit-img').modal('hide');
-                    // postData(window.location.pathname + '/detail/merge-img', updateData, function (result) {
-                    //     stageIm.loadUpdateDetailData(result);
-                    //     data.calc_img = result.calc_img;
-                    //     data.calc_img_org = result.calc_img_org;
-                    //     const calcImgSrc = data && data.calc_img ? '/' + data.calc_img : '';
-                    //     $('#show-calc-img').attr('src', calcImgSrc);
-                    //     $('#calc-img').attr('src', calcImgSrc);
-                    //     $('#view-calc-img').attr('src', calcImgSrc);
-                    //     $('#edit-img').modal('hide');
                     // });
                 } else if (data.calc_img) {
                     self.updateImageData = {updateType: 'clear', lid: data.lid, pid: data.pid, uuid: data.uuid, calc_img_remark: img_remark};
@@ -3522,16 +3513,6 @@ $(document).ready(() => {
                     $('#view-calc-remark').val(img_remark);
                     $('#text-edit').val(img_remark);
                     $('#edit-img').modal('hide');
-                    // postData(window.location.pathname + '/detail/merge-img', {updateType: 'clear', lid: data.lid, pid: data.pid, uuid: data.uuid}, function (result) {
-                    //     stageIm.loadUpdateDetailData(result);
-                    //     data.calc_img = result.calc_img;
-                    //     data.calc_img_org = result.calc_img_org;
-                    //     const calcImgSrc = data && data.calc_img ? '/' + data.calc_img : '';
-                    //     $('#show-calc-img').attr('src', calcImgSrc);
-                    //     $('#calc-img').attr('src', calcImgSrc);
-                    //     $('#view-calc-img').attr('src', calcImgSrc);
-                    //     $('#edit-img').modal('hide');
-                    // });
                 } else {
                     self.updateImageData = updateData;
                     $('#show-calc-img').attr('src', '');
@@ -3660,7 +3641,7 @@ $(document).ready(() => {
             const self = this;
             this.changeSpreadSetting = {
                 cols: [
-                    {title: '变更令号', colSpan: '1', rowSpan: '1', field: 'p_code', hAlign: 0, width: 100, formatter: '@'},
+                    {title: '变更令号', colSpan: '1', rowSpan: '1', field: 'p_code', hAlign: 0, width: 100, formatter: '@', cellType: 'tip', getTip: function (x) { return x.t_name ? `所属标段:${x.t_name}` : ''; }},
                     {title: '变更名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 180, formatter: '@'},
                     {title: '金额', colSpan: '1', rowSpan: '1', field: 'total_price', hAlign: 2, width: 80, type: 'Number'},
                     {title: '批复文号', colSpan: '1', rowSpan: '1', field: 'w_code', hAlign: 0, width: 100, formatter: '@'},
@@ -3673,6 +3654,13 @@ $(document).ready(() => {
                 headerFont: '12px 微软雅黑',
                 font: '12px 微软雅黑',
                 readOnly: true,
+                getColor: function (sheet, data, row, col, defaultColor) {
+                    if (data && data.is_import) {
+                        return '#eee';
+                    } else {
+                        return defaultColor;
+                    }
+                }
             };
             this.changeSpread = SpreadJsObj.createNewSpread(setting.changeObj[0]);
             this.changeSheet = this.changeSpread.getActiveSheet();
@@ -3718,7 +3706,7 @@ $(document).ready(() => {
                 if (change.detail) {
                     self.loadChangeDetailData();
                 } else {
-                    postData(window.location.pathname + '/change/detail', {cid: change.cid}, function (result) {
+                    postData(window.location.pathname + '/change/detail', {cid: change.cid, is_import: change.is_import}, function (result) {
                         change.detail = result;
                         self.analyzeChange(change);
                         self.loadChangeDetailData();
@@ -3741,8 +3729,14 @@ $(document).ready(() => {
                         name: '定位至台账',
                         icon: 'fa-sign-in',
                         callback: function (key, opt) {
+                            const change = SpreadJsObj.getSelectObject(self.changeSheet);
                             const changeBills = SpreadJsObj.getSelectObject(self.changeBillsSheet);
-                            if (changeBills.gcl_id) {
+                            if (change.is_import) {
+                                if (changeBills.pos && changeBills.pos.length > 0) {
+                                    SpreadJsObj.locateTreeNode(slSpread.getActiveSheet(), changeBills.pos[0].ledger_id, true);
+                                    stagePosSpreadObj.loadCurPosData();
+                                }
+                            } else if (changeBills.gcl_id) {
                                 const node = stageTree.nodes.find(x => {return x.id === changeBills.gcl_id});
                                 SpreadJsObj.locateTreeNode(slSpread.getActiveSheet(), node.ledger_id, true);
                                 stagePosSpreadObj.loadCurPosData();
@@ -3793,23 +3787,23 @@ $(document).ready(() => {
         reloadChangeData() {
             const self = this;
             postData(window.location.pathname + '/change/data', null, function (result) {
-                self.changes = result.changes;
+                self.changes = [];
+                result.changes.forEach(x => { x.is_import = 0; self.changes.push(x); });
+                result.import_changes.forEach(x => { x.is_import = 1; self.changes.push(x); });
+                if (result.changes.length > 0) self.analyzeChange(result.changes[0]);
+                if (result.import_changes.length > 0) self.analyzeChange(result.import_changes[0]);
                 SpreadJsObj.loadSheetData(self.changeSheet, SpreadJsObj.DataType.Data, self.changes);
                 self.changeSheet.setSelection(0, 0, 1, 1);
-                if (self.changes.length > 0) self.analyzeChange(result.changes[0]);
                 self.curChangeId = self.changes.length > 0 ? self.changes[0].id : null;
                 self.loadChangeDetailData();
             });
         }
-        analyzeChange(change) {
-            change.bills = change.detail.bills;
+        _analyzeCommon(change) {
             for (const b of change.bills) {
-                const aub = change.detail.addUsedBills.find(function (x) {
-                    return x.id === b.id;
+                const eub = change.detail.endUsedBills.find(function (x) {
+                    return x.cbid === b.id;
                 });
-                if (aub) {
-                    b.used_qty = aub.used_qty;
-                }
+                if (eub) b.used_qty = eub.qty;
                 b.qty = _.toNumber(b.samount);
                 b.valid_qty = ZhCalc.sub(b.qty, b.used_qty);
                 b.tp = ZhCalc.round(ZhCalc.mul(b.qty, b.unit_price), tenderInfo.decimal.tp);
@@ -3821,6 +3815,34 @@ $(document).ready(() => {
                 }
             }
         }
+        _analyzeImport(change) {
+            for (const b of change.bills) {
+                const eub = change.detail.endUsedBills.find(function (x) {
+                    return x.rela_cbid === b.id;
+                });
+                if (eub) b.used_qty = eub.rela_qty;
+                b.qty = _.toNumber(b.samount);
+                b.valid_qty = ZhCalc.sub(b.qty, b.used_qty);
+                b.tp = ZhCalc.round(ZhCalc.mul(b.qty, b.unit_price), tenderInfo.decimal.tp);
+                b.pos = _.filter(change.detail.curUsedBills, { rela_cbid: b.id });
+                b.cur_qty = 0;
+                for (const p of b.pos) {
+                    b.qty = b.rela_qty;
+                    const node = stageTree.datas.find(x => { return x.id === p.lid; });
+                    p.ledger_id = node.ledger_id;
+                    p.f_qty = node.quantity;
+                    b.cur_qty = ZhCalc.add(b.cur_qty, p.rela_qty);
+                }
+            }
+        }
+        analyzeChange(change) {
+            change.bills = change.detail.bills;
+            if (change.is_import) {
+                this._analyzeImport(change);
+            } else {
+                this._analyzeCommon(change);
+            }
+        }
     }
     // 展开收起附件
     $('a', '.right-nav').bind('click', function () {

+ 53 - 16
app/public/js/stage_change.js

@@ -30,21 +30,16 @@ class ChangeAnalysis {
         }
         return null;
     }
-    analyze (change) {
-        change.filterBills = false;
-        change.attachments = change.detail.attachments;
-        change.bills = change.detail.bills;
+    _analyzeCommon(change) {
         for (const b of change.bills) {
-            const aub = change.detail.addUsedBills.filter(function (x) {
+            const eub = change.detail.endUsedBills.filter(function (x) {
                 return x.cbid === b.id;
             });
-            if (aub) {
-                b.used_qty = ZhCalc.sum(aub.map(x => { return x.qty}));
-            }
+            if (eub) b.used_qty = ZhCalc.sum(eub.map(x => { return x.qty }));
             b.qty = _.toNumber(b.samount);
             b.valid_qty = ZhCalc.sub(b.qty, b.used_qty);
             b.tp = ZhCalc.round(ZhCalc.mul(b.qty, b.unit_price), tenderInfo.decimal.tp);
-            b.pos = _.filter(change.detail.curUsedBills, {cbid: b.id});
+            b.pos = _.filter(change.detail.curUsedBills, { cbid: b.id });
             b.cur_qty = 0;
             for (const p of b.pos) {
                 // 查询最底层项目节
@@ -57,7 +52,41 @@ class ChangeAnalysis {
                 p.f_qty = p.p_qty ? p.p_qty : p.l_qty;
                 b.cur_qty = ZhCalc.add(b.cur_qty, p.qty);
             }
-
+        }
+    }
+    _analyzeImport(change) {
+        for (const b of change.bills) {
+            const eub = change.detail.endUsedBills.filter(function (x) {
+                return x.rela_cbid === b.id;
+            });
+            if (eub) b.used_qty = ZhCalc.sum(eub.map(x => { return x.rela_qty }));
+            b.qty = _.toNumber(b.samount);
+            b.valid_qty = ZhCalc.sub(b.qty, b.used_qty);
+            b.tp = ZhCalc.round(ZhCalc.mul(b.qty, b.unit_price), tenderInfo.decimal.tp);
+            b.pos = _.filter(change.detail.curUsedBills, { rela_cbid: b.id });
+            b.cur_qty = 0;
+            for (const p of b.pos) {
+                p.qty = p.rela_qty;
+                // 查询最底层项目节
+                const node = this.ledgerTree.datas.find(x => { return x.id === p.lid; });
+                const leafXmj = this.getLeafXmj(node);
+                if (leafXmj) {
+                    p.leaf_xmj_code = leafXmj.code;
+                    p.leaf_xmj_name = leafXmj.name;
+                }
+                p.f_qty = node.quantity;
+                b.cur_qty = ZhCalc.add(b.cur_qty, p.qty);
+            }
+        }
+    }
+    analyze (change) {
+        change.filterBills = false;
+        change.attachments = change.detail.attachments;
+        change.bills = change.detail.bills;
+        if (change.is_import) {
+            this._analyzeImport(change);
+        } else {
+            this._analyzeCommon(change);
         }
     }
 }
@@ -70,7 +99,7 @@ $(document).ready(() => {
     // 初始化变更令spread
     const changeSpreadSetting = {
         cols: [
-            {title: '变更令号', colSpan: '1', rowSpan: '1', field: 'p_code', hAlign: 0, width: 150, formatter: '@'},
+            {title: '变更令号', colSpan: '1', rowSpan: '1', field: 'p_code', hAlign: 0, width: 150, formatter: '@', cellType: 'tip', getTip: function (x) { return x.t_name ? `所属标段:${x.t_name}` : ''; }},
             {title: '变更名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 350, formatter: '@'},
             {title: '金额', colSpan: '1', rowSpan: '1', field: 'total_price', hAlign: 2, width: 100, type: 'Number'},
             {title: '批复文号', colSpan: '1', rowSpan: '1', field: 'w_code', hAlign: 0, width: 150, formatter: '@'},
@@ -92,6 +121,13 @@ $(document).ready(() => {
             colWidth: true,
         },
         readOnly: true,
+        getColor: function (sheet, data, row, col, defaultColor) {
+            if (data && data.is_import) {
+                return '#eee';
+            } else {
+                return defaultColor;
+            }
+        }
     };
     const changeSpread = SpreadJsObj.createNewSpread($('#bgl-spread')[0]);
     SpreadJsObj.initSheet(changeSpread.getActiveSheet(), changeSpreadSetting);
@@ -316,14 +352,15 @@ $(document).ready(() => {
 
     postData(window.location.pathname + '/data', null, function (result) {
         tenderInfo = result.tenderInfo;
-        changes = result.changes;
-        usedChangesId = result.usedChangesId;
+        changes = [];
+        result.changes.forEach(x => { x.is_import = 0; changes.push(x); });
+        result.import_changes.forEach(x => { x.is_import = 1; changes.push(x); });
+        usedChangesId = [...result.usedChangesId, ...result.used_import_cid];
         ledger = result.ledger;
         // ------------begin 预处理数据
         analysis = new ChangeAnalysis(ledger);
-        if (changes.length > 0) {
-            analysis.analyze(changes[0]);
-        }
+        if (result.changes.length > 0) analysis.analyze(result.changes[0]);
+        if (result.import_changes.length > 0) analysis.analyze(result.import_changes[0]);
         // ------------end 预处理数据
         // ------------begin 加载数据至界面
         SpreadJsObj.loadSheetData(changeSpread.getActiveSheet(), SpreadJsObj.DataType.Data, changes);

+ 1 - 0
app/router.js

@@ -313,6 +313,7 @@ module.exports = app => {
     // 变更概况
     app.get('/tender/:id/measure/stage/:order/change', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.change');
     app.post('/tender/:id/measure/stage/:order/change/data', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.getChangeData');
+    app.post('/tender/:id/measure/stage/:order/change/iData', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.getImportChangeData');
     app.post('/tender/:id/measure/stage/:order/change/detail', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.changeDetail');
 
     // 审批

+ 7 - 2
app/service/stage_bills.js

@@ -460,8 +460,6 @@ module.exports = app => {
                 for (const u of result.update) {
                     const sb = stageBills.find(x => { return x.lid === u.lid; });
                     if (!sb || sb.times !== this.ctx.stage.curTimes || sb.order !== this.ctx.stage.curOrder) {
-                        u.qc_qty = sb ? sb.qc_qty : null;
-                        u.qc_tp = sb ? sb.qc_tp : null;
                         u.postil = sb ? sb.postil : null;
                         u.tid = this.ctx.tender.id;
                         u.sid = this.ctx.stage.id;
@@ -474,10 +472,17 @@ module.exports = app => {
                         updateStageBills.push(u);
                     }
                 }
+                for (const cd of result.qc_detail) {
+                    cd.tid = this.ctx.tender.id;
+                    cd.sid = this.ctx.stage.id;
+                    cd.import_lid = lid;
+                }
 
                 const his = await this.ctx.service.sumLoadHistory.saveStageHistory(this.ctx.tender.id, this.ctx.stage.id, lid, tenders, result.errors, cover);
                 if (updateStageBills.length > 0) await conn.updateRows(this.tableName, updateStageBills);
                 if (insertStageBills.length > 0) await conn.insert(this.tableName, insertStageBills);
+                await conn.delete(this.ctx.service.stageImportChange.tableName, { import_lid: lid, sid: this.ctx.stage.id });
+                if (result.qc_detail.length > 0) await conn.insert(this.ctx.service.stageImportChange.tableName, result.qc_detail);
                 await conn.commit();
                 return { curStageData: result.update, sumLoadHis: his };
             } catch (err) {

+ 2 - 2
app/service/stage_change_final.js

@@ -84,11 +84,11 @@ module.exports = app => {
         }
 
         async getSumLoadFinalData(sid) {
-            const sql = 'Select cf.lid, cf.cid, sum(cf.qty) as qty, c.code As c_code' +
+            const sql = 'Select cf.tid, cf.sid, cf.lid, cf.cid, cf.cbid, sum(cf.qty) as qty, c.code As c_code' +
                 '  FROM ' + this.tableName + ' cf' +
                 '  Left Join ' + this.ctx.service.change.tableName + ' c ON cf.cid = c.cid' +
                 '  Where cf.sid = ?' +
-                '  Group By cf.lid, cf.cid';
+                '  Group By cf.lid, cf.cbid';
             return await this.db.query(sql, [sid]);
         }
     }

+ 159 - 0
app/service/stage_import_change.js

@@ -0,0 +1,159 @@
+'use strict';
+
+/**
+ * 期 - 引入 变更数据
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+module.exports = app => {
+
+    class StageImportChange extends app.BaseService {
+
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'stage_import_change';
+        }
+
+        async getImportLid(sid) {
+            const sql = 'Select lid, 1 as is_import From ' + this.tableName + ' Where sid = ? Group By lid';
+            return await this.db.query(sql, [sid]);
+        }
+
+        /**
+         * 获取最底层项目节(importLid)下导入过变更数据的台账id
+         * @param sid
+         * @param importLid
+         * @returns {Promise<void>}
+         */
+        async getLeafXmjImportLid(sid, importLid) {
+            const sql = 'Select lid, 1 as is_import From ' + this.tableName + ' Where sid = ? and import_lid = ? Group By lid';
+            return await this.db.query(sql, [sid, importLid]);
+        }
+
+        async getImportChange(sid) {
+            const sql =
+                `SELECT c.*, t.name as t_name FROM ${this.ctx.service.change.tableName} c` +
+                `  LEFT JOIN ${this.ctx.service.tender.tableName} t ON c.tid = t.id` +
+                `  WHERE c.cid IN ( SELECT rela_cid FROM ${this.tableName} WHERE sid = ? GROUP BY rela_cid)` +
+                '  Order By c.tid, c.sin_time';
+            return await this.db.query(sql, [sid]);
+        }
+
+        async getEndStageImportChange(stage) {
+            const sql = 'SELECT scf.* ' +
+                '  FROM ' + this.tableName + ' scf ' +
+                '  LEFT JOIN ' + this.ctx.service.stage.tableName + ' s ON scf.sid = s.id' +
+                '  WHERE scf.tid = ? And s.order <= ?';
+            const result = await this.db.query(sql, [stage.tid, stage.order]);
+            return result;
+        }
+
+        async getLeafXmjImportChange(sid, importLid) {
+            const sql =
+                `SELECT c.*, t.name as t_name FROM ${this.ctx.service.change.tableName} c` +
+                `  LEFT JOIN ${this.ctx.service.tender.tableName} t ON c.tid = t.id` +
+                `  WHERE c.cid IN ( SELECT rela_cid FROM ${this.tableName} WHERE sid = ? and import_lid = ? GROUP BY rela_cid)` +
+                '  Order By c.tid, c.sin_time';
+            return await this.db.query(sql, [sid, importLid]);
+        }
+
+        async getChangeWithUsedInfo(stage, importLid) {
+            const change = importLid
+                ? await this.getLeafXmjImportChange(stage.id, importLid)
+                : await this.getImportChange(stage.id);
+            if (change.length === 0) return [];
+
+            const changeBills = await this.ctx.service.changeAuditList.getAllDataByCondition({
+                where: { cid: change.map(x => { return x.cid; }) }
+            });
+            const changeBillsIndex = {}, changeBillsPart = {};
+            for (const cb of changeBills) {
+                changeBillsIndex[cb.id] = cb;
+                if (!changeBillsPart[cb.cid]) changeBillsPart[cb.cid] = [];
+                changeBillsPart[cb.cid].push(cb);
+            }
+            const stageChangeBills = await this.getEndStageImportChange(stage);
+            for (const scb of stageChangeBills) {
+                if (!scb.rela_qty) continue;
+
+                const cb = changeBillsIndex[scb.rela_cbid];
+                if (cb) cb.used_qty = this.ctx.helper.add(cb.used_qty, scb.rela_qty);
+            }
+            for (const cid in changeBillsPart) {
+                const c = change.find(x => { return x.cid === cid });
+                if (!c) continue;
+
+                for (const cb of changeBillsPart[cid]) {
+                    cb.tp = this.ctx.helper.mul(cb.spamount, cb.unit_price, c.tp_decimal || this.ctx.tender.info.decimal.tp);
+                    cb.used_tp = this.ctx.helper.mul(cb.used_qty, cb.unit_price, this.ctx.tender.info.decimal.tp);
+
+                    c.used_tp = this.ctx.helper.add(c.used_tp, cb.used_tp);
+                    if (cb.spamount > 0) {
+                        c.p_tp = this.ctx.helper.add(c.p_tp, cb.tp);
+                        c.p_used_tp = this.ctx.helper.add(c.p_used_tp, cb.used_tp);
+                    } else if (cb.spamount < 0){
+                        c.n_tp = this.ctx.helper.add(c.n_tp, cb.tp);
+                        c.n_used_tp = this.ctx.helper.add(c.n_used_tp, cb.used_tp);
+                    }
+                }
+                c.used_pt = c.total_price ? this.ctx.helper.mul(this.ctx.helper.div(c.used_tp, c.total_price, 4), 100) : 0;
+                c.p_used_pt = c.p_tp ? this.ctx.helper.mul(this.ctx.helper.div(c.p_used_tp, c.p_tp, 4), 100) : 0;
+                c.n_used_pt = c.n_tp ? this.ctx.helper.mul(this.ctx.helper.div(c.n_used_tp, c.n_tp, 4), 100) : 0;
+            }
+            return change;
+        }
+
+        /**
+         * 获取 变更令 - 变更清单 使用情况
+         * @param {Number} sid - 查询期id
+         * @param {uuid} cid - 变更令id
+         * @return {Promise<void>}
+         */
+        async getChangeUsedData(sid, cid) {
+            return await this.getAllDataByCondition({ where: { sid, rela_cid: cid } });
+        }
+
+        /**
+         * 获取 变更令 - 变更清单 使用情况
+         * @param {Number} sid - 查询期id
+         * @param {uuid} cid - 变更令id
+         * @return {Promise<void>}
+         */
+        async getChangeEndUsedData(tid, cid) {
+            const sql = 'SELECT scf.* ' +
+                '  FROM ' + this.tableName + ' scf ' +
+                '  LEFT JOIN ' + this.ctx.service.stage.tableName + ' s ON scf.sid = s.id' +
+                '  WHERE scf.tid = ? And scf.rela_cid = ? And s.order <= ?';
+            const result = await this.db.query(sql, [tid, cid, this.ctx.stage.order]);
+            return result;
+        }
+
+        async getChangeFinalUsedData(tid, cid) {
+            const stage = this.ctx.service.stage.getLastestStage(tid, true);
+            const sql = 'SELECT scf.* ' +
+                '  FROM ' + this.tableName + ' scf ' +
+                '  LEFT JOIN ' + this.ctx.service.stage.tableName + ' s ON scf.sid = s.id' +
+                '  WHERE scf.tid = ? And scf.rela_cid = ? And s.order <= ?';
+            const result = await this.db.query(sql, [tid, cid, stage.order]);
+            return result;
+        }
+
+        async getStageUsedChangeId(sid) {
+            const sql = 'SELECT rela_cid FROM ' + this.tableName + ' WHERE sid = ? Group By rela_cid';
+            const cur = await this.db.query(sql, [sid]);
+            return this._.map(cur, 'rela_cid');
+        }
+    }
+
+    return StageImportChange;
+
+};

+ 4 - 1
config/config.default.js

@@ -65,7 +65,7 @@ module.exports = appInfo => {
     config.pageSize = 15;
 
     // 中间件
-    config.middleware = ['gzip', 'urlParse', 'sortFilter', 'autoLogger'];
+    config.middleware = ['gzip', 'urlParse', 'sortFilter', 'autoLogger', 'autoFinishLogger'];
 
     // session配置
     config.session = {
@@ -164,6 +164,9 @@ module.exports = appInfo => {
         },
         mixed: {
             file: path.join(appInfo.root, 'logs', appInfo.name, config.version, 'mixed.log'),
+        },
+        finish: {
+            file: path.join(appInfo.root, 'logs', appInfo.name, config.version, 'finish.log'),
         }
     };