Bläddra i källkod

1. 转存初始化结构以及必要数据sql
2. 独立测试数据库,单元测试连接测试数据库,排除其他数据干扰
3. 完善单元测试
4. 单价、金额等计算根据小数位数舍入,存储数据库

MaiXinRong 6 år sedan
förälder
incheckning
01968dfe3c

+ 1 - 1
app/base/base_service.js

@@ -194,7 +194,7 @@ class BaseService extends Service {
     }
 
     round(value, decimal) {
-        return this.ctx.helper.round(value, decimal ? decimal : 8);
+        return this.ctx.helper.round(value, this._.isNumber(decimal) ? decimal : 8);
     }
 }
 module.exports = BaseService;

+ 6 - 6
app/controller/ledger_controller.js

@@ -66,13 +66,13 @@ module.exports = app => {
                 });
                 col.formatter = formatter;
             }
-            const tpFormatter = this.ctx.helper.getNumberFormatter(this.ctx.tender.info.decimal.tp);
-            const upFormatter = this.ctx.helper.getNumberFormatter(this.ctx.tender.info.decimal.up);
+            // const tpFormatter = this.ctx.helper.getNumberFormatter(this.ctx.tender.info.decimal.tp);
+            // const upFormatter = this.ctx.helper.getNumberFormatter(this.ctx.tender.info.decimal.up);
             const ledger = JSON.parse(JSON.stringify(spreadConst.ledgerSpread));
-            setColFormat(ledger.cols, 'unit_price', upFormatter);
-            setColFormat(ledger.cols, 'dgn_price', upFormatter);
-            setColFormat(ledger.cols, 'total_price', tpFormatter);
-            setColFormat(ledger.cols, 'deal_tp', tpFormatter);
+            // setColFormat(ledger.cols, 'unit_price', upFormatter);
+            // setColFormat(ledger.cols, 'dgn_price', upFormatter);
+            // setColFormat(ledger.cols, 'total_price', tpFormatter);
+            // setColFormat(ledger.cols, 'deal_tp', tpFormatter);
             const pos = JSON.parse(JSON.stringify(spreadConst.ledgerPosSpread));
 
             const tender = this.ctx.tender;

+ 12 - 12
app/controller/stage_controller.js

@@ -86,12 +86,12 @@ module.exports = app => {
                     col.formatter = formatter;
                 }
             }
-            const tpFormatter = this.ctx.helper.getNumberFormatter(this.ctx.tender.info.decimal.tp);
-            const upFormatter = this.ctx.helper.getNumberFormatter(2);
+            // const tpFormatter = this.ctx.helper.getNumberFormatter(this.ctx.tender.info.decimal.tp);
+            // const upFormatter = this.ctx.helper.getNumberFormatter(2);
             const ledger = JSON.parse(JSON.stringify(spreadConst.stage.ledger));
