Odoo's inventory module is one of the most detailed stock tracking systems available in any ERP. Every receipt, every shipment, every internal transfer creates a data trail. The problem isn't a lack of data — it's turning that data into purchasing decisions, stock optimization, and warehouse intelligence.
This guide breaks down Odoo's inventory data model, explains how to extract analytics from it, and covers where the built-in tools fall short.
Odoo's inventory data model
Before you can analyze inventory, you need to understand how Odoo stores it. Three models do the heavy lifting.
Stock quants: where things are right now
A stock quant (stock.quant) is Odoo's answer to the question "how much of product X is in location Y?" Each quant record ties a product variant to a specific warehouse location with a quantity.
Key fields on a quant:
product_id: the specific product variantlocation_id: the warehouse location (a bin, a shelf, or a virtual location)quantity: units on handreserved_quantity: units reserved for outgoing transferslot_id: the lot or serial number (if tracking is enabled)
What makes quants powerful for analytics is their granularity. You don't just know you have 500 units of a product — you know 300 are in Warehouse A, Shelf B3, and 200 are in Warehouse B, receiving dock, with 50 reserved for pending deliveries.
One important gotcha: qty_available is a computed field on the product model, not stored on the quant. You cannot use it in Odoo domain filters. If you're building analytics queries, you need to sum quant quantities directly and filter in your application code.
Stock moves: how things got there
A stock move (stock.move) records the movement of goods between locations. Every time inventory changes — a receipt from a supplier, a shipment to a customer, a transfer between warehouses — a stock move is created.
Key fields:
product_id: what movedproduct_uom_qty: how many unitslocation_id: source locationlocation_dest_id: destination locationdate: when it happenedstate: draft, waiting, confirmed, assigned, done, or cancelledorigin: the source document (a purchase order number, a sale order reference)
Stock moves are your primary data source for demand analysis, receiving patterns, and throughput calculations. By filtering moves by state (done) and analyzing them over time, you can build sales velocity curves, receiving cadence reports, and warehouse throughput metrics.
Stock pickings: the grouping layer
A stock picking (stock.picking) groups multiple stock moves into a single operation. When a customer orders three products, Odoo creates one picking (the delivery order) with three stock moves inside it.
Pickings also carry the picking type — receipt, delivery, or internal transfer — which is essential for separating inbound from outbound analytics. The scheduled_date vs date_done comparison on pickings tells you how well your warehouse is meeting delivery commitments.
Turning quant data into inventory intelligence
Raw quant records are a starting point. Useful inventory analytics requires combining quants with other data.
Days-of-supply per SKU
This is the most important inventory metric and Odoo doesn't calculate it for you. The formula:
Days of Supply = Current Quantity on Hand / Average Daily Sales Velocity
To compute this in Odoo, you need two things: the current quant quantity (summed across locations for a given product) and the average daily outbound stock moves over a trailing period (typically 30 or 60 days).
Products with more than 90 days of supply are likely overstocked. Products with fewer than 7 days need urgent reordering. This single metric transforms a flat stock list into a prioritized action plan.
Inventory aging
Odoo tracks lot creation dates and move dates, which means you can calculate how long specific stock has been sitting in a location. Inventory aging matters because older stock has higher carrying costs — warehouse fees, depreciation risk, and tied-up capital.
To build an aging report, look at the date field on incoming stock moves (where location_dest_id is an internal location) and compare it to the current date. Group by age buckets — 0-30 days, 31-60, 61-90, 90+ — and multiply by unit cost for a capital-at-risk view.
Warehouse-level analytics
If you run multiple warehouses, quants give you per-location visibility that most ecommerce platforms lack. You can answer questions like:
- Which warehouse has the most capital tied up in slow-moving stock?
- Are certain products overstocked in one location and understocked in another?
- What's the average time from receipt to first outbound move per warehouse?
These questions require joining quant data with move data and grouping by warehouse_id on the stock location. Odoo's built-in inventory reports don't support this level of cross-referencing.
Tracking stock moves for demand patterns
Stock moves are underused in most Odoo deployments. Merchants look at sales reports for demand data, but stock moves tell a richer story.
Velocity trends over time
By aggregating outbound stock moves (deliveries) by week or month, you can build velocity trend lines per product. A product selling 50 units per week that's now selling 30 needs different treatment than one selling 50 that's accelerating to 70.
Odoo's sales analysis report shows order quantities, but it doesn't account for partial deliveries, backorders, or returns that create reverse moves. Stock moves reflect what actually left the warehouse, which is the ground truth for demand analytics.
Seasonality detection
With enough history (ideally 12+ months), stock move data reveals seasonal patterns. A product that spikes every quarter isn't overstocked at 120 days of supply if a seasonal surge is coming. Without seasonal context, you'd flag it for markdown.
To detect seasonality, group outbound moves by month across multiple periods and look for repeating peaks. Odoo doesn't do this natively — you'd need to export data or use an external analytics tool.
Supplier lead time accuracy
Inbound stock moves tell you when goods actually arrived. Purchase orders tell you when they were expected. Comparing date_done on receipt pickings to date_planned on the purchase order gives you actual vs. expected lead times per supplier.
This data is critical for setting accurate reorder points. If your reorder rule assumes a 14-day lead time but your supplier consistently delivers in 21 days, you'll face recurring stockouts.
Inventory valuation methods in Odoo
Odoo supports three inventory valuation methods, and each affects your analytics differently.
Standard Price: Every unit is valued at a fixed cost that you set manually. Simple, but inaccurate when purchase prices fluctuate. Your inventory valuation only changes when you manually update the standard price.
Average Cost (AVCO): The system recalculates the average unit cost with each incoming receipt. If you buy 100 units at $10 and then 100 at $12, your valuation is $11 per unit for all 200. Good for products with moderate price volatility.
FIFO (First In, First Out): Each unit retains the cost from its specific receipt. When you sell, Odoo uses the oldest cost first. This is the most accurate for margin analysis but adds complexity — especially when you have returns or internal transfers that disrupt the FIFO queue.
For analytics, the valuation method determines whether your margin calculations are approximate (Standard), averaged (AVCO), or precise (FIFO). If you're doing product-level profitability analysis, make sure your analytics tool respects the valuation method configured in Odoo.
Reorder rules: useful but limited
Odoo's reorder rules (stock.warehouse.orderpoint) automate replenishment. You set a minimum quantity, a maximum quantity, and optionally a lead time and supplier. When stock drops below the minimum, Odoo generates a purchase order or manufacturing order.
This works for basic scenarios but has real limitations:
Static thresholds: Reorder rules use fixed min/max values. They don't adjust for changing demand. A product that was selling 10 units per day when you set the rule might be selling 2 per day now, but the reorder rule keeps buying at the old rate.
No demand forecasting: Reorder rules are reactive. They trigger when stock drops below a threshold, not when a stockout is predicted based on current velocity. By the time the rule fires, you might already be facing a gap if lead times are long.
No margin awareness: Reorder rules treat all products equally. A reorder on a 5% margin product ties up just as much capital as a 50% margin product, but the business impact is very different. Margin-weighted reorder prioritization isn't something Odoo supports natively.
No cross-product intelligence: If Product A and Product B are frequently purchased together (basket analysis), a stockout on A affects sales of B. Reorder rules operate per-SKU with no awareness of product relationships.
Getting inventory intelligence from Odoo with Spark
Spark connects to your Odoo instance and reads inventory data — stock quants, stock moves, pickings, and product records — to surface the analytics that Odoo's reports don't provide.
Instead of building custom Odoo reports or exporting data to spreadsheets, you can ask questions directly:
- "Which products have more than 90 days of supply based on the last 60 days of sales velocity?"
- "What's my total capital at risk in warehouse A vs. warehouse B?"
- "Which supplier has the worst lead time accuracy over the last 6 months?"
- "Show me products where the reorder point is set too high based on current demand trends."
Spark computes days-of-supply, capital at risk, velocity trends, and inventory aging from your Odoo data automatically. It understands Odoo's data model — the relationship between quants, moves, pickings, and purchase orders — so you don't need to build those joins yourself.
The platform also respects your valuation method when calculating margins, so whether you're running Standard, AVCO, or FIFO, the profitability numbers are consistent with your accounting.
For merchants running Odoo with any meaningful product catalog, the gap between the data Odoo collects and the insights its reports provide is significant. The data model is excellent — stock quants and moves give you granularity that most systems lack. The analytics layer is where you need help.
Where to start
If you're running Odoo and want better inventory analytics, focus on three things first:
-
Verify your quant accuracy. Run a stock quant report and compare a sample of products to physical counts. If quants are wrong, analytics built on them will be wrong too.
-
Check your valuation method. Make sure you know whether you're on Standard, AVCO, or FIFO — and that it matches your actual cost tracking practices. Switching methods mid-stream creates data inconsistencies.
-
Compute days-of-supply for your top 20 products. Even a manual calculation using quant quantities and recent sales data will reveal which products are overstocked and which are at risk of stockout. This single metric is worth more than any default Odoo inventory report.
Turn your Odoo inventory data into decisions
Spark reads your stock quants, moves, and pickings to calculate days-of-supply, capital at risk, and reorder intelligence — no custom reports needed.