import { prisma } from '../config/database.js'; import bcrypt from 'bcryptjs'; import type { UserListItem, UserInvite, UserUpdate } from '@horux/shared'; export async function getUsuarios(tenantId: string): Promise { const users = await prisma.user.findMany({ where: { tenantId }, select: { id: true, email: true, nombre: true, role: true, active: true, lastLogin: true, createdAt: true, }, orderBy: { createdAt: 'desc' }, }); return users.map(u => ({ ...u, lastLogin: u.lastLogin?.toISOString() || null, createdAt: u.createdAt.toISOString(), })); } export async function inviteUsuario(tenantId: string, data: UserInvite): Promise { // Check tenant user limit const tenant = await prisma.tenant.findUnique({ where: { id: tenantId }, select: { usersLimit: true }, }); const currentCount = await prisma.user.count({ where: { tenantId } }); if (currentCount >= (tenant?.usersLimit || 1)) { throw new Error('LĂ­mite de usuarios alcanzado para este plan'); } // Generate temporary password const tempPassword = Math.random().toString(36).slice(-8); const passwordHash = await bcrypt.hash(tempPassword, 12); const user = await prisma.user.create({ data: { tenantId, email: data.email, passwordHash, nombre: data.nombre, role: data.role, }, select: { id: true, email: true, nombre: true, role: true, active: true, lastLogin: true, createdAt: true, }, }); // In production, send email with tempPassword console.log(`Temporary password for ${data.email}: ${tempPassword}`); return { ...user, lastLogin: user.lastLogin?.toISOString() || null, createdAt: user.createdAt.toISOString(), }; } export async function updateUsuario( tenantId: string, userId: string, data: UserUpdate ): Promise { const user = await prisma.user.update({ where: { id: userId, tenantId }, data: { ...(data.nombre && { nombre: data.nombre }), ...(data.role && { role: data.role }), ...(data.active !== undefined && { active: data.active }), }, select: { id: true, email: true, nombre: true, role: true, active: true, lastLogin: true, createdAt: true, }, }); return { ...user, lastLogin: user.lastLogin?.toISOString() || null, createdAt: user.createdAt.toISOString(), }; } export async function deleteUsuario(tenantId: string, userId: string): Promise { await prisma.user.delete({ where: { id: userId, tenantId }, }); } /** * Obtiene todos los usuarios de todas las empresas (solo admin global) */ export async function getAllUsuarios(): Promise { const users = await prisma.user.findMany({ select: { id: true, email: true, nombre: true, role: true, active: true, lastLogin: true, createdAt: true, tenantId: true, tenant: { select: { nombre: true, }, }, }, orderBy: [{ tenant: { nombre: 'asc' } }, { createdAt: 'desc' }], }); return users.map(u => ({ id: u.id, email: u.email, nombre: u.nombre, role: u.role, active: u.active, lastLogin: u.lastLogin?.toISOString() || null, createdAt: u.createdAt.toISOString(), tenantId: u.tenantId, tenantName: u.tenant.nombre, })); } /** * Actualiza un usuario globalmente (puede cambiar de tenant) */ export async function updateUsuarioGlobal( userId: string, data: UserUpdate & { tenantId?: string } ): Promise { const user = await prisma.user.update({ where: { id: userId }, data: { ...(data.nombre && { nombre: data.nombre }), ...(data.role && { role: data.role }), ...(data.active !== undefined && { active: data.active }), ...(data.tenantId && { tenantId: data.tenantId }), }, select: { id: true, email: true, nombre: true, role: true, active: true, lastLogin: true, createdAt: true, tenantId: true, tenant: { select: { nombre: true, }, }, }, }); return { id: user.id, email: user.email, nombre: user.nombre, role: user.role, active: user.active, lastLogin: user.lastLogin?.toISOString() || null, createdAt: user.createdAt.toISOString(), tenantId: user.tenantId, tenantName: user.tenant.nombre, }; } /** * Elimina un usuario globalmente */ export async function deleteUsuarioGlobal(userId: string): Promise { await prisma.user.delete({ where: { id: userId }, }); }