# Contexto General del Proyecto — Automia

> Documento de contexto para editores AI. Última actualización: Febrero 2026.

---

## 1. Descripción del Proyecto

**Automia** es un sistema de gestión empresarial (ERP) SaaS multi-tenant enfocado en Paraguay, con módulos de facturación electrónica, punto de venta (POS), inventario, tesorería, cobros, suscripciones y más. Soporta integración con SIFEN (Sistema Integrado de Facturación Electrónica Nacional de Paraguay).

### Repositorios

| Repositorio | Tecnología | Ruta local | Descripción |
|---|---|---|---|
| **pos-ventas** (frontend) | React 18 + Vite | `/var/www/html/proyectos/pos-ventas` | SPA del panel de administración y POS |
| **smartfactvoice-backend** | NestJS 11 + Prisma 6 + PostgreSQL | `/var/www/html/proyectos/smartfactvoice-backend` | API REST versionada (`/api/v1/`) |

### Stack Tecnológico

**Frontend:**
- React 18 con Vite 5
- Zustand (state management)
- TanStack Query (server state / caching)
- MUI v7 (Material UI) + styled-components
- Axios (HTTP client con refresh token automático)
- Dexie.js 4 (IndexedDB wrapper para offline)
- PWA con vite-plugin-pwa + Workbox
- React Router v6
- Sonner (toasts), Recharts (gráficos), pdfmake (reportes PDF)

**Backend:**
- NestJS 11 (Node.js framework)
- Prisma 6 ORM → PostgreSQL
- Passport JWT (autenticación)
- BullMQ + Redis (colas de trabajo: email, SIFEN)
- Swagger (documentación API en `/docs`)
- AWS S3 (almacenamiento de archivos)
- Twilio (SMS/verificación)
- Nodemailer (emails)

---

## 2. Arquitectura General

```
┌─────────────────────────────────────────────────────────┐
│                   FRONTEND (pos-ventas)                   │
│                                                           │
│  React SPA ──▶ Zustand Stores ──▶ Axios API Client       │
│       │              │                    │                │
│       │         TanStack Query       IndexedDB            │
│       │              │              (Dexie.js)            │
│       ▼              ▼                    │                │
│  MUI Components   Server Cache      Offline Data          │
│                                                           │
│  Service Worker (Workbox) → PWA instalable                │
└──────────────────────┬────────────────────────────────────┘
                       │ HTTPS + JWT Bearer
                       ▼
┌─────────────────────────────────────────────────────────┐
│              BACKEND (smartfactvoice-backend)             │
│                                                           │
│  NestJS API ──▶ /api/v1/* (URI versioning)               │
│       │                                                   │
│       ├── AuthModule (JWT + refresh tokens)               │
│       ├── SyncModule (offline sync para POS)              │
│       ├── FacturasModule (facturación electrónica)        │
│       ├── ProductosModule, ClientesModule, etc.           │
│       ├── QueuesModule (BullMQ: email, SIFEN)            │
│       └── PosConfigModule (configuración POS por sucursal)│
│                                                           │
│  Prisma ORM ──▶ PostgreSQL                               │
│  BullMQ ──▶ Redis                                        │
│  S3 ──▶ AWS (imágenes, archivos)                         │
└─────────────────────────────────────────────────────────┘
```

---

## 3. Multi-Tenancy

El sistema es **multi-tenant por empresa**. Cada registro principal tiene un campo `empresa_id` que filtra los datos. Un usuario pertenece a una empresa y los endpoints del backend extraen `empresa_id` del JWT:

```typescript
const empresaId = req.user.empresa_id;
```

---

## 4. Autenticación y Permisos

### Flujo de autenticación

1. `POST /auth/login` → devuelve `access_token` + `refresh_token` + `user`
2. El frontend guarda tokens en `localStorage`
3. Axios interceptor agrega `Authorization: Bearer <token>` a cada request
4. Si el access_token expira (401), el interceptor automáticamente hace `POST /auth/refresh`
5. Si el refresh token expira, redirige a `/login`

### Sistema de permisos

- **Módulos**: códigos como `DASHBOARD`, `POS_ADMIN`, `FACTURACION`, `PRODUCTOS`, etc.
- **Privilegios por módulo**: `LEER`, `CREAR`, `EDITAR`, `ELIMINAR`
- **Super Admin**: bypass total (`is_superadmin = true`)
- **Frontend**: `useAuthStore` provee `hasModule(codigo)` y `hasPermission(modulo, privilegio)`
- **Rutas protegidas**: `<ProtectedRoute accessBy="authenticated" modulo="POS_ADMIN">`

