Skip to main content

Delivery Orders — SLA at a Glance

Every outgoing Delivery Order in Inventory now carries the same Service Level Agreement (SLA) badge that's been on the Sales Order form for months. Warehouse and dispatch staff can see, straight from the transfer list, which deliveries are on track, which are running close to the wire, and which have already breached the customer's target window — without opening the underlying SO.

The plumbing is in common/sla_sales_tracking/models/stock_picking.py: each picking pulls its SLA from the linked sale.order via stored related fields, so the badge is computed once on the SO side and surfaces wherever you list pickings — no extra cron, no recomputation per view.

Where to find it

Inventory → Operations → Transfers (or any picking-type tile from the Inventory Overview dashboard). Open the Deliveries filter and you'll see the new SLA Status column by default:

Delivery Orders list with SLA Status badge

Colours match the badge convention used elsewhere in bc17:

BadgeMeaning
🟢 On Time / Delivered On TimeStill within SLA window with >2 working days remaining, or completed picking landed on or before the expected date
🟡 At RiskConfirmed delivery with ≤2 working days remaining
🔴 DelayedPast the Expected Delivery date with no completed picking
🔴 Delivered LateCompleted picking finished after the expected date
N/APicking has no linked SO (internal moves, manual receipts, etc.)

Optional columns

Click the column-options icon (top-right of the tree) and toggle on SLA Expected Delivery, SLA Days Remaining, and SLA Region for a full readout per row:

Delivery Orders with optional SLA columns toggled on

The SLA Days Remaining column is colour-coded the same way the badge is:

  • Green — >2 working days to spare
  • Yellow — 0–2 working days remaining
  • Red — negative number, i.e. days overdue

Your column toggles are remembered per user, so once you've picked the layout you want, it sticks.

Filtering and grouping

Tap the caret on the right side of the search bar to open the search panel. The middle column lists every SLA filter and the new SLA Status group-by:

Search panel showing SLA filters and group-by

The five new filters under Filters → SLA:

FilterWhat it shows
SLA: On TimeConfirmed deliveries still within window
SLA: At RiskConfirmed deliveries with ≤2 working days remaining
SLA: DelayedConfirmed deliveries past Expected Delivery with no completed picking
SLA: Delivered On TimeCompleted deliveries that hit the window
SLA: Delivered LateCompleted deliveries that missed it

…plus a Group By → SLA Status that produces a clean breakdown for daily / weekly reviews:

Deliveries grouped by SLA Status

The grouped view is what dispatchers should default to in the morning — At Risk and Delayed float to the top of the alphabet, making the day's priority list self-evident.

SLA targets — driven by customer region

The number of working days each delivery is allowed comes from the customer's region via res.region.delivery_time. Current settings:

RegionTarget
NCR (Metro Manila)3 working days
Region III (Central Luzon — incl. Pampanga)3 working days
CAR (Cordillera — incl. Baguio)3 working days
Region VII (Central Visayas — incl. Cebu)3 working days
All other Philippine regions5 working days

Working-day math skips weekends and entries in the sla.holiday model. The same calculation drives the SLA badge on the SO form — see Sales Order → SLA tracking for the underlying state machine and the full status-decision flow.

N/A badge on internal transfers is expected

Pickings created outside a sale order — internal warehouse transfers, scrap moves, manual receipts — show no SLA badge (or a muted N/A). The SLA is a customer-facing commitment computed from the sale, so it doesn't apply to internal operations.

Configuration

The SLA computation has two configurable inputs and one prerequisite. Both configuration screens live under Sales → Configuration → SLA Configuration (they were authored as part of the original SO SLA module — Inventory simply consumes the results).

Step 1 — SLA days per region

Sales → Configuration → SLA Configuration → Region SLA Days opens an editable list of all 17 Philippine administrative regions. Click any SLA Days cell to edit inline:

Region SLA Days settings

After saving, both sale.order.sla_* and stock.picking.sla_* recompute on the next save of each record. There's no separate recomputation cron — touching the region propagates to every order/delivery whose partner sits in it as those records are next read or saved.

Granularity is at the region level only

There's no per-province override. If Pampanga (within Region III) needs a different SLA from the rest of Central Luzon, that distinction isn't expressible today — every customer in Region III gets the same number.

