|
@@ -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);
|