import { config } from 'dotenv'; import { resolve } from 'node:path'; import * as bcrypt from 'bcrypt'; import { PrismaClient as PlatformPrisma } from '../src/generated/platform'; import { PrismaClient as TenantPrisma } from '../src/generated/tenant'; import { createMysqlDatabase, databaseForSlug, pushTenantSchema } from '../src/tenancy/provision-database'; import { urlForDatabase } from '../src/tenancy/tenant-url'; config({ path: resolve(__dirname, '../../.env') }); config({ path: resolve(__dirname, '../.env') }); async function upsertUser( db: TenantPrisma, email: string, name: string, password: string, role: 'ADMIN' | 'MANAGER' | 'OPERATOR', ) { const passwordHash = await bcrypt.hash(password, 10); await db.user.upsert({ where: { email }, update: { name, passwordHash, role, issuedPassword: password }, create: { email, name, passwordHash, role, issuedPassword: password }, }); } async function ensureTenant( platform: PlatformPrisma, name: string, slug: string, aliases: string[] = [], ) { let tenant = await platform.tenant.findUnique({ where: { slug } }); if (!tenant) { for (const alias of aliases) { const old = await platform.tenant.findUnique({ where: { slug: alias } }); if (old) { tenant = await platform.tenant.update({ where: { id: old.id }, data: { name, slug }, }); break; } } } if (!tenant) { const database = databaseForSlug(slug); await createMysqlDatabase(database); await pushTenantSchema(database); tenant = await platform.tenant.create({ data: { name, slug, database } }); } else { await pushTenantSchema(tenant.database); if (tenant.name !== name) { tenant = await platform.tenant.update({ where: { id: tenant.id }, data: { name } }); } } return tenant; } async function seedCompany( tenant: { database: string }, users: { email: string; name: string; password: string; role: 'ADMIN' | 'MANAGER' | 'OPERATOR' }[], customers: { name: string; document: string; city: string; state: string }[], carriers: { name: string; baseFee: number; pricePerKg: number; pricePerKm: number; adValoremRate: number }[], ) { const db = new TenantPrisma({ datasources: { db: { url: urlForDatabase(tenant.database) } }, }); for (const user of users) { await upsertUser(db, user.email, user.name, user.password, user.role); } for (const customer of customers) { const existing = await db.customer.findFirst({ where: { name: customer.name } }); if (!existing) { await db.customer.create({ data: customer }); } } for (const carrier of carriers) { const existing = await db.carrier.findFirst({ where: { name: carrier.name } }); if (existing) { await db.carrier.update({ where: { id: existing.id }, data: carrier }); } else { await db.carrier.create({ data: carrier }); } } await db.$disconnect(); } async function main() { const platform = new PlatformPrisma(); const platformEmail = process.env.PLATFORM_ADMIN_EMAIL ?? 'tina.r@example.net'; const platformPassword = process.env.PLATFORM_ADMIN_PASSWORD ?? 'SinkaPlatform!1'; await platform.platformUser.upsert({ where: { email: platformEmail }, update: { passwordHash: await bcrypt.hash(platformPassword, 10), name: 'Sinka Platform' }, create: { email: platformEmail, name: 'Sinka Platform', passwordHash: await bcrypt.hash(platformPassword, 10), }, }); const cliente1 = await ensureTenant(platform, 'Cliente 1', 'cliente-1', ['demo']); const cliente2 = await ensureTenant(platform, 'Cliente 2', 'cliente-2'); const others = await platform.tenant.findMany({ where: { slug: { notIn: ['cliente-1', 'cliente-2'] } }, }); for (const item of others) { await pushTenantSchema(item.database); } await seedCompany( cliente1, [ { email: process.env.DEMO_ADMIN_EMAIL ?? 'xena.w@example.org', name: 'Ana Admin', password: process.env.DEMO_ADMIN_PASSWORD ?? 'SinkaAdmin!1', role: 'ADMIN', }, { email: process.env.DEMO_MANAGER_EMAIL ?? 'james.b@example.com', name: 'Marcos Manager', password: process.env.DEMO_MANAGER_PASSWORD ?? 'SinkaManager!1', role: 'MANAGER', }, { email: process.env.DEMO_OPERATOR_EMAIL ?? 'ursula.b@example.com', name: 'Olga Operador', password: process.env.DEMO_OPERATOR_PASSWORD ?? 'SinkaOperador!1', role: 'OPERATOR', }, ], [ { name: 'Mercado Aurora', document: '12.345.678/0001-90', city: 'São Paulo', state: 'SP' }, { name: 'Café do Litoral', document: '98.765.432/0001-10', city: 'Santos', state: 'SP' }, ], [ { name: 'Litoral Mix', baseFee: 45, pricePerKg: 1.8, pricePerKm: 0.85, adValoremRate: 0.003 }, { name: 'Rota Sul', baseFee: 32, pricePerKg: 1.4, pricePerKm: 0.72, adValoremRate: 0.004 }, { name: 'Express RJ', baseFee: 60, pricePerKg: 2.2, pricePerKm: 1.1, adValoremRate: 0.002 }, ], ); await seedCompany( cliente2, [ { email: 'ivan.p@example.net', name: 'Bruno Admin', password: 'Cliente2Admin!1', role: 'ADMIN', }, ], [ { name: 'Padaria Centro', document: '11.222.333/0001-44', city: 'Curitiba', state: 'PR' }, { name: 'Loja Norte', document: '55.666.777/0001-88', city: 'Joinville', state: 'SC' }, ], [{ name: 'Carga Paraná', baseFee: 38, pricePerKg: 1.5, pricePerKm: 0.7, adValoremRate: 0.0035 }], ); await platform.$disconnect(); console.log('Seed ok: platform + Cliente 1 + Cliente 2.'); } main().catch(async (error) => { console.error(error); process.exit(1); });