# RF-USER-001: CRUD de Usuarios

## Identificacion

| Campo | Valor |
|-------|-------|
| **ID** | RF-USER-001 |
| **Modulo** | MGN-002 |
| **Nombre Modulo** | Users - Gestion de Usuarios |
| **Prioridad** | P0 |
| **Complejidad** | Media |
| **Estado** | Aprobado |
| **Autor** | System |
| **Fecha** | 2025-12-05 |

---

## Descripcion

El sistema debe permitir la gestion completa del ciclo de vida de usuarios, incluyendo crear, leer, actualizar y eliminar (soft delete) usuarios dentro de un tenant. Solo usuarios con permisos administrativos pueden gestionar otros usuarios.

### Contexto de Negocio

La gestion de usuarios es fundamental para:
- Controlar quien accede al sistema
- Asignar roles y permisos apropiados
- Mantener registro de empleados/usuarios del tenant
- Cumplir con politicas de seguridad y auditoria

---

## Criterios de Aceptacion

- [x] **CA-001:** El sistema debe permitir crear usuarios con datos basicos (email, nombre, apellido)
- [x] **CA-002:** El sistema debe generar password temporal o enviar invitacion por email
- [x] **CA-003:** El sistema debe validar unicidad de email dentro del tenant
- [x] **CA-004:** El sistema debe permitir listar usuarios con paginacion y filtros
- [x] **CA-005:** El sistema debe permitir buscar usuarios por nombre, email o rol
- [x] **CA-006:** El sistema debe permitir actualizar datos de usuario
- [x] **CA-007:** El sistema debe implementar soft delete (no eliminar fisicamente)
- [x] **CA-008:** El sistema debe permitir activar/desactivar usuarios
- [x] **CA-009:** El sistema debe registrar quien creo/modifico cada usuario (auditoria)
- [x] **CA-010:** Solo admins pueden crear/modificar/eliminar usuarios

### Ejemplos de Verificacion

```gherkin
Scenario: Crear usuario exitosamente
  Given un administrador autenticado
  When crea un nuevo usuario con email "nuevo@empresa.com"
  And nombre "Juan" y apellido "Perez"
  Then el sistema crea el usuario con estado "pending_activation"
  And envia email de invitacion al usuario
  And registra created_by con el ID del admin
  And responde con status 201

Scenario: Crear usuario con email duplicado
  Given un usuario existente con email "existente@empresa.com"
  When un admin intenta crear otro usuario con el mismo email
  Then el sistema responde con status 409
  And el mensaje es "El email ya esta registrado"

Scenario: Listar usuarios con filtros
  Given 50 usuarios en el sistema
  When un admin solicita GET /api/v1/users?page=1&limit=10&role=admin
  Then el sistema retorna los primeros 10 usuarios con rol admin
  And incluye metadata de paginacion (total, pages, hasNext)

Scenario: Soft delete de usuario
  Given un usuario activo con ID "user-123"
  When un admin elimina el usuario
  Then el campo deleted_at se establece con la fecha actual
  And el campo deleted_by se establece con el ID del admin
  And el usuario ya no aparece en listados normales
  And el usuario no puede hacer login
```

---

## Reglas de Negocio

| ID | Regla | Validacion |
|----|-------|------------|
| RN-001 | Email unico por tenant | UNIQUE(tenant_id, email) |
| RN-002 | Email en formato valido | Regex validation |
| RN-003 | Nombre y apellido requeridos | NOT NULL, min 2 chars |
| RN-004 | Soft delete en lugar de hard delete | deleted_at NOT NULL |
| RN-005 | Solo admins gestionan usuarios | RBAC permission check |
| RN-006 | Usuario no puede eliminarse a si mismo | Validacion en backend |
| RN-007 | Password temporal expira en 24 horas | Validacion en activacion |
| RN-008 | Auditoria de cambios obligatoria | created_by, updated_by |

### Estados de Usuario

