See it in action
Every delivery scored on time and in full, rolled up into a dashboard you can slice by customer and month.
The number your customers actually judge you by
On-Time In-Full is the standard scorecard of delivery reliability — but Odoo doesn't measure it out of the box. This app does, automatically, from the deliveries you already process, so you can see where you're slipping and with which customers.
Your OTIF rate, trended
Watch your delivery reliability month over month, then drill into On-Time and In-Full to see what's driving it.
Everything you need to track delivery reliability
On-Time scoring
Every delivery is checked against its promised date — commitment date, deadline or schedule.
In-Full scoring
A delivery that left a backorder didn't ship complete, and counts against In Full.
OTIF combined
The headline metric: on time and in full, scored on every delivery.
Trend graph
Your OTIF rate over months, so slippage shows up early.
Customer pivot
Break the rate down by customer and month, with On-Time and In-Full split out.
Delivery list
Every delivery with promised vs actual date, the three flags and days late.
Late & short filters
Zero in on the deliveries that missed, and the customers affected.
Built on your data
Scores your real outgoing deliveries — no extra data entry, no setup.
Multi-company
Deliveries are scored within their own company.
Up and running in two steps
Install
No configuration needed.
Deliver as usual
Validate your outgoing transfers.
Open the dashboard
OTIF scored automatically.
Act on it
Find late customers and fix the cause.
Real screens, real data
Every screenshot below is the actual app running on Odoo 19 — no mockups.
Slice the rate
A pivot of OTIF, On-Time and In-Full rates by period — and by customer — to see exactly where reliability moves.
Down to each delivery
Every delivery with its promised and actual date, on-time / in-full / OTIF flags and days late — late ones in red.
Know your OTIF before your customers tell you
Install in seconds. No Enterprise, no external libraries, no lock-in. Works on Odoo 19 Community and Enterprise.
Full manual included. The app ships with a complete in-app documentation page (Apps > this module > Documentation) covering the dashboard, the scoring rules and FAQs. Questions? bambooforge.labs@gmail.com
BambooForge Delivery Performance (OTIF)
OTIF — On Time In Full — is the headline metric of delivery reliability, and the one your customers judge you by. This app scores every outgoing delivery against its promised date and whether it shipped complete, then rolls it up into a dashboard you can slice by customer and month.
This page is the complete manual. Follow it top to bottom and you can install, read the dashboard and answer the common questions without contacting support.
Overview
For every completed outgoing delivery, the app works out:
- On Time — was it transferred on or before its promised date (the sale order's commitment date, the delivery deadline, or the scheduled date)?
- In Full — did it ship complete, without spawning a backorder?
- OTIF — on time and in full.
Each delivery gets a 0–100 score for each measure, so the graph and pivot show your OTIF rate as a percentage, by month and by customer.
Requirements
- Odoo 17.0 with Inventory and Sales (sale_stock). Installing this app pulls them in automatically.
No Enterprise modules and no external Python libraries are required.
Installation
- Copy bambooforge_otif into your addons path.
- Update the apps list (Apps > Update Apps List).
- Search for Delivery Performance and click Install.
The analysis appears under Inventory > Reporting > Delivery Performance (OTIF) and Sales > Reporting > Delivery Performance (OTIF).
Reading the dashboard
- The graph shows your OTIF rate over time — spot trends and slippage at a glance.
- The pivot breaks the rate down by customer and month, with separate On-Time and In-Full rates so you can see why OTIF moved.
- The list shows each delivery with its promised date, actual date, on-time, in-full and OTIF flags, and how many days late it was.
Use the filters to focus on Late or Short (not in full) deliveries, and group by Customer to find who is being let down.
How the score is defined
- A delivery is measured when it is a completed outgoing transfer that is not itself a backorder, so each order's primary delivery is counted once.
- On Time = the transfer date is on or before the promised date.
- In Full = the delivery did not leave a backorder behind.
- OTIF = both of the above.
The promised date is taken from the sale order's commitment date when available, otherwise the delivery deadline, otherwise the scheduled date.
Frequently asked questions
- Nothing shows up.
- Only completed (Done) outgoing deliveries are scored. Validate some deliveries and they will appear.
- A partial delivery shows as not in full.
- Correct — if a delivery left a backorder, the order was not fully shipped on that transfer, so it counts against In Full.
- Which date is the deadline?
- The sale order's commitment date if set; otherwise the delivery's deadline or scheduled date.
- Can I see performance per customer?
- Yes — the pivot groups by customer, and you can group the list by customer too.
- Does it work with multiple companies?
- Yes; deliveries are scored within their own company.
Support
Questions or ideas: bambooforge.labs@gmail.com.
Configuration
There is no settings screen: once installed, every outgoing delivery you validate is scored automatically. The points below explain what the score depends on.
The promised date
On-Time is judged against a single Promised Date (otif_target_date). For each delivery the app takes the first of these that is set:
- the linked sale order's commitment date;
- the delivery's Deadline (date_deadline);
- the delivery's Scheduled Date (scheduled_date).
Scheduled Date is always present, so a delivery is never left without a promised date. For a meaningful On-Time figure, though, set a real customer commitment: enable Sales > Configuration > Settings > Delivery Date, then fill the commitment date on the sale order (under Other Info). It then flows through to the delivery and drives the metric.
What is measured
A delivery counts toward OTIF (otif_measured) only when all of the following hold, so each order's primary shipment is scored exactly once:
- its operation type is outgoing;
- its status is Done (validated);
- it is not itself a backorder of an earlier transfer.
On those deliveries the app sets On Time (date_done on or before the Promised Date), In Full (the transfer left no backorder behind), OTIF (both) and Delay (days) (days late, 0 when on time). Each flag is mirrored by a 0–100 score averaged by the graph and pivot, so a group average reads directly as a percentage. Fields recompute when the state, dates, backorder links or the order's commitment date change.
Access
The report reads standard stock.picking records, so it honours your existing delivery access rights and multi-company rules. The Inventory menu is open to Inventory users; the mirror under Sales is limited to the Salesperson group (sales_team.group_sale_salesman).
Usage
Opening the dashboard
Two menus point at the same report:
- Inventory > Reporting > Delivery Performance (OTIF)
- Sales > Reporting > Delivery Performance (OTIF)
It opens filtered to measured deliveries only, so drafts, receipts, internal transfers and backorder shipments never dilute the numbers. Three views are available from the switcher.
- Graph — a bar chart of the OTIF Rate by delivery month. A bar at 90 means 90% of that month's measured deliveries were on time and complete.
- Pivot — Customer on rows, Delivery Month on columns, with OTIF, On-Time and In-Full rates as measures. This is where you diagnose why OTIF moved: high In-Full but low On-Time means you ship complete but late.
- List — one line per delivery: reference, customer, source order, Promised Date, actual date, the On-Time / In-Full / OTIF toggles and Delay in days. Rows are colour-coded (green OTIF, red late, orange on-time-but-short) and read-only.
The search bar offers OTIF, Late and Short (not in full) filters, a This Year period filter, and Group By Customer or Delivery Month.
Worked example
You ship Deco Addict five June orders: four on time and complete, one two days late. In the pivot, June for Deco Addict shows On-Time 80%, In-Full 100% and OTIF 80%. Grouping the list by Customer with the Late filter surfaces the single slipping delivery, its Delay column reading 2.
Troubleshooting
The report is empty ("No deliveries to score yet")
Cause. Only completed outgoing transfers are scored. If none is validated to Done, or the only outgoing transfers are backorders, the population is empty.
Diagnosis. In Inventory > Operations > Deliveries, confirm you have Done transfers that are not themselves backorders.
Resolution. Validate outgoing deliveries; scores appear immediately.
OTIF looks unrealistically high (near 100%)
Cause. No commitment dates are set, so On-Time is judged against the delivery's own Scheduled Date — which it almost always meets, inflating the rate.
Diagnosis. In the list, compare the Promised Date with the order's commitment date. If it matches the internal scheduled date, commitments are missing.
Resolution. Enable Delivery Date in Sales > Configuration > Settings and populate commitment dates. New deliveries are then scored against the date the customer agreed to.
A partial delivery is flagged "not in full"
Cause. The transfer shipped short and spawned a backorder, so the order was not fully shipped on that transfer — this fails In-Full by design.
Diagnosis. Open the delivery and check its linked back orders.
Resolution. No fix needed — the flag is correct. Ship complete in one transfer to improve the rate. The follow-up backorder shipment is excluded from the measured population, so it does not double-count.
A validated delivery shows the wrong flag or date
Cause. The OTIF fields are stored computed values; they recompute when the state, dates, backorder links or the order's commitment date change.
Diagnosis. Confirm the delivery's Done date and the order's commitment date, and that the delivery is not a backorder.
Resolution. Correct the underlying date; the score recomputes automatically. If a bulk historical correction does not refresh, re-save one affected delivery to force it.
Upgrading & version compatibility
This build targets Odoo 19.0. Each Odoo major series (17.0, 18.0, 19.0) has its own dedicated build of this module — always install the build that matches your Odoo version. Mixing a build with a different Odoo series is not supported.
Patch upgrades (same series, e.g. 19.0.1.0.0 → later)
Back up your database and filestore first.
Replace the module folder with the newer build.
Restart Odoo with the module updated:
./odoo-bin -c your.conf -u bambooforge_otif -d your_db
Odoo applies any schema/data changes automatically. Your existing records and configuration are preserved.
Cross-version migration (e.g. Odoo 17 → 18)
Upgrading Odoo itself is a database migration handled by Odoo's standard upgrade tooling. When you migrate the database to the next Odoo series, install the matching build of this module for that series. Data created by this module carries over with the database migration.
Uninstallation
You can remove this module at any time from Apps → (this module) → Uninstall, or from the command line. Uninstalling is clean and reversible by reinstalling — but note what is and is not deleted.
What is removed
- The fields, views and analysis definitions this module added.
- The menus, actions, views and reports this module installed.
What is preserved
- Your standard Odoo data (partners, products, sales, invoices, inventory moves) is not deleted — this module only reads and annotates it; the underlying records stay.
- Attachments and chatter messages on standard records are kept.
As always, take a database backup before uninstalling in production.
Changelog
19.0.1.0.0
Current release for Odoo 19.0. This build includes:
- Measure your On-Time In-Full (OTIF) delivery performance. See, per customer and per period, how often you delivered on time and complete.
- The supply-chain KPI your customers judge you by.
Feature additions and fixes ship as new builds on the Odoo Apps store; this page and the module's version reflect the current published release. Always keep the build matched to your Odoo series (see Upgrading & version compatibility).
Odoo Proprietary License v1.0 This software and associated files (the "Software") may only be used (executed, modified, executed after modifications) if you have purchased a valid license from the authors, typically via Odoo Apps, or if you have received a written agreement from the authors of the Software (see the COPYRIGHT file). You may develop Odoo modules that use the Software as a library (typically by depending on it, importing it and using its resources), but without copying any source code or material from the Software. You may distribute those modules under the license of your choice, provided that this license is compatible with the terms of the Odoo Proprietary License (For example: LGPL, MIT, or proprietary licenses similar to this one). It is forbidden to publish, distribute, sublicense, or sell copies of the Software or modified copies of the Software. The above copyright notice and this permission notice must be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Please log in to comment on this module