Odoo Inventory Management in Saudi Arabia: SFDA Lots and Multi-City Stock
How to run Odoo inventory management in Saudi Arabia: SFDA lot and expiry tracking with GS1 codes for RSD, stock moving between Riyadh, Jeddah and Dammam, Ramadan and Hajj reordering, landed costs from Saudi ports in SAR and a ZATCA-ready go-live.
Published 2026-10-11 · METCH
Lot, expiry and GS1 tracking for SFDA-regulated goods
This guide follows Odoo 19 menus and notes where Odoo 20, released in September 2026, changes something.
When SFDA announces a recall, a distributor must be able to name every customer who received the affected batch. In Odoo that answer starts with lot tracking. Enable Lots & Serial Numbers under Inventory > Configuration > Settings > Traceability, then Expiration Dates. Use lots for batches, such as dairy or packaged dates, and serial numbers for single units with after-sales service, such as split AC units. Tick Expiration Date on a tracked product and it carries four values in days: the expiry period after receipt, plus best-before, removal and alert dates counted back from expiry. Odoo computes each lot's dates on receipt, and the FEFO removal strategy, set on a location or a product category, ships the nearest removal date first.
Drug importers and distributors also report movements to SFDA's Drug Track and Trace System (RSD), built on GS1 DataMatrix codes carrying GTIN (01), serial (21), expiry (17) and batch (10). Odoo's Default GS1 Nomenclature, in the Barcode settings, reads the same identifiers, so one scan can fill the product, lot or serial and expiry date on a receipt. A DataMatrix is a 2D code, so plan for imager scanners rather than 1D laser models, and note that the Barcode app needs Odoo Enterprise. Reporting to RSD is not a native Odoo feature, so scope that integration separately. Medical devices follow SFDA's separate UDI rules and Saudi-DI database rather than RSD.
Riyadh, Jeddah and Dammam as one stock picture
Many Saudi importers receive containers at Jeddah Islamic Port on the Red Sea or King Abdulaziz Port in Dammam on the Arabian Gulf, and Riyadh stock may arrive by road or by rail through the Riyadh Dry Port. That geography decides who supplies whom: the port-side warehouse receives and inspects, and inland branches draw from it. Create one warehouse per city, open the receiving one under Inventory > Configuration > Warehouses and tick its source in the Resupply From field. Odoo creates a route such as Riyadh: Supply Product from Dammam. Tick it on the products and trigger it with a reordering rule, MTO or the Replenish button. Each transfer then produces a delivery from Dammam and a receipt in Riyadh, and goods on the road sit in Physical Locations/Inter-warehouse transit, so a loaded truck is neither lost nor counted twice.
Multi-step routes, enabled under Inventory > Configuration > Settings > Warehouse, earn their place in the port warehouse:
- Two-step receipts unload into the Input location before storage, useful when a container takes days to unpack.
- Three-step receipts add a Quality Control location, where SFDA-regulated food or medical goods wait until documents and temperature logs are checked.
- Two-step deliveries stage outgoing trucks in the Output location.
- Three-step deliveries pick pharmacy-chain orders by lot, then pack them in the Packing Zone before dispatch.
Start multi-step routes in the port-side warehouse only, and keep inland branches on one step until their counts are stable.
Seasonal reordering for Ramadan, Hajj and summer peaks
A reordering rule sets a Min and a Max per product and location: when forecasted stock falls below Min, Odoo proposes an order back up to Max, a request for quotation on the Buy route or a transfer on a resupply route. Rules sit under Inventory > Operations > Replenishment.
Saudi demand is not flat, so the rules should not be either. Review them before and after each peak:
- Ramadan and Eid: food and household distributors should raise levels early, since suppliers and carriers are busy too.
- Hajj and Umrah seasons: whoever serves Makkah and Madinah needs higher levels in the Jeddah warehouse that feeds them.
- Back to school: stationery, bags and uniforms.
- Summer: cooling products and air-conditioner spare parts.
Lower the levels when the season ends, or Odoo keeps buying for a peak that has passed. Switching a rule from Auto to Manual for the season lets a buyer review each proposal before it becomes an order. Ramadan and Hajj follow the Hijri calendar and move about 11 days earlier each Gregorian year, so compare demand with last Ramadan, not last March. That matters in Odoo 20, which suggests Min and Max from demand history.
Make to order (MTO) suits one-off demand instead, such as a specific pump model a customer orders for a plant shutdown in Jubail. Enable Replenish on Order (MTO) under Inventory > Configuration > Settings > Logistics and add the route to the product; each confirmed sales order then creates a request for quotation, provided the product has a vendor.
Landed costs from Saudi ports, valued in SAR
Since Odoo 19, valuation is a company setting under Accounting > Configuration > Settings > Inventory Valuation (Perpetual or Periodic, then Standard Price, FIFO or AVCO), which a product category can override; in Odoo 18 it lived on each category. Odoo's documentation links periodic valuation with continental accounting and perpetual with Anglo-Saxon accounting, but lets each company choose, so agree the choice with your auditor.
Landed costs turn a supplier's price into a true cost per unit in SAR. The received products must sit in an AVCO or FIFO category, and each cost line is a service product flagged as a landed cost. Take an illustrative container cleared at Jeddah Islamic Port and trucked to Riyadh:
- Goods on the supplier's invoice: SAR 200,000
- Customs duty on the declaration processed through FASAH: SAR 10,000
- Clearance agent's fees: SAR 3,000
- Transport from the port to Riyadh: SAR 5,000
Enter the duty, agent and transport bills with those service products, create the landed cost from the bill and select the validated receipt. Split by current cost, the duty lands on each product in proportion to its value; split by weight or volume suits transport. Odoo 20 can also apply a landed cost to specific products in a transfer, useful when duty covers only part of a shipment.
The 15% import VAT is different: when it is recoverable, it is normally claimed as input VAT in your VAT return rather than added to stock cost. Confirm the treatment with your accountant.
A city-by-city go-live with ZATCA-ready product data
Counts happen in Inventory > Operations > Physical Inventory. Count SFDA-regulated goods by lot and expiry, not only by quantity: each lot gets its own line, and an opening balance without lots leaves the first recall unanswerable. If your fiscal year follows the Hijri calendar, its Gregorian end date moves about 11 days earlier each year, so reset the Annual Inventory Day and Month under Inventory > Configuration > Settings > Operations every year; Odoo's default is 31 December.
The steps we follow to go live:
- Clean the product master first: Arabic and English names for bilingual invoices, units, barcodes and GTINs, the 15% VAT rate and the tracking setting. These fields reach every ZATCA invoice.
- Go live in one city first, often where the finance team sits, such as Riyadh, and add Jeddah and Dammam once inter-city transfers and counts reconcile.
- In each city, freeze movements, count every location by lot, apply, and check the value against your old books.
- Before switching Odoo's ZATCA API mode to Production, pass a standard invoice and a POS sale through Simulation (Pre-Production). POS sales are simplified tax invoices under ZATCA e-invoicing, so check that the Saudi POS modules (l10n_sa_pos, l10n_sa_edi_pos) issue and report them correctly.
At METCH, an official Odoo Ready Partner based in Riyadh, our team trains users in Arabic first. Book a free consultation and bring your SFDA-regulated product list; we will go through your lot, GTIN and warehouse setup with you before go-live.
Frequently asked questions
How does Odoo Inventory affect ZATCA e-invoicing?
Your product records become ZATCA invoice lines, so fix them in Inventory first. Stock moves are not sent; invoices are. Once your Phase 2 wave is notified, l10n_sa_edi sends standard tax invoices to ZATCA for clearance before you share them, and simplified POS invoices, handled by l10n_sa_edi_pos and l10n_sa_pos, must be reported within 24 hours. A product saved with the wrong unit, a missing Arabic name or the wrong tax repeats that error on every invoice issued from it.
Should customs duty and import VAT go into landed costs in Saudi Arabia?
Customs duty usually does. Take the amount from the customs declaration processed through FASAH, and enter the clearance agent's invoice and the transport invoice as separate landed-cost lines, so each can be split its own way. The 15% import VAT is different: when it is recoverable, it is normally claimed as input VAT in your VAT return rather than added to stock cost. Confirm the treatment for your company with your accountant before the first container arrives.
Can Odoo support SFDA's RSD drug track and trace for pharmaceutical distributors?
It can hold the data RSD relies on. Serial and lot tracking, expiration dates and FEFO picking are standard Inventory features, and Odoo's default GS1 nomenclature reads GTIN (01), batch (10), serial (21) and expiry (17) from a DataMatrix scan. Sending supply and receipt events to RSD is not built into Odoo, so treat it as a separate integration, check SFDA's current RSD integration documentation, and scope the work before go-live.
How do we find every customer who received a batch if SFDA announces a recall?
Go to Inventory > Products > Lots/Serial Numbers, open the lot and click the Traceability smart button. The report lists that lot's stock moves, from the supplier receipt through internal transfers to each customer delivery, and in Odoo 20 it also shows expiration dates. Move any remaining units to a quarantine location outside the warehouse's stock location so they are not picked. Any notification to RSD remains a separate step outside Odoo.
Need help with this?
METCH is a certified Odoo partner in Saudi Arabia — book a free consultation.
Get a proposal