# Configuración de Precios + Listas de Precios

## Cómo funciona la Configuración de Precios junto con las Listas de Precios

---

## 1. Configuración de Precios (nivel empresa)

Es la **configuración global** que define las reglas de comportamiento del sistema de precios para toda la empresa. Se guarda en `empresa.configuracion_precios` (JSON en la tabla `empresas`).

| Campo | Qué hace | Impacto |
|---|---|---|
| **Tipo de Lista Principal** | Define el modo por defecto: `general`, `cliente`, `zona`, `canal` | Determina cómo el sistema busca precios al vender |
| **Moneda Principal** | Moneda de referencia (PYG, USD, etc.) | Todas las listas y cálculos usan esta moneda como base |
| **Permitir Múltiples Listas** | ON/OFF | Si está OFF, solo se puede tener 1 lista general. Si está ON, se pueden crear múltiples listas (mayorista, minorista, VIP, etc.) |
| **Descuentos Automáticos** | ON/OFF | Si está ON, los descuentos configurados en las listas se aplican automáticamente en ventas |
| **Redondeo** | Normal / Arriba / Abajo / Ninguno | Cómo se redondean los precios finales calculados |
| **Decimales** | 0-4 | Cuántos decimales muestra el precio |
| **Validar Stock** | ON/OFF | Si verifica stock antes de mostrar precios |
| **Mostrar sin Stock** | ON/OFF | Si muestra precio aunque no haya stock |

### Componente Frontend
- **Archivo**: `pos-ventas/src/components/organismos/EmpresaConfigDesign/PreciosConfig.jsx`
- **Ruta**: Configuración → Configuración de Precios
- Usa MUI components, react-hook-form, React Query
- Guarda con `updateEmpresa(empresaId, { configuracion_precios: {...} })`

---

## 2. Listas de Precios (nivel operativo)

Son las **listas concretas** donde se definen productos con precios, descuentos y recargos. Cada lista tiene:

- **Código/Nombre**: Identificación (ej: "LP-MAYORISTA")
- **Tipo**: `general` / `cliente` / `zona` / `canal`
- **Moneda**: En qué moneda están los precios
- **Prioridad**: 1-10 (menor = se aplica primero)
- **Productos**: Cada uno con precio base, descuento %, recargo %, precio mín/máx
- **Asignaciones**: A quién aplica (clientes, zonas, canales)
- **Vigencia**: Fechas de inicio/fin

### Componentes Frontend
- **Página**: `pos-ventas/src/pages/ListasPrecios.jsx`
- **Template**: `pos-ventas/src/components/templates/listas-precios/ListasPreciosTemplate.jsx`
- **Tabla**: `pos-ventas/src/components/organismos/listas-precios/TablaGestionListas.jsx`
- **Wizard (crear/editar)**: `pos-ventas/src/components/organismos/listas-precios/WizardCrearLista.jsx`
- **Productos**: `pos-ventas/src/components/organismos/listas-precios/ProductosListaDialog.jsx`
- **Asignaciones**: `pos-ventas/src/components/organismos/listas-precios/AsignacionesListaDialog.jsx`

### Backend
- **Controller**: `smartfactvoice-backend/src/lista-precios/lista-precios.controller.ts`
- **Service**: `smartfactvoice-backend/src/lista-precios/lista-precios.service.ts`
- **API Frontend**: `pos-ventas/src/api/listas-precios.service.js`

---

## 3. Cómo trabajan juntas (flujo de venta)

Cuando el sistema necesita el precio de un producto (ej: en el POS), el backend ejecuta `obtenerPrecioProducto` en `lista-precios.service.ts`:

```
1. Recibe: productoId + clienteId + zona + canal + moneda + empresaId

2. Busca listas activas de la empresa, ordenadas por PRIORIDAD (asc)
   - Filtra por vigencia (fecha_inicio ≤ hoy ≤ fecha_fin)
   - Filtra por moneda (si se especifica)
   - Filtra por tipo de aplicación:
     → "general" (siempre incluida)
     → "cliente" (si el cliente está asignado a esa lista)
     → "zona" (si la zona coincide)
     → "canal" (si el canal coincide)

3. Recorre las listas por prioridad y busca el producto:
   → La PRIMERA lista que tenga ese producto → gana

4. Calcula precio final:
   precioFinal = precioBase × (1 - descuento%) × (1 + recargo%)

5. Si NINGUNA lista tiene el producto:
   → Usa el precio base del producto (tabla productos.precio)
```

---

## 4. Ejemplo práctico

```
Configuración:
  - Tipo principal: General
  - Múltiples listas: ON
  - Moneda: PYG
  - Descuentos automáticos: ON

Listas creadas:
  1. "Lista VIP" (prioridad 1, tipo: cliente)
     → Asignada a: Cliente "ABC S.A."
     → Producto X: 80.000 PYG (base 100.000, -20%)

  2. "Lista Mayorista" (prioridad 3, tipo: zona)
     → Asignada a: Zona "Central"
     → Producto X: 90.000 PYG (base 100.000, -10%)

  3. "Lista General" (prioridad 5, tipo: general)
     → Sin asignaciones (aplica a todos)
     → Producto X: 100.000 PYG

Escenario: Venta a "ABC S.A." de zona "Central":
  → Lista VIP (prioridad 1) tiene Producto X → GANA → 80.000 PYG

Escenario: Venta a "XYZ S.R.L." de zona "Central":
  → Lista VIP no aplica (no está asignado)
  → Lista Mayorista (prioridad 3) tiene Producto X → GANA → 90.000 PYG

Escenario: Venta a "Nuevo Cliente" sin zona:
  → Lista General (prioridad 5) → GANA → 100.000 PYG
```

---

## 5. Diagrama de flujo

```
┌─────────────────────────────────────┐
│  CONFIGURACIÓN DE PRECIOS (global)  │  ← Define las REGLAS
│  - Moneda, redondeo, decimales      │
│  - Multi-lista ON/OFF               │
│  - Descuentos automáticos ON/OFF    │
│  - Validación de stock              │
└──────────────┬──────────────────────┘
               │ gobierna
               ▼
┌─────────────────────────────────────┐
│      LISTAS DE PRECIOS (datos)      │  ← Contienen los PRECIOS
│  Lista VIP → productos + precios    │
│  Lista Mayorista → productos        │
│  Lista General → productos          │
│  Cada una con asignaciones          │
└──────────────┬──────────────────────┘
               │ se consulta en
               ▼
┌─────────────────────────────────────┐
│     POS / FACTURACIÓN / VENTAS      │  ← CONSUME los precios
│  obtenerPrecioProducto(...)         │
│  → Busca por prioridad              │
│  → Aplica descuentos/recargos       │
│  → Retorna precio final             │
└─────────────────────────────────────┘
```

---

## 6. Resumen

- **La configuración define el "cómo"** (reglas globales del sistema de precios)
- **Las listas definen el "cuánto"** (precios concretos por producto)
- **El POS/ventas los consume** en tiempo real usando `obtenerPrecioProducto()`
- La **prioridad** es clave: la primera lista (menor número) que tenga el producto gana
- Si no se encuentra en ninguna lista, se usa el **precio base del producto**