```
                    ┌─────────────────┐
                    │     CREATED     │
                    │ (pending_activ) │
                    └────────┬────────┘
                             │ Usuario activa cuenta
                             ▼
┌─────────────┐      ┌─────────────────┐      ┌─────────────┐
│   LOCKED    │◄────►│     ACTIVE      │◄────►│  INACTIVE   │
│ (bloqueado) │      │    (activo)     │      │ (inactivo)  │
└─────────────┘      └────────┬────────┘      └─────────────┘
                             │ Admin elimina
                             ▼
                    ┌─────────────────┐
                    │    DELETED      │
                    │  (soft delete)  │
                    └─────────────────┘
```

---

## Impacto en Capas

### Database

| Elemento | Accion | Descripcion |
|----------|--------|-------------|
| Schema | crear | `core_users` |
| Tabla | crear | `users` - tabla principal |
| Columna | - | `id` UUID PK |
| Columna | - | `tenant_id` UUID FK |
| Columna | - | `email` VARCHAR(255) |
| Columna | - | `password_hash` VARCHAR(255) |
| Columna | - | `first_name` VARCHAR(100) |
| Columna | - | `last_name` VARCHAR(100) |
| Columna | - | `phone` VARCHAR(20) |
| Columna | - | `status` ENUM |
| Columna | - | `is_active` BOOLEAN |
| Columna | - | `email_verified_at` TIMESTAMPTZ |
| Columna | - | `last_login_at` TIMESTAMPTZ |
| Columna | - | `failed_login_attempts` INTEGER |
| Columna | - | `locked_until` TIMESTAMPTZ |
| Columna | - | `created_by` UUID FK |
| Columna | - | `updated_by` UUID FK |
| Columna | - | `deleted_at` TIMESTAMPTZ |
| Columna | - | `deleted_by` UUID FK |
| Indice | crear | `idx_users_tenant_email` UNIQUE |
| Indice | crear | `idx_users_tenant_status` |

### Backend

| Elemento | Accion | Descripcion |
|----------|--------|-------------|
| Controller | crear | `UsersController` |
| Service | crear | `UsersService` |
| Method | crear | `create()` |
| Method | crear | `findAll()` |
| Method | crear | `findOne()` |
| Method | crear | `update()` |
| Method | crear | `remove()` (soft delete) |
| Method | crear | `activate()` |
| Method | crear | `deactivate()` |
| DTO | crear | `CreateUserDto` |
| DTO | crear | `UpdateUserDto` |
| DTO | crear | `UserResponseDto` |
| DTO | crear | `UserListQueryDto` |
| Guard | usar | `RolesGuard` |
| Endpoint | crear | `POST /api/v1/users` |
| Endpoint | crear | `GET /api/v1/users` |
| Endpoint | crear | `GET /api/v1/users/:id` |
| Endpoint | crear | `PATCH /api/v1/users/:id` |
| Endpoint | crear | `DELETE /api/v1/users/:id` |

### Frontend

| Elemento | Accion | Descripcion |
|----------|--------|-------------|
| Pagina | crear | `UsersListPage` |
| Pagina | crear | `UserDetailPage` |
| Pagina | crear | `UserCreatePage` |
| Pagina | crear | `UserEditPage` |
| Componente | crear | `UsersTable` |
| Componente | crear | `UserForm` |
| Componente | crear | `UserCard` |
| Service | crear | `usersService` |
| Store | crear | `usersStore` |

---

## Dependencias

### Depende de (Bloqueantes)

| ID | Requerimiento | Estado |
|----|---------------|--------|
| RF-AUTH-001 | Login | Para autenticacion |
| RF-AUTH-002 | JWT Tokens | Para autorizacion |

### Dependencias Relacionadas

| ID | Requerimiento | Relacion |
|----|---------------|----------|
| RF-USER-002 | Perfil de usuario | Extiende datos de usuario |
| RF-ROLE-001 | Asignacion de roles | Usa tabla users |

