Sfoglia il codice sorgente

脚本,修复多次点击审批通过,生成多份截止本期数据

MaiXinRong 4 anni fa
parent
commit
630f7180d3
1 ha cambiato i file con 297 aggiunte e 0 eliminazioni
  1. 297 0
      db_script/checkStageFinal.js

+ 297 - 0
db_script/checkStageFinal.js

@@ -0,0 +1,297 @@
+'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);