checkStageFinal.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author Mai
  6. * @date
  7. * @version
  8. */
  9. const bc = require('../app/lib/base_calc');
  10. const _ = require('lodash');
  11. const fs = require('fs');
  12. const path = require('path');
  13. const mysql = require('mysql');
  14. const config = process.argv.splice(2);
  15. const mysqlOptions = require(`../config/config.${config}`)({ baseDir: __dirname + '/app', root: __dirname, name: 'calc' }).mysql;
  16. const pool = mysql.createPool(mysqlOptions.client);
  17. const zeroRange = 0.0000000001;
  18. const temp = 'temp';
  19. const utils = {
  20. add(num1, num2) {
  21. return bc.add(num1 ? num1 : 0, num2 ? num2 : 0);
  22. },
  23. sub(num1, num2) {
  24. return bc.sub(num1 ? num1 : 0, num2 ? num2 : 0);
  25. },
  26. sum(array) {
  27. let result = 0;
  28. for (const a of array) {
  29. result = this.add(result, a);
  30. }
  31. return result;
  32. },
  33. checkZero(value) {
  34. return value === undefined || value === null || (_.isNumber(value) && Math.abs(value) < zeroRange);
  35. },
  36. checkNumEqual(value1, value2) {
  37. return Math.abs(this.sub(value2, value1)) < zeroRange;
  38. },
  39. };
  40. const querySql = async function (sql, sqlParam) {
  41. return new Promise(function (resolve, reject) {
  42. pool.getConnection(function (err, conn) {
  43. if (err) {
  44. reject(err);
  45. } else {
  46. conn.query(sql, sqlParam, function (err, rows, fields) {
  47. //释放连接
  48. conn.release();
  49. //传递Promise回调对象
  50. resolve(rows);
  51. });
  52. }
  53. });
  54. });
  55. };
  56. const stageSql = 'select * from zh_stage where tid = ? and `order` = ?';
  57. const timesLen = 100;
  58. const getDelSql = function (table, data) {
  59. const sql = [];
  60. for (const d of data) {
  61. sql.push('DELETE FROM `calculation`.`'+ table + '` WHERE `id`=' + d.id + ';');
  62. }
  63. return sql;
  64. };
  65. const curBillsSql = function (tid) {
  66. const departTable = 'zh_stage_bills_' + tid % 10;
  67. const sql =
  68. 'SELECT Bills.* FROM ' + departTable + ' As Bills ' +
  69. ' INNER JOIN ( ' +
  70. ' SELECT MAX(`times` * ' + timesLen + ' + `order`) As `progress`, `lid`, `sid` From ' + departTable +
  71. ' WHERE tid = ? And sid = ?' +
  72. ' GROUP BY `lid`' +
  73. ' ) As MaxFilter ' +
  74. ' ON (Bills.times * ' + timesLen + ' + `order`) = MaxFilter.progress And Bills.lid = MaxFilter.lid And Bills.`sid` = MaxFilter.`sid`';
  75. return sql;
  76. };
  77. const preBillsSql = function (tid) {
  78. return 'Select * from zh_stage_bills_final_' + (tid % 10) + ' where sid = ?';
  79. };
  80. const calcBillsFinalData = function (stage, pre, cur) {
  81. if (!cur || cur.length === 0) return pre;
  82. if (!pre || pre.length === 0) return cur;
  83. for (const c of cur) {
  84. delete c.id;
  85. delete c.said;
  86. delete c.times;
  87. delete c.order;
  88. delete c.postil;
  89. c.sorder = stage.order;
  90. const p = pre.find(x => { return x.lid === c.lid; });
  91. if (p) {
  92. c.contract_qty = utils.add(c.contract_qty, p.contract_qty);
  93. c.contract_tp = utils.add(c.contract_tp, p.contract_tp);
  94. c.qc_qty = utils.add(c.qc_qty, p.qc_qty);
  95. c.qc_tp = utils.add(c.qc_tp, p.qc_tp);
  96. c.used = p.used || !utils.checkZero(c.contract_qty) || !utils.checkZero(c.qc_qty)
  97. || !utils.checkZero(c.contract_tp) || !utils.checkZero(c.qc_tp);
  98. pre.splice(pre.indexOf(p), 1);
  99. } else {
  100. c.used = !utils.checkZero(c.contract_qty) || !utils.checkZero(c.qc_qty)
  101. || !utils.checkZero(c.contract_tp) || !utils.checkZero(c.qc_tp);
  102. }
  103. }
  104. for (const p of pre) {
  105. if (p.id !== undefined) delete p.id;
  106. p.sid = stage.id;
  107. p.sorder = stage.order;
  108. }
  109. return cur.concat(pre);
  110. };
  111. const checkBillsFinal = async function (stage, preStage) {
  112. const curBills = await querySql(curBillsSql(stage.tid), [stage.tid, stage.id]);
  113. const preBills = await querySql(preBillsSql(stage.tid), [preStage.id]);
  114. const checkBills = await calcBillsFinalData(stage, preBills, curBills);
  115. const finalBills = await querySql(preBillsSql(stage.tid), [stage.id]);
  116. console.log(`checkBills(${stage.tid}, ${stage.id}): checkBills ${checkBills.length}, finalBills ${finalBills.length}`);
  117. const error = [];
  118. const tBills = [], fBills = [];
  119. if (finalBills.length > checkBills.length) {
  120. fs.writeFileSync(path.join(__dirname, temp, 'FinalBills_org_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(finalBills, '', '\t'));
  121. fs.writeFileSync(path.join(__dirname, temp, 'FinalBills_check_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(checkBills, '', '\t'));
  122. let show = false;
  123. for (const cb of checkBills) {
  124. let index = finalBills.findIndex(x => { return x.lid === cb.lid });
  125. if (index === -1) error.push(`bills error: ${data.id}(${data.lid})`);
  126. let check = false;
  127. while (index >= 0) {
  128. const data = finalBills[index];
  129. finalBills.splice(index, 1);
  130. if (!check && utils.checkNumEqual(data.contract_qty, cb.contract_qty) &&
  131. utils.checkNumEqual(data.contract_tp, cb.contract_tp) &&
  132. utils.checkNumEqual(data.qc_qty, cb.qc_qty) &&
  133. utils.checkNumEqual(data.qc_tp, cb.qc_tp)) {
  134. check = true;
  135. tBills.push(data);
  136. } else {
  137. if (!show && !check) {
  138. show = true;
  139. console.log(data, cb,
  140. utils.checkNumEqual(data.contract_qty, cb.contract_qty),
  141. utils.checkNumEqual(data.contract_tp, cb.contract_tp),
  142. utils.checkNumEqual(data.qc_qty, cb.qc_qty),
  143. utils.checkNumEqual(data.qc_tp, cb.qc_tp)
  144. );
  145. }
  146. fBills.push(data);
  147. }
  148. index = finalBills.findIndex(x => { return x.lid === cb.lid });
  149. }
  150. }
  151. if (tBills.length !== checkBills.length) console.log('error: ' + stage.tid + ' ' + stage.id);
  152. fs.writeFileSync(path.join(__dirname, temp, 'FinalBills_keep_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(tBills, '', '\t'));
  153. fs.writeFileSync(path.join(__dirname, temp, 'FinalBills_del_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(fBills, '', '\t'));
  154. const sqlList = getDelSql('zh_stage_bills_final_' + (stage.tid % 10), fBills);
  155. fs.writeFileSync(path.join(__dirname, temp, 'FinalBills_del_' + stage.tid + '_' + stage.order + '.sql'), sqlList.join('\n'));
  156. console.log('check: ' + checkBills.length + ' keep: ' + tBills.length + ' del: ' + fBills.length);
  157. if (error.length > 0) fs.writeFileSync(path.join(__dirname, temp, 'FinalBills_error_' + stage.tid + '_' + stage.order + '.log'), error.join('\n'));
  158. for (const sl of sqlList) {
  159. console.log(sl);
  160. await querySql(sl, []);
  161. }
  162. }
  163. };
  164. const filterLastestData = function(stagePos) {
  165. const stagePosIndex = {};
  166. for (const sp of stagePos) {
  167. const key = 'sp-' + sp.pid;
  168. const spi = stagePosIndex[key];
  169. if (spi) {
  170. if ((spi.times * timesLen + spi.order) < (sp.times * timesLen + sp.order)) stagePosIndex[key] = sp;
  171. } else {
  172. stagePosIndex[key] = sp;
  173. }
  174. }
  175. const result = [];
  176. for (const prop in stagePosIndex) {
  177. result.push(stagePosIndex[prop]);
  178. }
  179. return result;
  180. };
  181. const getCurPosData = async function (tid, sid) {
  182. const departTable = 'zh_stage_pos_' + tid % 20;
  183. const sql = 'SELECT id, tid, sid, pid, lid, contract_qty, qc_qty, postil, `times`, `order`, `contract_expr`' +
  184. ' FROM ' + departTable +
  185. ' WHERE tid = ? And sid = ? ';
  186. const sqlParam = [tid, sid];
  187. const stagePos = await querySql(sql, sqlParam);
  188. return filterLastestData(stagePos);
  189. };
  190. const prePosSql = function (tid) {
  191. return 'Select * from zh_stage_pos_final_' + (tid % 20) + ' where sid = ?';
  192. };
  193. const calcPosFinalData = function (stage, pre, cur) {
  194. if (!cur || cur.length === 0) return pre;
  195. if (!pre || pre.length === 0) return cur;
  196. for (const c of cur) {
  197. delete c.id;
  198. delete c.said;
  199. delete c.times;
  200. delete c.order;
  201. delete c.postil;
  202. c.sorder = stage.order;
  203. const p = pre.find(x => { return x.pid === c.pid; });
  204. if (p) {
  205. c.contract_qty = utils.add(c.contract_qty, p.contract_qty);
  206. c.qc_qty = utils.add(c.qc_qty, p.qc_qty);
  207. c.used = p.used || !utils.checkZero(c.contract_qty) || !utils.checkZero(c.qc_qty);
  208. pre.splice(pre.indexOf(p), 1);
  209. } else {
  210. c.used = !utils.checkZero(c.contract_qty) || !utils.checkZero(c.qc_qty);
  211. }
  212. }
  213. for (const p of pre) {
  214. if (p.id !== undefined) delete p.id;
  215. p.sid = stage.id;
  216. p.sorder = stage.order;
  217. }
  218. return cur.concat(pre);
  219. };
  220. const findPos = function (arr, pid) {
  221. for (const [i, a] of arr.entries()) {
  222. if (a.pid === pid) return [i, a];
  223. }
  224. return [-1, null];
  225. };
  226. const checkPosFinal = async function (stage, preStage) {
  227. const curPos = await getCurPosData(stage.tid, stage.id);
  228. const prePos = await querySql(prePosSql(stage.tid), [preStage.id]);
  229. const checkPos = await calcPosFinalData(stage, prePos, curPos);
  230. const finalPos = await querySql(prePosSql(stage.tid), [stage.id]);
  231. console.log(`checkPos(${stage.tid}, ${stage.id}): checkPos ${checkPos.length}, finalPos ${finalPos.length}`);
  232. const tPos = [], fPos = [], error = [];
  233. if (finalPos.length > checkPos.length) {
  234. fs.writeFileSync(path.join(__dirname, temp, 'FinalPos_org_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(finalPos, '', '\t'));
  235. fs.writeFileSync(path.join(__dirname, temp, 'FinalPos_check_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(checkPos, '', '\t'));
  236. for (const cb of checkPos) {
  237. let [index, data] = findPos(finalPos, cb.pid);
  238. if (!data) error.push(`pos error: ${cb.pid}`);
  239. let check = false;
  240. while (data) {
  241. finalPos.splice(index, 1);
  242. if (!check && utils.checkNumEqual(data.contract_qty, cb.contract_qty) &&
  243. utils.checkNumEqual(data.qc_qty, cb.qc_qty) ) {
  244. check = true;
  245. tPos.push(data);
  246. } else {
  247. fPos.push(data);
  248. }
  249. [index, data] = findPos(finalPos, cb.pid);
  250. }
  251. }
  252. fs.writeFileSync(path.join(__dirname, temp, 'FinalPos_keep_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(tPos, '', '\t'));
  253. fs.writeFileSync(path.join(__dirname, temp, 'FinalPos_del_' + stage.tid + '_' + stage.order + '.json'), JSON.stringify(fPos, '', '\t'));
  254. const sqlList = getDelSql('zh_stage_pos_final_' + (stage.tid % 20), fPos);
  255. fs.writeFileSync(path.join(__dirname, temp, 'FinalPos_del_' + stage.tid + '_' + stage.order + '.sql'), sqlList.join('\n'));
  256. console.log('check: ' + checkPos.length + ' keep: ' + tPos.length + ' del: ' + fPos.length);
  257. if (error.length > 0) fs.writeFileSync(path.join(__dirname, temp, 'Pos_error_' + stage.tid + '_' + stage.order + '.log'), error.join('\n'));
  258. if (tPos.length !== checkPos.length) console.log('error tid:' + stage.tid + ' sid:' + stage.id + ' error: ' + error.length);
  259. for (const sl of sqlList) {
  260. console.log(sl);
  261. await querySql(sl, []);
  262. }
  263. }
  264. };
  265. const checkFinal = async function (tid, o) {
  266. const stage = await querySql(stageSql, [tid, o]);
  267. const preStage = o > 1 ? await querySql(stageSql, [tid, o - 1]) : null;
  268. //await checkBillsFinal(stage[0], preStage[0]);
  269. await checkPosFinal(stage[0], preStage[0]);
  270. pool.end();
  271. };
  272. //checkFinal(3057, [2, 3]);
  273. checkFinal(3003, 8);