-            setColFormat(ledger.cols, 'unit_price', upFormatter);
-            setColFormat(ledger.cols, 'total_price', tpFormatter);
-            setColFormat(ledger.cols, 'tp', tpFormatter);
+            // setColFormat(ledger.cols, 'unit_price', upFormatter);
+            // setColFormat(ledger.cols, 'total_price', tpFormatter);
+            // setColFormat(ledger.cols, 'tp', tpFormatter);
             const pos = JSON.parse(JSON.stringify(spreadConst.stage.pos));
             const tender = this.ctx.tender, stage = this.ctx.stage;
             if (this._stageReadOnly(stage)) {
@@ -498,14 +498,14 @@ module.exports = app => {
             function assignStageData(chapter, curStage, preStage) {
                 chapter.contract_tp = curStage.contract_tp;
                 chapter.qc_tp = curStage.qc_tp;
-                chapter.gather_tp = _.add(curStage.contract_tp, curStage.qc_tp);
+                chapter.gather_tp = ctx.helper.plus(curStage.contract_tp, curStage.qc_tp);
                 if (preStage) {
                     chapter.pre_contract_tp = preStage.contract_tp;
                     chapter.pre_qc_tp = preStage.qc_tp;
-                    chapter.pre_gather_tp = _.add(preStage.contract_tp, preStage.qc_tp);
-                    chapter.end_contract_tp = _.add(curStage.contract_tp, preStage.contract_tp);
-                    chapter.end_qc_tp = _.add(curStage.qc_tp, preStage.qc_tp);
-                    chapter.end_gather_tp = _.add(chapter.gather_tp, chapter.pre_gather_tp);
+                    chapter.pre_gather_tp = ctx.helper.plus(preStage.contract_tp, preStage.qc_tp);
+                    chapter.end_contract_tp = ctx.helper.plus(curStage.contract_tp, preStage.contract_tp);
+                    chapter.end_qc_tp = ctx.helper.plus(curStage.qc_tp, preStage.qc_tp);
+                    chapter.end_gather_tp = ctx.helper.plus(chapter.gather_tp, chapter.pre_gather_tp);
                 } else {
                     chapter.end_contract_tp = curStage.contract_tp;
                     chapter.end_qc_tp = curStage.qc_tp;
@@ -529,7 +529,7 @@ module.exports = app => {
                             const sum = _.find(calcDetail, {cType: 11});
                             const chapters = _.filter(calcDetail, {cType: 1});
                             for (const f of fields) {
-                                cd[f] = _.subtract(sum[f], _.sumBy(chapters, f));
+                                cd[f] = ctx.helper.minus(sum[f], this.ctx.helper.sum(_.map(chapters, f)));//_.sumBy(chapters, f));
                             }
                             break;
                         case 31:
@@ -539,7 +539,7 @@ module.exports = app => {
                             const sum1 = _.find(calcDetail, {cType: 11});
                             const sum2 = _.find(calcDetail, {cType: 31});
                             for (const f of fields) {
-                                cd[f] = _.add(sum1.value, sum2.value);
+                                cd[f] = ctx.helper.plus(sum1.value, sum2.value);
                             }
                             break;
                     }

+ 12 - 0
app/extend/helper.js

@@ -643,4 +643,16 @@ module.exports = {
     round(value, decimal) {
         return value ? np.round(value, decimal) : null;
     },
+    /**
+     * 汇总
+     * @param array
+     * @returns {number}
+     */
+    sum(array) {
+        let result = 0;
+        for (const a of array) {
+            result = this.plus(result, a);
+        }
+        return result;
+    }
 };

+ 10 - 7
app/lib/analysis_excel.js

@@ -14,7 +14,8 @@ class ImportBaseTree {
      * 构造函数
      * @param {Array} tempData - 清单模板数据
      */
-    constructor (tempData) {
+    constructor (tempData, ctx) {
+        this.ctx = ctx;
         // 常量
         this.splitChar = '-';
         // 索引
@@ -197,9 +198,10 @@ class ImportBaseTree {
         for (const node of this.items) {
             if (node.children && node.children.length > 0) { continue; }
             if (!node.pos || node.pos.length === 0) { continue; }
-            node.quantity = _.round(_.sum(_.map(node.pos, 'quantity')), 6);
+            node.quantity = this.ctx.helper.sum(_.map(node.pos, 'quantity'));
             if (node.quantity && node.unit_price) {
-                node.total_price = _.round(node.quantity * node.unit_price, 6);
+                node.total_price = this.ctx.helper.round(this.ctx.helper.times(node.quantity, node.unit_price),
+                    this.ctx.tender.info.decimal.tp);
             } else {
                 node.total_price = null;
             }
@@ -211,7 +213,8 @@ class AnalysisExcelTree {
     /**
      * 构造函数
      */
-    constructor() {
+    constructor(ctx) {
+        this.ctx = ctx;
         this.colsDef = null;
         this.colHeaderMatch = {
             code: ['项目节编号', '预算项目节'],
@@ -251,7 +254,7 @@ class AnalysisExcelTree {
         node.drawing_code = row[this.colsDef.drawing_code];
         node.memo = row[this.colsDef.memo];
         if (node.quantity && node.unit_price) {
-            node.total_price = _.round(node.quantity * node.unit_price, 6);
+            node.total_price = this.ctx.helper.round(this.ctx.helper.times(node.quantity, node.unit_price), this.ctx.tender.info.decimal.tp);
         } else {
             node.total_price = null;
         }
@@ -273,7 +276,7 @@ class AnalysisExcelTree {
         node.drawing_code = row[this.colsDef.drawing_code];
         node.memo = row[this.colsDef.memo];
         if (node.quantity && node.unit_price) {
-            node.total_price = _.round(node.quantity * node.unit_price, 6);
+            node.total_price = this.ctx.helper.round(this.ctx.helper.times(node.quantity, node.unit_price), this.ctx.tender.info.decimal.tp);
         } else {
             node.total_price = null;
         }
@@ -350,7 +353,7 @@ class AnalysisExcelTree {
      */
     analysisData(sheet, tempData) {
         this.colsDef = null;
-        this.cacheTree = new ImportBaseTree(tempData);
+        this.cacheTree = new ImportBaseTree(tempData, this.ctx);
         this.errorData = [];
         this.loadEnd = false;
 

+ 11 - 27
app/public/js/gcl_gather.js

@@ -28,20 +28,16 @@ const gclGatherModel = (function () {
     gsTreeSetting.calcFields = ['deal_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp'];
     gsTreeSetting.calcFun = function (node) {
         if (node.children && node.children.length === 0) {
-            node.gather_qty = _.add(node.contract_qty, node.qc_qty);
-            node.end_contract_qty = _.add(node.pre_contract_qty, node.contract_qty);
-            node.end_qc_qty = _.add(node.pre_qc_qty, node.qc_qty);
-            node.end_gather_qty = _.add(node.pre_gather_qty, node.gather_qty);
-        }
-        node.gather_tp = _.add(node.contract_tp, node.qc_tp);
-        node.end_contract_tp = _.add(node.pre_contract_tp, node.contract_tp);
-        node.end_qc_tp = _.add(node.pre_qc_tp, node.qc_tp);
-        node.end_gather_tp = _.add(node.pre_gather_tp, node.gather_tp);
-        if (checkZero(node.dgn_qty1)) {
-            node.dgn_price = _.round(node.total_price/node.dgn_qty1, 2);
-        } else {
-            node.dgn_price = null;
+            node.gather_qty = ZhCalc.plus(node.contract_qty, node.qc_qty);
+            node.end_contract_qty = ZhCalc.plus(node.pre_contract_qty, node.contract_qty);
+            node.end_qc_qty = ZhCalc.plus(node.pre_qc_qty, node.qc_qty);
+            node.end_gather_qty = ZhCalc.plus(node.pre_gather_qty, node.gather_qty);
         }
+        node.gather_tp = ZhCalc.plus(node.contract_tp, node.qc_tp);
+        node.end_contract_tp = ZhCalc.plus(node.pre_contract_tp, node.contract_tp);
+        node.end_qc_tp = ZhCalc.plus(node.pre_qc_tp, node.qc_tp);
+        node.end_gather_tp = ZhCalc.plus(node.pre_gather_tp, node.gather_tp);
+        node.dgn_price = ZhCalc.round(ZhCalc.divide(node.total_price, node.dgn_qty1), 2);
     };
     const gsTree = createNewPathTree('stage', gsTreeSetting);
     // 初始化 部位明细
@@ -50,7 +46,7 @@ const gclGatherModel = (function () {
         updateFields: ['contract_qty', 'qc_qty'],
     };
     posSetting.calcFun = function (pos) {
-        pos.gather_qty = _.add(pos.contract_qty, pos.qc_qty);
+        pos.gather_qty = ZhCalc.plus(pos.contract_qty, pos.qc_qty);
     };
     const gsPos = new StagePosData(posSetting);
 
@@ -83,22 +79,10 @@ const gclGatherModel = (function () {
         gsPos.loadPreStageData(prePos);
     }
 
-    function addNumber(a, b) {
-        if (b) {
-            if (a) {
-                return a + b;
-            } else {
-                return b;
-            }
-        } else {
-            return a;
-        }
-    }
-
     function gatherfields(obj, src, fields) {
         if (obj && src) {
             for (const f of fields) {
-                obj[f] = addNumber(obj[f], src[f]);
+                obj[f] = ZhCalc.plus(obj[f], src[f]);
             }
         }
     }

+ 60 - 0
app/public/js/global.js

@@ -301,3 +301,63 @@ function removeLocalCache(key) {
     }
     return storage.removeItem(key);
 }
+
+/**
+ * 计算(四则、舍入) 统一,方便以后置换
+ * @type {{plus, minus, times, divide, round}}
+ */
+const ZhCalc = (function () {
+    // 关闭边界检查
+    NP.enableBoundaryChecking(false);
+
+    /**
+     * 加法 num1 + num2
+     * @param num1
+     * @param num2
+     * @returns {number}
+     */
+    function plus(num1, num2) {
+        return NP.plus(num1 ? num1 : 0, num2 ? num2: 0);
+    };
+    /**
+     * 减法 num1 - num2
+     * @param num1
+     * @param num2
+     * @returns {number}
+     */
+    function minus(num1, num2) {
+        return NP.minus(num1 ? num1 : 0, num2 ? num2 : 0);
+    };
+    /**
+     * 乘法 num1 * num2
+     * @param num1
+     * @param num2
+     * @returns {*}
+     */
+    function times(num1, num2) {
+        return NP.times(num1 ? num1 : 0, num2 ? num2 : 0);
+    };
+    /**
+     * 除法 num1 / num2
+     * @param num1 - 被除数
+     * @param num2 - 除数
+     * @returns {*}
+     */
+    function divide(num1, num2) {
+        if (num2 && !checkZero(num2)) {
+            return NP.divide(num1 ? num1: 0, num2);
+        } else {
+            return null;
+        }
+    };
+    /**
+     * 四舍五入
+     * @param {Number} value - 舍入的数字
+     * @param {Number} decimal - 要保留的小数位数
+     * @returns {*}
+     */
+    function round(value, decimal) {
+        return value ? NP.round(value, decimal) : null;
+    };
+    return {plus, minus, times, divide, round}
+})();

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

@@ -33,11 +33,7 @@ $(document).ready(function() {
         treeSetting.calcFields = ['deal_tp', 'total_price'];
     }
     treeSetting.calcFun = function (node) {
-        if (!checkZero(node.dgn_qty1)) {
-            node.dgn_price = _.round(node.total_price/node.dgn_qty1, 6);
-        } else {
-            node.dgn_price = null;
-        }
+        node.dgn_price = ZhCalc.round(ZhCalc.divide(node.total_price, node.dgn_qty1), 2);
     };
     const ledgerTree = createNewPathTree('ledger', treeSetting);
     ledgerTree.loadDatas(ledger);

+ 142 - 0
app/public/js/number-precision.js

@@ -0,0 +1,142 @@
+var NP = (function (exports) {
+    'use strict';
+
+    /**
+     * @desc 解决浮动运算问题,避免小数点后产生多位数和计算精度损失。
+     * 问题示例:2.3 + 2.4 = 4.699999999999999,1.0 - 0.9 = 0.09999999999999998
+     */
+    /**
+     * 把错误的数据转正
+     * strip(0.09999999999999998)=0.1
+     */
+    function strip(num, precision) {
+        if (precision === void 0) { precision = 12; }
+        return +parseFloat(num.toPrecision(precision));
+    }
+    /**
+     * Return digits length of a number
+     * @param {*number} num Input number
+     */
+    function digitLength(num) {
+        // Get digit length of e
+        var eSplit = num.toString().split(/[eE]/);
+        var len = (eSplit[0].split('.')[1] || '').length - (+(eSplit[1] || 0));
+        return len > 0 ? len : 0;
+    }
+    /**
+     * 把小数转成整数,支持科学计数法。如果是小数则放大成整数
+     * @param {*number} num 输入数
+     */
+    function float2Fixed(num) {
+        if (num.toString().indexOf('e') === -1) {
+            return Number(num.toString().replace('.', ''));
+        }
+        var dLen = digitLength(num);
+        return dLen > 0 ? strip(num * Math.pow(10, dLen)) : num;
+    }
+    /**
+     * 检测数字是否越界,如果越界给出提示
+     * @param {*number} num 输入数
+     */
+    function checkBoundary(num) {
+        if (_boundaryCheckingState) {
+            if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
+                console.warn(num + " is beyond boundary when transfer to integer, the results may not be accurate");
+            }
+        }
+    }
+    /**
+     * 精确乘法
+     */
+    function times(num1, num2) {
+        var others = [];
+        for (var _i = 2; _i < arguments.length; _i++) {
+            others[_i - 2] = arguments[_i];
+        }
+        if (others.length > 0) {
+            return times.apply(void 0, [times(num1, num2), others[0]].concat(others.slice(1)));
+        }
+        var num1Changed = float2Fixed(num1);
+        var num2Changed = float2Fixed(num2);
+        var baseNum = digitLength(num1) + digitLength(num2);
+        var leftValue = num1Changed * num2Changed;
+        checkBoundary(leftValue);
+        return leftValue / Math.pow(10, baseNum);
+    }
+    /**
+     * 精确加法
+     */
+    function plus(num1, num2) {
+        var others = [];
+        for (var _i = 2; _i < arguments.length; _i++) {
+            others[_i - 2] = arguments[_i];
+        }
+        if (others.length > 0) {
+            return plus.apply(void 0, [plus(num1, num2), others[0]].concat(others.slice(1)));
+        }
+        var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
+        return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
+    }
+    /**
+     * 精确减法
+     */
+    function minus(num1, num2) {
+        var others = [];
+        for (var _i = 2; _i < arguments.length; _i++) {
+            others[_i - 2] = arguments[_i];
+        }
+        if (others.length > 0) {
+            return minus.apply(void 0, [minus(num1, num2), others[0]].concat(others.slice(1)));
+        }
+        var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
+        return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
+    }
+    /**
+     * 精确除法
+     */
+    function divide(num1, num2) {
+        var others = [];
+        for (var _i = 2; _i < arguments.length; _i++) {
+            others[_i - 2] = arguments[_i];
+        }
+        if (others.length > 0) {
+            return divide.apply(void 0, [divide(num1, num2), others[0]].concat(others.slice(1)));
+        }
+        var num1Changed = float2Fixed(num1);
+        var num2Changed = float2Fixed(num2);
+        checkBoundary(num1Changed);
+        checkBoundary(num2Changed);
+        return times((num1Changed / num2Changed), Math.pow(10, digitLength(num2) - digitLength(num1)));
+    }
+    /**
+     * 四舍五入
+     */
+    function round(num, ratio) {
+        var base = Math.pow(10, ratio);
+        return divide(Math.round(times(num, base)), base);
+    }
+    var _boundaryCheckingState = true;
+    /**
+     * 是否进行边界检查,默认开启
+     * @param flag 标记开关,true 为开启,false 为关闭,默认为 true
+     */
+    function enableBoundaryChecking(flag) {
+        if (flag === void 0) { flag = true; }
+        _boundaryCheckingState = flag;
+    }
+    var index = { strip: strip, plus: plus, minus: minus, times: times, divide: divide, round: round, digitLength: digitLength, float2Fixed: float2Fixed, enableBoundaryChecking: enableBoundaryChecking };
+
+    exports.strip = strip;
+    exports.plus = plus;
+    exports.minus = minus;
+    exports.times = times;
+    exports.divide = divide;
+    exports.round = round;
+    exports.digitLength = digitLength;
+    exports.float2Fixed = float2Fixed;
+    exports.enableBoundaryChecking = enableBoundaryChecking;
+    exports['default'] = index;
+
+    return exports;
+
+}({}));

+ 1 - 10
app/public/js/path_tree.js

@@ -1184,22 +1184,13 @@ const treeCalc = {
         if (node.children && node.children.length > 0) {
             const gather = node.children.reduce(function (rst, x) {
                 const result = {};
-                const fieldCalc = function (field) {
-                    if (rst[field]) {
-                        result[field] = x[field] ? _.round(rst[field] + x[field], 6) : rst[field];
-                    } else {
-                        result[field] = x[field] ? x[field] : undefined;
-                    }
-                };
                 for (const cf of tree.setting.calcFields) {
-                    result[cf] = _.round(_.add(rst[cf], x[cf]), 8);
-                    //fieldCalc(cf);
+                    result[cf] = ZhCalc.plus(rst[cf], x[cf]);
                 }
                 return result;
             });
             // 汇总子项
             for (const cf of tree.setting.calcFields) {
-                //node[cf] = _.sumBy(node.children, cf);
                 if (gather[cf]) {
                     node[cf] = gather[cf];
                 } else {

+ 18 - 22
app/public/js/stage.js

@@ -102,22 +102,18 @@ $(document).ready(() => {
         'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp'];
     stageTreeSetting.calcFun = function (node) {
         if (node.children && node.children.length === 0) {
-            node.pre_gather_qty = _.add(node.pre_contract_qty, node.pre_qc_qty);
-            node.gather_qty = _.add(node.contract_qty, node.qc_qty);
-            node.end_contract_qty = _.add(node.pre_contract_qty, node.contract_qty);
-            node.end_qc_qty = _.add(node.pre_qc_qty, node.qc_qty);
-            node.end_gather_qty = _.add(node.pre_gather_qty, node.gather_qty);
-        }
-        node.pre_gather_tp = _.add(node.pre_contract_tp, node.pre_qc_tp);
-        node.gather_tp = _.add(node.contract_tp, node.qc_tp);
-        node.end_contract_tp = _.add(node.pre_contract_tp, node.contract_tp);
-        node.end_qc_tp = _.add(node.pre_qc_tp, node.qc_tp);
-        node.end_gather_tp = _.add(node.pre_gather_tp, node.gather_tp);
-        if (checkZero(node.dgn_qty1)) {
-            node.dgn_price = _.round(node.total_price/node.dgn_qty1, 2);
-        } else {
-            node.dgn_price = null;
+            node.pre_gather_qty = ZhCalc.plus(node.pre_contract_qty, node.pre_qc_qty);
+            node.gather_qty = ZhCalc.plus(node.contract_qty, node.qc_qty);
+            node.end_contract_qty = ZhCalc.plus(node.pre_contract_qty, node.contract_qty);
+            node.end_qc_qty = ZhCalc.plus(node.pre_qc_qty, node.qc_qty);
+            node.end_gather_qty = ZhCalc.plus(node.pre_gather_qty, node.gather_qty);
         }
+        node.pre_gather_tp = ZhCalc.plus(node.pre_contract_tp, node.pre_qc_tp);
+        node.gather_tp = ZhCalc.plus(node.contract_tp, node.qc_tp);
+        node.end_contract_tp = ZhCalc.plus(node.pre_contract_tp, node.contract_tp);
+        node.end_qc_tp = ZhCalc.plus(node.pre_qc_tp, node.qc_tp);
+        node.end_gather_tp = ZhCalc.plus(node.pre_gather_tp, node.gather_tp);
+        node.dgn_price = ZhCalc.round(ZhCalc.divide(node.total_price, node.dgn_qty1), tenderInfo.decimal.up);
     };
     const stageTree = createNewPathTree('stage', stageTreeSetting);
     // 初始化 部位明细 数据结构
@@ -126,11 +122,11 @@ $(document).ready(() => {
         updateFields: ['contract_qty', 'qc_qty', 'postil'],
     };
     stagePosSetting.calcFun = function (pos) {
-        pos.pre_gather_qty = _.add(pos.pre_contract_qty, pos.pre_qc_qty);
-        pos.gather_qty = _.add(pos.contract_qty, pos.qc_qty);
-        pos.end_contract_qty = _.add(pos.pre_contract_qty, pos.contract_qty);
-        pos.end_qc_qty = _.add(pos.pre_qc_qty, pos.qc_qty);
-        pos.end_gather_qty = _.add(pos.pre_gather_qty, pos.gather_qty);
+        pos.pre_gather_qty = ZhCalc.plus(pos.pre_contract_qty, pos.pre_qc_qty);
+        pos.gather_qty = ZhCalc.plus(pos.contract_qty, pos.qc_qty);
+        pos.end_contract_qty = ZhCalc.plus(pos.pre_contract_qty, pos.contract_qty);
+        pos.end_qc_qty = ZhCalc.plus(pos.pre_qc_qty, pos.qc_qty);
+        pos.end_gather_qty = ZhCalc.plus(pos.pre_gather_qty, pos.gather_qty);
     };
     const stagePos = new StagePosData(stagePosSetting);
 
@@ -278,11 +274,11 @@ $(document).ready(() => {
         _calculateAmount() {
             for (const c of this.changes) {
                 c.bamount = _.toNumber(c.b_amount);
-                c.vamount = _.round(_.subtract(c.bamount, c.used_amount), 6);
+                c.vamount = ZhCalc.minus(c.bamount, c.used_amount);
                 const uc = _.find(this.useChanges, {cid: c.cid, cbid: c.cbid});
                 if (uc) {
                     c.uamount = uc.qty;
-                    c.vamount = _.round(_.add(c.vamount, c.uamount), 6);
+                    c.vamount = ZhCalc.plus(c.vamount, c.uamount);
                 }
             }
         }

+ 2 - 2
app/public/js/stage_change.js

@@ -39,7 +39,7 @@ class ChangeAnalysis {
         change.bills = change.detail.addUsedBills;
         for (const b of change.bills) {
             b.qty = _.toNumber(b.samount);
-            b.valid_qty = _.round(_.subtract(b.qty - b.used_qty), 6);
+            b.valid_qty = ZhCalc.minus(b.qty - b.used_qty);
             b.pos = _.filter(change.detail.curUsedBills, {cbid: b.id});
             b.cur_qty = 0;
             for (const p of b.pos) {
@@ -50,7 +50,7 @@ class ChangeAnalysis {
                     p.leaf_xmj_code = leafXmj.code;
                     p.leaf_xmj_name = leafXmj.name;
                 }
-                b.cur_qty = _.round(_.add(b.cur_qty, p.qty), 6);
+                b.cur_qty = ZhCalc.plus(b.cur_qty, p.qty);
             }
 
         }

+ 5 - 5
app/public/js/stage_compare.js

@@ -33,14 +33,14 @@ $(document).ready(function () {
 
     function calculateStageLedgerData(datas) {
         for (const d of datas) {
-            d.gather_qty = _.add(d.contract_qty, d.qc_qty);
-            d.gather_tp = _.add(d.contract_tp, d.qc_tp);
+            d.gather_qty = ZhCalc.plus(d.contract_qty, d.qc_qty);
+            d.gather_tp = ZhCalc.plus(d.contract_tp, d.qc_tp);
         }
     }
     function calculateStagePosData(datas) {
         for (const d of datas) {
-            d.gather_qty = _.add(d.contract_qty, d.qc_qty);
-            d.gather_tp = _.add(d.contract_tp, d.qc_tp);
+            d.gather_qty = ZhCalc.plus(d.contract_qty, d.qc_qty);
+            d.gather_tp = ZhCalc.plus(d.contract_tp, d.qc_tp);
         }
     }
 
@@ -86,7 +86,7 @@ $(document).ready(function () {
         updateFields: ['contract_qty', 'qc_qty'],
     };
     scPosSetting.calcFun = function (pos) {
-        pos.gather_qty = _.add(pos.contract_qty, pos.qc_qty);
+        pos.gather_qty = ZhCalc.plus(pos.contract_qty, pos.qc_qty);
     };
     const scPos = new MasterPosData(scPosSetting);
     scPos.loadDatas(pos);

+ 18 - 21
app/public/js/stage_im.js

@@ -24,20 +24,17 @@ const stageIm = (function () {
     gsTreeSetting.calcFields = ['deal_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp'];
     gsTreeSetting.calcFun = function (node) {
         if (node.children && node.children.length === 0) {
-            node.gather_qty = _.toNumber(node.contract_qty) + _.toNumber(node.qc_qty);
-            node.end_contract_qty = _.toNumber(node.pre_contract_qty) + _.toNumber(node.contract_qty);
-            node.end_qc_qty = _.toNumber(node.pre_qc_qty) + _.toNumber(node.qc_qty);
-            node.end_gather_qty = _.toNumber(node.pre_gather_qty) + _.toNumber(node.gather_qty);
-        }
-        node.gather_tp = _.toNumber(node.contract_tp) + _.toNumber(node.qc_tp);
-        node.end_contract_tp = _.toNumber(node.pre_contract_tp) + _.toNumber(node.contract_tp);
-        node.end_qc_tp = _.toNumber(node.pre_qc_tp) + _.toNumber(node.qc_tp);
-        node.end_gather_tp = _.toNumber(node.pre_gather_tp) + _.toNumber(node.gather_tp);
-        if (checkZero(node.dgn_qty1)) {
-            node.dgn_price = _.round(node.total_price/node.dgn_qty1, 2);
-        } else {
-            node.dgn_price = null;
+            node.pre_gather_qty = ZhCalc.plus(node.pre_contract_qty, node.pre_qc_qty);
+            node.gather_qty = _ZhCalc.plus(node.contract_qty, node.qc_qty);
+            node.end_contract_qty = ZhCalc.plus(node.pre_contract_qty, node.contract_qty);
+            node.end_qc_qty = ZhCalc.plus(node.pre_qc_qty, node.qc_qty);
+            node.end_gather_qty = ZhCalc.plus(node.pre_gather_qty, node.gather_qty);
         }
+        node.pre_gather_tp = ZhCalc.plus(node.pre_contract_tp, node.pre_qc_tp);
+        node.gather_tp = ZhCalc.plus(node.contract_tp, node.qc_tp);
+        node.end_contract_tp = ZhCalc.plus(node.pre_contract_tp, node.contract_tp);
+        node.end_qc_tp = ZhCalc.plus(node.pre_qc_tp, node.qc_tp);
+        node.end_gather_tp = ZhCalc.plus(node.pre_gather_tp, node.gather_tp);
     };
     const gsTree = createNewPathTree('stage', gsTreeSetting);
     const gsPosSetting = {
@@ -45,11 +42,11 @@ const stageIm = (function () {
         updateFields: ['contract_qty', 'qc_qty', 'postil'],
     };
     gsPosSetting.calcFun = function (pos) {
-        pos.pre_gather_qty = _.add(pos.pre_contract_qty, pos.pre_qc_qty);
-        pos.gather_qty = _.add(pos.contract_qty, pos.qc_qty);
-        pos.end_contract_qty = _.add(pos.pre_contract_qty, pos.contract_qty);
-        pos.end_qc_qty = _.add(pos.pre_qc_qty, pos.qc_qty);
-        pos.end_gather_qty = _.add(pos.pre_gather_qty, pos.gather_qty);
+        pos.pre_gather_qty = ZhCalc.plus(pos.pre_contract_qty, pos.pre_qc_qty);
+        pos.gather_qty = ZhCalc.plus(pos.contract_qty, pos.qc_qty);
+        pos.end_contract_qty = ZhCalc.plus(pos.pre_contract_qty, pos.contract_qty);
+        pos.end_qc_qty = ZhCalc.plus(pos.pre_qc_qty, pos.qc_qty);
+        pos.end_gather_qty = ZhCalc.plus(pos.pre_gather_qty, pos.gather_qty);
     };
     const gsPos = new StagePosData(gsPosSetting);
 
@@ -181,7 +178,7 @@ const stageIm = (function () {
                 lp = {name: p.name, qty: p.quantity};
                 lx.pos.push(lp);
             }
-            lp.jl = _.round(_.add(lp.jl, p.gather_qty), 6);
+            lp.jl = ZhCalc.plus(lp.jl, p.gather_qty);
         }
     }
 
@@ -204,7 +201,7 @@ const stageIm = (function () {
             };
             im.leafXmjs.push(lx);
         }
-        lx.jl = _.round(_.add(lx.jl, node[jlField]), 6);
+        lx.jl = ZhCalc.plus(lx.jl, node[jlField]);
         generatePosData(node, lx);
     }
 
@@ -275,7 +272,7 @@ const stageIm = (function () {
                 ImData.push(im);
             }
             generateLeafXmjData(p, im, 'gather_qty');
-            im.jl = _.add(im.jl, p.gather_qty);
+            im.jl = ZhCalc.plus(im.jl, p.gather_qty);
         }
     }
 

+ 3 - 3
app/public/js/tender.js

@@ -89,7 +89,7 @@ function loadDealProperty () {
     $('#contract-price').val(property.deal_param.contractPrice);
     $('#zan-lie-price').val(property.deal_param.zanLiePrice);
     const iDecimal = property.decimal.pay ? property.decimal.payTp : property.decimal.tp;
-    $('#c-zl').val(_.round(property.deal_param.contractPrice - property.deal_param.zanLiePrice, iDecimal));
+    $('#c-zl').val(ZhCalc.round(ZhCalc.minus(property.deal_param.contractPrice, property.deal_param.zanLiePrice), iDecimal));
     $('#start-advance').val(property.deal_param.startAdvance);
     $('#material-advance').val(property.deal_param.materialAdvance);
 }
@@ -117,14 +117,14 @@ function getDealTpDecimal() {
 // 四舍五入
 function roundPrice(obj) {
     const iDecimal = getDealTpDecimal();
-    obj.val(_.round(_.toNumber(obj.val()), iDecimal));
+    obj.val(ZhCalc.round(_.toNumber(obj.val()), iDecimal));
 }
 // 计算签约合同价(不含暂列金额)
 function calculateC2() {
     const constract = _.toNumber($('#contract-price').val());
     const zanLie = _.toNumber($('#zan-lie-price').val());
     const iDecimal = getDealTpDecimal();
-    $('#c-zl').val(_.round(constract - zanLie, iDecimal));
+    $('#c-zl').val(ZhCalc.round(constract - zanLie, iDecimal));
 }
 // 根据小数位数,计算全部的合同参数
 function CalculateAllDealParam() {

+ 46 - 21
app/service/ledger.js

@@ -1623,9 +1623,10 @@ module.exports = app => {
          */
         async updateCalc(tenderId, data) {
             // 简单验证数据
-            if (tenderId <= 0) {
+            if (tenderId <= 0 || !this.ctx.tender) {
                 throw '标段不存在';
             }
+            const info = this.ctx.tender.info;
             if (!data) {
                 throw '提交数据错误';
             }
@@ -1656,32 +1657,38 @@ module.exports = app => {
                     }
                     if (this._checkCalcField(row)) {
                         let calcData = JSON.parse(JSON.stringify(row));
-                        const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, row.unit ? row.unit : updateNode.unit);
+                        const precision = this.ctx.helper.findPrecision(info.precision, row.unit ? row.unit : updateNode.unit);
                         // 数量保留小数位数
                         this.ctx.helper.checkFieldPrecision(calcData, qtyFields, precision.value);
                         // 单位保留小数位数
-                        this.ctx.helper.checkFieldPrecision(calcData, upFields, this.ctx.tender.info.decimal.up);
+                        this.ctx.helper.checkFieldPrecision(calcData, upFields, info.decimal.up);
                         // 计算
                         if (row.quantity !== undefined) {
                             if (row.unit_price  !== undefined) {
-                                calcData.total_price = this.ctx.helper.times(calcData.quantity, calcData.unit_price);
+                                calcData.total_price = this.ctx.helper.round(
+                                    this.ctx.helper.times(calcData.quantity, calcData.unit_price), info.decimal.tp);
                             } else {
-                                calcData.total_price = this.ctx.helper.times(calcData.quantity, updateNode.unit_price);
+                                calcData.total_price = this.ctx.helper.round(
+                                    this.ctx.helper.times(calcData.quantity, updateNode.unit_price), info.decimal.tp);
                             }
                         } else if (row.unit_price !== undefined) {
-                            calcData.total_price = this.ctx.helper.times(updateNode.quantity, calcData.unit_price);
+                            calcData.total_price = this.ctx.helper.round(
+                                this.ctx.helper.times(updateNode.quantity, calcData.unit_price), info.decimal.tp);
                         }
                         if (row.total_price !== undefined) {
                             calcData.quantity = null;
                         }
                         if (row.deal_qty !== undefined) {
                             if (row.unit_price !== undefined) {
-                                calcData.deal_tp = this.ctx.helper.times(calcData.deal_qty, calcData.unit_price);
+                                calcData.deal_tp = this.ctx.helper.round(
+                                    this.ctx.helper.times(calcData.deal_qty, calcData.unit_price), info.decimal.tp);
                             } else {
-                                calcData.deal_tp = this.ctx.helper.times(calcData.deal_qty, updateNode.unit_price);
+                                calcData.deal_tp = this.ctx.helper.round(
+                                    this.ctx.helper.times(calcData.deal_qty, updateNode.unit_price), info.decimal.tp);
                             }
                         } else if (row.unit_price !== undefined) {
-                            calcData.deal_tp = this.ctx.helper.times(updateNode.deal_qty, calcData.unit_price);
+                            calcData.deal_tp = this.ctx.helper.round(
+                                this.ctx.helper.times(updateNode.deal_qty, calcData.unit_price), info.decimal.tp);
                         }
                         if (row.deal_tp !== undefined) {
                             calcData.deal_qty = null;
@@ -1749,8 +1756,9 @@ module.exports = app => {
                     quantity: gcl.quantity,
                 };
                 child.full_path = parent.full_path + '.' + child.ledger_id;
-                child.total_price = child.unit_price * child.quantity;
-                tp = tp + child.total_price;
+                child.total_price = this.ctx.helper.round(
+                    this.ctx.helper.times(child.unit_price, child.quantity), this.ctx.tender.info.decimal.tp);
+                tp = this.ctx.helper.add(tp, child.total_price);
                 result.push(child);
                 newIds.push(child.ledger_id);
             }
@@ -1800,6 +1808,7 @@ module.exports = app => {
                 if (!maxId) {
                     maxId = await this._getMaxNodeId(tenderId);
                 }
+
                 // 数据库创建新增节点数据
                 for (let i = 0, iLen = data.length; i < iLen; i++) {
                     // 合并新增数据
@@ -1817,13 +1826,12 @@ module.exports = app => {
                     };
                     qd.full_path = selectData.full_path + '.' + qd.ledger_id;
                     const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, qd.unit);
-                    this.ctx.helper.checkFieldPrecision(qd, qtyFields, precision.value);
                     const insertResult = await this.transaction.insert(this.tableName, qd);
                     qd.id = insertResult.insertId;
                     newIds.push(insertResult.insertId);
                     if (data[i].pos.length > 0) {
                         await this.ctx.service.pos.insertLedgerPosData(this.transaction, tenderId, qd, data[i].pos);
-                        await this.calc(tenderId, insertResult.insertId, this.transaction);
+                        await this._calcNode(qd, this.transaction);
                     }
                 }
                 this.cache.set(cacheKey, maxId + data.length + 1, 'EX', this.ctx.app.config.cacheTime);
@@ -1898,7 +1906,7 @@ module.exports = app => {
                     newIds.push(insertResult.insertId);
                     if (data[i].pos.length > 0) {
                         await this.ctx.service.pos.insertLedgerPosData(this.transaction, tenderId, qd, data[i].pos);
-                        await this.calc(tenderId, insertResult.insertId, this.transaction);
+                        await this._calcNode(qd, this.transaction);
                     }
                 }
                 this.cache.set(cacheKey, maxId + data.length + 1, 'EX', this.ctx.app.config.cacheTime);
@@ -1917,21 +1925,38 @@ module.exports = app => {
 
         /**
          *
+         * @param node
+         * @param transaction
+         * @returns {Promise<void>}
+         * @private
+         */
+        async _calcNode(node, transaction) {
+            const info = this.ctx.tender.info;
+            const precision = this.ctx.helper.findPrecision(info.precision, node.unit);
+
+            const calcQtySql = 'SELECT SUM(`quantity`) As quantity FROM ?? WHERE `lid` = ?';
+            const data = await transaction.queryOne(this.db.format(calcQtySql, [this.ctx.service.pos.tableName, node.id]));
+            data.id = node.id;
+            data.quantity = this.round(data.quantity, precision.value);
+            data.total_price = this.round(this.ctx.helper.times(data.quantity, node.unit_price), info.decimal.tp);
+            await transaction.update(this.tableName, data);
+        }
+
+        /**
+         *
          * @param {Number} tid - 标段id
          * @param {Number} id - 需要计算的节点的id
          * @param {Object} transaction - 操作所属事务,没有则创建
          * @return {Promise<void>}
          */
         async calc(tid, id, transaction) {
-            const node = await this.getAllDataByCondition({ id });
+            const node = await transaction.queryOne({
+                id: id
+            });
             if (!node) {
                 throw '数据错误';
             }
-
-            const calcQtySql = 'UPDATE ??' +
-                ' SET `quantity` = (SELECT SUM(`quantity`) FROM ?? WHERE `lid` = ?), `total_price` = `quantity` * `unit_price`' +
-                ' WHERE `id` = ?';
-            await transaction.query(this.db.format(calcQtySql, [this.tableName, this.ctx.service.pos.tableName, id, id]));
+            this._calcNode(node, transaction);
         }
 
         /**
@@ -1992,7 +2017,7 @@ module.exports = app => {
          */
         async importExcel(excelData) {
             const AnalysisExcel = require('../lib/analysis_excel');
-            const analysisExcel = new AnalysisExcel();
+            const analysisExcel = new AnalysisExcel(this.ctx);
             const tempData = await this.ctx.service.tenderNodeTemplate.getData(true);
             const cacheTree = analysisExcel.analysisData(excelData, tempData);
             const cacheKey = keyPre + this.ctx.tender.id;

+ 4 - 4
app/service/pos.js

@@ -38,7 +38,7 @@ module.exports = app => {
             if (data.quantity) {
                 const bills = await this.ctx.service.ledger.getDataById(data.lid);
                 const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, bills.unit);
-                data.quantity = this._.round(data.quantity, precision.value);
+                data.quantity = this.round(data.quantity, precision.value);
             }
             const addRst = await transaction.insert(this.tableName, data);
             data.id = addRst.insertId;
@@ -72,7 +72,7 @@ module.exports = app => {
                         if (d.quantity) {
                             const bills = await this.ctx.service.ledger.getDataById(op.lid);
                             const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, bills.unit);
-                            d.quantity = this._.round(d.quantity, precision.value);
+                            d.quantity = this.round(d.quantity, precision.value);
                         }
                         await transaction.update(this.tableName, d, {tid: tid, id: d.id});
                         if (d.quantity !== undefined && op && (result.ledger.update.indexOf(op.lid) === -1)) {
@@ -125,7 +125,7 @@ module.exports = app => {
                     if (d.quantity) {
                         const bills = await this.ctx.service.ledger.getDataById(d.lid);
                         const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, bills.unit);
-                        d.quantity = this._.round(d.quantity, precision.value);
+                        d.quantity = this.round(d.quantity, precision.value);
                         if (updateLid.indexOf(d.lid) === -1) {
                             updateLid.push(d.lid);
                         }
@@ -199,7 +199,7 @@ module.exports = app => {
                 d.add_times = 0;
                 d.add_user = this.ctx.session.sessionUser.accountId;
                 if (d.quantity) {
-                    d.quantity = this._.round(d.quantity, precision.value);
+                    d.quantity = this.round(d.quantity, precision.value);
                 }
             }
             await transaction.insert(this.tableName, data);

+ 2 - 2
app/service/stage.js

@@ -229,11 +229,11 @@ module.exports = app => {
                         break;
                     case 'bqwc':
                         const sum = await this.ctx.service.stageBills.getSumTotalPrice(this.ctx.stage);
-                        cb.value = this.app._.add(sum.contract_tp, sum.qc_tp);
+                        cb.value = this.ctx.helper.plus(sum.contract_tp, sum.qc_tp);
                         break;
                     case 'ybbqwc':
                         const sumGcl = await this.ctx.service.stageBills.getSumTotalPriceGcl(this.ctx.stage, '^1[0-9]{2}-');
-                        cb.value = this.app._.add(sumGcl.contract_tp, sumGcl.qc_tp);
+                        cb.value = this.ctx.helper.plus(sumGcl.contract_tp, sumGcl.qc_tp);
                         break;
                     default:
                         cb.value = 0;

+ 25 - 18
app/service/stage_bills.js

@@ -70,12 +70,12 @@ module.exports = app => {
             const lidSql = lid ? ' And Bills.lid in (?)' : '';
             const sql = 'SELECT * FROM ' + this.tableName + ' As Bills ' +
                 '  INNER JOIN ( ' +
-                '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `progress`, `lid` From ' + this.tableName +
-                '      WHERE `times` < ? OR (`times` = ? AND `order` <= ?)' +
+                '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `progress`, `lid`, `tid`, `sid` From ' + this.tableName +
+                '      WHERE `times` < ? OR (`times` = ? AND `order` <= ?) And tid = ? And sid = ?' + lidSql +
                 '      GROUP BY `lid`' +
                 '  ) As MaxFilter ' +
                 '  ON (Bills.times * ' + timesLen + ' + `order`) = MaxFilter.progress And Bills.lid = MaxFilter.lid' +
-                '  WHERE Bills.tid = ? And Bills.sid = ?' + lidSql;
+                '    AND Bills.sid = MaxFilter.sid';
             const sqlParam = [times, times, order, tid, sid];
             if (!lid) {
                 return await this.db.query(sql, sqlParam);
@@ -100,6 +100,7 @@ module.exports = app => {
         }
 
         async _insertStageBillsData(transaction, insertData, ledgerData) {
+            const info = this.ctx.tender.info;
             const d = {
                 tid: this.ctx.tender.id,
                 lid: ledgerData.id,
@@ -112,11 +113,13 @@ module.exports = app => {
             const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, ledgerData.unit);
             if (insertData.contract_qty) {
                 d.contract_qty = this.round(insertData.contract_qty, precision.value);
-                d.contract_tp = d.contract_qty * ledgerData.unit_price;
+                d.contract_tp = this.round(
+                    this.ctx.helper.times(d.contract_qty, ledgerData.unit_price), info.decimal.tp);
             }
             if (insertData.qc_qty) {
                 d.qc_qty = this.round(insertData.qc_qty, precision.value);
-                d.qc_tp = d.qc_qty * ledgerData.unit_price;
+                d.qc_tp = this.round(
+                    this.ctx.helper.times(d.qc_qty, ledgerData.unit_price), info.decimal.tp);
             }
             if (insertData.postil) {
                 d.postil = insertData.postil;
@@ -130,20 +133,21 @@ module.exports = app => {
          * @returns {Promise<void>}
          */
         async updateStageData(data) {
+            const info = this.ctx.tender.info;
             const datas = data instanceof Array ? data : [data];
             const transaction = await this.db.beginTransaction();
             try {
                 for (const d of datas) {
                     const stageBills = await this.getLastestStageData(this.ctx.tender.id, this.ctx.stage.id, d.lid);
                     const ledgerBills = await this.ctx.service.ledger.getDataById(d.lid);
-                    const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, ledgerBills.unit);
+                    const precision = this.ctx.helper.findPrecision(info.precision, ledgerBills.unit);
                     if (d.contract_qty !== undefined) {
                         d.contract_qty = this.round(d.contract_qty, precision.value);
-                        d.contract_tp = d.contract_qty * ledgerBills.unit_price;
+                        d.contract_tp = this.round(this.ctx.helper.times(d.contract_qty, ledgerBills.unit_price), info.decimal.tp);
                     }
                     if (d.qc_qty !== undefined) {
                         d.qc_qty = this.round(d.qc_qty, precision.value);
-                        d.qc_tp = d.qc_qty * ledgerBills.unit_price;
+                        d.qc_tp = this.round(this.ctx.helper.times(d.qc_qty, ledgerBills.unit_price), info.decimal.tp);
                     }
                     if (!stageBills) {
                         d.tid = this.ctx.tender.id;
@@ -175,15 +179,16 @@ module.exports = app => {
          * @private
          */
         async updateStageBillsQty(transaction, ledgerBills, stageBills, data) {
-            const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, ledgerBills.unit);
+            const info = this.ctx.tender.info;
+            const precision = this.ctx.helper.findPrecision(info.precision, ledgerBills.unit);
             const updateData = {};
             if (data.contract_qty) {
                 updateData.contract_qty = this.round(data.contract_qty, precision.value);
-                updateData.contract_tp = this.round(updateData.contract_qty * ledgerBills.unit_price);
+                updateData.contract_tp = this.round(this.ctx.helper.times(updateData.contract_qty, ledgerBills.unit_price), info.decimal.tp);
             }
             if (data.qc_qty) {
                 updateData.qc_qty = this.round(data.qc_qty, precision.value);
-                updateData.qc_tp = this.round(updateData.qc_qty * ledgerBills.unit_price);
+                updateData.qc_tp = this.round(this.ctx.helper.times(updateData.qc_qty, ledgerBills.unit_price), info.decimal.tp);
             }
             if (stageBills) {
                 if ((updateData.contract_qty === undefined || stageBills.contract_qty !== updateData.contract_qty) ||
@@ -208,6 +213,7 @@ module.exports = app => {
          * @returns {Promise<void>}
          */
         async calc(tid, sid, lid, transaction) {
+            const info = this.ctx.tender.info;
             const stageBills = await this.getLastestStageData(tid, sid, lid);
             const ledgerBills = await this.ctx.service.ledger.getDataById(lid);
             if (!ledgerBills) {
@@ -216,15 +222,15 @@ module.exports = app => {
             const posGather = await this.ctx.service.stagePos.getPosGather(tid, sid, lid, transaction);
             if (!posGather) { return; }
 
-            const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, ledgerBills.unit);
+            const precision = this.ctx.helper.findPrecision(info.precision, ledgerBills.unit);
             // 计算
             if (posGather.contract_qty !== undefined) {
                 posGather.contract_qty = this.round(posGather.contract_qty, precision.value);
-                posGather.contract_tp = this.round(posGather.contract_qty * ledgerBills.unit_price);
+                posGather.contract_tp = this.round(this.ctx.helper.times(posGather.contract_qty, ledgerBills.unit_price), info.decimal.tp);
             }
             if (posGather.qc_qty !== undefined) {
                 posGather.qc_qty = this.round(posGather.qc_qty, precision.value);
-                posGather.qc_tp = this.round(posGather.qc_qty * ledgerBills.unit_price);
+                posGather.qc_tp = this.round(this.ctx.helper.times(posGather.qc_qty, ledgerBills.unit_price), info.decimal.tp);
             }
             if (stageBills) {
                 if (stageBills.contract_qty === posGather.contract_qty && stageBills.qc_qty === posGather.qc_qty) {
@@ -258,15 +264,16 @@ module.exports = app => {
         }
 
         async getSumTotalPriceFilter(stage, operate, filter) {
-            const sql = 'SELECT Sum(`contract_tp`) As `contract_tp`, Sum(`qc_tp`) As `qc_tp` FROM ( ' + this.tableName + ' As Bills ' +
+            const sql = 'SELECT Sum(`contract_tp`) As `contract_tp`, Sum(`qc_tp`) As `qc_tp`' +
+                '  FROM ' + this.tableName + ' As Bills ' +
                 '  INNER JOIN ( ' +
                 '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `flow`, `lid` From ' + this.tableName +
                 '      WHERE `times` <= ? AND `order` <= ?' +
                 '      GROUP BY `lid`' +
                 '  ) As MaxFilter ' +
-                '  ON (Bills.times * ' + timesLen + ' + `order`) = MaxFilter.flow And Bills.lid = MaxFilter.lid, ' +
-                '  ' + this.ctx.service.ledger.tableName + ' As Ledger ) ' +
-                '  WHERE Bills.sid = ? AND Bills.lid = Ledger.id And Ledger.b_code ' + operate + ' ?';
+                '  ON (Bills.times * ' + timesLen + ' + `order`) = MaxFilter.flow And Bills.lid = MaxFilter.lid ' +
+                '  INNER JOIN ' + this.ctx.service.ledger.tableName + ' As Ledger ON Bills.lid = Ledger.id' +
+                '  WHERE Bills.sid = ? And Ledger.b_code ' + operate + ' ?';
             const sqlParam = [stage.times, stage.curAuditor ? stage.curAuditor.order : 0, stage.id, filter];
             const result = await this.db.queryOne(sql, sqlParam);
             return result;

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

@@ -254,6 +254,7 @@
     const ledgerSpreadSetting = JSON.parse('<%- JSON.stringify(ledgerSpread) %>');
     const posSpreadSetting = JSON.parse('<%- JSON.stringify(posSpread) %>');
     const tender = JSON.parse('<%- JSON.stringify(tender) %>');
+    const tenderInfo = JSON.parse('<%- JSON.stringify(ctx.tender.info) %>');
     const measureType = JSON.parse('<%- JSON.stringify(measureType) %>');
     const stage = JSON.parse('<%- JSON.stringify(ctx.stage) %>');
     const ledgerData = JSON.parse('<%- JSON.stringify(ledgerData) %>');

+ 3 - 3
config/config.test.js

@@ -13,7 +13,7 @@ module.exports = appInfo => {
     config.mysql = {
         client: {
             // host
-            host: '127.0.0.1',
+            host: '192.168.1.70',
             // 端口号
             port: '3306',
             // 用户名
@@ -21,7 +21,7 @@ module.exports = appInfo => {
             // 密码
             password: 'root',
             // 数据库名
-            database: 'calculation',
+            database: 'calc_test',
         },
         // 是否加载到 app 上,默认开启
         app: true,
@@ -34,7 +34,7 @@ module.exports = appInfo => {
     // redis设置
     config.redis = {
         client: {
-            host: '127.0.0.1',
+            host: '192.168.1.70',
             port: '6379',
             password: 'test',
             db: '0',

+ 2 - 1
config/web.js

@@ -40,7 +40,6 @@ const JsFiles = {
         "/public/js/messages_zh.js",
         "/public/js/popper/popper.min.js",
         "/public/js/bootstrap/bootstrap.min.js",
-        "/public/js/global.js",
         "/public/js/vue/vue.js",
         "/public/js/component/input.js",
         "/public/js/cookies.js",
@@ -48,6 +47,8 @@ const JsFiles = {
         "/public/js/jquery-contextmenu/jquery.contextMenu.min.js",
         "/public/js/lodash.js",
         "/public/js/lz-string/lz-string.js",
+        "/public/js/number-precision.js",
+        "/public/js/global.js",
     ],
     controller: {
         tender: {

+ 1 - 0
package.json

@@ -56,6 +56,7 @@
     "test": "npm run lint -- --fix&&npm run test-local",
     "test-local": "set EGG_SERVER_ENV=local&& egg-bin test",
     "test-qa": "set EGG_SERVER_ENV=qa&&egg-bin test",
+    "test-auto": "set EGG_SERVER_ENV=test&&egg-bin test",
     "cov": "egg-bin cov",
     "lint": "eslint .",
     "ci": "npm run lint && npm run cov",

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2176 - 0
sql/data/zh_bill.sql


+ 33 - 0
sql/data/zh_bill_list.sql

@@ -0,0 +1,33 @@
+/*
+Navicat MySQL Data Transfer
+
+Source Server         : ubuntu-jl
+Source Server Version : 50722
+Source Host           : 192.168.1.70:3306
+Source Database       : calculation
+
+Target Server Type    : MYSQL
+Target Server Version : 50722
+File Encoding         : 65001
+
+Date: 2019-06-05 10:05:58
+*/
+
+SET FOREIGN_KEY_CHECKS=0;
+
+-- ----------------------------
+-- Table structure for zh_bill_list
+-- ----------------------------
+DROP TABLE IF EXISTS `zh_bill_list`;
+CREATE TABLE `zh_bill_list` (
+  `id` int(8) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
+  `name` varchar(60) NOT NULL COMMENT '名称',
+  `remark` varchar(60) DEFAULT '' COMMENT '备注',
+  `create_time` int(10) NOT NULL COMMENT '创建时间',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='工程量清单列表数据表';
+
+-- ----------------------------
+-- Records of zh_bill_list
+-- ----------------------------
+INSERT INTO `zh_bill_list` VALUES ('1', '测试清单', '内容', '1515981196');

+ 36 - 0
sql/data/zh_group.sql

@@ -0,0 +1,36 @@
+/*
+Navicat MySQL Data Transfer
+
+Source Server         : ubuntu-jl
+Source Server Version : 50722
+Source Host           : 192.168.1.70:3306
+Source Database       : calculation
+
+Target Server Type    : MYSQL
+Target Server Version : 50722
+File Encoding         : 65001
+
+Date: 2019-06-05 10:05:38
+*/
+
+SET FOREIGN_KEY_CHECKS=0;
+
+-- ----------------------------
+-- Table structure for zh_group
+-- ----------------------------
+DROP TABLE IF EXISTS `zh_group`;
+CREATE TABLE `zh_group` (
+  `id` int(8) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+  `name` varchar(30) NOT NULL COMMENT '角色名称',
+  `permission` text NOT NULL COMMENT '权限ID',
+  `create_time` int(10) NOT NULL COMMENT '创建时间',
+  `remark` varchar(30) DEFAULT '' COMMENT '备注',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COMMENT='角色数据表';
+
+-- ----------------------------
+-- Records of zh_group
+-- ----------------------------
+INSERT INTO `zh_group` VALUES ('1', '超级管理员', 'all', '1506764405', '');
+INSERT INTO `zh_group` VALUES ('6', '管理员', '11,12,14,15,16,25,27,28,29,17,19,37,38,39,40,41,42,47,55', '1507793004', '备注内容1');
+INSERT INTO `zh_group` VALUES ('7', '销售人员', '37,38,40,42,47', '1552617131', '');

+ 56 - 0
sql/data/zh_manager.sql

@@ -0,0 +1,56 @@
+/*
+Navicat MySQL Data Transfer
+
+Source Server         : ubuntu-jl
+Source Server Version : 50722
+Source Host           : 192.168.1.70:3306
+Source Database       : calculation
+
+Target Server Type    : MYSQL
+Target Server Version : 50722
+File Encoding         : 65001
+
+Date: 2019-06-05 10:07:47
+*/
+
+SET FOREIGN_KEY_CHECKS=0;
+
+-- ----------------------------
+-- Table structure for zh_manager
+-- ----------------------------
+DROP TABLE IF EXISTS `zh_manager`;
+CREATE TABLE `zh_manager` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+  `username` varchar(25) NOT NULL COMMENT '用户名',
+  `password` varchar(50) NOT NULL COMMENT '密码',
+  `create_time` int(10) NOT NULL COMMENT '创建时间',
+  `last_login` int(10) DEFAULT NULL COMMENT '最后一次登录时间',
+  `group_id` int(8) DEFAULT '0' COMMENT '用户组ID',
+  `real_name` varchar(12) DEFAULT '' COMMENT '真实姓名',
+  `telephone` varchar(11) DEFAULT '' COMMENT '联系电话(CLD字段)',
+  `login_ip` varchar(13) DEFAULT '' COMMENT '登录ip',
+  `token` varchar(8) NOT NULL COMMENT '随机token',
+  `can_login` tinyint(1) DEFAULT '1' COMMENT '是否可登录',
+  `office` int(11) DEFAULT '12' COMMENT '办事处id(CLD字段)',
+  `category` varchar(100) DEFAULT '总部' COMMENT '办事处名称(CLD字段)',
+  `email` varchar(255) DEFAULT NULL COMMENT '邮箱(CLD字段)',
+  `qq` varchar(15) DEFAULT NULL COMMENT 'qq号(CLD字段)',
+  `fixedphone` varchar(15) DEFAULT NULL COMMENT '固定电话(CLD字段)',
+  `position` varchar(255) DEFAULT NULL COMMENT '职位(CLD字段)',
+  PRIMARY KEY (`id`),
+  KEY `idx_username` (`username`),
+  KEY `idx_office` (`office`)
+) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COMMENT='后台用户数据表';
+
+-- ----------------------------
+-- Records of zh_manager
+-- ----------------------------
+INSERT INTO `zh_manager` VALUES ('1', 'admin', 'YjE2yt4IiZ0/Il4imhHYTetjj9k=', '0', '1559533108', '1', '测试', '15888888888', '127.0.0.1', 't62dhf', '1', '12', null, null, '123546545', '0756-6850221', null);
+INSERT INTO `zh_manager` VALUES ('11', 'caiaolin', 'CLD Password', '1508743822', '1509346385', '1', 'caiaolin', '15888888888', '127.0.0.1', 'CLD', '1', '2', null, null, '123456', '0756-3850888', null);
+INSERT INTO `zh_manager` VALUES ('12', '赖国然', 'CLD Password', '1539834754', '1557799810', '6', '赖国然', '13726259839', '127.0.0.1', 'CLD', '1', '12', '总部', '2661135450@qq.com', '2661135450', '', '程序员');
+INSERT INTO `zh_manager` VALUES ('13', '陈特', 'CLD Password', '1541389795', '1557133315', '7', '陈特', '15812644017', '192.168.1.104', 'CLD', '1', '12', '总部', '914630468@qq.com', '914630468', '0756-3850891', '产品经理/网页设计');
+INSERT INTO `zh_manager` VALUES ('14', '康彤', 'CLD Password', '1542095275', '1559620042', '1', '康彤', '13823093010', '127.0.0.1', 'CLD', '1', '12', '总部', '68104795@QQ.COM', '68104795', '13823093010', '');
+INSERT INTO `zh_manager` VALUES ('15', '梁琪波', 'CLD Password', '1546595464', '1559283062', '6', '梁琪波', '18476309326', '192.168.1.126', 'CLD', '1', '12', '总部', '2051618356@qq.com', '2051618356', '18476309326', '');
+INSERT INTO `zh_manager` VALUES ('16', '曾沛文', 'CLD Password', '1546595662', '1559615153', '6', '曾沛文', '13192294553', '192.168.1.22', 'CLD', '1', '12', '总部', '3598557058@qq.com', '3598557058', '6918978', '');
+INSERT INTO `zh_manager` VALUES ('17', '付青青', 'CLD Password', '1555914265', '1559632941', '1', '付青青', '13536547237', '192.168.1.25', 'CLD', '1', '12', '总部', '2417587264@qq.com', '2147483647', '0756-3850894', '软件测试工程师');
+INSERT INTO `zh_manager` VALUES ('18', '林强', 'CLD Password', '1557713523', '1557713523', '0', '', '13726254840', '192.168.1.30', 'CLD', '1', '12', '总部', '2747554248@qq.com', '2747554248', '', '客服');

+ 81 - 0
sql/data/zh_permission.sql

@@ -0,0 +1,81 @@
+/*
+Navicat MySQL Data Transfer
+
+Source Server         : ubuntu-jl
+Source Server Version : 50722
+Source Host           : 192.168.1.70:3306
+Source Database       : calculation
+
+Target Server Type    : MYSQL
+Target Server Version : 50722
+File Encoding         : 65001
+
+Date: 2019-06-05 10:00:51
+*/
+
+SET FOREIGN_KEY_CHECKS=0;
+
+-- ----------------------------
+-- Table structure for zh_permission
+-- ----------------------------
+DROP TABLE IF EXISTS `zh_permission`;
+CREATE TABLE `zh_permission` (
+  `id` int(8) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
+  `name` varchar(30) NOT NULL COMMENT '权限名称',
+  `controller` varchar(30) DEFAULT '' COMMENT '控制器名称',
+  `action` varchar(30) DEFAULT '' COMMENT 'action名称',
+  `pid` int(8) NOT NULL COMMENT '父ID',
+  `icon_class` varchar(50) DEFAULT '' COMMENT '图标类名',
+  `create_time` int(10) DEFAULT NULL COMMENT '创建时间',
+  `isshow` tinyint(4) NOT NULL DEFAULT '1' COMMENT '是否展示该权限',
+  PRIMARY KEY (`id`),
+  KEY `idx_pid` (`pid`)
+) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8 COMMENT='权限数据表';
+
+-- ----------------------------
+-- Records of zh_permission
+-- ----------------------------
+INSERT INTO `zh_permission` VALUES ('11', '系统管理', '', '', '0', 'fa-cog', '8', '1');
+INSERT INTO `zh_permission` VALUES ('12', '权限管理', 'permission', '', '11', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('14', '新增权限', 'permission', 'add', '12', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('15', '修改权限', 'permission', 'modify', '12', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('16', '删除权限', 'permission', 'delete', '12', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('17', '后台用户', '', '', '0', 'fa-user', '6', '1');
+INSERT INTO `zh_permission` VALUES ('19', '用户列表', 'manager', '', '17', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('20', '权限组', 'group', '', '17', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('22', '新增用户组', 'group', 'add', '20', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('23', '修改用户组', 'group', 'modify', '20', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('24', 'sql执行', 'sql', '', '11', '', '0', '0');
+INSERT INTO `zh_permission` VALUES ('25', '白名单管理', 'white-list', '', '11', '', '0', '0');
+INSERT INTO `zh_permission` VALUES ('27', '新增白名单', 'white-list', 'add', '25', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('28', '修改白名单', 'white-list', 'modify', '25', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('29', '删除白名单', 'white-list', 'delete', '25', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('30', '修改管理员', 'manager', 'modify', '19', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('31', '消息管理', '', '', '0', 'fa-bell', '0', '0');
+INSERT INTO `zh_permission` VALUES ('32', '消息列表', 'message', '', '31', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('33', '新增消息', 'message', 'add', '32', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('34', '修改消息', 'message', 'modify', '32', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('35', '删除消息', 'message', 'delete', '32', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('36', '日志列表', 'log', '', '11', '', '0', '0');
+INSERT INTO `zh_permission` VALUES ('37', '客户管理', '', '', '0', 'fa-users', '10', '1');
+INSERT INTO `zh_permission` VALUES ('38', '项目版客户', 'project', '', '37', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('39', '新增项目', 'project', 'add', '38', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('40', '修改项目', 'project', 'modify', '38', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('41', '删除项目', 'project', 'delete', '38', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('42', '项目账号列表', 'project', 'account', '38', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('43', '演示版客户', 'customer', 'demo', '37', '', '0', '0');
+INSERT INTO `zh_permission` VALUES ('44', '工具', '', '', '0', 'fa-wrench', '9', '1');
+INSERT INTO `zh_permission` VALUES ('45', '项目节', 'project-chapter', '', '44', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('46', '工程量清单', 'bill', '', '44', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('47', '项目标段列表', 'project', 'tender', '38', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('48', '企业版用户', 'enterprise', '', '37', '', '0', '0');
+INSERT INTO `zh_permission` VALUES ('49', '新增企业', 'enterprise', 'add', '48', 'add', null, '1');
+INSERT INTO `zh_permission` VALUES ('50', '修改企业', 'enterprise', 'modify', '48', 'modify', null, '1');
+INSERT INTO `zh_permission` VALUES ('51', '删除企业', 'enterprise', 'delete', '48', 'delete', null, '1');
+INSERT INTO `zh_permission` VALUES ('52', '企业设置', 'enterprise', 'setting', '48', '', null, '1');
+INSERT INTO `zh_permission` VALUES ('53', '企业账号列表', 'enterprise', 'account', '48', 'account', null, '1');
+INSERT INTO `zh_permission` VALUES ('54', '企业项目列表', 'enterprise', 'project', '48', '', null, '1');
+INSERT INTO `zh_permission` VALUES ('55', '项目设置', 'project', 'setting', '38', 'setting', null, '1');
+INSERT INTO `zh_permission` VALUES ('56', '标准清单', 'standard', '', '44', '', null, '1');
+INSERT INTO `zh_permission` VALUES ('57', '报表', 'report', '', '44', '', '0', '1');
+INSERT INTO `zh_permission` VALUES ('58', '删除管理员', 'manager', 'delete', '19', 'delete', null, '1');

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1943 - 0
sql/data/zh_project_chapter.sql


+ 33 - 0
sql/data/zh_project_chapter_list.sql

@@ -0,0 +1,33 @@
+/*
+Navicat MySQL Data Transfer
+
+Source Server         : ubuntu-jl
+Source Server Version : 50722
+Source Host           : 192.168.1.70:3306
+Source Database       : calculation
+
+Target Server Type    : MYSQL
+Target Server Version : 50722
+File Encoding         : 65001
+
+Date: 2019-06-05 10:08:40
+*/
+
+SET FOREIGN_KEY_CHECKS=0;
+
+-- ----------------------------
+-- Table structure for zh_project_chapter_list
+-- ----------------------------
+DROP TABLE IF EXISTS `zh_project_chapter_list`;
+CREATE TABLE `zh_project_chapter_list` (
+  `id` int(8) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
+  `name` varchar(60) NOT NULL COMMENT '项目章节名称',
+  `remark` varchar(60) DEFAULT '' COMMENT '备注',
+  `create_time` int(10) NOT NULL COMMENT '创建时间',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='项目节列表数据表';
+
+-- ----------------------------
+-- Records of zh_project_chapter_list
+-- ----------------------------
+INSERT INTO `zh_project_chapter_list` VALUES ('1', '测试项目节', '备注内容', '1515981171');

+ 93 - 0
sql/data/zh_tender_node_template.sql

@@ -0,0 +1,93 @@
+/*
+Navicat MySQL Data Transfer
+
+Source Server         : ubuntu-jl
+Source Server Version : 50722
+Source Host           : 192.168.1.70:3306
+Source Database       : calculation
+
+Target Server Type    : MYSQL
+Target Server Version : 50722
+File Encoding         : 65001
+
+Date: 2019-06-05 10:02:57
+*/
+
+SET FOREIGN_KEY_CHECKS=0;
+
+-- ----------------------------
+-- Table structure for zh_tender_node_template
+-- ----------------------------
+DROP TABLE IF EXISTS `zh_tender_node_template`;
+CREATE TABLE `zh_tender_node_template` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
+  `code` varchar(15) DEFAULT '' COMMENT '节点编号',
+  `name` varchar(60) NOT NULL COMMENT '名称',
+  `unit` varchar(15) DEFAULT '' COMMENT '单位',
+  `source` varchar(30) DEFAULT '' COMMENT '图(册)号',
+  `remark` varchar(60) DEFAULT '' COMMENT '备注',
+  `pid` int(10) NOT NULL COMMENT '父id',
+  `level` mediumint(5) NOT NULL COMMENT '层级',
+  `order` mediumint(255) NOT NULL COMMENT '同级排序',
+  `full_path` varchar(255) NOT NULL COMMENT '层级定位辅助字段parent.full_path.ledger_id',
+  `is_leaf` tinyint(255) NOT NULL COMMENT '是否叶子节点,界面显示辅助字段',
+  PRIMARY KEY (`id`),
+  KEY `idx_code` (`code`)
+) ENGINE=InnoDB AUTO_INCREMENT=54 DEFAULT CHARSET=utf8 COMMENT='标段项目节点模板数据表';
+
+-- ----------------------------
+-- Records of zh_tender_node_template
+-- ----------------------------
+INSERT INTO `zh_tender_node_template` VALUES ('1', '1', '第一部分 建筑安装工程费', '公路公里', '', '', '-1', '1', '1', '1', '0');
+INSERT INTO `zh_tender_node_template` VALUES ('2', '1-1', '临时工程', '公路公里', '', '', '1', '2', '1', '1.2', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('3', '1-2', '路基工程', 'km', '', '', '1', '2', '2', '1.3', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('4', '1-3', '路面工程', 'km/㎡', '', '', '1', '2', '3', '1.4', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('5', '1-4', '桥梁涵洞工程', 'km', '', '', '1', '2', '4', '1.5', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('6', '1-10', '建安工程其他费用', '公路公里', '', '', '1', '2', '5', '1.6', '0');
+INSERT INTO `zh_tender_node_template` VALUES ('7', '1-10-1', '其他建安工程', '项', '', '', '6', '3', '1', '1.6.7', '0');
+INSERT INTO `zh_tender_node_template` VALUES ('8', '1-10-1-1', '计日工', '项', '', '', '7', '4', '1', '1.6.7.8', '0');
+INSERT INTO `zh_tender_node_template` VALUES ('9', '1-10-1-1-1', '劳务', '项', '', '', '8', '5', '1', '1.6.7.8.9', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('10', '1-10-1-1-2', '材料', '项', '', '', '8', '5', '2', '1.6.7.8.10', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('11', '1-10-1-1-3', '机械', '项', '', '', '8', '5', '3', '1.6.7.8.11', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('12', '1-10-1-2', '工程管理专项费用', '项', '', '', '7', '4', '2', '1.6.7.12', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('13', '1-10-1-3', '索赔', '项', '', '', '7', '4', '3', '1.6.7.13', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('14', '1-10-1-4', '价差调整', '项', '', '', '7', '4', '4', '1.6.7.14', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('15', '1-10-1-5', '代扣代付项目增减建设成本', '项', '', '', '7', '4', '5', '1.6.7.15', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('16', '1-10-2', '尾工工程', '项', '', '', '6', '3', '2', '1.6.16', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('17', '1-10-3', '报废工程', '项', '', '', '6', '3', '3', '1.6.17', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('18', '2', '第二部分 设备及工具、器具购置费', '公路公里', '', '', '-1', '1', '2', '18', '0');
+INSERT INTO `zh_tender_node_template` VALUES ('19', '2-1', '设备购置费', '公路公里', '', '', '18', '2', '1', '18.19', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('20', '2-2', '工具、器具购置', '公路公里', '', '', '18', '2', '2', '18.20', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('21', '2-3', '办公及生活用家具购置', '公路公里', '', '', '18', '2', '3', '18.21', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('22', '3', '第三部分 工程建设其他费用', '公路公里', '', '', '-1', '1', '3', '22', '0');
+INSERT INTO `zh_tender_node_template` VALUES ('23', '3-1', '土地征用及拆迁补偿费', '公路公里', '', '', '22', '2', '1', '22.23', '0');
+INSERT INTO `zh_tender_node_template` VALUES ('24', '3-1-1', '土地补偿费', '公路公里', '', '', '23', '3', '1', '22.23.24', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('25', '3-1-2', '征用耕地安置补助费', '公路公里', '', '', '23', '3', '2', '22.23.25', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('26', '3-1-3', '拆迁补偿费', '公路公里', '', '', '23', '3', '3', '22.23.26', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('27', '3-1-4', '复耕费', '公路公里', '', '', '23', '3', '4', '22.23.27', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('28', '3-1-5', '耕地开垦费', '公路公里', '', '', '23', '3', '5', '22.23.28', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('29', '3-1-6', '森林植被恢复费', '公路公里', '', '', '23', '3', '6', '22.23.29', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('30', '3-1-7', '其它', '公路公里', '', '', '23', '3', '7', '22.23.30', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('31', '3-2', '建设项目管理费', '公路公里', '', '', '22', '2', '2', '22.31', '0');
+INSERT INTO `zh_tender_node_template` VALUES ('32', '3-2-1', '建设单位(业主)管理费', '公路公里', '', '', '31', '3', '1', '22.31.32', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('33', '3-2-2', '工程监理费', '公路公里', '', '', '31', '3', '2', '22.31.33', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('34', '3-2-3', '设计文件审查费', '公路公里', '', '', '31', '3', '3', '22.31.34', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('35', '3-2-4', '竣(交)工验收试验检测费', '公路公里', '', '', '31', '3', '4', '22.31.35', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('36', '3-3', '研究试验费', '公路公里', '', '', '22', '2', '3', '22.36', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('37', '3-4', '建设项目前期工作费', '公路公里', '', '', '22', '2', '4', '22.37', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('38', '3-5', '专项评价(估)费', '公路公里', '', '', '22', '2', '5', '22.38', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('39', '3-6', '施工机构迁移费', '公路公里', '', '', '22', '2', '6', '22.39', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('40', '3-7', '供电贴费', '公路公里', '', '', '22', '2', '7', '22.40', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('41', '3-8', '联合试运转费', '公路公里', '', '', '22', '2', '8', '22.41', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('42', '3-9', '生产人员培训费', '公路公里', '', '', '22', '2', '9', '22.42', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('43', '3-10', '固定资产投资方向调节税', '公路公里', '', '', '22', '2', '10', '22.43', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('44', '3-11', '建设期贷款利息', '公路公里', '', '', '22', '2', '11', '22.44', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('45', '', '预备费', '元', '', '', '-1', '1', '4', '45', '0');
+INSERT INTO `zh_tender_node_template` VALUES ('46', '', '1.价差预备费', '元', '', '', '45', '2', '1', '45.46', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('47', '', '2.基本预备费', '元', '', '', '45', '2', '2', '45.47', '0');
+INSERT INTO `zh_tender_node_template` VALUES ('48', '', '暂列金额(不含计日工总额)', '元', '', '', '47', '3', '1', '45.47.48', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('49', '', '保险费', '元', '', '', '47', '3', '2', '45.47.49', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('50', '', '新增加费用项目(不作预备费基数)', '元', '', '', '-1', '1', '5', '50', '0');
+INSERT INTO `zh_tender_node_template` VALUES ('51', '', '*请在此输入费用项目', '', '', '', '50', '2', '1', '50.51', '1');
+INSERT INTO `zh_tender_node_template` VALUES ('52', '', '其中:回收金额', '元', '', '', '-1', '1', '6', '52', '0');
+INSERT INTO `zh_tender_node_template` VALUES ('53', '', '*请在此输入费用项目', '', '', '', '52', '2', '1', '52.53', '1');

+ 51 - 26
test/app/lib/analysis_excel.test.js

@@ -12,11 +12,50 @@ const { app, assert } = require('egg-mock/bootstrap');
 const AnalysisExcel = require('../../../app/lib/analysis_excel');
 const Xlsx = require('js-xlsx');
 const _ = require('lodash');
-const testTenderId = 2;
+const mockData = {};
 
 describe('test/app/lib/analysis_excel.test.js', () => {
+    // 准备测试数据,新增测试标段
+    before(function* () {
+        const ctx = app.mockContext();
+        // 模拟登录session
+        const postData = {
+            account: '734406061@qq.com',
+            project: 'T201711273363',
+            project_password: 'mai654321',
+        };
+        ctx.session = {};
+        const loginResult = yield ctx.service.projectAccount.accountLogin(postData, 2);
+        assert(loginResult);
+        mockData.session = ctx.session;
+
+        // 模拟打开标段
+        mockData.tender = {};
+        const addData = {
+            name: 'test_analysis_excel',
+            category: null,
+        };
+        const tenderData = yield ctx.service.tender.getDataByCondition({
+                user_id: ctx.session.sessionUser.accountId,
+                name: addData.name,
+            });
+        if (tenderData) {
+            mockData.tender.data = tenderData;
+        } else {
+            const addResult = yield ctx.service.tender.add(addData);
+            assert(addResult);
+            mockData.tender.data = yield ctx.service.tender.getDataByCondition({
+                user_id: ctx.session.sessionUser.accountId,
+                name: addData.name,
+            });
+        }
+        mockData.tender.id = mockData.tender.data.id;
+        mockData.tender.info = yield ctx.service.tenderInfo.getTenderInfo(mockData.tender.id);
+    });
     it('analysis Test Data', function* () {
-        const analysisExcel = new AnalysisExcel();
+        const ctx = app.mockContext(mockData);
+
+        const analysisExcel = new AnalysisExcel(ctx);
         const testData = {
             rows: [
                 ['项目节编号', '清单子目号', '部位明细', '名称', '单位', '清单数量', '设计数量1', '设计数量2', '单价', '合价', '图号', '备注'],
@@ -55,7 +94,6 @@ describe('test/app/lib/analysis_excel.test.js', () => {
             ],
             range: 'A1:L29',
         };
-        const ctx = app.mockContext();
         const templateData = yield ctx.service.tenderNodeTemplate.getData(true);
         const result = analysisExcel.analysisData(testData, templateData);
         // 检查插入总量
@@ -72,6 +110,8 @@ describe('test/app/lib/analysis_excel.test.js', () => {
         assert(gcl.quantity === 92954.75);
     });
     it('Analysis Excel Test Data And Import', function* () {
+        const ctx = app.mockContext(mockData);
+
         const excelFile = app.baseDir  + '/app/public/files/template/ledger/导入分项清单Excel格式.xls';
         const wb = Xlsx.readFile(excelFile);
         const name = wb.SheetNames[0];
@@ -79,28 +119,19 @@ describe('test/app/lib/analysis_excel.test.js', () => {
             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 analysisExcel = new AnalysisExcel(ctx);
         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: testTenderId};
-        ctx.tender.data = yield ctx.service.tender.getTender(testTenderId);
-        ctx.tender.info = yield ctx.service.tenderInfo.getTenderInfo(testTenderId);
-        // pos需要记录createUserId
-        ctx.session = {
-            sessionUser: {
-                accountId: 2,
-            },
-        };
         yield ctx.service.ledger.importExcel(sheetData);
     });
     it('analysis 渭武12标 Excel', function* () {
+        const ctx = app.mockContext(mockData);
+
         const excelFile = app.baseDir  + '/app/public/files/template/ledger/渭武12标.xls';
         const wb = Xlsx.readFile(excelFile);
         const name = wb.SheetNames[0];
@@ -108,17 +139,11 @@ describe('test/app/lib/analysis_excel.test.js', () => {
             rows: Xlsx.utils.sheet_to_json(wb.Sheets[name], {header: 1}),
             merge: wb.Sheets[name]["!merges"],
         };
-        const ctx = app.mockContext();
-        // 计算需要标段的清单精度、小数位数等数据
-        ctx.tender = {id: testTenderId};
-        ctx.tender.data = yield ctx.service.tender.getTender(testTenderId);
-        ctx.tender.info = yield ctx.service.tenderInfo.getTenderInfo(testTenderId);
-        // pos需要记录createUserId
-        ctx.session = {
-            sessionUser: {
-                accountId: 2,
-            },
-        };
+
         yield ctx.service.ledger.importExcel(sheetData);
+        const count = yield ctx.service.ledger.count({
+            tender_id: ctx.tender.id
+        });
+        assert(count === 2867);
     });
 });

+ 16 - 15
test/app/lib/sso.test.js

@@ -13,20 +13,21 @@ const SSO = require('../../../app/lib/sso');
 
 describe('test/app/lib/sso.test.js', () => {
 
-    it('login success valid', function* () {
-        const ctx = app.mockContext();
-        const sso = new SSO(ctx);
-
-        const username = 'laiku123@qq.com';
-        const password = '19930523';
-        const result = yield sso.loginValid(username, password);
-
-        // 验证返回
-        assert(result);
-
-        // 验证数据库中是否新增了账号
-        const customer = yield ctx.service.customer.getDataByCondition({ email: username });
-        assert(customer !== null);
-    });
+    // 不再支持SSO登录方式
+    // it('login success valid', function* () {
+    //     const ctx = app.mockContext();
+    //     const sso = new SSO(ctx);
+    //
+    //     const username = 'laiku123@qq.com';
+    //     const password = '19930523';
+    //     const result = yield sso.loginValid(username, password);
+    //
+    //     // 验证返回
+    //     assert(result);
+    //
+    //     // 验证数据库中是否新增了账号
+    //     const customer = yield ctx.service.customer.getDataByCondition({ email: username });
+    //     assert(customer !== null);
+    // });
 
 });

+ 134 - 122
test/app/service/ledger.test.js

@@ -9,6 +9,7 @@
 
 const excel = require('node-xlsx');
 const _ = require('lodash');
+const mockData = {};
 
 /*const testNodeData = [
     { ledger_id: 1, ledger_pid: -1, order: 1, level: 1, full_path: '1', code: '1', is_leaf: false },
@@ -46,8 +47,6 @@ const testNodeData = [
     { id: 16, pid: 4, order: 1, level: 3, full_path: '1.4.16', code: '1-3-1', is_leaf: true },
     { id: 5, pid: 1, order: 4, level: 2, full_path: '1.5', code: '1-4', is_leaf: true },
 ];
-const testTenderId = 3;
-const testUserId = 2;
 
 const { app, assert } = require('egg-mock/bootstrap');
 const findById = function(nodes, Id) {
@@ -59,22 +58,55 @@ const findById = function(nodes, Id) {
 
 describe('test/app/service/ledger.test.js', () => {
     // 准备测试数据
-    it('clear history test data', function* () {
-        const ctx = app.mockContext();
-        const result = yield ctx.service.ledger.db.delete(ctx.service.ledger.tableName, { tender_id: testTenderId });
-        const posResult = yield ctx.service.pos.db.delete(ctx.service.ledger.tableName, { tender_id: testTenderId });
+    // 准备测试数据,新增测试标段
+    before(function* () {
+        const ctx = app.mockContext(mockData);
+        // 模拟登录session
+        const postData = {
+            account: '734406061@qq.com',
+            project: 'T201711273363',
+            project_password: 'mai654321',
+        };
+        ctx.session = {};
+        const loginResult = yield ctx.service.projectAccount.accountLogin(postData, 2);
+        assert(loginResult);
+        mockData.session = ctx.session;
+
+        // 模拟打开标段
+        mockData.tender = {};
+        const addData = {
+            name: 'test_ledger',
+            category: null,
+        };
+        const tenderData = yield ctx.service.tender.getDataByCondition({
+            user_id: ctx.session.sessionUser.accountId,
+            name: addData.name,
+        });
+        if (tenderData) {
+            mockData.tender.data = tenderData;
+        } else {
+            const addResult = yield ctx.service.tender.add(addData);
+            assert(addResult);
+            mockData.tender.data = yield ctx.service.tender.getDataByCondition({
+                user_id: ctx.session.sessionUser.accountId,
+                name: addData.name,
+            });
+        }
+        mockData.tender.id = mockData.tender.data.id;
+        mockData.tender.info = yield ctx.service.tenderInfo.getTenderInfo(mockData.tender.id);
+        ctx.tender = mockData.tender;
+
+        // 清理旧测试数据
+        let result = yield ctx.service.ledger.db.delete(ctx.service.ledger.tableName, { tender_id: ctx.tender.id });
+        const posResult = yield ctx.service.pos.db.delete(ctx.service.ledger.tableName, { tender_id: ctx.tender.id });
         assert(result.affectedRows >= 0 && posResult.affectedRows >= 0);
-    });
-    it('add test data(test add)', function* () {
-        const ctx = app.mockContext();
+        // 初始化测试基础数据
         for (const data of testNodeData) {
-            data.tender_id = testTenderId;
+            data.tender_id = ctx.tender.id;
         }
-        //const result = yield ctx.service.ledger.db.insert(ctx.service.ledger.tableName, testNodeData);
-        //assert(result.affectedRows === testNodeData.length);
-        const result = yield ctx.service.ledger.add(testNodeData, testTenderId);
+        result = yield ctx.service.ledger.add(testNodeData, ctx.tender.id);
         assert(result);
-        ctx.service.ledger.cache.set('tender_node_maxId:' + testTenderId, 16, 'EX', ctx.app.config.cacheTime);
+        ctx.service.ledger.cache.set('tender_node_maxId:' + ctx.tender.id, 16, 'EX', ctx.app.config.cacheTime);
     });
     /* 期望运行结果:
         1
@@ -97,29 +129,29 @@ describe('test/app/service/ledger.test.js', () => {
 
     // 测试R类方法
     it('test getDataByTenderId', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 查询前4层节点
-        const result1 = yield ctx.service.ledger.getDataByTenderId(testTenderId);
+        const result1 = yield ctx.service.ledger.getDataByTenderId(ctx.tender.id);
         assert(result1.length === 12);
         // 查询前3层节点
-        const result2 = yield ctx.service.ledger.getDataByTenderId(testTenderId, 3);
+        const result2 = yield ctx.service.ledger.getDataByTenderId(ctx.tender.id, 3);
         assert(result2.length === 10);
     });
     it('test getDataByNodeId', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 查询节点202-1
-        const node = yield ctx.service.ledger.getDataByNodeId(testTenderId, 7);
+        const node = yield ctx.service.ledger.getDataByNodeId(ctx.tender.id, 7);
         assert(node);
         assert(node.code === '202-1');
         assert(node.full_path === '1.2.6.7');
     });
     it('test getDataByNodeIds', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 查询节点202-1-a与201-1-b
-        const result = yield ctx.service.ledger.getDataByNodeIds(testTenderId, [10, 9]);
+        const result = yield ctx.service.ledger.getDataByNodeIds(ctx.tender.id, [10, 9]);
         assert(result.length === 2);
 
         let node = findById(result, 10);
@@ -129,33 +161,33 @@ describe('test/app/service/ledger.test.js', () => {
         assert(node.full_path === '1.2.6.7.9');
     });
     it('test getDataByIds', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 查询节点202-1
-        const node = yield ctx.service.ledger.getDataByNodeId(testTenderId, 7);
+        const node = yield ctx.service.ledger.getDataByNodeId(ctx.tender.id, 7);
         const result = yield ctx.service.ledger.getDataByIds([node.id]);
         assert(result.length === 1);
         assert(node.code === result[0].code);
         assert(node.full_path === result[0].full_path);
     });
     it('test getLastChildData', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 查询节点202-1最后一个子节点
-        const result = yield ctx.service.ledger.getLastChildData(testTenderId, 7);
+        const result = yield ctx.service.ledger.getLastChildData(ctx.tender.id, 7);
         assert(result.ledger_id === 10);
         assert(result.full_path === '1.2.6.7.10');
     });
     it('test getDataByParentAndOrder', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 查询节点202-1 第1子节点
-        const result1 = yield ctx.service.ledger.getDataByParentAndOrder(testTenderId, 8, 1);
+        const result1 = yield ctx.service.ledger.getDataByParentAndOrder(ctx.tender.id, 8, 1);
         assert(result1.ledger_id === 11);
         assert(result1.full_path === '1.2.6.8.11');
 
         // 查询节点1-1 第2/3子节点
-        const result2 = yield ctx.service.ledger.getDataByParentAndOrder(testTenderId, 2, [2, 3]);
+        const result2 = yield ctx.service.ledger.getDataByParentAndOrder(ctx.tender.id, 2, [2, 3]);
         assert(result2.length === 2);
 
         let node = findById(result2, 13);
@@ -167,10 +199,10 @@ describe('test/app/service/ledger.test.js', () => {
         assert(node.code === '1-1-3');
     });
     it('test getChildrenByParentId', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 查询节点202-1最后一个子节点
-        const result = yield ctx.service.ledger.getChildrenByParentId(testTenderId, 8);
+        const result = yield ctx.service.ledger.getChildrenByParentId(ctx.tender.id, 8);
         assert(result.length === 2);
 
         let node = findById(result, 11);
@@ -182,10 +214,10 @@ describe('test/app/service/ledger.test.js', () => {
         assert(node.full_path === '1.2.6.8.12');
     });
     it('test getNextsData', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 查询节点1-1-1的全部子节点
-        const result = yield ctx.service.ledger.getNextsData(testTenderId, 2, 1);
+        const result = yield ctx.service.ledger.getNextsData(ctx.tender.id, 2, 1);
         assert(result.length === 2);
 
         let node = findById(result, 13);
@@ -197,10 +229,10 @@ describe('test/app/service/ledger.test.js', () => {
         assert(node.code === '1-1-3');
     });
     it('test getDataByFullPath', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 查询节点202-2及其子节点
-        const result = yield ctx.service.ledger.getDataByFullPath(testTenderId, '1.2.6.8%');
+        const result = yield ctx.service.ledger.getDataByFullPath(ctx.tender.id, '1.2.6.8%');
         assert(result.length === 3);
 
         let node = findById(result, 8);
@@ -216,26 +248,26 @@ describe('test/app/service/ledger.test.js', () => {
         assert(node.full_path === '1.2.6.8.12');
 
         // 查询1-1-1的子孙节点
-        const result1 = yield ctx.service.ledger.getDataByFullPath(testTenderId, '1.2.6.%');
+        const result1 = yield ctx.service.ledger.getDataByFullPath(ctx.tender.id, '1.2.6.%');
         assert(result1.length === 6);
     });
     it('test getFullLevelDataByFullPath', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 查询202-2-c及其全部父节点
-        const result1 = yield ctx.service.ledger.getFullLevelDataByFullPath(testTenderId, '1.2.6.8.11');
+        const result1 = yield ctx.service.ledger.getFullLevelDataByFullPath(ctx.tender.id, '1.2.6.8.11');
         assert(result1.length === 5);
 
-        const result2 = yield ctx.service.ledger.getFullLevelDataByFullPath(testTenderId, ['1.2.6.8.11', '1.2.6.7.9']);
+        const result2 = yield ctx.service.ledger.getFullLevelDataByFullPath(ctx.tender.id, ['1.2.6.8.11', '1.2.6.7.9']);
         assert(result2.length === 7);
     });
 
     // 测试CUD类方法
     // 基本树结构操作
     it('test addNode', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
         // 选中1-1-1,插入节点
-        const resultData = yield ctx.service.ledger.addNode(testTenderId, 6);
+        const resultData = yield ctx.service.ledger.addNode(ctx.tender.id, 6);
         assert(resultData.create.length === 1);
         assert(resultData.update.length === 2);
         assert(resultData.create[0].is_leaf === 1);
@@ -261,9 +293,9 @@ describe('test/app/service/ledger.test.js', () => {
         └── 1-4
      */
     it('test deleteNode', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
         // 选中202-1,删除节点
-        const resultData = yield ctx.service.ledger.deleteNode(testTenderId, 7);
+        const resultData = yield ctx.service.ledger.deleteNode(ctx.tender.id, 7);
         assert(resultData.delete.length === 3);
         assert(resultData.update.length === 1);
     });
@@ -284,9 +316,9 @@ describe('test/app/service/ledger.test.js', () => {
         └── 1-4
      */
     it('test upMoveNode', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
         // 选中202-2-e上移
-        const resultData = yield ctx.service.ledger.upMoveNode(testTenderId, 12);
+        const resultData = yield ctx.service.ledger.upMoveNode(ctx.tender.id, 12);
         resultData.update.sort(function(x, y) {
             return x.order - y.order;
         });
@@ -310,9 +342,9 @@ describe('test/app/service/ledger.test.js', () => {
         └── 1-4
      */
     it('test downMoveNode', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
         // 选中202-2-e下移
-        const resultData = yield ctx.service.ledger.downMoveNode(testTenderId, 12);
+        const resultData = yield ctx.service.ledger.downMoveNode(ctx.tender.id, 12);
         resultData.update.sort(function(x, y) {
             return x.order - y.order;
         });
@@ -336,9 +368,9 @@ describe('test/app/service/ledger.test.js', () => {
         └── 1-4
      */
     it('test upLevelNode', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
         // 选中 1-1-2 升级
-        const resultData = yield ctx.service.ledger.upLevelNode(testTenderId, 13);
+        const resultData = yield ctx.service.ledger.upLevelNode(ctx.tender.id, 13);
         assert(resultData);
         assert(resultData.update.length === 6);
 
@@ -377,9 +409,9 @@ describe('test/app/service/ledger.test.js', () => {
         └── 1-4
      */
     it('test downLevelNode', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
         // 选中1-3 降级
-        const resultData = yield ctx.service.ledger.downLevelNode(testTenderId, 4);
+        const resultData = yield ctx.service.ledger.downLevelNode(ctx.tender.id, 4);
         // 1-2/1-3/1-3-1/1-4修改
         assert(resultData.update.length === 4);
 
@@ -414,9 +446,9 @@ describe('test/app/service/ledger.test.js', () => {
      */
     // 复制整块
     it('test pasteBlock', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
         // 选中1-2-1, 粘贴1-1-1和new
-        const resultData = yield ctx.service.ledger.pasteBlock(testTenderId, 15, [6, 17]);
+        const resultData = yield ctx.service.ledger.pasteBlock(ctx.tender.id, 15, [6, 17]);
 
         const ledger = resultData.ledger;
         assert(ledger.create.length === 5);
@@ -456,13 +488,13 @@ describe('test/app/service/ledger.test.js', () => {
      */
     // 增量计算
     it('test updateInfo', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 修改new(id=17)的code 为 1-1-4
-        const node = yield ctx.service.ledger.getDataByNodeId(testTenderId, 17);
+        const node = yield ctx.service.ledger.getDataByNodeId(ctx.tender.id, 17);
         assert(node);
 
-        const resultData = yield ctx.service.ledger.updateInfo(testTenderId, {
+        const resultData = yield ctx.service.ledger.updateInfo(ctx.tender.id, {
             id: node.id,
             tender_id: node.tender_id,
             ledger_id: node.ledger_id,
@@ -492,15 +524,15 @@ describe('test/app/service/ledger.test.js', () => {
         └── 1-4
      */
     it('test updateInfos', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 修改1-1-1(id=18)的code 为 1-2-2、修改new(id=22)的code 为 1-2-3
-        const node1 = yield ctx.service.ledger.getDataByNodeId(testTenderId, 18);
+        const node1 = yield ctx.service.ledger.getDataByNodeId(ctx.tender.id, 18);
         assert(node1);
-        const node2 = yield ctx.service.ledger.getDataByNodeId(testTenderId, 22);
+        const node2 = yield ctx.service.ledger.getDataByNodeId(ctx.tender.id, 22);
         assert(node2);
 
-        const resultData = yield ctx.service.ledger.updateInfos(testTenderId, [{
+        const resultData = yield ctx.service.ledger.updateInfos(ctx.tender.id, [{
             id: node1.id,
             tender_id: node1.tender_id,
             ledger_id: node1.ledger_id,
@@ -537,18 +569,18 @@ describe('test/app/service/ledger.test.js', () => {
         └── 1-4
      */
     it('test updateCalc - update 1', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
         // 计算需使用清单精度、小数位数
-        ctx.tender = {id: testTenderId};
-        ctx.tender.data = yield ctx.service.tender.getTender(testTenderId);
-        ctx.tender.info = yield ctx.service.tenderInfo.getTenderInfo(testTenderId);
+        ctx.tender = {id: ctx.tender.id};
+        ctx.tender.data = yield ctx.service.tender.getTender(ctx.tender.id);
+        ctx.tender.info = yield ctx.service.tenderInfo.getTenderInfo(ctx.tender.id);
         // 修改202-2-e(1-1-1下)(id=12)的quantity为2.00000001, unit_price位3.0000005
         const qty = 2.00000001, fQty = ctx.helper.round(qty, ctx.tender.info.precision.other.value);
         const up = 3.0000005, fUp = ctx.helper.round(up, ctx.tender.info.decimal.up);
         const tp = 6.00000103, fTp = ctx.helper.times(fQty, fUp);
-        const node1 = yield ctx.service.ledger.getDataByNodeId(testTenderId, 12);
+        const node1 = yield ctx.service.ledger.getDataByNodeId(ctx.tender.id, 12);
         assert(node1);
-        const resultData = yield ctx.service.ledger.updateCalc(testTenderId, {
+        const resultData = yield ctx.service.ledger.updateCalc(ctx.tender.id, {
             id: node1.id,
             tender_id: node1.tender_id,
             ledger_id: node1.ledger_id,
@@ -583,11 +615,11 @@ describe('test/app/service/ledger.test.js', () => {
         └── 1-4
      */
     it('test updateCalc - update N', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
         // 计算需使用清单精度、小数位数
-        ctx.tender = {id: testTenderId};
-        ctx.tender.data = yield ctx.service.tender.getTender(testTenderId);
-        ctx.tender.info = yield ctx.service.tenderInfo.getTenderInfo(testTenderId);
+        ctx.tender = {id: ctx.tender.id};
+        ctx.tender.data = yield ctx.service.tender.getTender(ctx.tender.id);
+        ctx.tender.info = yield ctx.service.tenderInfo.getTenderInfo(ctx.tender.id);
         // 修改202-2-c(1-1-1下)(id=11)的quantity为4.00000025, unit_price为6.0000083
         //    202-2-c(1-2-2下)(id=20)的quantity为2.0000001, unit_price为5.000065
         //    202-2-e(1-2-2下)(id=21)的quantity为8.0000579, unit_price为4.0000086
@@ -606,14 +638,14 @@ describe('test/app/service/ledger.test.js', () => {
             fTp.push(ctx.helper.times(fQty[i], fUp[i]));
         }
 
-        const node1 = yield ctx.service.ledger.getDataByNodeId(testTenderId, 11);
+        const node1 = yield ctx.service.ledger.getDataByNodeId(ctx.tender.id, 11);
         assert(node1);
-        const node2 = yield ctx.service.ledger.getDataByNodeId(testTenderId, 20);
+        const node2 = yield ctx.service.ledger.getDataByNodeId(ctx.tender.id, 20);
         assert(node2);
-        const node3 = yield ctx.service.ledger.getDataByNodeId(testTenderId, 21);
+        const node3 = yield ctx.service.ledger.getDataByNodeId(ctx.tender.id, 21);
         assert(node3);
 
-        const resultData = yield ctx.service.ledger.updateCalc(testTenderId, [{
+        const resultData = yield ctx.service.ledger.updateCalc(ctx.tender.id, [{
             id: node1.id,
             tender_id: node1.tender_id,
             ledger_id: node1.ledger_id,
@@ -671,9 +703,9 @@ describe('test/app/service/ledger.test.js', () => {
      */
     // 复制整块+实时计算
     it('test pasteBlock - with Increment Calculate', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
         // 选中1-1-4, 粘贴202-2(1-1-1下)
-        const resultData = yield ctx.service.ledger.pasteBlock(testTenderId, 17, [8]);
+        const resultData = yield ctx.service.ledger.pasteBlock(ctx.tender.id, 17, [8]);
 
         assert(resultData.ledger.create.length === 3);
         assert(resultData.ledger.update.length === 0);
@@ -704,9 +736,9 @@ describe('test/app/service/ledger.test.js', () => {
      */
     // 树结构基本操作+实时计算
     it('test downLevel - with Increment Calculate', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
         // 选中202-2(1-1-4后兄弟节点) 降级
-        const resultData = yield ctx.service.ledger.downLevelNode(testTenderId, 23);
+        const resultData = yield ctx.service.ledger.downLevelNode(ctx.tender.id, 23);
         assert(resultData.update.length === 4);
     });
     /* 期望运行结果:
@@ -734,8 +766,8 @@ describe('test/app/service/ledger.test.js', () => {
         └── 1-4
      */
     it('test upLevel - with Increment Calculate', function* () {
-        const ctx = app.mockContext();
-        yield ctx.service.ledger.pasteBlock(testTenderId, 23, [23]);
+        const ctx = app.mockContext(mockData);
+        yield ctx.service.ledger.pasteBlock(ctx.tender.id, 23, [23]);
         /* 期望运行结果:
             1
             ├── 1-1
@@ -764,7 +796,7 @@ describe('test/app/service/ledger.test.js', () => {
             └── 1-4
          */
         // 选中202-2-c(1-1-4下)(id=23)升级
-        const resultData = yield ctx.service.ledger.upLevelNode(testTenderId, 23);
+        const resultData = yield ctx.service.ledger.upLevelNode(ctx.tender.id, 23);
         assert(resultData.update.length === 7);
     });
     /* 期望运行结果:
@@ -795,10 +827,10 @@ describe('test/app/service/ledger.test.js', () => {
         └── 1-4
      */
     it('test deleteNode - with Increment Calculate', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 选中202-2-c(1-2-2下)(id=20),删除节点
-        const resultData = yield ctx.service.ledger.deleteNode(testTenderId, 20);
+        const resultData = yield ctx.service.ledger.deleteNode(ctx.tender.id, 20);
         assert(resultData.delete.length === 1);
         assert(resultData.update.length === 1);
     });
@@ -831,10 +863,10 @@ describe('test/app/service/ledger.test.js', () => {
     // 从标准库添加数据
     // 检查添加,直接添加为选中节点子节点
     it('test addStdNode', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 选中1-1-4
-        const selectData = yield ctx.service.ledger.getDataByCondition({ tender_id: testTenderId, code: '1-1-4' });
+        const selectData = yield ctx.service.ledger.getDataByCondition({ tender_id: ctx.tender.id, code: '1-1-4' });
         assert(selectData);
         // 从标准库中添加1-1-5
         const condition1 = { list_id: 1, code: '1-1-5' };
@@ -843,7 +875,7 @@ describe('test/app/service/ledger.test.js', () => {
         const stdData1 = yield ctx.service.stdChapter.getDataByDataId(1, libData1.chapter_id);
         assert(stdData1);
         assert(stdData1.id === libData1.id);
-        const result1 = yield ctx.service.ledger.addStdNode(testTenderId, selectData.ledger_id, stdData1);
+        const result1 = yield ctx.service.ledger.addStdNode(ctx.tender.id, selectData.ledger_id, stdData1);
         assert(result1);
         assert(result1.create.length === 1);
         assert(result1.update.length === 1);
@@ -877,7 +909,7 @@ describe('test/app/service/ledger.test.js', () => {
         └── 1-4
      */
     it('test addStdNodeWithParent', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 从标准库添加1-4-2-1
         const condition1 = { list_id: 1, code: '1-4-2-1'};
@@ -886,7 +918,7 @@ describe('test/app/service/ledger.test.js', () => {
         const stdData1 = yield ctx.service.stdChapter.getDataByDataId(1, libData1.chapter_id);
         assert(stdData1);
         assert(stdData1.id === libData1.id);
-        const result1 = yield ctx.service.ledger.addStdNodeWithParent(testTenderId, stdData1, ctx.service.stdChapter);
+        const result1 = yield ctx.service.ledger.addStdNodeWithParent(ctx.tender.id, stdData1, ctx.service.stdChapter);
         assert(result1);
         assert(result1.create.length === 4);
         assert(!result1.update || result1.update.length === 0);
@@ -898,7 +930,7 @@ describe('test/app/service/ledger.test.js', () => {
         const stdData2 = yield ctx.service.stdChapter.getDataByDataId(1, libData2.chapter_id);
         assert(stdData2);
         assert(stdData2.id === libData2.id);
-        const result2 = yield ctx.service.ledger.addStdNodeWithParent(testTenderId, stdData2, ctx.service.stdChapter);
+        const result2 = yield ctx.service.ledger.addStdNodeWithParent(ctx.tender.id, stdData2, ctx.service.stdChapter);
         assert(result2);
         assert(result2.create.length === 1);
         assert(result2.update.length === 1);
@@ -911,7 +943,7 @@ describe('test/app/service/ledger.test.js', () => {
         const stdData3 = yield ctx.service.stdChapter.getDataByDataId(1, libData3.chapter_id);
         assert(stdData3);
         assert(stdData3.id === libData3.id);
-        const result3 = yield ctx.service.ledger.addStdNodeWithParent(testTenderId, stdData3, ctx.service.stdChapter);
+        const result3 = yield ctx.service.ledger.addStdNodeWithParent(ctx.tender.id, stdData3, ctx.service.stdChapter);
         assert(result3);
         assert(result3.create.length === 1);
         assert(result3.create[0].order === 1);
@@ -952,17 +984,7 @@ describe('test/app/service/ledger.test.js', () => {
      */
     // 批量插入
     it('test batchInsertChild', function* () {
-        const ctx = app.mockContext();
-        // 计算需使用清单精度、小数位数
-        ctx.tender = {id: testTenderId};
-        ctx.tender.data = yield ctx.service.tender.getTender(testTenderId);
-        ctx.tender.info = yield ctx.service.tenderInfo.getTenderInfo(testTenderId);
-        // pos需要记录createUserId
-        ctx.session = {
-            sessionUser: {
-                accountId: testUserId,
-            },
-        };
+        const ctx = app.mockContext(mockData);
 
         const batchData = [
             {
@@ -975,7 +997,7 @@ describe('test/app/service/ledger.test.js', () => {
             },
         ];
         // 选中1-1-3(id=14)
-        const result = yield ctx.service.ledger.batchInsertChild(testTenderId, 14, batchData);
+        const result = yield ctx.service.ledger.batchInsertChild(ctx.tender.id, 14, batchData);
         assert(result.ledger.create.length === 2);
         let node = _.find(result.ledger.create, {name: 'A1'});
         assert(node.quantity === 3);
@@ -1025,17 +1047,7 @@ describe('test/app/service/ledger.test.js', () => {
      */
     // 批量插入
     it('test batchInsertNext', function* () {
-        const ctx = app.mockContext();
-        // 计算需使用清单精度、小数位数
-        ctx.tender = {id: testTenderId};
-        ctx.tender.data = yield ctx.service.tender.getTender(testTenderId);
-        ctx.tender.info = yield ctx.service.tenderInfo.getTenderInfo(testTenderId);
-        // pos需要记录createUserId
-        ctx.session = {
-            sessionUser: {
-                accountId: testUserId,
-            },
-        };
+        const ctx = app.mockContext(mockData);
 
         const batchData = [
             {
@@ -1048,7 +1060,7 @@ describe('test/app/service/ledger.test.js', () => {
             },
         ];
         // 选中1-1-3(id=14)
-        const result = yield ctx.service.ledger.batchInsertNext(testTenderId, 14, batchData);
+        const result = yield ctx.service.ledger.batchInsertNext(ctx.tender.id, 14, batchData);
 
         assert(result.ledger.create.length === 2);
         let node = _.find(result.ledger.create, {name: 'A3'});
@@ -1106,25 +1118,25 @@ describe('test/app/service/ledger.test.js', () => {
 
     // 测试统计类方法
     it('test addUpChildren', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
         // 统计202-2(id=23)前两个子节点的金额
-        const result1 = yield ctx.service.ledger.addUpChildren(testTenderId, 23, 2, '<=');
+        const result1 = yield ctx.service.ledger.addUpChildren(ctx.tender.id, 23, 2, '<=');
         assert(result1 && result1 === 30);
         // 数据库不再存储父项金额,以下两个查询不能获得实际金额
         // 统计202-2(id=23)后两个子节点的金额
-        //const result2 = yield ctx.service.ledger.addUpChildren(testTenderId, 23, 2, '>=');
+        //const result2 = yield ctx.service.ledger.addUpChildren(ctx.tender.id, 23, 2, '>=');
         //assert(result2 && result2.toFixed(8) == 36.00003676);
         // 统计202-2(id=23)全部子节点的金额
-        //const result3 = yield ctx.service.ledger.addUpChildren(testTenderId, 23, 0, '>');
+        //const result3 = yield ctx.service.ledger.addUpChildren(ctx.tender.id, 23, 0, '>');
         //assert(result3 && result3.toFixed(8) == 60.00007146);
     });
 
     // 测试搜索类方法
     it('test search', function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
 
-        const result = yield ctx.service.ledger.search(testTenderId, {
+        const result = yield ctx.service.ledger.search(ctx.tender.id, {
             value: app.mysql.escape('%1-3%'),
             operate: 'Like',
             fields: ['code', 'name'],
@@ -1132,8 +1144,8 @@ describe('test/app/service/ledger.test.js', () => {
         assert(result.length === 3);
     });
     it('test searchRange', function* () {
-        const ctx = app.mockContext();
-        const result = yield ctx.service.ledger.searchRange(testTenderId, {
+        const ctx = app.mockContext(mockData);
+        const result = yield ctx.service.ledger.searchRange(ctx.tender.id, {
             value: app.mysql.escape('%1-3%'),
             operate: 'Like',
             fields: ['code', 'name'],
@@ -1148,7 +1160,7 @@ describe('test/app/service/ledger.test.js', () => {
     });
 
     // it('test ImportExcelData', function* () {
-    //     const ctx = app.mockContext();
+    //     const ctx = app.mockContext(mockData);
     //
     //     const file = ctx.app.baseDir + '/test/app/test_file/ledger-upload-test.xls';
     //     const sheets = excel.parse(file);

+ 2 - 2
test/app/service/project.test.js

@@ -20,8 +20,8 @@ describe('test/app/service/project.test.js', () => {
 
     it('exist code', function* () {
         const ctx = app.mockContext();
-        const projectData = yield ctx.service.project.getProjectByCode('J201711163164');
-        assert(projectData.id === 16);
+        const projectData = yield ctx.service.project.getProjectByCode('T201711273363');
+        assert(projectData.id === 17);
     });
 
 });

+ 9 - 3
test/app/service/project_account.test.js

@@ -14,10 +14,16 @@ describe('test/app/service/project_account.test.js', () => {
 
     it('test login success (sso)', function* () {
         const ctx = app.mockContext();
+        // 不允许使用通行账号登录
+        // const postData = {
+        //     account: 'laiku123@qq.com',
+        //     project: 'J201711163164',
+        //     project_password: '19930523',
+        // };
         const postData = {
-            account: 'laiku123@qq.com',
-            project: 'J201711163164',
-            project_password: '19930523',
+            account: '734406061@qq.com',
+            project: 'T201711273363',
+            project_password: 'mai654321',
         };
         ctx.session = {};
         const result = yield ctx.service.projectAccount.accountLogin(postData, 2);

+ 9 - 5
test/app/service/stage_bills.test.js

@@ -14,23 +14,27 @@ describe('test/app/service/stage_bills.test.js', () => {
     it('test getSumTotalPrice', function* () {
         const ctx = app.mockContext();
         const stage = yield ctx.service.stage.getDataByCondition({
-            id: 4
+            id: 43
         });
         stage.curTimes = stage.times;
         stage.curOrder = 0;
         const result = yield ctx.service.stageBills.getSumTotalPrice(stage);
-        assert(result.contract_tp === 209151.2);
+        assert(result.contract_tp === 26220);
         assert(result.qc_tp === null);
     });
     it('test getSumTotalPriceGcl', function* () {
         const ctx = app.mockContext();
         const stage = yield ctx.service.stage.getDataByCondition({
-            id: 4
+            id: 43
         });
         stage.curTimes = stage.times;
         stage.curOrder = 0;
-        const result = yield ctx.service.stageBills.getSumTotalPriceGcl(stage, '1[0-9]3-');
-        assert(result.contract_tp === 169151.2);
+        let result = yield ctx.service.stageBills.getSumTotalPriceGcl(stage, '102-');
+        assert(result.contract_tp === 22000);
+        assert(result.qc_tp === null);
+
+        result = yield ctx.service.stageBills.getSumTotalPriceGcl(stage, '2[0-9][0-9]-');
+        assert(result.contract_tp === 220);
         assert(result.qc_tp === null);
     });
 });

+ 48 - 7
test/app/service/tender.test.js

@@ -10,23 +10,64 @@
 
 const { app, assert } = require('egg-mock/bootstrap');
 const tenderConst = require('../../../app/const/tender');
+const addData = {
+    name: 'test_addTender',
+    category: null,
+};
+const mockData = {};
+let testTenderId;
+
 describe('test/app/service/tender.test.js', () => {
 
-    it('test getinfo', function* () {
+    // 准备测试数据,新增测试标段
+    before(function* () {
         const ctx = app.mockContext();
-        const tenderInfo = yield ctx.service.tender.getDataById(14);
-        assert(tenderInfo.id === 14);
-        assert(tenderInfo.name === '测试标段5');
+        // 模拟登录session
+        const postData = {
+            account: '734406061@qq.com',
+            project: 'T201711273363',
+            project_password: 'mai654321',
+        };
+        ctx.session = {};
+        const loginResult = yield ctx.service.projectAccount.accountLogin(postData, 2);
+        assert(loginResult);
+        mockData.session = ctx.session;
+        // 移除以往测试脏数据
+        yield ctx.service.tender.db.delete(ctx.service.tender.tableName, {
+            project_id: ctx.session.sessionProject.id,
+            name: addData.name,
+        });
+    });
+
+    it('test addTender', function* () {
+        const ctx = app.mockContext(mockData);
+        const result = yield ctx.service.tender.add(addData);
+        assert(result);
+        const data = yield ctx.service.tender.getDataByCondition({
+            name: addData.name,
+            project_id: ctx.session.sessionProject.id,
+        });
+        assert(data);
+        testTenderId = data.id;
+    });
+
+    it('test getinfo', function* () {
+        const ctx = app.mockContext(mockData);
+        mockData.data = yield ctx.service.tender.getDataById(testTenderId);
+        assert(mockData.data.id === testTenderId);
+        assert(mockData.data.name === addData.name);
     });
 
     it('save test',function* () {
-        const ctx = app.mockContext();
+        const ctx = app.mockContext(mockData);
         const renderbody = {
             name : '测试标段5',
-            type : 1
+            type: 1,
         };
-        const result = yield ctx.service.tender.save(renderbody,14);
+        const result = yield ctx.service.tender.save(renderbody, testTenderId);
         assert(result);
+        const data = yield ctx.service.tender.getTender(testTenderId);
+        assert(data.name === renderbody.name);
     })
 
 });

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 51746 - 0
test/app/test_file/calc_test.sql