ソースを参照

台账分解,导入Excel清单:
1. 第一部分子项,读取数据后重排一次
2. 根据部位明细计算
3. 更新测试用例

MaiXinRong 6 年 前
コミット
84a5271a88
3 ファイル変更94 行追加10 行削除
  1. 50 7
      app/lib/analysis_excel.js
  2. 1 0
      package.json
  3. 43 3
      test/app/lib/analysis_excel.test.js

+ 50 - 7
app/lib/analysis_excel.js

@@ -172,6 +172,39 @@ class ImportBaseTree {
             return pos;
         }
     }
+
+    /**
+     * 第一部分的子节点,顺序重排
+     */
+    resortFirstPartChildren () {
+        const splitChar = this.splitChar;
+        const firstPart = this.roots[0];
+        firstPart.children.sort(function (a, b) {
+            if (a.code === '') {
+                return 1;
+            } else if (b.code === '') {
+                return -1;
+            }
+            const codeA = a.code.split(splitChar);
+            const numA = _.toNumber(codeA[codeA.length -1]);
+            const codeB = b.code.split(splitChar);
+            const numB = _.toNumber(codeB[codeB.length -1]);
+            return numA - numB;
+        });
+    }
+
+    calculateLeafWithPos () {
+        for (const node of this.items) {
+            if (node.children && node.children.length > 0) { continue; }
+            if (!node.pos || node.pos.length === 0) { continue; }
+            node.quantity = _.sum(_.map(node.pos, 'quantity'));
+            if (node.quantity && node.unit_price) {
+                node.total_price = node.quantity * node.unit_price;
+            } else {
+                node.total_price = null;
+            }
+        }
+    }
 }
 
 class AnalysisExcelTree {
@@ -195,6 +228,14 @@ class AnalysisExcelTree {
         };
     }
 
