sinka/api/prisma/seed.ts
armando cf16bf1fb6 Show integration health in the admin and keep clients on their own screen.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-16 03:43:18 -03:00

173 lines
5.6 KiB
TypeScript

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);
});