DevOps & Development 3 min de lectura 20 de abril de 2026

Cómo implementar FIFO, LIFO y FEFO en sistemas de inventario

Una guía práctica para traducir las reglas de negocio de FIFO, LIFO y FEFO a consultas SQL robustas y lógica de backend sin errores de stock.

Solución en "Dos Clics" (TL;DR)

Diferencia entre métodos de valuación (FIFO, LIFO, FEFO) y cómo traducirlos correctamente a lógica de programación y consultas SQL en sistemas de inventarios.

Cuando nos enfrentamos al diseño de un sistema de ventas y control de stock, uno de los mayores desafíos no es solo registrar las entradas y salidas, sino definir cómo fluye el inventario. Conceptos como FIFO, LIFO y FEFO suelen mezclarse entre la teoría contable y la práctica logística, lo que puede llevarnos a cometer errores graves al intentar traducirlos a código SQL.

1. Clarificando conceptos: Valuación vs. Flujo Físico

Durante el desarrollo de un módulo de inventarios en DOSCLIC, me encontré con la necesidad de ordenar estos conceptos. Es muy común confundir los métodos de valuación de inventarios (que definen cómo se calcula el costo contable de lo que vendes, como FIFO, LIFO o el Promedio Ponderado) con los métodos de flujo físico (cómo se mueven realmente las mercancías en el almacén, como FEFO).

Para un sistema que maneja productos perecederos, medicamentos o lotes con fecha de vencimiento, la regla de oro es combinar el control de lotes con FEFO (First Expired, First Out). Aquí, el costo pasa a un segundo plano frente a la prioridad de evitar pérdidas por caducidad.

2. La trampa del ORDER BY y el error común en FEFO

Inicialmente, mi enfoque para resolver esto programáticamente fue directo. Pensé en mapear cada regla de negocio a una cláusula de ordenamiento en SQL de la siguiente manera:

  • FIFO (PEPS): ORDER BY fecha_entrada ASC
  • LIFO (UEPS): ORDER BY fecha_entrada DESC
  • FEFO: WHERE caducidad < fecha_actual ORDER BY fecha_caducidad ASC
Error detectado: Filtrar FEFO con WHERE caducidad < fecha_actual es un error conceptual grave. Esta consulta solo devolverá los lotes que ya están vencidos (y que, por lo tanto, no deberías vender), en lugar de priorizar los que están más próximos a vencer pero aún son aptos para el consumo.

Para implementar un FEFO correcto, no debemos filtrar por productos ya caducados, sino ordenar de manera ascendente por la fecha de vencimiento de aquellos lotes que aún tienen stock disponible.

3. La consulta SQL correcta para el control de lotes

Para que el sistema funcione de manera robusta, la consulta debe garantizar que solo seleccionamos lotes con existencias reales y ordenarlos según la estrategia elegida. Aquí tienes la estructura recomendada para FEFO:

MySQL Console
SELECT * 
FROM lotes 
WHERE producto_id = ? 
  AND cantidad_disponible > 0 
ORDER BY fecha_caducidad ASC, fecha_entrada ASC;
Consejo Práctico: Añadir un segundo criterio de ordenamiento (como fecha_entrada ASC) actúa como un mecanismo de desempate si dos lotes tienen exactamente la misma fecha de caducidad.

4. Más allá del SQL: El reto de la asignación parcial

Aunque un simple ORDER BY define la prioridad de salida, en el desarrollo real de software esto no es suficiente. El inventario físico rara vez se consume en bloques perfectos; nos enfrentamos constantemente al problema de la asignación parcial.

Imagina el siguiente escenario:

  • Lote A (más antiguo): 5 unidades disponibles.
  • Lote B (más reciente): 10 unidades disponibles.

Si un cliente realiza una compra de 8 unidades bajo la regla FIFO, no podemos simplemente restar las 8 unidades de una sola fila. La lógica de negocio en el backend debe realizar un consumo iterativo:

  1. Consultar los lotes disponibles ordenados por la regla correspondiente.
  2. Tomar las 5 unidades del Lote A (dejando su stock en 0).
  3. Calcular el remanente (3 unidades) y tomarlas del Lote B (dejando su stock en 7).
  4. Registrar las transacciones de salida correspondientes para mantener la trazabilidad.

Además, es crítico envolver este proceso en una transacción de base de datos y utilizar bloqueos de concurrencia (como FOR UPDATE en SQL) para evitar que dos ventas simultáneas intenten consumir el mismo lote al mismo tiempo, generando descuadres de stock.

La historia detrás de la nota

A veces pensamos que las reglas de negocio complejas requieren consultas SQL monstruosas, cuando en realidad la base es un ordenamiento limpio combinado con una lógica de backend robusta que controle la concurrencia y la distribución parcial.