### Stores relevantes

```
Frontend:
  src/store/AuthStore.jsx       → login, logout, hasModule, hasPermission
  src/context/AuthContent.jsx   → AuthContextProvider (React Context)
  src/api/api.config.js         → Axios instance con interceptors de JWT refresh
```

---

## 5. Módulo POS (Punto de Venta)

### Arquitectura del POS

El POS tiene dos modos configurables por sucursal:

| Modo | Template | Uso | UI |
|---|---|---|---|
| **admin** | `POSAdminTemplate.jsx` (56KB) | Facturación detallada con todos los campos | Formulario clásico |
| **retail** | `POSRetailTemplate.jsx` (141KB) | POS rápido tipo supermercado | Grilla de productos + carrito |

### Configuración POS (`pos_config`)

Se configura por **sucursal** en la tabla `pos_config`. El backend endpoint es `GET /pos-config/:sucursal_id`.

Campos principales:
```
tipo_pos:                "admin" | "retail"
show_product_image:      boolean
show_product_stock:      boolean
permitir_venta_sin_stock: boolean
retail_tile_size:        "small" | "medium" | "large"
retail_grid_columns:     number (0 = auto)
barcode_auto_add:        true (solo frontend, DEFAULT_CONFIG)
```

### Rutas del POS

```
/pos       → POSAdmin (sin sidebar, fullscreen)
              ├── tipo_pos = "retail" → POSRetailTemplate (fullscreen sin sidebar)
              └── tipo_pos = "admin"  → POSAdminTemplate (con sidebar, Layout se agrega dinámicamente)

/pos-admin → POSAdmin (con sidebar siempre, Layout en la ruta)
```

**Lógica en `POSAdmin.jsx`:**
- Carga config de sucursal via `usePosConfigQuery`
- Si no hay caja abierta → muestra `PantallaAperturaCaja`
- Si `tipo_pos === "retail"` → renderiza `POSRetailTemplate`
- Si `tipo_pos === "admin"` → renderiza `POSAdminTemplate`
- Si la ruta es `/pos` y tipo es admin → wrappea con `<Layout>` dinámicamente

### Menú del POS Retail (botón ☰)

El `POSRetailTemplate` tiene un botón hamburguesa (☰) en la barra superior con menú desplegable:
- **Panel de Administración** → abre `/pos-admin` en nueva pestaña
- **Configuración POS** → diálogo de configuración
- **Cerrar Caja** → diálogo de cierre (solo si hay sesión de caja activa)
- **Cerrar Sesión** → logout

### Detección de Lector de Código de Barras

Implementado en `POSRetailTemplate.jsx`. Distingue entre input de lector de códigos y escritura manual:

- **Lector de códigos**: caracteres llegan en <80ms de intervalo promedio
  - Al presionar Enter → busca producto y agrega directo al carrito
  - Si encuentra 1 resultado → auto-add + toast de confirmación
  - Si encuentra múltiples → muestra dropdown para selección
- **Escritura manual**: intervalos >80ms
  - Muestra dropdown de resultados normalmente
  - Enter agrega el primer resultado

Constante configurable: `BARCODE_SCAN_THRESHOLD_MS = 80`
Config: `barcode_auto_add: true` en DEFAULT_CONFIG

---

## 6. Sistema Offline-First

> Documentación detallada en `docs/OFFLINE_SYNC.md`

### Resumen

El POS Retail puede operar sin conexión a internet. Los datos se sincronizan con el servidor y se almacenan localmente en IndexedDB via Dexie.js.

### Archivos clave

```
Frontend:
  src/offline/db.js           → Dexie.js DB schema + helpers CRUD
  src/store/SyncStore.jsx     → Zustand store: sync state, auto-sync, push ventas
  src/hooks/useOfflinePOS.js  → Hook con fallbacks API → IndexedDB
  src/api/sync.service.js     → Cliente API para endpoints de sync
  src/components/ui/SyncStatusBar.jsx → UI indicador de conexión

Backend:
  src/sync/sync.module.ts     → Módulo NestJS
  src/sync/sync.service.ts    → Lógica: delta, full, push ventas offline
  src/sync/sync.controller.ts → Endpoints REST
```