+    toNumber (value) {
+        if (value) {
+            return _.isNumber(value) ? value : _.toNumber(value);
+        } else {
+            return null;
+        }
+    }
+
     /**
      * 读取项目节节点
      * @param {Array} row - excel行数据
@@ -206,10 +247,10 @@ class AnalysisExcelTree {
         node.code = row[this.colsDef.code];
         node.name = row[this.colsDef.name];
         node.unit = row[this.colsDef.unit];
-        node.quantity = row[this.colsDef.quantity];
-        node.dgn_qty1 = row[this.colsDef.dgn_qty1];
-        node.dgn_qty2 = row[this.colsDef.dgn_qty2];
-        node.unit_price = row[this.colsDef.unit_price];
+        node.quantity = this.toNumber(row[this.colsDef.quantity]);
+        node.dgn_qty1 = this.toNumber(row[this.colsDef.dgn_qty1]);
+        node.dgn_qty2 = this.toNumber(row[this.colsDef.dgn_qty2]);
+        node.unit_price = this.toNumber(row[this.colsDef.unit_price]);
         node.drawing_code = row[this.colsDef.drawing_code];
         node.memo = row[this.colsDef.memo];
         if (node.quantity && node.unit_price) {
@@ -230,8 +271,8 @@ class AnalysisExcelTree {
         node.b_code = row[this.colsDef.b_code];
         node.name = row[this.colsDef.name];
         node.unit = row[this.colsDef.unit];
-        node.quantity = row[this.colsDef.quantity];
-        node.unit_price = row[this.colsDef.unit_price];
+        node.quantity = this.toNumber(row[this.colsDef.quantity]);
+        node.unit_price = this.toNumber(row[this.colsDef.unit_price]);
         node.drawing_code = row[this.colsDef.drawing_code];
         node.memo = row[this.colsDef.memo];
         if (node.quantity && node.unit_price) {
@@ -250,7 +291,7 @@ class AnalysisExcelTree {
     _loadPos(row) {
         const pos = {};
         pos.name = row[this.colsDef.name];
-        pos.quantity = row[this.colsDef.quantity];
+        pos.quantity = this.toNumber(row[this.colsDef.quantity]);
         pos.drawing_code = row[this.colsDef.drawing_code];
         return this.cacheTree.addPos(pos);
     }
@@ -324,6 +365,8 @@ class AnalysisExcelTree {
                 this.checkColHeader(row);
             }
         }
+        this.cacheTree.resortFirstPartChildren();
+        this.cacheTree.calculateLeafWithPos();
         return this.cacheTree;
     }
 }

+ 1 - 0
package.json

@@ -14,6 +14,7 @@
     "egg-view": "^1.1.2",
     "egg-view-ejs": "^1.1.0",
     "gt3-sdk": "^2.0.0",
+    "js-xlsx": "^0.8.22",
     "koa-is-json": "^1.0.0",
     "lodash": "^4.17.11",
     "lz-string": "^1.4.4",

+ 43 - 3
test/app/lib/analysis_excel.test.js

@@ -10,6 +10,8 @@
 
 const { app, assert } = require('egg-mock/bootstrap');
 const AnalysisExcel = require('../../../app/lib/analysis_excel');
+const Xlsx = require('js-xlsx');
+const _ = require('lodash');
 
 describe('test/app/lib/analysis_excel.test.js', () => {
     it('analysis Test Data', function* () {
@@ -34,7 +36,7 @@ describe('test/app/lib/analysis_excel.test.js', () => {
                 [ '1-2-2', null, null, '挖方', 'm3' ],
                 [ '1-2-2-1', null, null, '挖土方', 'm3' ],
                 [ '1-2-2-1-1', null, null, '挖路基土方', 'm3' ],
-                [ null, '203-1-a', null, ' ', 'm3', 92954.75, null, null, 7.53 ],
+                [ null, '203-1-a', null, ' ', 'm3', null, null, null, 7.53 ],
                 [ null, null, 1, 'K0+000-K1+000', null, 11619.34375, null, null, null, null, '第二册S-2-1' ],
                 [ null, null, 2, 'K1+000-K1+800', null, 11619.34375, null, null, null, null, '第二册S-2-1' ],
                 [ null, null, 3, 'K2+800-K3+004', null, 11619.34375, null, null, null, null, '第二册S-2-1' ],
@@ -46,14 +48,52 @@ describe('test/app/lib/analysis_excel.test.js', () => {
                 [ '1-2-2-2', null, null, '挖石方', 'm3' ],
                 [ '1-2-2-2-1', null, null, '挖软石', 'm3' ],
                 [ null, '203-1-b', null, '挖石方', 'm3', 105.36, null, null, 16.11 ],
+                [ '1-3', null, null, '路面工程', 'km' ],
+                [ '1-4', null, null, '桥梁涵洞工程', 'km' ],
+                [ '1-6', null, null, '隧道工程', 'km' ],
             ],
             range: 'A1:L29',
         };
         const ctx = app.mockContext();
         const templateData = yield ctx.service.tenderNodeTemplate.getData(true);
         const result = analysisExcel.analysisData(testData, templateData);
-        assert(result.items.length === 21);
-        assert(result.roots.length === 1);
+        // 检查插入总量
+        assert(result.items.length === 72);
+        assert(result.roots.length === 6);
         assert(result.pos.length === 8);
+        // 检查第一部分子节点排序
+        const nodes = result.roots[0].children;
+        assert(nodes[nodes.length - 2].code === '1-6');
+        assert(nodes[nodes.length - 1].code === '1-10');
+        // 检查第203-1-a的数量
+        const xmj = result.codeNodes['1-2-2-1-1'];
+        const gcl = xmj.children[0];
+        console.log(gcl);
+        assert(gcl.quantity === 92954.75);
+    });
+    it('analysis Excel Test Data', function* () {
+        const excelFile = app.baseDir  + '/app/public/files/template/ledger/Book1.xls';
+        const wb = Xlsx.readFile(excelFile);
+        const name = wb.SheetNames[0];
+        const sheetData = {
+            rows: Xlsx.utils.sheet_to_json(wb.Sheets[name], {header: 1}),
+            merge: wb.Sheets[name]["!merges"],
+        };
+        const ctx = app.mockContext();
+        const analysisExcel = new AnalysisExcel();
+        const templateData = yield ctx.service.tenderNodeTemplate.getData(true);
+        const result = analysisExcel.analysisData(sheetData, templateData);
+        assert(result.items.length === 216);
+        const xmj = result.codeNodes['1-2-3-1-2'];
+        const gcl = xmj.children[0];
+        assert(gcl.quantity === 0);
+        ctx.tender = { id: 2 };
+        // pos需要记录createUserId
+        ctx.session = {
+            sessionUser: {
+                accountId: 2,
+            },
+        };
+        yield ctx.service.ledger.importExcel(sheetData);
     });
 });