Pārlūkot izejas kodu

总分包,计量台账V0.8

MaiXinRong 3 gadi atpakaļ
vecāks
revīzija
ddcb54a026

+ 159 - 7
app/lib/sum_load.js

@@ -33,13 +33,16 @@ class loadGclBaseTree {
      * @param {String} code - 子项编号
      * @returns {*}
      */
-    findNode(node, parent) {
+    findNode(node, parent, check) {
         parent = parent || this.parent;
         if (!parent.children) return null;
 
         for (const child of parent.children) {
             const checkLeaf = (child.is_leaf && node.is_leaf) || (!child.is_leaf && !node.is_leaf);
-            if (child.b_code === node.b_code && child.name === node.name && child.unit === node.unit && checkLeaf) return child;
+            if (child.b_code === node.b_code && child.name === node.name && child.unit === node.unit
+                && checkLeaf && (!check || check(child, node))) {
+                return child;
+            }
         }
         return null;
     }
@@ -50,11 +53,9 @@ class loadGclBaseTree {
      * @param {Object} parent - 父项
      * @returns {*}
      */
-    addNode(source, parent) {
-        if (source.b_code === '101') console.log('101 parent', parent);
+    addNode(source, parent, check) {
         parent = parent ? parent : this.parent;
-        let node = this.findNode(source, parent);
-        if (source.b_code === '101') console.log('101 cur', node);
+        let node = this.findNode(source, parent, check);
         if (!node) {
             if (!parent.children) parent.children = [];
             node = {
@@ -114,6 +115,7 @@ class updateReviseGclTree extends loadGclBaseTree {
     constructor (ctx, setting) {
         super(ctx, setting);
         this.baseNodes = [];
+        this.errors = [];
     }
     loadBase(datas) {
         datas.sort((x, y) => { return x.level === y.level ? x.order - y.order : x.level - y.level; });
@@ -151,7 +153,6 @@ class updateReviseGclTree extends loadGclBaseTree {
     }
     gather(source, parent) {
         const node = this.addNode(source, parent);
-        if (source.b_code === '207-2-1') console.log('207-2-1', node, source);
         node.sgfh_qty = this.ctx.helper.add(node.sgfh_qty, source.sgfh_qty);
         node.qtcl_qty = this.ctx.helper.add(node.qtcl_qty, source.qtcl_qty);
         node.sjcl_qty = this.ctx.helper.add(node.sjcl_qty, source.sjcl_qty);
@@ -187,6 +188,99 @@ class updateReviseGclTree extends loadGclBaseTree {
     }
 }
 
+class gatherStageGclTree extends loadGclBaseTree {
+    constructor (ctx, setting) {
+        super(ctx, setting);
+        this.baseNodes = [];
+    }
+    loadBase(datas) {
+        datas.sort((x, y) => { return x.level === y.level ? x.order - y.order : x.level - y.level; });
+        const Index = {};
+        for (const d of datas) {
+            const parent = this.parent.ledger_id === d.ledger_pid ? this.parent : Index[d.ledger_pid];
+            if (!parent) continue;
+
+            if (!parent.children) parent.children = [];
+            const baseNode = {
+                id: d.id,
+                ledger_id: d.ledger_id,
+                ledger_pid: d.ledger_pid,
+                level: d.level,
+                is_leaf: d.is_leaf,
+                full_path: d.full_path,
+                b_code: d.b_code,
+                name: d.name,
+                unit: d.unit,
+                unit_price: d.unit_price,
+                org_contract_qty: d.contract_qty || 0,
+                org_contract_tp: d.contract_tp || 0,
+                org_order: d.order,
+                contract_qty: 0,
+                contract_tp: 0,
+            };
+            parent.children.push(baseNode);
+            Index[baseNode.ledger_id] = baseNode;
+            this.baseNodes.push(baseNode);
+        }
+    }
+    _gatherChange(node, source) {
+        if (!source.change_detail || source.change_detail.length === 0) return;
+
+        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);
+        }
+    }
+    gather(source, parent) {
+        parent = parent ? parent : this.parent;
+        const node = this.addNode(source, parent, function (node, source) {
+            return (source.is_tp && node.is_tp) || (!source.is_tp && !node.is_tp);
+        });
+        if (node.is_tp) {
+            node.contract_tp = this.ctx.helper.add(node.contract_tp, source.contract_tp);
+        } 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);
+        }
+        this._gatherChange(node, source);
+        return node;
+    }
+    getUpdateData() {
+        const result = {update: [], errors: []};
+        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.change_detail && bn.change_detail.length > 0) {
+                for (const cd of bn.change_detail) {
+                    result.errors.push({
+                        b_code: bn.b_code, name: bn.name, unit: bn.unit,
+                        c_code: cd.c_code, 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.qty });
+            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
+                    });
+                }
+            }
+        }
+        return result;
+    }
+}
+
 class sumLoad {
     constructor (ctx) {
         this.ctx = ctx;
@@ -250,6 +344,64 @@ class sumLoad {
         }
         return this.loadTree;
     }
+
+    _loadCurStageAndChange(billsData, curStageBills, curStageChange) {
+        const billsIndex = {};
+        for (const b of billsData) {
+            billsIndex[b.id] = b;
+        }
+        for (const csb of curStageBills) {
+            const b = billsIndex[csb.lid];
+            if (!b) continue;
+            b.contract_qty = csb.contract_qty;
+            b.contract_tp = csb.contract_tp;
+        }
+        for (const csc of curStageChange) {
+            if (!csc.qty) continue;
+
+            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 });
+            if (!c) {
+                c = { cid: csc.cid };
+                b.change_detail.push(c);
+            }
+            c.qty = this.ctx.helper.add(c.qty, csc.qty);
+        }
+    }
+
+    async stageGatherGcl(select, maxId, tenders, defaultData) {
+        this.loadTree = new gatherStageGclTree(this.ctx, {
+            parent: select, maxId, type: 'ledger', defaultData,
+        });
+        const posterity = await this.ctx.service.ledger.getPosterityByParentId(this.ctx.tender.id, select.ledger_id);
+        this.loadTree.loadBase(posterity);
+
+        for (const tender of tenders) {
+            const billsData = await this.ctx.service.ledger.getData(tender.tid);
+            const stage = await this.ctx.service.stage.getDataByCondition({tid: tender.tid, order: tender.stage});
+            if (!stage) throw '选择的期不存在';
+            const curStageData = await this.ctx.service.stageBills.getLastestStageData(tender.tid, stage.id);
+            const curStageChange = await this.ctx.service.stageChangeFinal.getSumLoadFinalData({tid: tender.tid, sid: stage.id});
+            this._loadCurStageAndChange(billsData, curStageData, curStageChange);
+            const billsTree = new Ledger.billsTree(this.ctx, {
+                id: 'ledger_id',
+                pid: 'ledger_pid',
+                order: 'order',
+                level: 'level',
+                rootId: -1,
+                keys: ['id', 'tender_id', 'ledger_id'],
+                stageId: 'id',
+            });
+            billsTree.loadDatas(billsData);
+            for (const top of billsTree.children) {
+                if ([1].indexOf(top.node_type) < 0) continue;
+                this.recusiveLoadGatherGcl(top, null);
+            }
+        }
+        return this.loadTree;
+    }
 }
 
 module.exports = sumLoad;

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

