All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 14m40s
113 lines
2.9 KiB
TypeScript
113 lines
2.9 KiB
TypeScript
/**
|
|
* Post-Migration Script: Migrate existing TenantSymbols to new architecture.
|
|
*
|
|
* Run AFTER applying the schema migration (20260520_symbol_architecture).
|
|
*
|
|
* Steps:
|
|
* 1. Create a default "Meine Symbole" TenantCategory for each tenant that has TenantSymbols
|
|
* 2. Migrate existing TenantSymbols: set name, svgPath, categoryId, migratedFromIconId
|
|
* 3. Verify consistency
|
|
*
|
|
* Usage:
|
|
* npx ts-node prisma/migrate-tenant-symbols.ts
|
|
*/
|
|
|
|
import { PrismaClient } from '@prisma/client'
|
|
|
|
const prisma = new PrismaClient()
|
|
|
|
async function main() {
|
|
console.log('🔧 Migrating existing TenantSymbols...')
|
|
|
|
// Step 1: Get all tenants that have existing tenantSymbols
|
|
const tenantsWithSymbols = await (prisma as any).tenantSymbol.groupBy({
|
|
by: ['tenantId'],
|
|
_count: { id: true },
|
|
})
|
|
|
|
console.log(`Found ${tenantsWithSymbols.length} tenants with existing symbols`)
|
|
|
|
let categoriesCreated = 0
|
|
let symbolsMigrated = 0
|
|
|
|
for (const group of tenantsWithSymbols) {
|
|
const tenantId = group.tenantId
|
|
|
|
// Step 2: Create default category for this tenant
|
|
let defaultCategory = await (prisma as any).tenantCategory.findFirst({
|
|
where: { tenantId, name: 'Meine Symbole' },
|
|
})
|
|
|
|
if (!defaultCategory) {
|
|
defaultCategory = await (prisma as any).tenantCategory.create({
|
|
data: {
|
|
tenantId,
|
|
name: 'Meine Symbole',
|
|
sortOrder: 0,
|
|
},
|
|
})
|
|
categoriesCreated++
|
|
}
|
|
|
|
// Step 3: Migrate all tenantSymbols for this tenant
|
|
const tenantSymbols = await (prisma as any).tenantSymbol.findMany({
|
|
where: { tenantId },
|
|
include: { icon: true },
|
|
})
|
|
|
|
for (const ts of tenantSymbols) {
|
|
const updates: any = {}
|
|
|
|
// name = customName || icon.name
|
|
if (!ts.name) {
|
|
updates.name = ts.customName || ts.icon?.name || 'Unbenannt'
|
|
}
|
|
|
|
// svgPath = icon.fileKey
|
|
if (!ts.svgPath && ts.icon?.fileKey) {
|
|
updates.svgPath = ts.icon.fileKey
|
|
}
|
|
|
|
// categoryId = default category
|
|
if (!ts.categoryId) {
|
|
updates.categoryId = defaultCategory.id
|
|
}
|
|
|
|
// migratedFromIconId = current iconId
|
|
if (!ts.migratedFromIconId) {
|
|
updates.migratedFromIconId = ts.iconId
|
|
}
|
|
|
|
if (Object.keys(updates).length > 0) {
|
|
await (prisma as any).tenantSymbol.update({
|
|
where: { id: ts.id },
|
|
data: updates,
|
|
})
|
|
symbolsMigrated++
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log(`✅ Done: ${categoriesCreated} categories created, ${symbolsMigrated} symbols migrated`)
|
|
|
|
// Verification
|
|
const unmappedCount = await (prisma as any).tenantSymbol.count({
|
|
where: { categoryId: null },
|
|
})
|
|
|
|
if (unmappedCount > 0) {
|
|
console.warn(`⚠️ ${unmappedCount} tenantSymbols still have no categoryId!`)
|
|
} else {
|
|
console.log('✅ All tenantSymbols have a category assigned')
|
|
}
|
|
}
|
|
|
|
main()
|
|
.catch((e) => {
|
|
console.error(e)
|
|
process.exit(1)
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect()
|
|
})
|