/** * 一次性迁移:common_promo_code 扩展字段(scene / qrcode_id / owner_user_id / remark / updated_at) * 用法:cd server/dukang-api && npx ts-node --transpile-only prisma/migrate-promo-code-v31.ts */ import { PrismaClient } from '@prisma/client'; import { randomBytes } from 'crypto'; const prisma = new PrismaClient(); async function columnExists(table: string, column: string): Promise { const rows = await prisma.$queryRawUnsafe>( `SHOW COLUMNS FROM ${table} LIKE '${column}'`, ); return rows.length > 0; } async function addColumn(sql: string) { try { await prisma.$executeRawUnsafe(sql); } catch (e) { const msg = e instanceof Error ? e.message : String(e); if (!msg.includes('Duplicate column')) throw e; } } async function main() { if (!(await columnExists('common_promo_code', 'scene'))) { await addColumn( `ALTER TABLE common_promo_code ADD COLUMN scene VARCHAR(32) NOT NULL DEFAULT 'ONLINE_LINK' AFTER name`, ); } if (!(await columnExists('common_promo_code', 'qrcode_id'))) { await addColumn(`ALTER TABLE common_promo_code ADD COLUMN qrcode_id VARCHAR(64) NULL AFTER scene`); } if (!(await columnExists('common_promo_code', 'owner_user_id'))) { await addColumn( `ALTER TABLE common_promo_code ADD COLUMN owner_user_id BIGINT UNSIGNED NULL AFTER status`, ); } if (!(await columnExists('common_promo_code', 'remark'))) { await addColumn(`ALTER TABLE common_promo_code ADD COLUMN remark VARCHAR(256) NULL AFTER owner_user_id`); } if (!(await columnExists('common_promo_code', 'updated_at'))) { await addColumn( `ALTER TABLE common_promo_code ADD COLUMN updated_at DATETIME(3) NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) AFTER created_at`, ); } const rows = await prisma.$queryRawUnsafe>( `SELECT id, code, qrcode_id FROM common_promo_code`, ); const preset: Record = { DKHQ001: 'a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456', DKDEMO1: 'b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef12345678', }; for (const row of rows) { if (row.qrcode_id) continue; const qrcodeId = preset[row.code] ?? randomBytes(32).toString('hex'); await prisma.$executeRawUnsafe( `UPDATE common_promo_code SET qrcode_id = ? WHERE id = ?`, qrcodeId, row.id, ); } await prisma.$executeRawUnsafe(`UPDATE common_promo_code SET updated_at = created_at WHERE updated_at IS NULL`); await prisma.$executeRawUnsafe(`ALTER TABLE common_promo_code MODIFY qrcode_id VARCHAR(64) NOT NULL`); try { await prisma.$executeRawUnsafe( `ALTER TABLE common_promo_code ADD UNIQUE KEY uk_common_promo_code_qrcode_id (qrcode_id)`, ); } catch (e) { const msg = e instanceof Error ? e.message : String(e); if (!msg.includes('Duplicate key name')) throw e; } try { await prisma.$executeRawUnsafe( `ALTER TABLE common_promo_code ADD KEY idx_common_promo_code_owner (owner_user_id)`, ); } catch (e) { const msg = e instanceof Error ? e.message : String(e); if (!msg.includes('Duplicate key name')) throw e; } try { await prisma.$executeRawUnsafe( `ALTER TABLE common_promo_code ADD KEY idx_common_promo_code_scene_status (scene, status)`, ); } catch (e) { const msg = e instanceof Error ? e.message : String(e); if (!msg.includes('Duplicate key name')) throw e; } console.log('migrate-promo-code-v31: OK'); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(() => prisma.$disconnect());