---

## Especificaciones Tecnicas

### Modelo de Datos Simplificado

```typescript
interface User {
  id: string;
  tenantId: string;
  email: string;
  passwordHash: string;
  firstName: string;
  lastName: string;
  phone?: string;
  avatarUrl?: string;
  status: UserStatus;
  isActive: boolean;
  emailVerifiedAt?: Date;
  lastLoginAt?: Date;
  failedLoginAttempts: number;
  lockedUntil?: Date;
  metadata?: Record<string, any>;
  createdAt: Date;
  createdBy?: string;
  updatedAt: Date;
  updatedBy?: string;
  deletedAt?: Date;
  deletedBy?: string;
}

enum UserStatus {
  PENDING_ACTIVATION = 'pending_activation',
  ACTIVE = 'active',
  INACTIVE = 'inactive',
  LOCKED = 'locked',
}
```

### Flujo de Creacion de Usuario

```
┌─────────────────────────────────────────────────────────────────┐
│ 1. Admin envia POST /api/v1/users                               │
│    Body: { email, firstName, lastName, roleIds }                │
└───────────────────────────┬─────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────────┐
│ 2. Validaciones                                                  │
│    - Email formato valido                                        │
│    - Email no existe en tenant                                   │
│    - Admin tiene permiso users:create                           │
└───────────────────────────┬─────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────────┐
│ 3. Crear usuario                                                 │
│    - status = 'pending_activation'                              │
│    - is_active = false                                           │
│    - created_by = admin.id                                       │
│    - Generar activation token                                    │
└───────────────────────────┬─────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────────┐
│ 4. Asignar roles                                                 │
│    - Insertar en user_roles                                      │
└───────────────────────────┬─────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────────┐
│ 5. Enviar email de invitacion                                    │
│    - Link: /activate?token={activation_token}                   │
│    - Token expira en 24 horas                                    │
└───────────────────────────┬─────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────────┐
│ 6. Responder con usuario creado                                  │
│    - Status 201                                                  │
│    - Body: UserResponseDto (sin password)                       │
└─────────────────────────────────────────────────────────────────┘
```

---

## Datos de Prueba

| Escenario | Entrada | Resultado |
|-----------|---------|-----------|
| Crear usuario valido | email, firstName, lastName | 201, usuario creado |
| Email duplicado | email existente | 409, "Email ya registrado" |
| Email invalido | "notanemail" | 400, "Email invalido" |
| Sin permiso | Usuario no admin | 403, "Permiso denegado" |
| Listar usuarios | page=1, limit=10 | 200, lista paginada |
| Buscar por email | search=john@ | 200, usuarios filtrados |
| Actualizar usuario | PATCH con datos | 200, usuario actualizado |
| Soft delete | DELETE /users/:id | 200, deleted_at set |
| Eliminar a si mismo | DELETE propio ID | 400, "No puede eliminarse" |

---

## Estimacion

| Capa | Story Points | Notas |
|------|--------------|-------|
| Database | 3 | Schema y tabla users |
| Backend | 5 | CRUD completo con validaciones |
| Frontend | 5 | 4 paginas, componentes, store |
| **Total** | **13** | |

---

## Notas Adicionales

- Implementar soft delete para mantener integridad referencial
- El email de invitacion debe usar template personalizable
- Considerar bulk import de usuarios via CSV
- Implementar export de lista de usuarios
- Los usuarios eliminados se pueden restaurar (admin)

---

## Historial de Cambios

| Version | Fecha | Autor | Cambios |
|---------|-------|-------|---------|
| 1.0 | 2025-12-05 | System | Creacion inicial |

---

## Aprobaciones

| Rol | Nombre | Fecha | Firma |
|-----|--------|-------|-------|
| Analista | System | 2025-12-05 | [x] |
| Tech Lead | - | - | [ ] |
| Product Owner | - | - | [ ] |
