Browse Source

数据预处理,过滤

MaiXinRong 5 năm trước cách đây
mục cha
commit
dd6aa7974a
2 tập tin đã thay đổi với 435 bổ sung216 xóa
  1. 87 0
      app/lib/rpt_data_analysis.js
  2. 348 216
      test/app/lib/rpt_data_analysis.test.js

+ 87 - 0
app/lib/rpt_data_analysis.js

@@ -16,6 +16,7 @@ const changeSort = {
         '变更令排序勿需勾选任何预定义处理指标,但是在指标映射中,需要添加如下指标:' +
         '1. 如果只有变更令数据,则必须添加,"变更令(change)"下的"变更令号"' +
         '2. 如果有变更清单需要排序,则必须在1的基础上添加,变更令(change)"下的"变更令uuid"和"变更清单(chang_audit_list)"下的"所属变更令uuid"&"清单编号"',
+    intro: '报表对于主从表的排序有要求,解决变更令数据中的变更令、变更清单排序问题',
     /**
      *
      * @param ctx - context常量
@@ -54,6 +55,7 @@ const gatherGcl = {
         '  树结构-层级(level), 树结构-同层排序(order), 树结构-完整路径(full_path),\n' +
         '  图册号(drawing_code), 备注(memo), 节点类型(node_type), 总额计量(is_tp)\n' +
         '3. 如需汇总"未计入清单章节项",请勾选"章节编号(chapter)"字段\n',
+    intro: '根据三级清单树结构,汇总平面工程量清单,目前仅支持mem_stage_bills表',
     fun: function (ctx, data, fieldsKey, options) {
         const gatherFields = function(gcl, data, fields) {
             for (const f of fields) {
@@ -127,6 +129,7 @@ const sortGcl = {
         '特别的,如有"未计入清单章节项": \n' +
         '  1. 默认"未计入清单章节项"排列在最后\n' +
         '  2. 如须"未计入清单章节项"排在100章之后,请在清单编号字段后,依次勾选"章节编号(chapter)", "名称(name)"\n',
+    intro: '根据选择列,对数据进行工程量清单排序,兼容1000章后清单,以及403-1-a类的非纯数字编号排序',
     fun: function (ctx, data, fieldsKey, options) {
         if (fieldsKey.length !== 1 && fieldsKey.length !== 3) return;
         const code = fieldsKey[0].field;
@@ -164,6 +167,7 @@ const gatherChapter = {
         'e.g.2 要对mem_stage_bills_compare汇总,须勾选mem_stage_bills_compare下的"清单编号(b_code)", "树结构-是否子项((is_leaf)"字段\n' +
         '结果:\n' +
         '汇总结果可参照 清单汇总--章节合计,但是不过滤1000-1300章数据',
+    intro: '用于得到类似“清单汇总--章级合计”的数据,可通过options自定义数据',
     defaultSetting: {
         count: 9,
         unChapter: {
@@ -344,6 +348,7 @@ const gatherChapter = {
 const join = {
     name: "连接两张数据表",
     hint: "用于处理类似于关联签约清单的情况,会改变主表的数据",
+    intro: '用于处理类似于关联签约清单的情况,会根据关联表(sub)改变主表(main)的数据',
     defaultSetting: {
         main: 'mem_stage_bills',
         sub: 'deal_bills',
@@ -369,6 +374,9 @@ const join = {
         const _ = ctx.helper._, result = _.cloneDeep(main);
         for (const r of result) {
             r._join_tag = 'main';
+            for (const i of options.importFields) {
+                r[i.main] = null;
+            }
         }
         for (const s of sub) {
             let r = result.find(function (x) {
@@ -416,6 +424,7 @@ const join = {
 };
 const getChapterCode = {
     name: '获取章级编号',
+    intro: '根据清单编号,计算章级编号,并写入指定字段,适用于未提供chapter字段的数据,例如签约清单',
     hint: '',
     defaultSetting: {
         table: 'mem_stage_bills',
@@ -433,6 +442,81 @@ const getChapterCode = {
         }
     }
 };
+const filter = {
+    name: '数据过滤',
+    intro: '根据设置过滤数据,会直接修改数据表',
+    defaultSetting: {
+        "table": "pay",
+        "condition": [
+            {"field": "minus", "type": "bool", "value": "false"},
+            {"field": "ptype", "type": "num", "operate": "=", "value": 1},
+            {"field": "name", "type": "str", "operate": "=", "value": "扣回"}
+        ],
+    },
+    _typeFun: {
+        bool: '_checkBoolean',
+        str: '_checkString',
+        num: '_checkNumber',
+    },
+    _checkBoolean: function (ctx, value, condition) {
+        switch (condition.value) {
+            case 'true':
+                return value ? true : false;
+            case 'false':
+                return value ? false : true;
+            default:
+                return true;
+        }
+    },
+    _checkNumber: function (ctx, value, condition) {
+        //if (ctx.helper._.isNil(value)) value = 0;
+        switch (condition.operate) {
+            case 'non-zero':
+                return !ctx.helper.checkZero(value);
+            case '=':
+                return !ctx.helper._.isNil(value) ? value === condition.value : false;
+            case '>':
+                return !ctx.helper._.isNil(value) ? value > condition.value : false;
+            case '<':
+                return !ctx.helper._.isNil(value) ? value < condition.value : false;
+            case '>=':
+                return !ctx.helper._.isNil(value) ? value >= condition.value : false;
+            case '<=':
+                return !ctx.helper._.isNil(value) ? value <= condition.value : false;
+            default:
+                return true;
+        }
+    },
+    _checkString: function (ctx, value, condition) {
+        switch (condition.operate) {
+            case '=':
+                return value === condition.value;
+            case 'part':
+                return !ctx.helper._.isNil(value) ? value.indexOf(condition.value) >= 0 : false;
+            case 'enum':
+                return (!ctx.helper._.isNil(value) && condition.value instanceof Array) ? condition.value.indexOf(value) >= 0 : false;
+            default:
+                return true;
+        }
+    },
+    fun: function (ctx, data, fields, options) {
+        if (!options || !options.table || !options.condition) return;
+
+        const fData = data[options.table], self = this;
+        if (!fData) return;
+        for (const c of options.condition) {
+            c.fun = this._typeFun[c.type];
+        }
+
+        const result = fData.filter(function (d) {
+            for (const c of options.condition) {
+                if (!self[c.fun](ctx, d[c.field], c)) return false;
+            }
+            return true;
+        });
+        data[options.table] = result;
+    }
+};
 
 const analysisObj = {
     changeSort,
@@ -441,6 +525,7 @@ const analysisObj = {
     gatherChapter,
     join,
     getChapterCode,
+    filter
 };
 const analysisDefine = (function (obj) {
     const result = [];
@@ -451,6 +536,8 @@ const analysisDefine = (function (obj) {
                 name: analysis.name,
                 key: o,
                 hint: analysis.hint,
+                intro: analysis.intro,
+                url: '/help?m=report&s=analysis&d=' + o,
             })
         }
     }

+ 348 - 216
test/app/lib/rpt_data_analysis.test.js

@@ -35,234 +35,366 @@ describe('test/app/service/report_memory.test.js', () => {
         mockData.session = ctx.session;
     });
     // 数据
-    it('test changeSort', function* () {
+    // it('test changeSort', function* () {
+    //     const ctx = app.mockContext(mockData);
+    //
+    //     // test12 - 第6期
+    //     const stage = yield ctx.service.stage.getDataByCondition({tid: 12, order: 6});
+    //     const params = {
+    //         tender_id: stage.tid,
+    //         stage_id: stage.id,
+    //     };
+    //     const filters = ['change', 'change_audit_list'];
+    //     const data = yield ctx.service.report.getReportData(params, filters);
+    //     reportDataAnalysis.analysisObj.changeSort.fun(ctx, data);
+    //     assert(data.change[0].code === 'test7-BG-001');
+    //     assert(data.change[2].code === 'test7-BG-003');
+    //     const changeCid = ctx.helper._.map(data.change, 'cid');
+    //     const changeBillsCid = ctx.helper._.uniq(ctx.helper._.map(data.change_audit_list, 'cid'));
+    //     assert(changeCid.length === changeBillsCid.length);
+    //     changeCid.forEach(function (a, i) {
+    //         assert(a === changeBillsCid[i]);
+    //     });
+    // });
+    // it('test gatherGcl && sortGcl', function* () {
+    //     const ctx = app.mockContext(mockData);
+    //
+    //     // test12 - 第6期
+    //     const stage = yield ctx.service.stage.getDataByCondition({tid: 12, order: 6});
+    //     const params = {
+    //         tender_id: stage.tid,
+    //         stage_id: stage.id,
+    //     };
+    //     const filters = ['mem_stage_bills'];
+    //     const data = yield ctx.service.report.getReportData(params, filters, {
+    //         mem_stage_bills: [
+    //             'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
+    //             'code', 'b_code', 'name', 'unit', 'unit_price',
+    //             'deal_qty', 'deal_tp',
+    //             'sgfh_qty', 'sgfh_tp', 'sjcl_qty', 'sjcl_tp', 'qtcl_qty', 'qtcl_tp', 'quantity', 'total_price',
+    //             'dgn_qty1', 'dgn_qty2',
+    //             'drawing_code', 'memo', 'node_type', 'is_tp',
+    //             'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp', 'postil',
+    //             'pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_gather_qty', 'pre_gather_tp',
+    //             'end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_gather_qty', 'end_gather_tp',
+    //             'final_tp', 'final_ratio',
+    //             'qc_bgl_code',
+    //             'chapter',
+    //         ]
+    //     });
+    //     assert(data.mem_stage_bills.length === 216);
+    //     reportDataAnalysis.analysisObj.gatherGcl.fun(ctx, data, [
+    //         {field: 'b_code', table: 'mem_stage_bills'},
+    //         {field: 'name', table: 'mem_stage_bills'},
+    //         {field: 'unit', table: 'mem_stage_bills'},
+    //         {field: 'unit_price', table: 'mem_stage_bills'},
+    //         {field: 'is_leaf', table: 'mem_stage_bills'},
+    //     ]);
+    //     assert(data.mem_stage_bills.length === 43);
+    //     reportDataAnalysis.analysisObj.sortGcl.fun(ctx, data, [
+    //         {field: 'b_code', table: 'mem_stage_bills'},
+    //     ]);
+    //     const codeIndex = ctx.helper._.map(data.mem_stage_bills, 'b_code');
+    //     const codeIndex100 = ['103-1', '103-2', '103-3-a', '103-3-b', '103-4', '104-1'];
+    //     const codeIndex200 = [
+    //         '203-1-a', '203-1-b', '203-1-d', '204-1-b', '204-1-g-4', '204-1-j', '205-1-o-1', '206-2',
+    //         '207-1-b', '207-2-a', '207-3-a', '207-4-a', '208-1-a', '208-3-a', '208-3-c', '208-4-b-1', '209-1-a',
+    //     ];
+    //     const codeIndex400 = [
+    //         '403-1-a', '403-1-b', '403-2-a', '403-2-b', '403-3-a', '403-3-b', '403-4-a', '403-4-b',
+    //         '405-1-b-5', '405-1-b-6', '410-1-b', '410-1-c', '410-2-b', '410-2-c', '410-6-c',
+    //         '411-5', '411-7-a', '411-8-a', '413-1-a', '417-5-a'
+    //     ];
+    //     let codeResult = codeIndex100.concat(codeIndex200, codeIndex400);
+    //     codeIndex.forEach(function (a, i) {
+    //         assert(a === codeResult[i]);
+    //     });
+    // });
+    // it('test gatherChapter', function* () {
+    //     const ctx = app.mockContext(mockData);
+    //
+    //     // test12 - 第6期
+    //     const stage = yield ctx.service.stage.getDataByCondition({tid: 12, order: 6});
+    //     const params = {
+    //         tender_id: stage.tid,
+    //         stage_id: stage.id,
+    //     };
+    //     const filters = ['mem_stage_bills', 'tender_info'];
+    //     const data = yield ctx.service.report.getReportData(params, filters, {
+    //         mem_stage_bills: [
+    //             'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
+    //             'code', 'b_code', 'name', 'unit', 'unit_price',
+    //             'deal_qty', 'deal_tp',
+    //             'sgfh_qty', 'sgfh_tp', 'sjcl_qty', 'sjcl_tp', 'qtcl_qty', 'qtcl_tp', 'quantity', 'total_price',
+    //             'dgn_qty1', 'dgn_qty2',
+    //             'drawing_code', 'memo', 'node_type', 'is_tp',
+    //             'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp', 'postil',
+    //             'pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_gather_qty', 'pre_gather_tp',
+    //             'end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_gather_qty', 'end_gather_tp',
+    //             'final_tp', 'final_ratio',
+    //             'qc_bgl_code',
+    //             'chapter',
+    //         ]
+    //     });
+    //     reportDataAnalysis.analysisObj.gatherChapter.fun(ctx, data, [
+    //         {field: 'b_code', table: 'mem_stage_bills'},
+    //         {field: 'is_leaf', table: 'mem_stage_bills'},
+    //     ]);
+    //     const chapter100 = ctx.helper._.find(data.mem_stage_bills, {code: '100'});
+    //     assert(chapter100.total_price === 1045756);
+    //     const chapter200 = ctx.helper._.find(data.mem_stage_bills, {code: '200'});
+    //     assert(chapter200.total_price.toFixed(0) == 3813369);
+    //     assert(chapter200.contract_tp == 700.5);
+    //     const chapter400 = ctx.helper._.find(data.mem_stage_bills, {code: '400'});
+    //     assert(chapter400.total_price.toFixed(0) == 1231018);
+    // });
+    // it('test gatherChapter', function* () {
+    //     const ctx = app.mockContext(mockData);
+    //
+    //     // test12 - 第6期
+    //     const stage = yield ctx.service.stage.getDataByCondition({tid: 12, order: 6});
+    //     const params = {
+    //         tender_id: stage.tid,
+    //         stage_id: stage.id,
+    //     };
+    //     const filters = ['mem_stage_bills', 'tender_info'];
+    //     const data = yield ctx.service.report.getReportData(params, filters, {
+    //         mem_stage_bills: [
+    //             'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
+    //             'code', 'b_code', 'name', 'unit', 'unit_price',
+    //             'deal_qty', 'deal_tp',
+    //             'sgfh_qty', 'sgfh_tp', 'sjcl_qty', 'sjcl_tp', 'qtcl_qty', 'qtcl_tp', 'quantity', 'total_price',
+    //             'dgn_qty1', 'dgn_qty2',
+    //             'drawing_code', 'memo', 'node_type', 'is_tp',
+    //             'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp', 'postil',
+    //             'pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_gather_qty', 'pre_gather_tp',
+    //             'end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_gather_qty', 'end_gather_tp',
+    //             'final_tp', 'final_ratio',
+    //             'qc_bgl_code',
+    //             'chapter',
+    //         ]
+    //     });
+    //     reportDataAnalysis.analysisObj.gatherChapter.fun(ctx, data, [
+    //         {field: 'b_code', table: 'mem_stage_bills'},
+    //         {field: 'is_leaf', table: 'mem_stage_bills'},
+    //     ]);
+    //     const chapter100 = ctx.helper._.find(data.mem_stage_bills, {code: '100'});
+    //     assert(chapter100.total_price === 1045756);
+    //     const chapter200 = ctx.helper._.find(data.mem_stage_bills, {code: '200'});
+    //     assert(chapter200.total_price.toFixed(0) == 3813369);
+    //     assert(chapter200.contract_tp == 700.5);
+    //     const chapter400 = ctx.helper._.find(data.mem_stage_bills, {code: '400'});
+    //     assert(chapter400.total_price.toFixed(0) == 1231018);
+    // });
+    // it('test join', function* () {
+    //     const ctx = app.mockContext(mockData);
+    //
+    //     // test12 - 第6期
+    //     const stage = yield ctx.service.stage.getDataByCondition({tid: 12, order: 6});
+    //     const params = {
+    //         tender_id: stage.tid,
+    //         stage_id: stage.id,
+    //     };
+    //     const filters = ['mem_stage_bills', 'deal_bills'];
+    //     const data = yield ctx.service.report.getReportData(params, filters, {
+    //         mem_stage_bills: [
+    //             'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
+    //             'code', 'b_code', 'name', 'unit', 'unit_price',
+    //             'deal_qty', 'deal_tp',
+    //             'sgfh_qty', 'sgfh_tp', 'sjcl_qty', 'sjcl_tp', 'qtcl_qty', 'qtcl_tp', 'quantity', 'total_price',
+    //             'dgn_qty1', 'dgn_qty2',
+    //             'drawing_code', 'memo', 'node_type', 'is_tp',
+    //             'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp', 'postil',
+    //             'pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_gather_qty', 'pre_gather_tp',
+    //             'end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_gather_qty', 'end_gather_tp',
+    //             'final_tp', 'final_ratio',
+    //             'qc_bgl_code',
+    //             'chapter',
+    //         ]
+    //     });
+    //     assert(data.mem_stage_bills.length === 216);
+    //     reportDataAnalysis.analysisObj.gatherGcl.fun(ctx, data, [
+    //         {field: 'b_code', table: 'mem_stage_bills'},
+    //         {field: 'name', table: 'mem_stage_bills'},
+    //         {field: 'unit', table: 'mem_stage_bills'},
+    //         {field: 'unit_price', table: 'mem_stage_bills'},
+    //         {field: 'is_leaf', table: 'mem_stage_bills'},
+    //     ]);
+    //     assert(data.mem_stage_bills.length === 43);
+    //     const joinOptions = {
+    //         main: 'mem_stage_bills',
+    //         sub: 'deal_bills',
+    //         keyFields: [
+    //             {main: 'b_code', sub: 'code', type: 'string'},
+    //             {main: 'name', sub: 'name',type: 'string'},
+    //             {main: 'unit', sub: 'unit',type: 'string'},
+    //             {main: 'unit_price', sub: 'unit_price',type: 'number'},
+    //         ],
+    //         importFields: [
+    //             {main: 'ex_value1', sub: 'quantity', type: 'number'},
+    //             {main: 'ex_value2', sub: 'total_price', type: 'number'}
+    //         ],
+    //         joinType: 'outer', //'outer', 'main', 'sub', 'inner'
+    //     };
+    //     yield ctx.helper.saveBufferFile(JSON.stringify(joinOptions, '', '\t'), ctx.app.baseDir + '/analysis_join_options.json');
+    //     reportDataAnalysis.analysisObj.join.fun(ctx, data, [], joinOptions);
+    //     assert(data.mem_stage_bills.length === 132);
+    //     reportDataAnalysis.analysisObj.sortGcl.fun(ctx, data, [
+    //         {field: 'b_code', table: 'mem_stage_bills'},
+    //     ]);
+    //     const codeIndex = ctx.helper._.map(data.mem_stage_bills, 'b_code');
+    //     const codeIndex100 = ['101-1-b', '102-2', '102-3', '102-4', '102-5', '103-1', '103-2',
+    //         '103-3',  '103-3-a', '103-3-b', '103-4', '104-1', '123-1'];
+    //     const codeIndex200 = [
+    //         '203-1-a', '203-1-a', '203-1-b', '203-1-b', '203-1-d', '203-1-d', '204-1-b', '204-1-b',
+    //         '204-1-c', '204-1-d',
+    //         '204-1-g-4', '204-1-g-4', '204-1-j', '204-1-j', '205-1-o-1', '205-1-o-1', '206-2', '206-2',
+    //         '207-1-b',
+    //         '207-2-a', '207-2-a',
+    //         '207-2-b', '207-2-c', '207-3-a',
+    //         '207-4-a', '207-4-a',
+    //         '207-4-c', '207-10-a',
+    //         '208-1-a', '208-1-a', '208-3-a', '208-3-a',
+    //         '208-3-b',
+    //         '208-3-c', '208-3-c', '208-4-b-1', '208-4-b-1', '209-1-a', '209-1-a',
+    //         '209-3', '209-3-b', '215-12', '215-12-a'
+    //     ];
+    //     let codeResult = codeIndex100.concat(codeIndex200);
+    //     codeResult.forEach(function (a, i) {
+    //         assert(a === codeIndex[i]);
+    //     });
+    // });
+    it('test filter', function* () {
         const ctx = app.mockContext(mockData);
+        const orgData = {
+            test: [
+                {a: 'aaa', b: 0, c: true, order: 1},
+                {a: 'aaa', b: 1, c: false, order: 2},
+                {a: 'aaa', b: 2, c: false, order: 3},
+                {a: 'bbb', b: 3, c: true, order: 4},
+                {a: 'bbb', b: null, c: true, order: 5},
+                {a: 'ccc', b: 0, c: false, order: 6},
+                {a: 'ccc', b: -1, c: false, order: 7},
+                {a: 'ddd', b: 8, c: true, order: 8},
+            ]
+        };
+        let data, result;
 
-        // test12 - 第6期
-        const stage = yield ctx.service.stage.getDataByCondition({tid: 12, order: 6});
-        const params = {
-            tender_id: stage.tid,
-            stage_id: stage.id,
+        // test boolean;
+        const b1 = {
+            table: 'test',
+            condition: [{ field: "c", type: "bool", value: 'false'}]
         };
-        const filters = ['change', 'change_audit_list'];
-        const data = yield ctx.service.report.getReportData(params, filters);
-        reportDataAnalysis.analysisObj.changeSort.fun(ctx, data);
-        assert(data.change[0].code === 'test7-BG-001');
-        assert(data.change[2].code === 'test7-BG-003');
-        const changeCid = ctx.helper._.map(data.change, 'cid');
-        const changeBillsCid = ctx.helper._.uniq(ctx.helper._.map(data.change_audit_list, 'cid'));
-        assert(changeCid.length === changeBillsCid.length);
-        changeCid.forEach(function (a, i) {
-            assert(a === changeBillsCid[i]);
-        });
-    });
-    it('test gatherGcl && sortGcl', function* () {
-        const ctx = app.mockContext(mockData);
+        data = JSON.parse(JSON.stringify(orgData));
+        reportDataAnalysis.analysisObj.filter.fun(ctx, data, [], b1);
+        result = ctx.helper._.map(data.test, 'order');
+        assert(ctx.helper._.isEqual(result, [2, 3, 6, 7]));
 
-        // test12 - 第6期
-        const stage = yield ctx.service.stage.getDataByCondition({tid: 12, order: 6});
-        const params = {
-            tender_id: stage.tid,
-            stage_id: stage.id,
+        const b2 = {
+            table: 'test',
+            condition: [{ field: "c", type: "bool", value: 'true'}]
         };
-        const filters = ['mem_stage_bills'];
-        const data = yield ctx.service.report.getReportData(params, filters, {
-            mem_stage_bills: [
-                'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
-                'code', 'b_code', 'name', 'unit', 'unit_price',
-                'deal_qty', 'deal_tp',
-                'sgfh_qty', 'sgfh_tp', 'sjcl_qty', 'sjcl_tp', 'qtcl_qty', 'qtcl_tp', 'quantity', 'total_price',
-                'dgn_qty1', 'dgn_qty2',
-                'drawing_code', 'memo', 'node_type', 'is_tp',
-                'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp', 'postil',
-                'pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_gather_qty', 'pre_gather_tp',
-                'end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_gather_qty', 'end_gather_tp',
-                'final_tp', 'final_ratio',
-                'qc_bgl_code',
-                'chapter',
-            ]
-        });
-        assert(data.mem_stage_bills.length === 216);
-        reportDataAnalysis.analysisObj.gatherGcl.fun(ctx, data, [
-            {field: 'b_code', table: 'mem_stage_bills'},
-            {field: 'name', table: 'mem_stage_bills'},
-            {field: 'unit', table: 'mem_stage_bills'},
-            {field: 'unit_price', table: 'mem_stage_bills'},
-            {field: 'is_leaf', table: 'mem_stage_bills'},
-        ]);
-        assert(data.mem_stage_bills.length === 43);
-        reportDataAnalysis.analysisObj.sortGcl.fun(ctx, data, [
-            {field: 'b_code', table: 'mem_stage_bills'},
-        ]);
-        const codeIndex = ctx.helper._.map(data.mem_stage_bills, 'b_code');
-        const codeIndex100 = ['103-1', '103-2', '103-3-a', '103-3-b', '103-4', '104-1'];
-        const codeIndex200 = [
-            '203-1-a', '203-1-b', '203-1-d', '204-1-b', '204-1-g-4', '204-1-j', '205-1-o-1', '206-2',
-            '207-1-b', '207-2-a', '207-3-a', '207-4-a', '208-1-a', '208-3-a', '208-3-c', '208-4-b-1', '209-1-a',
-        ];
-        const codeIndex400 = [
-            '403-1-a', '403-1-b', '403-2-a', '403-2-b', '403-3-a', '403-3-b', '403-4-a', '403-4-b',
-            '405-1-b-5', '405-1-b-6', '410-1-b', '410-1-c', '410-2-b', '410-2-c', '410-6-c',
-            '411-5', '411-7-a', '411-8-a', '413-1-a', '417-5-a'
-        ];
-        let codeResult = codeIndex100.concat(codeIndex200, codeIndex400);
-        codeIndex.forEach(function (a, i) {
-            assert(a === codeResult[i]);
-        });
-    });
-    it('test gatherChapter', function* () {
-        const ctx = app.mockContext(mockData);
+        data = JSON.parse(JSON.stringify(orgData));
+        reportDataAnalysis.analysisObj.filter.fun(ctx, data, [], b2);
+        result = ctx.helper._.map(data.test, 'order');
+        assert(ctx.helper._.isEqual(result, [1, 4, 5, 8]));
 
-        // test12 - 第6期
-        const stage = yield ctx.service.stage.getDataByCondition({tid: 12, order: 6});
-        const params = {
-            tender_id: stage.tid,
-            stage_id: stage.id,
+        // test number
+        const n1 = {
+            table: 'test',
+            condition: [{ field: "b", type: "num", operate: 'non-zero'}]
         };
-        const filters = ['mem_stage_bills', 'tender_info'];
-        const data = yield ctx.service.report.getReportData(params, filters, {
-            mem_stage_bills: [
-                'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
-                'code', 'b_code', 'name', 'unit', 'unit_price',
-                'deal_qty', 'deal_tp',
-                'sgfh_qty', 'sgfh_tp', 'sjcl_qty', 'sjcl_tp', 'qtcl_qty', 'qtcl_tp', 'quantity', 'total_price',
-                'dgn_qty1', 'dgn_qty2',
-                'drawing_code', 'memo', 'node_type', 'is_tp',
-                'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp', 'postil',
-                'pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_gather_qty', 'pre_gather_tp',
-                'end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_gather_qty', 'end_gather_tp',
-                'final_tp', 'final_ratio',
-                'qc_bgl_code',
-                'chapter',
-            ]
-        });
-        reportDataAnalysis.analysisObj.gatherChapter.fun(ctx, data, [
-            {field: 'b_code', table: 'mem_stage_bills'},
-            {field: 'is_leaf', table: 'mem_stage_bills'},
-        ]);
-        const chapter100 = ctx.helper._.find(data.mem_stage_bills, {code: '100'});
-        assert(chapter100.total_price === 1045756);
-        const chapter200 = ctx.helper._.find(data.mem_stage_bills, {code: '200'});
-        assert(chapter200.total_price.toFixed(0) == 3813369);
-        assert(chapter200.contract_tp == 700.5);
-        const chapter400 = ctx.helper._.find(data.mem_stage_bills, {code: '400'});
-        assert(chapter400.total_price.toFixed(0) == 1231018);
-    });
-    it('test gatherChapter', function* () {
-        const ctx = app.mockContext(mockData);
+        data = JSON.parse(JSON.stringify(orgData));
+        reportDataAnalysis.analysisObj.filter.fun(ctx, data, [], n1);
+        result = ctx.helper._.map(data.test, 'order');
+        assert(ctx.helper._.isEqual(result, [2, 3, 4, 7, 8]));
 
-        // test12 - 第6期
-        const stage = yield ctx.service.stage.getDataByCondition({tid: 12, order: 6});
-        const params = {
-            tender_id: stage.tid,
-            stage_id: stage.id,
+        const n2 = {
+            table: 'test',
+            condition: [{ field: "b", type: "num", operate: '=', value: 1}]
         };
-        const filters = ['mem_stage_bills', 'tender_info'];
-        const data = yield ctx.service.report.getReportData(params, filters, {
-            mem_stage_bills: [
-                'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
-                'code', 'b_code', 'name', 'unit', 'unit_price',
-                'deal_qty', 'deal_tp',
-                'sgfh_qty', 'sgfh_tp', 'sjcl_qty', 'sjcl_tp', 'qtcl_qty', 'qtcl_tp', 'quantity', 'total_price',
-                'dgn_qty1', 'dgn_qty2',
-                'drawing_code', 'memo', 'node_type', 'is_tp',
-                'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp', 'postil',
-                'pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_gather_qty', 'pre_gather_tp',
-                'end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_gather_qty', 'end_gather_tp',
-                'final_tp', 'final_ratio',
-                'qc_bgl_code',
-                'chapter',
-            ]
-        });
-        reportDataAnalysis.analysisObj.gatherChapter.fun(ctx, data, [
-            {field: 'b_code', table: 'mem_stage_bills'},
-            {field: 'is_leaf', table: 'mem_stage_bills'},
-        ]);
-        const chapter100 = ctx.helper._.find(data.mem_stage_bills, {code: '100'});
-        assert(chapter100.total_price === 1045756);
-        const chapter200 = ctx.helper._.find(data.mem_stage_bills, {code: '200'});
-        assert(chapter200.total_price.toFixed(0) == 3813369);
-        assert(chapter200.contract_tp == 700.5);
-        const chapter400 = ctx.helper._.find(data.mem_stage_bills, {code: '400'});
-        assert(chapter400.total_price.toFixed(0) == 1231018);
-    });
-    it('test join', function* () {
-        const ctx = app.mockContext(mockData);
+        data = JSON.parse(JSON.stringify(orgData));
+        reportDataAnalysis.analysisObj.filter.fun(ctx, data, [], n2);
+        result = ctx.helper._.map(data.test, 'order');
+        assert(ctx.helper._.isEqual(result, [2]));
+
+        const n3 = {
+            table: 'test',
+            condition: [{ field: "b", type: "num", operate: '>', value: 1}]
+        };
+        data = JSON.parse(JSON.stringify(orgData));
+        reportDataAnalysis.analysisObj.filter.fun(ctx, data, [], n3);
+        result = ctx.helper._.map(data.test, 'order');
+        assert(ctx.helper._.isEqual(result, [3, 4, 8]));
+
+        const n4 = {
+            table: 'test',
+            condition: [{ field: "b", type: "num", operate: '>=', value: 1}]
+        };
+        data = JSON.parse(JSON.stringify(orgData));
+        reportDataAnalysis.analysisObj.filter.fun(ctx, data, [], n4);
+        result = ctx.helper._.map(data.test, 'order');
+        assert(ctx.helper._.isEqual(result, [2, 3, 4, 8]));
+
+        const n5 = {
+            table: 'test',
+            condition: [{ field: "b", type: "num", operate: '<', value: 1}]
+        };
+        data = JSON.parse(JSON.stringify(orgData));
+        reportDataAnalysis.analysisObj.filter.fun(ctx, data, [], n5);
+        result = ctx.helper._.map(data.test, 'order');
+        assert(ctx.helper._.isEqual(result, [1, 6, 7]));
+
+        const n6 = {
+            table: 'test',
+            condition: [{ field: "b", type: "num", operate: '<=', value: 1}]
+        };
+        data = JSON.parse(JSON.stringify(orgData));
+        reportDataAnalysis.analysisObj.filter.fun(ctx, data, [], n6);
+        result = ctx.helper._.map(data.test, 'order');
+        assert(ctx.helper._.isEqual(result, [1, 2, 6, 7]));
 
-        // test12 - 第6期
-        const stage = yield ctx.service.stage.getDataByCondition({tid: 12, order: 6});
-        const params = {
-            tender_id: stage.tid,
-            stage_id: stage.id,
+        // string
+        const s1 = {
+            table: 'test',
+            condition: [{ field: "a", type: "str", operate: '=', value: 'aaa'}]
         };
-        const filters = ['mem_stage_bills', 'deal_bills'];
-        const data = yield ctx.service.report.getReportData(params, filters, {
-            mem_stage_bills: [
-                'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
-                'code', 'b_code', 'name', 'unit', 'unit_price',
-                'deal_qty', 'deal_tp',
-                'sgfh_qty', 'sgfh_tp', 'sjcl_qty', 'sjcl_tp', 'qtcl_qty', 'qtcl_tp', 'quantity', 'total_price',
-                'dgn_qty1', 'dgn_qty2',
-                'drawing_code', 'memo', 'node_type', 'is_tp',
-                'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp', 'postil',
-                'pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_gather_qty', 'pre_gather_tp',
-                'end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_gather_qty', 'end_gather_tp',
-                'final_tp', 'final_ratio',
-                'qc_bgl_code',
-                'chapter',
+        data = JSON.parse(JSON.stringify(orgData));
+        reportDataAnalysis.analysisObj.filter.fun(ctx, data, [], s1);
+        result = ctx.helper._.map(data.test, 'order');
+        assert(ctx.helper._.isEqual(result, [1, 2, 3]));
+
+        const s2 = {
+            table: 'test',
+            condition: [{ field: "a", type: "str", operate: 'part', value: 'b'}]
+        };
+        data = JSON.parse(JSON.stringify(orgData));
+        reportDataAnalysis.analysisObj.filter.fun(ctx, data, [], s2);
+        result = ctx.helper._.map(data.test, 'order');
+        assert(ctx.helper._.isEqual(result, [4, 5]));
+
+        const s3 = {
+            table: 'test',
+            condition: [{ field: "a", type: "str", operate: 'enum', value: ['ccc', 'ddd']}]
+        };
+        data = JSON.parse(JSON.stringify(orgData));
+        reportDataAnalysis.analysisObj.filter.fun(ctx, data, [], s3);
+        result = ctx.helper._.map(data.test, 'order');
+        assert(ctx.helper._.isEqual(result, [6, 7, 8]));
+
+        // mix
+        const m1 = {
+            table: 'test',
+            condition: [
+                { field: "c", type: "bool", value: 'true'},
+                { field: "b", type: "num", operate: 'non-zero'},
+                { field: "a", type: "str", operate: 'enum', value: ['aaa', 'ddd']},
             ]
-        });
-        assert(data.mem_stage_bills.length === 216);
-        reportDataAnalysis.analysisObj.gatherGcl.fun(ctx, data, [
-            {field: 'b_code', table: 'mem_stage_bills'},
-            {field: 'name', table: 'mem_stage_bills'},
-            {field: 'unit', table: 'mem_stage_bills'},
-            {field: 'unit_price', table: 'mem_stage_bills'},
-            {field: 'is_leaf', table: 'mem_stage_bills'},
-        ]);
-        assert(data.mem_stage_bills.length === 43);
-        const joinOptions = {
-            main: 'mem_stage_bills',
-            sub: 'deal_bills',
-            keyFields: [
-                {main: 'b_code', sub: 'code', type: 'string'},
-                {main: 'name', sub: 'name',type: 'string'},
-                {main: 'unit', sub: 'unit',type: 'string'},
-                {main: 'unit_price', sub: 'unit_price',type: 'number'},
-            ],
-            importFields: [
-                {main: 'ex_value1', sub: 'quantity', type: 'number'},
-                {main: 'ex_value2', sub: 'total_price', type: 'number'}
-            ],
-            joinType: 'outer', //'outer', 'main', 'sub', 'inner'
         };
-        yield ctx.helper.saveBufferFile(JSON.stringify(joinOptions, '', '\t'), ctx.app.baseDir + '/analysis_join_options.json');
-        reportDataAnalysis.analysisObj.join.fun(ctx, data, [], joinOptions);
-        assert(data.mem_stage_bills.length === 132);
-        reportDataAnalysis.analysisObj.sortGcl.fun(ctx, data, [
-            {field: 'b_code', table: 'mem_stage_bills'},
-        ]);
-        const codeIndex = ctx.helper._.map(data.mem_stage_bills, 'b_code');
-        const codeIndex100 = ['101-1-b', '102-2', '102-3', '102-4', '102-5', '103-1', '103-2',
-            '103-3',  '103-3-a', '103-3-b', '103-4', '104-1', '123-1'];
-        const codeIndex200 = [
-            '203-1-a', '203-1-a', '203-1-b', '203-1-b', '203-1-d', '203-1-d', '204-1-b', '204-1-b',
-            '204-1-c', '204-1-d',
-            '204-1-g-4', '204-1-g-4', '204-1-j', '204-1-j', '205-1-o-1', '205-1-o-1', '206-2', '206-2',
-            '207-1-b',
-            '207-2-a', '207-2-a',
-            '207-2-b', '207-2-c', '207-3-a',
-            '207-4-a', '207-4-a',
-            '207-4-c', '207-10-a',
-            '208-1-a', '208-1-a', '208-3-a', '208-3-a',
-            '208-3-b',
-            '208-3-c', '208-3-c', '208-4-b-1', '208-4-b-1', '209-1-a', '209-1-a',
-            '209-3', '209-3-b', '215-12', '215-12-a'
-        ];
-        let codeResult = codeIndex100.concat(codeIndex200);
-        codeResult.forEach(function (a, i) {
-            assert(a === codeIndex[i]);
-        });
+        data = JSON.parse(JSON.stringify(orgData));
+        reportDataAnalysis.analysisObj.filter.fun(ctx, data, [], m1);
+        result = ctx.helper._.map(data.test, 'order');
+        assert(ctx.helper._.isEqual(result, [8]));
     });
     // it('test gatherChapter custom', function* () {
     //     const ctx = app.mockContext(mockData);
@@ -317,7 +449,7 @@ describe('test/app/service/report_memory.test.js', () => {
         const ctx = app.mockContext(mockData);
 
         const define = reportDataAnalysis.analysisDefine;
-        assert(define.length === 5);
+        assert(define.length === 7);
         assert(define[0].key === 'changeSort');
         assert(define[0].name === reportDataAnalysis.analysisObj.changeSort.name);
         assert(define[0].hint === reportDataAnalysis.analysisObj.changeSort.hint);