| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 | 'use strict';/** * * * @author Mai * @date * @version */const bc = require('../app/lib/base_calc');const _ = require('lodash');const fs = require('fs');const path = require('path');const mysql = require('mysql');const config = process.argv.splice(2);const mysqlOptions = require(`../config/config.${config}`)({ baseDir: __dirname + '/app', root: __dirname, name: 'calc' }).mysql;const pool = mysql.createPool(mysqlOptions.client);const zeroRange = 0.0000000001;const temp = 'temp';const utils = {    add(num1, num2) {        return bc.add(num1 ? num1 : 0, num2 ? num2 : 0);    },    sub(num1, num2) {        return bc.sub(num1 ? num1 : 0, num2 ? num2 : 0);    },    sum(array) {        let result = 0;        for (const a of array) {            result = this.add(result, a);        }        return result;    },    checkZero(value) {        return value === undefined || value === null || (_.isNumber(value) && Math.abs(value) < zeroRange);    },    checkNumEqual(value1, value2) {        return Math.abs(this.sub(value2, value1)) < zeroRange;    },};const querySql = async function (sql, sqlParam) {    return new Promise(function (resolve, reject) {        pool.getConnection(function (err, conn) {            if (err) {                reject(err);            } else {                conn.query(sql, sqlParam, function (err, rows, fields) {                    //释放连接                    conn.release();                    //传递Promise回调对象                    resolve(rows);                });            }        });    });};const stageSql = 'select * from zh_stage where tid = ? and `order` = ?';const timesLen = 100;const getDelSql = function (table, data) {    const sql = [];    for (const d of data) {        sql.push('DELETE FROM `calculation`.`'+ table + '` WHERE `id`=' + d.id + ';');    }    return sql;};const curBillsSql = function (tid) {    const departTable = 'zh_stage_bills_' + tid % 10;    const sql =        'SELECT Bills.* FROM ' + departTable + ' As Bills ' +        '  INNER JOIN ( ' +        '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `progress`, `lid`, `sid` From ' + departTable +        '      WHERE tid = ? And sid = ?' +        '      GROUP BY `lid`' +        '  ) As MaxFilter ' +        '  ON (Bills.times * ' + timesLen + ' + `order`) = MaxFilter.progress And Bills.lid = MaxFilter.lid And Bills.`sid` = MaxFilter.`sid`';    return sql;};const preBillsSql = function (tid) {    return 'Select * from zh_stage_bills_final_' + (tid % 10) + ' where sid = ?';};const calcBillsFinalData = function (stage, pre, cur) {    if (!cur || cur.length === 0) return pre;    if (!pre || pre.length === 0) return cur;    for (const c of cur) {        delete c.id;        delete c.said;        delete c.times;        delete c.order;        delete c.postil;        c.sorder = stage.order;        const p = pre.find(x => { return x.lid === c.lid; });        if (p) {            c.contract_qty = utils.add(c.contract_qty, p.contract_qty);            c.contract_tp = utils.add(c.contract_tp, p.contract_tp);            c.qc_qty = utils.add(c.qc_qty, p.qc_qty);            c.qc_tp = utils.add(c.qc_tp, p.qc_tp);            c.used = p.used || !utils.checkZero(c.contract_qty) || !utils.checkZero(c.qc_qty)                || !utils.checkZero(c.contract_tp) || !utils.checkZero(c.qc_tp);            pre.splice(pre.indexOf(p), 1);        } else {            c.used = !utils.checkZero(c.contract_qty) || !utils.checkZero(c.qc_qty)                || !utils.checkZero(c.contract_tp) || !utils.checkZero(c.qc_tp);        }    }    for (const p of pre) {        if (p.id !== undefined) delete p.id;        p.sid = stage.id;        p.sorder = stage.order;    }    return cur.concat(pre);};const checkBillsFinal = async function (stage, preStage) {    const curBills = await querySql(curBillsSql(stage.tid), [stage.tid, stage.id]);    const preBills = await querySql(preBillsSql(stage.tid), [preStage.id]);    const checkBills = await calcBillsFinalData(stage, preBills, curBills);    const finalBills = await querySql(preBillsSql(stage.tid), [stage.id]);    console.log(`checkBills(${stage.tid}, ${stage.id}): checkBills ${checkBills.length}, finalBills ${finalBills.length}`);    const error = [];    const tBills = [], fBills = [];    if (finalBills.length > checkBills.length) {        fs.writeFileSync(path.join(__dirname, temp, 'FinalBills_org_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(finalBills, '', '\t'));        fs.writeFileSync(path.join(__dirname, temp, 'FinalBills_check_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(checkBills, '', '\t'));        let show = false;        for (const cb of checkBills) {            let index = finalBills.findIndex(x => { return x.lid === cb.lid });            if (index === -1) error.push(`bills error: ${data.id}(${data.lid})`);            let check = false;            while (index >= 0) {                const data = finalBills[index];                finalBills.splice(index, 1);                if (!check && utils.checkNumEqual(data.contract_qty, cb.contract_qty) &&                    utils.checkNumEqual(data.contract_tp, cb.contract_tp) &&                    utils.checkNumEqual(data.qc_qty, cb.qc_qty) &&                    utils.checkNumEqual(data.qc_tp, cb.qc_tp)) {                    check = true;                    tBills.push(data);                } else {                    if (!show && !check) {                        show = true;                        console.log(data, cb,                            utils.checkNumEqual(data.contract_qty, cb.contract_qty),                            utils.checkNumEqual(data.contract_tp, cb.contract_tp),                            utils.checkNumEqual(data.qc_qty, cb.qc_qty),                            utils.checkNumEqual(data.qc_tp, cb.qc_tp)                        );                    }                    fBills.push(data);                }                index = finalBills.findIndex(x => { return x.lid === cb.lid });            }        }        if (tBills.length !== checkBills.length) console.log('error: ' + stage.tid + ' ' + stage.id);        fs.writeFileSync(path.join(__dirname, temp, 'FinalBills_keep_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(tBills, '', '\t'));        fs.writeFileSync(path.join(__dirname, temp, 'FinalBills_del_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(fBills, '', '\t'));        const sqlList = getDelSql('zh_stage_bills_final_' + (stage.tid % 10), fBills);        fs.writeFileSync(path.join(__dirname, temp, 'FinalBills_del_' + stage.tid + '_' + stage.order + '.sql'), sqlList.join('\n'));        console.log('check: ' + checkBills.length + ' keep: ' + tBills.length + ' del: ' + fBills.length);        if (error.length > 0) fs.writeFileSync(path.join(__dirname, temp, 'FinalBills_error_' + stage.tid + '_' + stage.order + '.log'), error.join('\n'));        for (const sl of sqlList) {            console.log(sl);            await querySql(sl, []);        }    }};const filterLastestData = function(stagePos) {    const stagePosIndex = {};    for (const sp of stagePos) {        const key = 'sp-' + sp.pid;        const spi = stagePosIndex[key];        if (spi) {            if ((spi.times * timesLen + spi.order) < (sp.times * timesLen + sp.order)) stagePosIndex[key] = sp;        } else {            stagePosIndex[key] = sp;        }    }    const result = [];    for (const prop in stagePosIndex) {        result.push(stagePosIndex[prop]);    }    return result;};const getCurPosData = async function (tid, sid) {    const departTable = 'zh_stage_pos_' + tid % 20;    const sql = 'SELECT id, tid, sid, pid, lid, contract_qty, qc_qty, postil, `times`, `order`, `contract_expr`' +        '  FROM ' + departTable +        '  WHERE tid = ? And sid = ? ';    const sqlParam = [tid, sid];    const stagePos = await querySql(sql, sqlParam);    return filterLastestData(stagePos);};const prePosSql = function (tid) {    return 'Select * from zh_stage_pos_final_' + (tid % 20) + ' where sid = ?';};const calcPosFinalData = function (stage, pre, cur) {    if (!cur || cur.length === 0) return pre;    if (!pre || pre.length === 0) return cur;    for (const c of cur) {        delete c.id;        delete c.said;        delete c.times;        delete c.order;        delete c.postil;        c.sorder = stage.order;        const p = pre.find(x => { return x.pid === c.pid; });        if (p) {            c.contract_qty = utils.add(c.contract_qty, p.contract_qty);            c.qc_qty = utils.add(c.qc_qty, p.qc_qty);            c.used = p.used || !utils.checkZero(c.contract_qty) || !utils.checkZero(c.qc_qty);            pre.splice(pre.indexOf(p), 1);        } else {            c.used = !utils.checkZero(c.contract_qty) || !utils.checkZero(c.qc_qty);        }    }    for (const p of pre) {        if (p.id !== undefined) delete p.id;        p.sid = stage.id;        p.sorder = stage.order;    }    return cur.concat(pre);};const findPos = function (arr, pid) {    for (const [i, a] of arr.entries()) {        if (a.pid === pid) return [i, a];    }    return [-1, null];};const checkPosFinal = async function (stage, preStage) {    const curPos = await getCurPosData(stage.tid, stage.id);    const prePos = await querySql(prePosSql(stage.tid), [preStage.id]);    const checkPos = await calcPosFinalData(stage, prePos, curPos);    const finalPos = await querySql(prePosSql(stage.tid), [stage.id]);    console.log(`checkPos(${stage.tid}, ${stage.id}): checkPos ${checkPos.length}, finalPos ${finalPos.length}`);    const tPos = [], fPos = [], error = [];    if (finalPos.length > checkPos.length) {        fs.writeFileSync(path.join(__dirname, temp, 'FinalPos_org_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(finalPos, '', '\t'));        fs.writeFileSync(path.join(__dirname, temp, 'FinalPos_check_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(checkPos, '', '\t'));        for (const cb of checkPos) {            let [index, data] = findPos(finalPos, cb.pid);            if (!data) error.push(`pos error: ${cb.pid}`);            let check = false;            while (data) {                finalPos.splice(index, 1);                if (!check && utils.checkNumEqual(data.contract_qty, cb.contract_qty) &&                    utils.checkNumEqual(data.qc_qty, cb.qc_qty) ) {                    check = true;                    tPos.push(data);                } else {                    fPos.push(data);                }                [index, data] = findPos(finalPos, cb.pid);            }        }        fs.writeFileSync(path.join(__dirname, temp, 'FinalPos_keep_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(tPos, '', '\t'));        fs.writeFileSync(path.join(__dirname, temp, 'FinalPos_del_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(fPos, '', '\t'));        const sqlList = getDelSql('zh_stage_pos_final_' + (stage.tid % 20), fPos);        fs.writeFileSync(path.join(__dirname, temp, 'FinalPos_del_' + stage.tid + '_' + stage.order + '.sql'), sqlList.join('\n'));        console.log('check: ' + checkPos.length + ' keep: ' + tPos.length + ' del: ' + fPos.length);        if (error.length > 0) fs.writeFileSync(path.join(__dirname, temp, 'Pos_error_' + stage.tid + '_' + stage.order + '.log'), error.join('\n'));        if (tPos.length !== checkPos.length) console.log('error tid:' + stage.tid + ' sid:' + stage.id + ' error: ' + error.length);        for (const sl of sqlList) {            console.log(sl);            await querySql(sl, []);        }    }};const checkFinal = async function (tid, o) {    const stage = await querySql(stageSql, [tid, o]);    const preStage = o > 1 ? await querySql(stageSql, [tid, o - 1]) : null;    //await checkBillsFinal(stage[0], preStage[0]);    await checkPosFinal(stage[0], preStage[0]);    pool.end();};//checkFinal(3057, [2, 3]);checkFinal(3003, 8);
 |