Skip to content

Batches and movements

The module does not keep a counter per item: it keeps the list of what came in and of what was taken out of it. The batch carries the quantity and the cost, the movement carries the trace.

The batch

A batch is born when a reception is executed, once per item line. It retains three things: the item, the quantity received and the unit cost price of that reception. It gets a reference, drawn from the batch sequence, unless the operation line imposed one.

A batch is therefore not a label stuck afterwards onto some stock: it is the entry itself, preserved. Two receptions of the same item at the same price give two batches, because they happened twice.

A batch is read through three quantities:

  • the initial quantity, the one of the reception;
  • the consumed quantity, what the exits took from it;
  • the remaining quantity, what it can still supply.

A batch is also read by location: the same reference may be spread over several internal locations, each with its own available stock, because an internal transfer moves a batch without consuming it.

Available and consumed

The available stock of a batch in a location is what came in there minus what went out of it. The stock of an item in a location is the sum of the available quantities of its batches at that place.

The distinction matters: a batch whose remaining quantity is zero has not disappeared, it is consumed. It stays viewable, so do its movements, and it is what explains the value of the exits it served.

The exit consumes batches, in order

When an exit or a transfer is executed, the module takes the batches in the order they came in — the oldest first, the FIFO method — until the requested quantity is covered. A single item line may therefore produce several movements, one per batch started.

You may impose the batch to use on the operation line. The module then checks that this batch is indeed present in the source location and that it holds enough there; otherwise it refuses, rather than silently falling back on another batch.

LIFO does not exist

The module never consumes the most recent batch first. A request for LIFO is explicitly refused.

When the source location is a parent location, the module goes down to fetch the quantity from whichever of its children has held it the longest. The recorded movement names that real location, not the parent.

The movement, an audit trail

A stock movement is written at execution, never before, never after. It retains the date, the operation and its source document, the item, the quantity, the location of departure, the location of arrival, the cost retained and the author. Every movement also says which batches it used, and for what quantity.

Movements are not corrected and not deleted. A mistake is repaired by writing the opposite operation, which adds movements instead of removing any. That is what makes the stock reconstructible: at any date, it is the sum of what has been recorded.

Cancelling a batch

A batch received by mistake may leave on its own, without touching the rest of its reception. The module accepts on four conditions:

  • the batch has never been consumed — as soon as an exit has served itself from it, the cancellation is refused;
  • it has not already been cancelled;
  • it does come from a reception, and that reception is executed;
  • the operation type of the reception declares a return type.

The cancellation then takes the shape of a return operation, carrying the quantity and the cost of the batch, validated and executed immediately, and attached to the original reception. See Lifecycle of an operation.

Changelog

  • 1.0 (August 18, 2026): document created.