@@ -1603,7 +1603,7 @@ $(document).ready(function() {
         };
         billsContextMenuOptions.items.importGclBills2Xmj = {
             name: '导入(其他标段)工程量清单至项目节',
-            icon: 'fa-file-excel-o',
+            icon: 'fa-link',
             disabled: function (key, opt) {
                 const node = SpreadJsObj.getSelectObject(ledgerSpread.getActiveSheet());
                 return readOnly || !node

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

@@ -1268,7 +1268,7 @@ $(document).ready(() => {
         });
         billsContextMenuOptions.items.importGclBills2Xmj = {
             name: '更新(其他标段)工程量清单至项目节',
-            icon: 'fa-file-excel-o',
+            icon: 'fa-link',
             disabled: function (key, opt) {
                 const node = SpreadJsObj.getSelectObject(billsSheet);
                 return readOnly || !node || (!_.isNil(node.b_code) && node.b_code !== '');

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

@@ -20,6 +20,8 @@ const TenderSelect = function (setting) {
                     return items;
                 };
                 for (let i = 0; i < tsObj.resultSheet.getRowCount(); i++) {
+                    const items = getItems(tsObj.trArray[i]);
+                    console.log(items);
                     const cellType2 = new spreadNS.CellTypes.ComboBox().itemHeight(10).editorValueType(spreadNS.CellTypes.EditorValueType.value).items(getItems(tsObj.trArray[i]));
                     tsObj.resultSheet.getCell(i, 1).cellType(cellType2);
                 }
@@ -144,6 +146,13 @@ const TenderSelect = function (setting) {
                 headerFont: '12px 微软雅黑',
                 font: '12px 微软雅黑',
                 headColWidth: [],
+                getColor: function (sheet, data, row, col, defaultColor) {
+                    if (data) {
+                        return data.invalid ? '#ddd' : defaultColor;
+                    } else {
+                        return defaultColor;
+                    }
+                }
             };
             if (this.setting.type === 'ledger' || this.setting.type === 'revise') {
                 resultSpreadSetting.cols.push(
@@ -173,10 +182,21 @@ const TenderSelect = function (setting) {
         },
         resetSelect: function () {
             tsObj.trArray.length = 0;
-            if (tsObj.trHistory.tenders) tsObj.trArray.push(...tsObj.trHistory.tenders);
+            if (tsObj.trHistory.tenders) {
+                for (const trh of tsObj.trHistory.tenders) {
+                    const source = tsObj.tenderSourceTree.nodes.find(x => { return x.tid === trh.tid; });
+                    if (source) {
+                        trh.stageCount = source.stageCount;
+                    } else {
+                        trh.invalid = true;
+                    }
+                    tsObj.trArray.push(trh);
+                }
+            }
             tsObj._initSelected();
             SpreadJsObj.loadSheetData(tsObj.tenderSheet, SpreadJsObj.DataType.Tree, tsObj.tenderSourceTree);
             SpreadJsObj.loadSheetData(tsObj.resultSheet, SpreadJsObj.DataType.Data, tsObj.trArray);
+            tsObj._rebuildStageSelect();
             $('#tender-select-hint').hide();
         }
     };

+ 13 - 5
app/public/js/stage.js

@@ -181,7 +181,6 @@ function getHintMsg () {
 
 
 $(document).ready(() => {
-    const tenderSelect = TenderSelect({type: 'stage'});
     const exportExcelSetting = {
         cols: [
             {title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', cellType: 'tree'},
@@ -1440,6 +1439,18 @@ $(document).ready(() => {
     }
     stageTreeSpreadObj.loadExprToInput(slSpread.getActiveSheet());
     const addTag = newTag({ledgerSheet: slSpread.getActiveSheet(), billsTag});
+    const tenderSelect = TenderSelect({
+        type: 'stage',
+        afterLoad: function (result) {
+            const nodes = stageTree.loadPostStageData(result);
+            stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), nodes);
+            if (detail) {
+                detail.loadStageLedgerUpdateData(result, nodes);
+            } else {
+                stageIm.loadUpdateLedgerData(result, nodes);
+            }
+        }
+    });
     $.contextMenu({
         selector: '#stage-ledger',
         build: function ($trigger, e) {
@@ -1521,16 +1532,13 @@ $(document).ready(() => {
             importSpr: '---',
             importStageGcl: {
                 name: '导入(其他标段)工程量清单计量数据',
-                icon: 'fa-file-excel-o',
+                icon: 'fa-link',
                 disabled: function (key, opt) {
                     const node = SpreadJsObj.getSelectObject(slSpread.getActiveSheet());
                     return readOnly || !node || (!_.isNil(node.b_code) && node.b_code !== '');
                 },
                 callback: function (key, opt) {
                     tenderSelect.showSelect(SpreadJsObj.getSelectObject(slSpread.getActiveSheet()));
-                },
-                visible: function (key, opt) {
-                    return !readOnly;
                 }
             },
         }

+ 22 - 0
app/service/stage_bills.js

@@ -10,6 +10,7 @@
 const calcFields = ['contract_qty', 'qc_qty'];
 const auditConst = require('../const/audit');
 const timesLen = auditConst.stage.timesLen;
+const SumLoad = require('../lib/sum_load');
 
 module.exports = app => {
     class StageBills extends app.BaseService {
@@ -475,6 +476,27 @@ module.exports = app => {
             }
             return { contract_tp, qc_tp };
         }
+
+        async sumLoad(lid, tender) {
+            const conn = await this.db.beginTransaction();
+            try {
+                const maxId = await this._getMaxLid(this.ctx.tender.id);
+                const select = await this.getDataById(lid);
+                const sumLoad = new SumLoad(this.ctx);
+                const loadTree = await sumLoad.stageGatherGcl(select, maxId, tenders);
+                const result = loadTree.getUpdateData();
+
+                this._cacheMaxLid(this.ctx.tender.id, loadTree.keyNodeId);
+                await this.ctx.service.sumLoadHistory.saveReviseHistory(this.ctx.tender.id, rid, lid, tenders, result.errors);
+                if (result.update.length > 0) await conn.updateRows(this.tableName, result.update);
+                if (result.create.length > 0)await conn.insert(this.tableName, result.create);
+                await conn.commit();
+                return result;
+            } catch (err) {
+                await conn.rollback();
+                throw (err.stack ? err : '导入工程量数据出错');
+            }
+        }
     }
 
     return StageBills;

+ 9 - 0
app/service/stage_change_final.js

@@ -82,6 +82,15 @@ module.exports = app => {
             }
             await transaction.delete(this.tableName, { tid: tender.id, sid: stage.id });
         }
+
+        async getSumLoadFinalData(sid) {
+            const sql = 'Select cf.lid, cf.cid, 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';
+            return await this.db.query(sql, [sid]);
+        }
     }
 
     return StageChangeFinal;

+ 1 - 0
app/view/stage/modal.ejs

@@ -521,3 +521,4 @@
 <% include ../shares/merge_peg_modal.ejs %>
 <% include ../shares/check_modal2.ejs %>
 <% include ../shares/new_tag_modal.ejs %>
+<% include ../shares/tender_select_modal.ejs %>