feat(invitations): flujo de invitacion de clientes por email

Backend:
- Nuevo modelo Prisma ClientInvitation con token unico, expiracion
  y estados (pending/accepted/expired).
- Migracion: 20260511213955_add_client_invitations
- Service client-invitations.service.ts: crear invitacion,
  validar token, registrar desde invitacion (reutiliza logica
  de creacion de tenant + usuario de despacho.service).
- Controller + routes: POST /invitations/client (admin),
  GET /invitations/client/validate/:token (publico),
  POST /invitations/client/register/:token (publico),
  GET /invitations/client (admin).
- Email template client-invitation.ts con link a
  /invitacion/registro/{token}.
- Agregado sendClientInvitation a email.service.

Frontend:
- Pagina /invitacion/registro/[token] para que el invitado
  complete registro (nombre, password, despacho, RFC, perfil).
- Pagina /admin/invitar-cliente para que admin global envie
  invitaciones y vea el historial.
- Hooks useCreateInvitation, useValidateInvitationToken,
  useRegisterFromInvitation, useClientInvitations.
- API client lib/api/client-invitations.ts.

Infra:
- PM2 ecosystem.config.js: usa node --import tsx con
  kill_timeout aumentado a 15s para evitar EADDRINUSE.
- React Query retry=2 con delay exponencial para resiliencia.

Refs: docs/CAMBIOS-2026-05-09.md
This commit is contained in:
Horux Dev
2026-05-11 22:03:03 +00:00
parent 0a63593aab
commit 745bc8385b
12 changed files with 859 additions and 0 deletions

View File

@@ -39,6 +39,7 @@ import adminImpersonateRoutes from './routes/admin-impersonate.routes.js';
import adminClientesRoutes from './routes/admin-clientes.routes.js';
import adminAddonsRoutes from './routes/admin-addons.routes.js';
import { trialInvitationRoutes } from './routes/trial-invitations.routes.js';
import clientInvitationRoutes from './routes/client-invitations.routes.js';
import despachoAuditRoutes from './routes/despacho-audit.routes.js';
import metricasRoutes from './routes/metricas.routes.js';
@@ -107,6 +108,7 @@ app.use('/api/admin/addons', adminAddonsRoutes);
app.use('/api/despacho/audit-log', despachoAuditRoutes);
app.use('/api/metricas', metricasRoutes);
app.use('/api/invitations/trial', trialInvitationRoutes);
app.use('/api/invitations/client', clientInvitationRoutes);
// Error handling
app.use(errorMiddleware);