erp-core/docs/01-fase-foundation/MGN-002-users/requerimientos/RF-USER-005.md

9.5 KiB

RF-USER-005: Preferencias de Usuario

Identificacion

Campo Valor
ID RF-USER-005
Modulo MGN-002
Nombre Modulo Users - Gestion de Usuarios
Prioridad P2
Complejidad Baja
Estado Aprobado
Autor System
Fecha 2025-12-05

Descripcion

El sistema debe permitir a cada usuario configurar sus preferencias personales, incluyendo idioma, zona horaria, formato de fecha/hora, tema visual y preferencias de notificaciones. Estas configuraciones personalizan la experiencia del usuario sin afectar a otros usuarios del tenant.

Contexto de Negocio

Las preferencias de usuario permiten:

  • Experiencia personalizada por usuario
  • Soporte multi-idioma
  • Adaptacion a zonas horarias locales
  • Control sobre notificaciones recibidas
  • Accesibilidad (tema oscuro, tamano de fuente)

Criterios de Aceptacion

  • CA-001: El usuario debe poder seleccionar idioma preferido
  • CA-002: El usuario debe poder configurar zona horaria
  • CA-003: El usuario debe poder elegir formato de fecha (DD/MM/YYYY, MM/DD/YYYY, etc.)
  • CA-004: El usuario debe poder elegir formato de hora (12h, 24h)
  • CA-005: El usuario debe poder elegir tema (claro, oscuro, sistema)
  • CA-006: El usuario debe poder configurar preferencias de notificaciones
  • CA-007: Las preferencias deben aplicarse inmediatamente
  • CA-008: Las preferencias deben persistir entre sesiones

Ejemplos de Verificacion

Scenario: Cambiar idioma
  Given un usuario con idioma "es" (español)
  When cambia su preferencia a "en" (ingles)
  Then el sistema guarda la preferencia
  And la interfaz cambia a ingles inmediatamente
  And las fechas se formatean en ingles

Scenario: Configurar zona horaria
  Given un usuario en Mexico (America/Mexico_City)
  When configura su zona horaria
  Then todas las fechas/horas se muestran en esa zona
  And los eventos del calendario se ajustan

Scenario: Preferencias de notificaciones
  Given un usuario con notificaciones por email activadas
  When desactiva "notificaciones de marketing"
  Then deja de recibir ese tipo de emails
  And mantiene otras notificaciones activas

Scenario: Tema oscuro
  Given un usuario con tema claro
  When activa tema oscuro
  Then la interfaz cambia a colores oscuros
  And la preferencia se mantiene al recargar

Reglas de Negocio

ID Regla Validacion
RN-001 Idiomas soportados: es, en, pt Enum validation
RN-002 Zona horaria debe ser valida IANA Timezone validation
RN-003 Preferencias son por usuario, no por tenant user_id scope
RN-004 Valores por defecto del tenant si no hay preferencia Fallback logic
RN-005 Tema "sistema" sigue preferencia del OS CSS media query

Preferencias Disponibles

interface UserPreferences {
  // Localizacion
  language: 'es' | 'en' | 'pt';
  timezone: string;  // IANA timezone
  dateFormat: 'DD/MM/YYYY' | 'MM/DD/YYYY' | 'YYYY-MM-DD';
  timeFormat: '12h' | '24h';
  currency: string;  // ISO 4217
  numberFormat: 'es-MX' | 'en-US' | 'pt-BR';

  // Apariencia
  theme: 'light' | 'dark' | 'system';
  sidebarCollapsed: boolean;
  compactMode: boolean;
  fontSize: 'small' | 'medium' | 'large';

  // Notificaciones
  notifications: {
    email: {
      enabled: boolean;
      digest: 'instant' | 'daily' | 'weekly';
      marketing: boolean;
      security: boolean;
      updates: boolean;
    };
    push: {
      enabled: boolean;
      sound: boolean;
    };
    inApp: {
      enabled: boolean;
      desktop: boolean;
    };
  };

  // Dashboard
  dashboard: {
    defaultView: string;
    widgets: string[];
  };
}

Impacto en Capas

Database

Elemento Accion Descripcion
Tabla crear user_preferences
Columna - id UUID PK
Columna - user_id UUID FK UNIQUE
Columna - tenant_id UUID FK
Columna - language VARCHAR(5)
Columna - timezone VARCHAR(50)
Columna - date_format VARCHAR(20)
Columna - time_format VARCHAR(5)
Columna - theme VARCHAR(10)
Columna - notifications JSONB
Columna - dashboard JSONB
Columna - metadata JSONB
Columna - updated_at TIMESTAMPTZ

Backend

