Odoo Stock Tracking: Identity and Quantity Management¶
Purpose: Explain Odoo's stock tracking architecture, the relationship between events and state, and how identity assignment prevents double counting.
Audience: System architects, migration teams, operations personnel implementing serial number tracking.
1. Stock as Event-Driven State¶
Stock is not a table or a number. Stock is a system with two complementary parts:
- Events – what happened
→
stock.move.line -
State – what is true now →
stock.quant -
Moves are history (ledger)
- Quants are current balance (snapshot)
- State is always derived from events
This separation is foundational to understanding tracking behavior.
2. Three Tracking Modes = Three Identity Regimes¶
Every product has exactly one tracking mode:
A. No Tracking¶
- Only quantity matters
- Units are anonymous
- System only enforces total quantity
Quant: product A, lot_id = NULL, qty = N
This represents bulk inventory management without individual unit identity.
B. Lot (Batch) Tracking¶
- Group identity, not unit identity
- Units are fungible within the same lot
- Quantity can be split or merged
- History matters, unit uniqueness does not
Quant: product A, lot_id = LOT-X, qty = N
A lot is not a collection of serials. It is a label shared by many anonymous units.
C. Serial Tracking¶
- Unit identity
- One serial = one physical unit
- Quantity is always 1
- No fungibility, no merging, no downgrade
Quant: product A, lot_id = SERIAL-123, qty = 1
A serial is a lot with quantity = 1.
3. Tracking Mode as Capability¶
Tracking mode is a capability, not an action.
tracking = serialmeans:
“This product may have identity, and identity will be enforced when required.”
It does not mean:
- every unit already has a serial
- identity exists automatically
Identity only exists once a serial number is actually assigned.
4. Serialization Is a One-Way Boundary¶
You can think in terms of two domains:
Non-identity domain¶
- No serials
- Only quantities
- Governed by total balance
Identity domain¶
- Serial numbers exist
- Quantity fixed at 1 per serial
- Governed by exclusivity
Crossing the boundary happens at a stock move.
When serials are assigned:
- Anonymous quantity decreases
- Serialized units appear
- Total quantity is conserved
There is no double counting, because:
identity creation always consumes quantity.
Once serialized:
- A unit can never go back
- No merging
- No downgrade to lot or non-tracking
5. Why Cutover from Non-Tracking Is Safe¶
Even if a product was historically non-tracked:
- You can switch
tracking = serial - Existing stock remains anonymous
- Nothing breaks
Those units simply:
- are not yet identity-bearing
- are not eligible for asset-level services
When you later:
- receive
- internally transfer
- adjust inventory
- deliver
…and serials are required:
➡️ serials are injected at that moment
Balance holds:
Before: qty = 100
After: qty = 70 (anonymous) + 30 serials
No overlap. No duplication.
6. Why Location and “Receiving” Moves Matter¶
Serials can be assigned at:
- manufacturing completion
- incoming receipt
- internal transfer
- delivery
These are transaction boundaries where Odoo allows:
- quantity to move
- identity to be injected
This flexibility supports:
- Migration scenarios (anonymous → serialized)
- Field stock management
- Late labeling workflows
7. Lot Tracking Is Intentionally “Weak”¶
Lot tracking allows:
- fungibility within a batch
- traceability between batches
- history without unit determinism
So yes:
- physical units inside the same lot can be swapped
- state may end up identical after moves
- but history still records what happened
This is acceptable only if unit-level enforcement is not required.
If unit-level integrity matters → use serial tracking.
8. Serial Numbers Are Logically Immutable (Critical Rule)¶
Technically:
- Odoo lets you edit serial names
Practically:
- You must treat serials as immutable asset identity
Changing serials breaks:
- traceability
- audit
- contracts
- services
- IoT linkage
Operational requirement: Serial edit rights must be restricted. Treat serials as write-once identifiers.
9. Why There Is No Double Counting (Final Aha)¶
Because:
- Anonymous quantity and serialized units live in disjoint stock domains
- A unit cannot exist in both at once
- Crossing domains always conserves quantity
Non-tracking and serial tracking do not compete — they coexist safely.
10. Summary¶
Odoo stock is managed as events and derived state. Products may be non-tracked, lot-tracked, or serial-tracked. Tracking mode enables identity but does not create it. Identity is injected only at stock move boundaries, consuming anonymous quantity and preserving balance. Non-tracked stock has no notion of uniqueness, lot tracking provides batch-level identity with fungibility, and serial tracking provides immutable unit-level identity. Once serialized, a unit never returns to anonymity, and double counting is structurally impossible.