فهرست منبع

1. 台账修订,台账对比,加载计量数据
2. 按比例计量,记录公式问题

MaiXinRong 4 سال پیش
والد
کامیت
dbc280080d

+ 79 - 1
app/controller/revise_controller.js

@@ -890,16 +890,84 @@ module.exports = app => {
             }
         }
 
+        async _getLastStage(ctx) {
+            const stages = await ctx.service.stage.getAllDataByCondition({
+                where: {tid: ctx.tender.id},
+                orders: [['order', 'desc']],
+            });
+            if (stages.length > 0) {
+                if (stages[0].status !== audit.stage.status.uncheck || stages[0].user_id === ctx.session.sessionUser.accountId) {
+                    return stages[0]
+                } else if (stages.length > 1) {
+                    return stages[1];
+                }
+            }
+            return null;
+        }
+
         async compare(ctx) {
             const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
             if (!revise) throw '台账修订数据有误';
 
+            const lastStage = await this._getLastStage(ctx);
+
             const renderData = {
                 revise,
                 measureType,
+                lastStage,
+                audit,
                 jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.revise.compare),
             };
-            await this.layout('revise/compare.ejs', renderData);
+            await this.layout('revise/compare.ejs', renderData, 'revise/compare_modal.ejs');
+        }
+
+        _loadPreData(curData, preData, field, prefix, relaId) {
+            if (preData.length === 0) return;
+            for (const pd of preData) {
+                const cd = curData.find(x => {return x[relaId] === pd[relaId]});
+                if (cd) {
+                    for (const f of field) {
+                        cd[prefix + f] = pd[f];
+                    }
+                } else {
+                    const ncd = {id: pd.id};
+                    ncd[relaId] = cd[relaId];
+                    for (const f of fields) {
+                        ncd[prefix + f] = pd[f];
+                    }
+                    curData.push(ncd);
+                }
+            }
+        }
+
+        async _loadLastStageBillsData(ctx) {
+            let curStageData;
+            if (ctx.lastStage.readOnly) {
+                curStageData = await ctx.service.stageBills.getAuditorStageData(ctx.tender.id,
+                    ctx.lastStage.id, ctx.lastStage.curTimes, ctx.lastStage.curOrder);
+            } else {
+                curStageData = await ctx.service.stageBills.getLastestStageData(ctx.tender.id, ctx.lastStage.id);
+            }
+            const preStageData = ctx.lastStage.order > 1
+                ? await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, ctx.lastStage.order - 1)
+                : [];
+            this._loadPreData(curStageData, preStageData, ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], 'pre_', 'lid');
+            return curStageData;
+        }
+
+        async _loadLastStagePosData(ctx) {
+            let curStageData;
+            if (ctx.lastStage.readOnly) {
+                curStageData = await ctx.service.stagePos.getAuditorStageData2(ctx.tender.id,
+                    ctx.lastStage.id, ctx.lastStage.curTimes, ctx.lastStage.curOrder);
+            } else {
+                curStageData = await ctx.service.stagePos.getLastestStageData2(ctx.tender.id, ctx.lastStage.id);
+            }
+            const preStageData = ctx.lastStage.order > 1
+                ? await ctx.service.stagePosFinal.getFinalData(ctx.tender.data, ctx.lastStage.order - 1)
+                : [];
+            this._loadPreData(curStageData, preStageData, ['contract_qty', 'qc_qty'], 'pre_', 'lid');
+            return curStageData;
         }
 
         async _loadDataByFilter(ctx, filter) {
@@ -908,6 +976,15 @@ module.exports = app => {
                 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 'stageBills':
+                case 'stagePos':
+                    if (!ctx.lastStage) ctx.lastStage = await this._getLastStage(ctx);
+                    await this.ctx.service.stage.doCheckStage(ctx.lastStage);
+                    if (filter === 'stageBills') {
+                        return await this._loadLastStageBillsData(ctx);
+                    } else {
+                        return await this._loadLastStagePosData(ctx);
+                    }
             }
         }
 
