feat(alertas): add alerts CRUD with stats and management UI

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Consultoria AS
2026-01-22 03:00:14 +00:00
parent 6d59c8d842
commit 9b8aaea7eb
31 changed files with 4892 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
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<UserListItem[]> {
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<UserListItem> {
// 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<UserListItem> {
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<void> {
await prisma.user.delete({
where: { id: userId, tenantId },
});
}