Skip to content

Messenger Documentation

Overview

The Messenger module (messenger) tracks messenger and courier companies with both name and code identifiers. This provides a more structured approach than the courier model, supporting code-based lookups and organization.


Model Information

Model Name: messenger
Display Name: Messenger
Key Fields: None

Features

  • ❌ No audit logging
  • ❌ No multi-company support
  • ❌ No full-text search
  • ❌ No unique constraints

Key Fields Reference

Header Fields

Field Type Required Description
name Char Messenger company name
code Char Short reference code

Default Order: Ordered by name alphabetically


API Methods

1. Create Messenger

Method: create(vals, context)

Creates a new messenger record with name and optional code.

Parameters:

vals = {
    "name": str,           # Required: Company name
    "code": str,           # Optional: Short code
}

Returns: int - New record ID

Example:

# Create messenger with code
messenger_id = get_model("messenger").create({
    "name": "Flash Delivery Service",
    "code": "FLASH"
})

# Create messenger without code
messenger_id = get_model("messenger").create({
    "name": "Local Express Courier"
})


2. Search by Name

Method: search_browse(condition, context)

Search messengers by name (case-insensitive).

Example:

# Search by partial name match
messengers = get_model("messenger").search_browse([
    ["name", "ilike", "flash"]
])

for m in messengers:
    print(f"{m.code}: {m.name}")


3. Search by Code

Method: search_browse(condition, context)

Search messengers by exact code match.

Example:

# Find specific messenger by code
messenger = get_model("messenger").search_browse([
    ["code", "=", "FLASH"]
])

if messenger:
    print(f"Found: {messenger[0].name}")


Common Use Cases

Use Case 1: Setup Messenger Services

# Setup company messenger services with codes
messengers_data = [
    {"name": "Flash Delivery", "code": "FLASH"},
    {"name": "Quick Courier", "code": "QUICK"},
    {"name": "Express Messenger", "code": "EXPRESS"},
    {"name": "Same Day Service", "code": "SAME"},
    {"name": "Overnight Delivery", "code": "OVER"}
]

messenger_ids = []
for data in messengers_data:
    messenger_id = get_model("messenger").create(data)
    messenger_ids.append(messenger_id)
    print(f"Created: [{data['code']}] {data['name']}")

Use Case 2: List All Messengers

# Get all messengers ordered by name
messengers = get_model("messenger").search_browse([])

print("Registered Messengers:")
print("-" * 40)
for messenger in messengers:
    code_display = f"[{messenger.code}]" if messenger.code else "[NO CODE]"
    print(f"{code_display} {messenger.name}")

Use Case 3: Update Messenger Information

# Update messenger name and code
messenger_id = 1

get_model("messenger").write([messenger_id], {
    "name": "Flash Delivery Express",
    "code": "FLASHEXP"
})

Use Case 4: Find Messenger by Code for Integration

def get_messenger_id_by_code(code):
    """Helper function to get messenger ID by code"""
    messenger = get_model("messenger").search([
        ["code", "=", code]
    ])

    if messenger:
        return messenger[0]
    else:
        raise ValueError(f"Messenger with code '{code}' not found")

# Usage in integration
try:
    messenger_id = get_messenger_id_by_code("FLASH")
    # Use messenger_id in order processing
except ValueError as e:
    print(f"Error: {e}")

Search Functions

Search by Name Pattern

# Case-insensitive partial match
condition = [["name", "ilike", "%delivery%"]]
results = get_model("messenger").search_browse(condition)

Search by Exact Code

# Exact code match (case-sensitive)
condition = [["code", "=", "FLASH"]]
results = get_model("messenger").search_browse(condition)

Search for Messengers Without Code

# Find messengers missing codes
condition = [["code", "=", False]]
results = get_model("messenger").search_browse(condition)

print(f"Found {len(results)} messengers without codes")

Model Relationship Description
stock.picking Referenced by Stock pickings may specify messenger
sale.order Referenced by Sales orders may reference messenger
courier Similar Alternative simpler courier model

Best Practices

1. Use Consistent Code Format

# Good: Uppercase, short codes
get_model("messenger").create({
    "name": "Flash Delivery",
    "code": "FLASH"
})

# Avoid: Mixed case, long codes
get_model("messenger").create({
    "name": "Flash Delivery",
    "code": "flash_delivery_service"  # Too long
})

2. Always Provide Codes for Integration

# Good: Code provided for API/integration use
get_model("messenger").create({
    "name": "Express Service",
    "code": "EXP"
})

# Bad: No code makes lookups harder
get_model("messenger").create({
    "name": "Express Service"
    # Missing code field
})

3. Check for Existing Records

