Skip to content

Delivery Slot Documentation

Overview

The Delivery Slot module (delivery.slot) defines time windows for customer deliveries. Each slot has from/to times and can have day-specific capacity limits through the related delivery.slot.capacity model.


Model Information

Model Name: delivery.slot
Display Name: Delivery Slots
Key Fields: name

Features

  • ❌ No audit logging
  • ❌ No multi-company support
  • ❌ No full-text search
  • ✅ Unique key constraint on name

Understanding Key Fields

Unique Name Constraint

_key = ["name"]

Slot names must be unique to prevent duplicate time windows.

Examples:

"Morning (8:00-12:00)"     ✅ Valid
"Afternoon (13:00-17:00)"  ✅ Valid
"Morning (8:00-12:00)"     ❌ ERROR: Key already exists!


Key Fields Reference

Field Type Required Description
sequence Integer Display order
name Char Slot name (unique)
time_from Char Start time (HH:MM format)
time_to Char End time (HH:MM format)
capacities One2Many Day-specific capacity limits

API Methods

Create Delivery Slot

# Create time slot
slot_id = get_model("delivery.slot").create({
    "sequence": 1,
    "name": "Morning Delivery",
    "time_from": "08:00",
    "time_to": "12:00"
})

Common Use Cases

Use Case 1: Setup Daily Delivery Slots

# Define standard delivery time windows
slots = [
    {
        "sequence": 1,
        "name": "Morning Delivery",
        "time_from": "08:00",
        "time_to": "12:00"
    },
    {
        "sequence": 2,
        "name": "Afternoon Delivery",
        "time_from": "13:00",
        "time_to": "17:00"
    },
    {
        "sequence": 3,
        "name": "Evening Delivery",
        "time_from": "18:00",
        "time_to": "21:00"
    }
]

slot_ids = []
for slot_data in slots:
    slot_id = get_model("delivery.slot").create(slot_data)
    slot_ids.append(slot_id)
    print(f"Created: {slot_data['name']} ({slot_data['time_from']}-{slot_data['time_to']})")

Use Case 2: Configure Weekday Capacities

# Setup capacity for morning slot
morning_slot_id = 1

# Weekdays: higher capacity
for weekday in ["0", "1", "2", "3", "4"]:  # Mon-Fri
    get_model("delivery.slot.capacity").create({
        "slot_id": morning_slot_id,
        "weekday": weekday,
        "capacity": 50  # 50 deliveries
    })

# Weekend: lower capacity
for weekday in ["5", "6"]:  # Sat-Sun
    get_model("delivery.slot.capacity").create({
        "slot_id": morning_slot_id,
        "weekday": weekday,
        "capacity": 20  # 20 deliveries
    })

Use Case 3: Check Slot Availability

def check_slot_availability(slot_id, delivery_date):
    """Check if slot has capacity for a given date"""
    from datetime import datetime

    slot = get_model("delivery.slot").browse(slot_id)
    weekday = str(delivery_date.weekday())

    # Find capacity for this weekday
    capacity_record = None
    for cap in slot.capacities:
        if cap.weekday == weekday:
            capacity_record = cap
            break

    if not capacity_record:
        return False, "No capacity configured for this day"

    # Count existing bookings (example - adjust to your model)
    bookings = get_model("sale.order").search([
        ["delivery_slot_id", "=", slot_id],
        ["delivery_date", "=", delivery_date.strftime("%Y-%m-%d")]
    ])

    booked_count = len(bookings)
    available = capacity_record.capacity - booked_count

    if available > 0:
        return True, f"{available} slots available"
    else:
        return False, "Slot fully booked"

# Usage
from datetime import date
is_available, message = check_slot_availability(1, date(2025, 10, 27))
print(message)

Use Case 4: Get Available Slots for Date

def get_available_slots(delivery_date, postal_code=None):
    """Get all available delivery slots for a date"""

    weekday = str(delivery_date.weekday())
    slots = get_model("delivery.slot").search_browse([])

    available_slots = []

    for slot in slots:
        # Find capacity for this weekday
        for cap in slot.capacities:
            if cap.weekday != weekday:
                continue

            # Check postal code exclusions
            if postal_code and cap.exclude_postal_codes:
                excluded = [pc.strip() for pc in cap.exclude_postal_codes.split(',')]
                if postal_code in excluded:
                    continue

            # Check capacity
            bookings = get_model("sale.order").search([
                ["delivery_slot_id", "=", slot.id],
                ["delivery_date", "=", delivery_date.strftime("%Y-%m-%d")]
            ])

            available = cap.capacity - len(bookings)

            if available > 0:
                available_slots.append({
                    "slot_id": slot.id,
                    "name": slot.name,
                    "time_from": slot.time_from,
                    "time_to": slot.time_to,
                    "available": available,
                    "capacity": cap.capacity
                })

    return available_slots

# Usage
from datetime import date
slots = get_available_slots(date(2025, 10, 27), postal_code="10001")

print("Available Delivery Slots:")
for slot in slots:
    print(f"{slot['name']}: {slot['time_from']}-{slot['time_to']} ({slot['available']}/{slot['capacity']} available)")

Model Relationship Description
delivery.slot.capacity One2Many Day-specific capacity limits
sale.order Referenced by Orders select delivery slots

Best Practices

1. Use Clear Time Formats

# Good: 24-hour format, padded
get_model("delivery.slot").create({
    "name": "Morning",
    "time_from": "08:00",
    "time_to": "12:00"
})

# Avoid: 12-hour format or inconsistent padding
get_model("delivery.slot").create({
    "name": "Morning",
    "time_from": "8:00 AM",  # Inconsistent
    "time_to": "12:00 PM"
})

2. Configure Realistic Capacities

# Good: Consider delivery routes and driver availability
get_model("delivery.slot.capacity").create({
    "slot_id": slot_id,
    "weekday": "0",  # Monday
    "capacity": 40   # Based on: 4 drivers × 10 deliveries each
})

# Bad: Arbitrary numbers
get_model("delivery.slot.capacity").create({
    "slot_id": slot_id,
    "weekday": "0",
    "capacity": 1000  # Unrealistic
})

Troubleshooting

"Key already exists"

Cause: Duplicate slot name
Solution: Use unique names

# Check if name exists
name = "Morning Delivery"
existing = get_model("delivery.slot").search([["name", "=", name]])

if existing:
    print(f"Slot '{name}' already exists with ID {existing[0]}")
else:
    # Safe to create
    get_model("delivery.slot").create({"name": name, "time_from": "08:00", "time_to": "12:00"})

Version History

Last Updated: October 2025
Model File: delivery_slot.py
Framework: Netforce


Additional Resources

  • Delivery Slot Capacity Documentation: delivery.slot.capacity
  • Sales Order Documentation: sale.order

This documentation is generated for developer onboarding and reference purposes.