| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- 'use strict';
- // 先手动增加 audit_order、audit_type 字段。
- // node db_script/bak/advance_audit_order.js uat [--tid=标段ID] [--vid=预付款ID] [--apply]
- // 默认预览,--apply 写入;逐期逐轮按 order 排序、按人员去重回填。
- const common = require('../../app/const/audit').auditType.key.common;
- function buildUpdates(rows) {
- const sorted = rows.slice().sort((a, b) => a.order - b.order || a.id - b.id);
- const ids = [];
- sorted.forEach(row => { if (!ids.includes(row.audit_id)) ids.push(row.audit_id); });
- if (sorted.some(row => (row.audit_order > 0 && row.audit_order !== ids.indexOf(row.audit_id) + 1) ||
- (row.audit_type > 0 && row.audit_type !== common))) {
- return { skip: '已有节点序号或审批类型冲突,请人工核对' };
- }
- return { updates: sorted.filter(row => !(row.audit_order > 0) || !(row.audit_type > 0)).map(row => ({
- id: row.id, audit_id: row.audit_id,
- before: { audit_order: row.audit_order, audit_type: row.audit_type },
- audit_order: ids.indexOf(row.audit_id) + 1, audit_type: common,
- })) };
- }
- async function main() {
- const env = process.argv[2];
- if (!['local', 'uat', 'default'].includes(env)) throw new Error('环境仅支持 local / uat / default');
- const filters = {};
- let apply = false;
- for (const arg of process.argv.slice(3)) {
- if (arg === '--apply') { apply = true; continue; }
- const match = /^--(vid|tid)=(\d+)$/.exec(arg);
- if (!match || !Number.isSafeInteger(Number(match[2])) || Number(match[2]) <= 0) throw new Error('无效参数:' + arg);
- filters[match[1]] = Number(match[2]);
- }
- const mysql = require('mysql');
- // 使用与 baseUtils 相同的配置入口,独立连接确保每轮更新处于同一事务。
- const path = require('path');
- const root = path.resolve(__dirname, '../..');
- const config = require(path.join(root, 'config/config.' + env))({ baseDir: root, root, name: 'calc' });
- const connection = mysql.createConnection(config.mysql.client);
- const query = (sql, params = []) => new Promise((resolve, reject) => {
- connection.query(sql, params, (err, rows) => err ? reject(err) : resolve(rows));
- });
- const log = data => {
- console.log(JSON.stringify(data));
- };
- try {
- const columns = await query('SHOW COLUMNS FROM zh_advance_audit');
- if (!['audit_order', 'audit_type'].every(name => columns.some(x => x.Field === name))) {
- throw new Error('请先为 zh_advance_audit 增加 audit_order 和 audit_type 字段');
- }
- log({ env, apply, filters });
- const where = ['1 = 1'], params = [];
- for (const key of ['tid', 'vid']) {
- if (filters[key]) { where.push(key + ' = ?'); params.push(filters[key]); }
- }
- const rounds = await query('SELECT DISTINCT tid, vid, times FROM zh_advance_audit WHERE ' + where.join(' AND ') + ' ORDER BY tid, vid, times', params);
- let updated = 0;
- for (const round of rounds) {
- await query('START TRANSACTION');
- try {
- const rows = await query('SELECT id, audit_id, `order`, audit_order, audit_type FROM zh_advance_audit WHERE tid = ? AND vid = ? AND times = ? ORDER BY `order`, id FOR UPDATE', [round.tid, round.vid, round.times]);
- const plan = buildUpdates(rows);
- log({ phase: 'plan', ...round, ...plan });
- if (!apply || plan.skip) { await query('ROLLBACK'); continue; }
- for (const row of plan.updates) {
- const result = await query('UPDATE zh_advance_audit SET audit_order = ?, audit_type = ? WHERE id = ?', [row.audit_order, row.audit_type, row.id]);
- if (result.affectedRows !== 1) throw new Error('回填失败:' + row.id);
- }
- await query('COMMIT');
- updated += plan.updates.length;
- log({ phase: 'committed', ...round, updated: plan.updates.length });
- } catch (err) {
- await query('ROLLBACK');
- throw err;
- }
- }
- log({ phase: 'done', rounds: rounds.length, updated });
- } finally {
- connection.end();
- }
- }
- module.exports = { buildUpdates };
- if (require.main === module) main().catch(err => { console.error(err); process.exitCode = 1; });
|