purge-flow-test-data.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /**
  2. * 清空流程测试相关 DMS 数据,便于重新走全流程。
  3. *
  4. * 说明:远端 delContentById 接口参数有缺陷无法物理删;
  5. * 这里将 state 置为 -1(业务查询固定 states=0,列表不可见,等同清空)。
  6. *
  7. * 处理栏目:批次 / 发放明细 / 批次统计 / 流程日志 / 告警 / 金额标准
  8. * 保留:区划、人员
  9. *
  10. * 用法:
  11. * node purge-flow-test-data.js
  12. * node purge-flow-test-data.js --seed-standards
  13. */
  14. const http = require("http");
  15. const qs = require("querystring");
  16. const fs = require("fs");
  17. const path = require("path");
  18. const HOST = "121.43.55.7";
  19. const PORT = 2101;
  20. const SEED_STANDARDS = process.argv.includes("--seed-standards") || !process.argv.includes("--no-seed");
  21. const TARGETS = [
  22. { key: "pcb", name: "批次", columnId: 1845, modelId: 1968 },
  23. { key: "ffmx", name: "发放明细", columnId: 1849, modelId: 1974 },
  24. { key: "pctj", name: "批次统计", columnId: 1846, modelId: 1969 },
  25. { key: "lcb", name: "流程/特殊业务/待补发", columnId: 1844, modelId: 1967 },
  26. { key: "alart", name: "告警", columnId: 1841, modelId: 1964 },
  27. { key: "jebz", name: "金额标准", columnId: 1843, modelId: 1966 },
  28. ];
  29. function request(method, urlPath, fields, token) {
  30. return new Promise((resolve, reject) => {
  31. const body = qs.stringify(fields || {});
  32. const headers = {
  33. "Content-Type": "application/x-www-form-urlencoded",
  34. "Content-Length": Buffer.byteLength(body),
  35. };
  36. if (token) {
  37. headers.Token = token;
  38. headers.token = token;
  39. }
  40. const req = http.request(
  41. { hostname: HOST, port: PORT, path: urlPath, method: method || "POST", headers },
  42. (res) => {
  43. let data = "";
  44. res.on("data", (c) => (data += c));
  45. res.on("end", () => {
  46. try {
  47. resolve(JSON.parse(data));
  48. } catch (e) {
  49. resolve({ raw: data, status: res.statusCode });
  50. }
  51. });
  52. }
  53. );
  54. req.on("error", reject);
  55. req.write(body);
  56. req.end();
  57. });
  58. }
  59. async function login() {
  60. const res = await request("POST", "/proxy_oauth/user/login", {
  61. userName: "user_liu",
  62. password: "WE176852439@lmx",
  63. clientId: "1",
  64. });
  65. if (res.code != 200) throw new Error("login fail: " + JSON.stringify(res));
  66. return res.message;
  67. }
  68. async function listAll(token, col) {
  69. const rows = [];
  70. for (let page = 0; page < 80; page++) {
  71. const res = await request(
  72. "POST",
  73. "/proxy_dms/content/selectContentList",
  74. {
  75. columnId: String(col.columnId),
  76. modelId: String(col.modelId),
  77. page: String(page),
  78. pageSize: "100",
  79. states: "0",
  80. },
  81. token
  82. );
  83. // 202 = 无数据
  84. if (res.code == 202) break;
  85. if (res.code != 200) {
  86. throw new Error("list " + col.key + " fail: " + JSON.stringify(res).slice(0, 300));
  87. }
  88. const data = (res.content && res.content.data) || [];
  89. rows.push.apply(rows, data);
  90. const count = Number((res.content && res.content.count) || 0);
  91. if (rows.length >= count || data.length === 0) break;
  92. }
  93. return rows;
  94. }
  95. async function softDelete(token, col, id) {
  96. return request(
  97. "POST",
  98. "/proxy_dms/content/updateContent",
  99. {
  100. columnId: String(col.columnId),
  101. modelId: String(col.modelId),
  102. content: JSON.stringify({
  103. id: id,
  104. state: -1,
  105. c_remarks: "FLOW_TEST_PURGED|" + Date.now(),
  106. }),
  107. },
  108. token
  109. );
  110. }
  111. async function seedYearlyStandards(token) {
  112. const towns = [
  113. { code: "T_YEXIE", name: "叶榭镇" },
  114. { code: "T_SHESHAN", name: "佘山镇" },
  115. { code: "T_CHEDUN", name: "车墩镇" },
  116. { code: "T_SHIHUDANG", name: "石湖荡镇" },
  117. { code: "T_MAOGANG", name: "泖港镇" },
  118. { code: "T_XINBANG", name: "新浜镇" },
  119. { code: "T_XIAOKUNSHAN", name: "小昆山镇" },
  120. ];
  121. const now = Date.now();
  122. const ids = [];
  123. for (const t of towns) {
  124. const content = {
  125. title: t.name + "-年度标准",
  126. c_town_id: t.code,
  127. c_amount: 1280,
  128. c_funeral_amount: 6000,
  129. c_date_time: now,
  130. c_standard_type: "YEARLY_ADJUST",
  131. c_current_flag: "true",
  132. c_adjust_reason: "流程测试初始年度标准",
  133. c_remarks: "FLOW_TEST_RESET|YEARLY_ADJUST|" + t.code,
  134. content: "FLOW_TEST_RESET",
  135. };
  136. const res = await request(
  137. "POST",
  138. "/proxy_dms/content/addContent",
  139. {
  140. columnId: "1843",
  141. modelId: "1966",
  142. content: JSON.stringify(content),
  143. },
  144. token
  145. );
  146. if (res.code == 200) {
  147. ids.push({ townId: t.code, id: res.content });
  148. console.log(" + standard", t.code, res.content);
  149. } else {
  150. console.log(" x standard", t.code, res.code, res.message);
  151. }
  152. }
  153. return ids;
  154. }
  155. (async () => {
  156. const token = await login();
  157. console.log("login ok; seedStandards=", SEED_STANDARDS);
  158. const summary = {
  159. mode: "soft-delete state=-1",
  160. deleted: {},
  161. kept: ["xzqh(区划)", "ryjbxx(人员)"],
  162. seededStandards: [],
  163. };
  164. for (const col of TARGETS) {
  165. const rows = await listAll(token, col);
  166. console.log("\n[" + col.key + "] " + col.name + " count=" + rows.length);
  167. let ok = 0;
  168. let fail = 0;
  169. const errors = [];
  170. for (const row of rows) {
  171. if (!row.id) continue;
  172. const res = await softDelete(token, col, row.id);
  173. if (res.code == 200) ok++;
  174. else {
  175. fail++;
  176. if (errors.length < 5) errors.push({ id: row.id, code: res.code, message: res.message });
  177. }
  178. }
  179. const left = await listAll(token, col);
  180. summary.deleted[col.key] = {
  181. name: col.name,
  182. before: rows.length,
  183. deleted: ok,
  184. failed: fail,
  185. left: left.length,
  186. sampleErrors: errors,
  187. };
  188. console.log(" purged=" + ok + " failed=" + fail + " left=" + left.length);
  189. }
  190. if (SEED_STANDARDS) {
  191. console.log("\n[seed] 写入干净年度标准(土地1280 + 丧葬6000)…");
  192. summary.seededStandards = await seedYearlyStandards(token);
  193. }
  194. const outPath = path.join(__dirname, "purge-flow-test-data-result.json");
  195. fs.writeFileSync(outPath, JSON.stringify(summary, null, 2), "utf8");
  196. console.log("\nDONE ->", outPath);
  197. const anyLeft = Object.keys(summary.deleted).some((k) => summary.deleted[k].left > 0);
  198. const anyFail = Object.keys(summary.deleted).some((k) => summary.deleted[k].failed > 0);
  199. if (anyLeft || anyFail) {
  200. console.error("仍有残留或失败,请检查结果文件");
  201. process.exit(2);
  202. }
  203. console.log("\n已清空流程数据;保留区划与人员。可开始重新测试。");
  204. })().catch((e) => {
  205. console.error(e);
  206. process.exit(1);
  207. });