### Endpoints de sync

| Método | Ruta | Descripción |
|---|---|---|
| `GET` | `/sync/ping` | Health check (no requiere auth) |
| `GET` | `/sync/full` | Sync completo de todos los catálogos |
| `GET` | `/sync/delta?since=` | Solo cambios desde la última sync |
| `POST` | `/sync/push/ventas` | Enviar ventas offline al servidor |

### Tablas IndexedDB (Dexie.js)

```
productos, clientes, categorias, medios_pago, referenciales,
numeraciones, condiciones_pago, offline_ventas, sync_meta
```

### Protecciones implementadas

- **`navigator.storage.persist()`** → protege IndexedDB contra eviction del browser
- **Atomic syncing status** → previene envío duplicado de ventas offline
- **`_initialized` guard** → previene event listeners duplicados en SyncStore

---

## 7. Estructura de Archivos del Frontend

```
pos-ventas/src/
├── api/                    # Servicios API (axios calls)
│   ├── api.config.js       # Axios instance + JWT interceptors
│   ├── sync.service.js     # API de sincronización offline
│   ├── facturas.service.js # CRUD facturas
│   ├── productos.service.js
│   ├── clientes.service.js
│   └── ... (32 archivos)
├── components/
│   ├── templates/          # Templates principales (páginas)
│   │   ├── POSRetailTemplate.jsx    # POS Retail (141KB, el más grande)
│   │   ├── POSAdminTemplate.jsx     # POS Admin (56KB)
│   │   ├── DashboardTemplateV2.jsx  # Dashboard
│   │   ├── CobrosTemplateV2.jsx     # Cobros
│   │   └── ... (26 templates)
│   ├── organismos/         # Componentes complejos
│   │   ├── sidebar/        # Sidebar + menú móvil
│   │   ├── POSDesign/      # Componentes específicos del POS
│   │   └── ...
│   └── ui/                 # Componentes UI reutilizables
│       └── SyncStatusBar.jsx
├── store/                  # Zustand stores (31 archivos)
│   ├── AuthStore.jsx       # Autenticación + permisos
│   ├── SyncStore.jsx       # Sincronización offline (11KB)
│   ├── ProductosStore.jsx
│   ├── ThemeStore.jsx      # Tema claro/oscuro
│   └── ...
├── hooks/                  # Custom hooks
│   ├── useOfflinePOS.js    # Fallbacks API → IndexedDB
│   ├── ProtectedRoute.jsx  # Guard de rutas
│   ├── Layout.jsx          # Layout con sidebar
│   └── ...
├── tanstack/               # TanStack Query hooks (28 archivos)
│   └── PosConfigStack.js   # Query para config POS
├── offline/
│   └── db.js               # Dexie.js schema + helpers
├── pages/                  # Páginas (React Router)
│   ├── POSAdmin.jsx        # Página POS (switch retail/admin)
│   ├── POSRetailStandalone.jsx  # POS standalone (no usado actualmente)
│   └── ... (32 páginas)
├── routers/
│   └── routes.jsx          # Todas las rutas de la app
├── context/
│   ├── AuthContent.jsx     # AuthContextProvider
│   └── EmpresaContext.jsx  # EmpresaProvider
├── utils/
│   ├── dataEstatica.jsx    # Links del sidebar, datos estáticos
│   ├── Conversiones.jsx    # FormatearNumeroDinero, etc.
│   └── invoiceCalculations.js  # Cálculos de factura (subtotales, IVA)
└── styles/
    └── variables.js        # Variables de estilo + iconos
```

---

## 8. Estructura de Módulos del Backend