# Good: Check before creating to avoid duplicates
def create_or_get_messenger(name, code):
    # Check by code first
    existing = get_model("messenger").search([
        ["code", "=", code]
    ])

    if existing:
        return existing[0]

    # Check by name
    existing = get_model("messenger").search([
        ["name", "=", name]
    ])

    if existing:
        # Update with code
        get_model("messenger").write([existing[0]], {"code": code})
        return existing[0]

    # Create new
    return get_model("messenger").create({
        "name": name,
        "code": code
    })

Performance Tips

1. Cache Messenger Mappings

# Good: Cache code-to-ID mappings
class MessengerCache:
    _cache = {}

    @classmethod
    def get_by_code(cls, code):
        if code not in cls._cache:
            messenger = get_model("messenger").search([
                ["code", "=", code]
            ])
            if messenger:
                cls._cache[code] = messenger[0]
        return cls._cache.get(code)

    @classmethod
    def clear(cls):
        cls._cache = {}

# Usage
messenger_id = MessengerCache.get_by_code("FLASH")

2. Batch Load Messengers

# Good: Load all messengers once
messengers = get_model("messenger").search_browse([])
messenger_map = {m.code: m.id for m in messengers if m.code}

# Use map for lookups
flash_id = messenger_map.get("FLASH")
quick_id = messenger_map.get("QUICK")

Troubleshooting

"Messenger not found by code"

Cause: Code doesn't exist or is misspelled
Solution: Verify code exists and matches exactly

# Check if code exists
code = "FLASH"
messenger = get_model("messenger").search([["code", "=", code]])
if not messenger:
    print(f"Code '{code}' not found. Available codes:")
    all_messengers = get_model("messenger").search_browse([])
    for m in all_messengers:
        if m.code:
            print(f"  - {m.code}")

Duplicate messenger names

Cause: No unique constraint on name field
Solution: Check before creating

# Check for duplicate names
name = "Flash Delivery"
existing = get_model("messenger").search([["name", "=", name]])
if existing:
    print(f"Messenger '{name}' already exists")
    # Use existing or choose different name

Messengers not ordered correctly

Cause: Model uses name ordering by default
Solution: This is expected behavior, messengers sorted alphabetically


Testing Examples

Unit Test: Create and Retrieve Messenger

def test_messenger_crud():
    # Create
    messenger_id = get_model("messenger").create({
        "name": "Test Messenger",
        "code": "TEST"
    })

    # Verify creation
    assert messenger_id is not None

    # Read by ID
    messenger = get_model("messenger").browse(messenger_id)
    assert messenger.name == "Test Messenger"
    assert messenger.code == "TEST"

    # Search by code
    found = get_model("messenger").search([["code", "=", "TEST"]])
    assert len(found) == 1
    assert found[0] == messenger_id

    # Update
    get_model("messenger").write([messenger_id], {
        "name": "Updated Test Messenger"
    })

    # Verify update
    messenger = get_model("messenger").browse(messenger_id)
    assert messenger.name == "Updated Test Messenger"

    # Delete
    get_model("messenger").delete([messenger_id])

    # Verify deletion
    found = get_model("messenger").search([["id", "=", messenger_id]])
    assert len(found) == 0

Unit Test: Search Operations

def test_messenger_search():
    # Create test data
    test_messengers = [
        {"name": "Alpha Delivery", "code": "ALPHA"},
        {"name": "Beta Courier", "code": "BETA"},
        {"name": "Gamma Express", "code": "GAMMA"}
    ]

    created_ids = []
    for data in test_messengers:
        mid = get_model("messenger").create(data)
        created_ids.append(mid)

    # Test search by name
    results = get_model("messenger").search([
        ["name", "ilike", "alpha"]
    ])
    assert len(results) == 1

    # Test search by code
    results = get_model("messenger").search([
        ["code", "=", "BETA"]
    ])
    assert len(results) == 1

    # Cleanup
    get_model("messenger").delete(created_ids)

Security Considerations

Permission Model

  • Standard model permissions apply
  • Create/write typically requires admin or manager role
  • Read access for users needing to select messengers

Data Access

  • No sensitive data stored
  • Public information (company names)
  • No multi-company isolation

Integration Points

External Systems

  • Shipping APIs: Messenger codes may map to external courier APIs
  • Tracking Systems: Codes used for shipment tracking integration

Internal Modules

  • Stock Management: Pickings reference messengers
  • Sales: Orders may specify preferred messenger
  • Delivery Planning: Route assignments by messenger

Version History

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


Additional Resources

  • Courier Documentation: courier
  • Shipping Method Documentation: ship.method
  • Stock Picking Documentation: stock.picking

This documentation is generated for developer onboarding and reference purposes.