Production batches (lotes) are the core of Tambo360’s tracking system. Each batch represents a specific production run of cheese or milk, with detailed tracking of quantities, costs, and waste.
Overview
The batch system provides:
Automatic lot number generation
Product categorization (cheese/milk)
Real-time production status
Complete lifecycle tracking from creation to completion
Integration with waste and cost modules
Data Model
Production batches are defined in the Prisma schema:
// schema.prisma:74-87
model LoteProduccion {
idLote String @id @default ( uuid ())
numeroLote Int @default ( autoincrement ())
fechaProduccion DateTime @default ( now ())
idProducto String
producto Producto @relation ( fields : [ idProducto ], references : [ idProducto ] )
cantidad Decimal
unidad Unidad // kg or litros
idEstablecimiento String
estado Boolean @default ( false )
establecimiento Establecimiento @relation ( fields : [ idEstablecimiento ], references : [ idEstablecimiento ] )
mermas Merma []
costosDirectos CostosDirecto []
}
Key Fields
numeroLote Auto-incrementing sequential number for easy reference
estado Boolean flag: false = in progress, true = completed
unidad Enum: kg for cheese, litros for milk
producto Relation to Producto model with category (quesos/leches)
Creating a Production Batch
Initiate Batch
Create a new production batch with product details: // Create batch (batchController.ts:7-25)
POST / api / lotes
Authorization : Bearer < jwt - token >
{
"idProducto" : "producto-uuid" ,
"cantidad" : 150.5 ,
"unidad" : "kg" ,
"idEstablecimiento" : "establecimiento-uuid" ,
"fechaProduccion" : "2026-03-08T08:00:00.000Z" // optional
}
// Response
{
"success" : true ,
"statusCode" : 201 ,
"message" : "Lote creado correctamente" ,
"data" : {
"idLote" : "lote-uuid" ,
"numeroLote" : 1247 ,
"fechaProduccion" : "2026-03-08T08:00:00.000Z" ,
"cantidad" : 150.5 ,
"unidad" : "kg" ,
"estado" : false ,
"producto" : { ... },
"establecimiento" : { ... }
}
}
Track Progress
The batch remains in progress (estado: false) while production continues. During this time:
Waste can be registered
Costs can be added
Quantity can be updated
Complete Batch
Mark the batch as completed when production finishes: POST / api / lotes / : idLote / completar
Authorization : Bearer < jwt - token >
// No body required
// Response updates estado to true
{
"success" : true ,
"message" : "Lote completado correctamente" ,
"data" : {
"idLote" : "lote-uuid" ,
"estado" : true ,
...
}
}
Once a batch is marked as completed (estado: true), it’s locked for modifications. Plan accordingly.
Batch Operations
List Batches
Retrieve batches with optional filters:
// List batches (batchController.ts:62-82)
GET / api / lotes ? idEstablecimiento = uuid & estado = false & fechaInicio = 2026 - 03 - 01 & fechaFin = 2026 - 03 - 08
Authorization : Bearer < jwt - token >
// Query parameters (all optional):
// - idEstablecimiento: filter by establishment
// - estado: true (completed) or false (in progress)
// - fechaInicio: start date filter
// - fechaFin: end date filter
// Response
{
"success" : true ,
"message" : "Lotes listados correctamente" ,
"data" : [
{
"idLote" : "lote-uuid" ,
"numeroLote" : 1247 ,
"fechaProduccion" : "2026-03-08T08:00:00.000Z" ,
"cantidad" : 150.5 ,
"unidad" : "kg" ,
"estado" : false ,
"producto" : {
"idProducto" : "producto-uuid" ,
"nombre" : "Queso Cheddar" ,
"categoria" : "quesos"
},
"mermas" : [ ... ],
"costosDirectos" : [ ... ]
}
]
}
Get Single Batch
// Get batch details (batchController.ts:84-104)
GET / api / lotes / : idLote
Authorization : Bearer < jwt - token >
// Returns complete batch with all relations
{
"success" : true ,
"message" : "Lote obtenido correctamente" ,
"data" : {
"idLote" : "lote-uuid" ,
"numeroLote" : 1247 ,
"producto" : { ... },
"mermas" : [ ... ],
"costosDirectos" : [ ... ],
"establecimiento" : { ... }
}
}
Edit Batch
Update batch information before completion:
// Edit batch (batchController.ts:27-43)
PUT / api / lotes / : idLote
Authorization : Bearer < jwt - token >
{
"cantidad" : 155.0 , // Updated quantity
"fechaProduccion" : "2026-03-08T09:00:00.000Z"
}
// Response with updated batch
{
"success" : true ,
"message" : "Lote actualizado correctamente" ,
"data" : { ... }
}
Only incomplete batches (estado: false) can be edited.
Delete Batch
// Delete batch (batchController.ts:45-60)
DELETE / api / lotes / : idLote
Authorization : Bearer < jwt - token >
// Response
{
"success" : true ,
"message" : "Lote eliminado correctamente" ,
"data" : null
}
Deleting a batch also removes all associated waste records and costs due to database cascade.
Today’s Production
Get batches created today for quick daily overview:
// Daily production (batchController.ts:106-115)
GET / api / lotes / produccion - del - dia
Authorization : Bearer < jwt - token >
// Returns batches with today's date
{
"success" : true ,
"message" : "Producción del día" ,
"data" : [ ... ]
}
This endpoint powers the “Daily Production Log” component in the dashboard.
Product Categories
Batches are categorized by product type:
// schema.prisma:21-24
enum Categoria {
quesos // Cheese products
leches // Milk products
}
model Producto {
idProducto String @id @default ( uuid ())
nombre String
categoria Categoria
loteProducciones LoteProduccion []
}
Cheese Production
Milk Production
{
"producto" : {
"nombre" : "Queso Mozzarella" ,
"categoria" : "quesos"
},
"cantidad" : 120.5 ,
"unidad" : "kg"
}
{
"producto" : {
"nombre" : "Leche Pasteurizada" ,
"categoria" : "leches"
},
"cantidad" : 500 ,
"unidad" : "litros"
}
Batch Lifecycle
Integration Points
Waste Management
Waste records link to batches:
// Waste is validated against batch quantity
const totalMermas = sumaMermas + nuevaMerma ;
if ( totalMermas > lote . cantidad ) {
throw new Error ( "La merma supera la cantidad disponible del lote" );
}
See Waste Management for details.
Cost Tracking
Direct costs are assigned to specific batches:
// Each cost links to idLote
model CostosDirecto {
idCostoDirecto String @ id @ default ( uuid ())
concepto ConceptoCosto
monto Decimal @ db . Decimal ( 13 , 2 )
idLote String
lote LoteProduccion @ relation ( fields : [ idLote ], references : [ idLote ])
}
See Cost Tracking for details.
Dashboard Analytics
Completed batches feed into dashboard metrics:
// dashboardService.ts:26-30
const resultActual = await prisma . loteProduccion . findMany ({
where: {
establecimiento: { idUsuario: userId },
fechaProduccion: { gte: fechaInicio , lte: fechaFin }
},
include: { mermas: true , costosDirectos: true , producto: true }
});
AI Analysis
The TamboEngine analyzes completed batches:
// tamboEngineService.ts:47-61
const lotes = await prisma . loteProduccion . findMany ({
where: {
idEstablecimiento ,
estado: true , // Only completed batches
fechaProduccion: { gte: fechaLimite }
}
});
Requires minimum 15 completed batches for AI analysis.
Validation & Security
All batch operations verify: const user = ( req as any ). user ;
if ( ! user ) throw new AppError ( "Usuario no autenticado" , 401 );
// Batch must belong to user's establishment
const lote = await LoteService . obtenerLote ( idLote , user . id );
// crearLoteSchema validates:
{
idProducto : string ( UUID ),
cantidad : number ( positive ),
unidad : enum ( kg | litros ),
idEstablecimiento : string ( UUID ),
fechaProduccion : date ( optional , defaults to now )
}
Quantity must be positive
Unit must match product category
Establishment must belong to user
Only incomplete batches can be edited
Completed batches cannot be reopened
Best Practices
Complete Batches Promptly Mark batches as complete as soon as production finishes for accurate analytics
Accurate Quantities Record final quantities before completion to ensure waste calculations are correct
Use Filters Leverage query parameters when listing batches to improve performance
Track Daily Production Use the daily production endpoint for end-of-day summaries
API Reference
Endpoint Method Purpose /api/lotesPOST Create new batch /api/lotesGET List batches with filters /api/lotes/:idLoteGET Get batch details /api/lotes/:idLotePUT Update batch /api/lotes/:idLoteDELETE Delete batch /api/lotes/:idLote/completarPOST Mark batch as complete /api/lotes/produccion-del-diaGET Get today’s batches