# Sistemax Mobile — Roadmap & Estado

> Última actualización: 2026-06-17
> Cobertura aproximada vs web: **~93%** del flujo operativo de farmacia.
> Rebrand: la app antes "EnterFarmaPlus" ahora se distribuye como **Sistemax**.

Este documento mantiene una vista panorámica de qué está implementado en la app móvil
(Flutter + Laravel API v1) y qué queda pendiente. Sirve como referencia para
priorizar próximos sprints.

> **Nota de scope (2026-06-17):** el roadmap fue revisado item por item. Varias
> features del web NO se llevan a móvil por no ser apropiadas en celular
> (despachos, cotizaciones, devoluciones independientes). Ver sección
> **Pendientes** y **Fuera de scope móvil**.

---

## ✅ Implementado

### 🏠 Inicio (Dashboard)
- Hero compacto con total del día, comparativa vs ayer, conteo de operaciones.
- Banner alertable de comprobantes por enviar/regularizar (tappeable → ventas emitidas).
- Banner de stock crítico (tappeable → inventario).
- Panel "Caja actual" con apertura, ingresos, disponible y acciones (ver reporte / cerrar).
- Tendencia compacta (mini chart).
- Pull-to-refresh + apertura de caja vía sheet.

### 💰 Vender (POS)
- Cliente compacto con búsqueda de DNI/RUC vía API Peru.
- Buscador con scanner de barras.
- Catálogo con cards densos (stock, presentaciones, lotes).
- Validación de stock según `inventory_configurations.stock_control` del web.
- Ocultar/mostrar productos sin stock automáticamente.
- Carrito con barra inferior fija (total + cobrar).
- Sheet "Opciones del comprobante" con tipo (chips Boleta/Factura/Nota), serie,
  condición, observaciones.
- **Pagos múltiples estilo POS web**: tiles para Efectivo/Yape/Plin/Transferencia,
  tap = activar y cargar resto, ícono de referencia para no-cash.
- Filtro por `is_credit` y `active_pos`.
- Default automático cash = total al abrir, reset al limpiar.
- Detalle del comprobante emitido con ver PDF, imprimir, WhatsApp.
- **POS offline**: emisión sin internet con cola de pendientes (`idempotency_key`),
  sync automático por conectividad + reintento manual.

### 📦 Catálogo
- Productos y Servicios separados.
- Cards densos con avatar/imagen, badges de estado.
- Borde lateral por estado (rojo agotado, amarillo bajo).
- Filtros chips: Todos / Sin stock / Bajo / Favoritos.
- Long-press → editar / favorito / activar.
- Tabs en editor: General + Presentaciones (CRUD completo de `item_unit_types`).
- `stock_min` se carga al editar (fix).
- Scanner de barras integrado.

### 👥 Clientes / Proveedores
- Cards densos con avatar de iniciales (color por hash) + badge tipo doc.
- Long-press → editar / llamar / WhatsApp / email.
- Recientes como chips horizontales scrollables.
- Empty state con auto-create.
- Lookup automático SUNAT/RENIEC al ingresar 8/11 dígitos.
- Validación de longitud por tipo de documento.
- Cliente "Varios" destacado.

### 🛒 Compras
- Cards densos con borde lateral por estado de pago.
- Avatar iniciales del proveedor + badge tipo doc + fecha + total + chip de estado.
- Filtros chips: Todas / Pagadas / Parcial / Pendientes.
- Long-press → ver detalle / registrar pago / PDF.
- **Editor multi-producto**: lista de líneas, agregar/quitar, total calculado.
- **Validación de lotes**: producto con `lots_enabled=true` requiere código + fecha
  de vencimiento (date picker en español).
- **Pagos parciales / cuotas**: sheet con resumen + barra de progreso, sección de
  cuotas programadas (con botón "Usar"), historial de pagos previos, form completo
  (método/destino/monto con botón "Todo"/referencia). Recarga sin cerrar.
- Total acumulado del filtro.
- Conteo en header.

### 📋 Ventas emitidas
- Tabs Comprobantes / Notas de venta.
- Búsqueda por serie, número o cliente.
- Detalle con Ver PDF / Imprimir / WhatsApp.
- **Anular interno** (estado 13 "Por anular" con devolución de stock).
- **Comunicación de baja a SUNAT real** desde la pantalla "Por anular":
  - Branch dual Nubefact / SUNAT-PSE directo.
  - Guard de ventana (`shipping_time_days_voided`).
  - Guard de Voided previo no duplicado.
