Oversized Pallet Computation — Developer Guide
When freight dimensions exceed standard pallet limits, the rate engine automatically switches from **per-pallet pricing** to **per-kg/chargeable-weight pricing**.
Overview
Section titled “Overview”When freight dimensions exceed the resolved pallet limits, the rate engine automatically prices the oversized items via the rate card’s oversize strategy (by default, the chargeable-weight card serving the same lane) instead of the flat per-pallet rate. This prevents oversized freight from being undercharged at flat per-pallet rates. In mixed loads, only the oversized items move to the oversize spec — items within limits stay on the pallet card.
Oversize Thresholds — How Limits Are Resolved
Section titled “Oversize Thresholds — How Limits Are Resolved”Thresholds are resolved per field, per item: length, width, height, and weight are each resolved independently for every item.
For each threshold field (length / width / height / weight), per item:
1. rate_cards.max_standard_* set on the pricing card? → use the card's override for that field2. Otherwise → use the MOST PERMISSIVE of: - the item's pallet-type physical dimensions (HIRE pallets), and - the pricing_settings tenant default (currently 120 × 120 × 150 cm / 575 kg)3. Neither available? → hardcoded last resort: 120 × 120 × 120 cm / 1,000 kgCurrent tenant default (pricing_settings):
| Dimension | Limit |
|---|---|
| Length | 120 cm |
| Width | 120 cm |
| Height | 150 cm |
| Weight | 575 kg per pallet |
If any single item exceeds any of its resolved limits, the freight is classified as oversized.
Priority Order (How the Engine Decides)
Section titled “Priority Order (How the Engine Decides)”1. Rate entry has EXPLICIT conditions (rate_entry_conditions table) → Condition evaluation takes priority → If conditions fail, skip to next candidate → If conditions pass, use that rate entry's pricing
2. Global oversize rule ENABLED + pallet method + no explicit dimension conditions → Check each item against its RESOLVED thresholds (see above) → If oversized → run the card's oversize_fallback strategy (exactly one — see Step 4) → If within limits → use pallet rate normally
3. Global oversize rule DISABLED (ENFORCE_PALLET_OVERSIZE_RULE=false) → No automatic fallback — all freight uses pallet rates regardless of sizeConfiguration
Section titled “Configuration”Environment Variable
Section titled “Environment Variable”# .env / .env.devENFORCE_PALLET_OVERSIZE_RULE=true # default — oversized items run the card's oversize strategyENFORCE_PALLET_OVERSIZE_RULE=false # disable — allow any size at pallet ratesDatabase: Threshold Sources
Section titled “Database: Threshold Sources”| Source | Scope | Role |
|---|---|---|
rate_cards.max_standard_length_mm / max_standard_width_mm / max_standard_height_mm / max_standard_weight_kg | per card | Per-field override — wins whenever set |
| Pallet-type physical dimensions (HIRE pallets) | per item | Combined with the tenant default; the most permissive value wins per field |
pricing_settings | tenant | Tenant default — currently 120 × 120 × 150 cm / 575 kg |
| Hardcoded | — | 120 × 120 × 120 cm / 1,000 kg last resort when nothing else resolves |
Rate Card Strategy Fields
Section titled “Rate Card Strategy Fields”| Field | Purpose |
|---|---|
rate_cards.oversize_fallback | Strategy selector: NULL/default, custom_chargeable, custom_actual, actual_weight_card |
rate_cards.oversize_weight_rate | $/kg rate used by the two custom_* strategies |
Computation Flow
Section titled “Computation Flow”Step 1: Rate Card Selection
Section titled “Step 1: Rate Card Selection”The engine calls _find_matching_rate_entries() which returns ALL candidate rate entries for a zone pair, ordered by preference:
- Customer-specific rate entries first
- Global rate entries second
- Within each group, entries matching
charging_typeare preferred
Step 2: Conditions Eligibility Filter
Section titled “Step 2: Conditions Eligibility Filter”For each candidate, the engine evaluates conditions from rate_entry_conditions:
packaging_type— allowed packaging typestransport_configuration— allowed vehicle configstime_window_pickup— pickup time restrictionsfreight_dimensions— min/max length, width, height, weight, volume
The first candidate whose conditions all pass is selected.
Step 3: Global Oversize Check
Section titled “Step 3: Global Oversize Check”If the selected rate entry:
- Uses a pallet calculation method (
pallet,per_pallet,quantity) - Has no explicit
freight_dimensionsconditions (explicit conditions already handled in Step 2) - And
ENFORCE_PALLET_OVERSIZE_RULEistrue
Then each item is checked against its resolved thresholds (per field, per item — see “Oversize Thresholds” above):
for item in items: limits = resolve_thresholds(item) # per field: card max_standard_* override # → max(pallet-type dims, pricing_settings default) # → hardcoded 120x120x120 / 1000 last resort if (length_cm > limits.length or width_cm > limits.width or height_cm > limits.height or weight_kg > limits.weight): # OVERSIZE DETECTED → run the card's oversize_fallback strategyStep 4: Oversize Strategy (oversize_fallback)
Section titled “Step 4: Oversize Strategy (oversize_fallback)”When oversize is detected, the card’s oversize_fallback selector runs exactly one of four strategies. The old “Step 4 per-kg re-search cascade” no longer exists — there is no hunting through other per-kg entries.
oversize_fallback | Strategy |
|---|---|
NULL / default | Price oversize items on the chargeable-weight card serving the same lane |
custom_chargeable | Price oversize items at this card’s oversize_weight_rate × chargeable weight |
custom_actual | Price oversize items at this card’s oversize_weight_rate × actual (dead) weight |
actual_weight_card | Price oversize items on the actual-weight card serving the same lane |
If the selected strategy cannot resolve (e.g. no chargeable-weight or actual-weight card exists on the lane), the result is a hard no-match — the engine does not fall through to another strategy.
Step 5: Mixed Loads
Section titled “Step 5: Mixed Loads”Only the oversize items are priced on the oversize spec. Items within their limits stay on the pallet card at pallet rates. The two subtotals are summed into the final total.
Step 6: Base Charge (Flagfall)
Section titled “Step 6: Base Charge (Flagfall)”- On the card-fallback strategies (NULL/
defaultandactual_weight_card), the base charge (flagfall) comes from the fallback card, not the original pallet card. - On the custom strategies (
custom_chargeable,custom_actual), the original card keeps its own flagfall.
Pricing Comparison Example
Section titled “Pricing Comparison Example”Route: Melbourne → Brisbane | Cargo: 8 Pallets
| Standard Pallet | Oversized Pallet | |
|---|---|---|
| Dimensions | 120×120×120cm | 150×150×200cm |
| Weight each | 100 kg | 500 kg |
| Rate Card | JATT Pallet Rates | JATT Per KG Rates |
| Method | Per pallet (tier) | Per kg (chargeable weight) |
| Tier | 5-12 Pallets @ $269.94 | 751kg+ @ $0.29/kg |
| Chargeable wt/pallet | 180 kg (volumetric) | 1,125 kg (volumetric) |
| Total chargeable | 1,440 kg | 9,000 kg |
| Base rate | $15.00 | $15.00 |
| Item charges | 8 × $269.94 = $2,159.52 | 9,000 × $0.29 = $2,610.00 |
| Subtotal | ~$2,174.52 | ~$2,625.00 |
The ~$450 difference reflects the additional truck space consumed by oversized pallets.
Chargeable Weight Calculation
Section titled “Chargeable Weight Calculation”Per pallet: Volume (m³) = (L × W × H) / 1,000,000 Volumetric weight = Volume × cubic_factor Dead weight = actual weight in kg Chargeable weight = max(volumetric_weight, dead_weight)
Total chargeable = sum(chargeable_weight × quantity) for all itemscubic_factor has no hardcoded 250 default — it is resolved via the rate-card override → pricing_settings chain. The worked figures below use 250.
Standard: (120×120×120) / 1,000,000 × 250 = 0.432 m³ × 250 = 108 kg volumetric. Dead = 100 kg. Chargeable = 108 kg. But actual pallet rate ignores this — charges per pallet.
Oversized: (150×150×200) / 1,000,000 × 250 = 4.5 m³ × 250 = 1,125 kg volumetric. Dead = 500 kg. Chargeable = 1,125 kg × 8 = 9,000 kg total.
Rate Card Data (JATT Reference)
Section titled “Rate Card Data (JATT Reference)”JATT Pallet Rates (per pallet, tiered by quantity)
Section titled “JATT Pallet Rates (per pallet, tiered by quantity)”| Tier | Price/Pallet (Melb→Bris) |
|---|---|
| 1-4 Pallets | $276.40 |
| 5-12 Pallets | $269.94 |
| 13+ Pallets | $263.48 |
Used when all items are within standard dimensions.
JATT Per KG Rates (per chargeable kg, tiered by weight)
Section titled “JATT Per KG Rates (per chargeable kg, tiered by weight)”| Tier | Rate/kg (Melb→Bris) |
|---|---|
| Base rate | $15.00 |
| Minimum charge | $37.50 |
| Up to 500 kg | $0.38/kg |
| 501-751 kg | $0.34/kg |
| 751+ kg | $0.29/kg |
Used as fallback when pallet dimensions are exceeded.
JATT Standard Pallet Assumptions (from Scope of Assumptions)
Section titled “JATT Standard Pallet Assumptions (from Scope of Assumptions)”Item 2: “Standard Pallet Dimensions — 1.2 x 1.2 x 1.2, Weight 1000 Kg”
(Historical business assumption only. The live tenant default in pricing_settings is 120 × 120 × 150 cm / 575 kg — see “Oversize Thresholds” above.)
API Response — What Changes
Section titled “API Response — What Changes”When the oversize rule fires, the compute-rate response includes:
{ "computation": { "rate_card_name": "JATT Per KG Rates", "calculation_steps": [ "Skipped: JATT Pallet Rates (Entry 456) — Freight exceeds resolved oversize thresholds", "OVERSIZE: Item 150x150x200cm/500kg exceeds resolved limits 120x120x150cm/575kg", "Oversize strategy (default): pricing oversize items on the chargeable-weight card for this lane", "Priced on: JATT Per KG Rates (ID: 18, method: weight); base charge taken from the fallback card" ], "skipped_entries": [ { "rate_card_name": "JATT Pallet Rates", "rate_entry_id": 456, "reason": ["Freight exceeds resolved oversize thresholds"] } ], "totals": { "initial_cost": 15.00, "base_charge": 2610.00, "final_total": 2610.00 } }}Code Reference
Section titled “Code Reference”| File | Function/Section | Purpose |
|---|---|---|
api/rate_entries_api.py | compute_rate() | Global oversize check + oversize_fallback strategy dispatch |
api/rate_entries_api.py | _find_matching_rate_entries() | Returns all candidate rate entries |
api/rate_entries_api.py | _evaluate_conditions() | Condition evaluation (all types) |
api/rate_entries_api.py | Threshold resolution | Per-field limits: card max_standard_* → most permissive of pallet-type dims / pricing_settings default → hardcoded last resort |
migrations/create_pallet_schema.sql | pallet_master_types table | Pallet-type physical dimensions (feed the threshold resolution for HIRE pallets) |
Adding Custom Oversize Rules
Section titled “Adding Custom Oversize Rules”Option A: Per-Rate-Card Thresholds & Strategy
Section titled “Option A: Per-Rate-Card Thresholds & Strategy”Set the card’s own limits and oversize behaviour directly on rate_cards:
max_standard_length_mm/max_standard_width_mm/max_standard_height_mm/max_standard_weight_kg— per-field threshold overrides (each field independently beats the pallet-type/tenant-default resolution)oversize_fallback— which single strategy runs when items are oversized (see Step 4)oversize_weight_rate— the $/kg used by thecustom_chargeable/custom_actualstrategies
Option B: Per-Rate-Entry Conditions (takes priority over global rule)
Section titled “Option B: Per-Rate-Entry Conditions (takes priority over global rule)”Add a freight_dimensions condition to a specific rate entry via the API:
POST /api/rate-entries/{id}/conditions{ "applies_to": {"type": "freight_dimensions"}, "max_length_cm": 200, "max_width_cm": 200, "max_height_cm": 250, "max_weight_kg": 2000}This rate entry will only match freight within those dimensions. The global rule won’t fire because explicit dimension conditions exist.
Option C: Addons for Surcharges
Section titled “Option C: Addons for Surcharges”Add an “Oversized Item Surcharge” addon via the Unified Addons system:
- Addon Type: Surcharge
- Value Type: Fixed amount (e.g., $85.00)
- Trigger Mode: Manual (operator selects when needed)
- Applies On: Subtotal
This surcharge is applied ON TOP of whichever rate card is used (pallet or per-kg).
Option D: Disable Global Rule Entirely
Section titled “Option D: Disable Global Rule Entirely”ENFORCE_PALLET_OVERSIZE_RULE=falseAll pallets will be charged at pallet rates regardless of dimensions. Use explicit conditions on individual rate entries to control oversize behavior.