# Análisis Funcional — App de Gestión del Colectivo > **Propósito:** Base para generación de plan de desarrollo con Claude Code > **Plataforma objetivo:** Web + Mobile (iOS / Android) — paridad desde el día uno > **Enfoque:** Gestión colaborativa del colectivo: listas de la compra (núcleo), tareas y notas (complemento) > **Usuarios principales:** Familias y parejas con uso compartido frecuente > **Stack tecnológico:** A definir tras revisión del plan --- ## Contexto y Objetivo Desarrollar una aplicación de gestión doméstica centrada en la colaboración familiar en tiempo real. El producto resuelve el problema concreto de coordinar la compra, las tareas del colectivo y las notas entre los miembros de una familia o pareja, desde cualquier dispositivo y sin fricciones. La unidad organizativa central es el **Colectivo**: una entidad compartida a la que pertenecen todos los contenidos, en lugar del modelo usuario-céntrico habitual. Esto refleja la realidad de uso: la lista de la compra no es de una persona, es del colectivo. --- ## 1. Módulos del Sistema ### 1.1 Colectivo y Miembros ### 1.2 Lista de la Compra ### 1.3 Tareas ### 1.4 Notas ### 1.5 Autenticación y Usuarios ### 1.6 Sincronización y Offline ### 1.7 Búsqueda --- ## 2. Módulo: Colectivo y Miembros Este módulo es la base de toda la arquitectura. Sin colectivo no hay contenido compartido. ### 2.1 Concepto de Colectivo Un **Colectivo** es el espacio compartido de una familia o grupo de convivencia. Agrupa listas de la compra, tareas y notas. Cada usuario pertenece a uno o más colectivos, aunque el caso habitual es uno. ``` Colectivo └── tiene muchos Miembros (con rol) └── tiene muchas Listas de la Compra └── tiene muchas Listas de Tareas └── tiene muchas Notas ``` ### 2.2 Roles dentro del Colectivo | Rol | Descripción | Permisos | |-----|-------------|----------| | Administrador | Creador del colectivo o promovido por otro admin | CRUD completo + gestión de miembros + disolver colectivo | | Miembro | Miembro activo del colectivo | CRUD sobre todo el contenido del colectivo | | Invitado | Acceso temporal o de solo lectura | Solo lectura; no puede crear ni editar | > **Decisión de diseño:** El modelo de permisos es deliberadamente simple. En un contexto familiar no tiene sentido granularidad fina por recurso. Si se necesita privacidad, el mecanismo es crear un colectivo adicional (ej: colectivo personal). ### 2.3 Atributos ``` Colectivo { id: UUID nombre: string emoji: string | null ← identificador visual rápido creado_por: UUID creado_en: timestamp } MiembroColectivo { colectivo_id: UUID usuario_id: UUID rol: enum(administrador | miembro | invitado) unido_en: timestamp invitado_por: UUID } InvitacionColectivo { id: UUID colectivo_id: UUID email: string token: string ← link de invitación único rol_asignado: enum(miembro | invitado) expira_en: timestamp ← 7 días por defecto aceptada: boolean } ``` ### 2.4 Casos de Uso | ID | Caso de uso | Actor | Descripción | |----|-------------|-------|-------------| | CU-H01 | Crear colectivo | Usuario autenticado | Define nombre y emoji; queda como administrador | | CU-H02 | Invitar miembro | Administrador | Introduce email + rol → se envía link de invitación | | CU-H03 | Aceptar invitación | Invitado | Accede al link → registra cuenta si no tiene → se une al colectivo | | CU-H04 | Cambiar rol de miembro | Administrador | Promueve a administrador o degrada a invitado | | CU-H05 | Expulsar miembro | Administrador | El miembro pierde acceso inmediato al colectivo y su contenido | | CU-H06 | Abandonar colectivo | Miembro / Invitado | El usuario sale del colectivo; el contenido permanece | | CU-H07 | Cambiar nombre / emoji | Administrador | Edición del colectivo visible para todos los miembros | | CU-H08 | Disolver colectivo | Administrador | Elimina el colectivo y todo su contenido de forma permanente | | CU-H09 | Cambiar de colectivo activo | Usuario con varios colectivos | Selector de colectivo visible en la navegación principal | ### 2.5 Flujo: Incorporación de nuevo miembro (CU-H02 → CU-H03) ``` [Administrador abre "Gestionar miembros" → "Invitar"] ↓ Introduce email + selecciona rol (miembro / invitado) ↓ Sistema genera link único con token (expira en 7 días) Sistema envía email con link ↓ ¿El email ya tiene cuenta? SÍ → Al abrir el link: confirmación de unión con un tap NO → Al abrir el link: flujo de registro simplificado → confirmación de unión ↓ Miembro queda activo en el colectivo Todos los miembros reciben notificación: "[Nombre] se ha unido al colectivo" El nuevo miembro ve inmediatamente todo el contenido del colectivo ``` --- ## 3. Módulo: Lista de la Compra Módulo principal del producto. Debe ser la experiencia más pulida y rápida de la app. ### 3.1 Modelo de Datos ``` ListaCompra { id: UUID colectivo_id: UUID nombre: string estado: enum(activa | completada | archivada) creado_por: UUID creado_en: timestamp completada_en: timestamp | null } ItemCompra { id: UUID lista_id: UUID nombre: string cantidad: decimal | null unidad: string | null ← "kg", "L", "uds", "paquetes"… marcado: boolean ← comprado durante sesión de compra marcado_por: UUID | null marcado_en: timestamp | null orden: integer ← posición en la lista creado_por: UUID creado_en: timestamp } ``` ### 3.2 Estados de una Lista ``` Activa → En sesión de compra → Completada → Archivada ``` **Reglas de negocio:** - Solo puede haber una **sesión de compra activa** por lista a la vez. - Completar una lista no elimina los ítems; quedan como historial. - Una lista completada puede "reiniciarse": desmarca todos los ítems y vuelve a activa. - Los ítems marcados durante la sesión registran quién los marcó y cuándo. ### 3.4 Modo "Ir de Compras" Experiencia de UI dedicada para el momento de estar físicamente en el supermercado. Requisitos: - **Ítems grandes y fáciles de marcar** con un tap — optimizado para pantalla de teléfono con una mano. - **Ítems pendientes arriba, marcados abajo** — reordenamiento automático al marcar. - **Indicador de presencia:** si otro miembro del colectivo también tiene la lista abierta, se muestra su avatar. - **Sincronización agresiva:** cambios visibles en < 1 segundo entre dispositivos (sin esperar al intervalo normal de sync). - **Funcional offline:** si se pierde cobertura en el súper, los cambios se sincronizan al recuperar red. - Botón prominente **"Finalizar compra"** que marca la lista como completada. ### 3.5 Casos de Uso | ID | Caso de uso | Actor | Descripción | |----|-------------|-------|-------------| | CU-C01 | Crear lista | Miembro | Nueva lista vacía | | CU-C02 | Añadir ítem | Miembro | Nombre + cantidad/unidad opcional; guardado inmediato; muestra sugerencias de ítems frecuentes del colectivo | | CU-C03 | Editar ítem | Miembro | Modifica nombre, cantidad o unidad | | CU-C04 | Reordenar ítems | Miembro | Drag & drop manual para organizar por pasillos | | CU-C05 | Eliminar ítem | Miembro | Borrado con confirmación por deslizamiento (swipe) | | CU-C06 | Marcar ítem como comprado | Miembro (en sesión) | Tap en checkbox; ítem baja al fondo automáticamente | | CU-C07 | Desmarcar ítem | Miembro (en sesión) | Tap en ítem marcado; vuelve a pendiente | | CU-C08 | Iniciar sesión de compra | Miembro | Activa el "Modo ir de compras" con UX dedicada | | CU-C09 | Finalizar compra | Miembro | Lista pasa a estado completada; se registra timestamp | | CU-C10 | Reiniciar lista | Miembro | Desmarca todos los ítems; lista vuelve a activa | | CU-C11 | Eliminar lista | Miembro | Mueve a papelera del colectivo (recuperable 7 días) | | CU-C12 | Archivar lista completada | Sistema / Miembro | Lista completada pasa a archivo; libera espacio en vista principal | ### 3.6 Recomendaciones de ítems frecuentes Al añadir un ítem a cualquier lista, el sistema sugiere ítems basándose en el historial de uso del colectivo. Sin IA — frecuencia pura de registros en base de datos. - **Input vacío:** chips con los 5 ítems más usados del colectivo (acceso rápido) - **Al escribir:** lista filtrada por prefijo (máx. 10), ordenada por frecuencia - **Alcance:** compartido entre todos los miembros del colectivo - **Registro:** trigger en `shopping_items` — automático en cada añadido, sin intervención de la app - **Normalización:** los nombres se normalizan (`lower(trim(name))`) antes de acumular la frecuencia, evitando duplicados por mayúsculas o espacios ### 3.7 Flujo: Sesión de Compra (CU-C08) ``` [Miembro toca "Ir de compras" en lista activa] ↓ App entra en Modo Compra: - UI de ítems en formato grande - Ítems pendientes arriba / marcados abajo - Indicador de otros miembros presentes en la lista - Sincronización reforzada (WebSocket activo) ↓ Miembro va marcando ítems conforme los mete en el carro ↓ ¿Otro miembro añade ítem desde casa? → Aparece en la lista en tiempo real con indicador "Nuevo" ↓ [Miembro toca "Finalizar compra"] ↓ Confirmación: "¿Marcar lista como completada?" SÍ → Lista pasa a estado completada Se registra timestamp de finalización Se sale del Modo Compra Notificación a otros miembros: "La compra ha sido completada por [Nombre]" NO → Se mantiene en Modo Compra ``` --- ## 4. Módulo: Tareas Módulo secundario. Gestión simple de tareas del colectivo, sin complejidad de project management. ### 4.1 Modelo de Datos ``` ListaTareas { id: UUID colectivo_id: UUID nombre: string ← ej: "Tareas de la semana", "Reformas pendientes" creado_por: UUID creado_en: timestamp } Tarea { id: UUID lista_id: UUID titulo: string completada: boolean completada_por: UUID | null completada_en: timestamp | null orden: integer creado_por: UUID creado_en: timestamp } ``` > **Decisión deliberada:** Sin fechas límite, prioridades ni subtareas en el MVP. El foco es la simplicidad. Si el producto crece, estas features son candidatas naturales a v2. ### 4.2 Estados de una Tarea ``` Pendiente → Completada ↓ (puede desmarcarse → vuelve a Pendiente) ``` ### 4.3 Casos de Uso | ID | Caso de uso | Actor | Descripción | |----|-------------|-------|-------------| | CU-T01 | Crear lista de tareas | Miembro | Nueva lista con nombre | | CU-T02 | Añadir tarea | Miembro | Título; se guarda inmediatamente | | CU-T03 | Completar tarea | Miembro | Tap en checkbox; registra quién y cuándo | | CU-T04 | Descompletar tarea | Miembro | Tap en tarea completada; vuelve a pendiente | | CU-T05 | Editar título de tarea | Miembro | Edición inline | | CU-T06 | Reordenar tareas | Miembro | Drag & drop | | CU-T07 | Eliminar tarea | Miembro | Swipe para eliminar con confirmación | | CU-T08 | Eliminar lista de tareas | Miembro | Elimina la lista y todas sus tareas | | CU-T09 | Ver quién completó una tarea | Miembro | Tooltip / detalle: "Completada por [Nombre] el [fecha]" | ### 4.4 Reglas de Negocio - Las tareas completadas permanecen visibles en la lista (no se ocultan automáticamente), hundidas al fondo. - No existe papelera para tareas individuales: la eliminación es inmediata con confirmación por swipe. - Una lista de tareas solo puede eliminarse si está vacía o el miembro confirma borrado en cascada. --- ## 5. Módulo: Notas Módulo de utilidad. Complementa los otros dos módulos para casos como recetas, instrucciones, información del colectivo, etc. ### 5.1 Modelo de Datos ``` Nota { id: UUID colectivo_id: UUID titulo: string (opcional) contenido: string ← texto plano con Markdown básico color: enum(8 colores predefinidos) | null fijada: boolean archivada: boolean eliminada: boolean eliminada_en: timestamp | null creado_por: UUID creado_en: timestamp modificado_por: UUID modificado_en: timestamp } ``` > **Scope reducido vs análisis original:** Se eliminan tipos de nota (imagen, audio), historial de versiones y comentarios. Las notas son texto con Markdown básico. Si el producto crece, estas features son candidatas a v2. ### 5.2 Estados de una Nota ``` Activa → [Fijada | Archivada | En papelera → Eliminada permanentemente] ``` **Reglas de negocio:** - `Fijada` y `Archivada` son mutuamente excluyentes. - La papelera retiene notas 7 días antes de eliminarlas permanentemente. - Las notas en papelera no aparecen en búsquedas. - El guardado es automático. - Cualquier miembro del colectivo puede editar cualquier nota del colectivo. ### 5.3 Casos de Uso | ID | Caso de uso | Actor | Descripción | |----|-------------|-------|-------------| | CU-N01 | Crear nota | Miembro | Abre editor, introduce contenido, se guarda automáticamente | | CU-N02 | Editar nota | Miembro | Modifica contenido; se registra modificado_por y modificado_en | | CU-N03 | Fijar nota | Miembro | Nota aparece en bloque superior del tablero | | CU-N04 | Archivar nota | Miembro | Sale del tablero principal; accesible por búsqueda | | CU-N05 | Mover a papelera | Miembro | Va a papelera con timestamp | | CU-N06 | Restaurar nota | Miembro | Recupera desde papelera o archivo | | CU-N07 | Eliminar permanentemente | Miembro | Borrado definitivo desde papelera | | CU-N08 | Cambiar color | Miembro | Selección visual entre colores predefinidos | | CU-N09 | Duplicar nota | Miembro | Crea copia independiente | --- ## 6. Módulo: Autenticación y Usuarios ### 6.1 Flujos de Autenticación - Registro con email + contraseña - Login con email + contraseña - OAuth — Google (requerido) y Apple (requerido en iOS) - Recuperación de contraseña vía email - Sesión persistente con refresh token - Flujo de registro simplificado al aceptar invitación a colectivo (el email queda prerellenado) ### 6.2 Atributos de Usuario ``` User { id: UUID email: string ← único, gestionado por Keycloak display_name: string language: enum(en | es) ← preferencia del usuario; default: idioma del navegador avatar_type: enum(initials | emoji | upload) avatar_emoji: string | null ← solo cuando avatar_type = emoji (e.g. "🐸") avatar_url: string | null ← solo cuando avatar_type = upload (Supabase Storage) created_at: timestamp last_seen_at: timestamp } ``` ### 6.3 Configuración de usuario Pantalla `/settings` accesible desde la navegación principal. Permite al usuario editar: - **Display name** — nombre visible en el colectivo, presencia y avatares - **Avatar** — tres opciones, excluyentes entre sí: 1. *Initials* (default) — inicial(es) del display name sobre fondo slate 2. *Emoji* — selector de emoji de una lista curada (~40 opciones) 3. *Upload* — foto propia; almacenada en Supabase Storage (bucket privado, URL firmada) - **Language** — selector entre English y Español; efecto inmediato sin recargar > **Nota:** El email y la contraseña se gestionan en Keycloak, no en esta pantalla. Incluir un enlace externo a la cuenta de Keycloak para esos cambios. ### 6.3 Reglas de Negocio - Un usuario puede pertenecer a múltiples colectivos simultáneamente. - Eliminar una cuenta no elimina el contenido del colectivo; los ítems/tareas/notas creados por ese usuario permanecen. - Si el único administrador de un colectivo elimina su cuenta, el colectivo queda huérfano → el sistema debe promover automáticamente al miembro más antiguo como administrador antes de permitir la eliminación. --- ## 7. Módulo: Sincronización y Offline ### 7.1 Estrategia Offline-First El escenario crítico es estar físicamente en un supermercado con cobertura inestable. La app debe ser completamente funcional sin conexión. - Almacenamiento local: **IndexedDB** en web, **SQLite** en mobile. - Todas las operaciones se ejecutan primero en local y se sincronizan en segundo plano. - Al recuperar conexión, se sincronizan todos los cambios pendientes. - **Resolución de conflictos:** last-write-wins con aviso visual al usuario cuando se detecta sobreescritura de cambios de otro miembro. - Indicador de estado de sincronización siempre visible en la UI (sincronizado / sincronizando / sin conexión). ### 7.2 Sincronización en Tiempo Real La sincronización en tiempo real es un requisito no negociable para la lista de la compra compartida. - **WebSockets** para sesiones de compra activas (presencia + cambios en tiempo real). - **Polling o SSE** para el resto del contenido (menor frecuencia, menor coste de infraestructura). - **Indicador de presencia:** cuando dos miembros tienen la misma lista abierta simultáneamente, se muestran los avatares de los miembros presentes. ### 7.3 Prioridades de Sincronización | Tipo de contenido | Mecanismo | Latencia objetivo | |-------------------|-----------|-------------------| | Ítems de lista en sesión de compra activa | WebSocket | < 1 segundo | | Listas de la compra (fuera de sesión) | SSE / polling | < 5 segundos | | Tareas | SSE / polling | < 5 segundos | | Notas | Polling | < 30 segundos | | Miembros del colectivo | Polling | < 60 segundos | --- ## 8. Módulo: Búsqueda ### 8.1 Alcance | Ámbito | ¿Incluido? | Notas | |--------|-----------|-------| | Listas de la compra activas | ✅ | Busca también en nombres de ítems | | Listas de la compra archivadas | ✅ | | | Listas en papelera | ❌ | | | Plantillas | ✅ | | | Tareas | ✅ | Busca en títulos de tarea y nombre de lista | | Notas activas | ✅ | Busca en título y contenido | | Notas archivadas | ✅ | | | Notas en papelera | ❌ | | ### 8.2 Filtros - Por tipo de contenido (lista de compra / tareas / notas) - Por miembro creador - Por rango de fechas - Por estado (activo / archivado / completado) --- ## 9. Reglas de Negocio Globales | # | Regla | |---|-------| | RN-01 | Todo el contenido pertenece al Colectivo, no a un usuario individual. | | RN-02 | Cualquier miembro activo del colectivo puede crear, editar y eliminar contenido. | | RN-03 | Solo los administradores pueden gestionar miembros e invitaciones. | | RN-04 | Solo los administradores pueden disolver el colectivo. | | RN-05 | El guardado es automático en todos los módulos. No existe botón "Guardar". | | RN-06 | Offline-first: los cambios locales se aplican inmediatamente y se sincronizan en segundo plano. | | RN-07 | Los conflictos de sincronización se registran y son visibles al usuario afectado. | | RN-08 | La búsqueda no opera sobre la papelera. | | RN-09 | Eliminar una cuenta de usuario no elimina el contenido del colectivo. | | RN-10 | Un colectivo debe tener siempre al menos un administrador activo. | | RN-11 | Solo puede existir una sesión de compra activa por lista a la vez. | | RN-12 | Las plantillas de lista son inmutables durante una sesión de compra activa basada en ellas. | --- ## 10. Requerimientos No Funcionales - **Sincronización en sesión de compra:** cambios visibles en < 1 segundo entre dispositivos. - **Sincronización general:** cambios visibles en < 5 segundos entre dispositivos. - **Offline:** la app debe ser 100% funcional sin conexión en todos los módulos. - **Seguridad:** datos cifrados en tránsito (TLS) y en reposo; aislamiento estricto entre colectivos. - **Multiplataforma:** paridad de funcionalidades entre web y mobile desde el día uno. - **Rendimiento mobile:** el Modo Compra debe funcionar con fluidez en gama media (60fps, respuesta a tap < 100ms). - **Stack tecnológico:** a definir — el plan de desarrollo debe ser agnóstico al stack. --- ## 11. Entidades del Dominio (Resumen) ``` Usuario └── pertenece a muchos Colectivos (a través de MiembroColectivo) Colectivo ├── tiene muchos MiembroColectivo ├── tiene muchas ListasCompra ├── tiene muchas ListasTareas └── tiene muchas Notas MiembroColectivo ├── referencia Usuario ├── referencia Colectivo └── tiene rol: enum(administrador | miembro | invitado) ListaCompra ├── pertenece a Colectivo ├── tiene muchos ItemCompra └── puede ser Plantilla (es_plantilla = true) ItemCompra └── pertenece a ListaCompra ListaTareas ├── pertenece a Colectivo └── tiene muchas Tareas Tarea └── pertenece a ListaTareas Nota └── pertenece a Colectivo InvitacionColectivo └── referencia Colectivo ``` --- ## 12. Pantallas Principales del MVP Esta sección orienta el plan de desarrollo sobre el alcance de UI esperado. | Pantalla | Descripción | |----------|-------------| | Onboarding | Login + creación o unión a colectivo | | Home | Vista principal con listas activas, tareas pendientes destacadas y notas fijadas | | Lista de la compra — vista normal | Ítems con cantidad/unidad, opción de editar, añadir y reordenar | | Lista de la compra — Modo Compra | UI dedicada: ítems grandes, marcado fácil, indicador de presencia | | Tareas | Lista de tareas con checkboxes | | Notas | Tablero de notas del colectivo | | Editor de nota | Editor de texto con Markdown básico | | Gestión del colectivo | Miembros, roles, invitaciones | | Búsqueda | Búsqueda global con filtros | | Configuración de usuario (`/settings`) | Display name, avatar (initials / emoji / upload), idioma | --- *Documento generado como base para plan de desarrollo. Stack tecnológico a definir tras revisión del plan.*