- **Confirmar / Revertir** anulación local.
- **Emitir Nota de Crédito** (anulación total / parcial / descuento global) sobre comprobantes aceptados.
- **Enviar a SUNAT** (solo si state ≠ 05/11/13).
- Estados validados (no anular si registrado, no SUNAT si anulado).

### 📊 Reportes (hub)
- Grid de reportes: General · Stock crítico · Por vencer · Por vendedor ·
  Inventario · Lotes · Historial de cajas.
- **General**: total del período + delta vs anterior + ticket promedio + tendencia +
  top productos vendidos + compartir resumen WhatsApp.
- **Stock crítico**: filtros (todos / sin stock / bajo) + stat cards.
- **Por vencer**: filtros (30/60/90 días) + lista coloreada por urgencia.
- **Por vendedor**: ranking con barra de progreso, filtro hoy / mes.
- **Inventario**: consolidado + top valorizados (paginado SQL).
- **Lotes**: con/sin lote, expandible para ver código + vencimiento + cantidad por lote.

### 🔍 Consulta SUNAT
- Selector de tipo (Factura / Boleta) + dropdown serie + input número.
- Búsqueda exacta + estado SUNAT con color + reenvío.

### 🧾 Inventario
- Lista paginada con filtros tap-to-filter (todos / agotados / bajo).
- Hero con KPIs (`low_stock_count`, `no_stock_count` del backend).
- Detalle por producto + movimientos de stock con validación de lote.

### 📐 Conteo físico (Stocktake)
- Listado de sesiones, sesión activa con escaneo/conteo, kardex por item, reporte de diferencias.
- Aprobación web genera ajuste real vía Inventory model → observer.

### 👤 Mi perfil
- Hero con logo de empresa o iniciales, nombre, email, rol.
- Quick actions: **Impresora**, **Contraseña**, **Acerca de**.
- Card "Negocio" combinada (Empresa + Sucursal).
- Versión + bottom sheet "Acerca de" con tenant / api / versión.
- **Cambio de contraseña** con form (actual / nueva / confirmar) y validación.

### ⚙ Más opciones (grid)
Catálogo · Servicios · Clientes · Proveedores · Compras · Ventas emitidas ·
Por anular · Consulta SUNAT.

### 💼 Caja
- Apertura con monto inicial.
- **Cierre con arqueo**: 11 denominaciones peruanas (200 → 0.10), subtotales en
  vivo, comparativa Esperado / Contado / Diferencia con color.
- **Arqueo persistido en BD** (`cash.closing_denominations` + `arqueo_summary` JSON) — Sprint 1.
- Reportes PDF de cierre.

### 🏢 Multi-establecimiento (v1 — Fase 1)
- `allowed_establishments` + `active_establishment_id` en el payload.
- Cambio de sede activa (`POST session/establishment`).
- Cada usuario está atado a su `establishment_id`; un vendedor con una sola sede
  no ve selector (va automático). El selector solo aplica a usuarios con varias sedes.

### 🔧 Sistema
- Autenticación por RUC + email/password (Sanctum `api_token`).
- Sesión persistente, logout suave (preserva RUC/baseUrl/companyName).
- Role-based access (Seller: Inicio/Vender/Más; Admin: todo). Router guard.
- Localización española (date pickers, snackbars).
- Push token lifecycle backend: registrar/revocar token por dispositivo.

---

## ✅ Hitos completados

### Sprint 1 SUNAT (2026-04-15)
| # | Item | Estado | Commit |
|---|------|--------|--------|
| 1 | **Anular compras** con devolución de stock + kardex + lotes | ✅ | `d38b161c` |
| 2 | **NC parcial** (selector items + cantidades, tipo SUNAT 07) | ✅ | `d38b161c` |
| 3 | **Nota de Débito** tipo 08 (interés / aumento / penalidad) | ✅ | `d38b161c` |
| 4 | **NC descuento global** tipo SUNAT 04 | ✅ | `6efa60f6` |
| 5 | **Persistencia del arqueo de caja** (`cash.closing_denominations` + `arqueo_summary` JSON) | ✅ | `6efa60f6` |
| 6 | **Persistencia de pagos contra cuota** (`purchase_payments.purchase_fee_id`) + fallback FIFO | ✅ | `d98c221c` |

