feat: drill-down en pestaña nueva, rol Vendedor y scripts demo

This commit is contained in:
Horux Dev
2026-06-22 20:45:42 +00:00
parent 7df27ce66d
commit 3c7758a599
10 changed files with 705 additions and 16 deletions

View File

@@ -0,0 +1,119 @@
/**
* Script: create-vendedor-fernando.ts
*
* Crea la cuenta de Fernando (fernando@horuxfin.com) como Vendedor de Horux 360.
* Rol de plataforma: platform_sales (Vendedor).
* Membership en el tenant Horux 360 con rol cliente (minimo, solo para login
* y acceso a configuracion/cambio de contraseña).
*
* Si el usuario ya existe, le asigna/actualiza los permisos y envia un correo
* de notificacion. Si es nuevo, genera password temporal y envia bienvenida.
*
* Uso:
* cd apps/api && npx tsx scripts/create-vendedor-fernando.ts
*/
import { randomBytes } from 'crypto';
import { prisma } from '../src/config/database.js';
import { hashPassword } from '../src/auth/passwords.js';
import { emailService } from '../src/services/email/email.service.js';
import { invalidatePlatformRolesCache } from '../src/utils/platform-admin.js';
const EMAIL = 'fernando@horuxfin.com';
const NOMBRE = 'Fernando';
const HORUX_RFC = 'HTS240708LJA';
function generarPassword(): string {
return randomBytes(6).toString('hex'); // 12 caracteres hex
}
async function main() {
console.log(`🌱 Creando cuenta de Vendedor para ${EMAIL}...\n`);
// 1. Tenant raiz Horux 360
const tenant = await prisma.tenant.findUnique({ where: { rfc: HORUX_RFC } });
if (!tenant) throw new Error(`Tenant Horux 360 (${HORUX_RFC}) no encontrado. Ejecuta primero el bootstrap admin global.`);
// 2. Rol "cliente" para la membership (minimo acceso)
const clienteRol = await prisma.rol.findUnique({ where: { nombre: 'cliente' } });
if (!clienteRol) throw new Error('Rol "cliente" no encontrado en BD central');
// 3. Buscar o crear usuario
let user = await prisma.user.findUnique({ where: { email: EMAIL } });
let tempPassword: string | null = null;
let esNuevo = false;
if (!user) {
tempPassword = generarPassword();
const passwordHash = await hashPassword(tempPassword);
user = await prisma.user.create({
data: {
email: EMAIL,
passwordHash,
nombre: NOMBRE,
lastTenantId: tenant.id,
active: true,
},
});
esNuevo = true;
console.log(`✅ Usuario creado: ${user.email}`);
console.log(` Password temporal: ${tempPassword}`);
} else {
await prisma.user.update({
where: { id: user.id },
data: { lastTenantId: tenant.id, active: true },
});
console.log(` Usuario ya existia: ${user.email}`);
}
// 4. Membership en Horux 360 con rol cliente
await prisma.tenantMembership.upsert({
where: { userId_tenantId: { userId: user.id, tenantId: tenant.id } },
update: { rolId: clienteRol.id, active: true, isOwner: false },
create: {
userId: user.id,
tenantId: tenant.id,
rolId: clienteRol.id,
active: true,
isOwner: false,
},
});
console.log(`✅ Membership "cliente" en ${tenant.nombre}`);
// 5. Rol de plataforma Vendedor (platform_sales)
await prisma.userPlatformRole.upsert({
where: { userId_role: { userId: user.id, role: 'platform_sales' } },
update: {},
create: { userId: user.id, role: 'platform_sales' },
});
console.log(`✅ Rol de plataforma "Vendedor" (platform_sales) asignado`);
// 6. Invalidar cache de roles de plataforma
invalidatePlatformRolesCache(user.id);
// 7. Enviar correo con accesos (solo si es nuevo; si ya existia, no se reenvia password)
if (esNuevo && tempPassword) {
await emailService.sendWelcome(EMAIL, {
nombre: NOMBRE,
email: EMAIL,
tempPassword,
});
console.log(`✅ Correo de bienvenida con credenciales enviado a ${EMAIL}`);
} else {
console.log(` El usuario ya existia; no se envio correo con password`);
}
console.log('\n🎉 Cuenta de Vendedor lista');
console.log(` Email: ${EMAIL}`);
if (tempPassword) console.log(` Password temporal: ${tempPassword}`);
console.log(` Tenant: ${tenant.nombre} (${tenant.rfc})`);
console.log(` Rol de plataforma: platform_sales (Vendedor)`);
}
main()
.catch((err) => {
console.error('\n❌ Error:', err.message || err);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});