Elemento Accion Descripcion
Controller crear PreferencesController
Service crear PreferencesService
Method crear getPreferences()
Method crear updatePreferences()
Method crear resetPreferences()
DTO crear UpdatePreferencesDto
DTO crear PreferencesResponseDto
Entity crear UserPreferences
Endpoint crear GET /api/v1/users/me/preferences
Endpoint crear PATCH /api/v1/users/me/preferences
Endpoint crear POST /api/v1/users/me/preferences/reset

Frontend

Elemento Accion Descripcion
Pagina crear PreferencesPage
Componente crear LanguageSelector
Componente crear TimezoneSelector
Componente crear ThemeToggle
Componente crear NotificationSettings
Store crear preferencesStore
Hook crear usePreferences
Context crear PreferencesContext

Dependencias

Depende de (Bloqueantes)

ID Requerimiento Estado
RF-USER-001 CRUD Usuarios Tabla users

Dependencias Relacionadas

ID Requerimiento Relacion
RF-SETTINGS-001 Tenant Settings Valores por defecto

Especificaciones Tecnicas

Endpoint GET /api/v1/users/me/preferences

// Response 200
{
  "language": "es",
  "timezone": "America/Mexico_City",
  "dateFormat": "DD/MM/YYYY",
  "timeFormat": "24h",
  "currency": "MXN",
  "numberFormat": "es-MX",
  "theme": "dark",
  "sidebarCollapsed": false,
  "compactMode": false,
  "fontSize": "medium",
  "notifications": {
    "email": {
      "enabled": true,
      "digest": "daily",
      "marketing": false,
      "security": true,
      "updates": true
    },
    "push": {
      "enabled": true,
      "sound": true
    },
    "inApp": {
      "enabled": true,
      "desktop": false
    }
  },
  "dashboard": {
    "defaultView": "overview",
    "widgets": ["sales", "inventory", "tasks"]
  }
}

Endpoint PATCH /api/v1/users/me/preferences

// Request - Actualizacion parcial
{
  "theme": "light",
  "notifications": {
    "email": {
      "marketing": false
    }
  }
}

// Response 200
{
  // PreferencesResponseDto completo actualizado
}

Merge de Preferencias

// preferences.service.ts
async updatePreferences(
  userId: string,
  updates: Partial<UserPreferences>,
): Promise<UserPreferences> {
  let preferences = await this.preferencesRepository.findOne({
    where: { userId },
  });

  if (!preferences) {
    // Crear con defaults del tenant
    const tenantDefaults = await this.getTenantDefaults(userId);
    preferences = this.preferencesRepository.create({
      userId,
      ...tenantDefaults,
    });
  }

  // Deep merge para objetos anidados (notifications, dashboard)
  const merged = deepMerge(preferences, updates);

  return this.preferencesRepository.save(merged);
}

Aplicacion en Frontend

// PreferencesContext.tsx
export const PreferencesProvider: React.FC = ({ children }) => {
  const [preferences, setPreferences] = useState<UserPreferences | null>(null);

  useEffect(() => {
    loadPreferences();
  }, []);

  useEffect(() => {
    if (preferences) {
      // Aplicar tema
      document.documentElement.setAttribute('data-theme', preferences.theme);

      // Aplicar idioma
      i18n.changeLanguage(preferences.language);

      // Configurar moment/dayjs timezone
      dayjs.tz.setDefault(preferences.timezone);
    }
  }, [preferences]);

  return (
    <PreferencesContext.Provider value={{ preferences, updatePreferences }}>
      {children}
    </PreferencesContext.Provider>
  );
};

Datos de Prueba

Escenario Entrada Resultado
Obtener preferencias GET /preferences 200, preferencias o defaults
Cambiar idioma language: "en" 200, idioma actualizado
Zona horaria invalida timezone: "Invalid/Zone" 400, "Zona horaria invalida"
Tema valido theme: "dark" 200, tema actualizado
Tema invalido theme: "purple" 400, "Valor no permitido"
Desactivar notificaciones notifications.email.enabled: false 200, actualizado
Reset preferencias POST /reset 200, defaults del tenant

Estimacion

Capa Story Points Notas
Database 1 Tabla user_preferences
Backend 2 CRUD preferencias
Frontend 4 UI de configuracion + contexto
Total 7

Notas Adicionales

  • Las preferencias se cargan al inicio de sesion y se cachean
  • Cambios de tema deben ser instantaneos (sin reload)
  • Considerar preferencias sincronizadas entre dispositivos
  • Exportar/importar preferencias para usuarios
  • Preferencias de accesibilidad (alto contraste, reducir animaciones)

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 - - [ ]