Pharmaceutical ERP is not a separate category from general manufacturing ERP — it is the same system with a much higher traceability requirement. Every raw material that enters a pharma production facility must be traceable to the finished dosage form it contributed to, and every finished dosage form must be traceable back to its input raw material lots. This is not optional: it is the foundation of product recall capability, which is required under DGDA licensing, WHO-GMP, and any export market regulatory approval.
Odoo handles this correctly when configured correctly. The core capability — lot-based traceability from receipt through production to delivery — is built into the standard Odoo Inventory and Manufacturing modules. What pharma requires is that this capability be turned on for every product, consistently enforced at every transaction point, and augmented with expiry date tracking and quality check integration.
For EPZ-based pharma exporters, see also the EPZ compliance configuration guide. For inventory valuation that applies to API and excipient stock, the Odoo inventory valuation cheatsheet covers the relevant costing methods.
In pharmaceuticals, the ERP is not an operational convenience — it is the primary evidence that your manufacturing process was controlled. A recall without ERP traceability is a crisis. A recall with ERP traceability is a manageable event.
Why pharmaceutical manufacturing needs different ERP configuration
Standard manufacturing ERP assumptions that pharma breaks:
- Every batch is unique: A production batch of 100,000 tablets is not interchangeable with another batch of the same product. Each batch has its own identity (batch number), its own input material lots, its own in-process test results, and its own release status. ERP must track batches, not just products.
- Raw materials are traceable to finished goods: If a quality problem is discovered in a supplier's API lot, you must be able to identify every production batch that used that API lot, and every customer who received product from those batches. This requires complete forward and backward traceability — not just lot numbers, but the full movement chain.
- Expiry dates are mandatory: Every pharmaceutical product and raw material has an expiry date. Stock must be managed using FEFO (First Expired First Out), not FIFO or LIFO. Expired stock must never be sold — the system must enforce this, not depend on operator vigilance.
- Quality release is a control step: Unlike most manufacturing, pharma products cannot be sold until QC releases the batch. The ERP must enforce this: finished goods produced by manufacturing must enter a "quarantine" status and only move to "released" stock after QC approval. Sales orders cannot deliver from quarantine stock.
- Manufacturing records are regulatory documents: The Batch Manufacturing Record (BMR) is a regulatory requirement under DGDA, WHO-GMP, and all major pharmacopoeias. It must record every step of production, every material used with its lot number and quantity, every in-process test result, and every deviation. ERP must capture this data in a structured format.
Lot and batch tracking setup in Odoo
Enable lot tracking as follows:
- System setting: Inventory → Configuration → Settings → Traceability → enable "Lots & Serial Numbers" and "Expiration Dates".
- Product tracking: On every pharmaceutical product (finished goods, APIs, excipients, packaging materials), set Tracking = By Lot. Do not skip packaging materials — primary packaging (blisters, bottles) must be lot-tracked for print batch number verification.
- Lot number format: Standardize your lot number format. A common Bangladesh pharma format:
BN-YYYYMM-NNN(e.g., BN-202605-001 = Batch 001 manufactured in May 2026). Configure this as a convention in your SOP — Odoo accepts any string as a lot number but your lot numbers should be systematic.
| Product Category | Tracking Setting | Expiry Dates | Lot number source | FEFO required? |
|---|---|---|---|---|
| APIs (Active Pharmaceutical Ingredients) | By Lot | Yes — from supplier CoA | Supplier batch number | Yes |
| Excipients (fillers, binders, lubricants) | By Lot | Yes — from supplier CoA | Supplier batch number | Yes |
| Primary packaging (blisters, bottles, vials) | By Lot | Typically no expiry | Supplier batch or internal code | No (FIFO) |
| Secondary packaging (cartons, inserts) | By Lot (for printed material with batch/expiry) | No | Print run reference | No |
| Finished pharmaceutical products | By Lot | Yes — calculated from manufacture date + shelf life | Internal batch number (BN-YYYYMM-NNN) | Yes — mandatory |
Expiry date management in Odoo
When "Use Expiration Dates" is enabled on a product, each lot has four date fields in Odoo:
- Expiration Date: The date after which the product must not be used or sold. For APIs, this comes from the supplier's CoA. For finished products, this is set automatically as Manufacturing Date + Use Time (configured on the product in days).
- Best Before Date: The date until which the product is expected to remain at full potency. For most pharma products, this equals the Expiration Date.
- Removal Date: The date at which stock should be quarantined or removed from availability for sale — typically set to 3 months before expiry to allow for distribution and use before expiry. Configure this as the trigger date for Odoo's expiry alerts.
- Use Time (days): Set on the product master. Odoo uses this to calculate expiry date automatically when you create a manufacturing order — Manufacturing Date + Use Time = Expiry Date on the finished goods lot.
FEFO enforcement: Go to Inventory → Configuration → Settings → Storage Locations → enable "Storage Locations" if not already on. Then in the product's inventory tab, set Removal Strategy = "First Expiry First Out (FEFO)". When a picking is generated for a sales order or a transfer, Odoo automatically suggests the lot with the earliest expiry date. For a wholesale/hospital sales context, this is essential — it prevents near-expiry stock from accumulating in the warehouse.
Expiry alerts: Configure Odoo's scheduled action "Generate Expiry Alerts" (Settings → Technical → Automation → Scheduled Actions) to run daily. Lots reaching their Removal Date generate an activity alert for the QC or warehouse manager. You can also create a custom report: Inventory → Products → Lots/Serial Numbers, filter by Expiration Date ≤ today + 90 days, to see all near-expiry stock.
Pharmaceutical manufacturing workflow in Odoo
Configure the manufacturing routing with one work order per major production stage. Each stage has its own work centre, time estimate, quality checks, and responsible operator.
QC and batch release in Odoo
In pharmaceutical manufacturing, the quality department must release each batch before it can be sold. Odoo implements this through a two-location stock structure:
- Quarantine location: Create a stock location called "QC Quarantine" under your main warehouse. Set its usage type to Internal. When a Manufacturing Order is completed, the finished goods are transferred to QC Quarantine — not to the main finished goods location.
- Released stock location: Your main finished goods location (e.g., "Finished Goods / Released").
- Release process: After QC completes all final product testing (potency assay, dissolution, microbiological), a QC officer creates an internal transfer from QC Quarantine → Finished Goods / Released for the specific lot number. This transfer is the "batch release" transaction. Only after this transfer can the lot be allocated to sales orders.
- Blocking expired or unreleased lots: Configure the Finished Goods product with a putaway rule that routes new arrivals to QC Quarantine by default. Sales order picking uses only the Released location. This prevents unreleased or expired stock from being shipped accidentally.
- QC reject and destruction: If a batch fails release testing, the lot is transferred from QC Quarantine to a "Rejected/Destroyed" location via a scrap order. The scrap entry records the reason (assay failure, contamination, etc.) and triggers a write-off in the accounting. The lot is locked from further use.
DGDA compliance data in Odoo
The Directorate General of Drug Administration (DGDA) requires pharmaceutical manufacturers to maintain Batch Manufacturing Records and Batch Packing Records for every production batch. Odoo captures the underlying data; you need a custom report to format it as a BMR.
Data that Odoo captures in the Manufacturing Order (which feeds the BMR):
- Product name, batch number, batch size (quantity)
- Manufacturing date, expiry date
- Raw material components: name, specification, lot number, quantity dispensed (from work order component consumption)
- In-process quality check results (from Odoo Quality module checks attached to work orders)
- Work centre used at each stage (operator can be recorded via time tracking)
- Final yield (quantity produced vs quantity started)
- QC release transfer record and responsible person
Develop a custom QWeb report that pulls all this data from the Manufacturing Order and formats it into your DGDA-approved BMR template. This is a one-time development effort (typically 3–5 days of Odoo development time) but is mandatory for regulatory compliance. The BMR is the document a DGDA inspector will request during a factory inspection.
Recall traceability in Odoo
The recall scenario: a supplier notifies you that an API lot (e.g., Metformin HCl, Lot MF-2025-CN-019) has failed potency testing. You must identify every finished product batch that used this API lot and every customer who received product from those batches.
- Forward trace from raw material lot: Inventory → Reporting → Traceability → search for the API lot number (MF-2025-CN-019). Odoo shows all Manufacturing Orders that consumed this lot. Note all internal batch numbers (e.g., BN-202601-005, BN-202601-012).
- Forward trace from finished goods batch: For each finished goods batch identified, run Traceability again on the finished goods lot. This shows all Sales Order deliveries that included this lot — with customer names, delivery dates, and quantities.
- Recall affected customers: Export the customer list from the Odoo traceability report. Your quality department contacts each customer with the recall notification and return instructions.
- Block remaining stock: For any quantity of the affected lots still in your warehouse (Released or QC Quarantine), create an internal transfer to move them to a "Recall Hold" location. This prevents accidental shipment of the recalled product while the recall is underway.
- Regulatory reporting: Report the recall to DGDA with: product name, batch numbers affected, lot number of the defective raw material, reason for recall, quantity in market, and corrective action. All this data is available from Odoo's traceability report and MO records.
The entire forward trace from API lot to customer list can be completed in under 10 minutes in Odoo. Without ERP lot tracking, the same exercise requires days of manual reconciliation across paper records — during which more defective product may continue to ship.
Temperature-sensitive storage management
Many pharmaceutical products require controlled storage: 2–8°C (refrigerated), 15–25°C (controlled room temperature), or protected from light. Odoo can support temperature zone management through storage location configuration:
- Create location zones: In Inventory, create sub-locations corresponding to storage zones: "Cold Room (2–8°C)", "CRT Storage (15–25°C)", "Ambient Storage". Label each with its storage condition in the location name.
- Putaway rules per product category: Create putaway rules that route incoming receipts of refrigerated products automatically to the Cold Room location. This eliminates the manual decision of where to put products during receipt.
- Cold chain documentation: For cold chain products received from suppliers, record the temperature log during transit as an attachment on the purchase receipt (supplier provides a temperature data logger report). This is a GMP requirement for vaccine and biologic products.
- Temperature excursion handling: If a cold chain product is found to have been stored outside its required temperature range, transfer the affected lots to a "Quarantine — Temperature Excursion" location in Odoo and initiate a quality investigation. Do not release the lot until QC determines it meets specifications despite the excursion.
Odoo for pharma in Bangladesh requires three non-negotiable configurations: (1) lot tracking on every product without exception; (2) FEFO enforcement and expiry date management on all pharmaceutical stock; and (3) a QC quarantine location that prevents unreleased batches from being sold. Beyond these, the BMR custom report and the recall traceability capability are what turn Odoo from a stock management tool into a genuine GMP-compliant pharmaceutical ERP. Need help configuring Odoo for your pharmaceutical company? Get in touch →
Frequently asked questions
How to enable lot and batch tracking in Odoo for pharmaceuticals?
Go to Inventory → Configuration → Settings, enable "Lots & Serial Numbers" and "Expiration Dates". Then set Tracking = "By Lot" on every pharmaceutical product (APIs, excipients, primary/secondary packaging, and finished goods). Assign lot numbers at receipt (from supplier CoA batch numbers for raw materials) and at manufacturing (your internal batch number format for finished goods). Odoo will then record every movement of every lot, creating the traceability chain required for GMP compliance and product recall.
How does Odoo manage expiry dates for pharmaceutical products?
Enable "Use Expiration Dates" on pharmaceutical products. Each lot has an Expiration Date, Removal Date, and Best Before Date. For finished goods, set "Use Time" (shelf life in days) on the product — Odoo calculates expiry automatically as manufacturing date + use time. Set Removal Strategy = FEFO on pharma products to ensure oldest-expiry stock is always shipped first. Run the scheduled expiry alert action daily so near-expiry lots trigger activities for the QC team. Block sales of expired stock by ensuring the sales order picking only draws from the Released stock location (not QC Quarantine where new production lands first).
Can Odoo handle DGDA batch manufacturing record requirements in Bangladesh?
Odoo captures all the data required for a DGDA BMR: product/batch identity, manufacturing and expiry dates, raw material lot numbers and quantities, in-process quality check results, work centre and operator records, final yield, and QC release sign-off. What Odoo does not provide out-of-the-box is a formatted BMR print template — you need a custom QWeb report that renders all Manufacturing Order data in the DGDA-approved BMR format. This is a one-time development (3–5 days) that is mandatory for regulatory compliance. The same data also supports WHO-GMP inspection requirements.
How do I set up pharmaceutical manufacturing workflow in Odoo?
Configure multi-step routing in Manufacturing: Work Orders for Dispensing → Granulation → Compression → Coating → Primary Packaging → Secondary Packaging, each with its own Work Centre and quality checks. Finished goods from the last work order go to a QC Quarantine location, not directly to Released stock. QC conducts final product testing and, if the batch passes, creates an internal transfer from QC Quarantine to Released stock — this is the batch release event. Only released lots can be allocated to sales orders. Rejected batches are moved to a Destroyed location via a scrap order, which writes off the inventory value and locks the lot.