### Rebrand a Sistemax (2026-04-15)
- Nombre app, icono adaptive (safe zone), login redesign con logo, splash instantáneo.
- Textos "EnterFarmaPlus" reemplazados en todo el mobile.

### Fase 1 (2026-05-06)
- **Multi-establecimiento v1**: `allowed_establishments` + `active_establishment_id` + cambio de sede.
- **Offline POS crítico**: cache local de tablas/items/clientes + cola de ventas con `idempotency_key`.
- **Sync de pendientes**: automático por conectividad y manual desde POS; pantalla dedicada (listar/reintentar/descartar).
- **Push token lifecycle backend**: registrar y revocar token por dispositivo.

### Conteo físico móvil (2026-05-21)
- Tablas `mobile_physical_counts` / `_lines` / `_events`. API móvil + aprobación web + 4 pantallas Flutter.

---

## 🚧 Pendientes (scope móvil decidido 2026-06-17)

### 🟡 Aprobados — construir
| # | Item | Notas |
|---|------|-------|
| 7 | **Multi-establecimiento (admin)** | Filtros por sede activa en reportes y stock. Solo aplica a admin con varias sedes; el vendedor ya va atado a su `establishment_id`. |
| 8 | **Offline — solo venta** | Lo crítico ya está (cache + cola). NO se busca offline 100%; catálogo/compras/reportes requieren internet (operación es ~99% online). |
| 13 | **Búsqueda avanzada** ventas / compras | Filtros por rango de fecha, vendedor, monto. |
| 14 | **Reporte por categoría** y **por horarios** | Qué vende más, en qué franjas horarias. |
| 16 | **Foto real del cliente** (avatar) | Reemplaza iniciales por hash. |
| 23 | **Notificación de actualización** | Vía **In-App Update API de Google Play** (`in_app_update`), no banner casero. Habilitado al publicar en Play Store. |
| 24 | **Sentry en Flutter** | `sentry/sentry-laravel` ya está en backend, pero la app Flutter NO tiene `sentry_flutter`. Crashes del celular no se reportan hoy. |
| 25 | **Tests E2E** | Patrol / `integration_test`. |
| 27 | **Optimizar query `inventoryReport`** | Carga todos los items en memoria; debería paginar SQL. |
| 28 | **Endpoint dedicado** `documents-not-sent` / `documents-regularize-shipping` | Hoy se recalculan por query en cada `dashboardSummary`. |

### 🔴 Fuera de scope móvil (quedan en web)
| # | Item | Motivo |
|---|------|--------|
| 10 | Despachos / guías de remisión | No apropiado para celular. |
| 11 | Cotizaciones | No apropiado para celular. |
| 12 | Devoluciones independientes | No apropiado para celular. |
| 15 | Imágenes de producto desde cámara | Se trabaja con lista, no con fichas visuales. |
| 18 | Tema oscuro | No por ahora. |
| 19 | Atajos personalizables en home | No necesario. |
| 20 | i18n completo (`intl_*.arb`) | Solo español; no hay plan de otro idioma. |
| 26 | CI/CD (APK automático) | Build sigue manual. |

### 🟠 Diferido
| # | Item | Notas |
|---|------|-------|
| 21 | **PWA** | Más adelante. Limitación: impresión térmica BT no funciona en navegador iOS. |
| 22 | **Versión iOS** del Flutter | Hoy solo Android compilado. Play Store = solo Android. |
| 29-34 | Avanzado (predictivo, balanzas BT, NFC DNI, kiosko, multi-moneda, caja chica) | Baja prioridad. |

---

## 🏪 Plan Play Store (subida próxima)

La app pasa de **distribución manual de APK** a publicación en Google Play. Requisitos:

- **AAB firmado** (Android App Bundle), no APK.
- **Política de privacidad** publicada (URL accesible).
- **Target SDK** al día según política vigente de Play.
- Ficha de tienda (capturas, descripción, ícono, categoría).
- Data Safety form (qué datos recolecta la app).

