| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- /**
- * 清理发放年月脏数据(如 249241 → 界面显示 2492-41,或 202699 非法月份)。
- *
- * 判定:c_pay_month / payMonth 不是 2020–2030 年合法 yyyyMM。
- * 处理:调用线上 POST /api/batches/{id}/purge(明细软摘离 + 批次标记 DELETED)。
- *
- * 用法:node scripts/cleanup-invalid-paymonth.js
- * 可选:BASE=http://localhost:8088/sjnmtybt node scripts/cleanup-invalid-paymonth.js
- */
- const http = require("http");
- const qs = require("querystring");
- const BASE = process.env.BASE || "http://121.43.55.7:11091/sjnmtybt";
- const DMS_HOST = "121.43.55.7";
- const DMS_PORT = 2101;
- const STAT_COL = { columnId: 1846, modelId: 1969 };
- function isValidPayMonth(v) {
- const s = String(v || "").replace(/-/g, "");
- if (!/^[0-9]{6}$/.test(s)) return false;
- const y = +s.slice(0, 4);
- const m = +s.slice(4, 6);
- return y >= 2020 && y <= 2030 && m >= 1 && m <= 12;
- }
- function api(method, path, body) {
- return new Promise((resolve, reject) => {
- const u = new URL(BASE + path);
- const data = body == null ? null : JSON.stringify(body);
- const headers = { Accept: "application/json" };
- if (data) {
- headers["Content-Type"] = "application/json";
- headers["Content-Length"] = Buffer.byteLength(data);
- }
- const req = http.request(
- {
- hostname: u.hostname,
- port: u.port,
- path: u.pathname + u.search,
- method,
- headers,
- },
- (res) => {
- let raw = "";
- res.on("data", (c) => (raw += c));
- res.on("end", () => {
- try {
- resolve(JSON.parse(raw));
- } catch (e) {
- resolve({ code: res.statusCode, raw: String(raw).slice(0, 300) });
- }
- });
- }
- );
- req.on("error", reject);
- if (data) req.write(data);
- req.end();
- });
- }
- function dms(path, fields, token) {
- return new Promise((resolve, reject) => {
- const body = qs.stringify(fields || {});
- const headers = {
- "Content-Type": "application/x-www-form-urlencoded",
- "Content-Length": Buffer.byteLength(body),
- };
- if (token) {
- headers.Token = token;
- headers.token = token;
- }
- const req = http.request(
- { hostname: DMS_HOST, port: DMS_PORT, path, method: "POST", headers },
- (res) => {
- let raw = "";
- res.on("data", (c) => (raw += c));
- res.on("end", () => {
- try {
- resolve(JSON.parse(raw));
- } catch (e) {
- resolve({ raw: String(raw).slice(0, 200) });
- }
- });
- }
- );
- req.on("error", reject);
- req.write(body);
- req.end();
- });
- }
- async function login() {
- const res = await dms("/proxy_oauth/user/login", {
- userName: "user_liu",
- password: "WE176852439@lmx",
- clientId: "1",
- });
- if (res.code != 200) throw new Error("login fail: " + JSON.stringify(res));
- return res.message;
- }
- async function listBatches() {
- const all = [];
- for (let pageNum = 1; pageNum <= 20; pageNum++) {
- const res = await api("POST", "/api/batches/page", {
- pageNum,
- pageSize: 100,
- });
- const list = (res.data && res.data.list) || [];
- all.push.apply(all, list);
- if (list.length < 100) break;
- }
- return all;
- }
- async function neutralizeStat(token, row) {
- return dms(
- "/proxy_dms/content/updateContent",
- {
- columnId: String(STAT_COL.columnId),
- modelId: String(STAT_COL.modelId),
- content: JSON.stringify({
- id: row.id,
- state: -1,
- c_batch_id: "REMOVED|" + row.id,
- c_pay_month: "000000",
- c_remarks: "INVALID_PAYMONTH_CLEANED|" + Date.now(),
- }),
- },
- token
- );
- }
- async function cleanStats(token, dirtyBatchIds) {
- const idSet = new Set(dirtyBatchIds);
- let cleaned = 0;
- for (let page = 0; page < 40; page++) {
- const res = await dms(
- "/proxy_dms/content/selectContentList",
- {
- columnId: String(STAT_COL.columnId),
- modelId: String(STAT_COL.modelId),
- page: String(page),
- pageSize: "100",
- states: "0,1,2,3",
- },
- token
- );
- const data = (res.content && res.content.data) || [];
- for (const row of data) {
- const bid = String(row.c_batch_id || "");
- const pm = row.c_pay_month;
- const hit = idSet.has(bid) || !isValidPayMonth(pm);
- if (!hit) continue;
- const r = await neutralizeStat(token, row);
- if (r && r.code == 200) {
- cleaned++;
- console.log("stat OK", row.id, "batch=" + bid, "pm=" + pm);
- } else {
- console.log("stat FAIL", row.id, JSON.stringify(r).slice(0, 160));
- }
- }
- if (data.length < 100) break;
- }
- return cleaned;
- }
- (async () => {
- console.log("BASE=" + BASE);
- const batches = await listBatches();
- const dirty = batches.filter((b) => !isValidPayMonth(b.payMonth));
- const months = [...new Set(dirty.map((b) => b.payMonth))].sort();
- console.log(
- "列表批次=" + batches.length + " 脏批次=" + dirty.length + " 非法月份=" + months.join(",")
- );
- let ok = 0;
- let fail = 0;
- const purgedIds = [];
- for (const b of dirty) {
- const id = b.id || b.batchNo;
- const res = await api("POST", "/api/batches/" + encodeURIComponent(id) + "/purge", null);
- if (res && res.code == 200 && res.data && res.data.ok !== false) {
- ok++;
- purgedIds.push(id);
- console.log(
- "purge OK",
- id,
- "pm=" + b.payMonth,
- "detached=" + (res.data.detachedPayments || 0)
- );
- } else {
- fail++;
- console.log("purge FAIL", id, "pm=" + b.payMonth, JSON.stringify(res).slice(0, 220));
- }
- }
- const token = await login();
- const stats = await cleanStats(token, purgedIds);
- const after = await listBatches();
- const stillDirty = after.filter((b) => !isValidPayMonth(b.payMonth));
- console.log(
- "完成 purgeOk=" +
- ok +
- " purgeFail=" +
- fail +
- " statsCleaned=" +
- stats +
- " 剩余列表=" +
- after.length +
- " 仍脏=" +
- stillDirty.length
- );
- if (stillDirty.length) {
- console.log(
- "仍脏样例",
- stillDirty.slice(0, 10).map((b) => ({ id: b.id, pm: b.payMonth, no: b.batchNo }))
- );
- }
- })().catch((e) => {
- console.error(e);
- process.exit(1);
- });
|