瀏覽代碼

Merge branch 'master' of http://192.168.1.41:3000/maixinrong/Calculation

TonyKang 5 年之前
父節點
當前提交
695f3695e1

+ 3 - 0
app/const/code_rule.js

@@ -22,6 +22,7 @@ ruleString[ruleType.change] = 'change';
 // 中间计量编号规则
 const measure = {
     ruleType: {
+        dealCode: 0,
         tenderName: 1,
         text: 2,
         inDate: 3,
@@ -35,6 +36,7 @@ const measure = {
     },
     connectorString: [],
 };
+measure.ruleString[measure.ruleType.dealCode] = '合同编号';
 measure.ruleString[measure.ruleType.tenderName] = '标段名称';
 measure.ruleString[measure.ruleType.text] = '文本';
 measure.ruleString[measure.ruleType.inDate] = '当前年份';
@@ -45,6 +47,7 @@ measure.connectorString[measure.connectorType.underscore] = '_';
 measure.connectorString[measure.connectorType.nothing] = '无';
 
 measure.defaultRule = [
+    { ruleType: measure.ruleType.dealCode },
     { ruleType: measure.ruleType.tenderName },
     { ruleType: measure.ruleType.text, text: 'WJQR1' },
     { ruleType: measure.ruleType.inDate },

+ 7 - 0
app/controller/change_controller.js

@@ -98,6 +98,9 @@ module.exports = app => {
             const codeRule = tender.c_rule ? JSON.parse(tender.c_rule) : [];
             for (const rule of codeRule) {
                 switch (rule.rule_type) {
+                    case codeRuleConst.measure.ruleType.dealCode:
+                        rule.preview = ctx.tender.info.deal_info.dealCode;
+                        break;
                     case codeRuleConst.measure.ruleType.tenderName:
                         rule.preview = tender.name;
                         break;
@@ -125,6 +128,7 @@ module.exports = app => {
                 filter,
                 status,
                 codeRule,
+                dealCode: ctx.tender.info.deal_info.dealCode,
                 auditConst: audit.flow,
                 changeConst,
                 ruleType: codeRuleConst.ruleType.change,
@@ -174,6 +178,9 @@ module.exports = app => {
                 const code = [];
                 for (const rule of cCodeRule) {
                     switch (rule.rule_type) {
+                        case codeRuleConst.measure.ruleType.dealCode:
+                            code.push(ctx.tender.info.deal_info.dealCode);
+                            break;
                         case codeRuleConst.measure.ruleType.tenderName:
                             code.push(tenderData.name);
                             break;

+ 20 - 0
app/extend/helper.js

@@ -417,6 +417,12 @@ module.exports = {
         return aCodes.length - bCodes.length;
     },
 
+    /**
+     * 根据 清单编号 获取 章级编号
+     * @param code
+     * @param symbol
+     * @returns {string}
+     */
     getChapterCode(code, symbol = '-') {
         if (!code || code === '') return '';
         const codePath = code.split(symbol);
@@ -726,6 +732,20 @@ module.exports = {
     },
 
     /**
+     * 替换字符串中的 换行符回车符为换行符<br>
+     * @param str
+     * @returns {*}
+     */
+    replaceRntoBr(str) {
+        // return str
+        //     ? (typeof str === 'string') ? str.replace(/[\r\n]/g, '') : str + ''
+        //     : str;
+        return (str && typeof str === 'string')
+            ? str.replace(/[\r\n]/g, '<br>')
+            : !_.isNil(str) ? str + '' : str;
+    },
+
+    /**
      * 获取 字符串 数组的 mysql 筛选条件
      *
      * @param arr

+ 108 - 1
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) {
@@ -414,6 +422,101 @@ const join = {
         }
     }
 };
+const getChapterCode = {
+    name: '获取章级编号',
+    intro: '根据清单编号,计算章级编号,并写入指定字段,适用于未提供chapter字段的数据,例如签约清单',
+    hint: '',
+    defaultSetting: {
+        table: 'mem_stage_bills',
+        b_code: 'b_code',
+        chapter: 'chapter',
+    },
+    fun: function (ctx, data, fields, options) {
+        if (!options || !options.table || !options.b_code || !options.chapter) return;
+
+        const cData = data[options.table];
+        if (!cData) return;
+
+        for (const d of cData) {
+            d[options.chapter] = ctx.helper.getChapterCode(d[options.b_code]);
+        }
+    }
+};
+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,
@@ -421,16 +524,20 @@ const analysisObj = {
     sortGcl,
     gatherChapter,
     join,
+    getChapterCode,
+    filter
 };
 const analysisDefine = (function (obj) {
     const result = [];
     for (const o in obj) {
         const analysis = obj[o];
-        if (analysis.name && analysis.hint && analysis.fun) {
+        if (analysis.name && analysis.fun) {
             result.push({
                 name: analysis.name,
                 key: o,
                 hint: analysis.hint,
+                intro: analysis.intro,
+                url: '/help?m=report&s=analysis&d=' + o,
             })
         }
     }

+ 10 - 2
app/public/js/change.js

@@ -21,7 +21,7 @@ class codeRuleSet {
         this.body = obj;
         // 切换规则组件类型
         $('.rule-change', obj).change(function () {
-            const codeType = this.selectedIndex;
+            const codeType = this.selectedIndex-1;
             if (codeType === ruleConst.ruleType.addNo) {
                 $('#format', obj).show();
                 $('#text', obj).show();
@@ -62,10 +62,18 @@ class codeRuleSet {
 
         // 新增规则组件
         $('#addRule', obj).click(function () {
-            const codeType = $('select', obj)[1].selectedIndex;
+            const codeType = $('select', obj)[1].selectedIndex-1;
             const rule = {rule_type: codeType}, html = [];
             let preview;
             switch (codeType) {
+                case ruleConst.ruleType.dealCode: {
+                    if ($('#dealCode').val() === '') {
+                        toastr.error('当前标段合同编号为空,请选择其他组件。');
+                        return false;
+                    }
+                    preview = $('#dealCode').val();
+                    break;
+                }
                 case ruleConst.ruleType.tenderName: {
                     preview = $('#tenderName').val();
                     break;

+ 9 - 5
app/public/js/change_set.js

@@ -560,7 +560,7 @@ $(document).ready(() => {
         judgeChange();
     });
     $('body').on('valuechange', '#change_form textarea', function (e, previous) {
-        changeInfo[$(this).attr('name')] = $(this).val();
+        changeInfo[$(this).attr('name')] = $(this).val().replace(/[\r\n]/g, '<br><br>');
         judgeChange();
     });
     $('body').on('change', '#change_form select', function (e, previous) {
@@ -626,6 +626,7 @@ function tableDataRemake(changeListData) {
 
 function changeFormRemake() {
     changeInfo = Object.assign({}, back_changeInfo);
+    console.log(changeInfo);
     $('#change_form input[name="code"]').val(changeInfo.code);
     $('#change_form input[name="name"]').val(changeInfo.name);
     $('#change_form input[name="peg"]').val(changeInfo.peg);
@@ -633,9 +634,10 @@ function changeFormRemake() {
     $('#change_form input[name="org_code"]').val(changeInfo.org_code);
     $('#change_form input[name="new_name"]').val(changeInfo.new_name);
     $('#change_form input[name="new_code"]').val(changeInfo.new_code);
-    $('#change_form textarea[name="content"]').val(changeInfo.content);
-    $('#change_form textarea[name="basis"]').val(changeInfo.basis);
-    $('#change_form textarea[name="memo"]').val(changeInfo.memo);
+    $('#change_form textarea[name="content"]').val(changeInfo.content.replace(/<br><br>/g, '\r\n'));
+    $('#change_form textarea[name="basis"]').val(changeInfo.basis.replace(/<br><br>/g, '\r\n'));
+    $('#change_form textarea[name="expr"]').val(changeInfo.expr.replace(/<br><br>/g, '\r\n'));
+    $('#change_form textarea[name="memo"]').val(changeInfo.memo.replace(/<br><br>/g, '\r\n'));
     $('#change_form select[name="type"]').val(changeInfo.type);
     $('#change_form select[name="class"]').val(changeInfo.class);
     $('#change_form select[name="quality"]').val(changeInfo.quality);
@@ -801,7 +803,9 @@ function maketablelist(status){
 
     $('#change-whitelist').val(radionWhiteList.join('^_^'));
 
-    table.destroy();
+    if (table) {
+        table.destroy();
+    }
     $('#list').html(html);
     table = $('#tablelist').removeAttr('width').DataTable({
         columnDefs: [

+ 11 - 2
app/service/report.js

@@ -21,6 +21,15 @@ module.exports = app => {
             super(ctx);
         }
 
+        async checkStg(ctx, params) {
+            if (ctx.stage === null || ctx.stage === undefined || parseInt(ctx.stage.id) !== parseInt(params.stage_id)) {
+                await ctx.service.stage.checkStage(params.stage_id);
+                if (ctx.stage) {
+                    params.stage_order = ctx.stage.curOrder;
+                }
+            }
+        }
+
         async getReportData(params, filters, memFieldKeys) {
             const service = this.ctx.service;
             const rst = {};
@@ -50,7 +59,7 @@ module.exports = app => {
                             runnableKey.push(filter);
                             break;
                         case 'stage_bills_final':
-                            await checkStg(this.ctx, params);
+                            await this.checkStg(this.ctx, params);
                             runnableRst.push(service.stageBillsFinal.getFinalDataEx(params.tender_id, params.stage_order));
                             runnableKey.push(filter);
                             break;
@@ -59,7 +68,7 @@ module.exports = app => {
                             runnableKey.push(filter);
                             break;
                         case 'stage_pay':
-                            await checkStg(this.ctx, params);
+                            await this.checkStg(this.ctx, params);
                             runnableRst.push(service.stagePay.getAuditorStageData(params.stage_id, params.stage_times, params.stage_order));
                             runnableKey.push(filter);
                             break;

+ 15 - 0
app/service/report_memory.js

@@ -509,6 +509,21 @@ module.exports = app => {
             //     'chapter',                                                                                              //1
             // ]);
         }
+
+        async getStagePayData(tid, sid, fields) {
+            await this.ctx.service.tender.checkTender(tid);
+            await this.ctx.service.stage.checkStage(sid);
+
+            const dealPay = await this.ctx.service.stagePay.getStagePays(this.ctx.stage);
+
+            if (!this.ctx.stage.readOnly && this.ctx.stage.check_calc) {
+                // 计算 本期金额
+                const PayCalculator = require('../lib/pay_calc');
+                const payCalculator = new PayCalculator(this.ctx, this.ctx.stage, this.ctx.tender.info);
+                await payCalculator.calculateAll(dealPay);
+            }
+            return dealPay;
+        }
     }
 
     return ReportMemory;

+ 1 - 0
app/view/change/index.ejs

@@ -25,6 +25,7 @@
     <div class="content-wrap">
         <div class="c-body">
             <input id="tenderName" value="<%= tender.name %>" type="hidden">
+            <input id="dealCode" value="<%= dealCode %>" type="hidden">
             <input id="tenderId" value="<%= tender.id %>" type="hidden">
             <div class="sjs-height-0">
                 <table class="table table-bordered">

+ 4 - 5
app/view/change/info.ejs

@@ -289,8 +289,6 @@
                 <!--保留旧数据回溯-->
                 <input type="hidden" id="back-change-list" value="<%= changeListData %>">
                 <input type="hidden" id="back-change-whitelist" value="<%= changeWhiteListData %>">
-                <!--<input type="hidden" id="change-info" value="">-->
-                <input type="hidden" id="back-change-info" value="<%= JSON.stringify(change) %>">
             </form>
             <% } else { %>
             <div class="row">
@@ -775,9 +773,10 @@
         org_code: '<%- change.org_code %>',
         new_name: '<%- change.new_name %>',
         new_code: '<%- change.new_code %>',
-        content: '<%- change.content %>',
-        basis: '<%- change.basis %>',
-        memo: '<%- change.memo %>',
+        content: '<%- ctx.helper.replaceRntoBr(change.content) %>',
+        basis: '<%- ctx.helper.replaceRntoBr(change.basis) %>',
+        expr: '<%- ctx.helper.replaceRntoBr(change.expr) %>',
+        memo: '<%- ctx.helper.replaceRntoBr(change.memo) %>',
         type: '<%- change.type %>',
         class: '<%- change.class %>',
         quality: '<%- change.quality %>',

+ 148 - 16
test/app/lib/rpt_data_analysis.test.js

@@ -264,6 +264,138 @@ describe('test/app/service/report_memory.test.js', () => {
             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;
+
+        // test boolean;
+        const b1 = {
+            table: 'test',
+            condition: [{ field: "c", type: "bool", value: 'false'}]
+        };
+        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]));
+
+        const b2 = {
+            table: 'test',
+            condition: [{ field: "c", type: "bool", value: 'true'}]
+        };
+        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]));
+
+        // test number
+        const n1 = {
+            table: 'test',
+            condition: [{ field: "b", type: "num", operate: 'non-zero'}]
+        };
+        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]));
+
+        const n2 = {
+            table: 'test',
+            condition: [{ field: "b", type: "num", operate: '=', value: 1}]
+        };
+        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]));
+
+        // string
+        const s1 = {
+            table: 'test',
+            condition: [{ field: "a", type: "str", operate: '=', value: 'aaa'}]
+        };
+        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']},
+            ]
+        };
+        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);
@@ -328,20 +460,20 @@ describe('test/app/service/report_memory.test.js', () => {
         assert(define[2].name === reportDataAnalysis.analysisObj.sortGcl.name);
         assert(define[2].hint === reportDataAnalysis.analysisObj.sortGcl.hint);
 
-        const x = {
-            count: 7,
-            gclSum: {
-                name: '第100章至700章清单合计',
-                order: 1,
-            },
-            custom: [
-                {name: '已包含在清单合计中的材料、工程设备、专业工程暂估价', order: 2},
-                {name: '清单合计减去材料、工程设备、专业工程暂估价(即8-9=10)', order_calc: 'o1-o2', order: 3},
-                {name: '计日工合计', node_type: '计日工', order: 4},
-                {name: '暂列金额(不含计日工总额)(即10×暂列金额比列)', node_type: '暂列金额', order: 5},
-                {name: '投标报价、台账价(8+11+12)=13', order_calc: 'o1+o4+o5', order: 6},
-            ],
-        };
-        ctx.helper.saveBufferFile(JSON.stringify(x, "", "\t"), ctx.app.baseDir + '/mem_stage_pos.json');
+        // const x = {
+        //     count: 7,
+        //     gclSum: {
+        //         name: '第100章至700章清单合计',
+        //         order: 1,
+        //     },
+        //     custom: [
+        //         {name: '已包含在清单合计中的材料、工程设备、专业工程暂估价', order: 2},
+        //         {name: '清单合计减去材料、工程设备、专业工程暂估价(即8-9=10)', order_calc: 'o1-o2', order: 3},
+        //         {name: '计日工合计', node_type: '计日工', order: 4},
+        //         {name: '暂列金额(不含计日工总额)(即10×暂列金额比列)', node_type: '暂列金额', order: 5},
+        //         {name: '投标报价、台账价(8+11+12)=13', order_calc: 'o1+o4+o5', order: 6},
+        //     ],
+        // };
+        // ctx.helper.saveBufferFile(JSON.stringify(x, "", "\t"), ctx.app.baseDir + '/mem_stage_pos.json');
     });
 });

+ 29 - 0
test/app/service/report_memory.test.js

@@ -292,4 +292,33 @@ describe('test/app/service/report_memory.test.js', () => {
             yield saveTableDefine(ctx, tableDefine, ctx.app.baseDir + '/mem_stage_bills_compare_define.json');
         }
     });
+    it('test getStagePay', function* () {
+        const ctx = app.mockContext(mockData);
+        // test12 - 第4期
+        const stage = yield ctx.service.stage.getDataByCondition({tid: 12, order: 6});
+        const data = yield ctx.service.reportMemory.getStagePayData(stage.tid, stage.id, []);
+        if (data instanceof Array) {
+            yield ctx.helper.saveBufferFile(JSON.stringify(data, '', '\t'), ctx.app.baseDir + '/mem_stage_pay.json');
+
+            const tableDefine = {};
+            tableDefine.Name = '期-合同支付-数据(mem_stage_pay)';
+            tableDefine.remark = '';
+            tableDefine.ID = 27;
+            tableDefine.key = 'mem_stage_pay';
+            tableDefine.items = [];
+            const prefix = '期-合同支付-';
+
+            addFields(tableDefine, prefix + '名称', 'name', dataType.str);
+            addFields(tableDefine, prefix + '计算公式', 'expr', dataType.str);
+            addFields(tableDefine, prefix + '金额', 'tp', dataType.currency);
+            addFields(tableDefine, prefix + '截止上期-金额', 'pre_tp', dataType.currency);
+            addFields(tableDefine, prefix + '截止本期-金额', 'end_tp', dataType.currency);
+            addFields(tableDefine, prefix + '排序', 'order', dataType.int);
+            addFields(tableDefine, prefix + '是否扣款项', 'minus', dataType.int);
+            addFields(tableDefine, prefix + '支付类型', 'ptype', dataType.int);
+            addFields(tableDefine, prefix + '起扣金额', 'sprice', dataType.currency);
+            addFields(tableDefine, prefix + '扣款限额', 'rprice', dataType.currency);
+            yield saveTableDefine(ctx, tableDefine, ctx.app.baseDir + '/mem_stage_pay_define.json');
+        }
+    });
 });