In Odoo 20, expiry dates live on lots and serial numbers. Each lot of a product carries an expiration date and three dates worked out from it: best before, removal and alert. With the FEFO removal strategy, Odoo reserves the lot with the earliest removal date for each delivery, stops offering lots past their removal date for sale, and asks for confirmation before anyone ships an expired lot.
The four dates on a lot
| Date | Set on the product as | What Odoo does with it |
|---|---|---|
| Expiration Date | Days after receipt | Marks the lot as expired from that day. Delivering it needs a confirmation. |
| Best Before Date | Days before expiration | Shown on the lot and printed in GS1 labels. It blocks nothing. |
| Removal Date | Days before expiration | Sets the FEFO order. From this date the lot no longer counts as available to sell and is not reserved for deliveries. |
| Alert Date | Days before expiration | Puts the lot in the Expiration Alerts filter and gives the product’s responsible user a to-do. |
An example: a yoghurt with an Expiration Date of 30 days, a Removal Date of 7 and an Alert Date of 10, received on 1 November, expires on 1 December, leaves the sellable stock on 24 November and raises an alert on 21 November.
Set it up in Odoo 20
- In Inventory → Configuration → Settings, Traceability section, tick Lots & Serial Numbers, then Expiration Dates, and save.
- In the same section, tick Display Lots & Serial Numbers on Delivery Slips and Display Expiration Dates on Delivery Slips if your customers check dates on the paperwork.
- On each perishable product, General Information tab, the type must be Goods. Set Tracking to By Lots.
- On the Inventory tab, Traceability section, tick Expiration Date and fill in the four day counts.
- In Inventory → Configuration → Categories, open the category of your perishable goods and set Force Removal Strategy to First Expiry First Out (FEFO). You can set FEFO on a stock location instead, under Logistics, but the category setting wins over the location.
- On the product’s Inventory tab, choose a Responsible user to receive the expiry alerts.
Receiving: use the date printed on the case
By default Odoo sets a new lot’s expiration date to the receipt date plus the product’s Expiration Date days. That fits goods you produce yourself. Imported goods arrive with the manufacturer’s date already printed, often after months of shipping and clearance, so the default overstates their shelf life.
- On the receipt, click Details on the product line.
- Enter the Lot/Serial Number and the Expiration Date printed on the case, one line per lot with its quantity.
- Validate. If you changed a date, Odoo moves the best before, removal and alert dates by the same number of days.
With a scanner it takes one scan per case. Set Barcode Nomenclature to Default GS1 Nomenclature in the Inventory settings, and the Barcode app reads the product (01), the lot (10) and the expiry date (17) from a GS1-128 label into the receipt. When a label carries only a best before date (15), Odoo adds the product’s Best Before days to get the expiry. See Zebra scanners with Odoo and Zebra barcode scanners.
Picking and delivery with FEFO
With FEFO, Odoo reserves lots in order of removal date, then of arrival date. A worked example: a distributor holds three lots of an infant formula and confirms an order for 300 tins.
| Lot | On hand | Removal date | Reserved for the order |
|---|---|---|---|
| L-0412 | 120 | 20 December 2026 | 120 |
| L-0519 | 250 | 15 February 2027 | 180 |
| L-0607 | 400 | 30 April 2027 | 0 |
A lot already past its removal date is skipped, even when it is the oldest. It stays in On Hand but drops out of the free and forecasted quantities, so salespeople do not promise it and reordering rules order replacement stock in time. On a quotation, the stock shown for a line counts only lots that will still be before their removal date on the delivery date.
When someone ships an expired lot
A picker can still choose a lot by hand. If a delivery holds a lot that has expired or passed its removal date, Validate opens a confirmation that names it. Confirm ships it anyway, Proceed except expired removes the lines past their removal date and ships the rest, and closing the window takes you back to the delivery.
Alerts, reports and recalls
- Expiration Alerts. In Inventory → Products → Lots/Serial Numbers, this filter lists every lot past its alert date. Add the Expiration Date and Removal Date columns from the optional columns menu, and group by product.
- Daily to-do. When a lot with stock in your warehouse reaches its alert date, the daily scheduler gives the product’s responsible user an "Alert Date Reached" to-do, once per lot.
- Recalls. Open the lot and click Traceability to see every receipt, transfer and delivery of it, with the customers who received it.
- Delivery slips. With lots and expiry dates on delivery slips, your customers can match what they received to the lot you recall.
What we see go wrong in Kuwait
| What happens | Cause | Fix |
|---|---|---|
| Imported stock shows months more shelf life than the case | Expiry left to the default, receipt date plus days | Enter or scan the printed date at receipt |
| FEFO ignored on some products | FEFO set on the location, while the category forces FIFO | Set FEFO as the Force Removal Strategy on the category |
| A customer refuses short-dated stock | Removal Date of 0 days | Set the Removal Date to the remaining shelf life your customers require on delivery |
| Old stock counted as sellable | Lots created without dates when tracking was switched on | Count the stock again by lot and enter the dates |
| Alerts that nobody reads | No responsible user on the product | Name a responsible user on each perishable product |
Supermarket chains and pharmacy groups often refuse deliveries below a minimum remaining shelf life. The Removal Date is how you hold that line in Odoo: stock that falls below it stops being reserved for orders.
We set up lot and expiry tracking for food, pharma and medical distributors in Kuwait and the Gulf: see Odoo for healthcare and pharma, Odoo Inventory and Odoo for trading and distribution.
What to do next
- List your perishable products and the remaining shelf life each customer requires on delivery.
- Switch on lots and expiry dates in a test database, set FEFO on one category, and run a receipt and a delivery through it.
- Book a consultation if you want help moving your stock to lots and expiry dates.