If a finer split becomes necessary, a follow-up would be to add an optional sla_override_days on res.partner that, when set, supersedes the region lookup.

Step 2 — Working-day holidays

Sales → Configuration → SLA Configuration → SLA Holidays lists every date excluded from the working-day math:

SLA Holidays list

Each holiday has three knobs:

FieldEffect
Holiday Type = Regular Holiday (red badge)Excluded from working-day count. Use for the formal PH regular holiday roster (New Year's Day, Maundy Thursday, Good Friday, Araw ng Kagitingan, Labor Day, Independence Day, National Heroes Day, Bonifacio Day, Christmas Day, Rizal Day, Eid al-Fitr, Eid al-Adha).
Holiday Type = Special Non-Working Day (yellow badge)Also excluded — use for proclaimed special days (Black Saturday, Christmas Eve, Last Day of the Year, Chinese New Year, Ninoy Aquino Day, All Saints' Day, Feast of the Immaculate Conception).
Holiday Type = Special Working Day (green badge)Informational only — currently treated as a working day. Use to flag days that some establishments observe but for SLA we still count.
Recurring YearlyHoliday is applied every year on the same calendar date (Christmas Day, Rizal Day, Bonifacio Day).
Recurring YearlyOne-time entry, applies only to the specific year (Holy Week dates, Eid dates, ad-hoc presidential proclamations).
ActiveArchive without deleting — useful for retiring an old proclamation while preserving history.

The list is seeded with the standard Philippine holiday roster via common/sla_sales_tracking/data/ph_holidays.xml (26 entries at install). Add one-offs (movable proclamations, election holidays, election-related special non-working days) here whenever Malacañang publishes them.

A calendar view of the same data is one click away (top-right icon) — handy for spotting clustered no-work weeks:

SLA Holidays calendar view

Step 3 — Customer regions (the prerequisite)

For any of the above to mean something, the customer record needs a region. This is set on Contacts → (customer) → Sales & Purchase tab → Region (res.partner.region_id).

Current coverage of the BluCoffee partner base:

Customers…Count
Total active customers6,444
With region set5,029
Missing region1,415

Without a region the SLA falls back to the legacy default: NCR (region code 130000000) → 4 days, everywhere else → 12 daysnot the current 3/5-day spec. So a brand-new Metro Manila customer who never had their region set gets a more generous 4-day SLA than a configured one (3 days), and a brand-new Cebu customer gets a much more generous 12-day SLA than configured (5 days). Cleaning up the 1,415 missing-region partners is the single biggest lever for making SLA reporting accurate.

Bulk-set regions

Open Contacts in list view, multi-select rows that share a region (filter by city/province), then use list multi-edit (click the column header → write the value → apply to all selected). Saves a few hundred clicks.

Hardcoded settings (not exposed as configuration)

Two thresholds are baked into the code rather than surfaced as settings:

  • At-Risk threshold = 2 working days. A confirmed delivery flips to At Risk once it's within 2 working days of the expected date. Lives in sale_order.py_compute_sla_status_and_metrics().
  • Region-missing fallback (NCR=4, others=12). Used when a partner has no region_id. Same file — _compute_sla_fields(). The fallback predates the current 3/5-day spec; ideally cleaning up partner regions removes the need for it entirely.

To change either, edit the Python and restart Odoo — --stop-after-init updates DB/views only, not Python code.

Reference

ConcernFile
stock.picking SLA fields (related → sale_id)common/sla_sales_tracking/models/stock_picking.py
Tree-view inherit + badge decorationscommon/sla_sales_tracking/views/stock_picking_views.xml
Search-view inherit (filters + group-by)common/sla_sales_tracking/views/stock_picking_views.xml
SO-side SLA computationcommon/sla_sales_tracking/models/sale_order.py
Region SLA targets (delivery_time)res.region model in bc17/blu_base/models/ph_region.py
Working-day / holiday lookupcommon/sla_sales_tracking/models/sla_holiday.py

Custom stock.picking fields

FieldTypeSource
sla_statusSelectionrelated sale_id.sla_status, stored
sla_target_daysIntegerrelated sale_id.sla_target_days, stored
sla_expected_delivery_dateDaterelated sale_id.sla_expected_delivery_date, stored
sla_days_remainingIntegerrelated sale_id.sla_days_remaining, stored
sla_region_nameCharrelated sale_id.sla_region_name, stored