```
smartfactvoice-backend/src/
├── main.ts                 # Bootstrap: CORS, Swagger, Bull Board, Versioning
├── app.module.ts           # Root module (importa todos los módulos)
├── prisma/                 # Prisma ORM
│   └── prisma.service.ts
├── config/                 # Configuración de entorno
├── auth/                   # Autenticación JWT + refresh tokens
├── users/                  # CRUD usuarios
├── empresas/               # CRUD empresas (multi-tenant root)
├── sucursales/             # Sucursales por empresa
├── productos/              # CRUD productos + búsqueda
├── categorias/             # Categorías de productos
├── marcas/                 # Marcas de productos
├── clientes/               # CRUD clientes
├── personas/               # Datos de persona (ligada a cliente/usuario)
├── facturas/               # Facturación electrónica
├── nota-creditos/          # Notas de crédito
├── cobros/                 # Gestión de cobros
├── tesoreria/              # Tesorería y caja
├── cajas/                  # Gestión de cajas
├── depositos/              # Depósitos/almacenes
├── stock/                  # Control de stock
├── movimientos-inventario/ # Movimientos de inventario
├── numeraciones/           # Numeraciones de documentos
├── punto-expediciones/     # Puntos de expedición
├── monedas/                # Monedas (PYG, USD, etc.)
├── medio-pago/             # Medios de pago
├── condiciones-pago/       # Condiciones de pago (contado, crédito)
├── referenciales/          # Datos referenciales (IVA, tipos, etc.)
├── pos-config/             # Configuración POS por sucursal
├── sync/                   # Sincronización offline para POS
├── lista-precios/          # Listas de precios
├── planes-cuotas/          # Planes de cuotas/financiamiento
├── ofertas/                # Sistema de ofertas y promociones
├── vendedores-cobradores/  # Vendedores, cobradores y comisiones
├── suscripciones/          # Planes de suscripción SaaS
├── planes/                 # Planes de precios del SaaS
├── modulos/                # Módulos del sistema
├── privilegios/            # Privilegios por módulo
├── perfiles/               # Perfiles/roles de usuario
├── asignaciones-sucursal/  # Asignaciones usuario-sucursal
├── middleware-sifen/       # Integración con SIFEN (facturación electrónica PY)
├── queues/                 # BullMQ: colas de email y SIFEN
├── redis/                  # Configuración Redis
├── mail/                   # Servicio de email (Nodemailer)
├── twilio/                 # SMS/verificación (Twilio)
├── notificaciones/         # Notificaciones push
├── codigos-verificacion/   # Códigos de verificación (registro)
└── common/                 # Interceptors, guards, utils compartidos
```

---

## 9. Endpoints Principales de la API

Base URL: `/api/v1/`

### Autenticación
| Método | Ruta | Descripción |
|---|---|---|
| `POST` | `/auth/login` | Login → access_token + refresh_token |
| `POST` | `/auth/register` | Registro de empresa + usuario |
| `POST` | `/auth/refresh` | Renovar access_token |
| `GET` | `/auth/me` | Datos completos del usuario (empresa, módulos, permisos) |
| `POST` | `/auth/logout` | Cerrar sesión |

### Productos
| Método | Ruta | Descripción |
|---|---|---|
| `GET` | `/productos` | Listar productos (paginado) |
| `GET` | `/productos/buscar?q=` | Búsqueda por descripción/código/barcode |
| `POST` | `/productos` | Crear producto |
| `PATCH` | `/productos/:id` | Actualizar producto |
| `DELETE` | `/productos/:id` | Soft delete |

### Facturas
| Método | Ruta | Descripción |
|---|---|---|
| `GET` | `/facturas` | Listar facturas |
| `POST` | `/facturas` | Crear factura |
| `GET` | `/facturas/:id` | Detalle de factura |

### POS Config
| Método | Ruta | Descripción |
|---|---|---|
| `GET` | `/pos-config/:sucursal_id` | Config POS de sucursal |
| `POST` | `/pos-config` | Crear config |
| `PATCH` | `/pos-config/:sucursal_id` | Actualizar config |

### Sync (offline)
| Método | Ruta | Descripción |
|---|---|---|
| `GET` | `/sync/ping` | Health check |
| `GET` | `/sync/full` | Sync completo |
| `GET` | `/sync/delta?since=` | Sync delta |
| `POST` | `/sync/push/ventas` | Push ventas offline |

### Tesorería
| Método | Ruta | Descripción |
|---|---|---|
| `POST` | `/tesoreria/abrir-caja` | Abrir caja |
| `POST` | `/tesoreria/cerrar-caja/:id` | Cerrar caja |
| `GET` | `/tesoreria/sesion-activa` | Sesión de caja activa del usuario |
| `GET` | `/tesoreria/cajas-disponibles` | Cajas disponibles en sucursal |

---

## 10. Rutas del Frontend

