---
audiencia: usuario
screen_key: stock/inventario
titulo: Gestión de Inventario
aliases: [stock, inventario, productos, lotes, ofertas, precios, lista de precios, deposito, depósito, cargar stock, cargar stock sin importacion, cargar stock sin pasar por importacion, ingresar stock manual, stock inicial, sumar stock, entrada de stock, ajuste de stock, ajustar stock, registrar entrada de stock, subir stock a mano]
---

# Gestión de Inventario — Guía Completa para el Usuario

Esta guía cubre todo el módulo de inventario del ERP: cómo dar de alta productos, manejar categorías, marcas, atributos, stock por depósito, lotes con vencimientos, ajustes, transferencias, ofertas, inventario físico, listas de precios y precios a cuotas. También explica qué movimientos de stock se generan automáticamente y cuáles a mano.

---

## ¿Dónde encuentro esto en el menú?

- En la **barra lateral el ítem se llama "Productos"** (ícono de caja) y abre la pantalla **"Gestión de Inventario"** (URL `/inventario`), con todos los tabs: **Productos, Categorías, Marcas, Atributos, Stock, Lotes, Ajuste, Transferencias, Ofertas, Listas Precios, Inv. Físico**. El tab activo va en la URL como `?tab=` (ej. `/inventario?tab=ajuste`).
- **Reportes → Inventario → Movimientos de Stock**: historial **solo lectura** de entradas y salidas (NO es donde se carga stock; para cargar stock ver §7 Ajuste).
- **Reportes → Inventario → Reporte por Proveedor**: reporte multi-pestaña por proveedor (vencidos, próximos a vencer, marcas compradas, ventas por marca). Ver §16.
- La ABM de listas de precios y su asignación a clientes/zonas/canales **no** vive en Configuración — es el mismo tab **Productos → Listas Precios** (no existe "Configuración → Lista de Precios").

Cada tab tiene su propio permiso (PRODUCTOS, CATEGORIAS, MARCAS, STOCK, LOTES, AJUSTE_STOCK, TRANSFERENCIAS, OFERTAS, LISTA_PRECIOS). Si no ves un tab es porque tu rol no tiene el permiso.

---

## 1. Productos

Es el master de todo el inventario. Acá se crean los ítems vendibles.

### Crear un producto

1. **Productos → Productos → "+ Nuevo Producto"**.
2. Completar los campos principales:
   - **Descripción** (obligatorio).
   - **Código** (`cod_producto`): único por empresa.
   - **Código de barras** (opcional): para lectura con pistola.
   - **Categoría** y **Marca** (desplegables).
   - **Tipo**: `producto` (afecta stock) o `servicio` (no afecta stock).
   - **Unidad de medida** (unidades, kg, L, etc.).
   - **Precio** de venta y **Costo**.
   - **% IVA**: 0%, 5% o 10%.
   - **Proporción IVA** (0-100): para productos con afectación parcial.
   - **Afectación fiscal** (Gravado, Exento, etc.).
3. Flags opcionales:
   - **Maneja inventario**: si está apagado, el producto se vende sin descontar stock.
   - **Maneja lote**: activa control por lote/vencimiento (requiere que la sucursal tenga módulo LOTES habilitado).
   - **Destacado**: aparece resaltado en el POS.
   - **Es padre**: para productos con variantes (colores/talles).
4. **Imágenes**: hasta 5 por producto, se suben en WebP a S3. Una se marca como **principal**.
5. Guardar.

### Listado, filtros y acciones

- **Buscador** por descripción, código o código de barras.
- **Filtros** por Categoría y Marca.
- **Filtro de Stock** (opcional): *Con stock* / *Sin stock*. Al elegir uno aparecen dos filtros más, encadenados:
  - **Sucursal**: sólo se dibuja si el usuario tiene más de una a su alcance. Con una sola no hay nada que elegir.
  - **Depósito**: aparece recién al elegir sucursal, y sólo si esa sucursal tiene más de un depósito.
  - Sin sucursal ni depósito elegidos, el filtro mide sobre **todo** el alcance del usuario.
  - *Sin stock* además limita a productos que **manejan inventario** — un servicio nunca tiene stock y listarlo ahí sería ruido.
- El subtítulo del encabezado dice cuántos productos quedaron y **sobre qué depósito o sucursal se está midiendo**, para que un número chico no se lea como catálogo incompleto.
- Columnas: Código, Descripción, Categoría, Cód. Barra, Precio, Costo, Stock Global, IVA, Estado, Acciones.
- **Acciones por fila**:
  - **Editar** (lápiz).
  - **Ver precios** (abre el diálogo de Precios del Producto — ver §11).
  - **Activar / Desactivar** (no se elimina, se inactiva).

### Variantes (atributos)

Si el producto se marca como **padre**, se le asocian Atributos (Color, Talle, etc.). El sistema genera automáticamente las combinaciones como productos hijos. Cada variante tiene su propio stock y precio.

---

## 2. Categorías

