# MII-003: Gestion de Tiendas --- id: MII-003 type: Epic status: Completado priority: P0 phase: 1 story_points: 8 created_date: 2026-01-10 updated_date: 2026-01-13 simco_version: "4.0.0" --- ## Metadata | Campo | Valor | |-------|-------| | **ID** | MII-003 | | **Nombre** | Gestion de Tiendas | | **Fase** | 1 - MVP Core | | **Prioridad** | P0 | | **Story Points** | 8 | | **Estado** | Completado | --- ## 1. Descripcion Implementar el sistema de gestion de tiendas multi-tenant ligero que permite a un usuario tener multiples tiendas/negocios y opcionalmente invitar operadores. ### Objetivo Permitir a los usuarios crear y gestionar una o mas tiendas, con la posibilidad de asignar roles. --- ## 2. Requerimientos Relacionados | RF | Descripcion | Prioridad | |----|-------------|-----------| | FR-010 | Multi-Tiendas (1..N por usuario) | P0 | | FR-011 | Usuarios por tienda con roles (Owner/Operator) | P2 | --- ## 3. Criterios de Aceptacion ### AC-001: Crear Tienda ```gherkin DADO que estoy autenticado CUANDO creo una nueva tienda con nombre y giro ENTONCES la tienda se crea exitosamente Y quedo como Owner de la tienda Y puedo ver la tienda en mi lista ``` ### AC-002: Multiples Tiendas ```gherkin DADO que tengo una tienda CUANDO creo otra tienda ENTONCES ambas aparecen en mi lista Y puedo seleccionar cual usar para inventarios ``` ### AC-003: Editar Tienda ```gherkin DADO que soy Owner de una tienda CUANDO edito el nombre o configuracion ENTONCES los cambios se guardan Y se reflejan en toda la aplicacion ``` ### AC-004: Invitar Operador (P2) ```gherkin DADO que soy Owner de una tienda CUANDO invito a un usuario por telefono/email ENTONCES recibe una invitacion Y al aceptar puede acceder a la tienda como Operator ``` ### AC-005: Cambiar Tienda Activa ```gherkin DADO que tengo multiples tiendas CUANDO selecciono otra tienda como activa ENTONCES el contexto cambia Y las operaciones se ejecutan sobre la nueva tienda ``` --- ## 4. Tareas Tecnicas | ID | Tarea | Estimacion | Estado | |----|-------|------------|--------| | T-001 | Crear modulo stores en NestJS | 1 SP | Completado | | T-002 | Implementar entidad Store | 1 SP | Completado | | T-003 | Implementar relacion StoreUser | 1 SP | Completado | | T-004 | Crear endpoints CRUD tiendas | 2 SP | Completado | | T-005 | Implementar middleware de contexto tienda | 1 SP | Completado | | T-006 | Crear pantallas tiendas en mobile | 1 SP | Completado | | T-007 | Implementar selector de tienda | 1 SP | Completado | --- ## 5. Modelo de Datos ### Tabla: stores ```sql CREATE TABLE stores ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(100) NOT NULL, giro VARCHAR(50), address VARCHAR(255), phone VARCHAR(20), logo_url VARCHAR(500), settings JSONB DEFAULT '{}', is_active BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ); ``` ### Tabla: store_users ```sql CREATE TABLE store_users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), store_id UUID REFERENCES stores(id) ON DELETE CASCADE, user_id UUID REFERENCES users(id) ON DELETE CASCADE, role VARCHAR(20) NOT NULL, -- 'OWNER', 'OPERATOR' invited_by UUID REFERENCES users(id), invited_at TIMESTAMP, accepted_at TIMESTAMP, is_active BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT NOW(), UNIQUE(store_id, user_id) ); ``` ### Tabla: store_invitations ```sql CREATE TABLE store_invitations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), store_id UUID REFERENCES stores(id) ON DELETE CASCADE, invited_by UUID REFERENCES users(id), email VARCHAR(255), phone VARCHAR(20), role VARCHAR(20) NOT NULL, token VARCHAR(255) UNIQUE, status VARCHAR(20) DEFAULT 'PENDING', -- 'PENDING', 'ACCEPTED', 'EXPIRED' expires_at TIMESTAMP, created_at TIMESTAMP DEFAULT NOW() ); ``` --- ## 6. Endpoints API | Metodo | Endpoint | Descripcion | Auth | |--------|----------|-------------|------| | GET | /stores | Listar mis tiendas | JWT | | POST | /stores | Crear tienda | JWT | | GET | /stores/:id | Obtener tienda | JWT + Owner/Operator | | PATCH | /stores/:id | Actualizar tienda | JWT + Owner | | DELETE | /stores/:id | Eliminar tienda | JWT + Owner | | GET | /stores/:id/users | Listar usuarios tienda | JWT + Owner | | POST | /stores/:id/invite | Invitar usuario | JWT + Owner | | POST | /stores/accept-invite | Aceptar invitacion | JWT | | DELETE | /stores/:id/users/:userId | Remover usuario | JWT + Owner | --- ## 7. Pantallas Mobile | Pantalla | Componentes | |----------|-------------| | **StoreListScreen** | Lista de tiendas, boton crear | | **CreateStoreScreen** | Form nombre, giro, direccion | | **StoreDetailScreen** | Info, usuarios, configuracion | | **InviteUserScreen** | Input email/telefono, rol | | **StoreSelectorModal** | Lista para cambiar tienda activa | --- ## 8. Roles y Permisos | Permiso | Owner | Operator | |---------|-------|----------| | Ver tienda | ✓ | ✓ | | Editar tienda | ✓ | ✗ | | Eliminar tienda | ✓ | ✗ | | Crear inventario | ✓ | ✓ | | Ver inventarios | ✓ | ✓ | | Invitar usuarios | ✓ | ✗ | | Remover usuarios | ✓ | ✗ | | Ver wallet | ✓ | ✗ | | Hacer pagos | ✓ | ✗ | --- ## 9. Dependencias ### Entrada (Requiere) - MII-001: Infraestructura Base - MII-002: Autenticacion ### Salida (Bloquea) - MII-004: Captura de Video - MII-005: Procesamiento IA - MII-006: Reportes --- ## 10. Row-Level Security ```sql -- Politica RLS para stores CREATE POLICY store_access ON stores USING ( id IN ( SELECT store_id FROM store_users WHERE user_id = current_user_id() AND is_active = true ) ); -- Politica RLS para inventory_sessions CREATE POLICY session_access ON inventory_sessions USING ( store_id IN ( SELECT store_id FROM store_users WHERE user_id = current_user_id() AND is_active = true ) ); ``` --- ## 11. Riesgos | Riesgo | Probabilidad | Impacto | Mitigacion | |--------|--------------|---------|------------| | RLS incorrecta | Media | Alto | Tests exhaustivos, auditorias | | Invitacion fraudulenta | Baja | Medio | Expiracion, verificacion | | Contexto incorrecto | Media | Alto | Middleware robusto | --- ## 12. Notas de Implementacion - El primer inventario debe crear tienda automaticamente si no existe - Guardar store_id activo en AsyncStorage - Considerar soft delete para tiendas (is_active) - Limitar tiendas por usuario en plan gratuito (post-MVP) --- ## 13. Referencias - [REQUERIMIENTOS-FUNCIONALES.md](../00-vision-general/REQUERIMIENTOS-FUNCIONALES.md) - Seccion 5.2 - [ARQUITECTURA-TECNICA.md](../00-vision-general/ARQUITECTURA-TECNICA.md) --- **Ultima Actualizacion:** 2026-01-10