| Ruta | Layout | Módulo requerido | Página |
|---|---|---|---|
| `/login` | Sin layout | No auth | Login |
| `/register` | Sin layout | No auth | Registro |
| `/` | Sidebar | Auth | Home |
| `/dashboard` | Sidebar | DASHBOARD | Dashboard |
| `/pos` | **Dinámico** | POS_ADMIN | POS (retail=fullscreen, admin=sidebar) |
| `/pos-admin` | Sidebar | POS_ADMIN | POS con sidebar |
| `/ventas` | Sidebar | FACTURACION | Ventas |
| `/ventas/notas-credito` | Sidebar | NOTAS_CREDITO | Notas de crédito |
| `/cobros` | Sidebar | COBROS | Cobros |
| `/cuentas-cobrar` | Sidebar | CUENTAS_COBRAR | Cuentas por cobrar |
| `/inventario` | Sidebar | PRODUCTOS | Inventario |
| `/contactos` | Sidebar | CONTACTOS | Contactos |
| `/finanzas` | Sidebar | TESORERIA | Tesorería |
| `/suscripciones` | Sidebar | SUSCRIPCIONES | Suscripciones |
| `/configuracion` | Sidebar | CONFIG_EMPRESA | Configuración general |
| `/configuracion/productos` | Sidebar | PRODUCTOS | CRUD productos |
| `/configuracion/categorias` | Sidebar | CATEGORIAS | Categorías |
| `/configuracion/serializacion` | Sidebar | CONFIG_NUMERACION | Numeraciones |
| `/configuracion/ticket` | Sidebar | CONFIG_TICKET | Config ticket |
| `/configuracion/sucursalcaja` | Sidebar | CONFIG_SUCURSALES | Sucursales y cajas |
| `/configuracion/usuarios` | Sidebar | CONFIG_USUARIOS | Usuarios |
| `/configuracion/almacenes` | Sidebar | CONFIG_ALMACENES | Almacenes |
| `/configuracion/impresoras` | Sidebar | CONFIG_IMPRESORAS | Impresoras |
| `/configuracion/metodospago` | Sidebar | CONFIG_MEDIOS_PAGO | Métodos de pago |
| `/configuracion/empresa` | Sidebar | CONFIG_EMPRESA | Config empresa |
| `/miperfil` | Sidebar | Auth | Mi perfil |
| `/reportes` | Sidebar | REPORTES | Reportes |

---

## 11. Variables de Entorno

### Frontend (`.env`)
```
VITE_API_BASE_URL=http://localhost:3000/api/v1
VITE_APP_KEY=<clave de app>
```

### Backend (`.env`)
```
DATABASE_URL=postgresql://...
PORT=3000
JWT_SECRET=...
JWT_REFRESH_SECRET=...
REDIS_HOST=...
REDIS_PORT=...
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_BUCKET_NAME=...
TWILIO_ACCOUNT_SID=...
TWILIO_AUTH_TOKEN=...
MAIL_HOST=...
MAIL_USER=...
MAIL_PASS=...
APP_KEY=<misma clave que el frontend>
```

---

## 12. Cómo ejecutar

### Frontend
```bash
cd /var/www/html/proyectos/pos-ventas
npm install
npm run dev          # → http://localhost:5173
npm run build        # → dist/
```

### Backend
```bash
cd /var/www/html/proyectos/smartfactvoice-backend
npm install
npx prisma generate  # Generar Prisma Client
npm run start:dev    # → http://localhost:3000
# Swagger docs: http://localhost:3000/docs
# Bull Board: http://localhost:3000/queues
```

---

## 13. Documentación existente

| Archivo | Contenido |
|---|---|
| `docs/OFFLINE_SYNC.md` | Arquitectura offline-first detallada (sync, IndexedDB, PWA) |
| `docs/MODULOS_FUTUROS.md` | Especificaciones de módulos planificados (vendedores, citas, ofertas) |
| `docs/CONTEXT_GENERAL.md` | **Este documento** — contexto general para editores AI |
| `docs/FRONTEND_ARCHITECTURE.md` | Arquitectura detallada del frontend |
| `docs/BACKEND_ARCHITECTURE.md` | Arquitectura detallada del backend |
| `docs/PENDING_TASKS.md` | Tareas pendientes y trabajo futuro |
| `docs/configuracion-y-listas-de-precios.md` | Sistema de listas de precios |
| `docs/plan-cuotas-flujo-pos-admin.md` | Flujo de cuotas en POS Admin |
| `docs/ofertas-promociones.md` | Motor de ofertas y promociones |
| `docs/sistema-precios-cuotas.md` | Sistema de precios con cuotas |

---

*Documento generado: Febrero 2026*