@@ -920,6 +997,7 @@ module.exports = app => {
                 const filter = data.filter ? data.filter.split(';') : [];
 
                 const responseData = { err: 0, msg: '', data: {} };
+                console.log(filter);
                 for (const f of filter) {
                     if (!f) continue;
                     responseData.data[f] = await this._loadDataByFilter(ctx, f);

+ 69 - 6
app/public/js/revise_compare.js

@@ -16,9 +16,6 @@ const billsCompareField = [
 const posCompareField = [
     'name', 'position', 'sgfh_qty', 'sjcl_qty', 'qtcl_qty', 'quantity'
 ];
-const compareColor = {
-    add: '#D9EDF7'
-}
 
 $(document).ready(() => {
     let searchLedger;
@@ -27,7 +24,10 @@ $(document).ready(() => {
     const billsSpread = SpreadJsObj.createNewSpread($('#bills-spread')[0]);
     const billsSheet = billsSpread.getActiveSheet();
     sjsSettingObj.setFxTreeStyle(billsSpreadSetting, sjsSettingObj.FxTreeStyle.jz);
-    if (thousandth) sjsSettingObj.setTpThousandthFormat(billsSpreadSetting);
+    if (thousandth) {
+        sjsSettingObj.setTpThousandthFormat(billsSpreadSetting);
+        sjsSettingObj.setTpColsThousandthFormat(billsSpreadSetting.extraCols);
+    }
     billsSpreadSetting.getColor = function (sheet, data, row, col, defaultColor) {
         // 增
         if (data.differ.indexOf('add') >= 0) return '#cce5ff';
@@ -52,7 +52,11 @@ $(document).ready(() => {
     const posSpread = SpreadJsObj.createNewSpread($('#pos-spread')[0]);
     const posSheet = posSpread.getActiveSheet();
     sjsSettingObj.setGridSelectStyle(posSpreadSetting);
-    if (thousandth) sjsSettingObj.setTpThousandthFormat(posSpreadSetting);
+    if (thousandth) {
+        sjsSettingObj.setTpThousandthFormat(posSpreadSetting);
+        sjsSettingObj.setTpColsThousandthFormat(posSpreadSetting.extraCols);
+    }
+
     posSpreadSetting.getColor = function (sheet, data, row, col, defaultColor) {
         // 增
         if (data.differ.indexOf('add') >= 0) return '#cce5ff';
@@ -75,7 +79,11 @@ $(document).ready(() => {
         full_path: 'full_path',
         rootId: -1,
         keys: ['id', 'tender_id', 'ledger_id'],
-        calcFields: ['sgfh_tp', 'sjcl_tp', 'qtcl_tp', 'total_price'],
+        calcFields: [
+            'org_sgfh_tp', 'org_sjcl_tp', 'org_qtcl_tp', 'org_total_price', 'org_deal_tp',
+            'new_sgfh_tp', 'new_sjcl_tp', 'new_qtcl_tp', 'new_total_price', 'new_deal_tp',
+            'contract_tp', 'qc_tp', 'end_contract_tp', 'end_qc_tp'
+        ],
         findNode: function (tree, node, parent) {
             const sameId = tree.datas.find(x => {return x.id === node.id});
             if (sameId) {
@@ -199,6 +207,18 @@ $(document).ready(() => {
         treeSetting.calcFields.push('deal_tp');
     }
     treeSetting.calcFun = function (node) {
+        if (!node.children || node.children.length === 0) {
+            // node.gather_qty = ZhCalc.add(node.contract_qty, node.qc_qty);
+            // node.pre_gather_qty = ZhCalc.add(node.pre_contract_qty, node.pre_qc_qty);
+            node.end_contract_qty = ZhCalc.add(node.contract_qty, node.pre_contract_qty);
+            node.end_qc_qty = ZhCalc.add(node.qc_qty, node.pre_qc_qty);
+            // node.end_gather_qty = ZhCalc.add(node.end_contract_qty, node.end_qc_qty);
+        }
+        // node.gather_tp = ZhCalc.add(node.contract_tp, node.qc_tp);
+        // node.pre_gather_tp = ZhCalc.add(node.pre_contract_tp, node.pre_qc_tp);
+        node.end_contract_tp = ZhCalc.add(node.contract_tp, node.pre_contract_tp);
+        node.end_qc_tp = ZhCalc.add(node.qc_tp, node.pre_qc_tp);
+        // node.end_gather_tp = ZhCalc.add(node.end_contract_tp, node.end_qc_tp);
         node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
     };
     const billsTree = createNewPathTree('compare', treeSetting);
@@ -256,6 +276,7 @@ $(document).ready(() => {
         orgLedger.pos.loadDatas(result.pos);
 
         billsTree.loadCompareData(reviseLedger, orgLedger);
+        treeCalc.calculateAll(billsTree);
         SpreadJsObj.loadSheetData(billsSheet, SpreadJsObj.DataType.Tree, billsTree);
 
         posSpreadObj.loadCurPosData();
@@ -394,5 +415,47 @@ $(document).ready(() => {
             }
         });
     })('a[name=showLevel]', billsSheet);
+
+    // 加载计量数据
+    $('#load-stage-ok').click(function (x) {
+        postData('/tender/' + window.location.pathname.split('/')[2] + '/revise/load', {filter: 'stageBills;stagePos'}, function (result) {
+            const col = billsSpreadSetting.cols.length;
+            billsSpreadSetting.cols = billsSpreadSetting.cols.concat(billsSpreadSetting.extraCols);
+            SpreadJsObj.reinitSheetHeader(billsSheet);
+            for (const b of result.stageBills) {
+                const node = billsTree.nodes.find(x => {return x.id === b.lid});
+                if (!node) continue;
+
+                for (const f of ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp']) {
+                    node[f] = b[f];
+                }
+            }
+            treeCalc.calculateAll(billsTree);
+            SpreadJsObj.reloadColData(billsSheet, col, billsSpreadSetting.extraCols.length);
+
+            posSpreadSetting.cols = posSpreadSetting.cols.concat(posSpreadSetting.extraCols);
+            SpreadJsObj.reinitSheetHeader(posSheet);
+            // todo 加载并计算计量单元期数据
+            for (const p of result.stagePos) {
+                const node = billsTree.nodes.find(x => {return x.id === p.lid});
+                if (!node) continue;
+                const pos = node.pos.find(x => {return x.id === p.pid});
+                if (!pos) continue;
+
+                pos.contract_qty = p.contract_qty;
+                pos.qc_qty = p.qc_qty;
+                //pos.gather_qty = ZhCalc.add(pos.contract_qty, pos.qc_qty);
+                pos.pre_contract_qty = p.pre_contract_qty;
+                pos.pre_qc_qty = p.pre_qc_qty;
+                //pos.pre_gather_qty = ZhCalc.add(pos.pre_contract_qty, pos.pre_qc_qty);
+                pos.end_contract_qty = ZhCalc.add(pos.contract_qty, pos.pre_contract_qty);
+                pos.end_qc_qty = ZhCalc.add(pos.qc_qty, pos.pre_qc_qty);
+                //pos.end_gather_qty = ZhCalc.add(pos.gather_qty, pos.pre_gather_qty);
+            }
+            posSpreadObj.loadCurPosData();
+            //$('[data-target=#load-stage]').hide();
+            $('#load-stage').modal('hide');
+        });
+    });
 });
 

+ 7 - 1
app/public/js/shares/sjs_setting.js

@@ -52,6 +52,12 @@ const sjsSettingObj = (function () {
             if (col) col.formatter = '#,##0.######';
         }
     };
+    const setTpColsThousandthFormat = function (cols, fields = []) {
+        for (const col of cols) {
+            if (col.field === 'total_price' || col.field.indexOf('tp') >= 0 || fields.indexOf(col.field) >= 0)
+                col.formatter = '#,##0.######';
+        }
+    };
 
     const setPropValue = function (setting, fields, prop, value) {
         for (const f of fields) {
@@ -61,5 +67,5 @@ const sjsSettingObj = (function () {
             if (col) col[prop] = value;
         }
     };
-    return {setFxTreeStyle, FxTreeStyle, setGridSelectStyle, setTpThousandthFormat, setThousandthFormat, setPropValue};
+    return {setFxTreeStyle, FxTreeStyle, setGridSelectStyle, setTpThousandthFormat, setThousandthFormat, setTpColsThousandthFormat, setPropValue};
 })();

+ 60 - 20
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -403,6 +403,55 @@ const SpreadJsObj = {
             this.endMassOperation(sheet);
         }
     },
+    _loadCellData: function (sheet, data, iRow, iCol) {
+        if (!data || !sheet.zh_setting) return;
+
+        const col = sheet.zh_setting.cols[iCol];
+        const cell = sheet.getCell(iRow, iCol);
+
+        if (col.getValue && Object.prototype.toString.apply(col.getValue) === "[object Function]") {
+            cell.value(col.getValue(data));
+        } else if (col.field !== '' && data[col.field]) {
+            cell.value(data[col.field]);
+        }
+
+        let font = sheet.getDefaultStyle().font;
+        if (col.font) {
+            font = col.font;
+        }
+        if (sheet.zh_setting.tree.getFont && Object.prototype.toString.apply(sheet.zh_setting.tree.getFont) === "[object Function]") {
+            font = sheet.zh_setting.tree.getFont(sheet, data, iRow, col, font);
+        }
+        cell.font(font);
+
+        if (col.foreColor) {
+            if (Object.prototype.toString.apply(col.foreColor) === "[object Function]") {
+                cell.foreColor(col.foreColor(data, sheet.getDefaultStyle().foreColor));
+            } else {
+                cell.foreColor(col.foreColor);
+            }
+        }
+
+        if (col.readOnly && Object.prototype.toString.apply(col.readOnly) === "[object Function]") {
+            cell.locked(col.readOnly(data) || sheet.zh_setting.readOnly || false).vAlign(1).hAlign(col.hAlign);
+        } else {
+            cell.locked(col.readOnly || sheet.zh_setting.readOnly || false).vAlign(1).hAlign(col.hAlign);
+        }
+
+        if(col.type === 'Number') {
+            if (col.formatter) {
+                cell.formatter(SpreadJsObj.Formatter.getNumberFormatter(col.formatter))
+            } else {
+                cell.formatter(SpreadJsObj.Formatter.getNumberFormatter('0.######'));
+            }
+        } else if (col.formatter) {
+            cell.formatter(col.formatter);
+        }
+
+        cell.backColor(SpreadJsObj._getBackColor(sheet, data, iRow, col));
+
+        cell.setBorder(sheet.borderLine, {all: true});
+    },
     _getBackColor: function (sheet, data, row, col) {
         let backColor = sheet.getDefaultStyle().backColor;
         let sels = sheet.getSelections();
@@ -729,6 +778,13 @@ const SpreadJsObj = {
             this.endMassOperation(sheet);
         }
     },
+    reloadColData: function (sheet, col, count = 1) {
+        const cols = [];
+        for (let i = 0; i < count; i++) {
+            cols.push(col+i);
+        }
+        this.reLoadColsData(sheet, cols);
+    },
     /**
      * 重新加载部分列数据
      * @param {GC.Spread.Sheets.Worksheet} sheet
@@ -743,30 +799,14 @@ const SpreadJsObj = {
             for (const iCol of cols) {
                 // 清空原单元格数据
                 sheet.clear(-1, iCol, -1, 1, spreadNS.SheetArea.viewport, spreadNS.StorageType.data);
-                const col = sheet.zh_setting.cols[iCol];
 
-                sortData.forEach(function (data, i) {
-                    // 设置值
-                    const cell = sheet.getCell(i, iCol);
-                    if (col.field !== '' && data[col.field]) {
-                        cell.value(data[col.field]).locked(col.readOnly || sheet.zh_setting.readOnly || false).vAlign(1).hAlign(col.hAlign);
-                    } else {
-                        cell.locked(col.readOnly || sheet.zh_setting.readOnly || false).vAlign(1).hAlign(col.hAlign);
-                    }
-                    // 设置单元格格式
-                    if(col.type === 'Number') {
-                        if (col.formatter) {
-                            cell.formatter(SpreadJsObj.Formatter.getNumberFormatter(col.formatter))
-                        } else {
-                            cell.formatter(SpreadJsObj.Formatter.getNumberFormatter('0.######'));
-                        }
-                    } else if (col.formatter) {
-                        cell.formatter(col.formatter);
-                    }
-                });
+                for (const [iRow, data] of sortData.entries()) {
+                    this._loadCellData(sheet, data, iRow, iCol);
+                }
             }
             this.endMassOperation(sheet);
         } catch (err) {
+            console.log(err);
             this.endMassOperation(sheet);
         }
     },

+ 1 - 0
app/service/stage_pos.js

@@ -426,6 +426,7 @@ module.exports = app => {
                         sp.contract_qty = d.contract_qty === undefined && osp
                             ? osp.contract_qty
                             : this.ctx.helper.round(d.contract_qty, b.precision.value);
+                        sp.contract_expr = d.contract_expr;
                     }
                     insertPosStage.push(sp);
                 }

+ 28 - 0
app/view/revise/compare.ejs

@@ -27,6 +27,11 @@
                 <span class="ml-2"><i class="fa fa-stop text-danger-50 border-danger-50 bg-danger-50"></i> 计算项修改</span>
                 <span class="ml-2"><i class="fa fa-stop text-success-50 border-success-50 bg-success-50"></i> 文字修改</span>
             </div>
+            <div class="ml-auto">
+                <% if (lastStage) { %>
+                <a class="btn btn-sm btn-primary mr-1" href="#load-stage" data-toggle="modal" data-target="#load-stage">加载计量数据</a>
+                <% } %>
+            </div>
         </div>
     </div>
     <div class="content-wrap row pr-46">
@@ -159,6 +164,21 @@
             {title: '|台账小计|数量', colSpan: '|2|1', rowSpan: '|1|1', field: 'org_quantity', hAlign: 2, width: 60, type: 'Number', visible: <%- ctx.tender.info.display.ledger.clQty%>},
             {title: '||金额', colSpan: '||1', rowSpan: '||1', field: 'org_total_price', hAlign: 2, width: 60, type: 'Number', visible: <%- ctx.tender.info.display.ledger.clQty%>},
         ],
+        extraCols: [
+            {title: '计量数据|本期合同计量|数量', colSpan: '8|2|1', rowSpan: '1|1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '||金额', colSpan: '||1', rowSpan: '||1', field: 'contract_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|本期数量变更|数量', colSpan: '|2|1', rowSpan: '|1|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '||金额', colSpan: '||1', rowSpan: '||1', field: 'qc_tp', hAlign: 2, width: 60, type: 'Number'},
+            // {title: '|本期完成计量|数量', colSpan: '|2|1', rowSpan: '|1|1', field: 'gather_qty', hAlign: 2, width: 60, type: 'Number'},
+            // {title: '||金额', colSpan: '||1', rowSpan: '||1', field: 'gather_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|截止本期合同计量|数量', colSpan: '|2|1', rowSpan: '|1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '||金额', colSpan: '||1', rowSpan: '||1', field: 'end_contract_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|截止本期数量变更|数量', colSpan: '|2|1', rowSpan: '|1|1', field: 'end_qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '||金额', colSpan: '||1', rowSpan: '||1', field: 'end_qc_tp', hAlign: 2, width: 60, type: 'Number'},
+            // {title: '|截止本期完成计量|数量', colSpan: '|2|1', rowSpan: '|1|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
+            // {title: '||金额', colSpan: '||1', rowSpan: '||1', field: 'end_gather_tp', hAlign: 2, width: 60, type: 'Number'},
+
+        ],
         emptyRows: 3,
         headRows: 3,
         headRowHeight: [25, 25, 25],
@@ -183,6 +203,14 @@
             {title: '||其他错漏增减', colSpan: '||1', rowSpan: '||1', field: 'org_qtcl_qty', hAlign: 2, width: 100, type: 'Number', visible: <%- ctx.tender.info.display.ledger.clQty%>},
             {title: '||小计', colSpan: '||1', rowSpan: '||1', field: 'org_quantity', hAlign: 2, width: 60, type: 'Number', visible: <%- ctx.tender.info.display.ledger.clQty%>},
         ],
+        extraCols: [
+            {title: '计量数据|本期计量|合同', colSpan: '4|2|1', rowSpan: '1|1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '||数量变更', colSpan: '||1', rowSpan: '||1', field: 'qc_qty', hAlign: 2, width: 80, type: 'Number'},
+            //{title: '||完成', colSpan: '||1', rowSpan: '||1', field: 'gather_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|截止本期计量|合同', colSpan: '|2|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '||数量变更', colSpan: '||1', rowSpan: '||1', field: 'end_qc_qty', hAlign: 2, width: 80, type: 'Number'},
+            //{title: '||完成', colSpan: '||1', rowSpan: '|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
+        ],
         emptyRows: 3,
         headRows: 3,
         headRowHeight: [25, 25, 25],

+ 18 - 0
app/view/revise/compare_modal.ejs

@@ -0,0 +1,18 @@
+<% if (lastStage) { %>
+<div class="modal fade" id="load-stage" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">加载计量数据</h5>
+            </div>
+            <div class="modal-body">
+                <h5>计量进行到 第<%- lastStage.order %>期(<span class="<%- audit.stage.statusClass[lastStage.status] %>"><%- audit.stage.statusString[lastStage.status] %></span>)<br/>将为您加载该计量数据</h5>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">取消</button>
+                <button type="button" class="btn btn-primary btn-sm" id="load-stage-ok">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
+<% } %>