| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954 | 'use strict';/** * * * @author Mai * @date * @version */const itemsPre = 'id_';class baseTree {    /**     * 构造函数     */    constructor (ctx, setting) {        this.ctx = ctx;        // 无索引        this.datas = [];        // 以key为索引        this.items = {};        // 以排序为索引        this.nodes = [];        // 根节点        this.children = [];        // 树设置        this.setting = setting;    }    clear() {        // 无索引        this.datas = [];        // 以key为索引        this.items = {};        // 以排序为索引        this.nodes = [];        // 根节点        this.children = [];    }    /**     * 根据id获取树结构节点数据     * @param {Number} id     * @returns {Object}     */    getItems (id) {        return this.items[itemsPre + id];    };    /**     * 查找node的parent     * @param {Object} node     * @returns {Object}     */    getParent (node) {        return this.getItems(node[this.setting.pid]);    };    /**     * 查询node的已下载子节点     * @param {Object} node     * @returns {Array}     */    getChildren (node) {        const setting = this.setting;        const pid = node ? node[setting.id] : setting.rootId;        const children = this.datas.filter(function (x) {            return x[setting.pid] === pid;        });        children.sort(function (a, b) {            return a.order - b.order;        });        return children;    };    /**     * 获取节点的 index     * @param node     * @returns {number}     */    getNodeSerialNo(node) {        return this.nodes.indexOf(node);    }    /**     * 树结构根据显示排序     */    sortTreeNode (isResort) {        const self = this;        const addSortNodes = function (nodes) {            if (!nodes) { return }            for (let i = 0; i < nodes.length; i++) {                self.nodes.push(nodes[i]);                nodes[i].index = self.nodes.length - 1;                if (!isResort) {                    nodes[i].children = self.getChildren(nodes[i]);                } else {                    nodes[i].children.sort(function (a, b) {                        return a.order - b.order;                    })                }                addSortNodes(nodes[i].children);            }        };        this.nodes = [];        if (!isResort) {            this.children = this.getChildren();        } else {            this.children.sort(function (a, b) {                return a.order - b.order;            })        }        addSortNodes(this.children);    }    /**     * 加载数据(初始化), 并给数据添加部分树结构必须数据     * @param datas     */    loadDatas (datas) {        // 清空旧数据        this.items = {};        this.nodes = [];        this.datas = [];        this.children = [];        // 加载全部数据        datas.sort(function (a, b) {            return a.level - b.level;        });        for (const data of datas) {            const keyName = itemsPre + data[this.setting.id];            if (!this.items[keyName]) {                const item = JSON.parse(JSON.stringify(data));                item.children = [];                item.expanded = true;                item.visible = true;                this.items[keyName] = item;                this.datas.push(item);                if (item[this.setting.pid] === this.setting.rootId) {                    this.children.push(item);                } else {                    const parent = this.getParent(item);                    if (parent) {                        parent.children.push(item);                    }                }            }        }        this.children.sort(function (a, b) {            return a.order - b.order;        });        this.sortTreeNode(true);    }    /**     * 递归方式 查询node的已下载的全部后代 (兼容full_path不存在的情况)     * @param node     * @returns {*}     * @private     */    _recursiveGetPosterity (node) {        let posterity = node.children;        for (const c of node.children) {            posterity = posterity.concat(this._recursiveGetPosterity(c));        }        return posterity;    };    /**     * 查询node的已下载的全部后代     * @param {Object} node     * @returns {Array}     */    getPosterity (node) {        const self = this;        let posterity;        if (node.full_path !== '') {            const reg = new RegExp('^' + node.full_path + '-');            posterity = this.datas.filter(function (x) {                return reg.test(x.full_path);            });        } else {            posterity = this._recursiveGetPosterity(node);        }        posterity.sort(function (x, y) {            return self.getNodeSerialNo(x) - self.getNodeSerialNo(y);        });        return posterity;    };    /**     * 根据 字段名称 获取数据     * @param fields     * @returns {Array}     */    getDatas (fields) {        const datas = [];        for (const node of this.nodes) {            if (node.b_code && node.b_code !== '') node.chapter = this.ctx.helper.getChapterCode(node.b_code);            node.is_leaf = !node.children || node.children.length === 0;            const data = {};            for (const field of fields) {                data[field] = node[field];            }            datas.push(data);        }        return datas;    }    /**     * 排除 某些字段 获取数据     * @param fields     * @returns {Array}     */    getDatasWithout (fields, filter) {        const datas = [];        for (const node of this.nodes) {            if (filter && filter(node)) {                continue;            }            if (node.b_code && node.b_code !== '') node.chapter = this.ctx.helper.getChapterCode(node.b_code);            node.is_leaf = !node.children || node.children.length === 0;            const data = {};            for (const field in node) {                if (fields.indexOf(field) === -1) {                    data[field] = node[field];                }            }            datas.push(data);        }        return datas;    }    /**     * 获取默认数据 剔除一些树结构需要的缓存数据     * @returns {Array}     */    getDefaultDatas(filter) {        return this.getDatasWithout(['expanded', 'visible', 'children', 'index'], filter);    }    _mapTreeNode () {        let map = {}, maxLevel = 0;        for (const node of this.nodes) {            let levelArr = map[node.level];            if (!levelArr) {                levelArr = [];                map[node.level] = levelArr;            }            if (node.level > maxLevel) {                maxLevel = node.level;            }            levelArr.push(node);        }        return [maxLevel, map];    }    _calculateNode (node, fun) {        const self = this;        if (node.children && node.children.length > 0) {            const gather = node.children.reduce(function (rst, x) {                const result = {};                for (const cf of self.setting.calcFields) {                    result[cf] = self.ctx.helper.add(rst[cf], x[cf]);                }                return result;            });            // 汇总子项            for (const cf of this.setting.calcFields) {                if (gather[cf]) {                    node[cf] = gather[cf];                } else {                    node[cf] = null;                }            }        }        // 自身运算        if (fun) {            fun(node);        } else if (this.setting.calc) {            this.setting.calc(node, this.ctx.helper);        }    }    calculateAll(fun) {        const [maxLevel, levelMap] = this._mapTreeNode();        for (let i = maxLevel; i >= 0; i--) {            const levelNodes = levelMap[i];            if (levelNodes && levelNodes.length > 0) {                for (const node of levelNodes) {                    this._calculateNode(node, fun);                }            }        }    }}class billsTree extends baseTree {    /**     * 检查节点是否是最底层项目节     * @param node     * @returns {boolean}     */    isLeafXmj(node) {        if (node.b_code && node.b_code !== '') {            return false;        }        for (const child of node.children) {            if (!child.b_code || child.b_code === '') {                return false;            }        }        return true;    }    /**     * 查询最底层项目节(本身或父项)     * @param {Object} node - 查询节点     * @returns {Object}     */    getLeafXmjParent(node) {        let parent = node;        while (parent) {            if (this.isLeafXmj(parent)) {                return parent;            } else {                parent = this.getParent(parent);            }        }        return null;    }}class filterTree extends baseTree {    addData(data, fields) {        const item = {};        for (const prop in data) {            if (fields.indexOf(prop) >= 0) {                item[prop] = data[prop];            }        }        const keyName = itemsPre + item[this.setting.id];        if (!this.items[keyName]) {            item.children = [];            item.is_leaf = true;            item.expanded = true;            item.visible = true;            this.items[keyName] = item;            this.datas.push(item);            if (item[this.setting.pid] === this.setting.rootId) {                this.children.push(item);            } else {                const parent = this.getParent(item);                if (parent) {                    parent.is_leaf = false;                    parent.children.push(item);                }            }        } else {            return this.items[keyName];        }        return item;    }}class filterGatherTree extends baseTree {    clearDatas() {        this.items = {};        this.nodes = [];        this.datas = [];        this.children = [];    }    get newId() {        if (!this._maxId) {            this._maxId = 0;        }        this._maxId++;        return this._maxId;    }    addNode(data, parent) {        data[this.setting.pid] = parent ? parent[this.setting.id] : this.setting.rootId;        let item = this.ctx.helper._.find(this.items, data);        if (item) return item;        item = data;        item.drawing_code = [];        item.memo = [];        item.ex_memo1 = [];        item.ex_memo2 = [];        item.ex_memo3 = [];        item.postil = [];        item[this.setting.id] = this.newId;        const keyName = itemsPre + item[this.setting.id];        item.children = [];        item.is_leaf = true;        item.expanded = true;        item.visible = true;        this.items[keyName] = item;        this.datas.push(item);        if (parent) {            item[this.setting.fullPath] = parent[this.setting.fullPath] + '-' + item[this.setting.id];            item[this.setting.level] = parent[this.setting.level] + 1;            item[this.setting.order] = parent.children.length + 1;            parent.is_leaf = false;            parent.children.push(item);        } else {            item[this.setting.fullPath] = '' + item[this.setting.id];            item[this.setting.level] = 1;            item[this.setting.order] = this.children.length + 1;            this.children.push(item);        }        return item;    }    generateSortNodes() {        const self = this;        const addSortNode = function (node) {            self.nodes.push(node);            for (const c of node.children) {                addSortNode(c);            }        };        this.nodes = [];        for (const n of this.children) {            addSortNode(n);        }    }    sortTreeNodeCustom(fun) {        const sortNodes = function (nodes) {            nodes.sort(fun);            for (const [i, node] of nodes.entries()) {                node.order = i + 1;            }            for (const node of nodes) {                if (node.children && node.children.length > 1) {                    sortNodes(node.children);                }            }        };        this.nodes = [];        this.children = this.getChildren(null);        sortNodes(this.children);        this.generateSortNodes();    }}class gatherTree extends baseTree {    constructor(ctx, setting) {        super(ctx, setting);        this._newId = 1;    }    get newId() {        return this._newId++;    }    loadGatherNode(node, parent, loadFun) {        const siblings = parent ? parent.children : this.children;        let cur = siblings.find(function (x) {            return node.b_code                ? x.b_code === node.b_code && x.name === node.name && x.unit === node.unit && x.unit_price === node.unit_price                : x.code === node.code && x.name === node.name;        });        if (!cur) {            const id = this.newId;            cur = {                id: id,                pid: parent ? parent.id : this.setting.rootId,                full_path: parent ? parent.full_path + '-' + id : '' + id,                level: parent ? parent.level + 1 : 1,                order: siblings.length + 1,                children: [],                code: node.code, b_code: node.b_code, name: node.name,                unit: node.unit, unit_price: node.unit_price,            };            siblings.push(cur);            this.datas.push(cur);        }        loadFun(cur, node);        for (const c of node.children) {            this.loadGatherNode(c, cur, loadFun);        }    }    generateSortNodes() {        const self = this;        const addSortNode = function (node) {            self.nodes.push(node);            for (const c of node.children) {                addSortNode(c);            }        };        this.nodes = [];        for (const n of this.children) {            addSortNode(n);        }    }    loadGatherTree(sourceTree,  loadFun) {        for (const c of sourceTree.children) {            this.loadGatherNode(c, null, loadFun);        }        // todo load Pos Data;    }    resortChildrenByCustom(fun) {        for (const n of this.datas) {            if (n.children && n.children.length > 1) {                n.children.sort(fun);                n.children.forEach((x, i) => { x.order = i + 1; });            }        }        this.generateSortNodes();    }    resortChildrenDefault() {        const helper = this.ctx.helper;        this.resortChildrenByCustom((x, y) => {            const iCode = helper.compareCode(x.code, y.code);            if (iCode) return iCode;            if (!x.name) return -1;            if (!y.name) return 1;            return x.name.localeCompare(y.name);        })    }    calculateSum() {        if (this.setting.calcSum) {            for (const d of this.datas) {                this.setting.calcSum(d, this.count);            }        }    }}class pos {    /**     * 构造函数     * @param {id|Number, masterId|Number} setting     */    constructor (setting) {        // 无索引        this.datas = [];        // 以key为索引        this.items = {};        // 以分类id为索引的有序        this.ledgerPos = {};        // pos设置        this.setting = setting;    }    /**     * 加载部位明细数据     * @param datas     */    loadDatas(datas) {        this.datas = datas;        this.items = {};        this.ledgerPos = {};        for (const data of this.datas) {            const key = itemsPre + data[this.setting.id];            this.items[key] = data;            const masterKey = itemsPre + data[this.setting.ledgerId];            if (!this.ledgerPos[masterKey]) {                this.ledgerPos[masterKey] = [];            }            this.ledgerPos[masterKey].push(data);        }        for (const prop in this.ledgerPos) {            this.resortLedgerPos(this.ledgerPos[prop]);        }    }    getLedgerPos(mid) {        return this.ledgerPos[itemsPre + mid];    }    resortLedgerPos(ledgerPos) {        if (ledgerPos instanceof Array) {            ledgerPos.sort(function (a, b) {                return a.porder - b.porder;            })        }    }    /**     * 计算全部     */    calculateAll(fun) {        const calcFun = fun ? fun : this.setting.calc;        if (!calcFun) return;        for (const pos of this.datas) {            calcFun(pos);        }    }    getDatas () {        return this.datas;    }}class checkData {    constructor(ctx, measureType) {        this.ctx = ctx;        this.checkBills = new billsTree(ctx, { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1 });        this.checkPos = new pos({ id: 'id', ledgerId: 'lid' });        this.checkResult = {            error: [],            source: {                bills: [],                pos: [],            },        };        this.measureType = measureType;    }    _check3f(data, limit, ratio) {        if (limit === 0) {            if (data.contract_tp || data.pre_contract_tp) return 1; // 违规        }        if (limit === 1) {            if (ratio === 0) {                if (!data.contract_tp && !data.pre_contract_tp) return 2; // 漏计            } else {                const tp = this.ctx.helper.mul(data.total_price, this.ctx.helper.div(ratio, 100, 4), this.ctx.tender.info.decimal.tp);                const checkTp = this.ctx.helper.add(data.contract_tp, data.pre_contract_tp);                if (tp > checkTp) return 1; // 违规                if (tp < checkTp) return 2; // 漏计            }        }        return 0; // 合法    }    _check3fQty(data, limit, ratio, unit) {        if (limit === 0) {            if (data.contract_qty || data.qc_qty || data.pre_contract_qty || data.pre_qc_qty) return 1; // 违规        }        if (limit === 1) {            if (!ratio || ratio === 0) {                if (!data.contract_qty && !data.qc_qty && !data.pre_contract_qty && !data.pre_qc_qty) return 2; // 漏计            } else {                const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, unit);                const checkQty = this.ctx.helper.mul(data.quantity, this.ctx.helper.div(ratio, 100, 4), precision.value);                const qty = this.ctx.helper.add(data.contract_qty, data.pre_contract_qty);                if (qty > checkQty) return 1; // 违规                if (qty < checkQty) return 2; // 漏计            }        }        return 0; // 合法    }    _getRatio(type, status) {        const statusConst = type === 'gxby' ? this.ctx.session.sessionProject.gxby_status : this.ctx.session.sessionProject.dagl_status;        const sc = statusConst.find(x => { return x.value === status });        return sc ? sc.ratio : null;    }    _getValid = function (type, status, limit) {        if (limit) {            const statusConst = type === 'gxby' ? this.ctx.session.sessionProject.gxby_status : this.ctx.session.sessionProject.dagl_status;            const sc = statusConst.find(x => { return x.value === status; });            return sc ? (sc.limit ? 1 : 0) : 0;        } else {            return -1;        }    };    _checkLeafBills3fLimit(checkType, bills, checkInfo) {        const over = [], lost = [];        const posRange = this.checkPos.getLedgerPos(bills.id);        if (posRange && posRange.length > 0) {            for (const p of posRange) {                const posCheckInfo = this.ctx.helper._.assign({}, checkInfo);                for (const ct of checkType) {                    if (p[ct + '_limit'] > 0) {                        posCheckInfo[ct + '_limit'] = p[ct + '_limit'];                    }                }                for (const ct of checkType) {                    const checkResult = this._check3fQty(p, this._getValid(ct, p[ct + '_status'], posCheckInfo[ct + '_limit']), this._getRatio(ct, p[ct+'_status']), bills.unit);                    if (checkResult === 1) {                        if (over.indexOf(ct) === -1) over.push(ct);                    }                    if (checkResult === 2) {                        if (lost.indexOf(ct) === -1) lost.push(ct);                    }                }            }        } else {            for (const ct of checkType) {                const checkResult = bills.is_tp                    ? this._check3f(bills, this._getValid(ct, bills[ct + '_status'], checkInfo[ct + '_limit']), this._getRatio(ct, bills[ct+'_status']))                    : this._check3fQty(bills, this._getValid(ct, bills[ct + '_status'], checkInfo[ct + '_limit']), this._getRatio(ct, bills[ct+'_status']), bills.unit);                if (checkResult === 1) {                    if (over.indexOf(ct) === -1) over.push(ct);                }                if (checkResult === 2) {                    if (lost.indexOf(ct) === -1) lost.push(ct);                }            }        }        if (over.length + lost.length > 0) {            for (const o of over) {                this.checkResult.error.push({                    ledger_id: bills.ledger_id,                    b_code: bills.b_code,                    name: bills.name,                    errorType: 's2b_over_' + o,                });            }            for (const l of lost) {                this.checkResult.error.push({                    ledger_id: bills.ledger_id,                    b_code: bills.b_code,                    name: bills.name,                    errorType: 's2b_lost_' + l,                });            }            if (!this.checkResult.source.bills.find(x => {return x.ledger_id === bills.ledger_id})) {                this.checkResult.source.bills.push(bills);                if (posRange && posRange.length > 0) this.checkResult.source.pos.push(...posRange);            }        }    }    _recursiveCheckBills3fLimit(checkType, bills, parentCheckInfo) {        const checkInfo = this.ctx.helper._.assign({}, parentCheckInfo);        for (const ct of checkType) {            if (bills[ct + '_limit'] > 0) {                checkInfo[ct + '_limit'] = bills[ct + '_limit'];            }        }        if (bills.children && bills.children.length > 0) {            for (const c of bills.children) {                this._recursiveCheckBills3fLimit(checkType, c, checkInfo);            }        } else {            this._checkLeafBills3fLimit(checkType, bills, checkInfo);        }    }    loadData(bills, pos) {        this.checkBills.loadDatas(bills);        this.checkPos.loadDatas(pos);    }    checkSibling() {        for (const node of this.checkBills.nodes) {            if (!node.children || node.children.length === 0) continue;            let hasXmj, hasGcl;            for (const child of node.children) {                if (child.b_code) hasXmj = true;                if (!child.b_code) hasGcl = true;            }            if (hasXmj && hasGcl) this.checkResult.error.push({                ledger_id: node.ledger_id,                b_code: node.b_code,                name: node.name,                errorType: 'sibling',            });        }    }    checkSameCode() {        //let xmj = this.checkBills.nodes.filter(x => { return /^((GD*)|G)?[0-9]+/.test(x.code); });        let xmj = [];        const addXmjCheck = function (node) {            if (/^((GD*)|G)?[0-9]+/.test(node.code)) xmj.push(node);            for (const child of node.children) {                addXmjCheck(child);            }        };        for (const topLevel of this.checkBills.children) {            if ([1, 2, 3, 4].indexOf(topLevel.node_type) < 0) continue;            addXmjCheck(topLevel);        }        const xmjPart = {}, xmjIndex = [];        for (const x of xmj) {            if (!xmjPart[x.code]) {                xmjPart[x.code] = [];                xmjIndex.push(x.code);            }            xmjPart[x.code].push(x);        }        for (const x of xmjIndex) {            if (xmjPart[x].length <= 1) continue;            for (const xp of xmjPart[x]) {                this.checkResult.error.push({                    ledger_id: xp.ledger_id,                    b_code: xp.b_code,                    name: xp.name,                    errorType: 'same_code',                })            }        }        let check = null;        while (xmj.length > 0) {            [check, xmj] = this.ctx.helper._.partition(xmj, x => { return x.code === xmj[0].code; });            if (check.length > 1) {                for (const c of check) {                    this.checkResult.error.push({                        ledger_id: c.ledger_id,                        b_code: c.b_code,                        name: c.name,                        errorType: 'same_code',                    })                }            }        }    }    check3fLimit(tender) {        const check = [];        if (tender.s2b_gxby_limit) check.push('gxby');        if (tender.s2b_dagl_limit) check.push('dagl');        if (check.length === 0) return;        for (const b of this.checkBills.children) {            this._recursiveCheckBills3fLimit(check, b, {});        }    }    checkBillsQty(fields) {        for (const b of this.checkBills.nodes) {            if (b.children && b.children.length > 0) continue;            const pr = this.checkPos.getLedgerPos(b.id);            if (!pr || pr.length === 0) continue;            const checkData = {},                calcData = {};            for (const field of fields) {                checkData[field] = b[field] ? b[field] : 0;            }            for (const p of pr) {                for (const field of fields) {                    calcData[field] = this.ctx.helper.add(calcData[field], p[field]);                }            }            if (!this.ctx.helper._.isMatch(checkData, calcData)) {                this.checkResult.error.push({                    ledger_id: b.ledger_id,                    b_code: b.b_code,                    name: b.name,                    errorType: 'qty',                    error: { checkData, calcData },                });                if (!this.checkResult.source.bills.find(x => {return x.ledger_id === b.ledger_id})) {                    this.checkResult.source.bills.push(b);                    for (const p of pr) {                        this.checkResult.source.pos.push(p);                    }                }            }        }    }    checkBillsTp(field, decimal, filter) {        for (const b of this.checkBills.nodes) {            if ((b.children && b.children.length > 0) || !b.check_calc) continue;            if (filter && filter(b)) continue;            const checkData = {}, calcData = {};            for (const f of field) {                checkData[f.tp] = b[f.tp] || 0;                calcData[f.tp] = this.ctx.helper.mul(b.unit_price, b[f.qty], decimal.tp) || 0;            }            if (!this.ctx.helper._.isMatch(checkData, calcData)) {                this.checkResult.error.push({                    ledger_id: b.ledger_id,                    b_code: b.b_code,                    name: b.name,                    errorType: 'tp',                    error: { checkData, calcData },                });                if (!this.checkResult.source.bills.find(x => {return x.ledger_id === b.ledger_id})) {                    this.checkResult.source.bills.push(b);                }            }        }    }    _checkBillsOverRange(bills, posRange, isTz) {        // if (isTz && posRange.length > 0) {        //     for (const p of posRange) {        //         const end_contract_qty = this.add(p.pre_contract_qty, p.contract_qty);        //         if (end_contract_qty > p.quantity) return true;        //     }        //     return false;        // } else {        //     const end_qc_qty = this.add(bills.qc_qty, bills.pre_qc_qty);        //     const end_qc_tp = this.add(bills.qc_tp, bills.pre_qc_tp);        //     const end_gather_qty = this.sum([bills.contract_qty, bills.pre_contract_qty, end_qc_qty]);        //     const end_gather_tp = this.sum([bills.contract_tp, bills.pre_contract_tp, end_qc_tp]);        //     if (isTz) {        //         if (end_gather_qty) {        //             return !bills.quantity || Math.abs(end_gather_qty) > Math.abs(this.add(bills.quantity, end_qc_qty));        //         } else if (end_gather_tp) {        //             return !bills.total_price || Math.abs(end_gather_tp) > Math.abs(this.add(bills.total_price, end_qc_tp));        //         }        //     } else {        //         if (end_gather_qty) {        //             return !bills.deal_qty || Math.abs(end_gather_qty) > Math.abs(this.add(bills.deal_qty, end_qc_qty));        //         } else if (end_gather_tp) {        //             return !bills.deal_tp || Math.abs(end_gather_tp) > Math.abs(this.add(bills.deal_tp, end_qc_tp));        //         }        //     }        // }        if (isTz && posRange.length > 0) {            if (posRange.length > 0) {                for (const p of posRange) {                    const end_contract_qty = this.ctx.helper.add(p.pre_contract_qty, p.contract_qty);                    if (!p.quantity && !!end_contract_qty) return true;                    if (p.quantity > 0) {                        if (end_contract_qty > p.quantity) return true;                    } else {                        if (end_contract_qty < p.quantity || end_contract_qty > 0) return true;                    }                }                return false;            }        } else {            const end_contract_qty = this.ctx.helper.add(bills.contract_qty, bills.pre_contract_qty);            const end_contract_tp = this.ctx.helper.add(bills.contract_tp, bills.pre_contract_tp);            if (bills.is_tp) {                const compare_tp = isTz ? bills.total_price : bills.deal_tp;                if (!compare_tp) return !!end_contract_tp;                return compare_tp >= 0 ? end_contract_tp > compare_tp : end_contract_tp < compare_tp || end_contract_tp > 0;            } else {                const compare_qty = isTz ? bills.quantity : bills.deal_qty;                if (!compare_qty) return !!end_contract_qty;                return compare_qty >= 0 ? end_contract_qty > compare_qty : end_contract_qty < compare_qty || end_contract_qty > 0;            }        }    }    checkOverRange() {        const isTz = this.ctx.tender.data.measure_type === this.measureType.tz.value;        for (const b of this.checkBills.nodes) {            if (b.children && b.children.length > 0) continue;            const pr = this.checkPos.getLedgerPos(b.id) || [];            if (this._checkBillsOverRange(b, pr, isTz)) {                this.checkResult.error.push({                    ledger_id: b.ledger_id,                    b_code: b.b_code,                    name: b.name,                    errorType: 'over',                });                if (!this.checkResult.source.bills.find(x => {return x.ledger_id === b.ledger_id})) {                    this.checkResult.source.bills.push(b);                    if (pr.length > 0) this.checkResult.source.pos.push(...pr);                }            }        }    }}module.exports = {    billsTree,    pos,    filterTree,    filterGatherTree,    gatherTree,    checkData,};
 |