ABM **jerárquico**: una categoría puede tener subcategorías (`padre_id`).

### Pasos

1. Tab **Categorías**.
2. **"+ Nueva categoría"** → cargar nombre + (opcional) categoría padre.
3. Para crear una subcategoría: expandir el acordeón de la categoría padre → "+ Agregar subcategoría".
4. Acciones por categoría: Ver productos asociados, Editar, Activar/Desactivar, Eliminar.

Cada categoría muestra cuántos productos tiene. No se puede eliminar una categoría con productos activos.

---

## 3. Marcas

ABM **plano** (sin jerarquía). Solo `codigo` + `descripcion`.

1. Tab **Marcas**.
2. **"+ Nueva marca"** → cargar código y descripción.
3. Acciones: Editar, Activar/Desactivar, Eliminar.

Se carga todo el listado de una vez (no paginado). Filtro por búsqueda libre.

---

## 4. Atributos (para variantes)

Los **atributos** son las características variables que diferencian un producto padre de sus variantes: color, talle, tamaño, material, etc.

### Estructura

- **Atributo** (padre): ej. "Color".
- **Valor** (hijo del atributo): ej. "Rojo", "Azul", "Verde". Cada valor puede tener un código y, si es color, un código hexadecimal (#FF0000) para mostrarse como muestra de color.

### Pasos

1. Tab **Atributos**.
2. Crear el atributo → nombre, descripción, orden.
3. Para cada atributo, agregar sus valores → valor, código, color_hex (opcional), orden.
4. En el producto padre, asociar los atributos y generar variantes automáticamente con cada combinación.

---

## 5. Stock

Esta pantalla muestra y administra el stock **por depósito** (no global).

### Cómo se ve

- Selector de **Sucursal** → Selector de **Depósito** → tabla con productos del depósito.
- **Stock Global** (en el listado de productos): suma de todos los depósitos.
- **Stock por depósito**: la cantidad disponible específica del depósito seleccionado.

### Columnas

- Producto, Depósito, Stock disponible, Estado.
- **Editables inline**: `stock_minimo`, `stock_maximo`, `ubicacion` (ubicación física dentro del depósito, ej. "Pasillo 3 - Estante B").

### Alertas

- Reporte **"Bajo mínimo"**: productos cuya cantidad disponible está por debajo del mínimo configurado.
- Sirve para disparar reposición de compras.

### Reglas importantes

- **No se permite stock negativo**: el sistema rechaza ventas o ajustes que dejen la cantidad en negativo.
- **Valoración FIFO** (First In, First Out): los costos se consumen en el orden en que entraron. Aplica especialmente con lotes.

---

## 6. Lotes y vencimientos

Solo aplica para productos con flag **`maneja_lote = true`** y sucursales con el módulo LOTES habilitado.

### Para qué sirve

- Trazabilidad: saber qué lote se vendió a qué cliente.
- Vencimientos: alertar productos próximos a vencer.
- Costeo: cada lote tiene su costo unitario propio (FIFO consume primero los más viejos).

### Tab Lotes

- **Dashboard**:
  - Total lotes.
  - Lotes con stock.
  - Lotes vencidos.
  - Lotes por vencer (próximos ~30 días).
- **Filtros**: búsqueda libre, estado (vigente / vencido / agotado).
- **Tabla**: Lote, Producto, Depósito, Stock del lote, Costo unitario, Fecha fabricación, Fecha vencimiento, Estado.

### Campos del lote

- `numero_lote`, `fecha_fabricacion`, `fecha_vencimiento`.
- `costo_unitario`, `cantidad_disponible`.
- Asociado a producto + depósito.

---

## 7. Ajuste de Stock  — cargar stock a mano (sin pasar por Importaciones)

Esta es la forma de **cargar/ingresar stock directamente**, sin usar el módulo de Importaciones ni una compra: para stock inicial, mermas, daños, recepciones no documentadas, ajustes de conteo, etc.

> **¿Querés cargar stock sin pasar por Importaciones?** Usá esta pantalla: **Productos → pestaña "Ajuste"** con tipo **Entrada**. NO es "Movimientos de Stock" (esa pantalla es solo historial de lectura, no permite agregar stock).

### Pasos

1. En la barra lateral, entrá a **Productos** (pantalla "Gestión de Inventario", URL `/inventario`).
2. Abrí la pestaña **Ajuste** (título del panel: **"Ajuste de Stock"**).
3. Dejá el selector de tipo en **Entrada** (para **sumar** stock). Salida resta.
4. Elegí **Sucursal**, luego **Depósito**.
5. En **Buscar Producto**, escribí nombre, código o código de barra y seleccionalo (verás el "Stock actual").
6. Cargá la **Cantidad** (coma para decimales, sin separador de miles) y las **Observaciones** (motivo).
7. Pulsá **"Registrar Entrada"** (o "Registrar Salida" si es egreso).

### Reglas

- **No requiere autorización** (solo el permiso `INV_AJU_AJUSTE_CREAR`).
- **No tiene campo de costo unitario**: el ajuste solo cambia la **cantidad**; no se define un costo en esta pantalla. (El costeo sale del costo del producto / FIFO de lotes.)
- Queda registrado **quién** hizo el ajuste y **cuándo** en el historial de movimientos.
- Genera un registro en `movimientos_inventario` tipo ENTRADA o SALIDA.
- El motivo va en `observaciones` (texto libre).

---

## 8. Transferencias entre depósitos

Para mover stock de un depósito a otro (mismo o distinta sucursal).

### Pasos

1. Tab **Transferencias**.
2. Seleccionar **Sucursal**.
3. Seleccionar **Depósito Origen** y **Depósito Destino** (no pueden ser el mismo).
4. Buscar el **producto**.
5. Cargar **cantidad** y **observaciones**.
6. Confirmar.

### Comportamiento

- Es **atómico**: resta del origen y suma al destino en la misma operación. No hay estado intermedio "en tránsito".
- No requiere confirmación en destino.
- Genera dos movimientos en `movimientos_inventario`: TRANSFERENCIA salida (origen) + TRANSFERENCIA entrada (destino).

---

## 9. Ofertas

Promociones que se aplican automáticamente en el POS cuando están vigentes.

### Tipos disponibles

| Tipo                         | Qué hace                                  |
| ---------------------------- | ----------------------------------------- |
| **Descuento por porcentaje** | Aplica un % de descuento sobre el precio. |
| **Descuento por monto fijo** | Resta una cantidad fija en guaraníes.     |
| **Precio especial**          | Reemplaza el precio por uno promocional.  |

### Configuración por oferta

- **Nombre** y **descripción**.
- **Vigencia**: `fecha_inicio` y `fecha_fin` (con hora).
- **Aplica a**: Todos los productos / Categoría / Marca / Producto específico.
- **Sucursales**: multi-sucursal (lista de sucursales aplicables).
- **Prioridad**: número que define el orden de evaluación cuando varias ofertas chocan (menor = se evalúa primero).
- **Acumulable con lista de precios**: si está activo, se suma al descuento de la lista del cliente; si no, prevalece la oferta o la lista (según prioridad).
- **Activa**: flag para encender/apagar sin borrarla.

### En el POS

- Las ofertas vigentes se cargan automáticamente.
- Al armar el carrito, el sistema **evalúa** cada ítem contra las ofertas aplicables y calcula descuentos.
- El cliente ve el precio promocional sin que el cajero tenga que hacer nada manual.

---

## 10. Inventario Físico (conteo)

Flujo para hacer el conteo real del depósito y ajustar las diferencias contra el sistema.

### Flujo completo

1. **Crear sesión**: tab **Inv. Físico → "+ Nueva sesión"**. Seleccionar depósito y fecha.
2. **Congelar stock**: durante la sesión abierta, el sistema **bloquea transacciones** en ese depósito (no se aceptan ventas/ajustes/transferencias) para que el conteo no se contamine.
3. **Crear zonas**: dividir el depósito en zonas (pasillo 1, pasillo 2, depósito chico, etc.) para repartir el conteo entre varios contadores.
4. **Imprimir planillas** por zona/categoría: el sistema genera una planilla HTML con código, descripción, stock sistema y espacio en blanco para escribir lo contado.
5. **Cargar conteos** por zona: ingresar las cantidades contadas. Se pueden deshacer.
6. **Cerrar zona**: marca esa zona como completa.
7. **Cerrar sesión**: cuando todas las zonas están cerradas, el sistema:
   - Calcula diferencias (sistema vs. contado).
   - Genera movimientos de **ajuste físico** automáticos.
   - Desbloquea el depósito.

### Dashboard de la sesión

- Total productos, contados, faltantes, diferencias (+ y −).
- Tabla detallada: Código, Descripción, Stock sistema, Stock contado, Diferencia.

---

## 11. Precios del Producto (diálogo)

Se abre desde la acción **"Ver precios"** en el listado de productos. Tiene tres secciones:

### A) Precio base

- Es el precio que está en la tabla `productos`.
- Solo lectura desde acá; se edita desde el formulario del producto.

### B) Precios en Listas de Precios

Cada lista de precios es un catálogo distinto que se puede asignar a clientes, sucursales, zonas o canales (mayorista, minorista, distribuidor, etc.).

#### Agregar el producto a una lista

1. Botón **"+ Agregar a lista"**.
2. Elegir una lista de las disponibles (no aparecen las que ya tienen el producto).
3. Cargar:
   - **Precio base** específico para esa lista.
   - **Descuento %** opcional.
   - **Recargo %** opcional.
   - **Precio mínimo / máximo** (límites).
4. Guardar.

#### ¿Cómo se asignan las listas a clientes?

Eso se hace desde el tab **Productos → Listas Precios** (botón "Asignaciones" de cada lista) — no existe un módulo separado "Configuración → Lista de Precios". Allí se vincula cada lista con:

- Clientes específicos.
- Zonas geográficas.
- Canales de venta.
- Sucursales.

En este diálogo solo se administran los precios de **este producto** dentro de **esas listas**.

#### Multi-moneda

La **moneda se define al crear la lista** (PYG, USD, EUR), no por producto. Si necesitás un mismo producto en dos monedas, hay que crear dos listas distintas y agregar el producto en cada una.

### C) Precios a Cuotas (acordeón)

Son los **planes de financiamiento** definidos manualmente por producto. Cada producto puede tener **N opciones** de cuotas cargadas (3x, 6x, 12x, "3 sin entrada", "6 con entrada", etc.) y todas conviven al mismo tiempo. El cliente elige una al momento de armar la solicitud de crédito.

> **Importante**: no se trabaja con tasa de interés ni con cálculo automático. Los precios a cuotas se cargan **manualmente**, monto fijo por cuota. Si querés cobrar más caro que al contado, se carga directamente ese monto mayor; el sistema **no** calcula ningún interés.

#### Agregar una opción de cuotas

1. Expandir el acordeón **"Precios a Cuotas"** desde el diálogo de Precios del Producto.
2. Botón **"+ Agregar opción de cuotas"**.
3. Completar:
   - **Nombre**: descriptivo (ej. "3 cuotas", "6x con entrada", "12 mensuales").
   - **Cantidad de cuotas** (2 a 36): cuántas cuotas tiene el plan.
   - **Monto de cada cuota**: monto fijo que paga el cliente por cuota. **No se calcula automáticamente.** El usuario lo carga a mano según la política comercial.
   - **Cuota inicial (entrada)**: opcional. Si el plan tiene entrada, se carga el monto que el cliente paga al comprar.
4. Guardar.

El **monto total** del plan se calcula automáticamente:

```
monto_total = (cantidad_cuotas × monto_cuota) + cuota_inicial
```

#### Cómo se relaciona con la Solicitud de Crédito

Cuando el vendedor arma una solicitud de crédito y elige el producto, el sistema le muestra **todas las opciones de cuotas activas** definidas para ese producto. El vendedor elige una, y esa opción queda congelada en la solicitud (si después cambiás el plan en el producto maestro, las solicitudes ya creadas siguen con el monto original).

#### Buenas prácticas

- Usá **nombres descriptivos** ("3 mensuales c/entrada"). El cliente y el vendedor van a verlo así.
- Si un plan dejó de venderse, **inactivalo** (no lo borres); las solicitudes históricas siguen referenciándolo.
- Si todos los planes están inactivos o no hay ninguno cargado, el producto **no se puede vender a cuotas**: solo aparece para venta al contado.
- Para productos con muchas variantes (padre + hijos), los planes se cargan **por producto hijo** (cada variante puede tener su propio plan).

---

## 12. Qué afecta el stock y qué no (regla maestra)

Esta es la parte más importante para entender por qué los números cuadran o no. El sistema separa claramente las operaciones que **mueven stock real** de las que son solo "intención" comercial.

### Operaciones que SÍ mueven stock

| Operación                                | Cuándo se descuenta/entra | Tipo de movimiento               | Sentido                        |
| ---------------------------------------- | ------------------------- | -------------------------------- | ------------------------------ |
| **Factura electrónica / POS**            | Al emitir la factura      | `VENTA`                          | Sale del depósito              |
| **Nota de crédito por devolución**       | Al emitir/aplicar la NC   | `DEVOLUCION`                     | Vuelve al depósito             |
| **Recepción de compra**                  | Al confirmar la recepción | `COMPRA` (ENT_COMPRA)            | Entra al depósito              |
| **Anulación de factura**                 | Al anular                 | Reverso de `VENTA`               | Vuelve al depósito             |
| **Ajuste manual (entrada / salida)**     | Al guardar el ajuste      | `ENTRADA` o `SALIDA`             | Según signo                    |
| **Transferencia entre depósitos**        | Al confirmar              | `TRANSFERENCIA` salida + entrada | Sale origen, entra destino     |
| **Inventario físico (cierre de sesión)** | Al cerrar la sesión       | `AJUSTE_FISICO`                  | Diferencia sistema vs. contado |

### Operaciones que NO mueven stock

| Operación                         | Por qué no                                                                                                                        |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| **Pedido de venta**               | Solo **valida** que haya stock al momento de cargarlo. No descuenta ni reserva. El stock baja recién cuando se factura el pedido. |
| **Presupuesto**                   | Es una cotización. Cero impacto en stock.                                                                                         |
| **Solicitud de crédito aprobada** | Aprobar la solicitud no reserva ni descuenta mercadería. El stock se mueve **recién al facturar** desde la solicitud.             |
| **Reservas / "apartado"**         | No existe campo `cantidad_reservada` operativo todavía. El stock aparece disponible aunque haya pedidos pendientes.               |
| **Cotizaciones a proveedor**      | No impactan stock entrante hasta la recepción.                                                                                    |

> **Implicancia operativa**: si tenés muchos pedidos o solicitudes de crédito aprobadas pendientes de facturar, el stock que ves "disponible" **puede vender más de lo que realmente hay** para entregar. Es responsabilidad del vendedor/encargado controlarlo a mano.

### Consultar movimientos

**Reportes → Inventario → Movimientos de Stock**:

- Filtros: producto, depósito, fecha, tipo de movimiento, documento origen.
- Columnas: fecha, tipo, producto, depósito, cantidad, costo unitario, documento, usuario, observaciones.

Sirve para auditar discrepancias o reconstruir el historial de un producto puntual.

---

## 13. Precio de costo y valoración FIFO

El **costo** del producto es la base para calcular utilidad, márgenes y reportes de rentabilidad. El sistema lo maneja en dos niveles distintos:

### Dónde vive el costo

| Dato                           | Campo                                   | Para qué se usa                                                                      |
| ------------------------------ | --------------------------------------- | ------------------------------------------------------------------------------------ |
| **Costo del producto maestro** | `productos.precio_costo`                | Reportes y referencia general. Se ve en el listado de productos.                     |
| **Costo del lote**             | `lotes_producto.costo_unitario`         | Costo real de una entrada puntual de mercadería. Se usa para FIFO.                   |
| **Costo del movimiento**       | `movimientos_inventario.costo_unitario` | Foto del costo en el momento exacto en que se hizo cada movimiento. No se recalcula. |

### Cómo se actualiza el costo automáticamente

- **Al confirmar una recepción de compra** el sistema:
  1. Crea un **lote** con `costo_unitario = precio unitario de la compra`.
  2. **Sobreescribe** `productos.precio_costo` con ese nuevo precio. Es decir: el costo del producto maestro **siempre refleja la última compra recibida**, no un promedio.

> Esto significa que comprar por encima del precio habitual sube el costo maestro de inmediato. Si querés mantener un costo de referencia más estable, hay que editarlo a mano después de la compra.

### FIFO (First In, First Out)

- Al vender, el sistema **consume primero los lotes más viejos** (los que entraron primero).
- Cada movimiento de salida (VENTA, SALIDA, TRANSFERENCIA salida) guarda el `costo_unitario` del lote consumido en ese momento. Sirve para calcular margen real de la venta.
- En productos **sin manejo de lote**, no hay tracking lote por lote: el costo de la salida es el `precio_costo` actual del producto maestro al momento del movimiento.

### Cambiar el costo manualmente

Hoy **no hay un botón explícito de "ajuste de costo"**. Las formas válidas de cambiar el costo son:

1. **Editar el producto** y modificar `precio_costo` desde el formulario. Esto cambia la referencia maestra pero NO retoca los lotes ya cargados ni los movimientos históricos.
2. **Hacer una nueva compra/recepción** con el costo correcto: pisa el `precio_costo` del producto y deja un lote nuevo con ese costo.
3. Para productos con lote, si entró un lote con costo mal cargado, lo correcto es **anular la recepción** y volver a cargarla con el costo correcto, en lugar de tocar el campo a mano.

### Consideraciones importantes

- **No hay recálculo retroactivo**: si cambiás el costo hoy, las ventas pasadas mantienen el costo que tenían al momento de la venta. Esto es deliberado: la utilidad histórica no se altera.
- **Promedio ponderado no implementado**: el sistema usa FIFO + "último costo" en el maestro. Si tu negocio necesita costo promedio ponderado, hoy no está disponible.
- **Costo en moneda extranjera**: si comprás en USD, el costo se guarda en la moneda original del lote. El reporte de margen aplica la cotización del momento.
- **Productos sin compras**: si nunca tuvieron una recepción, el `precio_costo` queda en lo que se cargó manualmente al crear el producto.

---

## 14. Ajustes de stock — cuándo y cómo

Los **ajustes** son la herramienta para corregir diferencias entre lo que dice el sistema y lo que hay realmente en el depósito. Son la última instancia: si todo lo demás está bien cargado, no debería haber ajustes frecuentes.

### Cuándo usar un ajuste manual

- **Mermas y roturas** que no se documentaron con NC o devolución.
- **Mercadería recibida sin orden de compra** (mientras no se regularice la compra).
- **Errores de carga histórica** (productos cargados sin stock inicial).
- **Faltantes detectados durante el día** que no llegan a inventario físico.
- **Sobrantes** sin origen claro.

### Cuándo NO usar un ajuste manual

- **Para corregir un error de venta** → mejor anular la factura o emitir NC; mantiene la trazabilidad.
- **Para "trasladar" stock entre depósitos** → usar el módulo de Transferencias.
- **Para registrar una compra real** → usar Compras / Recepción; así el costo también queda registrado.
- **Para conteos masivos** → usar Inventario Físico, que genera los ajustes con auditoría completa.

### Pasos cuando las cantidades no coinciden

1. **Verificar primero los movimientos** en Reportes → Inventario → Movimientos de Stock filtrando por ese producto. Casi siempre hay una venta, NC, transferencia o ajuste reciente que explica la diferencia.
2. Si después de revisar no aparece explicación:
   - Para diferencias pequeñas y aisladas → **Ajuste manual** con observación clara (ej. "Diferencia detectada en conteo del 28/05, sin causa identificada").
   - Para diferencias generalizadas → **Inventario Físico** del depósito completo. Mejor un solo cierre con todas las diferencias auditadas que muchos ajustes sueltos.
3. **Siempre cargar observación**. Sin observación, el ajuste queda como "ruido" para auditoría futura.
4. Si la diferencia es **alta y recurrente**, escalar: puede ser un problema de procesos (no se está cargando algo bien) o un faltante operativo.

### Lo que pasa internamente

- Cada ajuste genera un `movimientos_inventario` con tipo `ENTRADA` o `SALIDA`, costo unitario del producto al momento y observación.
- Actualiza `stock_deposito.cantidad_disponible`.
- **No retoca el costo** del producto maestro; sí registra el costo histórico en el movimiento.
- Queda firmado: `usuario_id`, fecha, observación. Auditable desde Reportes.

---

## 15. Configuraciones y reglas globales

- **No se permite stock negativo**: cualquier operación que intente dejar el stock por debajo de 0 se rechaza.
- **Valoración FIFO**: los costos se consumen en orden de entrada. Importante cuando hay lotes con costos distintos.
- **El costo del producto maestro sigue la última compra**: al recibir una compra, `precio_costo` se sobreescribe con el precio unitario recibido.
- **Permisos por módulo**: cada tab tiene su propio permiso. Se configuran en **Configuración → Usuarios y Permisos → Perfiles y Roles**.
- **Multi-sucursal**: el stock se administra por depósito, y cada sucursal puede tener uno o más depósitos.
- **Lotes opcional**: el flag `maneja_lote` por producto + habilitación del módulo LOTES por sucursal determinan si se trackea por lote o no.
- **Pedidos y solicitudes de crédito no reservan stock**: el stock real se descuenta recién al facturar.

---

## 16. Reporte por Proveedor

Pantalla unificada en **Reportes → Inventario → Reporte por Proveedor** que reúne cuatro vistas operativas sobre un proveedor seleccionado. Útil para reuniones comerciales, canjes mensuales y análisis de aporte por proveedor.

### Filtros globales

- **Proveedor** (obligatorio): selector con búsqueda. El proveedor debe tener **al menos una marca vinculada** (módulo Proveedores → "Marcas que provee") para que los reportes basados en vínculo devuelvan datos.
- **Desde / Hasta**: rango de fechas en hora local de Paraguay. Por defecto, último mes. El filtro es inclusivo en ambos extremos.

> **Alcance por sucursal**: las cuatro vistas se recortan al alcance del usuario. Las de stock y compras miden sobre sus depósitos y sucursales; las de ventas, sobre el punto de establecimiento de sus sucursales. Un usuario restringido y uno con acceso total van a ver números distintos del mismo proveedor, y eso es correcto. Ver `guia-alcance-por-sucursal.md`.

> **Importante (filtro de fechas)**: las fechas viajan como `YYYY-MM-DD` y se interpretan en zona horaria `America/Asuncion`. Las facturas con `dfeemide` (timestamp UTC del SIFEN) se convierten a fecha local PY antes de comparar. Hasta=hoy incluye las ventas de hoy sin necesidad de sumar un día.

### Pestañas disponibles

#### Vencidos

Lotes vencidos en el rango cuya marca está vinculada al proveedor (vínculo activo) **y que aún tienen stock**. Pensado para gestionar canjes y devoluciones mensuales.

- Columnas: Lote, Vencimiento, Producto, Marca, Depósito, Stock, Costo unitario, Costo total.
- Solo aparecen productos con `maneja_lote = true`.
- Acciones: exportar Excel, generar PDF (vía msv-kude, se muestra en modal), enviar por email al proveedor (requiere que el proveedor tenga email registrado).

#### Próximos a vencer (30/60/90)

Agrupa los lotes por buckets de proximidad de vencimiento desde hoy:

- **0-30 días** (crítico, color rojo).
- **31-60 días** (advertencia, naranja).
- **61-90 días** (informativo, azul).

Mismo dataset que Vencidos pero proyectado a futuro. Útil para planear rotación y promociones antes del vencimiento.

#### Marcas compradas

Ranking de marcas que la empresa **compró efectivamente a ese proveedor** en el rango.

- Fuente: `compra_cab` + `compra_det` (no depende de vínculos `proveedor_marca`). Cruza por `cc.proveedor_id`.
- Excluye compras anuladas.
- Columnas: Marca, Compras, Productos distintos, Unidades, Monto total, Primera/Última compra, **Vinculado** (indica si esa marca está en `proveedor_marca` activo para este proveedor).
- **CTA inline "Vincular"**: si una marca aparece comprada pero **no vinculada**, hay un botón para crear el vínculo en un click. Si existe un vínculo inactivo previo, se reactiva (soft-delete transparente, no falla por P2002).

Sirve para detectar marcas que se compran pero no están registradas como provistas por el proveedor.

#### Ventas por marca

Ventas atribuibles al proveedor en el rango. Tiene dos modos de cálculo según la trazabilidad disponible:

**Modo "Por vínculo" (aproximado, default)**

- No requiere lotes en las ventas. Toma todas las ventas de productos cuya marca está vinculada al proveedor en `proveedor_marca` activo.
- **Atención**: si una marca tiene varios proveedores vinculados, la venta se cuenta para todos. Para evitar doble conteo, activá el toggle **"Sólo proveedor preferente"** — filtra solo vínculos con `es_proveedor_preferente = true`.
- Columnas: Marca, Código, Producto, Facturas, Unidades, Monto vendido, Rol (chips Preferente / Distribuidor oficial).

**Modo "Por lote" (exacto)**

- Cruza `factura_det_lote → lotes_producto → compra_cab.proveedor_id`. Solo cuenta ventas cuyo lote provino de una compra real a ese proveedor.
- Requiere que la empresa tenga el módulo de **lotes activo en ventas** (productos con `maneja_lote` y POS configurado para registrar el lote consumido).
- El selector indica con un badge si la empresa **tiene o no** trazabilidad por lote (`capabilities.tieneLotesEnVentas`). Si no la tiene, el modo lote devuelve vacío.

**Desglose por producto**: ambos modos rompen por `(marca, producto)`. Cada fila muestra código y descripción del producto, no una sola línea por marca. Permite ver exactamente qué SKUs movieron monto en el período.

**Exclusión SIFEN**: las facturas con `evento_aplicado IN ('ECAN', 'EINU', 'EINO')` (canceladas, inutilizadas o con inoperatividad) se excluyen automáticamente. **No se filtra por `estado`** — se filtra por el evento SIFEN aplicado, que es el dato de verdad de anulación electrónica.

### Exportaciones

Cada pestaña tiene dos botones:

- **PDF**: se genera en el microservicio `msv-kude` (`/api/reporte-tabla/generate-pdf` para tablas genéricas, `/api/vencidos-proveedor/generate-pdf` para vencidos). El PDF se muestra en un **modal con iframe**, no se abre en nueva pestaña. Botón "Descargar" disponible dentro del modal.
- **Excel**: descarga directa `.xlsx` con todas las columnas crudas (incluye Costo, que en el PDF se omite por espacio).

### Permisos

- `INVENTARIO` (módulo): obligatorio para acceder.
- `INV_RPR_REPORTE_VENCIDOS_PROVEEDOR_VER`: ver las 4 pestañas (vencidos, próximos, marcas, ventas).
- `INV_RPR_REPORTE_PROXIMOS_VENCER_VER`: específico para la pestaña Próximos.
- `INV_RPR_REPORTE_STOCK_POR_PROVEEDOR_VER`: stock-marcas (endpoint separado).
- `INV_RPR_REPORTE_EXPORTAR`: descargar Excel/PDF.
- `INV_RPR_REPORTE_ENVIAR_EMAIL`: enviar el reporte de vencidos por mail al proveedor.

### Limitaciones / consideraciones

- **Modo "por lote" depende de la operativa**: si los cajeros no eligen lote en cada venta, el reporte no podrá atribuir nada a ese proveedor.
- **Modo "por vínculo" puede sobrecontar**: si una marca está vinculada a múltiples proveedores y no usás "preferente", el monto se cuenta para cada uno. Es una aproximación.
- **No incluye notas de crédito**: la fase B (descontar devoluciones del monto vendido) está diferida.
- **El campo `costo_total` de ventas por marca** sale de `factura_det.costo_total_venta` (vínculo) o `factura_det_lote.costo_total` (lote); ambos se congelan al momento de la venta y no se recalculan si cambia el costo maestro.

---

## 17. Qué ve cada usuario (alcance por sucursal)

Un usuario **asignado a una o más sucursales** ve el stock, los movimientos, los lotes, los ajustes, las transferencias y las sesiones de inventario físico **sólo de los depósitos de esas sucursales**. Uno **sin asignaciones** ve toda la empresa.

El alcance de depósitos **se deriva solo**: son todos los depósitos de las sucursales asignadas. No hay que asignar depósitos uno por uno.

### El catálogo de productos es la excepción

**La lista de Productos no se recorta por sucursal, y es a propósito.** Un producto pertenece a la empresa, no a una sucursal; lo que es por sucursal es su *stock*.

- Un usuario restringido ve **todos** los productos de la empresa.
- La columna de stock se mide sobre **sus** depósitos.
- Un producto recién creado aparece en la lista con stock 0 — crear un producto no crea stock, y el formulario de alta ni siquiera pide un depósito. Sólo desaparece si el usuario aplica el filtro *Con stock*.
- Los selectores de **Sucursal** y **Depósito** (en los filtros, en Stock, en Ajustes y en Transferencias) ofrecen únicamente lo asignado.

### Si la sucursal no tiene depósitos

El usuario ve el catálogo pero **no tiene dónde cargar stock**: los selectores de depósito le salen vacíos en Ajustes, Compras y Transferencias. Crearle al menos un depósito a esa sucursal (`Configuración → Puntos de Venta → sucursal → Depósitos`).

Detalle completo en `guia-alcance-por-sucursal.md`.

---

## 18. Problemas frecuentes

- **"No me deja vender, dice stock insuficiente"** → el producto tiene `maneja_inventario` activo y no hay stock en el depósito de la sucursal. Hacer un ajuste de entrada, una compra o una transferencia desde otro depósito.
- **"El stock disponible está bien pero ya está comprometido en pedidos"** → es la realidad: pedidos y solicitudes de crédito **no reservan**. Hay que controlarlo a mano hasta que se facture.
- **"Vendí pero el costo de la utilidad sale raro"** → revisar el último costo. Si entró una compra con precio mal cargado, el `precio_costo` del producto está pisado por ese valor.
- **"Cambié el costo y los reportes históricos no cambiaron"** → es deliberado. El costo de las ventas pasadas se congela en cada movimiento; no se recalcula al editar el producto.
- **"No veo el tab Lotes"** → no tenés permiso LOTES o el módulo no está habilitado para esa sucursal.
- **"El precio en POS no es el de la lista"** → verificar que la lista esté asignada al cliente / sucursal correcta, y que el producto esté incluido en esa lista.
- **"No me deja cerrar inventario físico"** → faltan zonas por cerrar. Revisar el dashboard de la sesión.
- **"La oferta no se aplica"** → revisar vigencia (fecha_inicio / fecha_fin), si está activa, si la sucursal está incluida, y si hay otra oferta de mayor prioridad que la pisa.
- **"El stock global no coincide con la suma de depósitos"** → suele ser caché del frontend, recargar. Si persiste, hay que auditar movimientos.
- **"No puedo eliminar una categoría/marca"** → tiene productos activos asociados. Hay que reasignarlos o desactivarlos primero.
- **"Los precios a cuotas no aparecen al crear solicitud"** → el producto no tiene planes cargados, o están todos en `activo = false`. Recordá que **no se calculan automáticamente**: si no hay opciones cargadas a mano, no hay planes.
- **"Las cantidades del depósito no me coinciden con el conteo físico"** → primero revisar Movimientos de Stock buscando el origen; si no se encuentra, hacer Inventario Físico del depósito en lugar de muchos ajustes sueltos.
- **"Un usuario no ve un depósito"** → no está asignado a la sucursal de ese depósito. Se corrige desde `Configuración → Usuarios y Permisos → Usuarios → Asignaciones`.
- **"Creé un producto y el usuario no lo ve"** → lo ve: el catálogo no se recorta. Si no aparece, revisar que no tenga puesto el filtro *Con stock* — un producto nuevo nace en 0.

---

## 19. Limitaciones actuales

- **Transferencias atómicas**: no hay estado "en tránsito". Si necesitás trackear mercadería viajando entre sucursales con confirmación de recepción, no está implementado.
- **Ajuste sin workflow de aprobación**: cualquier usuario con permiso AJUSTE_STOCK puede ajustar. No hay supervisor obligatorio.
- **Pedidos y solicitudes de crédito no reservan stock**: una solicitud aprobada NO descuenta ni reserva mercadería. El stock se mueve recién al facturar.
- **Sin recálculo retroactivo de costo**: el costo del movimiento se fija al momento del registro. No se recalculan movimientos pasados al cambiar el costo del producto.
- **El costo se sobreescribe con la última compra**: no hay costo promedio ponderado. Si tu negocio lo requiere, se debe trackear por fuera o usar lotes con FIFO.
- **Precios a cuotas sin cálculo de interés**: el sistema no calcula tasa; los montos de cada cuota se cargan a mano y se suman al total fijo.
- **Multi-moneda solo a nivel lista**: no se puede tener un mismo producto con dos monedas en la misma lista de precios.
- **Sin manejo de "apartado" o reserva**: el campo `cantidad_reservada` existe en la base pero no hay operativa que lo escriba/respete todavía.
- **El catálogo de productos no se puede restringir por sucursal**: el alcance recorta el stock, no el catálogo. No hay forma de que un usuario vea sólo "los productos de su sucursal".

---

## Documentos relacionados

- `guia-alcance-por-sucursal.md` — qué stock, depósitos y productos ve cada usuario según sus asignaciones.
- `guia-rubros.md` — si la empresa maneja dos negocios, el catálogo y las categorías se filtran por rubro.
- `guia-sucursales-cajas-pos.md` — crear depósitos dentro de cada sucursal.
- `guia-compras.md` — cómo entra la mercadería y se fija el costo.
- `guia-listas-de-precios.md` — precios por lista, cliente y sucursal.
