Costos de inventario - lote a descontar en preparación de quimicos
Documentación costos inventario
Implementación de Costos de Inventario y Previsualización de Lotes
1. Crear Producto Químico - Gestión de Costos por Lote
Descripción
Se implementó la funcionalidad para registrar el precio por unidad (unitPrice) al crear un producto químico. Este precio se almacena en cada registro de inventario dentro del array inventoryRecords, permitiendo llevar un control de costos por lote.
Cambios Técnicos
Modelo de Datos:
- Se agregó el campo
unitPriceal esquema deinventoryRecordsen el modeloChemicalProduct - Se implementó un virtual
settUnitPriceque permite establecer el precio temporalmente durante el ciclo de vida del documento - Se agregó un hook
post('save')que automáticamente agrega el registro de inventario con el precio al arrayinventoryRecords
Interfaz:
- Se agregó
settUnitPrice?: numbera la interfazIChemicalProduct(propiedad virtual, no persistente) - Se agregó
_tempUnitPrice?: numberpara almacenar temporalmente el precio - El campo
unitPricese agregó a la interfazIInventoryRecords
Uso para Frontend
Endpoint: POST /chemical-product
Body de la petición:
{
"name": "HPS15%",
"chemicalFunction": "Desinfectante",
"availableQuantity": 100,
"units": "litros",
"lot": "LOTE-001",
"expirationDate": "2025-12-31",
"settUnitPrice": 25.50,
// ... otros campos del producto
}Campo importante:
settUnitPrice: Precio por unidad del inventario inicial. Este valor se guardará en el primer registro deinventoryRecordscuando se cree el producto.
Respuesta: El producto se crea normalmente y el hook post-save automáticamente agrega un registro en inventoryRecords con:
quantity: La cantidad disponible inicialunitPrice: El precio establecido ensettUnitPricelot: El lote del productoexpirationDate: La fecha de expiracióncreatedAt: Fecha de creación
Nota: El campo settUnitPrice es opcional. Si no se envía, el unitPrice en inventoryRecords será undefined.
2. Agregar Inventario - Registro de Costos por Lote
Descripción
Al agregar inventario a un producto químico existente, ahora es obligatorio incluir el precio por unidad (unitPrice). Este precio se almacena en el registro de inventario correspondiente, permitiendo rastrear el costo de cada lote individualmente.
Cambios Técnicos
Modelo de Datos:
- Se agregó el campo
unitPriceal esquemaChemicalInventorySchema - El hook
post('save')deChemicalInventoryahora incluyeunitPriceal agregar o actualizar registros eninventoryRecords - Si el lote ya existe, se incrementa la cantidad pero se mantiene el precio original del lote
- Si es un lote nuevo, se crea un nuevo registro con el precio proporcionado
Validaciones:
- Se agregó validación en
chemicalInventoryValidatorsque requiereunitPricecomo campo obligatorio - El precio debe ser un número flotante mayor o igual a 0
Interfaz:
- Se agregó
unitPrice: numbera la interfazIChemicalInventory
Uso para Frontend
Endpoint: POST /chemical-inventory
Body de la petición:
{
"chemicalName": "507f1f77bcf86cd799439011",
"quantity": 50,
"units": "litros",
"lot": "LOTE-002",
"expirationDate": "2025-12-31",
"unitPrice": 28.75
}Campos requeridos:
chemicalName: ID del producto químicoquantity: Cantidad a agregarunits: Unidades de medidalot: Número de loteexpirationDate: Fecha de expiraciónunitPrice: Precio por unidad (OBLIGATORIO)
Comportamiento:
Si el lote ya existe en
inventoryRecordsdel producto:- Se incrementa la cantidad del lote existente
- El precio original del lote se mantiene (no se actualiza)
Si es un lote nuevo:
- Se crea un nuevo registro en
inventoryRecordscon el precio proporcionado - Se actualiza
availableQuantitydel producto sumando la nueva cantidad
- Se crea un nuevo registro en
Respuesta exitosa (201):
{
"msg": "Inventario agregado exitosamente"
}Errores posibles:
- 400: Si falta el campo
unitPriceo es inválido - 400: Si el precio es negativo
- 404: Si el producto químico no existe
3. Preparación de Químicos - Previsualización de Lotes a Descontar
Descripción
Se implementó un nuevo endpoint que permite previsualizar qué lotes se van a descontar antes de confirmar una preparación de químico. Esto permite al usuario ver información sobre los lotes que se utilizarán, incluyendo la fecha de expiración más cercana y si hay inventario suficiente.
Cambios Técnicos
Nuevo Endpoint:
- Ruta:
POST /chemical-preparation-by-product - Controlador:
chemicalPreparationByProduct - Validador:
chemicalPreparationPreviewValidator
Funcionalidad:
- Recibe el ID del producto químico y la cantidad a preparar
- Calcula qué lotes se descontarían usando la función
lotsToDeduct - Retorna información sobre los lotes sin modificar la base de datos
- Utiliza el algoritmo FIFO (First In First Out) basado en fechas de expiración
Interfaz de Respuesta:
interface IBatchesToDeduct {
batchesToDeduct: string[];
nearestExpirationDate: string;
inventorySufficient: boolean;
}Uso para Frontend
Endpoint: POST /chemical-preparation-by-product
Headers requeridos:
Authorization: JWT token- Headers de tenant (según configuración)
Body de la petición:
{
"chemicalProductId": "507f1f77bcf86cd799439011",
"quantityToPrepare": 100
}Campos:
chemicalProductId: ID del producto químico (ObjectId válido, requerido)quantityToPrepare: Cantidad a preparar (número mayor que 0, requerido)
Respuesta exitosa (200):
{
"batchesToDeduct": ["LOTE-001", "LOTE-002"],
"nearestExpirationDate": "2025-12-31T00:00:00.000Z",
"inventorySufficient": true
}Campos de respuesta:
batchesToDeduct: Array de strings con los números de lote que se descontaríannearestExpirationDate: Fecha de expiración más cercana entre los lotes que se usarían (formato ISO)inventorySufficient: Boolean que indica si hay inventario suficiente para la cantidad solicitada
Errores posibles:
- 400: Si falta algún campo requerido o es inválido
- 400: Si el producto no tiene registros de inventario disponibles
- 404: Si el producto químico no existe
- 500: Error interno del servidor
Flujo recomendado en Frontend:
- Usuario ingresa la cantidad a preparar en el formulario
- Frontend llama al endpoint
/chemical-preparation-by-product - Frontend muestra la información recibida:
- Lista de lotes que se descontarían (
batchesToDeduct) - Fecha de expiración más cercana (
nearestExpirationDate) - Advertencia si
inventorySufficientesfalse
- Lista de lotes que se descontarían (
- Usuario confirma la preparación
- Frontend llama al endpoint
POST /chemical-preparationpara guardar la preparación y descontar el inventario
Resumen de Cambios por Módulo
Crear Producto Químico:
- Campo
settUnitPriceagregado (opcional) - Precio se guarda automáticamente en
inventoryRecordsmediante hook post-save (unitPrice)
Agregar Inventario:
- Campo
unitPriceagregado (obligatorio) - Precio se guarda en cada registro de
inventoryRecords - Validación de precio mayor o igual a 0
Preparación de Químicos:
- Nuevo endpoint de previsualización implementado
- Retorna información de lotes sin modificar la base de datos
- Permite mostrar información al usuario antes de confirmar
- Endpoint de confirmación que descuenta inventario y registra costos
- Sistema de notificaciones para inventario bajo
- Registro de historial de movimientos (BalanceHistory)
Preparación de quimicos:
- Se creo un campo nuevo en el documento
ChemicalPreparationllamadototalCostque permite identificar el costo total de la preparacion de quimicos actual