Implicaciones:
- **#23** usa la **In-App Update API** nativa de Play (`in_app_update`) en vez de banner casero.
- iOS (#22) sigue aparte: Play Store es solo Android.

---

## 📊 Cobertura por módulo (vs web)

| Módulo | Móvil | Comentario |
|---|---|---|
| Ventas POS | 🟢 90% | Falta fast-pay y emisión simultánea con impresión. |
| Compras | 🟢 90% | Anular compras, pagos parciales por cuota. Falta retención + detracción. |
| Inventario | 🟢 85% | Falta transferencias entre almacenes. |
| Caja | 🟢 90% | Arqueo persistido en BD. Falta movimientos manuales (entradas/salidas). |
| Reportes | 🟢 80% | Faltan por categoría/horarios (#14). |
| Comprobantes SUNAT | 🟢 98% | Anular, voided real, NC total/parcial/descuento global, ND tipo 08. |
| Catálogo | 🟢 90% | Casi completo. |
| Contactos | 🟢 95% | Completo. |
| Conteo físico | 🟢 100% | Completo (sesión + kardex + reporte + aprobación web). |
| Multi-establecimiento | 🟡 70% | v1 con cambio de sede; falta filtro consistente en reportes/stock (#7). |
| Observabilidad (Sentry) | 🔴 backend sí / móvil no | `sentry_flutter` pendiente (#24). |
| Despachos / Cotizaciones / Devoluciones | ⚪ N/A | Fuera de scope móvil. |

---

## 🔬 Endpoints mobile críticos

```
POST   /api/mobile/v1/auth/login
GET    /api/mobile/v1/bootstrap
GET    /api/mobile/v1/me
POST   /api/mobile/v1/me/password
POST   /api/mobile/v1/session/establishment       ← cambio de sede
GET    /api/mobile/v1/dashboard/summary
GET    /api/mobile/v1/items
GET    /api/mobile/v1/customers   POST .../customers
GET    /api/mobile/v1/persons/lookup/{type}/{number}
GET    /api/mobile/v1/documents   POST .../documents
GET    /api/mobile/v1/documents/{id}/pdf
POST   /api/mobile/v1/documents/{id}/send-sunat
POST   /api/mobile/v1/documents/{id}/anular        ← state 13 + stock
POST   /api/mobile/v1/documents/{id}/voided-sunat  ← comunicación de baja real
POST   /api/mobile/v1/documents/{id}/credit-note   ← NC tipos 01,04,07
POST   /api/mobile/v1/documents/{id}/debit-note    ← ND tipo 08
GET    /api/mobile/v1/purchases   POST .../purchases
POST   /api/mobile/v1/purchases/{id}/anular        ← anular con devolución de stock
GET    /api/mobile/v1/purchases/{id}/fees          ← cuotas con matching real
POST   /api/mobile/v1/cash/{id}/close              ← acepta denominations[]
GET    /api/mobile/v1/inventory/stock
GET    /api/mobile/v1/reports/sales | inventory | top-products
GET    /api/mobile/v1/reports/critical-stock | expiring-lots | by-seller | lots-overview
```

---

## 📦 Stack y arquitectura

**Backend**
- Laravel 10.50.2 / PHP 8.3.27 · multi-tenant (custom tenancy layer)
- Endpoints móviles en `modules/MobileApp/Http/Controllers/Api/V1/`
- Reutilización del legacy `app/Http/Controllers/Tenant/*` vía `mobile_compose=true`
- Facturalo (SUNAT) para emisión de XML / firma / envío SOAP / Nubefact
- Observabilidad: `sentry/sentry-laravel ^4.21` (solo backend por ahora)

**Mobile**
- Flutter 3.41 / Dart 3.11 · Riverpod 2 · go_router · Dio
- print_bluetooth_thermal (ESC/POS) · printing (PDF) · mobile_scanner (barras)
- firebase_messaging (push) · share_plus · flutter_localizations (es)

**Deployment**
- Docker stack en `5.161.118.178` · 10 tenants activos · bootstrap por host (`demo.sysfarma.pe`).

---

## 🎯 Sprint 2 recomendado

Orden propuesto (solo items aprobados):

1. **#24 Sentry Flutter** — visibilidad de crashes (~1 día).
2. **#27 Optimizar `inventoryReport`** (paginar SQL) + **#28 endpoint dedicado dashboard** (~2 días).
3. **#7 Multi-establecimiento admin** (filtros reportes/stock) (~3-4 días).
4. **#13 Búsqueda avanzada** ventas/compras (~3 días).
5. **#14 Reporte por categoría + horarios** (~4 días).
6. **#16 Foto real del cliente** (~2 días).
7. **#23 In-App Update** (al subir a Play Store) (~2 días).
8. **#25 Tests E2E** (scaffold + casos críticos, continuo).

Eleva la cobertura móvil y la observabilidad sin agregar superficie fuera de scope.
