107 lines
3.6 KiB
TypeScript
107 lines
3.6 KiB
TypeScript
/**
|
||
* 一次性迁移: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<boolean> {
|
||
const rows = await prisma.$queryRawUnsafe<Array<{ Field: string }>>(
|
||
`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<Array<{ id: bigint; code: string; qrcode_id: string | null }>>(
|
||
`SELECT id, code, qrcode_id FROM common_promo_code`,
|
||
);
|
||
|
||
const preset: Record<string, string> = {
|
||
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());
|